diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index 2a11d8ee..a75c7caf 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -88,6 +88,7 @@ public: void dumpSpv(std::vector& out); protected: + spv::BuiltIn TranslateBuiltInDecoration(glslang::TBuiltInVariable); spv::Id createSpvVariable(const glslang::TIntermSymbol*); spv::Id getSampledType(const glslang::TSampler&); spv::Id convertGlslangToSpvType(const glslang::TType& type); @@ -120,6 +121,7 @@ protected: void addDecoration(spv::Id id, spv::Decoration dec); void addDecoration(spv::Id id, spv::Decoration dec, unsigned value); void addMemberDecoration(spv::Id id, int member, spv::Decoration dec); + void addMemberDecoration(spv::Id id, int member, spv::Decoration dec, unsigned value); spv::Id createSpvSpecConstant(const glslang::TIntermTyped&); spv::Id createSpvConstant(const glslang::TType& type, const glslang::TConstUnionArray&, int& nextConst, bool specConstant); bool isTrivialLeaf(const glslang::TIntermTyped* node); @@ -319,7 +321,7 @@ spv::Decoration TranslateInterpolationDecoration(const glslang::TQualifier& qual return (spv::Decoration)spv::BadValue; } -// If glslang type is invaraiant, return SPIR-V invariant decoration. +// If glslang type is invariant, return SPIR-V invariant decoration. spv::Decoration TranslateInvariantDecoration(const glslang::TQualifier& qualifier) { if (qualifier.invariant) @@ -329,13 +331,34 @@ spv::Decoration TranslateInvariantDecoration(const glslang::TQualifier& qualifie } // Translate glslang built-in variable to SPIR-V built in decoration. -spv::BuiltIn TranslateBuiltInDecoration(glslang::TBuiltInVariable builtIn) +spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltInVariable builtIn) { switch (builtIn) { + case glslang::EbvPointSize: + switch (glslangIntermediate->getStage()) { + case EShLangGeometry: + builder.addCapability(spv::CapabilityGeometryPointSize); + break; + case EShLangTessControl: + case EShLangTessEvaluation: + builder.addCapability(spv::CapabilityTessellationPointSize); + break; + } + return spv::BuiltInPointSize; + + case glslang::EbvClipDistance: + builder.addCapability(spv::CapabilityClipDistance); + return spv::BuiltInClipDistance; + + case glslang::EbvCullDistance: + builder.addCapability(spv::CapabilityCullDistance); + return spv::BuiltInCullDistance; + + case glslang::EbvViewportIndex: + // TODO: builder.addCapability(spv::CapabilityMultiViewport); + return spv::BuiltInViewportIndex; + case glslang::EbvPosition: return spv::BuiltInPosition; - case glslang::EbvPointSize: return spv::BuiltInPointSize; - case glslang::EbvClipDistance: return spv::BuiltInClipDistance; - case glslang::EbvCullDistance: return spv::BuiltInCullDistance; case glslang::EbvVertexId: return spv::BuiltInVertexId; case glslang::EbvInstanceId: return spv::BuiltInInstanceId; case glslang::EbvBaseVertex: @@ -347,7 +370,6 @@ spv::BuiltIn TranslateBuiltInDecoration(glslang::TBuiltInVariable builtIn) case glslang::EbvPrimitiveId: return spv::BuiltInPrimitiveId; case glslang::EbvInvocationId: return spv::BuiltInInvocationId; case glslang::EbvLayer: return spv::BuiltInLayer; - case glslang::EbvViewportIndex: return spv::BuiltInViewportIndex; case glslang::EbvTessLevelInner: return spv::BuiltInTessLevelInner; case glslang::EbvTessLevelOuter: return spv::BuiltInTessLevelOuter; case glslang::EbvTessCoord: return spv::BuiltInTessCoord; @@ -476,8 +498,10 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(const glslang::TIntermediate* gls // Add the top-level modes for this shader. - if (glslangIntermediate->getXfbMode()) + if (glslangIntermediate->getXfbMode()) { + builder.addCapability(spv::CapabilityTransformFeedback); builder.addExecutionMode(shaderEntry, spv::ExecutionModeXfb); + } unsigned int mode; switch (glslangIntermediate->getStage()) { @@ -1659,16 +1683,19 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty // built-in variable decorations spv::BuiltIn builtIn = TranslateBuiltInDecoration(glslangType.getQualifier().builtIn); if (builtIn != spv::BadValue) - builder.addMemberDecoration(spvType, member, spv::DecorationBuiltIn, (int)builtIn); + addMemberDecoration(spvType, member, spv::DecorationBuiltIn, (int)builtIn); } } // Decorate the structure addDecoration(spvType, TranslateLayoutDecoration(type, qualifier.layoutMatrix)); addDecoration(spvType, TranslateBlockDecoration(type)); - if (type.getQualifier().hasStream()) + if (type.getQualifier().hasStream()) { + builder.addCapability(spv::CapabilityGeometryStreams); builder.addDecoration(spvType, spv::DecorationStream, type.getQualifier().layoutStream); + } if (glslangIntermediate->getXfbMode()) { + builder.addCapability(spv::CapabilityTransformFeedback); if (type.getQualifier().hasXfbStride()) builder.addDecoration(spvType, spv::DecorationXfbStride, type.getQualifier().layoutXfbStride); if (type.getQualifier().hasXfbBuffer()) @@ -2787,24 +2814,31 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv: unaryOp = spv::OpFwidth; break; case glslang::EOpDPdxFine: + builder.addCapability(spv::CapabilityDerivativeControl); unaryOp = spv::OpDPdxFine; break; case glslang::EOpDPdyFine: + builder.addCapability(spv::CapabilityDerivativeControl); unaryOp = spv::OpDPdyFine; break; case glslang::EOpFwidthFine: + builder.addCapability(spv::CapabilityDerivativeControl); unaryOp = spv::OpFwidthFine; break; case glslang::EOpDPdxCoarse: + builder.addCapability(spv::CapabilityDerivativeControl); unaryOp = spv::OpDPdxCoarse; break; case glslang::EOpDPdyCoarse: + builder.addCapability(spv::CapabilityDerivativeControl); unaryOp = spv::OpDPdyCoarse; break; case glslang::EOpFwidthCoarse: + builder.addCapability(spv::CapabilityDerivativeControl); unaryOp = spv::OpFwidthCoarse; break; case glslang::EOpInterpolateAtCentroid: + builder.addCapability(spv::CapabilityInterpolationFunction); libCall = spv::GLSLstd450InterpolateAtCentroid; break; case glslang::EOpAny: @@ -3180,9 +3214,11 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv:: libCall = spv::GLSLstd450Refract; break; case glslang::EOpInterpolateAtSample: + builder.addCapability(spv::CapabilityInterpolationFunction); libCall = spv::GLSLstd450InterpolateAtSample; break; case glslang::EOpInterpolateAtOffset: + builder.addCapability(spv::CapabilityInterpolationFunction); libCall = spv::GLSLstd450InterpolateAtOffset; break; case glslang::EOpAddCarry: @@ -3352,6 +3388,7 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol if (symbol->getQualifier().hasComponent()) builder.addDecoration(id, spv::DecorationComponent, symbol->getQualifier().layoutComponent); if (glslangIntermediate->getXfbMode()) { + builder.addCapability(spv::CapabilityTransformFeedback); if (symbol->getQualifier().hasXfbStride()) builder.addDecoration(id, spv::DecorationXfbStride, symbol->getQualifier().layoutXfbStride); if (symbol->getQualifier().hasXfbBuffer()) @@ -3362,13 +3399,16 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol } addDecoration(id, TranslateInvariantDecoration(symbol->getType().getQualifier())); - if (symbol->getQualifier().hasStream()) + if (symbol->getQualifier().hasStream()) { + builder.addCapability(spv::CapabilityGeometryStreams); builder.addDecoration(id, spv::DecorationStream, symbol->getQualifier().layoutStream); + } if (symbol->getQualifier().hasSet()) builder.addDecoration(id, spv::DecorationDescriptorSet, symbol->getQualifier().layoutSet); if (symbol->getQualifier().hasBinding()) builder.addDecoration(id, spv::DecorationBinding, symbol->getQualifier().layoutBinding); if (glslangIntermediate->getXfbMode()) { + builder.addCapability(spv::CapabilityTransformFeedback); if (symbol->getQualifier().hasXfbStride()) builder.addDecoration(id, spv::DecorationXfbStride, symbol->getQualifier().layoutXfbStride); if (symbol->getQualifier().hasXfbBuffer()) @@ -3378,7 +3418,7 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol // built-in variable decorations spv::BuiltIn builtIn = TranslateBuiltInDecoration(symbol->getQualifier().builtIn); if (builtIn != spv::BadValue) - builder.addDecoration(id, spv::DecorationBuiltIn, (int)builtIn); + addDecoration(id, spv::DecorationBuiltIn, (int)builtIn); return id; } @@ -3404,6 +3444,13 @@ void TGlslangToSpvTraverser::addMemberDecoration(spv::Id id, int member, spv::De builder.addMemberDecoration(id, (unsigned)member, dec); } +// If 'dec' is valid, add a one-operand decoration to a struct member +void TGlslangToSpvTraverser::addMemberDecoration(spv::Id id, int member, spv::Decoration dec, unsigned value) +{ + if (dec != spv::BadValue) + builder.addMemberDecoration(id, (unsigned)member, dec, value); +} + // Make a full tree of instructions to build a SPIR-V specialization constant, // or regularly constant if possible. // diff --git a/SPIRV/SpvBuilder.h b/SPIRV/SpvBuilder.h index 33c3ec4b..fbfbfad0 100755 --- a/SPIRV/SpvBuilder.h +++ b/SPIRV/SpvBuilder.h @@ -55,6 +55,7 @@ #include #include #include +#include namespace spv { @@ -78,7 +79,7 @@ public: memoryModel = mem; } - void addCapability(spv::Capability cap) { capabilities.push_back(cap); } + void addCapability(spv::Capability cap) { capabilities.insert(cap); } // To get a new for anything needing a new one. Id getUniqueId() { return ++uniqueId; } @@ -525,7 +526,7 @@ public: std::vector extensions; AddressingModel addressModel; MemoryModel memoryModel; - std::vector capabilities; + std::set capabilities; int builderNumber; Module module; Block* buildPoint; diff --git a/Test/baseResults/spv.130.frag.out b/Test/baseResults/spv.130.frag.out index 7091d5a9..6b47b7dd 100644 --- a/Test/baseResults/spv.130.frag.out +++ b/Test/baseResults/spv.130.frag.out @@ -10,6 +10,7 @@ Linked fragment stage: // Id's are bound by 213 Capability Shader + Capability ClipDistance 1: ExtInstImport "GLSL.std.450" MemoryModel Logical GLSL450 EntryPoint Fragment 4 "main" 17 68 79 99 173 184 185 186 diff --git a/Test/baseResults/spv.140.frag.out b/Test/baseResults/spv.140.frag.out index 01b2e472..6028f604 100755 --- a/Test/baseResults/spv.140.frag.out +++ b/Test/baseResults/spv.140.frag.out @@ -8,6 +8,7 @@ Linked fragment stage: // Id's are bound by 101 Capability Shader + Capability ClipDistance 1: ExtInstImport "GLSL.std.450" MemoryModel Logical GLSL450 EntryPoint Fragment 4 "main" 16 28 33 43 diff --git a/Test/baseResults/spv.150.geom.out b/Test/baseResults/spv.150.geom.out index 31fda5fc..b09f0c04 100755 --- a/Test/baseResults/spv.150.geom.out +++ b/Test/baseResults/spv.150.geom.out @@ -8,6 +8,9 @@ Linked geometry stage: // Id's are bound by 71 Capability Geometry + Capability GeometryPointSize + Capability ClipDistance + Capability GeometryStreams 1: ExtInstImport "GLSL.std.450" MemoryModel Logical GLSL450 EntryPoint Geometry 4 "main" 10 18 29 33 47 49 51 70 diff --git a/Test/baseResults/spv.150.vert.out b/Test/baseResults/spv.150.vert.out index 8767bf80..2a347b40 100755 --- a/Test/baseResults/spv.150.vert.out +++ b/Test/baseResults/spv.150.vert.out @@ -8,6 +8,7 @@ Linked vertex stage: // Id's are bound by 50 Capability Shader + Capability ClipDistance 1: ExtInstImport "GLSL.std.450" MemoryModel Logical GLSL450 EntryPoint Vertex 4 "main" 13 17 39 48 49 diff --git a/Test/baseResults/spv.330.geom.out b/Test/baseResults/spv.330.geom.out index fb409a9d..55ee35c8 100755 --- a/Test/baseResults/spv.330.geom.out +++ b/Test/baseResults/spv.330.geom.out @@ -8,6 +8,8 @@ Linked geometry stage: // Id's are bound by 32 Capability Geometry + Capability ClipDistance + Capability GeometryStreams 1: ExtInstImport "GLSL.std.450" MemoryModel Logical GLSL450 EntryPoint Geometry 4 "main" 13 20 diff --git a/Test/baseResults/spv.400.frag.out b/Test/baseResults/spv.400.frag.out index f0709740..1dcfbd30 100644 --- a/Test/baseResults/spv.400.frag.out +++ b/Test/baseResults/spv.400.frag.out @@ -10,6 +10,7 @@ Linked fragment stage: // Id's are bound by 1104 Capability Shader + Capability ClipDistance 1: ExtInstImport "GLSL.std.450" MemoryModel Logical GLSL450 EntryPoint Fragment 4 "main" 13 1025 1031 1036 1048 1074 1095 1097 diff --git a/Test/baseResults/spv.400.tesc.out b/Test/baseResults/spv.400.tesc.out index 6905c4a0..eea07ce7 100755 --- a/Test/baseResults/spv.400.tesc.out +++ b/Test/baseResults/spv.400.tesc.out @@ -10,6 +10,8 @@ Linked tessellation control stage: // Id's are bound by 93 Capability Tessellation + Capability TessellationPointSize + Capability ClipDistance 1: ExtInstImport "GLSL.std.450" MemoryModel Logical GLSL450 EntryPoint TessellationControl 4 "main" 23 40 43 46 52 66 73 79 83 84 87 88 91 92 diff --git a/Test/baseResults/spv.400.tese.out b/Test/baseResults/spv.400.tese.out index 325da158..03e181ce 100755 --- a/Test/baseResults/spv.400.tese.out +++ b/Test/baseResults/spv.400.tese.out @@ -10,6 +10,8 @@ Linked tessellation evaluation stage: // Id's are bound by 98 Capability Tessellation + Capability TessellationPointSize + Capability ClipDistance 1: ExtInstImport "GLSL.std.450" MemoryModel Logical GLSL450 EntryPoint TessellationEvaluation 4 "main" 21 38 41 47 53 61 68 77 81 82 86 90 93 94 97 diff --git a/Test/baseResults/spv.420.geom.out b/Test/baseResults/spv.420.geom.out index 3ba3dacb..0d659c5b 100644 --- a/Test/baseResults/spv.420.geom.out +++ b/Test/baseResults/spv.420.geom.out @@ -10,6 +10,8 @@ Linked geometry stage: // Id's are bound by 74 Capability Geometry + Capability GeometryPointSize + Capability GeometryStreams 1: ExtInstImport "GLSL.std.450" MemoryModel Logical GLSL450 EntryPoint Geometry 4 "main" 14 23 28 33 46 diff --git a/Test/baseResults/spv.430.vert.out b/Test/baseResults/spv.430.vert.out index 750fff07..2bf2aafd 100755 --- a/Test/baseResults/spv.430.vert.out +++ b/Test/baseResults/spv.430.vert.out @@ -10,6 +10,7 @@ Linked vertex stage: // Id's are bound by 69 Capability Shader + Capability ClipDistance 1: ExtInstImport "GLSL.std.450" MemoryModel Logical GLSL450 EntryPoint Vertex 4 "main" 12 23 34 44 45 65 67 68 diff --git a/Test/baseResults/spv.bool.vert.out b/Test/baseResults/spv.bool.vert.out index 0fece207..7f85e6b0 100644 --- a/Test/baseResults/spv.bool.vert.out +++ b/Test/baseResults/spv.bool.vert.out @@ -10,6 +10,8 @@ Linked vertex stage: // Id's are bound by 50 Capability Shader + Capability ClipDistance + Capability CullDistance 1: ExtInstImport "GLSL.std.450" MemoryModel Logical GLSL450 EntryPoint Vertex 4 "main" 24 48 49 diff --git a/Test/baseResults/spv.interpOps.frag.out b/Test/baseResults/spv.interpOps.frag.out index ef701f02..c132b441 100644 --- a/Test/baseResults/spv.interpOps.frag.out +++ b/Test/baseResults/spv.interpOps.frag.out @@ -10,6 +10,7 @@ Linked fragment stage: // Id's are bound by 101 Capability Shader + Capability InterpolationFunction 1: ExtInstImport "GLSL.std.450" MemoryModel Logical GLSL450 EntryPoint Fragment 4 "main" 13 24 33 41 99