//-------------------------------------------------------------------------------------- // File: EffectAPI.cpp // // Effect API entry point // // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A // PARTICULAR PURPOSE. // // Copyright (c) Microsoft Corporation. All rights reserved. // // http://go.microsoft.com/fwlink/p/?LinkId=271568 //-------------------------------------------------------------------------------------- #include "pchfx.h" #include using namespace D3DX11Effects; //------------------------------------------------------------------------------------- struct handle_closer { void operator()(HANDLE h) { if (h) CloseHandle(h); } }; typedef public std::unique_ptr ScopedHandle; inline HANDLE safe_handle( HANDLE h ) { return (h == INVALID_HANDLE_VALUE) ? 0 : h; } //------------------------------------------------------------------------------------- static HRESULT LoadBinaryFromFile( _In_z_ LPCWSTR pFileName, _Inout_ std::unique_ptr& data, _Out_ uint32_t& size ) { // open the file #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) ScopedHandle hFile( safe_handle( CreateFile2( pFileName, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr ) ) ); #else ScopedHandle hFile( safe_handle( CreateFileW( pFileName, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr ) ) ); #endif if ( !hFile ) { return HRESULT_FROM_WIN32( GetLastError() ); } // Get the file size LARGE_INTEGER FileSize = { 0 }; #if (_WIN32_WINNT >= _WIN32_WINNT_VISTA) FILE_STANDARD_INFO fileInfo; if ( !GetFileInformationByHandleEx( hFile.get(), FileStandardInfo, &fileInfo, sizeof(fileInfo) ) ) { return HRESULT_FROM_WIN32( GetLastError() ); } FileSize = fileInfo.EndOfFile; #else GetFileSizeEx( hFile.get(), &FileSize ); #endif // File is too big for 32-bit allocation or contains no data, so reject read if ( !FileSize.LowPart || FileSize.HighPart > 0) { return E_FAIL; } // create enough space for the file data data.reset( new uint8_t[ FileSize.LowPart ] ); if (!data) { return E_OUTOFMEMORY; } // read the data in DWORD BytesRead = 0; if (!ReadFile( hFile.get(), data.get(), FileSize.LowPart, &BytesRead, nullptr )) { return HRESULT_FROM_WIN32( GetLastError() ); } if (BytesRead < FileSize.LowPart) { return E_FAIL; } size = BytesRead; return S_OK; } //-------------------------------------------------------------------------------------- _Use_decl_annotations_ HRESULT WINAPI D3DX11CreateEffectFromMemory(LPCVOID pData, SIZE_T DataLength, UINT FXFlags, ID3D11Device *pDevice, ID3DX11Effect **ppEffect, LPCSTR srcName ) { if ( !pData || !DataLength || !pDevice || !ppEffect ) return E_INVALIDARG; #ifdef _M_X64 if ( DataLength > 0xFFFFFFFF ) return E_INVALIDARG; #endif HRESULT hr = S_OK; // Note that pData must point to a compiled effect, not HLSL VN( *ppEffect = new CEffect( FXFlags & D3DX11_EFFECT_RUNTIME_VALID_FLAGS) ); VH( ((CEffect*)(*ppEffect))->LoadEffect(pData, static_cast(DataLength) ) ); VH( ((CEffect*)(*ppEffect))->BindToDevice(pDevice, (srcName) ? srcName : "D3DX11Effect" ) ); lExit: if (FAILED(hr)) { SAFE_RELEASE(*ppEffect); } return hr; } //-------------------------------------------------------------------------------------- _Use_decl_annotations_ HRESULT WINAPI D3DX11CreateEffectFromFile( LPCWSTR pFileName, UINT FXFlags, ID3D11Device *pDevice, ID3DX11Effect **ppEffect ) { if ( !pFileName || !pDevice || !ppEffect ) return E_INVALIDARG; std::unique_ptr fileData; uint32_t size; HRESULT hr = LoadBinaryFromFile( pFileName, fileData, size ); if ( FAILED(hr) ) return hr; hr = S_OK; // Note that pData must point to a compiled effect, not HLSL VN( *ppEffect = new CEffect( FXFlags & D3DX11_EFFECT_RUNTIME_VALID_FLAGS) ); VH( ((CEffect*)(*ppEffect))->LoadEffect( fileData.get(), size ) ); // Create debug object name from input filename CHAR strFileA[MAX_PATH]; int result = WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, pFileName, -1, strFileA, MAX_PATH, nullptr, FALSE ); if ( !result ) { DPF(0, "Failed to load effect file due to WC to MB conversion failure: %S", pFileName); hr = E_FAIL; goto lExit; } const CHAR* pstrName = strrchr( strFileA, '\\' ); if (!pstrName) { pstrName = strFileA; } else { pstrName++; } VH( ((CEffect*)(*ppEffect))->BindToDevice(pDevice, pstrName) ); lExit: if (FAILED(hr)) { SAFE_RELEASE(*ppEffect); } return hr; } //-------------------------------------------------------------------------------------- _Use_decl_annotations_ HRESULT D3DX11CompileEffectFromMemory( LPCVOID pData, SIZE_T DataLength, LPCSTR srcName, const D3D_SHADER_MACRO *pDefines, ID3DInclude *pInclude, UINT HLSLFlags, UINT FXFlags, ID3D11Device *pDevice, ID3DX11Effect **ppEffect, ID3DBlob **ppErrors ) { if ( !pData || !DataLength || !pDevice || !ppEffect ) return E_INVALIDARG; if ( FXFlags & D3DCOMPILE_EFFECT_CHILD_EFFECT ) { DPF(0, "Effect pools (i.e. D3DCOMPILE_EFFECT_CHILD_EFFECT) not supported" ); return E_NOTIMPL; } ID3DBlob *blob = nullptr; HRESULT hr = D3DCompile( pData, DataLength, srcName, pDefines, pInclude, "", "fx_5_0", HLSLFlags, FXFlags, &blob, ppErrors ); if ( FAILED(hr) ) { DPF(0, "D3DCompile of fx_5_0 profile failed: %08X", hr ); return hr; } hr = S_OK; VN( *ppEffect = new CEffect( FXFlags & D3DX11_EFFECT_RUNTIME_VALID_FLAGS ) ); VH( ((CEffect*)(*ppEffect))->LoadEffect(blob->GetBufferPointer(), static_cast( blob->GetBufferSize() ) ) ); SAFE_RELEASE( blob ); VH( ((CEffect*)(*ppEffect))->BindToDevice(pDevice, (srcName) ? srcName : "D3DX11Effect" ) ); lExit: if (FAILED(hr)) { SAFE_RELEASE(*ppEffect); } return hr; } //-------------------------------------------------------------------------------------- _Use_decl_annotations_ HRESULT D3DX11CompileEffectFromFile( LPCWSTR pFileName, const D3D_SHADER_MACRO *pDefines, ID3DInclude *pInclude, UINT HLSLFlags, UINT FXFlags, ID3D11Device *pDevice, ID3DX11Effect **ppEffect, ID3DBlob **ppErrors ) { if ( !pFileName || !pDevice || !ppEffect ) return E_INVALIDARG; if ( FXFlags & D3DCOMPILE_EFFECT_CHILD_EFFECT ) { DPF(0, "Effect pools (i.e. D3DCOMPILE_EFFECT_CHILD_EFFECT) not supported" ); return E_NOTIMPL; } ID3DBlob *blob = nullptr; #if (D3D_COMPILER_VERSION >= 46) && ( !defined(WINAPI_FAMILY) || ( (WINAPI_FAMILY != WINAPI_FAMILY_APP) && (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) ) ) HRESULT hr = D3DCompileFromFile( pFileName, pDefines, pInclude, "", "fx_5_0", HLSLFlags, FXFlags, &blob, ppErrors ); if ( FAILED(hr) ) { DPF(0, "D3DCompileFromFile of fx_5_0 profile failed %08X: %S", hr, pFileName ); return hr; } #else // D3D_COMPILER_VERSION < 46 std::unique_ptr fileData; uint32_t size; HRESULT hr = LoadBinaryFromFile( pFileName, fileData, size ); if ( FAILED(hr) ) { DPF(0, "Failed to load effect file %08X: %S", hr, pFileName); return hr; } // Create debug object name from input filename CHAR strFileA[MAX_PATH]; int result = WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, pFileName, -1, strFileA, MAX_PATH, nullptr, FALSE ); if ( !result ) { DPF(0, "Failed to load effect file due to WC to MB conversion failure: %S", pFileName); return E_FAIL; } const CHAR* pstrName = strrchr( strFileA, '\\' ); if (!pstrName) { pstrName = strFileA; } else { pstrName++; } hr = D3DCompile( fileData.get(), size, pstrName, pDefines, pInclude, "", "fx_5_0", HLSLFlags, FXFlags, &blob, ppErrors ); if ( FAILED(hr) ) { DPF(0, "D3DCompile of fx_5_0 profile failed: %08X", hr ); return hr; } #endif // D3D_COMPILER_VERSION #ifdef _M_X64 if ( blob->GetBufferSize() > 0xFFFFFFFF ) { SAFE_RELEASE( blob ); return E_FAIL; } #endif // _M_X64 hr = S_OK; VN( *ppEffect = new CEffect( FXFlags & D3DX11_EFFECT_RUNTIME_VALID_FLAGS ) ); VH( ((CEffect*)(*ppEffect))->LoadEffect(blob->GetBufferPointer(), static_cast( blob->GetBufferSize() ) ) ); SAFE_RELEASE( blob ); #if (D3D_COMPILER_VERSION >= 46) && ( !defined(WINAPI_FAMILY) || ( (WINAPI_FAMILY != WINAPI_FAMILY_APP) && (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) ) ) // Create debug object name from input filename CHAR strFileA[MAX_PATH]; int result = WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, pFileName, -1, strFileA, MAX_PATH, nullptr, FALSE ); if ( !result ) { DPF(0, "Failed to load effect file due to WC to MB conversion failure: %S", pFileName); hr = E_FAIL; goto lExit; } const CHAR* pstrName = strrchr( strFileA, '\\' ); if (!pstrName) { pstrName = strFileA; } else { pstrName++; } #endif VH( ((CEffect*)(*ppEffect))->BindToDevice(pDevice, pstrName) ); lExit: if (FAILED(hr)) { SAFE_RELEASE(*ppEffect); } return hr; }