Commit 3da79b7b by Jamie Madill

Reject shaders using attribute aliasing.

The current code rejects any shaders that use more than the caps allow, but a bug would crash us before the check. We don't support aliasing in shaders that use a lot of uniforms because this causes problems with the D3D back-end, currently. This changes the crash in the dEQP aliasing tests to a link error. See dEQP-GLES2.functional.attribute_location.bind_aliasing.* BUG=angleproject:901 Change-Id: I6906d3345abe9f89cfa0aa6cec4be26b5b2851d0 Reviewed-on: https://chromium-review.googlesource.com/266928Tested-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarBrandon Jones <bajones@chromium.org>
parent 30cb86d8
...@@ -322,7 +322,7 @@ Error Program::link(const Data &data) ...@@ -322,7 +322,7 @@ Error Program::link(const Data &data)
} }
ASSERT(mVertexShader->getType() == GL_VERTEX_SHADER); ASSERT(mVertexShader->getType() == GL_VERTEX_SHADER);
if (!linkAttributes(mInfoLog, mAttributeBindings, mVertexShader)) if (!linkAttributes(data, mInfoLog, mAttributeBindings, mVertexShader))
{ {
return Error(GL_NO_ERROR); return Error(GL_NO_ERROR);
} }
...@@ -446,15 +446,25 @@ Error Program::loadBinary(GLenum binaryFormat, const void *binary, GLsizei lengt ...@@ -446,15 +446,25 @@ Error Program::loadBinary(GLenum binaryFormat, const void *binary, GLsizei lengt
return Error(GL_NO_ERROR); return Error(GL_NO_ERROR);
} }
// TODO(jmadill): replace MAX_VERTEX_ATTRIBS
for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i) for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
{ {
stream.readInt(&mLinkedAttribute[i].type); stream.readInt(&mLinkedAttribute[i].type);
stream.readString(&mLinkedAttribute[i].name); stream.readString(&mLinkedAttribute[i].name);
stream.readInt(&mProgram->getShaderAttributes()[i].type);
stream.readString(&mProgram->getShaderAttributes()[i].name);
stream.readInt(&mProgram->getSemanticIndexes()[i]); stream.readInt(&mProgram->getSemanticIndexes()[i]);
} }
unsigned int attribCount = stream.readInt<unsigned int>();
for (unsigned int attribIndex = 0; attribIndex < attribCount; ++attribIndex)
{
GLenum type = stream.readInt<GLenum>();
GLenum precision = stream.readInt<GLenum>();
std::string name = stream.readString();
GLint arraySize = stream.readInt<GLint>();
int location = stream.readInt<int>();
mProgram->setShaderAttribute(attribIndex, type, precision, name, arraySize, location);
}
rx::LinkResult result = mProgram->load(mInfoLog, &stream); rx::LinkResult result = mProgram->load(mInfoLog, &stream);
if (result.error.isError() || !result.linkSuccess) if (result.error.isError() || !result.linkSuccess)
{ {
...@@ -480,15 +490,25 @@ Error Program::saveBinary(GLenum *binaryFormat, void *binary, GLsizei bufSize, G ...@@ -480,15 +490,25 @@ Error Program::saveBinary(GLenum *binaryFormat, void *binary, GLsizei bufSize, G
stream.writeInt(ANGLE_MINOR_VERSION); stream.writeInt(ANGLE_MINOR_VERSION);
stream.writeBytes(reinterpret_cast<const unsigned char*>(ANGLE_COMMIT_HASH), ANGLE_COMMIT_HASH_SIZE); stream.writeBytes(reinterpret_cast<const unsigned char*>(ANGLE_COMMIT_HASH), ANGLE_COMMIT_HASH_SIZE);
// TODO(jmadill): replace MAX_VERTEX_ATTRIBS
for (unsigned int i = 0; i < MAX_VERTEX_ATTRIBS; ++i) for (unsigned int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
{ {
stream.writeInt(mLinkedAttribute[i].type); stream.writeInt(mLinkedAttribute[i].type);
stream.writeString(mLinkedAttribute[i].name); stream.writeString(mLinkedAttribute[i].name);
stream.writeInt(mProgram->getShaderAttributes()[i].type);
stream.writeString(mProgram->getShaderAttributes()[i].name);
stream.writeInt(mProgram->getSemanticIndexes()[i]); stream.writeInt(mProgram->getSemanticIndexes()[i]);
} }
const auto &shaderAttributes = mProgram->getShaderAttributes();
stream.writeInt(shaderAttributes.size());
for (const auto &attrib : shaderAttributes)
{
stream.writeInt(attrib.type);
stream.writeInt(attrib.precision);
stream.writeString(attrib.name);
stream.writeInt(attrib.arraySize);
stream.writeInt(attrib.location);
}
gl::Error error = mProgram->save(&stream); gl::Error error = mProgram->save(&stream);
if (error.isError()) if (error.isError())
{ {
...@@ -1306,10 +1326,21 @@ bool Program::linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::stri ...@@ -1306,10 +1326,21 @@ bool Program::linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::stri
} }
// Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices // Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices
bool Program::linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, const Shader *vertexShader) bool Program::linkAttributes(const Data &data,
InfoLog &infoLog,
const AttributeBindings &attributeBindings,
const Shader *vertexShader)
{ {
unsigned int usedLocations = 0; unsigned int usedLocations = 0;
const std::vector<sh::Attribute> &shaderAttributes = vertexShader->getActiveAttributes(); const std::vector<sh::Attribute> &shaderAttributes = vertexShader->getActiveAttributes();
GLuint maxAttribs = data.caps->maxVertexAttributes;
// TODO(jmadill): handle aliasing robustly
if (shaderAttributes.size() >= maxAttribs)
{
infoLog.append("Too many vertex attributes.");
return false;
}
// Link attributes that have a binding location // Link attributes that have a binding location
for (unsigned int attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++) for (unsigned int attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++)
...@@ -1320,13 +1351,13 @@ bool Program::linkAttributes(InfoLog &infoLog, const AttributeBindings &attribut ...@@ -1320,13 +1351,13 @@ bool Program::linkAttributes(InfoLog &infoLog, const AttributeBindings &attribut
const int location = attribute.location == -1 ? attributeBindings.getAttributeBinding(attribute.name) : attribute.location; const int location = attribute.location == -1 ? attributeBindings.getAttributeBinding(attribute.name) : attribute.location;
mProgram->getShaderAttributes()[attributeIndex] = attribute; mProgram->setShaderAttribute(attributeIndex, attribute);
if (location != -1) // Set by glBindAttribLocation or by location layout qualifier if (location != -1) // Set by glBindAttribLocation or by location layout qualifier
{ {
const int rows = VariableRegisterCount(attribute.type); const int rows = VariableRegisterCount(attribute.type);
if (rows + location > MAX_VERTEX_ATTRIBS) if (static_cast<GLuint>(rows + location) > maxAttribs)
{ {
infoLog.append("Active attribute (%s) at location %d is too big to fit", attribute.name.c_str(), location); infoLog.append("Active attribute (%s) at location %d is too big to fit", attribute.name.c_str(), location);
...@@ -1339,8 +1370,9 @@ bool Program::linkAttributes(InfoLog &infoLog, const AttributeBindings &attribut ...@@ -1339,8 +1370,9 @@ bool Program::linkAttributes(InfoLog &infoLog, const AttributeBindings &attribut
sh::ShaderVariable &linkedAttribute = mLinkedAttribute[rowLocation]; sh::ShaderVariable &linkedAttribute = mLinkedAttribute[rowLocation];
// In GLSL 3.00, attribute aliasing produces a link error // In GLSL 3.00, attribute aliasing produces a link error
// In GLSL 1.00, attribute aliasing is allowed // In GLSL 1.00, attribute aliasing is allowed, but ANGLE currently has a bug
if (mProgram->getShaderVersion() >= 300) // TODO(jmadill): fix aliasing on ES2
// if (mProgram->getShaderVersion() >= 300)
{ {
if (!linkedAttribute.name.empty()) if (!linkedAttribute.name.empty())
{ {
...@@ -1367,9 +1399,9 @@ bool Program::linkAttributes(InfoLog &infoLog, const AttributeBindings &attribut ...@@ -1367,9 +1399,9 @@ bool Program::linkAttributes(InfoLog &infoLog, const AttributeBindings &attribut
if (location == -1) // Not set by glBindAttribLocation or by location layout qualifier if (location == -1) // Not set by glBindAttribLocation or by location layout qualifier
{ {
int rows = VariableRegisterCount(attribute.type); int rows = VariableRegisterCount(attribute.type);
int availableIndex = AllocateFirstFreeBits(&usedLocations, rows, MAX_VERTEX_ATTRIBS); int availableIndex = AllocateFirstFreeBits(&usedLocations, rows, maxAttribs);
if (availableIndex == -1 || availableIndex + rows > MAX_VERTEX_ATTRIBS) if (availableIndex == -1 || static_cast<GLuint>(availableIndex + rows) > maxAttribs)
{ {
infoLog.append("Too many active attributes (%s)", attribute.name.c_str()); infoLog.append("Too many active attributes (%s)", attribute.name.c_str());
...@@ -1380,7 +1412,7 @@ bool Program::linkAttributes(InfoLog &infoLog, const AttributeBindings &attribut ...@@ -1380,7 +1412,7 @@ bool Program::linkAttributes(InfoLog &infoLog, const AttributeBindings &attribut
} }
} }
for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; ) for (GLuint attributeIndex = 0; attributeIndex < maxAttribs;)
{ {
int index = vertexShader->getSemanticIndex(mLinkedAttribute[attributeIndex].name); int index = vertexShader->getSemanticIndex(mLinkedAttribute[attributeIndex].name);
int rows = VariableRegisterCount(mLinkedAttribute[attributeIndex].type); int rows = VariableRegisterCount(mLinkedAttribute[attributeIndex].type);
......
...@@ -224,7 +224,10 @@ class Program : angle::NonCopyable ...@@ -224,7 +224,10 @@ class Program : angle::NonCopyable
void unlink(bool destroy = false); void unlink(bool destroy = false);
void resetUniformBlockBindings(); void resetUniformBlockBindings();
bool linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, const Shader *vertexShader); bool linkAttributes(const Data &data,
InfoLog &infoLog,
const AttributeBindings &attributeBindings,
const Shader *vertexShader);
bool linkUniformBlocks(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps); bool linkUniformBlocks(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps);
bool areMatchingInterfaceBlocks(gl::InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, bool areMatchingInterfaceBlocks(gl::InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock,
const sh::InterfaceBlock &fragmentInterfaceBlock); const sh::InterfaceBlock &fragmentInterfaceBlock);
......
...@@ -131,4 +131,26 @@ void ProgramImpl::reset() ...@@ -131,4 +131,26 @@ void ProgramImpl::reset()
mTransformFeedbackLinkedVaryings.clear(); mTransformFeedbackLinkedVaryings.clear();
} }
void ProgramImpl::setShaderAttribute(size_t index, const sh::Attribute &attrib)
{
if (mShaderAttributes.size() <= index)
{
mShaderAttributes.resize(index + 1);
}
mShaderAttributes[index] = attrib;
}
void ProgramImpl::setShaderAttribute(size_t index, GLenum type, GLenum precision, const std::string &name, GLint size, int location)
{
if (mShaderAttributes.size() <= index)
{
mShaderAttributes.resize(index + 1);
}
mShaderAttributes[index].type = type;
mShaderAttributes[index].precision = precision;
mShaderAttributes[index].name = name;
mShaderAttributes[index].arraySize = size;
mShaderAttributes[index].location = location;
}
} }
...@@ -102,14 +102,13 @@ class ProgramImpl : angle::NonCopyable ...@@ -102,14 +102,13 @@ class ProgramImpl : angle::NonCopyable
const std::vector<gl::VariableLocation> &getUniformIndices() const { return mUniformIndex; } const std::vector<gl::VariableLocation> &getUniformIndices() const { return mUniformIndex; }
const std::vector<gl::UniformBlock*> &getUniformBlocks() const { return mUniformBlocks; } const std::vector<gl::UniformBlock*> &getUniformBlocks() const { return mUniformBlocks; }
const std::vector<gl::LinkedVarying> &getTransformFeedbackLinkedVaryings() const { return mTransformFeedbackLinkedVaryings; } const std::vector<gl::LinkedVarying> &getTransformFeedbackLinkedVaryings() const { return mTransformFeedbackLinkedVaryings; }
const sh::Attribute *getShaderAttributes() const { return mShaderAttributes; } const std::vector<sh::Attribute> getShaderAttributes() { return mShaderAttributes; }
const SemanticIndexArray &getSemanticIndexes() const { return mSemanticIndex; } const SemanticIndexArray &getSemanticIndexes() const { return mSemanticIndex; }
std::vector<gl::LinkedUniform*> &getUniforms() { return mUniforms; } std::vector<gl::LinkedUniform*> &getUniforms() { return mUniforms; }
std::vector<gl::VariableLocation> &getUniformIndices() { return mUniformIndex; } std::vector<gl::VariableLocation> &getUniformIndices() { return mUniformIndex; }
std::vector<gl::UniformBlock*> &getUniformBlocks() { return mUniformBlocks; } std::vector<gl::UniformBlock*> &getUniformBlocks() { return mUniformBlocks; }
std::vector<gl::LinkedVarying> &getTransformFeedbackLinkedVaryings() { return mTransformFeedbackLinkedVaryings; } std::vector<gl::LinkedVarying> &getTransformFeedbackLinkedVaryings() { return mTransformFeedbackLinkedVaryings; }
sh::Attribute *getShaderAttributes() { return mShaderAttributes; }
SemanticIndexArray &getSemanticIndexes() { return mSemanticIndex; } SemanticIndexArray &getSemanticIndexes() { return mSemanticIndex; }
gl::LinkedUniform *getUniformByLocation(GLint location) const; gl::LinkedUniform *getUniformByLocation(GLint location) const;
...@@ -120,6 +119,9 @@ class ProgramImpl : angle::NonCopyable ...@@ -120,6 +119,9 @@ class ProgramImpl : angle::NonCopyable
GLuint getUniformIndex(const std::string &name) const; GLuint getUniformIndex(const std::string &name) const;
GLuint getUniformBlockIndex(const std::string &name) const; GLuint getUniformBlockIndex(const std::string &name) const;
void setShaderAttribute(size_t index, const sh::Attribute &attrib);
void setShaderAttribute(size_t index, GLenum type, GLenum precision, const std::string &name, GLint size, int location);
virtual void reset(); virtual void reset();
protected: protected:
...@@ -129,7 +131,9 @@ class ProgramImpl : angle::NonCopyable ...@@ -129,7 +131,9 @@ class ProgramImpl : angle::NonCopyable
std::vector<gl::LinkedVarying> mTransformFeedbackLinkedVaryings; std::vector<gl::LinkedVarying> mTransformFeedbackLinkedVaryings;
SemanticIndexArray mSemanticIndex; SemanticIndexArray mSemanticIndex;
sh::Attribute mShaderAttributes[gl::MAX_VERTEX_ATTRIBS];
private:
std::vector<sh::Attribute> mShaderAttributes;
}; };
} }
......
...@@ -379,7 +379,7 @@ std::string DynamicHLSL::generateVaryingHLSL(const ShaderD3D *shader) const ...@@ -379,7 +379,7 @@ std::string DynamicHLSL::generateVaryingHLSL(const ShaderD3D *shader) const
std::string DynamicHLSL::generateVertexShaderForInputLayout(const std::string &sourceShader, std::string DynamicHLSL::generateVertexShaderForInputLayout(const std::string &sourceShader,
const VertexFormat inputLayout[], const VertexFormat inputLayout[],
const sh::Attribute shaderAttributes[]) const const std::vector<sh::Attribute> &shaderAttributes) const
{ {
std::string structHLSL, initHLSL; std::string structHLSL, initHLSL;
...@@ -406,7 +406,7 @@ std::string DynamicHLSL::generateVertexShaderForInputLayout(const std::string &s ...@@ -406,7 +406,7 @@ std::string DynamicHLSL::generateVertexShaderForInputLayout(const std::string &s
structHLSL += " float2 spriteTexCoord : SPRITETEXCOORD0;\n"; structHLSL += " float2 spriteTexCoord : SPRITETEXCOORD0;\n";
} }
for (unsigned int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) for (size_t attributeIndex = 0; attributeIndex < shaderAttributes.size(); ++attributeIndex)
{ {
const sh::Attribute &shaderAttribute = shaderAttributes[attributeIndex]; const sh::Attribute &shaderAttribute = shaderAttributes[attributeIndex];
if (!shaderAttribute.name.empty()) if (!shaderAttribute.name.empty())
......
...@@ -56,8 +56,9 @@ class DynamicHLSL : angle::NonCopyable ...@@ -56,8 +56,9 @@ class DynamicHLSL : angle::NonCopyable
int packVaryings(gl::InfoLog &infoLog, VaryingPacking packing, ShaderD3D *fragmentShader, int packVaryings(gl::InfoLog &infoLog, VaryingPacking packing, ShaderD3D *fragmentShader,
ShaderD3D *vertexShader, const std::vector<std::string>& transformFeedbackVaryings); ShaderD3D *vertexShader, const std::vector<std::string>& transformFeedbackVaryings);
std::string generateVertexShaderForInputLayout(const std::string &sourceShader, const gl::VertexFormat inputLayout[], std::string generateVertexShaderForInputLayout(const std::string &sourceShader,
const sh::Attribute shaderAttributes[]) const; const gl::VertexFormat inputLayout[],
const std::vector<sh::Attribute> &shaderAttributes) const;
std::string generatePixelShaderForOutputSignature(const std::string &sourceShader, const std::vector<PixelShaderOutputVariable> &outputVariables, std::string generatePixelShaderForOutputSignature(const std::string &sourceShader, const std::vector<PixelShaderOutputVariable> &outputVariables,
bool usesFragDepth, const std::vector<GLenum> &outputLayout) const; bool usesFragDepth, const std::vector<GLenum> &outputLayout) const;
bool generateShaderLinkHLSL(const gl::Data &data, gl::InfoLog &infoLog, int registers, bool generateShaderLinkHLSL(const gl::Data &data, gl::InfoLog &infoLog, int registers,
......
...@@ -924,7 +924,7 @@ gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::VertexFormat i ...@@ -924,7 +924,7 @@ gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::VertexFormat i
} }
// Generate new dynamic layout with attribute conversions // Generate new dynamic layout with attribute conversions
std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(mVertexHLSL, inputLayout, mShaderAttributes); std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(mVertexHLSL, inputLayout, getShaderAttributes());
// Generate new vertex executable // Generate new vertex executable
ShaderExecutableD3D *vertexExecutable = NULL; ShaderExecutableD3D *vertexExecutable = NULL;
......
...@@ -183,12 +183,8 @@ LinkResult ProgramGL::link(const gl::Data &data, gl::InfoLog &infoLog, ...@@ -183,12 +183,8 @@ LinkResult ProgramGL::link(const gl::Data &data, gl::InfoLog &infoLog,
std::string attributeName(&attributeNameBuffer[0], attributeNameLength); std::string attributeName(&attributeNameBuffer[0], attributeNameLength);
mShaderAttributes[i].type = attributeType;
// TODO: determine attribute precision // TODO: determine attribute precision
mShaderAttributes[i].precision = GL_NONE; setShaderAttribute(static_cast<size_t>(i), attributeType, GL_NONE, attributeName, attributeSize, i);
mShaderAttributes[i].name = attributeName;
mShaderAttributes[i].arraySize = attributeSize;
mShaderAttributes[i].location = i;
} }
return LinkResult(true, gl::Error(GL_NO_ERROR)); return LinkResult(true, gl::Error(GL_NO_ERROR));
......
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