EffectAPI.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. //--------------------------------------------------------------------------------------
  2. // File: EffectAPI.cpp
  3. //
  4. // Effect API entry point
  5. //
  6. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  7. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  8. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  9. // PARTICULAR PURPOSE.
  10. //
  11. // Copyright (c) Microsoft Corporation. All rights reserved.
  12. //
  13. // http://go.microsoft.com/fwlink/p/?LinkId=271568
  14. //--------------------------------------------------------------------------------------
  15. #include "pchfx.h"
  16. #include <memory>
  17. using namespace D3DX11Effects;
  18. //-------------------------------------------------------------------------------------
  19. struct handle_closer { void operator()(HANDLE h) { if (h) CloseHandle(h); } };
  20. typedef public std::unique_ptr<void, handle_closer> ScopedHandle;
  21. inline HANDLE safe_handle( HANDLE h ) { return (h == INVALID_HANDLE_VALUE) ? 0 : h; }
  22. //-------------------------------------------------------------------------------------
  23. static HRESULT LoadBinaryFromFile( _In_z_ LPCWSTR pFileName, _Inout_ std::unique_ptr<uint8_t[]>& data, _Out_ uint32_t& size )
  24. {
  25. // open the file
  26. #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
  27. ScopedHandle hFile( safe_handle( CreateFile2( pFileName,
  28. GENERIC_READ,
  29. FILE_SHARE_READ,
  30. OPEN_EXISTING,
  31. nullptr ) ) );
  32. #else
  33. ScopedHandle hFile( safe_handle( CreateFileW( pFileName,
  34. GENERIC_READ,
  35. FILE_SHARE_READ,
  36. nullptr,
  37. OPEN_EXISTING,
  38. FILE_ATTRIBUTE_NORMAL,
  39. nullptr ) ) );
  40. #endif
  41. if ( !hFile )
  42. {
  43. return HRESULT_FROM_WIN32( GetLastError() );
  44. }
  45. // Get the file size
  46. LARGE_INTEGER FileSize = { 0 };
  47. #if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
  48. FILE_STANDARD_INFO fileInfo;
  49. if ( !GetFileInformationByHandleEx( hFile.get(), FileStandardInfo, &fileInfo, sizeof(fileInfo) ) )
  50. {
  51. return HRESULT_FROM_WIN32( GetLastError() );
  52. }
  53. FileSize = fileInfo.EndOfFile;
  54. #else
  55. GetFileSizeEx( hFile.get(), &FileSize );
  56. #endif
  57. // File is too big for 32-bit allocation or contains no data, so reject read
  58. if ( !FileSize.LowPart || FileSize.HighPart > 0)
  59. {
  60. return E_FAIL;
  61. }
  62. // create enough space for the file data
  63. data.reset( new uint8_t[ FileSize.LowPart ] );
  64. if (!data)
  65. {
  66. return E_OUTOFMEMORY;
  67. }
  68. // read the data in
  69. DWORD BytesRead = 0;
  70. if (!ReadFile( hFile.get(),
  71. data.get(),
  72. FileSize.LowPart,
  73. &BytesRead,
  74. nullptr
  75. ))
  76. {
  77. return HRESULT_FROM_WIN32( GetLastError() );
  78. }
  79. if (BytesRead < FileSize.LowPart)
  80. {
  81. return E_FAIL;
  82. }
  83. size = BytesRead;
  84. return S_OK;
  85. }
  86. //--------------------------------------------------------------------------------------
  87. _Use_decl_annotations_
  88. HRESULT WINAPI D3DX11CreateEffectFromMemory(LPCVOID pData, SIZE_T DataLength, UINT FXFlags,
  89. ID3D11Device *pDevice, ID3DX11Effect **ppEffect, LPCSTR srcName )
  90. {
  91. if ( !pData || !DataLength || !pDevice || !ppEffect )
  92. return E_INVALIDARG;
  93. #ifdef _M_X64
  94. if ( DataLength > 0xFFFFFFFF )
  95. return E_INVALIDARG;
  96. #endif
  97. HRESULT hr = S_OK;
  98. // Note that pData must point to a compiled effect, not HLSL
  99. VN( *ppEffect = new CEffect( FXFlags & D3DX11_EFFECT_RUNTIME_VALID_FLAGS) );
  100. VH( ((CEffect*)(*ppEffect))->LoadEffect(pData, static_cast<uint32_t>(DataLength) ) );
  101. VH( ((CEffect*)(*ppEffect))->BindToDevice(pDevice, (srcName) ? srcName : "D3DX11Effect" ) );
  102. lExit:
  103. if (FAILED(hr))
  104. {
  105. SAFE_RELEASE(*ppEffect);
  106. }
  107. return hr;
  108. }
  109. //--------------------------------------------------------------------------------------
  110. _Use_decl_annotations_
  111. HRESULT WINAPI D3DX11CreateEffectFromFile( LPCWSTR pFileName, UINT FXFlags, ID3D11Device *pDevice, ID3DX11Effect **ppEffect )
  112. {
  113. if ( !pFileName || !pDevice || !ppEffect )
  114. return E_INVALIDARG;
  115. std::unique_ptr<uint8_t[]> fileData;
  116. uint32_t size;
  117. HRESULT hr = LoadBinaryFromFile( pFileName, fileData, size );
  118. if ( FAILED(hr) )
  119. return hr;
  120. hr = S_OK;
  121. // Note that pData must point to a compiled effect, not HLSL
  122. VN( *ppEffect = new CEffect( FXFlags & D3DX11_EFFECT_RUNTIME_VALID_FLAGS) );
  123. VH( ((CEffect*)(*ppEffect))->LoadEffect( fileData.get(), size ) );
  124. // Create debug object name from input filename
  125. CHAR strFileA[MAX_PATH];
  126. int result = WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, pFileName, -1, strFileA, MAX_PATH, nullptr, FALSE );
  127. if ( !result )
  128. {
  129. DPF(0, "Failed to load effect file due to WC to MB conversion failure: %ls", pFileName);
  130. hr = E_FAIL;
  131. goto lExit;
  132. }
  133. const CHAR* pstrName = strrchr( strFileA, '\\' );
  134. if (!pstrName)
  135. {
  136. pstrName = strFileA;
  137. }
  138. else
  139. {
  140. pstrName++;
  141. }
  142. VH( ((CEffect*)(*ppEffect))->BindToDevice(pDevice, pstrName) );
  143. lExit:
  144. if (FAILED(hr))
  145. {
  146. SAFE_RELEASE(*ppEffect);
  147. }
  148. return hr;
  149. }
  150. //--------------------------------------------------------------------------------------
  151. _Use_decl_annotations_
  152. HRESULT D3DX11CompileEffectFromMemory( LPCVOID pData, SIZE_T DataLength, LPCSTR srcName,
  153. const D3D_SHADER_MACRO *pDefines, ID3DInclude *pInclude, UINT HLSLFlags, UINT FXFlags,
  154. ID3D11Device *pDevice, ID3DX11Effect **ppEffect, ID3DBlob **ppErrors )
  155. {
  156. if ( !pData || !DataLength || !pDevice || !ppEffect )
  157. return E_INVALIDARG;
  158. if ( FXFlags & D3DCOMPILE_EFFECT_CHILD_EFFECT )
  159. {
  160. DPF(0, "Effect pools (i.e. D3DCOMPILE_EFFECT_CHILD_EFFECT) not supported" );
  161. return E_NOTIMPL;
  162. }
  163. ID3DBlob *blob = nullptr;
  164. HRESULT hr = D3DCompile( pData, DataLength, srcName, pDefines, pInclude, "", "fx_5_0", HLSLFlags, FXFlags, &blob, ppErrors );
  165. if ( FAILED(hr) )
  166. {
  167. DPF(0, "D3DCompile of fx_5_0 profile failed: %08X", hr );
  168. return hr;
  169. }
  170. hr = S_OK;
  171. VN( *ppEffect = new CEffect( FXFlags & D3DX11_EFFECT_RUNTIME_VALID_FLAGS ) );
  172. VH( ((CEffect*)(*ppEffect))->LoadEffect(blob->GetBufferPointer(), static_cast<uint32_t>( blob->GetBufferSize() ) ) );
  173. SAFE_RELEASE( blob );
  174. VH( ((CEffect*)(*ppEffect))->BindToDevice(pDevice, (srcName) ? srcName : "D3DX11Effect" ) );
  175. lExit:
  176. if (FAILED(hr))
  177. {
  178. SAFE_RELEASE(*ppEffect);
  179. }
  180. return hr;
  181. }
  182. //--------------------------------------------------------------------------------------
  183. _Use_decl_annotations_
  184. HRESULT D3DX11CompileEffectFromFile( LPCWSTR pFileName,
  185. const D3D_SHADER_MACRO *pDefines, ID3DInclude *pInclude, UINT HLSLFlags, UINT FXFlags,
  186. ID3D11Device *pDevice, ID3DX11Effect **ppEffect, ID3DBlob **ppErrors )
  187. {
  188. if ( !pFileName || !pDevice || !ppEffect )
  189. return E_INVALIDARG;
  190. if ( FXFlags & D3DCOMPILE_EFFECT_CHILD_EFFECT )
  191. {
  192. DPF(0, "Effect pools (i.e. D3DCOMPILE_EFFECT_CHILD_EFFECT) not supported" );
  193. return E_NOTIMPL;
  194. }
  195. ID3DBlob *blob = nullptr;
  196. #if (D3D_COMPILER_VERSION >= 46) && ( !defined(WINAPI_FAMILY) || ( (WINAPI_FAMILY != WINAPI_FAMILY_APP) && (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) ) )
  197. HRESULT hr = D3DCompileFromFile( pFileName, pDefines, pInclude, "", "fx_5_0", HLSLFlags, FXFlags, &blob, ppErrors );
  198. if ( FAILED(hr) )
  199. {
  200. DPF(0, "D3DCompileFromFile of fx_5_0 profile failed %08X: %ls", hr, pFileName );
  201. return hr;
  202. }
  203. #else // D3D_COMPILER_VERSION < 46
  204. std::unique_ptr<uint8_t[]> fileData;
  205. uint32_t size;
  206. HRESULT hr = LoadBinaryFromFile( pFileName, fileData, size );
  207. if ( FAILED(hr) )
  208. {
  209. DPF(0, "Failed to load effect file %08X: %ls", hr, pFileName);
  210. return hr;
  211. }
  212. // Create debug object name from input filename
  213. CHAR strFileA[MAX_PATH];
  214. int result = WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, pFileName, -1, strFileA, MAX_PATH, nullptr, FALSE );
  215. if ( !result )
  216. {
  217. DPF(0, "Failed to load effect file due to WC to MB conversion failure: %ls", pFileName);
  218. return E_FAIL;
  219. }
  220. const CHAR* pstrName = strrchr( strFileA, '\\' );
  221. if (!pstrName)
  222. {
  223. pstrName = strFileA;
  224. }
  225. else
  226. {
  227. pstrName++;
  228. }
  229. hr = D3DCompile( fileData.get(), size, pstrName, pDefines, pInclude, "", "fx_5_0", HLSLFlags, FXFlags, &blob, ppErrors );
  230. if ( FAILED(hr) )
  231. {
  232. DPF(0, "D3DCompile of fx_5_0 profile failed: %08X", hr );
  233. return hr;
  234. }
  235. #endif // D3D_COMPILER_VERSION
  236. #ifdef _M_X64
  237. if ( blob->GetBufferSize() > 0xFFFFFFFF )
  238. {
  239. SAFE_RELEASE( blob );
  240. return E_FAIL;
  241. }
  242. #endif // _M_X64
  243. hr = S_OK;
  244. VN( *ppEffect = new CEffect( FXFlags & D3DX11_EFFECT_RUNTIME_VALID_FLAGS ) );
  245. VH( ((CEffect*)(*ppEffect))->LoadEffect(blob->GetBufferPointer(), static_cast<uint32_t>( blob->GetBufferSize() ) ) );
  246. SAFE_RELEASE( blob );
  247. #if (D3D_COMPILER_VERSION >= 46) && ( !defined(WINAPI_FAMILY) || ( (WINAPI_FAMILY != WINAPI_FAMILY_APP) && (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) ) )
  248. // Create debug object name from input filename
  249. CHAR strFileA[MAX_PATH];
  250. int result = WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, pFileName, -1, strFileA, MAX_PATH, nullptr, FALSE );
  251. if ( !result )
  252. {
  253. DPF(0, "Failed to load effect file due to WC to MB conversion failure: %ls", pFileName);
  254. hr = E_FAIL;
  255. goto lExit;
  256. }
  257. const CHAR* pstrName = strrchr( strFileA, '\\' );
  258. if (!pstrName)
  259. {
  260. pstrName = strFileA;
  261. }
  262. else
  263. {
  264. pstrName++;
  265. }
  266. #endif
  267. VH( ((CEffect*)(*ppEffect))->BindToDevice(pDevice, pstrName) );
  268. lExit:
  269. if (FAILED(hr))
  270. {
  271. SAFE_RELEASE(*ppEffect);
  272. }
  273. return hr;
  274. }