diff options
Diffstat (limited to 'thirdparty/glslang/SPIRV/GlslangToSpv.cpp')
-rwxr-xr-x[-rw-r--r--] | thirdparty/glslang/SPIRV/GlslangToSpv.cpp | 1681 |
1 files changed, 988 insertions, 693 deletions
diff --git a/thirdparty/glslang/SPIRV/GlslangToSpv.cpp b/thirdparty/glslang/SPIRV/GlslangToSpv.cpp index 4ef6cd7fc1..0c8a87e3ce 100644..100755 --- a/thirdparty/glslang/SPIRV/GlslangToSpv.cpp +++ b/thirdparty/glslang/SPIRV/GlslangToSpv.cpp @@ -46,9 +46,7 @@ namespace spv { #include "GLSL.std.450.h" #include "GLSL.ext.KHR.h" #include "GLSL.ext.EXT.h" -#ifdef AMD_EXTENSIONS #include "GLSL.ext.AMD.h" -#endif #include "GLSL.ext.NV.h" } @@ -89,9 +87,29 @@ private: }; struct OpDecorations { + public: + OpDecorations(spv::Decoration precision, spv::Decoration noContraction, spv::Decoration nonUniform) : + precision(precision) +#ifndef GLSLANG_WEB + , + noContraction(noContraction), + nonUniform(nonUniform) +#endif + { } + spv::Decoration precision; - spv::Decoration noContraction; - spv::Decoration nonUniform; + +#ifdef GLSLANG_WEB + void addNoContraction(spv::Builder&, spv::Id) const { } + void addNonUniform(spv::Builder&, spv::Id) const { } +#else + void addNoContraction(spv::Builder& builder, spv::Id t) { builder.addDecoration(t, noContraction); } + void addNonUniform(spv::Builder& builder, spv::Id t) { builder.addDecoration(t, nonUniform); } + protected: + spv::Decoration noContraction; + spv::Decoration nonUniform; +#endif + }; } // namespace @@ -138,7 +156,7 @@ protected: spv::LoopControlMask TranslateLoopControl(const glslang::TIntermLoop&, std::vector<unsigned int>& operands) const; spv::StorageClass TranslateStorageClass(const glslang::TType&); void addIndirectionIndexCapabilities(const glslang::TType& baseType, const glslang::TType& indexType); - spv::Id createSpvVariable(const glslang::TIntermSymbol*); + spv::Id createSpvVariable(const glslang::TIntermSymbol*, spv::Id forcedType); spv::Id getSampledType(const glslang::TSampler&); spv::Id getInvertedSwizzleType(const glslang::TIntermTyped&); spv::Id createInvertedSwizzle(spv::Decoration precision, const glslang::TIntermTyped&, spv::Id parentResult); @@ -169,7 +187,7 @@ protected: void makeGlobalInitializers(const glslang::TIntermSequence&); void visitFunctions(const glslang::TIntermSequence&); void handleFunctionEntry(const glslang::TIntermAggregate* node); - void translateArguments(const glslang::TIntermAggregate& node, std::vector<spv::Id>& arguments); + void translateArguments(const glslang::TIntermAggregate& node, std::vector<spv::Id>& arguments, spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags); void translateArguments(glslang::TIntermUnary& node, std::vector<spv::Id>& arguments); spv::Id createImageTextureFunctionCall(glslang::TIntermOperator* node); spv::Id handleUserFunctionCall(const glslang::TIntermAggregate*); @@ -178,36 +196,30 @@ protected: glslang::TBasicType typeProxy, bool reduceComparison = true); spv::Id createBinaryMatrixOperation(spv::Op, OpDecorations&, spv::Id typeId, spv::Id left, spv::Id right); spv::Id createUnaryOperation(glslang::TOperator op, OpDecorations&, spv::Id typeId, spv::Id operand, - glslang::TBasicType typeProxy); + glslang::TBasicType typeProxy, const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags); spv::Id createUnaryMatrixOperation(spv::Op op, OpDecorations&, spv::Id typeId, spv::Id operand, glslang::TBasicType typeProxy); spv::Id createConversion(glslang::TOperator op, OpDecorations&, spv::Id destTypeId, spv::Id operand, glslang::TBasicType typeProxy); spv::Id createIntWidthConversion(glslang::TOperator op, spv::Id operand, int vectorSize); spv::Id makeSmearedConstant(spv::Id constant, int vectorSize); - spv::Id createAtomicOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy); + spv::Id createAtomicOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy, const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags); spv::Id createInvocationsOperation(glslang::TOperator op, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy); spv::Id CreateInvocationsVectorOperation(spv::Op op, spv::GroupOperation groupOperation, spv::Id typeId, std::vector<spv::Id>& operands); spv::Id createSubgroupOperation(glslang::TOperator op, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy); spv::Id createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy); spv::Id createNoArgOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId); spv::Id getSymbolId(const glslang::TIntermSymbol* node); -#ifdef NV_EXTENSIONS void addMeshNVDecoration(spv::Id id, int member, const glslang::TQualifier & qualifier); -#endif spv::Id createSpvConstant(const glslang::TIntermTyped&); spv::Id createSpvConstantFromConstUnionArray(const glslang::TType& type, const glslang::TConstUnionArray&, int& nextConst, bool specConstant); bool isTrivialLeaf(const glslang::TIntermTyped* node); bool isTrivial(const glslang::TIntermTyped* node); spv::Id createShortCircuit(glslang::TOperator, glslang::TIntermTyped& left, glslang::TIntermTyped& right); -#ifdef AMD_EXTENSIONS spv::Id getExtBuiltins(const char* name); -#endif - void addPre13Extension(const char* ext) - { - if (builder.getSpvVersion() < glslang::EShTargetSpv_1_3) - builder.addExtension(ext); - } + std::pair<spv::Id, spv::Id> getForcedType(spv::BuiltIn, const glslang::TType&); + spv::Id translateForcedType(spv::Id object); + spv::Id createCompositeConstruct(spv::Id typeId, std::vector<spv::Id> constituents); glslang::SpvOptions& options; spv::Function* shaderEntry; @@ -224,6 +236,7 @@ protected: bool linkageOnly; // true when visiting the set of objects in the AST present only for establishing interface, whether or not they were statically used std::set<spv::Id> iOSet; // all input/output variables from either static use or declaration of interface const glslang::TIntermediate* glslangIntermediate; + bool nanMinMaxClamp; // true if use NMin/NMax/NClamp instead of FMin/FMax/FClamp spv::Id stdBuiltins; std::unordered_map<const char*, spv::Id> extBuiltinMap; @@ -232,11 +245,17 @@ protected: std::unordered_map<std::string, spv::Function*> functionMap; std::unordered_map<const glslang::TTypeList*, spv::Id> structMap[glslang::ElpCount][glslang::ElmCount]; // for mapping glslang block indices to spv indices (e.g., due to hidden members): - std::unordered_map<const glslang::TTypeList*, std::vector<int> > memberRemapper; + std::unordered_map<int, std::vector<int>> memberRemapper; + // for mapping glslang symbol struct to symbol Id + std::unordered_map<const glslang::TTypeList*, int> glslangTypeToIdMap; std::stack<bool> breakForLoop; // false means break for switch std::unordered_map<std::string, const glslang::TIntermSymbol*> counterOriginator; // Map pointee types for EbtReference to their forward pointers std::map<const glslang::TType *, spv::Id> forwardPointers; + // Type forcing, for when SPIR-V wants a different type than the AST, + // requiring local translation to and from SPIR-V type on every access. + // Maps <builtin-variable-id -> AST-required-type-id> + std::unordered_map<spv::Id, spv::Id> forceType; }; // @@ -246,6 +265,10 @@ protected: // Translate glslang profile to SPIR-V source language. spv::SourceLanguage TranslateSourceLanguage(glslang::EShSource source, EProfile profile) { +#ifdef GLSLANG_WEB + return spv::SourceLanguageESSL; +#endif + switch (source) { case glslang::EShSourceGlsl: switch (profile) { @@ -270,12 +293,12 @@ spv::ExecutionModel TranslateExecutionModel(EShLanguage stage) { switch (stage) { case EShLangVertex: return spv::ExecutionModelVertex; + case EShLangFragment: return spv::ExecutionModelFragment; + case EShLangCompute: return spv::ExecutionModelGLCompute; +#ifndef GLSLANG_WEB case EShLangTessControl: return spv::ExecutionModelTessellationControl; case EShLangTessEvaluation: return spv::ExecutionModelTessellationEvaluation; case EShLangGeometry: return spv::ExecutionModelGeometry; - case EShLangFragment: return spv::ExecutionModelFragment; - case EShLangCompute: return spv::ExecutionModelGLCompute; -#ifdef NV_EXTENSIONS case EShLangRayGenNV: return spv::ExecutionModelRayGenerationNV; case EShLangIntersectNV: return spv::ExecutionModelIntersectionNV; case EShLangAnyHitNV: return spv::ExecutionModelAnyHitNV; @@ -334,7 +357,7 @@ spv::Decoration TranslateBlockDecoration(const glslang::TType& type, bool useSto case glslang::EvqBuffer: return useStorageBuffer ? spv::DecorationBlock : spv::DecorationBufferBlock; case glslang::EvqVaryingIn: return spv::DecorationBlock; case glslang::EvqVaryingOut: return spv::DecorationBlock; -#ifdef NV_EXTENSIONS +#ifndef GLSLANG_WEB case glslang::EvqPayloadNV: return spv::DecorationBlock; case glslang::EvqPayloadInNV: return spv::DecorationBlock; case glslang::EvqHitAttrNV: return spv::DecorationBlock; @@ -354,18 +377,18 @@ spv::Decoration TranslateBlockDecoration(const glslang::TType& type, bool useSto void TranslateMemoryDecoration(const glslang::TQualifier& qualifier, std::vector<spv::Decoration>& memory, bool useVulkanMemoryModel) { if (!useVulkanMemoryModel) { - if (qualifier.coherent) + if (qualifier.isCoherent()) memory.push_back(spv::DecorationCoherent); - if (qualifier.volatil) { + if (qualifier.isVolatile()) { memory.push_back(spv::DecorationVolatile); memory.push_back(spv::DecorationCoherent); } } - if (qualifier.restrict) + if (qualifier.isRestrict()) memory.push_back(spv::DecorationRestrict); - if (qualifier.readonly) + if (qualifier.isReadOnly()) memory.push_back(spv::DecorationNonWritable); - if (qualifier.writeonly) + if (qualifier.isWriteOnly()) memory.push_back(spv::DecorationNonReadable); } @@ -409,7 +432,7 @@ spv::Decoration TranslateLayoutDecoration(const glslang::TType& type, glslang::T assert(type.getQualifier().layoutPacking == glslang::ElpNone); } return spv::DecorationMax; -#ifdef NV_EXTENSIONS +#ifndef GLSLANG_WEB case glslang::EvqPayloadNV: case glslang::EvqPayloadInNV: case glslang::EvqHitAttrNV: @@ -433,16 +456,14 @@ spv::Decoration TGlslangToSpvTraverser::TranslateInterpolationDecoration(const g if (qualifier.smooth) // Smooth decoration doesn't exist in SPIR-V 1.0 return spv::DecorationMax; - else if (qualifier.nopersp) + else if (qualifier.isNonPerspective()) return spv::DecorationNoPerspective; else if (qualifier.flat) return spv::DecorationFlat; -#ifdef AMD_EXTENSIONS - else if (qualifier.explicitInterp) { + else if (qualifier.isExplicitInterpolation()) { builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter); return spv::DecorationExplicitInterpAMD; } -#endif else return spv::DecorationMax; } @@ -452,15 +473,18 @@ spv::Decoration TGlslangToSpvTraverser::TranslateInterpolationDecoration(const g // should be applied. spv::Decoration TGlslangToSpvTraverser::TranslateAuxiliaryStorageDecoration(const glslang::TQualifier& qualifier) { - if (qualifier.patch) - return spv::DecorationPatch; - else if (qualifier.centroid) + if (qualifier.centroid) return spv::DecorationCentroid; +#ifndef GLSLANG_WEB + else if (qualifier.patch) + return spv::DecorationPatch; else if (qualifier.sample) { builder.addCapability(spv::CapabilitySampleRateShading); return spv::DecorationSample; - } else - return spv::DecorationMax; + } +#endif + + return spv::DecorationMax; } // If glslang type is invariant, return SPIR-V invariant decoration. @@ -475,29 +499,36 @@ spv::Decoration TranslateInvariantDecoration(const glslang::TQualifier& qualifie // If glslang type is noContraction, return SPIR-V NoContraction decoration. spv::Decoration TranslateNoContractionDecoration(const glslang::TQualifier& qualifier) { - if (qualifier.noContraction) +#ifndef GLSLANG_WEB + if (qualifier.isNoContraction()) return spv::DecorationNoContraction; else +#endif return spv::DecorationMax; } // If glslang type is nonUniform, return SPIR-V NonUniform decoration. spv::Decoration TGlslangToSpvTraverser::TranslateNonUniformDecoration(const glslang::TQualifier& qualifier) { +#ifndef GLSLANG_WEB if (qualifier.isNonUniform()) { - builder.addExtension("SPV_EXT_descriptor_indexing"); + builder.addIncorporatedExtension("SPV_EXT_descriptor_indexing", spv::Spv_1_5); builder.addCapability(spv::CapabilityShaderNonUniformEXT); return spv::DecorationNonUniformEXT; } else +#endif return spv::DecorationMax; } -spv::MemoryAccessMask TGlslangToSpvTraverser::TranslateMemoryAccess(const spv::Builder::AccessChain::CoherentFlags &coherentFlags) +spv::MemoryAccessMask TGlslangToSpvTraverser::TranslateMemoryAccess( + const spv::Builder::AccessChain::CoherentFlags &coherentFlags) { - if (!glslangIntermediate->usingVulkanMemoryModel() || coherentFlags.isImage) { - return spv::MemoryAccessMaskNone; - } spv::MemoryAccessMask mask = spv::MemoryAccessMaskNone; + +#ifndef GLSLANG_WEB + if (!glslangIntermediate->usingVulkanMemoryModel() || coherentFlags.isImage) + return mask; + if (coherentFlags.volatil || coherentFlags.coherent || coherentFlags.devicecoherent || @@ -516,15 +547,20 @@ spv::MemoryAccessMask TGlslangToSpvTraverser::TranslateMemoryAccess(const spv::B if (mask != spv::MemoryAccessMaskNone) { builder.addCapability(spv::CapabilityVulkanMemoryModelKHR); } +#endif + return mask; } -spv::ImageOperandsMask TGlslangToSpvTraverser::TranslateImageOperands(const spv::Builder::AccessChain::CoherentFlags &coherentFlags) +spv::ImageOperandsMask TGlslangToSpvTraverser::TranslateImageOperands( + const spv::Builder::AccessChain::CoherentFlags &coherentFlags) { - if (!glslangIntermediate->usingVulkanMemoryModel()) { - return spv::ImageOperandsMaskNone; - } spv::ImageOperandsMask mask = spv::ImageOperandsMaskNone; + +#ifndef GLSLANG_WEB + if (!glslangIntermediate->usingVulkanMemoryModel()) + return mask; + if (coherentFlags.volatil || coherentFlags.coherent || coherentFlags.devicecoherent || @@ -543,12 +579,15 @@ spv::ImageOperandsMask TGlslangToSpvTraverser::TranslateImageOperands(const spv: if (mask != spv::ImageOperandsMaskNone) { builder.addCapability(spv::CapabilityVulkanMemoryModelKHR); } +#endif + return mask; } spv::Builder::AccessChain::CoherentFlags TGlslangToSpvTraverser::TranslateCoherent(const glslang::TType& type) { - spv::Builder::AccessChain::CoherentFlags flags; + spv::Builder::AccessChain::CoherentFlags flags = {}; +#ifndef GLSLANG_WEB flags.coherent = type.getQualifier().coherent; flags.devicecoherent = type.getQualifier().devicecoherent; flags.queuefamilycoherent = type.getQualifier().queuefamilycoherent; @@ -566,12 +605,16 @@ spv::Builder::AccessChain::CoherentFlags TGlslangToSpvTraverser::TranslateCohere flags.coherent || flags.volatil; flags.isImage = type.getBasicType() == glslang::EbtSampler; +#endif return flags; } -spv::Scope TGlslangToSpvTraverser::TranslateMemoryScope(const spv::Builder::AccessChain::CoherentFlags &coherentFlags) +spv::Scope TGlslangToSpvTraverser::TranslateMemoryScope( + const spv::Builder::AccessChain::CoherentFlags &coherentFlags) { - spv::Scope scope; + spv::Scope scope = spv::ScopeMax; + +#ifndef GLSLANG_WEB if (coherentFlags.volatil || coherentFlags.coherent) { // coherent defaults to Device scope in the old model, QueueFamilyKHR scope in the new model scope = glslangIntermediate->usingVulkanMemoryModel() ? spv::ScopeQueueFamilyKHR : spv::ScopeDevice; @@ -583,12 +626,12 @@ spv::Scope TGlslangToSpvTraverser::TranslateMemoryScope(const spv::Builder::Acce scope = spv::ScopeWorkgroup; } else if (coherentFlags.subgroupcoherent) { scope = spv::ScopeSubgroup; - } else { - scope = spv::ScopeMax; } if (glslangIntermediate->usingVulkanMemoryModel() && scope == spv::ScopeDevice) { builder.addCapability(spv::CapabilityVulkanMemoryModelDeviceScopeKHR); } +#endif + return scope; } @@ -601,6 +644,7 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI { switch (builtIn) { case glslang::EbvPointSize: +#ifndef GLSLANG_WEB // Defer adding the capability until the built-in is actually used. if (! memberDeclaration) { switch (glslangIntermediate->getStage()) { @@ -615,8 +659,28 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI break; } } +#endif return spv::BuiltInPointSize; + case glslang::EbvPosition: return spv::BuiltInPosition; + case glslang::EbvVertexId: return spv::BuiltInVertexId; + case glslang::EbvInstanceId: return spv::BuiltInInstanceId; + case glslang::EbvVertexIndex: return spv::BuiltInVertexIndex; + case glslang::EbvInstanceIndex: return spv::BuiltInInstanceIndex; + + case glslang::EbvFragCoord: return spv::BuiltInFragCoord; + case glslang::EbvPointCoord: return spv::BuiltInPointCoord; + case glslang::EbvFace: return spv::BuiltInFrontFacing; + case glslang::EbvFragDepth: return spv::BuiltInFragDepth; + + case glslang::EbvNumWorkGroups: return spv::BuiltInNumWorkgroups; + case glslang::EbvWorkGroupSize: return spv::BuiltInWorkgroupSize; + case glslang::EbvWorkGroupId: return spv::BuiltInWorkgroupId; + case glslang::EbvLocalInvocationId: return spv::BuiltInLocalInvocationId; + case glslang::EbvLocalInvocationIndex: return spv::BuiltInLocalInvocationIndex; + case glslang::EbvGlobalInvocationId: return spv::BuiltInGlobalInvocationId; + +#ifndef GLSLANG_WEB // These *Distance capabilities logically belong here, but if the member is declared and // then never used, consumers of SPIR-V prefer the capability not be declared. // They are now generated when used, rather than here when declared. @@ -639,7 +703,7 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI glslangIntermediate->getStage() == EShLangTessControl || glslangIntermediate->getStage() == EShLangTessEvaluation) { - builder.addExtension(spv::E_SPV_EXT_shader_viewport_index_layer); + builder.addIncorporatedExtension(spv::E_SPV_EXT_shader_viewport_index_layer, spv::Spv_1_5); builder.addCapability(spv::CapabilityShaderViewportIndexLayerEXT); } return spv::BuiltInViewportIndex; @@ -656,39 +720,31 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI return spv::BuiltInSampleMask; case glslang::EbvLayer: -#ifdef NV_EXTENSIONS if (glslangIntermediate->getStage() == EShLangMeshNV) { return spv::BuiltInLayer; } -#endif builder.addCapability(spv::CapabilityGeometry); if (glslangIntermediate->getStage() == EShLangVertex || glslangIntermediate->getStage() == EShLangTessControl || glslangIntermediate->getStage() == EShLangTessEvaluation) { - builder.addExtension(spv::E_SPV_EXT_shader_viewport_index_layer); + builder.addIncorporatedExtension(spv::E_SPV_EXT_shader_viewport_index_layer, spv::Spv_1_5); builder.addCapability(spv::CapabilityShaderViewportIndexLayerEXT); } return spv::BuiltInLayer; - case glslang::EbvPosition: return spv::BuiltInPosition; - case glslang::EbvVertexId: return spv::BuiltInVertexId; - case glslang::EbvInstanceId: return spv::BuiltInInstanceId; - case glslang::EbvVertexIndex: return spv::BuiltInVertexIndex; - case glslang::EbvInstanceIndex: return spv::BuiltInInstanceIndex; - case glslang::EbvBaseVertex: - addPre13Extension(spv::E_SPV_KHR_shader_draw_parameters); + builder.addIncorporatedExtension(spv::E_SPV_KHR_shader_draw_parameters, spv::Spv_1_3); builder.addCapability(spv::CapabilityDrawParameters); return spv::BuiltInBaseVertex; case glslang::EbvBaseInstance: - addPre13Extension(spv::E_SPV_KHR_shader_draw_parameters); + builder.addIncorporatedExtension(spv::E_SPV_KHR_shader_draw_parameters, spv::Spv_1_3); builder.addCapability(spv::CapabilityDrawParameters); return spv::BuiltInBaseInstance; case glslang::EbvDrawId: - addPre13Extension(spv::E_SPV_KHR_shader_draw_parameters); + builder.addIncorporatedExtension(spv::E_SPV_KHR_shader_draw_parameters, spv::Spv_1_3); builder.addCapability(spv::CapabilityDrawParameters); return spv::BuiltInDrawIndex; @@ -707,17 +763,7 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI case glslang::EbvTessLevelOuter: return spv::BuiltInTessLevelOuter; case glslang::EbvTessCoord: return spv::BuiltInTessCoord; case glslang::EbvPatchVertices: return spv::BuiltInPatchVertices; - case glslang::EbvFragCoord: return spv::BuiltInFragCoord; - case glslang::EbvPointCoord: return spv::BuiltInPointCoord; - case glslang::EbvFace: return spv::BuiltInFrontFacing; - case glslang::EbvFragDepth: return spv::BuiltInFragDepth; case glslang::EbvHelperInvocation: return spv::BuiltInHelperInvocation; - case glslang::EbvNumWorkGroups: return spv::BuiltInNumWorkgroups; - case glslang::EbvWorkGroupSize: return spv::BuiltInWorkgroupSize; - case glslang::EbvWorkGroupId: return spv::BuiltInWorkgroupId; - case glslang::EbvLocalInvocationId: return spv::BuiltInLocalInvocationId; - case glslang::EbvLocalInvocationIndex: return spv::BuiltInLocalInvocationIndex; - case glslang::EbvGlobalInvocationId: return spv::BuiltInGlobalInvocationId; case glslang::EbvSubGroupSize: builder.addExtension(spv::E_SPV_KHR_shader_ballot); @@ -732,27 +778,27 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI case glslang::EbvSubGroupEqMask: builder.addExtension(spv::E_SPV_KHR_shader_ballot); builder.addCapability(spv::CapabilitySubgroupBallotKHR); - return spv::BuiltInSubgroupEqMaskKHR; + return spv::BuiltInSubgroupEqMask; case glslang::EbvSubGroupGeMask: builder.addExtension(spv::E_SPV_KHR_shader_ballot); builder.addCapability(spv::CapabilitySubgroupBallotKHR); - return spv::BuiltInSubgroupGeMaskKHR; + return spv::BuiltInSubgroupGeMask; case glslang::EbvSubGroupGtMask: builder.addExtension(spv::E_SPV_KHR_shader_ballot); builder.addCapability(spv::CapabilitySubgroupBallotKHR); - return spv::BuiltInSubgroupGtMaskKHR; + return spv::BuiltInSubgroupGtMask; case glslang::EbvSubGroupLeMask: builder.addExtension(spv::E_SPV_KHR_shader_ballot); builder.addCapability(spv::CapabilitySubgroupBallotKHR); - return spv::BuiltInSubgroupLeMaskKHR; + return spv::BuiltInSubgroupLeMask; case glslang::EbvSubGroupLtMask: builder.addExtension(spv::E_SPV_KHR_shader_ballot); builder.addCapability(spv::CapabilitySubgroupBallotKHR); - return spv::BuiltInSubgroupLtMaskKHR; + return spv::BuiltInSubgroupLtMask; case glslang::EbvNumSubgroups: builder.addCapability(spv::CapabilityGroupNonUniform); @@ -794,7 +840,7 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI builder.addCapability(spv::CapabilityGroupNonUniform); builder.addCapability(spv::CapabilityGroupNonUniformBallot); return spv::BuiltInSubgroupLtMask; -#ifdef AMD_EXTENSIONS + case glslang::EbvBaryCoordNoPersp: builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter); return spv::BuiltInBaryCoordNoPerspAMD; @@ -822,15 +868,14 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI case glslang::EbvBaryCoordPullModel: builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter); return spv::BuiltInBaryCoordPullModelAMD; -#endif case glslang::EbvDeviceIndex: - addPre13Extension(spv::E_SPV_KHR_device_group); + builder.addIncorporatedExtension(spv::E_SPV_KHR_device_group, spv::Spv_1_3); builder.addCapability(spv::CapabilityDeviceGroup); return spv::BuiltInDeviceIndex; case glslang::EbvViewIndex: - addPre13Extension(spv::E_SPV_KHR_multiview); + builder.addIncorporatedExtension(spv::E_SPV_KHR_multiview, spv::Spv_1_3); builder.addCapability(spv::CapabilityMultiView); return spv::BuiltInViewIndex; @@ -844,7 +889,6 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI builder.addCapability(spv::CapabilityFragmentDensityEXT); return spv::BuiltInFragInvocationCountEXT; -#ifdef NV_EXTENSIONS case glslang::EbvViewportMaskNV: if (!memberDeclaration) { builder.addExtension(spv::E_SPV_NV_viewport_array2); @@ -888,7 +932,7 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI builder.addCapability(spv::CapabilityShadingRateNV); return spv::BuiltInInvocationsPerPixelNV; - // raytracing + // ray tracing case glslang::EbvLaunchIdNV: return spv::BuiltInLaunchIdNV; case glslang::EbvLaunchSizeNV: @@ -917,6 +961,8 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI return spv::BuiltInWorldToObjectNV; case glslang::EbvIncomingRayFlagsNV: return spv::BuiltInIncomingRayFlagsNV; + + // barycentrics case glslang::EbvBaryCoordNV: builder.addExtension(spv::E_SPV_NV_fragment_shader_barycentric); builder.addCapability(spv::CapabilityFragmentBarycentricNV); @@ -925,23 +971,44 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI builder.addExtension(spv::E_SPV_NV_fragment_shader_barycentric); builder.addCapability(spv::CapabilityFragmentBarycentricNV); return spv::BuiltInBaryCoordNoPerspNV; - case glslang::EbvTaskCountNV: + + // mesh shaders + case glslang::EbvTaskCountNV: return spv::BuiltInTaskCountNV; - case glslang::EbvPrimitiveCountNV: + case glslang::EbvPrimitiveCountNV: return spv::BuiltInPrimitiveCountNV; - case glslang::EbvPrimitiveIndicesNV: + case glslang::EbvPrimitiveIndicesNV: return spv::BuiltInPrimitiveIndicesNV; - case glslang::EbvClipDistancePerViewNV: + case glslang::EbvClipDistancePerViewNV: return spv::BuiltInClipDistancePerViewNV; - case glslang::EbvCullDistancePerViewNV: + case glslang::EbvCullDistancePerViewNV: return spv::BuiltInCullDistancePerViewNV; - case glslang::EbvLayerPerViewNV: + case glslang::EbvLayerPerViewNV: return spv::BuiltInLayerPerViewNV; - case glslang::EbvMeshViewCountNV: + case glslang::EbvMeshViewCountNV: return spv::BuiltInMeshViewCountNV; - case glslang::EbvMeshViewIndicesNV: + case glslang::EbvMeshViewIndicesNV: return spv::BuiltInMeshViewIndicesNV; -#endif + + // sm builtins + case glslang::EbvWarpsPerSM: + builder.addExtension(spv::E_SPV_NV_shader_sm_builtins); + builder.addCapability(spv::CapabilityShaderSMBuiltinsNV); + return spv::BuiltInWarpsPerSMNV; + case glslang::EbvSMCount: + builder.addExtension(spv::E_SPV_NV_shader_sm_builtins); + builder.addCapability(spv::CapabilityShaderSMBuiltinsNV); + return spv::BuiltInSMCountNV; + case glslang::EbvWarpID: + builder.addExtension(spv::E_SPV_NV_shader_sm_builtins); + builder.addCapability(spv::CapabilityShaderSMBuiltinsNV); + return spv::BuiltInWarpIDNV; + case glslang::EbvSMID: + builder.addExtension(spv::E_SPV_NV_shader_sm_builtins); + builder.addCapability(spv::CapabilityShaderSMBuiltinsNV); + return spv::BuiltInSMIDNV; +#endif + default: return spv::BuiltInMax; } @@ -952,8 +1019,12 @@ spv::ImageFormat TGlslangToSpvTraverser::TranslateImageFormat(const glslang::TTy { assert(type.getBasicType() == glslang::EbtSampler); +#ifdef GLSLANG_WEB + return spv::ImageFormatUnknown; +#endif + // Check for capabilities - switch (type.getQualifier().layoutFormat) { + switch (type.getQualifier().getFormat()) { case glslang::ElfRg32f: case glslang::ElfRg16f: case glslang::ElfR11fG11fB10f: @@ -990,7 +1061,7 @@ spv::ImageFormat TGlslangToSpvTraverser::TranslateImageFormat(const glslang::TTy } // do the translation - switch (type.getQualifier().layoutFormat) { + switch (type.getQualifier().getFormat()) { case glslang::ElfNone: return spv::ImageFormatUnknown; case glslang::ElfRgba32f: return spv::ImageFormatRgba32f; case glslang::ElfRgba16f: return spv::ImageFormatRgba16f; @@ -1104,27 +1175,25 @@ spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::T return spv::StorageClassOutput; if (glslangIntermediate->getSource() != glslang::EShSourceHlsl || - type.getQualifier().storage == glslang::EvqUniform) { - if (type.getBasicType() == glslang::EbtAtomicUint) + type.getQualifier().storage == glslang::EvqUniform) { + if (type.isAtomic()) return spv::StorageClassAtomicCounter; if (type.containsOpaque()) return spv::StorageClassUniformConstant; } -#ifdef NV_EXTENSIONS if (type.getQualifier().isUniformOrBuffer() && - type.getQualifier().layoutShaderRecordNV) { + type.getQualifier().isShaderRecordNV()) { return spv::StorageClassShaderRecordBufferNV; } -#endif if (glslangIntermediate->usingStorageBuffer() && type.getQualifier().storage == glslang::EvqBuffer) { - addPre13Extension(spv::E_SPV_KHR_storage_buffer_storage_class); + builder.addIncorporatedExtension(spv::E_SPV_KHR_storage_buffer_storage_class, spv::Spv_1_3); return spv::StorageClassStorageBuffer; } if (type.getQualifier().isUniformOrBuffer()) { - if (type.getQualifier().layoutPushConstant) + if (type.getQualifier().isPushConstant()) return spv::StorageClassPushConstant; if (type.getBasicType() == glslang::EbtBlock) return spv::StorageClassUniform; @@ -1132,11 +1201,11 @@ spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::T } switch (type.getQualifier().storage) { - case glslang::EvqShared: return spv::StorageClassWorkgroup; case glslang::EvqGlobal: return spv::StorageClassPrivate; case glslang::EvqConstReadOnly: return spv::StorageClassFunction; case glslang::EvqTemporary: return spv::StorageClassFunction; -#ifdef NV_EXTENSIONS + case glslang::EvqShared: return spv::StorageClassWorkgroup; +#ifndef GLSLANG_WEB case glslang::EvqPayloadNV: return spv::StorageClassRayPayloadNV; case glslang::EvqPayloadInNV: return spv::StorageClassIncomingRayPayloadNV; case glslang::EvqHitAttrNV: return spv::StorageClassHitAttributeNV; @@ -1155,15 +1224,16 @@ spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::T void TGlslangToSpvTraverser::addIndirectionIndexCapabilities(const glslang::TType& baseType, const glslang::TType& indexType) { +#ifndef GLSLANG_WEB if (indexType.getQualifier().isNonUniform()) { // deal with an asserted non-uniform index // SPV_EXT_descriptor_indexing already added in TranslateNonUniformDecoration if (baseType.getBasicType() == glslang::EbtSampler) { if (baseType.getQualifier().hasAttachment()) builder.addCapability(spv::CapabilityInputAttachmentArrayNonUniformIndexingEXT); - else if (baseType.isImage() && baseType.getSampler().dim == glslang::EsdBuffer) + else if (baseType.isImage() && baseType.getSampler().isBuffer()) builder.addCapability(spv::CapabilityStorageTexelBufferArrayNonUniformIndexingEXT); - else if (baseType.isTexture() && baseType.getSampler().dim == glslang::EsdBuffer) + else if (baseType.isTexture() && baseType.getSampler().isBuffer()) builder.addCapability(spv::CapabilityUniformTexelBufferArrayNonUniformIndexingEXT); else if (baseType.isImage()) builder.addCapability(spv::CapabilityStorageImageArrayNonUniformIndexingEXT); @@ -1179,17 +1249,18 @@ void TGlslangToSpvTraverser::addIndirectionIndexCapabilities(const glslang::TTyp // assume a dynamically uniform index if (baseType.getBasicType() == glslang::EbtSampler) { if (baseType.getQualifier().hasAttachment()) { - builder.addExtension("SPV_EXT_descriptor_indexing"); + builder.addIncorporatedExtension("SPV_EXT_descriptor_indexing", spv::Spv_1_5); builder.addCapability(spv::CapabilityInputAttachmentArrayDynamicIndexingEXT); - } else if (baseType.isImage() && baseType.getSampler().dim == glslang::EsdBuffer) { - builder.addExtension("SPV_EXT_descriptor_indexing"); + } else if (baseType.isImage() && baseType.getSampler().isBuffer()) { + builder.addIncorporatedExtension("SPV_EXT_descriptor_indexing", spv::Spv_1_5); builder.addCapability(spv::CapabilityStorageTexelBufferArrayDynamicIndexingEXT); - } else if (baseType.isTexture() && baseType.getSampler().dim == glslang::EsdBuffer) { - builder.addExtension("SPV_EXT_descriptor_indexing"); + } else if (baseType.isTexture() && baseType.getSampler().isBuffer()) { + builder.addIncorporatedExtension("SPV_EXT_descriptor_indexing", spv::Spv_1_5); builder.addCapability(spv::CapabilityUniformTexelBufferArrayDynamicIndexingEXT); } } } +#endif } // Return whether or not the given type is something that should be tied to a @@ -1199,10 +1270,8 @@ bool IsDescriptorResource(const glslang::TType& type) // uniform and buffer blocks are included, unless it is a push_constant if (type.getBasicType() == glslang::EbtBlock) return type.getQualifier().isUniformOrBuffer() && -#ifdef NV_EXTENSIONS - ! type.getQualifier().layoutShaderRecordNV && -#endif - ! type.getQualifier().layoutPushConstant; + ! type.getQualifier().isShaderRecordNV() && + ! type.getQualifier().isPushConstant(); // non block... // basically samplerXXX/subpass/sampler/texture are all included @@ -1222,16 +1291,21 @@ void InheritQualifiers(glslang::TQualifier& child, const glslang::TQualifier& pa if (parent.invariant) child.invariant = true; - if (parent.nopersp) - child.nopersp = true; -#ifdef AMD_EXTENSIONS - if (parent.explicitInterp) - child.explicitInterp = true; -#endif if (parent.flat) child.flat = true; if (parent.centroid) child.centroid = true; +#ifndef GLSLANG_WEB + if (parent.nopersp) + child.nopersp = true; + if (parent.explicitInterp) + child.explicitInterp = true; + if (parent.perPrimitiveNV) + child.perPrimitiveNV = true; + if (parent.perViewNV) + child.perViewNV = true; + if (parent.perTaskNV) + child.perTaskNV = true; if (parent.patch) child.patch = true; if (parent.sample) @@ -1256,13 +1330,6 @@ void InheritQualifiers(glslang::TQualifier& child, const glslang::TQualifier& pa child.readonly = true; if (parent.writeonly) child.writeonly = true; -#ifdef NV_EXTENSIONS - if (parent.perPrimitiveNV) - child.perPrimitiveNV = true; - if (parent.perViewNV) - child.perViewNV = true; - if (parent.perTaskNV) - child.perTaskNV = true; #endif } @@ -1291,7 +1358,8 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const gl sequenceDepth(0), logger(buildLogger), builder(spvVersion, (glslang::GetKhronosToolId() << 16) | glslang::GetSpirvGeneratorVersion(), logger), inEntryPoint(false), entryPointTerminated(false), linkageOnly(false), - glslangIntermediate(glslangIntermediate) + glslangIntermediate(glslangIntermediate), + nanMinMaxClamp(glslangIntermediate->getNanMinMaxClamp()) { spv::ExecutionModel executionModel = TranslateExecutionModel(glslangIntermediate->getStage()); @@ -1332,13 +1400,13 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const gl if (glslangIntermediate->usingPhysicalStorageBuffer()) { addressingModel = spv::AddressingModelPhysicalStorageBuffer64EXT; - builder.addExtension(spv::E_SPV_EXT_physical_storage_buffer); + builder.addIncorporatedExtension(spv::E_SPV_EXT_physical_storage_buffer, spv::Spv_1_5); builder.addCapability(spv::CapabilityPhysicalStorageBufferAddressesEXT); }; if (glslangIntermediate->usingVulkanMemoryModel()) { memoryModel = spv::MemoryModelVulkanKHR; builder.addCapability(spv::CapabilityVulkanMemoryModelKHR); - builder.addExtension(spv::E_SPV_KHR_vulkan_memory_model); + builder.addIncorporatedExtension(spv::E_SPV_KHR_vulkan_memory_model, spv::Spv_1_5); } builder.setMemoryModel(addressingModel, memoryModel); @@ -1367,6 +1435,84 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const gl builder.addCapability(spv::CapabilityShader); break; + case EShLangFragment: + builder.addCapability(spv::CapabilityShader); + if (glslangIntermediate->getPixelCenterInteger()) + builder.addExecutionMode(shaderEntry, spv::ExecutionModePixelCenterInteger); + + if (glslangIntermediate->getOriginUpperLeft()) + builder.addExecutionMode(shaderEntry, spv::ExecutionModeOriginUpperLeft); + else + builder.addExecutionMode(shaderEntry, spv::ExecutionModeOriginLowerLeft); + + if (glslangIntermediate->getEarlyFragmentTests()) + builder.addExecutionMode(shaderEntry, spv::ExecutionModeEarlyFragmentTests); + + if (glslangIntermediate->getPostDepthCoverage()) { + builder.addCapability(spv::CapabilitySampleMaskPostDepthCoverage); + builder.addExecutionMode(shaderEntry, spv::ExecutionModePostDepthCoverage); + builder.addExtension(spv::E_SPV_KHR_post_depth_coverage); + } + + if (glslangIntermediate->getDepth() != glslang::EldUnchanged && glslangIntermediate->isDepthReplacing()) + builder.addExecutionMode(shaderEntry, spv::ExecutionModeDepthReplacing); + +#ifndef GLSLANG_WEB + switch(glslangIntermediate->getDepth()) { + case glslang::EldGreater: mode = spv::ExecutionModeDepthGreater; break; + case glslang::EldLess: mode = spv::ExecutionModeDepthLess; break; + default: mode = spv::ExecutionModeMax; break; + } + if (mode != spv::ExecutionModeMax) + builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); + switch (glslangIntermediate->getInterlockOrdering()) { + case glslang::EioPixelInterlockOrdered: mode = spv::ExecutionModePixelInterlockOrderedEXT; + break; + case glslang::EioPixelInterlockUnordered: mode = spv::ExecutionModePixelInterlockUnorderedEXT; + break; + case glslang::EioSampleInterlockOrdered: mode = spv::ExecutionModeSampleInterlockOrderedEXT; + break; + case glslang::EioSampleInterlockUnordered: mode = spv::ExecutionModeSampleInterlockUnorderedEXT; + break; + case glslang::EioShadingRateInterlockOrdered: mode = spv::ExecutionModeShadingRateInterlockOrderedEXT; + break; + case glslang::EioShadingRateInterlockUnordered: mode = spv::ExecutionModeShadingRateInterlockUnorderedEXT; + break; + default: mode = spv::ExecutionModeMax; + break; + } + if (mode != spv::ExecutionModeMax) { + builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); + if (mode == spv::ExecutionModeShadingRateInterlockOrderedEXT || + mode == spv::ExecutionModeShadingRateInterlockUnorderedEXT) { + builder.addCapability(spv::CapabilityFragmentShaderShadingRateInterlockEXT); + } else if (mode == spv::ExecutionModePixelInterlockOrderedEXT || + mode == spv::ExecutionModePixelInterlockUnorderedEXT) { + builder.addCapability(spv::CapabilityFragmentShaderPixelInterlockEXT); + } else { + builder.addCapability(spv::CapabilityFragmentShaderSampleInterlockEXT); + } + builder.addExtension(spv::E_SPV_EXT_fragment_shader_interlock); + } +#endif + break; + + case EShLangCompute: + builder.addCapability(spv::CapabilityShader); + builder.addExecutionMode(shaderEntry, spv::ExecutionModeLocalSize, glslangIntermediate->getLocalSize(0), + glslangIntermediate->getLocalSize(1), + glslangIntermediate->getLocalSize(2)); + if (glslangIntermediate->getLayoutDerivativeModeNone() == glslang::LayoutDerivativeGroupQuads) { + builder.addCapability(spv::CapabilityComputeDerivativeGroupQuadsNV); + builder.addExecutionMode(shaderEntry, spv::ExecutionModeDerivativeGroupQuadsNV); + builder.addExtension(spv::E_SPV_NV_compute_shader_derivatives); + } else if (glslangIntermediate->getLayoutDerivativeModeNone() == glslang::LayoutDerivativeGroupLinear) { + builder.addCapability(spv::CapabilityComputeDerivativeGroupLinearNV); + builder.addExecutionMode(shaderEntry, spv::ExecutionModeDerivativeGroupLinearNV); + builder.addExtension(spv::E_SPV_NV_compute_shader_derivatives); + } + break; +#ifndef GLSLANG_WEB case EShLangTessEvaluation: case EShLangTessControl: builder.addCapability(spv::CapabilityTessellation); @@ -1436,56 +1582,6 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const gl builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, glslangIntermediate->getVertices()); break; - case EShLangFragment: - builder.addCapability(spv::CapabilityShader); - if (glslangIntermediate->getPixelCenterInteger()) - builder.addExecutionMode(shaderEntry, spv::ExecutionModePixelCenterInteger); - - if (glslangIntermediate->getOriginUpperLeft()) - builder.addExecutionMode(shaderEntry, spv::ExecutionModeOriginUpperLeft); - else - builder.addExecutionMode(shaderEntry, spv::ExecutionModeOriginLowerLeft); - - if (glslangIntermediate->getEarlyFragmentTests()) - builder.addExecutionMode(shaderEntry, spv::ExecutionModeEarlyFragmentTests); - - if (glslangIntermediate->getPostDepthCoverage()) { - builder.addCapability(spv::CapabilitySampleMaskPostDepthCoverage); - builder.addExecutionMode(shaderEntry, spv::ExecutionModePostDepthCoverage); - builder.addExtension(spv::E_SPV_KHR_post_depth_coverage); - } - - switch(glslangIntermediate->getDepth()) { - case glslang::EldGreater: mode = spv::ExecutionModeDepthGreater; break; - case glslang::EldLess: mode = spv::ExecutionModeDepthLess; break; - default: mode = spv::ExecutionModeMax; break; - } - if (mode != spv::ExecutionModeMax) - builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); - - if (glslangIntermediate->getDepth() != glslang::EldUnchanged && glslangIntermediate->isDepthReplacing()) - builder.addExecutionMode(shaderEntry, spv::ExecutionModeDepthReplacing); - break; - - case EShLangCompute: - builder.addCapability(spv::CapabilityShader); - builder.addExecutionMode(shaderEntry, spv::ExecutionModeLocalSize, glslangIntermediate->getLocalSize(0), - glslangIntermediate->getLocalSize(1), - glslangIntermediate->getLocalSize(2)); -#ifdef NV_EXTENSIONS - if (glslangIntermediate->getLayoutDerivativeModeNone() == glslang::LayoutDerivativeGroupQuads) { - builder.addCapability(spv::CapabilityComputeDerivativeGroupQuadsNV); - builder.addExecutionMode(shaderEntry, spv::ExecutionModeDerivativeGroupQuadsNV); - builder.addExtension(spv::E_SPV_NV_compute_shader_derivatives); - } else if (glslangIntermediate->getLayoutDerivativeModeNone() == glslang::LayoutDerivativeGroupLinear) { - builder.addCapability(spv::CapabilityComputeDerivativeGroupLinearNV); - builder.addExecutionMode(shaderEntry, spv::ExecutionModeDerivativeGroupLinearNV); - builder.addExtension(spv::E_SPV_NV_compute_shader_derivatives); - } -#endif - break; - -#ifdef NV_EXTENSIONS case EShLangRayGenNV: case EShLangIntersectNV: case EShLangAnyHitNV: @@ -1536,8 +1632,10 @@ void TGlslangToSpvTraverser::finishSpv() for (auto it = iOSet.cbegin(); it != iOSet.cend(); ++it) entryPoint->addIdOperand(*it); - // Add capabilities, extensions, remove unneeded decorations, etc., + // Add capabilities, extensions, remove unneeded decorations, etc., // based on the resulting SPIR-V. + // Note: WebGPU code generation must have the opportunity to aggressively + // prune unreachable merge blocks and continue targets. builder.postProcess(); } @@ -1565,6 +1663,9 @@ void TGlslangToSpvTraverser::dumpSpv(std::vector<unsigned int>& out) void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol) { SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); + if (symbol->getType().isStruct()) + glslangTypeToIdMap[symbol->getType().getStruct()] = symbol->getId(); + if (symbol->getType().getQualifier().isSpecConstant()) spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); @@ -1572,8 +1673,8 @@ void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol) // Formal function parameters were mapped during makeFunctions(). spv::Id id = getSymbolId(symbol); - // Include all "static use" and "linkage only" interface variables on the OpEntryPoint instruction if (builder.isPointer(id)) { + // Include all "static use" and "linkage only" interface variables on the OpEntryPoint instruction // Consider adding to the OpEntryPoint interface list. // Only looking at structures if they have at least one member. if (!symbol->getType().isStruct() || symbol->getType().getStruct()->size() > 0) { @@ -1585,6 +1686,14 @@ void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol) iOSet.insert(id); } } + + // If the SPIR-V type is required to be different than the AST type, + // translate now from the SPIR-V type to the AST type, for the consuming + // operation. + // Note this turns it from an l-value to an r-value. + // Currently, all symbols needing this are inputs; avoid the map lookup when non-input. + if (symbol->getType().getQualifier().storage == glslang::EvqVaryingIn) + id = translateForcedType(id); } // Only process non-linkage-only nodes for generating actual static uses @@ -1602,13 +1711,16 @@ void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol) // See comments in handleUserFunctionCall(). // B) Specialization constants (normal constants don't even come in as a variable), // These are also pure R-values. + // C) R-Values from type translation, see above call to translateForcedType() glslang::TQualifier qualifier = symbol->getQualifier(); - if (qualifier.isSpecConstant() || rValueParameters.find(symbol->getId()) != rValueParameters.end()) + if (qualifier.isSpecConstant() || rValueParameters.find(symbol->getId()) != rValueParameters.end() || + !builder.isPointerType(builder.getTypeId(id))) builder.setAccessChainRValue(id); else builder.setAccessChainLValue(id); } +#ifdef ENABLE_HLSL // Process linkage-only nodes for any special additional interface work. if (linkageOnly) { if (glslangIntermediate->getHlslFunctionality1()) { @@ -1640,11 +1752,18 @@ void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol) } } } +#endif } bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::TIntermBinary* node) { builder.setLine(node->getLoc().line, node->getLoc().getFilename()); + if (node->getLeft()->getAsSymbolNode() != nullptr && node->getLeft()->getType().isStruct()) { + glslangTypeToIdMap[node->getLeft()->getType().getStruct()] = node->getLeft()->getAsSymbolNode()->getId(); + } + if (node->getRight()->getAsSymbolNode() != nullptr && node->getRight()->getType().isStruct()) { + glslangTypeToIdMap[node->getRight()->getType().getStruct()] = node->getRight()->getAsSymbolNode()->getId(); + } SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); if (node->getType().getQualifier().isSpecConstant()) @@ -1734,7 +1853,7 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T // Load through a block reference is performed with a dot operator that // is mapped to EOpIndexDirectStruct. When we get to the actual reference, // do a load and reset the access chain. - if (node->getLeft()->getBasicType() == glslang::EbtReference && + if (node->getLeft()->isReference() && !node->getLeft()->getType().isArray() && node->getOp() == glslang::EOpIndexDirectStruct) { @@ -1749,9 +1868,12 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T { // 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]; + int glslangId = glslangTypeToIdMap[node->getLeft()->getType().getStruct()]; + if (memberRemapper.find(glslangId) != memberRemapper.end()) { + std::vector<int>& remapper = memberRemapper[glslangId]; + assert(remapper.size() > 0); + spvIndex = remapper[glslangIndex]; + } } // normal case for indexing array or structure or block @@ -1860,6 +1982,71 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T } } +// Figure out what, if any, type changes are needed when accessing a specific built-in. +// Returns <the type SPIR-V requires for declarion, the type to translate to on use>. +// Also see comment for 'forceType', regarding tracking SPIR-V-required types. +std::pair<spv::Id, spv::Id> TGlslangToSpvTraverser::getForcedType(spv::BuiltIn builtIn, + const glslang::TType& glslangType) +{ + switch(builtIn) + { + case spv::BuiltInSubgroupEqMask: + case spv::BuiltInSubgroupGeMask: + case spv::BuiltInSubgroupGtMask: + case spv::BuiltInSubgroupLeMask: + case spv::BuiltInSubgroupLtMask: { + // these require changing a 64-bit scaler -> a vector of 32-bit components + if (glslangType.isVector()) + break; + std::pair<spv::Id, spv::Id> ret(builder.makeVectorType(builder.makeUintType(32), 4), + builder.makeUintType(64)); + return ret; + } + default: + break; + } + + std::pair<spv::Id, spv::Id> ret(spv::NoType, spv::NoType); + return ret; +} + +// For an object previously identified (see getForcedType() and forceType) +// as needing type translations, do the translation needed for a load, turning +// an L-value into in R-value. +spv::Id TGlslangToSpvTraverser::translateForcedType(spv::Id object) +{ + const auto forceIt = forceType.find(object); + if (forceIt == forceType.end()) + return object; + + spv::Id desiredTypeId = forceIt->second; + spv::Id objectTypeId = builder.getTypeId(object); + assert(builder.isPointerType(objectTypeId)); + objectTypeId = builder.getContainedTypeId(objectTypeId); + if (builder.isVectorType(objectTypeId) && + builder.getScalarTypeWidth(builder.getContainedTypeId(objectTypeId)) == 32) { + if (builder.getScalarTypeWidth(desiredTypeId) == 64) { + // handle 32-bit v.xy* -> 64-bit + builder.clearAccessChain(); + builder.setAccessChainLValue(object); + object = builder.accessChainLoad(spv::NoPrecision, spv::DecorationMax, objectTypeId); + std::vector<spv::Id> components; + components.push_back(builder.createCompositeExtract(object, builder.getContainedTypeId(objectTypeId), 0)); + components.push_back(builder.createCompositeExtract(object, builder.getContainedTypeId(objectTypeId), 1)); + + spv::Id vecType = builder.makeVectorType(builder.getContainedTypeId(objectTypeId), 2); + return builder.createUnaryOp(spv::OpBitcast, desiredTypeId, + builder.createCompositeConstruct(vecType, components)); + } else { + logger->missingFunctionality("forcing 32-bit vector type to non 64-bit scalar"); + } + } else { + logger->missingFunctionality("forcing non 32-bit vector type"); + } + + return object; +} + bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TIntermUnary* node) { builder.setLine(node->getLoc().line, node->getLoc().getFilename()); @@ -1935,20 +2122,31 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI invertedType = getInvertedSwizzleType(*node->getOperand()); builder.clearAccessChain(); + TIntermNode *operandNode; if (invertedType != spv::NoType) - node->getOperand()->getAsBinaryNode()->getLeft()->traverse(this); + operandNode = node->getOperand()->getAsBinaryNode()->getLeft(); else - node->getOperand()->traverse(this); + operandNode = node->getOperand(); + + operandNode->traverse(this); spv::Id operand = spv::NoResult; + spv::Builder::AccessChain::CoherentFlags lvalueCoherentFlags; + +#ifndef GLSLANG_WEB if (node->getOp() == glslang::EOpAtomicCounterIncrement || node->getOp() == glslang::EOpAtomicCounterDecrement || node->getOp() == glslang::EOpAtomicCounter || - node->getOp() == glslang::EOpInterpolateAtCentroid) + node->getOp() == glslang::EOpInterpolateAtCentroid) { operand = builder.accessChainGetLValue(); // Special case l-value operands - else + lvalueCoherentFlags = builder.getAccessChain().coherentFlags; + lvalueCoherentFlags |= TranslateCoherent(operandNode->getAsTyped()->getType()); + } else +#endif + { operand = accessChainLoad(node->getOperand()->getType()); + } OpDecorations decorations = { TranslatePrecisionDecoration(node->getOperationPrecision()), TranslateNoContractionDecoration(node->getType().getQualifier()), @@ -1960,12 +2158,12 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI // if not, then possibly an operation if (! result) - result = createUnaryOperation(node->getOp(), decorations, resultType(), operand, node->getOperand()->getBasicType()); + result = createUnaryOperation(node->getOp(), decorations, resultType(), operand, node->getOperand()->getBasicType(), lvalueCoherentFlags); if (result) { if (invertedType) { result = createInvertedSwizzle(decorations.precision, *node->getOperand(), result); - builder.addDecoration(result, decorations.nonUniform); + decorations.addNonUniform(builder, result); } builder.clearAccessChain(); @@ -1985,6 +2183,7 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI spv::Id one = 0; if (node->getBasicType() == glslang::EbtFloat) one = builder.makeFloatConstant(1.0F); +#ifndef GLSLANG_WEB else if (node->getBasicType() == glslang::EbtDouble) one = builder.makeDoubleConstant(1.0); else if (node->getBasicType() == glslang::EbtFloat16) @@ -1995,6 +2194,7 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI one = builder.makeInt16Constant(1); else if (node->getBasicType() == glslang::EbtInt64 || node->getBasicType() == glslang::EbtUint64) one = builder.makeInt64Constant(1); +#endif else one = builder.makeIntConstant(1); glslang::TOperator op; @@ -2022,12 +2222,14 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI return false; +#ifndef GLSLANG_WEB case glslang::EOpEmitStreamVertex: builder.createNoResultOp(spv::OpEmitStreamVertex, operand); return false; case glslang::EOpEndStreamPrimitive: builder.createNoResultOp(spv::OpEndStreamPrimitive, operand); return false; +#endif default: logger->missingFunctionality("unknown glslang unary"); @@ -2035,6 +2237,39 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI } } +// Construct a composite object, recursively copying members if their types don't match +spv::Id TGlslangToSpvTraverser::createCompositeConstruct(spv::Id resultTypeId, std::vector<spv::Id> constituents) +{ + for (int c = 0; c < (int)constituents.size(); ++c) { + spv::Id& constituent = constituents[c]; + spv::Id lType = builder.getContainedTypeId(resultTypeId, c); + spv::Id rType = builder.getTypeId(constituent); + if (lType != rType) { + if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_4) { + constituent = builder.createUnaryOp(spv::OpCopyLogical, lType, constituent); + } else if (builder.isStructType(rType)) { + std::vector<spv::Id> rTypeConstituents; + int numrTypeConstituents = builder.getNumTypeConstituents(rType); + for (int i = 0; i < numrTypeConstituents; ++i) { + rTypeConstituents.push_back(builder.createCompositeExtract(constituent, builder.getContainedTypeId(rType, i), i)); + } + constituents[c] = createCompositeConstruct(lType, rTypeConstituents); + } else { + assert(builder.isArrayType(rType)); + std::vector<spv::Id> rTypeConstituents; + int numrTypeConstituents = builder.getNumTypeConstituents(rType); + + spv::Id elementRType = builder.getContainedTypeId(rType); + for (int i = 0; i < numrTypeConstituents; ++i) { + rTypeConstituents.push_back(builder.createCompositeExtract(constituent, elementRType, i)); + } + constituents[c] = createCompositeConstruct(lType, rTypeConstituents); + } + } + } + return builder.createCompositeConstruct(resultTypeId, constituents); +} + bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TIntermAggregate* node) { SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); @@ -2052,14 +2287,15 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt builder.setAccessChainRValue(result); return false; - } else if (node->getOp() == glslang::EOpImageStore || -#ifdef AMD_EXTENSIONS + } +#ifndef GLSLANG_WEB + else if (node->getOp() == glslang::EOpImageStore || node->getOp() == glslang::EOpImageStoreLod || -#endif node->getOp() == glslang::EOpImageAtomicStore) { // "imageStore" is a special case, which has no result return false; } +#endif glslang::TOperator binOp = glslang::EOpNull; bool reduceComparison = true; @@ -2067,6 +2303,8 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt bool noReturnValue = false; bool atomic = false; + spv::Builder::AccessChain::CoherentFlags lvalueCoherentFlags; + assert(node->getOp()); spv::Decoration precision = TranslatePrecisionDecoration(node->getOperationPrecision()); @@ -2264,7 +2502,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt { builder.setLine(node->getLoc().line, node->getLoc().getFilename()); std::vector<spv::Id> arguments; - translateArguments(*node, arguments); + translateArguments(*node, arguments, lvalueCoherentFlags); spv::Id constructed; if (node->getOp() == glslang::EOpConstructTextureSampler) constructed = builder.createOp(spv::OpSampledImage, resultType(), arguments); @@ -2274,7 +2512,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt std::vector<spv::Id> constituents; for (int c = 0; c < (int)arguments.size(); ++c) constituents.push_back(arguments[c]); - constructed = builder.createCompositeConstruct(resultType(), constituents); + constructed = createCompositeConstruct(resultType(), constituents); } else if (isMatrix) constructed = builder.createMatrixConstructor(precision, arguments, resultType()); else @@ -2327,6 +2565,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt // which can be emitted by the one in createBinaryOperation() binOp = glslang::EOpMod; break; + case glslang::EOpEmitVertex: case glslang::EOpEndPrimitive: case glslang::EOpBarrier: @@ -2350,10 +2589,6 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt // These all have 0 operands and will naturally finish up in the code below for 0 operands break; - case glslang::EOpAtomicStore: - noReturnValue = true; - // fallthrough - case glslang::EOpAtomicLoad: case glslang::EOpAtomicAdd: case glslang::EOpAtomicMin: case glslang::EOpAtomicMax: @@ -2365,6 +2600,14 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt atomic = true; break; +#ifndef GLSLANG_WEB + case glslang::EOpAtomicStore: + noReturnValue = true; + // fallthrough + case glslang::EOpAtomicLoad: + atomic = true; + break; + case glslang::EOpAtomicCounterAdd: case glslang::EOpAtomicCounterSubtract: case glslang::EOpAtomicCounterMin: @@ -2379,7 +2622,17 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt atomic = true; break; -#ifdef NV_EXTENSIONS + case glslang::EOpAbsDifference: + case glslang::EOpAddSaturate: + case glslang::EOpSubSaturate: + case glslang::EOpAverage: + case glslang::EOpAverageRounded: + case glslang::EOpMul32x16: + builder.addCapability(spv::CapabilityIntegerFunctions2INTEL); + builder.addExtension("SPV_INTEL_shader_integer_functions2"); + binOp = node->getOp(); + break; + case glslang::EOpIgnoreIntersectionNV: case glslang::EOpTerminateRayNV: case glslang::EOpTraceNV: @@ -2387,11 +2640,16 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt case glslang::EOpWritePackedPrimitiveIndices4x8NV: noReturnValue = true; break; -#endif case glslang::EOpCooperativeMatrixLoad: case glslang::EOpCooperativeMatrixStore: noReturnValue = true; break; + case glslang::EOpBeginInvocationInterlock: + case glslang::EOpEndInvocationInterlock: + builder.addExtension(spv::E_SPV_EXT_fragment_shader_interlock); + noReturnValue = true; + break; +#endif default: break; @@ -2439,16 +2697,31 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt // special case l-value operands; there are just a few bool lvalue = false; switch (node->getOp()) { - case glslang::EOpFrexp: case glslang::EOpModf: if (arg == 1) lvalue = true; break; + + case glslang::EOpAtomicAdd: + case glslang::EOpAtomicMin: + case glslang::EOpAtomicMax: + case glslang::EOpAtomicAnd: + case glslang::EOpAtomicOr: + case glslang::EOpAtomicXor: + case glslang::EOpAtomicExchange: + case glslang::EOpAtomicCompSwap: + if (arg == 0) + lvalue = true; + break; + +#ifndef GLSLANG_WEB + case glslang::EOpFrexp: + if (arg == 1) + lvalue = true; + break; case glslang::EOpInterpolateAtSample: case glslang::EOpInterpolateAtOffset: -#ifdef AMD_EXTENSIONS case glslang::EOpInterpolateAtVertex: -#endif if (arg == 0) { lvalue = true; @@ -2459,14 +2732,6 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt invertedType = convertGlslangToSpvType(glslangOperands[0]->getAsBinaryNode()->getLeft()->getType()); } break; - case glslang::EOpAtomicAdd: - case glslang::EOpAtomicMin: - case glslang::EOpAtomicMax: - case glslang::EOpAtomicAnd: - case glslang::EOpAtomicOr: - case glslang::EOpAtomicXor: - case glslang::EOpAtomicExchange: - case glslang::EOpAtomicCompSwap: case glslang::EOpAtomicLoad: case glslang::EOpAtomicStore: case glslang::EOpAtomicCounterAdd: @@ -2499,6 +2764,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt if (arg == 1) lvalue = true; break; +#endif default: break; } @@ -2508,6 +2774,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt else glslangOperands[arg]->traverse(this); +#ifndef GLSLANG_WEB if (node->getOp() == glslang::EOpCooperativeMatrixLoad || node->getOp() == glslang::EOpCooperativeMatrixStore) { @@ -2550,16 +2817,20 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt continue; } } +#endif - if (lvalue) + if (lvalue) { operands.push_back(builder.accessChainGetLValue()); - else { + lvalueCoherentFlags = builder.getAccessChain().coherentFlags; + lvalueCoherentFlags |= TranslateCoherent(glslangOperands[arg]->getAsTyped()->getType()); + } else { builder.setLine(node->getLoc().line, node->getLoc().getFilename()); operands.push_back(accessChainLoad(glslangOperands[arg]->getAsTyped()->getType())); } } builder.setLine(node->getLoc().line, node->getLoc().getFilename()); +#ifndef GLSLANG_WEB if (node->getOp() == glslang::EOpCooperativeMatrixLoad) { std::vector<spv::IdImmediate> idImmOps; @@ -2586,9 +2857,11 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt builder.createNoResultOp(spv::OpCooperativeMatrixStoreNV, idImmOps); result = 0; - } else if (atomic) { + } else +#endif + if (atomic) { // Handle all atomics - result = createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType()); + result = createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType(), lvalueCoherentFlags); } else { // Pass through to generic operations. switch (glslangOperands.size()) { @@ -2603,7 +2876,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt result = createUnaryOperation( node->getOp(), decorations, resultType(), operands.front(), - glslangOperands[0]->getAsTyped()->getBasicType()); + glslangOperands[0]->getAsTyped()->getBasicType(), lvalueCoherentFlags); } break; default: @@ -2965,6 +3238,14 @@ bool TGlslangToSpvTraverser::visitBranch(glslang::TVisit /* visit */, glslang::T builder.clearAccessChain(); break; +#ifndef GLSLANG_WEB + case glslang::EOpDemote: + builder.createNoResultOp(spv::OpDemoteToHelperInvocationEXT); + builder.addExtension(spv::E_SPV_EXT_demote_to_helper_invocation); + builder.addCapability(spv::CapabilityDemoteToHelperInvocationEXT); + break; +#endif + default: assert(0); break; @@ -2973,7 +3254,7 @@ bool TGlslangToSpvTraverser::visitBranch(glslang::TVisit /* visit */, glslang::T return false; } -spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol* node) +spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol* node, spv::Id forcedType) { // First, steer off constants, which are not SPIR-V variables, but // can still have a mapping to a SPIR-V Id. @@ -2986,51 +3267,57 @@ spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol* // Now, handle actual variables spv::StorageClass storageClass = TranslateStorageClass(node->getType()); - spv::Id spvType = convertGlslangToSpvType(node->getType()); + spv::Id spvType = forcedType == spv::NoType ? convertGlslangToSpvType(node->getType()) + : forcedType; - const bool contains16BitType = node->getType().containsBasicType(glslang::EbtFloat16) || - node->getType().containsBasicType(glslang::EbtInt16) || - node->getType().containsBasicType(glslang::EbtUint16); + const bool contains16BitType = node->getType().contains16BitFloat() || + node->getType().contains16BitInt(); if (contains16BitType) { switch (storageClass) { case spv::StorageClassInput: case spv::StorageClassOutput: - addPre13Extension(spv::E_SPV_KHR_16bit_storage); + builder.addIncorporatedExtension(spv::E_SPV_KHR_16bit_storage, spv::Spv_1_3); builder.addCapability(spv::CapabilityStorageInputOutput16); break; - case spv::StorageClassPushConstant: - addPre13Extension(spv::E_SPV_KHR_16bit_storage); - builder.addCapability(spv::CapabilityStoragePushConstant16); - break; case spv::StorageClassUniform: - addPre13Extension(spv::E_SPV_KHR_16bit_storage); + builder.addIncorporatedExtension(spv::E_SPV_KHR_16bit_storage, spv::Spv_1_3); if (node->getType().getQualifier().storage == glslang::EvqBuffer) builder.addCapability(spv::CapabilityStorageUniformBufferBlock16); else builder.addCapability(spv::CapabilityStorageUniform16); break; +#ifndef GLSLANG_WEB + case spv::StorageClassPushConstant: + builder.addIncorporatedExtension(spv::E_SPV_KHR_16bit_storage, spv::Spv_1_3); + builder.addCapability(spv::CapabilityStoragePushConstant16); + break; case spv::StorageClassStorageBuffer: case spv::StorageClassPhysicalStorageBufferEXT: - addPre13Extension(spv::E_SPV_KHR_16bit_storage); + builder.addIncorporatedExtension(spv::E_SPV_KHR_16bit_storage, spv::Spv_1_3); builder.addCapability(spv::CapabilityStorageUniformBufferBlock16); break; +#endif default: + if (node->getType().contains16BitFloat()) + builder.addCapability(spv::CapabilityFloat16); + if (node->getType().contains16BitInt()) + builder.addCapability(spv::CapabilityInt16); break; } } - const bool contains8BitType = node->getType().containsBasicType(glslang::EbtInt8) || - node->getType().containsBasicType(glslang::EbtUint8); - if (contains8BitType) { + if (node->getType().contains8BitInt()) { if (storageClass == spv::StorageClassPushConstant) { - builder.addExtension(spv::E_SPV_KHR_8bit_storage); + builder.addIncorporatedExtension(spv::E_SPV_KHR_8bit_storage, spv::Spv_1_5); builder.addCapability(spv::CapabilityStoragePushConstant8); } else if (storageClass == spv::StorageClassUniform) { - builder.addExtension(spv::E_SPV_KHR_8bit_storage); + builder.addIncorporatedExtension(spv::E_SPV_KHR_8bit_storage, spv::Spv_1_5); builder.addCapability(spv::CapabilityUniformAndStorageBuffer8BitAccess); } else if (storageClass == spv::StorageClassStorageBuffer) { - builder.addExtension(spv::E_SPV_KHR_8bit_storage); + builder.addIncorporatedExtension(spv::E_SPV_KHR_8bit_storage, spv::Spv_1_5); builder.addCapability(spv::CapabilityStorageBuffer8BitAccess); + } else { + builder.addCapability(spv::CapabilityInt8); } } @@ -3045,15 +3332,15 @@ spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol* spv::Id TGlslangToSpvTraverser::getSampledType(const glslang::TSampler& sampler) { switch (sampler.type) { + case glslang::EbtInt: return builder.makeIntType(32); + case glslang::EbtUint: return builder.makeUintType(32); case glslang::EbtFloat: return builder.makeFloatType(32); -#ifdef AMD_EXTENSIONS +#ifndef GLSLANG_WEB case glslang::EbtFloat16: builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float_fetch); builder.addCapability(spv::CapabilityFloat16ImageAMD); return builder.makeFloatType(16); #endif - case glslang::EbtInt: return builder.makeIntType(32); - case glslang::EbtUint: return builder.makeUintType(32); default: assert(0); return builder.makeFloatType(32); @@ -3111,23 +3398,30 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty spvType = builder.makeVoidType(); assert (! type.isArray()); break; + case glslang::EbtBool: + // "transparent" bool doesn't exist in SPIR-V. The GLSL convention is + // a 32-bit int where non-0 means true. + if (explicitLayout != glslang::ElpNone) + spvType = builder.makeUintType(32); + else + spvType = builder.makeBoolType(); + break; + case glslang::EbtInt: + spvType = builder.makeIntType(32); + break; + case glslang::EbtUint: + spvType = builder.makeUintType(32); + break; case glslang::EbtFloat: spvType = builder.makeFloatType(32); break; +#ifndef GLSLANG_WEB case glslang::EbtDouble: spvType = builder.makeFloatType(64); break; case glslang::EbtFloat16: spvType = builder.makeFloatType(16); break; - case glslang::EbtBool: - // "transparent" bool doesn't exist in SPIR-V. The GLSL convention is - // a 32-bit int where non-0 means true. - if (explicitLayout != glslang::ElpNone) - spvType = builder.makeUintType(32); - else - spvType = builder.makeBoolType(); - break; case glslang::EbtInt8: spvType = builder.makeIntType(8); break; @@ -3140,12 +3434,6 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty case glslang::EbtUint16: spvType = builder.makeUintType(16); break; - case glslang::EbtInt: - spvType = builder.makeIntType(32); - break; - case glslang::EbtUint: - spvType = builder.makeUintType(32); - break; case glslang::EbtInt64: spvType = builder.makeIntType(64); break; @@ -3156,22 +3444,38 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty builder.addCapability(spv::CapabilityAtomicStorage); spvType = builder.makeUintType(32); break; -#ifdef NV_EXTENSIONS case glslang::EbtAccStructNV: spvType = builder.makeAccelerationStructureNVType(); break; + case glslang::EbtReference: + { + // Make the forward pointer, then recurse to convert the structure type, then + // patch up the forward pointer with a real pointer type. + if (forwardPointers.find(type.getReferentType()) == forwardPointers.end()) { + spv::Id forwardId = builder.makeForwardPointer(spv::StorageClassPhysicalStorageBufferEXT); + forwardPointers[type.getReferentType()] = forwardId; + } + spvType = forwardPointers[type.getReferentType()]; + if (!forwardReferenceOnly) { + spv::Id referentType = convertGlslangToSpvType(*type.getReferentType()); + builder.makePointerFromForwardPointer(spv::StorageClassPhysicalStorageBufferEXT, + forwardPointers[type.getReferentType()], + referentType); + } + } + break; #endif case glslang::EbtSampler: { const glslang::TSampler& sampler = type.getSampler(); - if (sampler.sampler) { - // pure sampler + if (sampler.isPureSampler()) { spvType = builder.makeSamplerType(); } else { // an image is present, make its type - spvType = builder.makeImageType(getSampledType(sampler), TranslateDimensionality(sampler), sampler.shadow, sampler.arrayed, sampler.ms, - sampler.image ? 2 : 1, TranslateImageFormat(type)); - if (sampler.combined) { + spvType = builder.makeImageType(getSampledType(sampler), TranslateDimensionality(sampler), + sampler.isShadow(), sampler.isArrayed(), sampler.isMultiSample(), + sampler.isImageClass() ? 2 : 1, TranslateImageFormat(type)); + if (sampler.isCombined()) { // already has both image and sampler, make the combined type spvType = builder.makeSampledImageType(spvType); } @@ -3193,27 +3497,10 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty // else, we haven't seen it... if (type.getBasicType() == glslang::EbtBlock) - memberRemapper[glslangMembers].resize(glslangMembers->size()); + memberRemapper[glslangTypeToIdMap[glslangMembers]].resize(glslangMembers->size()); spvType = convertGlslangStructToSpvType(type, glslangMembers, explicitLayout, qualifier); } break; - case glslang::EbtReference: - { - // Make the forward pointer, then recurse to convert the structure type, then - // patch up the forward pointer with a real pointer type. - if (forwardPointers.find(type.getReferentType()) == forwardPointers.end()) { - spv::Id forwardId = builder.makeForwardPointer(spv::StorageClassPhysicalStorageBufferEXT); - forwardPointers[type.getReferentType()] = forwardId; - } - spvType = forwardPointers[type.getReferentType()]; - if (!forwardReferenceOnly) { - spv::Id referentType = convertGlslangToSpvType(*type.getReferentType()); - builder.makePointerFromForwardPointer(spv::StorageClassPhysicalStorageBufferEXT, - forwardPointers[type.getReferentType()], - referentType); - } - } - break; default: assert(0); break; @@ -3232,6 +3519,10 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty builder.addExtension(spv::E_SPV_NV_cooperative_matrix); if (type.getBasicType() == glslang::EbtFloat16) builder.addCapability(spv::CapabilityFloat16); + if (type.getBasicType() == glslang::EbtUint8 || + type.getBasicType() == glslang::EbtInt8) { + builder.addCapability(spv::CapabilityInt8); + } spv::Id scope = makeArraySizeId(*type.getTypeParameters(), 1); spv::Id rows = makeArraySizeId(*type.getTypeParameters(), 2); @@ -3278,10 +3569,12 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty if (type.isSizedArray()) spvType = builder.makeArrayType(spvType, makeArraySizeId(*type.getArraySizes(), 0), stride); else { +#ifndef GLSLANG_WEB if (!lastBufferBlockMember) { - builder.addExtension("SPV_EXT_descriptor_indexing"); + builder.addIncorporatedExtension("SPV_EXT_descriptor_indexing", spv::Spv_1_5); builder.addCapability(spv::CapabilityRuntimeDescriptorArrayEXT); } +#endif spvType = builder.makeRuntimeArray(spvType); } if (stride > 0) @@ -3297,7 +3590,7 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty // bool TGlslangToSpvTraverser::filterMember(const glslang::TType& member) { -#ifdef NV_EXTENSIONS +#ifndef GLSLANG_WEB auto& extensions = glslangIntermediate->getRequestedExtensions(); if (member.getFieldName() == "gl_SecondaryViewportMaskNV" && @@ -3340,12 +3633,15 @@ spv::Id TGlslangToSpvTraverser::convertGlslangStructToSpvType(const glslang::TTy if (glslangMember.hiddenMember()) { ++memberDelta; if (type.getBasicType() == glslang::EbtBlock) - memberRemapper[glslangMembers][i] = -1; + memberRemapper[glslangTypeToIdMap[glslangMembers]][i] = -1; } else { if (type.getBasicType() == glslang::EbtBlock) { - memberRemapper[glslangMembers][i] = i - memberDelta; - if (filterMember(glslangMember)) + if (filterMember(glslangMember)) { + memberDelta++; + memberRemapper[glslangTypeToIdMap[glslangMembers]][i] = -1; continue; + } + memberRemapper[glslangTypeToIdMap[glslangMembers]][i] = i - memberDelta; } // modify just this child's view of the qualifier glslang::TQualifier memberQualifier = glslangMember.getQualifier(); @@ -3361,7 +3657,7 @@ spv::Id TGlslangToSpvTraverser::convertGlslangStructToSpvType(const glslang::TTy // Make forward pointers for any pointer members, and create a list of members to // convert to spirv types after creating the struct. - if (glslangMember.getBasicType() == glslang::EbtReference) { + if (glslangMember.isReference()) { if (forwardPointers.find(glslangMember.getReferentType()) == forwardPointers.end()) { deferredForwardPointers.push_back(std::make_pair(&glslangMember, memberQualifier)); } @@ -3403,7 +3699,7 @@ void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type, glslang::TType& glslangMember = *(*glslangMembers)[i].type; int member = i; if (type.getBasicType() == glslang::EbtBlock) { - member = memberRemapper[glslangMembers][i]; + member = memberRemapper[glslangTypeToIdMap[glslangMembers]][i]; if (filterMember(glslangMember)) continue; } @@ -3428,13 +3724,14 @@ void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type, glslangIntermediate->getSource() == glslang::EShSourceHlsl) { builder.addMemberDecoration(spvType, member, TranslateInterpolationDecoration(memberQualifier)); builder.addMemberDecoration(spvType, member, TranslateAuxiliaryStorageDecoration(memberQualifier)); -#ifdef NV_EXTENSIONS +#ifndef GLSLANG_WEB addMeshNVDecoration(spvType, member, memberQualifier); #endif } } builder.addMemberDecoration(spvType, member, TranslateInvariantDecoration(memberQualifier)); +#ifndef GLSLANG_WEB if (type.getBasicType() == glslang::EbtBlock && qualifier.storage == glslang::EvqBuffer) { // Add memory decorations only to top-level members of shader storage block @@ -3444,6 +3741,8 @@ void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type, builder.addMemberDecoration(spvType, member, memory[i]); } +#endif + // Location assignment was already completed correctly by the front end, // just track whether a member needs to be decorated. // Ignore member locations if the container is an array, as that's @@ -3480,6 +3779,7 @@ void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type, if (builtIn != spv::BuiltInMax) builder.addMemberDecoration(spvType, member, spv::DecorationBuiltIn, (int)builtIn); +#ifndef GLSLANG_WEB // nonuniform builder.addMemberDecoration(spvType, member, TranslateNonUniformDecoration(glslangMember.getQualifier())); @@ -3489,7 +3789,6 @@ void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type, memberQualifier.semanticName); } -#ifdef NV_EXTENSIONS if (builtIn == spv::BuiltInLayer) { // SPV_NV_viewport_array2 extension if (glslangMember.getQualifier().layoutViewportRelative){ @@ -3828,10 +4127,10 @@ void TGlslangToSpvTraverser::declareUseOfStructMember(const glslang::TTypeList& const glslang::TBuiltInVariable glslangBuiltIn = members[glslangMember].type->getQualifier().builtIn; switch (glslangBuiltIn) { + case glslang::EbvPointSize: +#ifndef GLSLANG_WEB case glslang::EbvClipDistance: case glslang::EbvCullDistance: - case glslang::EbvPointSize: -#ifdef NV_EXTENSIONS case glslang::EbvViewportMaskNV: case glslang::EbvSecondaryPositionNV: case glslang::EbvSecondaryViewportMaskNV: @@ -3894,15 +4193,17 @@ void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslF if (paramPrecision != spv::NoPrecision) decorations.push_back(paramPrecision); TranslateMemoryDecoration(type.getQualifier(), decorations, useVulkanMemoryModel); - if (type.getBasicType() == glslang::EbtReference) { + if (type.isReference()) { // Original and non-writable params pass the pointer directly and // use restrict/aliased, others are stored to a pointer in Function // memory and use RestrictPointer/AliasedPointer. if (originalParam(type.getQualifier().storage, type, false) || !writableParam(type.getQualifier().storage)) { - decorations.push_back(type.getQualifier().restrict ? spv::DecorationRestrict : spv::DecorationAliased); + decorations.push_back(type.getQualifier().isRestrict() ? spv::DecorationRestrict : + spv::DecorationAliased); } else { - decorations.push_back(type.getQualifier().restrict ? spv::DecorationRestrictPointerEXT : spv::DecorationAliasedPointerEXT); + decorations.push_back(type.getQualifier().isRestrict() ? spv::DecorationRestrictPointerEXT : + spv::DecorationAliasedPointerEXT); } } }; @@ -3930,8 +4231,12 @@ void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslF std::vector<std::vector<spv::Decoration>> paramDecorations; // list of decorations per parameter glslang::TIntermSequence& parameters = glslFunction->getSequence()[0]->getAsAggregate()->getSequence(); +#ifdef ENABLE_HLSL bool implicitThis = (int)parameters.size() > 0 && parameters[0]->getAsSymbolNode()->getName() == glslangIntermediate->implicitThisName; +#else + bool implicitThis = false; +#endif paramDecorations.resize(parameters.size()); for (int p = 0; p < (int)parameters.size(); ++p) { @@ -3963,6 +4268,14 @@ void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslF symbolValues[parameters[p]->getAsSymbolNode()->getId()] = function->getParamId(p); // give a name too builder.addName(function->getParamId(p), parameters[p]->getAsSymbolNode()->getName().c_str()); + + const glslang::TType& paramType = parameters[p]->getAsTyped()->getType(); + if (paramType.contains8BitInt()) + builder.addCapability(spv::CapabilityInt8); + if (paramType.contains16BitInt()) + builder.addCapability(spv::CapabilityInt16); + if (paramType.contains16BitFloat()) + builder.addCapability(spv::CapabilityFloat16); } } } @@ -4001,19 +4314,19 @@ void TGlslangToSpvTraverser::handleFunctionEntry(const glslang::TIntermAggregate builder.setBuildPoint(functionBlock); } -void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate& node, std::vector<spv::Id>& arguments) +void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate& node, std::vector<spv::Id>& arguments, spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags) { const glslang::TIntermSequence& glslangArguments = node.getSequence(); glslang::TSampler sampler = {}; bool cubeCompare = false; -#ifdef AMD_EXTENSIONS +#ifndef GLSLANG_WEB bool f16ShadowCompare = false; #endif if (node.isTexture() || node.isImage()) { sampler = glslangArguments[0]->getAsTyped()->getType().getSampler(); cubeCompare = sampler.dim == glslang::EsdCube && sampler.arrayed && sampler.shadow; -#ifdef AMD_EXTENSIONS +#ifndef GLSLANG_WEB f16ShadowCompare = sampler.shadow && glslangArguments[1]->getAsTyped()->getType().getBasicType() == glslang::EbtFloat16; #endif } @@ -4022,6 +4335,7 @@ void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate& builder.clearAccessChain(); glslangArguments[i]->traverse(this); +#ifndef GLSLANG_WEB // Special case l-value operands bool lvalue = false; switch (node.getOp()) { @@ -4042,7 +4356,6 @@ void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate& if ((sampler.ms && i == 3) || (! sampler.ms && i == 2)) lvalue = true; break; -#ifdef AMD_EXTENSIONS case glslang::EOpSparseTexture: if (((cubeCompare || f16ShadowCompare) && i == 3) || (! (cubeCompare || f16ShadowCompare) && i == 2)) lvalue = true; @@ -4056,21 +4369,6 @@ void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate& if ((f16ShadowCompare && i == 4) || (! f16ShadowCompare && i == 3)) lvalue = true; break; -#else - case glslang::EOpSparseTexture: - if ((cubeCompare && i == 3) || (! cubeCompare && i == 2)) - lvalue = true; - break; - case glslang::EOpSparseTextureClamp: - if ((cubeCompare && i == 4) || (! cubeCompare && i == 3)) - lvalue = true; - break; - case glslang::EOpSparseTextureLod: - case glslang::EOpSparseTextureOffset: - if (i == 3) - lvalue = true; - break; -#endif case glslang::EOpSparseTextureFetch: if ((sampler.dim != glslang::EsdRect && i == 3) || (sampler.dim == glslang::EsdRect && i == 2)) lvalue = true; @@ -4079,7 +4377,6 @@ void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate& if ((sampler.dim != glslang::EsdRect && i == 4) || (sampler.dim == glslang::EsdRect && i == 3)) lvalue = true; break; -#ifdef AMD_EXTENSIONS case glslang::EOpSparseTextureLodOffset: case glslang::EOpSparseTextureGrad: case glslang::EOpSparseTextureOffsetClamp: @@ -4095,23 +4392,6 @@ void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate& if ((f16ShadowCompare && i == 7) || (! f16ShadowCompare && i == 6)) lvalue = true; break; -#else - case glslang::EOpSparseTextureLodOffset: - case glslang::EOpSparseTextureGrad: - case glslang::EOpSparseTextureOffsetClamp: - if (i == 4) - lvalue = true; - break; - case glslang::EOpSparseTextureGradOffset: - case glslang::EOpSparseTextureGradClamp: - if (i == 5) - lvalue = true; - break; - case glslang::EOpSparseTextureGradOffsetClamp: - if (i == 6) - lvalue = true; - break; -#endif case glslang::EOpSparseTextureGather: if ((sampler.shadow && i == 3) || (! sampler.shadow && i == 2)) lvalue = true; @@ -4121,7 +4401,6 @@ void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate& if ((sampler.shadow && i == 4) || (! sampler.shadow && i == 3)) lvalue = true; break; -#ifdef AMD_EXTENSIONS case glslang::EOpSparseTextureGatherLod: if (i == 3) lvalue = true; @@ -4135,8 +4414,6 @@ void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate& if (i == 3) lvalue = true; break; -#endif -#ifdef NV_EXTENSIONS case glslang::EOpImageSampleFootprintNV: if (i == 4) lvalue = true; @@ -4154,14 +4431,16 @@ void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate& if (i == 7) lvalue = true; break; -#endif default: break; } - if (lvalue) + if (lvalue) { arguments.push_back(builder.accessChainGetLValue()); - else + lvalueCoherentFlags = builder.getAccessChain().coherentFlags; + lvalueCoherentFlags |= TranslateCoherent(glslangArguments[i]->getAsTyped()->getType()); + } else +#endif arguments.push_back(accessChainLoad(glslangArguments[i]->getAsTyped()->getType())); } } @@ -4186,7 +4465,9 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO ? node->getAsAggregate()->getSequence()[0]->getAsTyped()->getType() : node->getAsUnaryNode()->getOperand()->getAsTyped()->getType(); const glslang::TSampler sampler = imageType.getSampler(); -#ifdef AMD_EXTENSIONS +#ifdef GLSLANG_WEB + const bool f16ShadowCompare = false; +#else bool f16ShadowCompare = (sampler.shadow && node->getAsAggregate()) ? node->getAsAggregate()->getSequence()[1]->getAsTyped()->getType().getBasicType() == glslang::EbtFloat16 : false; @@ -4202,9 +4483,11 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO return spv::ImageOperandsMaskNone; }; + spv::Builder::AccessChain::CoherentFlags lvalueCoherentFlags; + std::vector<spv::Id> arguments; if (node->getAsAggregate()) - translateArguments(*node->getAsAggregate(), arguments); + translateArguments(*node->getAsAggregate(), arguments, lvalueCoherentFlags); else translateArguments(*node->getAsUnaryNode(), arguments); spv::Decoration precision = TranslatePrecisionDecoration(node->getOperationPrecision()); @@ -4231,6 +4514,7 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO return builder.createTextureQueryCall(spv::OpImageQuerySizeLod, params, isUnsignedResult); } else return builder.createTextureQueryCall(spv::OpImageQuerySize, params, isUnsignedResult); +#ifndef GLSLANG_WEB case glslang::EOpImageQuerySamples: case glslang::EOpTextureQuerySamples: return builder.createTextureQueryCall(spv::OpImageQuerySamples, params, isUnsignedResult); @@ -4241,6 +4525,7 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO return builder.createTextureQueryCall(spv::OpImageQueryLevels, params, isUnsignedResult); case glslang::EOpSparseTexelsResident: return builder.createUnaryOp(spv::OpImageSparseTexelsResident, builder.makeBoolType(), arguments[0]); +#endif default: assert(0); break; @@ -4282,12 +4567,12 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO operands.push_back(coord); spv::IdImmediate imageOperands = { false, spv::ImageOperandsMaskNone }; imageOperands.word = imageOperands.word | signExtensionMask(); - if (sampler.ms) { + if (sampler.isMultiSample()) { imageOperands.word = imageOperands.word | spv::ImageOperandsSampleMask; } if (imageOperands.word != spv::ImageOperandsMaskNone) { operands.push_back(imageOperands); - if (sampler.ms) { + if (sampler.isMultiSample()) { spv::IdImmediate imageOperand = { true, *(opIt++) }; operands.push_back(imageOperand); } @@ -4299,22 +4584,16 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO spv::IdImmediate coord = { true, *(opIt++) }; operands.push_back(coord); -#ifdef AMD_EXTENSIONS if (node->getOp() == glslang::EOpImageLoad || node->getOp() == glslang::EOpImageLoadLod) { -#else - if (node->getOp() == glslang::EOpImageLoad) { -#endif spv::ImageOperandsMask mask = spv::ImageOperandsMaskNone; - if (sampler.ms) { + if (sampler.isMultiSample()) { mask = mask | spv::ImageOperandsSampleMask; } -#ifdef AMD_EXTENSIONS if (cracked.lod) { builder.addExtension(spv::E_SPV_AMD_shader_image_load_store_lod); builder.addCapability(spv::CapabilityImageReadWriteLodAMD); mask = mask | spv::ImageOperandsLodMask; } -#endif mask = mask | TranslateImageOperands(TranslateCoherent(imageType)); mask = (spv::ImageOperandsMask)(mask & ~spv::ImageOperandsMakeTexelAvailableKHRMask); mask = mask | signExtensionMask(); @@ -4326,12 +4605,10 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO spv::IdImmediate imageOperand = { true, *opIt++ }; operands.push_back(imageOperand); } -#ifdef AMD_EXTENSIONS if (mask & spv::ImageOperandsLodMask) { spv::IdImmediate imageOperand = { true, *opIt++ }; operands.push_back(imageOperand); } -#endif if (mask & spv::ImageOperandsMakeTexelVisibleKHRMask) { spv::IdImmediate imageOperand = { true, builder.makeUintConstant(TranslateMemoryScope(TranslateCoherent(imageType))) }; @@ -4349,18 +4626,10 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO result[0] = builder.createConstructor(precision, result, convertGlslangToSpvType(node->getType())); return result[0]; -#ifdef AMD_EXTENSIONS } else if (node->getOp() == glslang::EOpImageStore || node->getOp() == glslang::EOpImageStoreLod) { -#else - } else if (node->getOp() == glslang::EOpImageStore) { -#endif // Push the texel value before the operands -#ifdef AMD_EXTENSIONS - if (sampler.ms || cracked.lod) { -#else - if (sampler.ms) { -#endif + if (sampler.isMultiSample() || cracked.lod) { spv::IdImmediate texel = { true, *(opIt + 1) }; operands.push_back(texel); } else { @@ -4369,16 +4638,14 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO } spv::ImageOperandsMask mask = spv::ImageOperandsMaskNone; - if (sampler.ms) { + if (sampler.isMultiSample()) { mask = mask | spv::ImageOperandsSampleMask; } -#ifdef AMD_EXTENSIONS if (cracked.lod) { builder.addExtension(spv::E_SPV_AMD_shader_image_load_store_lod); builder.addCapability(spv::CapabilityImageReadWriteLodAMD); mask = mask | spv::ImageOperandsLodMask; } -#endif mask = mask | TranslateImageOperands(TranslateCoherent(imageType)); mask = (spv::ImageOperandsMask)(mask & ~spv::ImageOperandsMakeTexelVisibleKHRMask); mask = mask | signExtensionMask(); @@ -4390,12 +4657,10 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO spv::IdImmediate imageOperand = { true, *opIt++ }; operands.push_back(imageOperand); } -#ifdef AMD_EXTENSIONS if (mask & spv::ImageOperandsLodMask) { spv::IdImmediate imageOperand = { true, *opIt++ }; operands.push_back(imageOperand); } -#endif if (mask & spv::ImageOperandsMakeTexelAvailableKHRMask) { spv::IdImmediate imageOperand = { true, builder.makeUintConstant(TranslateMemoryScope(TranslateCoherent(imageType))) }; @@ -4406,28 +4671,22 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO if (builder.getImageTypeFormat(builder.getImageType(operands.front().word)) == spv::ImageFormatUnknown) builder.addCapability(spv::CapabilityStorageImageWriteWithoutFormat); return spv::NoResult; -#ifdef AMD_EXTENSIONS } else if (node->getOp() == glslang::EOpSparseImageLoad || node->getOp() == glslang::EOpSparseImageLoadLod) { -#else - } else if (node->getOp() == glslang::EOpSparseImageLoad) { -#endif builder.addCapability(spv::CapabilitySparseResidency); if (builder.getImageTypeFormat(builder.getImageType(operands.front().word)) == spv::ImageFormatUnknown) builder.addCapability(spv::CapabilityStorageImageReadWithoutFormat); spv::ImageOperandsMask mask = spv::ImageOperandsMaskNone; - if (sampler.ms) { + if (sampler.isMultiSample()) { mask = mask | spv::ImageOperandsSampleMask; } -#ifdef AMD_EXTENSIONS if (cracked.lod) { builder.addExtension(spv::E_SPV_AMD_shader_image_load_store_lod); builder.addCapability(spv::CapabilityImageReadWriteLodAMD); mask = mask | spv::ImageOperandsLodMask; } -#endif mask = mask | TranslateImageOperands(TranslateCoherent(imageType)); mask = (spv::ImageOperandsMask)(mask & ~spv::ImageOperandsMakeTexelAvailableKHRMask); mask = mask | signExtensionMask(); @@ -4439,12 +4698,10 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO spv::IdImmediate imageOperand = { true, *opIt++ }; operands.push_back(imageOperand); } -#ifdef AMD_EXTENSIONS if (mask & spv::ImageOperandsLodMask) { spv::IdImmediate imageOperand = { true, *opIt++ }; operands.push_back(imageOperand); } -#endif if (mask & spv::ImageOperandsMakeTexelVisibleKHRMask) { spv::IdImmediate imageOperand = { true, builder.makeUintConstant(TranslateMemoryScope(TranslateCoherent(imageType))) }; operands.push_back(imageOperand); @@ -4467,7 +4724,7 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO // GLSL "IMAGE_PARAMS" will involve in constructing an image texel pointer and this pointer, // as the first source operand, is required by SPIR-V atomic operations. // For non-MS, the sample value should be 0 - spv::IdImmediate sample = { true, sampler.ms ? *(opIt++) : builder.makeUintConstant(0) }; + spv::IdImmediate sample = { true, sampler.isMultiSample() ? *(opIt++) : builder.makeUintConstant(0) }; operands.push_back(sample); spv::Id resultTypeId; @@ -4485,11 +4742,11 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO for (; opIt != arguments.end(); ++opIt) operands.push_back(*opIt); - return createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType()); + return createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType(), lvalueCoherentFlags); } } -#ifdef AMD_EXTENSIONS +#ifndef GLSLANG_WEB // Check for fragment mask functions other than queries if (cracked.fragMask) { assert(sampler.ms); @@ -4530,45 +4787,32 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO // Check for texture functions other than queries bool sparse = node->isSparseTexture(); -#ifdef NV_EXTENSIONS bool imageFootprint = node->isImageFootprint(); -#endif - - bool cubeCompare = sampler.dim == glslang::EsdCube && sampler.arrayed && sampler.shadow; + bool cubeCompare = sampler.dim == glslang::EsdCube && sampler.isArrayed() && sampler.isShadow(); // check for bias argument bool bias = false; -#ifdef AMD_EXTENSIONS if (! cracked.lod && ! cracked.grad && ! cracked.fetch && ! cubeCompare) { -#else - if (! cracked.lod && ! cracked.gather && ! cracked.grad && ! cracked.fetch && ! cubeCompare) { -#endif int nonBiasArgCount = 2; -#ifdef AMD_EXTENSIONS if (cracked.gather) ++nonBiasArgCount; // comp argument should be present when bias argument is present if (f16ShadowCompare) ++nonBiasArgCount; -#endif if (cracked.offset) ++nonBiasArgCount; -#ifdef AMD_EXTENSIONS else if (cracked.offsets) ++nonBiasArgCount; -#endif if (cracked.grad) nonBiasArgCount += 2; if (cracked.lodClamp) ++nonBiasArgCount; if (sparse) ++nonBiasArgCount; -#ifdef NV_EXTENSIONS if (imageFootprint) //Following three extra arguments // int granularity, bool coarse, out gl_TextureFootprint2DNV footprint nonBiasArgCount += 3; -#endif if ((int)arguments.size() > nonBiasArgCount) bias = true; } @@ -4580,7 +4824,7 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO params.sampler = builder.createUnaryOp(spv::OpImage, builder.getImageType(params.sampler), params.sampler); } -#ifdef AMD_EXTENSIONS +#ifndef GLSLANG_WEB if (cracked.gather) { const auto& sourceExtensions = glslangIntermediate->getRequestedExtensions(); if (bias || cracked.lod || @@ -4598,11 +4842,7 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO bool noImplicitLod = false; // sort out where Dref is coming from -#ifdef AMD_EXTENSIONS if (cubeCompare || f16ShadowCompare) { -#else - if (cubeCompare) { -#endif params.Dref = arguments[2]; ++extraArgs; } else if (sampler.shadow && cracked.gather) { @@ -4623,19 +4863,15 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO if (cracked.lod) { params.lod = arguments[2 + extraArgs]; ++extraArgs; - } else if (glslangIntermediate->getStage() != EShLangFragment -#ifdef NV_EXTENSIONS - // NV_compute_shader_derivatives layout qualifiers allow for implicit LODs - && !(glslangIntermediate->getStage() == EShLangCompute && - (glslangIntermediate->getLayoutDerivativeModeNone() != glslang::LayoutDerivativeNone)) -#endif - ) { + } else if (glslangIntermediate->getStage() != EShLangFragment && + !(glslangIntermediate->getStage() == EShLangCompute && + glslangIntermediate->hasLayoutDerivativeModeNone())) { // we need to invent the default lod for an explicit lod instruction for a non-fragment stage noImplicitLod = true; } // multisample - if (sampler.ms) { + if (sampler.isMultiSample()) { params.sample = arguments[2 + extraArgs]; // For MS, "sample" should be specified ++extraArgs; } @@ -4656,6 +4892,7 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO ++extraArgs; } +#ifndef GLSLANG_WEB // lod clamp if (cracked.lodClamp) { params.lodClamp = arguments[2 + extraArgs]; @@ -4666,7 +4903,6 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO params.texelOut = arguments[2 + extraArgs]; ++extraArgs; } - // gather component if (cracked.gather && ! sampler.shadow) { // default component is 0, if missing, otherwise an argument @@ -4676,7 +4912,6 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO } else params.component = builder.makeIntConstant(0); } -#ifdef NV_EXTENSIONS spv::Id resultStruct = spv::NoResult; if (imageFootprint) { //Following three extra arguments @@ -4693,7 +4928,7 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO ++extraArgs; } -#ifdef NV_EXTENSIONS +#ifndef GLSLANG_WEB if (imageFootprint) { builder.addExtension(spv::E_SPV_NV_shader_image_footprint); builder.addCapability(spv::CapabilityImageFootprintNV); @@ -4776,6 +5011,7 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO } } +#ifndef GLSLANG_WEB // nonprivate if (imageType.getQualifier().nonprivate) { params.nonprivate = true; @@ -4785,6 +5021,7 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO if (imageType.getQualifier().volatil) { params.volatil = true; } +#endif std::vector<spv::Id> result( 1, builder.createTextureCall(precision, resultType(), sparse, cracked.fetch, cracked.proj, cracked.gather, @@ -5019,6 +5256,30 @@ spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, OpD binOp = spv::OpLogicalNotEqual; break; + case glslang::EOpAbsDifference: + binOp = isUnsigned ? spv::OpAbsUSubINTEL : spv::OpAbsISubINTEL; + break; + + case glslang::EOpAddSaturate: + binOp = isUnsigned ? spv::OpUAddSatINTEL : spv::OpIAddSatINTEL; + break; + + case glslang::EOpSubSaturate: + binOp = isUnsigned ? spv::OpUSubSatINTEL : spv::OpISubSatINTEL; + break; + + case glslang::EOpAverage: + binOp = isUnsigned ? spv::OpUAverageINTEL : spv::OpIAverageINTEL; + break; + + case glslang::EOpAverageRounded: + binOp = isUnsigned ? spv::OpUAverageRoundedINTEL : spv::OpIAverageRoundedINTEL; + break; + + case glslang::EOpMul32x16: + binOp = isUnsigned ? spv::OpUMul32x16INTEL : spv::OpIMul32x16INTEL; + break; + case glslang::EOpLessThan: case glslang::EOpGreaterThan: case glslang::EOpLessThanEqual: @@ -5045,8 +5306,8 @@ spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, OpD builder.promoteScalar(decorations.precision, left, right); spv::Id result = builder.createBinOp(binOp, typeId, left, right); - builder.addDecoration(result, decorations.noContraction); - builder.addDecoration(result, decorations.nonUniform); + decorations.addNoContraction(builder, result); + decorations.addNonUniform(builder, result); return builder.setPrecision(result, decorations.precision); } @@ -5058,7 +5319,7 @@ spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, OpD if (reduceComparison && (op == glslang::EOpEqual || op == glslang::EOpNotEqual) && (builder.isVector(left) || builder.isMatrix(left) || builder.isAggregate(left))) { spv::Id result = builder.createCompositeCompare(decorations.precision, left, right, op == glslang::EOpEqual); - builder.addDecoration(result, decorations.nonUniform); + decorations.addNonUniform(builder, result); return result; } @@ -5119,8 +5380,8 @@ spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, OpD if (binOp != spv::OpNop) { spv::Id result = builder.createBinOp(binOp, typeId, left, right); - builder.addDecoration(result, decorations.noContraction); - builder.addDecoration(result, decorations.nonUniform); + decorations.addNoContraction(builder, result); + decorations.addNonUniform(builder, result); return builder.setPrecision(result, decorations.precision); } @@ -5184,8 +5445,8 @@ spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, OpDecora if (firstClass) { spv::Id result = builder.createBinOp(op, typeId, left, right); - builder.addDecoration(result, decorations.noContraction); - builder.addDecoration(result, decorations.nonUniform); + decorations.addNoContraction(builder, result); + decorations.addNonUniform(builder, result); return builder.setPrecision(result, decorations.precision); } @@ -5224,14 +5485,14 @@ spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, OpDecora spv::Id leftVec = leftMat ? builder.createCompositeExtract( left, vecType, indexes) : smearVec; spv::Id rightVec = rightMat ? builder.createCompositeExtract(right, vecType, indexes) : smearVec; spv::Id result = builder.createBinOp(op, vecType, leftVec, rightVec); - builder.addDecoration(result, decorations.noContraction); - builder.addDecoration(result, decorations.nonUniform); + decorations.addNoContraction(builder, result); + decorations.addNonUniform(builder, result); results.push_back(builder.setPrecision(result, decorations.precision)); } // put the pieces together spv::Id result = builder.setPrecision(builder.createCompositeConstruct(typeId, results), decorations.precision); - builder.addDecoration(result, decorations.nonUniform); + decorations.addNonUniform(builder, result); return result; } default: @@ -5241,7 +5502,7 @@ spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, OpDecora } spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, OpDecorations& decorations, spv::Id typeId, - spv::Id operand, glslang::TBasicType typeProxy) + spv::Id operand, glslang::TBasicType typeProxy, const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags) { spv::Op unaryOp = spv::OpNop; int extBuiltins = -1; @@ -5409,6 +5670,7 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, OpDe case glslang::EOpUnpackHalf2x16: libCall = spv::GLSLstd450UnpackHalf2x16; break; +#ifndef GLSLANG_WEB case glslang::EOpPackSnorm4x8: libCall = spv::GLSLstd450PackSnorm4x8; break; @@ -5427,6 +5689,7 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, OpDe case glslang::EOpUnpackDouble2x32: libCall = spv::GLSLstd450UnpackDouble2x32; break; +#endif case glslang::EOpPackInt2x32: case glslang::EOpUnpackInt2x32: @@ -5460,6 +5723,28 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, OpDe case glslang::EOpFwidth: unaryOp = spv::OpFwidth; break; + + case glslang::EOpAny: + unaryOp = spv::OpAny; + break; + case glslang::EOpAll: + unaryOp = spv::OpAll; + break; + + case glslang::EOpAbs: + if (isFloat) + libCall = spv::GLSLstd450FAbs; + else + libCall = spv::GLSLstd450SAbs; + break; + case glslang::EOpSign: + if (isFloat) + libCall = spv::GLSLstd450FSign; + else + libCall = spv::GLSLstd450SSign; + break; + +#ifndef GLSLANG_WEB case glslang::EOpDPdxFine: unaryOp = spv::OpDPdxFine; break; @@ -5479,32 +5764,10 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, OpDe unaryOp = spv::OpFwidthCoarse; break; case glslang::EOpInterpolateAtCentroid: -#ifdef AMD_EXTENSIONS if (typeProxy == glslang::EbtFloat16) builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float); -#endif libCall = spv::GLSLstd450InterpolateAtCentroid; break; - case glslang::EOpAny: - unaryOp = spv::OpAny; - break; - case glslang::EOpAll: - unaryOp = spv::OpAll; - break; - - case glslang::EOpAbs: - if (isFloat) - libCall = spv::GLSLstd450FAbs; - else - libCall = spv::GLSLstd450SAbs; - break; - case glslang::EOpSign: - if (isFloat) - libCall = spv::GLSLstd450FSign; - else - libCall = spv::GLSLstd450SSign; - break; - case glslang::EOpAtomicCounterIncrement: case glslang::EOpAtomicCounterDecrement: case glslang::EOpAtomicCounter: @@ -5512,7 +5775,7 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, OpDe // Handle all of the atomics in one place, in createAtomicOperation() std::vector<spv::Id> operands; operands.push_back(operand); - return createAtomicOperation(op, decorations.precision, typeId, operands, typeProxy); + return createAtomicOperation(op, decorations.precision, typeId, operands, typeProxy, lvalueCoherentFlags); } case glslang::EOpBitFieldReverse: @@ -5531,12 +5794,23 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, OpDe libCall = spv::GLSLstd450FindSMsb; break; + case glslang::EOpCountLeadingZeros: + builder.addCapability(spv::CapabilityIntegerFunctions2INTEL); + builder.addExtension("SPV_INTEL_shader_integer_functions2"); + unaryOp = spv::OpUCountLeadingZerosINTEL; + break; + + case glslang::EOpCountTrailingZeros: + builder.addCapability(spv::CapabilityIntegerFunctions2INTEL); + builder.addExtension("SPV_INTEL_shader_integer_functions2"); + unaryOp = spv::OpUCountTrailingZerosINTEL; + break; + case glslang::EOpBallot: case glslang::EOpReadFirstInvocation: case glslang::EOpAnyInvocation: case glslang::EOpAllInvocations: case glslang::EOpAllInvocationsEqual: -#ifdef AMD_EXTENSIONS case glslang::EOpMinInvocations: case glslang::EOpMaxInvocations: case glslang::EOpAddInvocations: @@ -5555,7 +5829,6 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, OpDe case glslang::EOpMinInvocationsExclusiveScanNonUniform: case glslang::EOpMaxInvocationsExclusiveScanNonUniform: case glslang::EOpAddInvocationsExclusiveScanNonUniform: -#endif { std::vector<spv::Id> operands; operands.push_back(operand); @@ -5600,7 +5873,6 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, OpDe operands.push_back(operand); return createSubgroupOperation(op, typeId, operands, typeProxy); } -#ifdef AMD_EXTENSIONS case glslang::EOpMbcnt: extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_ballot); libCall = spv::MbcntAMD; @@ -5615,15 +5887,13 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, OpDe extBuiltins = getExtBuiltins(spv::E_SPV_AMD_gcn_shader); libCall = spv::CubeFaceCoordAMD; break; -#endif -#ifdef NV_EXTENSIONS case glslang::EOpSubgroupPartition: unaryOp = spv::OpGroupNonUniformPartitionNV; break; -#endif case glslang::EOpConstructReference: unaryOp = spv::OpBitcast; break; +#endif case glslang::EOpCopyObject: unaryOp = spv::OpCopyObject; @@ -5642,8 +5912,8 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, OpDe id = builder.createUnaryOp(unaryOp, typeId, operand); } - builder.addDecoration(id, decorations.noContraction); - builder.addDecoration(id, decorations.nonUniform); + decorations.addNoContraction(builder, id); + decorations.addNonUniform(builder, id); return builder.setPrecision(id, decorations.precision); } @@ -5671,14 +5941,14 @@ spv::Id TGlslangToSpvTraverser::createUnaryMatrixOperation(spv::Op op, OpDecorat indexes.push_back(c); spv::Id srcVec = builder.createCompositeExtract(operand, srcVecType, indexes); spv::Id destVec = builder.createUnaryOp(op, destVecType, srcVec); - builder.addDecoration(destVec, decorations.noContraction); - builder.addDecoration(destVec, decorations.nonUniform); + decorations.addNoContraction(builder, destVec); + decorations.addNonUniform(builder, destVec); results.push_back(builder.setPrecision(destVec, decorations.precision)); } // put the pieces together spv::Id result = builder.setPrecision(builder.createCompositeConstruct(typeId, results), decorations.precision); - builder.addDecoration(result, decorations.nonUniform); + decorations.addNonUniform(builder, result); return result; } @@ -5770,110 +6040,49 @@ spv::Id TGlslangToSpvTraverser::createConversion(glslang::TOperator op, OpDecora int vectorSize = builder.isVectorType(destType) ? builder.getNumTypeComponents(destType) : 0; switch (op) { - case glslang::EOpConvInt8ToBool: - case glslang::EOpConvUint8ToBool: - zero = builder.makeUint8Constant(0); - zero = makeSmearedConstant(zero, vectorSize); - return builder.createBinOp(spv::OpINotEqual, destType, operand, zero); - case glslang::EOpConvInt16ToBool: - case glslang::EOpConvUint16ToBool: - zero = builder.makeUint16Constant(0); - zero = makeSmearedConstant(zero, vectorSize); - return builder.createBinOp(spv::OpINotEqual, destType, operand, zero); case glslang::EOpConvIntToBool: case glslang::EOpConvUintToBool: zero = builder.makeUintConstant(0); zero = makeSmearedConstant(zero, vectorSize); return builder.createBinOp(spv::OpINotEqual, destType, operand, zero); - case glslang::EOpConvInt64ToBool: - case glslang::EOpConvUint64ToBool: - zero = builder.makeUint64Constant(0); - zero = makeSmearedConstant(zero, vectorSize); - return builder.createBinOp(spv::OpINotEqual, destType, operand, zero); - case glslang::EOpConvFloatToBool: zero = builder.makeFloatConstant(0.0F); zero = makeSmearedConstant(zero, vectorSize); return builder.createBinOp(spv::OpFOrdNotEqual, destType, operand, zero); - - case glslang::EOpConvDoubleToBool: - zero = builder.makeDoubleConstant(0.0); - zero = makeSmearedConstant(zero, vectorSize); - return builder.createBinOp(spv::OpFOrdNotEqual, destType, operand, zero); - - case glslang::EOpConvFloat16ToBool: - zero = builder.makeFloat16Constant(0.0F); - zero = makeSmearedConstant(zero, vectorSize); - return builder.createBinOp(spv::OpFOrdNotEqual, destType, operand, zero); - case glslang::EOpConvBoolToFloat: convOp = spv::OpSelect; zero = builder.makeFloatConstant(0.0F); one = builder.makeFloatConstant(1.0F); break; - case glslang::EOpConvBoolToDouble: - convOp = spv::OpSelect; - zero = builder.makeDoubleConstant(0.0); - one = builder.makeDoubleConstant(1.0); - break; - - case glslang::EOpConvBoolToFloat16: - convOp = spv::OpSelect; - zero = builder.makeFloat16Constant(0.0F); - one = builder.makeFloat16Constant(1.0F); - break; - - case glslang::EOpConvBoolToInt8: - zero = builder.makeInt8Constant(0); - one = builder.makeInt8Constant(1); - convOp = spv::OpSelect; - break; - - case glslang::EOpConvBoolToUint8: - zero = builder.makeUint8Constant(0); - one = builder.makeUint8Constant(1); - convOp = spv::OpSelect; - break; - - case glslang::EOpConvBoolToInt16: - zero = builder.makeInt16Constant(0); - one = builder.makeInt16Constant(1); - convOp = spv::OpSelect; - break; - - case glslang::EOpConvBoolToUint16: - zero = builder.makeUint16Constant(0); - one = builder.makeUint16Constant(1); - convOp = spv::OpSelect; - break; - case glslang::EOpConvBoolToInt: case glslang::EOpConvBoolToInt64: - if (op == glslang::EOpConvBoolToInt64) +#ifndef GLSLANG_WEB + if (op == glslang::EOpConvBoolToInt64) { zero = builder.makeInt64Constant(0); - else - zero = builder.makeIntConstant(0); - - if (op == glslang::EOpConvBoolToInt64) one = builder.makeInt64Constant(1); - else + } else +#endif + { + zero = builder.makeIntConstant(0); one = builder.makeIntConstant(1); + } convOp = spv::OpSelect; break; case glslang::EOpConvBoolToUint: case glslang::EOpConvBoolToUint64: - if (op == glslang::EOpConvBoolToUint64) +#ifndef GLSLANG_WEB + if (op == glslang::EOpConvBoolToUint64) { zero = builder.makeUint64Constant(0); - else - zero = builder.makeUintConstant(0); - - if (op == glslang::EOpConvBoolToUint64) one = builder.makeUint64Constant(1); - else + } else +#endif + { + zero = builder.makeUintConstant(0); one = builder.makeUintConstant(1); + } convOp = spv::OpSelect; break; @@ -5908,17 +6117,6 @@ spv::Id TGlslangToSpvTraverser::createConversion(glslang::TOperator op, OpDecora convOp = spv::OpConvertUToF; break; - case glslang::EOpConvDoubleToFloat: - case glslang::EOpConvFloatToDouble: - case glslang::EOpConvDoubleToFloat16: - case glslang::EOpConvFloat16ToDouble: - case glslang::EOpConvFloatToFloat16: - case glslang::EOpConvFloat16ToFloat: - convOp = spv::OpFConvert; - if (builder.isMatrixType(destType)) - return createUnaryMatrixOperation(convOp, decorations, destType, operand, typeProxy); - break; - case glslang::EOpConvFloat16ToInt8: case glslang::EOpConvFloatToInt8: case glslang::EOpConvDoubleToInt8: @@ -5944,13 +6142,16 @@ spv::Id TGlslangToSpvTraverser::createConversion(glslang::TOperator op, OpDecora case glslang::EOpConvInt64ToUint64: if (builder.isInSpecConstCodeGenMode()) { // Build zero scalar or vector for OpIAdd. +#ifndef GLSLANG_WEB if(op == glslang::EOpConvUint8ToInt8 || op == glslang::EOpConvInt8ToUint8) { zero = builder.makeUint8Constant(0); } else if (op == glslang::EOpConvUint16ToInt16 || op == glslang::EOpConvInt16ToUint16) { zero = builder.makeUint16Constant(0); } else if (op == glslang::EOpConvUint64ToInt64 || op == glslang::EOpConvInt64ToUint64) { zero = builder.makeUint64Constant(0); - } else { + } else +#endif + { zero = builder.makeUintConstant(0); } zero = makeSmearedConstant(zero, vectorSize); @@ -5977,6 +6178,71 @@ spv::Id TGlslangToSpvTraverser::createConversion(glslang::TOperator op, OpDecora convOp = spv::OpConvertFToU; break; +#ifndef GLSLANG_WEB + case glslang::EOpConvInt8ToBool: + case glslang::EOpConvUint8ToBool: + zero = builder.makeUint8Constant(0); + zero = makeSmearedConstant(zero, vectorSize); + return builder.createBinOp(spv::OpINotEqual, destType, operand, zero); + case glslang::EOpConvInt16ToBool: + case glslang::EOpConvUint16ToBool: + zero = builder.makeUint16Constant(0); + zero = makeSmearedConstant(zero, vectorSize); + return builder.createBinOp(spv::OpINotEqual, destType, operand, zero); + case glslang::EOpConvInt64ToBool: + case glslang::EOpConvUint64ToBool: + zero = builder.makeUint64Constant(0); + zero = makeSmearedConstant(zero, vectorSize); + return builder.createBinOp(spv::OpINotEqual, destType, operand, zero); + case glslang::EOpConvDoubleToBool: + zero = builder.makeDoubleConstant(0.0); + zero = makeSmearedConstant(zero, vectorSize); + return builder.createBinOp(spv::OpFOrdNotEqual, destType, operand, zero); + case glslang::EOpConvFloat16ToBool: + zero = builder.makeFloat16Constant(0.0F); + zero = makeSmearedConstant(zero, vectorSize); + return builder.createBinOp(spv::OpFOrdNotEqual, destType, operand, zero); + case glslang::EOpConvBoolToDouble: + convOp = spv::OpSelect; + zero = builder.makeDoubleConstant(0.0); + one = builder.makeDoubleConstant(1.0); + break; + case glslang::EOpConvBoolToFloat16: + convOp = spv::OpSelect; + zero = builder.makeFloat16Constant(0.0F); + one = builder.makeFloat16Constant(1.0F); + break; + case glslang::EOpConvBoolToInt8: + zero = builder.makeInt8Constant(0); + one = builder.makeInt8Constant(1); + convOp = spv::OpSelect; + break; + case glslang::EOpConvBoolToUint8: + zero = builder.makeUint8Constant(0); + one = builder.makeUint8Constant(1); + convOp = spv::OpSelect; + break; + case glslang::EOpConvBoolToInt16: + zero = builder.makeInt16Constant(0); + one = builder.makeInt16Constant(1); + convOp = spv::OpSelect; + break; + case glslang::EOpConvBoolToUint16: + zero = builder.makeUint16Constant(0); + one = builder.makeUint16Constant(1); + convOp = spv::OpSelect; + break; + case glslang::EOpConvDoubleToFloat: + case glslang::EOpConvFloatToDouble: + case glslang::EOpConvDoubleToFloat16: + case glslang::EOpConvFloat16ToDouble: + case glslang::EOpConvFloatToFloat16: + case glslang::EOpConvFloat16ToFloat: + convOp = spv::OpFConvert; + if (builder.isMatrixType(destType)) + return createUnaryMatrixOperation(convOp, decorations, destType, operand, typeProxy); + break; + case glslang::EOpConvInt8ToInt16: case glslang::EOpConvInt8ToInt: case glslang::EOpConvInt8ToInt64: @@ -6087,6 +6353,15 @@ spv::Id TGlslangToSpvTraverser::createConversion(glslang::TOperator op, OpDecora case glslang::EOpConvPtrToUint64: convOp = spv::OpConvertPtrToU; break; + case glslang::EOpConvPtrToUvec2: + case glslang::EOpConvUvec2ToPtr: + if (builder.isVector(operand)) + builder.promoteIncorporatedExtension(spv::E_SPV_EXT_physical_storage_buffer, + spv::E_SPV_KHR_physical_storage_buffer, spv::Spv_1_5); + convOp = spv::OpBitcast; + break; +#endif + default: break; } @@ -6103,7 +6378,7 @@ spv::Id TGlslangToSpvTraverser::createConversion(glslang::TOperator op, OpDecora result = builder.createUnaryOp(convOp, destType, operand); result = builder.setPrecision(result, decorations.precision); - builder.addDecoration(result, decorations.nonUniform); + decorations.addNonUniform(builder, result); return result; } @@ -6120,7 +6395,7 @@ spv::Id TGlslangToSpvTraverser::makeSmearedConstant(spv::Id constant, int vector } // For glslang ops that map to SPV atomic opCodes -spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv::Decoration /*precision*/, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy) +spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv::Decoration /*precision*/, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy, const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags) { spv::Op opCode = spv::OpNop; @@ -6206,7 +6481,9 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv scopeId = builder.makeUintConstant(spv::ScopeDevice); } // semantics default to relaxed - spv::Id semanticsId = builder.makeUintConstant(spv::MemorySemanticsMaskNone); + spv::Id semanticsId = builder.makeUintConstant(lvalueCoherentFlags.isVolatile() && glslangIntermediate->usingVulkanMemoryModel() ? + spv::MemorySemanticsVolatileMask : + spv::MemorySemanticsMaskNone); spv::Id semanticsId2 = semanticsId; pointerId = operands[0]; @@ -6236,7 +6513,10 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv // Check for capabilities unsigned semanticsImmediate = builder.getConstantScalar(semanticsId) | builder.getConstantScalar(semanticsId2); - if (semanticsImmediate & (spv::MemorySemanticsMakeAvailableKHRMask | spv::MemorySemanticsMakeVisibleKHRMask | spv::MemorySemanticsOutputMemoryKHRMask)) { + if (semanticsImmediate & (spv::MemorySemanticsMakeAvailableKHRMask | + spv::MemorySemanticsMakeVisibleKHRMask | + spv::MemorySemanticsOutputMemoryKHRMask | + spv::MemorySemanticsVolatileMask)) { builder.addCapability(spv::CapabilityVulkanMemoryModelKHR); } @@ -6274,10 +6554,8 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv // Create group invocation operations. spv::Id TGlslangToSpvTraverser::createInvocationsOperation(glslang::TOperator op, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy) { -#ifdef AMD_EXTENSIONS bool isUnsigned = isTypeUnsignedInt(typeProxy); bool isFloat = isTypeFloat(typeProxy); -#endif spv::Op opCode = spv::OpNop; std::vector<spv::IdImmediate> spvGroupOperands; @@ -6294,7 +6572,6 @@ spv::Id TGlslangToSpvTraverser::createInvocationsOperation(glslang::TOperator op builder.addCapability(spv::CapabilitySubgroupVoteKHR); } else { builder.addCapability(spv::CapabilityGroups); -#ifdef AMD_EXTENSIONS if (op == glslang::EOpMinInvocationsNonUniform || op == glslang::EOpMaxInvocationsNonUniform || op == glslang::EOpAddInvocationsNonUniform || @@ -6305,9 +6582,7 @@ spv::Id TGlslangToSpvTraverser::createInvocationsOperation(glslang::TOperator op op == glslang::EOpMaxInvocationsExclusiveScanNonUniform || op == glslang::EOpAddInvocationsExclusiveScanNonUniform) builder.addExtension(spv::E_SPV_AMD_shader_ballot); -#endif -#ifdef AMD_EXTENSIONS switch (op) { case glslang::EOpMinInvocations: case glslang::EOpMaxInvocations: @@ -6342,7 +6617,6 @@ spv::Id TGlslangToSpvTraverser::createInvocationsOperation(glslang::TOperator op spv::IdImmediate groupOp = { false, (unsigned)groupOperation }; spvGroupOperands.push_back(groupOp); } -#endif } for (auto opIt = operands.begin(); opIt != operands.end(); ++opIt) { @@ -6389,7 +6663,6 @@ spv::Id TGlslangToSpvTraverser::createInvocationsOperation(glslang::TOperator op builder.createCompositeConstruct(uvec2Type, components)); } -#ifdef AMD_EXTENSIONS case glslang::EOpMinInvocations: case glslang::EOpMaxInvocations: case glslang::EOpAddInvocations: @@ -6476,7 +6749,6 @@ spv::Id TGlslangToSpvTraverser::createInvocationsOperation(glslang::TOperator op return CreateInvocationsVectorOperation(opCode, groupOperation, typeId, operands); break; -#endif default: logger->missingFunctionality("invocation operation"); return spv::NoResult; @@ -6490,7 +6762,6 @@ spv::Id TGlslangToSpvTraverser::createInvocationsOperation(glslang::TOperator op spv::Id TGlslangToSpvTraverser::CreateInvocationsVectorOperation(spv::Op op, spv::GroupOperation groupOperation, spv::Id typeId, std::vector<spv::Id>& operands) { -#ifdef AMD_EXTENSIONS assert(op == spv::OpGroupFMin || op == spv::OpGroupUMin || op == spv::OpGroupSMin || op == spv::OpGroupFMax || op == spv::OpGroupUMax || op == spv::OpGroupSMax || op == spv::OpGroupFAdd || op == spv::OpGroupIAdd || op == spv::OpGroupBroadcast || @@ -6498,12 +6769,6 @@ spv::Id TGlslangToSpvTraverser::CreateInvocationsVectorOperation(spv::Op op, spv op == spv::OpGroupFMinNonUniformAMD || op == spv::OpGroupUMinNonUniformAMD || op == spv::OpGroupSMinNonUniformAMD || op == spv::OpGroupFMaxNonUniformAMD || op == spv::OpGroupUMaxNonUniformAMD || op == spv::OpGroupSMaxNonUniformAMD || op == spv::OpGroupFAddNonUniformAMD || op == spv::OpGroupIAddNonUniformAMD); -#else - assert(op == spv::OpGroupFMin || op == spv::OpGroupUMin || op == spv::OpGroupSMin || - op == spv::OpGroupFMax || op == spv::OpGroupUMax || op == spv::OpGroupSMax || - op == spv::OpGroupFAdd || op == spv::OpGroupIAdd || op == spv::OpGroupBroadcast || - op == spv::OpSubgroupReadInvocationKHR); -#endif // Handle group invocation operations scalar by scalar. // The result type is the same type as the original type. @@ -6627,7 +6892,6 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s builder.addCapability(spv::CapabilityGroupNonUniform); builder.addCapability(spv::CapabilityGroupNonUniformQuad); break; -#ifdef NV_EXTENSIONS case glslang::EOpSubgroupPartitionedAdd: case glslang::EOpSubgroupPartitionedMul: case glslang::EOpSubgroupPartitionedMin: @@ -6652,12 +6916,12 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s builder.addExtension(spv::E_SPV_NV_shader_subgroup_partitioned); builder.addCapability(spv::CapabilityGroupNonUniformPartitionedNV); break; -#endif default: assert(0 && "Unhandled subgroup operation!"); } - const bool isUnsigned = typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64; - const bool isFloat = typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble; + + const bool isUnsigned = isTypeUnsignedInt(typeProxy); + const bool isFloat = isTypeFloat(typeProxy); const bool isBool = typeProxy == glslang::EbtBool; spv::Op opCode = spv::OpNop; @@ -6686,11 +6950,9 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s case glslang::EOpSubgroupInclusiveAdd: case glslang::EOpSubgroupExclusiveAdd: case glslang::EOpSubgroupClusteredAdd: -#ifdef NV_EXTENSIONS case glslang::EOpSubgroupPartitionedAdd: case glslang::EOpSubgroupPartitionedInclusiveAdd: case glslang::EOpSubgroupPartitionedExclusiveAdd: -#endif if (isFloat) { opCode = spv::OpGroupNonUniformFAdd; } else { @@ -6701,11 +6963,9 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s case glslang::EOpSubgroupInclusiveMul: case glslang::EOpSubgroupExclusiveMul: case glslang::EOpSubgroupClusteredMul: -#ifdef NV_EXTENSIONS case glslang::EOpSubgroupPartitionedMul: case glslang::EOpSubgroupPartitionedInclusiveMul: case glslang::EOpSubgroupPartitionedExclusiveMul: -#endif if (isFloat) { opCode = spv::OpGroupNonUniformFMul; } else { @@ -6716,11 +6976,9 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s case glslang::EOpSubgroupInclusiveMin: case glslang::EOpSubgroupExclusiveMin: case glslang::EOpSubgroupClusteredMin: -#ifdef NV_EXTENSIONS case glslang::EOpSubgroupPartitionedMin: case glslang::EOpSubgroupPartitionedInclusiveMin: case glslang::EOpSubgroupPartitionedExclusiveMin: -#endif if (isFloat) { opCode = spv::OpGroupNonUniformFMin; } else if (isUnsigned) { @@ -6733,11 +6991,9 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s case glslang::EOpSubgroupInclusiveMax: case glslang::EOpSubgroupExclusiveMax: case glslang::EOpSubgroupClusteredMax: -#ifdef NV_EXTENSIONS case glslang::EOpSubgroupPartitionedMax: case glslang::EOpSubgroupPartitionedInclusiveMax: case glslang::EOpSubgroupPartitionedExclusiveMax: -#endif if (isFloat) { opCode = spv::OpGroupNonUniformFMax; } else if (isUnsigned) { @@ -6750,11 +7006,9 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s case glslang::EOpSubgroupInclusiveAnd: case glslang::EOpSubgroupExclusiveAnd: case glslang::EOpSubgroupClusteredAnd: -#ifdef NV_EXTENSIONS case glslang::EOpSubgroupPartitionedAnd: case glslang::EOpSubgroupPartitionedInclusiveAnd: case glslang::EOpSubgroupPartitionedExclusiveAnd: -#endif if (isBool) { opCode = spv::OpGroupNonUniformLogicalAnd; } else { @@ -6765,11 +7019,9 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s case glslang::EOpSubgroupInclusiveOr: case glslang::EOpSubgroupExclusiveOr: case glslang::EOpSubgroupClusteredOr: -#ifdef NV_EXTENSIONS case glslang::EOpSubgroupPartitionedOr: case glslang::EOpSubgroupPartitionedInclusiveOr: case glslang::EOpSubgroupPartitionedExclusiveOr: -#endif if (isBool) { opCode = spv::OpGroupNonUniformLogicalOr; } else { @@ -6780,11 +7032,9 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s case glslang::EOpSubgroupInclusiveXor: case glslang::EOpSubgroupExclusiveXor: case glslang::EOpSubgroupClusteredXor: -#ifdef NV_EXTENSIONS case glslang::EOpSubgroupPartitionedXor: case glslang::EOpSubgroupPartitionedInclusiveXor: case glslang::EOpSubgroupPartitionedExclusiveXor: -#endif if (isBool) { opCode = spv::OpGroupNonUniformLogicalXor; } else { @@ -6842,7 +7092,6 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s case glslang::EOpSubgroupClusteredXor: groupOperation = spv::GroupOperationClusteredReduce; break; -#ifdef NV_EXTENSIONS case glslang::EOpSubgroupPartitionedAdd: case glslang::EOpSubgroupPartitionedMul: case glslang::EOpSubgroupPartitionedMin: @@ -6870,7 +7119,6 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s case glslang::EOpSubgroupPartitionedExclusiveXor: groupOperation = spv::GroupOperationPartitionedExclusiveScanNV; break; -#endif } // build the instruction @@ -6928,7 +7176,7 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv:: switch (op) { case glslang::EOpMin: if (isFloat) - libCall = spv::GLSLstd450FMin; + libCall = nanMinMaxClamp ? spv::GLSLstd450NMin : spv::GLSLstd450FMin; else if (isUnsigned) libCall = spv::GLSLstd450UMin; else @@ -6940,7 +7188,7 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv:: break; case glslang::EOpMax: if (isFloat) - libCall = spv::GLSLstd450FMax; + libCall = nanMinMaxClamp ? spv::GLSLstd450NMax : spv::GLSLstd450FMax; else if (isUnsigned) libCall = spv::GLSLstd450UMax; else @@ -6959,7 +7207,7 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv:: case glslang::EOpClamp: if (isFloat) - libCall = spv::GLSLstd450FClamp; + libCall = nanMinMaxClamp ? spv::GLSLstd450NClamp : spv::GLSLstd450FClamp; else if (isUnsigned) libCall = spv::GLSLstd450UClamp; else @@ -7002,18 +7250,57 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv:: case glslang::EOpRefract: libCall = spv::GLSLstd450Refract; break; + case glslang::EOpBarrier: + { + // This is for the extended controlBarrier function, with four operands. + // The unextended barrier() goes through createNoArgOperation. + assert(operands.size() == 4); + unsigned int executionScope = builder.getConstantScalar(operands[0]); + unsigned int memoryScope = builder.getConstantScalar(operands[1]); + unsigned int semantics = builder.getConstantScalar(operands[2]) | builder.getConstantScalar(operands[3]); + builder.createControlBarrier((spv::Scope)executionScope, (spv::Scope)memoryScope, (spv::MemorySemanticsMask)semantics); + if (semantics & (spv::MemorySemanticsMakeAvailableKHRMask | + spv::MemorySemanticsMakeVisibleKHRMask | + spv::MemorySemanticsOutputMemoryKHRMask | + spv::MemorySemanticsVolatileMask)) { + builder.addCapability(spv::CapabilityVulkanMemoryModelKHR); + } + if (glslangIntermediate->usingVulkanMemoryModel() && (executionScope == spv::ScopeDevice || memoryScope == spv::ScopeDevice)) { + builder.addCapability(spv::CapabilityVulkanMemoryModelDeviceScopeKHR); + } + return 0; + } + break; + case glslang::EOpMemoryBarrier: + { + // This is for the extended memoryBarrier function, with three operands. + // The unextended memoryBarrier() goes through createNoArgOperation. + assert(operands.size() == 3); + unsigned int memoryScope = builder.getConstantScalar(operands[0]); + unsigned int semantics = builder.getConstantScalar(operands[1]) | builder.getConstantScalar(operands[2]); + builder.createMemoryBarrier((spv::Scope)memoryScope, (spv::MemorySemanticsMask)semantics); + if (semantics & (spv::MemorySemanticsMakeAvailableKHRMask | + spv::MemorySemanticsMakeVisibleKHRMask | + spv::MemorySemanticsOutputMemoryKHRMask | + spv::MemorySemanticsVolatileMask)) { + builder.addCapability(spv::CapabilityVulkanMemoryModelKHR); + } + if (glslangIntermediate->usingVulkanMemoryModel() && memoryScope == spv::ScopeDevice) { + builder.addCapability(spv::CapabilityVulkanMemoryModelDeviceScopeKHR); + } + return 0; + } + break; + +#ifndef GLSLANG_WEB case glslang::EOpInterpolateAtSample: -#ifdef AMD_EXTENSIONS if (typeProxy == glslang::EbtFloat16) builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float); -#endif libCall = spv::GLSLstd450InterpolateAtSample; break; case glslang::EOpInterpolateAtOffset: -#ifdef AMD_EXTENSIONS if (typeProxy == glslang::EbtFloat16) builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float); -#endif libCall = spv::GLSLstd450InterpolateAtOffset; break; case glslang::EOpAddCarry: @@ -7055,11 +7342,9 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv:: assert(builder.isPointerType(typeId1)); typeId1 = builder.getContainedTypeId(typeId1); int width = builder.getScalarTypeWidth(typeId1); -#ifdef AMD_EXTENSIONS if (width == 16) // Using 16-bit exp operand, enable extension SPV_AMD_gpu_shader_int16 builder.addExtension(spv::E_SPV_AMD_gpu_shader_int16); -#endif if (builder.getNumComponents(operands[0]) == 1) frexpIntType = builder.makeIntegerType(width, true); else @@ -7089,7 +7374,6 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv:: case glslang::EOpSubgroupClusteredOr: case glslang::EOpSubgroupClusteredXor: case glslang::EOpSubgroupQuadBroadcast: -#ifdef NV_EXTENSIONS case glslang::EOpSubgroupPartitionedAdd: case glslang::EOpSubgroupPartitionedMul: case glslang::EOpSubgroupPartitionedMin: @@ -7111,10 +7395,8 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv:: case glslang::EOpSubgroupPartitionedExclusiveAnd: case glslang::EOpSubgroupPartitionedExclusiveOr: case glslang::EOpSubgroupPartitionedExclusiveXor: -#endif return createSubgroupOperation(op, typeId, operands, typeProxy); -#ifdef AMD_EXTENSIONS case glslang::EOpSwizzleInvocations: extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_ballot); libCall = spv::SwizzleInvocationsAMD; @@ -7168,44 +7450,7 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv:: extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_explicit_vertex_parameter); libCall = spv::InterpolateAtVertexAMD; break; -#endif - case glslang::EOpBarrier: - { - // This is for the extended controlBarrier function, with four operands. - // The unextended barrier() goes through createNoArgOperation. - assert(operands.size() == 4); - unsigned int executionScope = builder.getConstantScalar(operands[0]); - unsigned int memoryScope = builder.getConstantScalar(operands[1]); - unsigned int semantics = builder.getConstantScalar(operands[2]) | builder.getConstantScalar(operands[3]); - builder.createControlBarrier((spv::Scope)executionScope, (spv::Scope)memoryScope, (spv::MemorySemanticsMask)semantics); - if (semantics & (spv::MemorySemanticsMakeAvailableKHRMask | spv::MemorySemanticsMakeVisibleKHRMask | spv::MemorySemanticsOutputMemoryKHRMask)) { - builder.addCapability(spv::CapabilityVulkanMemoryModelKHR); - } - if (glslangIntermediate->usingVulkanMemoryModel() && (executionScope == spv::ScopeDevice || memoryScope == spv::ScopeDevice)) { - builder.addCapability(spv::CapabilityVulkanMemoryModelDeviceScopeKHR); - } - return 0; - } - break; - case glslang::EOpMemoryBarrier: - { - // This is for the extended memoryBarrier function, with three operands. - // The unextended memoryBarrier() goes through createNoArgOperation. - assert(operands.size() == 3); - unsigned int memoryScope = builder.getConstantScalar(operands[0]); - unsigned int semantics = builder.getConstantScalar(operands[1]) | builder.getConstantScalar(operands[2]); - builder.createMemoryBarrier((spv::Scope)memoryScope, (spv::MemorySemanticsMask)semantics); - if (semantics & (spv::MemorySemanticsMakeAvailableKHRMask | spv::MemorySemanticsMakeVisibleKHRMask | spv::MemorySemanticsOutputMemoryKHRMask)) { - builder.addCapability(spv::CapabilityVulkanMemoryModelKHR); - } - if (glslangIntermediate->usingVulkanMemoryModel() && memoryScope == spv::ScopeDevice) { - builder.addCapability(spv::CapabilityVulkanMemoryModelDeviceScopeKHR); - } - return 0; - } - break; -#ifdef NV_EXTENSIONS case glslang::EOpReportIntersectionNV: { typeId = builder.makeBoolType(); @@ -7227,11 +7472,10 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv:: case glslang::EOpWritePackedPrimitiveIndices4x8NV: builder.createNoResultOp(spv::OpWritePackedPrimitiveIndices4x8NV, operands); return 0; -#endif case glslang::EOpCooperativeMatrixMulAdd: opCode = spv::OpCooperativeMatrixMulAddNV; break; - +#endif // GLSLANG_WEB default: return 0; } @@ -7252,7 +7496,7 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv:: id = builder.createCompositeExtract(mulOp, typeId, 0); for (int i = 1; i < componentCount; ++i) { builder.setPrecision(id, precision); - id = builder.createBinOp(spv::OpIAdd, typeId, id, builder.createCompositeExtract(operands[0], typeId, i)); + id = builder.createBinOp(spv::OpIAdd, typeId, id, builder.createCompositeExtract(mulOp, typeId, i)); } } else { switch (consumedOperands) { @@ -7275,6 +7519,7 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv:: } } +#ifndef GLSLANG_WEB // Decode the return types that were structures switch (op) { case glslang::EOpAddCarry: @@ -7304,6 +7549,7 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv:: default: break; } +#endif return builder.setPrecision(id, precision); } @@ -7315,12 +7561,6 @@ spv::Id TGlslangToSpvTraverser::createNoArgOperation(glslang::TOperator op, spv: spv::Scope memoryBarrierScope = glslangIntermediate->usingVulkanMemoryModel() ? spv::ScopeQueueFamilyKHR : spv::ScopeDevice; switch (op) { - case glslang::EOpEmitVertex: - builder.createNoResultOp(spv::OpEmitVertex); - return 0; - case glslang::EOpEndPrimitive: - builder.createNoResultOp(spv::OpEndPrimitive); - return 0; case glslang::EOpBarrier: if (glslangIntermediate->getStage() == EShLangTessControl) { if (glslangIntermediate->usingVulkanMemoryModel()) { @@ -7341,18 +7581,10 @@ spv::Id TGlslangToSpvTraverser::createNoArgOperation(glslang::TOperator op, spv: builder.createMemoryBarrier(memoryBarrierScope, spv::MemorySemanticsAllMemory | spv::MemorySemanticsAcquireReleaseMask); return 0; - case glslang::EOpMemoryBarrierAtomicCounter: - builder.createMemoryBarrier(memoryBarrierScope, spv::MemorySemanticsAtomicCounterMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return 0; case glslang::EOpMemoryBarrierBuffer: builder.createMemoryBarrier(memoryBarrierScope, spv::MemorySemanticsUniformMemoryMask | spv::MemorySemanticsAcquireReleaseMask); return 0; - case glslang::EOpMemoryBarrierImage: - builder.createMemoryBarrier(memoryBarrierScope, spv::MemorySemanticsImageMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return 0; case glslang::EOpMemoryBarrierShared: builder.createMemoryBarrier(memoryBarrierScope, spv::MemorySemanticsWorkgroupMemoryMask | spv::MemorySemanticsAcquireReleaseMask); @@ -7361,6 +7593,15 @@ spv::Id TGlslangToSpvTraverser::createNoArgOperation(glslang::TOperator op, spv: builder.createMemoryBarrier(spv::ScopeWorkgroup, spv::MemorySemanticsAllMemory | spv::MemorySemanticsAcquireReleaseMask); return 0; +#ifndef GLSLANG_WEB + case glslang::EOpMemoryBarrierAtomicCounter: + builder.createMemoryBarrier(memoryBarrierScope, spv::MemorySemanticsAtomicCounterMemoryMask | + spv::MemorySemanticsAcquireReleaseMask); + return 0; + case glslang::EOpMemoryBarrierImage: + builder.createMemoryBarrier(memoryBarrierScope, spv::MemorySemanticsImageMemoryMask | + spv::MemorySemanticsAcquireReleaseMask); + return 0; case glslang::EOpAllMemoryBarrierWithGroupSync: builder.createControlBarrier(spv::ScopeWorkgroup, spv::ScopeDevice, spv::MemorySemanticsAllMemory | @@ -7405,30 +7646,69 @@ spv::Id TGlslangToSpvTraverser::createNoArgOperation(glslang::TOperator op, spv: builder.createMemoryBarrier(spv::ScopeSubgroup, spv::MemorySemanticsWorkgroupMemoryMask | spv::MemorySemanticsAcquireReleaseMask); return spv::NoResult; + + case glslang::EOpEmitVertex: + builder.createNoResultOp(spv::OpEmitVertex); + return 0; + case glslang::EOpEndPrimitive: + builder.createNoResultOp(spv::OpEndPrimitive); + return 0; + case glslang::EOpSubgroupElect: { std::vector<spv::Id> operands; return createSubgroupOperation(op, typeId, operands, glslang::EbtVoid); } -#ifdef AMD_EXTENSIONS case glslang::EOpTime: { std::vector<spv::Id> args; // Dummy arguments spv::Id id = builder.createBuiltinCall(typeId, getExtBuiltins(spv::E_SPV_AMD_gcn_shader), spv::TimeAMD, args); return builder.setPrecision(id, precision); } -#endif -#ifdef NV_EXTENSIONS case glslang::EOpIgnoreIntersectionNV: builder.createNoResultOp(spv::OpIgnoreIntersectionNV); return 0; case glslang::EOpTerminateRayNV: builder.createNoResultOp(spv::OpTerminateRayNV); return 0; + + case glslang::EOpBeginInvocationInterlock: + builder.createNoResultOp(spv::OpBeginInvocationInterlockEXT); + return 0; + case glslang::EOpEndInvocationInterlock: + builder.createNoResultOp(spv::OpEndInvocationInterlockEXT); + return 0; + + case glslang::EOpIsHelperInvocation: + { + std::vector<spv::Id> args; // Dummy arguments + builder.addExtension(spv::E_SPV_EXT_demote_to_helper_invocation); + builder.addCapability(spv::CapabilityDemoteToHelperInvocationEXT); + return builder.createOp(spv::OpIsHelperInvocationEXT, typeId, args); + } + + case glslang::EOpReadClockSubgroupKHR: { + std::vector<spv::Id> args; + args.push_back(builder.makeUintConstant(spv::ScopeSubgroup)); + builder.addExtension(spv::E_SPV_KHR_shader_clock); + builder.addCapability(spv::CapabilityShaderClockKHR); + return builder.createOp(spv::OpReadClockKHR, typeId, args); + } + + case glslang::EOpReadClockDeviceKHR: { + std::vector<spv::Id> args; + args.push_back(builder.makeUintConstant(spv::ScopeDevice)); + builder.addExtension(spv::E_SPV_KHR_shader_clock); + builder.addCapability(spv::CapabilityShaderClockKHR); + return builder.createOp(spv::OpReadClockKHR, typeId, args); + } #endif default: - logger->missingFunctionality("unknown operation with no arguments"); - return 0; + break; } + + logger->missingFunctionality("unknown operation with no arguments"); + + return 0; } spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol) @@ -7441,22 +7721,26 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol } // it was not found, create it - id = createSpvVariable(symbol); + spv::BuiltIn builtIn = TranslateBuiltInDecoration(symbol->getQualifier().builtIn, false); + auto forcedType = getForcedType(builtIn, symbol->getType()); + id = createSpvVariable(symbol, forcedType.first); symbolValues[symbol->getId()] = id; + if (forcedType.second != spv::NoType) + forceType[id] = forcedType.second; if (symbol->getBasicType() != glslang::EbtBlock) { builder.addDecoration(id, TranslatePrecisionDecoration(symbol->getType())); builder.addDecoration(id, TranslateInterpolationDecoration(symbol->getType().getQualifier())); builder.addDecoration(id, TranslateAuxiliaryStorageDecoration(symbol->getType().getQualifier())); -#ifdef NV_EXTENSIONS +#ifndef GLSLANG_WEB addMeshNVDecoration(id, /*member*/ -1, symbol->getType().getQualifier()); + if (symbol->getQualifier().hasComponent()) + builder.addDecoration(id, spv::DecorationComponent, symbol->getQualifier().layoutComponent); + if (symbol->getQualifier().hasIndex()) + builder.addDecoration(id, spv::DecorationIndex, symbol->getQualifier().layoutIndex); #endif if (symbol->getType().getQualifier().hasSpecConstantId()) builder.addDecoration(id, spv::DecorationSpecId, symbol->getType().getQualifier().layoutSpecConstantId); - if (symbol->getQualifier().hasIndex()) - builder.addDecoration(id, spv::DecorationIndex, symbol->getQualifier().layoutIndex); - if (symbol->getQualifier().hasComponent()) - builder.addDecoration(id, spv::DecorationComponent, symbol->getQualifier().layoutComponent); // atomic counters use this: if (symbol->getQualifier().hasOffset()) builder.addDecoration(id, spv::DecorationOffset, symbol->getQualifier().layoutOffset); @@ -7495,6 +7779,12 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol builder.addDecoration(id, spv::DecorationOffset, symbol->getQualifier().layoutXfbOffset); } + // add built-in variable decoration + if (builtIn != spv::BuiltInMax) { + builder.addDecoration(id, spv::DecorationBuiltIn, (int)builtIn); + } + +#ifndef GLSLANG_WEB if (symbol->getType().isImage()) { std::vector<spv::Decoration> memory; TranslateMemoryDecoration(symbol->getType().getQualifier(), memory, glslangIntermediate->usingVulkanMemoryModel()); @@ -7502,15 +7792,9 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol builder.addDecoration(id, memory[i]); } - // built-in variable decorations - spv::BuiltIn builtIn = TranslateBuiltInDecoration(symbol->getQualifier().builtIn, false); - if (builtIn != spv::BuiltInMax) - builder.addDecoration(id, spv::DecorationBuiltIn, (int)builtIn); - // nonuniform builder.addDecoration(id, TranslateNonUniformDecoration(symbol->getType().getQualifier())); -#ifdef NV_EXTENSIONS if (builtIn == spv::BuiltInSampleMask) { spv::Decoration decoration; // GL_NV_sample_mask_override_coverage extension @@ -7520,6 +7804,7 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol decoration = (spv::Decoration)spv::DecorationMax; builder.addDecoration(id, decoration); if (decoration != spv::DecorationMax) { + builder.addCapability(spv::CapabilitySampleMaskOverrideCoverageNV); builder.addExtension(spv::E_SPV_NV_sample_mask_override_coverage); } } @@ -7548,7 +7833,6 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol builder.addCapability(spv::CapabilityFragmentBarycentricNV); builder.addExtension(spv::E_SPV_NV_fragment_shader_barycentric); } -#endif if (glslangIntermediate->getHlslFunctionality1() && symbol->getType().getQualifier().semanticName != nullptr) { builder.addExtension("SPV_GOOGLE_hlsl_functionality1"); @@ -7556,14 +7840,15 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol symbol->getType().getQualifier().semanticName); } - if (symbol->getBasicType() == glslang::EbtReference) { + if (symbol->isReference()) { builder.addDecoration(id, symbol->getType().getQualifier().restrict ? spv::DecorationRestrictPointerEXT : spv::DecorationAliasedPointerEXT); } +#endif return id; } -#ifdef NV_EXTENSIONS +#ifndef GLSLANG_WEB // add per-primitive, per-view. per-task decorations to a struct member (member >= 0) or an object void TGlslangToSpvTraverser::addMeshNVDecoration(spv::Id id, int member, const glslang::TQualifier& qualifier) { @@ -7699,6 +7984,19 @@ spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glsla for (unsigned int i = 0; i < (unsigned int)glslangType.getVectorSize(); ++i) { bool zero = nextConst >= consts.size(); switch (glslangType.getBasicType()) { + case glslang::EbtInt: + spvConsts.push_back(builder.makeIntConstant(zero ? 0 : consts[nextConst].getIConst())); + break; + case glslang::EbtUint: + spvConsts.push_back(builder.makeUintConstant(zero ? 0 : consts[nextConst].getUConst())); + break; + case glslang::EbtFloat: + spvConsts.push_back(builder.makeFloatConstant(zero ? 0.0F : (float)consts[nextConst].getDConst())); + break; + case glslang::EbtBool: + spvConsts.push_back(builder.makeBoolConstant(zero ? false : consts[nextConst].getBConst())); + break; +#ifndef GLSLANG_WEB case glslang::EbtInt8: spvConsts.push_back(builder.makeInt8Constant(zero ? 0 : consts[nextConst].getI8Const())); break; @@ -7711,30 +8009,19 @@ spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glsla case glslang::EbtUint16: spvConsts.push_back(builder.makeUint16Constant(zero ? 0 : consts[nextConst].getU16Const())); break; - case glslang::EbtInt: - spvConsts.push_back(builder.makeIntConstant(zero ? 0 : consts[nextConst].getIConst())); - break; - case glslang::EbtUint: - spvConsts.push_back(builder.makeUintConstant(zero ? 0 : consts[nextConst].getUConst())); - break; case glslang::EbtInt64: spvConsts.push_back(builder.makeInt64Constant(zero ? 0 : consts[nextConst].getI64Const())); break; case glslang::EbtUint64: spvConsts.push_back(builder.makeUint64Constant(zero ? 0 : consts[nextConst].getU64Const())); break; - case glslang::EbtFloat: - spvConsts.push_back(builder.makeFloatConstant(zero ? 0.0F : (float)consts[nextConst].getDConst())); - break; case glslang::EbtDouble: spvConsts.push_back(builder.makeDoubleConstant(zero ? 0.0 : consts[nextConst].getDConst())); break; case glslang::EbtFloat16: spvConsts.push_back(builder.makeFloat16Constant(zero ? 0.0F : (float)consts[nextConst].getDConst())); break; - case glslang::EbtBool: - spvConsts.push_back(builder.makeBoolConstant(zero ? false : consts[nextConst].getBConst())); - break; +#endif default: assert(0); break; @@ -7746,6 +8033,19 @@ spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glsla bool zero = nextConst >= consts.size(); spv::Id scalar = 0; switch (glslangType.getBasicType()) { + case glslang::EbtInt: + scalar = builder.makeIntConstant(zero ? 0 : consts[nextConst].getIConst(), specConstant); + break; + case glslang::EbtUint: + scalar = builder.makeUintConstant(zero ? 0 : consts[nextConst].getUConst(), specConstant); + break; + case glslang::EbtFloat: + scalar = builder.makeFloatConstant(zero ? 0.0F : (float)consts[nextConst].getDConst(), specConstant); + break; + case glslang::EbtBool: + scalar = builder.makeBoolConstant(zero ? false : consts[nextConst].getBConst(), specConstant); + break; +#ifndef GLSLANG_WEB case glslang::EbtInt8: scalar = builder.makeInt8Constant(zero ? 0 : consts[nextConst].getI8Const(), specConstant); break; @@ -7758,34 +8058,23 @@ spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glsla case glslang::EbtUint16: scalar = builder.makeUint16Constant(zero ? 0 : consts[nextConst].getU16Const(), specConstant); break; - case glslang::EbtInt: - scalar = builder.makeIntConstant(zero ? 0 : consts[nextConst].getIConst(), specConstant); - break; - case glslang::EbtUint: - scalar = builder.makeUintConstant(zero ? 0 : consts[nextConst].getUConst(), specConstant); - break; case glslang::EbtInt64: scalar = builder.makeInt64Constant(zero ? 0 : consts[nextConst].getI64Const(), specConstant); break; case glslang::EbtUint64: scalar = builder.makeUint64Constant(zero ? 0 : consts[nextConst].getU64Const(), specConstant); break; - case glslang::EbtFloat: - scalar = builder.makeFloatConstant(zero ? 0.0F : (float)consts[nextConst].getDConst(), specConstant); - break; case glslang::EbtDouble: scalar = builder.makeDoubleConstant(zero ? 0.0 : consts[nextConst].getDConst(), specConstant); break; case glslang::EbtFloat16: scalar = builder.makeFloat16Constant(zero ? 0.0F : (float)consts[nextConst].getDConst(), specConstant); break; - case glslang::EbtBool: - scalar = builder.makeBoolConstant(zero ? false : consts[nextConst].getBConst(), specConstant); - break; case glslang::EbtReference: scalar = builder.makeUint64Constant(zero ? 0 : consts[nextConst].getU64Const(), specConstant); scalar = builder.createUnaryOp(spv::OpBitcast, typeId, scalar); break; +#endif default: assert(0); break; @@ -7929,7 +8218,7 @@ spv::Id TGlslangToSpvTraverser::createShortCircuit(glslang::TOperator op, glslan return builder.createOp(spv::OpPhi, boolTypeId, phiOperands); } -#ifdef AMD_EXTENSIONS +#ifndef GLSLANG_WEB // Return type Id of the imported set of extended instructions corresponds to the name. // Import this set if it has not been imported yet. spv::Id TGlslangToSpvTraverser::getExtBuiltins(const char* name) @@ -7969,7 +8258,8 @@ int GetSpirvGeneratorVersion() // return 5; // make OpArrayLength result type be an int with signedness of 0 // return 6; // revert version 5 change, which makes a different (new) kind of incorrect code, // versions 4 and 6 each generate OpArrayLength as it has long been done - return 7; // GLSL volatile keyword maps to both SPIR-V decorations Volatile and Coherent + // return 7; // GLSL volatile keyword maps to both SPIR-V decorations Volatile and Coherent + return 8; // switch to new dead block eliminator; use OpUnreachable } // Write SPIR-V out to a binary file @@ -7989,6 +8279,7 @@ void OutputSpvBin(const std::vector<unsigned int>& spirv, const char* baseName) // Write SPIR-V out to a text file with 32-bit hexadecimal words void OutputSpvHex(const std::vector<unsigned int>& spirv, const char* baseName, const char* varName) { +#ifndef GLSLANG_WEB std::ofstream out; out.open(baseName, std::ios::binary | std::ios::out); if (out.fail()) @@ -8016,6 +8307,7 @@ void OutputSpvHex(const std::vector<unsigned int>& spirv, const char* baseName, out << "};"; } out.close(); +#endif } // @@ -8049,11 +8341,14 @@ void GlslangToSpv(const TIntermediate& intermediate, std::vector<unsigned int>& #if ENABLE_OPT // If from HLSL, run spirv-opt to "legalize" the SPIR-V for Vulkan // eg. forward and remove memory writes of opaque types. - if ((intermediate.getSource() == EShSourceHlsl || options->optimizeSize) && !options->disableOptimizer) + bool prelegalization = intermediate.getSource() == EShSourceHlsl; + if ((intermediate.getSource() == EShSourceHlsl || options->optimizeSize) && !options->disableOptimizer) { SpirvToolsLegalize(intermediate, spirv, logger, options); + prelegalization = false; + } if (options->validate) - SpirvToolsValidate(intermediate, spirv, logger); + SpirvToolsValidate(intermediate, spirv, logger, prelegalization); if (options->disassemble) SpirvToolsDisassemble(std::cout, spirv); |