diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index ca6a577a..fb4e1156 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -91,11 +91,11 @@ protected: spv::Id createSpvVariable(const glslang::TIntermSymbol*); spv::Id getSampledType(const glslang::TSampler&); spv::Id convertGlslangToSpvType(const glslang::TType& type); - spv::Id convertGlslangToSpvType(const glslang::TType& type, glslang::TLayoutPacking); + spv::Id convertGlslangToSpvType(const glslang::TType& type, glslang::TLayoutPacking, glslang::TLayoutMatrix); glslang::TLayoutPacking getExplicitLayout(const glslang::TType& type) const; - int getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking); - int getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking); - void updateMemberOffset(const glslang::TType& structType, const glslang::TType& memberType, int& currentOffset, int& nextOffset, glslang::TLayoutPacking); + int getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking, glslang::TLayoutMatrix); + int getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking, glslang::TLayoutMatrix); + void updateMemberOffset(const glslang::TType& structType, const glslang::TType& memberType, int& currentOffset, int& nextOffset, glslang::TLayoutPacking, glslang::TLayoutMatrix); bool isShaderEntrypoint(const glslang::TIntermAggregate* node); void makeFunctions(const glslang::TIntermSequence&); @@ -140,7 +140,7 @@ protected: std::unordered_map symbolValues; std::unordered_set constReadOnlyParameters; // set of formal function parameters that have glslang qualifier constReadOnly, so we know they are not local function "const" that are write-once std::unordered_map functionMap; - std::unordered_map structMap[glslang::ElpStd430 + 1]; + std::unordered_map structMap[glslang::ElpCount][glslang::ElmCount]; std::unordered_map > memberRemapper; // for mapping glslang block indices to spv indices (e.g., due to hidden members) std::stack breakForLoop; // false means break for switch std::stack loopTerminal; // code from the last part of a for loop: for(...; ...; terminal), needed for e.g., continue }; @@ -256,14 +256,17 @@ spv::Decoration TranslateBlockDecoration(const glslang::TType& type) } // Translate glslang type to SPIR-V layout decorations. -spv::Decoration TranslateLayoutDecoration(const glslang::TType& type) +spv::Decoration TranslateLayoutDecoration(const glslang::TType& type, glslang::TLayoutMatrix matrixLayout) { if (type.isMatrix()) { - switch (type.getQualifier().layoutMatrix) { + switch (matrixLayout) { case glslang::ElmRowMajor: return spv::DecorationRowMajor; - default: + case glslang::ElmColumnMajor: return spv::DecorationColMajor; + default: + // opaque layouts don't need a majorness + return (spv::Decoration)spv::BadValue; } } else { switch (type.getBasicType()) { @@ -1451,16 +1454,17 @@ spv::Id TGlslangToSpvTraverser::getSampledType(const glslang::TSampler& sampler) } } -// Convert from a glslang type to an SPV type, by calling into -// recursive version of this function. +// Convert from a glslang type to an SPV type, by calling into a +// recursive version of this function. This establishes the inherited +// layout state rooted from the top-level type. spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& type) { - return convertGlslangToSpvType(type, getExplicitLayout(type)); + return convertGlslangToSpvType(type, getExplicitLayout(type), type.getQualifier().layoutMatrix); } // Do full recursive conversion of an arbitrary glslang type to a SPIR-V Id. // explicitLayout can be kept the same throughout the heirarchical recursive walk. -spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& type, glslang::TLayoutPacking explicitLayout) +spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& type, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout) { spv::Id spvType = 0; @@ -1505,7 +1509,7 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty // If we've seen this struct type, return it const glslang::TTypeList* glslangStruct = type.getStruct(); std::vector structFields; - spvType = structMap[explicitLayout][glslangStruct]; + spvType = structMap[explicitLayout][matrixLayout][glslangStruct]; if (spvType) break; @@ -1524,13 +1528,16 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty } else { if (type.getBasicType() == glslang::EbtBlock) memberRemapper[glslangStruct][i] = i - memberDelta; - structFields.push_back(convertGlslangToSpvType(glslangType, explicitLayout)); + // modify just the children's view of matrix layout, if there is one for this member + glslang::TLayoutMatrix subMatrixLayout = glslangType.getQualifier().layoutMatrix; + structFields.push_back(convertGlslangToSpvType(glslangType, explicitLayout, + subMatrixLayout != glslang::ElmNone ? subMatrixLayout : matrixLayout)); } } // Make the SPIR-V type spvType = builder.makeStructType(structFields, type.getTypeName().c_str()); - structMap[explicitLayout][glslangStruct] = spvType; + structMap[explicitLayout][matrixLayout][glslangStruct] = spvType; // Name and decorate the non-hidden members int offset = -1; @@ -1539,10 +1546,16 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty int member = i; if (type.getBasicType() == glslang::EbtBlock) member = memberRemapper[glslangStruct][i]; + + // modify just the children's view of matrix layout, if there is one for this member + glslang::TLayoutMatrix subMatrixLayout = glslangType.getQualifier().layoutMatrix; + if (subMatrixLayout == glslang::ElmNone) + subMatrixLayout = matrixLayout; + // using -1 above to indicate a hidden member if (member >= 0) { builder.addMemberName(spvType, member, glslangType.getFieldName().c_str()); - addMemberDecoration(spvType, member, TranslateLayoutDecoration(glslangType)); + addMemberDecoration(spvType, member, TranslateLayoutDecoration(glslangType, subMatrixLayout)); addMemberDecoration(spvType, member, TranslatePrecisionDecoration(glslangType)); addMemberDecoration(spvType, member, TranslateInterpolationDecoration(glslangType)); addMemberDecoration(spvType, member, TranslateInvariantDecoration(glslangType)); @@ -1555,14 +1568,14 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty else if (explicitLayout != glslang::ElpNone) { // figure out what to do with offset, which is accumulating int nextOffset; - updateMemberOffset(type, glslangType, offset, nextOffset, explicitLayout); + updateMemberOffset(type, glslangType, offset, nextOffset, explicitLayout, subMatrixLayout); if (offset >= 0) builder.addMemberDecoration(spvType, member, spv::DecorationOffset, offset); offset = nextOffset; } if (glslangType.isMatrix() && explicitLayout != glslang::ElpNone) - builder.addMemberDecoration(spvType, member, spv::DecorationMatrixStride, getMatrixStride(glslangType, explicitLayout)); + builder.addMemberDecoration(spvType, member, spv::DecorationMatrixStride, getMatrixStride(glslangType, explicitLayout, subMatrixLayout)); // built-in variable decorations spv::BuiltIn builtIn = TranslateBuiltInDecoration(glslangType.getQualifier().builtIn); @@ -1572,7 +1585,7 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty } // Decorate the structure - addDecoration(spvType, TranslateLayoutDecoration(type)); + addDecoration(spvType, TranslateLayoutDecoration(type, matrixLayout)); addDecoration(spvType, TranslateBlockDecoration(type)); if (type.getQualifier().hasStream()) builder.addDecoration(spvType, spv::DecorationStream, type.getQualifier().layoutStream); @@ -1620,7 +1633,7 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty // except for the very top if it is an array of blocks; that array is // not laid out in memory in a way needing a stride. if (explicitLayout && type.getBasicType() != glslang::EbtBlock) - builder.addDecoration(spvType, spv::DecorationArrayStride, getArrayStride(type, explicitLayout)); + builder.addDecoration(spvType, spv::DecorationArrayStride, getArrayStride(type, explicitLayout, matrixLayout)); } return spvType; @@ -1651,14 +1664,14 @@ glslang::TLayoutPacking TGlslangToSpvTraverser::getExplicitLayout(const glslang: } // Given an array type, returns the integer stride required for that array -int TGlslangToSpvTraverser::getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking explicitLayout) +int TGlslangToSpvTraverser::getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout) { int size; - int stride = glslangIntermediate->getBaseAlignment(arrayType, size, explicitLayout == glslang::ElpStd140); + 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 (arrayType.getQualifier().layoutMatrix == glslang::ElmRowMajor) + if (matrixLayout == glslang::ElmRowMajor) stride *= arrayType.getMatrixRows(); else stride *= arrayType.getMatrixCols(); @@ -1669,10 +1682,10 @@ int TGlslangToSpvTraverser::getArrayStride(const glslang::TType& arrayType, glsl // Given a matrix 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) +int TGlslangToSpvTraverser::getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout) { int size; - return glslangIntermediate->getBaseAlignment(matrixType, size, explicitLayout == glslang::ElpStd140); + return glslangIntermediate->getBaseAlignment(matrixType, size, explicitLayout == glslang::ElpStd140, matrixLayout == glslang::ElmRowMajor); } // Given a member type of a struct, realign the current offset for it, and compute @@ -1682,7 +1695,7 @@ int TGlslangToSpvTraverser::getMatrixStride(const glslang::TType& matrixType, gl // the migration of data from nextOffset -> currentOffset. It should be -1 on the first call. // -1 means a non-forced member offset (no decoration needed). void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& structType, const glslang::TType& memberType, int& currentOffset, int& nextOffset, - glslang::TLayoutPacking explicitLayout) + glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout) { // this will get a positive value when deemed necessary nextOffset = -1; @@ -1711,7 +1724,7 @@ void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& structType // but possibly not yet correctly aligned. int memberSize; - int memberAlignment = glslangIntermediate->getBaseAlignment(memberType, memberSize, explicitLayout == glslang::ElpStd140); + int memberAlignment = glslangIntermediate->getBaseAlignment(memberType, memberSize, 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 007c0297..98e4ae62 100644 --- a/Test/baseResults/spv.layoutNested.vert.out +++ b/Test/baseResults/spv.layoutNested.vert.out @@ -7,132 +7,217 @@ Linked vertex stage: // Module Version 10000 // Generated by (magic number): 80001 -// Id's are bound by 54 +// Id's are bound by 63 Capability Shader 1: ExtInstImport "GLSL.std.450" MemoryModel Logical GLSL450 - EntryPoint Vertex 4 "main" 38 52 53 + EntryPoint Vertex 4 "main" 61 62 Source GLSL 450 Name 4 "main" - Name 13 "S" - MemberName 13(S) 0 "a" - MemberName 13(S) 1 "b" - MemberName 13(S) 2 "c" - Name 15 "s" - Name 18 "S" - MemberName 18(S) 0 "a" - MemberName 18(S) 1 "b" - MemberName 18(S) 2 "c" - Name 23 "Block140" - MemberName 23(Block140) 0 "u" - MemberName 23(Block140) 1 "s" - MemberName 23(Block140) 2 "v" - Name 25 "inst140" - Name 36 "gl_PerVertex" - MemberName 36(gl_PerVertex) 0 "gl_Position" - MemberName 36(gl_PerVertex) 1 "gl_PointSize" - MemberName 36(gl_PerVertex) 2 "gl_ClipDistance" - MemberName 36(gl_PerVertex) 3 "gl_CullDistance" - Name 38 "" - Name 45 "S" - MemberName 45(S) 0 "a" - MemberName 45(S) 1 "b" - MemberName 45(S) 2 "c" - Name 48 "Block430" - MemberName 48(Block430) 0 "u" - MemberName 48(Block430) 1 "s" - MemberName 48(Block430) 2 "v" - Name 50 "inst430" - Name 52 "gl_VertexID" - Name 53 "gl_InstanceID" - MemberDecorate 13(S) 1 ColMajor - Decorate 12 ArrayStride 32 - MemberDecorate 18(S) 0 Offset 0 - MemberDecorate 18(S) 1 ColMajor - MemberDecorate 18(S) 1 Offset 16 - MemberDecorate 18(S) 1 MatrixStride 16 - MemberDecorate 18(S) 2 Offset 144 - Decorate 22 ArrayStride 16 - MemberDecorate 23(Block140) 0 Offset 0 - MemberDecorate 23(Block140) 1 Offset 16 - MemberDecorate 23(Block140) 2 Offset 976 - Decorate 23(Block140) Block - Decorate 25(inst140) DescriptorSet 0 - Decorate 25(inst140) Binding 0 - MemberDecorate 36(gl_PerVertex) 0 BuiltIn Position - MemberDecorate 36(gl_PerVertex) 1 BuiltIn PointSize - MemberDecorate 36(gl_PerVertex) 2 BuiltIn ClipDistance - MemberDecorate 36(gl_PerVertex) 3 BuiltIn CullDistance - Decorate 36(gl_PerVertex) Block - Decorate 12 ArrayStride 16 - MemberDecorate 45(S) 0 Offset 0 - MemberDecorate 45(S) 1 ColMajor - MemberDecorate 45(S) 1 Offset 16 - MemberDecorate 45(S) 1 MatrixStride 8 - MemberDecorate 45(S) 2 Offset 80 - Decorate 47 ArrayStride 16 - MemberDecorate 48(Block430) 0 Offset 0 - MemberDecorate 48(Block430) 1 Offset 16 - MemberDecorate 48(Block430) 2 Offset 592 - Decorate 48(Block430) BufferBlock - Decorate 50(inst430) DescriptorSet 0 - Decorate 50(inst430) Binding 1 - Decorate 52(gl_VertexID) BuiltIn VertexId - Decorate 53(gl_InstanceID) BuiltIn InstanceId + Name 14 "S" + MemberName 14(S) 0 "a" + MemberName 14(S) 1 "b" + MemberName 14(S) 2 "c" + Name 19 "Block140" + MemberName 19(Block140) 0 "u" + MemberName 19(Block140) 1 "s" + MemberName 19(Block140) 2 "v" + Name 21 "inst140" + Name 22 "S" + MemberName 22(S) 0 "a" + MemberName 22(S) 1 "b" + MemberName 22(S) 2 "c" + Name 25 "Block430" + MemberName 25(Block430) 0 "u" + MemberName 25(Block430) 1 "s" + MemberName 25(Block430) 2 "v" + Name 27 "inst430" + Name 28 "S" + MemberName 28(S) 0 "a" + MemberName 28(S) 1 "b" + MemberName 28(S) 2 "c" + Name 30 "s" + Name 31 "T" + MemberName 31(T) 0 "m" + MemberName 31(T) 1 "a" + Name 33 "t" + Name 34 "T" + MemberName 34(T) 0 "m" + MemberName 34(T) 1 "a" + Name 35 "Nestor" + MemberName 35(Nestor) 0 "nestorT" + Name 36 "Bt1" + MemberName 36(Bt1) 0 "nt" + Name 38 "Btn1" + Name 39 "T" + MemberName 39(T) 0 "m" + MemberName 39(T) 1 "a" + Name 40 "Nestor" + MemberName 40(Nestor) 0 "nestorT" + Name 41 "Bt2" + MemberName 41(Bt2) 0 "nt" + Name 43 "Btn2" + Name 44 "Bt3" + MemberName 44(Bt3) 0 "ntcol" + MemberName 44(Bt3) 1 "ntrow" + Name 46 "Btn3" + Name 47 "T" + MemberName 47(T) 0 "m" + MemberName 47(T) 1 "a" + Name 48 "Nestor" + MemberName 48(Nestor) 0 "nestorT" + Name 49 "bBt1" + MemberName 49(bBt1) 0 "nt" + Name 51 "bBtn1" + Name 52 "T" + MemberName 52(T) 0 "m" + MemberName 52(T) 1 "a" + Name 53 "Nestor" + MemberName 53(Nestor) 0 "nestorT" + Name 54 "bBt2" + MemberName 54(bBt2) 0 "nt" + Name 56 "bBtn2" + Name 57 "bBt3" + MemberName 57(bBt3) 0 "ntcol" + MemberName 57(bBt3) 1 "ntrow" + Name 59 "bBtn3" + Name 61 "gl_VertexID" + Name 62 "gl_InstanceID" + Decorate 13 ArrayStride 32 + MemberDecorate 14(S) 0 Offset 0 + MemberDecorate 14(S) 1 ColMajor + MemberDecorate 14(S) 1 Offset 16 + MemberDecorate 14(S) 1 MatrixStride 16 + MemberDecorate 14(S) 2 Offset 144 + Decorate 18 ArrayStride 16 + MemberDecorate 19(Block140) 0 Offset 0 + MemberDecorate 19(Block140) 1 Offset 16 + MemberDecorate 19(Block140) 2 Offset 976 + Decorate 19(Block140) Block + Decorate 21(inst140) DescriptorSet 0 + Decorate 21(inst140) Binding 0 + Decorate 13 ArrayStride 16 + MemberDecorate 22(S) 0 Offset 0 + MemberDecorate 22(S) 1 ColMajor + MemberDecorate 22(S) 1 Offset 16 + MemberDecorate 22(S) 1 MatrixStride 8 + MemberDecorate 22(S) 2 Offset 80 + Decorate 24 ArrayStride 16 + MemberDecorate 25(Block430) 0 Offset 0 + MemberDecorate 25(Block430) 1 Offset 16 + MemberDecorate 25(Block430) 2 Offset 592 + Decorate 25(Block430) BufferBlock + Decorate 27(inst430) DescriptorSet 0 + Decorate 27(inst430) Binding 1 + MemberDecorate 34(T) 0 RowMajor + MemberDecorate 34(T) 0 Offset 0 + MemberDecorate 34(T) 0 MatrixStride 16 + MemberDecorate 34(T) 1 Offset 32 + MemberDecorate 35(Nestor) 0 Offset 0 + MemberDecorate 36(Bt1) 0 Offset 0 + Decorate 36(Bt1) Block + Decorate 38(Btn1) DescriptorSet 1 + Decorate 38(Btn1) Binding 0 + MemberDecorate 39(T) 0 ColMajor + MemberDecorate 39(T) 0 Offset 0 + MemberDecorate 39(T) 0 MatrixStride 16 + MemberDecorate 39(T) 1 Offset 32 + MemberDecorate 40(Nestor) 0 Offset 0 + MemberDecorate 41(Bt2) 0 Offset 0 + Decorate 41(Bt2) Block + Decorate 43(Btn2) DescriptorSet 1 + Decorate 43(Btn2) Binding 0 + MemberDecorate 44(Bt3) 0 Offset 0 + MemberDecorate 44(Bt3) 1 Offset 48 + Decorate 44(Bt3) Block + Decorate 46(Btn3) DescriptorSet 1 + Decorate 46(Btn3) Binding 0 + MemberDecorate 47(T) 0 RowMajor + MemberDecorate 47(T) 0 Offset 0 + MemberDecorate 47(T) 0 MatrixStride 8 + MemberDecorate 47(T) 1 Offset 16 + MemberDecorate 48(Nestor) 0 Offset 0 + MemberDecorate 49(bBt1) 0 Offset 0 + Decorate 49(bBt1) BufferBlock + Decorate 51(bBtn1) DescriptorSet 1 + Decorate 51(bBtn1) Binding 0 + MemberDecorate 52(T) 0 ColMajor + MemberDecorate 52(T) 0 Offset 0 + MemberDecorate 52(T) 0 MatrixStride 8 + MemberDecorate 52(T) 1 Offset 16 + MemberDecorate 53(Nestor) 0 Offset 0 + MemberDecorate 54(bBt2) 0 Offset 0 + Decorate 54(bBt2) BufferBlock + Decorate 56(bBtn2) DescriptorSet 1 + Decorate 56(bBtn2) Binding 0 + MemberDecorate 57(bBt3) 0 Offset 0 + MemberDecorate 57(bBt3) 1 Offset 24 + Decorate 57(bBt3) BufferBlock + Decorate 59(bBtn3) DescriptorSet 1 + Decorate 59(bBtn3) Binding 0 + Decorate 61(gl_VertexID) BuiltIn VertexId + Decorate 62(gl_InstanceID) BuiltIn InstanceId 2: TypeVoid 3: TypeFunction 2 - 6: TypeInt 32 0 - 7: TypeVector 6(int) 3 - 8: TypeFloat 32 - 9: TypeVector 8(float) 2 - 10: TypeMatrix 9(fvec2) 2 - 11: 6(int) Constant 4 - 12: TypeArray 10 11 - 13(S): TypeStruct 7(ivec3) 12 6(int) - 14: TypePointer Private 13(S) - 15(s): 14(ptr) Variable Private - 16: TypeInt 32 1 - 17: 16(int) Constant 2 - 18(S): TypeStruct 7(ivec3) 12 6(int) - 19: 6(int) Constant 3 - 20: TypeArray 18(S) 19 - 21: 6(int) Constant 2 - 22: TypeArray 20 21 - 23(Block140): TypeStruct 16(int) 22 9(fvec2) - 24: TypePointer Uniform 23(Block140) - 25(inst140): 24(ptr) Variable Uniform - 26: 16(int) Constant 0 - 27: TypePointer Uniform 16(int) - 31: TypePointer Private 6(int) - 33: TypeVector 8(float) 4 - 34: 6(int) Constant 1 - 35: TypeArray 8(float) 34 -36(gl_PerVertex): TypeStruct 33(fvec4) 8(float) 35 35 - 37: TypePointer Output 36(gl_PerVertex) - 38: 37(ptr) Variable Output - 43: TypePointer Output 33(fvec4) - 45(S): TypeStruct 7(ivec3) 12 6(int) - 46: TypeArray 45(S) 19 - 47: TypeArray 46 21 - 48(Block430): TypeStruct 16(int) 47 9(fvec2) - 49: TypePointer Uniform 48(Block430) - 50(inst430): 49(ptr) Variable Uniform - 51: TypePointer Input 16(int) - 52(gl_VertexID): 51(ptr) Variable Input -53(gl_InstanceID): 51(ptr) Variable Input + 6: TypeInt 32 1 + 7: TypeInt 32 0 + 8: TypeVector 7(int) 3 + 9: TypeFloat 32 + 10: TypeVector 9(float) 2 + 11: TypeMatrix 10(fvec2) 2 + 12: 7(int) Constant 4 + 13: TypeArray 11 12 + 14(S): TypeStruct 8(ivec3) 13 7(int) + 15: 7(int) Constant 3 + 16: TypeArray 14(S) 15 + 17: 7(int) Constant 2 + 18: TypeArray 16 17 + 19(Block140): TypeStruct 6(int) 18 10(fvec2) + 20: TypePointer Uniform 19(Block140) + 21(inst140): 20(ptr) Variable Uniform + 22(S): TypeStruct 8(ivec3) 13 7(int) + 23: TypeArray 22(S) 15 + 24: TypeArray 23 17 + 25(Block430): TypeStruct 6(int) 24 10(fvec2) + 26: TypePointer Uniform 25(Block430) + 27(inst430): 26(ptr) Variable Uniform + 28(S): TypeStruct 8(ivec3) 13 7(int) + 29: TypePointer Private 28(S) + 30(s): 29(ptr) Variable Private + 31(T): TypeStruct 11 6(int) + 32: TypePointer Private 31(T) + 33(t): 32(ptr) Variable Private + 34(T): TypeStruct 11 6(int) + 35(Nestor): TypeStruct 34(T) + 36(Bt1): TypeStruct 35(Nestor) + 37: TypePointer Uniform 36(Bt1) + 38(Btn1): 37(ptr) Variable Uniform + 39(T): TypeStruct 11 6(int) + 40(Nestor): TypeStruct 39(T) + 41(Bt2): TypeStruct 40(Nestor) + 42: TypePointer Uniform 41(Bt2) + 43(Btn2): 42(ptr) Variable Uniform + 44(Bt3): TypeStruct 40(Nestor) 35(Nestor) + 45: TypePointer Uniform 44(Bt3) + 46(Btn3): 45(ptr) Variable Uniform + 47(T): TypeStruct 11 6(int) + 48(Nestor): TypeStruct 47(T) + 49(bBt1): TypeStruct 48(Nestor) + 50: TypePointer Uniform 49(bBt1) + 51(bBtn1): 50(ptr) Variable Uniform + 52(T): TypeStruct 11 6(int) + 53(Nestor): TypeStruct 52(T) + 54(bBt2): TypeStruct 53(Nestor) + 55: TypePointer Uniform 54(bBt2) + 56(bBtn2): 55(ptr) Variable Uniform + 57(bBt3): TypeStruct 48(Nestor) 53(Nestor) + 58: TypePointer Uniform 57(bBt3) + 59(bBtn3): 58(ptr) Variable Uniform + 60: TypePointer Input 6(int) + 61(gl_VertexID): 60(ptr) Variable Input +62(gl_InstanceID): 60(ptr) Variable Input 4(main): 2 Function None 3 5: Label - 28: 27(ptr) AccessChain 25(inst140) 26 - 29: 16(int) Load 28 - 30: 6(int) Bitcast 29 - 32: 31(ptr) AccessChain 15(s) 17 - Store 32 30 - 39: 31(ptr) AccessChain 15(s) 17 - 40: 6(int) Load 39 - 41: 8(float) ConvertUToF 40 - 42: 33(fvec4) CompositeConstruct 41 41 41 41 - 44: 43(ptr) AccessChain 38 26 - Store 44 42 Return FunctionEnd diff --git a/Test/spv.layoutNested.vert b/Test/spv.layoutNested.vert index aa403fc5..ac44cbe3 100644 --- a/Test/spv.layoutNested.vert +++ b/Test/spv.layoutNested.vert @@ -1,6 +1,6 @@ #version 450 -// should get 3 SPV types: no layout, 140, and 430 +// should get 3 SPV types for S: no layout, 140, and 430 struct S { highp uvec3 a; @@ -24,8 +24,50 @@ layout(set = 0, binding = 1, std430) buffer Block430 S s; +// should get 5 SPV types for T: no layout, 140/row, 140/col, 430/row, and 430/col +struct T { + mat2 m; + int a; +}; + +T t; + +struct Nestor { + T nestorT; +}; + +layout(set = 1, binding = 0, std140) uniform Bt1 +{ + layout(row_major) Nestor nt; +} Btn1; + +layout(set = 1, binding = 0, std140) uniform Bt2 +{ + layout(column_major) Nestor nt; +} Btn2; + +layout(row_major, set = 1, binding = 0, std140) uniform Bt3 +{ + layout(column_major) Nestor ntcol; + Nestor ntrow; // should be row major decoration version of Nestor +} Btn3; + +layout(set = 1, binding = 0, std430) buffer bBt1 +{ + layout(row_major) Nestor nt; +} bBtn1; + +layout(set = 1, binding = 0, std430) buffer bBt2 +{ + layout(column_major) Nestor nt; +} bBtn2; + +layout(set = 1, binding = 0, std430) buffer bBt3 +{ + layout(row_major) Nestor ntcol; + Nestor ntrow; // should be col major decoration version of Nestor +} bBtn3; + void main() { - s.c = inst140.u; - gl_Position = vec4(s.c); } diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h index 06e84492..df606ff5 100644 --- a/glslang/Include/Types.h +++ b/glslang/Include/Types.h @@ -186,15 +186,15 @@ enum TLayoutPacking { ElpShared, // default, but different than saying nothing ElpStd140, ElpStd430, - ElpPacked - // If expanding, see bitfield width below + ElpPacked, + ElpCount // If expanding, see bitfield width below }; enum TLayoutMatrix { ElmNone, ElmRowMajor, - ElmColumnMajor // default, but different than saying nothing - // If expanding, see bitfield width below + ElmColumnMajor, // default, but different than saying nothing + ElmCount // If expanding, see bitfield width below }; // Union of geometry shader and tessellation shader geometry types. diff --git a/glslang/Include/revision.h b/glslang/Include/revision.h index 42a916c1..2b4d4257 100644 --- a/glslang/Include/revision.h +++ b/glslang/Include/revision.h @@ -2,5 +2,5 @@ // For the version, it uses the latest git tag followed by the number of commits. // For the date, it uses the current date (when then script is run). -#define GLSLANG_REVISION "SPIRV99.860" -#define GLSLANG_DATE "19-Dec-2015" +#define GLSLANG_REVISION "SPIRV99.861" +#define GLSLANG_DATE "20-Dec-2015" diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 72e6010f..9ed4f86a 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -5345,8 +5345,11 @@ void TParseContext::fixBlockUniformOffsets(TQualifier& qualifier, TTypeList& typ const TSourceLoc& memberLoc = typeList[member].loc; // "When align is applied to an array, it effects only the start of the array, not the array's internal stride." - - int memberAlignment = intermediate.getBaseAlignment(*typeList[member].type, memberSize, qualifier.layoutPacking == ElpStd140); + + // 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, + subMatrixLayout != ElmNone ? subMatrixLayout == ElmRowMajor : qualifier.layoutMatrix == ElmRowMajor); if (memberQualifier.hasOffset()) { // "The specified offset must be a multiple // of the base alignment of the type of the block member it qualifies, or a compile-time error results." diff --git a/glslang/MachineIndependent/linkValidate.cpp b/glslang/MachineIndependent/linkValidate.cpp index 5e4104cb..1a543c16 100644 --- a/glslang/MachineIndependent/linkValidate.cpp +++ b/glslang/MachineIndependent/linkValidate.cpp @@ -859,7 +859,7 @@ int TIntermediate::getBaseAlignmentScalar(const TType& type, int& size) // // The size is returned in the 'size' parameter // Return value is the alignment of the type. -int TIntermediate::getBaseAlignment(const TType& type, int& size, bool std140) +int TIntermediate::getBaseAlignment(const TType& type, int& size, bool std140, bool rowMajor) { int alignment; @@ -921,7 +921,7 @@ int TIntermediate::getBaseAlignment(const TType& type, int& size, bool std140) 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); + alignment = getBaseAlignment(derefType, size, std140, rowMajor); if (std140) alignment = std::max(baseAlignmentVec4Std140, alignment); RoundToPow2(size, alignment); @@ -937,7 +937,10 @@ int TIntermediate::getBaseAlignment(const TType& type, int& size, bool std140) int maxAlignment = std140 ? baseAlignmentVec4Std140 : 0; for (size_t m = 0; m < memberList.size(); ++m) { int memberSize; - int memberAlignment = getBaseAlignment(*memberList[m].type, memberSize, std140); + // 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, + (subMatrixLayout != ElmNone) ? (subMatrixLayout == ElmRowMajor) : rowMajor); maxAlignment = std::max(maxAlignment, memberAlignment); RoundToPow2(size, memberAlignment); size += memberSize; @@ -968,11 +971,11 @@ int TIntermediate::getBaseAlignment(const TType& type, int& size, bool std140) // 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); + alignment = getBaseAlignment(derefType, size, std140, rowMajor); if (std140) alignment = std::max(baseAlignmentVec4Std140, alignment); RoundToPow2(size, alignment); - if (type.getQualifier().layoutMatrix == ElmRowMajor) + if (rowMajor) size *= type.getMatrixRows(); else size *= type.getMatrixCols(); diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h index 27bac7bd..99335945 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); + static int getBaseAlignment(const TType&, int& size, bool std140, bool rowMajor); protected: void error(TInfoSink& infoSink, const char*); diff --git a/glslang/MachineIndependent/reflection.cpp b/glslang/MachineIndependent/reflection.cpp index 85caff7a..5a1479ad 100644 --- a/glslang/MachineIndependent/reflection.cpp +++ b/glslang/MachineIndependent/reflection.cpp @@ -123,7 +123,10 @@ public: int memberSize; int offset = 0; for (int m = 0; m <= index; ++m) { - int memberAlignment = intermediate.getBaseAlignment(*memberList[m].type, memberSize, type.getQualifier().layoutPacking == ElpStd140); + // 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, + subMatrixLayout != ElmNone ? subMatrixLayout == ElmRowMajor : type.getQualifier().layoutMatrix == ElmRowMajor); RoundToPow2(offset, memberAlignment); if (m < index) offset += memberSize; @@ -141,7 +144,8 @@ public: int lastOffset = getOffset(blockType, lastIndex); int lastMemberSize; - intermediate.getBaseAlignment(*memberList[lastIndex].type, lastMemberSize, blockType.getQualifier().layoutPacking == ElpStd140); + intermediate.getBaseAlignment(*memberList[lastIndex].type, lastMemberSize, blockType.getQualifier().layoutPacking == ElpStd140, + blockType.getQualifier().layoutMatrix == ElmRowMajor); return lastOffset + lastMemberSize; }