SPV: Generalize multiple struct-type instances for interpolation/invariant qualifiers.

This commit is contained in:
John Kessenich 2015-12-24 10:30:13 -07:00
parent 69d01eadd6
commit e0b6cad44f
4 changed files with 108 additions and 50 deletions

View File

@ -91,7 +91,7 @@ protected:
spv::Id createSpvVariable(const glslang::TIntermSymbol*); spv::Id createSpvVariable(const glslang::TIntermSymbol*);
spv::Id getSampledType(const glslang::TSampler&); spv::Id getSampledType(const glslang::TSampler&);
spv::Id convertGlslangToSpvType(const glslang::TType& type); spv::Id convertGlslangToSpvType(const glslang::TType& type);
spv::Id convertGlslangToSpvType(const glslang::TType& type, glslang::TLayoutPacking, glslang::TLayoutMatrix); spv::Id convertGlslangToSpvType(const glslang::TType& type, glslang::TLayoutPacking, const glslang::TQualifier&);
glslang::TLayoutPacking getExplicitLayout(const glslang::TType& type) const; glslang::TLayoutPacking getExplicitLayout(const glslang::TType& type) const;
int getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking, glslang::TLayoutMatrix); int getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking, glslang::TLayoutMatrix);
int getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking, glslang::TLayoutMatrix); int getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking, glslang::TLayoutMatrix);
@ -299,30 +299,30 @@ spv::Decoration TranslateLayoutDecoration(const glslang::TType& type, glslang::T
// Translate glslang type to SPIR-V interpolation decorations. // Translate glslang type to SPIR-V interpolation decorations.
// Returns spv::Decoration(spv::BadValue) when no decoration // Returns spv::Decoration(spv::BadValue) when no decoration
// should be applied. // should be applied.
spv::Decoration TranslateInterpolationDecoration(const glslang::TType& type) spv::Decoration TranslateInterpolationDecoration(const glslang::TQualifier& qualifier)
{ {
if (type.getQualifier().smooth) { if (qualifier.smooth) {
// Smooth decoration doesn't exist in SPIR-V 1.0 // Smooth decoration doesn't exist in SPIR-V 1.0
return (spv::Decoration)spv::BadValue; return (spv::Decoration)spv::BadValue;
} }
if (type.getQualifier().nopersp) if (qualifier.nopersp)
return spv::DecorationNoPerspective; return spv::DecorationNoPerspective;
else if (type.getQualifier().patch) else if (qualifier.patch)
return spv::DecorationPatch; return spv::DecorationPatch;
else if (type.getQualifier().flat) else if (qualifier.flat)
return spv::DecorationFlat; return spv::DecorationFlat;
else if (type.getQualifier().centroid) else if (qualifier.centroid)
return spv::DecorationCentroid; return spv::DecorationCentroid;
else if (type.getQualifier().sample) else if (qualifier.sample)
return spv::DecorationSample; return spv::DecorationSample;
else else
return (spv::Decoration)spv::BadValue; return (spv::Decoration)spv::BadValue;
} }
// If glslang type is invaraiant, return SPIR-V invariant decoration. // If glslang type is invaraiant, return SPIR-V invariant decoration.
spv::Decoration TranslateInvariantDecoration(const glslang::TType& type) spv::Decoration TranslateInvariantDecoration(const glslang::TQualifier& qualifier)
{ {
if (type.getQualifier().invariant) if (qualifier.invariant)
return spv::DecorationInvariant; return spv::DecorationInvariant;
else else
return (spv::Decoration)spv::BadValue; return (spv::Decoration)spv::BadValue;
@ -420,6 +420,34 @@ spv::ImageFormat TranslateImageFormat(const glslang::TType& type)
} }
} }
void InheritQualifiers(glslang::TQualifier& child, const glslang::TQualifier& parent)
{
if (child.layoutMatrix == glslang::ElmNone)
child.layoutMatrix = parent.layoutMatrix;
if (parent.invariant)
child.invariant = true;
if (parent.nopersp)
child.nopersp = true;
if (parent.flat)
child.flat = true;
if (parent.centroid)
child.centroid = true;
if (parent.patch)
child.patch = true;
if (parent.sample)
child.sample = true;
}
bool HasNonLayoutQualifiers(const glslang::TQualifier& qualifier)
{
// This should list qualifiers that simultaneous satisify:
// - struct members can inherit from a struct declaration
// - effect decorations on the struct members (note smooth does not, and expecting something like volatile to effect the whole object)
// - are not part of the offset/st430/etc or row/column-major layout
return qualifier.invariant || qualifier.nopersp || qualifier.flat || qualifier.centroid || qualifier.patch || qualifier.sample;
}
// //
// Implement the TGlslangToSpvTraverser class. // Implement the TGlslangToSpvTraverser class.
// //
@ -1467,14 +1495,14 @@ spv::Id TGlslangToSpvTraverser::getSampledType(const glslang::TSampler& sampler)
// layout state rooted from the top-level type. // layout state rooted from the top-level type.
spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& type) spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& type)
{ {
return convertGlslangToSpvType(type, getExplicitLayout(type), type.getQualifier().layoutMatrix); return convertGlslangToSpvType(type, getExplicitLayout(type), type.getQualifier());
} }
// Do full recursive conversion of an arbitrary glslang type to a SPIR-V Id. // 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. // explicitLayout can be kept the same throughout the heirarchical recursive walk.
spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& type, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout) spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& type, glslang::TLayoutPacking explicitLayout, const glslang::TQualifier& qualifier)
{ {
spv::Id spvType = 0; spv::Id spvType = spv::NoResult;
switch (type.getBasicType()) { switch (type.getBasicType()) {
case glslang::EbtVoid: case glslang::EbtVoid:
@ -1503,13 +1531,13 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
case glslang::EbtSampler: case glslang::EbtSampler:
{ {
const glslang::TSampler& sampler = type.getSampler(); const glslang::TSampler& sampler = type.getSampler();
// an image is present, make its type // an image is present, make its type
spvType = builder.makeImageType(getSampledType(sampler), TranslateDimensionality(sampler), sampler.shadow, sampler.arrayed, sampler.ms, spvType = builder.makeImageType(getSampledType(sampler), TranslateDimensionality(sampler), sampler.shadow, sampler.arrayed, sampler.ms,
sampler.image ? 2 : 1, TranslateImageFormat(type)); sampler.image ? 2 : 1, TranslateImageFormat(type));
if (! sampler.image) { if (! sampler.image) {
spvType = builder.makeSampledImageType(spvType); spvType = builder.makeSampledImageType(spvType);
}
} }
}
break; break;
case glslang::EbtStruct: case glslang::EbtStruct:
case glslang::EbtBlock: case glslang::EbtBlock:
@ -1517,8 +1545,12 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
// If we've seen this struct type, return it // If we've seen this struct type, return it
const glslang::TTypeList* glslangStruct = type.getStruct(); const glslang::TTypeList* glslangStruct = type.getStruct();
std::vector<spv::Id> structFields; std::vector<spv::Id> structFields;
spvType = structMap[explicitLayout][matrixLayout][glslangStruct];
if (spvType) // Try to share structs for different layouts, but not yet for other
// kinds of qualification (primarily not yet including interpolant qualification).
if (! HasNonLayoutQualifiers(qualifier))
spvType = structMap[explicitLayout][qualifier.layoutMatrix][glslangStruct];
if (spvType != spv::NoResult)
break; break;
// else, we haven't seen it... // else, we haven't seen it...
@ -1536,16 +1568,17 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
} else { } else {
if (type.getBasicType() == glslang::EbtBlock) if (type.getBasicType() == glslang::EbtBlock)
memberRemapper[glslangStruct][i] = i - memberDelta; memberRemapper[glslangStruct][i] = i - memberDelta;
// modify just the children's view of matrix layout, if there is one for this member // modify just this child's view of the qualifier
glslang::TLayoutMatrix subMatrixLayout = glslangType.getQualifier().layoutMatrix; glslang::TQualifier subQualifier = glslangType.getQualifier();
structFields.push_back(convertGlslangToSpvType(glslangType, explicitLayout, InheritQualifiers(subQualifier, qualifier);
subMatrixLayout != glslang::ElmNone ? subMatrixLayout : matrixLayout)); structFields.push_back(convertGlslangToSpvType(glslangType, explicitLayout, subQualifier));
} }
} }
// Make the SPIR-V type // Make the SPIR-V type
spvType = builder.makeStructType(structFields, type.getTypeName().c_str()); spvType = builder.makeStructType(structFields, type.getTypeName().c_str());
structMap[explicitLayout][matrixLayout][glslangStruct] = spvType; if (! HasNonLayoutQualifiers(qualifier))
structMap[explicitLayout][qualifier.layoutMatrix][glslangStruct] = spvType;
// Name and decorate the non-hidden members // Name and decorate the non-hidden members
int offset = -1; int offset = -1;
@ -1555,18 +1588,17 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
if (type.getBasicType() == glslang::EbtBlock) if (type.getBasicType() == glslang::EbtBlock)
member = memberRemapper[glslangStruct][i]; member = memberRemapper[glslangStruct][i];
// modify just the children's view of matrix layout, if there is one for this member // modify just this child's view of the qualifier
glslang::TLayoutMatrix subMatrixLayout = glslangType.getQualifier().layoutMatrix; glslang::TQualifier subQualifier = glslangType.getQualifier();
if (subMatrixLayout == glslang::ElmNone) InheritQualifiers(subQualifier, qualifier);
subMatrixLayout = matrixLayout;
// using -1 above to indicate a hidden member // using -1 above to indicate a hidden member
if (member >= 0) { if (member >= 0) {
builder.addMemberName(spvType, member, glslangType.getFieldName().c_str()); builder.addMemberName(spvType, member, glslangType.getFieldName().c_str());
addMemberDecoration(spvType, member, TranslateLayoutDecoration(glslangType, subMatrixLayout)); addMemberDecoration(spvType, member, TranslateLayoutDecoration(glslangType, subQualifier.layoutMatrix));
addMemberDecoration(spvType, member, TranslatePrecisionDecoration(glslangType)); addMemberDecoration(spvType, member, TranslatePrecisionDecoration(glslangType));
addMemberDecoration(spvType, member, TranslateInterpolationDecoration(glslangType)); addMemberDecoration(spvType, member, TranslateInterpolationDecoration(subQualifier));
addMemberDecoration(spvType, member, TranslateInvariantDecoration(glslangType)); addMemberDecoration(spvType, member, TranslateInvariantDecoration(subQualifier));
if (glslangType.getQualifier().hasLocation()) if (glslangType.getQualifier().hasLocation())
builder.addMemberDecoration(spvType, member, spv::DecorationLocation, glslangType.getQualifier().layoutLocation); builder.addMemberDecoration(spvType, member, spv::DecorationLocation, glslangType.getQualifier().layoutLocation);
if (glslangType.getQualifier().hasComponent()) if (glslangType.getQualifier().hasComponent())
@ -1576,14 +1608,14 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
else if (explicitLayout != glslang::ElpNone) { else if (explicitLayout != glslang::ElpNone) {
// figure out what to do with offset, which is accumulating // figure out what to do with offset, which is accumulating
int nextOffset; int nextOffset;
updateMemberOffset(type, glslangType, offset, nextOffset, explicitLayout, subMatrixLayout); updateMemberOffset(type, glslangType, offset, nextOffset, explicitLayout, subQualifier.layoutMatrix);
if (offset >= 0) if (offset >= 0)
builder.addMemberDecoration(spvType, member, spv::DecorationOffset, offset); builder.addMemberDecoration(spvType, member, spv::DecorationOffset, offset);
offset = nextOffset; offset = nextOffset;
} }
if (glslangType.isMatrix() && explicitLayout != glslang::ElpNone) if (glslangType.isMatrix() && explicitLayout != glslang::ElpNone)
builder.addMemberDecoration(spvType, member, spv::DecorationMatrixStride, getMatrixStride(glslangType, explicitLayout, subMatrixLayout)); builder.addMemberDecoration(spvType, member, spv::DecorationMatrixStride, getMatrixStride(glslangType, explicitLayout, subQualifier.layoutMatrix));
// built-in variable decorations // built-in variable decorations
spv::BuiltIn builtIn = TranslateBuiltInDecoration(glslangType.getQualifier().builtIn); spv::BuiltIn builtIn = TranslateBuiltInDecoration(glslangType.getQualifier().builtIn);
@ -1593,7 +1625,7 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
} }
// Decorate the structure // Decorate the structure
addDecoration(spvType, TranslateLayoutDecoration(type, matrixLayout)); addDecoration(spvType, TranslateLayoutDecoration(type, qualifier.layoutMatrix));
addDecoration(spvType, TranslateBlockDecoration(type)); addDecoration(spvType, TranslateBlockDecoration(type));
if (type.getQualifier().hasStream()) if (type.getQualifier().hasStream())
builder.addDecoration(spvType, spv::DecorationStream, type.getQualifier().layoutStream); builder.addDecoration(spvType, spv::DecorationStream, type.getQualifier().layoutStream);
@ -1641,7 +1673,7 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
// except for the very top if it is an array of blocks; that array is // 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. // not laid out in memory in a way needing a stride.
if (explicitLayout && type.getBasicType() != glslang::EbtBlock) if (explicitLayout && type.getBasicType() != glslang::EbtBlock)
builder.addDecoration(spvType, spv::DecorationArrayStride, getArrayStride(type, explicitLayout, matrixLayout)); builder.addDecoration(spvType, spv::DecorationArrayStride, getArrayStride(type, explicitLayout, qualifier.layoutMatrix));
} }
return spvType; return spvType;
@ -3146,7 +3178,7 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
if (! symbol->getType().isStruct()) { if (! symbol->getType().isStruct()) {
addDecoration(id, TranslatePrecisionDecoration(symbol->getType())); addDecoration(id, TranslatePrecisionDecoration(symbol->getType()));
addDecoration(id, TranslateInterpolationDecoration(symbol->getType())); addDecoration(id, TranslateInterpolationDecoration(symbol->getType().getQualifier()));
if (symbol->getQualifier().hasLocation()) if (symbol->getQualifier().hasLocation())
builder.addDecoration(id, spv::DecorationLocation, symbol->getQualifier().layoutLocation); builder.addDecoration(id, spv::DecorationLocation, symbol->getQualifier().layoutLocation);
if (symbol->getQualifier().hasIndex()) if (symbol->getQualifier().hasIndex())
@ -3163,7 +3195,7 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
} }
} }
addDecoration(id, TranslateInvariantDecoration(symbol->getType())); addDecoration(id, TranslateInvariantDecoration(symbol->getType().getQualifier()));
if (symbol->getQualifier().hasStream()) if (symbol->getQualifier().hasStream())
builder.addDecoration(id, spv::DecorationStream, symbol->getQualifier().layoutStream); builder.addDecoration(id, spv::DecorationStream, symbol->getQualifier().layoutStream);
if (symbol->getQualifier().hasSet()) if (symbol->getQualifier().hasSet())

View File

@ -7,12 +7,12 @@ Linked vertex stage:
// Module Version 10000 // Module Version 10000
// Generated by (magic number): 80001 // Generated by (magic number): 80001
// Id's are bound by 63 // Id's are bound by 69
Capability Shader Capability Shader
1: ExtInstImport "GLSL.std.450" 1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450 MemoryModel Logical GLSL450
EntryPoint Vertex 4 "main" 61 62 EntryPoint Vertex 4 "main" 62 65 67 68
Source GLSL 450 Source GLSL 450
Name 4 "main" Name 4 "main"
Name 14 "S" Name 14 "S"
@ -82,8 +82,18 @@ Linked vertex stage:
MemberName 57(bBt3) 0 "ntcol" MemberName 57(bBt3) 0 "ntcol"
MemberName 57(bBt3) 1 "ntrow" MemberName 57(bBt3) 1 "ntrow"
Name 59 "bBtn3" Name 59 "bBtn3"
Name 61 "gl_VertexID" Name 60 "S"
Name 62 "gl_InstanceID" MemberName 60(S) 0 "a"
MemberName 60(S) 1 "b"
MemberName 60(S) 2 "c"
Name 62 "sout"
Name 63 "S"
MemberName 63(S) 0 "a"
MemberName 63(S) 1 "b"
MemberName 63(S) 2 "c"
Name 65 "soutinv"
Name 67 "gl_VertexID"
Name 68 "gl_InstanceID"
Decorate 13 ArrayStride 32 Decorate 13 ArrayStride 32
MemberDecorate 14(S) 0 Offset 0 MemberDecorate 14(S) 0 Offset 0
MemberDecorate 14(S) 1 ColMajor MemberDecorate 14(S) 1 ColMajor
@ -156,8 +166,15 @@ Linked vertex stage:
Decorate 57(bBt3) BufferBlock Decorate 57(bBt3) BufferBlock
Decorate 59(bBtn3) DescriptorSet 1 Decorate 59(bBtn3) DescriptorSet 1
Decorate 59(bBtn3) Binding 0 Decorate 59(bBtn3) Binding 0
Decorate 61(gl_VertexID) BuiltIn VertexId MemberDecorate 60(S) 0 Flat
Decorate 62(gl_InstanceID) BuiltIn InstanceId MemberDecorate 60(S) 1 Flat
MemberDecorate 60(S) 2 Flat
MemberDecorate 63(S) 0 Invariant
MemberDecorate 63(S) 1 Invariant
MemberDecorate 63(S) 2 Invariant
Decorate 65(soutinv) Invariant
Decorate 67(gl_VertexID) BuiltIn VertexId
Decorate 68(gl_InstanceID) BuiltIn InstanceId
2: TypeVoid 2: TypeVoid
3: TypeFunction 2 3: TypeFunction 2
6: TypeInt 32 1 6: TypeInt 32 1
@ -214,9 +231,15 @@ Linked vertex stage:
57(bBt3): TypeStruct 48(Nestor) 53(Nestor) 57(bBt3): TypeStruct 48(Nestor) 53(Nestor)
58: TypePointer Uniform 57(bBt3) 58: TypePointer Uniform 57(bBt3)
59(bBtn3): 58(ptr) Variable Uniform 59(bBtn3): 58(ptr) Variable Uniform
60: TypePointer Input 6(int) 60(S): TypeStruct 8(ivec3) 13 7(int)
61(gl_VertexID): 60(ptr) Variable Input 61: TypePointer Output 60(S)
62(gl_InstanceID): 60(ptr) Variable Input 62(sout): 61(ptr) Variable Output
63(S): TypeStruct 8(ivec3) 13 7(int)
64: TypePointer Output 63(S)
65(soutinv): 64(ptr) Variable Output
66: TypePointer Input 6(int)
67(gl_VertexID): 66(ptr) Variable Input
68(gl_InstanceID): 66(ptr) Variable Input
4(main): 2 Function None 3 4(main): 2 Function None 3
5: Label 5: Label
Return Return

View File

@ -1,6 +1,6 @@
#version 450 #version 450
// should get 3 SPV types for S: no layout, 140, and 430 // should get 3 SPV types for S: no layout, 140, and 430, plus extras for interpolation or invariant differences
struct S struct S
{ {
highp uvec3 a; highp uvec3 a;
@ -71,3 +71,6 @@ layout(set = 1, binding = 0, std430) buffer bBt3
void main() void main()
{ {
} }
flat out S sout;
invariant out S soutinv;

View File

@ -2,5 +2,5 @@
// For the version, it uses the latest git tag followed by the number of commits. // 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). // For the date, it uses the current date (when then script is run).
#define GLSLANG_REVISION "SPIRV99.865" #define GLSLANG_REVISION "SPIRV99.866"
#define GLSLANG_DATE "22-Dec-2015" #define GLSLANG_DATE "24-Dec-2015"