Commit 3935e51d by Geoff Lang

Refactor HLSLCompiler to use stl objects and encapulate workarounds.

* Pass std::strings for the source and profile. * Create a wrapper struct for storing the compile configurations and pass them to the compiler with an std::vector. * Remove function typedefs, they're available from the platform.h header. BUG=angle:755 Change-Id: I19dd2be1655a12f76fc5718450db974a7ec324ec Reviewed-on: https://chromium-review.googlesource.com/219287Reviewed-by: 's avatarBrandon Jones <bajones@chromium.org> Tested-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 18bd4100
...@@ -203,7 +203,7 @@ class Renderer ...@@ -203,7 +203,7 @@ class Renderer
virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type, virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers) = 0; bool separatedOutputBuffers) = 0;
virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers, D3DWorkaroundType workaround) = 0; bool separatedOutputBuffers, D3DWorkaroundType workaround) = 0;
virtual UniformStorage *createUniformStorage(size_t storageSize) = 0; virtual UniformStorage *createUniformStorage(size_t storageSize) = 0;
......
...@@ -15,6 +15,18 @@ ...@@ -15,6 +15,18 @@
namespace rx namespace rx
{ {
CompileConfig::CompileConfig()
: flags(0),
name()
{
}
CompileConfig::CompileConfig(UINT flags, const std::string &name)
: flags(flags),
name(name)
{
}
HLSLCompiler::HLSLCompiler() HLSLCompiler::HLSLCompiler()
: mD3DCompilerModule(NULL), : mD3DCompilerModule(NULL),
mD3DCompileFunc(NULL) mD3DCompileFunc(NULL)
...@@ -54,7 +66,7 @@ bool HLSLCompiler::initialize() ...@@ -54,7 +66,7 @@ bool HLSLCompiler::initialize()
return false; return false;
} }
mD3DCompileFunc = reinterpret_cast<CompileFuncPtr>(GetProcAddress(mD3DCompilerModule, "D3DCompile")); mD3DCompileFunc = reinterpret_cast<pD3DCompile>(GetProcAddress(mD3DCompilerModule, "D3DCompile"));
ASSERT(mD3DCompileFunc); ASSERT(mD3DCompileFunc);
return mD3DCompileFunc != NULL; return mD3DCompileFunc != NULL;
...@@ -70,23 +82,18 @@ void HLSLCompiler::release() ...@@ -70,23 +82,18 @@ void HLSLCompiler::release()
} }
} }
ShaderBlob *HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile, ID3DBlob *HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile,
const UINT optimizationFlags[], const char *flagNames[], int attempts) const const std::vector<CompileConfig> &configs) const
{ {
ASSERT(mD3DCompilerModule && mD3DCompileFunc); ASSERT(mD3DCompilerModule && mD3DCompileFunc);
if (!hlsl) for (size_t i = 0; i < configs.size(); ++i)
{
return NULL;
}
pD3DCompile compileFunc = reinterpret_cast<pD3DCompile>(mD3DCompileFunc);
for (int i = 0; i < attempts; ++i)
{ {
ID3DBlob *errorMessage = NULL; ID3DBlob *errorMessage = NULL;
ID3DBlob *binary = NULL; ID3DBlob *binary = NULL;
HRESULT result = compileFunc(hlsl, strlen(hlsl), gl::g_fakepath, NULL, NULL, "main", profile, optimizationFlags[i], 0, &binary, &errorMessage); HRESULT result = mD3DCompileFunc(hlsl.c_str(), hlsl.length(), gl::g_fakepath, NULL, NULL, "main", profile.c_str(),
configs[i].flags, 0, &binary, &errorMessage);
if (errorMessage) if (errorMessage)
{ {
...@@ -101,20 +108,20 @@ ShaderBlob *HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const char *hlsl ...@@ -101,20 +108,20 @@ ShaderBlob *HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const char *hlsl
if (SUCCEEDED(result)) if (SUCCEEDED(result))
{ {
return (ShaderBlob*)binary; return binary;
} }
else else
{ {
if (result == E_OUTOFMEMORY) if (result == E_OUTOFMEMORY)
{ {
return gl::error(GL_OUT_OF_MEMORY, (ShaderBlob*)NULL); return gl::error<ID3DBlob*>(GL_OUT_OF_MEMORY, NULL);
} }
infoLog.append("Warning: D3D shader compilation failed with %s flags.", flagNames[i]); infoLog.append("Warning: D3D shader compilation failed with %s flags.", configs[i].name.c_str());
if (i + 1 < attempts) if (i + 1 < configs.size())
{ {
infoLog.append(" Retrying with %s.\n", flagNames[i + 1]); infoLog.append(" Retrying with %s.\n", configs[i + 1].name.c_str());
} }
} }
} }
......
...@@ -2,6 +2,10 @@ ...@@ -2,6 +2,10 @@
#define LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_ #define LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_
#include "common/angleutils.h" #include "common/angleutils.h"
#include "common/platform.h"
#include <vector>
#include <string>
namespace gl namespace gl
{ {
...@@ -11,8 +15,14 @@ class InfoLog; ...@@ -11,8 +15,14 @@ class InfoLog;
namespace rx namespace rx
{ {
typedef void* ShaderBlob; struct CompileConfig
typedef void(*CompileFuncPtr)(); {
UINT flags;
std::string name;
CompileConfig();
CompileConfig(UINT flags, const std::string &name);
};
class HLSLCompiler class HLSLCompiler
{ {
...@@ -23,14 +33,14 @@ class HLSLCompiler ...@@ -23,14 +33,14 @@ class HLSLCompiler
bool initialize(); bool initialize();
void release(); void release();
ShaderBlob *compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile, ID3DBlob *compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile,
const UINT optimizationFlags[], const char *flagNames[], int attempts) const; const std::vector<CompileConfig> &configs) const;
private: private:
DISALLOW_COPY_AND_ASSIGN(HLSLCompiler); DISALLOW_COPY_AND_ASSIGN(HLSLCompiler);
HMODULE mD3DCompilerModule; HMODULE mD3DCompilerModule;
CompileFuncPtr mD3DCompileFunc; pD3DCompile mD3DCompileFunc;
}; };
} }
......
...@@ -137,7 +137,7 @@ ShaderExecutable *ProgramD3D::getPixelExecutableForOutputLayout(gl::InfoLog &inf ...@@ -137,7 +137,7 @@ ShaderExecutable *ProgramD3D::getPixelExecutableForOutputLayout(gl::InfoLog &inf
outputSignature); outputSignature);
// Generate new pixel executable // Generate new pixel executable
ShaderExecutable *pixelExecutable = mRenderer->compileToExecutable(infoLog, finalPixelHLSL.c_str(), rx::SHADER_PIXEL, ShaderExecutable *pixelExecutable = mRenderer->compileToExecutable(infoLog, finalPixelHLSL, rx::SHADER_PIXEL,
transformFeedbackLinkedVaryings, separatedOutputBuffers, transformFeedbackLinkedVaryings, separatedOutputBuffers,
mPixelWorkarounds); mPixelWorkarounds);
...@@ -154,7 +154,7 @@ ShaderExecutable *ProgramD3D::getVertexExecutableForInputLayout(gl::InfoLog &inf ...@@ -154,7 +154,7 @@ ShaderExecutable *ProgramD3D::getVertexExecutableForInputLayout(gl::InfoLog &inf
std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(mVertexHLSL, inputLayout, shaderAttributes); std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(mVertexHLSL, inputLayout, shaderAttributes);
// Generate new vertex executable // Generate new vertex executable
ShaderExecutable *vertexExecutable = mRenderer->compileToExecutable(infoLog, finalVertexHLSL.c_str(), ShaderExecutable *vertexExecutable = mRenderer->compileToExecutable(infoLog, finalVertexHLSL,
rx::SHADER_VERTEX, rx::SHADER_VERTEX,
transformFeedbackLinkedVaryings, separatedOutputBuffers, transformFeedbackLinkedVaryings, separatedOutputBuffers,
mVertexWorkarounds); mVertexWorkarounds);
...@@ -171,7 +171,7 @@ ShaderExecutable *ProgramD3D::getGeometryExecutable(gl::InfoLog &infoLog, gl::Sh ...@@ -171,7 +171,7 @@ ShaderExecutable *ProgramD3D::getGeometryExecutable(gl::InfoLog &infoLog, gl::Sh
std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(registers, fragmentShaderD3D, vertexShaderD3D); std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(registers, fragmentShaderD3D, vertexShaderD3D);
ShaderExecutable *geometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL.c_str(), ShaderExecutable *geometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL,
rx::SHADER_GEOMETRY, transformFeedbackLinkedVaryings, rx::SHADER_GEOMETRY, transformFeedbackLinkedVaryings,
separatedOutputBuffers, rx::ANGLE_D3D_WORKAROUND_NONE); separatedOutputBuffers, rx::ANGLE_D3D_WORKAROUND_NONE);
......
...@@ -2345,7 +2345,7 @@ ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length ...@@ -2345,7 +2345,7 @@ ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length
return executable; return executable;
} }
ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers, D3DWorkaroundType workaround) bool separatedOutputBuffers, D3DWorkaroundType workaround)
{ {
...@@ -2366,25 +2366,28 @@ ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const ch ...@@ -2366,25 +2366,28 @@ ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const ch
return NULL; return NULL;
} }
const char *profileVersion = NULL; unsigned int profileMajorVersion = 0;
unsigned int profileMinorVersion = 0;
switch (mFeatureLevel) switch (mFeatureLevel)
{ {
case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_11_0:
profileVersion = "5_0"; profileMajorVersion = 5;
profileMinorVersion = 0;
break; break;
case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_1:
profileVersion = "4_1"; profileMajorVersion = 4;
profileMinorVersion = 1;
break; break;
case D3D_FEATURE_LEVEL_10_0: case D3D_FEATURE_LEVEL_10_0:
profileVersion = "4_0"; profileMajorVersion = 4;
profileMinorVersion = 0;
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
return NULL; return NULL;
} }
char profile[32]; std::string profile = FormatString("%s_%u_%u", profileType, profileMajorVersion, profileMinorVersion);
snprintf(profile, ArraySize(profile), "%s_%s", profileType, profileVersion);
UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL0; UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL0;
...@@ -2403,29 +2406,18 @@ ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const ch ...@@ -2403,29 +2406,18 @@ ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const ch
// Sometimes D3DCompile will fail with the default compilation flags for complicated shaders when it would otherwise pass with alternative options. // 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. // Try the default flags first and if compilation fails, try some alternatives.
const UINT extraFlags[] = std::vector<CompileConfig> configs;
{ configs.push_back(CompileConfig(flags, "default" ));
flags, configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_VALIDATION, "skip validation" ));
flags | D3DCOMPILE_SKIP_VALIDATION, configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_OPTIMIZATION, "skip optimization"));
flags | D3DCOMPILE_SKIP_OPTIMIZATION
};
const static char *extraFlagNames[] =
{
"default",
"skip validation",
"skip optimization"
};
int attempts = ArraySize(extraFlags);
ID3DBlob *binary = (ID3DBlob*)mCompiler.compileToBinary(infoLog, shaderHLSL, profile, extraFlags, extraFlagNames, attempts); ID3DBlob *binary = mCompiler.compileToBinary(infoLog, shaderHLSL, profile, configs);
if (!binary) if (!binary)
{ {
return NULL; return NULL;
} }
ShaderExecutable *executable = loadExecutable((DWORD *)binary->GetBufferPointer(), binary->GetBufferSize(), type, ShaderExecutable *executable = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type,
transformFeedbackVaryings, separatedOutputBuffers); transformFeedbackVaryings, separatedOutputBuffers);
SafeRelease(binary); SafeRelease(binary);
......
...@@ -148,7 +148,7 @@ class Renderer11 : public Renderer ...@@ -148,7 +148,7 @@ class Renderer11 : public Renderer
virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type, virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers); bool separatedOutputBuffers);
virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers, D3DWorkaroundType workaround); bool separatedOutputBuffers, D3DWorkaroundType workaround);
virtual UniformStorage *createUniformStorage(size_t storageSize); virtual UniformStorage *createUniformStorage(size_t storageSize);
......
...@@ -2907,27 +2907,29 @@ ShaderExecutable *Renderer9::loadExecutable(const void *function, size_t length, ...@@ -2907,27 +2907,29 @@ ShaderExecutable *Renderer9::loadExecutable(const void *function, size_t length,
return executable; return executable;
} }
ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers, D3DWorkaroundType workaround) bool separatedOutputBuffers, D3DWorkaroundType workaround)
{ {
// Transform feedback is not supported in ES2 or D3D9 // Transform feedback is not supported in ES2 or D3D9
ASSERT(transformFeedbackVaryings.size() == 0); ASSERT(transformFeedbackVaryings.size() == 0);
const char *profile = NULL; const char *profileType = NULL;
switch (type) switch (type)
{ {
case rx::SHADER_VERTEX: case rx::SHADER_VERTEX:
profile = getMajorShaderModel() >= 3 ? "vs_3_0" : "vs_2_0"; profileType = "vs";
break; break;
case rx::SHADER_PIXEL: case rx::SHADER_PIXEL:
profile = getMajorShaderModel() >= 3 ? "ps_3_0" : "ps_2_0"; profileType = "ps";
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
return NULL; return NULL;
} }
unsigned int profileMajorVersion = (getMajorShaderModel() >= 3) ? 3 : 2;
unsigned int profileMinorVersion = 0;
std::string profile = FormatString("%s_%u_%u", profileType, profileMajorVersion, profileMinorVersion);
UINT flags = ANGLE_COMPILE_OPTIMIZATION_LEVEL; UINT flags = ANGLE_COMPILE_OPTIMIZATION_LEVEL;
...@@ -2956,23 +2958,12 @@ ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const cha ...@@ -2956,23 +2958,12 @@ ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const cha
// Sometimes D3DCompile will fail with the default compilation flags for complicated shaders when it would otherwise pass with alternative options. // 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. // Try the default flags first and if compilation fails, try some alternatives.
const UINT extraFlags[] = std::vector<CompileConfig> configs;
{ configs.push_back(CompileConfig(flags, "default" ));
flags, configs.push_back(CompileConfig(flags | D3DCOMPILE_AVOID_FLOW_CONTROL, "avoid flow control" ));
flags | D3DCOMPILE_AVOID_FLOW_CONTROL, configs.push_back(CompileConfig(flags | D3DCOMPILE_PREFER_FLOW_CONTROL, "prefer flow control"));
flags | D3DCOMPILE_PREFER_FLOW_CONTROL
};
const static char *extraFlagNames[] =
{
"default",
"avoid flow control",
"prefer flow control"
};
int attempts = ArraySize(extraFlags);
ID3DBlob *binary = (ID3DBlob*)mCompiler.compileToBinary(infoLog, shaderHLSL, profile, extraFlags, extraFlagNames, attempts); ID3DBlob *binary = mCompiler.compileToBinary(infoLog, shaderHLSL, profile, configs);
if (!binary) if (!binary)
{ {
return NULL; return NULL;
......
...@@ -152,7 +152,7 @@ class Renderer9 : public Renderer ...@@ -152,7 +152,7 @@ class Renderer9 : public Renderer
virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type, virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers); bool separatedOutputBuffers);
virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers, D3DWorkaroundType workaround); bool separatedOutputBuffers, D3DWorkaroundType workaround);
virtual UniformStorage *createUniformStorage(size_t storageSize); virtual UniformStorage *createUniformStorage(size_t storageSize);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment