Refactor HLSL compilation out of Renderer.
This moves the start-up and tear-down code for D3DCompiler.dll into an object
that Renderer9 and Renderer11 use. This will help future efforts to remove
references to HLSL at the GL/Renderer interface level.
BUG=angle:558
Change-Id: I18fcf9b237265d69c1d7d2ea345696c8fd31df29
Reviewed-on: https://chromium-review.googlesource.com/185568
Tested-by: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libGLESv2/renderer/Renderer.cpp b/src/libGLESv2/renderer/Renderer.cpp
index 9ade993..78c4b2d 100644
--- a/src/libGLESv2/renderer/Renderer.cpp
+++ b/src/libGLESv2/renderer/Renderer.cpp
@@ -26,147 +26,9 @@
Renderer::Renderer(egl::Display *display) : mDisplay(display)
{
- mD3dCompilerModule = NULL;
- mD3DCompileFunc = NULL;
mCurrentClientVersion = 2;
}
-Renderer::~Renderer()
-{
- if (mD3dCompilerModule)
- {
- FreeLibrary(mD3dCompilerModule);
- mD3dCompilerModule = NULL;
- }
-}
-
-bool Renderer::initializeCompiler()
-{
- TRACE_EVENT0("gpu", "initializeCompiler");
-#if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES)
- // Find a D3DCompiler module that had already been loaded based on a predefined list of versions.
- static TCHAR* d3dCompilerNames[] = ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES;
-
- for (size_t i = 0; i < ArraySize(d3dCompilerNames); ++i)
- {
- if (GetModuleHandleEx(0, d3dCompilerNames[i], &mD3dCompilerModule))
- {
- break;
- }
- }
-#endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES
-
- if (!mD3dCompilerModule)
- {
- // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with.
- mD3dCompilerModule = LoadLibrary(D3DCOMPILER_DLL);
- }
-
- if (!mD3dCompilerModule)
- {
- ERR("No D3D compiler module found - aborting!\n");
- return false;
- }
-
- mD3DCompileFunc = reinterpret_cast<pCompileFunc>(GetProcAddress(mD3dCompilerModule, "D3DCompile"));
- ASSERT(mD3DCompileFunc);
-
- return mD3DCompileFunc != NULL;
-}
-
-// Compiles HLSL code into executable binaries
-ShaderBlob *Renderer::compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile, UINT optimizationFlags, bool alternateFlags)
-{
- if (!hlsl)
- {
- return NULL;
- }
-
- HRESULT result = S_OK;
- UINT flags = 0;
- std::string sourceText;
- if (gl::perfActive())
- {
- flags |= D3DCOMPILE_DEBUG;
-
-#ifdef NDEBUG
- flags |= optimizationFlags;
-#else
- flags |= D3DCOMPILE_SKIP_OPTIMIZATION;
-#endif
-
- std::string sourcePath = getTempPath();
- sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(hlsl);
- writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size());
- }
- else
- {
- flags |= optimizationFlags;
- sourceText = hlsl;
- }
-
- // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders when it would otherwise pass with alternative options.
- // Try the default flags first and if compilation fails, try some alternatives.
- const static UINT extraFlags[] =
- {
- 0,
- D3DCOMPILE_AVOID_FLOW_CONTROL,
- D3DCOMPILE_PREFER_FLOW_CONTROL
- };
-
- const static char * const extraFlagNames[] =
- {
- "default",
- "avoid flow control",
- "prefer flow control"
- };
-
- int attempts = alternateFlags ? ArraySize(extraFlags) : 1;
- pD3DCompile compileFunc = reinterpret_cast<pD3DCompile>(mD3DCompileFunc);
- for (int i = 0; i < attempts; ++i)
- {
- ID3DBlob *errorMessage = NULL;
- ID3DBlob *binary = NULL;
-
- result = compileFunc(hlsl, strlen(hlsl), gl::g_fakepath, NULL, NULL,
- "main", profile, flags | extraFlags[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 == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
- {
- return gl::error(GL_OUT_OF_MEMORY, (ShaderBlob*) NULL);
- }
-
- infoLog.append("Warning: D3D shader compilation failed with ");
- infoLog.append(extraFlagNames[i]);
- infoLog.append(" flags.");
- if (i + 1 < attempts)
- {
- infoLog.append(" Retrying with ");
- infoLog.append(extraFlagNames[i + 1]);
- infoLog.append(".\n");
- }
- }
- }
-
- return NULL;
-}
-
}
extern "C"
diff --git a/src/libGLESv2/renderer/Renderer.h b/src/libGLESv2/renderer/Renderer.h
index fa14806..f15482c 100644
--- a/src/libGLESv2/renderer/Renderer.h
+++ b/src/libGLESv2/renderer/Renderer.h
@@ -65,9 +65,6 @@
class TextureStorage;
class UniformStorage;
-typedef void * ShaderBlob;
-typedef void (*pCompileFunc)();
-
struct ConfigDesc
{
GLenum renderTargetFormat;
@@ -101,7 +98,6 @@
{
public:
explicit Renderer(egl::Display *display);
- virtual ~Renderer();
virtual EGLint initialize() = 0;
virtual bool resetDevice() = 0;
@@ -276,16 +272,11 @@
virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const = 0;
protected:
- bool initializeCompiler();
- ShaderBlob *compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile, UINT optimizationFlags, bool alternateFlags);
-
egl::Display *mDisplay;
private:
DISALLOW_COPY_AND_ASSIGN(Renderer);
- HMODULE mD3dCompilerModule;
- pCompileFunc mD3DCompileFunc;
int mCurrentClientVersion;
};
diff --git a/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp b/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp
new file mode 100644
index 0000000..f45ba5b
--- /dev/null
+++ b/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp
@@ -0,0 +1,163 @@
+#include "precompiled.h"
+#include "libGLESv2/renderer/d3d/HLSLCompiler.h"
+#include "libGLESv2/Program.h"
+#include "libGLESv2/main.h"
+
+#include "common/utilities.h"
+
+#include "third_party/trace_event/trace_event.h"
+
+namespace rx
+{
+
+HLSLCompiler::HLSLCompiler()
+ : mD3DCompilerModule(NULL),
+ mD3DCompileFunc(NULL)
+{
+}
+
+HLSLCompiler::~HLSLCompiler()
+{
+ release();
+}
+
+bool HLSLCompiler::initialize()
+{
+ TRACE_EVENT0("gpu", "initializeCompiler");
+#if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES)
+ // Find a D3DCompiler module that had already been loaded based on a predefined list of versions.
+ static TCHAR* d3dCompilerNames[] = ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES;
+
+ for (size_t i = 0; i < ArraySize(d3dCompilerNames); ++i)
+ {
+ if (GetModuleHandleEx(0, d3dCompilerNames[i], &mD3DCompilerModule))
+ {
+ break;
+ }
+ }
+#endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES
+
+ if (!mD3DCompilerModule)
+ {
+ // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with.
+ mD3DCompilerModule = LoadLibrary(D3DCOMPILER_DLL);
+ }
+
+ if (!mD3DCompilerModule)
+ {
+ ERR("No D3D compiler module found - aborting!\n");
+ return false;
+ }
+
+ mD3DCompileFunc = reinterpret_cast<CompileFuncPtr>(GetProcAddress(mD3DCompilerModule, "D3DCompile"));
+ ASSERT(mD3DCompileFunc);
+
+ 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,
+ unsigned int optimizationFlags, bool alternateFlags) const
+{
+ ASSERT(mD3DCompilerModule && mD3DCompileFunc);
+
+ if (!hlsl)
+ {
+ return NULL;
+ }
+
+ HRESULT result = S_OK;
+ UINT flags = 0;
+ std::string sourceText;
+ if (gl::perfActive())
+ {
+ flags |= D3DCOMPILE_DEBUG;
+
+#ifdef NDEBUG
+ flags |= optimizationFlags;
+#else
+ flags |= D3DCOMPILE_SKIP_OPTIMIZATION;
+#endif
+
+ std::string sourcePath = getTempPath();
+ sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(hlsl);
+ writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size());
+ }
+ else
+ {
+ flags |= optimizationFlags;
+ sourceText = hlsl;
+ }
+
+ // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders when it would otherwise pass with alternative options.
+ // Try the default flags first and if compilation fails, try some alternatives.
+ const static UINT extraFlags[] =
+ {
+ 0,
+ D3DCOMPILE_AVOID_FLOW_CONTROL,
+ D3DCOMPILE_PREFER_FLOW_CONTROL
+ };
+
+ const static char * const extraFlagNames[] =
+ {
+ "default",
+ "avoid flow control",
+ "prefer flow control"
+ };
+
+ int attempts = alternateFlags ? ArraySize(extraFlags) : 1;
+ pD3DCompile compileFunc = reinterpret_cast<pD3DCompile>(mD3DCompileFunc);
+ for (int i = 0; i < attempts; ++i)
+ {
+ ID3DBlob *errorMessage = NULL;
+ ID3DBlob *binary = NULL;
+
+ result = compileFunc(hlsl, strlen(hlsl), gl::g_fakepath, NULL, NULL,
+ "main", profile, flags | extraFlags[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(extraFlagNames[i]);
+ infoLog.append(" flags.");
+ if (i + 1 < attempts)
+ {
+ infoLog.append(" Retrying with ");
+ infoLog.append(extraFlagNames[i + 1]);
+ infoLog.append(".\n");
+ }
+ }
+ }
+
+ return NULL;
+}
+
+}
diff --git a/src/libGLESv2/renderer/d3d/HLSLCompiler.h b/src/libGLESv2/renderer/d3d/HLSLCompiler.h
new file mode 100644
index 0000000..cf8caf2
--- /dev/null
+++ b/src/libGLESv2/renderer/d3d/HLSLCompiler.h
@@ -0,0 +1,40 @@
+#ifndef LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_
+#define LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_
+
+#include "common/angleutils.h"
+
+#include <windows.h>
+
+namespace gl
+{
+class InfoLog;
+}
+
+namespace rx
+{
+
+typedef void* ShaderBlob;
+typedef void(*CompileFuncPtr)();
+
+class HLSLCompiler
+{
+ public:
+ HLSLCompiler();
+ ~HLSLCompiler();
+
+ bool initialize();
+ void release();
+
+ ShaderBlob *compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile,
+ unsigned int optimizationFlags, bool alternateFlags) const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HLSLCompiler);
+
+ HMODULE mD3DCompilerModule;
+ CompileFuncPtr mD3DCompileFunc;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_
diff --git a/src/libGLESv2/renderer/d3d11/Renderer11.cpp b/src/libGLESv2/renderer/d3d11/Renderer11.cpp
index 31d31c4..f9c84dd 100644
--- a/src/libGLESv2/renderer/d3d11/Renderer11.cpp
+++ b/src/libGLESv2/renderer/d3d11/Renderer11.cpp
@@ -113,7 +113,7 @@
EGLint Renderer11::initialize()
{
- if (!initializeCompiler())
+ if (!mCompiler.initialize())
{
return EGL_NOT_INITIALIZED;
}
@@ -1800,6 +1800,8 @@
FreeLibrary(mDxgiModule);
mDxgiModule = NULL;
}
+
+ mCompiler.release();
}
bool Renderer11::resetDevice()
@@ -2837,7 +2839,7 @@
return NULL;
}
- ID3DBlob *binary = (ID3DBlob*)compileToBinary(infoLog, shaderHLSL, profile, D3DCOMPILE_OPTIMIZATION_LEVEL0, false);
+ ID3DBlob *binary = (ID3DBlob*)mCompiler.compileToBinary(infoLog, shaderHLSL, profile, D3DCOMPILE_OPTIMIZATION_LEVEL0, false);
if (!binary)
{
return NULL;
diff --git a/src/libGLESv2/renderer/d3d11/Renderer11.h b/src/libGLESv2/renderer/d3d11/Renderer11.h
index 2f7d403..1a1ea0e 100644
--- a/src/libGLESv2/renderer/d3d11/Renderer11.h
+++ b/src/libGLESv2/renderer/d3d11/Renderer11.h
@@ -14,6 +14,7 @@
#include "common/mathutil.h"
#include "libGLESv2/renderer/Renderer.h"
+#include "libGLESv2/renderer/d3d/HLSLCompiler.h"
#include "libGLESv2/renderer/d3d11/RenderStateCache.h"
#include "libGLESv2/renderer/d3d11/InputLayoutCache.h"
#include "libGLESv2/renderer/RenderTarget.h"
@@ -250,6 +251,8 @@
HMODULE mDxgiModule;
HDC mDc;
+ HLSLCompiler mCompiler;
+
bool mDeviceLost;
void initializeDevice();
diff --git a/src/libGLESv2/renderer/d3d9/Renderer9.cpp b/src/libGLESv2/renderer/d3d9/Renderer9.cpp
index 2e7c083..7aae33b 100644
--- a/src/libGLESv2/renderer/d3d9/Renderer9.cpp
+++ b/src/libGLESv2/renderer/d3d9/Renderer9.cpp
@@ -156,6 +156,8 @@
SafeRelease(mD3d9);
SafeRelease(mD3d9Ex);
+ mCompiler.release();
+
if (mDeviceWindow)
{
DestroyWindow(mDeviceWindow);
@@ -173,7 +175,7 @@
EGLint Renderer9::initialize()
{
- if (!initializeCompiler())
+ if (!mCompiler.initialize())
{
return EGL_NOT_INITIALIZED;
}
@@ -3348,7 +3350,7 @@
// Work-around a D3D9 compiler bug that presents itself when using conditional discard, by disabling optimization
UINT optimizationFlags = (workaround == ANGLE_D3D_WORKAROUND_SM3_OPTIMIZER ? D3DCOMPILE_SKIP_OPTIMIZATION : ANGLE_COMPILE_OPTIMIZATION_LEVEL);
- ID3DBlob *binary = (ID3DBlob*)compileToBinary(infoLog, shaderHLSL, profile, optimizationFlags, true);
+ ID3DBlob *binary = (ID3DBlob*)mCompiler.compileToBinary(infoLog, shaderHLSL, profile, optimizationFlags, true);
if (!binary)
{
return NULL;
diff --git a/src/libGLESv2/renderer/d3d9/Renderer9.h b/src/libGLESv2/renderer/d3d9/Renderer9.h
index 78e70cc..f568cb1 100644
--- a/src/libGLESv2/renderer/d3d9/Renderer9.h
+++ b/src/libGLESv2/renderer/d3d9/Renderer9.h
@@ -11,6 +11,7 @@
#include "common/angleutils.h"
#include "common/mathutil.h"
+#include "libGLESv2/renderer/d3d/HLSLCompiler.h"
#include "libGLESv2/renderer/d3d9/ShaderCache.h"
#include "libGLESv2/renderer/d3d9/VertexDeclarationCache.h"
#include "libGLESv2/renderer/Renderer.h"
@@ -261,6 +262,8 @@
IDirect3DDevice9 *mDevice;
IDirect3DDevice9Ex *mDeviceEx; // Might be null if D3D9Ex is not supported.
+ HLSLCompiler mCompiler;
+
Blit9 *mBlit;
HWND mDeviceWindow;