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
virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
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,
bool separatedOutputBuffers, D3DWorkaroundType workaround) = 0;
virtual UniformStorage *createUniformStorage(size_t storageSize) = 0;
......
......@@ -15,6 +15,18 @@
namespace rx
{
CompileConfig::CompileConfig()
: flags(0),
name()
{
}
CompileConfig::CompileConfig(UINT flags, const std::string &name)
: flags(flags),
name(name)
{
}
HLSLCompiler::HLSLCompiler()
: mD3DCompilerModule(NULL),
mD3DCompileFunc(NULL)
......@@ -54,7 +66,7 @@ bool HLSLCompiler::initialize()
return false;
}
mD3DCompileFunc = reinterpret_cast<CompileFuncPtr>(GetProcAddress(mD3DCompilerModule, "D3DCompile"));
mD3DCompileFunc = reinterpret_cast<pD3DCompile>(GetProcAddress(mD3DCompilerModule, "D3DCompile"));
ASSERT(mD3DCompileFunc);
return mD3DCompileFunc != NULL;
......@@ -70,23 +82,18 @@ void HLSLCompiler::release()
}
}
ShaderBlob *HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile,
const UINT optimizationFlags[], const char *flagNames[], int attempts) const
ID3DBlob *HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile,
const std::vector<CompileConfig> &configs) const
{
ASSERT(mD3DCompilerModule && mD3DCompileFunc);
if (!hlsl)
{
return NULL;
}
pD3DCompile compileFunc = reinterpret_cast<pD3DCompile>(mD3DCompileFunc);
for (int i = 0; i < attempts; ++i)
for (size_t i = 0; i < configs.size(); ++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);
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)
{
......@@ -101,20 +108,20 @@ ShaderBlob *HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const char *hlsl
if (SUCCEEDED(result))
{
return (ShaderBlob*)binary;
return binary;
}
else
{
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 @@
#define LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_
#include "common/angleutils.h"
#include "common/platform.h"
#include <vector>
#include <string>
namespace gl
{
......@@ -11,8 +15,14 @@ class InfoLog;
namespace rx
{
typedef void* ShaderBlob;
typedef void(*CompileFuncPtr)();
struct CompileConfig
{
UINT flags;
std::string name;
CompileConfig();
CompileConfig(UINT flags, const std::string &name);
};
class HLSLCompiler
{
......@@ -23,14 +33,14 @@ class HLSLCompiler
bool initialize();
void release();
ShaderBlob *compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile,
const UINT optimizationFlags[], const char *flagNames[], int attempts) const;
ID3DBlob *compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile,
const std::vector<CompileConfig> &configs) const;
private:
DISALLOW_COPY_AND_ASSIGN(HLSLCompiler);
HMODULE mD3DCompilerModule;
CompileFuncPtr mD3DCompileFunc;
pD3DCompile mD3DCompileFunc;
};
}
......
......@@ -137,7 +137,7 @@ ShaderExecutable *ProgramD3D::getPixelExecutableForOutputLayout(gl::InfoLog &inf
outputSignature);
// 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,
mPixelWorkarounds);
......@@ -154,7 +154,7 @@ ShaderExecutable *ProgramD3D::getVertexExecutableForInputLayout(gl::InfoLog &inf
std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(mVertexHLSL, inputLayout, shaderAttributes);
// Generate new vertex executable
ShaderExecutable *vertexExecutable = mRenderer->compileToExecutable(infoLog, finalVertexHLSL.c_str(),
ShaderExecutable *vertexExecutable = mRenderer->compileToExecutable(infoLog, finalVertexHLSL,
rx::SHADER_VERTEX,
transformFeedbackLinkedVaryings, separatedOutputBuffers,
mVertexWorkarounds);
......@@ -171,7 +171,7 @@ ShaderExecutable *ProgramD3D::getGeometryExecutable(gl::InfoLog &infoLog, gl::Sh
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,
separatedOutputBuffers, rx::ANGLE_D3D_WORKAROUND_NONE);
......
......@@ -2345,7 +2345,7 @@ ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length
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,
bool separatedOutputBuffers, D3DWorkaroundType workaround)
{
......@@ -2366,25 +2366,28 @@ ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const ch
return NULL;
}
const char *profileVersion = NULL;
unsigned int profileMajorVersion = 0;
unsigned int profileMinorVersion = 0;
switch (mFeatureLevel)
{
case D3D_FEATURE_LEVEL_11_0:
profileVersion = "5_0";
profileMajorVersion = 5;
profileMinorVersion = 0;
break;
case D3D_FEATURE_LEVEL_10_1:
profileVersion = "4_1";
profileMajorVersion = 4;
profileMinorVersion = 1;
break;
case D3D_FEATURE_LEVEL_10_0:
profileVersion = "4_0";
profileMajorVersion = 4;
profileMinorVersion = 0;
break;
default:
UNREACHABLE();
return NULL;
}
char profile[32];
snprintf(profile, ArraySize(profile), "%s_%s", profileType, profileVersion);
std::string profile = FormatString("%s_%u_%u", profileType, profileMajorVersion, profileMinorVersion);
UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL0;
......@@ -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.
// Try the default flags first and if compilation fails, try some alternatives.
const UINT extraFlags[] =
{
flags,
flags | D3DCOMPILE_SKIP_VALIDATION,
flags | D3DCOMPILE_SKIP_OPTIMIZATION
};
const static char *extraFlagNames[] =
{
"default",
"skip validation",
"skip optimization"
};
int attempts = ArraySize(extraFlags);
std::vector<CompileConfig> configs;
configs.push_back(CompileConfig(flags, "default" ));
configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_VALIDATION, "skip validation" ));
configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_OPTIMIZATION, "skip optimization"));
ID3DBlob *binary = (ID3DBlob*)mCompiler.compileToBinary(infoLog, shaderHLSL, profile, extraFlags, extraFlagNames, attempts);
ID3DBlob *binary = mCompiler.compileToBinary(infoLog, shaderHLSL, profile, configs);
if (!binary)
{
return NULL;
}
ShaderExecutable *executable = loadExecutable((DWORD *)binary->GetBufferPointer(), binary->GetBufferSize(), type,
ShaderExecutable *executable = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type,
transformFeedbackVaryings, separatedOutputBuffers);
SafeRelease(binary);
......
......@@ -148,7 +148,7 @@ class Renderer11 : public Renderer
virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
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,
bool separatedOutputBuffers, D3DWorkaroundType workaround);
virtual UniformStorage *createUniformStorage(size_t storageSize);
......
......@@ -2907,27 +2907,29 @@ ShaderExecutable *Renderer9::loadExecutable(const void *function, size_t length,
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,
bool separatedOutputBuffers, D3DWorkaroundType workaround)
{
// Transform feedback is not supported in ES2 or D3D9
ASSERT(transformFeedbackVaryings.size() == 0);
const char *profile = NULL;
const char *profileType = NULL;
switch (type)
{
case rx::SHADER_VERTEX:
profile = getMajorShaderModel() >= 3 ? "vs_3_0" : "vs_2_0";
profileType = "vs";
break;
case rx::SHADER_PIXEL:
profile = getMajorShaderModel() >= 3 ? "ps_3_0" : "ps_2_0";
profileType = "ps";
break;
default:
UNREACHABLE();
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;
......@@ -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.
// Try the default flags first and if compilation fails, try some alternatives.
const UINT extraFlags[] =
{
flags,
flags | D3DCOMPILE_AVOID_FLOW_CONTROL,
flags | D3DCOMPILE_PREFER_FLOW_CONTROL
};
const static char *extraFlagNames[] =
{
"default",
"avoid flow control",
"prefer flow control"
};
int attempts = ArraySize(extraFlags);
std::vector<CompileConfig> configs;
configs.push_back(CompileConfig(flags, "default" ));
configs.push_back(CompileConfig(flags | D3DCOMPILE_AVOID_FLOW_CONTROL, "avoid flow control" ));
configs.push_back(CompileConfig(flags | D3DCOMPILE_PREFER_FLOW_CONTROL, "prefer flow control"));
ID3DBlob *binary = (ID3DBlob*)mCompiler.compileToBinary(infoLog, shaderHLSL, profile, extraFlags, extraFlagNames, attempts);
ID3DBlob *binary = mCompiler.compileToBinary(infoLog, shaderHLSL, profile, configs);
if (!binary)
{
return NULL;
......
......@@ -152,7 +152,7 @@ class Renderer9 : public Renderer
virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
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,
bool separatedOutputBuffers, D3DWorkaroundType workaround);
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