Row major matrix packing fix
Row major matrix packing wasn't properly detected when the layout
qualifier was on the block member rather than on the block itself
or when a nested structure had a matrix packing qualifier.
Fixes all failing tests in:
deqp/functional/gles3/uniformbuffers*
No regressions in:
dEQP-GLES3.functional.ubo*
Change-Id: I1549a70c4286a8a84b695bc876d71d9cf636b306
Reviewed-on: https://swiftshader-review.googlesource.com/16588
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/OpenGL/compiler/OutputASM.cpp b/src/OpenGL/compiler/OutputASM.cpp
index 76a177a..4ef41be 100644
--- a/src/OpenGL/compiler/OutputASM.cpp
+++ b/src/OpenGL/compiler/OutputASM.cpp
@@ -285,8 +285,8 @@
{
}
- BlockLayoutEncoder::BlockLayoutEncoder(bool rowMajor)
- : mCurrentOffset(0), isRowMajor(rowMajor)
+ BlockLayoutEncoder::BlockLayoutEncoder()
+ : mCurrentOffset(0)
{
}
@@ -295,20 +295,15 @@
int arrayStride;
int matrixStride;
- bool isVariableRowMajor = isRowMajor;
- TLayoutMatrixPacking matrixPacking = type.getLayoutQualifier().matrixPacking;
- if(matrixPacking != EmpUnspecified)
- {
- isVariableRowMajor = (matrixPacking == EmpRowMajor);
- }
- getBlockLayoutInfo(type, type.getArraySize(), isVariableRowMajor, &arrayStride, &matrixStride);
+ bool isRowMajor = type.getLayoutQualifier().matrixPacking == EmpRowMajor;
+ getBlockLayoutInfo(type, type.getArraySize(), isRowMajor, &arrayStride, &matrixStride);
const BlockMemberInfo memberInfo(static_cast<int>(mCurrentOffset * BytesPerComponent),
static_cast<int>(arrayStride * BytesPerComponent),
static_cast<int>(matrixStride * BytesPerComponent),
- (matrixStride > 0) && isVariableRowMajor);
+ (matrixStride > 0) && isRowMajor);
- advanceOffset(type, type.getArraySize(), isVariableRowMajor, arrayStride, matrixStride);
+ advanceOffset(type, type.getArraySize(), isRowMajor, arrayStride, matrixStride);
return memberInfo;
}
@@ -330,7 +325,7 @@
mCurrentOffset = sw::align(mCurrentOffset, ComponentsPerRegister);
}
- Std140BlockEncoder::Std140BlockEncoder(bool rowMajor) : BlockLayoutEncoder(rowMajor)
+ Std140BlockEncoder::Std140BlockEncoder() : BlockLayoutEncoder()
{
}
@@ -2376,7 +2371,7 @@
arg = &unpackedUniform;
index = 0;
}
- else if((srcBlock->matrixPacking() == EmpRowMajor) && memberType.isMatrix())
+ else if((memberType.getLayoutQualifier().matrixPacking == EmpRowMajor) && memberType.isMatrix())
{
int numCols = memberType.getNominalSize();
int numRows = memberType.getSecondarySize();
@@ -3591,7 +3586,7 @@
block->blockStorage(), isRowMajor, registerIndex, blockId));
blockDefinitions.push_back(BlockDefinitionIndexMap());
- Std140BlockEncoder currentBlockEncoder(isRowMajor);
+ Std140BlockEncoder currentBlockEncoder;
currentBlockEncoder.enterAggregateType();
for(const auto &field : fields)
{
diff --git a/src/OpenGL/compiler/OutputASM.h b/src/OpenGL/compiler/OutputASM.h
index f6fd184..a1d16f8 100644
--- a/src/OpenGL/compiler/OutputASM.h
+++ b/src/OpenGL/compiler/OutputASM.h
@@ -99,7 +99,7 @@
class BlockLayoutEncoder
{
public:
- BlockLayoutEncoder(bool rowMajor);
+ BlockLayoutEncoder();
virtual ~BlockLayoutEncoder() {}
BlockMemberInfo encodeType(const TType &type);
@@ -117,7 +117,6 @@
protected:
size_t mCurrentOffset;
- bool isRowMajor;
void nextRegister();
@@ -130,7 +129,7 @@
class Std140BlockEncoder : public BlockLayoutEncoder
{
public:
- Std140BlockEncoder(bool rowMajor);
+ Std140BlockEncoder();
void enterAggregateType() override;
void exitAggregateType() override;
diff --git a/src/OpenGL/compiler/ParseHelper.cpp b/src/OpenGL/compiler/ParseHelper.cpp
index a7d7d01..4f6ffff 100644
--- a/src/OpenGL/compiler/ParseHelper.cpp
+++ b/src/OpenGL/compiler/ParseHelper.cpp
@@ -781,9 +781,8 @@
return true;
if (type.getBasicType() == EbtStruct || type.isInterfaceBlock()) {
- const TFieldList& fields = type.getStruct()->fields();
- for(unsigned int i = 0; i < fields.size(); ++i) {
- if (containsSampler(*fields[i]->type()))
+ for(const auto &field : type.getStruct()->fields()) {
+ if (containsSampler(*(field->type())))
return true;
}
}
@@ -2296,11 +2295,11 @@
size_t instanceSize = 0;
TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion();
- for(size_t index = 0; index < fields.size(); ++index) {
- if (fields[index]->name() == identifier) {
+ for(const auto &field : fields) {
+ if (field->name() == identifier) {
break;
} else {
- instanceSize += fields[index]->type()->getObjectSize();
+ instanceSize += field->type()->getObjectSize();
}
}
@@ -2356,8 +2355,7 @@
}
// check for sampler types and apply layout qualifiers
- for(size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex) {
- TField* field = (*fieldList)[memberIndex];
+ for(const auto &field : *fieldList) {
TType* fieldType = field->type();
if(IsSampler(fieldType->getBasicType())) {
error(field->line(), "unsupported type", fieldType->getBasicString(), "sampler types are not allowed in interface blocks");
@@ -2399,6 +2397,9 @@
}
fieldType->setLayoutQualifier(fieldLayoutQualifier);
+
+ // Recursively propagate the matrix packing setting down to all block/structure members
+ fieldType->setMatrixPackingIfUnspecified(fieldLayoutQualifier.matrixPacking);
}
// add array index
@@ -2418,9 +2419,8 @@
if(!instanceName)
{
// define symbols for the members of the interface block
- for(size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
+ for(const auto &field : *fieldList)
{
- TField* field = (*fieldList)[memberIndex];
TType* fieldType = field->type();
// set parent pointer of the field variable
@@ -2925,12 +2925,12 @@
recover();
}
- for(unsigned int i = 0; i < fieldList->size(); ++i)
+ for(const auto &field : *fieldList)
{
//
// Careful not to replace already known aspects of type, like array-ness
//
- TType *type = (*fieldList)[i]->type();
+ TType *type = field->type();
type->setBasicType(typeSpecifier.type);
type->setNominalSize(typeSpecifier.primarySize);
type->setSecondarySize(typeSpecifier.secondarySize);
@@ -2951,7 +2951,7 @@
type->setStruct(typeSpecifier.userDef->getStruct());
}
- if(structNestingErrorCheck(typeSpecifier.line, *(*fieldList)[i]))
+ if(structNestingErrorCheck(typeSpecifier.line, *field))
{
recover();
}
@@ -2986,17 +2986,16 @@
}
// ensure we do not specify any storage qualifiers on the struct members
- for(unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++)
+ for(const auto &field : *fieldList)
{
- const TField &field = *(*fieldList)[typeListIndex];
- const TQualifier qualifier = field.type()->getQualifier();
+ const TQualifier qualifier = field->type()->getQualifier();
switch(qualifier)
{
case EvqGlobal:
case EvqTemporary:
break;
default:
- error(field.line(), "invalid qualifier on struct member", getQualifierString(qualifier));
+ error(field->line(), "invalid qualifier on struct member", getQualifierString(qualifier));
recover();
break;
}
diff --git a/src/OpenGL/compiler/SymbolTable.cpp b/src/OpenGL/compiler/SymbolTable.cpp
index 5d7ad33..0269efc 100644
--- a/src/OpenGL/compiler/SymbolTable.cpp
+++ b/src/OpenGL/compiler/SymbolTable.cpp
@@ -113,9 +113,9 @@
bool TStructure::containsArrays() const
{
- for(size_t i = 0; i < mFields->size(); ++i)
+ for(const auto& field : *mFields)
{
- const TType *fieldType = (*mFields)[i]->type();
+ const TType *fieldType = field->type();
if(fieldType->isArray() || fieldType->isStructureContainingArrays())
return true;
}
@@ -124,9 +124,9 @@
bool TStructure::containsType(TBasicType type) const
{
- for(size_t i = 0; i < mFields->size(); ++i)
+ for(const auto& field : *mFields)
{
- const TType *fieldType = (*mFields)[i]->type();
+ const TType *fieldType = field->type();
if(fieldType->getBasicType() == type || fieldType->isStructureContainingType(type))
return true;
}
@@ -135,23 +135,31 @@
bool TStructure::containsSamplers() const
{
- for(size_t i = 0; i < mFields->size(); ++i)
+ for(const auto& field : *mFields)
{
- const TType *fieldType = (*mFields)[i]->type();
+ const TType *fieldType = field->type();
if(IsSampler(fieldType->getBasicType()) || fieldType->isStructureContainingSamplers())
return true;
}
return false;
}
+void TStructure::setMatrixPackingIfUnspecified(TLayoutMatrixPacking matrixPacking)
+{
+ for(auto& field : *mFields)
+ {
+ field->type()->setMatrixPackingIfUnspecified(matrixPacking);
+ }
+}
+
TString TFieldListCollection::buildMangledName() const
{
TString mangledName(mangledNamePrefix());
mangledName += *mName;
- for(size_t i = 0; i < mFields->size(); ++i)
+ for(const auto& field : *mFields)
{
mangledName += '-';
- mangledName += (*mFields)[i]->type()->getMangledName();
+ mangledName += field->type()->getMangledName();
}
return mangledName;
}
@@ -159,9 +167,9 @@
size_t TFieldListCollection::calculateObjectSize() const
{
size_t size = 0;
- for(size_t i = 0; i < mFields->size(); ++i)
+ for(const auto& field : *mFields)
{
- size_t fieldSize = (*mFields)[i]->type()->getObjectSize();
+ size_t fieldSize = field->type()->getObjectSize();
if(fieldSize > INT_MAX - size)
size = INT_MAX;
else
@@ -173,8 +181,8 @@
int TStructure::calculateDeepestNesting() const
{
int maxNesting = 0;
- for(size_t i = 0; i < mFields->size(); ++i)
- maxNesting = std::max(maxNesting, (*mFields)[i]->type()->getDeepestStructNesting());
+ for(const auto& field : *mFields)
+ maxNesting = std::max(maxNesting, field->type()->getDeepestStructNesting());
return 1 + maxNesting;
}
diff --git a/src/OpenGL/compiler/Types.h b/src/OpenGL/compiler/Types.h
index 960352f..4b11498 100644
--- a/src/OpenGL/compiler/Types.h
+++ b/src/OpenGL/compiler/Types.h
@@ -137,6 +137,8 @@
bool equals(const TStructure &other) const;
+ void setMatrixPackingIfUnspecified(TLayoutMatrixPacking matrixPacking);
+
void setUniqueId(int uniqueId)
{
mUniqueId = uniqueId;
@@ -282,6 +284,21 @@
TLayoutQualifier getLayoutQualifier() const { return layoutQualifier; }
void setLayoutQualifier(TLayoutQualifier lq) { layoutQualifier = lq; }
+ void setMatrixPackingIfUnspecified(TLayoutMatrixPacking matrixPacking)
+ {
+ if(isStruct())
+ {
+ // If the structure's matrix packing is specified, it overrules the block's matrix packing
+ structure->setMatrixPackingIfUnspecified((layoutQualifier.matrixPacking == EmpUnspecified) ?
+ matrixPacking : layoutQualifier.matrixPacking);
+ }
+ // If the member's matrix packing is specified, it overrules any higher level matrix packing
+ if(layoutQualifier.matrixPacking == EmpUnspecified)
+ {
+ layoutQualifier.matrixPacking = matrixPacking;
+ }
+ }
+
// One-dimensional size of single instance type
int getNominalSize() const { return primarySize; }
void setNominalSize(int s) { primarySize = s; }