Lazily load the HLSL compiler DLL.

If the user is loading resources straight from the disk with the
binary shader cache, they shouldn't need to load the compiler DLL
at all. Note: might be a good idea to track more statistics here.

BUG=angleproject:1014

Change-Id: Ie75dcce3eb249347c545f1bbca7d0977df7addee
Reviewed-on: https://chromium-review.googlesource.com/282554
Reviewed-by: Kenneth Russell <kbr@chromium.org>
Tested-by: Jamie Madill <jmadill@chromium.org>
This commit is contained in:
Jamie Madill 2015-07-13 09:59:53 -04:00
Родитель e0f623a40a
Коммит a8bb9cdc7d
4 изменённых файлов: 72 добавлений и 54 удалений

Просмотреть файл

@ -106,9 +106,10 @@ CompileConfig::CompileConfig(UINT flags, const std::string &name)
}
HLSLCompiler::HLSLCompiler()
: mD3DCompilerModule(NULL),
mD3DCompileFunc(NULL),
mD3DDisassembleFunc(NULL)
: mInitialized(false),
mD3DCompilerModule(nullptr),
mD3DCompileFunc(nullptr),
mD3DDisassembleFunc(nullptr)
{
}
@ -117,8 +118,13 @@ HLSLCompiler::~HLSLCompiler()
release();
}
bool HLSLCompiler::initialize()
gl::Error HLSLCompiler::initialize()
{
if (mInitialized)
{
return gl::Error(GL_NO_ERROR);
}
TRACE_EVENT0("gpu.angle", "HLSLCompiler::initialize");
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
#if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES)
@ -142,8 +148,7 @@ bool HLSLCompiler::initialize()
if (!mD3DCompilerModule)
{
ERR("No D3D compiler module found - aborting!\n");
return false;
return gl::Error(GL_INVALID_OPERATION, "No D3D compiler module found - aborting!\n");
}
mD3DCompileFunc = reinterpret_cast<pD3DCompile>(GetProcAddress(mD3DCompilerModule, "D3DCompile"));
@ -155,29 +160,42 @@ bool HLSLCompiler::initialize()
#else
// D3D Shader compiler is linked already into this module, so the export
// can be directly assigned.
mD3DCompilerModule = NULL;
mD3DCompilerModule = nullptr;
mD3DCompileFunc = reinterpret_cast<pD3DCompile>(D3DCompile);
mD3DDisassembleFunc = reinterpret_cast<pD3DDisassemble>(D3DDisassemble);
#endif
return mD3DCompileFunc != NULL;
if (mD3DCompileFunc == nullptr)
{
return gl::Error(GL_INVALID_OPERATION, "Error finding D3DCompile entry point");
}
mInitialized = true;
return gl::Error(GL_NO_ERROR);
}
void HLSLCompiler::release()
{
if (mD3DCompilerModule)
if (mInitialized)
{
FreeLibrary(mD3DCompilerModule);
mD3DCompilerModule = NULL;
mD3DCompileFunc = NULL;
mD3DDisassembleFunc = NULL;
mD3DCompilerModule = nullptr;
mD3DCompileFunc = nullptr;
mD3DDisassembleFunc = nullptr;
mInitialized = false;
}
}
gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile,
const std::vector<CompileConfig> &configs, const D3D_SHADER_MACRO *overrideMacros,
ID3DBlob **outCompiledBlob, std::string *outDebugInfo) const
ID3DBlob **outCompiledBlob, std::string *outDebugInfo)
{
gl::Error error = initialize();
if (error.isError())
{
return error;
}
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
ASSERT(mD3DCompilerModule);
#endif
@ -192,14 +210,14 @@ gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string
}
#endif
const D3D_SHADER_MACRO *macros = overrideMacros ? overrideMacros : NULL;
const D3D_SHADER_MACRO *macros = overrideMacros ? overrideMacros : nullptr;
for (size_t i = 0; i < configs.size(); ++i)
{
ID3DBlob *errorMessage = NULL;
ID3DBlob *binary = NULL;
ID3DBlob *errorMessage = nullptr;
ID3DBlob *binary = nullptr;
HRESULT result = mD3DCompileFunc(hlsl.c_str(), hlsl.length(), gl::g_fakepath, macros, NULL, "main", profile.c_str(),
HRESULT result = mD3DCompileFunc(hlsl.c_str(), hlsl.length(), gl::g_fakepath, macros, nullptr, "main", profile.c_str(),
configs[i].flags, 0, &binary, &errorMessage);
if (errorMessage)
@ -217,7 +235,7 @@ gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string
// some very long shaders have trouble deciding which loops to unroll and
// turning off forced unrolls allows them to compile properly.
{
macros = NULL; // Disable [loop] and [flatten]
macros = nullptr; // Disable [loop] and [flatten]
// Retry without changing compiler flags
i--;
@ -255,52 +273,64 @@ gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string
}
}
(*outDebugInfo) += "\n" + disassembleBinary(binary) + "\n// ASSEMBLY END\n";
std::string disassembly;
error = disassembleBinary(binary, &disassembly);
if (error.isError())
{
return error;
}
(*outDebugInfo) += "\n" + disassembly + "\n// ASSEMBLY END\n";
#endif
return gl::Error(GL_NO_ERROR);
}
else
if (result == E_OUTOFMEMORY)
{
if (result == E_OUTOFMEMORY)
{
*outCompiledBlob = NULL;
return gl::Error(GL_OUT_OF_MEMORY, "HLSL compiler had an unexpected failure, result: 0x%X.", result);
}
*outCompiledBlob = nullptr;
return gl::Error(GL_OUT_OF_MEMORY, "HLSL compiler had an unexpected failure, result: 0x%X.", result);
}
infoLog << "Warning: D3D shader compilation failed with " << configs[i].name << " flags.";
infoLog << "Warning: D3D shader compilation failed with " << configs[i].name << " flags.";
if (i + 1 < configs.size())
{
infoLog << " Retrying with " << configs[i + 1].name;
}
if (i + 1 < configs.size())
{
infoLog << " Retrying with " << configs[i + 1].name;
}
}
// None of the configurations succeeded in compiling this shader but the compiler is still intact
*outCompiledBlob = NULL;
*outCompiledBlob = nullptr;
return gl::Error(GL_NO_ERROR);
}
std::string HLSLCompiler::disassembleBinary(ID3DBlob *shaderBinary) const
gl::Error HLSLCompiler::disassembleBinary(ID3DBlob *shaderBinary, std::string *disassemblyOut)
{
gl::Error error = initialize();
if (error.isError())
{
return error;
}
// Retrieve disassembly
UINT flags = D3D_DISASM_ENABLE_DEFAULT_VALUE_PRINTS | D3D_DISASM_ENABLE_INSTRUCTION_NUMBERING;
ID3DBlob *disassembly = NULL;
ID3DBlob *disassembly = nullptr;
pD3DDisassemble disassembleFunc = reinterpret_cast<pD3DDisassemble>(mD3DDisassembleFunc);
LPCVOID buffer = shaderBinary->GetBufferPointer();
SIZE_T bufSize = shaderBinary->GetBufferSize();
HRESULT result = disassembleFunc(buffer, bufSize, flags, "", &disassembly);
std::string asmSrc;
if (SUCCEEDED(result))
{
asmSrc = reinterpret_cast<const char*>(disassembly->GetBufferPointer());
*disassemblyOut = std::string(reinterpret_cast<const char*>(disassembly->GetBufferPointer()));
}
else
{
*disassemblyOut = "";
}
SafeRelease(disassembly);
return asmSrc;
return gl::Error(GL_NO_ERROR);
}
}

Просмотреть файл

@ -32,18 +32,20 @@ class HLSLCompiler : angle::NonCopyable
HLSLCompiler();
~HLSLCompiler();
bool initialize();
void release();
// Attempt to compile a HLSL shader using the supplied configurations, may output a NULL compiled blob
// even if no GL errors are returned.
gl::Error compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile,
const std::vector<CompileConfig> &configs, const D3D_SHADER_MACRO *overrideMacros,
ID3DBlob **outCompiledBlob, std::string *outDebugInfo) const;
ID3DBlob **outCompiledBlob, std::string *outDebugInfo);
std::string disassembleBinary(ID3DBlob* shaderBinary) const;
gl::Error disassembleBinary(ID3DBlob *shaderBinary, std::string *disassemblyOut);
private:
gl::Error initialize();
bool mInitialized;
HMODULE mD3DCompilerModule;
pD3DCompile mD3DCompileFunc;
pD3DDisassemble mD3DDisassembleFunc;

Просмотреть файл

@ -343,13 +343,6 @@ egl::Error Renderer11::initialize()
{
double loadDLLsBegin = ANGLEPlatformCurrent()->currentTime();
if (!mCompiler.initialize())
{
return egl::Error(EGL_NOT_INITIALIZED,
D3D11_INIT_COMPILER_ERROR,
"Failed to initialize compiler.");
}
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = nullptr;
{

Просмотреть файл

@ -171,13 +171,6 @@ void Renderer9::release()
egl::Error Renderer9::initialize()
{
if (!mCompiler.initialize())
{
return egl::Error(EGL_NOT_INITIALIZED,
D3D9_INIT_COMPILER_ERROR,
"Compiler failed to initialize.");
}
TRACE_EVENT0("gpu.angle", "GetModuleHandle_d3d9");
mD3d9Module = GetModuleHandle(TEXT("d3d9.dll"));