diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index 654fe874..c17a73e9 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -1707,25 +1707,25 @@ glslang::TLayoutPacking TGlslangToSpvTraverser::getExplicitLayout(const glslang: int TGlslangToSpvTraverser::getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout) { int size; - int stride = glslangIntermediate->getBaseAlignment(arrayType, size, explicitLayout == glslang::ElpStd140, matrixLayout == glslang::ElmRowMajor); - if (arrayType.isMatrix()) { - // GLSL strides are set to alignments of the matrix flattened to individual rows/cols, - // but SPV needs an array stride for the whole matrix, not the rows/cols - if (matrixLayout == glslang::ElmRowMajor) - stride *= arrayType.getMatrixRows(); - else - stride *= arrayType.getMatrixCols(); - } + int stride; + glslangIntermediate->getBaseAlignment(arrayType, size, stride, explicitLayout == glslang::ElpStd140, matrixLayout == glslang::ElmRowMajor); return stride; } -// Given a matrix type, returns the integer stride required for that matrix +// Given a matrix type, or array (of array) of matrixes type, returns the integer stride required for that matrix // when used as a member of an interface block int TGlslangToSpvTraverser::getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout) { + glslang::TType elementType; + elementType.shallowCopy(matrixType); + elementType.clearArraySizes(); + int size; - return glslangIntermediate->getBaseAlignment(matrixType, size, explicitLayout == glslang::ElpStd140, matrixLayout == glslang::ElmRowMajor); + int stride; + glslangIntermediate->getBaseAlignment(elementType, size, stride, explicitLayout == glslang::ElpStd140, matrixLayout == glslang::ElmRowMajor); + + return stride; } // Given a member type of a struct, realign the current offset for it, and compute @@ -1764,7 +1764,8 @@ void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& structType // but possibly not yet correctly aligned. int memberSize; - int memberAlignment = glslangIntermediate->getBaseAlignment(memberType, memberSize, explicitLayout == glslang::ElpStd140, matrixLayout == glslang::ElmRowMajor); + int dummyStride; + int memberAlignment = glslangIntermediate->getBaseAlignment(memberType, memberSize, dummyStride, explicitLayout == glslang::ElpStd140, matrixLayout == glslang::ElmRowMajor); glslang::RoundToPow2(currentOffset, memberAlignment); nextOffset = currentOffset + memberSize; } diff --git a/Test/baseResults/spv.layoutNested.vert.out b/Test/baseResults/spv.layoutNested.vert.out index 54ed9b73..ac51aab5 100644 --- a/Test/baseResults/spv.layoutNested.vert.out +++ b/Test/baseResults/spv.layoutNested.vert.out @@ -100,7 +100,7 @@ Linked vertex stage: MemberDecorate 14(S) 1 Offset 16 MemberDecorate 14(S) 1 MatrixStride 16 MemberDecorate 14(S) 2 Offset 144 - Decorate 18 ArrayStride 16 + Decorate 18 ArrayStride 480 MemberDecorate 19(Block140) 0 Offset 0 MemberDecorate 19(Block140) 1 Offset 16 MemberDecorate 19(Block140) 2 Offset 976 @@ -113,7 +113,7 @@ Linked vertex stage: MemberDecorate 22(S) 1 Offset 16 MemberDecorate 22(S) 1 MatrixStride 8 MemberDecorate 22(S) 2 Offset 80 - Decorate 24 ArrayStride 16 + Decorate 24 ArrayStride 288 MemberDecorate 25(Block430) 0 Offset 0 MemberDecorate 25(Block430) 1 Offset 16 MemberDecorate 25(Block430) 2 Offset 592 diff --git a/Test/sample.frag.out b/Test/sample.frag.out index ebc450ca..8885dbac 100644 --- a/Test/sample.frag.out +++ b/Test/sample.frag.out @@ -1,15 +1,15 @@ -#### BEGIN COMPILER 0 INFO LOG #### -0:? Sequence -0:37 Function Definition: main( (void) -0:37 Function Parameters: -0:39 Sequence -0:39 move second child to first child (4-component vector of float) -0:39 'gl_FragColor' (FragColor 4-component vector of float) -0:39 Construct vec4 (4-component vector of float) -0:39 'color' (varying in 3-component vector of float) -0:39 1.000000 (const float) - -#### END COMPILER 0 INFO LOG #### -#### BEGIN LINKER INFO LOG #### - -#### END LINKER INFO LOG #### +#### BEGIN COMPILER 0 INFO LOG #### +0:? Sequence +0:37 Function Definition: main( (void) +0:37 Function Parameters: +0:39 Sequence +0:39 move second child to first child (4-component vector of float) +0:39 'gl_FragColor' (FragColor 4-component vector of float) +0:39 Construct vec4 (4-component vector of float) +0:39 'color' (varying in 3-component vector of float) +0:39 1.000000 (const float) + +#### END COMPILER 0 INFO LOG #### +#### BEGIN LINKER INFO LOG #### + +#### END LINKER INFO LOG #### diff --git a/Test/sample.vert.out b/Test/sample.vert.out index ebb700d2..aef6bb14 100644 --- a/Test/sample.vert.out +++ b/Test/sample.vert.out @@ -1,20 +1,20 @@ -#### BEGIN COMPILER 0 INFO LOG #### -0:? Sequence -0:37 Function Definition: main( (void) -0:37 Function Parameters: -0:39 Sequence -0:39 move second child to first child (3-component vector of float) -0:39 'color' (varying out 3-component vector of float) -0:39 1.000000 (const float) -0:39 1.000000 (const float) -0:39 1.000000 (const float) -0:41 move second child to first child (4-component vector of float) -0:41 'gl_Position' (Position 4-component vector of float) -0:41 matrix-times-vector (4-component vector of float) -0:41 'gl_ModelViewProjectionMatrix' (uniform 4X4 matrix of float) -0:41 'gl_Vertex' (attribute 4-component vector of float) - -#### END COMPILER 0 INFO LOG #### -#### BEGIN LINKER INFO LOG #### - -#### END LINKER INFO LOG #### +#### BEGIN COMPILER 0 INFO LOG #### +0:? Sequence +0:37 Function Definition: main( (void) +0:37 Function Parameters: +0:39 Sequence +0:39 move second child to first child (3-component vector of float) +0:39 'color' (varying out 3-component vector of float) +0:39 1.000000 (const float) +0:39 1.000000 (const float) +0:39 1.000000 (const float) +0:41 move second child to first child (4-component vector of float) +0:41 'gl_Position' (Position 4-component vector of float) +0:41 matrix-times-vector (4-component vector of float) +0:41 'gl_ModelViewProjectionMatrix' (uniform 4X4 matrix of float) +0:41 'gl_Vertex' (attribute 4-component vector of float) + +#### END COMPILER 0 INFO LOG #### +#### BEGIN LINKER INFO LOG #### + +#### END LINKER INFO LOG #### diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h index df606ff5..f1695839 100644 --- a/glslang/Include/Types.h +++ b/glslang/Include/Types.h @@ -1206,6 +1206,10 @@ public: arraySizes = new TArraySizes; *arraySizes = s; } + void clearArraySizes() + { + arraySizes = 0; + } void addArrayOuterSizes(const TArraySizes& s) { if (arraySizes == nullptr) diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 5836926a..7d952c65 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -5353,7 +5353,8 @@ void TParseContext::fixBlockUniformOffsets(TQualifier& qualifier, TTypeList& typ // modify just the children's view of matrix layout, if there is one for this member TLayoutMatrix subMatrixLayout = typeList[member].type->getQualifier().layoutMatrix; - int memberAlignment = intermediate.getBaseAlignment(*typeList[member].type, memberSize, qualifier.layoutPacking == ElpStd140, + int dummyStride; + int memberAlignment = intermediate.getBaseAlignment(*typeList[member].type, memberSize, dummyStride, qualifier.layoutPacking == ElpStd140, subMatrixLayout != ElmNone ? subMatrixLayout == ElmRowMajor : qualifier.layoutMatrix == ElmRowMajor); if (memberQualifier.hasOffset()) { // "The specified offset must be a multiple diff --git a/glslang/MachineIndependent/linkValidate.cpp b/glslang/MachineIndependent/linkValidate.cpp index 1a543c16..7c96d225 100644 --- a/glslang/MachineIndependent/linkValidate.cpp +++ b/glslang/MachineIndependent/linkValidate.cpp @@ -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; } diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h index 99335945..043d31fa 100644 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -305,7 +305,7 @@ public: } int addXfbBufferOffset(const TType&); unsigned int computeTypeXfbSize(const TType&, bool& containsDouble) const; - static int getBaseAlignment(const TType&, int& size, bool std140, bool rowMajor); + static int getBaseAlignment(const TType&, int& size, int& stride, bool std140, bool rowMajor); protected: void error(TInfoSink& infoSink, const char*); diff --git a/glslang/MachineIndependent/reflection.cpp b/glslang/MachineIndependent/reflection.cpp index 5a1479ad..9ef6d02f 100644 --- a/glslang/MachineIndependent/reflection.cpp +++ b/glslang/MachineIndependent/reflection.cpp @@ -121,11 +121,12 @@ public: return memberList[index].type->getQualifier().layoutOffset; int memberSize; + int dummyStride; int offset = 0; for (int m = 0; m <= index; ++m) { // 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 = intermediate.getBaseAlignment(*memberList[m].type, memberSize, type.getQualifier().layoutPacking == ElpStd140, + int memberAlignment = intermediate.getBaseAlignment(*memberList[m].type, memberSize, dummyStride, type.getQualifier().layoutPacking == ElpStd140, subMatrixLayout != ElmNone ? subMatrixLayout == ElmRowMajor : type.getQualifier().layoutMatrix == ElmRowMajor); RoundToPow2(offset, memberAlignment); if (m < index) @@ -144,7 +145,8 @@ public: int lastOffset = getOffset(blockType, lastIndex); int lastMemberSize; - intermediate.getBaseAlignment(*memberList[lastIndex].type, lastMemberSize, blockType.getQualifier().layoutPacking == ElpStd140, + int dummyStride; + intermediate.getBaseAlignment(*memberList[lastIndex].type, lastMemberSize, dummyStride, blockType.getQualifier().layoutPacking == ElpStd140, blockType.getQualifier().layoutMatrix == ElmRowMajor); return lastOffset + lastMemberSize;