3 * Copyright (c) 2007-2010 SlimDX Group
\r
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
\r
6 * of this software and associated documentation files (the "Software"), to deal
\r
7 * in the Software without restriction, including without limitation the rights
\r
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
\r
9 * copies of the Software, and to permit persons to whom the Software is
\r
10 * furnished to do so, subject to the following conditions:
\r
12 * The above copyright notice and this permission notice shall be included in
\r
13 * all copies or substantial portions of the Software.
\r
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
\r
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
\r
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
\r
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
\r
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
\r
23 #include "../VersionConfig.h"
\r
24 #if SLIMDX_D3DX_VERSION < 42
\r
29 #include "../stack_array.h"
\r
30 #include "../DataStream.h"
\r
31 #include "../ComObject.h"
\r
33 #include "Direct3D9Exception.h"
\r
36 #include "VertexShader9.h"
\r
37 #include "PixelShader9.h"
\r
38 #include "FragmentLinker.h"
\r
40 using namespace System;
\r
41 using namespace System::Runtime::InteropServices;
\r
47 FragmentLinker::FragmentLinker( SlimDX::Direct3D9::Device^ device, int cacheSize )
\r
49 IDirect3DDevice9* devicePointer = device->InternalPointer;
\r
50 ID3DXFragmentLinker* linker;
\r
52 HRESULT hr = D3DXCreateFragmentLinker( devicePointer, cacheSize, &linker );
\r
55 throw gcnew Direct3D9Exception( Result::Last );
\r
60 DataStream^ FragmentLinker::Gather( array<Byte>^ sourceData, array<Macro>^ defines,
\r
61 Include^ includeFile, ShaderFlags flags, [Out] String^% errors )
\r
63 ID3DXBuffer* fragmentBuffer;
\r
64 ID3DXBuffer* errorBuffer;
\r
65 pin_ptr<const Byte> pinnedData = &sourceData[0];
\r
67 IncludeShim includeShim = IncludeShim( includeFile );
\r
68 ID3DXInclude* includePtr = NULL;
\r
69 if( includeFile != nullptr )
\r
70 includePtr = &includeShim;
\r
72 array<GCHandle>^ handles;
\r
73 stack_array<D3DXMACRO> macros = Macro::Marshal( defines, handles );
\r
74 D3DXMACRO* macrosPtr = macros.size() > 0 ? ¯os[0] : NULL;
\r
76 #pragma warning(push)
\r
77 #pragma warning(disable:4996)
\r
78 HRESULT hr = D3DXGatherFragments( reinterpret_cast<LPCSTR>( pinnedData ), sourceData->Length, macrosPtr, includePtr,
\r
79 static_cast<DWORD>( flags ), &fragmentBuffer, &errorBuffer );
\r
80 #pragma warning(pop)
\r
82 //clean up after marshaling macros
\r
83 Macro::Unmarshal( handles );
\r
84 //marshal errors if necessary
\r
85 errors = Utilities::BufferToString( errorBuffer );
\r
87 if( RECORD_D3D9( hr ).IsFailure )
\r
90 return gcnew DataStream( fragmentBuffer );
\r
93 // We know that Gather is obsolete, we declared it ourselves
\r
94 #pragma warning(disable:4947)
\r
95 DataStream^ FragmentLinker::Gather( String^ sourceData, array<Macro>^ defines,
\r
96 Include^ includeFile, ShaderFlags flags, [Out] String^% errors )
\r
98 array<Byte>^ sourceBytes = System::Text::ASCIIEncoding::ASCII->GetBytes( sourceData );
\r
99 return Gather( sourceBytes, defines, includeFile, flags, errors );
\r
101 #pragma warning(default:4947)
\r
103 DataStream^ FragmentLinker::GatherFromFile( String^ fileName, array<Macro>^ defines,
\r
104 Include^ includeFile, ShaderFlags flags, [Out] String^% errors )
\r
106 ID3DXBuffer* fragmentBuffer;
\r
107 ID3DXBuffer* errorBuffer;
\r
108 pin_ptr<const wchar_t> pinnedFile = PtrToStringChars( fileName );
\r
110 IncludeShim includeShim = IncludeShim( includeFile );
\r
111 ID3DXInclude* includePtr = NULL;
\r
112 if( includeFile != nullptr )
\r
113 includePtr = &includeShim;
\r
115 array<GCHandle>^ handles;
\r
116 stack_array<D3DXMACRO> macros = Macro::Marshal( defines, handles );
\r
117 D3DXMACRO* macrosPtr = macros.size() > 0 ? ¯os[0] : NULL;
\r
119 #pragma warning(push)
\r
120 #pragma warning(disable:4996)
\r
121 HRESULT hr = D3DXGatherFragmentsFromFile( reinterpret_cast<LPCTSTR>( pinnedFile ), macrosPtr, includePtr,
\r
122 static_cast<DWORD>( flags ), &fragmentBuffer, &errorBuffer );
\r
123 #pragma warning(pop)
\r
125 //clean up after marshaling macros
\r
126 Macro::Unmarshal( handles );
\r
127 //marshal errors if necessary
\r
128 errors = Utilities::BufferToString( errorBuffer );
\r
130 if( RECORD_D3D9( hr ).IsFailure )
\r
133 return gcnew DataStream( fragmentBuffer );
\r
136 Result FragmentLinker::AddFragments( array<int>^ fragments )
\r
138 pin_ptr<int> pinnedFragments = &fragments[0];
\r
139 HRESULT hr = InternalPointer->AddFragments( reinterpret_cast<const DWORD*>( pinnedFragments ) );
\r
140 return RECORD_D3D9( hr );
\r
143 Result FragmentLinker::AddFragments( DataStream^ fragments )
\r
145 HRESULT hr = InternalPointer->AddFragments( reinterpret_cast<const DWORD*>( fragments->PositionPointer ) );
\r
146 return RECORD_D3D9( hr );
\r
149 DataStream^ FragmentLinker::GetFragment( EffectHandle^ name )
\r
151 D3DXHANDLE handle = name != nullptr ? name->InternalHandle : NULL;
\r
152 ID3DXBuffer* fragment;
\r
154 HRESULT hr = InternalPointer->GetFragment( handle, &fragment );
\r
155 GC::KeepAlive( name );
\r
157 if( RECORD_D3D9( hr ).IsFailure )
\r
160 return gcnew DataStream( fragment );
\r
163 DataStream^ FragmentLinker::Fragments::get()
\r
165 ID3DXBuffer* fragments;
\r
167 HRESULT hr = InternalPointer->GetAllFragments( &fragments );
\r
169 if( RECORD_D3D9( hr ).IsFailure )
\r
172 return gcnew DataStream( fragments );
\r
175 SlimDX::Direct3D9::Device^ FragmentLinker::Device::get()
\r
177 IDirect3DDevice9* device;
\r
178 //This method always returns the value S_OK.
\r
179 InternalPointer->GetDevice( &device );
\r
181 return SlimDX::Direct3D9::Device::FromPointer( device );
\r
184 FragmentDescription FragmentLinker::GetFragmentDescription( EffectHandle^ name )
\r
186 D3DXHANDLE handle = name != nullptr ? name->InternalHandle : NULL;
\r
187 D3DXFRAGMENT_DESC description;
\r
189 HRESULT hr = InternalPointer->GetFragmentDesc( handle, &description );
\r
190 GC::KeepAlive( name );
\r
191 if( RECORD_D3D9( hr ).IsFailure )
\r
192 return FragmentDescription();
\r
194 FragmentDescription outDesc;
\r
195 outDesc.Name = gcnew String( description.Name );
\r
196 outDesc.Target = description.Target;
\r
201 EffectHandle^ FragmentLinker::GetFragmentHandle( int index )
\r
203 D3DXHANDLE handle = InternalPointer->GetFragmentHandleByIndex( index );
\r
204 if( handle == NULL )
\r
207 return gcnew EffectHandle( handle );
\r
210 EffectHandle^ FragmentLinker::GetFragmentHandle( String^ name )
\r
212 array<Byte>^ nameBytes = System::Text::ASCIIEncoding::ASCII->GetBytes( name );
\r
213 pin_ptr<const Byte> pinnedName = &nameBytes[0];
\r
215 D3DXHANDLE handle = InternalPointer->GetFragmentHandleByName( reinterpret_cast<LPCSTR>( pinnedName ) );
\r
216 if( handle == NULL )
\r
219 return gcnew EffectHandle( handle );
\r
222 void FragmentLinker::ClearCache()
\r
224 //This method always returns the value S_OK.
\r
225 InternalPointer->ClearCache();
\r
228 ShaderBytecode^ FragmentLinker::LinkShader( String^ profile, ShaderFlags flags, array<EffectHandle^>^ fragmentHandles, [Out] String^% errors )
\r
230 ID3DXBuffer* bytecode;
\r
231 ID3DXBuffer* errorBuffer;
\r
232 array<Byte>^ profileBytes = System::Text::ASCIIEncoding::ASCII->GetBytes( profile );
\r
233 pin_ptr<const Byte> pinnedProfile = &profileBytes[0];
\r
235 stack_array<D3DXHANDLE> handles = stackalloc( D3DXHANDLE, fragmentHandles->Length );
\r
236 for( int i = 0; i < fragmentHandles->Length; ++i )
\r
237 handles[i] = fragmentHandles[i] != nullptr ? fragmentHandles[i]->InternalHandle : NULL;
\r
239 HRESULT hr = InternalPointer->LinkShader( reinterpret_cast<LPCSTR>( pinnedProfile ), static_cast<DWORD>( flags ), &handles[0], fragmentHandles->Length, &bytecode, &errorBuffer );
\r
240 GC::KeepAlive( fragmentHandles );
\r
243 //marshal errors if necessary
\r
244 errors = Utilities::BufferToString( errorBuffer );
\r
245 if( Result::Last.IsFailure )
\r
248 return ShaderBytecode::FromPointer( bytecode );
\r
251 VertexShader^ FragmentLinker::LinkVertexShader( String^ profile, ShaderFlags flags, array<EffectHandle^>^ fragmentHandles, [Out] String^% errors )
\r
253 IDirect3DVertexShader9* shader;
\r
254 ID3DXBuffer* errorBuffer;
\r
255 array<Byte>^ profileBytes = System::Text::ASCIIEncoding::ASCII->GetBytes( profile );
\r
256 pin_ptr<const Byte> pinnedProfile = &profileBytes[0];
\r
258 stack_array<D3DXHANDLE> handles = stackalloc( D3DXHANDLE, fragmentHandles->Length );
\r
259 for( int i = 0; i < fragmentHandles->Length; ++i )
\r
260 handles[i] = fragmentHandles[i] != nullptr ? fragmentHandles[i]->InternalHandle : NULL;
\r
262 HRESULT hr = InternalPointer->LinkVertexShader( reinterpret_cast<LPCSTR>( pinnedProfile ), static_cast<DWORD>( flags ), &handles[0], fragmentHandles->Length, &shader, &errorBuffer );
\r
263 GC::KeepAlive( fragmentHandles );
\r
266 //marshal errors if necessary
\r
267 errors = Utilities::BufferToString( errorBuffer );
\r
268 if( Result::Last.IsFailure )
\r
271 return VertexShader::FromPointer( shader );
\r
274 PixelShader^ FragmentLinker::LinkPixelShader( String^ profile, ShaderFlags flags, array<EffectHandle^>^ fragmentHandles, [Out] String^% errors )
\r
276 IDirect3DPixelShader9* shader;
\r
277 ID3DXBuffer* errorBuffer;
\r
278 array<Byte>^ profileBytes = System::Text::ASCIIEncoding::ASCII->GetBytes( profile );
\r
279 pin_ptr<const Byte> pinnedProfile = &profileBytes[0];
\r
281 stack_array<D3DXHANDLE> handles = stackalloc( D3DXHANDLE, fragmentHandles->Length);
\r
282 for( int i = 0; i < fragmentHandles->Length; ++i )
\r
283 handles[i] = fragmentHandles[i] != nullptr ? fragmentHandles[i]->InternalHandle : NULL;
\r
285 HRESULT hr = InternalPointer->LinkPixelShader( reinterpret_cast<LPCSTR>( pinnedProfile ), static_cast<DWORD>( flags ), &handles[0], fragmentHandles->Length, &shader, &errorBuffer );
\r
286 GC::KeepAlive( fragmentHandles );
\r
289 //marshal errors if necessary
\r
290 errors = Utilities::BufferToString( errorBuffer );
\r
291 if( Result::Last.IsFailure )
\r
294 return PixelShader::FromPointer( shader );
\r
297 int FragmentLinker::FragmentCount::get()
\r
299 return InternalPointer->GetNumberOfFragments();
\r