diff options
Diffstat (limited to 'lib/win32/Effects11/EffectAPI.cpp')
-rw-r--r-- | lib/win32/Effects11/EffectAPI.cpp | 335 |
1 files changed, 335 insertions, 0 deletions
diff --git a/lib/win32/Effects11/EffectAPI.cpp b/lib/win32/Effects11/EffectAPI.cpp new file mode 100644 index 0000000000..69e1671b22 --- /dev/null +++ b/lib/win32/Effects11/EffectAPI.cpp @@ -0,0 +1,335 @@ +//-------------------------------------------------------------------------------------- +// 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 <memory> + +using namespace D3DX11Effects; + +//------------------------------------------------------------------------------------- + +struct handle_closer { void operator()(HANDLE h) { if (h) CloseHandle(h); } }; + +typedef public std::unique_ptr<void, handle_closer> 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<uint8_t[]>& 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<uint32_t>(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<uint8_t[]> 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<uint32_t>( 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<uint8_t[]> 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<uint32_t>( 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; +} |