SPV: recursively propagate row/col majorness through nested structures.
This includes doing structure uniqueness modulo majorness, for shared nested structures.
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index ca6a577..fb4e115 100755
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -91,11 +91,11 @@
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 @@
std::unordered_map<int, spv::Id> symbolValues;
std::unordered_set<int> 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<std::string, spv::Function*> functionMap;
- std::unordered_map<const glslang::TTypeList*, spv::Id> structMap[glslang::ElpStd430 + 1];
+ std::unordered_map<const glslang::TTypeList*, spv::Id> structMap[glslang::ElpCount][glslang::ElmCount];
std::unordered_map<const glslang::TTypeList*, std::vector<int> > memberRemapper; // for mapping glslang block indices to spv indices (e.g., due to hidden members)
std::stack<bool> breakForLoop; // false means break for switch
std::stack<glslang::TIntermTyped*> loopTerminal; // code from the last part of a for loop: for(...; ...; terminal), needed for e.g., continue };
@@ -256,14 +256,17 @@
}
// 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 @@
}
}
-// 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 @@
// If we've seen this struct type, return it
const glslang::TTypeList* glslangStruct = type.getStruct();
std::vector<spv::Id> structFields;
- spvType = structMap[explicitLayout][glslangStruct];
+ spvType = structMap[explicitLayout][matrixLayout][glslangStruct];
if (spvType)
break;
@@ -1524,13 +1528,16 @@
} 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 @@
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 @@
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 @@
}
// 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 @@
// 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 @@
}
// 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 @@
// 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 @@
// 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 @@
// 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 007c029..98e4ae6 100644
--- a/Test/baseResults/spv.layoutNested.vert.out
+++ b/Test/baseResults/spv.layoutNested.vert.out
@@ -7,132 +7,217 @@
// 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 aa403fc..ac44cbe 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 @@
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 06e8449..df606ff 100644
--- a/glslang/Include/Types.h
+++ b/glslang/Include/Types.h
@@ -186,15 +186,15 @@
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 42a916c..2b4d425 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 72e6010..9ed4f86 100644
--- a/glslang/MachineIndependent/ParseHelper.cpp
+++ b/glslang/MachineIndependent/ParseHelper.cpp
@@ -5345,8 +5345,11 @@
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 5e4104c..1a543c1 100644
--- a/glslang/MachineIndependent/linkValidate.cpp
+++ b/glslang/MachineIndependent/linkValidate.cpp
@@ -859,7 +859,7 @@
//
// 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 @@
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 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 @@
// 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 27bac7b..9933594 100644
--- a/glslang/MachineIndependent/localintermediate.h
+++ b/glslang/MachineIndependent/localintermediate.h
@@ -305,7 +305,7 @@
}
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 85caff7..5a1479a 100644
--- a/glslang/MachineIndependent/reflection.cpp
+++ b/glslang/MachineIndependent/reflection.cpp
@@ -123,7 +123,10 @@
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 @@
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;
}