Pārlūkot izejas kodu

Updated glslang.

Бранимир Караџић 4 gadi atpakaļ
vecāks
revīzija
6538544f2f
31 mainītis faili ar 2911 papildinājumiem un 688 dzēšanām
  1. 12 0
      3rdparty/glslang/CHANGES.md
  2. 2 0
      3rdparty/glslang/SPIRV/GLSL.ext.EXT.h
  3. 1 0
      3rdparty/glslang/SPIRV/GLSL.ext.KHR.h
  4. 414 22
      3rdparty/glslang/SPIRV/GlslangToSpv.cpp
  5. 3 0
      3rdparty/glslang/SPIRV/SPVRemapper.cpp
  6. 17 0
      3rdparty/glslang/SPIRV/doc.cpp
  7. 21 6
      3rdparty/glslang/SPIRV/spirv.hpp
  8. 1 1
      3rdparty/glslang/build_info.h
  9. 10 0
      3rdparty/glslang/glslang/Include/BaseTypes.h
  10. 4 0
      3rdparty/glslang/glslang/Include/Common.h
  11. 136 0
      3rdparty/glslang/glslang/Include/SpirvIntrinsics.h
  12. 112 4
      3rdparty/glslang/glslang/Include/Types.h
  13. 17 0
      3rdparty/glslang/glslang/Include/intermediate.h
  14. 43 2
      3rdparty/glslang/glslang/MachineIndependent/Initialize.cpp
  15. 176 15
      3rdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp
  16. 16 0
      3rdparty/glslang/glslang/MachineIndependent/ParseHelper.h
  17. 27 0
      3rdparty/glslang/glslang/MachineIndependent/Scan.cpp
  18. 355 0
      3rdparty/glslang/glslang/MachineIndependent/SpirvIntrinsics.cpp
  19. 4 0
      3rdparty/glslang/glslang/MachineIndependent/SymbolTable.cpp
  20. 13 0
      3rdparty/glslang/glslang/MachineIndependent/SymbolTable.h
  21. 30 0
      3rdparty/glslang/glslang/MachineIndependent/Versions.cpp
  22. 3 0
      3rdparty/glslang/glslang/MachineIndependent/Versions.h
  23. 25 0
      3rdparty/glslang/glslang/MachineIndependent/attribute.cpp
  24. 2 1
      3rdparty/glslang/glslang/MachineIndependent/attribute.h
  25. 349 1
      3rdparty/glslang/glslang/MachineIndependent/glslang.m4
  26. 349 1
      3rdparty/glslang/glslang/MachineIndependent/glslang.y
  27. 592 503
      3rdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp
  28. 142 129
      3rdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp.h
  29. 11 0
      3rdparty/glslang/glslang/MachineIndependent/intermOut.cpp
  30. 19 0
      3rdparty/glslang/glslang/MachineIndependent/localintermediate.h
  31. 5 3
      3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp

+ 12 - 0
3rdparty/glslang/CHANGES.md

@@ -3,6 +3,18 @@
 All notable changes to this project will be documented in this file.
 All notable changes to this project will be documented in this file.
 This project adheres to [Semantic Versioning](https://semver.org/).
 This project adheres to [Semantic Versioning](https://semver.org/).
 
 
+## 11.5.0 2021-06-23
+
+### Other changes
+* Implement GLSL_EXT_shader_atomic_float2
+* Implement GL_EXT_spirv_intrinsics
+* Fixed SPIR-V remapper not remapping OpExtInst instruction set IDs
+* only declare compatibility gl_ variables in compatibility mode
+* Add support for float spec const vector initialization
+* Implement GL_EXT_subgroup_uniform_control_flow.
+* Fix arrays dimensioned with spec constant sized gl_WorkGroupSize
+* Add support for 64bit integer scalar and vector types to bitCount() builtin
+
 ## 11.4.0 2021-04-22
 ## 11.4.0 2021-04-22
 
 
 ### Other changes
 ### Other changes

+ 2 - 0
3rdparty/glslang/SPIRV/GLSL.ext.EXT.h

@@ -36,6 +36,8 @@ static const char* const E_SPV_EXT_fragment_fully_covered = "SPV_EXT_fragment_fu
 static const char* const E_SPV_EXT_fragment_invocation_density = "SPV_EXT_fragment_invocation_density";
 static const char* const E_SPV_EXT_fragment_invocation_density = "SPV_EXT_fragment_invocation_density";
 static const char* const E_SPV_EXT_demote_to_helper_invocation = "SPV_EXT_demote_to_helper_invocation";
 static const char* const E_SPV_EXT_demote_to_helper_invocation = "SPV_EXT_demote_to_helper_invocation";
 static const char* const E_SPV_EXT_shader_atomic_float_add = "SPV_EXT_shader_atomic_float_add";
 static const char* const E_SPV_EXT_shader_atomic_float_add = "SPV_EXT_shader_atomic_float_add";
+static const char* const E_SPV_EXT_shader_atomic_float16_add = "SPV_EXT_shader_atomic_float16_add";
+static const char* const E_SPV_EXT_shader_atomic_float_min_max = "SPV_EXT_shader_atomic_float_min_max";
 static const char* const E_SPV_EXT_shader_image_int64 = "SPV_EXT_shader_image_int64";
 static const char* const E_SPV_EXT_shader_image_int64 = "SPV_EXT_shader_image_int64";
 
 
 #endif  // #ifndef GLSLextEXT_H
 #endif  // #ifndef GLSLextEXT_H

+ 1 - 0
3rdparty/glslang/SPIRV/GLSL.ext.KHR.h

@@ -51,5 +51,6 @@ static const char* const E_SPV_KHR_ray_query                    = "SPV_KHR_ray_q
 static const char* const E_SPV_KHR_fragment_shading_rate        = "SPV_KHR_fragment_shading_rate";
 static const char* const E_SPV_KHR_fragment_shading_rate        = "SPV_KHR_fragment_shading_rate";
 static const char* const E_SPV_KHR_terminate_invocation         = "SPV_KHR_terminate_invocation";
 static const char* const E_SPV_KHR_terminate_invocation         = "SPV_KHR_terminate_invocation";
 static const char* const E_SPV_KHR_workgroup_memory_explicit_layout = "SPV_KHR_workgroup_memory_explicit_layout";
 static const char* const E_SPV_KHR_workgroup_memory_explicit_layout = "SPV_KHR_workgroup_memory_explicit_layout";
+static const char* const E_SPV_KHR_subgroup_uniform_control_flow = "SPV_KHR_subgroup_uniform_control_flow";
 
 
 #endif  // #ifndef GLSLextKHR_H
 #endif  // #ifndef GLSLextKHR_H

+ 414 - 22
3rdparty/glslang/SPIRV/GlslangToSpv.cpp

@@ -160,6 +160,7 @@ protected:
     spv::SelectionControlMask TranslateSwitchControl(const glslang::TIntermSwitch&) const;
     spv::SelectionControlMask TranslateSwitchControl(const glslang::TIntermSwitch&) const;
     spv::LoopControlMask TranslateLoopControl(const glslang::TIntermLoop&, std::vector<unsigned int>& operands) const;
     spv::LoopControlMask TranslateLoopControl(const glslang::TIntermLoop&, std::vector<unsigned int>& operands) const;
     spv::StorageClass TranslateStorageClass(const glslang::TType&);
     spv::StorageClass TranslateStorageClass(const glslang::TType&);
+    void TranslateLiterals(const glslang::TVector<const glslang::TIntermConstantUnion*>&, std::vector<unsigned>&) const;
     void addIndirectionIndexCapabilities(const glslang::TType& baseType, const glslang::TType& indexType);
     void addIndirectionIndexCapabilities(const glslang::TType& baseType, const glslang::TType& indexType);
     spv::Id createSpvVariable(const glslang::TIntermSymbol*, spv::Id forcedType);
     spv::Id createSpvVariable(const glslang::TIntermSymbol*, spv::Id forcedType);
     spv::Id getSampledType(const glslang::TSampler&);
     spv::Id getSampledType(const glslang::TSampler&);
@@ -178,6 +179,7 @@ protected:
     spv::Id accessChainLoad(const glslang::TType& type);
     spv::Id accessChainLoad(const glslang::TType& type);
     void    accessChainStore(const glslang::TType& type, spv::Id rvalue);
     void    accessChainStore(const glslang::TType& type, spv::Id rvalue);
     void multiTypeStore(const glslang::TType&, spv::Id rValue);
     void multiTypeStore(const glslang::TType&, spv::Id rValue);
+    spv::Id convertLoadedBoolInUniformToUint(const glslang::TType& type, spv::Id nominalTypeId, spv::Id loadedId);
     glslang::TLayoutPacking getExplicitLayout(const glslang::TType& type) const;
     glslang::TLayoutPacking getExplicitLayout(const glslang::TType& type) const;
     int getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking, glslang::TLayoutMatrix);
     int getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking, glslang::TLayoutMatrix);
     int getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking, glslang::TLayoutMatrix);
     int getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking, glslang::TLayoutMatrix);
@@ -1249,6 +1251,10 @@ spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::T
 {
 {
     if (type.getBasicType() == glslang::EbtRayQuery)
     if (type.getBasicType() == glslang::EbtRayQuery)
         return spv::StorageClassPrivate;
         return spv::StorageClassPrivate;
+#ifndef GLSLANG_WEB
+    if (type.getQualifier().isSpirvByReference())
+        return spv::StorageClassFunction;
+#endif
     if (type.getQualifier().isPipeInput())
     if (type.getQualifier().isPipeInput())
         return spv::StorageClassInput;
         return spv::StorageClassInput;
     if (type.getQualifier().isPipeOutput())
     if (type.getQualifier().isPipeOutput())
@@ -1297,6 +1303,7 @@ spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::T
     case glslang::EvqHitAttr:        return spv::StorageClassHitAttributeKHR;
     case glslang::EvqHitAttr:        return spv::StorageClassHitAttributeKHR;
     case glslang::EvqCallableData:   return spv::StorageClassCallableDataKHR;
     case glslang::EvqCallableData:   return spv::StorageClassCallableDataKHR;
     case glslang::EvqCallableDataIn: return spv::StorageClassIncomingCallableDataKHR;
     case glslang::EvqCallableDataIn: return spv::StorageClassIncomingCallableDataKHR;
+    case glslang::EvqSpirvStorageClass: return static_cast<spv::StorageClass>(type.getQualifier().spirvStorageClass);
 #endif
 #endif
     default:
     default:
         assert(0);
         assert(0);
@@ -1306,6 +1313,52 @@ spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::T
     return spv::StorageClassFunction;
     return spv::StorageClassFunction;
 }
 }
 
 
+// Translate glslang constants to SPIR-V literals
+void TGlslangToSpvTraverser::TranslateLiterals(const glslang::TVector<const glslang::TIntermConstantUnion*>& constants,
+                                               std::vector<unsigned>& literals) const
+{
+    for (auto constant : constants) {
+        if (constant->getBasicType() == glslang::EbtFloat) {
+            float floatValue = static_cast<float>(constant->getConstArray()[0].getDConst());
+            unsigned literal = *reinterpret_cast<unsigned*>(&floatValue);
+            literals.push_back(literal);
+        } else if (constant->getBasicType() == glslang::EbtInt) {
+            unsigned literal = constant->getConstArray()[0].getIConst();
+            literals.push_back(literal);
+        } else if (constant->getBasicType() == glslang::EbtUint) {
+            unsigned literal = constant->getConstArray()[0].getUConst();
+            literals.push_back(literal);
+        } else if (constant->getBasicType() == glslang::EbtBool) {
+            unsigned literal = constant->getConstArray()[0].getBConst();
+            literals.push_back(literal);
+        } else if (constant->getBasicType() == glslang::EbtString) {
+            auto str = constant->getConstArray()[0].getSConst()->c_str();
+            unsigned literal = 0;
+            char* literalPtr = reinterpret_cast<char*>(&literal);
+            unsigned charCount = 0;
+            char ch = 0;
+            do {
+                ch = *(str++);
+                *(literalPtr++) = ch;
+                ++charCount;
+                if (charCount == 4) {
+                    literals.push_back(literal);
+                    literalPtr = reinterpret_cast<char*>(&literal);
+                    charCount = 0;
+                }
+            } while (ch != 0);
+
+            // Partial literal is padded with 0
+            if (charCount > 0) {
+                for (; charCount < 4; ++charCount)
+                    *(literalPtr++) = 0;
+                literals.push_back(literal);
+            }
+        } else
+            assert(0); // Unexpected type
+    }
+}
+
 // Add capabilities pertaining to how an array is indexed.
 // Add capabilities pertaining to how an array is indexed.
 void TGlslangToSpvTraverser::addIndirectionIndexCapabilities(const glslang::TType& baseType,
 void TGlslangToSpvTraverser::addIndirectionIndexCapabilities(const glslang::TType& baseType,
                                                              const glslang::TType& indexType)
                                                              const glslang::TType& indexType)
@@ -1526,6 +1579,13 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
         builder.addCapability(spv::CapabilityRayTraversalPrimitiveCullingKHR);
         builder.addCapability(spv::CapabilityRayTraversalPrimitiveCullingKHR);
     }
     }
 
 
+#ifndef GLSLANG_WEB
+    if (glslangIntermediate->getSubgroupUniformControlFlow()) {
+        builder.addExtension(spv::E_SPV_KHR_subgroup_uniform_control_flow);
+        builder.addExecutionMode(shaderEntry, spv::ExecutionModeSubgroupUniformControlFlowKHR);
+    }
+#endif
+
     unsigned int mode;
     unsigned int mode;
     switch (glslangIntermediate->getStage()) {
     switch (glslangIntermediate->getStage()) {
     case EShLangVertex:
     case EShLangVertex:
@@ -1728,6 +1788,53 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
     default:
     default:
         break;
         break;
     }
     }
+
+#ifndef GLSLANG_WEB
+    //
+    // Add SPIR-V requirements (GL_EXT_spirv_intrinsics)
+    //
+    if (glslangIntermediate->hasSpirvRequirement()) {
+        const glslang::TSpirvRequirement& spirvRequirement = glslangIntermediate->getSpirvRequirement();
+
+        // Add SPIR-V extension requirement
+        for (auto& extension : spirvRequirement.extensions)
+            builder.addExtension(extension.c_str());
+
+        // Add SPIR-V capability requirement
+        for (auto capability : spirvRequirement.capabilities)
+            builder.addCapability(static_cast<spv::Capability>(capability));
+    }
+
+    //
+    // Add SPIR-V execution mode qualifiers (GL_EXT_spirv_intrinsics)
+    //
+    if (glslangIntermediate->hasSpirvExecutionMode()) {
+        const glslang::TSpirvExecutionMode spirvExecutionMode = glslangIntermediate->getSpirvExecutionMode();
+
+        // Add spirv_execution_mode
+        for (auto& mode : spirvExecutionMode.modes) {
+            if (!mode.second.empty()) {
+                std::vector<unsigned> literals;
+                TranslateLiterals(mode.second, literals);
+                builder.addExecutionMode(shaderEntry, static_cast<spv::ExecutionMode>(mode.first), literals);
+            } else
+                builder.addExecutionMode(shaderEntry, static_cast<spv::ExecutionMode>(mode.first));
+        }
+
+        // Add spirv_execution_mode_id
+        for (auto& modeId : spirvExecutionMode.modeIds) {
+            std::vector<spv::Id> operandIds;
+            assert(!modeId.second.empty());
+            for (auto extraOperand : modeId.second) {
+                int nextConst = 0;
+                spv::Id operandId = createSpvConstantFromConstUnionArray(
+                    extraOperand->getType(), extraOperand->getConstArray(), nextConst, false);
+                operandIds.push_back(operandId);
+            }
+            builder.addExecutionModeId(shaderEntry, static_cast<spv::ExecutionMode>(modeId.first), operandIds);
+        }
+    }
+#endif
 }
 }
 
 
 // Finish creating SPV, after the traversal is complete.
 // Finish creating SPV, after the traversal is complete.
@@ -2125,6 +2232,49 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
     }
     }
 }
 }
 
 
+spv::Id TGlslangToSpvTraverser::convertLoadedBoolInUniformToUint(const glslang::TType& type,
+                                                                 spv::Id nominalTypeId,
+                                                                 spv::Id loadedId)
+{
+    if (builder.isScalarType(nominalTypeId)) {
+        // Conversion for bool
+        spv::Id boolType = builder.makeBoolType();
+        if (nominalTypeId != boolType)
+            return builder.createBinOp(spv::OpINotEqual, boolType, loadedId, builder.makeUintConstant(0));
+    } else if (builder.isVectorType(nominalTypeId)) {
+        // Conversion for bvec
+        int vecSize = builder.getNumTypeComponents(nominalTypeId);
+        spv::Id bvecType = builder.makeVectorType(builder.makeBoolType(), vecSize);
+        if (nominalTypeId != bvecType)
+            loadedId = builder.createBinOp(spv::OpINotEqual, bvecType, loadedId,
+                makeSmearedConstant(builder.makeUintConstant(0), vecSize));
+    } else if (builder.isArrayType(nominalTypeId)) {
+        // Conversion for bool array
+        spv::Id boolArrayTypeId = convertGlslangToSpvType(type);
+        if (nominalTypeId != boolArrayTypeId)
+        {
+            // Use OpCopyLogical from SPIR-V 1.4 if available.
+            if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_4)
+                return builder.createUnaryOp(spv::OpCopyLogical, boolArrayTypeId, loadedId);
+
+            glslang::TType glslangElementType(type, 0);
+            spv::Id elementNominalTypeId = builder.getContainedTypeId(nominalTypeId);
+            std::vector<spv::Id> constituents;
+            for (int index = 0; index < type.getOuterArraySize(); ++index) {
+                // get the element
+                spv::Id elementValue = builder.createCompositeExtract(loadedId, elementNominalTypeId, index);
+
+                // recursively convert it
+                spv::Id elementConvertedValue = convertLoadedBoolInUniformToUint(glslangElementType, elementNominalTypeId, elementValue);
+                constituents.push_back(elementConvertedValue);
+            }
+            return builder.createCompositeConstruct(boolArrayTypeId, constituents);
+        }
+    }
+
+    return loadedId;
+}
+
 // Figure out what, if any, type changes are needed when accessing a specific built-in.
 // 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>.
 // 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.
 // Also see comment for 'forceType', regarding tracking SPIR-V-required types.
@@ -2310,10 +2460,14 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
         node->getOp() == glslang::EOpRayQueryGetWorldRayDirection ||
         node->getOp() == glslang::EOpRayQueryGetWorldRayDirection ||
         node->getOp() == glslang::EOpRayQueryGetIntersectionCandidateAABBOpaque ||
         node->getOp() == glslang::EOpRayQueryGetIntersectionCandidateAABBOpaque ||
         node->getOp() == glslang::EOpRayQueryTerminate ||
         node->getOp() == glslang::EOpRayQueryTerminate ||
-        node->getOp() == glslang::EOpRayQueryConfirmIntersection) {
+        node->getOp() == glslang::EOpRayQueryConfirmIntersection ||
+        (node->getOp() == glslang::EOpSpirvInst && operandNode->getAsTyped()->getQualifier().isSpirvByReference())) {
         operand = builder.accessChainGetLValue(); // Special case l-value operands
         operand = builder.accessChainGetLValue(); // Special case l-value operands
         lvalueCoherentFlags = builder.getAccessChain().coherentFlags;
         lvalueCoherentFlags = builder.getAccessChain().coherentFlags;
         lvalueCoherentFlags |= TranslateCoherent(operandNode->getAsTyped()->getType());
         lvalueCoherentFlags |= TranslateCoherent(operandNode->getAsTyped()->getType());
+    } else if (operandNode->getAsTyped()->getQualifier().isSpirvLiteral()) {
+        // Will be translated to a literal value, make a placeholder here
+        operand = spv::NoResult;
     } else
     } else
 #endif
 #endif
     {
     {
@@ -2334,6 +2488,38 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
         result = createUnaryOperation(node->getOp(), decorations, resultType(), operand,
         result = createUnaryOperation(node->getOp(), decorations, resultType(), operand,
             node->getOperand()->getBasicType(), lvalueCoherentFlags);
             node->getOperand()->getBasicType(), lvalueCoherentFlags);
 
 
+#ifndef GLSLANG_WEB
+    // it could be attached to a SPIR-V intruction
+    if (!result) {
+        if (node->getOp() == glslang::EOpSpirvInst) {
+            const auto& spirvInst = node->getSpirvInstruction();
+            if (spirvInst.set == "") {
+                spv::IdImmediate idImmOp = {true, operand};
+                if (operandNode->getAsTyped()->getQualifier().isSpirvLiteral()) {
+                    // Translate the constant to a literal value
+                    std::vector<unsigned> literals;
+                    glslang::TVector<const glslang::TIntermConstantUnion*> constants;
+                    constants.push_back(operandNode->getAsConstantUnion());
+                    TranslateLiterals(constants, literals);
+                    idImmOp = {false, literals[0]};
+                }
+
+                if (node->getBasicType() == glslang::EbtVoid)
+                    builder.createNoResultOp(static_cast<spv::Op>(spirvInst.id), {idImmOp});
+                else
+                    result = builder.createOp(static_cast<spv::Op>(spirvInst.id), resultType(), {idImmOp});
+            } else {
+                result = builder.createBuiltinCall(
+                    resultType(), spirvInst.set == "GLSL.std.450" ? stdBuiltins : getExtBuiltins(spirvInst.set.c_str()),
+                    spirvInst.id, {operand});
+            }
+
+            if (node->getBasicType() == glslang::EbtVoid)
+                return false; // done with this node
+        }
+    }
+#endif
+
     if (result) {
     if (result) {
         if (invertedType) {
         if (invertedType) {
             result = createInvertedSwizzle(decorations.precision, *node->getOperand(), result);
             result = createInvertedSwizzle(decorations.precision, *node->getOperand(), result);
@@ -3030,6 +3216,10 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
             if (arg == 1)
             if (arg == 1)
                 lvalue = true;
                 lvalue = true;
             break;
             break;
+        case glslang::EOpSpirvInst:
+            if (glslangOperands[arg]->getAsTyped()->getQualifier().isSpirvByReference())
+                lvalue = true;
+            break;
 #endif
 #endif
         default:
         default:
             break;
             break;
@@ -3135,7 +3325,12 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
                  visitSymbol(itNode->second);
                  visitSymbol(itNode->second);
                  spv::Id symId = getSymbolId(itNode->second);
                  spv::Id symId = getSymbolId(itNode->second);
                  operands.push_back(symId);
                  operands.push_back(symId);
-             } else {
+#ifndef GLSLANG_WEB
+             } else if (glslangOperands[arg]->getAsTyped()->getQualifier().isSpirvLiteral()) {
+                 // Will be translated to a literal value, make a placeholder here
+                 operands.push_back(spv::NoResult);
+#endif
+             } else  {
                 operands.push_back(accessChainLoad(glslangOperands[arg]->getAsTyped()->getType()));
                 operands.push_back(accessChainLoad(glslangOperands[arg]->getAsTyped()->getType()));
              }
              }
         }
         }
@@ -3177,6 +3372,34 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
             ? node->getSequence()[0]->getAsTyped()->getBasicType() : node->getBasicType();
             ? node->getSequence()[0]->getAsTyped()->getBasicType() : node->getBasicType();
         result = createAtomicOperation(node->getOp(), precision, resultType(), operands, typeProxy,
         result = createAtomicOperation(node->getOp(), precision, resultType(), operands, typeProxy,
             lvalueCoherentFlags);
             lvalueCoherentFlags);
+#ifndef GLSLANG_WEB
+    } else if (node->getOp() == glslang::EOpSpirvInst) {
+        const auto& spirvInst = node->getSpirvInstruction();
+        if (spirvInst.set == "") {
+            std::vector<spv::IdImmediate> idImmOps;
+            for (int i = 0; i < glslangOperands.size(); ++i) {
+                if (glslangOperands[i]->getAsTyped()->getQualifier().isSpirvLiteral()) {
+                    // Translate the constant to a literal value
+                    std::vector<unsigned> literals;
+                    glslang::TVector<const glslang::TIntermConstantUnion*> constants;
+                    constants.push_back(glslangOperands[i]->getAsConstantUnion());
+                    TranslateLiterals(constants, literals);
+                    idImmOps.push_back({false, literals[0]});
+                } else
+                    idImmOps.push_back({true, operands[i]});
+            }
+
+            if (node->getBasicType() == glslang::EbtVoid)
+                builder.createNoResultOp(static_cast<spv::Op>(spirvInst.id), idImmOps);
+            else
+                result = builder.createOp(static_cast<spv::Op>(spirvInst.id), resultType(), idImmOps);
+        } else {
+            result = builder.createBuiltinCall(
+                resultType(), spirvInst.set == "GLSL.std.450" ? stdBuiltins : getExtBuiltins(spirvInst.set.c_str()),
+                spirvInst.id, operands);
+        }
+        noReturnValue = node->getBasicType() == glslang::EbtVoid;
+#endif
     } else if (node->getOp() == glslang::EOpDebugPrintf) {
     } else if (node->getOp() == glslang::EOpDebugPrintf) {
         if (!nonSemanticDebugPrintf) {
         if (!nonSemanticDebugPrintf) {
             nonSemanticDebugPrintf = builder.import("NonSemantic.DebugPrintf");
             nonSemanticDebugPrintf = builder.import("NonSemantic.DebugPrintf");
@@ -3457,6 +3680,11 @@ bool TGlslangToSpvTraverser::visitSwitch(glslang::TVisit /* visit */, glslang::T
 
 
 void TGlslangToSpvTraverser::visitConstantUnion(glslang::TIntermConstantUnion* node)
 void TGlslangToSpvTraverser::visitConstantUnion(glslang::TIntermConstantUnion* node)
 {
 {
+#ifndef GLSLANG_WEB
+    if (node->getQualifier().isSpirvLiteral())
+        return; // Translated to a literal value, skip further processing
+#endif
+
     int nextConst = 0;
     int nextConst = 0;
     spv::Id constant = createSpvConstantFromConstUnionArray(node->getType(), node->getConstArray(), nextConst, false);
     spv::Id constant = createSpvConstantFromConstUnionArray(node->getType(), node->getConstArray(), nextConst, false);
 
 
@@ -3905,6 +4133,77 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
     case glslang::EbtString:
     case glslang::EbtString:
         // no type used for OpString
         // no type used for OpString
         return 0;
         return 0;
+#ifndef GLSLANG_WEB
+    case glslang::EbtSpirvType: {
+        // GL_EXT_spirv_intrinsics
+        const auto& spirvType = type.getSpirvType();
+        const auto& spirvInst = spirvType.spirvInst;
+
+        std::vector<spv::Id> operands;
+        for (const auto& typeParam : spirvType.typeParams) {
+            if (typeParam.isConstant) {
+                // Constant expression
+                if (typeParam.constant->isLiteral()) {
+                    if (typeParam.constant->getBasicType() == glslang::EbtFloat) {
+                        float floatValue = static_cast<float>(typeParam.constant->getConstArray()[0].getDConst());
+                        unsigned literal = *reinterpret_cast<unsigned*>(&floatValue);
+                        operands.push_back(literal);
+                    } else if (typeParam.constant->getBasicType() == glslang::EbtInt) {
+                        unsigned literal = typeParam.constant->getConstArray()[0].getIConst();
+                        operands.push_back(literal);
+                    } else if (typeParam.constant->getBasicType() == glslang::EbtUint) {
+                        unsigned literal = typeParam.constant->getConstArray()[0].getUConst();
+                        operands.push_back(literal);
+                    } else if (typeParam.constant->getBasicType() == glslang::EbtBool) {
+                        unsigned literal = typeParam.constant->getConstArray()[0].getBConst();
+                        operands.push_back(literal);
+                    } else if (typeParam.constant->getBasicType() == glslang::EbtString) {
+                        auto str = typeParam.constant->getConstArray()[0].getSConst()->c_str();
+                        unsigned literal = 0;
+                        char* literalPtr = reinterpret_cast<char*>(&literal);
+                        unsigned charCount = 0;
+                        char ch = 0;
+                        do {
+                            ch = *(str++);
+                            *(literalPtr++) = ch;
+                            ++charCount;
+                            if (charCount == 4) {
+                                operands.push_back(literal);
+                                literalPtr = reinterpret_cast<char*>(&literal);
+                                charCount = 0;
+                            }
+                        } while (ch != 0);
+
+                        // Partial literal is padded with 0
+                        if (charCount > 0) {
+                            for (; charCount < 4; ++charCount)
+                                *(literalPtr++) = 0;
+                            operands.push_back(literal);
+                        }
+                    } else
+                        assert(0); // Unexpected type
+                } else {
+                    int nextConst = 0;
+                    spv::Id constant = createSpvConstantFromConstUnionArray(
+                        typeParam.constant->getType(), typeParam.constant->getConstArray(), nextConst, false);
+                    operands.push_back(constant);
+                }
+            } else {
+                // Type specifier
+                spv::Id typeId = convertGlslangToSpvType(*typeParam.type);
+                operands.push_back(typeId);
+            }
+        }
+
+        if (spirvInst.set == "")
+            spvType = builder.createOp(static_cast<spv::Op>(spirvInst.id), spv::NoType, operands);
+        else {
+            spvType = builder.createBuiltinCall(
+                spv::NoType, getExtBuiltins(spirvInst.set.c_str()), spirvInst.id, operands);
+        }
+        break;
+    }
+#endif
     default:
     default:
         assert(0);
         assert(0);
         break;
         break;
@@ -4218,6 +4517,38 @@ void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type,
             builder.addCapability(spv::CapabilityGeometryShaderPassthroughNV);
             builder.addCapability(spv::CapabilityGeometryShaderPassthroughNV);
             builder.addExtension(spv::E_SPV_NV_geometry_shader_passthrough);
             builder.addExtension(spv::E_SPV_NV_geometry_shader_passthrough);
         }
         }
+
+        //
+        // Add SPIR-V decorations for members (GL_EXT_spirv_intrinsics)
+        //
+        if (glslangMember.getQualifier().hasSprivDecorate()) {
+            const glslang::TSpirvDecorate& spirvDecorate = glslangMember.getQualifier().getSpirvDecorate();
+
+            // Add spirv_decorate
+            for (auto& decorate : spirvDecorate.decorates) {
+                if (!decorate.second.empty()) {
+                    std::vector<unsigned> literals;
+                    TranslateLiterals(decorate.second, literals);
+                    builder.addMemberDecoration(spvType, member, static_cast<spv::Decoration>(decorate.first), literals);
+                }
+                else
+                    builder.addMemberDecoration(spvType, member, static_cast<spv::Decoration>(decorate.first));
+            }
+
+            // spirv_decorate_id not applied to members
+            assert(spirvDecorate.decorateIds.empty());
+
+            // Add spirv_decorate_string
+            for (auto& decorateString : spirvDecorate.decorateStrings) {
+                std::vector<const char*> strings;
+                assert(!decorateString.second.empty());
+                for (auto extraOperand : decorateString.second) {
+                    const char* string = extraOperand->getConstArray()[0].getSConst()->c_str();
+                    strings.push_back(string);
+                }
+                builder.addDecoration(spvType, static_cast<spv::Decoration>(decorateString.first), strings);
+            }
+        }
 #endif
 #endif
     }
     }
 
 
@@ -4273,19 +4604,7 @@ spv::Id TGlslangToSpvTraverser::accessChainLoad(const glslang::TType& type)
 
 
     // Need to convert to abstract types when necessary
     // Need to convert to abstract types when necessary
     if (type.getBasicType() == glslang::EbtBool) {
     if (type.getBasicType() == glslang::EbtBool) {
-        if (builder.isScalarType(nominalTypeId)) {
-            // Conversion for bool
-            spv::Id boolType = builder.makeBoolType();
-            if (nominalTypeId != boolType)
-                loadedId = builder.createBinOp(spv::OpINotEqual, boolType, loadedId, builder.makeUintConstant(0));
-        } else if (builder.isVectorType(nominalTypeId)) {
-            // Conversion for bvec
-            int vecSize = builder.getNumTypeComponents(nominalTypeId);
-            spv::Id bvecType = builder.makeVectorType(builder.makeBoolType(), vecSize);
-            if (nominalTypeId != bvecType)
-                loadedId = builder.createBinOp(spv::OpINotEqual, bvecType, loadedId,
-                    makeSmearedConstant(builder.makeUintConstant(0), vecSize));
-        }
+        loadedId = convertLoadedBoolInUniformToUint(type, nominalTypeId, loadedId);
     }
     }
 
 
     return loadedId;
     return loadedId;
@@ -4607,6 +4926,9 @@ bool TGlslangToSpvTraverser::originalParam(glslang::TStorageQualifier qualifier,
     if (glslangIntermediate->getSource() == glslang::EShSourceHlsl)
     if (glslangIntermediate->getSource() == glslang::EShSourceHlsl)
         return paramType.getBasicType() == glslang::EbtBlock;
         return paramType.getBasicType() == glslang::EbtBlock;
     return paramType.containsOpaque() ||                                                       // sampler, etc.
     return paramType.containsOpaque() ||                                                       // sampler, etc.
+#ifndef GLSLANG_WEB
+           paramType.getQualifier().isSpirvByReference() ||                                    // spirv_by_reference
+#endif
            (paramType.getBasicType() == glslang::EbtBlock && qualifier == glslang::EvqBuffer); // SSBO
            (paramType.getBasicType() == glslang::EbtBlock && qualifier == glslang::EvqBuffer); // SSBO
 }
 }
 
 
@@ -6893,13 +7215,17 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv
     case glslang::EOpImageAtomicAdd:
     case glslang::EOpImageAtomicAdd:
     case glslang::EOpAtomicCounterAdd:
     case glslang::EOpAtomicCounterAdd:
         opCode = spv::OpAtomicIAdd;
         opCode = spv::OpAtomicIAdd;
-        if (typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble) {
+        if (typeProxy == glslang::EbtFloat16 || typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble) {
             opCode = spv::OpAtomicFAddEXT;
             opCode = spv::OpAtomicFAddEXT;
             builder.addExtension(spv::E_SPV_EXT_shader_atomic_float_add);
             builder.addExtension(spv::E_SPV_EXT_shader_atomic_float_add);
-            if (typeProxy == glslang::EbtFloat)
+            if (typeProxy == glslang::EbtFloat16) {
+                builder.addExtension(spv::E_SPV_EXT_shader_atomic_float16_add);
+                builder.addCapability(spv::CapabilityAtomicFloat16AddEXT);
+            } else if (typeProxy == glslang::EbtFloat) {
                 builder.addCapability(spv::CapabilityAtomicFloat32AddEXT);
                 builder.addCapability(spv::CapabilityAtomicFloat32AddEXT);
-            else
+            } else {
                 builder.addCapability(spv::CapabilityAtomicFloat64AddEXT);
                 builder.addCapability(spv::CapabilityAtomicFloat64AddEXT);
+            }
         }
         }
         break;
         break;
     case glslang::EOpAtomicSubtract:
     case glslang::EOpAtomicSubtract:
@@ -6909,14 +7235,38 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv
     case glslang::EOpAtomicMin:
     case glslang::EOpAtomicMin:
     case glslang::EOpImageAtomicMin:
     case glslang::EOpImageAtomicMin:
     case glslang::EOpAtomicCounterMin:
     case glslang::EOpAtomicCounterMin:
-        opCode = (typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64) ?
-            spv::OpAtomicUMin : spv::OpAtomicSMin;
+        if (typeProxy == glslang::EbtFloat16 || typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble) {
+            opCode = spv::OpAtomicFMinEXT;
+            builder.addExtension(spv::E_SPV_EXT_shader_atomic_float_min_max);
+            if (typeProxy == glslang::EbtFloat16)
+                builder.addCapability(spv::CapabilityAtomicFloat16MinMaxEXT);
+            else if (typeProxy == glslang::EbtFloat)
+                builder.addCapability(spv::CapabilityAtomicFloat32MinMaxEXT);
+            else
+                builder.addCapability(spv::CapabilityAtomicFloat64MinMaxEXT);
+        } else if (typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64) {
+            opCode = spv::OpAtomicUMin;
+        } else {
+            opCode = spv::OpAtomicSMin;
+        }
         break;
         break;
     case glslang::EOpAtomicMax:
     case glslang::EOpAtomicMax:
     case glslang::EOpImageAtomicMax:
     case glslang::EOpImageAtomicMax:
     case glslang::EOpAtomicCounterMax:
     case glslang::EOpAtomicCounterMax:
-        opCode = (typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64) ?
-            spv::OpAtomicUMax : spv::OpAtomicSMax;
+        if (typeProxy == glslang::EbtFloat16 || typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble) {
+            opCode = spv::OpAtomicFMaxEXT;
+            builder.addExtension(spv::E_SPV_EXT_shader_atomic_float_min_max);
+            if (typeProxy == glslang::EbtFloat16)
+                builder.addCapability(spv::CapabilityAtomicFloat16MinMaxEXT);
+            else if (typeProxy == glslang::EbtFloat)
+                builder.addCapability(spv::CapabilityAtomicFloat32MinMaxEXT);
+            else
+                builder.addCapability(spv::CapabilityAtomicFloat64MinMaxEXT);
+        } else if (typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64) {
+            opCode = spv::OpAtomicUMax;
+        } else {
+            opCode = spv::OpAtomicSMax;
+        }
         break;
         break;
     case glslang::EOpAtomicAnd:
     case glslang::EOpAtomicAnd:
     case glslang::EOpImageAtomicAnd:
     case glslang::EOpImageAtomicAnd:
@@ -8458,6 +8808,48 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
         builder.addDecoration(id, symbol->getType().getQualifier().restrict ?
         builder.addDecoration(id, symbol->getType().getQualifier().restrict ?
             spv::DecorationRestrictPointerEXT : spv::DecorationAliasedPointerEXT);
             spv::DecorationRestrictPointerEXT : spv::DecorationAliasedPointerEXT);
     }
     }
+
+    //
+    // Add SPIR-V decorations for structure (GL_EXT_spirv_intrinsics)
+    //
+    if (symbol->getType().getQualifier().hasSprivDecorate()) {
+        const glslang::TSpirvDecorate& spirvDecorate = symbol->getType().getQualifier().getSpirvDecorate();
+
+        // Add spirv_decorate
+        for (auto& decorate : spirvDecorate.decorates) {
+            if (!decorate.second.empty()) {
+                std::vector<unsigned> literals;
+                TranslateLiterals(decorate.second, literals);
+                builder.addDecoration(id, static_cast<spv::Decoration>(decorate.first), literals);
+            }
+            else
+                builder.addDecoration(id, static_cast<spv::Decoration>(decorate.first));
+        }
+
+        // Add spirv_decorate_id
+        for (auto& decorateId : spirvDecorate.decorateIds) {
+            std::vector<spv::Id> operandIds;
+            assert(!decorateId.second.empty());
+            for (auto extraOperand : decorateId.second) {
+                int nextConst = 0;
+                spv::Id operandId = createSpvConstantFromConstUnionArray(
+                    extraOperand->getType(), extraOperand->getConstArray(), nextConst, false);
+                operandIds.push_back(operandId);
+            }
+            builder.addDecoration(id, static_cast<spv::Decoration>(decorateId.first), operandIds);
+        }
+
+        // Add spirv_decorate_string
+        for (auto& decorateString : spirvDecorate.decorateStrings) {
+            std::vector<const char*> strings;
+            assert(!decorateString.second.empty());
+            for (auto extraOperand : decorateString.second) {
+                const char* string = extraOperand->getConstArray()[0].getSConst()->c_str();
+                strings.push_back(string);
+            }
+            builder.addDecoration(id, static_cast<spv::Decoration>(decorateString.first), strings);
+        }
+    }
 #endif
 #endif
 
 
     return id;
     return id;

+ 3 - 0
3rdparty/glslang/SPIRV/SPVRemapper.cpp

@@ -544,6 +544,9 @@ namespace spv {
         // Extended instructions: currently, assume everything is an ID.
         // Extended instructions: currently, assume everything is an ID.
         // TODO: add whatever data we need for exceptions to that
         // TODO: add whatever data we need for exceptions to that
         if (opCode == spv::OpExtInst) {
         if (opCode == spv::OpExtInst) {
+
+            idFn(asId(word)); // Instruction set is an ID that also needs to be mapped
+
             word        += 2; // instruction set, and instruction from set
             word        += 2; // instruction set, and instruction from set
             numOperands -= 2;
             numOperands -= 2;
 
 

+ 17 - 0
3rdparty/glslang/SPIRV/doc.cpp

@@ -188,6 +188,7 @@ const char* ExecutionModeString(int mode)
     case ExecutionModeRoundingModeRTE:          return "RoundingModeRTE";
     case ExecutionModeRoundingModeRTE:          return "RoundingModeRTE";
     case ExecutionModeRoundingModeRTZ:          return "RoundingModeRTZ";
     case ExecutionModeRoundingModeRTZ:          return "RoundingModeRTZ";
     case ExecutionModeStencilRefReplacingEXT:   return "StencilRefReplacingEXT";
     case ExecutionModeStencilRefReplacingEXT:   return "StencilRefReplacingEXT";
+    case ExecutionModeSubgroupUniformControlFlowKHR: return "SubgroupUniformControlFlow";
 
 
     case ExecutionModeOutputLinesNV:            return "OutputLinesNV";
     case ExecutionModeOutputLinesNV:            return "OutputLinesNV";
     case ExecutionModeOutputPrimitivesNV:       return "OutputPrimitivesNV";
     case ExecutionModeOutputPrimitivesNV:       return "OutputPrimitivesNV";
@@ -965,8 +966,12 @@ const char* CapabilityString(int info)
 
 
     case CapabilityIntegerFunctions2INTEL:              return "CapabilityIntegerFunctions2INTEL";
     case CapabilityIntegerFunctions2INTEL:              return "CapabilityIntegerFunctions2INTEL";
 
 
+    case CapabilityAtomicFloat16AddEXT:                     return "AtomicFloat16AddEXT";
     case CapabilityAtomicFloat32AddEXT:                     return "AtomicFloat32AddEXT";
     case CapabilityAtomicFloat32AddEXT:                     return "AtomicFloat32AddEXT";
     case CapabilityAtomicFloat64AddEXT:                     return "AtomicFloat64AddEXT";
     case CapabilityAtomicFloat64AddEXT:                     return "AtomicFloat64AddEXT";
+    case CapabilityAtomicFloat16MinMaxEXT:                  return "AtomicFloat16MinMaxEXT";
+    case CapabilityAtomicFloat32MinMaxEXT:                  return "AtomicFloat32MinMaxEXT";
+    case CapabilityAtomicFloat64MinMaxEXT:                  return "AtomicFloat64MinMaxEXT";
 
 
     case CapabilityWorkgroupMemoryExplicitLayoutKHR:            return "CapabilityWorkgroupMemoryExplicitLayoutKHR";
     case CapabilityWorkgroupMemoryExplicitLayoutKHR:            return "CapabilityWorkgroupMemoryExplicitLayoutKHR";
     case CapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR:  return "CapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR";
     case CapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR:  return "CapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR";
@@ -1351,6 +1356,8 @@ const char* OpcodeString(int op)
     case 4432: return "OpSubgroupReadInvocationKHR";
     case 4432: return "OpSubgroupReadInvocationKHR";
 
 
     case OpAtomicFAddEXT: return "OpAtomicFAddEXT";
     case OpAtomicFAddEXT: return "OpAtomicFAddEXT";
+    case OpAtomicFMinEXT: return "OpAtomicFMinEXT";
+    case OpAtomicFMaxEXT: return "OpAtomicFMaxEXT";
 
 
     case 5000: return "OpGroupIAddNonUniformAMD";
     case 5000: return "OpGroupIAddNonUniformAMD";
     case 5001: return "OpGroupFAddNonUniformAMD";
     case 5001: return "OpGroupFAddNonUniformAMD";
@@ -2341,6 +2348,16 @@ void Parameterize()
     InstructionDesc[OpAtomicSMax].operands.push(OperandMemorySemantics, "'Semantics'");
     InstructionDesc[OpAtomicSMax].operands.push(OperandMemorySemantics, "'Semantics'");
     InstructionDesc[OpAtomicSMax].operands.push(OperandId, "'Value'");
     InstructionDesc[OpAtomicSMax].operands.push(OperandId, "'Value'");
 
 
+    InstructionDesc[OpAtomicFMinEXT].operands.push(OperandId, "'Pointer'");
+    InstructionDesc[OpAtomicFMinEXT].operands.push(OperandScope, "'Scope'");
+    InstructionDesc[OpAtomicFMinEXT].operands.push(OperandMemorySemantics, "'Semantics'");
+    InstructionDesc[OpAtomicFMinEXT].operands.push(OperandId, "'Value'");
+
+    InstructionDesc[OpAtomicFMaxEXT].operands.push(OperandId, "'Pointer'");
+    InstructionDesc[OpAtomicFMaxEXT].operands.push(OperandScope, "'Scope'");
+    InstructionDesc[OpAtomicFMaxEXT].operands.push(OperandMemorySemantics, "'Semantics'");
+    InstructionDesc[OpAtomicFMaxEXT].operands.push(OperandId, "'Value'");
+
     InstructionDesc[OpAtomicAnd].operands.push(OperandId, "'Pointer'");
     InstructionDesc[OpAtomicAnd].operands.push(OperandId, "'Pointer'");
     InstructionDesc[OpAtomicAnd].operands.push(OperandScope, "'Scope'");
     InstructionDesc[OpAtomicAnd].operands.push(OperandScope, "'Scope'");
     InstructionDesc[OpAtomicAnd].operands.push(OperandMemorySemantics, "'Semantics'");
     InstructionDesc[OpAtomicAnd].operands.push(OperandMemorySemantics, "'Semantics'");

+ 21 - 6
3rdparty/glslang/SPIRV/spirv.hpp

@@ -150,6 +150,7 @@ enum ExecutionMode {
     ExecutionModeSubgroupsPerWorkgroupId = 37,
     ExecutionModeSubgroupsPerWorkgroupId = 37,
     ExecutionModeLocalSizeId = 38,
     ExecutionModeLocalSizeId = 38,
     ExecutionModeLocalSizeHintId = 39,
     ExecutionModeLocalSizeHintId = 39,
+    ExecutionModeSubgroupUniformControlFlowKHR = 4421,
     ExecutionModePostDepthCoverage = 4446,
     ExecutionModePostDepthCoverage = 4446,
     ExecutionModeDenormPreserve = 4459,
     ExecutionModeDenormPreserve = 4459,
     ExecutionModeDenormFlushToZero = 4460,
     ExecutionModeDenormFlushToZero = 4460,
@@ -409,6 +410,7 @@ enum FPRoundingMode {
 enum LinkageType {
 enum LinkageType {
     LinkageTypeExport = 0,
     LinkageTypeExport = 0,
     LinkageTypeImport = 1,
     LinkageTypeImport = 1,
+    LinkageTypeLinkOnceODR = 2,
     LinkageTypeMax = 0x7fffffff,
     LinkageTypeMax = 0x7fffffff,
 };
 };
 
 
@@ -1010,8 +1012,12 @@ enum Capability {
     CapabilityFunctionPointersINTEL = 5603,
     CapabilityFunctionPointersINTEL = 5603,
     CapabilityIndirectReferencesINTEL = 5604,
     CapabilityIndirectReferencesINTEL = 5604,
     CapabilityAsmINTEL = 5606,
     CapabilityAsmINTEL = 5606,
+    CapabilityAtomicFloat32MinMaxEXT = 5612,
+    CapabilityAtomicFloat64MinMaxEXT = 5613,
+    CapabilityAtomicFloat16MinMaxEXT = 5616,
     CapabilityVectorComputeINTEL = 5617,
     CapabilityVectorComputeINTEL = 5617,
     CapabilityVectorAnyINTEL = 5619,
     CapabilityVectorAnyINTEL = 5619,
+    CapabilityExpectAssumeKHR = 5629,
     CapabilitySubgroupAvcMotionEstimationINTEL = 5696,
     CapabilitySubgroupAvcMotionEstimationINTEL = 5696,
     CapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697,
     CapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697,
     CapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698,
     CapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698,
@@ -1035,6 +1041,7 @@ enum Capability {
     CapabilityAtomicFloat32AddEXT = 6033,
     CapabilityAtomicFloat32AddEXT = 6033,
     CapabilityAtomicFloat64AddEXT = 6034,
     CapabilityAtomicFloat64AddEXT = 6034,
     CapabilityLongConstantCompositeINTEL = 6089,
     CapabilityLongConstantCompositeINTEL = 6089,
+    CapabilityAtomicFloat16AddEXT = 6095,
     CapabilityMax = 0x7fffffff,
     CapabilityMax = 0x7fffffff,
 };
 };
 
 
@@ -1102,15 +1109,15 @@ enum FragmentShadingRateMask {
 };
 };
 
 
 enum FPDenormMode {
 enum FPDenormMode {
-  FPDenormModePreserve = 0,
-  FPDenormModeFlushToZero = 1,
-  FPDenormModeMax = 0x7fffffff,
+    FPDenormModePreserve = 0,
+    FPDenormModeFlushToZero = 1,
+    FPDenormModeMax = 0x7fffffff,
 };
 };
 
 
 enum FPOperationMode {
 enum FPOperationMode {
-  FPOperationModeIEEE = 0,
-  FPOperationModeALT = 1,
-  FPOperationModeMax = 0x7fffffff,
+    FPOperationModeIEEE = 0,
+    FPOperationModeALT = 1,
+    FPOperationModeMax = 0x7fffffff,
 };
 };
 
 
 enum Op {
 enum Op {
@@ -1537,6 +1544,10 @@ enum Op {
     OpAsmTargetINTEL = 5609,
     OpAsmTargetINTEL = 5609,
     OpAsmINTEL = 5610,
     OpAsmINTEL = 5610,
     OpAsmCallINTEL = 5611,
     OpAsmCallINTEL = 5611,
+    OpAtomicFMinEXT = 5614,
+    OpAtomicFMaxEXT = 5615,
+    OpAssumeTrueKHR = 5630,
+    OpExpectKHR = 5631,
     OpDecorateString = 5632,
     OpDecorateString = 5632,
     OpDecorateStringGOOGLE = 5632,
     OpDecorateStringGOOGLE = 5632,
     OpMemberDecorateString = 5633,
     OpMemberDecorateString = 5633,
@@ -2119,6 +2130,10 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
     case OpAsmTargetINTEL: *hasResult = true; *hasResultType = true; break;
     case OpAsmTargetINTEL: *hasResult = true; *hasResultType = true; break;
     case OpAsmINTEL: *hasResult = true; *hasResultType = true; break;
     case OpAsmINTEL: *hasResult = true; *hasResultType = true; break;
     case OpAsmCallINTEL: *hasResult = true; *hasResultType = true; break;
     case OpAsmCallINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpAtomicFMinEXT: *hasResult = true; *hasResultType = true; break;
+    case OpAtomicFMaxEXT: *hasResult = true; *hasResultType = true; break;
+    case OpAssumeTrueKHR: *hasResult = false; *hasResultType = false; break;
+    case OpExpectKHR: *hasResult = true; *hasResultType = true; break;
     case OpDecorateString: *hasResult = false; *hasResultType = false; break;
     case OpDecorateString: *hasResult = false; *hasResultType = false; break;
     case OpMemberDecorateString: *hasResult = false; *hasResultType = false; break;
     case OpMemberDecorateString: *hasResult = false; *hasResultType = false; break;
     case OpVmeImageINTEL: *hasResult = true; *hasResultType = true; break;
     case OpVmeImageINTEL: *hasResult = true; *hasResultType = true; break;

+ 1 - 1
3rdparty/glslang/build_info.h

@@ -35,7 +35,7 @@
 #define GLSLANG_BUILD_INFO
 #define GLSLANG_BUILD_INFO
 
 
 #define GLSLANG_VERSION_MAJOR 11
 #define GLSLANG_VERSION_MAJOR 11
-#define GLSLANG_VERSION_MINOR 4
+#define GLSLANG_VERSION_MINOR 5
 #define GLSLANG_VERSION_PATCH 0
 #define GLSLANG_VERSION_PATCH 0
 #define GLSLANG_VERSION_FLAVOR ""
 #define GLSLANG_VERSION_FLAVOR ""
 
 

+ 10 - 0
3rdparty/glslang/glslang/Include/BaseTypes.h

@@ -65,6 +65,10 @@ enum TBasicType {
     EbtAccStruct,
     EbtAccStruct,
     EbtReference,
     EbtReference,
     EbtRayQuery,
     EbtRayQuery,
+#ifndef GLSLANG_WEB
+    // SPIR-V type defined by spirv_type
+    EbtSpirvType,
+#endif
 
 
     // HLSL types that live only temporarily.
     // HLSL types that live only temporarily.
     EbtString,
     EbtString,
@@ -91,6 +95,9 @@ enum TStorageQualifier {
     EvqUniform,       // read only, shared with app
     EvqUniform,       // read only, shared with app
     EvqBuffer,        // read/write, shared with app
     EvqBuffer,        // read/write, shared with app
     EvqShared,        // compute shader's read/write 'shared' qualifier
     EvqShared,        // compute shader's read/write 'shared' qualifier
+#ifndef GLSLANG_WEB
+    EvqSpirvStorageClass, // spirv_storage_class
+#endif
 
 
     EvqPayload,
     EvqPayload,
     EvqPayloadIn,
     EvqPayloadIn,
@@ -321,6 +328,9 @@ __inline const char* GetStorageQualifierString(TStorageQualifier q)
     case EvqGlobal:         return "global";         break;
     case EvqGlobal:         return "global";         break;
     case EvqConst:          return "const";          break;
     case EvqConst:          return "const";          break;
     case EvqConstReadOnly:  return "const (read only)"; break;
     case EvqConstReadOnly:  return "const (read only)"; break;
+#ifndef GLSLANG_WEB
+    case EvqSpirvStorageClass: return "spirv_storage_class"; break;
+#endif
     case EvqVaryingIn:      return "in";             break;
     case EvqVaryingIn:      return "in";             break;
     case EvqVaryingOut:     return "out";            break;
     case EvqVaryingOut:     return "out";            break;
     case EvqUniform:        return "uniform";        break;
     case EvqUniform:        return "uniform";        break;

+ 4 - 0
3rdparty/glslang/glslang/Include/Common.h

@@ -195,6 +195,10 @@ template <class K, class D, class HASH = std::hash<K>, class PRED = std::equal_t
 class TUnorderedMap : public std::unordered_map<K, D, HASH, PRED, pool_allocator<std::pair<K const, D> > > {
 class TUnorderedMap : public std::unordered_map<K, D, HASH, PRED, pool_allocator<std::pair<K const, D> > > {
 };
 };
 
 
+template <class K, class CMP = std::less<K> >
+class TSet : public std::set<K, CMP, pool_allocator<K> > {
+};
+
 //
 //
 // Persistent string memory.  Should only be used for strings that survive
 // Persistent string memory.  Should only be used for strings that survive
 // across compiles/links.
 // across compiles/links.

+ 136 - 0
3rdparty/glslang/glslang/Include/SpirvIntrinsics.h

@@ -0,0 +1,136 @@
+//
+// Copyright(C) 2021 Advanced Micro Devices, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+//    Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+//
+//    Redistributions in binary form must reproduce the above
+//    copyright notice, this list of conditions and the following
+//    disclaimer in the documentation and/or other materials provided
+//    with the distribution.
+//
+//    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+//    contributors may be used to endorse or promote products derived
+//    from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#pragma once
+
+#ifndef GLSLANG_WEB
+
+//
+// GL_EXT_spirv_intrinsics
+//
+#include "Common.h"
+
+namespace glslang {
+
+class TIntermTyped;
+class TIntermConstantUnion;
+class TType;
+
+// SPIR-V requirements
+struct TSpirvRequirement {
+    POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
+
+    // capability = [..]
+    TSet<TString> extensions;
+    // extension = [..]
+    TSet<int> capabilities;
+};
+
+// SPIR-V execution modes
+struct TSpirvExecutionMode {
+    POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
+
+    // spirv_execution_mode
+    TMap<int, TVector<const TIntermConstantUnion*>> modes;
+    // spirv_execution_mode_id
+    TMap<int, TVector<const TIntermConstantUnion*> > modeIds;
+};
+
+// SPIR-V decorations
+struct TSpirvDecorate {
+    POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
+
+    // spirv_decorate
+    TMap<int, TVector<const TIntermConstantUnion*> > decorates;
+    // spirv_decorate_id
+    TMap<int, TVector<const TIntermConstantUnion*> > decorateIds;
+    // spirv_decorate_string
+    TMap<int, TVector<const TIntermConstantUnion*> > decorateStrings;
+};
+
+// SPIR-V instruction
+struct TSpirvInstruction {
+    POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
+
+    TSpirvInstruction() { set = ""; id = -1; }
+
+    bool operator==(const TSpirvInstruction& rhs) const { return set == rhs.set && id == rhs.id; }
+    bool operator!=(const TSpirvInstruction& rhs) const { return !operator==(rhs); }
+
+    // spirv_instruction
+    TString set;
+    int     id;
+};
+
+// SPIR-V type parameter
+struct TSpirvTypeParameter {
+    POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
+
+    TSpirvTypeParameter(const TIntermConstantUnion* arg) { isConstant = true; constant = arg; }
+    TSpirvTypeParameter(const TType* arg) { isConstant = false; type = arg; }
+
+    bool operator==(const TSpirvTypeParameter& rhs) const
+    {
+        return isConstant == rhs.isConstant && ((isConstant && constant == rhs.constant) || (!isConstant && type == rhs.type));
+    }
+    bool operator!=(const TSpirvTypeParameter& rhs) const { return !operator==(rhs); }
+
+    bool isConstant;
+    union {
+        const TIntermConstantUnion* constant;
+        const TType* type;
+    };
+};
+
+typedef TVector<TSpirvTypeParameter> TSpirvTypeParameters;
+
+// SPIR-V type
+struct TSpirvType {
+    POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
+
+    bool operator==(const TSpirvType& rhs) const
+    {
+        return spirvInst == rhs.spirvInst && typeParams == rhs.typeParams;
+    }
+    bool operator!=(const TSpirvType& rhs) const { return !operator==(rhs); }
+
+    // spirv_type
+    TSpirvInstruction spirvInst;
+    TSpirvTypeParameters typeParams;
+};
+
+} // end namespace glslang
+
+#endif // GLSLANG_WEB

+ 112 - 4
3rdparty/glslang/glslang/Include/Types.h

@@ -44,11 +44,14 @@
 #include "../Include/BaseTypes.h"
 #include "../Include/BaseTypes.h"
 #include "../Public/ShaderLang.h"
 #include "../Public/ShaderLang.h"
 #include "arrays.h"
 #include "arrays.h"
+#include "SpirvIntrinsics.h"
 
 
 #include <algorithm>
 #include <algorithm>
 
 
 namespace glslang {
 namespace glslang {
 
 
+class TIntermAggregate;
+
 const int GlslangMaxTypeLength = 200;  // TODO: need to print block/struct one member per line, so this can stay bounded
 const int GlslangMaxTypeLength = 200;  // TODO: need to print block/struct one member per line, so this can stay bounded
 
 
 const char* const AnonymousPrefix = "anon@"; // for something like a block whose members can be directly accessed
 const char* const AnonymousPrefix = "anon@"; // for something like a block whose members can be directly accessed
@@ -487,7 +490,6 @@ enum TShaderInterface
     EsiCount
     EsiCount
 };
 };
 
 
-
 class TQualifier {
 class TQualifier {
 public:
 public:
     static const int layoutNotSet = -1;
     static const int layoutNotSet = -1;
@@ -501,6 +503,8 @@ public:
 #ifndef GLSLANG_WEB
 #ifndef GLSLANG_WEB
         noContraction = false;
         noContraction = false;
         nullInit = false;
         nullInit = false;
+        spirvByReference = false;
+        spirvLiteral = false;
 #endif
 #endif
         defaultBlock = false;
         defaultBlock = false;
     }
     }
@@ -518,6 +522,12 @@ public:
         nullInit = false;
         nullInit = false;
         defaultBlock = false;
         defaultBlock = false;
         clearLayout();
         clearLayout();
+#ifndef GLSLANG_WEB
+        spirvStorageClass = -1;
+        spirvDecorate = nullptr;
+        spirvByReference = false;
+        spirvLiteral = false;
+#endif
     }
     }
 
 
     void clearInterstage()
     void clearInterstage()
@@ -596,6 +606,10 @@ public:
     bool isPervertexNV() const { return false; }
     bool isPervertexNV() const { return false; }
     void setNullInit() { }
     void setNullInit() { }
     bool isNullInit() const { return false; }
     bool isNullInit() const { return false; }
+    void setSpirvByReference() { }
+    bool isSpirvByReference() { return false; }
+    void setSpirvLiteral() { }
+    bool isSpirvLiteral() { return false; }
 #else
 #else
     bool noContraction: 1; // prevent contraction and reassociation, e.g., for 'precise' keyword, and expressions it affects
     bool noContraction: 1; // prevent contraction and reassociation, e.g., for 'precise' keyword, and expressions it affects
     bool nopersp      : 1;
     bool nopersp      : 1;
@@ -618,6 +632,8 @@ public:
     bool shadercallcoherent : 1;
     bool shadercallcoherent : 1;
     bool nonprivate   : 1;
     bool nonprivate   : 1;
     bool nullInit : 1;
     bool nullInit : 1;
+    bool spirvByReference : 1;
+    bool spirvLiteral : 1;
     bool isWriteOnly() const { return writeonly; }
     bool isWriteOnly() const { return writeonly; }
     bool isReadOnly() const { return readonly; }
     bool isReadOnly() const { return readonly; }
     bool isRestrict() const { return restrict; }
     bool isRestrict() const { return restrict; }
@@ -655,6 +671,10 @@ public:
     bool isPervertexNV() const { return pervertexNV; }
     bool isPervertexNV() const { return pervertexNV; }
     void setNullInit() { nullInit = true; }
     void setNullInit() { nullInit = true; }
     bool isNullInit() const { return nullInit; }
     bool isNullInit() const { return nullInit; }
+    void setSpirvByReference() { spirvByReference = true; }
+    bool isSpirvByReference() const { return spirvByReference; }
+    void setSpirvLiteral() { spirvLiteral = true; }
+    bool isSpirvLiteral() const { return spirvLiteral; }
 #endif
 #endif
 
 
     bool isPipeInput() const
     bool isPipeInput() const
@@ -948,6 +968,10 @@ public:
     bool layoutViewportRelative;
     bool layoutViewportRelative;
     int layoutSecondaryViewportRelativeOffset;
     int layoutSecondaryViewportRelativeOffset;
     bool layoutShaderRecord;
     bool layoutShaderRecord;
+
+    // GL_EXT_spirv_intrinsics
+    int spirvStorageClass;
+    TSpirvDecorate* spirvDecorate;
 #endif
 #endif
 
 
     bool hasUniformLayout() const
     bool hasUniformLayout() const
@@ -1079,6 +1103,15 @@ public:
     {
     {
         return nonUniform;
         return nonUniform;
     }
     }
+
+    // GL_EXT_spirv_intrinsics
+    bool hasSprivDecorate() const { return spirvDecorate != nullptr; }
+    void setSpirvDecorate(int decoration, const TIntermAggregate* args = nullptr);
+    void setSpirvDecorateId(int decoration, const TIntermAggregate* args);
+    void setSpirvDecorateString(int decoration, const TIntermAggregate* args);
+    const TSpirvDecorate& getSpirvDecorate() const { assert(spirvDecorate); return *spirvDecorate; }
+    TSpirvDecorate& getSpirvDecorate() { assert(spirvDecorate); return *spirvDecorate; }
+    TString getSpirvDecorateQualifierString() const;
 #endif
 #endif
     bool hasSpecConstantId() const
     bool hasSpecConstantId() const
     {
     {
@@ -1423,6 +1456,10 @@ public:
     const TType* userDef;
     const TType* userDef;
     TSourceLoc loc;
     TSourceLoc loc;
     TArraySizes* typeParameters;
     TArraySizes* typeParameters;
+#ifndef GLSLANG_WEB
+    // SPIR-V type defined by spirv_type directive
+    TSpirvType* spirvType;
+#endif
 
 
 #ifdef GLSLANG_WEB
 #ifdef GLSLANG_WEB
     bool isCoopmat() const { return false; }
     bool isCoopmat() const { return false; }
@@ -1441,6 +1478,9 @@ public:
         loc = l;
         loc = l;
         typeParameters = nullptr;
         typeParameters = nullptr;
         coopmat = false;
         coopmat = false;
+#ifndef GLSLANG_WEB
+        spirvType = nullptr;
+#endif
     }
     }
 
 
     void initQualifiers(bool global = false)
     void initQualifiers(bool global = false)
@@ -1477,6 +1517,11 @@ public:
         return matrixCols == 0 && vectorSize == 1 && arraySizes == nullptr && userDef == nullptr;
         return matrixCols == 0 && vectorSize == 1 && arraySizes == nullptr && userDef == nullptr;
     }
     }
 
 
+#ifndef GLSLANG_WEB
+    // GL_EXT_spirv_intrinsics
+    void setSpirvType(const TSpirvInstruction& spirvInst, const TSpirvTypeParameters* typeParams = nullptr);
+#endif
+
     // "Image" is a superset of "Subpass"
     // "Image" is a superset of "Subpass"
     bool isImage()   const { return basicType == EbtSampler && sampler.isImage(); }
     bool isImage()   const { return basicType == EbtSampler && sampler.isImage(); }
     bool isSubpass() const { return basicType == EbtSampler && sampler.isSubpass(); }
     bool isSubpass() const { return basicType == EbtSampler && sampler.isSubpass(); }
@@ -1494,6 +1539,9 @@ public:
                    bool isVector = false) :
                    bool isVector = false) :
                             basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), vector1(isVector && vs == 1), coopmat(false),
                             basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), vector1(isVector && vs == 1), coopmat(false),
                             arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(nullptr)
                             arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(nullptr)
+#ifndef GLSLANG_WEB
+                            , spirvType(nullptr)
+#endif
                             {
                             {
                                 sampler.clear();
                                 sampler.clear();
                                 qualifier.clear();
                                 qualifier.clear();
@@ -1505,6 +1553,9 @@ public:
           bool isVector = false) :
           bool isVector = false) :
                             basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), vector1(isVector && vs == 1), coopmat(false),
                             basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), vector1(isVector && vs == 1), coopmat(false),
                             arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(nullptr)
                             arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(nullptr)
+#ifndef GLSLANG_WEB
+                            , spirvType(nullptr)
+#endif
                             {
                             {
                                 sampler.clear();
                                 sampler.clear();
                                 qualifier.clear();
                                 qualifier.clear();
@@ -1518,6 +1569,9 @@ public:
                             basicType(p.basicType),
                             basicType(p.basicType),
                             vectorSize(p.vectorSize), matrixCols(p.matrixCols), matrixRows(p.matrixRows), vector1(false), coopmat(p.coopmat),
                             vectorSize(p.vectorSize), matrixCols(p.matrixCols), matrixRows(p.matrixRows), vector1(false), coopmat(p.coopmat),
                             arraySizes(p.arraySizes), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(p.typeParameters)
                             arraySizes(p.arraySizes), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(p.typeParameters)
+#ifndef GLSLANG_WEB
+                            , spirvType(p.spirvType)
+#endif
                             {
                             {
                                 if (basicType == EbtSampler)
                                 if (basicType == EbtSampler)
                                     sampler = p.sampler;
                                     sampler = p.sampler;
@@ -1552,6 +1606,9 @@ public:
         basicType(EbtSampler), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false),
         basicType(EbtSampler), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false),
         arraySizes(as), structure(nullptr), fieldName(nullptr), typeName(nullptr),
         arraySizes(as), structure(nullptr), fieldName(nullptr), typeName(nullptr),
         sampler(sampler), typeParameters(nullptr)
         sampler(sampler), typeParameters(nullptr)
+#ifndef GLSLANG_WEB
+        , spirvType(nullptr)
+#endif
     {
     {
         qualifier.clear();
         qualifier.clear();
         qualifier.storage = q;
         qualifier.storage = q;
@@ -1602,6 +1659,9 @@ public:
     TType(TTypeList* userDef, const TString& n) :
     TType(TTypeList* userDef, const TString& n) :
                             basicType(EbtStruct), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false),
                             basicType(EbtStruct), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false),
                             arraySizes(nullptr), structure(userDef), fieldName(nullptr), typeParameters(nullptr)
                             arraySizes(nullptr), structure(userDef), fieldName(nullptr), typeParameters(nullptr)
+#ifndef GLSLANG_WEB
+                            , spirvType(nullptr)
+#endif
                             {
                             {
                                 sampler.clear();
                                 sampler.clear();
                                 qualifier.clear();
                                 qualifier.clear();
@@ -1611,6 +1671,9 @@ public:
     TType(TTypeList* userDef, const TString& n, const TQualifier& q) :
     TType(TTypeList* userDef, const TString& n, const TQualifier& q) :
                             basicType(EbtBlock), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false),
                             basicType(EbtBlock), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false),
                             qualifier(q), arraySizes(nullptr), structure(userDef), fieldName(nullptr), typeParameters(nullptr)
                             qualifier(q), arraySizes(nullptr), structure(userDef), fieldName(nullptr), typeParameters(nullptr)
+#ifndef GLSLANG_WEB
+                            , spirvType(nullptr)
+#endif
                             {
                             {
                                 sampler.clear();
                                 sampler.clear();
                                 typeName = NewPoolTString(n.c_str());
                                 typeName = NewPoolTString(n.c_str());
@@ -1619,6 +1682,9 @@ public:
     explicit TType(TBasicType t, const TType &p, const TString& n) :
     explicit TType(TBasicType t, const TType &p, const TString& n) :
                             basicType(t), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false),
                             basicType(t), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false),
                             arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr)
                             arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr)
+#ifndef GLSLANG_WEB
+                            , spirvType(nullptr)
+#endif
                             {
                             {
                                 assert(t == EbtReference);
                                 assert(t == EbtReference);
                                 typeName = NewPoolTString(n.c_str());
                                 typeName = NewPoolTString(n.c_str());
@@ -1649,6 +1715,9 @@ public:
             referentType = copyOf.referentType;
             referentType = copyOf.referentType;
         }
         }
         typeParameters = copyOf.typeParameters;
         typeParameters = copyOf.typeParameters;
+#ifndef GLSLANG_WEB
+        spirvType = copyOf.spirvType;
+#endif
         coopmat = copyOf.isCoopMat();
         coopmat = copyOf.isCoopMat();
     }
     }
 
 
@@ -1770,7 +1839,7 @@ public:
     }
     }
     virtual bool isOpaque() const { return basicType == EbtSampler
     virtual bool isOpaque() const { return basicType == EbtSampler
 #ifndef GLSLANG_WEB
 #ifndef GLSLANG_WEB
-         || basicType == EbtAtomicUint || basicType == EbtAccStruct || basicType == EbtRayQuery
+            || basicType == EbtAtomicUint || basicType == EbtAccStruct || basicType == EbtRayQuery
 #endif
 #endif
         ; }
         ; }
     virtual bool isBuiltIn() const { return getQualifier().builtIn != EbvNone; }
     virtual bool isBuiltIn() const { return getQualifier().builtIn != EbvNone; }
@@ -2018,8 +2087,6 @@ public:
         }
         }
     }
     }
 
 
-
-
     const char* getBasicString() const
     const char* getBasicString() const
     {
     {
         return TType::getBasicString(basicType);
         return TType::getBasicString(basicType);
@@ -2050,6 +2117,7 @@ public:
         case EbtRayQuery:          return "rayQueryEXT";
         case EbtRayQuery:          return "rayQueryEXT";
         case EbtReference:         return "reference";
         case EbtReference:         return "reference";
         case EbtString:            return "string";
         case EbtString:            return "string";
+        case EbtSpirvType:         return "spirv_type";
 #endif
 #endif
         default:                   return "unknown type";
         default:                   return "unknown type";
         }
         }
@@ -2070,6 +2138,9 @@ public:
         const auto appendUint = [&](unsigned int u) { typeString.append(std::to_string(u).c_str()); };
         const auto appendUint = [&](unsigned int u) { typeString.append(std::to_string(u).c_str()); };
         const auto appendInt  = [&](int i)          { typeString.append(std::to_string(i).c_str()); };
         const auto appendInt  = [&](int i)          { typeString.append(std::to_string(i).c_str()); };
 
 
+        if (qualifier.hasSprivDecorate())
+            appendStr(qualifier.getSpirvDecorateQualifierString().c_str());
+
         if (qualifier.hasLayout()) {
         if (qualifier.hasLayout()) {
             // To reduce noise, skip this if the only layout is an xfb_buffer
             // To reduce noise, skip this if the only layout is an xfb_buffer
             // with no triggering xfb_offset.
             // with no triggering xfb_offset.
@@ -2219,6 +2290,10 @@ public:
             appendStr(" nonuniform");
             appendStr(" nonuniform");
         if (qualifier.isNullInit())
         if (qualifier.isNullInit())
             appendStr(" null-init");
             appendStr(" null-init");
+        if (qualifier.isSpirvByReference())
+            appendStr(" spirv_by_reference");
+        if (qualifier.isSpirvLiteral())
+            appendStr(" spirv_literal");
         appendStr(" ");
         appendStr(" ");
         appendStr(getStorageQualifierString());
         appendStr(getStorageQualifierString());
         if (isArray()) {
         if (isArray()) {
@@ -2455,6 +2530,15 @@ public:
                 (typeParameters != nullptr && right.typeParameters != nullptr && *typeParameters == *right.typeParameters));
                 (typeParameters != nullptr && right.typeParameters != nullptr && *typeParameters == *right.typeParameters));
     }
     }
 
 
+#ifndef GLSLANG_WEB
+    // See if two type's SPIR-V type contents match
+    bool sameSpirvType(const TType& right) const
+    {
+        return ((spirvType == nullptr && right.spirvType == nullptr) ||
+                (spirvType != nullptr && right.spirvType != nullptr && *spirvType == *right.spirvType));
+    }
+#endif
+
     // See if two type's elements match in all ways except basic type
     // See if two type's elements match in all ways except basic type
     bool sameElementShape(const TType& right) const
     bool sameElementShape(const TType& right) const
     {
     {
@@ -2493,7 +2577,11 @@ public:
     // See if two types match in all ways (just the actual type, not qualification)
     // See if two types match in all ways (just the actual type, not qualification)
     bool operator==(const TType& right) const
     bool operator==(const TType& right) const
     {
     {
+#ifndef GLSLANG_WEB
+        return sameElementType(right) && sameArrayness(right) && sameTypeParameters(right) && sameSpirvType(right);
+#else
         return sameElementType(right) && sameArrayness(right) && sameTypeParameters(right);
         return sameElementType(right) && sameArrayness(right) && sameTypeParameters(right);
+#endif
     }
     }
 
 
     bool operator!=(const TType& right) const
     bool operator!=(const TType& right) const
@@ -2512,6 +2600,10 @@ public:
         return 0;
         return 0;
     }
     }
 
 
+#ifndef GLSLANG_WEB
+    const TSpirvType& getSpirvType() const { assert(spirvType); return *spirvType; }
+#endif
+
 protected:
 protected:
     // Require consumer to pick between deep copy and shallow copy.
     // Require consumer to pick between deep copy and shallow copy.
     TType(const TType& type);
     TType(const TType& type);
@@ -2524,6 +2616,19 @@ protected:
     {
     {
         shallowCopy(copyOf);
         shallowCopy(copyOf);
 
 
+#ifndef GLSLANG_WEB
+        // GL_EXT_spirv_intrinsics
+        if (copyOf.qualifier.spirvDecorate) {
+            qualifier.spirvDecorate = new TSpirvDecorate;
+            *qualifier.spirvDecorate = *copyOf.qualifier.spirvDecorate;
+        }
+
+        if (copyOf.spirvType) {
+            spirvType = new TSpirvType;
+            *spirvType = *copyOf.spirvType;
+        }
+#endif
+
         if (copyOf.arraySizes) {
         if (copyOf.arraySizes) {
             arraySizes = new TArraySizes;
             arraySizes = new TArraySizes;
             *arraySizes = *copyOf.arraySizes;
             *arraySizes = *copyOf.arraySizes;
@@ -2583,6 +2688,9 @@ protected:
     TString *typeName;          // for structure type name
     TString *typeName;          // for structure type name
     TSampler sampler;
     TSampler sampler;
     TArraySizes* typeParameters;// nullptr unless a parameterized type; can be shared across types
     TArraySizes* typeParameters;// nullptr unless a parameterized type; can be shared across types
+#ifndef GLSLANG_WEB
+    TSpirvType* spirvType;  // SPIR-V type defined by spirv_type directive
+#endif
 };
 };
 
 
 } // end namespace glslang
 } // end namespace glslang

+ 17 - 0
3rdparty/glslang/glslang/Include/intermediate.h

@@ -71,6 +71,9 @@ enum TOperator {
     EOpFunctionCall,
     EOpFunctionCall,
     EOpFunction,        // For function definition
     EOpFunction,        // For function definition
     EOpParameters,      // an aggregate listing the parameters to a function
     EOpParameters,      // an aggregate listing the parameters to a function
+#ifndef GLSLANG_WEB
+    EOpSpirvInst,
+#endif
 
 
     //
     //
     // Unary operators
     // Unary operators
@@ -1616,8 +1619,15 @@ public:
     virtual       TIntermUnary* getAsUnaryNode()       { return this; }
     virtual       TIntermUnary* getAsUnaryNode()       { return this; }
     virtual const TIntermUnary* getAsUnaryNode() const { return this; }
     virtual const TIntermUnary* getAsUnaryNode() const { return this; }
     virtual void updatePrecision();
     virtual void updatePrecision();
+#ifndef GLSLANG_WEB
+    void setSpirvInstruction(const TSpirvInstruction& inst) { spirvInst = inst; }
+    const TSpirvInstruction& getSpirvInstruction() const { return spirvInst; }
+#endif
 protected:
 protected:
     TIntermTyped* operand;
     TIntermTyped* operand;
+#ifndef GLSLANG_WEB
+    TSpirvInstruction spirvInst;
+#endif
 };
 };
 
 
 typedef TVector<TIntermNode*> TIntermSequence;
 typedef TVector<TIntermNode*> TIntermSequence;
@@ -1648,6 +1658,10 @@ public:
     bool getDebug() const { return debug; }
     bool getDebug() const { return debug; }
     void setPragmaTable(const TPragmaTable& pTable);
     void setPragmaTable(const TPragmaTable& pTable);
     const TPragmaTable& getPragmaTable() const { return *pragmaTable; }
     const TPragmaTable& getPragmaTable() const { return *pragmaTable; }
+#ifndef GLSLANG_WEB
+    void setSpirvInstruction(const TSpirvInstruction& inst) { spirvInst = inst; }
+    const TSpirvInstruction& getSpirvInstruction() const { return spirvInst; }
+#endif
 protected:
 protected:
     TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
     TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
     TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator
     TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator
@@ -1658,6 +1672,9 @@ protected:
     bool optimize;
     bool optimize;
     bool debug;
     bool debug;
     TPragmaTable* pragmaTable;
     TPragmaTable* pragmaTable;
+#ifndef GLSLANG_WEB
+    TSpirvInstruction spirvInst;
+#endif
 };
 };
 
 
 //
 //

+ 43 - 2
3rdparty/glslang/glslang/MachineIndependent/Initialize.cpp

@@ -483,7 +483,8 @@ void TBuiltIns::relateTabledBuiltins(int /* version */, EProfile /* profile */,
 
 
 inline bool IncludeLegacy(int version, EProfile profile, const SpvVersion& spvVersion)
 inline bool IncludeLegacy(int version, EProfile profile, const SpvVersion& spvVersion)
 {
 {
-    return profile != EEsProfile && (version <= 130 || (spvVersion.spv == 0 && ARBCompatibility) || profile == ECompatibilityProfile);
+    return profile != EEsProfile && (version <= 130 || (spvVersion.spv == 0 && version == 140 && ARBCompatibility) ||
+           profile == ECompatibilityProfile);
 }
 }
 
 
 // Construct TBuiltInParseables base class.  This can be used for language-common constructs.
 // Construct TBuiltInParseables base class.  This can be used for language-common constructs.
@@ -1436,11 +1437,23 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
             " int64_t atomicMin(coherent volatile inout  int64_t,  int64_t);"
             " int64_t atomicMin(coherent volatile inout  int64_t,  int64_t);"
             "uint64_t atomicMin(coherent volatile inout uint64_t, uint64_t, int, int, int);"
             "uint64_t atomicMin(coherent volatile inout uint64_t, uint64_t, int, int, int);"
             " int64_t atomicMin(coherent volatile inout  int64_t,  int64_t, int, int, int);"
             " int64_t atomicMin(coherent volatile inout  int64_t,  int64_t, int, int, int);"
+            "float16_t atomicMin(coherent volatile inout float16_t, float16_t);"
+            "float16_t atomicMin(coherent volatile inout float16_t, float16_t, int, int, int);"
+            "   float atomicMin(coherent volatile inout float, float);"
+            "   float atomicMin(coherent volatile inout float, float, int, int, int);"
+            "  double atomicMin(coherent volatile inout double, double);"
+            "  double atomicMin(coherent volatile inout double, double, int, int, int);"
 
 
             "uint64_t atomicMax(coherent volatile inout uint64_t, uint64_t);"
             "uint64_t atomicMax(coherent volatile inout uint64_t, uint64_t);"
             " int64_t atomicMax(coherent volatile inout  int64_t,  int64_t);"
             " int64_t atomicMax(coherent volatile inout  int64_t,  int64_t);"
             "uint64_t atomicMax(coherent volatile inout uint64_t, uint64_t, int, int, int);"
             "uint64_t atomicMax(coherent volatile inout uint64_t, uint64_t, int, int, int);"
             " int64_t atomicMax(coherent volatile inout  int64_t,  int64_t, int, int, int);"
             " int64_t atomicMax(coherent volatile inout  int64_t,  int64_t, int, int, int);"
+            "float16_t atomicMax(coherent volatile inout float16_t, float16_t);"
+            "float16_t atomicMax(coherent volatile inout float16_t, float16_t, int, int, int);"
+            "   float atomicMax(coherent volatile inout float, float);"
+            "   float atomicMax(coherent volatile inout float, float, int, int, int);"
+            "  double atomicMax(coherent volatile inout double, double);"
+            "  double atomicMax(coherent volatile inout double, double, int, int, int);"
 
 
             "uint64_t atomicAnd(coherent volatile inout uint64_t, uint64_t);"
             "uint64_t atomicAnd(coherent volatile inout uint64_t, uint64_t);"
             " int64_t atomicAnd(coherent volatile inout  int64_t,  int64_t);"
             " int64_t atomicAnd(coherent volatile inout  int64_t,  int64_t);"
@@ -1461,6 +1474,8 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
             " int64_t atomicAdd(coherent volatile inout  int64_t,  int64_t);"
             " int64_t atomicAdd(coherent volatile inout  int64_t,  int64_t);"
             "uint64_t atomicAdd(coherent volatile inout uint64_t, uint64_t, int, int, int);"
             "uint64_t atomicAdd(coherent volatile inout uint64_t, uint64_t, int, int, int);"
             " int64_t atomicAdd(coherent volatile inout  int64_t,  int64_t, int, int, int);"
             " int64_t atomicAdd(coherent volatile inout  int64_t,  int64_t, int, int, int);"
+            "float16_t atomicAdd(coherent volatile inout float16_t, float16_t);"
+            "float16_t atomicAdd(coherent volatile inout float16_t, float16_t, int, int, int);"
             "   float atomicAdd(coherent volatile inout float, float);"
             "   float atomicAdd(coherent volatile inout float, float);"
             "   float atomicAdd(coherent volatile inout float, float, int, int, int);"
             "   float atomicAdd(coherent volatile inout float, float, int, int, int);"
             "  double atomicAdd(coherent volatile inout double, double);"
             "  double atomicAdd(coherent volatile inout double, double);"
@@ -1470,6 +1485,8 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
             " int64_t atomicExchange(coherent volatile inout  int64_t,  int64_t);"
             " int64_t atomicExchange(coherent volatile inout  int64_t,  int64_t);"
             "uint64_t atomicExchange(coherent volatile inout uint64_t, uint64_t, int, int, int);"
             "uint64_t atomicExchange(coherent volatile inout uint64_t, uint64_t, int, int, int);"
             " int64_t atomicExchange(coherent volatile inout  int64_t,  int64_t, int, int, int);"
             " int64_t atomicExchange(coherent volatile inout  int64_t,  int64_t, int, int, int);"
+            "float16_t atomicExchange(coherent volatile inout float16_t, float16_t);"
+            "float16_t atomicExchange(coherent volatile inout float16_t, float16_t, int, int, int);"
             "   float atomicExchange(coherent volatile inout float, float);"
             "   float atomicExchange(coherent volatile inout float, float);"
             "   float atomicExchange(coherent volatile inout float, float, int, int, int);"
             "   float atomicExchange(coherent volatile inout float, float, int, int, int);"
             "  double atomicExchange(coherent volatile inout double, double);"
             "  double atomicExchange(coherent volatile inout double, double);"
@@ -1482,11 +1499,13 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
 
 
             "uint64_t atomicLoad(coherent volatile in uint64_t, int, int, int);"
             "uint64_t atomicLoad(coherent volatile in uint64_t, int, int, int);"
             " int64_t atomicLoad(coherent volatile in  int64_t, int, int, int);"
             " int64_t atomicLoad(coherent volatile in  int64_t, int, int, int);"
+            "float16_t atomicLoad(coherent volatile in float16_t, int, int, int);"
             "   float atomicLoad(coherent volatile in float, int, int, int);"
             "   float atomicLoad(coherent volatile in float, int, int, int);"
             "  double atomicLoad(coherent volatile in double, int, int, int);"
             "  double atomicLoad(coherent volatile in double, int, int, int);"
 
 
             "void atomicStore(coherent volatile out uint64_t, uint64_t, int, int, int);"
             "void atomicStore(coherent volatile out uint64_t, uint64_t, int, int, int);"
             "void atomicStore(coherent volatile out  int64_t,  int64_t, int, int, int);"
             "void atomicStore(coherent volatile out  int64_t,  int64_t, int, int, int);"
+            "void atomicStore(coherent volatile out float16_t, float16_t, int, int, int);"
             "void atomicStore(coherent volatile out float, float, int, int, int);"
             "void atomicStore(coherent volatile out float, float, int, int, int);"
             "void atomicStore(coherent volatile out double, double, int, int, int);"
             "void atomicStore(coherent volatile out double, double, int, int, int);"
             "\n");
             "\n");
@@ -6478,6 +6497,24 @@ void TBuiltIns::addImageFunctions(TSampler sampler, const TString& typeName, int
                 commonBuiltins.append(imageParams);
                 commonBuiltins.append(imageParams);
                 commonBuiltins.append(", float");
                 commonBuiltins.append(", float");
                 commonBuiltins.append(", int, int, int);\n");
                 commonBuiltins.append(", int, int, int);\n");
+
+                commonBuiltins.append("float imageAtomicMin(volatile coherent ");
+                commonBuiltins.append(imageParams);
+                commonBuiltins.append(", float);\n");
+
+                commonBuiltins.append("float imageAtomicMin(volatile coherent ");
+                commonBuiltins.append(imageParams);
+                commonBuiltins.append(", float");
+                commonBuiltins.append(", int, int, int);\n");
+
+                commonBuiltins.append("float imageAtomicMax(volatile coherent ");
+                commonBuiltins.append(imageParams);
+                commonBuiltins.append(", float);\n");
+
+                commonBuiltins.append("float imageAtomicMax(volatile coherent ");
+                commonBuiltins.append(imageParams);
+                commonBuiltins.append(", float");
+                commonBuiltins.append(", int, int, int);\n");
             }
             }
         }
         }
     }
     }
@@ -7246,6 +7283,9 @@ void TBuiltIns::initialize(const TBuiltInResource &resources, int version, EProf
 
 
             snprintf(builtInConstant, maxSize, "const int  gl_MaxFragmentUniformVectors = %d;", resources.maxFragmentUniformVectors);
             snprintf(builtInConstant, maxSize, "const int  gl_MaxFragmentUniformVectors = %d;", resources.maxFragmentUniformVectors);
             s.append(builtInConstant);
             s.append(builtInConstant);
+
+            snprintf(builtInConstant, maxSize, "const int  gl_MaxVaryingVectors = %d;", resources.maxVaryingVectors);
+            s.append(builtInConstant);
         }
         }
 
 
         snprintf(builtInConstant, maxSize, "const int  gl_MaxVertexAttribs = %d;", resources.maxVertexAttribs);
         snprintf(builtInConstant, maxSize, "const int  gl_MaxVertexAttribs = %d;", resources.maxVertexAttribs);
@@ -7278,7 +7318,8 @@ void TBuiltIns::initialize(const TBuiltInResource &resources, int version, EProf
         snprintf(builtInConstant, maxSize, "const int  gl_MaxVertexUniformComponents = %d;", resources.maxVertexUniformComponents);
         snprintf(builtInConstant, maxSize, "const int  gl_MaxVertexUniformComponents = %d;", resources.maxVertexUniformComponents);
         s.append(builtInConstant);
         s.append(builtInConstant);
 
 
-        if (version < 150 || ARBCompatibility) {
+        // Moved from just being deprecated into compatibility profile only as of 4.20
+        if (version < 420 || profile == ECompatibilityProfile) {
             snprintf(builtInConstant, maxSize, "const int  gl_MaxVaryingFloats = %d;", resources.maxVaryingFloats);
             snprintf(builtInConstant, maxSize, "const int  gl_MaxVaryingFloats = %d;", resources.maxVaryingFloats);
             s.append(builtInConstant);
             s.append(builtInConstant);
         }
         }

+ 176 - 15
3rdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp

@@ -1092,12 +1092,31 @@ TFunction* TParseContext::handleFunctionDeclarator(const TSourceLoc& loc, TFunct
     TSymbol* symbol = symbolTable.find(function.getMangledName(), &builtIn);
     TSymbol* symbol = symbolTable.find(function.getMangledName(), &builtIn);
     if (symbol && symbol->getAsFunction() && builtIn)
     if (symbol && symbol->getAsFunction() && builtIn)
         requireProfile(loc, ~EEsProfile, "redefinition of built-in function");
         requireProfile(loc, ~EEsProfile, "redefinition of built-in function");
+#ifndef GLSLANG_WEB
+    // Check the validity of using spirv_literal qualifier
+    for (int i = 0; i < function.getParamCount(); ++i) {
+        if (function[i].type->getQualifier().isSpirvLiteral() && function.getBuiltInOp() != EOpSpirvInst)
+            error(loc, "'spirv_literal' can only be used on functions defined with 'spirv_instruction' for argument",
+                  function.getName().c_str(), "%d", i + 1);
+    }
+
+    // For function declaration with SPIR-V instruction qualifier, always ignore the built-in function and
+    // respect this redeclared one.
+    if (symbol && builtIn && function.getBuiltInOp() == EOpSpirvInst)
+        symbol = nullptr;
+#endif
     const TFunction* prevDec = symbol ? symbol->getAsFunction() : 0;
     const TFunction* prevDec = symbol ? symbol->getAsFunction() : 0;
     if (prevDec) {
     if (prevDec) {
         if (prevDec->isPrototyped() && prototype)
         if (prevDec->isPrototyped() && prototype)
             profileRequires(loc, EEsProfile, 300, nullptr, "multiple prototypes for same function");
             profileRequires(loc, EEsProfile, 300, nullptr, "multiple prototypes for same function");
         if (prevDec->getType() != function.getType())
         if (prevDec->getType() != function.getType())
             error(loc, "overloaded functions must have the same return type", function.getName().c_str(), "");
             error(loc, "overloaded functions must have the same return type", function.getName().c_str(), "");
+#ifndef GLSLANG_WEB
+        if (prevDec->getSpirvInstruction() != function.getSpirvInstruction()) {
+            error(loc, "overloaded functions must have the same qualifiers", function.getName().c_str(),
+                  "spirv_instruction");
+        }
+#endif
         for (int i = 0; i < prevDec->getParamCount(); ++i) {
         for (int i = 0; i < prevDec->getParamCount(); ++i) {
             if ((*prevDec)[i].type->getQualifier().storage != function[i].type->getQualifier().storage)
             if ((*prevDec)[i].type->getQualifier().storage != function[i].type->getQualifier().storage)
                 error(loc, "overloaded functions must have the same parameter storage qualifiers for argument", function[i].type->getStorageQualifierString(), "%d", i+1);
                 error(loc, "overloaded functions must have the same parameter storage qualifiers for argument", function[i].type->getStorageQualifierString(), "%d", i+1);
@@ -1299,6 +1318,15 @@ TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction
                         if (lValueErrorCheck(arguments->getLoc(), "assign", arg->getAsTyped()))
                         if (lValueErrorCheck(arguments->getLoc(), "assign", arg->getAsTyped()))
                             error(arguments->getLoc(), "Non-L-value cannot be passed for 'out' or 'inout' parameters.", "out", "");
                             error(arguments->getLoc(), "Non-L-value cannot be passed for 'out' or 'inout' parameters.", "out", "");
                     }
                     }
+#ifndef GLSLANG_WEB
+                    if (formalQualifier.isSpirvLiteral()) {
+                        if (!arg->getAsTyped()->getQualifier().isFrontEndConstant()) {
+                            error(arguments->getLoc(),
+                                  "Non front-end constant expressions cannot be passed for 'spirv_literal' parameters.",
+                                  "spirv_literal", "");
+                        }
+                    }
+#endif
                     const TType& argType = arg->getAsTyped()->getType();
                     const TType& argType = arg->getAsTyped()->getType();
                     const TQualifier& argQualifier = argType.getQualifier();
                     const TQualifier& argQualifier = argType.getQualifier();
                     if (argQualifier.isMemory() && (argType.containsOpaque() || argType.isReference())) {
                     if (argQualifier.isMemory() && (argType.containsOpaque() || argType.isReference())) {
@@ -1353,6 +1381,11 @@ TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction
             if (builtIn && fnCandidate->getBuiltInOp() != EOpNull) {
             if (builtIn && fnCandidate->getBuiltInOp() != EOpNull) {
                 // A function call mapped to a built-in operation.
                 // A function call mapped to a built-in operation.
                 result = handleBuiltInFunctionCall(loc, arguments, *fnCandidate);
                 result = handleBuiltInFunctionCall(loc, arguments, *fnCandidate);
+#ifndef GLSLANG_WEB
+            } else if (fnCandidate->getBuiltInOp() == EOpSpirvInst) {
+                // When SPIR-V instruction qualifier is specified, the function call is still mapped to a built-in operation.
+                result = handleBuiltInFunctionCall(loc, arguments, *fnCandidate);
+#endif
             } else {
             } else {
                 // This is a function call not mapped to built-in operator.
                 // This is a function call not mapped to built-in operator.
                 // It could still be a built-in function, but only if PureOperatorBuiltins == false.
                 // It could still be a built-in function, but only if PureOperatorBuiltins == false.
@@ -1430,6 +1463,35 @@ TIntermTyped* TParseContext::handleBuiltInFunctionCall(TSourceLoc loc, TIntermNo
     } else if (result->getAsOperator())
     } else if (result->getAsOperator())
         builtInOpCheck(loc, function, *result->getAsOperator());
         builtInOpCheck(loc, function, *result->getAsOperator());
 
 
+#ifndef GLSLANG_WEB
+    // Special handling for function call with SPIR-V instruction qualifier specified
+    if (function.getBuiltInOp() == EOpSpirvInst) {
+        if (auto agg = result->getAsAggregate()) {
+            // Propogate spirv_by_reference/spirv_literal from parameters to arguments
+            auto& sequence = agg->getSequence();
+            for (unsigned i = 0; i < sequence.size(); ++i) {
+                if (function[i].type->getQualifier().isSpirvByReference())
+                    sequence[i]->getAsTyped()->getQualifier().setSpirvByReference();
+                if (function[i].type->getQualifier().isSpirvLiteral())
+                    sequence[i]->getAsTyped()->getQualifier().setSpirvLiteral();
+            }
+
+            // Attach the function call to SPIR-V intruction
+            agg->setSpirvInstruction(function.getSpirvInstruction());
+        } else if (auto unaryNode = result->getAsUnaryNode()) {
+            // Propogate spirv_by_reference/spirv_literal from parameters to arguments
+            if (function[0].type->getQualifier().isSpirvByReference())
+                unaryNode->getOperand()->getQualifier().setSpirvByReference();
+            if (function[0].type->getQualifier().isSpirvLiteral())
+                unaryNode->getOperand()->getQualifier().setSpirvLiteral();
+
+            // Attach the function call to SPIR-V intruction
+            unaryNode->setSpirvInstruction(function.getSpirvInstruction());
+        } else
+            assert(0);
+    }
+#endif
+
     return result;
     return result;
 }
 }
 
 
@@ -2279,18 +2341,23 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
                 error(loc, "only supported on image with format r64i", fnCandidate.getName().c_str(), "");
                 error(loc, "only supported on image with format r64i", fnCandidate.getName().c_str(), "");
             else if (callNode.getType().getBasicType() == EbtUint64 && imageType.getQualifier().getFormat() != ElfR64ui)
             else if (callNode.getType().getBasicType() == EbtUint64 && imageType.getQualifier().getFormat() != ElfR64ui)
                 error(loc, "only supported on image with format r64ui", fnCandidate.getName().c_str(), "");
                 error(loc, "only supported on image with format r64ui", fnCandidate.getName().c_str(), "");
-        } else {
-            bool isImageAtomicOnFloatAllowed = ((fnCandidate.getName().compare(0, 14, "imageAtomicAdd") == 0) ||
-                (fnCandidate.getName().compare(0, 15, "imageAtomicLoad") == 0) ||
-                (fnCandidate.getName().compare(0, 16, "imageAtomicStore") == 0) ||
-                (fnCandidate.getName().compare(0, 19, "imageAtomicExchange") == 0));
-            if (imageType.getSampler().type == EbtFloat && isImageAtomicOnFloatAllowed &&
-                (fnCandidate.getName().compare(0, 19, "imageAtomicExchange") != 0)) // imageAtomicExchange doesn't require GL_EXT_shader_atomic_float
+        } else if (imageType.getSampler().type == EbtFloat) {
+            if (fnCandidate.getName().compare(0, 19, "imageAtomicExchange") == 0) {
+                // imageAtomicExchange doesn't require an extension
+            } else if ((fnCandidate.getName().compare(0, 14, "imageAtomicAdd") == 0) ||
+                       (fnCandidate.getName().compare(0, 15, "imageAtomicLoad") == 0) ||
+                       (fnCandidate.getName().compare(0, 16, "imageAtomicStore") == 0)) {
                 requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float, fnCandidate.getName().c_str());
                 requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float, fnCandidate.getName().c_str());
-            if (!isImageAtomicOnFloatAllowed)
+            } else if ((fnCandidate.getName().compare(0, 14, "imageAtomicMin") == 0) ||
+                       (fnCandidate.getName().compare(0, 14, "imageAtomicMax") == 0)) {
+                requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float2, fnCandidate.getName().c_str());
+            } else {
                 error(loc, "only supported on integer images", fnCandidate.getName().c_str(), "");
                 error(loc, "only supported on integer images", fnCandidate.getName().c_str(), "");
-            else if (imageType.getQualifier().getFormat() != ElfR32f && isEsProfile())
+            }
+            if (imageType.getQualifier().getFormat() != ElfR32f && isEsProfile())
                 error(loc, "only supported on image with format r32f", fnCandidate.getName().c_str(), "");
                 error(loc, "only supported on image with format r32f", fnCandidate.getName().c_str(), "");
+        } else {
+            error(loc, "not supported on this image type", fnCandidate.getName().c_str(), "");
         }
         }
 
 
         const size_t maxArgs = imageType.getSampler().isMultiSample() ? 5 : 4;
         const size_t maxArgs = imageType.getSampler().isMultiSample() ? 5 : 4;
@@ -2319,16 +2386,28 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
             memorySemanticsCheck(loc, fnCandidate, callNode);
             memorySemanticsCheck(loc, fnCandidate, callNode);
             if ((callNode.getOp() == EOpAtomicAdd || callNode.getOp() == EOpAtomicExchange ||
             if ((callNode.getOp() == EOpAtomicAdd || callNode.getOp() == EOpAtomicExchange ||
                 callNode.getOp() == EOpAtomicLoad || callNode.getOp() == EOpAtomicStore) &&
                 callNode.getOp() == EOpAtomicLoad || callNode.getOp() == EOpAtomicStore) &&
-                (arg0->getType().isFloatingDomain())) {
+                (arg0->getType().getBasicType() == EbtFloat ||
+                 arg0->getType().getBasicType() == EbtDouble)) {
                 requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float, fnCandidate.getName().c_str());
                 requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float, fnCandidate.getName().c_str());
+            } else if ((callNode.getOp() == EOpAtomicAdd || callNode.getOp() == EOpAtomicExchange ||
+                        callNode.getOp() == EOpAtomicLoad || callNode.getOp() == EOpAtomicStore ||
+                        callNode.getOp() == EOpAtomicMin || callNode.getOp() == EOpAtomicMax) &&
+                       arg0->getType().isFloatingDomain()) {
+                requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float2, fnCandidate.getName().c_str());
             }
             }
         } else if (arg0->getType().getBasicType() == EbtInt64 || arg0->getType().getBasicType() == EbtUint64) {
         } else if (arg0->getType().getBasicType() == EbtInt64 || arg0->getType().getBasicType() == EbtUint64) {
             const char* const extensions[2] = { E_GL_NV_shader_atomic_int64,
             const char* const extensions[2] = { E_GL_NV_shader_atomic_int64,
                                                 E_GL_EXT_shader_atomic_int64 };
                                                 E_GL_EXT_shader_atomic_int64 };
             requireExtensions(loc, 2, extensions, fnCandidate.getName().c_str());
             requireExtensions(loc, 2, extensions, fnCandidate.getName().c_str());
         } else if ((callNode.getOp() == EOpAtomicAdd || callNode.getOp() == EOpAtomicExchange) &&
         } else if ((callNode.getOp() == EOpAtomicAdd || callNode.getOp() == EOpAtomicExchange) &&
-                   (arg0->getType().isFloatingDomain())) {
+                   (arg0->getType().getBasicType() == EbtFloat ||
+                    arg0->getType().getBasicType() == EbtDouble)) {
             requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float, fnCandidate.getName().c_str());
             requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float, fnCandidate.getName().c_str());
+        } else if ((callNode.getOp() == EOpAtomicAdd || callNode.getOp() == EOpAtomicExchange ||
+                    callNode.getOp() == EOpAtomicLoad || callNode.getOp() == EOpAtomicStore ||
+                    callNode.getOp() == EOpAtomicMin || callNode.getOp() == EOpAtomicMax) &&
+                   arg0->getType().isFloatingDomain()) {
+            requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float2, fnCandidate.getName().c_str());
         }
         }
         break;
         break;
     }
     }
@@ -2931,7 +3010,8 @@ void TParseContext::reservedErrorCheck(const TSourceLoc& loc, const TString& ide
     // "Identifiers starting with "gl_" are reserved for use by OpenGL, and may not be
     // "Identifiers starting with "gl_" are reserved for use by OpenGL, and may not be
     // declared in a shader; this results in a compile-time error."
     // declared in a shader; this results in a compile-time error."
     if (! symbolTable.atBuiltInLevel()) {
     if (! symbolTable.atBuiltInLevel()) {
-        if (builtInName(identifier))
+        if (builtInName(identifier) && !extensionTurnedOn(E_GL_EXT_spirv_intrinsics))
+            // The extension GL_EXT_spirv_intrinsics allows us to declare identifiers starting with "gl_".
             error(loc, "identifiers starting with \"gl_\" are reserved", identifier.c_str(), "");
             error(loc, "identifiers starting with \"gl_\" are reserved", identifier.c_str(), "");
 
 
         // "__" are not supposed to be an error.  ES 300 (and desktop) added the clarification:
         // "__" are not supposed to be an error.  ES 300 (and desktop) added the clarification:
@@ -2939,7 +3019,8 @@ void TParseContext::reservedErrorCheck(const TSourceLoc& loc, const TString& ide
         // reserved; using such a name does not itself result in an error, but may result
         // reserved; using such a name does not itself result in an error, but may result
         // in undefined behavior."
         // in undefined behavior."
         // however, before that, ES tests required an error.
         // however, before that, ES tests required an error.
-        if (identifier.find("__") != TString::npos) {
+        if (identifier.find("__") != TString::npos && !extensionTurnedOn(E_GL_EXT_spirv_intrinsics)) {
+            // The extension GL_EXT_spirv_intrinsics allows us to declare identifiers starting with "__".
             if (isEsProfile() && version < 300)
             if (isEsProfile() && version < 300)
                 error(loc, "identifiers containing consecutive underscores (\"__\") are reserved, and an error if version < 300", identifier.c_str(), "");
                 error(loc, "identifiers containing consecutive underscores (\"__\") are reserved, and an error if version < 300", identifier.c_str(), "");
             else
             else
@@ -2960,14 +3041,16 @@ void TParseContext::reservedPpErrorCheck(const TSourceLoc& loc, const char* iden
     // single underscore) are also reserved, and defining such a name results in a
     // single underscore) are also reserved, and defining such a name results in a
     // compile-time error."
     // compile-time error."
     // however, before that, ES tests required an error.
     // however, before that, ES tests required an error.
-    if (strncmp(identifier, "GL_", 3) == 0)
+    if (strncmp(identifier, "GL_", 3) == 0 && !extensionTurnedOn(E_GL_EXT_spirv_intrinsics))
+        // The extension GL_EXT_spirv_intrinsics allows us to declare macros prefixed with "GL_".
         ppError(loc, "names beginning with \"GL_\" can't be (un)defined:", op,  identifier);
         ppError(loc, "names beginning with \"GL_\" can't be (un)defined:", op,  identifier);
     else if (strncmp(identifier, "defined", 8) == 0)
     else if (strncmp(identifier, "defined", 8) == 0)
         if (relaxedErrors())
         if (relaxedErrors())
             ppWarn(loc, "\"defined\" is (un)defined:", op,  identifier);
             ppWarn(loc, "\"defined\" is (un)defined:", op,  identifier);
         else
         else
             ppError(loc, "\"defined\" can't be (un)defined:", op,  identifier);
             ppError(loc, "\"defined\" can't be (un)defined:", op,  identifier);
-    else if (strstr(identifier, "__") != 0) {
+    else if (strstr(identifier, "__") != 0 && !extensionTurnedOn(E_GL_EXT_spirv_intrinsics)) {
+        // The extension GL_EXT_spirv_intrinsics allows us to declare macros prefixed with "__".
         if (isEsProfile() && version >= 300 &&
         if (isEsProfile() && version >= 300 &&
             (strcmp(identifier, "__LINE__") == 0 ||
             (strcmp(identifier, "__LINE__") == 0 ||
              strcmp(identifier, "__FILE__") == 0 ||
              strcmp(identifier, "__FILE__") == 0 ||
@@ -3115,6 +3198,7 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
     bool matrixInMatrix = false;
     bool matrixInMatrix = false;
     bool arrayArg = false;
     bool arrayArg = false;
     bool floatArgument = false;
     bool floatArgument = false;
+    bool intArgument = false;
     for (int arg = 0; arg < function.getParamCount(); ++arg) {
     for (int arg = 0; arg < function.getParamCount(); ++arg) {
         if (function[arg].type->isArray()) {
         if (function[arg].type->isArray()) {
             if (function[arg].type->isUnsizedArray()) {
             if (function[arg].type->isUnsizedArray()) {
@@ -3145,6 +3229,8 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
             specConstType = true;
             specConstType = true;
         if (function[arg].type->isFloatingDomain())
         if (function[arg].type->isFloatingDomain())
             floatArgument = true;
             floatArgument = true;
+        if (function[arg].type->isIntegerDomain())
+            intArgument = true;
         if (type.isStruct()) {
         if (type.isStruct()) {
             if (function[arg].type->contains16BitFloat()) {
             if (function[arg].type->contains16BitFloat()) {
                 requireFloat16Arithmetic(loc, "constructor", "can't construct structure containing 16-bit type");
                 requireFloat16Arithmetic(loc, "constructor", "can't construct structure containing 16-bit type");
@@ -3250,6 +3336,15 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
                 // and aren't making an array.
                 // and aren't making an array.
                 makeSpecConst = ! floatArgument && ! type.isArray();
                 makeSpecConst = ! floatArgument && ! type.isArray();
                 break;
                 break;
+
+            case EOpConstructVec2:
+            case EOpConstructVec3:
+            case EOpConstructVec4:
+                // This was the list of valid ones, if they aren't converting from int
+                // and aren't making an array.
+                makeSpecConst = ! intArgument && !type.isArray();
+                break;
+
             default:
             default:
                 // anything else wasn't white-listed in the spec as a conversion
                 // anything else wasn't white-listed in the spec as a conversion
                 makeSpecConst = false;
                 makeSpecConst = false;
@@ -3582,6 +3677,14 @@ void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& q
     if (!nonuniformOkay && qualifier.isNonUniform())
     if (!nonuniformOkay && qualifier.isNonUniform())
         error(loc, "for non-parameter, can only apply to 'in' or no storage qualifier", "nonuniformEXT", "");
         error(loc, "for non-parameter, can only apply to 'in' or no storage qualifier", "nonuniformEXT", "");
 
 
+#ifndef GLSLANG_WEB
+    if (qualifier.isSpirvByReference())
+        error(loc, "can only apply to parameter", "spirv_by_reference", "");
+
+    if (qualifier.isSpirvLiteral())
+        error(loc, "can only apply to parameter", "spirv_literal", "");
+#endif
+
     // Storage qualifier isn't ready for memberQualifierCheck, we should skip invariantCheck for it.
     // Storage qualifier isn't ready for memberQualifierCheck, we should skip invariantCheck for it.
     if (!isMemberCheck || structNestingLevel > 0)
     if (!isMemberCheck || structNestingLevel > 0)
         invariantCheck(loc, qualifier);
         invariantCheck(loc, qualifier);
@@ -3843,6 +3946,41 @@ void TParseContext::mergeQualifiers(const TSourceLoc& loc, TQualifier& dst, cons
     MERGE_SINGLETON(nonUniform);
     MERGE_SINGLETON(nonUniform);
 #endif
 #endif
 
 
+#ifndef GLSLANG_WEB
+    // SPIR-V storage class qualifier (GL_EXT_spirv_intrinsics)
+    dst.spirvStorageClass = src.spirvStorageClass;
+
+    // SPIR-V decorate qualifiers (GL_EXT_spirv_intrinsics)
+    if (src.hasSprivDecorate()) {
+        if (dst.hasSprivDecorate()) {
+            const TSpirvDecorate& srcSpirvDecorate = src.getSpirvDecorate();
+            TSpirvDecorate& dstSpirvDecorate = dst.getSpirvDecorate();
+            for (auto& decorate : srcSpirvDecorate.decorates) {
+                if (dstSpirvDecorate.decorates.find(decorate.first) != dstSpirvDecorate.decorates.end())
+                    error(loc, "too many SPIR-V decorate qualifiers", "spirv_decorate", "(decoration=%u)", decorate.first);
+                else
+                    dstSpirvDecorate.decorates.insert(decorate);
+            }
+
+            for (auto& decorateId : srcSpirvDecorate.decorateIds) {
+                if (dstSpirvDecorate.decorateIds.find(decorateId.first) != dstSpirvDecorate.decorateIds.end())
+                    error(loc, "too many SPIR-V decorate qualifiers", "spirv_decorate_id", "(decoration=%u)", decorateId.first);
+                else
+                    dstSpirvDecorate.decorateIds.insert(decorateId);
+            }
+
+            for (auto& decorateString : srcSpirvDecorate.decorateStrings) {
+                if (dstSpirvDecorate.decorates.find(decorateString.first) != dstSpirvDecorate.decorates.end())
+                    error(loc, "too many SPIR-V decorate qualifiers", "spirv_decorate_string", "(decoration=%u)", decorateString.first);
+                else
+                    dstSpirvDecorate.decorates.insert(decorateString);
+            }
+        } else {
+            dst.spirvDecorate = src.spirvDecorate;
+        }
+    }
+#endif
+
     if (repeated)
     if (repeated)
         error(loc, "replicated qualifiers", "", "");
         error(loc, "replicated qualifiers", "", "");
 }
 }
@@ -4806,6 +4944,17 @@ void TParseContext::paramCheckFix(const TSourceLoc& loc, const TQualifier& quali
     }
     }
     if (qualifier.isNonUniform())
     if (qualifier.isNonUniform())
         type.getQualifier().nonUniform = qualifier.nonUniform;
         type.getQualifier().nonUniform = qualifier.nonUniform;
+#ifndef GLSLANG_WEB
+    if (qualifier.isSpirvByReference())
+        type.getQualifier().setSpirvByReference();
+    if (qualifier.isSpirvLiteral()) {
+        if (type.getBasicType() == EbtFloat || type.getBasicType() == EbtInt || type.getBasicType() == EbtUint ||
+            type.getBasicType() == EbtBool)
+            type.getQualifier().setSpirvLiteral();
+        else
+            error(loc, "cannot use spirv_literal qualifier", type.getBasicTypeString().c_str(), "");
+#endif
+    }
 
 
     paramCheckFixStorage(loc, qualifier.storage, type);
     paramCheckFixStorage(loc, qualifier.storage, type);
 }
 }
@@ -5873,6 +6022,9 @@ void TParseContext::layoutObjectCheck(const TSourceLoc& loc, const TSymbol& symb
         case EvqVaryingIn:
         case EvqVaryingIn:
         case EvqVaryingOut:
         case EvqVaryingOut:
             if (!type.getQualifier().isTaskMemory() &&
             if (!type.getQualifier().isTaskMemory() &&
+#ifndef GLSLANG_WEB
+                !type.getQualifier().hasSprivDecorate() &&
+#endif
                 (type.getBasicType() != EbtBlock ||
                 (type.getBasicType() != EbtBlock ||
                  (!(*type.getStruct())[0].type->getQualifier().hasLocation() &&
                  (!(*type.getStruct())[0].type->getQualifier().hasLocation() &&
                    (*type.getStruct())[0].type->getQualifier().builtIn == EbvNone)))
                    (*type.getStruct())[0].type->getQualifier().builtIn == EbvNone)))
@@ -5934,6 +6086,11 @@ void TParseContext::layoutMemberLocationArrayCheck(const TSourceLoc& loc, bool m
 // Do layout error checking with respect to a type.
 // Do layout error checking with respect to a type.
 void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
 void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
 {
 {
+#ifndef GLSLANG_WEB
+    if (extensionTurnedOn(E_GL_EXT_spirv_intrinsics))
+        return; // Skip any check if GL_EXT_spirv_intrinsics is turned on
+#endif
+
     const TQualifier& qualifier = type.getQualifier();
     const TQualifier& qualifier = type.getQualifier();
 
 
     // first, intra-layout qualifier-only error checking
     // first, intra-layout qualifier-only error checking
@@ -7940,6 +8097,10 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
             memberQualifier.perViewNV = currentBlockQualifier.perViewNV;
             memberQualifier.perViewNV = currentBlockQualifier.perViewNV;
         if (currentBlockQualifier.perTaskNV)
         if (currentBlockQualifier.perTaskNV)
             memberQualifier.perTaskNV = currentBlockQualifier.perTaskNV;
             memberQualifier.perTaskNV = currentBlockQualifier.perTaskNV;
+        if (memberQualifier.storage == EvqSpirvStorageClass)
+            error(memberLoc, "member cannot have a spirv_storage_class qualifier", memberType.getFieldName().c_str(), "");
+        if (memberQualifier.hasSprivDecorate() && !memberQualifier.getSpirvDecorate().decorateIds.empty())
+            error(memberLoc, "member cannot have a spirv_decorate_id qualifier", memberType.getFieldName().c_str(), "");
 #endif
 #endif
         if ((currentBlockQualifier.storage == EvqUniform || currentBlockQualifier.storage == EvqBuffer) && (memberQualifier.isInterpolation() || memberQualifier.isAuxiliary()))
         if ((currentBlockQualifier.storage == EvqUniform || currentBlockQualifier.storage == EvqBuffer) && (memberQualifier.isInterpolation() || memberQualifier.isAuxiliary()))
             error(memberLoc, "member of uniform or buffer block cannot have an auxiliary or interpolation qualifier", memberType.getFieldName().c_str(), "");
             error(memberLoc, "member of uniform or buffer block cannot have an auxiliary or interpolation qualifier", memberType.getFieldName().c_str(), "");

+ 16 - 0
3rdparty/glslang/glslang/MachineIndependent/ParseHelper.h

@@ -470,6 +470,22 @@ public:
     void handleSwitchAttributes(const TAttributes& attributes, TIntermNode*);
     void handleSwitchAttributes(const TAttributes& attributes, TIntermNode*);
     // Determine loop control from attributes
     // Determine loop control from attributes
     void handleLoopAttributes(const TAttributes& attributes, TIntermNode*);
     void handleLoopAttributes(const TAttributes& attributes, TIntermNode*);
+    // Function attributes
+    void handleFunctionAttributes(const TSourceLoc&, const TAttributes&, TFunction*);
+
+    // GL_EXT_spirv_intrinsics
+    TSpirvRequirement* makeSpirvRequirement(const TSourceLoc& loc, const TString& name,
+                                            const TIntermAggregate* extensions, const TIntermAggregate* capabilities);
+    TSpirvRequirement* mergeSpirvRequirements(const TSourceLoc& loc, TSpirvRequirement* spirvReq1,
+                                                TSpirvRequirement* spirvReq2);
+    TSpirvTypeParameters* makeSpirvTypeParameters(const TSourceLoc& loc, const TIntermConstantUnion* constant);
+    TSpirvTypeParameters* makeSpirvTypeParameters(const TPublicType& type);
+    TSpirvTypeParameters* mergeSpirvTypeParameters(TSpirvTypeParameters* spirvTypeParams1,
+                                                   TSpirvTypeParameters* spirvTypeParams2);
+    TSpirvInstruction* makeSpirvInstruction(const TSourceLoc& loc, const TString& name, const TString& value);
+    TSpirvInstruction* makeSpirvInstruction(const TSourceLoc& loc, const TString& name, int value);
+    TSpirvInstruction* mergeSpirvInstruction(const TSourceLoc& loc, TSpirvInstruction* spirvInst1,
+                                             TSpirvInstruction* spirvInst2);
 #endif
 #endif
 
 
     void checkAndResizeMeshViewDim(const TSourceLoc&, TType&, bool isBlockMember);
     void checkAndResizeMeshViewDim(const TSourceLoc&, TType&, bool isBlockMember);

+ 27 - 0
3rdparty/glslang/glslang/MachineIndependent/Scan.cpp

@@ -586,6 +586,18 @@ void TScanContext::fillInKeywordMap()
     (*KeywordMap)["f64mat4x2"] =               F64MAT4X2;
     (*KeywordMap)["f64mat4x2"] =               F64MAT4X2;
     (*KeywordMap)["f64mat4x3"] =               F64MAT4X3;
     (*KeywordMap)["f64mat4x3"] =               F64MAT4X3;
     (*KeywordMap)["f64mat4x4"] =               F64MAT4X4;
     (*KeywordMap)["f64mat4x4"] =               F64MAT4X4;
+
+    // GL_EXT_spirv_intrinsics
+    (*KeywordMap)["spirv_instruction"] =       SPIRV_INSTRUCTION;
+    (*KeywordMap)["spirv_execution_mode"] =    SPIRV_EXECUTION_MODE;
+    (*KeywordMap)["spirv_execution_mode_id"] = SPIRV_EXECUTION_MODE_ID;
+    (*KeywordMap)["spirv_decorate"] =          SPIRV_DECORATE;
+    (*KeywordMap)["spirv_decorate_id"] =       SPIRV_DECORATE_ID;
+    (*KeywordMap)["spirv_decorate_string"] =   SPIRV_DECORATE_STRING;
+    (*KeywordMap)["spirv_type"] =              SPIRV_TYPE;
+    (*KeywordMap)["spirv_storage_class"] =     SPIRV_STORAGE_CLASS;
+    (*KeywordMap)["spirv_by_reference"] =      SPIRV_BY_REFERENCE;
+    (*KeywordMap)["spirv_literal"] =           SPIRV_LITERAL;
 #endif
 #endif
 
 
     (*KeywordMap)["sampler2D"] =               SAMPLER2D;
     (*KeywordMap)["sampler2D"] =               SAMPLER2D;
@@ -1747,6 +1759,21 @@ int TScanContext::tokenizeIdentifier()
             return keyword;
             return keyword;
         else
         else
             return identifierOrType();
             return identifierOrType();
+
+    case SPIRV_INSTRUCTION:
+    case SPIRV_EXECUTION_MODE:
+    case SPIRV_EXECUTION_MODE_ID:
+    case SPIRV_DECORATE:
+    case SPIRV_DECORATE_ID:
+    case SPIRV_DECORATE_STRING:
+    case SPIRV_TYPE:
+    case SPIRV_STORAGE_CLASS:
+    case SPIRV_BY_REFERENCE:
+    case SPIRV_LITERAL:
+        if (parseContext.symbolTable.atBuiltInLevel() ||
+            parseContext.extensionTurnedOn(E_GL_EXT_spirv_intrinsics))
+            return keyword;
+        return identifierOrType();
 #endif
 #endif
 
 
     default:
     default:

+ 355 - 0
3rdparty/glslang/glslang/MachineIndependent/SpirvIntrinsics.cpp

@@ -0,0 +1,355 @@
+//
+// Copyright(C) 2021 Advanced Micro Devices, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+//    Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+//
+//    Redistributions in binary form must reproduce the above
+//    copyright notice, this list of conditions and the following
+//    disclaimer in the documentation and/or other materials provided
+//    with the distribution.
+//
+//    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+//    contributors may be used to endorse or promote products derived
+//    from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef GLSLANG_WEB
+
+//
+// GL_EXT_spirv_intrinsics
+//
+#include "../Include/intermediate.h"
+#include "../Include/SpirvIntrinsics.h"
+#include "../Include/Types.h"
+#include "ParseHelper.h"
+
+namespace glslang {
+
+//
+// Handle SPIR-V requirements
+//
+TSpirvRequirement* TParseContext::makeSpirvRequirement(const TSourceLoc& loc, const TString& name,
+                                                       const TIntermAggregate* extensions,
+                                                       const TIntermAggregate* capabilities)
+{
+    TSpirvRequirement* spirvReq = new TSpirvRequirement;
+
+    if (name == "extensions") {
+        assert(extensions);
+        for (auto extension : extensions->getSequence()) {
+            assert(extension->getAsConstantUnion());
+            spirvReq->extensions.insert(*extension->getAsConstantUnion()->getConstArray()[0].getSConst());
+        }
+    } else if (name == "capabilities") {
+        assert(capabilities);
+        for (auto capability : capabilities->getSequence()) {
+            assert(capability->getAsConstantUnion());
+            spirvReq->capabilities.insert(capability->getAsConstantUnion()->getConstArray()[0].getIConst());
+        }
+    } else
+        error(loc, "unknow SPIR-V requirement", name.c_str(), "");
+
+    return spirvReq;
+}
+
+TSpirvRequirement* TParseContext::mergeSpirvRequirements(const TSourceLoc& loc, TSpirvRequirement* spirvReq1,
+                                                         TSpirvRequirement* spirvReq2)
+{
+    // Merge the second SPIR-V requirement to the first one
+    if (!spirvReq2->extensions.empty()) {
+        if (spirvReq1->extensions.empty())
+            spirvReq1->extensions = spirvReq2->extensions;
+        else
+            error(loc, "too many SPIR-V requirements", "extensions", "");
+    }
+
+    if (!spirvReq2->capabilities.empty()) {
+        if (spirvReq1->capabilities.empty())
+            spirvReq1->capabilities = spirvReq2->capabilities;
+        else
+            error(loc, "too many SPIR-V requirements", "capabilities", "");
+    }
+
+    return spirvReq1;
+}
+
+void TIntermediate::insertSpirvRequirement(const TSpirvRequirement* spirvReq)
+{
+    if (!spirvRequirement)
+        spirvRequirement = new TSpirvRequirement;
+
+    for (auto extension : spirvReq->extensions)
+        spirvRequirement->extensions.insert(extension);
+
+    for (auto capability : spirvReq->capabilities)
+        spirvRequirement->capabilities.insert(capability);
+}
+
+//
+// Handle SPIR-V execution modes
+//
+void TIntermediate::insertSpirvExecutionMode(int executionMode, const TIntermAggregate* args)
+{
+    if (!spirvExecutionMode)
+        spirvExecutionMode = new TSpirvExecutionMode;
+
+    TVector<const TIntermConstantUnion*> extraOperands;
+    if (args) {
+        for (auto arg : args->getSequence()) {
+            auto extraOperand = arg->getAsConstantUnion();
+            assert(extraOperand != nullptr);
+            extraOperands.push_back(extraOperand);
+        }
+    }
+    spirvExecutionMode->modes[executionMode] = extraOperands;
+}
+
+void TIntermediate::insertSpirvExecutionModeId(int executionMode, const TIntermAggregate* args)
+{
+    if (!spirvExecutionMode)
+        spirvExecutionMode = new TSpirvExecutionMode;
+
+    assert(args);
+    TVector<const TIntermConstantUnion*> extraOperands;
+
+    for (auto arg : args->getSequence()) {
+        auto extraOperand = arg->getAsConstantUnion();
+        assert(extraOperand != nullptr);
+        extraOperands.push_back(extraOperand);
+    }
+    spirvExecutionMode->modeIds[executionMode] = extraOperands;
+}
+
+//
+// Handle SPIR-V decorate qualifiers
+//
+void TQualifier::setSpirvDecorate(int decoration, const TIntermAggregate* args)
+{
+    if (!spirvDecorate)
+        spirvDecorate = new TSpirvDecorate;
+
+    TVector<const TIntermConstantUnion*> extraOperands;
+    if (args) {
+        for (auto arg : args->getSequence()) {
+            auto extraOperand = arg->getAsConstantUnion();
+            assert(extraOperand != nullptr);
+            extraOperands.push_back(extraOperand);
+        }
+    }
+    spirvDecorate->decorates[decoration] = extraOperands;
+}
+
+void TQualifier::setSpirvDecorateId(int decoration, const TIntermAggregate* args)
+{
+    if (!spirvDecorate)
+        spirvDecorate = new TSpirvDecorate;
+
+    assert(args);
+    TVector<const TIntermConstantUnion*> extraOperands;
+    for (auto arg : args->getSequence()) {
+        auto extraOperand = arg->getAsConstantUnion();
+        assert(extraOperand != nullptr);
+        extraOperands.push_back(extraOperand);
+    }
+    spirvDecorate->decorateIds[decoration] = extraOperands;
+}
+
+void TQualifier::setSpirvDecorateString(int decoration, const TIntermAggregate* args)
+{
+    if (!spirvDecorate)
+        spirvDecorate = new TSpirvDecorate;
+
+    assert(args);
+    TVector<const TIntermConstantUnion*> extraOperands;
+    for (auto arg : args->getSequence()) {
+        auto extraOperand = arg->getAsConstantUnion();
+        assert(extraOperand != nullptr);
+        extraOperands.push_back(extraOperand);
+    }
+    spirvDecorate->decorateStrings[decoration] = extraOperands;
+}
+
+TString TQualifier::getSpirvDecorateQualifierString() const
+{
+    assert(spirvDecorate);
+
+    TString qualifierString;
+
+    const auto appendFloat = [&](float f) { qualifierString.append(std::to_string(f).c_str()); };
+    const auto appendInt = [&](int i) { qualifierString.append(std::to_string(i).c_str()); };
+    const auto appendUint = [&](unsigned int u) { qualifierString.append(std::to_string(u).c_str()); };
+    const auto appendBool = [&](bool b) { qualifierString.append(std::to_string(b).c_str()); };
+    const auto appendStr = [&](const char* s) { qualifierString.append(s); };
+
+    const auto appendDecorate = [&](const TIntermConstantUnion* constant) {
+        if (constant->getBasicType() == EbtFloat) {
+            float value = static_cast<float>(constant->getConstArray()[0].getDConst());
+            appendFloat(value);
+        }
+        else if (constant->getBasicType() == EbtInt) {
+            int value = constant->getConstArray()[0].getIConst();
+            appendInt(value);
+        }
+        else if (constant->getBasicType() == EbtUint) {
+            unsigned value = constant->getConstArray()[0].getUConst();
+            appendUint(value);
+        }
+        else if (constant->getBasicType() == EbtBool) {
+            bool value = constant->getConstArray()[0].getBConst();
+            appendBool(value);
+        }
+        else if (constant->getBasicType() == EbtString) {
+            const TString* value = constant->getConstArray()[0].getSConst();
+            appendStr(value->c_str());
+        }
+        else
+            assert(0);
+    };
+
+    for (auto& decorate : spirvDecorate->decorates) {
+        appendStr("spirv_decorate(");
+        appendInt(decorate.first);
+        for (auto extraOperand : decorate.second) {
+            appendStr(", ");
+            appendDecorate(extraOperand);
+        }
+        appendStr(") ");
+    }
+
+    for (auto& decorateId : spirvDecorate->decorateIds) {
+        appendStr("spirv_decorate_id(");
+        appendInt(decorateId.first);
+        for (auto extraOperand : decorateId.second) {
+            appendStr(", ");
+            appendDecorate(extraOperand);
+        }
+        appendStr(") ");
+    }
+
+    for (auto& decorateString : spirvDecorate->decorateStrings) {
+        appendStr("spirv_decorate_string(");
+        appendInt(decorateString.first);
+        for (auto extraOperand : decorateString.second) {
+            appendStr(", ");
+            appendDecorate(extraOperand);
+        }
+        appendStr(") ");
+    }
+
+    return qualifierString;
+}
+
+//
+// Handle SPIR-V type specifiers
+//
+void TPublicType::setSpirvType(const TSpirvInstruction& spirvInst, const TSpirvTypeParameters* typeParams)
+{
+    if (!spirvType)
+        spirvType = new TSpirvType;
+
+    basicType = EbtSpirvType;
+    spirvType->spirvInst = spirvInst;
+    if (typeParams)
+        spirvType->typeParams = *typeParams;
+}
+
+TSpirvTypeParameters* TParseContext::makeSpirvTypeParameters(const TSourceLoc& loc, const TIntermConstantUnion* constant)
+{
+    TSpirvTypeParameters* spirvTypeParams = new TSpirvTypeParameters;
+    if (constant->getBasicType() != EbtFloat &&
+        constant->getBasicType() != EbtInt &&
+        constant->getBasicType() != EbtUint &&
+        constant->getBasicType() != EbtBool &&
+        constant->getBasicType() != EbtString)
+        error(loc, "this type not allowed", constant->getType().getBasicString(), "");
+    else {
+        assert(constant);
+        spirvTypeParams->push_back(TSpirvTypeParameter(constant));
+    }
+
+    return spirvTypeParams;
+}
+
+TSpirvTypeParameters* TParseContext::makeSpirvTypeParameters(const TPublicType& type)
+{
+    TSpirvTypeParameters* spirvTypeParams = new TSpirvTypeParameters;
+    spirvTypeParams->push_back(TSpirvTypeParameter(new TType(type)));
+    return spirvTypeParams;
+}
+
+TSpirvTypeParameters* TParseContext::mergeSpirvTypeParameters(TSpirvTypeParameters* spirvTypeParams1, TSpirvTypeParameters* spirvTypeParams2)
+{
+    // Merge SPIR-V type parameters of the second one to the first one
+    for (const auto& spirvTypeParam : *spirvTypeParams2)
+        spirvTypeParams1->push_back(spirvTypeParam);
+    return spirvTypeParams1;
+}
+
+//
+// Handle SPIR-V instruction qualifiers
+//
+TSpirvInstruction* TParseContext::makeSpirvInstruction(const TSourceLoc& loc, const TString& name, const TString& value)
+{
+    TSpirvInstruction* spirvInst = new TSpirvInstruction;
+    if (name == "set")
+        spirvInst->set = value;
+    else
+        error(loc, "unknown SPIR-V instruction qualifier", name.c_str(), "");
+
+    return spirvInst;
+}
+
+TSpirvInstruction* TParseContext::makeSpirvInstruction(const TSourceLoc& loc, const TString& name, int value)
+{
+    TSpirvInstruction* spirvInstuction = new TSpirvInstruction;
+    if (name == "id")
+        spirvInstuction->id = value;
+    else
+        error(loc, "unknown SPIR-V instruction qualifier", name.c_str(), "");
+
+    return spirvInstuction;
+}
+
+TSpirvInstruction* TParseContext::mergeSpirvInstruction(const TSourceLoc& loc, TSpirvInstruction* spirvInst1, TSpirvInstruction* spirvInst2)
+{
+    // Merge qualifiers of the second SPIR-V instruction to those of the first one
+    if (!spirvInst2->set.empty()) {
+        if (spirvInst1->set.empty())
+            spirvInst1->set = spirvInst2->set;
+        else
+            error(loc, "too many SPIR-V instruction qualifiers", "spirv_instruction", "(set)");
+    }
+
+    if (spirvInst2->id != -1) {
+        if (spirvInst1->id == -1)
+            spirvInst1->id = spirvInst2->id;
+        else
+            error(loc, "too many SPIR-V instruction qualifiers", "spirv_instruction", "(id)");
+    }
+
+    return spirvInst1;
+}
+
+} // end namespace glslang
+
+#endif // GLSLANG_WEB

+ 4 - 0
3rdparty/glslang/glslang/MachineIndependent/SymbolTable.cpp

@@ -77,6 +77,7 @@ void TType::buildMangledName(TString& mangledName) const
     case EbtAtomicUint:         mangledName += "au";     break;
     case EbtAtomicUint:         mangledName += "au";     break;
     case EbtAccStruct:          mangledName += "as";     break;
     case EbtAccStruct:          mangledName += "as";     break;
     case EbtRayQuery:           mangledName += "rq";     break;
     case EbtRayQuery:           mangledName += "rq";     break;
+    case EbtSpirvType:          mangledName += "spv-t";  break;
 #endif
 #endif
     case EbtSampler:
     case EbtSampler:
         switch (sampler.type) {
         switch (sampler.type) {
@@ -390,6 +391,9 @@ TFunction::TFunction(const TFunction& copyOf) : TSymbol(copyOf)
     implicitThis = copyOf.implicitThis;
     implicitThis = copyOf.implicitThis;
     illegalImplicitThis = copyOf.illegalImplicitThis;
     illegalImplicitThis = copyOf.illegalImplicitThis;
     defaultParamCount = copyOf.defaultParamCount;
     defaultParamCount = copyOf.defaultParamCount;
+#ifndef GLSLANG_WEB
+    spirvInst = copyOf.spirvInst;
+#endif
 }
 }
 
 
 TFunction* TFunction::clone() const
 TFunction* TFunction::clone() const

+ 13 - 0
3rdparty/glslang/glslang/MachineIndependent/SymbolTable.h

@@ -319,6 +319,15 @@ public:
     virtual TParameter& operator[](int i) { assert(writable); return parameters[i]; }
     virtual TParameter& operator[](int i) { assert(writable); return parameters[i]; }
     virtual const TParameter& operator[](int i) const { return parameters[i]; }
     virtual const TParameter& operator[](int i) const { return parameters[i]; }
 
 
+#ifndef GLSLANG_WEB
+    virtual void setSpirvInstruction(const TSpirvInstruction& inst)
+    {
+        relateToOperator(EOpSpirvInst);
+        spirvInst = inst;
+    }
+    virtual const TSpirvInstruction& getSpirvInstruction() const { return spirvInst; }
+#endif
+
 #if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
 #if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
     virtual void dump(TInfoSink& infoSink, bool complete = false) const override;
     virtual void dump(TInfoSink& infoSink, bool complete = false) const override;
 #endif
 #endif
@@ -342,6 +351,10 @@ protected:
                                // This is important for a static member function that has member variables in scope,
                                // This is important for a static member function that has member variables in scope,
                                // but is not allowed to use them, or see hidden symbols instead.
                                // but is not allowed to use them, or see hidden symbols instead.
     int  defaultParamCount;
     int  defaultParamCount;
+
+#ifndef GLSLANG_WEB
+    TSpirvInstruction spirvInst; // SPIR-V instruction qualifiers
+#endif
 };
 };
 
 
 //
 //

+ 30 - 0
3rdparty/glslang/glslang/MachineIndependent/Versions.cpp

@@ -251,6 +251,7 @@ void TParseVersions::initializeExtensionBehavior()
 
 
     extensionBehavior[E_GL_EXT_shader_16bit_storage]                    = EBhDisable;
     extensionBehavior[E_GL_EXT_shader_16bit_storage]                    = EBhDisable;
     extensionBehavior[E_GL_EXT_shader_8bit_storage]                     = EBhDisable;
     extensionBehavior[E_GL_EXT_shader_8bit_storage]                     = EBhDisable;
+    extensionBehavior[E_GL_EXT_subgroup_uniform_control_flow]           = EBhDisable;
 
 
     // #line and #include
     // #line and #include
     extensionBehavior[E_GL_GOOGLE_cpp_style_line_directive]          = EBhDisable;
     extensionBehavior[E_GL_GOOGLE_cpp_style_line_directive]          = EBhDisable;
@@ -332,6 +333,7 @@ void TParseVersions::initializeExtensionBehavior()
     extensionBehavior[E_GL_EXT_shader_image_int64]   = EBhDisable;
     extensionBehavior[E_GL_EXT_shader_image_int64]   = EBhDisable;
     extensionBehavior[E_GL_EXT_terminate_invocation]        = EBhDisable;
     extensionBehavior[E_GL_EXT_terminate_invocation]        = EBhDisable;
     extensionBehavior[E_GL_EXT_shared_memory_block]         = EBhDisable;
     extensionBehavior[E_GL_EXT_shared_memory_block]         = EBhDisable;
+    extensionBehavior[E_GL_EXT_spirv_intrinsics]            = EBhDisable;
 
 
     // OVR extensions
     // OVR extensions
     extensionBehavior[E_GL_OVR_multiview]                = EBhDisable;
     extensionBehavior[E_GL_OVR_multiview]                = EBhDisable;
@@ -353,6 +355,7 @@ void TParseVersions::initializeExtensionBehavior()
     extensionBehavior[E_GL_EXT_shader_subgroup_extended_types_int64]   = EBhDisable;
     extensionBehavior[E_GL_EXT_shader_subgroup_extended_types_int64]   = EBhDisable;
     extensionBehavior[E_GL_EXT_shader_subgroup_extended_types_float16] = EBhDisable;
     extensionBehavior[E_GL_EXT_shader_subgroup_extended_types_float16] = EBhDisable;
     extensionBehavior[E_GL_EXT_shader_atomic_float]                    = EBhDisable;
     extensionBehavior[E_GL_EXT_shader_atomic_float]                    = EBhDisable;
+    extensionBehavior[E_GL_EXT_shader_atomic_float2]                   = EBhDisable;
 }
 }
 
 
 #endif // GLSLANG_WEB
 #endif // GLSLANG_WEB
@@ -415,6 +418,7 @@ void TParseVersions::getPreamble(std::string& preamble)
             }
             }
             if (version >= 310) {
             if (version >= 310) {
                 preamble += "#define GL_EXT_null_initializer 1\n";
                 preamble += "#define GL_EXT_null_initializer 1\n";
+                preamble += "#define GL_EXT_subgroup_uniform_control_flow 1\n";
             }
             }
 
 
     } else { // !isEsProfile()
     } else { // !isEsProfile()
@@ -491,6 +495,7 @@ void TParseVersions::getPreamble(std::string& preamble)
             "#define GL_EXT_ray_tracing 1\n"
             "#define GL_EXT_ray_tracing 1\n"
             "#define GL_EXT_ray_query 1\n"
             "#define GL_EXT_ray_query 1\n"
             "#define GL_EXT_ray_flags_primitive_culling 1\n"
             "#define GL_EXT_ray_flags_primitive_culling 1\n"
+            "#define GL_EXT_spirv_intrinsics 1\n"
 
 
             "#define GL_AMD_shader_ballot 1\n"
             "#define GL_AMD_shader_ballot 1\n"
             "#define GL_AMD_shader_trinary_minmax 1\n"
             "#define GL_AMD_shader_trinary_minmax 1\n"
@@ -535,6 +540,7 @@ void TParseVersions::getPreamble(std::string& preamble)
             "#define GL_EXT_shader_subgroup_extended_types_float16 1\n"
             "#define GL_EXT_shader_subgroup_extended_types_float16 1\n"
 
 
             "#define GL_EXT_shader_atomic_float 1\n"
             "#define GL_EXT_shader_atomic_float 1\n"
+            "#define GL_EXT_shader_atomic_float2 1\n"
             ;
             ;
 
 
         if (version >= 150) {
         if (version >= 150) {
@@ -546,6 +552,7 @@ void TParseVersions::getPreamble(std::string& preamble)
         }
         }
         if (version >= 140) {
         if (version >= 140) {
             preamble += "#define GL_EXT_null_initializer 1\n";
             preamble += "#define GL_EXT_null_initializer 1\n";
+            preamble += "#define GL_EXT_subgroup_uniform_control_flow 1\n";
         }
         }
 #endif // GLSLANG_WEB
 #endif // GLSLANG_WEB
     }
     }
@@ -599,6 +606,29 @@ void TParseVersions::getPreamble(std::string& preamble)
         preamble += "\n";
         preamble += "\n";
     }
     }
 #endif
 #endif
+
+#ifndef GLSLANG_WEB
+    // GL_EXT_spirv_intrinsics
+    if (!isEsProfile()) {
+        switch (language) {
+        case EShLangVertex:         preamble += "#define GL_VERTEX_SHADER 1 \n";                    break;
+        case EShLangTessControl:    preamble += "#define GL_TESSELLATION_CONTROL_SHADER 1 \n";      break;
+        case EShLangTessEvaluation: preamble += "#define GL_TESSELLATION_EVALUATION_SHADER 1 \n";   break;
+        case EShLangGeometry:       preamble += "#define GL_GEOMETRY_SHADER 1 \n";                  break;
+        case EShLangFragment:       preamble += "#define GL_FRAGMENT_SHADER 1 \n";                  break;
+        case EShLangCompute:        preamble += "#define GL_COMPUTE_SHADER 1 \n";                   break;
+        case EShLangRayGen:         preamble += "#define GL_RAY_GENERATION_SHADER_EXT 1 \n";        break;
+        case EShLangIntersect:      preamble += "#define GL_INTERSECTION_SHADER_EXT 1 \n";          break;
+        case EShLangAnyHit:         preamble += "#define GL_ANY_HIT_SHADER_EXT 1 \n";               break;
+        case EShLangClosestHit:     preamble += "#define GL_CLOSEST_HIT_SHADER_EXT 1 \n";           break;
+        case EShLangMiss:           preamble += "#define GL_MISS_SHADER_EXT 1 \n";                  break;
+        case EShLangCallable:       preamble += "#define GL_CALLABLE_SHADER_EXT 1 \n";              break;
+        case EShLangTaskNV:         preamble += "#define GL_TASK_SHADER_NV 1 \n";                   break;
+        case EShLangMeshNV:         preamble += "#define GL_MESH_SHADER_NV 1 \n";                   break;
+        default:                                                                                    break;
+        }
+    }
+#endif
 }
 }
 
 
 //
 //

+ 3 - 0
3rdparty/glslang/glslang/MachineIndependent/Versions.h

@@ -204,6 +204,8 @@ const char* const E_GL_EXT_fragment_shading_rate            = "GL_EXT_fragment_s
 const char* const E_GL_EXT_shader_image_int64               = "GL_EXT_shader_image_int64";
 const char* const E_GL_EXT_shader_image_int64               = "GL_EXT_shader_image_int64";
 const char* const E_GL_EXT_null_initializer                 = "GL_EXT_null_initializer";
 const char* const E_GL_EXT_null_initializer                 = "GL_EXT_null_initializer";
 const char* const E_GL_EXT_shared_memory_block              = "GL_EXT_shared_memory_block";
 const char* const E_GL_EXT_shared_memory_block              = "GL_EXT_shared_memory_block";
+const char* const E_GL_EXT_subgroup_uniform_control_flow    = "GL_EXT_subgroup_uniform_control_flow";
+const char* const E_GL_EXT_spirv_intrinsics                 = "GL_EXT_spirv_intrinsics";
 
 
 // Arrays of extensions for the above viewportEXTs duplications
 // Arrays of extensions for the above viewportEXTs duplications
 
 
@@ -305,6 +307,7 @@ const char* const E_GL_EXT_shader_subgroup_extended_types_float16 = "GL_EXT_shad
 const char* const E_GL_EXT_terminate_invocation = "GL_EXT_terminate_invocation";
 const char* const E_GL_EXT_terminate_invocation = "GL_EXT_terminate_invocation";
 
 
 const char* const E_GL_EXT_shader_atomic_float = "GL_EXT_shader_atomic_float";
 const char* const E_GL_EXT_shader_atomic_float = "GL_EXT_shader_atomic_float";
+const char* const E_GL_EXT_shader_atomic_float2 = "GL_EXT_shader_atomic_float2";
 
 
 // Arrays of extensions for the above AEP duplications
 // Arrays of extensions for the above AEP duplications
 
 

+ 25 - 0
3rdparty/glslang/glslang/MachineIndependent/attribute.cpp

@@ -123,6 +123,8 @@ TAttributeType TParseContext::attributeFromName(const TString& name) const
         return EatPeelCount;
         return EatPeelCount;
     else if (name == "partial_count")
     else if (name == "partial_count")
         return EatPartialCount;
         return EatPartialCount;
+    else if (name == "subgroup_uniform_control_flow")
+        return EatSubgroupUniformControlFlow;
     else
     else
         return EatNone;
         return EatNone;
 }
 }
@@ -341,6 +343,29 @@ void TParseContext::handleLoopAttributes(const TAttributes& attributes, TIntermN
     }
     }
 }
 }
 
 
+
+//
+// Function attributes
+//
+void TParseContext::handleFunctionAttributes(const TSourceLoc& loc, const TAttributes& attributes, TFunction* function)
+{
+    for (auto it = attributes.begin(); it != attributes.end(); ++it) {
+        if (it->size() > 0) {
+            warn(loc, "attribute with arguments not recognized, skipping", "", "");
+            continue;
+        }
+
+        switch (it->name) {
+        case EatSubgroupUniformControlFlow:
+            intermediate.setSubgroupUniformControlFlow();
+            break;
+        default:
+            warn(loc, "attribute does not apply to a function", "", "");
+            break;
+        }
+    }
+}
+
 } // end namespace glslang
 } // end namespace glslang
 
 
 #endif // GLSLANG_WEB
 #endif // GLSLANG_WEB

+ 2 - 1
3rdparty/glslang/glslang/MachineIndependent/attribute.h

@@ -118,7 +118,8 @@ namespace glslang {
         EatFormatR8ui,
         EatFormatR8ui,
         EatFormatUnknown,
         EatFormatUnknown,
         EatNonWritable,
         EatNonWritable,
-        EatNonReadable
+        EatNonReadable,
+        EatSubgroupUniformControlFlow,
     };
     };
 
 
     class TIntermAggregate;
     class TIntermAggregate;

+ 349 - 1
3rdparty/glslang/glslang/MachineIndependent/glslang.m4

@@ -116,6 +116,9 @@ using namespace glslang;
             glslang::TIntermNodePair nodePair;
             glslang::TIntermNodePair nodePair;
             glslang::TIntermTyped* intermTypedNode;
             glslang::TIntermTyped* intermTypedNode;
             glslang::TAttributes* attributes;
             glslang::TAttributes* attributes;
+            glslang::TSpirvRequirement* spirvReq;
+            glslang::TSpirvInstruction* spirvInst;
+            glslang::TSpirvTypeParameters* spirvTypeParams;
         };
         };
         union {
         union {
             glslang::TPublicType type;
             glslang::TPublicType type;
@@ -271,6 +274,11 @@ GLSLANG_WEB_EXCLUDE_ON
 %token <lex> SUBPASSINPUT SUBPASSINPUTMS ISUBPASSINPUT ISUBPASSINPUTMS USUBPASSINPUT USUBPASSINPUTMS
 %token <lex> SUBPASSINPUT SUBPASSINPUTMS ISUBPASSINPUT ISUBPASSINPUTMS USUBPASSINPUT USUBPASSINPUTMS
 %token <lex> F16SUBPASSINPUT F16SUBPASSINPUTMS
 %token <lex> F16SUBPASSINPUT F16SUBPASSINPUTMS
 
 
+// spirv intrinsics
+%token <lex> SPIRV_INSTRUCTION SPIRV_EXECUTION_MODE SPIRV_EXECUTION_MODE_ID
+%token <lex> SPIRV_DECORATE SPIRV_DECORATE_ID SPIRV_DECORATE_STRING
+%token <lex> SPIRV_TYPE SPIRV_STORAGE_CLASS SPIRV_BY_REFERENCE SPIRV_LITERAL
+
 GLSLANG_WEB_EXCLUDE_OFF
 GLSLANG_WEB_EXCLUDE_OFF
 
 
 %token <lex> LEFT_OP RIGHT_OP
 %token <lex> LEFT_OP RIGHT_OP
@@ -362,6 +370,19 @@ GLSLANG_WEB_EXCLUDE_ON
 %type <interm.attributes> attribute attribute_list single_attribute
 %type <interm.attributes> attribute attribute_list single_attribute
 %type <interm.intermNode> demote_statement
 %type <interm.intermNode> demote_statement
 %type <interm.intermTypedNode> initializer_list
 %type <interm.intermTypedNode> initializer_list
+%type <interm.spirvReq> spirv_requirements_list spirv_requirements_parameter
+%type <interm.intermNode> spirv_extension_list spirv_capability_list
+%type <interm.intermNode> spirv_execution_mode_qualifier
+%type <interm.intermNode> spirv_execution_mode_parameter_list spirv_execution_mode_parameter spirv_execution_mode_id_parameter_list
+%type <interm.type> spirv_storage_class_qualifier
+%type <interm.type> spirv_decorate_qualifier
+%type <interm.intermNode> spirv_decorate_parameter_list spirv_decorate_parameter
+%type <interm.intermNode> spirv_decorate_id_parameter_list
+%type <interm.intermNode> spirv_decorate_string_parameter_list
+%type <interm.type> spirv_type_specifier
+%type <interm.spirvTypeParams> spirv_type_parameter_list spirv_type_parameter
+%type <interm.spirvInst> spirv_instruction_qualifier
+%type <interm.spirvInst> spirv_instruction_qualifier_list spirv_instruction_qualifier_id
 GLSLANG_WEB_EXCLUDE_OFF
 GLSLANG_WEB_EXCLUDE_OFF
 
 
 %start translation_unit
 %start translation_unit
@@ -875,6 +896,20 @@ declaration
         $$ = 0;
         $$ = 0;
         // TODO: 4.0 functionality: subroutines: make the identifier a user type for this signature
         // TODO: 4.0 functionality: subroutines: make the identifier a user type for this signature
     }
     }
+GLSLANG_WEB_EXCLUDE_ON
+    | spirv_instruction_qualifier function_prototype SEMICOLON {
+        parseContext.requireExtensions($2.loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V instruction qualifier");
+        $2.function->setSpirvInstruction(*$1); // Attach SPIR-V intruction qualifier
+        parseContext.handleFunctionDeclarator($2.loc, *$2.function, true /* prototype */);
+        $$ = 0;
+        // TODO: 4.0 functionality: subroutines: make the identifier a user type for this signature
+    }
+    | spirv_execution_mode_qualifier SEMICOLON {
+        parseContext.globalCheck($2.loc, "SPIR-V execution mode qualifier");
+        parseContext.requireExtensions($2.loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V execution mode qualifier");
+        $$ = 0;
+    }
+GLSLANG_WEB_EXCLUDE_OFF
     | init_declarator_list SEMICOLON {
     | init_declarator_list SEMICOLON {
         if ($1.intermNode && $1.intermNode->getAsAggregate())
         if ($1.intermNode && $1.intermNode->getAsAggregate())
             $1.intermNode->getAsAggregate()->setOperator(EOpSequence);
             $1.intermNode->getAsAggregate()->setOperator(EOpSequence);
@@ -944,6 +979,25 @@ function_prototype
         $$.function = $1;
         $$.function = $1;
         $$.loc = $2.loc;
         $$.loc = $2.loc;
     }
     }
+    | function_declarator RIGHT_PAREN attribute {
+        $$.function = $1;
+        $$.loc = $2.loc;
+        parseContext.requireExtensions($2.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute");
+        parseContext.handleFunctionAttributes($2.loc, *$3, $$.function);
+    }
+    | attribute function_declarator RIGHT_PAREN {
+        $$.function = $2;
+        $$.loc = $3.loc;
+        parseContext.requireExtensions($3.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute");
+        parseContext.handleFunctionAttributes($3.loc, *$1, $$.function);
+    }
+    | attribute function_declarator RIGHT_PAREN attribute {
+        $$.function = $2;
+        $$.loc = $3.loc;
+        parseContext.requireExtensions($3.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute");
+        parseContext.handleFunctionAttributes($3.loc, *$1, $$.function);
+        parseContext.handleFunctionAttributes($3.loc, *$4, $$.function);
+    }
     ;
     ;
 
 
 function_declarator
 function_declarator
@@ -1347,6 +1401,25 @@ GLSLANG_WEB_EXCLUDE_ON
     | non_uniform_qualifier {
     | non_uniform_qualifier {
         $$ = $1;
         $$ = $1;
     }
     }
+    | spirv_storage_class_qualifier {
+        parseContext.globalCheck($1.loc, "spirv_storage_class");
+        parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V storage class qualifier");
+        $$ = $1;
+    }
+    | spirv_decorate_qualifier {
+        parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V decorate qualifier");
+        $$ = $1;
+    }
+    | SPIRV_BY_REFERENCE {
+        parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_spirv_intrinsics, "spirv_by_reference");
+        $$.init($1.loc);
+        $$.qualifier.setSpirvByReference();
+    }
+    | SPIRV_LITERAL {
+        parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_spirv_intrinsics, "spirv_by_literal");
+        $$.init($1.loc);
+        $$.qualifier.setSpirvLiteral();
+    }
 GLSLANG_WEB_EXCLUDE_OFF
 GLSLANG_WEB_EXCLUDE_OFF
     ;
     ;
 
 
@@ -3407,6 +3480,10 @@ GLSLANG_WEB_EXCLUDE_ON
         $$.basicType = EbtUint;
         $$.basicType = EbtUint;
         $$.coopmat = true;
         $$.coopmat = true;
     }
     }
+    | spirv_type_specifier {
+        parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V type specifier");
+        $$ = $1;
+    }
 GLSLANG_WEB_EXCLUDE_OFF
 GLSLANG_WEB_EXCLUDE_OFF
     | struct_specifier {
     | struct_specifier {
         $$ = $1;
         $$ = $1;
@@ -3713,6 +3790,7 @@ selection_statement
     }
     }
 GLSLANG_WEB_EXCLUDE_ON
 GLSLANG_WEB_EXCLUDE_ON
     | attribute selection_statement_nonattributed {
     | attribute selection_statement_nonattributed {
+        parseContext.requireExtensions($2->getLoc(), 1, &E_GL_EXT_control_flow_attributes, "attribute");
         parseContext.handleSelectionAttributes(*$1, $2);
         parseContext.handleSelectionAttributes(*$1, $2);
         $$ = $2;
         $$ = $2;
     }
     }
@@ -3760,6 +3838,7 @@ switch_statement
     }
     }
 GLSLANG_WEB_EXCLUDE_ON
 GLSLANG_WEB_EXCLUDE_ON
     | attribute switch_statement_nonattributed {
     | attribute switch_statement_nonattributed {
+        parseContext.requireExtensions($2->getLoc(), 1, &E_GL_EXT_control_flow_attributes, "attribute");
         parseContext.handleSwitchAttributes(*$1, $2);
         parseContext.handleSwitchAttributes(*$1, $2);
         $$ = $2;
         $$ = $2;
     }
     }
@@ -3824,6 +3903,7 @@ iteration_statement
     }
     }
 GLSLANG_WEB_EXCLUDE_ON
 GLSLANG_WEB_EXCLUDE_ON
     | attribute iteration_statement_nonattributed {
     | attribute iteration_statement_nonattributed {
+        parseContext.requireExtensions($2->getLoc(), 1, &E_GL_EXT_control_flow_attributes, "attribute");
         parseContext.handleLoopAttributes(*$1, $2);
         parseContext.handleLoopAttributes(*$1, $2);
         $$ = $2;
         $$ = $2;
     }
     }
@@ -4027,7 +4107,6 @@ GLSLANG_WEB_EXCLUDE_ON
 attribute
 attribute
     : LEFT_BRACKET LEFT_BRACKET attribute_list RIGHT_BRACKET RIGHT_BRACKET {
     : LEFT_BRACKET LEFT_BRACKET attribute_list RIGHT_BRACKET RIGHT_BRACKET {
         $$ = $3;
         $$ = $3;
-        parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_control_flow_attributes, "attribute");
     }
     }
 
 
 attribute_list
 attribute_list
@@ -4047,4 +4126,273 @@ single_attribute
     }
     }
 GLSLANG_WEB_EXCLUDE_OFF
 GLSLANG_WEB_EXCLUDE_OFF
 
 
+GLSLANG_WEB_EXCLUDE_ON
+spirv_requirements_list
+    : spirv_requirements_parameter {
+        $$ = $1;
+    }
+    | spirv_requirements_list COMMA spirv_requirements_parameter {
+        $$ = parseContext.mergeSpirvRequirements($2.loc, $1, $3);
+    }
+
+spirv_requirements_parameter
+    : IDENTIFIER EQUAL LEFT_BRACKET spirv_extension_list RIGHT_BRACKET {
+        $$ = parseContext.makeSpirvRequirement($2.loc, *$1.string, $4->getAsAggregate(), nullptr);
+    }
+    | IDENTIFIER EQUAL LEFT_BRACKET spirv_capability_list RIGHT_BRACKET {
+        $$ = parseContext.makeSpirvRequirement($2.loc, *$1.string, nullptr, $4->getAsAggregate());
+    }
+
+spirv_extension_list
+    : STRING_LITERAL {
+        $$ = parseContext.intermediate.makeAggregate(parseContext.intermediate.addConstantUnion($1.string, $1.loc, true));
+    }
+    | spirv_extension_list COMMA STRING_LITERAL {
+        $$ = parseContext.intermediate.growAggregate($1, parseContext.intermediate.addConstantUnion($3.string, $3.loc, true));
+    }
+
+spirv_capability_list
+    : INTCONSTANT {
+        $$ = parseContext.intermediate.makeAggregate(parseContext.intermediate.addConstantUnion($1.i, $1.loc, true));
+    }
+    | spirv_capability_list COMMA INTCONSTANT {
+        $$ = parseContext.intermediate.growAggregate($1, parseContext.intermediate.addConstantUnion($3.i, $3.loc, true));
+    }
+
+spirv_execution_mode_qualifier
+    : SPIRV_EXECUTION_MODE LEFT_PAREN INTCONSTANT RIGHT_PAREN {
+        parseContext.intermediate.insertSpirvExecutionMode($3.i);
+        $$ = 0;
+    }
+    | SPIRV_EXECUTION_MODE LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT RIGHT_PAREN {
+        parseContext.intermediate.insertSpirvRequirement($3);
+        parseContext.intermediate.insertSpirvExecutionMode($5.i);
+        $$ = 0;
+    }
+    | SPIRV_EXECUTION_MODE LEFT_PAREN INTCONSTANT COMMA spirv_execution_mode_parameter_list RIGHT_PAREN {
+        parseContext.intermediate.insertSpirvExecutionMode($3.i, $5->getAsAggregate());
+        $$ = 0;
+    }
+    | SPIRV_EXECUTION_MODE LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_execution_mode_parameter_list RIGHT_PAREN {
+        parseContext.intermediate.insertSpirvRequirement($3);
+        parseContext.intermediate.insertSpirvExecutionMode($5.i, $7->getAsAggregate());
+        $$ = 0;
+    }
+    | SPIRV_EXECUTION_MODE_ID LEFT_PAREN INTCONSTANT COMMA spirv_execution_mode_id_parameter_list RIGHT_PAREN {
+        parseContext.intermediate.insertSpirvExecutionModeId($3.i, $5->getAsAggregate());
+        $$ = 0;
+    }
+    | SPIRV_EXECUTION_MODE_ID LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_execution_mode_id_parameter_list RIGHT_PAREN {
+        parseContext.intermediate.insertSpirvRequirement($3);
+        parseContext.intermediate.insertSpirvExecutionModeId($5.i, $7->getAsAggregate());
+        $$ = 0;
+    }
+
+spirv_execution_mode_parameter_list
+    : spirv_execution_mode_parameter {
+        $$ = parseContext.intermediate.makeAggregate($1);
+    }
+    | spirv_execution_mode_parameter_list COMMA spirv_execution_mode_parameter {
+        $$ = parseContext.intermediate.growAggregate($1, $3);
+    }
+
+spirv_execution_mode_parameter
+    : FLOATCONSTANT {
+        $$ = parseContext.intermediate.addConstantUnion($1.d, EbtFloat, $1.loc, true);
+    }
+    | INTCONSTANT {
+        $$ = parseContext.intermediate.addConstantUnion($1.i, $1.loc, true);
+    }
+    | UINTCONSTANT {
+        $$ = parseContext.intermediate.addConstantUnion($1.u, $1.loc, true);
+    }
+    | BOOLCONSTANT {
+        $$ = parseContext.intermediate.addConstantUnion($1.b, $1.loc, true);
+    }
+    | STRING_LITERAL {
+        $$ = parseContext.intermediate.addConstantUnion($1.string, $1.loc, true);
+    }
+
+spirv_execution_mode_id_parameter_list
+    : constant_expression {
+        if ($1->getBasicType() != EbtFloat &&
+            $1->getBasicType() != EbtInt &&
+            $1->getBasicType() != EbtUint &&
+            $1->getBasicType() != EbtBool &&
+            $1->getBasicType() != EbtString)
+            parseContext.error($1->getLoc(), "this type not allowed", $1->getType().getBasicString(), "");
+        $$ = parseContext.intermediate.makeAggregate($1);
+    }
+    | spirv_execution_mode_id_parameter_list COMMA constant_expression {
+        if ($3->getBasicType() != EbtFloat &&
+            $3->getBasicType() != EbtInt &&
+            $3->getBasicType() != EbtUint &&
+            $3->getBasicType() != EbtBool &&
+            $3->getBasicType() != EbtString)
+            parseContext.error($3->getLoc(), "this type not allowed", $3->getType().getBasicString(), "");
+        $$ = parseContext.intermediate.growAggregate($1, $3);
+    }
+
+spirv_storage_class_qualifier
+    : SPIRV_STORAGE_CLASS LEFT_PAREN INTCONSTANT RIGHT_PAREN {
+        $$.init($1.loc);
+        $$.qualifier.storage = EvqSpirvStorageClass;
+        $$.qualifier.spirvStorageClass = $3.i;
+    }
+    | SPIRV_STORAGE_CLASS LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT RIGHT_PAREN {
+        $$.init($1.loc);
+        parseContext.intermediate.insertSpirvRequirement($3);
+        $$.qualifier.storage = EvqSpirvStorageClass;
+        $$.qualifier.spirvStorageClass = $5.i;
+    }
+
+spirv_decorate_qualifier
+    : SPIRV_DECORATE LEFT_PAREN INTCONSTANT RIGHT_PAREN{
+        $$.init($1.loc);
+        $$.qualifier.setSpirvDecorate($3.i);
+    }
+    | SPIRV_DECORATE LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT RIGHT_PAREN{
+        $$.init($1.loc);
+        parseContext.intermediate.insertSpirvRequirement($3);
+        $$.qualifier.setSpirvDecorate($5.i);
+    }
+    | SPIRV_DECORATE LEFT_PAREN INTCONSTANT COMMA spirv_decorate_parameter_list RIGHT_PAREN {
+        $$.init($1.loc);
+        $$.qualifier.setSpirvDecorate($3.i, $5->getAsAggregate());
+    }
+    | SPIRV_DECORATE LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_decorate_parameter_list RIGHT_PAREN {
+        $$.init($1.loc);
+        parseContext.intermediate.insertSpirvRequirement($3);
+        $$.qualifier.setSpirvDecorate($5.i, $7->getAsAggregate());
+    }
+    | SPIRV_DECORATE_ID LEFT_PAREN INTCONSTANT COMMA spirv_decorate_id_parameter_list RIGHT_PAREN {
+        $$.init($1.loc);
+        $$.qualifier.setSpirvDecorateId($3.i, $5->getAsAggregate());
+    }
+    | SPIRV_DECORATE_ID LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_decorate_id_parameter_list RIGHT_PAREN {
+        $$.init($1.loc);
+        parseContext.intermediate.insertSpirvRequirement($3);
+        $$.qualifier.setSpirvDecorateId($5.i, $7->getAsAggregate());
+    }
+    | SPIRV_DECORATE_STRING LEFT_PAREN INTCONSTANT COMMA spirv_decorate_string_parameter_list RIGHT_PAREN {
+        $$.init($1.loc);
+        $$.qualifier.setSpirvDecorateString($3.i, $5->getAsAggregate());
+    }
+    | SPIRV_DECORATE_STRING LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_decorate_string_parameter_list RIGHT_PAREN {
+        $$.init($1.loc);
+        parseContext.intermediate.insertSpirvRequirement($3);
+        $$.qualifier.setSpirvDecorateString($5.i, $7->getAsAggregate());
+    }
+
+spirv_decorate_parameter_list
+    : spirv_decorate_parameter {
+        $$ = parseContext.intermediate.makeAggregate($1);
+    }
+    | spirv_decorate_parameter_list COMMA spirv_decorate_parameter {
+        $$ = parseContext.intermediate.growAggregate($1, $3);
+    }
+
+spirv_decorate_parameter
+    : FLOATCONSTANT {
+        $$ = parseContext.intermediate.addConstantUnion($1.d, EbtFloat, $1.loc, true);
+    }
+    | INTCONSTANT {
+        $$ = parseContext.intermediate.addConstantUnion($1.i, $1.loc, true);
+    }
+    | UINTCONSTANT {
+        $$ = parseContext.intermediate.addConstantUnion($1.u, $1.loc, true);
+    }
+    | BOOLCONSTANT {
+        $$ = parseContext.intermediate.addConstantUnion($1.b, $1.loc, true);
+    }
+
+spirv_decorate_id_parameter_list
+    : constant_expression {
+        if ($1->getBasicType() != EbtFloat &&
+            $1->getBasicType() != EbtInt &&
+            $1->getBasicType() != EbtUint &&
+            $1->getBasicType() != EbtBool)
+            parseContext.error($1->getLoc(), "this type not allowed", $1->getType().getBasicString(), "");
+        $$ = parseContext.intermediate.makeAggregate($1);
+    }
+    | spirv_decorate_id_parameter_list COMMA constant_expression {
+        if ($3->getBasicType() != EbtFloat &&
+            $3->getBasicType() != EbtInt &&
+            $3->getBasicType() != EbtUint &&
+            $3->getBasicType() != EbtBool)
+            parseContext.error($3->getLoc(), "this type not allowed", $3->getType().getBasicString(), "");
+        $$ = parseContext.intermediate.growAggregate($1, $3);
+    }
+
+spirv_decorate_string_parameter_list
+    : STRING_LITERAL {
+        $$ = parseContext.intermediate.makeAggregate(
+            parseContext.intermediate.addConstantUnion($1.string, $1.loc, true));
+    }
+    | spirv_decorate_string_parameter_list COMMA STRING_LITERAL {
+        $$ = parseContext.intermediate.growAggregate($1, parseContext.intermediate.addConstantUnion($3.string, $3.loc, true));
+    }
+
+spirv_type_specifier
+    : SPIRV_TYPE LEFT_PAREN spirv_instruction_qualifier_list COMMA spirv_type_parameter_list RIGHT_PAREN {
+        $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+        $$.setSpirvType(*$3, $5);
+    }
+    | SPIRV_TYPE LEFT_PAREN spirv_requirements_list COMMA spirv_instruction_qualifier_list COMMA spirv_type_parameter_list RIGHT_PAREN {
+        $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+        parseContext.intermediate.insertSpirvRequirement($3);
+        $$.setSpirvType(*$5, $7);
+    }
+    | SPIRV_TYPE LEFT_PAREN spirv_instruction_qualifier_list RIGHT_PAREN {
+        $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+        $$.setSpirvType(*$3);
+    }
+    | SPIRV_TYPE LEFT_PAREN spirv_requirements_list COMMA spirv_instruction_qualifier_list RIGHT_PAREN {
+        $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+        parseContext.intermediate.insertSpirvRequirement($3);
+        $$.setSpirvType(*$5);
+    }
+
+spirv_type_parameter_list
+    : spirv_type_parameter {
+        $$ = $1;
+    }
+    | spirv_type_parameter_list COMMA spirv_type_parameter {
+        $$ = parseContext.mergeSpirvTypeParameters($1, $3);
+    }
+
+spirv_type_parameter
+    : constant_expression {
+        $$ = parseContext.makeSpirvTypeParameters($1->getLoc(), $1->getAsConstantUnion());
+    }
+    | type_specifier {
+        $$ = parseContext.makeSpirvTypeParameters($1);
+    }
+
+spirv_instruction_qualifier
+    : SPIRV_INSTRUCTION LEFT_PAREN spirv_instruction_qualifier_list RIGHT_PAREN {
+        $$ = $3;
+    }
+    | SPIRV_INSTRUCTION LEFT_PAREN spirv_requirements_list COMMA spirv_instruction_qualifier_list RIGHT_PAREN {
+        parseContext.intermediate.insertSpirvRequirement($3);
+        $$ = $5;
+    }
+
+spirv_instruction_qualifier_list
+    : spirv_instruction_qualifier_id {
+        $$ = $1;
+    }
+    | spirv_instruction_qualifier_list COMMA spirv_instruction_qualifier_id {
+        $$ = parseContext.mergeSpirvInstruction($2.loc, $1, $3);
+    }
+
+spirv_instruction_qualifier_id
+    : IDENTIFIER EQUAL STRING_LITERAL {
+        $$ = parseContext.makeSpirvInstruction($2.loc, *$1.string, *$3.string);
+    }
+    | IDENTIFIER EQUAL INTCONSTANT {
+        $$ = parseContext.makeSpirvInstruction($2.loc, *$1.string, $3.i);
+    }
+GLSLANG_WEB_EXCLUDE_OFF
+
 %%
 %%

+ 349 - 1
3rdparty/glslang/glslang/MachineIndependent/glslang.y

@@ -116,6 +116,9 @@ using namespace glslang;
             glslang::TIntermNodePair nodePair;
             glslang::TIntermNodePair nodePair;
             glslang::TIntermTyped* intermTypedNode;
             glslang::TIntermTyped* intermTypedNode;
             glslang::TAttributes* attributes;
             glslang::TAttributes* attributes;
+            glslang::TSpirvRequirement* spirvReq;
+            glslang::TSpirvInstruction* spirvInst;
+            glslang::TSpirvTypeParameters* spirvTypeParams;
         };
         };
         union {
         union {
             glslang::TPublicType type;
             glslang::TPublicType type;
@@ -271,6 +274,11 @@ extern int yylex(YYSTYPE*, TParseContext&);
 %token <lex> SUBPASSINPUT SUBPASSINPUTMS ISUBPASSINPUT ISUBPASSINPUTMS USUBPASSINPUT USUBPASSINPUTMS
 %token <lex> SUBPASSINPUT SUBPASSINPUTMS ISUBPASSINPUT ISUBPASSINPUTMS USUBPASSINPUT USUBPASSINPUTMS
 %token <lex> F16SUBPASSINPUT F16SUBPASSINPUTMS
 %token <lex> F16SUBPASSINPUT F16SUBPASSINPUTMS
 
 
+// spirv intrinsics
+%token <lex> SPIRV_INSTRUCTION SPIRV_EXECUTION_MODE SPIRV_EXECUTION_MODE_ID
+%token <lex> SPIRV_DECORATE SPIRV_DECORATE_ID SPIRV_DECORATE_STRING
+%token <lex> SPIRV_TYPE SPIRV_STORAGE_CLASS SPIRV_BY_REFERENCE SPIRV_LITERAL
+
 
 
 
 
 %token <lex> LEFT_OP RIGHT_OP
 %token <lex> LEFT_OP RIGHT_OP
@@ -362,6 +370,19 @@ extern int yylex(YYSTYPE*, TParseContext&);
 %type <interm.attributes> attribute attribute_list single_attribute
 %type <interm.attributes> attribute attribute_list single_attribute
 %type <interm.intermNode> demote_statement
 %type <interm.intermNode> demote_statement
 %type <interm.intermTypedNode> initializer_list
 %type <interm.intermTypedNode> initializer_list
+%type <interm.spirvReq> spirv_requirements_list spirv_requirements_parameter
+%type <interm.intermNode> spirv_extension_list spirv_capability_list
+%type <interm.intermNode> spirv_execution_mode_qualifier
+%type <interm.intermNode> spirv_execution_mode_parameter_list spirv_execution_mode_parameter spirv_execution_mode_id_parameter_list
+%type <interm.type> spirv_storage_class_qualifier
+%type <interm.type> spirv_decorate_qualifier
+%type <interm.intermNode> spirv_decorate_parameter_list spirv_decorate_parameter
+%type <interm.intermNode> spirv_decorate_id_parameter_list
+%type <interm.intermNode> spirv_decorate_string_parameter_list
+%type <interm.type> spirv_type_specifier
+%type <interm.spirvTypeParams> spirv_type_parameter_list spirv_type_parameter
+%type <interm.spirvInst> spirv_instruction_qualifier
+%type <interm.spirvInst> spirv_instruction_qualifier_list spirv_instruction_qualifier_id
 
 
 
 
 %start translation_unit
 %start translation_unit
@@ -875,6 +896,20 @@ declaration
         $$ = 0;
         $$ = 0;
         // TODO: 4.0 functionality: subroutines: make the identifier a user type for this signature
         // TODO: 4.0 functionality: subroutines: make the identifier a user type for this signature
     }
     }
+
+    | spirv_instruction_qualifier function_prototype SEMICOLON {
+        parseContext.requireExtensions($2.loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V instruction qualifier");
+        $2.function->setSpirvInstruction(*$1); // Attach SPIR-V intruction qualifier
+        parseContext.handleFunctionDeclarator($2.loc, *$2.function, true /* prototype */);
+        $$ = 0;
+        // TODO: 4.0 functionality: subroutines: make the identifier a user type for this signature
+    }
+    | spirv_execution_mode_qualifier SEMICOLON {
+        parseContext.globalCheck($2.loc, "SPIR-V execution mode qualifier");
+        parseContext.requireExtensions($2.loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V execution mode qualifier");
+        $$ = 0;
+    }
+
     | init_declarator_list SEMICOLON {
     | init_declarator_list SEMICOLON {
         if ($1.intermNode && $1.intermNode->getAsAggregate())
         if ($1.intermNode && $1.intermNode->getAsAggregate())
             $1.intermNode->getAsAggregate()->setOperator(EOpSequence);
             $1.intermNode->getAsAggregate()->setOperator(EOpSequence);
@@ -944,6 +979,25 @@ function_prototype
         $$.function = $1;
         $$.function = $1;
         $$.loc = $2.loc;
         $$.loc = $2.loc;
     }
     }
+    | function_declarator RIGHT_PAREN attribute {
+        $$.function = $1;
+        $$.loc = $2.loc;
+        parseContext.requireExtensions($2.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute");
+        parseContext.handleFunctionAttributes($2.loc, *$3, $$.function);
+    }
+    | attribute function_declarator RIGHT_PAREN {
+        $$.function = $2;
+        $$.loc = $3.loc;
+        parseContext.requireExtensions($3.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute");
+        parseContext.handleFunctionAttributes($3.loc, *$1, $$.function);
+    }
+    | attribute function_declarator RIGHT_PAREN attribute {
+        $$.function = $2;
+        $$.loc = $3.loc;
+        parseContext.requireExtensions($3.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute");
+        parseContext.handleFunctionAttributes($3.loc, *$1, $$.function);
+        parseContext.handleFunctionAttributes($3.loc, *$4, $$.function);
+    }
     ;
     ;
 
 
 function_declarator
 function_declarator
@@ -1347,6 +1401,25 @@ single_type_qualifier
     | non_uniform_qualifier {
     | non_uniform_qualifier {
         $$ = $1;
         $$ = $1;
     }
     }
+    | spirv_storage_class_qualifier {
+        parseContext.globalCheck($1.loc, "spirv_storage_class");
+        parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V storage class qualifier");
+        $$ = $1;
+    }
+    | spirv_decorate_qualifier {
+        parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V decorate qualifier");
+        $$ = $1;
+    }
+    | SPIRV_BY_REFERENCE {
+        parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_spirv_intrinsics, "spirv_by_reference");
+        $$.init($1.loc);
+        $$.qualifier.setSpirvByReference();
+    }
+    | SPIRV_LITERAL {
+        parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_spirv_intrinsics, "spirv_by_literal");
+        $$.init($1.loc);
+        $$.qualifier.setSpirvLiteral();
+    }
 
 
     ;
     ;
 
 
@@ -3407,6 +3480,10 @@ type_specifier_nonarray
         $$.basicType = EbtUint;
         $$.basicType = EbtUint;
         $$.coopmat = true;
         $$.coopmat = true;
     }
     }
+    | spirv_type_specifier {
+        parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V type specifier");
+        $$ = $1;
+    }
 
 
     | struct_specifier {
     | struct_specifier {
         $$ = $1;
         $$ = $1;
@@ -3713,6 +3790,7 @@ selection_statement
     }
     }
 
 
     | attribute selection_statement_nonattributed {
     | attribute selection_statement_nonattributed {
+        parseContext.requireExtensions($2->getLoc(), 1, &E_GL_EXT_control_flow_attributes, "attribute");
         parseContext.handleSelectionAttributes(*$1, $2);
         parseContext.handleSelectionAttributes(*$1, $2);
         $$ = $2;
         $$ = $2;
     }
     }
@@ -3760,6 +3838,7 @@ switch_statement
     }
     }
 
 
     | attribute switch_statement_nonattributed {
     | attribute switch_statement_nonattributed {
+        parseContext.requireExtensions($2->getLoc(), 1, &E_GL_EXT_control_flow_attributes, "attribute");
         parseContext.handleSwitchAttributes(*$1, $2);
         parseContext.handleSwitchAttributes(*$1, $2);
         $$ = $2;
         $$ = $2;
     }
     }
@@ -3824,6 +3903,7 @@ iteration_statement
     }
     }
 
 
     | attribute iteration_statement_nonattributed {
     | attribute iteration_statement_nonattributed {
+        parseContext.requireExtensions($2->getLoc(), 1, &E_GL_EXT_control_flow_attributes, "attribute");
         parseContext.handleLoopAttributes(*$1, $2);
         parseContext.handleLoopAttributes(*$1, $2);
         $$ = $2;
         $$ = $2;
     }
     }
@@ -4027,7 +4107,6 @@ function_definition
 attribute
 attribute
     : LEFT_BRACKET LEFT_BRACKET attribute_list RIGHT_BRACKET RIGHT_BRACKET {
     : LEFT_BRACKET LEFT_BRACKET attribute_list RIGHT_BRACKET RIGHT_BRACKET {
         $$ = $3;
         $$ = $3;
-        parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_control_flow_attributes, "attribute");
     }
     }
 
 
 attribute_list
 attribute_list
@@ -4047,4 +4126,273 @@ single_attribute
     }
     }
 
 
 
 
+
+spirv_requirements_list
+    : spirv_requirements_parameter {
+        $$ = $1;
+    }
+    | spirv_requirements_list COMMA spirv_requirements_parameter {
+        $$ = parseContext.mergeSpirvRequirements($2.loc, $1, $3);
+    }
+
+spirv_requirements_parameter
+    : IDENTIFIER EQUAL LEFT_BRACKET spirv_extension_list RIGHT_BRACKET {
+        $$ = parseContext.makeSpirvRequirement($2.loc, *$1.string, $4->getAsAggregate(), nullptr);
+    }
+    | IDENTIFIER EQUAL LEFT_BRACKET spirv_capability_list RIGHT_BRACKET {
+        $$ = parseContext.makeSpirvRequirement($2.loc, *$1.string, nullptr, $4->getAsAggregate());
+    }
+
+spirv_extension_list
+    : STRING_LITERAL {
+        $$ = parseContext.intermediate.makeAggregate(parseContext.intermediate.addConstantUnion($1.string, $1.loc, true));
+    }
+    | spirv_extension_list COMMA STRING_LITERAL {
+        $$ = parseContext.intermediate.growAggregate($1, parseContext.intermediate.addConstantUnion($3.string, $3.loc, true));
+    }
+
+spirv_capability_list
+    : INTCONSTANT {
+        $$ = parseContext.intermediate.makeAggregate(parseContext.intermediate.addConstantUnion($1.i, $1.loc, true));
+    }
+    | spirv_capability_list COMMA INTCONSTANT {
+        $$ = parseContext.intermediate.growAggregate($1, parseContext.intermediate.addConstantUnion($3.i, $3.loc, true));
+    }
+
+spirv_execution_mode_qualifier
+    : SPIRV_EXECUTION_MODE LEFT_PAREN INTCONSTANT RIGHT_PAREN {
+        parseContext.intermediate.insertSpirvExecutionMode($3.i);
+        $$ = 0;
+    }
+    | SPIRV_EXECUTION_MODE LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT RIGHT_PAREN {
+        parseContext.intermediate.insertSpirvRequirement($3);
+        parseContext.intermediate.insertSpirvExecutionMode($5.i);
+        $$ = 0;
+    }
+    | SPIRV_EXECUTION_MODE LEFT_PAREN INTCONSTANT COMMA spirv_execution_mode_parameter_list RIGHT_PAREN {
+        parseContext.intermediate.insertSpirvExecutionMode($3.i, $5->getAsAggregate());
+        $$ = 0;
+    }
+    | SPIRV_EXECUTION_MODE LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_execution_mode_parameter_list RIGHT_PAREN {
+        parseContext.intermediate.insertSpirvRequirement($3);
+        parseContext.intermediate.insertSpirvExecutionMode($5.i, $7->getAsAggregate());
+        $$ = 0;
+    }
+    | SPIRV_EXECUTION_MODE_ID LEFT_PAREN INTCONSTANT COMMA spirv_execution_mode_id_parameter_list RIGHT_PAREN {
+        parseContext.intermediate.insertSpirvExecutionModeId($3.i, $5->getAsAggregate());
+        $$ = 0;
+    }
+    | SPIRV_EXECUTION_MODE_ID LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_execution_mode_id_parameter_list RIGHT_PAREN {
+        parseContext.intermediate.insertSpirvRequirement($3);
+        parseContext.intermediate.insertSpirvExecutionModeId($5.i, $7->getAsAggregate());
+        $$ = 0;
+    }
+
+spirv_execution_mode_parameter_list
+    : spirv_execution_mode_parameter {
+        $$ = parseContext.intermediate.makeAggregate($1);
+    }
+    | spirv_execution_mode_parameter_list COMMA spirv_execution_mode_parameter {
+        $$ = parseContext.intermediate.growAggregate($1, $3);
+    }
+
+spirv_execution_mode_parameter
+    : FLOATCONSTANT {
+        $$ = parseContext.intermediate.addConstantUnion($1.d, EbtFloat, $1.loc, true);
+    }
+    | INTCONSTANT {
+        $$ = parseContext.intermediate.addConstantUnion($1.i, $1.loc, true);
+    }
+    | UINTCONSTANT {
+        $$ = parseContext.intermediate.addConstantUnion($1.u, $1.loc, true);
+    }
+    | BOOLCONSTANT {
+        $$ = parseContext.intermediate.addConstantUnion($1.b, $1.loc, true);
+    }
+    | STRING_LITERAL {
+        $$ = parseContext.intermediate.addConstantUnion($1.string, $1.loc, true);
+    }
+
+spirv_execution_mode_id_parameter_list
+    : constant_expression {
+        if ($1->getBasicType() != EbtFloat &&
+            $1->getBasicType() != EbtInt &&
+            $1->getBasicType() != EbtUint &&
+            $1->getBasicType() != EbtBool &&
+            $1->getBasicType() != EbtString)
+            parseContext.error($1->getLoc(), "this type not allowed", $1->getType().getBasicString(), "");
+        $$ = parseContext.intermediate.makeAggregate($1);
+    }
+    | spirv_execution_mode_id_parameter_list COMMA constant_expression {
+        if ($3->getBasicType() != EbtFloat &&
+            $3->getBasicType() != EbtInt &&
+            $3->getBasicType() != EbtUint &&
+            $3->getBasicType() != EbtBool &&
+            $3->getBasicType() != EbtString)
+            parseContext.error($3->getLoc(), "this type not allowed", $3->getType().getBasicString(), "");
+        $$ = parseContext.intermediate.growAggregate($1, $3);
+    }
+
+spirv_storage_class_qualifier
+    : SPIRV_STORAGE_CLASS LEFT_PAREN INTCONSTANT RIGHT_PAREN {
+        $$.init($1.loc);
+        $$.qualifier.storage = EvqSpirvStorageClass;
+        $$.qualifier.spirvStorageClass = $3.i;
+    }
+    | SPIRV_STORAGE_CLASS LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT RIGHT_PAREN {
+        $$.init($1.loc);
+        parseContext.intermediate.insertSpirvRequirement($3);
+        $$.qualifier.storage = EvqSpirvStorageClass;
+        $$.qualifier.spirvStorageClass = $5.i;
+    }
+
+spirv_decorate_qualifier
+    : SPIRV_DECORATE LEFT_PAREN INTCONSTANT RIGHT_PAREN{
+        $$.init($1.loc);
+        $$.qualifier.setSpirvDecorate($3.i);
+    }
+    | SPIRV_DECORATE LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT RIGHT_PAREN{
+        $$.init($1.loc);
+        parseContext.intermediate.insertSpirvRequirement($3);
+        $$.qualifier.setSpirvDecorate($5.i);
+    }
+    | SPIRV_DECORATE LEFT_PAREN INTCONSTANT COMMA spirv_decorate_parameter_list RIGHT_PAREN {
+        $$.init($1.loc);
+        $$.qualifier.setSpirvDecorate($3.i, $5->getAsAggregate());
+    }
+    | SPIRV_DECORATE LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_decorate_parameter_list RIGHT_PAREN {
+        $$.init($1.loc);
+        parseContext.intermediate.insertSpirvRequirement($3);
+        $$.qualifier.setSpirvDecorate($5.i, $7->getAsAggregate());
+    }
+    | SPIRV_DECORATE_ID LEFT_PAREN INTCONSTANT COMMA spirv_decorate_id_parameter_list RIGHT_PAREN {
+        $$.init($1.loc);
+        $$.qualifier.setSpirvDecorateId($3.i, $5->getAsAggregate());
+    }
+    | SPIRV_DECORATE_ID LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_decorate_id_parameter_list RIGHT_PAREN {
+        $$.init($1.loc);
+        parseContext.intermediate.insertSpirvRequirement($3);
+        $$.qualifier.setSpirvDecorateId($5.i, $7->getAsAggregate());
+    }
+    | SPIRV_DECORATE_STRING LEFT_PAREN INTCONSTANT COMMA spirv_decorate_string_parameter_list RIGHT_PAREN {
+        $$.init($1.loc);
+        $$.qualifier.setSpirvDecorateString($3.i, $5->getAsAggregate());
+    }
+    | SPIRV_DECORATE_STRING LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_decorate_string_parameter_list RIGHT_PAREN {
+        $$.init($1.loc);
+        parseContext.intermediate.insertSpirvRequirement($3);
+        $$.qualifier.setSpirvDecorateString($5.i, $7->getAsAggregate());
+    }
+
+spirv_decorate_parameter_list
+    : spirv_decorate_parameter {
+        $$ = parseContext.intermediate.makeAggregate($1);
+    }
+    | spirv_decorate_parameter_list COMMA spirv_decorate_parameter {
+        $$ = parseContext.intermediate.growAggregate($1, $3);
+    }
+
+spirv_decorate_parameter
+    : FLOATCONSTANT {
+        $$ = parseContext.intermediate.addConstantUnion($1.d, EbtFloat, $1.loc, true);
+    }
+    | INTCONSTANT {
+        $$ = parseContext.intermediate.addConstantUnion($1.i, $1.loc, true);
+    }
+    | UINTCONSTANT {
+        $$ = parseContext.intermediate.addConstantUnion($1.u, $1.loc, true);
+    }
+    | BOOLCONSTANT {
+        $$ = parseContext.intermediate.addConstantUnion($1.b, $1.loc, true);
+    }
+
+spirv_decorate_id_parameter_list
+    : constant_expression {
+        if ($1->getBasicType() != EbtFloat &&
+            $1->getBasicType() != EbtInt &&
+            $1->getBasicType() != EbtUint &&
+            $1->getBasicType() != EbtBool)
+            parseContext.error($1->getLoc(), "this type not allowed", $1->getType().getBasicString(), "");
+        $$ = parseContext.intermediate.makeAggregate($1);
+    }
+    | spirv_decorate_id_parameter_list COMMA constant_expression {
+        if ($3->getBasicType() != EbtFloat &&
+            $3->getBasicType() != EbtInt &&
+            $3->getBasicType() != EbtUint &&
+            $3->getBasicType() != EbtBool)
+            parseContext.error($3->getLoc(), "this type not allowed", $3->getType().getBasicString(), "");
+        $$ = parseContext.intermediate.growAggregate($1, $3);
+    }
+
+spirv_decorate_string_parameter_list
+    : STRING_LITERAL {
+        $$ = parseContext.intermediate.makeAggregate(
+            parseContext.intermediate.addConstantUnion($1.string, $1.loc, true));
+    }
+    | spirv_decorate_string_parameter_list COMMA STRING_LITERAL {
+        $$ = parseContext.intermediate.growAggregate($1, parseContext.intermediate.addConstantUnion($3.string, $3.loc, true));
+    }
+
+spirv_type_specifier
+    : SPIRV_TYPE LEFT_PAREN spirv_instruction_qualifier_list COMMA spirv_type_parameter_list RIGHT_PAREN {
+        $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+        $$.setSpirvType(*$3, $5);
+    }
+    | SPIRV_TYPE LEFT_PAREN spirv_requirements_list COMMA spirv_instruction_qualifier_list COMMA spirv_type_parameter_list RIGHT_PAREN {
+        $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+        parseContext.intermediate.insertSpirvRequirement($3);
+        $$.setSpirvType(*$5, $7);
+    }
+    | SPIRV_TYPE LEFT_PAREN spirv_instruction_qualifier_list RIGHT_PAREN {
+        $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+        $$.setSpirvType(*$3);
+    }
+    | SPIRV_TYPE LEFT_PAREN spirv_requirements_list COMMA spirv_instruction_qualifier_list RIGHT_PAREN {
+        $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+        parseContext.intermediate.insertSpirvRequirement($3);
+        $$.setSpirvType(*$5);
+    }
+
+spirv_type_parameter_list
+    : spirv_type_parameter {
+        $$ = $1;
+    }
+    | spirv_type_parameter_list COMMA spirv_type_parameter {
+        $$ = parseContext.mergeSpirvTypeParameters($1, $3);
+    }
+
+spirv_type_parameter
+    : constant_expression {
+        $$ = parseContext.makeSpirvTypeParameters($1->getLoc(), $1->getAsConstantUnion());
+    }
+    | type_specifier {
+        $$ = parseContext.makeSpirvTypeParameters($1);
+    }
+
+spirv_instruction_qualifier
+    : SPIRV_INSTRUCTION LEFT_PAREN spirv_instruction_qualifier_list RIGHT_PAREN {
+        $$ = $3;
+    }
+    | SPIRV_INSTRUCTION LEFT_PAREN spirv_requirements_list COMMA spirv_instruction_qualifier_list RIGHT_PAREN {
+        parseContext.intermediate.insertSpirvRequirement($3);
+        $$ = $5;
+    }
+
+spirv_instruction_qualifier_list
+    : spirv_instruction_qualifier_id {
+        $$ = $1;
+    }
+    | spirv_instruction_qualifier_list COMMA spirv_instruction_qualifier_id {
+        $$ = parseContext.mergeSpirvInstruction($2.loc, $1, $3);
+    }
+
+spirv_instruction_qualifier_id
+    : IDENTIFIER EQUAL STRING_LITERAL {
+        $$ = parseContext.makeSpirvInstruction($2.loc, *$1.string, *$3.string);
+    }
+    | IDENTIFIER EQUAL INTCONSTANT {
+        $$ = parseContext.makeSpirvInstruction($2.loc, *$1.string, $3.i);
+    }
+
+
 %%
 %%

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 592 - 503
3rdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp


+ 142 - 129
3rdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp.h

@@ -368,134 +368,144 @@ extern int yydebug;
     USUBPASSINPUTMS = 569,         /* USUBPASSINPUTMS  */
     USUBPASSINPUTMS = 569,         /* USUBPASSINPUTMS  */
     F16SUBPASSINPUT = 570,         /* F16SUBPASSINPUT  */
     F16SUBPASSINPUT = 570,         /* F16SUBPASSINPUT  */
     F16SUBPASSINPUTMS = 571,       /* F16SUBPASSINPUTMS  */
     F16SUBPASSINPUTMS = 571,       /* F16SUBPASSINPUTMS  */
-    LEFT_OP = 572,                 /* LEFT_OP  */
-    RIGHT_OP = 573,                /* RIGHT_OP  */
-    INC_OP = 574,                  /* INC_OP  */
-    DEC_OP = 575,                  /* DEC_OP  */
-    LE_OP = 576,                   /* LE_OP  */
-    GE_OP = 577,                   /* GE_OP  */
-    EQ_OP = 578,                   /* EQ_OP  */
-    NE_OP = 579,                   /* NE_OP  */
-    AND_OP = 580,                  /* AND_OP  */
-    OR_OP = 581,                   /* OR_OP  */
-    XOR_OP = 582,                  /* XOR_OP  */
-    MUL_ASSIGN = 583,              /* MUL_ASSIGN  */
-    DIV_ASSIGN = 584,              /* DIV_ASSIGN  */
-    ADD_ASSIGN = 585,              /* ADD_ASSIGN  */
-    MOD_ASSIGN = 586,              /* MOD_ASSIGN  */
-    LEFT_ASSIGN = 587,             /* LEFT_ASSIGN  */
-    RIGHT_ASSIGN = 588,            /* RIGHT_ASSIGN  */
-    AND_ASSIGN = 589,              /* AND_ASSIGN  */
-    XOR_ASSIGN = 590,              /* XOR_ASSIGN  */
-    OR_ASSIGN = 591,               /* OR_ASSIGN  */
-    SUB_ASSIGN = 592,              /* SUB_ASSIGN  */
-    STRING_LITERAL = 593,          /* STRING_LITERAL  */
-    LEFT_PAREN = 594,              /* LEFT_PAREN  */
-    RIGHT_PAREN = 595,             /* RIGHT_PAREN  */
-    LEFT_BRACKET = 596,            /* LEFT_BRACKET  */
-    RIGHT_BRACKET = 597,           /* RIGHT_BRACKET  */
-    LEFT_BRACE = 598,              /* LEFT_BRACE  */
-    RIGHT_BRACE = 599,             /* RIGHT_BRACE  */
-    DOT = 600,                     /* DOT  */
-    COMMA = 601,                   /* COMMA  */
-    COLON = 602,                   /* COLON  */
-    EQUAL = 603,                   /* EQUAL  */
-    SEMICOLON = 604,               /* SEMICOLON  */
-    BANG = 605,                    /* BANG  */
-    DASH = 606,                    /* DASH  */
-    TILDE = 607,                   /* TILDE  */
-    PLUS = 608,                    /* PLUS  */
-    STAR = 609,                    /* STAR  */
-    SLASH = 610,                   /* SLASH  */
-    PERCENT = 611,                 /* PERCENT  */
-    LEFT_ANGLE = 612,              /* LEFT_ANGLE  */
-    RIGHT_ANGLE = 613,             /* RIGHT_ANGLE  */
-    VERTICAL_BAR = 614,            /* VERTICAL_BAR  */
-    CARET = 615,                   /* CARET  */
-    AMPERSAND = 616,               /* AMPERSAND  */
-    QUESTION = 617,                /* QUESTION  */
-    INVARIANT = 618,               /* INVARIANT  */
-    HIGH_PRECISION = 619,          /* HIGH_PRECISION  */
-    MEDIUM_PRECISION = 620,        /* MEDIUM_PRECISION  */
-    LOW_PRECISION = 621,           /* LOW_PRECISION  */
-    PRECISION = 622,               /* PRECISION  */
-    PACKED = 623,                  /* PACKED  */
-    RESOURCE = 624,                /* RESOURCE  */
-    SUPERP = 625,                  /* SUPERP  */
-    FLOATCONSTANT = 626,           /* FLOATCONSTANT  */
-    INTCONSTANT = 627,             /* INTCONSTANT  */
-    UINTCONSTANT = 628,            /* UINTCONSTANT  */
-    BOOLCONSTANT = 629,            /* BOOLCONSTANT  */
-    IDENTIFIER = 630,              /* IDENTIFIER  */
-    TYPE_NAME = 631,               /* TYPE_NAME  */
-    CENTROID = 632,                /* CENTROID  */
-    IN = 633,                      /* IN  */
-    OUT = 634,                     /* OUT  */
-    INOUT = 635,                   /* INOUT  */
-    STRUCT = 636,                  /* STRUCT  */
-    VOID = 637,                    /* VOID  */
-    WHILE = 638,                   /* WHILE  */
-    BREAK = 639,                   /* BREAK  */
-    CONTINUE = 640,                /* CONTINUE  */
-    DO = 641,                      /* DO  */
-    ELSE = 642,                    /* ELSE  */
-    FOR = 643,                     /* FOR  */
-    IF = 644,                      /* IF  */
-    DISCARD = 645,                 /* DISCARD  */
-    RETURN = 646,                  /* RETURN  */
-    SWITCH = 647,                  /* SWITCH  */
-    CASE = 648,                    /* CASE  */
-    DEFAULT = 649,                 /* DEFAULT  */
-    TERMINATE_INVOCATION = 650,    /* TERMINATE_INVOCATION  */
-    TERMINATE_RAY = 651,           /* TERMINATE_RAY  */
-    IGNORE_INTERSECTION = 652,     /* IGNORE_INTERSECTION  */
-    UNIFORM = 653,                 /* UNIFORM  */
-    SHARED = 654,                  /* SHARED  */
-    BUFFER = 655,                  /* BUFFER  */
-    FLAT = 656,                    /* FLAT  */
-    SMOOTH = 657,                  /* SMOOTH  */
-    LAYOUT = 658,                  /* LAYOUT  */
-    DOUBLECONSTANT = 659,          /* DOUBLECONSTANT  */
-    INT16CONSTANT = 660,           /* INT16CONSTANT  */
-    UINT16CONSTANT = 661,          /* UINT16CONSTANT  */
-    FLOAT16CONSTANT = 662,         /* FLOAT16CONSTANT  */
-    INT32CONSTANT = 663,           /* INT32CONSTANT  */
-    UINT32CONSTANT = 664,          /* UINT32CONSTANT  */
-    INT64CONSTANT = 665,           /* INT64CONSTANT  */
-    UINT64CONSTANT = 666,          /* UINT64CONSTANT  */
-    SUBROUTINE = 667,              /* SUBROUTINE  */
-    DEMOTE = 668,                  /* DEMOTE  */
-    PAYLOADNV = 669,               /* PAYLOADNV  */
-    PAYLOADINNV = 670,             /* PAYLOADINNV  */
-    HITATTRNV = 671,               /* HITATTRNV  */
-    CALLDATANV = 672,              /* CALLDATANV  */
-    CALLDATAINNV = 673,            /* CALLDATAINNV  */
-    PAYLOADEXT = 674,              /* PAYLOADEXT  */
-    PAYLOADINEXT = 675,            /* PAYLOADINEXT  */
-    HITATTREXT = 676,              /* HITATTREXT  */
-    CALLDATAEXT = 677,             /* CALLDATAEXT  */
-    CALLDATAINEXT = 678,           /* CALLDATAINEXT  */
-    PATCH = 679,                   /* PATCH  */
-    SAMPLE = 680,                  /* SAMPLE  */
-    NONUNIFORM = 681,              /* NONUNIFORM  */
-    COHERENT = 682,                /* COHERENT  */
-    VOLATILE = 683,                /* VOLATILE  */
-    RESTRICT = 684,                /* RESTRICT  */
-    READONLY = 685,                /* READONLY  */
-    WRITEONLY = 686,               /* WRITEONLY  */
-    DEVICECOHERENT = 687,          /* DEVICECOHERENT  */
-    QUEUEFAMILYCOHERENT = 688,     /* QUEUEFAMILYCOHERENT  */
-    WORKGROUPCOHERENT = 689,       /* WORKGROUPCOHERENT  */
-    SUBGROUPCOHERENT = 690,        /* SUBGROUPCOHERENT  */
-    NONPRIVATE = 691,              /* NONPRIVATE  */
-    SHADERCALLCOHERENT = 692,      /* SHADERCALLCOHERENT  */
-    NOPERSPECTIVE = 693,           /* NOPERSPECTIVE  */
-    EXPLICITINTERPAMD = 694,       /* EXPLICITINTERPAMD  */
-    PERVERTEXNV = 695,             /* PERVERTEXNV  */
-    PERPRIMITIVENV = 696,          /* PERPRIMITIVENV  */
-    PERVIEWNV = 697,               /* PERVIEWNV  */
-    PERTASKNV = 698,               /* PERTASKNV  */
-    PRECISE = 699                  /* PRECISE  */
+    SPIRV_INSTRUCTION = 572,       /* SPIRV_INSTRUCTION  */
+    SPIRV_EXECUTION_MODE = 573,    /* SPIRV_EXECUTION_MODE  */
+    SPIRV_EXECUTION_MODE_ID = 574, /* SPIRV_EXECUTION_MODE_ID  */
+    SPIRV_DECORATE = 575,          /* SPIRV_DECORATE  */
+    SPIRV_DECORATE_ID = 576,       /* SPIRV_DECORATE_ID  */
+    SPIRV_DECORATE_STRING = 577,   /* SPIRV_DECORATE_STRING  */
+    SPIRV_TYPE = 578,              /* SPIRV_TYPE  */
+    SPIRV_STORAGE_CLASS = 579,     /* SPIRV_STORAGE_CLASS  */
+    SPIRV_BY_REFERENCE = 580,      /* SPIRV_BY_REFERENCE  */
+    SPIRV_LITERAL = 581,           /* SPIRV_LITERAL  */
+    LEFT_OP = 582,                 /* LEFT_OP  */
+    RIGHT_OP = 583,                /* RIGHT_OP  */
+    INC_OP = 584,                  /* INC_OP  */
+    DEC_OP = 585,                  /* DEC_OP  */
+    LE_OP = 586,                   /* LE_OP  */
+    GE_OP = 587,                   /* GE_OP  */
+    EQ_OP = 588,                   /* EQ_OP  */
+    NE_OP = 589,                   /* NE_OP  */
+    AND_OP = 590,                  /* AND_OP  */
+    OR_OP = 591,                   /* OR_OP  */
+    XOR_OP = 592,                  /* XOR_OP  */
+    MUL_ASSIGN = 593,              /* MUL_ASSIGN  */
+    DIV_ASSIGN = 594,              /* DIV_ASSIGN  */
+    ADD_ASSIGN = 595,              /* ADD_ASSIGN  */
+    MOD_ASSIGN = 596,              /* MOD_ASSIGN  */
+    LEFT_ASSIGN = 597,             /* LEFT_ASSIGN  */
+    RIGHT_ASSIGN = 598,            /* RIGHT_ASSIGN  */
+    AND_ASSIGN = 599,              /* AND_ASSIGN  */
+    XOR_ASSIGN = 600,              /* XOR_ASSIGN  */
+    OR_ASSIGN = 601,               /* OR_ASSIGN  */
+    SUB_ASSIGN = 602,              /* SUB_ASSIGN  */
+    STRING_LITERAL = 603,          /* STRING_LITERAL  */
+    LEFT_PAREN = 604,              /* LEFT_PAREN  */
+    RIGHT_PAREN = 605,             /* RIGHT_PAREN  */
+    LEFT_BRACKET = 606,            /* LEFT_BRACKET  */
+    RIGHT_BRACKET = 607,           /* RIGHT_BRACKET  */
+    LEFT_BRACE = 608,              /* LEFT_BRACE  */
+    RIGHT_BRACE = 609,             /* RIGHT_BRACE  */
+    DOT = 610,                     /* DOT  */
+    COMMA = 611,                   /* COMMA  */
+    COLON = 612,                   /* COLON  */
+    EQUAL = 613,                   /* EQUAL  */
+    SEMICOLON = 614,               /* SEMICOLON  */
+    BANG = 615,                    /* BANG  */
+    DASH = 616,                    /* DASH  */
+    TILDE = 617,                   /* TILDE  */
+    PLUS = 618,                    /* PLUS  */
+    STAR = 619,                    /* STAR  */
+    SLASH = 620,                   /* SLASH  */
+    PERCENT = 621,                 /* PERCENT  */
+    LEFT_ANGLE = 622,              /* LEFT_ANGLE  */
+    RIGHT_ANGLE = 623,             /* RIGHT_ANGLE  */
+    VERTICAL_BAR = 624,            /* VERTICAL_BAR  */
+    CARET = 625,                   /* CARET  */
+    AMPERSAND = 626,               /* AMPERSAND  */
+    QUESTION = 627,                /* QUESTION  */
+    INVARIANT = 628,               /* INVARIANT  */
+    HIGH_PRECISION = 629,          /* HIGH_PRECISION  */
+    MEDIUM_PRECISION = 630,        /* MEDIUM_PRECISION  */
+    LOW_PRECISION = 631,           /* LOW_PRECISION  */
+    PRECISION = 632,               /* PRECISION  */
+    PACKED = 633,                  /* PACKED  */
+    RESOURCE = 634,                /* RESOURCE  */
+    SUPERP = 635,                  /* SUPERP  */
+    FLOATCONSTANT = 636,           /* FLOATCONSTANT  */
+    INTCONSTANT = 637,             /* INTCONSTANT  */
+    UINTCONSTANT = 638,            /* UINTCONSTANT  */
+    BOOLCONSTANT = 639,            /* BOOLCONSTANT  */
+    IDENTIFIER = 640,              /* IDENTIFIER  */
+    TYPE_NAME = 641,               /* TYPE_NAME  */
+    CENTROID = 642,                /* CENTROID  */
+    IN = 643,                      /* IN  */
+    OUT = 644,                     /* OUT  */
+    INOUT = 645,                   /* INOUT  */
+    STRUCT = 646,                  /* STRUCT  */
+    VOID = 647,                    /* VOID  */
+    WHILE = 648,                   /* WHILE  */
+    BREAK = 649,                   /* BREAK  */
+    CONTINUE = 650,                /* CONTINUE  */
+    DO = 651,                      /* DO  */
+    ELSE = 652,                    /* ELSE  */
+    FOR = 653,                     /* FOR  */
+    IF = 654,                      /* IF  */
+    DISCARD = 655,                 /* DISCARD  */
+    RETURN = 656,                  /* RETURN  */
+    SWITCH = 657,                  /* SWITCH  */
+    CASE = 658,                    /* CASE  */
+    DEFAULT = 659,                 /* DEFAULT  */
+    TERMINATE_INVOCATION = 660,    /* TERMINATE_INVOCATION  */
+    TERMINATE_RAY = 661,           /* TERMINATE_RAY  */
+    IGNORE_INTERSECTION = 662,     /* IGNORE_INTERSECTION  */
+    UNIFORM = 663,                 /* UNIFORM  */
+    SHARED = 664,                  /* SHARED  */
+    BUFFER = 665,                  /* BUFFER  */
+    FLAT = 666,                    /* FLAT  */
+    SMOOTH = 667,                  /* SMOOTH  */
+    LAYOUT = 668,                  /* LAYOUT  */
+    DOUBLECONSTANT = 669,          /* DOUBLECONSTANT  */
+    INT16CONSTANT = 670,           /* INT16CONSTANT  */
+    UINT16CONSTANT = 671,          /* UINT16CONSTANT  */
+    FLOAT16CONSTANT = 672,         /* FLOAT16CONSTANT  */
+    INT32CONSTANT = 673,           /* INT32CONSTANT  */
+    UINT32CONSTANT = 674,          /* UINT32CONSTANT  */
+    INT64CONSTANT = 675,           /* INT64CONSTANT  */
+    UINT64CONSTANT = 676,          /* UINT64CONSTANT  */
+    SUBROUTINE = 677,              /* SUBROUTINE  */
+    DEMOTE = 678,                  /* DEMOTE  */
+    PAYLOADNV = 679,               /* PAYLOADNV  */
+    PAYLOADINNV = 680,             /* PAYLOADINNV  */
+    HITATTRNV = 681,               /* HITATTRNV  */
+    CALLDATANV = 682,              /* CALLDATANV  */
+    CALLDATAINNV = 683,            /* CALLDATAINNV  */
+    PAYLOADEXT = 684,              /* PAYLOADEXT  */
+    PAYLOADINEXT = 685,            /* PAYLOADINEXT  */
+    HITATTREXT = 686,              /* HITATTREXT  */
+    CALLDATAEXT = 687,             /* CALLDATAEXT  */
+    CALLDATAINEXT = 688,           /* CALLDATAINEXT  */
+    PATCH = 689,                   /* PATCH  */
+    SAMPLE = 690,                  /* SAMPLE  */
+    NONUNIFORM = 691,              /* NONUNIFORM  */
+    COHERENT = 692,                /* COHERENT  */
+    VOLATILE = 693,                /* VOLATILE  */
+    RESTRICT = 694,                /* RESTRICT  */
+    READONLY = 695,                /* READONLY  */
+    WRITEONLY = 696,               /* WRITEONLY  */
+    DEVICECOHERENT = 697,          /* DEVICECOHERENT  */
+    QUEUEFAMILYCOHERENT = 698,     /* QUEUEFAMILYCOHERENT  */
+    WORKGROUPCOHERENT = 699,       /* WORKGROUPCOHERENT  */
+    SUBGROUPCOHERENT = 700,        /* SUBGROUPCOHERENT  */
+    NONPRIVATE = 701,              /* NONPRIVATE  */
+    SHADERCALLCOHERENT = 702,      /* SHADERCALLCOHERENT  */
+    NOPERSPECTIVE = 703,           /* NOPERSPECTIVE  */
+    EXPLICITINTERPAMD = 704,       /* EXPLICITINTERPAMD  */
+    PERVERTEXNV = 705,             /* PERVERTEXNV  */
+    PERPRIMITIVENV = 706,          /* PERPRIMITIVENV  */
+    PERVIEWNV = 707,               /* PERVIEWNV  */
+    PERTASKNV = 708,               /* PERTASKNV  */
+    PRECISE = 709                  /* PRECISE  */
   };
   };
   typedef enum yytokentype yytoken_kind_t;
   typedef enum yytokentype yytoken_kind_t;
 #endif
 #endif
@@ -527,6 +537,9 @@ union YYSTYPE
             glslang::TIntermNodePair nodePair;
             glslang::TIntermNodePair nodePair;
             glslang::TIntermTyped* intermTypedNode;
             glslang::TIntermTyped* intermTypedNode;
             glslang::TAttributes* attributes;
             glslang::TAttributes* attributes;
+            glslang::TSpirvRequirement* spirvReq;
+            glslang::TSpirvInstruction* spirvInst;
+            glslang::TSpirvTypeParameters* spirvTypeParams;
         };
         };
         union {
         union {
             glslang::TPublicType type;
             glslang::TPublicType type;
@@ -540,7 +553,7 @@ union YYSTYPE
         glslang::TArraySizes* typeParameters;
         glslang::TArraySizes* typeParameters;
     } interm;
     } interm;
 
 
-#line 544 "MachineIndependent/glslang_tab.cpp.h"
+#line 557 "MachineIndependent/glslang_tab.cpp.h"
 
 
 };
 };
 typedef union YYSTYPE YYSTYPE;
 typedef union YYSTYPE YYSTYPE;

+ 11 - 0
3rdparty/glslang/glslang/MachineIndependent/intermOut.cpp

@@ -696,6 +696,10 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
 
 
     case EOpConstructReference: out.debug << "Construct reference type"; break;
     case EOpConstructReference: out.debug << "Construct reference type"; break;
 
 
+#ifndef GLSLANG_WEB
+    case EOpSpirvInst: out.debug << "spirv_instruction"; break;
+#endif
+
     default: out.debug.message(EPrefixError, "Bad unary op");
     default: out.debug.message(EPrefixError, "Bad unary op");
     }
     }
 
 
@@ -1126,6 +1130,10 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
     case EOpIsHelperInvocation: out.debug << "IsHelperInvocation"; break;
     case EOpIsHelperInvocation: out.debug << "IsHelperInvocation"; break;
     case EOpDebugPrintf:  out.debug << "Debug printf";  break;
     case EOpDebugPrintf:  out.debug << "Debug printf";  break;
 
 
+#ifndef GLSLANG_WEB
+    case EOpSpirvInst: out.debug << "spirv_instruction"; break;
+#endif
+
     default: out.debug.message(EPrefixError, "Bad aggregation op");
     default: out.debug.message(EPrefixError, "Bad aggregation op");
     }
     }
 
 
@@ -1487,6 +1495,9 @@ void TIntermediate::output(TInfoSink& infoSink, bool tree)
     if (xfbMode)
     if (xfbMode)
         infoSink.debug << "in xfb mode\n";
         infoSink.debug << "in xfb mode\n";
 
 
+    if (getSubgroupUniformControlFlow())
+        infoSink.debug << "subgroup_uniform_control_flow\n";
+
     switch (language) {
     switch (language) {
     case EShLangVertex:
     case EShLangVertex:
         break;
         break;

+ 19 - 0
3rdparty/glslang/glslang/MachineIndependent/localintermediate.h

@@ -328,7 +328,10 @@ public:
         textureSamplerTransformMode(EShTexSampTransKeep),
         textureSamplerTransformMode(EShTexSampTransKeep),
         needToLegalize(false),
         needToLegalize(false),
         binaryDoubleOutput(false),
         binaryDoubleOutput(false),
+        subgroupUniformControlFlow(false),
         usePhysicalStorageBuffer(false),
         usePhysicalStorageBuffer(false),
+        spirvRequirement(nullptr),
+        spirvExecutionMode(nullptr),
         uniformLocationBase(0)
         uniformLocationBase(0)
 #endif
 #endif
     {
     {
@@ -864,6 +867,18 @@ public:
 
 
     void setBinaryDoubleOutput() { binaryDoubleOutput = true; }
     void setBinaryDoubleOutput() { binaryDoubleOutput = true; }
     bool getBinaryDoubleOutput() { return binaryDoubleOutput; }
     bool getBinaryDoubleOutput() { return binaryDoubleOutput; }
+
+    void setSubgroupUniformControlFlow() { subgroupUniformControlFlow = true; }
+    bool getSubgroupUniformControlFlow() const { return subgroupUniformControlFlow; }
+
+    // GL_EXT_spirv_intrinsics
+    void insertSpirvRequirement(const TSpirvRequirement* spirvReq);
+    bool hasSpirvRequirement() const { return spirvRequirement != nullptr; }
+    const TSpirvRequirement& getSpirvRequirement() const { return *spirvRequirement; }
+    void insertSpirvExecutionMode(int executionMode, const TIntermAggregate* args = nullptr);
+    void insertSpirvExecutionModeId(int executionMode, const TIntermAggregate* args);
+    bool hasSpirvExecutionMode() const { return spirvExecutionMode != nullptr; }
+    const TSpirvExecutionMode& getSpirvExecutionMode() const { return *spirvExecutionMode; }
 #endif // GLSLANG_WEB
 #endif // GLSLANG_WEB
 
 
     void addBlockStorageOverride(const char* nameStr, TBlockStorageClass backing)
     void addBlockStorageOverride(const char* nameStr, TBlockStorageClass backing)
@@ -1115,8 +1130,12 @@ protected:
 
 
     bool needToLegalize;
     bool needToLegalize;
     bool binaryDoubleOutput;
     bool binaryDoubleOutput;
+    bool subgroupUniformControlFlow;
     bool usePhysicalStorageBuffer;
     bool usePhysicalStorageBuffer;
 
 
+    TSpirvRequirement* spirvRequirement;
+    TSpirvExecutionMode* spirvExecutionMode;
+
     std::unordered_map<std::string, int> uniformLocationOverrides;
     std::unordered_map<std::string, int> uniformLocationOverrides;
     int uniformLocationBase;
     int uniformLocationBase;
     TNumericFeatures numericFeatures;
     TNumericFeatures numericFeatures;

+ 5 - 3
3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp

@@ -1191,9 +1191,11 @@ int TPpContext::tokenize(TPpToken& ppToken)
             // HLSL allows string literals.
             // HLSL allows string literals.
             // GLSL allows string literals with GL_EXT_debug_printf.
             // GLSL allows string literals with GL_EXT_debug_printf.
             if (ifdepth == 0 && parseContext.intermediate.getSource() != EShSourceHlsl) {
             if (ifdepth == 0 && parseContext.intermediate.getSource() != EShSourceHlsl) {
-                parseContext.requireExtensions(ppToken.loc, 1, &E_GL_EXT_debug_printf, "string literal");
-                if (!parseContext.extensionTurnedOn(E_GL_EXT_debug_printf))
-                    continue;
+              const char* const string_literal_EXTs[] = { E_GL_EXT_debug_printf, E_GL_EXT_spirv_intrinsics };
+              parseContext.requireExtensions(ppToken.loc, 2, string_literal_EXTs, "string literal");
+              if (!parseContext.extensionTurnedOn(E_GL_EXT_debug_printf) &&
+                  !parseContext.extensionTurnedOn(E_GL_EXT_spirv_intrinsics))
+                  continue;
             }
             }
             break;
             break;
         case '\'':
         case '\'':

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels