#include "precompiled.h" #include "libGLESv2/renderer/d3d/HLSLCompiler.h" #include "libGLESv2/Program.h" #include "libGLESv2/main.h" #include "common/utilities.h" #include "common/platform.h" #include "third_party/trace_event/trace_event.h" #include #if defined(__MINGW32__) && !defined(D3DCOMPILER_DLL) // Add define + typedefs for older MinGW-w64 headers (pre 5783) #define D3DCOMPILER_DLL L"d3dcompiler_43.dll" HRESULT WINAPI D3DCompile(const void *data, SIZE_T data_size, const char *filename, const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint, const char *target, UINT sflags, UINT eflags, ID3DBlob **shader, ID3DBlob **error_messages); typedef HRESULT (WINAPI *pD3DCompile)(const void *data, SIZE_T data_size, const char *filename, const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint, const char *target, UINT sflags, UINT eflags, ID3DBlob **shader, ID3DBlob **error_messages); #endif // __MINGW32__ && !D3DCOMPILER_DLL #ifndef QT_D3DCOMPILER_DLL #define QT_D3DCOMPILER_DLL D3DCOMPILER_DLL #endif #ifndef LoadLibrary #define LoadLibrary(dll) LoadPackagedLibrary(dll, NULL) #endif namespace rx { HLSLCompiler::HLSLCompiler() : mD3DCompilerModule(NULL), mD3DCompileFunc(NULL) { } HLSLCompiler::~HLSLCompiler() { release(); } bool HLSLCompiler::initialize() { TRACE_EVENT0("gpu", "initializeCompiler"); #if !defined(ANGLE_PLATFORM_WINRT) #if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES) // Find a D3DCompiler module that had already been loaded based on a predefined list of versions. static const char *d3dCompilerNames[] = ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES; for (size_t i = 0; i < ArraySize(d3dCompilerNames); ++i) { if (GetModuleHandleExA(0, d3dCompilerNames[i], &mD3DCompilerModule)) { break; } } #endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES // Load the compiler DLL specified by the environment, or default to QT_D3DCOMPILER_DLL const wchar_t *defaultCompiler = _wgetenv(L"QT_D3DCOMPILER_DLL"); if (!defaultCompiler) defaultCompiler = QT_D3DCOMPILER_DLL; const wchar_t *compilerDlls[] = { defaultCompiler, L"d3dcompiler_47.dll", L"d3dcompiler_46.dll", L"d3dcompiler_45.dll", L"d3dcompiler_44.dll", L"d3dcompiler_43.dll", 0 }; // Load the first available known compiler DLL for (int i = 0; compilerDlls[i]; ++i) { mD3DCompilerModule = LoadLibrary(compilerDlls[i]); if (mD3DCompilerModule) break; } if (!mD3DCompilerModule) { ERR("No D3D compiler module found - aborting!\n"); return false; } mD3DCompileFunc = reinterpret_cast(GetProcAddress(mD3DCompilerModule, "D3DCompile")); ASSERT(mD3DCompileFunc); #else mD3DCompileFunc = reinterpret_cast(&D3DCompile); #endif return mD3DCompileFunc != NULL; } void HLSLCompiler::release() { if (mD3DCompilerModule) { FreeLibrary(mD3DCompilerModule); mD3DCompilerModule = NULL; mD3DCompileFunc = NULL; } } ShaderBlob *HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile, const UINT optimizationFlags[], const char *flagNames[], int attempts) const { #if !defined(ANGLE_PLATFORM_WINRT) ASSERT(mD3DCompilerModule && mD3DCompileFunc); #endif if (!hlsl) { return NULL; } pD3DCompile compileFunc = reinterpret_cast(mD3DCompileFunc); for (int i = 0; i < attempts; ++i) { ID3DBlob *errorMessage = NULL; ID3DBlob *binary = NULL; HRESULT result = compileFunc(hlsl, strlen(hlsl), gl::g_fakepath, NULL, NULL, "main", profile, optimizationFlags[i], 0, &binary, &errorMessage); if (errorMessage) { const char *message = (const char*)errorMessage->GetBufferPointer(); infoLog.appendSanitized(message); TRACE("\n%s", hlsl); TRACE("\n%s", message); SafeRelease(errorMessage); } if (SUCCEEDED(result)) { return (ShaderBlob*)binary; } else { if (result == E_OUTOFMEMORY) { return gl::error(GL_OUT_OF_MEMORY, (ShaderBlob*)NULL); } infoLog.append("Warning: D3D shader compilation failed with "); infoLog.append(flagNames[i]); infoLog.append(" flags."); if (i + 1 < attempts) { infoLog.append(" Retrying with "); infoLog.append(flagNames[i + 1]); infoLog.append(".\n"); } } } return NULL; } }