Merge pull request #333 from dneto0/defer-capabilities-for-some-struct-members-until-used

SPV: Defer capability decl for ClipDistance, CullDistance, PointSize until…
This commit is contained in:
John Kessenich 2016-06-08 10:59:51 -06:00
commit 5022d681d1
3 changed files with 60 additions and 38 deletions

View File

@ -109,7 +109,7 @@ public:
protected: protected:
spv::Decoration TranslateAuxiliaryStorageDecoration(const glslang::TQualifier& qualifier); spv::Decoration TranslateAuxiliaryStorageDecoration(const glslang::TQualifier& qualifier);
spv::BuiltIn TranslateBuiltInDecoration(glslang::TBuiltInVariable, bool member); spv::BuiltIn TranslateBuiltInDecoration(glslang::TBuiltInVariable, bool memberDeclaration);
spv::ImageFormat TranslateImageFormat(const glslang::TType& type); spv::ImageFormat TranslateImageFormat(const glslang::TType& type);
spv::Id createSpvVariable(const glslang::TIntermSymbol*); spv::Id createSpvVariable(const glslang::TIntermSymbol*);
spv::Id getSampledType(const glslang::TSampler&); spv::Id getSampledType(const glslang::TSampler&);
@ -122,7 +122,7 @@ protected:
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);
void updateMemberOffset(const glslang::TType& structType, const glslang::TType& memberType, int& currentOffset, int& nextOffset, glslang::TLayoutPacking, glslang::TLayoutMatrix); void updateMemberOffset(const glslang::TType& structType, const glslang::TType& memberType, int& currentOffset, int& nextOffset, glslang::TLayoutPacking, glslang::TLayoutMatrix);
void declareClipCullCapability(const glslang::TTypeList& members, int member); void declareUseOfStructMember(const glslang::TTypeList& members, int glslangMember);
bool isShaderEntrypoint(const glslang::TIntermAggregate* node); bool isShaderEntrypoint(const glslang::TIntermAggregate* node);
void makeFunctions(const glslang::TIntermSequence&); void makeFunctions(const glslang::TIntermSequence&);
@ -401,11 +401,17 @@ spv::Decoration TranslateNoContractionDecoration(const glslang::TQualifier& qual
return (spv::Decoration)spv::BadValue; return (spv::Decoration)spv::BadValue;
} }
// Translate glslang built-in variable to SPIR-V built in decoration. // Translate a glslang built-in variable to a SPIR-V built in decoration. Also generate
spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltInVariable builtIn, bool member) // associated capabilities when required. For some built-in variables, a capability
// is generated only when using the variable in an executable instruction, but not when
// just declaring a struct member variable with it. This is true for PointSize,
// ClipDistance, and CullDistance.
spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltInVariable builtIn, bool memberDeclaration)
{ {
switch (builtIn) { switch (builtIn) {
case glslang::EbvPointSize: case glslang::EbvPointSize:
// Defer adding the capability until the built-in is actually used.
if (!memberDeclaration) {
switch (glslangIntermediate->getStage()) { switch (glslangIntermediate->getStage()) {
case EShLangGeometry: case EShLangGeometry:
builder.addCapability(spv::CapabilityGeometryPointSize); builder.addCapability(spv::CapabilityGeometryPointSize);
@ -417,6 +423,7 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI
default: default:
break; break;
} }
}
return spv::BuiltInPointSize; return spv::BuiltInPointSize;
// These *Distance capabilities logically belong here, but if the member is declared and // These *Distance capabilities logically belong here, but if the member is declared and
@ -426,12 +433,12 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI
// use needed is to trigger the capability. // use needed is to trigger the capability.
// //
case glslang::EbvClipDistance: case glslang::EbvClipDistance:
if (! member) if (!memberDeclaration)
builder.addCapability(spv::CapabilityClipDistance); builder.addCapability(spv::CapabilityClipDistance);
return spv::BuiltInClipDistance; return spv::BuiltInClipDistance;
case glslang::EbvCullDistance: case glslang::EbvCullDistance:
if (! member) if (!memberDeclaration)
builder.addCapability(spv::CapabilityCullDistance); builder.addCapability(spv::CapabilityCullDistance);
return spv::BuiltInCullDistance; return spv::BuiltInCullDistance;
@ -923,30 +930,34 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
// Add the next element in the chain // Add the next element in the chain
int index = node->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst(); const int glslangIndex = node->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst();
if (node->getLeft()->getBasicType() == glslang::EbtBlock && node->getOp() == glslang::EOpIndexDirectStruct) {
// This may be, e.g., an anonymous block-member selection, which generally need
// index remapping due to hidden members in anonymous blocks.
std::vector<int>& remapper = memberRemapper[node->getLeft()->getType().getStruct()];
assert(remapper.size() > 0);
index = remapper[index];
}
if (! node->getLeft()->getType().isArray() && if (! node->getLeft()->getType().isArray() &&
node->getLeft()->getType().isVector() && node->getLeft()->getType().isVector() &&
node->getOp() == glslang::EOpIndexDirect) { node->getOp() == glslang::EOpIndexDirect) {
// This is essentially a hard-coded vector swizzle of size 1, // This is essentially a hard-coded vector swizzle of size 1,
// so short circuit the access-chain stuff with a swizzle. // so short circuit the access-chain stuff with a swizzle.
std::vector<unsigned> swizzle; std::vector<unsigned> swizzle;
swizzle.push_back(node->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst()); swizzle.push_back(glslangIndex);
builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType())); builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()));
} else { } else {
// normal case for indexing array or structure or block int spvIndex = glslangIndex;
builder.accessChainPush(builder.makeIntConstant(index)); if (node->getLeft()->getBasicType() == glslang::EbtBlock &&
node->getOp() == glslang::EOpIndexDirectStruct)
{
// This may be, e.g., an anonymous block-member selection, which generally need
// index remapping due to hidden members in anonymous blocks.
std::vector<int>& remapper = memberRemapper[node->getLeft()->getType().getStruct()];
assert(remapper.size() > 0);
spvIndex = remapper[glslangIndex];
}
// Add capabilities here for accessing clip/cull distance // normal case for indexing array or structure or block
builder.accessChainPush(builder.makeIntConstant(spvIndex));
// Add capabilities here for accessing PointSize and clip/cull distance.
// We have deferred generation of associated capabilities until now.
if (node->getLeft()->getType().isStruct() && ! node->getLeft()->getType().isArray()) if (node->getLeft()->getType().isStruct() && ! node->getLeft()->getType().isArray())
declareClipCullCapability(*node->getLeft()->getType().getStruct(), index); declareUseOfStructMember(*(node->getLeft()->getType().getStruct()), glslangIndex);
} }
} }
return false; return false;
@ -2203,12 +2214,23 @@ void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& /*structTy
nextOffset = currentOffset + memberSize; nextOffset = currentOffset + memberSize;
} }
void TGlslangToSpvTraverser::declareClipCullCapability(const glslang::TTypeList& members, int member) void TGlslangToSpvTraverser::declareUseOfStructMember(const glslang::TTypeList& members, int glslangMember)
{ {
if (members[member].type->getQualifier().builtIn == glslang::EbvClipDistance) const glslang::TBuiltInVariable glslangBuiltIn = members[glslangMember].type->getQualifier().builtIn;
builder.addCapability(spv::CapabilityClipDistance); switch (glslangBuiltIn)
if (members[member].type->getQualifier().builtIn == glslang::EbvCullDistance) {
builder.addCapability(spv::CapabilityCullDistance); case glslang::EbvClipDistance:
case glslang::EbvCullDistance:
case glslang::EbvPointSize:
// Generate the associated capability. Delegate to TranslateBuiltInDecoration.
// Alternately, we could just call this for any glslang built-in, since the
// capability already guards against duplicates.
TranslateBuiltInDecoration(glslangBuiltIn, false);
break;
default:
// Capabilities were already generated when the struct was declared.
break;
}
} }
bool TGlslangToSpvTraverser::isShaderEntrypoint(const glslang::TIntermAggregate* node) bool TGlslangToSpvTraverser::isShaderEntrypoint(const glslang::TIntermAggregate* node)

View File

@ -10,6 +10,7 @@ Linked vertex stage:
// Id's are bound by 66 // Id's are bound by 66
Capability Shader Capability Shader
Capability ClipDistance
1: ExtInstImport "GLSL.std.450" 1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450 MemoryModel Logical GLSL450
EntryPoint Vertex 4 "main" 12 23 34 38 41 42 62 65 EntryPoint Vertex 4 "main" 12 23 34 38 41 42 62 65

View File

@ -10,7 +10,6 @@ Linked tessellation evaluation stage:
// Id's are bound by 119 // Id's are bound by 119
Capability Tessellation Capability Tessellation
Capability TessellationPointSize
1: ExtInstImport "GLSL.std.450" 1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450 MemoryModel Logical GLSL450
EntryPoint TessellationEvaluation 4 "main" 12 21 62 112 EntryPoint TessellationEvaluation 4 "main" 12 21 62 112