Commit 924513cd by Alexis Hetu Committed by Alexis Hétu

Structure field type validation

Uniforms and varyings structures were simply validating that both versions in fragment and vertex shaders were structures, without validating that the fields actually matched. All the structures and data required to perform the validation at link time was added. Fixes: dEQP-GLES3.functional.shaders.linkage.uniform.struct.type_conflict_1 Change-Id: Icbf888bbebf4ccf7d27f48cb98d4cd7ea5b42ca3 Reviewed-on: https://swiftshader-review.googlesource.com/15848Tested-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com>
parent 6d12331a
...@@ -55,9 +55,9 @@ namespace glsl ...@@ -55,9 +55,9 @@ namespace glsl
bool isRowMajorMatrix; bool isRowMajorMatrix;
}; };
struct Uniform struct ShaderVariable
{ {
Uniform(GLenum type, GLenum precision, const std::string &name, int arraySize, int registerIndex, int blockId, const BlockMemberInfo& blockMemberInfo); ShaderVariable(const TType& type, const std::string& name, int registerIndex);
GLenum type; GLenum type;
GLenum precision; GLenum precision;
...@@ -66,6 +66,13 @@ namespace glsl ...@@ -66,6 +66,13 @@ namespace glsl
int registerIndex; int registerIndex;
std::vector<ShaderVariable> fields;
};
struct Uniform : public ShaderVariable
{
Uniform(const TType& type, const std::string &name, int registerIndex, int blockId, const BlockMemberInfo& blockMemberInfo);
int blockId; int blockId;
BlockMemberInfo blockInfo; BlockMemberInfo blockInfo;
}; };
...@@ -150,10 +157,10 @@ namespace glsl ...@@ -150,10 +157,10 @@ namespace glsl
typedef std::vector<Attribute> ActiveAttributes; typedef std::vector<Attribute> ActiveAttributes;
struct Varying struct Varying : public ShaderVariable
{ {
Varying(GLenum type, const std::string &name, int arraySize, TQualifier qualifier, int reg = -1, int col = -1) Varying(const TType& type, const std::string &name, int reg = -1, int col = -1)
: type(type), name(name), arraySize(arraySize), qualifier(qualifier), reg(reg), col(col) : ShaderVariable(type, name, reg), qualifier(type.getQualifier()), col(col)
{ {
} }
...@@ -167,12 +174,7 @@ namespace glsl ...@@ -167,12 +174,7 @@ namespace glsl
return arraySize > 0 ? arraySize : 1; return arraySize > 0 ? arraySize : 1;
} }
GLenum type;
std::string name;
int arraySize;
TQualifier qualifier; TQualifier qualifier;
int reg; // First varying register, assigned during link
int col; // First register element, assigned during link int col; // First register element, assigned during link
}; };
...@@ -191,6 +193,7 @@ namespace glsl ...@@ -191,6 +193,7 @@ namespace glsl
protected: protected:
VaryingList varyings; VaryingList varyings;
ActiveUniforms activeUniforms; ActiveUniforms activeUniforms;
ActiveUniforms activeUniformStructs;
ActiveAttributes activeAttributes; ActiveAttributes activeAttributes;
ActiveUniformBlocks activeUniformBlocks; ActiveUniformBlocks activeUniformBlocks;
int shaderVersion; int shaderVersion;
...@@ -310,8 +313,6 @@ namespace glsl ...@@ -310,8 +313,6 @@ namespace glsl
void free(VariableArray &list, TIntermTyped *variable); void free(VariableArray &list, TIntermTyped *variable);
void declareUniform(const TType &type, const TString &name, int registerIndex, bool samplersOnly, int blockId = -1, BlockLayoutEncoder* encoder = nullptr); void declareUniform(const TType &type, const TString &name, int registerIndex, bool samplersOnly, int blockId = -1, BlockLayoutEncoder* encoder = nullptr);
GLenum glVariableType(const TType &type);
GLenum glVariablePrecision(const TType &type);
static int dim(TIntermNode *v); static int dim(TIntermNode *v);
static int dim2(TIntermNode *m); static int dim2(TIntermNode *m);
......
...@@ -61,11 +61,11 @@ namespace es2 ...@@ -61,11 +61,11 @@ namespace es2
} }
} }
Uniform::Uniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize, Uniform::Uniform(const glsl::Uniform &uniform, const BlockInfo &blockInfo)
const BlockInfo &blockInfo) : type(uniform.type), precision(uniform.precision), name(uniform.name),
: type(type), precision(precision), name(name), arraySize(arraySize), blockInfo(blockInfo) arraySize(uniform.arraySize), blockInfo(blockInfo), fields(uniform.fields)
{ {
if(blockInfo.index == -1) if((blockInfo.index == -1) && uniform.fields.empty())
{ {
size_t bytes = UniformTypeSize(type) * size(); size_t bytes = UniformTypeSize(type) * size();
data = new unsigned char[bytes]; data = new unsigned char[bytes];
...@@ -267,7 +267,7 @@ namespace es2 ...@@ -267,7 +267,7 @@ namespace es2
{ {
int rowCount = VariableRowCount(input.type); int rowCount = VariableRowCount(input.type);
int colCount = VariableColumnCount(input.type); int colCount = VariableColumnCount(input.type);
return (subscript == GL_INVALID_INDEX) ? input.reg : input.reg + (rowCount > 1 ? colCount * subscript : subscript); return (subscript == GL_INVALID_INDEX) ? input.registerIndex : input.registerIndex + (rowCount > 1 ? colCount * subscript : subscript);
} }
} }
} }
...@@ -1337,6 +1337,11 @@ namespace es2 ...@@ -1337,6 +1337,11 @@ namespace es2
return false; return false;
} }
if(!areMatchingFields(input.fields, output.fields, input.name))
{
return false;
}
matched = true; matched = true;
break; break;
} }
...@@ -1358,8 +1363,8 @@ namespace es2 ...@@ -1358,8 +1363,8 @@ namespace es2
{ {
if(output.name == input.name) if(output.name == input.name)
{ {
int in = input.reg; int in = input.registerIndex;
int out = output.reg; int out = output.registerIndex;
int components = VariableRegisterSize(output.type); int components = VariableRegisterSize(output.type);
int registers = VariableRegisterCount(output.type) * output.size(); int registers = VariableRegisterCount(output.type) * output.size();
...@@ -1406,7 +1411,7 @@ namespace es2 ...@@ -1406,7 +1411,7 @@ namespace es2
if(tfVaryingName == output.name) if(tfVaryingName == output.name)
{ {
int out = output.reg; int out = output.registerIndex;
int components = VariableRegisterSize(output.type); int components = VariableRegisterSize(output.type);
int registers = VariableRegisterCount(output.type) * output.size(); int registers = VariableRegisterCount(output.type) * output.size();
...@@ -1484,7 +1489,7 @@ namespace es2 ...@@ -1484,7 +1489,7 @@ namespace es2
totalComponents += componentCount; totalComponents += componentCount;
int reg = varying.reg; int reg = varying.registerIndex;
if(hasSubscript) if(hasSubscript)
{ {
reg += rowCount > 1 ? colCount * subscript : subscript; reg += rowCount > 1 ? colCount * subscript : subscript;
...@@ -1683,12 +1688,8 @@ namespace es2 ...@@ -1683,12 +1688,8 @@ namespace es2
bool Program::linkUniforms(const Shader *shader) bool Program::linkUniforms(const Shader *shader)
{ {
const glsl::ActiveUniforms &activeUniforms = shader->activeUniforms; for(const auto &uniform : shader->activeUniforms)
for(unsigned int uniformIndex = 0; uniformIndex < activeUniforms.size(); uniformIndex++)
{ {
const glsl::Uniform &uniform = activeUniforms[uniformIndex];
unsigned int blockIndex = GL_INVALID_INDEX; unsigned int blockIndex = GL_INVALID_INDEX;
if(uniform.blockId >= 0) if(uniform.blockId >= 0)
{ {
...@@ -1697,7 +1698,15 @@ namespace es2 ...@@ -1697,7 +1698,15 @@ namespace es2
blockIndex = getUniformBlockIndex(activeUniformBlocks[uniform.blockId].name); blockIndex = getUniformBlockIndex(activeUniformBlocks[uniform.blockId].name);
ASSERT(blockIndex != GL_INVALID_INDEX); ASSERT(blockIndex != GL_INVALID_INDEX);
} }
if(!defineUniform(shader->getType(), uniform.type, uniform.precision, uniform.name, uniform.arraySize, uniform.registerIndex, Uniform::BlockInfo(uniform, blockIndex))) if(!defineUniform(shader->getType(), uniform, Uniform::BlockInfo(uniform, blockIndex)))
{
return false;
}
}
for(const auto &uniformStruct : shader->activeUniformStructs)
{
if(!validateUniformStruct(shader->getType(), uniformStruct))
{ {
return false; return false;
} }
...@@ -1706,11 +1715,11 @@ namespace es2 ...@@ -1706,11 +1715,11 @@ namespace es2
return true; return true;
} }
bool Program::defineUniform(GLenum shader, GLenum type, GLenum precision, const std::string &name, unsigned int arraySize, int registerIndex, const Uniform::BlockInfo& blockInfo) bool Program::defineUniform(GLenum shader, const glsl::Uniform &glslUniform, const Uniform::BlockInfo& blockInfo)
{ {
if(IsSamplerUniform(type)) if(IsSamplerUniform(glslUniform.type))
{ {
int index = registerIndex; int index = glslUniform.registerIndex;
do do
{ {
...@@ -1720,9 +1729,9 @@ namespace es2 ...@@ -1720,9 +1729,9 @@ namespace es2
{ {
samplersVS[index].active = true; samplersVS[index].active = true;
switch(type) switch(glslUniform.type)
{ {
default: UNREACHABLE(type); default: UNREACHABLE(glslUniform.type);
case GL_INT_SAMPLER_2D: case GL_INT_SAMPLER_2D:
case GL_UNSIGNED_INT_SAMPLER_2D: case GL_UNSIGNED_INT_SAMPLER_2D:
case GL_SAMPLER_2D_SHADOW: case GL_SAMPLER_2D_SHADOW:
...@@ -1755,9 +1764,9 @@ namespace es2 ...@@ -1755,9 +1764,9 @@ namespace es2
{ {
samplersPS[index].active = true; samplersPS[index].active = true;
switch(type) switch(glslUniform.type)
{ {
default: UNREACHABLE(type); default: UNREACHABLE(glslUniform.type);
case GL_INT_SAMPLER_2D: case GL_INT_SAMPLER_2D:
case GL_UNSIGNED_INT_SAMPLER_2D: case GL_UNSIGNED_INT_SAMPLER_2D:
case GL_SAMPLER_2D_SHADOW: case GL_SAMPLER_2D_SHADOW:
...@@ -1788,31 +1797,36 @@ namespace es2 ...@@ -1788,31 +1797,36 @@ namespace es2
index++; index++;
} }
while(index < registerIndex + static_cast<int>(arraySize)); while(index < glslUniform.registerIndex + static_cast<int>(glslUniform.arraySize));
} }
Uniform *uniform = 0; Uniform *uniform = 0;
GLint location = getUniformLocation(name); GLint location = getUniformLocation(glslUniform.name);
if(location >= 0) // Previously defined, types must match if(location >= 0) // Previously defined, types must match
{ {
uniform = uniforms[uniformIndex[location].index]; uniform = uniforms[uniformIndex[location].index];
if(uniform->type != type) if(uniform->type != glslUniform.type)
{ {
appendToInfoLog("Types for uniform %s do not match between the vertex and fragment shader", uniform->name.c_str()); appendToInfoLog("Types for uniform %s do not match between the vertex and fragment shader", uniform->name.c_str());
return false; return false;
} }
if(uniform->precision != precision) if(uniform->precision != glslUniform.precision)
{ {
appendToInfoLog("Precisions for uniform %s do not match between the vertex and fragment shader", uniform->name.c_str()); appendToInfoLog("Precisions for uniform %s do not match between the vertex and fragment shader", uniform->name.c_str());
return false; return false;
} }
if(!areMatchingFields(uniform->fields, glslUniform.fields, uniform->name))
{
return false;
}
} }
else else
{ {
uniform = new Uniform(type, precision, name, arraySize, blockInfo); uniform = new Uniform(glslUniform, blockInfo);
} }
if(!uniform) if(!uniform)
...@@ -1822,28 +1836,28 @@ namespace es2 ...@@ -1822,28 +1836,28 @@ namespace es2
if(shader == GL_VERTEX_SHADER) if(shader == GL_VERTEX_SHADER)
{ {
uniform->vsRegisterIndex = registerIndex; uniform->vsRegisterIndex = glslUniform.registerIndex;
} }
else if(shader == GL_FRAGMENT_SHADER) else if(shader == GL_FRAGMENT_SHADER)
{ {
uniform->psRegisterIndex = registerIndex; uniform->psRegisterIndex = glslUniform.registerIndex;
} }
else UNREACHABLE(shader); else UNREACHABLE(shader);
if(!isUniformDefined(name)) if(!isUniformDefined(glslUniform.name))
{ {
uniforms.push_back(uniform); uniforms.push_back(uniform);
unsigned int index = (blockInfo.index == -1) ? static_cast<unsigned int>(uniforms.size() - 1) : GL_INVALID_INDEX; unsigned int index = (blockInfo.index == -1) ? static_cast<unsigned int>(uniforms.size() - 1) : GL_INVALID_INDEX;
for(int i = 0; i < uniform->size(); i++) for(int i = 0; i < uniform->size(); i++)
{ {
uniformIndex.push_back(UniformLocation(name, i, index)); uniformIndex.push_back(UniformLocation(glslUniform.name, i, index));
} }
} }
if(shader == GL_VERTEX_SHADER) if(shader == GL_VERTEX_SHADER)
{ {
if(registerIndex + uniform->registerCount() > MAX_VERTEX_UNIFORM_VECTORS) if(glslUniform.registerIndex + uniform->registerCount() > MAX_VERTEX_UNIFORM_VECTORS)
{ {
appendToInfoLog("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%d)", MAX_VERTEX_UNIFORM_VECTORS); appendToInfoLog("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%d)", MAX_VERTEX_UNIFORM_VECTORS);
return false; return false;
...@@ -1851,7 +1865,7 @@ namespace es2 ...@@ -1851,7 +1865,7 @@ namespace es2
} }
else if(shader == GL_FRAGMENT_SHADER) else if(shader == GL_FRAGMENT_SHADER)
{ {
if(registerIndex + uniform->registerCount() > MAX_FRAGMENT_UNIFORM_VECTORS) if(glslUniform.registerIndex + uniform->registerCount() > MAX_FRAGMENT_UNIFORM_VECTORS)
{ {
appendToInfoLog("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%d)", MAX_FRAGMENT_UNIFORM_VECTORS); appendToInfoLog("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%d)", MAX_FRAGMENT_UNIFORM_VECTORS);
return false; return false;
...@@ -1862,6 +1876,21 @@ namespace es2 ...@@ -1862,6 +1876,21 @@ namespace es2
return true; return true;
} }
bool Program::validateUniformStruct(GLenum shader, const glsl::Uniform &newUniformStruct)
{
for(const auto &uniformStruct : uniformStructs)
{
if(uniformStruct.name == newUniformStruct.name)
{
return areMatchingFields(uniformStruct.fields, newUniformStruct.fields, newUniformStruct.name);
}
}
uniformStructs.push_back(Uniform(newUniformStruct, Uniform::BlockInfo(newUniformStruct, -1)));
return true;
}
bool Program::areMatchingUniformBlocks(const glsl::UniformBlock &block1, const glsl::UniformBlock &block2, const Shader *shader1, const Shader *shader2) bool Program::areMatchingUniformBlocks(const glsl::UniformBlock &block1, const glsl::UniformBlock &block2, const Shader *shader1, const Shader *shader2)
{ {
// validate blocks for the same member types // validate blocks for the same member types
...@@ -1915,6 +1944,41 @@ namespace es2 ...@@ -1915,6 +1944,41 @@ namespace es2
return true; return true;
} }
bool Program::areMatchingFields(const std::vector<glsl::ShaderVariable>& fields1, const std::vector<glsl::ShaderVariable>& fields2, const std::string& name)
{
if(fields1.size() != fields2.size())
{
appendToInfoLog("Structure lengths for %s differ between vertex and fragment shaders", name.c_str());
return false;
}
for(int i = 0; i < fields1.size(); ++i)
{
if(fields1[i].name != fields2[i].name)
{
appendToInfoLog("Name mismatch for field '%d' of %s: ('%s', '%s')",
i, name.c_str(), fields1[i].name.c_str(), fields2[i].name.c_str());
return false;
}
if(fields1[i].type != fields2[i].type)
{
appendToInfoLog("Type for %s.%s differ between vertex and fragment shaders", name.c_str(), fields1[i].name.c_str());
return false;
}
if(fields1[i].arraySize != fields2[i].arraySize)
{
appendToInfoLog("Array size for %s.%s differ between vertex and fragment shaders", name.c_str(), fields1[i].name.c_str());
return false;
}
if(!areMatchingFields(fields1[i].fields, fields2[i].fields, fields1[i].name))
{
return false;
}
}
return true;
}
bool Program::linkUniformBlocks(const Shader *vertexShader, const Shader *fragmentShader) bool Program::linkUniformBlocks(const Shader *vertexShader, const Shader *fragmentShader)
{ {
const glsl::ActiveUniformBlocks &vertexUniformBlocks = vertexShader->activeUniformBlocks; const glsl::ActiveUniformBlocks &vertexUniformBlocks = vertexShader->activeUniformBlocks;
......
...@@ -49,8 +49,7 @@ namespace es2 ...@@ -49,8 +49,7 @@ namespace es2
bool isRowMajorMatrix; bool isRowMajorMatrix;
}; };
Uniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize, Uniform(const glsl::Uniform &uniform, const BlockInfo &blockInfo);
const BlockInfo &blockInfo);
~Uniform(); ~Uniform();
...@@ -63,6 +62,7 @@ namespace es2 ...@@ -63,6 +62,7 @@ namespace es2
const std::string name; const std::string name;
const unsigned int arraySize; const unsigned int arraySize;
const BlockInfo blockInfo; const BlockInfo blockInfo;
std::vector<glsl::ShaderVariable> fields;
unsigned char *data; unsigned char *data;
bool dirty; bool dirty;
...@@ -234,7 +234,9 @@ namespace es2 ...@@ -234,7 +234,9 @@ namespace es2
bool linkUniforms(const Shader *shader); bool linkUniforms(const Shader *shader);
bool linkUniformBlocks(const Shader *vertexShader, const Shader *fragmentShader); bool linkUniformBlocks(const Shader *vertexShader, const Shader *fragmentShader);
bool areMatchingUniformBlocks(const glsl::UniformBlock &block1, const glsl::UniformBlock &block2, const Shader *shader1, const Shader *shader2); bool areMatchingUniformBlocks(const glsl::UniformBlock &block1, const glsl::UniformBlock &block2, const Shader *shader1, const Shader *shader2);
bool defineUniform(GLenum shader, GLenum type, GLenum precision, const std::string &_name, unsigned int arraySize, int registerIndex, const Uniform::BlockInfo& blockInfo); bool areMatchingFields(const std::vector<glsl::ShaderVariable>& fields1, const std::vector<glsl::ShaderVariable>& fields2, const std::string& name);
bool validateUniformStruct(GLenum shader, const glsl::Uniform &newUniformStruct);
bool defineUniform(GLenum shader, const glsl::Uniform &uniform, const Uniform::BlockInfo& blockInfo);
bool defineUniformBlock(const Shader *shader, const glsl::UniformBlock &block); bool defineUniformBlock(const Shader *shader, const glsl::UniformBlock &block);
bool applyUniform(Device *device, GLint location, float* data); bool applyUniform(Device *device, GLint location, float* data);
bool applyUniform1bv(Device *device, GLint location, GLsizei count, const GLboolean *v); bool applyUniform1bv(Device *device, GLint location, GLsizei count, const GLboolean *v);
...@@ -303,6 +305,8 @@ namespace es2 ...@@ -303,6 +305,8 @@ namespace es2
typedef std::vector<Uniform*> UniformArray; typedef std::vector<Uniform*> UniformArray;
UniformArray uniforms; UniformArray uniforms;
typedef std::vector<Uniform> UniformStructArray;
UniformStructArray uniformStructs;
typedef std::vector<UniformLocation> UniformIndex; typedef std::vector<UniformLocation> UniformIndex;
UniformIndex uniformIndex; UniformIndex uniformIndex;
typedef std::vector<UniformBlock*> UniformBlockArray; typedef std::vector<UniformBlock*> UniformBlockArray;
......
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