SPV: Fix array strides by explicitly computing them in the getBaseAlignment() algorithm.

This commit is contained in:
John Kessenich 2015-12-29 17:11:44 -07:00
parent e0b6cad44f
commit 4998789d4e
9 changed files with 83 additions and 61 deletions

View file

@ -858,8 +858,14 @@ int TIntermediate::getBaseAlignmentScalar(const TType& type, int& size)
// otherwise it does not, yielding std430 rules.
//
// The size is returned in the 'size' parameter
//
// The stride is only non-0 for arrays or matrices, and is the stride of the
// top-level object nested within the type. E.g., for an array of matrices,
// it is the distances needed between matrices, despite the rules saying the
// stride comes from the flattening down to vectors.
//
// Return value is the alignment of the type.
int TIntermediate::getBaseAlignment(const TType& type, int& size, bool std140, bool rowMajor)
int TIntermediate::getBaseAlignment(const TType& type, int& size, int& stride, bool std140, bool rowMajor)
{
int alignment;
@ -916,16 +922,23 @@ int TIntermediate::getBaseAlignment(const TType& type, int& size, bool std140, b
//
// 10. If the member is an array of S structures, the S elements of the array are laid
// out in order, according to rule (9).
//
// Assuming, for rule 10: The stride is the same as the size of an element.
// rules 4, 6, and 8
stride = 0;
int dummyStride;
// rules 4, 6, 8, and 10
if (type.isArray()) {
// TODO: perf: this might be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness
TType derefType(type, 0);
alignment = getBaseAlignment(derefType, size, std140, rowMajor);
alignment = getBaseAlignment(derefType, size, dummyStride, std140, rowMajor);
if (std140)
alignment = std::max(baseAlignmentVec4Std140, alignment);
RoundToPow2(size, alignment);
size *= type.getOuterArraySize();
stride = size; // uses full matrix size for stride of an array of matrices (not quite what rule 6/8, but what's expected)
// uses the assumption for rule 10 in the comment above
size = stride * type.getOuterArraySize();
return alignment;
}
@ -939,7 +952,7 @@ int TIntermediate::getBaseAlignment(const TType& type, int& size, bool std140, b
int memberSize;
// modify just the children's view of matrix layout, if there is one for this member
TLayoutMatrix subMatrixLayout = memberList[m].type->getQualifier().layoutMatrix;
int memberAlignment = getBaseAlignment(*memberList[m].type, memberSize, std140,
int memberAlignment = getBaseAlignment(*memberList[m].type, memberSize, dummyStride, std140,
(subMatrixLayout != ElmNone) ? (subMatrixLayout == ElmRowMajor) : rowMajor);
maxAlignment = std::max(maxAlignment, memberAlignment);
RoundToPow2(size, memberAlignment);
@ -971,14 +984,15 @@ int TIntermediate::getBaseAlignment(const TType& type, int& size, bool std140, b
// rule 5: deref to row, not to column, meaning the size of vector is num columns instead of num rows
TType derefType(type, 0, type.getQualifier().layoutMatrix == ElmRowMajor);
alignment = getBaseAlignment(derefType, size, std140, rowMajor);
alignment = getBaseAlignment(derefType, size, dummyStride, std140, rowMajor);
if (std140)
alignment = std::max(baseAlignmentVec4Std140, alignment);
RoundToPow2(size, alignment);
stride = size; // use intra-matrix stride for stride of a just a matrix
if (rowMajor)
size *= type.getMatrixRows();
size = stride * type.getMatrixRows();
else
size *= type.getMatrixCols();
size = stride * type.getMatrixCols();
return alignment;
}