Commit a5ef8d89 by Cooper Partin Committed by Jamie Madill

Enabled loop indexing validation for fragment shaders compiled using renderers…

Enabled loop indexing validation for fragment shaders compiled using renderers configured for FL9_3 and below. BUG=angleproject:1130 Change-Id: I2b5d7091c394565354b14fbf9297276dce8d92a5 Reviewed-on: https://chromium-review.googlesource.com/294733Tested-by: 's avatarCooper Partin <coopp@microsoft.com> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent cc16c913
...@@ -204,7 +204,8 @@ std::vector<std::string> Extensions::getStrings() const ...@@ -204,7 +204,8 @@ std::vector<std::string> Extensions::getStrings() const
Limitations::Limitations() Limitations::Limitations()
: noFrontFacingSupport(false), : noFrontFacingSupport(false),
noSampleAlphaToCoverageSupport(false), noSampleAlphaToCoverageSupport(false),
attributeZeroRequiresZeroDivisorInEXT(false) attributeZeroRequiresZeroDivisorInEXT(false),
shadersRequireIndexedLoopValidation(false)
{ {
} }
......
...@@ -248,6 +248,9 @@ struct Limitations ...@@ -248,6 +248,9 @@ struct Limitations
bool attributeZeroRequiresZeroDivisorInEXT; bool attributeZeroRequiresZeroDivisorInEXT;
// TODO: add entry for renderers that don't support separate stencil masks/refs // TODO: add entry for renderers that don't support separate stencil masks/refs
// Renderer doesn't support non-constant indexing loops in fragment shader
bool shadersRequireIndexedLoopValidation;
}; };
struct TypePrecision struct TypePrecision
......
...@@ -65,9 +65,8 @@ const std::vector<VarT> *GetShaderVariables(const std::vector<VarT> *variableLis ...@@ -65,9 +65,8 @@ const std::vector<VarT> *GetShaderVariables(const std::vector<VarT> *variableLis
return variableList; return variableList;
} }
ShaderD3D::ShaderD3D(GLenum type) ShaderD3D::ShaderD3D(GLenum type, RendererD3D *renderer)
: mShaderType(type), : mShaderType(type), mShaderVersion(100), mRenderer(renderer)
mShaderVersion(100)
{ {
uncompile(); uncompile();
} }
...@@ -152,6 +151,16 @@ void ShaderD3D::uncompile() ...@@ -152,6 +151,16 @@ void ShaderD3D::uncompile()
void ShaderD3D::compileToHLSL(ShHandle compiler, const std::string &source) void ShaderD3D::compileToHLSL(ShHandle compiler, const std::string &source)
{ {
int compileOptions = (SH_OBJECT_CODE | SH_VARIABLES); int compileOptions = (SH_OBJECT_CODE | SH_VARIABLES);
// D3D11 Feature Level 9_3 and below do not support non-constant loop indexers in fragment
// shaders.
// Shader compilation will fail. To provide a better error message we can instruct the
// compiler to pre-validate.
if (mRenderer->getRendererLimitations().shadersRequireIndexedLoopValidation)
{
compileOptions |= SH_VALIDATE_LOOP_INDEXING;
}
std::string sourcePath; std::string sourcePath;
#if !defined (ANGLE_ENABLE_WINDOWS_STORE) #if !defined (ANGLE_ENABLE_WINDOWS_STORE)
......
...@@ -25,7 +25,7 @@ class ShaderD3D : public ShaderImpl ...@@ -25,7 +25,7 @@ class ShaderD3D : public ShaderImpl
friend class DynamicHLSL; friend class DynamicHLSL;
public: public:
ShaderD3D(GLenum type); ShaderD3D(GLenum type, RendererD3D *renderer);
virtual ~ShaderD3D(); virtual ~ShaderD3D();
// ShaderImpl implementation // ShaderImpl implementation
...@@ -80,6 +80,7 @@ class ShaderD3D : public ShaderImpl ...@@ -80,6 +80,7 @@ class ShaderD3D : public ShaderImpl
std::string mDebugInfo; std::string mDebugInfo;
std::map<std::string, unsigned int> mUniformRegisterMap; std::map<std::string, unsigned int> mUniformRegisterMap;
std::map<std::string, unsigned int> mInterfaceBlockRegisterMap; std::map<std::string, unsigned int> mInterfaceBlockRegisterMap;
RendererD3D *mRenderer;
}; };
} }
......
...@@ -2974,7 +2974,7 @@ CompilerImpl *Renderer11::createCompiler(const gl::Data &data) ...@@ -2974,7 +2974,7 @@ CompilerImpl *Renderer11::createCompiler(const gl::Data &data)
ShaderImpl *Renderer11::createShader(GLenum type) ShaderImpl *Renderer11::createShader(GLenum type)
{ {
return new ShaderD3D(type); return new ShaderD3D(type, this);
} }
ProgramImpl *Renderer11::createProgram(const gl::Program::Data &data) ProgramImpl *Renderer11::createProgram(const gl::Program::Data &data)
......
...@@ -1175,6 +1175,12 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, cons ...@@ -1175,6 +1175,12 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, cons
// D3D11 Feature Level 9_3 doesn't support alpha-to-coverage // D3D11 Feature Level 9_3 doesn't support alpha-to-coverage
limitations->noSampleAlphaToCoverageSupport = (renderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3); limitations->noSampleAlphaToCoverageSupport = (renderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3);
// D3D11 Feature Levels 9_3 and below do not support non-constant loop indexing and require
// additional
// pre-validation of the shader at compile time to produce a better error message.
limitations->shadersRequireIndexedLoopValidation =
(renderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3);
#ifdef ANGLE_ENABLE_WINDOWS_STORE #ifdef ANGLE_ENABLE_WINDOWS_STORE
// Setting a non-zero divisor on attribute zero doesn't work on certain Windows Phone 8-era devices. // Setting a non-zero divisor on attribute zero doesn't work on certain Windows Phone 8-era devices.
// We should prevent developers from doing this on ALL Windows Store devices. This will maintain consistency across all Windows devices. // We should prevent developers from doing this on ALL Windows Store devices. This will maintain consistency across all Windows devices.
......
...@@ -2664,7 +2664,7 @@ CompilerImpl *Renderer9::createCompiler(const gl::Data &data) ...@@ -2664,7 +2664,7 @@ CompilerImpl *Renderer9::createCompiler(const gl::Data &data)
ShaderImpl *Renderer9::createShader(GLenum type) ShaderImpl *Renderer9::createShader(GLenum type)
{ {
return new ShaderD3D(type); return new ShaderD3D(type, this);
} }
ProgramImpl *Renderer9::createProgram(const gl::Program::Data &data) ProgramImpl *Renderer9::createProgram(const gl::Program::Data &data)
......
...@@ -1057,8 +1057,79 @@ TEST_P(GLSLTest, DISABLED_PowOfSmallConstant) ...@@ -1057,8 +1057,79 @@ TEST_P(GLSLTest, DISABLED_PowOfSmallConstant)
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
} }
// Test that fragment shaders which contain non-constant loop indexers and compiled for FL9_3 and
// below
// fail with a specific error message.
// Additionally test that the same fragment shader compiles successfully with feature levels greater
// than FL9_3.
TEST_P(GLSLTest, LoopIndexingValidation)
{
const std::string fragmentShaderSource = SHADER_SOURCE
(
precision mediump float;
uniform float loopMax;
void main()
{
gl_FragColor = vec4(1, 0, 0, 1);
for (float l = 0.0; l < loopMax; l++)
{
if (loopMax > 3.0)
{
gl_FragColor.a += 0.1;
}
}
}
);
GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
const char *sourceArray[1] = {fragmentShaderSource.c_str()};
glShaderSource(shader, 1, sourceArray, nullptr);
glCompileShader(shader);
GLint compileResult;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
// If the test is configured to run limited to Feature Level 9_3, then it is
// assumed that shader compilation will fail with an expected error message containing
// "Loop index cannot be compared with non-constant expression"
if ((GetParam() == ES2_D3D11_FL9_3()))
{
if (compileResult != 0)
{
FAIL() << "Shader compilation succeeded, expected failure";
}
else
{
GLint infoLogLength;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
std::string infoLog;
infoLog.resize(infoLogLength);
glGetShaderInfoLog(shader, static_cast<GLsizei>(infoLog.size()), NULL, &infoLog[0]);
if (infoLog.find("Loop index cannot be compared with non-constant expression") ==
std::string::npos)
{
FAIL() << "Shader compilation failed with unexpected error message";
}
}
}
else
{
EXPECT_NE(0, compileResult);
}
if (shader != 0)
{
glDeleteShader(shader);
}
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against. // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
ANGLE_INSTANTIATE_TEST(GLSLTest, ES2_D3D9(), ES2_D3D11()); ANGLE_INSTANTIATE_TEST(GLSLTest, ES2_D3D9(), ES2_D3D11(), ES2_D3D11_FL9_3());
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against. // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
ANGLE_INSTANTIATE_TEST(GLSLTest_ES3, ES3_D3D11()); ANGLE_INSTANTIATE_TEST(GLSLTest_ES3, ES3_D3D11());
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