Commit a6f267f9 by Jamie Madill

Fix row-major layout tracking in interface blocks.

Some block field types, such as nested structs, were bugged. This only affects our "CollectVariables" path, not our current HLSL UBO path. BUG=angle:466 Change-Id: I2b8daf58aa7ec1ad06a80d38f57e76087eacccdc Reviewed-on: https://chromium-review.googlesource.com/213503Tested-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarNicolas Capens <capn@chromium.org>
parent f05cdee4
...@@ -87,7 +87,7 @@ struct COMPILER_EXPORT InterfaceBlockField : public ShaderVariable ...@@ -87,7 +87,7 @@ struct COMPILER_EXPORT InterfaceBlockField : public ShaderVariable
InterfaceBlockField(const InterfaceBlockField &other); InterfaceBlockField(const InterfaceBlockField &other);
InterfaceBlockField &operator=(const InterfaceBlockField &other); InterfaceBlockField &operator=(const InterfaceBlockField &other);
bool isRowMajorMatrix; bool isRowMajorLayout;
}; };
struct COMPILER_EXPORT Varying : public ShaderVariable struct COMPILER_EXPORT Varying : public ShaderVariable
......
...@@ -15,62 +15,11 @@ namespace sh ...@@ -15,62 +15,11 @@ namespace sh
{ {
BlockLayoutEncoder::BlockLayoutEncoder() BlockLayoutEncoder::BlockLayoutEncoder()
: mCurrentOffset(0), : mCurrentOffset(0)
mInRowMajorField(false)
{ {
} }
template <typename VarT> BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix)
void BlockLayoutEncoder::encodeVariables(const std::vector<VarT> &fields)
{
for (unsigned int fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
{
const VarT &variable = fields[fieldIndex];
if (variable.fields.size() > 0)
{
const unsigned int elementCount = std::max(1u, variable.arraySize);
for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
{
enterAggregateType();
encodeVariables(variable.fields);
exitAggregateType();
}
}
else
{
encodeVariable(variable);
}
}
}
// Only defined for interface block fields, and shader variable base
template void BlockLayoutEncoder::encodeVariables(const std::vector<ShaderVariable> &);
template void BlockLayoutEncoder::encodeVariables(const std::vector<InterfaceBlockField> &);
BlockMemberInfo BlockLayoutEncoder::encodeVariable(const InterfaceBlockField &field)
{
mInRowMajorField = field.isRowMajorMatrix;
return encodeVariable(static_cast<ShaderVariable>(field));
}
BlockMemberInfo BlockLayoutEncoder::encodeVariable(const sh::ShaderVariable &field)
{
int arrayStride;
int matrixStride;
ASSERT(field.fields.empty());
getBlockLayoutInfo(field.type, field.arraySize, mInRowMajorField, &arrayStride, &matrixStride);
const BlockMemberInfo memberInfo(mCurrentOffset * BytesPerComponent, arrayStride * BytesPerComponent, matrixStride * BytesPerComponent, mInRowMajorField);
advanceOffset(field.type, field.arraySize, mInRowMajorField, arrayStride, matrixStride);
return memberInfo;
}
void BlockLayoutEncoder::encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix)
{ {
int arrayStride; int arrayStride;
int matrixStride; int matrixStride;
...@@ -80,6 +29,8 @@ void BlockLayoutEncoder::encodeType(GLenum type, unsigned int arraySize, bool is ...@@ -80,6 +29,8 @@ void BlockLayoutEncoder::encodeType(GLenum type, unsigned int arraySize, bool is
const BlockMemberInfo memberInfo(mCurrentOffset * BytesPerComponent, arrayStride * BytesPerComponent, matrixStride * BytesPerComponent, isRowMajorMatrix); const BlockMemberInfo memberInfo(mCurrentOffset * BytesPerComponent, arrayStride * BytesPerComponent, matrixStride * BytesPerComponent, isRowMajorMatrix);
advanceOffset(type, arraySize, isRowMajorMatrix, arrayStride, matrixStride); advanceOffset(type, arraySize, isRowMajorMatrix, arrayStride, matrixStride);
return memberInfo;
} }
void BlockLayoutEncoder::nextRegister() void BlockLayoutEncoder::nextRegister()
......
...@@ -49,13 +49,7 @@ class BlockLayoutEncoder ...@@ -49,13 +49,7 @@ class BlockLayoutEncoder
public: public:
BlockLayoutEncoder(); BlockLayoutEncoder();
template <typename VarT> BlockMemberInfo encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix);
void encodeVariables(const std::vector<VarT> &fields);
BlockMemberInfo encodeVariable(const sh::ShaderVariable &field);
BlockMemberInfo encodeVariable(const InterfaceBlockField &field);
void encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix);
size_t getBlockSize() const { return mCurrentOffset * BytesPerComponent; } size_t getBlockSize() const { return mCurrentOffset * BytesPerComponent; }
size_t getCurrentRegister() const { return mCurrentOffset / ComponentsPerRegister; } size_t getCurrentRegister() const { return mCurrentOffset / ComponentsPerRegister; }
...@@ -69,7 +63,6 @@ class BlockLayoutEncoder ...@@ -69,7 +63,6 @@ class BlockLayoutEncoder
protected: protected:
size_t mCurrentOffset; size_t mCurrentOffset;
bool mInRowMajorField;
void nextRegister(); void nextRegister();
......
...@@ -89,7 +89,7 @@ Attribute &Attribute::operator=(const Attribute &other) ...@@ -89,7 +89,7 @@ Attribute &Attribute::operator=(const Attribute &other)
} }
InterfaceBlockField::InterfaceBlockField() InterfaceBlockField::InterfaceBlockField()
: isRowMajorMatrix(false) : isRowMajorLayout(false)
{} {}
InterfaceBlockField::~InterfaceBlockField() InterfaceBlockField::~InterfaceBlockField()
...@@ -97,13 +97,13 @@ InterfaceBlockField::~InterfaceBlockField() ...@@ -97,13 +97,13 @@ InterfaceBlockField::~InterfaceBlockField()
InterfaceBlockField::InterfaceBlockField(const InterfaceBlockField &other) InterfaceBlockField::InterfaceBlockField(const InterfaceBlockField &other)
: ShaderVariable(other), : ShaderVariable(other),
isRowMajorMatrix(other.isRowMajorMatrix) isRowMajorLayout(other.isRowMajorLayout)
{} {}
InterfaceBlockField &InterfaceBlockField::operator=(const InterfaceBlockField &other) InterfaceBlockField &InterfaceBlockField::operator=(const InterfaceBlockField &other)
{ {
ShaderVariable::operator=(other); ShaderVariable::operator=(other);
isRowMajorMatrix = other.isRowMajorMatrix; isRowMajorLayout = other.isRowMajorLayout;
return *this; return *this;
} }
......
...@@ -272,6 +272,7 @@ void CollectVariables::visitVariable(const TIntermSymbol *variable, ...@@ -272,6 +272,7 @@ void CollectVariables::visitVariable(const TIntermSymbol *variable,
interfaceBlock.isRowMajorLayout = (blockType->matrixPacking() == EmpRowMajor); interfaceBlock.isRowMajorLayout = (blockType->matrixPacking() == EmpRowMajor);
interfaceBlock.layout = sh::GetBlockLayoutType(blockType->blockStorage()); interfaceBlock.layout = sh::GetBlockLayoutType(blockType->blockStorage());
// Gather field information
sh::GetInterfaceBlockFields(*blockType, &interfaceBlock.fields); sh::GetInterfaceBlockFields(*blockType, &interfaceBlock.fields);
infoList->push_back(interfaceBlock); infoList->push_back(interfaceBlock);
...@@ -356,13 +357,14 @@ bool CollectVariables::visitBinary(Visit, TIntermBinary *binaryNode) ...@@ -356,13 +357,14 @@ bool CollectVariables::visitBinary(Visit, TIntermBinary *binaryNode)
{ {
if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock) if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock)
{ {
TIntermSymbol *symbol = binaryNode->getLeft()->getAsSymbolNode(); // NOTE: we do not determine static use for individual blocks of an array
ASSERT(symbol); TIntermTyped *blockNode = binaryNode->getLeft()->getAsTyped();
ASSERT(blockNode);
TIntermConstantUnion *constantUnion = binaryNode->getRight()->getAsConstantUnion(); TIntermConstantUnion *constantUnion = binaryNode->getRight()->getAsConstantUnion();
ASSERT(constantUnion); ASSERT(constantUnion);
const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock(); const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock();
sh::InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks); sh::InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks);
ASSERT(namedBlock); ASSERT(namedBlock);
namedBlock->staticUse = true; namedBlock->staticUse = true;
......
...@@ -356,7 +356,7 @@ void GetInterfaceBlockFields(const TInterfaceBlock &interfaceBlock, std::vector< ...@@ -356,7 +356,7 @@ void GetInterfaceBlockFields(const TInterfaceBlock &interfaceBlock, std::vector<
GetVariableTraverser traverser; GetVariableTraverser traverser;
traverser.traverse(fieldType, fullFieldName, fieldsOut); traverser.traverse(fieldType, fullFieldName, fieldsOut);
fieldsOut->back().isRowMajorMatrix = (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor); fieldsOut->back().isRowMajorLayout = (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
} }
} }
......
...@@ -110,6 +110,16 @@ void GetInputLayoutFromShader(const std::vector<sh::Attribute> &shaderAttributes ...@@ -110,6 +110,16 @@ void GetInputLayoutFromShader(const std::vector<sh::Attribute> &shaderAttributes
} }
} }
bool IsRowMajorLayout(const sh::InterfaceBlockField &var)
{
return var.isRowMajorLayout;
}
bool IsRowMajorLayout(const sh::ShaderVariable &var)
{
return false;
}
} }
VariableLocation::VariableLocation(const std::string &name, unsigned int element, unsigned int index) VariableLocation::VariableLocation(const std::string &name, unsigned int element, unsigned int index)
...@@ -1879,7 +1889,7 @@ bool ProgramBinary::linkValidateInterfaceBlockFields(InfoLog &infoLog, const std ...@@ -1879,7 +1889,7 @@ bool ProgramBinary::linkValidateInterfaceBlockFields(InfoLog &infoLog, const std
return false; return false;
} }
if (vertexUniform.isRowMajorMatrix != fragmentUniform.isRowMajorMatrix) if (vertexUniform.isRowMajorLayout != fragmentUniform.isRowMajorLayout)
{ {
infoLog.append("Matrix packings for %s differ between vertex and fragment shaders", uniformName.c_str()); infoLog.append("Matrix packings for %s differ between vertex and fragment shaders", uniformName.c_str());
return false; return false;
...@@ -2273,7 +2283,8 @@ bool ProgramBinary::gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, cons ...@@ -2273,7 +2283,8 @@ bool ProgramBinary::gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, cons
template <typename VarT> template <typename VarT>
void ProgramBinary::defineUniformBlockMembers(const std::vector<VarT> &fields, const std::string &prefix, int blockIndex, void ProgramBinary::defineUniformBlockMembers(const std::vector<VarT> &fields, const std::string &prefix, int blockIndex,
sh::BlockLayoutEncoder *encoder, std::vector<unsigned int> *blockUniformIndexes) sh::BlockLayoutEncoder *encoder, std::vector<unsigned int> *blockUniformIndexes,
bool inRowMajorLayout)
{ {
for (unsigned int uniformIndex = 0; uniformIndex < fields.size(); uniformIndex++) for (unsigned int uniformIndex = 0; uniformIndex < fields.size(); uniformIndex++)
{ {
...@@ -2282,19 +2293,23 @@ void ProgramBinary::defineUniformBlockMembers(const std::vector<VarT> &fields, c ...@@ -2282,19 +2293,23 @@ void ProgramBinary::defineUniformBlockMembers(const std::vector<VarT> &fields, c
if (field.isStruct()) if (field.isStruct())
{ {
bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field));
for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++) for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++)
{ {
encoder->enterAggregateType(); encoder->enterAggregateType();
const std::string uniformElementName = fieldName + (field.isArray() ? ArrayString(arrayElement) : ""); const std::string uniformElementName = fieldName + (field.isArray() ? ArrayString(arrayElement) : "");
defineUniformBlockMembers(field.fields, uniformElementName, blockIndex, encoder, blockUniformIndexes); defineUniformBlockMembers(field.fields, uniformElementName, blockIndex, encoder, blockUniformIndexes, rowMajorLayout);
encoder->exitAggregateType(); encoder->exitAggregateType();
} }
} }
else else
{ {
sh::BlockMemberInfo memberInfo = encoder->encodeVariable(field); bool isRowMajorMatrix = (IsMatrixType(field.type) && inRowMajorLayout);
sh::BlockMemberInfo memberInfo = encoder->encodeType(field.type, field.arraySize, isRowMajorMatrix);
LinkedUniform *newUniform = new LinkedUniform(field.type, field.precision, fieldName, field.arraySize, LinkedUniform *newUniform = new LinkedUniform(field.type, field.precision, fieldName, field.arraySize,
blockIndex, memberInfo); blockIndex, memberInfo);
...@@ -2329,7 +2344,7 @@ bool ProgramBinary::defineUniformBlock(InfoLog &infoLog, const Shader &shader, c ...@@ -2329,7 +2344,7 @@ bool ProgramBinary::defineUniformBlock(InfoLog &infoLog, const Shader &shader, c
} }
ASSERT(encoder); ASSERT(encoder);
defineUniformBlockMembers(interfaceBlock.fields, "", blockIndex, encoder, &blockUniformIndexes); defineUniformBlockMembers(interfaceBlock.fields, "", blockIndex, encoder, &blockUniformIndexes, interfaceBlock.isRowMajorLayout);
size_t dataSize = encoder->getBlockSize(); size_t dataSize = encoder->getBlockSize();
......
...@@ -221,7 +221,8 @@ class ProgramBinary : public RefCountObject ...@@ -221,7 +221,8 @@ class ProgramBinary : public RefCountObject
std::vector<LinkedVarying> *outTransformFeedbackLinkedVaryings) const; std::vector<LinkedVarying> *outTransformFeedbackLinkedVaryings) const;
template <typename VarT> template <typename VarT>
void defineUniformBlockMembers(const std::vector<VarT> &fields, const std::string &prefix, int blockIndex, void defineUniformBlockMembers(const std::vector<VarT> &fields, const std::string &prefix, int blockIndex,
sh::BlockLayoutEncoder *encoder, std::vector<unsigned int> *blockUniformIndexes); sh::BlockLayoutEncoder *encoder, std::vector<unsigned int> *blockUniformIndexes,
bool inRowMajorLayout);
bool defineUniformBlock(InfoLog &infoLog, const Shader &shader, const sh::InterfaceBlock &interfaceBlock); bool defineUniformBlock(InfoLog &infoLog, const Shader &shader, const sh::InterfaceBlock &interfaceBlock);
bool assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex); bool assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex);
void defineOutputVariables(FragmentShader *fragmentShader); void defineOutputVariables(FragmentShader *fragmentShader);
......
...@@ -164,7 +164,7 @@ TEST_F(CollectVertexVariablesTest, SimpleInterfaceBlock) ...@@ -164,7 +164,7 @@ TEST_F(CollectVertexVariablesTest, SimpleInterfaceBlock)
EXPECT_TRUE(field.staticUse); EXPECT_TRUE(field.staticUse);
EXPECT_GLENUM_EQ(GL_FLOAT, field.type); EXPECT_GLENUM_EQ(GL_FLOAT, field.type);
EXPECT_EQ("f", field.name); EXPECT_EQ("f", field.name);
EXPECT_FALSE(field.isRowMajorMatrix); EXPECT_FALSE(field.isRowMajorLayout);
EXPECT_TRUE(field.fields.empty()); EXPECT_TRUE(field.fields.empty());
} }
...@@ -201,7 +201,7 @@ TEST_F(CollectVertexVariablesTest, SimpleInstancedInterfaceBlock) ...@@ -201,7 +201,7 @@ TEST_F(CollectVertexVariablesTest, SimpleInstancedInterfaceBlock)
EXPECT_TRUE(field.staticUse); EXPECT_TRUE(field.staticUse);
EXPECT_GLENUM_EQ(GL_FLOAT, field.type); EXPECT_GLENUM_EQ(GL_FLOAT, field.type);
EXPECT_EQ("b.f", field.name); EXPECT_EQ("b.f", field.name);
EXPECT_FALSE(field.isRowMajorMatrix); EXPECT_FALSE(field.isRowMajorLayout);
EXPECT_TRUE(field.fields.empty()); EXPECT_TRUE(field.fields.empty());
} }
...@@ -238,7 +238,7 @@ TEST_F(CollectVertexVariablesTest, StructInterfaceBlock) ...@@ -238,7 +238,7 @@ TEST_F(CollectVertexVariablesTest, StructInterfaceBlock)
EXPECT_TRUE(field.isStruct()); EXPECT_TRUE(field.isStruct());
EXPECT_TRUE(field.staticUse); EXPECT_TRUE(field.staticUse);
EXPECT_EQ("s", field.name); EXPECT_EQ("s", field.name);
EXPECT_FALSE(field.isRowMajorMatrix); EXPECT_FALSE(field.isRowMajorLayout);
const sh::ShaderVariable &member = field.fields[0]; const sh::ShaderVariable &member = field.fields[0];
...@@ -282,7 +282,7 @@ TEST_F(CollectVertexVariablesTest, StructInstancedInterfaceBlock) ...@@ -282,7 +282,7 @@ TEST_F(CollectVertexVariablesTest, StructInstancedInterfaceBlock)
EXPECT_TRUE(field.isStruct()); EXPECT_TRUE(field.isStruct());
EXPECT_TRUE(field.staticUse); EXPECT_TRUE(field.staticUse);
EXPECT_EQ("b.s", field.name); EXPECT_EQ("b.s", field.name);
EXPECT_FALSE(field.isRowMajorMatrix); EXPECT_FALSE(field.isRowMajorLayout);
const sh::ShaderVariable &member = field.fields[0]; const sh::ShaderVariable &member = field.fields[0];
...@@ -292,3 +292,47 @@ TEST_F(CollectVertexVariablesTest, StructInstancedInterfaceBlock) ...@@ -292,3 +292,47 @@ TEST_F(CollectVertexVariablesTest, StructInstancedInterfaceBlock)
EXPECT_GLENUM_EQ(GL_FLOAT, member.type); EXPECT_GLENUM_EQ(GL_FLOAT, member.type);
EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, member.precision); EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, member.precision);
} }
TEST_F(CollectVertexVariablesTest, NestedStructRowMajorInterfaceBlock)
{
const std::string &shaderString =
"#version 300 es\n"
"struct st { mat2 m; };"
"layout(row_major) uniform b {\n"
" st s;\n"
"};"
"void main() {\n"
" gl_Position = vec4(s.m);\n"
"}\n";
const char *shaderStrings[] = { shaderString.c_str() };
ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES));
const std::vector<sh::InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks();
ASSERT_EQ(1u, interfaceBlocks.size());
const sh::InterfaceBlock &interfaceBlock = interfaceBlocks[0];
EXPECT_EQ(0u, interfaceBlock.arraySize);
EXPECT_TRUE(interfaceBlock.isRowMajorLayout);
EXPECT_EQ(sh::BLOCKLAYOUT_SHARED, interfaceBlock.layout);
EXPECT_EQ("b", interfaceBlock.name);
EXPECT_TRUE(interfaceBlock.staticUse);
ASSERT_EQ(1u, interfaceBlock.fields.size());
const sh::InterfaceBlockField &field = interfaceBlock.fields[0];
EXPECT_TRUE(field.isStruct());
EXPECT_TRUE(field.staticUse);
EXPECT_EQ("s", field.name);
EXPECT_TRUE(field.isRowMajorLayout);
const sh::ShaderVariable &member = field.fields[0];
// NOTE: we don't currently mark struct members as statically used or not
EXPECT_FALSE(member.isStruct());
EXPECT_EQ("m", member.name);
EXPECT_GLENUM_EQ(GL_FLOAT_MAT2, member.type);
EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, member.precision);
}
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