Browse Source

Update glslang

Alex Szpakowski 4 years ago
parent
commit
319faf5bc3
41 changed files with 4217 additions and 1493 deletions
  1. 1 0
      src/libraries/glslang/SPIRV/GLSL.ext.EXT.h
  2. 4 0
      src/libraries/glslang/SPIRV/GLSL.ext.KHR.h
  3. 296 87
      src/libraries/glslang/SPIRV/GlslangToSpv.cpp
  4. 40 13
      src/libraries/glslang/SPIRV/SpvBuilder.cpp
  5. 13 4
      src/libraries/glslang/SPIRV/SpvBuilder.h
  6. 32 0
      src/libraries/glslang/SPIRV/SpvPostProcess.cpp
  7. 12 10
      src/libraries/glslang/SPIRV/SpvTools.cpp
  8. 8 3
      src/libraries/glslang/SPIRV/SpvTools.h
  9. 59 14
      src/libraries/glslang/SPIRV/doc.cpp
  10. 134 12
      src/libraries/glslang/SPIRV/spirv.hpp
  11. 1 0
      src/libraries/glslang/SPIRV/spvIR.h
  12. 6 0
      src/libraries/glslang/glslang/Include/BaseTypes.h
  13. 112 11
      src/libraries/glslang/glslang/Include/Types.h
  14. 38 22
      src/libraries/glslang/glslang/Include/glslang_c_interface.h
  15. 3 2
      src/libraries/glslang/glslang/Include/glslang_c_shader_types.h
  16. 28 11
      src/libraries/glslang/glslang/Include/intermediate.h
  17. 4 10
      src/libraries/glslang/glslang/MachineIndependent/Constant.cpp
  18. 274 32
      src/libraries/glslang/glslang/MachineIndependent/Initialize.cpp
  19. 7 0
      src/libraries/glslang/glslang/MachineIndependent/IntermTraverse.cpp
  20. 16 7
      src/libraries/glslang/glslang/MachineIndependent/Intermediate.cpp
  21. 117 36
      src/libraries/glslang/glslang/MachineIndependent/ParseContextBase.cpp
  22. 492 42
      src/libraries/glslang/glslang/MachineIndependent/ParseHelper.cpp
  23. 46 9
      src/libraries/glslang/glslang/MachineIndependent/ParseHelper.h
  24. 99 1
      src/libraries/glslang/glslang/MachineIndependent/Scan.cpp
  25. 100 8
      src/libraries/glslang/glslang/MachineIndependent/ShaderLang.cpp
  26. 5 1
      src/libraries/glslang/glslang/MachineIndependent/SymbolTable.cpp
  27. 42 10
      src/libraries/glslang/glslang/MachineIndependent/SymbolTable.h
  28. 23 3
      src/libraries/glslang/glslang/MachineIndependent/Versions.cpp
  29. 7 1
      src/libraries/glslang/glslang/MachineIndependent/Versions.h
  30. 3 3
      src/libraries/glslang/glslang/MachineIndependent/gl_types.h
  31. 593 510
      src/libraries/glslang/glslang/MachineIndependent/glslang_tab.cpp
  32. 458 424
      src/libraries/glslang/glslang/MachineIndependent/glslang_tab.cpp.h
  33. 27 12
      src/libraries/glslang/glslang/MachineIndependent/intermOut.cpp
  34. 489 117
      src/libraries/glslang/glslang/MachineIndependent/iomapper.cpp
  35. 46 10
      src/libraries/glslang/glslang/MachineIndependent/iomapper.h
  36. 3 3
      src/libraries/glslang/glslang/MachineIndependent/limits.cpp
  37. 433 44
      src/libraries/glslang/glslang/MachineIndependent/linkValidate.cpp
  38. 108 11
      src/libraries/glslang/glslang/MachineIndependent/localintermediate.h
  39. 1 0
      src/libraries/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp
  40. 12 7
      src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpTokens.cpp
  41. 25 3
      src/libraries/glslang/glslang/Public/ShaderLang.h

+ 1 - 0
src/libraries/glslang/SPIRV/GLSL.ext.EXT.h

@@ -36,5 +36,6 @@ 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_image_int64 = "SPV_EXT_shader_image_int64";
 
 
 #endif  // #ifndef GLSLextEXT_H
 #endif  // #ifndef GLSLextEXT_H

+ 4 - 0
src/libraries/glslang/SPIRV/GLSL.ext.KHR.h

@@ -48,4 +48,8 @@ static const char* const E_SPV_KHR_shader_clock                 = "SPV_KHR_shade
 static const char* const E_SPV_KHR_non_semantic_info            = "SPV_KHR_non_semantic_info";
 static const char* const E_SPV_KHR_non_semantic_info            = "SPV_KHR_non_semantic_info";
 static const char* const E_SPV_KHR_ray_tracing                  = "SPV_KHR_ray_tracing";
 static const char* const E_SPV_KHR_ray_tracing                  = "SPV_KHR_ray_tracing";
 static const char* const E_SPV_KHR_ray_query                    = "SPV_KHR_ray_query";
 static const char* const E_SPV_KHR_ray_query                    = "SPV_KHR_ray_query";
+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_workgroup_memory_explicit_layout = "SPV_KHR_workgroup_memory_explicit_layout";
+
 #endif  // #ifndef GLSLextKHR_H
 #endif  // #ifndef GLSLextKHR_H

+ 296 - 87
src/libraries/glslang/SPIRV/GlslangToSpv.cpp

@@ -149,6 +149,7 @@ protected:
     spv::Decoration TranslateInterpolationDecoration(const glslang::TQualifier& qualifier);
     spv::Decoration TranslateInterpolationDecoration(const glslang::TQualifier& qualifier);
     spv::Decoration TranslateAuxiliaryStorageDecoration(const glslang::TQualifier& qualifier);
     spv::Decoration TranslateAuxiliaryStorageDecoration(const glslang::TQualifier& qualifier);
     spv::Decoration TranslateNonUniformDecoration(const glslang::TQualifier& qualifier);
     spv::Decoration TranslateNonUniformDecoration(const glslang::TQualifier& qualifier);
+    spv::Decoration TranslateNonUniformDecoration(const spv::Builder::AccessChain::CoherentFlags& coherentFlags);
     spv::Builder::AccessChain::CoherentFlags TranslateCoherent(const glslang::TType& type);
     spv::Builder::AccessChain::CoherentFlags TranslateCoherent(const glslang::TType& type);
     spv::MemoryAccessMask TranslateMemoryAccess(const spv::Builder::AccessChain::CoherentFlags &coherentFlags);
     spv::MemoryAccessMask TranslateMemoryAccess(const spv::Builder::AccessChain::CoherentFlags &coherentFlags);
     spv::ImageOperandsMask TranslateImageOperands(const spv::Builder::AccessChain::CoherentFlags &coherentFlags);
     spv::ImageOperandsMask TranslateImageOperands(const spv::Builder::AccessChain::CoherentFlags &coherentFlags);
@@ -189,6 +190,7 @@ protected:
     bool originalParam(glslang::TStorageQualifier, const glslang::TType&, bool implicitThisParam);
     bool originalParam(glslang::TStorageQualifier, const glslang::TType&, bool implicitThisParam);
     void makeFunctions(const glslang::TIntermSequence&);
     void makeFunctions(const glslang::TIntermSequence&);
     void makeGlobalInitializers(const glslang::TIntermSequence&);
     void makeGlobalInitializers(const glslang::TIntermSequence&);
+    void collectRayTracingLinkerObjects();
     void visitFunctions(const glslang::TIntermSequence&);
     void visitFunctions(const glslang::TIntermSequence&);
     void handleFunctionEntry(const glslang::TIntermAggregate* node);
     void handleFunctionEntry(const glslang::TIntermAggregate* node);
     void translateArguments(const glslang::TIntermAggregate& node, std::vector<spv::Id>& arguments,
     void translateArguments(const glslang::TIntermAggregate& node, std::vector<spv::Id>& arguments,
@@ -253,17 +255,17 @@ protected:
     bool nanMinMaxClamp;               // true if use NMin/NMax/NClamp instead of FMin/FMax/FClamp
     bool nanMinMaxClamp;               // true if use NMin/NMax/NClamp instead of FMin/FMax/FClamp
     spv::Id stdBuiltins;
     spv::Id stdBuiltins;
     spv::Id nonSemanticDebugPrintf;
     spv::Id nonSemanticDebugPrintf;
-    std::unordered_map<const char*, spv::Id> extBuiltinMap;
+    std::unordered_map<std::string, spv::Id> extBuiltinMap;
 
 
-    std::unordered_map<int, spv::Id> symbolValues;
-    std::unordered_set<int> rValueParameters;  // set of formal function parameters passed as rValues,
+    std::unordered_map<long long, spv::Id> symbolValues;
+    std::unordered_set<long long> rValueParameters;  // set of formal function parameters passed as rValues,
                                                // rather than a pointer
                                                // rather than a pointer
     std::unordered_map<std::string, spv::Function*> functionMap;
     std::unordered_map<std::string, spv::Function*> functionMap;
     std::unordered_map<const glslang::TTypeList*, spv::Id> structMap[glslang::ElpCount][glslang::ElmCount];
     std::unordered_map<const glslang::TTypeList*, spv::Id> structMap[glslang::ElpCount][glslang::ElmCount];
     // for mapping glslang block indices to spv indices (e.g., due to hidden members):
     // for mapping glslang block indices to spv indices (e.g., due to hidden members):
-    std::unordered_map<int, std::vector<int>> memberRemapper;
+    std::unordered_map<long long, std::vector<int>> memberRemapper;
     // for mapping glslang symbol struct to symbol Id
     // for mapping glslang symbol struct to symbol Id
-    std::unordered_map<const glslang::TTypeList*, int> glslangTypeToIdMap;
+    std::unordered_map<const glslang::TTypeList*, long long> glslangTypeToIdMap;
     std::stack<bool> breakForLoop;  // false means break for switch
     std::stack<bool> breakForLoop;  // false means break for switch
     std::unordered_map<std::string, const glslang::TIntermSymbol*> counterOriginator;
     std::unordered_map<std::string, const glslang::TIntermSymbol*> counterOriginator;
     // Map pointee types for EbtReference to their forward pointers
     // Map pointee types for EbtReference to their forward pointers
@@ -272,6 +274,9 @@ protected:
     // requiring local translation to and from SPIR-V type on every access.
     // requiring local translation to and from SPIR-V type on every access.
     // Maps <builtin-variable-id -> AST-required-type-id>
     // Maps <builtin-variable-id -> AST-required-type-id>
     std::unordered_map<spv::Id, spv::Id> forceType;
     std::unordered_map<spv::Id, spv::Id> forceType;
+
+    // Used later for generating OpTraceKHR/OpExecuteCallableKHR
+    std::unordered_map<unsigned int, glslang::TIntermSymbol *> locationToSymbol[2];
 };
 };
 
 
 //
 //
@@ -375,6 +380,7 @@ spv::Decoration TranslateBlockDecoration(const glslang::TType& type, bool useSto
         case glslang::EvqBuffer:       return useStorageBuffer ? spv::DecorationBlock : spv::DecorationBufferBlock;
         case glslang::EvqBuffer:       return useStorageBuffer ? spv::DecorationBlock : spv::DecorationBufferBlock;
         case glslang::EvqVaryingIn:    return spv::DecorationBlock;
         case glslang::EvqVaryingIn:    return spv::DecorationBlock;
         case glslang::EvqVaryingOut:   return spv::DecorationBlock;
         case glslang::EvqVaryingOut:   return spv::DecorationBlock;
+        case glslang::EvqShared:       return spv::DecorationBlock;
 #ifndef GLSLANG_WEB
 #ifndef GLSLANG_WEB
         case glslang::EvqPayload:      return spv::DecorationBlock;
         case glslang::EvqPayload:      return spv::DecorationBlock;
         case glslang::EvqPayloadIn:    return spv::DecorationBlock;
         case glslang::EvqPayloadIn:    return spv::DecorationBlock;
@@ -431,6 +437,7 @@ spv::Decoration TranslateLayoutDecoration(const glslang::TType& type, glslang::T
             break;
             break;
         case glslang::EbtBlock:
         case glslang::EbtBlock:
             switch (type.getQualifier().storage) {
             switch (type.getQualifier().storage) {
+            case glslang::EvqShared:
             case glslang::EvqUniform:
             case glslang::EvqUniform:
             case glslang::EvqBuffer:
             case glslang::EvqBuffer:
                 switch (type.getQualifier().layoutPacking) {
                 switch (type.getQualifier().layoutPacking) {
@@ -539,6 +546,20 @@ spv::Decoration TGlslangToSpvTraverser::TranslateNonUniformDecoration(const glsl
         return spv::DecorationMax;
         return spv::DecorationMax;
 }
 }
 
 
+// If lvalue flags contains nonUniform, return SPIR-V NonUniform decoration.
+spv::Decoration TGlslangToSpvTraverser::TranslateNonUniformDecoration(
+    const spv::Builder::AccessChain::CoherentFlags& coherentFlags)
+{
+#ifndef GLSLANG_WEB
+    if (coherentFlags.isNonUniform()) {
+        builder.addIncorporatedExtension("SPV_EXT_descriptor_indexing", spv::Spv_1_5);
+        builder.addCapability(spv::CapabilityShaderNonUniformEXT);
+        return spv::DecorationNonUniformEXT;
+    } else
+#endif
+        return spv::DecorationMax;
+}
+
 spv::MemoryAccessMask TGlslangToSpvTraverser::TranslateMemoryAccess(
 spv::MemoryAccessMask TGlslangToSpvTraverser::TranslateMemoryAccess(
     const spv::Builder::AccessChain::CoherentFlags &coherentFlags)
     const spv::Builder::AccessChain::CoherentFlags &coherentFlags)
 {
 {
@@ -614,6 +635,7 @@ spv::Builder::AccessChain::CoherentFlags TGlslangToSpvTraverser::TranslateCohere
                        flags.volatil;
                        flags.volatil;
     flags.isImage = type.getBasicType() == glslang::EbtSampler;
     flags.isImage = type.getBasicType() == glslang::EbtSampler;
 #endif
 #endif
+    flags.nonUniform = type.getQualifier().nonUniform;
     return flags;
     return flags;
 }
 }
 
 
@@ -709,13 +731,20 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI
         return spv::BuiltInCullDistance;
         return spv::BuiltInCullDistance;
 
 
     case glslang::EbvViewportIndex:
     case glslang::EbvViewportIndex:
-        builder.addCapability(spv::CapabilityMultiViewport);
+        if (glslangIntermediate->getStage() == EShLangGeometry ||
+            glslangIntermediate->getStage() == EShLangFragment) {
+            builder.addCapability(spv::CapabilityMultiViewport);
+        }
         if (glslangIntermediate->getStage() == EShLangVertex ||
         if (glslangIntermediate->getStage() == EShLangVertex ||
             glslangIntermediate->getStage() == EShLangTessControl ||
             glslangIntermediate->getStage() == EShLangTessControl ||
             glslangIntermediate->getStage() == EShLangTessEvaluation) {
             glslangIntermediate->getStage() == EShLangTessEvaluation) {
 
 
-            builder.addIncorporatedExtension(spv::E_SPV_EXT_shader_viewport_index_layer, spv::Spv_1_5);
-            builder.addCapability(spv::CapabilityShaderViewportIndexLayerEXT);
+            if (builder.getSpvVersion() < spv::Spv_1_5) {
+                builder.addIncorporatedExtension(spv::E_SPV_EXT_shader_viewport_index_layer, spv::Spv_1_5);
+                builder.addCapability(spv::CapabilityShaderViewportIndexLayerEXT);
+            }
+            else
+                builder.addCapability(spv::CapabilityShaderViewportIndex);
         }
         }
         return spv::BuiltInViewportIndex;
         return spv::BuiltInViewportIndex;
 
 
@@ -734,13 +763,19 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI
         if (glslangIntermediate->getStage() == EShLangMeshNV) {
         if (glslangIntermediate->getStage() == EShLangMeshNV) {
             return spv::BuiltInLayer;
             return spv::BuiltInLayer;
         }
         }
-        builder.addCapability(spv::CapabilityGeometry);
+        if (glslangIntermediate->getStage() == EShLangGeometry ||
+            glslangIntermediate->getStage() == EShLangFragment) {
+            builder.addCapability(spv::CapabilityGeometry);
+        }
         if (glslangIntermediate->getStage() == EShLangVertex ||
         if (glslangIntermediate->getStage() == EShLangVertex ||
             glslangIntermediate->getStage() == EShLangTessControl ||
             glslangIntermediate->getStage() == EShLangTessControl ||
             glslangIntermediate->getStage() == EShLangTessEvaluation) {
             glslangIntermediate->getStage() == EShLangTessEvaluation) {
 
 
-            builder.addIncorporatedExtension(spv::E_SPV_EXT_shader_viewport_index_layer, spv::Spv_1_5);
-            builder.addCapability(spv::CapabilityShaderViewportIndexLayerEXT);
+            if (builder.getSpvVersion() < spv::Spv_1_5) {
+                builder.addIncorporatedExtension(spv::E_SPV_EXT_shader_viewport_index_layer, spv::Spv_1_5);
+                builder.addCapability(spv::CapabilityShaderViewportIndexLayerEXT);
+            } else
+                builder.addCapability(spv::CapabilityShaderLayer);
         }
         }
         return spv::BuiltInLayer;
         return spv::BuiltInLayer;
 
 
@@ -769,6 +804,16 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI
         builder.addCapability(spv::CapabilityStencilExportEXT);
         builder.addCapability(spv::CapabilityStencilExportEXT);
         return spv::BuiltInFragStencilRefEXT;
         return spv::BuiltInFragStencilRefEXT;
 
 
+    case glslang::EbvShadingRateKHR:
+        builder.addExtension(spv::E_SPV_KHR_fragment_shading_rate);
+        builder.addCapability(spv::CapabilityFragmentShadingRateKHR);
+        return spv::BuiltInShadingRateKHR;
+
+    case glslang::EbvPrimitiveShadingRateKHR:
+        builder.addExtension(spv::E_SPV_KHR_fragment_shading_rate);
+        builder.addCapability(spv::CapabilityFragmentShadingRateKHR);
+        return spv::BuiltInPrimitiveShadingRateKHR;
+
     case glslang::EbvInvocationId:         return spv::BuiltInInvocationId;
     case glslang::EbvInvocationId:         return spv::BuiltInInvocationId;
     case glslang::EbvTessLevelInner:       return spv::BuiltInTessLevelInner;
     case glslang::EbvTessLevelInner:       return spv::BuiltInTessLevelInner;
     case glslang::EbvTessLevelOuter:       return spv::BuiltInTessLevelOuter;
     case glslang::EbvTessLevelOuter:       return spv::BuiltInTessLevelOuter;
@@ -963,7 +1008,17 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI
     case glslang::EbvInstanceCustomIndex:
     case glslang::EbvInstanceCustomIndex:
         return spv::BuiltInInstanceCustomIndexKHR;
         return spv::BuiltInInstanceCustomIndexKHR;
     case glslang::EbvHitT:
     case glslang::EbvHitT:
-        return spv::BuiltInHitTKHR;
+        {
+            // this is a GLSL alias of RayTmax
+            // in SPV_NV_ray_tracing it has a dedicated builtin
+            // but in SPV_KHR_ray_tracing it gets mapped to RayTmax
+            auto& extensions = glslangIntermediate->getRequestedExtensions();
+            if (extensions.find("GL_NV_ray_tracing") != extensions.end()) {
+                return spv::BuiltInHitTNV;
+            } else {
+                return spv::BuiltInRayTmaxKHR;
+            }
+        }
     case glslang::EbvHitKind:
     case glslang::EbvHitKind:
         return spv::BuiltInHitKindKHR;
         return spv::BuiltInHitKindKHR;
     case glslang::EbvObjectToWorld:
     case glslang::EbvObjectToWorld:
@@ -1071,6 +1126,10 @@ spv::ImageFormat TGlslangToSpvTraverser::TranslateImageFormat(const glslang::TTy
         builder.addCapability(spv::CapabilityStorageImageExtendedFormats);
         builder.addCapability(spv::CapabilityStorageImageExtendedFormats);
         break;
         break;
 
 
+    case glslang::ElfR64ui:
+    case glslang::ElfR64i:
+        builder.addExtension(spv::E_SPV_EXT_shader_image_int64);
+        builder.addCapability(spv::CapabilityInt64ImageEXT);
     default:
     default:
         break;
         break;
     }
     }
@@ -1117,6 +1176,8 @@ spv::ImageFormat TGlslangToSpvTraverser::TranslateImageFormat(const glslang::TTy
     case glslang::ElfRg8ui:         return spv::ImageFormatRg8ui;
     case glslang::ElfRg8ui:         return spv::ImageFormatRg8ui;
     case glslang::ElfR16ui:         return spv::ImageFormatR16ui;
     case glslang::ElfR16ui:         return spv::ImageFormatR16ui;
     case glslang::ElfR8ui:          return spv::ImageFormatR8ui;
     case glslang::ElfR8ui:          return spv::ImageFormatR8ui;
+    case glslang::ElfR64ui:         return spv::ImageFormatR64ui;
+    case glslang::ElfR64i:          return spv::ImageFormatR64i;
     default:                        return spv::ImageFormatMax;
     default:                        return spv::ImageFormatMax;
     }
     }
 }
 }
@@ -1187,7 +1248,7 @@ spv::LoopControlMask TGlslangToSpvTraverser::TranslateLoopControl(const glslang:
 spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::TType& type)
 spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::TType& type)
 {
 {
     if (type.getBasicType() == glslang::EbtRayQuery)
     if (type.getBasicType() == glslang::EbtRayQuery)
-        return spv::StorageClassFunction;
+        return spv::StorageClassPrivate;
     if (type.getQualifier().isPipeInput())
     if (type.getQualifier().isPipeInput())
         return spv::StorageClassInput;
         return spv::StorageClassInput;
     if (type.getQualifier().isPipeOutput())
     if (type.getQualifier().isPipeOutput())
@@ -1219,6 +1280,12 @@ spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::T
         return spv::StorageClassUniformConstant;
         return spv::StorageClassUniformConstant;
     }
     }
 
 
+    if (type.getQualifier().storage == glslang::EvqShared && type.getBasicType() == glslang::EbtBlock) {
+        builder.addExtension(spv::E_SPV_KHR_workgroup_memory_explicit_layout);
+        builder.addCapability(spv::CapabilityWorkgroupMemoryExplicitLayoutKHR);
+        return spv::StorageClassWorkgroup;
+    }
+
     switch (type.getQualifier().storage) {
     switch (type.getQualifier().storage) {
     case glslang::EvqGlobal:        return spv::StorageClassPrivate;
     case glslang::EvqGlobal:        return spv::StorageClassPrivate;
     case glslang::EvqConstReadOnly: return spv::StorageClassFunction;
     case glslang::EvqConstReadOnly: return spv::StorageClassFunction;
@@ -1353,6 +1420,8 @@ void InheritQualifiers(glslang::TQualifier& child, const glslang::TQualifier& pa
     if (parent.writeonly)
     if (parent.writeonly)
         child.writeonly = true;
         child.writeonly = true;
 #endif
 #endif
+    if (parent.nonUniform)
+        child.nonUniform = true;
 }
 }
 
 
 bool HasNonLayoutQualifiers(const glslang::TType& type, const glslang::TQualifier& qualifier)
 bool HasNonLayoutQualifiers(const glslang::TType& type, const glslang::TQualifier& qualifier)
@@ -1424,7 +1493,7 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
 
 
     if (glslangIntermediate->usingPhysicalStorageBuffer()) {
     if (glslangIntermediate->usingPhysicalStorageBuffer()) {
         addressingModel = spv::AddressingModelPhysicalStorageBuffer64EXT;
         addressingModel = spv::AddressingModelPhysicalStorageBuffer64EXT;
-        builder.addIncorporatedExtension(spv::E_SPV_EXT_physical_storage_buffer, spv::Spv_1_5);
+        builder.addIncorporatedExtension(spv::E_SPV_KHR_physical_storage_buffer, spv::Spv_1_5);
         builder.addCapability(spv::CapabilityPhysicalStorageBufferAddressesEXT);
         builder.addCapability(spv::CapabilityPhysicalStorageBufferAddressesEXT);
     }
     }
     if (glslangIntermediate->usingVulkanMemoryModel()) {
     if (glslangIntermediate->usingVulkanMemoryModel()) {
@@ -1454,7 +1523,7 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
     }
     }
 
 
     if (glslangIntermediate->getLayoutPrimitiveCulling()) {
     if (glslangIntermediate->getLayoutPrimitiveCulling()) {
-        builder.addCapability(spv::CapabilityRayTraversalPrimitiveCullingProvisionalKHR);
+        builder.addCapability(spv::CapabilityRayTraversalPrimitiveCullingKHR);
     }
     }
 
 
     unsigned int mode;
     unsigned int mode;
@@ -1482,15 +1551,16 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
             builder.addExtension(spv::E_SPV_KHR_post_depth_coverage);
             builder.addExtension(spv::E_SPV_KHR_post_depth_coverage);
         }
         }
 
 
-        if (glslangIntermediate->getDepth() != glslang::EldUnchanged && glslangIntermediate->isDepthReplacing())
+        if (glslangIntermediate->isDepthReplacing())
             builder.addExecutionMode(shaderEntry, spv::ExecutionModeDepthReplacing);
             builder.addExecutionMode(shaderEntry, spv::ExecutionModeDepthReplacing);
 
 
 #ifndef GLSLANG_WEB
 #ifndef GLSLANG_WEB
 
 
         switch(glslangIntermediate->getDepth()) {
         switch(glslangIntermediate->getDepth()) {
-        case glslang::EldGreater:  mode = spv::ExecutionModeDepthGreater; break;
-        case glslang::EldLess:     mode = spv::ExecutionModeDepthLess;    break;
-        default:                   mode = spv::ExecutionModeMax;          break;
+        case glslang::EldGreater:   mode = spv::ExecutionModeDepthGreater;   break;
+        case glslang::EldLess:      mode = spv::ExecutionModeDepthLess;      break;
+        case glslang::EldUnchanged: mode = spv::ExecutionModeDepthUnchanged; break;
+        default:                    mode = spv::ExecutionModeMax;            break;
         }
         }
         if (mode != spv::ExecutionModeMax)
         if (mode != spv::ExecutionModeMax)
             builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode);
             builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode);
@@ -1621,7 +1691,7 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
     {
     {
         auto& extensions = glslangIntermediate->getRequestedExtensions();
         auto& extensions = glslangIntermediate->getRequestedExtensions();
         if (extensions.find("GL_NV_ray_tracing") == extensions.end()) {
         if (extensions.find("GL_NV_ray_tracing") == extensions.end()) {
-            builder.addCapability(spv::CapabilityRayTracingProvisionalKHR);
+            builder.addCapability(spv::CapabilityRayTracingKHR);
             builder.addExtension("SPV_KHR_ray_tracing");
             builder.addExtension("SPV_KHR_ray_tracing");
         }
         }
         else {
         else {
@@ -1710,6 +1780,12 @@ void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol)
     if (symbol->getType().getQualifier().isSpecConstant())
     if (symbol->getType().getQualifier().isSpecConstant())
         spec_constant_op_mode_setter.turnOnSpecConstantOpMode();
         spec_constant_op_mode_setter.turnOnSpecConstantOpMode();
 
 
+#ifdef ENABLE_HLSL
+    // Skip symbol handling if it is string-typed
+    if (symbol->getBasicType() == glslang::EbtString)
+        return;
+#endif
+
     // getSymbolId() will set up all the IO decorations on the first call.
     // getSymbolId() will set up all the IO decorations on the first call.
     // Formal function parameters were mapped during makeFunctions().
     // Formal function parameters were mapped during makeFunctions().
     spv::Id id = getSymbolId(symbol);
     spv::Id id = getSymbolId(symbol);
@@ -1852,9 +1928,11 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
                 spv::Id leftRValue = accessChainLoad(node->getLeft()->getType());
                 spv::Id leftRValue = accessChainLoad(node->getLeft()->getType());
 
 
                 // do the operation
                 // do the operation
+                spv::Builder::AccessChain::CoherentFlags coherentFlags = TranslateCoherent(node->getLeft()->getType());
+                coherentFlags |= TranslateCoherent(node->getRight()->getType());
                 OpDecorations decorations = { TranslatePrecisionDecoration(node->getOperationPrecision()),
                 OpDecorations decorations = { TranslatePrecisionDecoration(node->getOperationPrecision()),
                                               TranslateNoContractionDecoration(node->getType().getQualifier()),
                                               TranslateNoContractionDecoration(node->getType().getQualifier()),
-                                              TranslateNonUniformDecoration(node->getType().getQualifier()) };
+                                              TranslateNonUniformDecoration(coherentFlags) };
                 rValue = createBinaryOperation(node->getOp(), decorations,
                 rValue = createBinaryOperation(node->getOp(), decorations,
                                                convertGlslangToSpvType(node->getType()), leftRValue, rValue,
                                                convertGlslangToSpvType(node->getType()), leftRValue, rValue,
                                                node->getType().getBasicType());
                                                node->getType().getBasicType());
@@ -1885,13 +1963,16 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
             if (! node->getLeft()->getType().isArray() &&
             if (! node->getLeft()->getType().isArray() &&
                 node->getLeft()->getType().isVector() &&
                 node->getLeft()->getType().isVector() &&
                 node->getOp() == glslang::EOpIndexDirect) {
                 node->getOp() == glslang::EOpIndexDirect) {
+                // Swizzle is uniform so propagate uniform into access chain
+                spv::Builder::AccessChain::CoherentFlags coherentFlags = TranslateCoherent(node->getLeft()->getType());
+                coherentFlags.nonUniform = 0;
                 // This is essentially a hard-coded vector swizzle of size 1,
                 // This is essentially a hard-coded vector swizzle of size 1,
                 // so short circuit the access-chain stuff with a swizzle.
                 // so short circuit the access-chain stuff with a swizzle.
                 std::vector<unsigned> swizzle;
                 std::vector<unsigned> swizzle;
                 swizzle.push_back(glslangIndex);
                 swizzle.push_back(glslangIndex);
                 int dummySize;
                 int dummySize;
                 builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()),
                 builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()),
-                                               TranslateCoherent(node->getLeft()->getType()),
+                                               coherentFlags,
                                                glslangIntermediate->getBaseAlignmentScalar(
                                                glslangIntermediate->getBaseAlignmentScalar(
                                                    node->getLeft()->getType(), dummySize));
                                                    node->getLeft()->getType(), dummySize));
             } else {
             } else {
@@ -1914,7 +1995,7 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
                 {
                 {
                     // This may be, e.g., an anonymous block-member selection, which generally need
                     // This may be, e.g., an anonymous block-member selection, which generally need
                     // index remapping due to hidden members in anonymous blocks.
                     // index remapping due to hidden members in anonymous blocks.
-                    int glslangId = glslangTypeToIdMap[node->getLeft()->getType().getStruct()];
+                    long long glslangId = glslangTypeToIdMap[node->getLeft()->getType().getStruct()];
                     if (memberRemapper.find(glslangId) != memberRemapper.end()) {
                     if (memberRemapper.find(glslangId) != memberRemapper.end()) {
                         std::vector<int>& remapper = memberRemapper[glslangId];
                         std::vector<int>& remapper = memberRemapper[glslangId];
                         assert(remapper.size() > 0);
                         assert(remapper.size() > 0);
@@ -1922,9 +2003,14 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
                     }
                     }
                 }
                 }
 
 
+                // Struct reference propagates uniform lvalue
+                spv::Builder::AccessChain::CoherentFlags coherentFlags =
+                        TranslateCoherent(node->getLeft()->getType());
+                coherentFlags.nonUniform = 0;
+
                 // normal case for indexing array or structure or block
                 // normal case for indexing array or structure or block
                 builder.accessChainPush(builder.makeIntConstant(spvIndex),
                 builder.accessChainPush(builder.makeIntConstant(spvIndex),
-                    TranslateCoherent(node->getLeft()->getType()),
+                        coherentFlags,
                         node->getLeft()->getType().getBufferReferenceAlignment());
                         node->getLeft()->getType().getBufferReferenceAlignment());
 
 
                 // Add capabilities here for accessing PointSize and clip/cull distance.
                 // Add capabilities here for accessing PointSize and clip/cull distance.
@@ -1958,15 +2044,20 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
             // restore the saved access chain
             // restore the saved access chain
             builder.setAccessChain(partial);
             builder.setAccessChain(partial);
 
 
+            // Only if index is nonUniform should we propagate nonUniform into access chain
+            spv::Builder::AccessChain::CoherentFlags index_flags = TranslateCoherent(node->getRight()->getType());
+            spv::Builder::AccessChain::CoherentFlags coherent_flags = TranslateCoherent(node->getLeft()->getType());
+            coherent_flags.nonUniform = index_flags.nonUniform;
+
             if (! node->getLeft()->getType().isArray() && node->getLeft()->getType().isVector()) {
             if (! node->getLeft()->getType().isArray() && node->getLeft()->getType().isVector()) {
                 int dummySize;
                 int dummySize;
-                builder.accessChainPushComponent(index, convertGlslangToSpvType(node->getLeft()->getType()),
-                                                TranslateCoherent(node->getLeft()->getType()),
+                builder.accessChainPushComponent(
+                    index, convertGlslangToSpvType(node->getLeft()->getType()), coherent_flags,
                                                 glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(),
                                                 glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(),
                                                 dummySize));
                                                 dummySize));
             } else
             } else
-                builder.accessChainPush(index, TranslateCoherent(node->getLeft()->getType()),
-                    node->getLeft()->getType().getBufferReferenceAlignment());
+                builder.accessChainPush(index, coherent_flags,
+                                        node->getLeft()->getType().getBufferReferenceAlignment());
         }
         }
         return false;
         return false;
     case glslang::EOpVectorSwizzle:
     case glslang::EOpVectorSwizzle:
@@ -2050,8 +2141,9 @@ std::pair<spv::Id, spv::Id> TGlslangToSpvTraverser::getForcedType(glslang::TBuil
             // these require changing a 64-bit scaler -> a vector of 32-bit components
             // these require changing a 64-bit scaler -> a vector of 32-bit components
             if (glslangType.isVector())
             if (glslangType.isVector())
                 break;
                 break;
-            std::pair<spv::Id, spv::Id> ret(builder.makeVectorType(builder.makeUintType(32), 4),
-                                            builder.makeUintType(64));
+            spv::Id ivec4_type = builder.makeVectorType(builder.makeUintType(32), 4);
+            spv::Id uint64_type = builder.makeUintType(64);
+            std::pair<spv::Id, spv::Id> ret(ivec4_type, uint64_type);
             return ret;
             return ret;
         }
         }
         // There are no SPIR-V builtins defined for these and map onto original non-transposed
         // There are no SPIR-V builtins defined for these and map onto original non-transposed
@@ -2090,7 +2182,7 @@ spv::Id TGlslangToSpvTraverser::translateForcedType(spv::Id object)
             // handle 32-bit v.xy* -> 64-bit
             // handle 32-bit v.xy* -> 64-bit
             builder.clearAccessChain();
             builder.clearAccessChain();
             builder.setAccessChainLValue(object);
             builder.setAccessChainLValue(object);
-            object = builder.accessChainLoad(spv::NoPrecision, spv::DecorationMax, objectTypeId);
+            object = builder.accessChainLoad(spv::NoPrecision, spv::DecorationMax, spv::DecorationMax, objectTypeId);
             std::vector<spv::Id> components;
             std::vector<spv::Id> components;
             components.push_back(builder.createCompositeExtract(object, builder.getContainedTypeId(objectTypeId), 0));
             components.push_back(builder.createCompositeExtract(object, builder.getContainedTypeId(objectTypeId), 0));
             components.push_back(builder.createCompositeExtract(object, builder.getContainedTypeId(objectTypeId), 1));
             components.push_back(builder.createCompositeExtract(object, builder.getContainedTypeId(objectTypeId), 1));
@@ -2106,7 +2198,7 @@ spv::Id TGlslangToSpvTraverser::translateForcedType(spv::Id object)
             // and we insert a transpose after loading the original non-transposed builtins
             // and we insert a transpose after loading the original non-transposed builtins
             builder.clearAccessChain();
             builder.clearAccessChain();
             builder.setAccessChainLValue(object);
             builder.setAccessChainLValue(object);
-            object = builder.accessChainLoad(spv::NoPrecision, spv::DecorationMax, objectTypeId);
+            object = builder.accessChainLoad(spv::NoPrecision, spv::DecorationMax, spv::DecorationMax, objectTypeId);
             return builder.createUnaryOp(spv::OpTranspose, desiredTypeId, object);
             return builder.createUnaryOp(spv::OpTranspose, desiredTypeId, object);
 
 
     } else  {
     } else  {
@@ -2292,7 +2384,8 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
 
 
             // The result of operation is always stored, but conditionally the
             // The result of operation is always stored, but conditionally the
             // consumed result.  The consumed result is always an r-value.
             // consumed result.  The consumed result is always an r-value.
-            builder.accessChainStore(result);
+            builder.accessChainStore(result,
+                                     TranslateNonUniformDecoration(builder.getAccessChain().coherentFlags));
             builder.clearAccessChain();
             builder.clearAccessChain();
             if (node->getOp() == glslang::EOpPreIncrement ||
             if (node->getOp() == glslang::EOpPreIncrement ||
                 node->getOp() == glslang::EOpPreDecrement)
                 node->getOp() == glslang::EOpPreDecrement)
@@ -2421,6 +2514,10 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
             // anything else gets there, so visit out of order, doing them all now.
             // anything else gets there, so visit out of order, doing them all now.
             makeGlobalInitializers(node->getAsAggregate()->getSequence());
             makeGlobalInitializers(node->getAsAggregate()->getSequence());
 
 
+            //Pre process linker objects for ray tracing stages
+            if (glslangIntermediate->isRayTracingStage())
+                collectRayTracingLinkerObjects();
+
             // Initializers are done, don't want to visit again, but functions and link objects need to be processed,
             // Initializers are done, don't want to visit again, but functions and link objects need to be processed,
             // so do them manually.
             // so do them manually.
             visitFunctions(node->getAsAggregate()->getSequence());
             visitFunctions(node->getAsAggregate()->getSequence());
@@ -2611,6 +2708,10 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
         else
         else
             constructed = builder.createConstructor(precision, arguments, resultType());
             constructed = builder.createConstructor(precision, arguments, resultType());
 
 
+        if (node->getType().getQualifier().isNonUniform()) {
+            builder.addDecoration(constructed, spv::DecorationNonUniformEXT);
+        }
+
         builder.clearAccessChain();
         builder.clearAccessChain();
         builder.setAccessChainRValue(constructed);
         builder.setAccessChainRValue(constructed);
 
 
@@ -2683,6 +2784,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
         break;
         break;
 
 
     case glslang::EOpAtomicAdd:
     case glslang::EOpAtomicAdd:
+    case glslang::EOpAtomicSubtract:
     case glslang::EOpAtomicMin:
     case glslang::EOpAtomicMin:
     case glslang::EOpAtomicMax:
     case glslang::EOpAtomicMax:
     case glslang::EOpAtomicAnd:
     case glslang::EOpAtomicAnd:
@@ -2726,10 +2828,12 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
         binOp = node->getOp();
         binOp = node->getOp();
         break;
         break;
 
 
-    case glslang::EOpIgnoreIntersection:
-    case glslang::EOpTerminateRay:
-    case glslang::EOpTrace:
-    case glslang::EOpExecuteCallable:
+    case glslang::EOpIgnoreIntersectionNV:
+    case glslang::EOpTerminateRayNV:
+    case glslang::EOpTraceNV:
+    case glslang::EOpTraceKHR:
+    case glslang::EOpExecuteCallableNV:
+    case glslang::EOpExecuteCallableKHR:
     case glslang::EOpWritePackedPrimitiveIndices4x8NV:
     case glslang::EOpWritePackedPrimitiveIndices4x8NV:
         noReturnValue = true;
         noReturnValue = true;
         break;
         break;
@@ -2738,7 +2842,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
     case glslang::EOpRayQueryGenerateIntersection:
     case glslang::EOpRayQueryGenerateIntersection:
     case glslang::EOpRayQueryConfirmIntersection:
     case glslang::EOpRayQueryConfirmIntersection:
         builder.addExtension("SPV_KHR_ray_query");
         builder.addExtension("SPV_KHR_ray_query");
-        builder.addCapability(spv::CapabilityRayQueryProvisionalKHR);
+        builder.addCapability(spv::CapabilityRayQueryKHR);
         noReturnValue = true;
         noReturnValue = true;
         break;
         break;
     case glslang::EOpRayQueryProceed:
     case glslang::EOpRayQueryProceed:
@@ -2761,7 +2865,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
     case glslang::EOpRayQueryGetIntersectionObjectToWorld:
     case glslang::EOpRayQueryGetIntersectionObjectToWorld:
     case glslang::EOpRayQueryGetIntersectionWorldToObject:
     case glslang::EOpRayQueryGetIntersectionWorldToObject:
         builder.addExtension("SPV_KHR_ray_query");
         builder.addExtension("SPV_KHR_ray_query");
-        builder.addCapability(spv::CapabilityRayQueryProvisionalKHR);
+        builder.addCapability(spv::CapabilityRayQueryKHR);
         break;
         break;
     case glslang::EOpCooperativeMatrixLoad:
     case glslang::EOpCooperativeMatrixLoad:
     case glslang::EOpCooperativeMatrixStore:
     case glslang::EOpCooperativeMatrixStore:
@@ -2852,6 +2956,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
             break;
             break;
 
 
         case glslang::EOpAtomicAdd:
         case glslang::EOpAtomicAdd:
+        case glslang::EOpAtomicSubtract:
         case glslang::EOpAtomicMin:
         case glslang::EOpAtomicMin:
         case glslang::EOpAtomicMax:
         case glslang::EOpAtomicMax:
         case glslang::EOpAtomicAnd:
         case glslang::EOpAtomicAnd:
@@ -3014,11 +3119,18 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
                     )) {
                     )) {
                 bool cond = glslangOperands[arg]->getAsConstantUnion()->getConstArray()[0].getBConst();
                 bool cond = glslangOperands[arg]->getAsConstantUnion()->getConstArray()[0].getBConst();
                 operands.push_back(builder.makeIntConstant(cond ? 1 : 0));
                 operands.push_back(builder.makeIntConstant(cond ? 1 : 0));
-            }
-            else {
+             } else if ((arg == 10 && glslangOp == glslang::EOpTraceKHR) ||
+                        (arg == 1  && glslangOp == glslang::EOpExecuteCallableKHR)) {
+                 const int opdNum = glslangOp == glslang::EOpTraceKHR ? 10 : 1;
+                 const int set = glslangOp == glslang::EOpTraceKHR ? 0 : 1;
+                 const int location = glslangOperands[opdNum]->getAsConstantUnion()->getConstArray()[0].getUConst();
+                 auto itNode = locationToSymbol[set].find(location);
+                 visitSymbol(itNode->second);
+                 spv::Id symId = getSymbolId(itNode->second);
+                 operands.push_back(symId);
+             } else {
                 operands.push_back(accessChainLoad(glslangOperands[arg]->getAsTyped()->getType()));
                 operands.push_back(accessChainLoad(glslangOperands[arg]->getAsTyped()->getType()));
-            }
-
+             }
         }
         }
     }
     }
 
 
@@ -3054,7 +3166,9 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
 #endif
 #endif
     if (atomic) {
     if (atomic) {
         // Handle all atomics
         // Handle all atomics
-        result = createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType(),
+        glslang::TBasicType typeProxy = (node->getOp() == glslang::EOpAtomicStore)
+            ? node->getSequence()[0]->getAsTyped()->getBasicType() : node->getBasicType();
+        result = createAtomicOperation(node->getOp(), precision, resultType(), operands, typeProxy,
             lvalueCoherentFlags);
             lvalueCoherentFlags);
     } else if (node->getOp() == glslang::EOpDebugPrintf) {
     } else if (node->getOp() == glslang::EOpDebugPrintf) {
         if (!nonSemanticDebugPrintf) {
         if (!nonSemanticDebugPrintf) {
@@ -3089,7 +3203,8 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
 
 
         for (unsigned int i = 0; i < temporaryLvalues.size(); ++i) {
         for (unsigned int i = 0; i < temporaryLvalues.size(); ++i) {
             builder.setAccessChain(complexLvalues[i]);
             builder.setAccessChain(complexLvalues[i]);
-            builder.accessChainStore(builder.createLoad(temporaryLvalues[i], spv::NoPrecision));
+            builder.accessChainStore(builder.createLoad(temporaryLvalues[i], spv::NoPrecision),
+                TranslateNonUniformDecoration(complexLvalues[i].coherentFlags));
         }
         }
     }
     }
 
 
@@ -3420,7 +3535,11 @@ bool TGlslangToSpvTraverser::visitBranch(glslang::TVisit /* visit */, glslang::T
 
 
     switch (node->getFlowOp()) {
     switch (node->getFlowOp()) {
     case glslang::EOpKill:
     case glslang::EOpKill:
-        builder.makeDiscard();
+        builder.makeStatementTerminator(spv::OpKill, "post-discard");
+        break;
+    case glslang::EOpTerminateInvocation:
+        builder.addExtension(spv::E_SPV_KHR_terminate_invocation);
+        builder.makeStatementTerminator(spv::OpTerminateInvocation, "post-terminate-invocation");
         break;
         break;
     case glslang::EOpBreak:
     case glslang::EOpBreak:
         if (breakForLoop.top())
         if (breakForLoop.top())
@@ -3457,6 +3576,12 @@ bool TGlslangToSpvTraverser::visitBranch(glslang::TVisit /* visit */, glslang::T
         builder.addExtension(spv::E_SPV_EXT_demote_to_helper_invocation);
         builder.addExtension(spv::E_SPV_EXT_demote_to_helper_invocation);
         builder.addCapability(spv::CapabilityDemoteToHelperInvocationEXT);
         builder.addCapability(spv::CapabilityDemoteToHelperInvocationEXT);
         break;
         break;
+    case glslang::EOpTerminateRayKHR:
+        builder.makeStatementTerminator(spv::OpTerminateRayKHR, "post-terminateRayKHR");
+        break;
+    case glslang::EOpIgnoreIntersectionKHR:
+        builder.makeStatementTerminator(spv::OpIgnoreIntersectionKHR, "post-ignoreIntersectionKHR");
+        break;
 #endif
 #endif
 
 
     default:
     default:
@@ -3511,6 +3636,11 @@ spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol*
             break;
             break;
 #endif
 #endif
         default:
         default:
+            if (storageClass == spv::StorageClassWorkgroup &&
+                node->getType().getBasicType() == glslang::EbtBlock) {
+                builder.addCapability(spv::CapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR);
+                break;
+            }
             if (node->getType().contains16BitFloat())
             if (node->getType().contains16BitFloat())
                 builder.addCapability(spv::CapabilityFloat16);
                 builder.addCapability(spv::CapabilityFloat16);
             if (node->getType().contains16BitInt())
             if (node->getType().contains16BitInt())
@@ -3529,6 +3659,9 @@ spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol*
         } else if (storageClass == spv::StorageClassStorageBuffer) {
         } else if (storageClass == spv::StorageClassStorageBuffer) {
             builder.addIncorporatedExtension(spv::E_SPV_KHR_8bit_storage, spv::Spv_1_5);
             builder.addIncorporatedExtension(spv::E_SPV_KHR_8bit_storage, spv::Spv_1_5);
             builder.addCapability(spv::CapabilityStorageBuffer8BitAccess);
             builder.addCapability(spv::CapabilityStorageBuffer8BitAccess);
+        } else if (storageClass == spv::StorageClassWorkgroup &&
+                   node->getType().getBasicType() == glslang::EbtBlock) {
+            builder.addCapability(spv::CapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR);
         } else {
         } else {
             builder.addCapability(spv::CapabilityInt8);
             builder.addCapability(spv::CapabilityInt8);
         }
         }
@@ -3540,13 +3673,14 @@ spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol*
 
 
     spv::Id initializer = spv::NoResult;
     spv::Id initializer = spv::NoResult;
 
 
-    if (node->getType().getQualifier().storage == glslang::EvqUniform &&
-        !node->getConstArray().empty()) {
-            int nextConst = 0;
-            initializer = createSpvConstantFromConstUnionArray(node->getType(),
-                                                               node->getConstArray(),
-                                                               nextConst,
-                                                               false /* specConst */);
+    if (node->getType().getQualifier().storage == glslang::EvqUniform && !node->getConstArray().empty()) {
+        int nextConst = 0;
+        initializer = createSpvConstantFromConstUnionArray(node->getType(),
+                                                           node->getConstArray(),
+                                                           nextConst,
+                                                           false /* specConst */);
+    } else if (node->getType().getQualifier().isNullInit()) {
+        initializer = builder.makeNullConstant(spvType);
     }
     }
 
 
     return builder.createVariable(spv::NoPrecision, storageClass, spvType, name, initializer);
     return builder.createVariable(spv::NoPrecision, storageClass, spvType, name, initializer);
@@ -3564,6 +3698,12 @@ spv::Id TGlslangToSpvTraverser::getSampledType(const glslang::TSampler& sampler)
             builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float_fetch);
             builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float_fetch);
             builder.addCapability(spv::CapabilityFloat16ImageAMD);
             builder.addCapability(spv::CapabilityFloat16ImageAMD);
             return builder.makeFloatType(16);
             return builder.makeFloatType(16);
+        case glslang::EbtInt64:      return builder.makeIntType(64);
+            builder.addExtension(spv::E_SPV_EXT_shader_image_int64);
+            builder.addCapability(spv::CapabilityFloat16ImageAMD);
+        case glslang::EbtUint64:     return builder.makeUintType(64);
+            builder.addExtension(spv::E_SPV_EXT_shader_image_int64);
+            builder.addCapability(spv::CapabilityFloat16ImageAMD);
 #endif
 #endif
         default:
         default:
             assert(0);
             assert(0);
@@ -3670,10 +3810,36 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
         spvType = builder.makeUintType(32);
         spvType = builder.makeUintType(32);
         break;
         break;
     case glslang::EbtAccStruct:
     case glslang::EbtAccStruct:
+        switch (glslangIntermediate->getStage()) {
+        case EShLangRayGen:
+        case EShLangIntersect:
+        case EShLangAnyHit:
+        case EShLangClosestHit:
+        case EShLangMiss:
+        case EShLangCallable:
+            // these all should have the RayTracingNV/KHR capability already
+            break;
+        default:
+            {
+                auto& extensions = glslangIntermediate->getRequestedExtensions();
+                if (extensions.find("GL_EXT_ray_query") != extensions.end()) {
+                    builder.addExtension(spv::E_SPV_KHR_ray_query);
+                    builder.addCapability(spv::CapabilityRayQueryKHR);
+                }
+            }
+            break;
+        }
         spvType = builder.makeAccelerationStructureType();
         spvType = builder.makeAccelerationStructureType();
         break;
         break;
     case glslang::EbtRayQuery:
     case glslang::EbtRayQuery:
-        spvType = builder.makeRayQueryType();
+        {
+            auto& extensions = glslangIntermediate->getRequestedExtensions();
+            if (extensions.find("GL_EXT_ray_query") != extensions.end()) {
+                builder.addExtension(spv::E_SPV_KHR_ray_query);
+                builder.addCapability(spv::CapabilityRayQueryKHR);
+            }
+            spvType = builder.makeRayQueryType();
+        }
         break;
         break;
     case glslang::EbtReference:
     case glslang::EbtReference:
         {
         {
@@ -3929,6 +4095,8 @@ void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type,
     // Name and decorate the non-hidden members
     // Name and decorate the non-hidden members
     int offset = -1;
     int offset = -1;
     int locationOffset = 0;  // for use within the members of this struct
     int locationOffset = 0;  // for use within the members of this struct
+    bool memberLocationInvalid = type.isArrayOfArrays() ||
+        (type.isArray() && (type.getQualifier().isArrayedIo(glslangIntermediate->getStage()) == false));
     for (int i = 0; i < (int)glslangMembers->size(); i++) {
     for (int i = 0; i < (int)glslangMembers->size(); i++) {
         glslang::TType& glslangMember = *(*glslangMembers)[i].type;
         glslang::TType& glslangMember = *(*glslangMembers)[i].type;
         int member = i;
         int member = i;
@@ -3981,7 +4149,7 @@ void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type,
         // just track whether a member needs to be decorated.
         // just track whether a member needs to be decorated.
         // Ignore member locations if the container is an array, as that's
         // Ignore member locations if the container is an array, as that's
         // ill-specified and decisions have been made to not allow this.
         // ill-specified and decisions have been made to not allow this.
-        if (! type.isArray() && memberQualifier.hasLocation())
+        if (!memberLocationInvalid && memberQualifier.hasLocation())
             builder.addMemberDecoration(spvType, member, spv::DecorationLocation, memberQualifier.layoutLocation);
             builder.addMemberDecoration(spvType, member, spv::DecorationLocation, memberQualifier.layoutLocation);
 
 
         if (qualifier.hasLocation())      // track for upcoming inheritance
         if (qualifier.hasLocation())      // track for upcoming inheritance
@@ -4087,6 +4255,7 @@ spv::Id TGlslangToSpvTraverser::accessChainLoad(const glslang::TType& type)
     alignment |= type.getBufferReferenceAlignment();
     alignment |= type.getBufferReferenceAlignment();
 
 
     spv::Id loadedId = builder.accessChainLoad(TranslatePrecisionDecoration(type),
     spv::Id loadedId = builder.accessChainLoad(TranslatePrecisionDecoration(type),
+        TranslateNonUniformDecoration(builder.getAccessChain().coherentFlags),
         TranslateNonUniformDecoration(type.getQualifier()),
         TranslateNonUniformDecoration(type.getQualifier()),
         nominalTypeId,
         nominalTypeId,
         spv::MemoryAccessMask(TranslateMemoryAccess(coherentFlags) & ~spv::MemoryAccessMakePointerAvailableKHRMask),
         spv::MemoryAccessMask(TranslateMemoryAccess(coherentFlags) & ~spv::MemoryAccessMakePointerAvailableKHRMask),
@@ -4154,7 +4323,7 @@ void TGlslangToSpvTraverser::accessChainStore(const glslang::TType& type, spv::I
     unsigned int alignment = builder.getAccessChain().alignment;
     unsigned int alignment = builder.getAccessChain().alignment;
     alignment |= type.getBufferReferenceAlignment();
     alignment |= type.getBufferReferenceAlignment();
 
 
-    builder.accessChainStore(rvalue,
+    builder.accessChainStore(rvalue, TranslateNonUniformDecoration(builder.getAccessChain().coherentFlags),
                              spv::MemoryAccessMask(TranslateMemoryAccess(coherentFlags) &
                              spv::MemoryAccessMask(TranslateMemoryAccess(coherentFlags) &
                                 ~spv::MemoryAccessMakePointerVisibleKHRMask),
                                 ~spv::MemoryAccessMakePointerVisibleKHRMask),
                              TranslateMemoryScope(coherentFlags), alignment);
                              TranslateMemoryScope(coherentFlags), alignment);
@@ -4259,6 +4428,7 @@ glslang::TLayoutPacking TGlslangToSpvTraverser::getExplicitLayout(const glslang:
     // has to be a uniform or buffer block or task in/out blocks
     // has to be a uniform or buffer block or task in/out blocks
     if (type.getQualifier().storage != glslang::EvqUniform &&
     if (type.getQualifier().storage != glslang::EvqUniform &&
         type.getQualifier().storage != glslang::EvqBuffer &&
         type.getQualifier().storage != glslang::EvqBuffer &&
+        type.getQualifier().storage != glslang::EvqShared &&
         !type.getQualifier().isTaskMemory())
         !type.getQualifier().isTaskMemory())
         return glslang::ElpNone;
         return glslang::ElpNone;
 
 
@@ -4542,7 +4712,39 @@ void TGlslangToSpvTraverser::makeGlobalInitializers(const glslang::TIntermSequen
         }
         }
     }
     }
 }
 }
+// Walk over all linker objects to create a map for payload and callable data linker objects
+// and their location to be used during codegen for OpTraceKHR and OpExecuteCallableKHR
+// This is done here since it is possible that these linker objects are not be referenced in the AST
+void TGlslangToSpvTraverser::collectRayTracingLinkerObjects()
+{
+    glslang::TIntermAggregate* linkerObjects = glslangIntermediate->findLinkerObjects();
+    for (auto& objSeq : linkerObjects->getSequence()) {
+        auto objNode = objSeq->getAsSymbolNode();
+        if (objNode != nullptr) {
+            if (objNode->getQualifier().hasLocation()) {
+                unsigned int location = objNode->getQualifier().layoutLocation;
+                auto st = objNode->getQualifier().storage;
+                int set;
+                switch (st)
+                {
+                case glslang::EvqPayload:
+                case glslang::EvqPayloadIn:
+                    set = 0;
+                    break;
+                case glslang::EvqCallableData:
+                case glslang::EvqCallableDataIn:
+                    set = 1;
+                    break;
 
 
+                default:
+                    set = -1;
+                }
+                if (set != -1)
+                    locationToSymbol[set].insert(std::make_pair(location, objNode));
+            }
+        }
+    }
+}
 // Process all the functions, while skipping initializers.
 // Process all the functions, while skipping initializers.
 void TGlslangToSpvTraverser::visitFunctions(const glslang::TIntermSequence& glslFunctions)
 void TGlslangToSpvTraverser::visitFunctions(const glslang::TIntermSequence& glslFunctions)
 {
 {
@@ -4686,8 +4888,10 @@ void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate&
         }
         }
 
 
         if (lvalue) {
         if (lvalue) {
-            arguments.push_back(builder.accessChainGetLValue());
+            spv::Id lvalue_id = builder.accessChainGetLValue();
+            arguments.push_back(lvalue_id);
             lvalueCoherentFlags = builder.getAccessChain().coherentFlags;
             lvalueCoherentFlags = builder.getAccessChain().coherentFlags;
+            builder.addDecoration(lvalue_id, TranslateNonUniformDecoration(lvalueCoherentFlags));
             lvalueCoherentFlags |= TranslateCoherent(glslangArguments[i]->getAsTyped()->getType());
             lvalueCoherentFlags |= TranslateCoherent(glslangArguments[i]->getAsTyped()->getType());
         } else
         } else
 #endif
 #endif
@@ -4750,12 +4954,15 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
 
 
     const bool isUnsignedResult = node->getType().getBasicType() == glslang::EbtUint;
     const bool isUnsignedResult = node->getType().getBasicType() == glslang::EbtUint;
 
 
+    if (builder.isSampledImage(params.sampler) &&
+        ((cracked.query && node->getOp() != glslang::EOpTextureQueryLod) || cracked.fragMask || cracked.fetch)) {
+        params.sampler = builder.createUnaryOp(spv::OpImage, builder.getImageType(params.sampler), params.sampler);
+        if (imageType.getQualifier().isNonUniform()) {
+            builder.addDecoration(params.sampler, spv::DecorationNonUniformEXT);
+        }
+    }
     // Check for queries
     // Check for queries
     if (cracked.query) {
     if (cracked.query) {
-        // OpImageQueryLod works on a sampled image, for other queries the image has to be extracted first
-        if (node->getOp() != glslang::EOpTextureQueryLod && builder.isSampledImage(params.sampler))
-            params.sampler = builder.createUnaryOp(spv::OpImage, builder.getImageType(params.sampler), params.sampler);
-
         switch (node->getOp()) {
         switch (node->getOp()) {
         case glslang::EOpImageQuerySize:
         case glslang::EOpImageQuerySize:
         case glslang::EOpTextureQuerySize:
         case glslang::EOpTextureQuerySize:
@@ -5009,10 +5216,6 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
         auto opIt = arguments.begin();
         auto opIt = arguments.begin();
         std::vector<spv::Id> operands;
         std::vector<spv::Id> operands;
 
 
-        // Extract the image if necessary
-        if (builder.isSampledImage(params.sampler))
-            params.sampler = builder.createUnaryOp(spv::OpImage, builder.getImageType(params.sampler), params.sampler);
-
         operands.push_back(params.sampler);
         operands.push_back(params.sampler);
         ++opIt;
         ++opIt;
 
 
@@ -5073,13 +5276,6 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
             bias = true;
             bias = true;
     }
     }
 
 
-    // See if the sampler param should really be just the SPV image part
-    if (cracked.fetch) {
-        // a fetch needs to have the image extracted first
-        if (builder.isSampledImage(params.sampler))
-            params.sampler = builder.createUnaryOp(spv::OpImage, builder.getImageType(params.sampler), params.sampler);
-    }
-
 #ifndef GLSLANG_WEB
 #ifndef GLSLANG_WEB
     if (cracked.gather) {
     if (cracked.gather) {
         const auto& sourceExtensions = glslangIntermediate->getRequestedExtensions();
         const auto& sourceExtensions = glslangIntermediate->getRequestedExtensions();
@@ -5239,7 +5435,7 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
 
 
             builder.accessChainPush(builder.makeIntConstant(i), flags, 0);
             builder.accessChainPush(builder.makeIntConstant(i), flags, 0);
             builder.accessChainStore(builder.createCompositeExtract(res, builder.getContainedTypeId(resType, i+1),
             builder.accessChainStore(builder.createCompositeExtract(res, builder.getContainedTypeId(resType, i+1),
-                i+1));
+                i+1), TranslateNonUniformDecoration(imageType.getQualifier()));
         }
         }
         return builder.createCompositeExtract(res, resultType(), 0);
         return builder.createCompositeExtract(res, resultType(), 0);
     }
     }
@@ -5375,6 +5571,7 @@ spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAgg
     // 3. Make the call.
     // 3. Make the call.
     spv::Id result = builder.createFunctionCall(function, spvArgs);
     spv::Id result = builder.createFunctionCall(function, spvArgs);
     builder.setPrecision(result, TranslatePrecisionDecoration(node->getType()));
     builder.setPrecision(result, TranslatePrecisionDecoration(node->getType()));
+    builder.addDecoration(result, TranslateNonUniformDecoration(node->getType().getQualifier()));
 
 
     // 4. Copy back out an "out" arguments.
     // 4. Copy back out an "out" arguments.
     lValueCount = 0;
     lValueCount = 0;
@@ -5384,6 +5581,7 @@ spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAgg
         else if (writableParam(qualifiers[a])) {
         else if (writableParam(qualifiers[a])) {
             if (qualifiers[a] == glslang::EvqOut || qualifiers[a] == glslang::EvqInOut) {
             if (qualifiers[a] == glslang::EvqOut || qualifiers[a] == glslang::EvqInOut) {
                 spv::Id copy = builder.createLoad(spvArgs[a], spv::NoPrecision);
                 spv::Id copy = builder.createLoad(spvArgs[a], spv::NoPrecision);
+                builder.addDecoration(copy, TranslateNonUniformDecoration(argTypes[a]->getQualifier()));
                 builder.setAccessChain(lValues[lValueCount]);
                 builder.setAccessChain(lValues[lValueCount]);
                 multiTypeStore(*argTypes[a], copy);
                 multiTypeStore(*argTypes[a], copy);
             }
             }
@@ -6171,6 +6369,11 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, OpDe
     case glslang::EOpConstructReference:
     case glslang::EOpConstructReference:
         unaryOp = spv::OpBitcast;
         unaryOp = spv::OpBitcast;
         break;
         break;
+
+    case glslang::EOpConvUint64ToAccStruct:
+    case glslang::EOpConvUvec2ToAccStruct:
+        unaryOp = spv::OpConvertUToAccelerationStructureKHR;
+        break;
 #endif
 #endif
 
 
     case glslang::EOpCopyObject:
     case glslang::EOpCopyObject:
@@ -6633,9 +6836,6 @@ spv::Id TGlslangToSpvTraverser::createConversion(glslang::TOperator op, OpDecora
         break;
         break;
     case glslang::EOpConvPtrToUvec2:
     case glslang::EOpConvPtrToUvec2:
     case glslang::EOpConvUvec2ToPtr:
     case glslang::EOpConvUvec2ToPtr:
-        if (builder.isVector(operand))
-            builder.promoteIncorporatedExtension(spv::E_SPV_EXT_physical_storage_buffer,
-                                                 spv::E_SPV_KHR_physical_storage_buffer, spv::Spv_1_5);
         convOp = spv::OpBitcast;
         convOp = spv::OpBitcast;
         break;
         break;
 #endif
 #endif
@@ -6693,6 +6893,7 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv
                 builder.addCapability(spv::CapabilityAtomicFloat64AddEXT);
                 builder.addCapability(spv::CapabilityAtomicFloat64AddEXT);
         }
         }
         break;
         break;
+    case glslang::EOpAtomicSubtract:
     case glslang::EOpAtomicCounterSubtract:
     case glslang::EOpAtomicCounterSubtract:
         opCode = spv::OpAtomicISub;
         opCode = spv::OpAtomicISub;
         break;
         break;
@@ -6815,6 +7016,10 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv
         builder.addCapability(spv::CapabilityVulkanMemoryModelKHR);
         builder.addCapability(spv::CapabilityVulkanMemoryModelKHR);
     }
     }
 
 
+    if (builder.getConstantScalar(scopeId) == spv::ScopeQueueFamily) {
+        builder.addCapability(spv::CapabilityVulkanMemoryModelKHR);
+    }
+
     if (glslangIntermediate->usingVulkanMemoryModel() && builder.getConstantScalar(scopeId) == spv::ScopeDevice) {
     if (glslangIntermediate->usingVulkanMemoryModel() && builder.getConstantScalar(scopeId) == spv::ScopeDevice) {
         builder.addCapability(spv::CapabilityVulkanMemoryModelDeviceScopeKHR);
         builder.addCapability(spv::CapabilityVulkanMemoryModelDeviceScopeKHR);
     }
     }
@@ -7757,10 +7962,16 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::
         typeId = builder.makeBoolType();
         typeId = builder.makeBoolType();
         opCode = spv::OpReportIntersectionKHR;
         opCode = spv::OpReportIntersectionKHR;
         break;
         break;
-    case glslang::EOpTrace:
+    case glslang::EOpTraceNV:
+        builder.createNoResultOp(spv::OpTraceNV, operands);
+        return 0;
+    case glslang::EOpTraceKHR:
         builder.createNoResultOp(spv::OpTraceRayKHR, operands);
         builder.createNoResultOp(spv::OpTraceRayKHR, operands);
         return 0;
         return 0;
-    case glslang::EOpExecuteCallable:
+    case glslang::EOpExecuteCallableNV:
+        builder.createNoResultOp(spv::OpExecuteCallableNV, operands);
+        return 0;
+    case glslang::EOpExecuteCallableKHR:
         builder.createNoResultOp(spv::OpExecuteCallableKHR, operands);
         builder.createNoResultOp(spv::OpExecuteCallableKHR, operands);
         return 0;
         return 0;
 
 
@@ -7805,7 +8016,7 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::
         opCode = spv::OpRayQueryGetIntersectionInstanceIdKHR;
         opCode = spv::OpRayQueryGetIntersectionInstanceIdKHR;
         break;
         break;
     case glslang::EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset:
     case glslang::EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset:
-        typeId = builder.makeIntType(32);
+        typeId = builder.makeUintType(32);
         opCode = spv::OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR;
         opCode = spv::OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR;
         break;
         break;
     case glslang::EOpRayQueryGetIntersectionGeometryIndex:
     case glslang::EOpRayQueryGetIntersectionGeometryIndex:
@@ -8048,11 +8259,11 @@ spv::Id TGlslangToSpvTraverser::createNoArgOperation(glslang::TOperator op, spv:
         spv::Id id = builder.createBuiltinCall(typeId, getExtBuiltins(spv::E_SPV_AMD_gcn_shader), spv::TimeAMD, args);
         spv::Id id = builder.createBuiltinCall(typeId, getExtBuiltins(spv::E_SPV_AMD_gcn_shader), spv::TimeAMD, args);
         return builder.setPrecision(id, precision);
         return builder.setPrecision(id, precision);
     }
     }
-    case glslang::EOpIgnoreIntersection:
-        builder.createNoResultOp(spv::OpIgnoreIntersectionKHR);
+    case glslang::EOpIgnoreIntersectionNV:
+        builder.createNoResultOp(spv::OpIgnoreIntersectionNV);
         return 0;
         return 0;
-    case glslang::EOpTerminateRay:
-        builder.createNoResultOp(spv::OpTerminateRayKHR);
+    case glslang::EOpTerminateRayNV:
+        builder.createNoResultOp(spv::OpTerminateRayNV);
         return 0;
         return 0;
     case glslang::EOpRayQueryInitialize:
     case glslang::EOpRayQueryInitialize:
         builder.createNoResultOp(spv::OpRayQueryInitializeKHR);
         builder.createNoResultOp(spv::OpRayQueryInitializeKHR);
@@ -8180,7 +8391,8 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
     }
     }
 
 
 #ifndef GLSLANG_WEB
 #ifndef GLSLANG_WEB
-    if (symbol->getType().isImage()) {
+    // Subgroup builtins which have input storage class are volatile for ray tracing stages.
+    if (symbol->getType().isImage() || symbol->getQualifier().isPipeInput()) {
         std::vector<spv::Decoration> memory;
         std::vector<spv::Decoration> memory;
         TranslateMemoryDecoration(symbol->getType().getQualifier(), memory,
         TranslateMemoryDecoration(symbol->getType().getQualifier(), memory,
             glslangIntermediate->usingVulkanMemoryModel());
             glslangIntermediate->usingVulkanMemoryModel());
@@ -8188,9 +8400,6 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
             builder.addDecoration(id, memory[i]);
             builder.addDecoration(id, memory[i]);
     }
     }
 
 
-    // nonuniform
-    builder.addDecoration(id, TranslateNonUniformDecoration(symbol->getType().getQualifier()));
-
     if (builtIn == spv::BuiltInSampleMask) {
     if (builtIn == spv::BuiltInSampleMask) {
           spv::Decoration decoration;
           spv::Decoration decoration;
           // GL_NV_sample_mask_override_coverage extension
           // GL_NV_sample_mask_override_coverage extension

+ 40 - 13
src/libraries/glslang/SPIRV/SpvBuilder.cpp

@@ -621,13 +621,13 @@ Id Builder::makeAccelerationStructureType()
 Id Builder::makeRayQueryType()
 Id Builder::makeRayQueryType()
 {
 {
     Instruction *type;
     Instruction *type;
-    if (groupedTypes[OpTypeRayQueryProvisionalKHR].size() == 0) {
-        type = new Instruction(getUniqueId(), NoType, OpTypeRayQueryProvisionalKHR);
-        groupedTypes[OpTypeRayQueryProvisionalKHR].push_back(type);
+    if (groupedTypes[OpTypeRayQueryKHR].size() == 0) {
+        type = new Instruction(getUniqueId(), NoType, OpTypeRayQueryKHR);
+        groupedTypes[OpTypeRayQueryKHR].push_back(type);
         constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
         constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
         module.mapInstruction(type);
         module.mapInstruction(type);
     } else {
     } else {
-        type = groupedTypes[OpTypeRayQueryProvisionalKHR].back();
+        type = groupedTypes[OpTypeRayQueryKHR].back();
     }
     }
 
 
     return type->getResultId();
     return type->getResultId();
@@ -869,6 +869,30 @@ bool Builder::isSpecConstantOpCode(Op opcode) const
     }
     }
 }
 }
 
 
+Id Builder::makeNullConstant(Id typeId)
+{
+    Instruction* constant;
+
+    // See if we already made it.
+    Id existing = NoResult;
+    for (int i = 0; i < (int)nullConstants.size(); ++i) {
+        constant = nullConstants[i];
+        if (constant->getTypeId() == typeId)
+            existing = constant->getResultId();
+    }
+
+    if (existing != NoResult)
+        return existing;
+
+    // Make it
+    Instruction* c = new Instruction(getUniqueId(), typeId, OpConstantNull);
+    constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c));
+    nullConstants.push_back(c);
+    module.mapInstruction(c);
+
+    return c->getResultId();
+}
+
 Id Builder::makeBoolConstant(bool b, bool specConstant)
 Id Builder::makeBoolConstant(bool b, bool specConstant)
 {
 {
     Id typeId = makeBoolType();
     Id typeId = makeBoolType();
@@ -1447,10 +1471,10 @@ void Builder::leaveFunction()
 }
 }
 
 
 // Comments in header
 // Comments in header
-void Builder::makeDiscard()
+void Builder::makeStatementTerminator(spv::Op opcode, const char *name)
 {
 {
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(new Instruction(OpKill)));
-    createAndSetNoPredecessorBlock("post-discard");
+    buildPoint->addInstruction(std::unique_ptr<Instruction>(new Instruction(opcode)));
+    createAndSetNoPredecessorBlock(name);
 }
 }
 
 
 // Comments in header
 // Comments in header
@@ -2761,12 +2785,14 @@ void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizz
 }
 }
 
 
 // Comments in header
 // Comments in header
-void Builder::accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
+void Builder::accessChainStore(Id rvalue, Decoration nonUniform, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
 {
 {
     assert(accessChain.isRValue == false);
     assert(accessChain.isRValue == false);
 
 
     transferAccessChainSwizzle(true);
     transferAccessChainSwizzle(true);
     Id base = collapseAccessChain();
     Id base = collapseAccessChain();
+    addDecoration(base, nonUniform);
+
     Id source = rvalue;
     Id source = rvalue;
 
 
     // dynamic component should be gone
     // dynamic component should be gone
@@ -2789,8 +2815,9 @@ void Builder::accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess, sp
 }
 }
 
 
 // Comments in header
 // Comments in header
-Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resultType,
-    spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
+Id Builder::accessChainLoad(Decoration precision, Decoration l_nonUniform,
+    Decoration r_nonUniform, Id resultType, spv::MemoryAccessMask memoryAccess,
+    spv::Scope scope, unsigned int alignment)
 {
 {
     Id id;
     Id id;
 
 
@@ -2854,9 +2881,9 @@ Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resu
         // Buffer accesses need the access chain decorated, and this is where
         // Buffer accesses need the access chain decorated, and this is where
         // loaded image types get decorated. TODO: This should maybe move to
         // loaded image types get decorated. TODO: This should maybe move to
         // createImageTextureFunctionCall.
         // createImageTextureFunctionCall.
-        addDecoration(id, nonUniform);
+        addDecoration(id, l_nonUniform);
         id = createLoad(id, precision, memoryAccess, scope, alignment);
         id = createLoad(id, precision, memoryAccess, scope, alignment);
-        addDecoration(id, nonUniform);
+        addDecoration(id, r_nonUniform);
     }
     }
 
 
     // Done, unless there are swizzles to do
     // Done, unless there are swizzles to do
@@ -2877,7 +2904,7 @@ Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resu
     if (accessChain.component != NoResult)
     if (accessChain.component != NoResult)
         id = setPrecision(createVectorExtractDynamic(id, resultType, accessChain.component), precision);
         id = setPrecision(createVectorExtractDynamic(id, resultType, accessChain.component), precision);
 
 
-    addDecoration(id, nonUniform);
+    addDecoration(id, r_nonUniform);
     return id;
     return id;
 }
 }
 
 

+ 13 - 4
src/libraries/glslang/SPIRV/SpvBuilder.h

@@ -293,6 +293,7 @@ public:
     }
     }
 
 
     // For making new constants (will return old constant if the requested one was already made).
     // For making new constants (will return old constant if the requested one was already made).
+    Id makeNullConstant(Id typeId);
     Id makeBoolConstant(bool b, bool specConstant = false);
     Id makeBoolConstant(bool b, bool specConstant = false);
     Id makeInt8Constant(int i, bool specConstant = false)
     Id makeInt8Constant(int i, bool specConstant = false)
         { return makeIntConstant(makeIntType(8),  (unsigned)i, specConstant); }
         { return makeIntConstant(makeIntType(8),  (unsigned)i, specConstant); }
@@ -357,8 +358,9 @@ public:
     // Generate all the code needed to finish up a function.
     // Generate all the code needed to finish up a function.
     void leaveFunction();
     void leaveFunction();
 
 
-    // Create a discard.
-    void makeDiscard();
+    // Create block terminator instruction for certain statements like
+    // discard, terminate-invocation, terminateRayEXT, or ignoreIntersectionEXT
+    void makeStatementTerminator(spv::Op opcode, const char *name);
 
 
     // Create a global or function local or IO variable.
     // Create a global or function local or IO variable.
     Id createVariable(Decoration precision, StorageClass, Id type, const char* name = nullptr,
     Id createVariable(Decoration precision, StorageClass, Id type, const char* name = nullptr,
@@ -624,6 +626,7 @@ public:
             CoherentFlags operator |=(const CoherentFlags &other) { return *this; }
             CoherentFlags operator |=(const CoherentFlags &other) { return *this; }
 #else
 #else
             bool isVolatile() const { return volatil; }
             bool isVolatile() const { return volatil; }
+            bool isNonUniform() const { return nonUniform; }
             bool anyCoherent() const {
             bool anyCoherent() const {
                 return coherent || devicecoherent || queuefamilycoherent || workgroupcoherent ||
                 return coherent || devicecoherent || queuefamilycoherent || workgroupcoherent ||
                     subgroupcoherent || shadercallcoherent;
                     subgroupcoherent || shadercallcoherent;
@@ -638,6 +641,7 @@ public:
             unsigned nonprivate : 1;
             unsigned nonprivate : 1;
             unsigned volatil : 1;
             unsigned volatil : 1;
             unsigned isImage : 1;
             unsigned isImage : 1;
+            unsigned nonUniform : 1;
 
 
             void clear() {
             void clear() {
                 coherent = 0;
                 coherent = 0;
@@ -649,6 +653,7 @@ public:
                 nonprivate = 0;
                 nonprivate = 0;
                 volatil = 0;
                 volatil = 0;
                 isImage = 0;
                 isImage = 0;
+                nonUniform = 0;
             }
             }
 
 
             CoherentFlags operator |=(const CoherentFlags &other) {
             CoherentFlags operator |=(const CoherentFlags &other) {
@@ -661,6 +666,7 @@ public:
                 nonprivate |= other.nonprivate;
                 nonprivate |= other.nonprivate;
                 volatil |= other.volatil;
                 volatil |= other.volatil;
                 isImage |= other.isImage;
                 isImage |= other.isImage;
+                nonUniform |= other.nonUniform;
                 return *this;
                 return *this;
             }
             }
 #endif
 #endif
@@ -721,11 +727,12 @@ public:
     }
     }
 
 
     // use accessChain and swizzle to store value
     // use accessChain and swizzle to store value
-    void accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone,
+    void accessChainStore(Id rvalue, Decoration nonUniform,
+        spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone,
         spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
         spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
 
 
     // use accessChain and swizzle to load an r-value
     // use accessChain and swizzle to load an r-value
-    Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType,
+    Id accessChainLoad(Decoration precision, Decoration l_nonUniform, Decoration r_nonUniform, Id ResultType,
         spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax,
         spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax,
             unsigned int alignment = 0);
             unsigned int alignment = 0);
 
 
@@ -832,6 +839,8 @@ public:
     std::unordered_map<unsigned int, std::vector<Instruction*>> groupedStructConstants;
     std::unordered_map<unsigned int, std::vector<Instruction*>> groupedStructConstants;
     // map type opcodes to type instructions
     // map type opcodes to type instructions
     std::unordered_map<unsigned int, std::vector<Instruction*>> groupedTypes;
     std::unordered_map<unsigned int, std::vector<Instruction*>> groupedTypes;
+    // list of OpConstantNull instructions
+    std::vector<Instruction*> nullConstants;
 
 
     // stack of switches
     // stack of switches
     std::stack<Block*> switchMerges;
     std::stack<Block*> switchMerges;

+ 32 - 0
src/libraries/glslang/SPIRV/SpvPostProcess.cpp

@@ -436,6 +436,38 @@ void Builder::postProcessFeatures() {
             }
             }
         }
         }
     }
     }
+
+    // If any Vulkan memory model-specific functionality is used, update the
+    // OpMemoryModel to match.
+    if (capabilities.find(spv::CapabilityVulkanMemoryModelKHR) != capabilities.end()) {
+        memoryModel = spv::MemoryModelVulkanKHR;
+        addIncorporatedExtension(spv::E_SPV_KHR_vulkan_memory_model, spv::Spv_1_5);
+    }
+
+    // Add Aliased decoration if there's more than one Workgroup Block variable.
+    if (capabilities.find(spv::CapabilityWorkgroupMemoryExplicitLayoutKHR) != capabilities.end()) {
+        assert(entryPoints.size() == 1);
+        auto &ep = entryPoints[0];
+
+        std::vector<Id> workgroup_variables;
+        for (int i = 0; i < (int)ep->getNumOperands(); i++) {
+            if (!ep->isIdOperand(i))
+                continue;
+
+            const Id id = ep->getIdOperand(i);
+            const Instruction *instr = module.getInstruction(id);
+            if (instr->getOpCode() != spv::OpVariable)
+                continue;
+
+            if (instr->getImmediateOperand(0) == spv::StorageClassWorkgroup)
+                workgroup_variables.push_back(id);
+        }
+
+        if (workgroup_variables.size() > 1) {
+            for (size_t i = 0; i < workgroup_variables.size(); i++)
+                addDecoration(workgroup_variables[i], spv::DecorationAliased);
+        }
+    }
 }
 }
 #endif
 #endif
 
 

+ 12 - 10
src/libraries/glslang/SPIRV/SpvTools.cpp

@@ -44,7 +44,6 @@
 
 
 #include "SpvTools.h"
 #include "SpvTools.h"
 #include "spirv-tools/optimizer.hpp"
 #include "spirv-tools/optimizer.hpp"
-#include "spirv-tools/libspirv.h"
 
 
 namespace glslang {
 namespace glslang {
 
 
@@ -114,11 +113,18 @@ void OptimizerMesssageConsumer(spv_message_level_t level, const char *source,
     out << std::endl;
     out << std::endl;
 }
 }
 
 
-// Use the SPIRV-Tools disassembler to print SPIR-V.
+// Use the SPIRV-Tools disassembler to print SPIR-V using a SPV_ENV_UNIVERSAL_1_3 environment.
 void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv)
 void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv)
+{
+    SpirvToolsDisassemble(out, spirv, spv_target_env::SPV_ENV_UNIVERSAL_1_3);
+}
+
+// Use the SPIRV-Tools disassembler to print SPIR-V with a provided SPIR-V environment.
+void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv,
+                           spv_target_env requested_context)
 {
 {
     // disassemble
     // disassemble
-    spv_context context = spvContextCreate(SPV_ENV_UNIVERSAL_1_3);
+    spv_context context = spvContextCreate(requested_context);
     spv_text text;
     spv_text text;
     spv_diagnostic diagnostic = nullptr;
     spv_diagnostic diagnostic = nullptr;
     spvBinaryToText(context, spirv.data(), spirv.size(),
     spvBinaryToText(context, spirv.data(), spirv.size(),
@@ -147,6 +153,8 @@ void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector<
     spv_validator_options options = spvValidatorOptionsCreate();
     spv_validator_options options = spvValidatorOptionsCreate();
     spvValidatorOptionsSetRelaxBlockLayout(options, intermediate.usingHlslOffsets());
     spvValidatorOptionsSetRelaxBlockLayout(options, intermediate.usingHlslOffsets());
     spvValidatorOptionsSetBeforeHlslLegalization(options, prelegalization);
     spvValidatorOptionsSetBeforeHlslLegalization(options, prelegalization);
+    spvValidatorOptionsSetScalarBlockLayout(options, intermediate.usingScalarBlockLayout());
+    spvValidatorOptionsSetWorkgroupScalarBlockLayout(options, intermediate.usingScalarBlockLayout());
     spvValidateWithOptions(context, options, &binary, &diagnostic);
     spvValidateWithOptions(context, options, &binary, &diagnostic);
 
 
     // report
     // report
@@ -174,10 +182,7 @@ void SpirvToolsTransform(const glslang::TIntermediate& intermediate, std::vector
     // line information into all SPIR-V instructions. This avoids loss of
     // line information into all SPIR-V instructions. This avoids loss of
     // information when instructions are deleted or moved. Later, remove
     // information when instructions are deleted or moved. Later, remove
     // redundant information to minimize final SPRIR-V size.
     // redundant information to minimize final SPRIR-V size.
-    if (options->generateDebugInfo) {
-        optimizer.RegisterPass(spvtools::CreatePropagateLineInfoPass());
-    }
-    else if (options->stripDebugInfo) {
+    if (options->stripDebugInfo) {
         optimizer.RegisterPass(spvtools::CreateStripDebugInfoPass());
         optimizer.RegisterPass(spvtools::CreateStripDebugInfoPass());
     }
     }
     optimizer.RegisterPass(spvtools::CreateWrapOpKillPass());
     optimizer.RegisterPass(spvtools::CreateWrapOpKillPass());
@@ -207,9 +212,6 @@ void SpirvToolsTransform(const glslang::TIntermediate& intermediate, std::vector
     }
     }
     optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass());
     optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass());
     optimizer.RegisterPass(spvtools::CreateCFGCleanupPass());
     optimizer.RegisterPass(spvtools::CreateCFGCleanupPass());
-    if (options->generateDebugInfo) {
-        optimizer.RegisterPass(spvtools::CreateRedundantLineInfoElimPass());
-    }
 
 
     spvtools::OptimizerOptions spvOptOptions;
     spvtools::OptimizerOptions spvOptOptions;
     optimizer.SetTargetEnv(MapToSpirvToolsEnv(intermediate.getSpv(), logger));
     optimizer.SetTargetEnv(MapToSpirvToolsEnv(intermediate.getSpv(), logger));

+ 8 - 3
src/libraries/glslang/SPIRV/SpvTools.h

@@ -41,9 +41,10 @@
 #ifndef GLSLANG_SPV_TOOLS_H
 #ifndef GLSLANG_SPV_TOOLS_H
 #define GLSLANG_SPV_TOOLS_H
 #define GLSLANG_SPV_TOOLS_H
 
 
-#ifdef ENABLE_OPT
+#if ENABLE_OPT
 #include <vector>
 #include <vector>
 #include <ostream>
 #include <ostream>
+#include "spirv-tools/libspirv.h"
 #endif
 #endif
 
 
 #include "../glslang/MachineIndependent/localintermediate.h"
 #include "../glslang/MachineIndependent/localintermediate.h"
@@ -62,11 +63,15 @@ struct SpvOptions {
     bool validate;
     bool validate;
 };
 };
 
 
-#ifdef ENABLE_OPT
+#if ENABLE_OPT
 
 
-// Use the SPIRV-Tools disassembler to print SPIR-V.
+// Use the SPIRV-Tools disassembler to print SPIR-V using a SPV_ENV_UNIVERSAL_1_3 environment.
 void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv);
 void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv);
 
 
+// Use the SPIRV-Tools disassembler to print SPIR-V with a provided SPIR-V environment.
+void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv,
+                           spv_target_env requested_context);
+
 // Apply the SPIRV-Tools validator to generated SPIR-V.
 // Apply the SPIRV-Tools validator to generated SPIR-V.
 void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
 void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
                         spv::SpvBuildLogger*, bool prelegalization);
                         spv::SpvBuildLogger*, bool prelegalization);

+ 59 - 14
src/libraries/glslang/SPIRV/doc.cpp

@@ -372,6 +372,8 @@ const char* BuiltInString(int builtIn)
     case 4424: return "BaseVertex";
     case 4424: return "BaseVertex";
     case 4425: return "BaseInstance";
     case 4425: return "BaseInstance";
     case 4426: return "DrawIndex";
     case 4426: return "DrawIndex";
+    case 4432: return "PrimitiveShadingRateKHR";
+    case 4444: return "ShadingRateKHR";
     case 5014: return "FragStencilRefEXT";
     case 5014: return "FragStencilRefEXT";
 
 
     case 4992: return "BaryCoordNoPerspAMD";
     case 4992: return "BaryCoordNoPerspAMD";
@@ -393,7 +395,7 @@ const char* BuiltInString(int builtIn)
     case BuiltInRayGeometryIndexKHR:         return "RayGeometryIndexKHR";
     case BuiltInRayGeometryIndexKHR:         return "RayGeometryIndexKHR";
     case BuiltInObjectToWorldKHR:            return "ObjectToWorldKHR";
     case BuiltInObjectToWorldKHR:            return "ObjectToWorldKHR";
     case BuiltInWorldToObjectKHR:            return "WorldToObjectKHR";
     case BuiltInWorldToObjectKHR:            return "WorldToObjectKHR";
-    case BuiltInHitTKHR:                     return "HitTKHR";
+    case BuiltInHitTNV:                      return "HitTNV";
     case BuiltInHitKindKHR:                  return "HitKindKHR";
     case BuiltInHitKindKHR:                  return "HitKindKHR";
     case BuiltInIncomingRayFlagsKHR:         return "IncomingRayFlagsKHR";
     case BuiltInIncomingRayFlagsKHR:         return "IncomingRayFlagsKHR";
     case BuiltInViewportMaskNV:              return "ViewportMaskNV";
     case BuiltInViewportMaskNV:              return "ViewportMaskNV";
@@ -521,6 +523,8 @@ const char* ImageFormatString(int format)
     case 37: return "Rg8ui";
     case 37: return "Rg8ui";
     case 38: return "R16ui";
     case 38: return "R16ui";
     case 39: return "R8ui";
     case 39: return "R8ui";
+    case 40: return "R64ui";
+    case 41: return "R64i";
 
 
     default:
     default:
         return "Bad";
         return "Bad";
@@ -911,9 +915,10 @@ const char* CapabilityString(int info)
     case CapabilityPerViewAttributesNV:             return "PerViewAttributesNV";
     case CapabilityPerViewAttributesNV:             return "PerViewAttributesNV";
     case CapabilityGroupNonUniformPartitionedNV:    return "GroupNonUniformPartitionedNV";
     case CapabilityGroupNonUniformPartitionedNV:    return "GroupNonUniformPartitionedNV";
     case CapabilityRayTracingNV:                    return "RayTracingNV";
     case CapabilityRayTracingNV:                    return "RayTracingNV";
+    case CapabilityRayTracingKHR:                   return "RayTracingKHR";
+    case CapabilityRayQueryKHR:                     return "RayQueryKHR";
     case CapabilityRayTracingProvisionalKHR:        return "RayTracingProvisionalKHR";
     case CapabilityRayTracingProvisionalKHR:        return "RayTracingProvisionalKHR";
-    case CapabilityRayQueryProvisionalKHR:          return "RayQueryProvisionalKHR";
-    case CapabilityRayTraversalPrimitiveCullingProvisionalKHR: return "RayTraversalPrimitiveCullingProvisionalKHR";
+    case CapabilityRayTraversalPrimitiveCullingKHR: return "RayTraversalPrimitiveCullingKHR";
     case CapabilityComputeDerivativeGroupQuadsNV:   return "ComputeDerivativeGroupQuadsNV";
     case CapabilityComputeDerivativeGroupQuadsNV:   return "ComputeDerivativeGroupQuadsNV";
     case CapabilityComputeDerivativeGroupLinearNV:  return "ComputeDerivativeGroupLinearNV";
     case CapabilityComputeDerivativeGroupLinearNV:  return "ComputeDerivativeGroupLinearNV";
     case CapabilityFragmentBarycentricNV:           return "FragmentBarycentricNV";
     case CapabilityFragmentBarycentricNV:           return "FragmentBarycentricNV";
@@ -952,14 +957,21 @@ const char* CapabilityString(int info)
     case CapabilityFragmentShaderPixelInterlockEXT:         return "CapabilityFragmentShaderPixelInterlockEXT";
     case CapabilityFragmentShaderPixelInterlockEXT:         return "CapabilityFragmentShaderPixelInterlockEXT";
     case CapabilityFragmentShaderShadingRateInterlockEXT:   return "CapabilityFragmentShaderShadingRateInterlockEXT";
     case CapabilityFragmentShaderShadingRateInterlockEXT:   return "CapabilityFragmentShaderShadingRateInterlockEXT";
 
 
+    case CapabilityFragmentShadingRateKHR:                  return "FragmentShadingRateKHR";
+
     case CapabilityDemoteToHelperInvocationEXT:             return "DemoteToHelperInvocationEXT";
     case CapabilityDemoteToHelperInvocationEXT:             return "DemoteToHelperInvocationEXT";
     case CapabilityShaderClockKHR:                          return "ShaderClockKHR";
     case CapabilityShaderClockKHR:                          return "ShaderClockKHR";
+    case CapabilityInt64ImageEXT:                           return "Int64ImageEXT";
 
 
     case CapabilityIntegerFunctions2INTEL:              return "CapabilityIntegerFunctions2INTEL";
     case CapabilityIntegerFunctions2INTEL:              return "CapabilityIntegerFunctions2INTEL";
 
 
     case CapabilityAtomicFloat32AddEXT:                     return "AtomicFloat32AddEXT";
     case CapabilityAtomicFloat32AddEXT:                     return "AtomicFloat32AddEXT";
     case CapabilityAtomicFloat64AddEXT:                     return "AtomicFloat64AddEXT";
     case CapabilityAtomicFloat64AddEXT:                     return "AtomicFloat64AddEXT";
 
 
+    case CapabilityWorkgroupMemoryExplicitLayoutKHR:            return "CapabilityWorkgroupMemoryExplicitLayoutKHR";
+    case CapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR:  return "CapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR";
+    case CapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR: return "CapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR";
+
     default: return "Bad";
     default: return "Bad";
     }
     }
 }
 }
@@ -1329,6 +1341,8 @@ const char* OpcodeString(int op)
     case 365: return "OpGroupNonUniformQuadBroadcast";
     case 365: return "OpGroupNonUniformQuadBroadcast";
     case 366: return "OpGroupNonUniformQuadSwap";
     case 366: return "OpGroupNonUniformQuadSwap";
 
 
+    case OpTerminateInvocation: return "OpTerminateInvocation";
+
     case 4421: return "OpSubgroupBallotKHR";
     case 4421: return "OpSubgroupBallotKHR";
     case 4422: return "OpSubgroupFirstInvocationKHR";
     case 4422: return "OpSubgroupFirstInvocationKHR";
     case 4428: return "OpSubgroupAllKHR";
     case 4428: return "OpSubgroupAllKHR";
@@ -1355,17 +1369,23 @@ const char* OpcodeString(int op)
     case OpDecorateStringGOOGLE:       return "OpDecorateStringGOOGLE";
     case OpDecorateStringGOOGLE:       return "OpDecorateStringGOOGLE";
     case OpMemberDecorateStringGOOGLE: return "OpMemberDecorateStringGOOGLE";
     case OpMemberDecorateStringGOOGLE: return "OpMemberDecorateStringGOOGLE";
 
 
+    case OpReportIntersectionKHR:             return "OpReportIntersectionKHR";
+    case OpIgnoreIntersectionNV:              return "OpIgnoreIntersectionNV";
+    case OpIgnoreIntersectionKHR:             return "OpIgnoreIntersectionKHR";
+    case OpTerminateRayNV:                    return "OpTerminateRayNV";
+    case OpTerminateRayKHR:                   return "OpTerminateRayKHR";
+    case OpTraceNV:                           return "OpTraceNV";
+    case OpTraceRayKHR:                       return "OpTraceRayKHR";
+    case OpTypeAccelerationStructureKHR:      return "OpTypeAccelerationStructureKHR";
+    case OpExecuteCallableNV:                 return "OpExecuteCallableNV";
+    case OpExecuteCallableKHR:                return "OpExecuteCallableKHR";
+    case OpConvertUToAccelerationStructureKHR: return "OpConvertUToAccelerationStructureKHR";
+
     case OpGroupNonUniformPartitionNV:       return "OpGroupNonUniformPartitionNV";
     case OpGroupNonUniformPartitionNV:       return "OpGroupNonUniformPartitionNV";
-    case OpReportIntersectionKHR:            return "OpReportIntersectionKHR";
-    case OpIgnoreIntersectionKHR:            return "OpIgnoreIntersectionKHR";
-    case OpTerminateRayKHR:                  return "OpTerminateRayKHR";
-    case OpTraceRayKHR:                      return "OpTraceRayKHR";
-    case OpTypeAccelerationStructureKHR:     return "OpTypeAccelerationStructureKHR";
-    case OpExecuteCallableKHR:               return "OpExecuteCallableKHR";
     case OpImageSampleFootprintNV:           return "OpImageSampleFootprintNV";
     case OpImageSampleFootprintNV:           return "OpImageSampleFootprintNV";
     case OpWritePackedPrimitiveIndices4x8NV: return "OpWritePackedPrimitiveIndices4x8NV";
     case OpWritePackedPrimitiveIndices4x8NV: return "OpWritePackedPrimitiveIndices4x8NV";
 
 
-    case OpTypeRayQueryProvisionalKHR:                                        return "OpTypeRayQueryProvisionalKHR";
+    case OpTypeRayQueryKHR:                                                   return "OpTypeRayQueryKHR";
     case OpRayQueryInitializeKHR:                                             return "OpRayQueryInitializeKHR";
     case OpRayQueryInitializeKHR:                                             return "OpRayQueryInitializeKHR";
     case OpRayQueryTerminateKHR:                                              return "OpRayQueryTerminateKHR";
     case OpRayQueryTerminateKHR:                                              return "OpRayQueryTerminateKHR";
     case OpRayQueryGenerateIntersectionKHR:                                   return "OpRayQueryGenerateIntersectionKHR";
     case OpRayQueryGenerateIntersectionKHR:                                   return "OpRayQueryGenerateIntersectionKHR";
@@ -1497,6 +1517,7 @@ void Parameterize()
     InstructionDesc[OpBranchConditional].setResultAndType(false, false);
     InstructionDesc[OpBranchConditional].setResultAndType(false, false);
     InstructionDesc[OpSwitch].setResultAndType(false, false);
     InstructionDesc[OpSwitch].setResultAndType(false, false);
     InstructionDesc[OpKill].setResultAndType(false, false);
     InstructionDesc[OpKill].setResultAndType(false, false);
+    InstructionDesc[OpTerminateInvocation].setResultAndType(false, false);
     InstructionDesc[OpReturn].setResultAndType(false, false);
     InstructionDesc[OpReturn].setResultAndType(false, false);
     InstructionDesc[OpReturnValue].setResultAndType(false, false);
     InstructionDesc[OpReturnValue].setResultAndType(false, false);
     InstructionDesc[OpUnreachable].setResultAndType(false, false);
     InstructionDesc[OpUnreachable].setResultAndType(false, false);
@@ -2698,7 +2719,7 @@ void Parameterize()
 
 
     InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandScope, "'Execution'");
     InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandScope, "'Execution'");
     InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandId, "X");
     InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandId, "X");
-    InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandLiteralNumber, "'Direction'");
+    InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandId, "'Direction'");
 
 
     InstructionDesc[OpSubgroupBallotKHR].operands.push(OperandId, "'Predicate'");
     InstructionDesc[OpSubgroupBallotKHR].operands.push(OperandId, "'Predicate'");
 
 
@@ -2761,7 +2782,20 @@ void Parameterize()
 
 
     InstructionDesc[OpTypeAccelerationStructureKHR].setResultAndType(true, false);
     InstructionDesc[OpTypeAccelerationStructureKHR].setResultAndType(true, false);
 
 
-    InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'NV Acceleration Structure'");
+    InstructionDesc[OpTraceNV].operands.push(OperandId, "'Acceleration Structure'");
+    InstructionDesc[OpTraceNV].operands.push(OperandId, "'Ray Flags'");
+    InstructionDesc[OpTraceNV].operands.push(OperandId, "'Cull Mask'");
+    InstructionDesc[OpTraceNV].operands.push(OperandId, "'SBT Record Offset'");
+    InstructionDesc[OpTraceNV].operands.push(OperandId, "'SBT Record Stride'");
+    InstructionDesc[OpTraceNV].operands.push(OperandId, "'Miss Index'");
+    InstructionDesc[OpTraceNV].operands.push(OperandId, "'Ray Origin'");
+    InstructionDesc[OpTraceNV].operands.push(OperandId, "'TMin'");
+    InstructionDesc[OpTraceNV].operands.push(OperandId, "'Ray Direction'");
+    InstructionDesc[OpTraceNV].operands.push(OperandId, "'TMax'");
+    InstructionDesc[OpTraceNV].operands.push(OperandId, "'Payload'");
+    InstructionDesc[OpTraceNV].setResultAndType(false, false);
+
+    InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Acceleration Structure'");
     InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Ray Flags'");
     InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Ray Flags'");
     InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Cull Mask'");
     InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Cull Mask'");
     InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'SBT Record Offset'");
     InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'SBT Record Offset'");
@@ -2777,17 +2811,28 @@ void Parameterize()
     InstructionDesc[OpReportIntersectionKHR].operands.push(OperandId, "'Hit Parameter'");
     InstructionDesc[OpReportIntersectionKHR].operands.push(OperandId, "'Hit Parameter'");
     InstructionDesc[OpReportIntersectionKHR].operands.push(OperandId, "'Hit Kind'");
     InstructionDesc[OpReportIntersectionKHR].operands.push(OperandId, "'Hit Kind'");
 
 
+    InstructionDesc[OpIgnoreIntersectionNV].setResultAndType(false, false);
+
     InstructionDesc[OpIgnoreIntersectionKHR].setResultAndType(false, false);
     InstructionDesc[OpIgnoreIntersectionKHR].setResultAndType(false, false);
 
 
+    InstructionDesc[OpTerminateRayNV].setResultAndType(false, false);
+
     InstructionDesc[OpTerminateRayKHR].setResultAndType(false, false);
     InstructionDesc[OpTerminateRayKHR].setResultAndType(false, false);
     
     
+    InstructionDesc[OpExecuteCallableNV].operands.push(OperandId, "SBT Record Index");
+    InstructionDesc[OpExecuteCallableNV].operands.push(OperandId, "CallableData ID");
+    InstructionDesc[OpExecuteCallableNV].setResultAndType(false, false);
+
     InstructionDesc[OpExecuteCallableKHR].operands.push(OperandId, "SBT Record Index");
     InstructionDesc[OpExecuteCallableKHR].operands.push(OperandId, "SBT Record Index");
-    InstructionDesc[OpExecuteCallableKHR].operands.push(OperandId, "CallableData ID");
+    InstructionDesc[OpExecuteCallableKHR].operands.push(OperandId, "CallableData");
     InstructionDesc[OpExecuteCallableKHR].setResultAndType(false, false);
     InstructionDesc[OpExecuteCallableKHR].setResultAndType(false, false);
 
 
+    InstructionDesc[OpConvertUToAccelerationStructureKHR].operands.push(OperandId, "Value");
+    InstructionDesc[OpConvertUToAccelerationStructureKHR].setResultAndType(true, true);
+
     // Ray Query
     // Ray Query
     InstructionDesc[OpTypeAccelerationStructureKHR].setResultAndType(true, false);
     InstructionDesc[OpTypeAccelerationStructureKHR].setResultAndType(true, false);
-    InstructionDesc[OpTypeRayQueryProvisionalKHR].setResultAndType(true, false);
+    InstructionDesc[OpTypeRayQueryKHR].setResultAndType(true, false);
 
 
     InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'RayQuery'");
     InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'RayQuery'");
     InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'AccelerationS'");
     InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'AccelerationS'");

+ 134 - 12
src/libraries/glslang/SPIRV/spirv.hpp

@@ -50,11 +50,11 @@ namespace spv {
 typedef unsigned int Id;
 typedef unsigned int Id;
 
 
 #define SPV_VERSION 0x10500
 #define SPV_VERSION 0x10500
-#define SPV_REVISION 3
+#define SPV_REVISION 4
 
 
 static const unsigned int MagicNumber = 0x07230203;
 static const unsigned int MagicNumber = 0x07230203;
 static const unsigned int Version = 0x00010500;
 static const unsigned int Version = 0x00010500;
-static const unsigned int Revision = 3;
+static const unsigned int Revision = 4;
 static const unsigned int OpCodeMask = 0xffff;
 static const unsigned int OpCodeMask = 0xffff;
 static const unsigned int WordCountShift = 16;
 static const unsigned int WordCountShift = 16;
 
 
@@ -168,10 +168,16 @@ enum ExecutionMode {
     ExecutionModeSampleInterlockUnorderedEXT = 5369,
     ExecutionModeSampleInterlockUnorderedEXT = 5369,
     ExecutionModeShadingRateInterlockOrderedEXT = 5370,
     ExecutionModeShadingRateInterlockOrderedEXT = 5370,
     ExecutionModeShadingRateInterlockUnorderedEXT = 5371,
     ExecutionModeShadingRateInterlockUnorderedEXT = 5371,
+    ExecutionModeSharedLocalMemorySizeINTEL = 5618,
+    ExecutionModeRoundingModeRTPINTEL = 5620,
+    ExecutionModeRoundingModeRTNINTEL = 5621,
+    ExecutionModeFloatingPointModeALTINTEL = 5622,
+    ExecutionModeFloatingPointModeIEEEINTEL = 5623,
     ExecutionModeMaxWorkgroupSizeINTEL = 5893,
     ExecutionModeMaxWorkgroupSizeINTEL = 5893,
     ExecutionModeMaxWorkDimINTEL = 5894,
     ExecutionModeMaxWorkDimINTEL = 5894,
     ExecutionModeNoGlobalOffsetINTEL = 5895,
     ExecutionModeNoGlobalOffsetINTEL = 5895,
     ExecutionModeNumSIMDWorkitemsINTEL = 5896,
     ExecutionModeNumSIMDWorkitemsINTEL = 5896,
+    ExecutionModeSchedulerTargetFmaxMhzINTEL = 5903,
     ExecutionModeMax = 0x7fffffff,
     ExecutionModeMax = 0x7fffffff,
 };
 };
 
 
@@ -204,6 +210,8 @@ enum StorageClass {
     StorageClassPhysicalStorageBuffer = 5349,
     StorageClassPhysicalStorageBuffer = 5349,
     StorageClassPhysicalStorageBufferEXT = 5349,
     StorageClassPhysicalStorageBufferEXT = 5349,
     StorageClassCodeSectionINTEL = 5605,
     StorageClassCodeSectionINTEL = 5605,
+    StorageClassDeviceOnlyINTEL = 5936,
+    StorageClassHostOnlyINTEL = 5937,
     StorageClassMax = 0x7fffffff,
     StorageClassMax = 0x7fffffff,
 };
 };
 
 
@@ -274,6 +282,8 @@ enum ImageFormat {
     ImageFormatRg8ui = 37,
     ImageFormatRg8ui = 37,
     ImageFormatR16ui = 38,
     ImageFormatR16ui = 38,
     ImageFormatR8ui = 39,
     ImageFormatR8ui = 39,
+    ImageFormatR64ui = 40,
+    ImageFormatR64i = 41,
     ImageFormatMax = 0x7fffffff,
     ImageFormatMax = 0x7fffffff,
 };
 };
 
 
@@ -372,6 +382,8 @@ enum FPFastMathModeShift {
     FPFastMathModeNSZShift = 2,
     FPFastMathModeNSZShift = 2,
     FPFastMathModeAllowRecipShift = 3,
     FPFastMathModeAllowRecipShift = 3,
     FPFastMathModeFastShift = 4,
     FPFastMathModeFastShift = 4,
+    FPFastMathModeAllowContractFastINTELShift = 16,
+    FPFastMathModeAllowReassocINTELShift = 17,
     FPFastMathModeMax = 0x7fffffff,
     FPFastMathModeMax = 0x7fffffff,
 };
 };
 
 
@@ -382,6 +394,8 @@ enum FPFastMathModeMask {
     FPFastMathModeNSZMask = 0x00000004,
     FPFastMathModeNSZMask = 0x00000004,
     FPFastMathModeAllowRecipMask = 0x00000008,
     FPFastMathModeAllowRecipMask = 0x00000008,
     FPFastMathModeFastMask = 0x00000010,
     FPFastMathModeFastMask = 0x00000010,
+    FPFastMathModeAllowContractFastINTELMask = 0x00010000,
+    FPFastMathModeAllowReassocINTELMask = 0x00020000,
 };
 };
 
 
 enum FPRoundingMode {
 enum FPRoundingMode {
@@ -482,12 +496,22 @@ enum Decoration {
     DecorationRestrictPointerEXT = 5355,
     DecorationRestrictPointerEXT = 5355,
     DecorationAliasedPointer = 5356,
     DecorationAliasedPointer = 5356,
     DecorationAliasedPointerEXT = 5356,
     DecorationAliasedPointerEXT = 5356,
+    DecorationSIMTCallINTEL = 5599,
     DecorationReferencedIndirectlyINTEL = 5602,
     DecorationReferencedIndirectlyINTEL = 5602,
+    DecorationClobberINTEL = 5607,
+    DecorationSideEffectsINTEL = 5608,
+    DecorationVectorComputeVariableINTEL = 5624,
+    DecorationFuncParamIOKindINTEL = 5625,
+    DecorationVectorComputeFunctionINTEL = 5626,
+    DecorationStackCallINTEL = 5627,
+    DecorationGlobalVariableOffsetINTEL = 5628,
     DecorationCounterBuffer = 5634,
     DecorationCounterBuffer = 5634,
     DecorationHlslCounterBufferGOOGLE = 5634,
     DecorationHlslCounterBufferGOOGLE = 5634,
     DecorationHlslSemanticGOOGLE = 5635,
     DecorationHlslSemanticGOOGLE = 5635,
     DecorationUserSemantic = 5635,
     DecorationUserSemantic = 5635,
     DecorationUserTypeGOOGLE = 5636,
     DecorationUserTypeGOOGLE = 5636,
+    DecorationFunctionRoundingModeINTEL = 5822,
+    DecorationFunctionDenormModeINTEL = 5823,
     DecorationRegisterINTEL = 5825,
     DecorationRegisterINTEL = 5825,
     DecorationMemoryINTEL = 5826,
     DecorationMemoryINTEL = 5826,
     DecorationNumbanksINTEL = 5827,
     DecorationNumbanksINTEL = 5827,
@@ -500,6 +524,17 @@ enum Decoration {
     DecorationMergeINTEL = 5834,
     DecorationMergeINTEL = 5834,
     DecorationBankBitsINTEL = 5835,
     DecorationBankBitsINTEL = 5835,
     DecorationForcePow2DepthINTEL = 5836,
     DecorationForcePow2DepthINTEL = 5836,
+    DecorationBurstCoalesceINTEL = 5899,
+    DecorationCacheSizeINTEL = 5900,
+    DecorationDontStaticallyCoalesceINTEL = 5901,
+    DecorationPrefetchINTEL = 5902,
+    DecorationStallEnableINTEL = 5905,
+    DecorationFuseLoopsInFunctionINTEL = 5907,
+    DecorationBufferLocationINTEL = 5921,
+    DecorationIOPipeStorageINTEL = 5944,
+    DecorationFunctionFloatingPointModeINTEL = 6080,
+    DecorationSingleElementVectorINTEL = 6085,
+    DecorationVectorComputeCallableFunctionINTEL = 6087,
     DecorationMax = 0x7fffffff,
     DecorationMax = 0x7fffffff,
 };
 };
 
 
@@ -558,8 +593,10 @@ enum BuiltIn {
     BuiltInBaseVertex = 4424,
     BuiltInBaseVertex = 4424,
     BuiltInBaseInstance = 4425,
     BuiltInBaseInstance = 4425,
     BuiltInDrawIndex = 4426,
     BuiltInDrawIndex = 4426,
+    BuiltInPrimitiveShadingRateKHR = 4432,
     BuiltInDeviceIndex = 4438,
     BuiltInDeviceIndex = 4438,
     BuiltInViewIndex = 4440,
     BuiltInViewIndex = 4440,
+    BuiltInShadingRateKHR = 4444,
     BuiltInBaryCoordNoPerspAMD = 4992,
     BuiltInBaryCoordNoPerspAMD = 4992,
     BuiltInBaryCoordNoPerspCentroidAMD = 4993,
     BuiltInBaryCoordNoPerspCentroidAMD = 4993,
     BuiltInBaryCoordNoPerspSampleAMD = 4994,
     BuiltInBaryCoordNoPerspSampleAMD = 4994,
@@ -610,7 +647,6 @@ enum BuiltIn {
     BuiltInObjectToWorldNV = 5330,
     BuiltInObjectToWorldNV = 5330,
     BuiltInWorldToObjectKHR = 5331,
     BuiltInWorldToObjectKHR = 5331,
     BuiltInWorldToObjectNV = 5331,
     BuiltInWorldToObjectNV = 5331,
-    BuiltInHitTKHR = 5332,
     BuiltInHitTNV = 5332,
     BuiltInHitTNV = 5332,
     BuiltInHitKindKHR = 5333,
     BuiltInHitKindKHR = 5333,
     BuiltInHitKindNV = 5333,
     BuiltInHitKindNV = 5333,
@@ -653,6 +689,7 @@ enum LoopControlShift {
     LoopControlLoopCoalesceINTELShift = 20,
     LoopControlLoopCoalesceINTELShift = 20,
     LoopControlMaxInterleavingINTELShift = 21,
     LoopControlMaxInterleavingINTELShift = 21,
     LoopControlSpeculatedIterationsINTELShift = 22,
     LoopControlSpeculatedIterationsINTELShift = 22,
+    LoopControlNoFusionINTELShift = 23,
     LoopControlMax = 0x7fffffff,
     LoopControlMax = 0x7fffffff,
 };
 };
 
 
@@ -674,6 +711,7 @@ enum LoopControlMask {
     LoopControlLoopCoalesceINTELMask = 0x00100000,
     LoopControlLoopCoalesceINTELMask = 0x00100000,
     LoopControlMaxInterleavingINTELMask = 0x00200000,
     LoopControlMaxInterleavingINTELMask = 0x00200000,
     LoopControlSpeculatedIterationsINTELMask = 0x00400000,
     LoopControlSpeculatedIterationsINTELMask = 0x00400000,
+    LoopControlNoFusionINTELMask = 0x00800000,
 };
 };
 
 
 enum FunctionControlShift {
 enum FunctionControlShift {
@@ -870,8 +908,12 @@ enum Capability {
     CapabilityGroupNonUniformQuad = 68,
     CapabilityGroupNonUniformQuad = 68,
     CapabilityShaderLayer = 69,
     CapabilityShaderLayer = 69,
     CapabilityShaderViewportIndex = 70,
     CapabilityShaderViewportIndex = 70,
+    CapabilityFragmentShadingRateKHR = 4422,
     CapabilitySubgroupBallotKHR = 4423,
     CapabilitySubgroupBallotKHR = 4423,
     CapabilityDrawParameters = 4427,
     CapabilityDrawParameters = 4427,
+    CapabilityWorkgroupMemoryExplicitLayoutKHR = 4428,
+    CapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR = 4429,
+    CapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR = 4430,
     CapabilitySubgroupVoteKHR = 4431,
     CapabilitySubgroupVoteKHR = 4431,
     CapabilityStorageBuffer16BitAccess = 4433,
     CapabilityStorageBuffer16BitAccess = 4433,
     CapabilityStorageUniformBufferBlock16 = 4433,
     CapabilityStorageUniformBufferBlock16 = 4433,
@@ -894,12 +936,15 @@ enum Capability {
     CapabilityRoundingModeRTE = 4467,
     CapabilityRoundingModeRTE = 4467,
     CapabilityRoundingModeRTZ = 4468,
     CapabilityRoundingModeRTZ = 4468,
     CapabilityRayQueryProvisionalKHR = 4471,
     CapabilityRayQueryProvisionalKHR = 4471,
-    CapabilityRayTraversalPrimitiveCullingProvisionalKHR = 4478,
+    CapabilityRayQueryKHR = 4472,
+    CapabilityRayTraversalPrimitiveCullingKHR = 4478,
+    CapabilityRayTracingKHR = 4479,
     CapabilityFloat16ImageAMD = 5008,
     CapabilityFloat16ImageAMD = 5008,
     CapabilityImageGatherBiasLodAMD = 5009,
     CapabilityImageGatherBiasLodAMD = 5009,
     CapabilityFragmentMaskAMD = 5010,
     CapabilityFragmentMaskAMD = 5010,
     CapabilityStencilExportEXT = 5013,
     CapabilityStencilExportEXT = 5013,
     CapabilityImageReadWriteLodAMD = 5015,
     CapabilityImageReadWriteLodAMD = 5015,
+    CapabilityInt64ImageEXT = 5016,
     CapabilityShaderClockKHR = 5055,
     CapabilityShaderClockKHR = 5055,
     CapabilitySampleMaskOverrideCoverageNV = 5249,
     CapabilitySampleMaskOverrideCoverageNV = 5249,
     CapabilityGeometryShaderPassthroughNV = 5251,
     CapabilityGeometryShaderPassthroughNV = 5251,
@@ -959,21 +1004,37 @@ enum Capability {
     CapabilitySubgroupBufferBlockIOINTEL = 5569,
     CapabilitySubgroupBufferBlockIOINTEL = 5569,
     CapabilitySubgroupImageBlockIOINTEL = 5570,
     CapabilitySubgroupImageBlockIOINTEL = 5570,
     CapabilitySubgroupImageMediaBlockIOINTEL = 5579,
     CapabilitySubgroupImageMediaBlockIOINTEL = 5579,
+    CapabilityRoundToInfinityINTEL = 5582,
+    CapabilityFloatingPointModeINTEL = 5583,
     CapabilityIntegerFunctions2INTEL = 5584,
     CapabilityIntegerFunctions2INTEL = 5584,
     CapabilityFunctionPointersINTEL = 5603,
     CapabilityFunctionPointersINTEL = 5603,
     CapabilityIndirectReferencesINTEL = 5604,
     CapabilityIndirectReferencesINTEL = 5604,
+    CapabilityAsmINTEL = 5606,
+    CapabilityVectorComputeINTEL = 5617,
+    CapabilityVectorAnyINTEL = 5619,
     CapabilitySubgroupAvcMotionEstimationINTEL = 5696,
     CapabilitySubgroupAvcMotionEstimationINTEL = 5696,
     CapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697,
     CapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697,
     CapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698,
     CapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698,
+    CapabilityVariableLengthArrayINTEL = 5817,
+    CapabilityFunctionFloatControlINTEL = 5821,
     CapabilityFPGAMemoryAttributesINTEL = 5824,
     CapabilityFPGAMemoryAttributesINTEL = 5824,
+    CapabilityFPFastMathModeINTEL = 5837,
+    CapabilityArbitraryPrecisionIntegersINTEL = 5844,
     CapabilityUnstructuredLoopControlsINTEL = 5886,
     CapabilityUnstructuredLoopControlsINTEL = 5886,
     CapabilityFPGALoopControlsINTEL = 5888,
     CapabilityFPGALoopControlsINTEL = 5888,
     CapabilityKernelAttributesINTEL = 5892,
     CapabilityKernelAttributesINTEL = 5892,
     CapabilityFPGAKernelAttributesINTEL = 5897,
     CapabilityFPGAKernelAttributesINTEL = 5897,
+    CapabilityFPGAMemoryAccessesINTEL = 5898,
+    CapabilityFPGAClusterAttributesINTEL = 5904,
+    CapabilityLoopFuseINTEL = 5906,
+    CapabilityFPGABufferLocationINTEL = 5920,
+    CapabilityUSMStorageClassesINTEL = 5935,
+    CapabilityIOPipesINTEL = 5943,
     CapabilityBlockingPipesINTEL = 5945,
     CapabilityBlockingPipesINTEL = 5945,
     CapabilityFPGARegINTEL = 5948,
     CapabilityFPGARegINTEL = 5948,
     CapabilityAtomicFloat32AddEXT = 6033,
     CapabilityAtomicFloat32AddEXT = 6033,
     CapabilityAtomicFloat64AddEXT = 6034,
     CapabilityAtomicFloat64AddEXT = 6034,
+    CapabilityLongConstantCompositeINTEL = 6089,
     CapabilityMax = 0x7fffffff,
     CapabilityMax = 0x7fffffff,
 };
 };
 
 
@@ -1024,6 +1085,34 @@ enum RayQueryCandidateIntersectionType {
     RayQueryCandidateIntersectionTypeMax = 0x7fffffff,
     RayQueryCandidateIntersectionTypeMax = 0x7fffffff,
 };
 };
 
 
+enum FragmentShadingRateShift {
+    FragmentShadingRateVertical2PixelsShift = 0,
+    FragmentShadingRateVertical4PixelsShift = 1,
+    FragmentShadingRateHorizontal2PixelsShift = 2,
+    FragmentShadingRateHorizontal4PixelsShift = 3,
+    FragmentShadingRateMax = 0x7fffffff,
+};
+
+enum FragmentShadingRateMask {
+    FragmentShadingRateMaskNone = 0,
+    FragmentShadingRateVertical2PixelsMask = 0x00000001,
+    FragmentShadingRateVertical4PixelsMask = 0x00000002,
+    FragmentShadingRateHorizontal2PixelsMask = 0x00000004,
+    FragmentShadingRateHorizontal4PixelsMask = 0x00000008,
+};
+
+enum FPDenormMode {
+  FPDenormModePreserve = 0,
+  FPDenormModeFlushToZero = 1,
+  FPDenormModeMax = 0x7fffffff,
+};
+
+enum FPOperationMode {
+  FPOperationModeIEEE = 0,
+  FPOperationModeALT = 1,
+  FPOperationModeMax = 0x7fffffff,
+};
+
 enum Op {
 enum Op {
     OpNop = 0,
     OpNop = 0,
     OpUndef = 1,
     OpUndef = 1,
@@ -1369,13 +1458,19 @@ enum Op {
     OpPtrEqual = 401,
     OpPtrEqual = 401,
     OpPtrNotEqual = 402,
     OpPtrNotEqual = 402,
     OpPtrDiff = 403,
     OpPtrDiff = 403,
+    OpTerminateInvocation = 4416,
     OpSubgroupBallotKHR = 4421,
     OpSubgroupBallotKHR = 4421,
     OpSubgroupFirstInvocationKHR = 4422,
     OpSubgroupFirstInvocationKHR = 4422,
     OpSubgroupAllKHR = 4428,
     OpSubgroupAllKHR = 4428,
     OpSubgroupAnyKHR = 4429,
     OpSubgroupAnyKHR = 4429,
     OpSubgroupAllEqualKHR = 4430,
     OpSubgroupAllEqualKHR = 4430,
     OpSubgroupReadInvocationKHR = 4432,
     OpSubgroupReadInvocationKHR = 4432,
-    OpTypeRayQueryProvisionalKHR = 4472,
+    OpTraceRayKHR = 4445,
+    OpExecuteCallableKHR = 4446,
+    OpConvertUToAccelerationStructureKHR = 4447,
+    OpIgnoreIntersectionKHR = 4448,
+    OpTerminateRayKHR = 4449,
+    OpTypeRayQueryKHR = 4472,
     OpRayQueryInitializeKHR = 4473,
     OpRayQueryInitializeKHR = 4473,
     OpRayQueryTerminateKHR = 4474,
     OpRayQueryTerminateKHR = 4474,
     OpRayQueryGenerateIntersectionKHR = 4475,
     OpRayQueryGenerateIntersectionKHR = 4475,
@@ -1398,15 +1493,11 @@ enum Op {
     OpWritePackedPrimitiveIndices4x8NV = 5299,
     OpWritePackedPrimitiveIndices4x8NV = 5299,
     OpReportIntersectionKHR = 5334,
     OpReportIntersectionKHR = 5334,
     OpReportIntersectionNV = 5334,
     OpReportIntersectionNV = 5334,
-    OpIgnoreIntersectionKHR = 5335,
     OpIgnoreIntersectionNV = 5335,
     OpIgnoreIntersectionNV = 5335,
-    OpTerminateRayKHR = 5336,
     OpTerminateRayNV = 5336,
     OpTerminateRayNV = 5336,
     OpTraceNV = 5337,
     OpTraceNV = 5337,
-    OpTraceRayKHR = 5337,
     OpTypeAccelerationStructureKHR = 5341,
     OpTypeAccelerationStructureKHR = 5341,
     OpTypeAccelerationStructureNV = 5341,
     OpTypeAccelerationStructureNV = 5341,
-    OpExecuteCallableKHR = 5344,
     OpExecuteCallableNV = 5344,
     OpExecuteCallableNV = 5344,
     OpTypeCooperativeMatrixNV = 5358,
     OpTypeCooperativeMatrixNV = 5358,
     OpCooperativeMatrixLoadNV = 5359,
     OpCooperativeMatrixLoadNV = 5359,
@@ -1441,8 +1532,11 @@ enum Op {
     OpUSubSatINTEL = 5596,
     OpUSubSatINTEL = 5596,
     OpIMul32x16INTEL = 5597,
     OpIMul32x16INTEL = 5597,
     OpUMul32x16INTEL = 5598,
     OpUMul32x16INTEL = 5598,
-    OpFunctionPointerINTEL = 5600,
+    OpConstFunctionPointerINTEL = 5600,
     OpFunctionPointerCallINTEL = 5601,
     OpFunctionPointerCallINTEL = 5601,
+    OpAsmTargetINTEL = 5609,
+    OpAsmINTEL = 5610,
+    OpAsmCallINTEL = 5611,
     OpDecorateString = 5632,
     OpDecorateString = 5632,
     OpDecorateStringGOOGLE = 5632,
     OpDecorateStringGOOGLE = 5632,
     OpMemberDecorateString = 5633,
     OpMemberDecorateString = 5633,
@@ -1565,7 +1659,12 @@ enum Op {
     OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814,
     OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814,
     OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815,
     OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815,
     OpSubgroupAvcSicGetInterRawSadsINTEL = 5816,
     OpSubgroupAvcSicGetInterRawSadsINTEL = 5816,
+    OpVariableLengthArrayINTEL = 5818,
+    OpSaveMemoryINTEL = 5819,
+    OpRestoreMemoryINTEL = 5820,
     OpLoopControlINTEL = 5887,
     OpLoopControlINTEL = 5887,
+    OpPtrCastToCrossWorkgroupINTEL = 5934,
+    OpCrossWorkgroupCastToPtrINTEL = 5938,
     OpReadPipeBlockingINTEL = 5946,
     OpReadPipeBlockingINTEL = 5946,
     OpWritePipeBlockingINTEL = 5947,
     OpWritePipeBlockingINTEL = 5947,
     OpFPGARegINTEL = 5949,
     OpFPGARegINTEL = 5949,
@@ -1587,6 +1686,10 @@ enum Op {
     OpRayQueryGetIntersectionObjectToWorldKHR = 6031,
     OpRayQueryGetIntersectionObjectToWorldKHR = 6031,
     OpRayQueryGetIntersectionWorldToObjectKHR = 6032,
     OpRayQueryGetIntersectionWorldToObjectKHR = 6032,
     OpAtomicFAddEXT = 6035,
     OpAtomicFAddEXT = 6035,
+    OpTypeBufferSurfaceINTEL = 6086,
+    OpTypeStructContinuedINTEL = 6090,
+    OpConstantCompositeContinuedINTEL = 6091,
+    OpSpecConstantCompositeContinuedINTEL = 6092,
     OpMax = 0x7fffffff,
     OpMax = 0x7fffffff,
 };
 };
 
 
@@ -1939,13 +2042,19 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
     case OpPtrEqual: *hasResult = true; *hasResultType = true; break;
     case OpPtrEqual: *hasResult = true; *hasResultType = true; break;
     case OpPtrNotEqual: *hasResult = true; *hasResultType = true; break;
     case OpPtrNotEqual: *hasResult = true; *hasResultType = true; break;
     case OpPtrDiff: *hasResult = true; *hasResultType = true; break;
     case OpPtrDiff: *hasResult = true; *hasResultType = true; break;
+    case OpTerminateInvocation: *hasResult = false; *hasResultType = false; break;
     case OpSubgroupBallotKHR: *hasResult = true; *hasResultType = true; break;
     case OpSubgroupBallotKHR: *hasResult = true; *hasResultType = true; break;
     case OpSubgroupFirstInvocationKHR: *hasResult = true; *hasResultType = true; break;
     case OpSubgroupFirstInvocationKHR: *hasResult = true; *hasResultType = true; break;
     case OpSubgroupAllKHR: *hasResult = true; *hasResultType = true; break;
     case OpSubgroupAllKHR: *hasResult = true; *hasResultType = true; break;
     case OpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break;
     case OpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break;
     case OpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break;
     case OpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break;
     case OpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break;
     case OpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break;
-    case OpTypeRayQueryProvisionalKHR: *hasResult = true; *hasResultType = false; break;
+    case OpTraceRayKHR: *hasResult = false; *hasResultType = false; break;
+    case OpExecuteCallableKHR: *hasResult = false; *hasResultType = false; break;
+    case OpConvertUToAccelerationStructureKHR: *hasResult = true; *hasResultType = true; break;
+    case OpIgnoreIntersectionKHR: *hasResult = false; *hasResultType = false; break;
+    case OpTerminateRayKHR: *hasResult = false; *hasResultType = false; break;
+    case OpTypeRayQueryKHR: *hasResult = true; *hasResultType = false; break;
     case OpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break;
     case OpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break;
     case OpRayQueryTerminateKHR: *hasResult = false; *hasResultType = false; break;
     case OpRayQueryTerminateKHR: *hasResult = false; *hasResultType = false; break;
     case OpRayQueryGenerateIntersectionKHR: *hasResult = false; *hasResultType = false; break;
     case OpRayQueryGenerateIntersectionKHR: *hasResult = false; *hasResultType = false; break;
@@ -2005,8 +2114,11 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
     case OpUSubSatINTEL: *hasResult = true; *hasResultType = true; break;
     case OpUSubSatINTEL: *hasResult = true; *hasResultType = true; break;
     case OpIMul32x16INTEL: *hasResult = true; *hasResultType = true; break;
     case OpIMul32x16INTEL: *hasResult = true; *hasResultType = true; break;
     case OpUMul32x16INTEL: *hasResult = true; *hasResultType = true; break;
     case OpUMul32x16INTEL: *hasResult = true; *hasResultType = true; break;
-    case OpFunctionPointerINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpConstFunctionPointerINTEL: *hasResult = true; *hasResultType = true; break;
     case OpFunctionPointerCallINTEL: *hasResult = true; *hasResultType = true; break;
     case OpFunctionPointerCallINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpAsmTargetINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpAsmINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpAsmCallINTEL: *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;
@@ -2127,7 +2239,12 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
     case OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: *hasResult = true; *hasResultType = true; break;
     case OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: *hasResult = true; *hasResultType = true; break;
     case OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: *hasResult = true; *hasResultType = true; break;
     case OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: *hasResult = true; *hasResultType = true; break;
     case OpSubgroupAvcSicGetInterRawSadsINTEL: *hasResult = true; *hasResultType = true; break;
     case OpSubgroupAvcSicGetInterRawSadsINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpVariableLengthArrayINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSaveMemoryINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpRestoreMemoryINTEL: *hasResult = false; *hasResultType = false; break;
     case OpLoopControlINTEL: *hasResult = false; *hasResultType = false; break;
     case OpLoopControlINTEL: *hasResult = false; *hasResultType = false; break;
+    case OpPtrCastToCrossWorkgroupINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpCrossWorkgroupCastToPtrINTEL: *hasResult = true; *hasResultType = true; break;
     case OpReadPipeBlockingINTEL: *hasResult = true; *hasResultType = true; break;
     case OpReadPipeBlockingINTEL: *hasResult = true; *hasResultType = true; break;
     case OpWritePipeBlockingINTEL: *hasResult = true; *hasResultType = true; break;
     case OpWritePipeBlockingINTEL: *hasResult = true; *hasResultType = true; break;
     case OpFPGARegINTEL: *hasResult = true; *hasResultType = true; break;
     case OpFPGARegINTEL: *hasResult = true; *hasResultType = true; break;
@@ -2149,6 +2266,10 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
     case OpRayQueryGetIntersectionObjectToWorldKHR: *hasResult = true; *hasResultType = true; break;
     case OpRayQueryGetIntersectionObjectToWorldKHR: *hasResult = true; *hasResultType = true; break;
     case OpRayQueryGetIntersectionWorldToObjectKHR: *hasResult = true; *hasResultType = true; break;
     case OpRayQueryGetIntersectionWorldToObjectKHR: *hasResult = true; *hasResultType = true; break;
     case OpAtomicFAddEXT: *hasResult = true; *hasResultType = true; break;
     case OpAtomicFAddEXT: *hasResult = true; *hasResultType = true; break;
+    case OpTypeBufferSurfaceINTEL: *hasResult = true; *hasResultType = false; break;
+    case OpTypeStructContinuedINTEL: *hasResult = false; *hasResultType = false; break;
+    case OpConstantCompositeContinuedINTEL: *hasResult = false; *hasResultType = false; break;
+    case OpSpecConstantCompositeContinuedINTEL: *hasResult = false; *hasResultType = false; break;
     }
     }
 }
 }
 #endif /* SPV_ENABLE_UTILITY_CODE */
 #endif /* SPV_ENABLE_UTILITY_CODE */
@@ -2164,6 +2285,7 @@ inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask
 inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); }
 inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); }
 inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); }
 inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); }
 inline RayFlagsMask operator|(RayFlagsMask a, RayFlagsMask b) { return RayFlagsMask(unsigned(a) | unsigned(b)); }
 inline RayFlagsMask operator|(RayFlagsMask a, RayFlagsMask b) { return RayFlagsMask(unsigned(a) | unsigned(b)); }
+inline FragmentShadingRateMask operator|(FragmentShadingRateMask a, FragmentShadingRateMask b) { return FragmentShadingRateMask(unsigned(a) | unsigned(b)); }
 
 
 }  // end namespace spv
 }  // end namespace spv
 
 

+ 1 - 0
src/libraries/glslang/SPIRV/spvIR.h

@@ -263,6 +263,7 @@ public:
         case OpBranchConditional:
         case OpBranchConditional:
         case OpSwitch:
         case OpSwitch:
         case OpKill:
         case OpKill:
+        case OpTerminateInvocation:
         case OpReturn:
         case OpReturn:
         case OpReturnValue:
         case OpReturnValue:
         case OpUnreachable:
         case OpUnreachable:

+ 6 - 0
src/libraries/glslang/glslang/Include/BaseTypes.h

@@ -228,6 +228,9 @@ enum TBuiltInVariable {
     EbvViewIndex,
     EbvViewIndex,
     EbvDeviceIndex,
     EbvDeviceIndex,
 
 
+    EbvShadingRateKHR,
+    EbvPrimitiveShadingRateKHR,
+
     EbvFragSizeEXT,
     EbvFragSizeEXT,
     EbvFragInvocationCountEXT,
     EbvFragInvocationCountEXT,
 
 
@@ -480,6 +483,9 @@ __inline const char* GetBuiltInVariableString(TBuiltInVariable v)
     case EbvWarpID:                     return "WarpIDNV";
     case EbvWarpID:                     return "WarpIDNV";
     case EbvSMID:                       return "SMIDNV";
     case EbvSMID:                       return "SMIDNV";
 
 
+    case EbvShadingRateKHR:             return "ShadingRateKHR";
+    case EbvPrimitiveShadingRateKHR:    return "PrimitiveShadingRateKHR";
+
     default:                      return "unknown built-in variable";
     default:                      return "unknown built-in variable";
     }
     }
 }
 }

+ 112 - 11
src/libraries/glslang/glslang/Include/Types.h

@@ -406,6 +406,7 @@ enum TLayoutFormat {
     ElfRg8i,
     ElfRg8i,
     ElfR16i,
     ElfR16i,
     ElfR8i,
     ElfR8i,
+    ElfR64i,
 
 
     ElfIntGuard,       // to help with comparisons
     ElfIntGuard,       // to help with comparisons
 
 
@@ -423,6 +424,7 @@ enum TLayoutFormat {
     ElfRg8ui,
     ElfRg8ui,
     ElfR16ui,
     ElfR16ui,
     ElfR8ui,
     ElfR8ui,
+    ElfR64ui,
 
 
     ElfCount
     ElfCount
 };
 };
@@ -497,7 +499,9 @@ public:
         declaredBuiltIn = EbvNone;
         declaredBuiltIn = EbvNone;
 #ifndef GLSLANG_WEB
 #ifndef GLSLANG_WEB
         noContraction = false;
         noContraction = false;
+        nullInit = false;
 #endif
 #endif
+        defaultBlock = false;
     }
     }
 
 
     // drop qualifiers that don't belong in a temporary variable
     // drop qualifiers that don't belong in a temporary variable
@@ -510,6 +514,8 @@ public:
         clearMemory();
         clearMemory();
         specConstant = false;
         specConstant = false;
         nonUniform = false;
         nonUniform = false;
+        nullInit = false;
+        defaultBlock = false;
         clearLayout();
         clearLayout();
     }
     }
 
 
@@ -568,6 +574,7 @@ public:
     bool specConstant : 1;
     bool specConstant : 1;
     bool nonUniform   : 1;
     bool nonUniform   : 1;
     bool explicitOffset   : 1;
     bool explicitOffset   : 1;
+    bool defaultBlock : 1; // default blocks with matching names have structures merged when linking
 
 
 #ifdef GLSLANG_WEB
 #ifdef GLSLANG_WEB
     bool isWriteOnly() const { return false; }
     bool isWriteOnly() const { return false; }
@@ -586,6 +593,8 @@ public:
     bool isNoContraction() const { return false; }
     bool isNoContraction() const { return false; }
     void setNoContraction() { }
     void setNoContraction() { }
     bool isPervertexNV() const { return false; }
     bool isPervertexNV() const { return false; }
+    void setNullInit() { }
+    bool isNullInit() const { 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;
@@ -607,6 +616,7 @@ public:
     bool subgroupcoherent  : 1;
     bool subgroupcoherent  : 1;
     bool shadercallcoherent : 1;
     bool shadercallcoherent : 1;
     bool nonprivate   : 1;
     bool nonprivate   : 1;
+    bool nullInit : 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; }
@@ -642,6 +652,8 @@ public:
     bool isNoContraction() const { return noContraction; }
     bool isNoContraction() const { return noContraction; }
     void setNoContraction() { noContraction = true; }
     void setNoContraction() { noContraction = true; }
     bool isPervertexNV() const { return pervertexNV; }
     bool isPervertexNV() const { return pervertexNV; }
+    void setNullInit() { nullInit = true; }
+    bool isNullInit() const { return nullInit; }
 #endif
 #endif
 
 
     bool isPipeInput() const
     bool isPipeInput() const
@@ -747,6 +759,46 @@ public:
         }
         }
     }
     }
 
 
+    TBlockStorageClass getBlockStorage() const {
+        if (storage == EvqUniform && !isPushConstant()) {
+            return EbsUniform;
+        }
+        else if (storage == EvqUniform) {
+            return EbsPushConstant;
+        }
+        else if (storage == EvqBuffer) {
+            return EbsStorageBuffer;
+        }
+        return EbsNone;
+    }
+
+    void setBlockStorage(TBlockStorageClass newBacking) {
+#ifndef GLSLANG_WEB
+        layoutPushConstant = (newBacking == EbsPushConstant);
+#endif
+        switch (newBacking) {
+        case EbsUniform :
+            if (layoutPacking == ElpStd430) {
+                // std430 would not be valid
+                layoutPacking = ElpStd140;
+            }
+            storage = EvqUniform;
+            break;
+        case EbsStorageBuffer : 
+            storage = EvqBuffer;
+            break;
+#ifndef GLSLANG_WEB
+        case EbsPushConstant :
+            storage = EvqUniform;
+            layoutSet = TQualifier::layoutSetEnd;
+            layoutBinding = TQualifier::layoutBindingEnd;
+            break;
+#endif
+        default:
+            break;
+        }
+    }
+
 #ifdef GLSLANG_WEB
 #ifdef GLSLANG_WEB
     bool isPerView() const { return false; }
     bool isPerView() const { return false; }
     bool isTaskMemory() const { return false; }
     bool isTaskMemory() const { return false; }
@@ -755,6 +807,12 @@ public:
     bool isPerPrimitive() const { return perPrimitiveNV; }
     bool isPerPrimitive() const { return perPrimitiveNV; }
     bool isPerView() const { return perViewNV; }
     bool isPerView() const { return perViewNV; }
     bool isTaskMemory() const { return perTaskNV; }
     bool isTaskMemory() const { return perTaskNV; }
+    bool isAnyPayload() const {
+        return storage == EvqPayload || storage == EvqPayloadIn;
+    }
+    bool isAnyCallable() const {
+        return storage == EvqCallableData || storage == EvqCallableDataIn;
+    }
 
 
     // True if this type of IO is supposed to be arrayed with extra level for per-vertex data
     // True if this type of IO is supposed to be arrayed with extra level for per-vertex data
     bool isArrayedIo(EShLanguage language) const
     bool isArrayedIo(EShLanguage language) const
@@ -837,6 +895,7 @@ public:
         return hasNonXfbLayout() ||
         return hasNonXfbLayout() ||
                hasXfb();
                hasXfb();
     }
     }
+
     TLayoutMatrix  layoutMatrix  : 3;
     TLayoutMatrix  layoutMatrix  : 3;
     TLayoutPacking layoutPacking : 4;
     TLayoutPacking layoutPacking : 4;
     int layoutOffset;
     int layoutOffset;
@@ -1117,6 +1176,8 @@ public:
         case ElfR32ui:        return "r32ui";
         case ElfR32ui:        return "r32ui";
         case ElfR16ui:        return "r16ui";
         case ElfR16ui:        return "r16ui";
         case ElfR8ui:         return "r8ui";
         case ElfR8ui:         return "r8ui";
+        case ElfR64ui:        return "r64ui";
+        case ElfR64i:         return "r64i";
         default:              return "none";
         default:              return "none";
         }
         }
     }
     }
@@ -1986,6 +2047,7 @@ public:
         case EbtAccStruct:         return "accelerationStructureNV";
         case EbtAccStruct:         return "accelerationStructureNV";
         case EbtRayQuery:          return "rayQueryEXT";
         case EbtRayQuery:          return "rayQueryEXT";
         case EbtReference:         return "reference";
         case EbtReference:         return "reference";
+        case EbtString:            return "string";
 #endif
 #endif
         default:                   return "unknown type";
         default:                   return "unknown type";
         }
         }
@@ -2153,6 +2215,8 @@ public:
             appendStr(" specialization-constant");
             appendStr(" specialization-constant");
         if (qualifier.nonUniform)
         if (qualifier.nonUniform)
             appendStr(" nonuniform");
             appendStr(" nonuniform");
+        if (qualifier.isNullInit())
+            appendStr(" null-init");
         appendStr(" ");
         appendStr(" ");
         appendStr(getStorageQualifierString());
         appendStr(getStorageQualifierString());
         if (isArray()) {
         if (isArray()) {
@@ -2272,6 +2336,17 @@ public:
         name += ';' ;
         name += ';' ;
     }
     }
 
 
+    // These variables are inconsistently declared inside and outside of gl_PerVertex in glslang right now.
+    // They are declared inside of 'in gl_PerVertex', but sitting as standalone when they are 'out'puts.
+    bool isInconsistentGLPerVertexMember(const TString& name) const
+    {
+        if (name == "gl_SecondaryPositionNV" ||
+            name == "gl_PositionPerViewNV")
+            return true;
+        return false;
+    }
+
+
     // Do two structure types match?  They could be declared independently,
     // Do two structure types match?  They could be declared independently,
     // in different places, but still might satisfy the definition of matching.
     // in different places, but still might satisfy the definition of matching.
     // From the spec:
     // From the spec:
@@ -2287,22 +2362,48 @@ public:
             (isStruct() && right.isStruct() && structure == right.structure))
             (isStruct() && right.isStruct() && structure == right.structure))
             return true;
             return true;
 
 
-        // Both being nullptr was caught above, now they both have to be structures of the same number of elements
-        if (!isStruct() || !right.isStruct() ||
-            structure->size() != right.structure->size())
-            return false;
-
         // Structure names have to match
         // Structure names have to match
         if (*typeName != *right.typeName)
         if (*typeName != *right.typeName)
             return false;
             return false;
 
 
-        // Compare the names and types of all the members, which have to match
-        for (unsigned int i = 0; i < structure->size(); ++i) {
-            if ((*structure)[i].type->getFieldName() != (*right.structure)[i].type->getFieldName())
-                return false;
+        // There are inconsistencies with how gl_PerVertex is setup. For now ignore those as errors if they
+        // are known inconsistencies.
+        bool isGLPerVertex = *typeName == "gl_PerVertex";
 
 
-            if (*(*structure)[i].type != *(*right.structure)[i].type)
-                return false;
+        // Both being nullptr was caught above, now they both have to be structures of the same number of elements
+        if (!isStruct() || !right.isStruct() ||
+            (structure->size() != right.structure->size() && !isGLPerVertex))
+            return false;
+
+        // Compare the names and types of all the members, which have to match
+        for (size_t li = 0, ri = 0; li < structure->size() || ri < right.structure->size(); ++li, ++ri) {
+            if (li < structure->size() && ri < right.structure->size()) {
+                if ((*structure)[li].type->getFieldName() == (*right.structure)[ri].type->getFieldName()) {
+                    if (*(*structure)[li].type != *(*right.structure)[ri].type)
+                        return false;
+                } else {
+                    // If one of the members is something that's inconsistently declared, skip over it
+                    // for now.
+                    if (isGLPerVertex) {
+                        if (isInconsistentGLPerVertexMember((*structure)[li].type->getFieldName())) {
+                            ri--;
+                            continue;
+                        } else if (isInconsistentGLPerVertexMember((*right.structure)[ri].type->getFieldName())) {
+                            li--;
+                            continue;
+                        }
+                    } else {
+                        return false;
+                    }
+                }
+            // If we get here, then there should only be inconsistently declared members left
+            } else if (li < structure->size()) {
+                if (!isInconsistentGLPerVertexMember((*structure)[li].type->getFieldName()))
+                    return false;
+            } else {
+                if (!isInconsistentGLPerVertexMember((*right.structure)[ri].type->getFieldName()))
+                    return false;
+            }
         }
         }
 
 
         return true;
         return true;

+ 38 - 22
src/libraries/glslang/glslang/Include/glslang_c_interface.h

@@ -203,28 +203,44 @@ typedef struct glsl_include_callbacks_s {
 extern "C" {
 extern "C" {
 #endif
 #endif
 
 
-int glslang_initialize_process();
-void glslang_finalize_process();
-
-glslang_shader_t* glslang_shader_create(const glslang_input_t* input);
-void glslang_shader_delete(glslang_shader_t* shader);
-int glslang_shader_preprocess(glslang_shader_t* shader, const glslang_input_t* input);
-int glslang_shader_parse(glslang_shader_t* shader, const glslang_input_t* input);
-const char* glslang_shader_get_preprocessed_code(glslang_shader_t* shader);
-const char* glslang_shader_get_info_log(glslang_shader_t* shader);
-const char* glslang_shader_get_info_debug_log(glslang_shader_t* shader);
-
-glslang_program_t* glslang_program_create();
-void glslang_program_delete(glslang_program_t* program);
-void glslang_program_add_shader(glslang_program_t* program, glslang_shader_t* shader);
-int glslang_program_link(glslang_program_t* program, int messages); // glslang_messages_t
-void glslang_program_SPIRV_generate(glslang_program_t* program, glslang_stage_t stage);
-size_t glslang_program_SPIRV_get_size(glslang_program_t* program);
-void glslang_program_SPIRV_get(glslang_program_t* program, unsigned int*);
-unsigned int* glslang_program_SPIRV_get_ptr(glslang_program_t* program);
-const char* glslang_program_SPIRV_get_messages(glslang_program_t* program);
-const char* glslang_program_get_info_log(glslang_program_t* program);
-const char* glslang_program_get_info_debug_log(glslang_program_t* program);
+#ifdef GLSLANG_IS_SHARED_LIBRARY
+    #ifdef _WIN32
+        #ifdef GLSLANG_EXPORTING
+            #define GLSLANG_EXPORT __declspec(dllexport)
+        #else
+            #define GLSLANG_EXPORT __declspec(dllimport)
+        #endif
+    #elif __GNUC__ >= 4
+        #define GLSLANG_EXPORT __attribute__((visibility("default")))
+    #endif
+#endif // GLSLANG_IS_SHARED_LIBRARY
+
+#ifndef GLSLANG_EXPORT
+#define GLSLANG_EXPORT
+#endif
+
+GLSLANG_EXPORT int glslang_initialize_process();
+GLSLANG_EXPORT void glslang_finalize_process();
+
+GLSLANG_EXPORT glslang_shader_t* glslang_shader_create(const glslang_input_t* input);
+GLSLANG_EXPORT void glslang_shader_delete(glslang_shader_t* shader);
+GLSLANG_EXPORT int glslang_shader_preprocess(glslang_shader_t* shader, const glslang_input_t* input);
+GLSLANG_EXPORT int glslang_shader_parse(glslang_shader_t* shader, const glslang_input_t* input);
+GLSLANG_EXPORT const char* glslang_shader_get_preprocessed_code(glslang_shader_t* shader);
+GLSLANG_EXPORT const char* glslang_shader_get_info_log(glslang_shader_t* shader);
+GLSLANG_EXPORT const char* glslang_shader_get_info_debug_log(glslang_shader_t* shader);
+
+GLSLANG_EXPORT glslang_program_t* glslang_program_create();
+GLSLANG_EXPORT void glslang_program_delete(glslang_program_t* program);
+GLSLANG_EXPORT void glslang_program_add_shader(glslang_program_t* program, glslang_shader_t* shader);
+GLSLANG_EXPORT int glslang_program_link(glslang_program_t* program, int messages); // glslang_messages_t
+GLSLANG_EXPORT void glslang_program_SPIRV_generate(glslang_program_t* program, glslang_stage_t stage);
+GLSLANG_EXPORT size_t glslang_program_SPIRV_get_size(glslang_program_t* program);
+GLSLANG_EXPORT void glslang_program_SPIRV_get(glslang_program_t* program, unsigned int*);
+GLSLANG_EXPORT unsigned int* glslang_program_SPIRV_get_ptr(glslang_program_t* program);
+GLSLANG_EXPORT const char* glslang_program_SPIRV_get_messages(glslang_program_t* program);
+GLSLANG_EXPORT const char* glslang_program_get_info_log(glslang_program_t* program);
+GLSLANG_EXPORT const char* glslang_program_get_info_debug_log(glslang_program_t* program);
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }

+ 3 - 2
src/libraries/glslang/glslang/Include/glslang_c_shader_types.h

@@ -100,8 +100,9 @@ typedef enum {
 typedef enum {
 typedef enum {
     GLSLANG_TARGET_VULKAN_1_0 = (1 << 22),
     GLSLANG_TARGET_VULKAN_1_0 = (1 << 22),
     GLSLANG_TARGET_VULKAN_1_1 = (1 << 22) | (1 << 12),
     GLSLANG_TARGET_VULKAN_1_1 = (1 << 22) | (1 << 12),
+    GLSLANG_TARGET_VULKAN_1_2 = (1 << 22) | (2 << 12),
     GLSLANG_TARGET_OPENGL_450 = 450,
     GLSLANG_TARGET_OPENGL_450 = 450,
-    LAST_ELEMENT_MARKER(GLSLANG_TARGET_CLIENT_VERSION_COUNT),
+    LAST_ELEMENT_MARKER(GLSLANG_TARGET_CLIENT_VERSION_COUNT = 4),
 } glslang_target_client_version_t;
 } glslang_target_client_version_t;
 
 
 /* SH_TARGET_LanguageVersion counterpart */
 /* SH_TARGET_LanguageVersion counterpart */
@@ -112,7 +113,7 @@ typedef enum {
     GLSLANG_TARGET_SPV_1_3 = (1 << 16) | (3 << 8),
     GLSLANG_TARGET_SPV_1_3 = (1 << 16) | (3 << 8),
     GLSLANG_TARGET_SPV_1_4 = (1 << 16) | (4 << 8),
     GLSLANG_TARGET_SPV_1_4 = (1 << 16) | (4 << 8),
     GLSLANG_TARGET_SPV_1_5 = (1 << 16) | (5 << 8),
     GLSLANG_TARGET_SPV_1_5 = (1 << 16) | (5 << 8),
-    LAST_ELEMENT_MARKER(GLSLANG_TARGET_LANGUAGE_VERSION_COUNT),
+    LAST_ELEMENT_MARKER(GLSLANG_TARGET_LANGUAGE_VERSION_COUNT = 6),
 } glslang_target_language_version_t;
 } glslang_target_language_version_t;
 
 
 /* EShExecutable counterpart */
 /* EShExecutable counterpart */

+ 28 - 11
src/libraries/glslang/glslang/Include/intermediate.h

@@ -280,6 +280,12 @@ enum TOperator {
     EOpConvUvec2ToPtr,
     EOpConvUvec2ToPtr,
     EOpConvPtrToUvec2,
     EOpConvPtrToUvec2,
 
 
+    // uint64_t -> accelerationStructureEXT
+    EOpConvUint64ToAccStruct,
+
+    // uvec2 -> accelerationStructureEXT
+    EOpConvUvec2ToAccStruct,
+
     //
     //
     // binary operations
     // binary operations
     //
     //
@@ -587,6 +593,7 @@ enum TOperator {
     EOpTime,
     EOpTime,
 
 
     EOpAtomicAdd,
     EOpAtomicAdd,
+    EOpAtomicSubtract,
     EOpAtomicMin,
     EOpAtomicMin,
     EOpAtomicMax,
     EOpAtomicMax,
     EOpAtomicAnd,
     EOpAtomicAnd,
@@ -628,13 +635,16 @@ enum TOperator {
     // Branch
     // Branch
     //
     //
 
 
-    EOpKill,            // Fragment only
+    EOpKill,                // Fragment only
+    EOpTerminateInvocation, // Fragment only
+    EOpDemote,              // Fragment only
+    EOpTerminateRayKHR,         // Any-hit only
+    EOpIgnoreIntersectionKHR,   // Any-hit only
     EOpReturn,
     EOpReturn,
     EOpBreak,
     EOpBreak,
     EOpContinue,
     EOpContinue,
     EOpCase,
     EOpCase,
     EOpDefault,
     EOpDefault,
-    EOpDemote,          // Fragment only
 
 
     //
     //
     // Constructors
     // Constructors
@@ -751,6 +761,7 @@ enum TOperator {
     EOpConstructNonuniform,     // expected to be transformed away, not present in final AST
     EOpConstructNonuniform,     // expected to be transformed away, not present in final AST
     EOpConstructReference,
     EOpConstructReference,
     EOpConstructCooperativeMatrix,
     EOpConstructCooperativeMatrix,
+    EOpConstructAccStruct,
     EOpConstructGuardEnd,
     EOpConstructGuardEnd,
 
 
     //
     //
@@ -911,11 +922,13 @@ enum TOperator {
     EOpAverageRounded,
     EOpAverageRounded,
     EOpMul32x16,
     EOpMul32x16,
 
 
-    EOpTrace,
+    EOpTraceNV,
+    EOpTraceKHR,
     EOpReportIntersection,
     EOpReportIntersection,
-    EOpIgnoreIntersection,
-    EOpTerminateRay,
-    EOpExecuteCallable,
+    EOpIgnoreIntersectionNV,
+    EOpTerminateRayNV,
+    EOpExecuteCallableNV,
+    EOpExecuteCallableKHR,
     EOpWritePackedPrimitiveIndices4x8NV,
     EOpWritePackedPrimitiveIndices4x8NV,
 
 
     //
     //
@@ -1123,6 +1136,8 @@ public:
     virtual TBasicType getBasicType() const { return type.getBasicType(); }
     virtual TBasicType getBasicType() const { return type.getBasicType(); }
     virtual TQualifier& getQualifier() { return type.getQualifier(); }
     virtual TQualifier& getQualifier() { return type.getQualifier(); }
     virtual const TQualifier& getQualifier() const { return type.getQualifier(); }
     virtual const TQualifier& getQualifier() const { return type.getQualifier(); }
+    virtual TArraySizes* getArraySizes() { return type.getArraySizes(); }
+    virtual const TArraySizes* getArraySizes() const { return type.getArraySizes(); }
     virtual void propagatePrecision(TPrecisionQualifier);
     virtual void propagatePrecision(TPrecisionQualifier);
     virtual int getVectorSize() const { return type.getVectorSize(); }
     virtual int getVectorSize() const { return type.getVectorSize(); }
     virtual int getMatrixCols() const { return type.getMatrixCols(); }
     virtual int getMatrixCols() const { return type.getMatrixCols(); }
@@ -1263,15 +1278,15 @@ public:
     // if symbol is initialized as symbol(sym), the memory comes from the pool allocator of sym. If sym comes from
     // if symbol is initialized as symbol(sym), the memory comes from the pool allocator of sym. If sym comes from
     // per process threadPoolAllocator, then it causes increased memory usage per compile
     // per process threadPoolAllocator, then it causes increased memory usage per compile
     // it is essential to use "symbol = sym" to assign to symbol
     // it is essential to use "symbol = sym" to assign to symbol
-    TIntermSymbol(int i, const TString& n, const TType& t)
+    TIntermSymbol(long long i, const TString& n, const TType& t)
         : TIntermTyped(t), id(i),
         : TIntermTyped(t), id(i),
 #ifndef GLSLANG_WEB
 #ifndef GLSLANG_WEB
         flattenSubset(-1),
         flattenSubset(-1),
 #endif
 #endif
         constSubtree(nullptr)
         constSubtree(nullptr)
           { name = n; }
           { name = n; }
-    virtual int getId() const { return id; }
-    virtual void changeId(int i) { id = i; }
+    virtual long long getId() const { return id; }
+    virtual void changeId(long long i) { id = i; }
     virtual const TString& getName() const { return name; }
     virtual const TString& getName() const { return name; }
     virtual void traverse(TIntermTraverser*);
     virtual void traverse(TIntermTraverser*);
     virtual       TIntermSymbol* getAsSymbolNode()       { return this; }
     virtual       TIntermSymbol* getAsSymbolNode()       { return this; }
@@ -1282,15 +1297,17 @@ public:
     TIntermTyped* getConstSubtree() const { return constSubtree; }
     TIntermTyped* getConstSubtree() const { return constSubtree; }
 #ifndef GLSLANG_WEB
 #ifndef GLSLANG_WEB
     void setFlattenSubset(int subset) { flattenSubset = subset; }
     void setFlattenSubset(int subset) { flattenSubset = subset; }
+    virtual const TString& getAccessName() const;
+
     int getFlattenSubset() const { return flattenSubset; } // -1 means full object
     int getFlattenSubset() const { return flattenSubset; } // -1 means full object
 #endif
 #endif
 
 
     // This is meant for cases where a node has already been constructed, and
     // This is meant for cases where a node has already been constructed, and
     // later on, it becomes necessary to switch to a different symbol.
     // later on, it becomes necessary to switch to a different symbol.
-    virtual void switchId(int newId) { id = newId; }
+    virtual void switchId(long long newId) { id = newId; }
 
 
 protected:
 protected:
-    int id;                      // the unique id of the symbol this node represents
+    long long id;                // the unique id of the symbol this node represents
 #ifndef GLSLANG_WEB
 #ifndef GLSLANG_WEB
     int flattenSubset;           // how deeply the flattened object rooted at id has been dereferenced
     int flattenSubset;           // how deeply the flattened object rooted at id has been dereferenced
 #endif
 #endif

+ 4 - 10
src/libraries/glslang/glslang/MachineIndependent/Constant.cpp

@@ -599,17 +599,11 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType)
             newConstArray[i].setDConst(log(unionArray[i].getDConst()));
             newConstArray[i].setDConst(log(unionArray[i].getDConst()));
             break;
             break;
         case EOpExp2:
         case EOpExp2:
-            {
-                const double inv_log2_e = 0.69314718055994530941723212145818;
-                newConstArray[i].setDConst(exp(unionArray[i].getDConst() * inv_log2_e));
-                break;
-            }
+            newConstArray[i].setDConst(exp2(unionArray[i].getDConst()));
+            break;
         case EOpLog2:
         case EOpLog2:
-            {
-                const double log2_e = 1.4426950408889634073599246810019;
-                newConstArray[i].setDConst(log2_e * log(unionArray[i].getDConst()));
-                break;
-            }
+            newConstArray[i].setDConst(log2(unionArray[i].getDConst()));
+            break;
         case EOpSqrt:
         case EOpSqrt:
             newConstArray[i].setDConst(sqrt(unionArray[i].getDConst()));
             newConstArray[i].setDConst(sqrt(unionArray[i].getDConst()));
             break;
             break;

+ 274 - 32
src/libraries/glslang/glslang/MachineIndependent/Initialize.cpp

@@ -509,6 +509,8 @@ TBuiltIns::TBuiltIns()
     prefixes[EbtUint8] = "u8";
     prefixes[EbtUint8] = "u8";
     prefixes[EbtInt16]  = "i16";
     prefixes[EbtInt16]  = "i16";
     prefixes[EbtUint16] = "u16";
     prefixes[EbtUint16] = "u16";
+    prefixes[EbtInt64]  = "i64";
+    prefixes[EbtUint64] = "u64";
 #endif
 #endif
 
 
     postfixes[2] = "2";
     postfixes[2] = "2";
@@ -1631,6 +1633,36 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
                 "uint atomicCounterExchange(atomic_uint, uint);"
                 "uint atomicCounterExchange(atomic_uint, uint);"
                 "uint atomicCounterCompSwap(atomic_uint, uint, uint);"
                 "uint atomicCounterCompSwap(atomic_uint, uint, uint);"
 
 
+                "\n");
+        }
+    }
+    else if (spvVersion.vulkanRelaxed) {
+        //
+        // Atomic counter functions act as aliases to normal atomic functions.
+        // replace definitions to take 'volatile coherent uint' instead of 'atomic_uint'
+        // and map to equivalent non-counter atomic op
+        //
+        if ((profile != EEsProfile && version >= 300) ||
+            (profile == EEsProfile && version >= 310)) {
+            commonBuiltins.append(
+                "uint atomicCounterIncrement(volatile coherent uint);"
+                "uint atomicCounterDecrement(volatile coherent uint);"
+                "uint atomicCounter(volatile coherent uint);"
+
+                "\n");
+        }
+        if (profile != EEsProfile && version >= 460) {
+            commonBuiltins.append(
+                "uint atomicCounterAdd(volatile coherent uint, uint);"
+                "uint atomicCounterSubtract(volatile coherent uint, uint);"
+                "uint atomicCounterMin(volatile coherent uint, uint);"
+                "uint atomicCounterMax(volatile coherent uint, uint);"
+                "uint atomicCounterAnd(volatile coherent uint, uint);"
+                "uint atomicCounterOr(volatile coherent uint, uint);"
+                "uint atomicCounterXor(volatile coherent uint, uint);"
+                "uint atomicCounterExchange(volatile coherent uint, uint);"
+                "uint atomicCounterCompSwap(volatile coherent uint, uint, uint);"
+
                 "\n");
                 "\n");
         }
         }
     }
     }
@@ -4134,7 +4166,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
     }
     }
 #ifndef GLSLANG_WEB
 #ifndef GLSLANG_WEB
     if ((profile != EEsProfile && version >= 420) || esBarrier) {
     if ((profile != EEsProfile && version >= 420) || esBarrier) {
-        if (spvVersion.vulkan == 0) {
+        if (spvVersion.vulkan == 0 || spvVersion.vulkanRelaxed) {
             commonBuiltins.append("void memoryBarrierAtomicCounter();");
             commonBuiltins.append("void memoryBarrierAtomicCounter();");
         }
         }
         commonBuiltins.append("void memoryBarrierImage();");
         commonBuiltins.append("void memoryBarrierImage();");
@@ -4434,9 +4466,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
             "\n");
             "\n");
         stageBuiltins[EShLangAnyHit].append(
         stageBuiltins[EShLangAnyHit].append(
             "void ignoreIntersectionNV();"
             "void ignoreIntersectionNV();"
-            "void ignoreIntersectionEXT();"
             "void terminateRayNV();"
             "void terminateRayNV();"
-            "void terminateRayEXT();"
             "\n");
             "\n");
         stageBuiltins[EShLangClosestHit].append(
         stageBuiltins[EShLangClosestHit].append(
             "void traceNV(accelerationStructureNV,uint,uint,uint,uint,uint,vec3,float,vec3,float,int);"
             "void traceNV(accelerationStructureNV,uint,uint,uint,uint,uint,vec3,float,vec3,float,int);"
@@ -4863,6 +4893,13 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
                 "in int gl_VertexIndex;"
                 "in int gl_VertexIndex;"
                 "in int gl_InstanceIndex;"
                 "in int gl_InstanceIndex;"
                 );
                 );
+
+        if (spvVersion.vulkan > 0 && version >= 140 && spvVersion.vulkanRelaxed)
+            stageBuiltins[EShLangVertex].append(
+                "in int gl_VertexID;"         // declare with 'in' qualifier
+                "in int gl_InstanceID;"
+                );
+
         if (version >= 440) {
         if (version >= 440) {
             stageBuiltins[EShLangVertex].append(
             stageBuiltins[EShLangVertex].append(
                 "in int gl_BaseVertexARB;"
                 "in int gl_BaseVertexARB;"
@@ -4900,7 +4937,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
                 "mediump float gl_PointSize;" // needs qualifier fixed later
                 "mediump float gl_PointSize;" // needs qualifier fixed later
                 );
                 );
         } else {
         } else {
-            if (spvVersion.vulkan == 0)
+            if (spvVersion.vulkan == 0 || spvVersion.vulkanRelaxed)
                 stageBuiltins[EShLangVertex].append(
                 stageBuiltins[EShLangVertex].append(
                     "in highp int gl_VertexID;"      // needs qualifier fixed later
                     "in highp int gl_VertexID;"      // needs qualifier fixed later
                     "in highp int gl_InstanceID;"    // needs qualifier fixed later
                     "in highp int gl_InstanceID;"    // needs qualifier fixed later
@@ -4943,6 +4980,11 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
             "\n");
             "\n");
     }
     }
 
 
+    if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 310)) {
+        stageBuiltins[EShLangVertex].append(
+            "out highp int gl_PrimitiveShadingRateEXT;" // GL_EXT_fragment_shading_rate
+            "\n");
+    }
 
 
     //============================================================================
     //============================================================================
     //
     //
@@ -5056,6 +5098,12 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
             "\n");
             "\n");
     }
     }
 
 
+    if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 310)) {
+        stageBuiltins[EShLangGeometry].append(
+            "out highp int gl_PrimitiveShadingRateEXT;" // GL_EXT_fragment_shading_rate
+            "\n");
+    }
+
     //============================================================================
     //============================================================================
     //
     //
     // Define the interface to the tessellation control shader.
     // Define the interface to the tessellation control shader.
@@ -5353,6 +5401,11 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
                 "in vec3 gl_BaryCoordNoPerspNV;"
                 "in vec3 gl_BaryCoordNoPerspNV;"
                 );
                 );
 
 
+        if (version >= 450)
+            stageBuiltins[EShLangFragment].append(
+                "flat in int gl_ShadingRateEXT;" // GL_EXT_fragment_shading_rate
+            );
+
     } else {
     } else {
         // ES profile
         // ES profile
 
 
@@ -5411,6 +5464,10 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
                 "in vec3 gl_BaryCoordNV;"
                 "in vec3 gl_BaryCoordNV;"
                 "in vec3 gl_BaryCoordNoPerspNV;"
                 "in vec3 gl_BaryCoordNoPerspNV;"
                 );
                 );
+        if (version >= 310)
+            stageBuiltins[EShLangFragment].append(
+                "flat in highp int gl_ShadingRateEXT;" // GL_EXT_fragment_shading_rate
+            );
     }
     }
 #endif
 #endif
 
 
@@ -5429,6 +5486,12 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
             "\n");
             "\n");
     }
     }
 
 
+    if (version >= 300 /* both ES and non-ES */) {
+        stageBuiltins[EShLangFragment].append(
+            "flat in highp uint gl_ViewID_OVR;"     // GL_OVR_multiview, GL_OVR_multiview2
+            "\n");
+    }
+
 #ifndef GLSLANG_ANGLE
 #ifndef GLSLANG_ANGLE
     // GL_ARB_shader_ballot
     // GL_ARB_shader_ballot
     if (profile != EEsProfile && version >= 450) {
     if (profile != EEsProfile && version >= 450) {
@@ -5441,6 +5504,15 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
             "in uint64_t gl_SubGroupLeMaskARB;"
             "in uint64_t gl_SubGroupLeMaskARB;"
             "in uint64_t gl_SubGroupLtMaskARB;"
             "in uint64_t gl_SubGroupLtMaskARB;"
             "\n";
             "\n";
+        const char* rtBallotDecls =
+            "uniform volatile uint gl_SubGroupSizeARB;"
+            "in volatile uint     gl_SubGroupInvocationARB;"
+            "in volatile uint64_t gl_SubGroupEqMaskARB;"
+            "in volatile uint64_t gl_SubGroupGeMaskARB;"
+            "in volatile uint64_t gl_SubGroupGtMaskARB;"
+            "in volatile uint64_t gl_SubGroupLeMaskARB;"
+            "in volatile uint64_t gl_SubGroupLtMaskARB;"
+            "\n";
         const char* fragmentBallotDecls =
         const char* fragmentBallotDecls =
             "uniform uint gl_SubGroupSizeARB;"
             "uniform uint gl_SubGroupSizeARB;"
             "flat in uint     gl_SubGroupInvocationARB;"
             "flat in uint     gl_SubGroupInvocationARB;"
@@ -5458,6 +5530,13 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
         stageBuiltins[EShLangFragment]      .append(fragmentBallotDecls);
         stageBuiltins[EShLangFragment]      .append(fragmentBallotDecls);
         stageBuiltins[EShLangMeshNV]        .append(ballotDecls);
         stageBuiltins[EShLangMeshNV]        .append(ballotDecls);
         stageBuiltins[EShLangTaskNV]        .append(ballotDecls);
         stageBuiltins[EShLangTaskNV]        .append(ballotDecls);
+        stageBuiltins[EShLangRayGen]        .append(rtBallotDecls);
+        stageBuiltins[EShLangIntersect]     .append(rtBallotDecls);
+        // No volatile qualifier on these builtins in any-hit
+        stageBuiltins[EShLangAnyHit]        .append(ballotDecls);
+        stageBuiltins[EShLangClosestHit]    .append(rtBallotDecls);
+        stageBuiltins[EShLangMiss]          .append(rtBallotDecls);
+        stageBuiltins[EShLangCallable]      .append(rtBallotDecls);
     }
     }
 
 
     // GL_KHR_shader_subgroup
     // GL_KHR_shader_subgroup
@@ -5495,6 +5574,21 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
             "in highp   uint  gl_NumSubgroups;"
             "in highp   uint  gl_NumSubgroups;"
             "in highp   uint  gl_SubgroupID;"
             "in highp   uint  gl_SubgroupID;"
             "\n";
             "\n";
+        // These builtins are volatile for RT stages
+        const char* rtSubgroupDecls =
+            "in mediump volatile uint  gl_SubgroupSize;"
+            "in mediump volatile uint  gl_SubgroupInvocationID;"
+            "in highp   volatile uvec4 gl_SubgroupEqMask;"
+            "in highp   volatile uvec4 gl_SubgroupGeMask;"
+            "in highp   volatile uvec4 gl_SubgroupGtMask;"
+            "in highp   volatile uvec4 gl_SubgroupLeMask;"
+            "in highp   volatile uvec4 gl_SubgroupLtMask;"
+            // GL_NV_shader_sm_builtins
+            "in highp    uint  gl_WarpsPerSMNV;"
+            "in highp    uint  gl_SMCountNV;"
+            "in highp volatile uint  gl_WarpIDNV;"
+            "in highp volatile uint  gl_SMIDNV;"
+            "\n";
 
 
         stageBuiltins[EShLangVertex]        .append(subgroupDecls);
         stageBuiltins[EShLangVertex]        .append(subgroupDecls);
         stageBuiltins[EShLangTessControl]   .append(subgroupDecls);
         stageBuiltins[EShLangTessControl]   .append(subgroupDecls);
@@ -5507,12 +5601,13 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
         stageBuiltins[EShLangMeshNV]        .append(computeSubgroupDecls);
         stageBuiltins[EShLangMeshNV]        .append(computeSubgroupDecls);
         stageBuiltins[EShLangTaskNV]        .append(subgroupDecls);
         stageBuiltins[EShLangTaskNV]        .append(subgroupDecls);
         stageBuiltins[EShLangTaskNV]        .append(computeSubgroupDecls);
         stageBuiltins[EShLangTaskNV]        .append(computeSubgroupDecls);
-        stageBuiltins[EShLangRayGen]        .append(subgroupDecls);
-        stageBuiltins[EShLangIntersect]     .append(subgroupDecls);
+        stageBuiltins[EShLangRayGen]        .append(rtSubgroupDecls);
+        stageBuiltins[EShLangIntersect]     .append(rtSubgroupDecls);
+        // No volatile qualifier on these builtins in any-hit
         stageBuiltins[EShLangAnyHit]        .append(subgroupDecls);
         stageBuiltins[EShLangAnyHit]        .append(subgroupDecls);
-        stageBuiltins[EShLangClosestHit]    .append(subgroupDecls);
-        stageBuiltins[EShLangMiss]          .append(subgroupDecls);
-        stageBuiltins[EShLangCallable]      .append(subgroupDecls);
+        stageBuiltins[EShLangClosestHit]    .append(rtSubgroupDecls);
+        stageBuiltins[EShLangMiss]          .append(rtSubgroupDecls);
+        stageBuiltins[EShLangCallable]      .append(rtSubgroupDecls);
     }
     }
 
 
     // GL_NV_ray_tracing/GL_EXT_ray_tracing
     // GL_NV_ray_tracing/GL_EXT_ray_tracing
@@ -5580,7 +5675,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
             "in    float  gl_RayTminNV;"
             "in    float  gl_RayTminNV;"
             "in    float  gl_RayTminEXT;"
             "in    float  gl_RayTminEXT;"
             "in    float  gl_RayTmaxNV;"
             "in    float  gl_RayTmaxNV;"
-            "in    float  gl_RayTmaxEXT;"
+            "in volatile float gl_RayTmaxEXT;"
             "in    mat4x3 gl_ObjectToWorldNV;"
             "in    mat4x3 gl_ObjectToWorldNV;"
             "in    mat4x3 gl_ObjectToWorldEXT;"
             "in    mat4x3 gl_ObjectToWorldEXT;"
             "in    mat3x4 gl_ObjectToWorld3x4EXT;"
             "in    mat3x4 gl_ObjectToWorld3x4EXT;"
@@ -5700,13 +5795,57 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
         commonBuiltins.append("const int gl_StorageSemanticsOutput   = 0x1000;\n");
         commonBuiltins.append("const int gl_StorageSemanticsOutput   = 0x1000;\n");
     }
     }
 
 
-#endif // !GLSLANG_ANGLE
-
-    if (version >= 300 /* both ES and non-ES */) {
-        stageBuiltins[EShLangFragment].append(
-            "flat in highp uint gl_ViewID_OVR;"     // GL_OVR_multiview, GL_OVR_multiview2
-            "\n");
+    // Adding these to common built-ins triggers an assert due to a memory corruption in related code when testing
+    // So instead add to each stage individually, avoiding the GLSLang bug
+    if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 310)) {
+        for (int stage=EShLangVertex; stage<EShLangCount; stage++)
+        {
+            stageBuiltins[static_cast<EShLanguage>(stage)].append("const highp int gl_ShadingRateFlag2VerticalPixelsEXT       = 1;\n");
+            stageBuiltins[static_cast<EShLanguage>(stage)].append("const highp int gl_ShadingRateFlag4VerticalPixelsEXT       = 2;\n");
+            stageBuiltins[static_cast<EShLanguage>(stage)].append("const highp int gl_ShadingRateFlag2HorizontalPixelsEXT     = 4;\n");
+            stageBuiltins[static_cast<EShLanguage>(stage)].append("const highp int gl_ShadingRateFlag4HorizontalPixelsEXT     = 8;\n");
+        }
+    }
+    
+    // GL_EXT_shader_image_int64
+    if ((profile != EEsProfile && version >= 420) ||
+        (profile == EEsProfile && version >= 310)) {
+            
+        const TBasicType bTypes[] = { EbtInt64, EbtUint64 };
+        for (int ms = 0; ms <= 1; ++ms) { // loop over "bool" multisample or not
+            for (int arrayed = 0; arrayed <= 1; ++arrayed) { // loop over "bool" arrayed or not
+                for (int dim = Esd1D; dim < EsdSubpass; ++dim) { // 1D, ..., buffer
+                    if ((dim == Esd1D || dim == EsdRect) && profile == EEsProfile)
+                        continue;
+                    
+                    if ((dim == Esd3D || dim == EsdRect || dim == EsdBuffer) && arrayed)
+                        continue;
+                    
+                    if (dim != Esd2D && ms)
+                        continue;
+                    
+                    // Loop over the bTypes
+                    for (size_t bType = 0; bType < sizeof(bTypes)/sizeof(TBasicType); ++bType) {
+                        //
+                        // Now, make all the function prototypes for the type we just built...
+                        //
+                        TSampler sampler;
+                    
+                        sampler.setImage(bTypes[bType], (TSamplerDim)dim, arrayed ? true : false,
+                                                                          false,
+                                                                          ms      ? true : false);
+
+                        TString typeName = sampler.getString();
+
+                        addQueryFunctions(sampler, typeName, version, profile);
+                        addImageFunctions(sampler, typeName, version, profile);
+                    }
+                }
+            }
+        }
     }
     }
+#endif // !GLSLANG_ANGLE
+    
 #endif // !GLSLANG_WEB
 #endif // !GLSLANG_WEB
 
 
     // printf("%s\n", commonBuiltins.c_str());
     // printf("%s\n", commonBuiltins.c_str());
@@ -5803,7 +5942,6 @@ void TBuiltIns::add2ndGenerationSamplingImaging(int version, EProfile profile, c
 #endif
 #endif
                             if (shadow && (bTypes[bType] == EbtInt || bTypes[bType] == EbtUint))
                             if (shadow && (bTypes[bType] == EbtInt || bTypes[bType] == EbtUint))
                                 continue;
                                 continue;
-
                             //
                             //
                             // Now, make all the function prototypes for the type we just built...
                             // Now, make all the function prototypes for the type we just built...
                             //
                             //
@@ -6028,8 +6166,16 @@ void TBuiltIns::addImageFunctions(TSampler sampler, const TString& typeName, int
 
 
     if ( profile != EEsProfile ||
     if ( profile != EEsProfile ||
         (profile == EEsProfile && version >= 310)) {
         (profile == EEsProfile && version >= 310)) {
-        if (sampler.type == EbtInt || sampler.type == EbtUint) {
-            const char* dataType = sampler.type == EbtInt ? "highp int" : "highp uint";
+        if (sampler.type == EbtInt || sampler.type == EbtUint || sampler.type == EbtInt64 || sampler.type == EbtUint64 ) {
+            
+            const char* dataType;
+            switch (sampler.type) {
+                case(EbtInt): dataType = "highp int"; break;
+                case(EbtUint): dataType = "highp uint"; break;
+                case(EbtInt64): dataType = "highp int64_t"; break;
+                case(EbtUint64): dataType = "highp uint64_t"; break;
+                default: dataType = "";
+            }
 
 
             const int numBuiltins = 7;
             const int numBuiltins = 7;
 
 
@@ -6444,7 +6590,7 @@ void TBuiltIns::addSamplingFunctions(TSampler sampler, const TString& typeName,
                                             s.append(");\n");
                                             s.append(");\n");
 
 
                                             // Add to the per-language set of built-ins
                                             // Add to the per-language set of built-ins
-                                            if (bias || lodClamp != 0) {
+                                            if (!grad && (bias || lodClamp != 0)) {
                                                 stageBuiltins[EShLangFragment].append(s);
                                                 stageBuiltins[EShLangFragment].append(s);
                                                 stageBuiltins[EShLangCompute].append(s);
                                                 stageBuiltins[EShLangCompute].append(s);
                                             } else
                                             } else
@@ -7342,6 +7488,12 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
             SpecialQualifier("gl_InstanceID", EvqInstanceId, EbvInstanceId, symbolTable);
             SpecialQualifier("gl_InstanceID", EvqInstanceId, EbvInstanceId, symbolTable);
         }
         }
 
 
+        if (spvVersion.vulkan > 0 && spvVersion.vulkanRelaxed) {
+            // treat these built-ins as aliases of VertexIndex and InstanceIndex
+            BuiltInVariable("gl_VertexID", EbvVertexIndex, symbolTable);
+            BuiltInVariable("gl_InstanceID", EbvInstanceIndex, symbolTable);
+        }
+
         if (profile != EEsProfile) {
         if (profile != EEsProfile) {
             if (version >= 440) {
             if (version >= 440) {
                 symbolTable.setVariableExtensions("gl_BaseVertexARB",   1, &E_GL_ARB_shader_draw_parameters);
                 symbolTable.setVariableExtensions("gl_BaseVertexARB",   1, &E_GL_ARB_shader_draw_parameters);
@@ -7665,6 +7817,20 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
             BuiltInVariable("gl_WarpIDNV",              EbvWarpID,          symbolTable);
             BuiltInVariable("gl_WarpIDNV",              EbvWarpID,          symbolTable);
             BuiltInVariable("gl_SMIDNV",                EbvSMID,            symbolTable);
             BuiltInVariable("gl_SMIDNV",                EbvSMID,            symbolTable);
         }
         }
+
+		if (language == EShLangGeometry || language == EShLangVertex) {
+			if ((profile == EEsProfile && version >= 310) ||
+				(profile != EEsProfile && version >= 450)) {
+				symbolTable.setVariableExtensions("gl_PrimitiveShadingRateEXT", 1, &E_GL_EXT_fragment_shading_rate);
+				BuiltInVariable("gl_PrimitiveShadingRateEXT", EbvPrimitiveShadingRateKHR, symbolTable);
+
+				symbolTable.setVariableExtensions("gl_ShadingRateFlag2VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
+				symbolTable.setVariableExtensions("gl_ShadingRateFlag4VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
+				symbolTable.setVariableExtensions("gl_ShadingRateFlag2HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
+				symbolTable.setVariableExtensions("gl_ShadingRateFlag4HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
+			}
+		}
+
 #endif // !GLSLANG_WEB
 #endif // !GLSLANG_WEB
         break;
         break;
 
 
@@ -8192,6 +8358,17 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
         }
         }
 
 
         symbolTable.setFunctionExtensions("helperInvocationEXT",            1, &E_GL_EXT_demote_to_helper_invocation);
         symbolTable.setFunctionExtensions("helperInvocationEXT",            1, &E_GL_EXT_demote_to_helper_invocation);
+
+        if ((profile == EEsProfile && version >= 310) ||
+            (profile != EEsProfile && version >= 450)) {
+            symbolTable.setVariableExtensions("gl_ShadingRateEXT", 1, &E_GL_EXT_fragment_shading_rate);
+            BuiltInVariable("gl_ShadingRateEXT", EbvShadingRateKHR, symbolTable);
+
+            symbolTable.setVariableExtensions("gl_ShadingRateFlag2VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
+            symbolTable.setVariableExtensions("gl_ShadingRateFlag4VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
+            symbolTable.setVariableExtensions("gl_ShadingRateFlag2HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
+            symbolTable.setVariableExtensions("gl_ShadingRateFlag4HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
+        }
 #endif // !GLSLANG_WEB
 #endif // !GLSLANG_WEB
         break;
         break;
 
 
@@ -8324,6 +8501,14 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
             symbolTable.setFunctionExtensions("dFdyCoarse",             1, &E_GL_NV_compute_shader_derivatives);
             symbolTable.setFunctionExtensions("dFdyCoarse",             1, &E_GL_NV_compute_shader_derivatives);
             symbolTable.setFunctionExtensions("fwidthCoarse",           1, &E_GL_NV_compute_shader_derivatives);
             symbolTable.setFunctionExtensions("fwidthCoarse",           1, &E_GL_NV_compute_shader_derivatives);
         }
         }
+
+        if ((profile == EEsProfile && version >= 310) ||
+            (profile != EEsProfile && version >= 450)) {
+            symbolTable.setVariableExtensions("gl_ShadingRateFlag2VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
+            symbolTable.setVariableExtensions("gl_ShadingRateFlag4VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
+            symbolTable.setVariableExtensions("gl_ShadingRateFlag2HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
+            symbolTable.setVariableExtensions("gl_ShadingRateFlag4HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
+        }
 #endif // !GLSLANG_WEB
 #endif // !GLSLANG_WEB
         break;
         break;
 
 
@@ -8378,9 +8563,7 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
             symbolTable.setFunctionExtensions("reportIntersectionNV", 1, &E_GL_NV_ray_tracing);
             symbolTable.setFunctionExtensions("reportIntersectionNV", 1, &E_GL_NV_ray_tracing);
             symbolTable.setFunctionExtensions("reportIntersectionEXT", 1, &E_GL_EXT_ray_tracing);
             symbolTable.setFunctionExtensions("reportIntersectionEXT", 1, &E_GL_EXT_ray_tracing);
             symbolTable.setFunctionExtensions("ignoreIntersectionNV", 1, &E_GL_NV_ray_tracing);
             symbolTable.setFunctionExtensions("ignoreIntersectionNV", 1, &E_GL_NV_ray_tracing);
-            symbolTable.setFunctionExtensions("ignoreIntersectionEXT", 1, &E_GL_EXT_ray_tracing);
             symbolTable.setFunctionExtensions("terminateRayNV", 1, &E_GL_NV_ray_tracing);
             symbolTable.setFunctionExtensions("terminateRayNV", 1, &E_GL_NV_ray_tracing);
-            symbolTable.setFunctionExtensions("terminateRayEXT", 1, &E_GL_EXT_ray_tracing);
             symbolTable.setFunctionExtensions("executeCallableNV", 1, &E_GL_NV_ray_tracing);
             symbolTable.setFunctionExtensions("executeCallableNV", 1, &E_GL_NV_ray_tracing);
             symbolTable.setFunctionExtensions("executeCallableEXT", 1, &E_GL_EXT_ray_tracing);
             symbolTable.setFunctionExtensions("executeCallableEXT", 1, &E_GL_EXT_ray_tracing);
 
 
@@ -8473,6 +8656,13 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
             BuiltInVariable("gl_WarpIDNV",              EbvWarpID,          symbolTable);
             BuiltInVariable("gl_WarpIDNV",              EbvWarpID,          symbolTable);
             BuiltInVariable("gl_SMIDNV",                EbvSMID,            symbolTable);
             BuiltInVariable("gl_SMIDNV",                EbvSMID,            symbolTable);
         }
         }
+        if ((profile == EEsProfile && version >= 310) ||
+            (profile != EEsProfile && version >= 450)) {
+            symbolTable.setVariableExtensions("gl_ShadingRateFlag2VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
+            symbolTable.setVariableExtensions("gl_ShadingRateFlag4VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
+            symbolTable.setVariableExtensions("gl_ShadingRateFlag2HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
+            symbolTable.setVariableExtensions("gl_ShadingRateFlag4HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
+        }
         break;
         break;
 
 
     case EShLangMeshNV:
     case EShLangMeshNV:
@@ -8617,6 +8807,14 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
             BuiltInVariable("gl_WarpIDNV",              EbvWarpID,          symbolTable);
             BuiltInVariable("gl_WarpIDNV",              EbvWarpID,          symbolTable);
             BuiltInVariable("gl_SMIDNV",                EbvSMID,            symbolTable);
             BuiltInVariable("gl_SMIDNV",                EbvSMID,            symbolTable);
         }
         }
+
+        if ((profile == EEsProfile && version >= 310) ||
+            (profile != EEsProfile && version >= 450)) {
+            symbolTable.setVariableExtensions("gl_ShadingRateFlag2VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
+            symbolTable.setVariableExtensions("gl_ShadingRateFlag4VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
+            symbolTable.setVariableExtensions("gl_ShadingRateFlag2HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
+            symbolTable.setVariableExtensions("gl_ShadingRateFlag4HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
+        }
         break;
         break;
 
 
     case EShLangTaskNV:
     case EShLangTaskNV:
@@ -8717,6 +8915,13 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
             BuiltInVariable("gl_WarpIDNV",              EbvWarpID,          symbolTable);
             BuiltInVariable("gl_WarpIDNV",              EbvWarpID,          symbolTable);
             BuiltInVariable("gl_SMIDNV",                EbvSMID,            symbolTable);
             BuiltInVariable("gl_SMIDNV",                EbvSMID,            symbolTable);
         }
         }
+        if ((profile == EEsProfile && version >= 310) ||
+            (profile != EEsProfile && version >= 450)) {
+            symbolTable.setVariableExtensions("gl_ShadingRateFlag2VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
+            symbolTable.setVariableExtensions("gl_ShadingRateFlag4VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
+            symbolTable.setVariableExtensions("gl_ShadingRateFlag2HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
+            symbolTable.setVariableExtensions("gl_ShadingRateFlag4HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
+        }
         break;
         break;
 #endif
 #endif
 
 
@@ -8786,6 +8991,14 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
     symbolTable.relateToOperator("memoryBarrierAtomicCounter", EOpMemoryBarrierAtomicCounter);
     symbolTable.relateToOperator("memoryBarrierAtomicCounter", EOpMemoryBarrierAtomicCounter);
     symbolTable.relateToOperator("memoryBarrierImage",         EOpMemoryBarrierImage);
     symbolTable.relateToOperator("memoryBarrierImage",         EOpMemoryBarrierImage);
 
 
+    if (spvVersion.vulkanRelaxed) {
+        //
+        // functions signature have been replaced to take uint operations on buffer variables
+        // remap atomic counter functions to atomic operations
+        //
+        symbolTable.relateToOperator("memoryBarrierAtomicCounter", EOpMemoryBarrierBuffer);
+    }
+
     symbolTable.relateToOperator("atomicLoad",     EOpAtomicLoad);
     symbolTable.relateToOperator("atomicLoad",     EOpAtomicLoad);
     symbolTable.relateToOperator("atomicStore",    EOpAtomicStore);
     symbolTable.relateToOperator("atomicStore",    EOpAtomicStore);
 
 
@@ -8793,6 +9006,20 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
     symbolTable.relateToOperator("atomicCounterDecrement", EOpAtomicCounterDecrement);
     symbolTable.relateToOperator("atomicCounterDecrement", EOpAtomicCounterDecrement);
     symbolTable.relateToOperator("atomicCounter",          EOpAtomicCounter);
     symbolTable.relateToOperator("atomicCounter",          EOpAtomicCounter);
 
 
+    if (spvVersion.vulkanRelaxed) {
+        //
+        // functions signature have been replaced to take uint operations
+        // remap atomic counter functions to atomic operations
+        //
+        // these atomic counter functions do not match signatures of glsl
+        // atomic functions, so they will be remapped to semantically
+        // equivalent functions in the parser
+        //
+        symbolTable.relateToOperator("atomicCounterIncrement", EOpNull);
+        symbolTable.relateToOperator("atomicCounterDecrement", EOpNull);
+        symbolTable.relateToOperator("atomicCounter", EOpNull);
+    }
+
     symbolTable.relateToOperator("clockARB",     EOpReadClockSubgroupKHR);
     symbolTable.relateToOperator("clockARB",     EOpReadClockSubgroupKHR);
     symbolTable.relateToOperator("clock2x32ARB", EOpReadClockSubgroupKHR);
     symbolTable.relateToOperator("clock2x32ARB", EOpReadClockSubgroupKHR);
 
 
@@ -8811,6 +9038,23 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
         symbolTable.relateToOperator("atomicCounterCompSwap", EOpAtomicCounterCompSwap);
         symbolTable.relateToOperator("atomicCounterCompSwap", EOpAtomicCounterCompSwap);
     }
     }
 
 
+    if (spvVersion.vulkanRelaxed) {
+        //
+        // functions signature have been replaced to take 'uint' instead of 'atomic_uint'
+        // remap atomic counter functions to non-counter atomic ops so
+        // functions act as aliases to non-counter atomic ops
+        //
+        symbolTable.relateToOperator("atomicCounterAdd", EOpAtomicAdd);
+        symbolTable.relateToOperator("atomicCounterSubtract", EOpAtomicSubtract);
+        symbolTable.relateToOperator("atomicCounterMin", EOpAtomicMin);
+        symbolTable.relateToOperator("atomicCounterMax", EOpAtomicMax);
+        symbolTable.relateToOperator("atomicCounterAnd", EOpAtomicAnd);
+        symbolTable.relateToOperator("atomicCounterOr", EOpAtomicOr);
+        symbolTable.relateToOperator("atomicCounterXor", EOpAtomicXor);
+        symbolTable.relateToOperator("atomicCounterExchange", EOpAtomicExchange);
+        symbolTable.relateToOperator("atomicCounterCompSwap", EOpAtomicCompSwap);
+    }
+
     symbolTable.relateToOperator("fma",               EOpFma);
     symbolTable.relateToOperator("fma",               EOpFma);
     symbolTable.relateToOperator("frexp",             EOpFrexp);
     symbolTable.relateToOperator("frexp",             EOpFrexp);
     symbolTable.relateToOperator("ldexp",             EOpLdexp);
     symbolTable.relateToOperator("ldexp",             EOpLdexp);
@@ -9197,10 +9441,10 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
     case EShLangClosestHit:
     case EShLangClosestHit:
     case EShLangMiss:
     case EShLangMiss:
         if (profile != EEsProfile && version >= 460) {
         if (profile != EEsProfile && version >= 460) {
-            symbolTable.relateToOperator("traceNV", EOpTrace);
-            symbolTable.relateToOperator("traceRayEXT", EOpTrace);
-            symbolTable.relateToOperator("executeCallableNV", EOpExecuteCallable);
-            symbolTable.relateToOperator("executeCallableEXT", EOpExecuteCallable);
+            symbolTable.relateToOperator("traceNV", EOpTraceNV);
+            symbolTable.relateToOperator("traceRayEXT", EOpTraceKHR);
+            symbolTable.relateToOperator("executeCallableNV", EOpExecuteCallableNV);
+            symbolTable.relateToOperator("executeCallableEXT", EOpExecuteCallableKHR);
         }
         }
         break;
         break;
     case EShLangIntersect:
     case EShLangIntersect:
@@ -9211,16 +9455,14 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
         break;
         break;
     case EShLangAnyHit:
     case EShLangAnyHit:
         if (profile != EEsProfile && version >= 460) {
         if (profile != EEsProfile && version >= 460) {
-            symbolTable.relateToOperator("ignoreIntersectionNV", EOpIgnoreIntersection);
-            symbolTable.relateToOperator("ignoreIntersectionEXT", EOpIgnoreIntersection);
-            symbolTable.relateToOperator("terminateRayNV", EOpTerminateRay);
-            symbolTable.relateToOperator("terminateRayEXT", EOpTerminateRay);
+            symbolTable.relateToOperator("ignoreIntersectionNV", EOpIgnoreIntersectionNV);
+            symbolTable.relateToOperator("terminateRayNV", EOpTerminateRayNV);
         }
         }
         break;
         break;
     case EShLangCallable:
     case EShLangCallable:
         if (profile != EEsProfile && version >= 460) {
         if (profile != EEsProfile && version >= 460) {
-            symbolTable.relateToOperator("executeCallableNV", EOpExecuteCallable);
-            symbolTable.relateToOperator("executeCallableEXT", EOpExecuteCallable);
+            symbolTable.relateToOperator("executeCallableNV", EOpExecuteCallableNV);
+            symbolTable.relateToOperator("executeCallableEXT", EOpExecuteCallableKHR);
         }
         }
         break;
         break;
     case EShLangMeshNV:
     case EShLangMeshNV:

+ 7 - 0
src/libraries/glslang/glslang/MachineIndependent/IntermTraverse.cpp

@@ -71,6 +71,13 @@ void TIntermConstantUnion::traverse(TIntermTraverser *it)
     it->visitConstantUnion(this);
     it->visitConstantUnion(this);
 }
 }
 
 
+const TString& TIntermSymbol::getAccessName() const {
+    if (getBasicType() == EbtBlock)
+        return getType().getTypeName();
+    else
+        return getName();
+}
+
 //
 //
 // Traverse a binary node.
 // Traverse a binary node.
 //
 //

+ 16 - 7
src/libraries/glslang/glslang/MachineIndependent/Intermediate.cpp

@@ -65,7 +65,7 @@ namespace glslang {
 // Returns the added node.
 // Returns the added node.
 //
 //
 
 
-TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TConstUnionArray& constArray,
+TIntermSymbol* TIntermediate::addSymbol(long long id, const TString& name, const TType& type, const TConstUnionArray& constArray,
                                         TIntermTyped* constSubtree, const TSourceLoc& loc)
                                         TIntermTyped* constSubtree, const TSourceLoc& loc)
 {
 {
     TIntermSymbol* node = new TIntermSymbol(id, name, type);
     TIntermSymbol* node = new TIntermSymbol(id, name, type);
@@ -2298,6 +2298,10 @@ TOperator TIntermediate::mapTypeToConstructorOp(const TType& type) const
     case EbtReference:
     case EbtReference:
         op = EOpConstructReference;
         op = EOpConstructReference;
         break;
         break;
+
+    case EbtAccStruct:
+        op = EOpConstructAccStruct;
+        break;
 #endif
 #endif
     default:
     default:
         break;
         break;
@@ -2866,7 +2870,7 @@ void TIntermediate::addToCallGraph(TInfoSink& /*infoSink*/, const TString& calle
             return;
             return;
     }
     }
 
 
-    callGraph.push_front(TCall(caller, callee));
+    callGraph.emplace_front(caller, callee);
 }
 }
 
 
 //
 //
@@ -3772,11 +3776,16 @@ void TIntermBinary::updatePrecision()
 {
 {
      if (getBasicType() == EbtInt || getBasicType() == EbtUint ||
      if (getBasicType() == EbtInt || getBasicType() == EbtUint ||
          getBasicType() == EbtFloat || getBasicType() == EbtFloat16) {
          getBasicType() == EbtFloat || getBasicType() == EbtFloat16) {
-        getQualifier().precision = std::max(right->getQualifier().precision, left->getQualifier().precision);
-        if (getQualifier().precision != EpqNone) {
-            left->propagatePrecision(getQualifier().precision);
-            right->propagatePrecision(getQualifier().precision);
-        }
+       if (op == EOpRightShift || op == EOpLeftShift) {
+         // For shifts get precision from left side only and thus no need to propagate
+         getQualifier().precision = left->getQualifier().precision;
+       } else {
+         getQualifier().precision = std::max(right->getQualifier().precision, left->getQualifier().precision);
+         if (getQualifier().precision != EpqNone) {
+           left->propagatePrecision(getQualifier().precision);
+           right->propagatePrecision(getQualifier().precision);
+         }
+       }
     }
     }
 }
 }
 
 

+ 117 - 36
src/libraries/glslang/glslang/MachineIndependent/ParseContextBase.cpp

@@ -127,22 +127,6 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op,
 {
 {
     TIntermBinary* binaryNode = node->getAsBinaryNode();
     TIntermBinary* binaryNode = node->getAsBinaryNode();
 
 
-    if (binaryNode) {
-        switch(binaryNode->getOp()) {
-        case EOpIndexDirect:
-        case EOpIndexIndirect:     // fall through
-        case EOpIndexDirectStruct: // fall through
-        case EOpVectorSwizzle:
-        case EOpMatrixSwizzle:
-            return lValueErrorCheck(loc, op, binaryNode->getLeft());
-        default:
-            break;
-        }
-        error(loc, " l-value required", op, "", "");
-
-        return true;
-    }
-
     const char* symbol = nullptr;
     const char* symbol = nullptr;
     TIntermSymbol* symNode = node->getAsSymbolNode();
     TIntermSymbol* symNode = node->getAsSymbolNode();
     if (symNode != nullptr)
     if (symNode != nullptr)
@@ -203,15 +187,40 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op,
     // Everything else is okay, no error.
     // Everything else is okay, no error.
     //
     //
     if (message == nullptr)
     if (message == nullptr)
+    {
+        if (binaryNode) {
+            switch (binaryNode->getOp()) {
+            case EOpIndexDirect:
+            case EOpIndexIndirect:     // fall through
+            case EOpIndexDirectStruct: // fall through
+            case EOpVectorSwizzle:
+            case EOpMatrixSwizzle:
+                return lValueErrorCheck(loc, op, binaryNode->getLeft());
+            default:
+                break;
+            }
+            error(loc, " l-value required", op, "", "");
+
+            return true;
+        }
         return false;
         return false;
+    }
 
 
     //
     //
     // If we get here, we have an error and a message.
     // If we get here, we have an error and a message.
     //
     //
+    const TIntermTyped* leftMostTypeNode = TIntermediate::findLValueBase(node, true);
+
     if (symNode)
     if (symNode)
         error(loc, " l-value required", op, "\"%s\" (%s)", symbol, message);
         error(loc, " l-value required", op, "\"%s\" (%s)", symbol, message);
     else
     else
-        error(loc, " l-value required", op, "(%s)", message);
+        if (binaryNode && binaryNode->getAsOperator()->getOp() == EOpIndexDirectStruct)
+            if(IsAnonymous(leftMostTypeNode->getAsSymbolNode()->getName()))
+                error(loc, " l-value required", op, "\"%s\" (%s)", leftMostTypeNode->getAsSymbolNode()->getAccessName().c_str(), message);
+            else
+                error(loc, " l-value required", op, "\"%s\" (%s)", leftMostTypeNode->getAsSymbolNode()->getName().c_str(), message);
+        else
+            error(loc, " l-value required", op, "(%s)", message);
 
 
     return true;
     return true;
 }
 }
@@ -219,28 +228,41 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op,
 // Test for and give an error if the node can't be read from.
 // Test for and give an error if the node can't be read from.
 void TParseContextBase::rValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node)
 void TParseContextBase::rValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node)
 {
 {
+    TIntermBinary* binaryNode = node->getAsBinaryNode();
+    const TIntermSymbol* symNode = node->getAsSymbolNode();
+
     if (! node)
     if (! node)
         return;
         return;
 
 
-    TIntermBinary* binaryNode = node->getAsBinaryNode();
-    if (binaryNode) {
-        switch(binaryNode->getOp()) {
-        case EOpIndexDirect:
-        case EOpIndexIndirect:
-        case EOpIndexDirectStruct:
-        case EOpVectorSwizzle:
-        case EOpMatrixSwizzle:
-            rValueErrorCheck(loc, op, binaryNode->getLeft());
-        default:
-            break;
-        }
+    if (node->getQualifier().isWriteOnly()) {
+        const TIntermTyped* leftMostTypeNode = TIntermediate::findLValueBase(node, true);
+
+        if (symNode != nullptr)
+            error(loc, "can't read from writeonly object: ", op, symNode->getName().c_str());
+        else if (binaryNode &&
+                (binaryNode->getAsOperator()->getOp() == EOpIndexDirectStruct ||
+                 binaryNode->getAsOperator()->getOp() == EOpIndexDirect))
+            if(IsAnonymous(leftMostTypeNode->getAsSymbolNode()->getName()))
+                error(loc, "can't read from writeonly object: ", op, leftMostTypeNode->getAsSymbolNode()->getAccessName().c_str());
+            else
+                error(loc, "can't read from writeonly object: ", op, leftMostTypeNode->getAsSymbolNode()->getName().c_str());
+        else
+            error(loc, "can't read from writeonly object: ", op, "");
 
 
-        return;
+    } else {
+        if (binaryNode) {
+            switch (binaryNode->getOp()) {
+            case EOpIndexDirect:
+            case EOpIndexIndirect:
+            case EOpIndexDirectStruct:
+            case EOpVectorSwizzle:
+            case EOpMatrixSwizzle:
+                rValueErrorCheck(loc, op, binaryNode->getLeft());
+            default:
+                break;
+            }
+        }
     }
     }
-
-    TIntermSymbol* symNode = node->getAsSymbolNode();
-    if (symNode && symNode->getQualifier().isWriteOnly())
-        error(loc, "can't read from writeonly object: ", op, symNode->getName().c_str());
 }
 }
 
 
 // Add 'symbol' to the list of deferred linkage symbols, which
 // Add 'symbol' to the list of deferred linkage symbols, which
@@ -579,7 +601,6 @@ void TParseContextBase::parseSwizzleSelector(const TSourceLoc& loc, const TStrin
         selector.push_back(0);
         selector.push_back(0);
 }
 }
 
 
-#ifdef ENABLE_HLSL
 //
 //
 // Make the passed-in variable information become a member of the
 // Make the passed-in variable information become a member of the
 // global uniform block.  If this doesn't exist yet, make it.
 // global uniform block.  If this doesn't exist yet, make it.
@@ -624,7 +645,67 @@ void TParseContextBase::growGlobalUniformBlock(const TSourceLoc& loc, TType& mem
 
 
     ++firstNewMember;
     ++firstNewMember;
 }
 }
-#endif
+
+void TParseContextBase::growAtomicCounterBlock(int binding, const TSourceLoc& loc, TType& memberType, const TString& memberName, TTypeList* typeList) {
+    // Make the atomic counter block, if not yet made.
+    const auto &at  = atomicCounterBuffers.find(binding);
+    if (at == atomicCounterBuffers.end()) {
+        atomicCounterBuffers.insert({binding, (TVariable*)nullptr });
+        atomicCounterBlockFirstNewMember.insert({binding, 0});
+    }
+
+    TVariable*& atomicCounterBuffer = atomicCounterBuffers[binding];
+    int& bufferNewMember = atomicCounterBlockFirstNewMember[binding];
+
+    if (atomicCounterBuffer == nullptr) {
+        TQualifier blockQualifier;
+        blockQualifier.clear();
+        blockQualifier.storage = EvqBuffer;
+        
+        char charBuffer[512];
+        if (binding != TQualifier::layoutBindingEnd) {
+            snprintf(charBuffer, 512, "%s_%d", getAtomicCounterBlockName(), binding);
+        } else {
+            snprintf(charBuffer, 512, "%s_0", getAtomicCounterBlockName());
+        }
+        
+        TType blockType(new TTypeList, *NewPoolTString(charBuffer), blockQualifier);
+        setUniformBlockDefaults(blockType);
+        blockType.getQualifier().layoutPacking = ElpStd430;
+        atomicCounterBuffer = new TVariable(NewPoolTString(""), blockType, true);
+        // If we arn't auto mapping bindings then set the block to use the same
+        // binding as what the atomic was set to use
+        if (!intermediate.getAutoMapBindings()) {
+            atomicCounterBuffer->getWritableType().getQualifier().layoutBinding = binding;
+        }
+        bufferNewMember = 0;
+
+        atomicCounterBuffer->getWritableType().getQualifier().layoutSet = atomicCounterBlockSet;
+    }
+
+    // Add the requested member as a member to the global block.
+    TType* type = new TType;
+    type->shallowCopy(memberType);
+    type->setFieldName(memberName);
+    if (typeList)
+        type->setStruct(typeList);
+    TTypeLoc typeLoc = {type, loc};
+    atomicCounterBuffer->getType().getWritableStruct()->push_back(typeLoc);
+
+    // Insert into the symbol table.
+    if (bufferNewMember == 0) {
+        // This is the first request; we need a normal symbol table insert
+        if (symbolTable.insert(*atomicCounterBuffer))
+            trackLinkage(*atomicCounterBuffer);
+        else
+            error(loc, "failed to insert the global constant buffer", "buffer", "");
+    } else {
+        // This is a follow-on request; we need to amend the first insert
+        symbolTable.amend(*atomicCounterBuffer, bufferNewMember);
+    }
+
+    ++bufferNewMember;
+}
 
 
 void TParseContextBase::finish()
 void TParseContextBase::finish()
 {
 {

+ 492 - 42
src/libraries/glslang/glslang/MachineIndependent/ParseHelper.cpp

@@ -87,6 +87,10 @@ TParseContext::TParseContext(TSymbolTable& symbolTable, TIntermediate& interm, b
     globalInputDefaults.clear();
     globalInputDefaults.clear();
     globalOutputDefaults.clear();
     globalOutputDefaults.clear();
 
 
+    globalSharedDefaults.clear();
+    globalSharedDefaults.layoutMatrix = ElmColumnMajor;
+    globalSharedDefaults.layoutPacking = ElpStd430;
+
 #ifndef GLSLANG_WEB
 #ifndef GLSLANG_WEB
     // "Shaders in the transform
     // "Shaders in the transform
     // feedback capturing mode have an initial global default of
     // feedback capturing mode have an initial global default of
@@ -221,6 +225,108 @@ void TParseContext::parserError(const char* s)
         error(getCurrentLoc(), "compilation terminated", "", "");
         error(getCurrentLoc(), "compilation terminated", "", "");
 }
 }
 
 
+void TParseContext::growGlobalUniformBlock(const TSourceLoc& loc, TType& memberType, const TString& memberName, TTypeList* typeList)
+{
+    bool createBlock = globalUniformBlock == nullptr;
+
+    if (createBlock) {
+        globalUniformBinding = intermediate.getGlobalUniformBinding();
+        globalUniformSet = intermediate.getGlobalUniformSet();
+    }
+
+    // use base class function to create/expand block
+    TParseContextBase::growGlobalUniformBlock(loc, memberType, memberName, typeList);
+
+    if (spvVersion.vulkan > 0 && spvVersion.vulkanRelaxed) {
+        // check for a block storage override
+        TBlockStorageClass storageOverride = intermediate.getBlockStorageOverride(getGlobalUniformBlockName());
+        TQualifier& qualifier = globalUniformBlock->getWritableType().getQualifier();
+        qualifier.defaultBlock = true;
+
+        if (storageOverride != EbsNone) {
+            if (createBlock) {
+                // Remap block storage
+                qualifier.setBlockStorage(storageOverride);
+
+                // check that the change didn't create errors
+                blockQualifierCheck(loc, qualifier, false);
+            }
+
+            // remap meber storage as well
+            memberType.getQualifier().setBlockStorage(storageOverride);
+        }
+    }
+}
+
+void TParseContext::growAtomicCounterBlock(int binding, const TSourceLoc& loc, TType& memberType, const TString& memberName, TTypeList* typeList)
+{
+    bool createBlock = atomicCounterBuffers.find(binding) == atomicCounterBuffers.end();
+
+    if (createBlock) {
+        atomicCounterBlockSet = intermediate.getAtomicCounterBlockSet();
+    }
+
+    // use base class function to create/expand block
+    TParseContextBase::growAtomicCounterBlock(binding, loc, memberType, memberName, typeList);
+    TQualifier& qualifier = atomicCounterBuffers[binding]->getWritableType().getQualifier();
+    qualifier.defaultBlock = true;
+
+    if (spvVersion.vulkan > 0 && spvVersion.vulkanRelaxed) {
+        // check for a Block storage override
+        TBlockStorageClass storageOverride = intermediate.getBlockStorageOverride(getAtomicCounterBlockName());
+
+        if (storageOverride != EbsNone) {
+            if (createBlock) {
+                // Remap block storage
+
+                qualifier.setBlockStorage(storageOverride);
+
+                // check that the change didn't create errors
+                blockQualifierCheck(loc, qualifier, false);
+            }
+
+            // remap meber storage as well
+            memberType.getQualifier().setBlockStorage(storageOverride);
+        }
+    }
+}
+
+const char* TParseContext::getGlobalUniformBlockName() const
+{
+    const char* name = intermediate.getGlobalUniformBlockName();
+    if (std::string(name) == "")
+        return "gl_DefaultUniformBlock";
+    else
+        return name;
+}
+void TParseContext::finalizeGlobalUniformBlockLayout(TVariable&)
+{
+}
+void TParseContext::setUniformBlockDefaults(TType& block) const
+{
+    block.getQualifier().layoutPacking = ElpStd140;
+    block.getQualifier().layoutMatrix = ElmColumnMajor;
+}
+
+
+const char* TParseContext::getAtomicCounterBlockName() const
+{
+    const char* name = intermediate.getAtomicCounterBlockName();
+    if (std::string(name) == "")
+        return "gl_AtomicCounterBlock";
+    else
+        return name;
+}
+void TParseContext::finalizeAtomicCounterBlockLayout(TVariable&)
+{
+}
+
+void TParseContext::setAtomicCounterBlockDefaults(TType& block) const
+{
+    block.getQualifier().layoutPacking = ElpStd430;
+    block.getQualifier().layoutMatrix = ElmRowMajor;
+}
+
 void TParseContext::handlePragma(const TSourceLoc& loc, const TVector<TString>& tokens)
 void TParseContext::handlePragma(const TSourceLoc& loc, const TVector<TString>& tokens)
 {
 {
 #ifndef GLSLANG_WEB
 #ifndef GLSLANG_WEB
@@ -1131,6 +1237,14 @@ TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction
 {
 {
     TIntermTyped* result = nullptr;
     TIntermTyped* result = nullptr;
 
 
+    if (spvVersion.vulkan != 0 && spvVersion.vulkanRelaxed) {
+        // allow calls that are invalid in Vulkan Semantics to be invisibily
+        // remapped to equivalent valid functions
+        result = vkRelaxedRemapFunctionCall(loc, function, arguments);
+        if (result)
+            return result;
+    }
+
     if (function->getBuiltInOp() == EOpArrayLength)
     if (function->getBuiltInOp() == EOpArrayLength)
         result = handleLengthMethod(loc, function, arguments);
         result = handleLengthMethod(loc, function, arguments);
     else if (function->getBuiltInOp() != EOpNull) {
     else if (function->getBuiltInOp() != EOpNull) {
@@ -1723,6 +1837,7 @@ void TParseContext::memorySemanticsCheck(const TSourceLoc& loc, const TFunction&
     // Grab the semantics and storage class semantics from the operands, based on opcode
     // Grab the semantics and storage class semantics from the operands, based on opcode
     switch (callNode.getOp()) {
     switch (callNode.getOp()) {
     case EOpAtomicAdd:
     case EOpAtomicAdd:
+    case EOpAtomicSubtract:
     case EOpAtomicMin:
     case EOpAtomicMin:
     case EOpAtomicMax:
     case EOpAtomicMax:
     case EOpAtomicAnd:
     case EOpAtomicAnd:
@@ -2076,14 +2191,32 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
     }
     }
 
 
 #ifndef GLSLANG_WEB
 #ifndef GLSLANG_WEB
-    case EOpTrace:
+    case EOpTraceNV:
         if (!(*argp)[10]->getAsConstantUnion())
         if (!(*argp)[10]->getAsConstantUnion())
-            error(loc, "argument must be compile-time constant", "payload number", "");
+            error(loc, "argument must be compile-time constant", "payload number", "a");
         break;
         break;
-    case EOpExecuteCallable:
+    case EOpTraceKHR:
+        if (!(*argp)[10]->getAsConstantUnion())
+            error(loc, "argument must be compile-time constant", "payload number", "a");
+        else {
+            unsigned int location = (*argp)[10]->getAsConstantUnion()->getAsConstantUnion()->getConstArray()[0].getUConst();
+            if (intermediate.checkLocationRT(0, location) < 0)
+                error(loc, "with layout(location =", "no rayPayloadEXT/rayPayloadInEXT declared", "%d)", location);
+        }
+        break;
+    case EOpExecuteCallableNV:
         if (!(*argp)[1]->getAsConstantUnion())
         if (!(*argp)[1]->getAsConstantUnion())
             error(loc, "argument must be compile-time constant", "callable data number", "");
             error(loc, "argument must be compile-time constant", "callable data number", "");
         break;
         break;
+    case EOpExecuteCallableKHR:
+        if (!(*argp)[1]->getAsConstantUnion())
+            error(loc, "argument must be compile-time constant", "callable data number", "");
+        else {
+            unsigned int location = (*argp)[1]->getAsConstantUnion()->getAsConstantUnion()->getConstArray()[0].getUConst();
+            if (intermediate.checkLocationRT(1, location) < 0)
+                error(loc, "with layout(location =", "no callableDataEXT/callableDataInEXT declared", "%d)", location);
+        }
+        break;
 
 
     case EOpRayQueryGetIntersectionType:
     case EOpRayQueryGetIntersectionType:
     case EOpRayQueryGetIntersectionT:
     case EOpRayQueryGetIntersectionT:
@@ -2121,9 +2254,15 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
     {
     {
         // Make sure the image types have the correct layout() format and correct argument types
         // Make sure the image types have the correct layout() format and correct argument types
         const TType& imageType = arg0->getType();
         const TType& imageType = arg0->getType();
-        if (imageType.getSampler().type == EbtInt || imageType.getSampler().type == EbtUint) {
-            if (imageType.getQualifier().getFormat() != ElfR32i && imageType.getQualifier().getFormat() != ElfR32ui)
+        if (imageType.getSampler().type == EbtInt || imageType.getSampler().type == EbtUint ||
+            imageType.getSampler().type == EbtInt64 || imageType.getSampler().type == EbtUint64) {
+            if (imageType.getQualifier().getFormat() != ElfR32i && imageType.getQualifier().getFormat() != ElfR32ui &&
+                imageType.getQualifier().getFormat() != ElfR64i && imageType.getQualifier().getFormat() != ElfR64ui)
                 error(loc, "only supported on image with format r32i or r32ui", fnCandidate.getName().c_str(), "");
                 error(loc, "only supported on image with format r32i or r32ui", fnCandidate.getName().c_str(), "");
+            if (callNode.getType().getBasicType() == EbtInt64 && imageType.getQualifier().getFormat() != ElfR64i)
+                error(loc, "only supported on image with format r64i", fnCandidate.getName().c_str(), "");
+            else if (callNode.getType().getBasicType() == EbtUint64 && imageType.getQualifier().getFormat() != ElfR64ui)
+                error(loc, "only supported on image with format r64ui", fnCandidate.getName().c_str(), "");
         } else {
         } else {
             bool isImageAtomicOnFloatAllowed = ((fnCandidate.getName().compare(0, 14, "imageAtomicAdd") == 0) ||
             bool isImageAtomicOnFloatAllowed = ((fnCandidate.getName().compare(0, 14, "imageAtomicAdd") == 0) ||
                 (fnCandidate.getName().compare(0, 15, "imageAtomicLoad") == 0) ||
                 (fnCandidate.getName().compare(0, 15, "imageAtomicLoad") == 0) ||
@@ -2148,6 +2287,7 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
     }
     }
 
 
     case EOpAtomicAdd:
     case EOpAtomicAdd:
+    case EOpAtomicSubtract:
     case EOpAtomicMin:
     case EOpAtomicMin:
     case EOpAtomicMax:
     case EOpAtomicMax:
     case EOpAtomicAnd:
     case EOpAtomicAnd:
@@ -2728,6 +2868,11 @@ void TParseContext::rValueErrorCheck(const TSourceLoc& loc, const char* op, TInt
     if (!(symNode && symNode->getQualifier().isWriteOnly())) // base class checks
     if (!(symNode && symNode->getQualifier().isWriteOnly())) // base class checks
         if (symNode && symNode->getQualifier().isExplicitInterpolation())
         if (symNode && symNode->getQualifier().isExplicitInterpolation())
             error(loc, "can't read from explicitly-interpolated object: ", op, symNode->getName().c_str());
             error(loc, "can't read from explicitly-interpolated object: ", op, symNode->getName().c_str());
+
+    // local_size_{xyz} must be assigned or specialized before gl_WorkGroupSize can be assigned. 
+    if(node->getQualifier().builtIn == EbvWorkGroupSize &&
+       !(intermediate.isLocalSizeSet() || intermediate.isLocalSizeSpecialized()))
+        error(loc, "can't read from gl_WorkGroupSize before a fixed workgroup size has been declared", op, "");
 }
 }
 
 
 //
 //
@@ -3355,7 +3500,7 @@ void TParseContext::transparentOpaqueCheck(const TSourceLoc& loc, const TType& t
 
 
     if (type.containsNonOpaque()) {
     if (type.containsNonOpaque()) {
         // Vulkan doesn't allow transparent uniforms outside of blocks
         // Vulkan doesn't allow transparent uniforms outside of blocks
-        if (spvVersion.vulkan > 0)
+        if (spvVersion.vulkan > 0 && !spvVersion.vulkanRelaxed)
             vulkanRemoved(loc, "non-opaque uniforms outside a block");
             vulkanRemoved(loc, "non-opaque uniforms outside a block");
         // OpenGL wants locations on these (unless they are getting automapped)
         // OpenGL wants locations on these (unless they are getting automapped)
         if (spvVersion.openGl > 0 && !type.getQualifier().hasLocation() && !intermediate.getAutoMapLocations())
         if (spvVersion.openGl > 0 && !type.getQualifier().hasLocation() && !intermediate.getAutoMapLocations())
@@ -3368,7 +3513,7 @@ void TParseContext::transparentOpaqueCheck(const TSourceLoc& loc, const TType& t
 //
 //
 void TParseContext::memberQualifierCheck(glslang::TPublicType& publicType)
 void TParseContext::memberQualifierCheck(glslang::TPublicType& publicType)
 {
 {
-    globalQualifierFixCheck(publicType.loc, publicType.qualifier);
+    globalQualifierFixCheck(publicType.loc, publicType.qualifier, true);
     checkNoShaderLayouts(publicType.loc, publicType.shaderQualifiers);
     checkNoShaderLayouts(publicType.loc, publicType.shaderQualifiers);
     if (publicType.qualifier.isNonUniform()) {
     if (publicType.qualifier.isNonUniform()) {
         error(publicType.loc, "not allowed on block or structure members", "nonuniformEXT", "");
         error(publicType.loc, "not allowed on block or structure members", "nonuniformEXT", "");
@@ -3379,7 +3524,7 @@ void TParseContext::memberQualifierCheck(glslang::TPublicType& publicType)
 //
 //
 // Check/fix just a full qualifier (no variables or types yet, but qualifier is complete) at global level.
 // Check/fix just a full qualifier (no variables or types yet, but qualifier is complete) at global level.
 //
 //
-void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& qualifier)
+void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& qualifier, bool isMemberCheck)
 {
 {
     bool nonuniformOkay = false;
     bool nonuniformOkay = false;
 
 
@@ -3404,6 +3549,16 @@ void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& q
     case EvqTemporary:
     case EvqTemporary:
         nonuniformOkay = true;
         nonuniformOkay = true;
         break;
         break;
+    case EvqUniform:
+        // According to GLSL spec: The std430 qualifier is supported only for shader storage blocks; a shader using
+        // the std430 qualifier on a uniform block will fail to compile.
+        // Only check the global declaration: layout(std430) uniform;
+        if (blockName == nullptr &&
+            qualifier.layoutPacking == ElpStd430)
+        {
+            error(loc, "it is invalid to declare std430 qualifier on uniform", "", "");
+        }
+        break;
     default:
     default:
         break;
         break;
     }
     }
@@ -3411,7 +3566,9 @@ 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", "");
 
 
-    invariantCheck(loc, qualifier);
+    // Storage qualifier isn't ready for memberQualifierCheck, we should skip invariantCheck for it.
+    if (!isMemberCheck || structNestingLevel > 0)
+        invariantCheck(loc, qualifier);
 }
 }
 
 
 //
 //
@@ -3422,7 +3579,7 @@ void TParseContext::globalQualifierTypeCheck(const TSourceLoc& loc, const TQuali
     if (! symbolTable.atGlobalLevel())
     if (! symbolTable.atGlobalLevel())
         return;
         return;
 
 
-    if (!(publicType.userDef && publicType.userDef->isReference())) {
+    if (!(publicType.userDef && publicType.userDef->isReference()) && !parsingBuiltins) {
         if (qualifier.isMemoryQualifierImageAndSSBOOnly() && ! publicType.isImage() && publicType.qualifier.storage != EvqBuffer) {
         if (qualifier.isMemoryQualifierImageAndSSBOOnly() && ! publicType.isImage() && publicType.qualifier.storage != EvqBuffer) {
             error(loc, "memory qualifiers cannot be used on this type", "", "");
             error(loc, "memory qualifiers cannot be used on this type", "", "");
         } else if (qualifier.isMemory() && (publicType.basicType != EbtSampler) && !publicType.qualifier.isUniformOrBuffer()) {
         } else if (qualifier.isMemory() && (publicType.basicType != EbtSampler) && !publicType.qualifier.isUniformOrBuffer()) {
@@ -4083,6 +4240,9 @@ void TParseContext::checkRuntimeSizable(const TSourceLoc& loc, const TIntermType
     if (isRuntimeLength(base))
     if (isRuntimeLength(base))
         return;
         return;
 
 
+    if (base.getType().getQualifier().builtIn == EbvSampleMask)
+        return;
+
     // Check for last member of a bufferreference type, which is runtime sizeable
     // Check for last member of a bufferreference type, which is runtime sizeable
     // but doesn't support runtime length
     // but doesn't support runtime length
     if (base.getType().getQualifier().storage == EvqBuffer) {
     if (base.getType().getQualifier().storage == EvqBuffer) {
@@ -4226,6 +4386,8 @@ TSymbol* TParseContext::redeclareBuiltinVariable(const TSourceLoc& loc, const TS
         (identifier == "gl_FragCoord"           && ((nonEsRedecls && version >= 150) || esRedecls)) ||
         (identifier == "gl_FragCoord"           && ((nonEsRedecls && version >= 150) || esRedecls)) ||
          identifier == "gl_ClipDistance"                                                            ||
          identifier == "gl_ClipDistance"                                                            ||
          identifier == "gl_CullDistance"                                                            ||
          identifier == "gl_CullDistance"                                                            ||
+         identifier == "gl_ShadingRateEXT"                                                          ||
+         identifier == "gl_PrimitiveShadingRateEXT"                                                 ||
          identifier == "gl_FrontColor"                                                              ||
          identifier == "gl_FrontColor"                                                              ||
          identifier == "gl_BackColor"                                                               ||
          identifier == "gl_BackColor"                                                               ||
          identifier == "gl_FrontSecondaryColor"                                                     ||
          identifier == "gl_FrontSecondaryColor"                                                     ||
@@ -4251,8 +4413,10 @@ TSymbol* TParseContext::redeclareBuiltinVariable(const TSourceLoc& loc, const TS
         // If it wasn't at a built-in level, then it's already been redeclared;
         // If it wasn't at a built-in level, then it's already been redeclared;
         // that is, this is a redeclaration of a redeclaration; reuse that initial
         // that is, this is a redeclaration of a redeclaration; reuse that initial
         // redeclaration.  Otherwise, make the new one.
         // redeclaration.  Otherwise, make the new one.
-        if (builtIn)
+        if (builtIn) {
             makeEditable(symbol);
             makeEditable(symbol);
+            symbolTable.amendSymbolIdLevel(*symbol);
+        }
 
 
         // Now, modify the type of the copy, as per the type of the current redeclaration.
         // Now, modify the type of the copy, as per the type of the current redeclaration.
 
 
@@ -4632,14 +4796,14 @@ void TParseContext::paramCheckFix(const TSourceLoc& loc, const TQualifier& quali
 
 
 void TParseContext::nestedBlockCheck(const TSourceLoc& loc)
 void TParseContext::nestedBlockCheck(const TSourceLoc& loc)
 {
 {
-    if (structNestingLevel > 0)
+    if (structNestingLevel > 0 || blockNestingLevel > 0)
         error(loc, "cannot nest a block definition inside a structure or block", "", "");
         error(loc, "cannot nest a block definition inside a structure or block", "", "");
-    ++structNestingLevel;
+    ++blockNestingLevel;
 }
 }
 
 
 void TParseContext::nestedStructCheck(const TSourceLoc& loc)
 void TParseContext::nestedStructCheck(const TSourceLoc& loc)
 {
 {
-    if (structNestingLevel > 0)
+    if (structNestingLevel > 0 || blockNestingLevel > 0)
         error(loc, "cannot nest a structure definition inside a structure or block", "", "");
         error(loc, "cannot nest a structure definition inside a structure or block", "", "");
     ++structNestingLevel;
     ++structNestingLevel;
 }
 }
@@ -4781,7 +4945,7 @@ void TParseContext::inductiveLoopCheck(const TSourceLoc& loc, TIntermNode* init,
     }
     }
 
 
     // get the unique id of the loop index
     // get the unique id of the loop index
-    int loopIndex = binaryInit->getLeft()->getAsSymbolNode()->getId();
+    long long loopIndex = binaryInit->getLeft()->getAsSymbolNode()->getId();
     inductiveLoopIds.insert(loopIndex);
     inductiveLoopIds.insert(loopIndex);
 
 
     // condition's form must be "loop-index relational-operator constant-expression"
     // condition's form must be "loop-index relational-operator constant-expression"
@@ -4967,14 +5131,22 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
         return;
         return;
     }
     }
     if (id == TQualifier::getLayoutPackingString(ElpPacked)) {
     if (id == TQualifier::getLayoutPackingString(ElpPacked)) {
-        if (spvVersion.spv != 0)
-            spvRemoved(loc, "packed");
+        if (spvVersion.spv != 0) {
+            if (spvVersion.vulkanRelaxed)
+                return; // silently ignore qualifier
+            else
+                spvRemoved(loc, "packed");
+        }
         publicType.qualifier.layoutPacking = ElpPacked;
         publicType.qualifier.layoutPacking = ElpPacked;
         return;
         return;
     }
     }
     if (id == TQualifier::getLayoutPackingString(ElpShared)) {
     if (id == TQualifier::getLayoutPackingString(ElpShared)) {
-        if (spvVersion.spv != 0)
-            spvRemoved(loc, "shared");
+        if (spvVersion.spv != 0) {
+            if (spvVersion.vulkanRelaxed)
+                return; // silently ignore qualifier
+            else
+                spvRemoved(loc, "shared");
+        }
         publicType.qualifier.layoutPacking = ElpShared;
         publicType.qualifier.layoutPacking = ElpShared;
         return;
         return;
     }
     }
@@ -5424,7 +5596,14 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
         if (! IsPow2(value))
         if (! IsPow2(value))
             error(loc, "must be a power of 2", "buffer_reference_align", "");
             error(loc, "must be a power of 2", "buffer_reference_align", "");
         else
         else
+#ifdef __ANDROID__
+            // Android NDK r15c tageting ABI 15 doesn't have full support for C++11
+            // (no std::exp2/log2). ::exp2 is available from C99 but ::log2 isn't
+            // available up until ABI 18 so we use the mathematical equivalent form
+            publicType.qualifier.layoutBufferReferenceAlign = (unsigned int)(std::log(value) / std::log(2.0));
+#else
             publicType.qualifier.layoutBufferReferenceAlign = (unsigned int)std::log2(value);
             publicType.qualifier.layoutBufferReferenceAlign = (unsigned int)std::log2(value);
+#endif
         if (nonLiteral)
         if (nonLiteral)
             error(loc, "needs a literal integer", "buffer_reference_align", "");
             error(loc, "needs a literal integer", "buffer_reference_align", "");
         return;
         return;
@@ -5715,6 +5894,8 @@ void TParseContext::layoutObjectCheck(const TSourceLoc& loc, const TSymbol& symb
                     error(loc, "can only specify on a uniform block", "push_constant", "");
                     error(loc, "can only specify on a uniform block", "push_constant", "");
                 if (qualifier.isShaderRecord())
                 if (qualifier.isShaderRecord())
                     error(loc, "can only specify on a buffer block", "shaderRecordNV", "");
                     error(loc, "can only specify on a buffer block", "shaderRecordNV", "");
+                if (qualifier.hasLocation() && type.isAtomic())
+                    error(loc, "cannot specify on atomic counter", "location", "");
             }
             }
             break;
             break;
         default:
         default:
@@ -5852,16 +6033,12 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
         if (type.getBasicType() == EbtSampler) {
         if (type.getBasicType() == EbtSampler) {
             int lastBinding = qualifier.layoutBinding;
             int lastBinding = qualifier.layoutBinding;
             if (type.isArray()) {
             if (type.isArray()) {
-                if (spvVersion.vulkan > 0)
-                    lastBinding += 1;
-                else {
+                if (spvVersion.vulkan == 0) {
                     if (type.isSizedArray())
                     if (type.isSizedArray())
-                        lastBinding += type.getCumulativeArraySize();
+                        lastBinding += (type.getCumulativeArraySize() - 1);
                     else {
                     else {
-                        lastBinding += 1;
 #ifndef GLSLANG_WEB
 #ifndef GLSLANG_WEB
-                        if (spvVersion.vulkan == 0)
-                            warn(loc, "assuming binding count of one for compile-time checking of binding numbers for unsized array", "[]", "");
+                        warn(loc, "assuming binding count of one for compile-time checking of binding numbers for unsized array", "[]", "");
 #endif
 #endif
                     }
                     }
                 }
                 }
@@ -5871,7 +6048,7 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
                 error(loc, "sampler binding not less than gl_MaxCombinedTextureImageUnits", "binding", type.isArray() ? "(using array)" : "");
                 error(loc, "sampler binding not less than gl_MaxCombinedTextureImageUnits", "binding", type.isArray() ? "(using array)" : "");
 #endif
 #endif
         }
         }
-        if (type.isAtomic()) {
+        if (type.isAtomic() && !spvVersion.vulkanRelaxed) {
             if (qualifier.layoutBinding >= (unsigned int)resources.maxAtomicCounterBindings) {
             if (qualifier.layoutBinding >= (unsigned int)resources.maxAtomicCounterBindings) {
                 error(loc, "atomic_uint binding is too large; see gl_MaxAtomicCounterBindings", "binding", "");
                 error(loc, "atomic_uint binding is too large; see gl_MaxAtomicCounterBindings", "binding", "");
                 return;
                 return;
@@ -5985,12 +6162,28 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
     }
     }
 }
 }
 
 
+static bool storageCanHaveLayoutInBlock(const enum TStorageQualifier storage)
+{
+    switch (storage) {
+    case EvqUniform:
+    case EvqBuffer:
+    case EvqShared:
+        return true;
+    default:
+        return false;
+    }
+}
+
 // Do layout error checking that can be done within a layout qualifier proper, not needing to know
 // Do layout error checking that can be done within a layout qualifier proper, not needing to know
 // if there are blocks, atomic counters, variables, etc.
 // if there are blocks, atomic counters, variables, etc.
 void TParseContext::layoutQualifierCheck(const TSourceLoc& loc, const TQualifier& qualifier)
 void TParseContext::layoutQualifierCheck(const TSourceLoc& loc, const TQualifier& qualifier)
 {
 {
-    if (qualifier.storage == EvqShared && qualifier.hasLayout())
-        error(loc, "cannot apply layout qualifiers to a shared variable", "shared", "");
+    if (qualifier.storage == EvqShared && qualifier.hasLayout()) {
+        if (spvVersion.spv > 0 && spvVersion.spv < EShTargetSpv_1_4) {
+            error(loc, "shared block requires at least SPIR-V 1.4", "shared block", "");
+        }
+        profileRequires(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, 0, E_GL_EXT_shared_memory_block, "shared block");
+    }
 
 
     // "It is a compile-time error to use *component* without also specifying the location qualifier (order does not matter)."
     // "It is a compile-time error to use *component* without also specifying the location qualifier (order does not matter)."
     if (qualifier.hasComponent() && ! qualifier.hasLocation())
     if (qualifier.hasComponent() && ! qualifier.hasLocation())
@@ -6073,7 +6266,7 @@ void TParseContext::layoutQualifierCheck(const TSourceLoc& loc, const TQualifier
             error(loc, "can only be used on an output", "xfb layout qualifier", "");
             error(loc, "can only be used on an output", "xfb layout qualifier", "");
     }
     }
     if (qualifier.hasUniformLayout()) {
     if (qualifier.hasUniformLayout()) {
-        if (! qualifier.isUniformOrBuffer() && !qualifier.isTaskMemory()) {
+        if (!storageCanHaveLayoutInBlock(qualifier.storage) && !qualifier.isTaskMemory()) {
             if (qualifier.hasMatrix() || qualifier.hasPacking())
             if (qualifier.hasMatrix() || qualifier.hasPacking())
                 error(loc, "matrix or packing qualifiers can only be used on a uniform or buffer", "layout", "");
                 error(loc, "matrix or packing qualifiers can only be used on a uniform or buffer", "layout", "");
             if (qualifier.hasOffset() || qualifier.hasAlign())
             if (qualifier.hasOffset() || qualifier.hasAlign())
@@ -6525,6 +6718,68 @@ const TFunction* TParseContext::findFunctionExplicitTypes(const TSourceLoc& loc,
     return bestMatch;
     return bestMatch;
 }
 }
 
 
+//
+// Adjust function calls that aren't declared in Vulkan to a
+// calls with equivalent effects
+//
+TIntermTyped* TParseContext::vkRelaxedRemapFunctionCall(const TSourceLoc& loc, TFunction* function, TIntermNode* arguments)
+{
+    TIntermTyped* result = nullptr;
+
+#ifndef GLSLANG_WEB
+    if (function->getBuiltInOp() != EOpNull) {
+        return nullptr;
+    }
+
+    if (function->getName() == "atomicCounterIncrement") {
+        // change atomicCounterIncrement into an atomicAdd of 1
+        TString name("atomicAdd");
+        TType uintType(EbtUint);
+
+        TFunction realFunc(&name, function->getType());
+
+        for (int i = 0; i < function->getParamCount(); ++i) {
+            realFunc.addParameter((*function)[i]);
+        }
+
+        TParameter tmpP = { 0, &uintType };
+        realFunc.addParameter(tmpP);
+        arguments = intermediate.growAggregate(arguments, intermediate.addConstantUnion(1, loc, true));
+
+        result = handleFunctionCall(loc, &realFunc, arguments);
+    } else if (function->getName() == "atomicCounterDecrement") {
+        // change atomicCounterDecrement into an atomicAdd with -1
+        // and subtract 1 from result, to return post-decrement value
+        TString name("atomicAdd");
+        TType uintType(EbtUint);
+
+        TFunction realFunc(&name, function->getType());
+
+        for (int i = 0; i < function->getParamCount(); ++i) {
+            realFunc.addParameter((*function)[i]);
+        }
+
+        TParameter tmpP = { 0, &uintType };
+        realFunc.addParameter(tmpP);
+        arguments = intermediate.growAggregate(arguments, intermediate.addConstantUnion(-1, loc, true));
+
+        result = handleFunctionCall(loc, &realFunc, arguments);
+
+        // post decrement, so that it matches AtomicCounterDecrement semantics
+        if (result) {
+            result = handleBinaryMath(loc, "-", EOpSub, result, intermediate.addConstantUnion(1, loc, true));
+        }
+    } else if (function->getName() == "atomicCounter") {
+        // change atomicCounter into a direct read of the variable
+        if (arguments->getAsTyped()) {
+            result = arguments->getAsTyped();
+        }
+    }
+#endif
+
+    return result;
+}
+
 // When a declaration includes a type, but not a variable name, it can be used
 // When a declaration includes a type, but not a variable name, it can be used
 // to establish defaults.
 // to establish defaults.
 void TParseContext::declareTypeDefaults(const TSourceLoc& loc, const TPublicType& publicType)
 void TParseContext::declareTypeDefaults(const TSourceLoc& loc, const TPublicType& publicType)
@@ -6535,18 +6790,105 @@ void TParseContext::declareTypeDefaults(const TSourceLoc& loc, const TPublicType
             error(loc, "atomic_uint binding is too large", "binding", "");
             error(loc, "atomic_uint binding is too large", "binding", "");
             return;
             return;
         }
         }
-
-        if(publicType.qualifier.hasOffset()) {
+        if (publicType.qualifier.hasOffset())
             atomicUintOffsets[publicType.qualifier.layoutBinding] = publicType.qualifier.layoutOffset;
             atomicUintOffsets[publicType.qualifier.layoutBinding] = publicType.qualifier.layoutOffset;
-        }
         return;
         return;
     }
     }
 
 
+    if (publicType.arraySizes) {
+        error(loc, "expect an array name", "", "");
+    }
+
     if (publicType.qualifier.hasLayout() && !publicType.qualifier.hasBufferReference())
     if (publicType.qualifier.hasLayout() && !publicType.qualifier.hasBufferReference())
         warn(loc, "useless application of layout qualifier", "layout", "");
         warn(loc, "useless application of layout qualifier", "layout", "");
 #endif
 #endif
 }
 }
 
 
+bool TParseContext::vkRelaxedRemapUniformVariable(const TSourceLoc& loc, TString& identifier, const TPublicType&,
+    TArraySizes*, TIntermTyped* initializer, TType& type)
+{
+    if (parsingBuiltins || symbolTable.atBuiltInLevel() || !symbolTable.atGlobalLevel() ||
+        type.getQualifier().storage != EvqUniform ||
+        !(type.containsNonOpaque()
+#ifndef GLSLANG_WEB
+            || type.getBasicType() == EbtAtomicUint
+#endif
+        )) {
+        return false;
+    }
+
+    if (type.getQualifier().hasLocation()) {
+        warn(loc, "ignoring layout qualifier for uniform", identifier.c_str(), "location");
+        type.getQualifier().layoutLocation = TQualifier::layoutLocationEnd;
+    }
+
+    if (initializer) {
+        warn(loc, "Ignoring initializer for uniform", identifier.c_str(), "");
+        initializer = nullptr;
+    }
+
+    if (type.isArray()) {
+        // do array size checks here
+        arraySizesCheck(loc, type.getQualifier(), type.getArraySizes(), initializer, false);
+
+        if (arrayQualifierError(loc, type.getQualifier()) || arrayError(loc, type)) {
+            error(loc, "array param error", identifier.c_str(), "");
+        }
+    }
+
+    // do some checking on the type as it was declared
+    layoutTypeCheck(loc, type);
+
+    int bufferBinding = TQualifier::layoutBindingEnd;
+    TVariable* updatedBlock = nullptr;
+
+#ifndef GLSLANG_WEB
+    // Convert atomic_uint into members of a buffer block
+    if (type.isAtomic()) {
+        type.setBasicType(EbtUint);
+        type.getQualifier().storage = EvqBuffer;
+
+        type.getQualifier().volatil = true;
+        type.getQualifier().coherent = true;
+
+        // xxTODO: use logic from fixOffset() to apply explicit member offset
+        bufferBinding = type.getQualifier().layoutBinding;
+        type.getQualifier().layoutBinding = TQualifier::layoutBindingEnd;
+        type.getQualifier().explicitOffset = false;
+        growAtomicCounterBlock(bufferBinding, loc, type, identifier, nullptr);
+        updatedBlock = atomicCounterBuffers[bufferBinding];
+    }
+#endif
+
+    if (!updatedBlock) {
+        growGlobalUniformBlock(loc, type, identifier, nullptr);
+        updatedBlock = globalUniformBlock;
+    }
+
+    //
+    //      don't assign explicit member offsets here
+    //      if any are assigned, need to be updated here and in the merge/link step
+    // fixBlockUniformOffsets(updatedBlock->getWritableType().getQualifier(), *updatedBlock->getWritableType().getWritableStruct());
+
+    // checks on update buffer object
+    layoutObjectCheck(loc, *updatedBlock);
+
+    TSymbol* symbol = symbolTable.find(identifier);
+
+    if (!symbol) {
+        if (updatedBlock == globalUniformBlock)
+            error(loc, "error adding uniform to default uniform block", identifier.c_str(), "");
+        else
+            error(loc, "error adding atomic counter to atomic counter block", identifier.c_str(), "");
+        return false;
+    }
+
+    // merge qualifiers
+    mergeObjectLayoutQualifiers(updatedBlock->getWritableType().getQualifier(), type.getQualifier(), true);
+
+    return true;
+}
+
 //
 //
 // Do everything necessary to handle a variable (non-block) declaration.
 // Do everything necessary to handle a variable (non-block) declaration.
 // Either redeclaring a variable, or making a new one, updating the symbol
 // Either redeclaring a variable, or making a new one, updating the symbol
@@ -6632,6 +6974,22 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden
     if (type.getQualifier().storage == EvqShared && type.containsCoopMat())
     if (type.getQualifier().storage == EvqShared && type.containsCoopMat())
         error(loc, "qualifier", "Cooperative matrix types must not be used in shared memory", "");
         error(loc, "qualifier", "Cooperative matrix types must not be used in shared memory", "");
 
 
+    if (profile == EEsProfile) {
+        if (type.getQualifier().isPipeInput() && type.getBasicType() == EbtStruct) {
+            if (type.getQualifier().isArrayedIo(language)) {
+                TType perVertexType(type, 0);
+                if (perVertexType.containsArray() && perVertexType.containsBuiltIn() == false) {
+                    error(loc, "A per vertex structure containing an array is not allowed as input in ES", type.getTypeName().c_str(), "");
+                }
+            }
+            else if (type.containsArray() && type.containsBuiltIn() == false) {
+                error(loc, "A structure containing an array is not allowed as input in ES", type.getTypeName().c_str(), "");
+            }
+            if (type.containsStructure())
+                error(loc, "A structure containing an struct is not allowed as input in ES", type.getTypeName().c_str(), "");
+        }
+    }
+
     if (identifier != "gl_FragCoord" && (publicType.shaderQualifiers.originUpperLeft || publicType.shaderQualifiers.pixelCenterInteger))
     if (identifier != "gl_FragCoord" && (publicType.shaderQualifiers.originUpperLeft || publicType.shaderQualifiers.pixelCenterInteger))
         error(loc, "can only apply origin_upper_left and pixel_center_origin to gl_FragCoord", "layout qualifier", "");
         error(loc, "can only apply origin_upper_left and pixel_center_origin to gl_FragCoord", "layout qualifier", "");
     if (identifier != "gl_FragDepth" && publicType.shaderQualifiers.getDepth() != EldNone)
     if (identifier != "gl_FragDepth" && publicType.shaderQualifiers.getDepth() != EldNone)
@@ -6642,6 +7000,14 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden
     if (symbol == nullptr)
     if (symbol == nullptr)
         reservedErrorCheck(loc, identifier);
         reservedErrorCheck(loc, identifier);
 
 
+    if (symbol == nullptr && spvVersion.vulkan > 0 && spvVersion.vulkanRelaxed) {
+        bool remapped = vkRelaxedRemapUniformVariable(loc, identifier, publicType, arraySizes, initializer, type);
+
+        if (remapped) {
+            return nullptr;
+        }
+    }
+
     inheritGlobalDefaults(type.getQualifier());
     inheritGlobalDefaults(type.getQualifier());
 
 
     // Declare the variable
     // Declare the variable
@@ -6749,6 +7115,11 @@ TVariable* TParseContext::declareNonArray(const TSourceLoc& loc, const TString&
 //
 //
 TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyped* initializer, TVariable* variable)
 TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyped* initializer, TVariable* variable)
 {
 {
+    // A null initializer is an aggregate that hasn't had an op assigned yet
+    // (still EOpNull, no relation to nullInit), and has no children.
+    bool nullInit = initializer->getAsAggregate() && initializer->getAsAggregate()->getOp() == EOpNull &&
+        initializer->getAsAggregate()->getSequence().size() == 0;
+
     //
     //
     // Identifier must be of type constant, a global, or a temporary, and
     // Identifier must be of type constant, a global, or a temporary, and
     // starting at version 120, desktop allows uniforms to have initializers.
     // starting at version 120, desktop allows uniforms to have initializers.
@@ -6756,9 +7127,36 @@ TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyp
     TStorageQualifier qualifier = variable->getType().getQualifier().storage;
     TStorageQualifier qualifier = variable->getType().getQualifier().storage;
     if (! (qualifier == EvqTemporary || qualifier == EvqGlobal || qualifier == EvqConst ||
     if (! (qualifier == EvqTemporary || qualifier == EvqGlobal || qualifier == EvqConst ||
            (qualifier == EvqUniform && !isEsProfile() && version >= 120))) {
            (qualifier == EvqUniform && !isEsProfile() && version >= 120))) {
-        error(loc, " cannot initialize this type of qualifier ", variable->getType().getStorageQualifierString(), "");
+        if (qualifier == EvqShared) {
+            // GL_EXT_null_initializer allows this for shared, if it's a null initializer
+            if (nullInit) {
+                const char* feature = "initialization with shared qualifier";
+                profileRequires(loc, EEsProfile, 0, E_GL_EXT_null_initializer, feature);
+                profileRequires(loc, ~EEsProfile, 0, E_GL_EXT_null_initializer, feature);
+            } else {
+                error(loc, "initializer can only be a null initializer ('{}')", "shared", "");
+            }
+        } else {
+            error(loc, " cannot initialize this type of qualifier ",
+                  variable->getType().getStorageQualifierString(), "");
+            return nullptr;
+        }
+    }
+
+    if (nullInit) {
+        // only some types can be null initialized
+        if (variable->getType().containsUnsizedArray()) {
+            error(loc, "null initializers can't size unsized arrays", "{}", "");
+            return nullptr;
+        }
+        if (variable->getType().containsOpaque()) {
+            error(loc, "null initializers can't be used on opaque values", "{}", "");
+            return nullptr;
+        }
+        variable->getWritableType().getQualifier().setNullInit();
         return nullptr;
         return nullptr;
     }
     }
+
     arrayObjectCheck(loc, variable->getType(), "array initializer");
     arrayObjectCheck(loc, variable->getType(), "array initializer");
 
 
     //
     //
@@ -6802,13 +7200,15 @@ TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyp
 
 
     // Uniforms require a compile-time constant initializer
     // Uniforms require a compile-time constant initializer
     if (qualifier == EvqUniform && ! initializer->getType().getQualifier().isFrontEndConstant()) {
     if (qualifier == EvqUniform && ! initializer->getType().getQualifier().isFrontEndConstant()) {
-        error(loc, "uniform initializers must be constant", "=", "'%s'", variable->getType().getCompleteString().c_str());
+        error(loc, "uniform initializers must be constant", "=", "'%s'",
+              variable->getType().getCompleteString().c_str());
         variable->getWritableType().getQualifier().makeTemporary();
         variable->getWritableType().getQualifier().makeTemporary();
         return nullptr;
         return nullptr;
     }
     }
     // Global consts require a constant initializer (specialization constant is okay)
     // Global consts require a constant initializer (specialization constant is okay)
     if (qualifier == EvqConst && symbolTable.atGlobalLevel() && ! initializer->getType().getQualifier().isConstant()) {
     if (qualifier == EvqConst && symbolTable.atGlobalLevel() && ! initializer->getType().getQualifier().isConstant()) {
-        error(loc, "global const initializers must be constant", "=", "'%s'", variable->getType().getCompleteString().c_str());
+        error(loc, "global const initializers must be constant", "=", "'%s'",
+              variable->getType().getCompleteString().c_str());
         variable->getWritableType().getQualifier().makeTemporary();
         variable->getWritableType().getQualifier().makeTemporary();
         return nullptr;
         return nullptr;
     }
     }
@@ -6828,7 +7228,8 @@ TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyp
         // "In declarations of global variables with no storage qualifier or with a const
         // "In declarations of global variables with no storage qualifier or with a const
         // qualifier any initializer must be a constant expression."
         // qualifier any initializer must be a constant expression."
         if (symbolTable.atGlobalLevel() && ! initializer->getType().getQualifier().isConstant()) {
         if (symbolTable.atGlobalLevel() && ! initializer->getType().getQualifier().isConstant()) {
-            const char* initFeature = "non-constant global initializer (needs GL_EXT_shader_non_constant_global_initializers)";
+            const char* initFeature =
+                "non-constant global initializer (needs GL_EXT_shader_non_constant_global_initializers)";
             if (isEsProfile()) {
             if (isEsProfile()) {
                 if (relaxedErrors() && ! extensionTurnedOn(E_GL_EXT_shader_non_constant_global_initializers))
                 if (relaxedErrors() && ! extensionTurnedOn(E_GL_EXT_shader_non_constant_global_initializers))
                     warn(loc, "not allowed in this version", initFeature, "");
                     warn(loc, "not allowed in this version", initFeature, "");
@@ -6842,7 +7243,8 @@ TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyp
         // Compile-time tagging of the variable with its constant value...
         // Compile-time tagging of the variable with its constant value...
 
 
         initializer = intermediate.addConversion(EOpAssign, variable->getType(), initializer);
         initializer = intermediate.addConversion(EOpAssign, variable->getType(), initializer);
-        if (! initializer || ! initializer->getType().getQualifier().isConstant() || variable->getType() != initializer->getType()) {
+        if (! initializer || ! initializer->getType().getQualifier().isConstant() ||
+            variable->getType() != initializer->getType()) {
             error(loc, "non-matching or non-convertible constant type for const initializer",
             error(loc, "non-matching or non-convertible constant type for const initializer",
                   variable->getType().getStorageQualifierString(), "");
                   variable->getType().getStorageQualifierString(), "");
             variable->getWritableType().getQualifier().makeTemporary();
             variable->getWritableType().getQualifier().makeTemporary();
@@ -6954,6 +7356,15 @@ TIntermTyped* TParseContext::convertInitializerList(const TSourceLoc& loc, const
             error(loc, "wrong vector size (or rows in a matrix column):", "initializer list", type.getCompleteString().c_str());
             error(loc, "wrong vector size (or rows in a matrix column):", "initializer list", type.getCompleteString().c_str());
             return nullptr;
             return nullptr;
         }
         }
+        TBasicType destType = type.getBasicType();
+        for (int i = 0; i < type.getVectorSize(); ++i) {
+            TBasicType initType = initList->getSequence()[i]->getAsTyped()->getBasicType();
+            if (destType != initType && !intermediate.canImplicitlyPromote(initType, destType)) {
+                error(loc, "type mismatch in initializer list", "initializer list", type.getCompleteString().c_str());
+                return nullptr;
+            }
+
+        }
     } else {
     } else {
         error(loc, "unexpected initializer-list type:", "initializer list", type.getCompleteString().c_str());
         error(loc, "unexpected initializer-list type:", "initializer list", type.getCompleteString().c_str());
         return nullptr;
         return nullptr;
@@ -7410,6 +7821,19 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T
 
 
         return node;
         return node;
 
 
+    case EOpConstructAccStruct:
+        if ((node->getType().isScalar() && node->getType().getBasicType() == EbtUint64)) {
+            // construct acceleration structure from uint64
+            requireExtensions(loc, 1, &E_GL_EXT_ray_tracing, "uint64_t conversion to acclerationStructureEXT");
+            return intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConvUint64ToAccStruct, true, node,
+                type);
+        } else if (node->getType().isVector() && node->getType().getBasicType() == EbtUint && node->getVectorSize() == 2) {
+            // construct acceleration structure from uint64
+            requireExtensions(loc, 1, &E_GL_EXT_ray_tracing, "uvec2 conversion to accelerationStructureEXT");
+            return intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConvUvec2ToAccStruct, true, node,
+                type);
+        } else
+            return nullptr;
 #endif // GLSLANG_WEB
 #endif // GLSLANG_WEB
 
 
     default:
     default:
@@ -7476,6 +7900,8 @@ void TParseContext::inheritMemoryQualifiers(const TQualifier& from, TQualifier&
 void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, const TString* instanceName,
 void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, const TString* instanceName,
     TArraySizes* arraySizes)
     TArraySizes* arraySizes)
 {
 {
+    if (spvVersion.vulkan > 0 && spvVersion.vulkanRelaxed)
+        blockStorageRemap(loc, blockName, currentBlockQualifier);
     blockStageIoCheck(loc, currentBlockQualifier);
     blockStageIoCheck(loc, currentBlockQualifier);
     blockQualifierCheck(loc, currentBlockQualifier, instanceName != nullptr);
     blockQualifierCheck(loc, currentBlockQualifier, instanceName != nullptr);
     if (arraySizes != nullptr) {
     if (arraySizes != nullptr) {
@@ -7490,10 +7916,10 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
         TType& memberType = *typeList[member].type;
         TType& memberType = *typeList[member].type;
         TQualifier& memberQualifier = memberType.getQualifier();
         TQualifier& memberQualifier = memberType.getQualifier();
         const TSourceLoc& memberLoc = typeList[member].loc;
         const TSourceLoc& memberLoc = typeList[member].loc;
-        globalQualifierFixCheck(memberLoc, memberQualifier);
         if (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal && memberQualifier.storage != currentBlockQualifier.storage)
         if (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal && memberQualifier.storage != currentBlockQualifier.storage)
             error(memberLoc, "member storage qualifier cannot contradict block storage qualifier", memberType.getFieldName().c_str(), "");
             error(memberLoc, "member storage qualifier cannot contradict block storage qualifier", memberType.getFieldName().c_str(), "");
         memberQualifier.storage = currentBlockQualifier.storage;
         memberQualifier.storage = currentBlockQualifier.storage;
+        globalQualifierFixCheck(memberLoc, memberQualifier);
 #ifndef GLSLANG_WEB
 #ifndef GLSLANG_WEB
         inheritMemoryQualifiers(currentBlockQualifier, memberQualifier);
         inheritMemoryQualifiers(currentBlockQualifier, memberQualifier);
         if (currentBlockQualifier.perPrimitiveNV)
         if (currentBlockQualifier.perPrimitiveNV)
@@ -7543,6 +7969,7 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
     case EvqBuffer:     defaultQualification = globalBufferDefaults;     break;
     case EvqBuffer:     defaultQualification = globalBufferDefaults;     break;
     case EvqVaryingIn:  defaultQualification = globalInputDefaults;      break;
     case EvqVaryingIn:  defaultQualification = globalInputDefaults;      break;
     case EvqVaryingOut: defaultQualification = globalOutputDefaults;     break;
     case EvqVaryingOut: defaultQualification = globalOutputDefaults;     break;
+    case EvqShared:     defaultQualification = globalSharedDefaults;     break;
     default:            defaultQualification.clear();                    break;
     default:            defaultQualification.clear();                    break;
     }
     }
 
 
@@ -7764,6 +8191,17 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
     trackLinkage(variable);
     trackLinkage(variable);
 }
 }
 
 
+//
+// allow storage type of block to be remapped at compile time
+//
+void TParseContext::blockStorageRemap(const TSourceLoc&, const TString* instanceName, TQualifier& qualifier)
+{
+    TBlockStorageClass type = intermediate.getBlockStorageOverride(instanceName->c_str());
+    if (type != EbsNone) {
+        qualifier.setBlockStorage(type);
+    }
+}
+
 // Do all block-declaration checking regarding the combination of in/out/uniform/buffer
 // Do all block-declaration checking regarding the combination of in/out/uniform/buffer
 // with a particular stage.
 // with a particular stage.
 void TParseContext::blockStageIoCheck(const TSourceLoc& loc, const TQualifier& qualifier)
 void TParseContext::blockStageIoCheck(const TSourceLoc& loc, const TQualifier& qualifier)
@@ -7806,6 +8244,12 @@ void TParseContext::blockStageIoCheck(const TSourceLoc& loc, const TQualifier& q
             error(loc, "output blocks cannot be used in a task shader", "out", "");
             error(loc, "output blocks cannot be used in a task shader", "out", "");
         }
         }
         break;
         break;
+    case EvqShared:
+        if (spvVersion.spv > 0 && spvVersion.spv < EShTargetSpv_1_4) {
+            error(loc, "shared block requires at least SPIR-V 1.4", "shared block", "");
+        }
+        profileRequires(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, 0, E_GL_EXT_shared_memory_block, "shared block");
+        break;
 #ifndef GLSLANG_WEB
 #ifndef GLSLANG_WEB
     case EvqPayload:
     case EvqPayload:
         profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "rayPayloadNV block");
         profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "rayPayloadNV block");
@@ -7964,7 +8408,7 @@ void TParseContext::fixXfbOffsets(TQualifier& qualifier, TTypeList& typeList)
 //
 //
 void TParseContext::fixBlockUniformOffsets(TQualifier& qualifier, TTypeList& typeList)
 void TParseContext::fixBlockUniformOffsets(TQualifier& qualifier, TTypeList& typeList)
 {
 {
-    if (!qualifier.isUniformOrBuffer() && !qualifier.isTaskMemory())
+    if (!storageCanHaveLayoutInBlock(qualifier.storage) && !qualifier.isTaskMemory())
         return;
         return;
     if (qualifier.layoutPacking != ElpStd140 && qualifier.layoutPacking != ElpStd430 && qualifier.layoutPacking != ElpScalar)
     if (qualifier.layoutPacking != ElpStd140 && qualifier.layoutPacking != ElpStd430 && qualifier.layoutPacking != ElpScalar)
         return;
         return;
@@ -8191,7 +8635,7 @@ void TParseContext::invariantCheck(const TSourceLoc& loc, const TQualifier& qual
 
 
     bool pipeOut = qualifier.isPipeOutput();
     bool pipeOut = qualifier.isPipeOutput();
     bool pipeIn = qualifier.isPipeInput();
     bool pipeIn = qualifier.isPipeInput();
-    if (version >= 300 || (!isEsProfile() && version >= 420)) {
+    if ((version >= 300 && isEsProfile()) || (!isEsProfile() && version >= 420)) {
         if (! pipeOut)
         if (! pipeOut)
             error(loc, "can only apply to an output", "invariant", "");
             error(loc, "can only apply to an output", "invariant", "");
     } else {
     } else {
@@ -8478,8 +8922,14 @@ void TParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, con
         }
         }
 #endif
 #endif
         break;
         break;
+    case EvqShared:
+        if (qualifier.hasMatrix())
+            globalSharedDefaults.layoutMatrix = qualifier.layoutMatrix;
+        if (qualifier.hasPacking())
+            globalSharedDefaults.layoutPacking = qualifier.layoutPacking;
+        break;
     default:
     default:
-        error(loc, "default qualifier requires 'uniform', 'buffer', 'in', or 'out' storage qualification", "", "");
+        error(loc, "default qualifier requires 'uniform', 'buffer', 'in', 'out' or 'shared' storage qualification", "", "");
         return;
         return;
     }
     }
 
 

+ 46 - 9
src/libraries/glslang/glslang/MachineIndependent/ParseHelper.h

@@ -67,7 +67,7 @@ struct TPragma {
 class TScanContext;
 class TScanContext;
 class TPpContext;
 class TPpContext;
 
 
-typedef std::set<int> TIdSetType;
+typedef std::set<long long> TIdSetType;
 typedef std::map<const TTypeList*, std::map<size_t, const TTypeList*>> TStructRecord;
 typedef std::map<const TTypeList*, std::map<size_t, const TTypeList*>> TStructRecord;
 
 
 //
 //
@@ -83,7 +83,7 @@ public:
           : TParseVersions(interm, version, profile, spvVersion, language, infoSink, forwardCompatible, messages),
           : TParseVersions(interm, version, profile, spvVersion, language, infoSink, forwardCompatible, messages),
             scopeMangler("::"),
             scopeMangler("::"),
             symbolTable(symbolTable),
             symbolTable(symbolTable),
-            statementNestingLevel(0), loopNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0),
+            statementNestingLevel(0), loopNestingLevel(0), structNestingLevel(0), blockNestingLevel(0), controlFlowNestingLevel(0),
             currentFunctionType(nullptr),
             currentFunctionType(nullptr),
             postEntryPointReturn(false),
             postEntryPointReturn(false),
             contextPragma(true, false),
             contextPragma(true, false),
@@ -92,7 +92,8 @@ public:
             limits(resources.limits),
             limits(resources.limits),
             globalUniformBlock(nullptr),
             globalUniformBlock(nullptr),
             globalUniformBinding(TQualifier::layoutBindingEnd),
             globalUniformBinding(TQualifier::layoutBindingEnd),
-            globalUniformSet(TQualifier::layoutSetEnd)
+            globalUniformSet(TQualifier::layoutSetEnd),
+            atomicCounterBlockSet(TQualifier::layoutSetEnd)
     {
     {
         if (entryPoint != nullptr)
         if (entryPoint != nullptr)
             sourceEntryPointName = *entryPoint;
             sourceEntryPointName = *entryPoint;
@@ -154,10 +155,11 @@ public:
             extensionCallback(line, extension, behavior);
             extensionCallback(line, extension, behavior);
     }
     }
 
 
-#ifdef ENABLE_HLSL
     // Manage the global uniform block (default uniforms in GLSL, $Global in HLSL)
     // Manage the global uniform block (default uniforms in GLSL, $Global in HLSL)
     virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr);
     virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr);
-#endif
+
+    // Manage global buffer (used for backing atomic counters in GLSL when using relaxed Vulkan semantics)
+    virtual void growAtomicCounterBlock(int binding, const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr);
 
 
     // Potentially rename shader entry point function
     // Potentially rename shader entry point function
     void renameShaderFunction(TString*& name) const
     void renameShaderFunction(TString*& name) const
@@ -178,7 +180,8 @@ public:
     TSymbolTable& symbolTable;        // symbol table that goes with the current language, version, and profile
     TSymbolTable& symbolTable;        // symbol table that goes with the current language, version, and profile
     int statementNestingLevel;        // 0 if outside all flow control or compound statements
     int statementNestingLevel;        // 0 if outside all flow control or compound statements
     int loopNestingLevel;             // 0 if outside all loops
     int loopNestingLevel;             // 0 if outside all loops
-    int structNestingLevel;           // 0 if outside blocks and structures
+    int structNestingLevel;           // 0 if outside structures
+    int blockNestingLevel;            // 0 if outside blocks
     int controlFlowNestingLevel;      // 0 if outside all flow control
     int controlFlowNestingLevel;      // 0 if outside all flow control
     const TType* currentFunctionType; // the return type of the function that's currently being parsed
     const TType* currentFunctionType; // the return type of the function that's currently being parsed
     bool functionReturnsValue;        // true if a non-void function has a return
     bool functionReturnsValue;        // true if a non-void function has a return
@@ -229,7 +232,24 @@ protected:
     // override this to set the language-specific name
     // override this to set the language-specific name
     virtual const char* getGlobalUniformBlockName() const { return ""; }
     virtual const char* getGlobalUniformBlockName() const { return ""; }
     virtual void setUniformBlockDefaults(TType&) const { }
     virtual void setUniformBlockDefaults(TType&) const { }
-    virtual void finalizeGlobalUniformBlockLayout(TVariable&) { }
+    virtual void finalizeGlobalUniformBlockLayout(TVariable&) {}
+
+    // Manage the atomic counter block (used for atomic_uints with Vulkan-Relaxed)
+    TMap<int, TVariable*> atomicCounterBuffers;
+    unsigned int atomicCounterBlockSet;
+    TMap<int, int> atomicCounterBlockFirstNewMember;
+    // override this to set the language-specific name
+    virtual const char* getAtomicCounterBlockName() const { return ""; }
+    virtual void setAtomicCounterBlockDefaults(TType&) const {}
+    virtual void finalizeAtomicCounterBlockLayout(TVariable&) {}
+    bool isAtomicCounterBlock(const TSymbol& symbol) {
+        const TVariable* var = symbol.getAsVariable();
+        if (!var)
+            return false;
+        const auto& at = atomicCounterBuffers.find(var->getType().getQualifier().layoutBinding);
+        return (at != atomicCounterBuffers.end() && (*at).second->getType() == var->getType());
+    }
+
     virtual void outputMessage(const TSourceLoc&, const char* szReason, const char* szToken,
     virtual void outputMessage(const TSourceLoc&, const char* szReason, const char* szToken,
                                const char* szExtraInfoFormat, TPrefixType prefix,
                                const char* szExtraInfoFormat, TPrefixType prefix,
                                va_list args);
                                va_list args);
@@ -292,6 +312,9 @@ public:
     bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) override;
     bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) override;
     void parserError(const char* s);     // for bison's yyerror
     void parserError(const char* s);     // for bison's yyerror
 
 
+    virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr) override;
+    virtual void growAtomicCounterBlock(int binding, const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr) override;
+
     void reservedErrorCheck(const TSourceLoc&, const TString&);
     void reservedErrorCheck(const TSourceLoc&, const TString&);
     void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) override;
     void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) override;
     bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) override;
     bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) override;
@@ -339,6 +362,10 @@ public:
     void checkPrecisionQualifier(const TSourceLoc&, TPrecisionQualifier);
     void checkPrecisionQualifier(const TSourceLoc&, TPrecisionQualifier);
     void memorySemanticsCheck(const TSourceLoc&, const TFunction&, const TIntermOperator& callNode);
     void memorySemanticsCheck(const TSourceLoc&, const TFunction&, const TIntermOperator& callNode);
 
 
+    TIntermTyped* vkRelaxedRemapFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*);
+    // returns true if the variable was remapped to something else
+    bool vkRelaxedRemapUniformVariable(const TSourceLoc&, TString&, const TPublicType&, TArraySizes*, TIntermTyped*, TType&);
+
     void assignError(const TSourceLoc&, const char* op, TString left, TString right);
     void assignError(const TSourceLoc&, const char* op, TString left, TString right);
     void unaryOpError(const TSourceLoc&, const char* op, TString operand);
     void unaryOpError(const TSourceLoc&, const char* op, TString operand);
     void binaryOpError(const TSourceLoc&, const char* op, TString left, TString right);
     void binaryOpError(const TSourceLoc&, const char* op, TString left, TString right);
@@ -365,7 +392,7 @@ public:
     void accStructCheck(const TSourceLoc & loc, const TType & type, const TString & identifier);
     void accStructCheck(const TSourceLoc & loc, const TType & type, const TString & identifier);
     void transparentOpaqueCheck(const TSourceLoc&, const TType&, const TString& identifier);
     void transparentOpaqueCheck(const TSourceLoc&, const TType&, const TString& identifier);
     void memberQualifierCheck(glslang::TPublicType&);
     void memberQualifierCheck(glslang::TPublicType&);
-    void globalQualifierFixCheck(const TSourceLoc&, TQualifier&);
+    void globalQualifierFixCheck(const TSourceLoc&, TQualifier&, bool isMemberCheck = false);
     void globalQualifierTypeCheck(const TSourceLoc&, const TQualifier&, const TPublicType&);
     void globalQualifierTypeCheck(const TSourceLoc&, const TQualifier&, const TPublicType&);
     bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType);
     bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType);
     void mergeQualifiers(const TSourceLoc&, TQualifier& dst, const TQualifier& src, bool force);
     void mergeQualifiers(const TSourceLoc&, TQualifier& dst, const TQualifier& src, bool force);
@@ -391,7 +418,7 @@ public:
     void arrayLimitCheck(const TSourceLoc&, const TString&, int size);
     void arrayLimitCheck(const TSourceLoc&, const TString&, int size);
     void limitCheck(const TSourceLoc&, int value, const char* limit, const char* feature);
     void limitCheck(const TSourceLoc&, int value, const char* limit, const char* feature);
 
 
-    void inductiveLoopBodyCheck(TIntermNode*, int loopIndexId, TSymbolTable&);
+    void inductiveLoopBodyCheck(TIntermNode*, long long loopIndexId, TSymbolTable&);
     void constantIndexExpressionCheck(TIntermNode*);
     void constantIndexExpressionCheck(TIntermNode*);
 
 
     void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&);
     void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&);
@@ -416,6 +443,7 @@ public:
     TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset);
     TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset);
     void inheritMemoryQualifiers(const TQualifier& from, TQualifier& to);
     void inheritMemoryQualifiers(const TQualifier& from, TQualifier& to);
     void declareBlock(const TSourceLoc&, TTypeList& typeList, const TString* instanceName = 0, TArraySizes* arraySizes = 0);
     void declareBlock(const TSourceLoc&, TTypeList& typeList, const TString* instanceName = 0, TArraySizes* arraySizes = 0);
+    void blockStorageRemap(const TSourceLoc&, const TString*, TQualifier&);
     void blockStageIoCheck(const TSourceLoc&, const TQualifier&);
     void blockStageIoCheck(const TSourceLoc&, const TQualifier&);
     void blockQualifierCheck(const TSourceLoc&, const TQualifier&, bool instanceName);
     void blockQualifierCheck(const TSourceLoc&, const TQualifier&, bool instanceName);
     void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation);
     void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation);
@@ -460,6 +488,14 @@ protected:
     void finish() override;
     void finish() override;
 #endif
 #endif
 
 
+    virtual const char* getGlobalUniformBlockName() const override;
+    virtual void finalizeGlobalUniformBlockLayout(TVariable&) override;
+    virtual void setUniformBlockDefaults(TType& block) const override;
+
+    virtual const char* getAtomicCounterBlockName() const override;
+    virtual void finalizeAtomicCounterBlockLayout(TVariable&) override;
+    virtual void setAtomicCounterBlockDefaults(TType& block) const override;
+
 public:
 public:
     //
     //
     // Generally, bison productions, the scanner, and the PP need read/write access to these; just give them direct access
     // Generally, bison productions, the scanner, and the PP need read/write access to these; just give them direct access
@@ -484,6 +520,7 @@ protected:
     TQualifier globalUniformDefaults;
     TQualifier globalUniformDefaults;
     TQualifier globalInputDefaults;
     TQualifier globalInputDefaults;
     TQualifier globalOutputDefaults;
     TQualifier globalOutputDefaults;
+    TQualifier globalSharedDefaults;
     TString currentCaller;        // name of last function body entered (not valid when at global scope)
     TString currentCaller;        // name of last function body entered (not valid when at global scope)
 #ifndef GLSLANG_WEB
 #ifndef GLSLANG_WEB
     int* atomicUintOffsets;       // to become an array of the right size to hold an offset per binding point
     int* atomicUintOffsets;       // to become an array of the right size to hold an offset per binding point

+ 99 - 1
src/libraries/glslang/glslang/MachineIndependent/Scan.cpp

@@ -365,6 +365,9 @@ void TScanContext::fillInKeywordMap()
     (*KeywordMap)["if"] =                      IF;
     (*KeywordMap)["if"] =                      IF;
     (*KeywordMap)["else"] =                    ELSE;
     (*KeywordMap)["else"] =                    ELSE;
     (*KeywordMap)["discard"] =                 DISCARD;
     (*KeywordMap)["discard"] =                 DISCARD;
+    (*KeywordMap)["terminateInvocation"] =     TERMINATE_INVOCATION;
+    (*KeywordMap)["terminateRayEXT"] =         TERMINATE_RAY;
+    (*KeywordMap)["ignoreIntersectionEXT"] =   IGNORE_INTERSECTION;
     (*KeywordMap)["return"] =                  RETURN;
     (*KeywordMap)["return"] =                  RETURN;
     (*KeywordMap)["void"] =                    VOID;
     (*KeywordMap)["void"] =                    VOID;
     (*KeywordMap)["bool"] =                    BOOL;
     (*KeywordMap)["bool"] =                    BOOL;
@@ -471,6 +474,28 @@ void TScanContext::fillInKeywordMap()
     (*KeywordMap)["image2DMSArray"] =          IMAGE2DMSARRAY;
     (*KeywordMap)["image2DMSArray"] =          IMAGE2DMSARRAY;
     (*KeywordMap)["iimage2DMSArray"] =         IIMAGE2DMSARRAY;
     (*KeywordMap)["iimage2DMSArray"] =         IIMAGE2DMSARRAY;
     (*KeywordMap)["uimage2DMSArray"] =         UIMAGE2DMSARRAY;
     (*KeywordMap)["uimage2DMSArray"] =         UIMAGE2DMSARRAY;
+    (*KeywordMap)["i64image1D"] =              I64IMAGE1D;
+    (*KeywordMap)["u64image1D"] =              U64IMAGE1D;
+    (*KeywordMap)["i64image2D"] =              I64IMAGE2D;
+    (*KeywordMap)["u64image2D"] =              U64IMAGE2D;
+    (*KeywordMap)["i64image3D"] =              I64IMAGE3D;
+    (*KeywordMap)["u64image3D"] =              U64IMAGE3D;
+    (*KeywordMap)["i64image2DRect"] =          I64IMAGE2DRECT;
+    (*KeywordMap)["u64image2DRect"] =          U64IMAGE2DRECT;
+    (*KeywordMap)["i64imageCube"] =            I64IMAGECUBE;
+    (*KeywordMap)["u64imageCube"] =            U64IMAGECUBE;
+    (*KeywordMap)["i64imageBuffer"] =          I64IMAGEBUFFER;
+    (*KeywordMap)["u64imageBuffer"] =          U64IMAGEBUFFER;
+    (*KeywordMap)["i64image1DArray"] =         I64IMAGE1DARRAY;
+    (*KeywordMap)["u64image1DArray"] =         U64IMAGE1DARRAY;
+    (*KeywordMap)["i64image2DArray"] =         I64IMAGE2DARRAY;
+    (*KeywordMap)["u64image2DArray"] =         U64IMAGE2DARRAY;
+    (*KeywordMap)["i64imageCubeArray"] =       I64IMAGECUBEARRAY;
+    (*KeywordMap)["u64imageCubeArray"] =       U64IMAGECUBEARRAY;
+    (*KeywordMap)["i64image2DMS"] =            I64IMAGE2DMS;
+    (*KeywordMap)["u64image2DMS"] =            U64IMAGE2DMS;
+    (*KeywordMap)["i64image2DMSArray"] =       I64IMAGE2DMSARRAY;
+    (*KeywordMap)["u64image2DMSArray"] =       U64IMAGE2DMSARRAY;
     (*KeywordMap)["double"] =                  DOUBLE;
     (*KeywordMap)["double"] =                  DOUBLE;
     (*KeywordMap)["dvec2"] =                   DVEC2;
     (*KeywordMap)["dvec2"] =                   DVEC2;
     (*KeywordMap)["dvec3"] =                   DVEC3;
     (*KeywordMap)["dvec3"] =                   DVEC3;
@@ -914,6 +939,17 @@ int TScanContext::tokenizeIdentifier()
     case CASE:
     case CASE:
         return keyword;
         return keyword;
 
 
+    case TERMINATE_INVOCATION:
+        if (!parseContext.extensionTurnedOn(E_GL_EXT_terminate_invocation))
+            return identifierOrType();
+        return keyword;
+
+    case TERMINATE_RAY:
+    case IGNORE_INTERSECTION:
+        if (!parseContext.extensionTurnedOn(E_GL_EXT_ray_tracing))
+            return identifierOrType();
+        return keyword;
+
     case BUFFER:
     case BUFFER:
         afterBuffer = true;
         afterBuffer = true;
         if ((parseContext.isEsProfile() && parseContext.version < 310) ||
         if ((parseContext.isEsProfile() && parseContext.version < 310) ||
@@ -982,7 +1018,7 @@ int TScanContext::tokenizeIdentifier()
         return keyword;
         return keyword;
     case PACKED:
     case PACKED:
         if ((parseContext.isEsProfile() && parseContext.version < 300) ||
         if ((parseContext.isEsProfile() && parseContext.version < 300) ||
-            (!parseContext.isEsProfile() && parseContext.version < 330))
+            (!parseContext.isEsProfile() && parseContext.version < 140))
             return reservedWord();
             return reservedWord();
         return identifierOrType();
         return identifierOrType();
 
 
@@ -1147,6 +1183,19 @@ int TScanContext::tokenizeIdentifier()
         afterType = true;
         afterType = true;
         return firstGenerationImage(false);
         return firstGenerationImage(false);
 
 
+    case I64IMAGE1D:
+    case U64IMAGE1D:
+    case I64IMAGE1DARRAY:
+    case U64IMAGE1DARRAY:
+    case I64IMAGE2DRECT:
+    case U64IMAGE2DRECT:
+        afterType = true;
+        if (parseContext.symbolTable.atBuiltInLevel() ||
+            parseContext.extensionTurnedOn(E_GL_EXT_shader_image_int64)) {
+            return firstGenerationImage(false);
+        }
+        return identifierOrType();
+
     case IMAGEBUFFER:
     case IMAGEBUFFER:
     case IIMAGEBUFFER:
     case IIMAGEBUFFER:
     case UIMAGEBUFFER:
     case UIMAGEBUFFER:
@@ -1155,6 +1204,18 @@ int TScanContext::tokenizeIdentifier()
             parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer))
             parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer))
             return keyword;
             return keyword;
         return firstGenerationImage(false);
         return firstGenerationImage(false);
+        
+    case I64IMAGEBUFFER:
+    case U64IMAGEBUFFER:
+        afterType = true;        
+        if (parseContext.symbolTable.atBuiltInLevel() ||
+            parseContext.extensionTurnedOn(E_GL_EXT_shader_image_int64)) {
+            if ((parseContext.isEsProfile() && parseContext.version >= 320) ||
+                parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer))
+                return keyword;
+            return firstGenerationImage(false);
+        }
+        return identifierOrType();
 
 
     case IMAGE2D:
     case IMAGE2D:
     case IIMAGE2D:
     case IIMAGE2D:
@@ -1171,6 +1232,20 @@ int TScanContext::tokenizeIdentifier()
         afterType = true;
         afterType = true;
         return firstGenerationImage(true);
         return firstGenerationImage(true);
 
 
+    case I64IMAGE2D:
+    case U64IMAGE2D:
+    case I64IMAGE3D:
+    case U64IMAGE3D:
+    case I64IMAGECUBE:
+    case U64IMAGECUBE:
+    case I64IMAGE2DARRAY:
+    case U64IMAGE2DARRAY:
+        afterType = true;
+        if (parseContext.symbolTable.atBuiltInLevel() ||
+            parseContext.extensionTurnedOn(E_GL_EXT_shader_image_int64))
+            return firstGenerationImage(true);
+        return identifierOrType();
+        
     case IMAGECUBEARRAY:
     case IMAGECUBEARRAY:
     case IIMAGECUBEARRAY:
     case IIMAGECUBEARRAY:
     case UIMAGECUBEARRAY:
     case UIMAGECUBEARRAY:
@@ -1179,6 +1254,18 @@ int TScanContext::tokenizeIdentifier()
             parseContext.extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array))
             parseContext.extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array))
             return keyword;
             return keyword;
         return secondGenerationImage();
         return secondGenerationImage();
+        
+    case I64IMAGECUBEARRAY:
+    case U64IMAGECUBEARRAY:
+        afterType = true;
+        if (parseContext.symbolTable.atBuiltInLevel() ||
+            parseContext.extensionTurnedOn(E_GL_EXT_shader_image_int64)) {
+            if ((parseContext.isEsProfile() && parseContext.version >= 320) ||
+                parseContext.extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array))
+                return keyword;
+            return secondGenerationImage();
+        }
+        return identifierOrType();
 
 
     case IMAGE2DMS:
     case IMAGE2DMS:
     case IIMAGE2DMS:
     case IIMAGE2DMS:
@@ -1188,6 +1275,17 @@ int TScanContext::tokenizeIdentifier()
     case UIMAGE2DMSARRAY:
     case UIMAGE2DMSARRAY:
         afterType = true;
         afterType = true;
         return secondGenerationImage();
         return secondGenerationImage();
+        
+    case I64IMAGE2DMS:
+    case U64IMAGE2DMS:
+    case I64IMAGE2DMSARRAY:
+    case U64IMAGE2DMSARRAY:
+        afterType = true;
+        if (parseContext.symbolTable.atBuiltInLevel() ||
+            parseContext.extensionTurnedOn(E_GL_EXT_shader_image_int64)) {
+            return secondGenerationImage();
+        }
+        return identifierOrType();
 
 
     case DOUBLE:
     case DOUBLE:
     case DVEC2:
     case DVEC2:

+ 100 - 8
src/libraries/glslang/glslang/MachineIndependent/ShaderLang.cpp

@@ -159,7 +159,7 @@ int MapVersionToIndex(int version)
     return index;
     return index;
 }
 }
 
 
-const int SpvVersionCount = 3;  // index range in MapSpvVersionToIndex
+const int SpvVersionCount = 4;  // index range in MapSpvVersionToIndex
 
 
 int MapSpvVersionToIndex(const SpvVersion& spvVersion)
 int MapSpvVersionToIndex(const SpvVersion& spvVersion)
 {
 {
@@ -167,8 +167,12 @@ int MapSpvVersionToIndex(const SpvVersion& spvVersion)
 
 
     if (spvVersion.openGl > 0)
     if (spvVersion.openGl > 0)
         index = 1;
         index = 1;
-    else if (spvVersion.vulkan > 0)
-        index = 2;
+    else if (spvVersion.vulkan > 0) {
+        if (!spvVersion.vulkanRelaxed)
+            index = 2;
+        else
+            index = 3;
+    }
 
 
     assert(index < SpvVersionCount);
     assert(index < SpvVersionCount);
 
 
@@ -723,6 +727,7 @@ void TranslateEnvironment(const TEnvironment* environment, EShMessages& messages
                 break;
                 break;
             case EShClientVulkan:
             case EShClientVulkan:
                 spvVersion.vulkanGlsl = environment->input.dialectVersion;
                 spvVersion.vulkanGlsl = environment->input.dialectVersion;
+                spvVersion.vulkanRelaxed = environment->input.vulkanRulesRelaxed;
                 break;
                 break;
             case EShClientOpenGL:
             case EShClientOpenGL:
                 spvVersion.openGl = environment->input.dialectVersion;
                 spvVersion.openGl = environment->input.dialectVersion;
@@ -949,6 +954,9 @@ bool ProcessDeferred(
     if (cachedTable)
     if (cachedTable)
         symbolTable->adoptLevels(*cachedTable);
         symbolTable->adoptLevels(*cachedTable);
 
 
+    if (intermediate.getUniqueId() != 0)
+        symbolTable->overwriteUniqueId(intermediate.getUniqueId());
+
     // Add built-in symbols that are potentially context dependent;
     // Add built-in symbols that are potentially context dependent;
     // they get popped again further down.
     // they get popped again further down.
     if (! AddContextSpecificSymbols(resources, compiler->infoSink, *symbolTable, version, profile, spvVersion,
     if (! AddContextSpecificSymbols(resources, compiler->infoSink, *symbolTable, version, profile, spvVersion,
@@ -1011,6 +1019,7 @@ bool ProcessDeferred(
     bool success = processingContext(*parseContext, ppContext, fullInput,
     bool success = processingContext(*parseContext, ppContext, fullInput,
                                      versionWillBeError, *symbolTable,
                                      versionWillBeError, *symbolTable,
                                      intermediate, optLevel, messages);
                                      intermediate, optLevel, messages);
+    intermediate.setUniqueId(symbolTable->getMaxSymbolId());
     return success;
     return success;
 }
 }
 
 
@@ -1270,14 +1279,15 @@ bool PreprocessDeferred(
     EShMessages messages,       // warnings/errors/AST; things to print out
     EShMessages messages,       // warnings/errors/AST; things to print out
     TShader::Includer& includer,
     TShader::Includer& includer,
     TIntermediate& intermediate, // returned tree, etc.
     TIntermediate& intermediate, // returned tree, etc.
-    std::string* outputString)
+    std::string* outputString,
+    TEnvironment* environment = nullptr)
 {
 {
     DoPreprocessing parser(outputString);
     DoPreprocessing parser(outputString);
     return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames,
     return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames,
                            preamble, optLevel, resources, defaultVersion,
                            preamble, optLevel, resources, defaultVersion,
                            defaultProfile, forceDefaultVersionAndProfile,
                            defaultProfile, forceDefaultVersionAndProfile,
                            forwardCompatible, messages, intermediate, parser,
                            forwardCompatible, messages, intermediate, parser,
-                           false, includer);
+                           false, includer, "", environment);
 }
 }
 #endif
 #endif
 
 
@@ -1757,6 +1767,7 @@ TShader::TShader(EShLanguage s)
     // clear environment (avoid constructors in them for use in a C interface)
     // clear environment (avoid constructors in them for use in a C interface)
     environment.input.languageFamily = EShSourceNone;
     environment.input.languageFamily = EShSourceNone;
     environment.input.dialect = EShClientNone;
     environment.input.dialect = EShClientNone;
+    environment.input.vulkanRulesRelaxed = false;
     environment.client.client = EShClientNone;
     environment.client.client = EShClientNone;
     environment.target.language = EShTargetNone;
     environment.target.language = EShTargetNone;
     environment.target.hlslFunctionality1 = false;
     environment.target.hlslFunctionality1 = false;
@@ -1810,6 +1821,11 @@ void TShader::addProcesses(const std::vector<std::string>& p)
     intermediate->addProcesses(p);
     intermediate->addProcesses(p);
 }
 }
 
 
+void  TShader::setUniqueId(unsigned long long id)
+{
+    intermediate->setUniqueId(id);
+}
+
 void TShader::setInvertY(bool invert)                   { intermediate->setInvertY(invert); }
 void TShader::setInvertY(bool invert)                   { intermediate->setInvertY(invert); }
 void TShader::setNanMinMaxClamp(bool useNonNan)         { intermediate->setNanMinMaxClamp(useNonNan); }
 void TShader::setNanMinMaxClamp(bool useNonNan)         { intermediate->setNanMinMaxClamp(useNonNan); }
 
 
@@ -1858,6 +1874,15 @@ void TShader::setResourceSetBinding(const std::vector<std::string>& base)   { in
 void TShader::setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { intermediate->setTextureSamplerTransformMode(mode); }
 void TShader::setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { intermediate->setTextureSamplerTransformMode(mode); }
 #endif
 #endif
 
 
+void TShader::addBlockStorageOverride(const char* nameStr, TBlockStorageClass backing) { intermediate->addBlockStorageOverride(nameStr, backing); }
+
+void TShader::setGlobalUniformBlockName(const char* name) { intermediate->setGlobalUniformBlockName(name); }
+void TShader::setGlobalUniformSet(unsigned int set) { intermediate->setGlobalUniformSet(set); }
+void TShader::setGlobalUniformBinding(unsigned int binding) { intermediate->setGlobalUniformBinding(binding); }
+
+void TShader::setAtomicCounterBlockName(const char* name) { intermediate->setAtomicCounterBlockName(name); }
+void TShader::setAtomicCounterBlockSet(unsigned int set) { intermediate->setAtomicCounterBlockSet(set); }
+
 #ifdef ENABLE_HLSL
 #ifdef ENABLE_HLSL
 // See comment above TDefaultHlslIoMapper in iomapper.cpp:
 // See comment above TDefaultHlslIoMapper in iomapper.cpp:
 void TShader::setHlslIoMapping(bool hlslIoMap)          { intermediate->setHlslIoMapping(hlslIoMap); }
 void TShader::setHlslIoMapping(bool hlslIoMap)          { intermediate->setHlslIoMapping(hlslIoMap); }
@@ -1909,7 +1934,8 @@ bool TShader::preprocess(const TBuiltInResource* builtInResources,
     return PreprocessDeferred(compiler, strings, numStrings, lengths, stringNames, preamble,
     return PreprocessDeferred(compiler, strings, numStrings, lengths, stringNames, preamble,
                               EShOptNone, builtInResources, defaultVersion,
                               EShOptNone, builtInResources, defaultVersion,
                               defaultProfile, forceDefaultVersionAndProfile,
                               defaultProfile, forceDefaultVersionAndProfile,
-                              forwardCompatible, message, includer, *intermediate, output_string);
+                              forwardCompatible, message, includer, *intermediate, output_string,
+                              &environment);
 }
 }
 #endif
 #endif
 
 
@@ -1972,7 +1998,10 @@ bool TProgram::link(EShMessages messages)
             error = true;
             error = true;
     }
     }
 
 
-    // TODO: Link: cross-stage error checking
+    if (!error) {
+        if (! crossStageCheck(messages))
+            error = true;
+    }
 
 
     return ! error;
     return ! error;
 }
 }
@@ -2016,7 +2045,7 @@ bool TProgram::linkStage(EShLanguage stage, EShMessages messages)
         intermediate[stage] = new TIntermediate(stage,
         intermediate[stage] = new TIntermediate(stage,
                                                 firstIntermediate->getVersion(),
                                                 firstIntermediate->getVersion(),
                                                 firstIntermediate->getProfile());
                                                 firstIntermediate->getProfile());
-
+        intermediate[stage]->setLimits(firstIntermediate->getLimits());
 
 
         // The new TIntermediate must use the same origin as the original TIntermediates.
         // The new TIntermediate must use the same origin as the original TIntermediates.
         // Otherwise linking will fail due to different coordinate systems.
         // Otherwise linking will fail due to different coordinate systems.
@@ -2049,6 +2078,69 @@ bool TProgram::linkStage(EShLanguage stage, EShMessages messages)
     return intermediate[stage]->getNumErrors() == 0;
     return intermediate[stage]->getNumErrors() == 0;
 }
 }
 
 
+//
+// Check that there are no errors in linker objects accross stages
+//
+// Return true if no errors.
+//
+bool TProgram::crossStageCheck(EShMessages) {
+
+    // make temporary intermediates to hold the linkage symbols for each linking interface
+    // while we do the checks
+    // Independent interfaces are:
+    //                  all uniform variables and blocks
+    //                  all buffer blocks
+    //                  all in/out on a stage boundary
+
+    TVector<TIntermediate*> activeStages;
+    for (int s = 0; s < EShLangCount; ++s) {
+        if (intermediate[s])
+            activeStages.push_back(intermediate[s]);
+    }
+
+    // no extra linking if there is only one stage
+    if (! (activeStages.size() > 1))
+        return true;
+
+    // setup temporary tree to hold unfirom objects from different stages
+    TIntermediate* firstIntermediate = activeStages.front();
+    TIntermediate uniforms(EShLangCount,
+                           firstIntermediate->getVersion(),
+                           firstIntermediate->getProfile());
+    uniforms.setSpv(firstIntermediate->getSpv());
+
+    TIntermAggregate uniformObjects(EOpLinkerObjects);
+    TIntermAggregate root(EOpSequence);
+    root.getSequence().push_back(&uniformObjects);
+    uniforms.setTreeRoot(&root);
+
+    bool error = false;
+
+    // merge uniforms from all stages into a single intermediate
+    for (unsigned int i = 0; i < activeStages.size(); ++i) {
+        uniforms.mergeUniformObjects(*infoSink, *activeStages[i]);
+    }
+    error |= uniforms.getNumErrors() != 0;
+
+    // copy final definition of global block back into each stage
+    for (unsigned int i = 0; i < activeStages.size(); ++i) {
+        // We only want to merge into already existing global uniform blocks.
+        // A stage that doesn't already know about the global doesn't care about it's content.
+        // Otherwise we end up pointing to the same object between different stages
+        // and that will break binding/set remappings
+        bool mergeExistingOnly = true;
+        activeStages[i]->mergeGlobalUniformBlocks(*infoSink, uniforms, mergeExistingOnly);
+    }
+
+    // compare cross stage symbols for each stage boundary
+    for (unsigned int i = 1; i < activeStages.size(); ++i) {
+        activeStages[i - 1]->checkStageIO(*infoSink, *activeStages[i]);
+        error |= (activeStages[i - 1]->getNumErrors() != 0);
+    }
+
+    return !error;
+}
+
 const char* TProgram::getInfoLog()
 const char* TProgram::getInfoLog()
 {
 {
     return infoSink->info.c_str();
     return infoSink->info.c_str();

+ 5 - 1
src/libraries/glslang/glslang/MachineIndependent/SymbolTable.cpp

@@ -85,6 +85,8 @@ void TType::buildMangledName(TString& mangledName) const
 #endif
 #endif
         case EbtInt:   mangledName += "i"; break;
         case EbtInt:   mangledName += "i"; break;
         case EbtUint:  mangledName += "u"; break;
         case EbtUint:  mangledName += "u"; break;
+        case EbtInt64:   mangledName += "i64"; break;
+        case EbtUint64:  mangledName += "u64"; break;
         default: break; // some compilers want this
         default: break; // some compilers want this
         }
         }
         if (sampler.isImageClass())
         if (sampler.isImageClass())
@@ -146,6 +148,8 @@ void TType::buildMangledName(TString& mangledName) const
         if (typeName)
         if (typeName)
             mangledName += *typeName;
             mangledName += *typeName;
         for (unsigned int i = 0; i < structure->size(); ++i) {
         for (unsigned int i = 0; i < structure->size(); ++i) {
+            if ((*structure)[i].type->getBasicType() == EbtVoid)
+                continue;
             mangledName += '-';
             mangledName += '-';
             (*structure)[i].type->buildMangledName(mangledName);
             (*structure)[i].type->buildMangledName(mangledName);
         }
         }
@@ -166,7 +170,7 @@ void TType::buildMangledName(TString& mangledName) const
         for (int i = 0; i < arraySizes->getNumDims(); ++i) {
         for (int i = 0; i < arraySizes->getNumDims(); ++i) {
             if (arraySizes->getDimNode(i)) {
             if (arraySizes->getDimNode(i)) {
                 if (arraySizes->getDimNode(i)->getAsSymbolNode())
                 if (arraySizes->getDimNode(i)->getAsSymbolNode())
-                    snprintf(buf, maxSize, "s%d", arraySizes->getDimNode(i)->getAsSymbolNode()->getId());
+                    snprintf(buf, maxSize, "s%lld", arraySizes->getDimNode(i)->getAsSymbolNode()->getId());
                 else
                 else
                     snprintf(buf, maxSize, "s%p", arraySizes->getDimNode(i));
                     snprintf(buf, maxSize, "s%p", arraySizes->getDimNode(i));
             } else
             } else

+ 42 - 10
src/libraries/glslang/glslang/MachineIndependent/SymbolTable.h

@@ -104,8 +104,8 @@ public:
     virtual const TAnonMember* getAsAnonMember() const { return 0; }
     virtual const TAnonMember* getAsAnonMember() const { return 0; }
     virtual const TType& getType() const = 0;
     virtual const TType& getType() const = 0;
     virtual TType& getWritableType() = 0;
     virtual TType& getWritableType() = 0;
-    virtual void setUniqueId(int id) { uniqueId = id; }
-    virtual int getUniqueId() const { return uniqueId; }
+    virtual void setUniqueId(long long id) { uniqueId = id; }
+    virtual long long getUniqueId() const { return uniqueId; }
     virtual void setExtensions(int numExts, const char* const exts[])
     virtual void setExtensions(int numExts, const char* const exts[])
     {
     {
         assert(extensions == 0);
         assert(extensions == 0);
@@ -130,7 +130,7 @@ protected:
     TSymbol& operator=(const TSymbol&);
     TSymbol& operator=(const TSymbol&);
 
 
     const TString *name;
     const TString *name;
-    unsigned int uniqueId;      // For cross-scope comparing during code generation
+    unsigned long long uniqueId;      // For cross-scope comparing during code generation
 
 
     // For tracking what extensions must be present
     // For tracking what extensions must be present
     // (don't use if correct version/profile is present).
     // (don't use if correct version/profile is present).
@@ -612,21 +612,28 @@ public:
     //   3: user-shader globals
     //   3: user-shader globals
     //
     //
 protected:
 protected:
+    static const uint32_t LevelFlagBitOffset = 56;
     static const int globalLevel = 3;
     static const int globalLevel = 3;
-    bool isSharedLevel(int level)  { return level <= 1; }              // exclude all per-compile levels
-    bool isBuiltInLevel(int level) { return level <= 2; }              // exclude user globals
-    bool isGlobalLevel(int level)  { return level <= globalLevel; }    // include user globals
+    static bool isSharedLevel(int level)  { return level <= 1; }            // exclude all per-compile levels
+    static bool isBuiltInLevel(int level) { return level <= 2; }            // exclude user globals
+    static bool isGlobalLevel(int level)  { return level <= globalLevel; }  // include user globals
 public:
 public:
     bool isEmpty() { return table.size() == 0; }
     bool isEmpty() { return table.size() == 0; }
     bool atBuiltInLevel() { return isBuiltInLevel(currentLevel()); }
     bool atBuiltInLevel() { return isBuiltInLevel(currentLevel()); }
     bool atGlobalLevel()  { return isGlobalLevel(currentLevel()); }
     bool atGlobalLevel()  { return isGlobalLevel(currentLevel()); }
-
+    static bool isBuiltInSymbol(long long uniqueId) {
+        int level = static_cast<int>(uniqueId >> LevelFlagBitOffset);
+        return isBuiltInLevel(level);
+    }
+    static constexpr uint64_t uniqueIdMask = (1LL << LevelFlagBitOffset) - 1;
+    static const uint32_t MaxLevelInUniqueID = 127;
     void setNoBuiltInRedeclarations() { noBuiltInRedeclarations = true; }
     void setNoBuiltInRedeclarations() { noBuiltInRedeclarations = true; }
     void setSeparateNameSpaces() { separateNameSpaces = true; }
     void setSeparateNameSpaces() { separateNameSpaces = true; }
 
 
     void push()
     void push()
     {
     {
         table.push_back(new TSymbolTableLevel);
         table.push_back(new TSymbolTableLevel);
+        updateUniqueIdLevelFlag();
     }
     }
 
 
     // Make a new symbol-table level to represent the scope introduced by a structure
     // Make a new symbol-table level to represent the scope introduced by a structure
@@ -639,6 +646,7 @@ public:
     {
     {
         assert(thisSymbol.getName().size() == 0);
         assert(thisSymbol.getName().size() == 0);
         table.push_back(new TSymbolTableLevel);
         table.push_back(new TSymbolTableLevel);
+        updateUniqueIdLevelFlag();
         table.back()->setThisLevel();
         table.back()->setThisLevel();
         insert(thisSymbol);
         insert(thisSymbol);
     }
     }
@@ -648,6 +656,7 @@ public:
         table[currentLevel()]->getPreviousDefaultPrecisions(p);
         table[currentLevel()]->getPreviousDefaultPrecisions(p);
         delete table.back();
         delete table.back();
         table.pop_back();
         table.pop_back();
+        updateUniqueIdLevelFlag();
     }
     }
 
 
     //
     //
@@ -685,6 +694,16 @@ public:
         return table[currentLevel()]->amend(symbol, firstNewMember);
         return table[currentLevel()]->amend(symbol, firstNewMember);
     }
     }
 
 
+    // Update the level info in symbol's unique ID to current level
+    void amendSymbolIdLevel(TSymbol& symbol)
+    {
+        // clamp level to avoid overflow
+        uint64_t level = (uint32_t)currentLevel() > MaxLevelInUniqueID ? MaxLevelInUniqueID : currentLevel();
+        uint64_t symbolId = symbol.getUniqueId();
+        symbolId &= uniqueIdMask;
+        symbolId |= (level << LevelFlagBitOffset);
+        symbol.setUniqueId(symbolId);
+    }
     //
     //
     // To allocate an internal temporary, which will need to be uniquely
     // To allocate an internal temporary, which will need to be uniquely
     // identified by the consumer of the AST, but never need to
     // identified by the consumer of the AST, but never need to
@@ -853,7 +872,7 @@ public:
         }
         }
     }
     }
 
 
-    int getMaxSymbolId() { return uniqueId; }
+    long long getMaxSymbolId() { return uniqueId; }
 #if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
 #if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
     void dump(TInfoSink& infoSink, bool complete = false) const;
     void dump(TInfoSink& infoSink, bool complete = false) const;
 #endif
 #endif
@@ -867,14 +886,27 @@ public:
             table[level]->readOnly();
             table[level]->readOnly();
     }
     }
 
 
+    // Add current level in the high-bits of unique id
+    void updateUniqueIdLevelFlag() {
+        // clamp level to avoid overflow
+        uint64_t level = (uint32_t)currentLevel() > MaxLevelInUniqueID ? MaxLevelInUniqueID : currentLevel();
+        uniqueId &= uniqueIdMask;
+        uniqueId |= (level << LevelFlagBitOffset);
+    }
+
+    void overwriteUniqueId(long long id)
+    {
+        uniqueId = id;
+        updateUniqueIdLevelFlag();
+    }
+
 protected:
 protected:
     TSymbolTable(TSymbolTable&);
     TSymbolTable(TSymbolTable&);
     TSymbolTable& operator=(TSymbolTableLevel&);
     TSymbolTable& operator=(TSymbolTableLevel&);
 
 
     int currentLevel() const { return static_cast<int>(table.size()) - 1; }
     int currentLevel() const { return static_cast<int>(table.size()) - 1; }
-
     std::vector<TSymbolTableLevel*> table;
     std::vector<TSymbolTableLevel*> table;
-    int uniqueId;     // for unique identification in code generation
+    long long uniqueId;     // for unique identification in code generation
     bool noBuiltInRedeclarations;
     bool noBuiltInRedeclarations;
     bool separateNameSpaces;
     bool separateNameSpaces;
     unsigned int adoptedLevels;
     unsigned int adoptedLevels;

+ 23 - 3
src/libraries/glslang/glslang/MachineIndependent/Versions.cpp

@@ -306,6 +306,7 @@ void TParseVersions::initializeExtensionBehavior()
     extensionBehavior[E_GL_EXT_tessellation_point_size]              = EBhDisable;
     extensionBehavior[E_GL_EXT_tessellation_point_size]              = EBhDisable;
     extensionBehavior[E_GL_EXT_texture_buffer]                       = EBhDisable;
     extensionBehavior[E_GL_EXT_texture_buffer]                       = EBhDisable;
     extensionBehavior[E_GL_EXT_texture_cube_map_array]               = EBhDisable;
     extensionBehavior[E_GL_EXT_texture_cube_map_array]               = EBhDisable;
+    extensionBehavior[E_GL_EXT_null_initializer]                     = EBhDisable;
 
 
     // OES matching AEP
     // OES matching AEP
     extensionBehavior[E_GL_OES_geometry_shader]          = EBhDisable;
     extensionBehavior[E_GL_OES_geometry_shader]          = EBhDisable;
@@ -328,6 +329,10 @@ void TParseVersions::initializeExtensionBehavior()
     extensionBehavior[E_GL_EXT_ray_flags_primitive_culling] = EBhDisable;
     extensionBehavior[E_GL_EXT_ray_flags_primitive_culling] = EBhDisable;
     extensionBehavior[E_GL_EXT_blend_func_extended]         = EBhDisable;
     extensionBehavior[E_GL_EXT_blend_func_extended]         = EBhDisable;
     extensionBehavior[E_GL_EXT_shader_implicit_conversions] = EBhDisable;
     extensionBehavior[E_GL_EXT_shader_implicit_conversions] = EBhDisable;
+    extensionBehavior[E_GL_EXT_fragment_shading_rate]       = EBhDisable;
+    extensionBehavior[E_GL_EXT_shader_image_int64]   = EBhDisable;
+    extensionBehavior[E_GL_EXT_terminate_invocation]        = EBhDisable;
+    extensionBehavior[E_GL_EXT_shared_memory_block]         = EBhDisable;
 
 
     // OVR extensions
     // OVR extensions
     extensionBehavior[E_GL_OVR_multiview]                = EBhDisable;
     extensionBehavior[E_GL_OVR_multiview]                = EBhDisable;
@@ -373,6 +378,7 @@ void TParseVersions::getPreamble(std::string& preamble)
             "#define GL_EXT_YUV_target 1\n"
             "#define GL_EXT_YUV_target 1\n"
             "#define GL_EXT_shader_texture_lod 1\n"
             "#define GL_EXT_shader_texture_lod 1\n"
             "#define GL_EXT_shadow_samplers 1\n"
             "#define GL_EXT_shadow_samplers 1\n"
+            "#define GL_EXT_fragment_shading_rate 1\n"
 
 
             // AEP
             // AEP
             "#define GL_ANDROID_extension_pack_es31a 1\n"
             "#define GL_ANDROID_extension_pack_es31a 1\n"
@@ -406,11 +412,14 @@ void TParseVersions::getPreamble(std::string& preamble)
             "#define GL_EXT_shader_non_constant_global_initializers 1\n"
             "#define GL_EXT_shader_non_constant_global_initializers 1\n"
             ;
             ;
 
 
-            if (isEsProfile() && version >= 300) {
+            if (version >= 300) {
                 preamble += "#define GL_NV_shader_noperspective_interpolation 1\n";
                 preamble += "#define GL_NV_shader_noperspective_interpolation 1\n";
             }
             }
+            if (version >= 310) {
+                preamble += "#define GL_EXT_null_initializer 1\n";
+            }
 
 
-    } else {
+    } else { // !isEsProfile()
         preamble =
         preamble =
             "#define GL_FRAGMENT_PRECISION_HIGH 1\n"
             "#define GL_FRAGMENT_PRECISION_HIGH 1\n"
             "#define GL_EXT_texture_array 1\n"
             "#define GL_EXT_texture_array 1\n"
@@ -466,6 +475,8 @@ void TParseVersions::getPreamble(std::string& preamble)
             "#define GL_EXT_buffer_reference_uvec2 1\n"
             "#define GL_EXT_buffer_reference_uvec2 1\n"
             "#define GL_EXT_demote_to_helper_invocation 1\n"
             "#define GL_EXT_demote_to_helper_invocation 1\n"
             "#define GL_EXT_debug_printf 1\n"
             "#define GL_EXT_debug_printf 1\n"
+            "#define GL_EXT_fragment_shading_rate 1\n"
+            "#define GL_EXT_shared_memory_block 1\n"
 
 
             // GL_KHR_shader_subgroup
             // GL_KHR_shader_subgroup
             "#define GL_KHR_shader_subgroup_basic 1\n"
             "#define GL_KHR_shader_subgroup_basic 1\n"
@@ -477,6 +488,7 @@ void TParseVersions::getPreamble(std::string& preamble)
             "#define GL_KHR_shader_subgroup_clustered 1\n"
             "#define GL_KHR_shader_subgroup_clustered 1\n"
             "#define GL_KHR_shader_subgroup_quad 1\n"
             "#define GL_KHR_shader_subgroup_quad 1\n"
 
 
+            "#define GL_EXT_shader_image_int64 1\n"
             "#define GL_EXT_shader_atomic_int64 1\n"
             "#define GL_EXT_shader_atomic_int64 1\n"
             "#define GL_EXT_shader_realtime_clock 1\n"
             "#define GL_EXT_shader_realtime_clock 1\n"
             "#define GL_EXT_ray_tracing 1\n"
             "#define GL_EXT_ray_tracing 1\n"
@@ -535,6 +547,9 @@ void TParseVersions::getPreamble(std::string& preamble)
             if (profile == ECompatibilityProfile)
             if (profile == ECompatibilityProfile)
                 preamble += "#define GL_compatibility_profile 1\n";
                 preamble += "#define GL_compatibility_profile 1\n";
         }
         }
+        if (version >= 140) {
+            preamble += "#define GL_EXT_null_initializer 1\n";
+        }
 #endif // GLSLANG_WEB
 #endif // GLSLANG_WEB
     }
     }
 
 
@@ -561,6 +576,11 @@ void TParseVersions::getPreamble(std::string& preamble)
             "#define GL_GOOGLE_include_directive 1\n"
             "#define GL_GOOGLE_include_directive 1\n"
             "#define GL_KHR_blend_equation_advanced 1\n"
             "#define GL_KHR_blend_equation_advanced 1\n"
             ;
             ;
+
+    // other general extensions
+    preamble +=
+            "#define GL_EXT_terminate_invocation 1\n"
+            ;
 #endif
 #endif
 
 
     // #define VULKAN XXXX
     // #define VULKAN XXXX
@@ -1256,7 +1276,7 @@ void TParseVersions::spvRemoved(const TSourceLoc& loc, const char* op)
 // Call for any operation removed because Vulkan SPIR-V is being generated.
 // Call for any operation removed because Vulkan SPIR-V is being generated.
 void TParseVersions::vulkanRemoved(const TSourceLoc& loc, const char* op)
 void TParseVersions::vulkanRemoved(const TSourceLoc& loc, const char* op)
 {
 {
-    if (spvVersion.vulkan > 0)
+    if (spvVersion.vulkan > 0 && !spvVersion.vulkanRelaxed)
         error(loc, "not allowed when using GLSL for Vulkan", op, "");
         error(loc, "not allowed when using GLSL for Vulkan", op, "");
 }
 }
 
 

+ 7 - 1
src/libraries/glslang/glslang/MachineIndependent/Versions.h

@@ -87,11 +87,12 @@ inline const char* ProfileName(EProfile profile)
 // The union of all requested rule sets will be applied.
 // The union of all requested rule sets will be applied.
 //
 //
 struct SpvVersion {
 struct SpvVersion {
-    SpvVersion() : spv(0), vulkanGlsl(0), vulkan(0), openGl(0) {}
+    SpvVersion() : spv(0), vulkanGlsl(0), vulkan(0), openGl(0), vulkanRelaxed(false) {}
     unsigned int spv; // the version of SPIR-V to target, as defined by "word 1" of the SPIR-V binary header
     unsigned int spv; // the version of SPIR-V to target, as defined by "word 1" of the SPIR-V binary header
     int vulkanGlsl;   // the version of GLSL semantics for Vulkan, from GL_KHR_vulkan_glsl, for "#define VULKAN XXX"
     int vulkanGlsl;   // the version of GLSL semantics for Vulkan, from GL_KHR_vulkan_glsl, for "#define VULKAN XXX"
     int vulkan;       // the version of Vulkan, for which SPIR-V execution environment rules to use
     int vulkan;       // the version of Vulkan, for which SPIR-V execution environment rules to use
     int openGl;       // the version of GLSL semantics for OpenGL, from GL_ARB_gl_spirv, for "#define GL_SPIRV XXX"
     int openGl;       // the version of GLSL semantics for OpenGL, from GL_ARB_gl_spirv, for "#define GL_SPIRV XXX"
+    bool vulkanRelaxed; // relax changes to GLSL for Vulkan, allowing some GL-specific to be compiled to Vulkan SPIR-V target
 };
 };
 
 
 //
 //
@@ -200,6 +201,10 @@ const char* const E_GL_EXT_ray_query                        = "GL_EXT_ray_query"
 const char* const E_GL_EXT_ray_flags_primitive_culling      = "GL_EXT_ray_flags_primitive_culling";
 const char* const E_GL_EXT_ray_flags_primitive_culling      = "GL_EXT_ray_flags_primitive_culling";
 const char* const E_GL_EXT_blend_func_extended              = "GL_EXT_blend_func_extended";
 const char* const E_GL_EXT_blend_func_extended              = "GL_EXT_blend_func_extended";
 const char* const E_GL_EXT_shader_implicit_conversions      = "GL_EXT_shader_implicit_conversions";
 const char* const E_GL_EXT_shader_implicit_conversions      = "GL_EXT_shader_implicit_conversions";
+const char* const E_GL_EXT_fragment_shading_rate            = "GL_EXT_fragment_shading_rate";
+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_shared_memory_block              = "GL_EXT_shared_memory_block";
 
 
 // Arrays of extensions for the above viewportEXTs duplications
 // Arrays of extensions for the above viewportEXTs duplications
 
 
@@ -298,6 +303,7 @@ const char* const E_GL_EXT_shader_subgroup_extended_types_int8    = "GL_EXT_shad
 const char* const E_GL_EXT_shader_subgroup_extended_types_int16   = "GL_EXT_shader_subgroup_extended_types_int16";
 const char* const E_GL_EXT_shader_subgroup_extended_types_int16   = "GL_EXT_shader_subgroup_extended_types_int16";
 const char* const E_GL_EXT_shader_subgroup_extended_types_int64   = "GL_EXT_shader_subgroup_extended_types_int64";
 const char* const E_GL_EXT_shader_subgroup_extended_types_int64   = "GL_EXT_shader_subgroup_extended_types_int64";
 const char* const E_GL_EXT_shader_subgroup_extended_types_float16 = "GL_EXT_shader_subgroup_extended_types_float16";
 const char* const E_GL_EXT_shader_subgroup_extended_types_float16 = "GL_EXT_shader_subgroup_extended_types_float16";
+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";
 
 

+ 3 - 3
src/libraries/glslang/glslang/MachineIndependent/gl_types.h

@@ -49,9 +49,9 @@
 #define GL_INT64_VEC4_ARB                 0x8FEB
 #define GL_INT64_VEC4_ARB                 0x8FEB
 
 
 #define GL_UNSIGNED_INT64_ARB             0x140F
 #define GL_UNSIGNED_INT64_ARB             0x140F
-#define GL_UNSIGNED_INT64_VEC2_ARB        0x8FE5
-#define GL_UNSIGNED_INT64_VEC3_ARB        0x8FE6
-#define GL_UNSIGNED_INT64_VEC4_ARB        0x8FE7
+#define GL_UNSIGNED_INT64_VEC2_ARB        0x8FF5
+#define GL_UNSIGNED_INT64_VEC3_ARB        0x8FF6
+#define GL_UNSIGNED_INT64_VEC4_ARB        0x8FF7
 #define GL_UNSIGNED_INT16_VEC2_NV         0x8FF1
 #define GL_UNSIGNED_INT16_VEC2_NV         0x8FF1
 #define GL_UNSIGNED_INT16_VEC3_NV         0x8FF2
 #define GL_UNSIGNED_INT16_VEC3_NV         0x8FF2
 #define GL_UNSIGNED_INT16_VEC4_NV         0x8FF3
 #define GL_UNSIGNED_INT16_VEC4_NV         0x8FF3

File diff suppressed because it is too large
+ 593 - 510
src/libraries/glslang/glslang/MachineIndependent/glslang_tab.cpp


+ 458 - 424
src/libraries/glslang/glslang/MachineIndependent/glslang_tab.cpp.h

@@ -1,8 +1,9 @@
-/* A Bison parser, made by GNU Bison 3.0.4.  */
+/* A Bison parser, made by GNU Bison 3.7.4.  */
 
 
 /* Bison interface for Yacc-like parsers in C
 /* Bison interface for Yacc-like parsers in C
 
 
-   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+   Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation,
+   Inc.
 
 
    This program is free software: you can redistribute it and/or modify
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    it under the terms of the GNU General Public License as published by
@@ -30,6 +31,10 @@
    This special exception was added by the Free Software Foundation in
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
    version 2.2 of Bison.  */
 
 
+/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual,
+   especially those whose name start with YY_ or yy_.  They are
+   private implementation details that can be changed or removed.  */
+
 #ifndef YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED
 #ifndef YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED
 # define YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED
 # define YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED
 /* Debug traces.  */
 /* Debug traces.  */
@@ -40,437 +45,466 @@
 extern int yydebug;
 extern int yydebug;
 #endif
 #endif
 
 
-/* Token type.  */
+/* Token kinds.  */
 #ifndef YYTOKENTYPE
 #ifndef YYTOKENTYPE
 # define YYTOKENTYPE
 # define YYTOKENTYPE
   enum yytokentype
   enum yytokentype
   {
   {
-    CONST = 258,
-    BOOL = 259,
-    INT = 260,
-    UINT = 261,
-    FLOAT = 262,
-    BVEC2 = 263,
-    BVEC3 = 264,
-    BVEC4 = 265,
-    IVEC2 = 266,
-    IVEC3 = 267,
-    IVEC4 = 268,
-    UVEC2 = 269,
-    UVEC3 = 270,
-    UVEC4 = 271,
-    VEC2 = 272,
-    VEC3 = 273,
-    VEC4 = 274,
-    MAT2 = 275,
-    MAT3 = 276,
-    MAT4 = 277,
-    MAT2X2 = 278,
-    MAT2X3 = 279,
-    MAT2X4 = 280,
-    MAT3X2 = 281,
-    MAT3X3 = 282,
-    MAT3X4 = 283,
-    MAT4X2 = 284,
-    MAT4X3 = 285,
-    MAT4X4 = 286,
-    SAMPLER2D = 287,
-    SAMPLER3D = 288,
-    SAMPLERCUBE = 289,
-    SAMPLER2DSHADOW = 290,
-    SAMPLERCUBESHADOW = 291,
-    SAMPLER2DARRAY = 292,
-    SAMPLER2DARRAYSHADOW = 293,
-    ISAMPLER2D = 294,
-    ISAMPLER3D = 295,
-    ISAMPLERCUBE = 296,
-    ISAMPLER2DARRAY = 297,
-    USAMPLER2D = 298,
-    USAMPLER3D = 299,
-    USAMPLERCUBE = 300,
-    USAMPLER2DARRAY = 301,
-    SAMPLER = 302,
-    SAMPLERSHADOW = 303,
-    TEXTURE2D = 304,
-    TEXTURE3D = 305,
-    TEXTURECUBE = 306,
-    TEXTURE2DARRAY = 307,
-    ITEXTURE2D = 308,
-    ITEXTURE3D = 309,
-    ITEXTURECUBE = 310,
-    ITEXTURE2DARRAY = 311,
-    UTEXTURE2D = 312,
-    UTEXTURE3D = 313,
-    UTEXTURECUBE = 314,
-    UTEXTURE2DARRAY = 315,
-    ATTRIBUTE = 316,
-    VARYING = 317,
-    FLOAT16_T = 318,
-    FLOAT32_T = 319,
-    DOUBLE = 320,
-    FLOAT64_T = 321,
-    INT64_T = 322,
-    UINT64_T = 323,
-    INT32_T = 324,
-    UINT32_T = 325,
-    INT16_T = 326,
-    UINT16_T = 327,
-    INT8_T = 328,
-    UINT8_T = 329,
-    I64VEC2 = 330,
-    I64VEC3 = 331,
-    I64VEC4 = 332,
-    U64VEC2 = 333,
-    U64VEC3 = 334,
-    U64VEC4 = 335,
-    I32VEC2 = 336,
-    I32VEC3 = 337,
-    I32VEC4 = 338,
-    U32VEC2 = 339,
-    U32VEC3 = 340,
-    U32VEC4 = 341,
-    I16VEC2 = 342,
-    I16VEC3 = 343,
-    I16VEC4 = 344,
-    U16VEC2 = 345,
-    U16VEC3 = 346,
-    U16VEC4 = 347,
-    I8VEC2 = 348,
-    I8VEC3 = 349,
-    I8VEC4 = 350,
-    U8VEC2 = 351,
-    U8VEC3 = 352,
-    U8VEC4 = 353,
-    DVEC2 = 354,
-    DVEC3 = 355,
-    DVEC4 = 356,
-    DMAT2 = 357,
-    DMAT3 = 358,
-    DMAT4 = 359,
-    F16VEC2 = 360,
-    F16VEC3 = 361,
-    F16VEC4 = 362,
-    F16MAT2 = 363,
-    F16MAT3 = 364,
-    F16MAT4 = 365,
-    F32VEC2 = 366,
-    F32VEC3 = 367,
-    F32VEC4 = 368,
-    F32MAT2 = 369,
-    F32MAT3 = 370,
-    F32MAT4 = 371,
-    F64VEC2 = 372,
-    F64VEC3 = 373,
-    F64VEC4 = 374,
-    F64MAT2 = 375,
-    F64MAT3 = 376,
-    F64MAT4 = 377,
-    DMAT2X2 = 378,
-    DMAT2X3 = 379,
-    DMAT2X4 = 380,
-    DMAT3X2 = 381,
-    DMAT3X3 = 382,
-    DMAT3X4 = 383,
-    DMAT4X2 = 384,
-    DMAT4X3 = 385,
-    DMAT4X4 = 386,
-    F16MAT2X2 = 387,
-    F16MAT2X3 = 388,
-    F16MAT2X4 = 389,
-    F16MAT3X2 = 390,
-    F16MAT3X3 = 391,
-    F16MAT3X4 = 392,
-    F16MAT4X2 = 393,
-    F16MAT4X3 = 394,
-    F16MAT4X4 = 395,
-    F32MAT2X2 = 396,
-    F32MAT2X3 = 397,
-    F32MAT2X4 = 398,
-    F32MAT3X2 = 399,
-    F32MAT3X3 = 400,
-    F32MAT3X4 = 401,
-    F32MAT4X2 = 402,
-    F32MAT4X3 = 403,
-    F32MAT4X4 = 404,
-    F64MAT2X2 = 405,
-    F64MAT2X3 = 406,
-    F64MAT2X4 = 407,
-    F64MAT3X2 = 408,
-    F64MAT3X3 = 409,
-    F64MAT3X4 = 410,
-    F64MAT4X2 = 411,
-    F64MAT4X3 = 412,
-    F64MAT4X4 = 413,
-    ATOMIC_UINT = 414,
-    ACCSTRUCTNV = 415,
-    ACCSTRUCTEXT = 416,
-    RAYQUERYEXT = 417,
-    FCOOPMATNV = 418,
-    ICOOPMATNV = 419,
-    UCOOPMATNV = 420,
-    SAMPLERCUBEARRAY = 421,
-    SAMPLERCUBEARRAYSHADOW = 422,
-    ISAMPLERCUBEARRAY = 423,
-    USAMPLERCUBEARRAY = 424,
-    SAMPLER1D = 425,
-    SAMPLER1DARRAY = 426,
-    SAMPLER1DARRAYSHADOW = 427,
-    ISAMPLER1D = 428,
-    SAMPLER1DSHADOW = 429,
-    SAMPLER2DRECT = 430,
-    SAMPLER2DRECTSHADOW = 431,
-    ISAMPLER2DRECT = 432,
-    USAMPLER2DRECT = 433,
-    SAMPLERBUFFER = 434,
-    ISAMPLERBUFFER = 435,
-    USAMPLERBUFFER = 436,
-    SAMPLER2DMS = 437,
-    ISAMPLER2DMS = 438,
-    USAMPLER2DMS = 439,
-    SAMPLER2DMSARRAY = 440,
-    ISAMPLER2DMSARRAY = 441,
-    USAMPLER2DMSARRAY = 442,
-    SAMPLEREXTERNALOES = 443,
-    SAMPLEREXTERNAL2DY2YEXT = 444,
-    ISAMPLER1DARRAY = 445,
-    USAMPLER1D = 446,
-    USAMPLER1DARRAY = 447,
-    F16SAMPLER1D = 448,
-    F16SAMPLER2D = 449,
-    F16SAMPLER3D = 450,
-    F16SAMPLER2DRECT = 451,
-    F16SAMPLERCUBE = 452,
-    F16SAMPLER1DARRAY = 453,
-    F16SAMPLER2DARRAY = 454,
-    F16SAMPLERCUBEARRAY = 455,
-    F16SAMPLERBUFFER = 456,
-    F16SAMPLER2DMS = 457,
-    F16SAMPLER2DMSARRAY = 458,
-    F16SAMPLER1DSHADOW = 459,
-    F16SAMPLER2DSHADOW = 460,
-    F16SAMPLER1DARRAYSHADOW = 461,
-    F16SAMPLER2DARRAYSHADOW = 462,
-    F16SAMPLER2DRECTSHADOW = 463,
-    F16SAMPLERCUBESHADOW = 464,
-    F16SAMPLERCUBEARRAYSHADOW = 465,
-    IMAGE1D = 466,
-    IIMAGE1D = 467,
-    UIMAGE1D = 468,
-    IMAGE2D = 469,
-    IIMAGE2D = 470,
-    UIMAGE2D = 471,
-    IMAGE3D = 472,
-    IIMAGE3D = 473,
-    UIMAGE3D = 474,
-    IMAGE2DRECT = 475,
-    IIMAGE2DRECT = 476,
-    UIMAGE2DRECT = 477,
-    IMAGECUBE = 478,
-    IIMAGECUBE = 479,
-    UIMAGECUBE = 480,
-    IMAGEBUFFER = 481,
-    IIMAGEBUFFER = 482,
-    UIMAGEBUFFER = 483,
-    IMAGE1DARRAY = 484,
-    IIMAGE1DARRAY = 485,
-    UIMAGE1DARRAY = 486,
-    IMAGE2DARRAY = 487,
-    IIMAGE2DARRAY = 488,
-    UIMAGE2DARRAY = 489,
-    IMAGECUBEARRAY = 490,
-    IIMAGECUBEARRAY = 491,
-    UIMAGECUBEARRAY = 492,
-    IMAGE2DMS = 493,
-    IIMAGE2DMS = 494,
-    UIMAGE2DMS = 495,
-    IMAGE2DMSARRAY = 496,
-    IIMAGE2DMSARRAY = 497,
-    UIMAGE2DMSARRAY = 498,
-    F16IMAGE1D = 499,
-    F16IMAGE2D = 500,
-    F16IMAGE3D = 501,
-    F16IMAGE2DRECT = 502,
-    F16IMAGECUBE = 503,
-    F16IMAGE1DARRAY = 504,
-    F16IMAGE2DARRAY = 505,
-    F16IMAGECUBEARRAY = 506,
-    F16IMAGEBUFFER = 507,
-    F16IMAGE2DMS = 508,
-    F16IMAGE2DMSARRAY = 509,
-    TEXTURECUBEARRAY = 510,
-    ITEXTURECUBEARRAY = 511,
-    UTEXTURECUBEARRAY = 512,
-    TEXTURE1D = 513,
-    ITEXTURE1D = 514,
-    UTEXTURE1D = 515,
-    TEXTURE1DARRAY = 516,
-    ITEXTURE1DARRAY = 517,
-    UTEXTURE1DARRAY = 518,
-    TEXTURE2DRECT = 519,
-    ITEXTURE2DRECT = 520,
-    UTEXTURE2DRECT = 521,
-    TEXTUREBUFFER = 522,
-    ITEXTUREBUFFER = 523,
-    UTEXTUREBUFFER = 524,
-    TEXTURE2DMS = 525,
-    ITEXTURE2DMS = 526,
-    UTEXTURE2DMS = 527,
-    TEXTURE2DMSARRAY = 528,
-    ITEXTURE2DMSARRAY = 529,
-    UTEXTURE2DMSARRAY = 530,
-    F16TEXTURE1D = 531,
-    F16TEXTURE2D = 532,
-    F16TEXTURE3D = 533,
-    F16TEXTURE2DRECT = 534,
-    F16TEXTURECUBE = 535,
-    F16TEXTURE1DARRAY = 536,
-    F16TEXTURE2DARRAY = 537,
-    F16TEXTURECUBEARRAY = 538,
-    F16TEXTUREBUFFER = 539,
-    F16TEXTURE2DMS = 540,
-    F16TEXTURE2DMSARRAY = 541,
-    SUBPASSINPUT = 542,
-    SUBPASSINPUTMS = 543,
-    ISUBPASSINPUT = 544,
-    ISUBPASSINPUTMS = 545,
-    USUBPASSINPUT = 546,
-    USUBPASSINPUTMS = 547,
-    F16SUBPASSINPUT = 548,
-    F16SUBPASSINPUTMS = 549,
-    LEFT_OP = 550,
-    RIGHT_OP = 551,
-    INC_OP = 552,
-    DEC_OP = 553,
-    LE_OP = 554,
-    GE_OP = 555,
-    EQ_OP = 556,
-    NE_OP = 557,
-    AND_OP = 558,
-    OR_OP = 559,
-    XOR_OP = 560,
-    MUL_ASSIGN = 561,
-    DIV_ASSIGN = 562,
-    ADD_ASSIGN = 563,
-    MOD_ASSIGN = 564,
-    LEFT_ASSIGN = 565,
-    RIGHT_ASSIGN = 566,
-    AND_ASSIGN = 567,
-    XOR_ASSIGN = 568,
-    OR_ASSIGN = 569,
-    SUB_ASSIGN = 570,
-    STRING_LITERAL = 571,
-    LEFT_PAREN = 572,
-    RIGHT_PAREN = 573,
-    LEFT_BRACKET = 574,
-    RIGHT_BRACKET = 575,
-    LEFT_BRACE = 576,
-    RIGHT_BRACE = 577,
-    DOT = 578,
-    COMMA = 579,
-    COLON = 580,
-    EQUAL = 581,
-    SEMICOLON = 582,
-    BANG = 583,
-    DASH = 584,
-    TILDE = 585,
-    PLUS = 586,
-    STAR = 587,
-    SLASH = 588,
-    PERCENT = 589,
-    LEFT_ANGLE = 590,
-    RIGHT_ANGLE = 591,
-    VERTICAL_BAR = 592,
-    CARET = 593,
-    AMPERSAND = 594,
-    QUESTION = 595,
-    INVARIANT = 596,
-    HIGH_PRECISION = 597,
-    MEDIUM_PRECISION = 598,
-    LOW_PRECISION = 599,
-    PRECISION = 600,
-    PACKED = 601,
-    RESOURCE = 602,
-    SUPERP = 603,
-    FLOATCONSTANT = 604,
-    INTCONSTANT = 605,
-    UINTCONSTANT = 606,
-    BOOLCONSTANT = 607,
-    IDENTIFIER = 608,
-    TYPE_NAME = 609,
-    CENTROID = 610,
-    IN = 611,
-    OUT = 612,
-    INOUT = 613,
-    STRUCT = 614,
-    VOID = 615,
-    WHILE = 616,
-    BREAK = 617,
-    CONTINUE = 618,
-    DO = 619,
-    ELSE = 620,
-    FOR = 621,
-    IF = 622,
-    DISCARD = 623,
-    RETURN = 624,
-    SWITCH = 625,
-    CASE = 626,
-    DEFAULT = 627,
-    UNIFORM = 628,
-    SHARED = 629,
-    BUFFER = 630,
-    FLAT = 631,
-    SMOOTH = 632,
-    LAYOUT = 633,
-    DOUBLECONSTANT = 634,
-    INT16CONSTANT = 635,
-    UINT16CONSTANT = 636,
-    FLOAT16CONSTANT = 637,
-    INT32CONSTANT = 638,
-    UINT32CONSTANT = 639,
-    INT64CONSTANT = 640,
-    UINT64CONSTANT = 641,
-    SUBROUTINE = 642,
-    DEMOTE = 643,
-    PAYLOADNV = 644,
-    PAYLOADINNV = 645,
-    HITATTRNV = 646,
-    CALLDATANV = 647,
-    CALLDATAINNV = 648,
-    PAYLOADEXT = 649,
-    PAYLOADINEXT = 650,
-    HITATTREXT = 651,
-    CALLDATAEXT = 652,
-    CALLDATAINEXT = 653,
-    PATCH = 654,
-    SAMPLE = 655,
-    NONUNIFORM = 656,
-    COHERENT = 657,
-    VOLATILE = 658,
-    RESTRICT = 659,
-    READONLY = 660,
-    WRITEONLY = 661,
-    DEVICECOHERENT = 662,
-    QUEUEFAMILYCOHERENT = 663,
-    WORKGROUPCOHERENT = 664,
-    SUBGROUPCOHERENT = 665,
-    NONPRIVATE = 666,
-    SHADERCALLCOHERENT = 667,
-    NOPERSPECTIVE = 668,
-    EXPLICITINTERPAMD = 669,
-    PERVERTEXNV = 670,
-    PERPRIMITIVENV = 671,
-    PERVIEWNV = 672,
-    PERTASKNV = 673,
-    PRECISE = 674
+    YYEMPTY = -2,
+    YYEOF = 0,                     /* "end of file"  */
+    YYerror = 256,                 /* error  */
+    YYUNDEF = 257,                 /* "invalid token"  */
+    CONST = 258,                   /* CONST  */
+    BOOL = 259,                    /* BOOL  */
+    INT = 260,                     /* INT  */
+    UINT = 261,                    /* UINT  */
+    FLOAT = 262,                   /* FLOAT  */
+    BVEC2 = 263,                   /* BVEC2  */
+    BVEC3 = 264,                   /* BVEC3  */
+    BVEC4 = 265,                   /* BVEC4  */
+    IVEC2 = 266,                   /* IVEC2  */
+    IVEC3 = 267,                   /* IVEC3  */
+    IVEC4 = 268,                   /* IVEC4  */
+    UVEC2 = 269,                   /* UVEC2  */
+    UVEC3 = 270,                   /* UVEC3  */
+    UVEC4 = 271,                   /* UVEC4  */
+    VEC2 = 272,                    /* VEC2  */
+    VEC3 = 273,                    /* VEC3  */
+    VEC4 = 274,                    /* VEC4  */
+    MAT2 = 275,                    /* MAT2  */
+    MAT3 = 276,                    /* MAT3  */
+    MAT4 = 277,                    /* MAT4  */
+    MAT2X2 = 278,                  /* MAT2X2  */
+    MAT2X3 = 279,                  /* MAT2X3  */
+    MAT2X4 = 280,                  /* MAT2X4  */
+    MAT3X2 = 281,                  /* MAT3X2  */
+    MAT3X3 = 282,                  /* MAT3X3  */
+    MAT3X4 = 283,                  /* MAT3X4  */
+    MAT4X2 = 284,                  /* MAT4X2  */
+    MAT4X3 = 285,                  /* MAT4X3  */
+    MAT4X4 = 286,                  /* MAT4X4  */
+    SAMPLER2D = 287,               /* SAMPLER2D  */
+    SAMPLER3D = 288,               /* SAMPLER3D  */
+    SAMPLERCUBE = 289,             /* SAMPLERCUBE  */
+    SAMPLER2DSHADOW = 290,         /* SAMPLER2DSHADOW  */
+    SAMPLERCUBESHADOW = 291,       /* SAMPLERCUBESHADOW  */
+    SAMPLER2DARRAY = 292,          /* SAMPLER2DARRAY  */
+    SAMPLER2DARRAYSHADOW = 293,    /* SAMPLER2DARRAYSHADOW  */
+    ISAMPLER2D = 294,              /* ISAMPLER2D  */
+    ISAMPLER3D = 295,              /* ISAMPLER3D  */
+    ISAMPLERCUBE = 296,            /* ISAMPLERCUBE  */
+    ISAMPLER2DARRAY = 297,         /* ISAMPLER2DARRAY  */
+    USAMPLER2D = 298,              /* USAMPLER2D  */
+    USAMPLER3D = 299,              /* USAMPLER3D  */
+    USAMPLERCUBE = 300,            /* USAMPLERCUBE  */
+    USAMPLER2DARRAY = 301,         /* USAMPLER2DARRAY  */
+    SAMPLER = 302,                 /* SAMPLER  */
+    SAMPLERSHADOW = 303,           /* SAMPLERSHADOW  */
+    TEXTURE2D = 304,               /* TEXTURE2D  */
+    TEXTURE3D = 305,               /* TEXTURE3D  */
+    TEXTURECUBE = 306,             /* TEXTURECUBE  */
+    TEXTURE2DARRAY = 307,          /* TEXTURE2DARRAY  */
+    ITEXTURE2D = 308,              /* ITEXTURE2D  */
+    ITEXTURE3D = 309,              /* ITEXTURE3D  */
+    ITEXTURECUBE = 310,            /* ITEXTURECUBE  */
+    ITEXTURE2DARRAY = 311,         /* ITEXTURE2DARRAY  */
+    UTEXTURE2D = 312,              /* UTEXTURE2D  */
+    UTEXTURE3D = 313,              /* UTEXTURE3D  */
+    UTEXTURECUBE = 314,            /* UTEXTURECUBE  */
+    UTEXTURE2DARRAY = 315,         /* UTEXTURE2DARRAY  */
+    ATTRIBUTE = 316,               /* ATTRIBUTE  */
+    VARYING = 317,                 /* VARYING  */
+    FLOAT16_T = 318,               /* FLOAT16_T  */
+    FLOAT32_T = 319,               /* FLOAT32_T  */
+    DOUBLE = 320,                  /* DOUBLE  */
+    FLOAT64_T = 321,               /* FLOAT64_T  */
+    INT64_T = 322,                 /* INT64_T  */
+    UINT64_T = 323,                /* UINT64_T  */
+    INT32_T = 324,                 /* INT32_T  */
+    UINT32_T = 325,                /* UINT32_T  */
+    INT16_T = 326,                 /* INT16_T  */
+    UINT16_T = 327,                /* UINT16_T  */
+    INT8_T = 328,                  /* INT8_T  */
+    UINT8_T = 329,                 /* UINT8_T  */
+    I64VEC2 = 330,                 /* I64VEC2  */
+    I64VEC3 = 331,                 /* I64VEC3  */
+    I64VEC4 = 332,                 /* I64VEC4  */
+    U64VEC2 = 333,                 /* U64VEC2  */
+    U64VEC3 = 334,                 /* U64VEC3  */
+    U64VEC4 = 335,                 /* U64VEC4  */
+    I32VEC2 = 336,                 /* I32VEC2  */
+    I32VEC3 = 337,                 /* I32VEC3  */
+    I32VEC4 = 338,                 /* I32VEC4  */
+    U32VEC2 = 339,                 /* U32VEC2  */
+    U32VEC3 = 340,                 /* U32VEC3  */
+    U32VEC4 = 341,                 /* U32VEC4  */
+    I16VEC2 = 342,                 /* I16VEC2  */
+    I16VEC3 = 343,                 /* I16VEC3  */
+    I16VEC4 = 344,                 /* I16VEC4  */
+    U16VEC2 = 345,                 /* U16VEC2  */
+    U16VEC3 = 346,                 /* U16VEC3  */
+    U16VEC4 = 347,                 /* U16VEC4  */
+    I8VEC2 = 348,                  /* I8VEC2  */
+    I8VEC3 = 349,                  /* I8VEC3  */
+    I8VEC4 = 350,                  /* I8VEC4  */
+    U8VEC2 = 351,                  /* U8VEC2  */
+    U8VEC3 = 352,                  /* U8VEC3  */
+    U8VEC4 = 353,                  /* U8VEC4  */
+    DVEC2 = 354,                   /* DVEC2  */
+    DVEC3 = 355,                   /* DVEC3  */
+    DVEC4 = 356,                   /* DVEC4  */
+    DMAT2 = 357,                   /* DMAT2  */
+    DMAT3 = 358,                   /* DMAT3  */
+    DMAT4 = 359,                   /* DMAT4  */
+    F16VEC2 = 360,                 /* F16VEC2  */
+    F16VEC3 = 361,                 /* F16VEC3  */
+    F16VEC4 = 362,                 /* F16VEC4  */
+    F16MAT2 = 363,                 /* F16MAT2  */
+    F16MAT3 = 364,                 /* F16MAT3  */
+    F16MAT4 = 365,                 /* F16MAT4  */
+    F32VEC2 = 366,                 /* F32VEC2  */
+    F32VEC3 = 367,                 /* F32VEC3  */
+    F32VEC4 = 368,                 /* F32VEC4  */
+    F32MAT2 = 369,                 /* F32MAT2  */
+    F32MAT3 = 370,                 /* F32MAT3  */
+    F32MAT4 = 371,                 /* F32MAT4  */
+    F64VEC2 = 372,                 /* F64VEC2  */
+    F64VEC3 = 373,                 /* F64VEC3  */
+    F64VEC4 = 374,                 /* F64VEC4  */
+    F64MAT2 = 375,                 /* F64MAT2  */
+    F64MAT3 = 376,                 /* F64MAT3  */
+    F64MAT4 = 377,                 /* F64MAT4  */
+    DMAT2X2 = 378,                 /* DMAT2X2  */
+    DMAT2X3 = 379,                 /* DMAT2X3  */
+    DMAT2X4 = 380,                 /* DMAT2X4  */
+    DMAT3X2 = 381,                 /* DMAT3X2  */
+    DMAT3X3 = 382,                 /* DMAT3X3  */
+    DMAT3X4 = 383,                 /* DMAT3X4  */
+    DMAT4X2 = 384,                 /* DMAT4X2  */
+    DMAT4X3 = 385,                 /* DMAT4X3  */
+    DMAT4X4 = 386,                 /* DMAT4X4  */
+    F16MAT2X2 = 387,               /* F16MAT2X2  */
+    F16MAT2X3 = 388,               /* F16MAT2X3  */
+    F16MAT2X4 = 389,               /* F16MAT2X4  */
+    F16MAT3X2 = 390,               /* F16MAT3X2  */
+    F16MAT3X3 = 391,               /* F16MAT3X3  */
+    F16MAT3X4 = 392,               /* F16MAT3X4  */
+    F16MAT4X2 = 393,               /* F16MAT4X2  */
+    F16MAT4X3 = 394,               /* F16MAT4X3  */
+    F16MAT4X4 = 395,               /* F16MAT4X4  */
+    F32MAT2X2 = 396,               /* F32MAT2X2  */
+    F32MAT2X3 = 397,               /* F32MAT2X3  */
+    F32MAT2X4 = 398,               /* F32MAT2X4  */
+    F32MAT3X2 = 399,               /* F32MAT3X2  */
+    F32MAT3X3 = 400,               /* F32MAT3X3  */
+    F32MAT3X4 = 401,               /* F32MAT3X4  */
+    F32MAT4X2 = 402,               /* F32MAT4X2  */
+    F32MAT4X3 = 403,               /* F32MAT4X3  */
+    F32MAT4X4 = 404,               /* F32MAT4X4  */
+    F64MAT2X2 = 405,               /* F64MAT2X2  */
+    F64MAT2X3 = 406,               /* F64MAT2X3  */
+    F64MAT2X4 = 407,               /* F64MAT2X4  */
+    F64MAT3X2 = 408,               /* F64MAT3X2  */
+    F64MAT3X3 = 409,               /* F64MAT3X3  */
+    F64MAT3X4 = 410,               /* F64MAT3X4  */
+    F64MAT4X2 = 411,               /* F64MAT4X2  */
+    F64MAT4X3 = 412,               /* F64MAT4X3  */
+    F64MAT4X4 = 413,               /* F64MAT4X4  */
+    ATOMIC_UINT = 414,             /* ATOMIC_UINT  */
+    ACCSTRUCTNV = 415,             /* ACCSTRUCTNV  */
+    ACCSTRUCTEXT = 416,            /* ACCSTRUCTEXT  */
+    RAYQUERYEXT = 417,             /* RAYQUERYEXT  */
+    FCOOPMATNV = 418,              /* FCOOPMATNV  */
+    ICOOPMATNV = 419,              /* ICOOPMATNV  */
+    UCOOPMATNV = 420,              /* UCOOPMATNV  */
+    SAMPLERCUBEARRAY = 421,        /* SAMPLERCUBEARRAY  */
+    SAMPLERCUBEARRAYSHADOW = 422,  /* SAMPLERCUBEARRAYSHADOW  */
+    ISAMPLERCUBEARRAY = 423,       /* ISAMPLERCUBEARRAY  */
+    USAMPLERCUBEARRAY = 424,       /* USAMPLERCUBEARRAY  */
+    SAMPLER1D = 425,               /* SAMPLER1D  */
+    SAMPLER1DARRAY = 426,          /* SAMPLER1DARRAY  */
+    SAMPLER1DARRAYSHADOW = 427,    /* SAMPLER1DARRAYSHADOW  */
+    ISAMPLER1D = 428,              /* ISAMPLER1D  */
+    SAMPLER1DSHADOW = 429,         /* SAMPLER1DSHADOW  */
+    SAMPLER2DRECT = 430,           /* SAMPLER2DRECT  */
+    SAMPLER2DRECTSHADOW = 431,     /* SAMPLER2DRECTSHADOW  */
+    ISAMPLER2DRECT = 432,          /* ISAMPLER2DRECT  */
+    USAMPLER2DRECT = 433,          /* USAMPLER2DRECT  */
+    SAMPLERBUFFER = 434,           /* SAMPLERBUFFER  */
+    ISAMPLERBUFFER = 435,          /* ISAMPLERBUFFER  */
+    USAMPLERBUFFER = 436,          /* USAMPLERBUFFER  */
+    SAMPLER2DMS = 437,             /* SAMPLER2DMS  */
+    ISAMPLER2DMS = 438,            /* ISAMPLER2DMS  */
+    USAMPLER2DMS = 439,            /* USAMPLER2DMS  */
+    SAMPLER2DMSARRAY = 440,        /* SAMPLER2DMSARRAY  */
+    ISAMPLER2DMSARRAY = 441,       /* ISAMPLER2DMSARRAY  */
+    USAMPLER2DMSARRAY = 442,       /* USAMPLER2DMSARRAY  */
+    SAMPLEREXTERNALOES = 443,      /* SAMPLEREXTERNALOES  */
+    SAMPLEREXTERNAL2DY2YEXT = 444, /* SAMPLEREXTERNAL2DY2YEXT  */
+    ISAMPLER1DARRAY = 445,         /* ISAMPLER1DARRAY  */
+    USAMPLER1D = 446,              /* USAMPLER1D  */
+    USAMPLER1DARRAY = 447,         /* USAMPLER1DARRAY  */
+    F16SAMPLER1D = 448,            /* F16SAMPLER1D  */
+    F16SAMPLER2D = 449,            /* F16SAMPLER2D  */
+    F16SAMPLER3D = 450,            /* F16SAMPLER3D  */
+    F16SAMPLER2DRECT = 451,        /* F16SAMPLER2DRECT  */
+    F16SAMPLERCUBE = 452,          /* F16SAMPLERCUBE  */
+    F16SAMPLER1DARRAY = 453,       /* F16SAMPLER1DARRAY  */
+    F16SAMPLER2DARRAY = 454,       /* F16SAMPLER2DARRAY  */
+    F16SAMPLERCUBEARRAY = 455,     /* F16SAMPLERCUBEARRAY  */
+    F16SAMPLERBUFFER = 456,        /* F16SAMPLERBUFFER  */
+    F16SAMPLER2DMS = 457,          /* F16SAMPLER2DMS  */
+    F16SAMPLER2DMSARRAY = 458,     /* F16SAMPLER2DMSARRAY  */
+    F16SAMPLER1DSHADOW = 459,      /* F16SAMPLER1DSHADOW  */
+    F16SAMPLER2DSHADOW = 460,      /* F16SAMPLER2DSHADOW  */
+    F16SAMPLER1DARRAYSHADOW = 461, /* F16SAMPLER1DARRAYSHADOW  */
+    F16SAMPLER2DARRAYSHADOW = 462, /* F16SAMPLER2DARRAYSHADOW  */
+    F16SAMPLER2DRECTSHADOW = 463,  /* F16SAMPLER2DRECTSHADOW  */
+    F16SAMPLERCUBESHADOW = 464,    /* F16SAMPLERCUBESHADOW  */
+    F16SAMPLERCUBEARRAYSHADOW = 465, /* F16SAMPLERCUBEARRAYSHADOW  */
+    IMAGE1D = 466,                 /* IMAGE1D  */
+    IIMAGE1D = 467,                /* IIMAGE1D  */
+    UIMAGE1D = 468,                /* UIMAGE1D  */
+    IMAGE2D = 469,                 /* IMAGE2D  */
+    IIMAGE2D = 470,                /* IIMAGE2D  */
+    UIMAGE2D = 471,                /* UIMAGE2D  */
+    IMAGE3D = 472,                 /* IMAGE3D  */
+    IIMAGE3D = 473,                /* IIMAGE3D  */
+    UIMAGE3D = 474,                /* UIMAGE3D  */
+    IMAGE2DRECT = 475,             /* IMAGE2DRECT  */
+    IIMAGE2DRECT = 476,            /* IIMAGE2DRECT  */
+    UIMAGE2DRECT = 477,            /* UIMAGE2DRECT  */
+    IMAGECUBE = 478,               /* IMAGECUBE  */
+    IIMAGECUBE = 479,              /* IIMAGECUBE  */
+    UIMAGECUBE = 480,              /* UIMAGECUBE  */
+    IMAGEBUFFER = 481,             /* IMAGEBUFFER  */
+    IIMAGEBUFFER = 482,            /* IIMAGEBUFFER  */
+    UIMAGEBUFFER = 483,            /* UIMAGEBUFFER  */
+    IMAGE1DARRAY = 484,            /* IMAGE1DARRAY  */
+    IIMAGE1DARRAY = 485,           /* IIMAGE1DARRAY  */
+    UIMAGE1DARRAY = 486,           /* UIMAGE1DARRAY  */
+    IMAGE2DARRAY = 487,            /* IMAGE2DARRAY  */
+    IIMAGE2DARRAY = 488,           /* IIMAGE2DARRAY  */
+    UIMAGE2DARRAY = 489,           /* UIMAGE2DARRAY  */
+    IMAGECUBEARRAY = 490,          /* IMAGECUBEARRAY  */
+    IIMAGECUBEARRAY = 491,         /* IIMAGECUBEARRAY  */
+    UIMAGECUBEARRAY = 492,         /* UIMAGECUBEARRAY  */
+    IMAGE2DMS = 493,               /* IMAGE2DMS  */
+    IIMAGE2DMS = 494,              /* IIMAGE2DMS  */
+    UIMAGE2DMS = 495,              /* UIMAGE2DMS  */
+    IMAGE2DMSARRAY = 496,          /* IMAGE2DMSARRAY  */
+    IIMAGE2DMSARRAY = 497,         /* IIMAGE2DMSARRAY  */
+    UIMAGE2DMSARRAY = 498,         /* UIMAGE2DMSARRAY  */
+    F16IMAGE1D = 499,              /* F16IMAGE1D  */
+    F16IMAGE2D = 500,              /* F16IMAGE2D  */
+    F16IMAGE3D = 501,              /* F16IMAGE3D  */
+    F16IMAGE2DRECT = 502,          /* F16IMAGE2DRECT  */
+    F16IMAGECUBE = 503,            /* F16IMAGECUBE  */
+    F16IMAGE1DARRAY = 504,         /* F16IMAGE1DARRAY  */
+    F16IMAGE2DARRAY = 505,         /* F16IMAGE2DARRAY  */
+    F16IMAGECUBEARRAY = 506,       /* F16IMAGECUBEARRAY  */
+    F16IMAGEBUFFER = 507,          /* F16IMAGEBUFFER  */
+    F16IMAGE2DMS = 508,            /* F16IMAGE2DMS  */
+    F16IMAGE2DMSARRAY = 509,       /* F16IMAGE2DMSARRAY  */
+    I64IMAGE1D = 510,              /* I64IMAGE1D  */
+    U64IMAGE1D = 511,              /* U64IMAGE1D  */
+    I64IMAGE2D = 512,              /* I64IMAGE2D  */
+    U64IMAGE2D = 513,              /* U64IMAGE2D  */
+    I64IMAGE3D = 514,              /* I64IMAGE3D  */
+    U64IMAGE3D = 515,              /* U64IMAGE3D  */
+    I64IMAGE2DRECT = 516,          /* I64IMAGE2DRECT  */
+    U64IMAGE2DRECT = 517,          /* U64IMAGE2DRECT  */
+    I64IMAGECUBE = 518,            /* I64IMAGECUBE  */
+    U64IMAGECUBE = 519,            /* U64IMAGECUBE  */
+    I64IMAGEBUFFER = 520,          /* I64IMAGEBUFFER  */
+    U64IMAGEBUFFER = 521,          /* U64IMAGEBUFFER  */
+    I64IMAGE1DARRAY = 522,         /* I64IMAGE1DARRAY  */
+    U64IMAGE1DARRAY = 523,         /* U64IMAGE1DARRAY  */
+    I64IMAGE2DARRAY = 524,         /* I64IMAGE2DARRAY  */
+    U64IMAGE2DARRAY = 525,         /* U64IMAGE2DARRAY  */
+    I64IMAGECUBEARRAY = 526,       /* I64IMAGECUBEARRAY  */
+    U64IMAGECUBEARRAY = 527,       /* U64IMAGECUBEARRAY  */
+    I64IMAGE2DMS = 528,            /* I64IMAGE2DMS  */
+    U64IMAGE2DMS = 529,            /* U64IMAGE2DMS  */
+    I64IMAGE2DMSARRAY = 530,       /* I64IMAGE2DMSARRAY  */
+    U64IMAGE2DMSARRAY = 531,       /* U64IMAGE2DMSARRAY  */
+    TEXTURECUBEARRAY = 532,        /* TEXTURECUBEARRAY  */
+    ITEXTURECUBEARRAY = 533,       /* ITEXTURECUBEARRAY  */
+    UTEXTURECUBEARRAY = 534,       /* UTEXTURECUBEARRAY  */
+    TEXTURE1D = 535,               /* TEXTURE1D  */
+    ITEXTURE1D = 536,              /* ITEXTURE1D  */
+    UTEXTURE1D = 537,              /* UTEXTURE1D  */
+    TEXTURE1DARRAY = 538,          /* TEXTURE1DARRAY  */
+    ITEXTURE1DARRAY = 539,         /* ITEXTURE1DARRAY  */
+    UTEXTURE1DARRAY = 540,         /* UTEXTURE1DARRAY  */
+    TEXTURE2DRECT = 541,           /* TEXTURE2DRECT  */
+    ITEXTURE2DRECT = 542,          /* ITEXTURE2DRECT  */
+    UTEXTURE2DRECT = 543,          /* UTEXTURE2DRECT  */
+    TEXTUREBUFFER = 544,           /* TEXTUREBUFFER  */
+    ITEXTUREBUFFER = 545,          /* ITEXTUREBUFFER  */
+    UTEXTUREBUFFER = 546,          /* UTEXTUREBUFFER  */
+    TEXTURE2DMS = 547,             /* TEXTURE2DMS  */
+    ITEXTURE2DMS = 548,            /* ITEXTURE2DMS  */
+    UTEXTURE2DMS = 549,            /* UTEXTURE2DMS  */
+    TEXTURE2DMSARRAY = 550,        /* TEXTURE2DMSARRAY  */
+    ITEXTURE2DMSARRAY = 551,       /* ITEXTURE2DMSARRAY  */
+    UTEXTURE2DMSARRAY = 552,       /* UTEXTURE2DMSARRAY  */
+    F16TEXTURE1D = 553,            /* F16TEXTURE1D  */
+    F16TEXTURE2D = 554,            /* F16TEXTURE2D  */
+    F16TEXTURE3D = 555,            /* F16TEXTURE3D  */
+    F16TEXTURE2DRECT = 556,        /* F16TEXTURE2DRECT  */
+    F16TEXTURECUBE = 557,          /* F16TEXTURECUBE  */
+    F16TEXTURE1DARRAY = 558,       /* F16TEXTURE1DARRAY  */
+    F16TEXTURE2DARRAY = 559,       /* F16TEXTURE2DARRAY  */
+    F16TEXTURECUBEARRAY = 560,     /* F16TEXTURECUBEARRAY  */
+    F16TEXTUREBUFFER = 561,        /* F16TEXTUREBUFFER  */
+    F16TEXTURE2DMS = 562,          /* F16TEXTURE2DMS  */
+    F16TEXTURE2DMSARRAY = 563,     /* F16TEXTURE2DMSARRAY  */
+    SUBPASSINPUT = 564,            /* SUBPASSINPUT  */
+    SUBPASSINPUTMS = 565,          /* SUBPASSINPUTMS  */
+    ISUBPASSINPUT = 566,           /* ISUBPASSINPUT  */
+    ISUBPASSINPUTMS = 567,         /* ISUBPASSINPUTMS  */
+    USUBPASSINPUT = 568,           /* USUBPASSINPUT  */
+    USUBPASSINPUTMS = 569,         /* USUBPASSINPUTMS  */
+    F16SUBPASSINPUT = 570,         /* F16SUBPASSINPUT  */
+    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  */
   };
   };
+  typedef enum yytokentype yytoken_kind_t;
 #endif
 #endif
 
 
 /* Value type.  */
 /* Value type.  */
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-
 union YYSTYPE
 union YYSTYPE
 {
 {
-#line 97 "MachineIndependent/glslang.y" /* yacc.c:1909  */
+#line 97 "MachineIndependent/glslang.y"
 
 
     struct {
     struct {
         glslang::TSourceLoc loc;
         glslang::TSourceLoc loc;
@@ -506,9 +540,9 @@ union YYSTYPE
         glslang::TArraySizes* typeParameters;
         glslang::TArraySizes* typeParameters;
     } interm;
     } interm;
 
 
-#line 510 "MachineIndependent/glslang_tab.cpp.h" /* yacc.c:1909  */
-};
+#line 544 "MachineIndependent/glslang_tab.cpp.h"
 
 
+};
 typedef union YYSTYPE YYSTYPE;
 typedef union YYSTYPE YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define YYSTYPE_IS_TRIVIAL 1
 # define YYSTYPE_IS_DECLARED 1
 # define YYSTYPE_IS_DECLARED 1

+ 27 - 12
src/libraries/glslang/glslang/MachineIndependent/intermOut.cpp

@@ -438,6 +438,9 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
     case EOpConvUint64ToPtr:  out.debug << "Convert uint64_t to pointer";   break;
     case EOpConvUint64ToPtr:  out.debug << "Convert uint64_t to pointer";   break;
     case EOpConvPtrToUint64:  out.debug << "Convert pointer to uint64_t";   break;
     case EOpConvPtrToUint64:  out.debug << "Convert pointer to uint64_t";   break;
 
 
+    case EOpConvUint64ToAccStruct: out.debug << "Convert uint64_t to acceleration structure"; break;
+    case EOpConvUvec2ToAccStruct:  out.debug << "Convert uvec2 to acceleration strucuture "; break;
+
     case EOpRadians:        out.debug << "radians";              break;
     case EOpRadians:        out.debug << "radians";              break;
     case EOpDegrees:        out.debug << "degrees";              break;
     case EOpDegrees:        out.debug << "degrees";              break;
     case EOpSin:            out.debug << "sine";                 break;
     case EOpSin:            out.debug << "sine";                 break;
@@ -829,6 +832,7 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
     case EOpConstructTextureSampler: out.debug << "Construct combined texture-sampler"; break;
     case EOpConstructTextureSampler: out.debug << "Construct combined texture-sampler"; break;
     case EOpConstructReference:  out.debug << "Construct reference";  break;
     case EOpConstructReference:  out.debug << "Construct reference";  break;
     case EOpConstructCooperativeMatrix:  out.debug << "Construct cooperative matrix";  break;
     case EOpConstructCooperativeMatrix:  out.debug << "Construct cooperative matrix";  break;
+    case EOpConstructAccStruct: out.debug << "Construct acceleration structure"; break;
 
 
     case EOpLessThan:         out.debug << "Compare Less Than";             break;
     case EOpLessThan:         out.debug << "Compare Less Than";             break;
     case EOpGreaterThan:      out.debug << "Compare Greater Than";          break;
     case EOpGreaterThan:      out.debug << "Compare Greater Than";          break;
@@ -882,6 +886,7 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
     case EOpTime:                       out.debug << "time";                  break;
     case EOpTime:                       out.debug << "time";                  break;
 
 
     case EOpAtomicAdd:                  out.debug << "AtomicAdd";             break;
     case EOpAtomicAdd:                  out.debug << "AtomicAdd";             break;
+    case EOpAtomicSubtract:             out.debug << "AtomicSubtract";        break;
     case EOpAtomicMin:                  out.debug << "AtomicMin";             break;
     case EOpAtomicMin:                  out.debug << "AtomicMin";             break;
     case EOpAtomicMax:                  out.debug << "AtomicMax";             break;
     case EOpAtomicMax:                  out.debug << "AtomicMax";             break;
     case EOpAtomicAnd:                  out.debug << "AtomicAnd";             break;
     case EOpAtomicAnd:                  out.debug << "AtomicAnd";             break;
@@ -1079,11 +1084,15 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
     case EOpSubpassLoad:   out.debug << "subpassLoad";   break;
     case EOpSubpassLoad:   out.debug << "subpassLoad";   break;
     case EOpSubpassLoadMS: out.debug << "subpassLoadMS"; break;
     case EOpSubpassLoadMS: out.debug << "subpassLoadMS"; break;
 
 
-    case EOpTrace:                            out.debug << "traceNV"; break;
+    case EOpTraceNV:                          out.debug << "traceNV"; break;
+    case EOpTraceKHR:                         out.debug << "traceRayKHR"; break;
     case EOpReportIntersection:               out.debug << "reportIntersectionNV"; break;
     case EOpReportIntersection:               out.debug << "reportIntersectionNV"; break;
-    case EOpIgnoreIntersection:               out.debug << "ignoreIntersectionNV"; break;
-    case EOpTerminateRay:                     out.debug << "terminateRayNV"; break;
-    case EOpExecuteCallable:                  out.debug << "executeCallableNV"; break;
+    case EOpIgnoreIntersectionNV:             out.debug << "ignoreIntersectionNV"; break;
+    case EOpIgnoreIntersectionKHR:            out.debug << "ignoreIntersectionKHR"; break;
+    case EOpTerminateRayNV:                   out.debug << "terminateRayNV"; break;
+    case EOpTerminateRayKHR:                  out.debug << "terminateRayKHR"; break;
+    case EOpExecuteCallableNV:                out.debug << "executeCallableNV"; break;
+    case EOpExecuteCallableKHR:               out.debug << "executeCallableKHR"; break;
     case EOpWritePackedPrimitiveIndices4x8NV: out.debug << "writePackedPrimitiveIndices4x8NV"; break;
     case EOpWritePackedPrimitiveIndices4x8NV: out.debug << "writePackedPrimitiveIndices4x8NV"; break;
 
 
     case EOpRayQueryInitialize:                                            out.debug << "rayQueryInitializeEXT"; break;
     case EOpRayQueryInitialize:                                            out.debug << "rayQueryInitializeEXT"; break;
@@ -1321,6 +1330,9 @@ static void OutputConstantUnion(TInfoSink& out, const TIntermTyped* node, const
                 out.debug << buf << "\n";
                 out.debug << buf << "\n";
             }
             }
             break;
             break;
+        case EbtString:
+            out.debug << "\"" << constUnion[i].getSConst()->c_str() << "\"\n";
+            break;
         default:
         default:
             out.info.message(EPrefixInternalError, "Unknown constant", node->getLoc());
             out.info.message(EPrefixInternalError, "Unknown constant", node->getLoc());
             break;
             break;
@@ -1406,14 +1418,17 @@ bool TOutputTraverser::visitBranch(TVisit /* visit*/, TIntermBranch* node)
     OutputTreeText(out, node, depth);
     OutputTreeText(out, node, depth);
 
 
     switch (node->getFlowOp()) {
     switch (node->getFlowOp()) {
-    case EOpKill:      out.debug << "Branch: Kill";           break;
-    case EOpBreak:     out.debug << "Branch: Break";          break;
-    case EOpContinue:  out.debug << "Branch: Continue";       break;
-    case EOpReturn:    out.debug << "Branch: Return";         break;
-    case EOpCase:      out.debug << "case: ";                 break;
-    case EOpDemote:    out.debug << "Demote";                 break;
-    case EOpDefault:   out.debug << "default: ";              break;
-    default:               out.debug << "Branch: Unknown Branch"; break;
+    case EOpKill:                   out.debug << "Branch: Kill";                  break;
+    case EOpTerminateInvocation:    out.debug << "Branch: TerminateInvocation";   break;
+    case EOpIgnoreIntersectionKHR:  out.debug << "Branch: IgnoreIntersectionKHR"; break;
+    case EOpTerminateRayKHR:        out.debug << "Branch: TerminateRayKHR";       break;
+    case EOpBreak:                  out.debug << "Branch: Break";                 break;
+    case EOpContinue:               out.debug << "Branch: Continue";              break;
+    case EOpReturn:                 out.debug << "Branch: Return";                break;
+    case EOpCase:                   out.debug << "case: ";                        break;
+    case EOpDemote:                 out.debug << "Demote";                        break;
+    case EOpDefault:                out.debug << "default: ";                     break;
+    default:                        out.debug << "Branch: Unknown Branch";        break;
     }
     }
 
 
     if (node->getExpression()) {
     if (node->getExpression()) {

+ 489 - 117
src/libraries/glslang/glslang/MachineIndependent/iomapper.cpp

@@ -37,9 +37,11 @@
 
 
 #include "../Include/Common.h"
 #include "../Include/Common.h"
 #include "../Include/InfoSink.h"
 #include "../Include/InfoSink.h"
+#include "../Include/Types.h"
 
 
 #include "gl_types.h"
 #include "gl_types.h"
 #include "iomapper.h"
 #include "iomapper.h"
+#include "SymbolTable.h"
 
 
 //
 //
 // Map IO bindings.
 // Map IO bindings.
@@ -82,17 +84,17 @@ public:
         // If a global is being visited, then we should also traverse it incase it's evaluation
         // If a global is being visited, then we should also traverse it incase it's evaluation
         // ends up visiting inputs we want to tag as live
         // ends up visiting inputs we want to tag as live
         else if (base->getQualifier().storage == EvqGlobal)
         else if (base->getQualifier().storage == EvqGlobal)
-            addGlobalReference(base->getName());
+            addGlobalReference(base->getAccessName());
 
 
         if (target) {
         if (target) {
             TVarEntryInfo ent = {base->getId(), base, ! traverseAll};
             TVarEntryInfo ent = {base->getId(), base, ! traverseAll};
             ent.stage = intermediate.getStage();
             ent.stage = intermediate.getStage();
             TVarLiveMap::iterator at = target->find(
             TVarLiveMap::iterator at = target->find(
-                ent.symbol->getName()); // std::lower_bound(target->begin(), target->end(), ent, TVarEntryInfo::TOrderById());
+                ent.symbol->getAccessName()); // std::lower_bound(target->begin(), target->end(), ent, TVarEntryInfo::TOrderById());
             if (at != target->end() && at->second.id == ent.id)
             if (at != target->end() && at->second.id == ent.id)
                 at->second.live = at->second.live || ! traverseAll; // update live state
                 at->second.live = at->second.live || ! traverseAll; // update live state
             else
             else
-                (*target)[ent.symbol->getName()] = ent;
+                (*target)[ent.symbol->getAccessName()] = ent;
         }
         }
     }
     }
 
 
@@ -125,7 +127,8 @@ public:
             return;
             return;
 
 
         TVarEntryInfo ent = { base->getId() };
         TVarEntryInfo ent = { base->getId() };
-        TVarLiveMap::const_iterator at = source->find(base->getName());
+        // Fix a defect, when block has no instance name, we need to find its block name
+        TVarLiveMap::const_iterator at = source->find(base->getAccessName());
         if (at == source->end())
         if (at == source->end())
             return;
             return;
 
 
@@ -181,7 +184,7 @@ struct TNotifyInOutAdaptor
 
 
     inline void operator()(std::pair<const TString, TVarEntryInfo>& entKey)
     inline void operator()(std::pair<const TString, TVarEntryInfo>& entKey)
     {
     {
-        resolver.notifyInOut(stage, entKey.second);
+        resolver.notifyInOut(entKey.second.stage, entKey.second);
     }
     }
 
 
 private:
 private:
@@ -189,12 +192,13 @@ private:
 };
 };
 
 
 struct TResolverUniformAdaptor {
 struct TResolverUniformAdaptor {
-    TResolverUniformAdaptor(EShLanguage s, TIoMapResolver& r, TInfoSink& i, bool& e)
+    TResolverUniformAdaptor(EShLanguage s, TIoMapResolver& r, TVarLiveMap* uniform[EShLangCount], TInfoSink& i, bool& e)
       : stage(s)
       : stage(s)
       , resolver(r)
       , resolver(r)
       , infoSink(i)
       , infoSink(i)
       , error(e)
       , error(e)
     {
     {
+        memcpy(uniformVarMap, uniform, EShLangCount * (sizeof(TVarLiveMap*)));
     }
     }
 
 
     inline void operator()(std::pair<const TString, TVarEntryInfo>& entKey) {
     inline void operator()(std::pair<const TString, TVarEntryInfo>& entKey) {
@@ -206,9 +210,9 @@ struct TResolverUniformAdaptor {
         ent.newIndex = -1;
         ent.newIndex = -1;
         const bool isValid = resolver.validateBinding(stage, ent);
         const bool isValid = resolver.validateBinding(stage, ent);
         if (isValid) {
         if (isValid) {
-            resolver.resolveBinding(stage, ent);
-            resolver.resolveSet(stage, ent);
-            resolver.resolveUniformLocation(stage, ent);
+            resolver.resolveSet(ent.stage, ent);
+            resolver.resolveBinding(ent.stage, ent);
+            resolver.resolveUniformLocation(ent.stage, ent);
 
 
             if (ent.newBinding != -1) {
             if (ent.newBinding != -1) {
                 if (ent.newBinding >= int(TQualifier::layoutBindingEnd)) {
                 if (ent.newBinding >= int(TQualifier::layoutBindingEnd)) {
@@ -217,6 +221,17 @@ struct TResolverUniformAdaptor {
                     infoSink.info.message(EPrefixInternalError, err.c_str());
                     infoSink.info.message(EPrefixInternalError, err.c_str());
                     error = true;
                     error = true;
                 }
                 }
+
+                if (ent.symbol->getQualifier().hasBinding()) {
+                    for (uint32_t idx = EShLangVertex; idx < EShLangCount; ++idx) {
+                        if (idx == ent.stage || uniformVarMap[idx] == nullptr)
+                            continue;
+                        auto entKey2 = uniformVarMap[idx]->find(entKey.first);
+                        if (entKey2 != uniformVarMap[idx]->end()) {
+                            entKey2->second.newBinding = ent.newBinding;
+                        }
+                    }
+                }
             }
             }
             if (ent.newSet != -1) {
             if (ent.newSet != -1) {
                 if (ent.newSet >= int(TQualifier::layoutSetEnd)) {
                 if (ent.newSet >= int(TQualifier::layoutSetEnd)) {
@@ -225,6 +240,16 @@ struct TResolverUniformAdaptor {
                     infoSink.info.message(EPrefixInternalError, err.c_str());
                     infoSink.info.message(EPrefixInternalError, err.c_str());
                     error = true;
                     error = true;
                 }
                 }
+                if (ent.symbol->getQualifier().hasSet()) {
+                    for (uint32_t idx = EShLangVertex; idx < EShLangCount; ++idx) {
+                        if ((idx == stage) || (uniformVarMap[idx] == nullptr))
+                            continue;
+                        auto entKey2 = uniformVarMap[idx]->find(entKey.first);
+                        if (entKey2 != uniformVarMap[idx]->end()) {
+                            entKey2->second.newSet = ent.newSet;
+                        }
+                    }
+                }
             }
             }
         } else {
         } else {
             TString errorMsg = "Invalid binding: " + entKey.first;
             TString errorMsg = "Invalid binding: " + entKey.first;
@@ -239,7 +264,7 @@ struct TResolverUniformAdaptor {
     TIoMapResolver& resolver;
     TIoMapResolver& resolver;
     TInfoSink&      infoSink;
     TInfoSink&      infoSink;
     bool&           error;
     bool&           error;
-
+    TVarLiveMap*    uniformVarMap[EShLangCount];
 private:
 private:
     TResolverUniformAdaptor& operator=(TResolverUniformAdaptor&) = delete;
     TResolverUniformAdaptor& operator=(TResolverUniformAdaptor&) = delete;
 };
 };
@@ -261,7 +286,7 @@ struct TResolverInOutAdaptor {
         ent.newBinding = -1;
         ent.newBinding = -1;
         ent.newSet = -1;
         ent.newSet = -1;
         ent.newIndex = -1;
         ent.newIndex = -1;
-        const bool isValid = resolver.validateInOut(stage, ent);
+        const bool isValid = resolver.validateInOut(ent.stage, ent);
         if (isValid) {
         if (isValid) {
             resolver.resolveInOutLocation(stage, ent);
             resolver.resolveInOutLocation(stage, ent);
             resolver.resolveInOutComponent(stage, ent);
             resolver.resolveInOutComponent(stage, ent);
@@ -292,21 +317,118 @@ private:
 };
 };
 
 
 // The class is used for reserving explicit uniform locations and ubo/ssbo/opaque bindings
 // The class is used for reserving explicit uniform locations and ubo/ssbo/opaque bindings
+// xxTODO: maybe this logic should be moved into the resolver's "validateInOut" and "validateUniform"
 
 
 struct TSymbolValidater
 struct TSymbolValidater
 {
 {
     TSymbolValidater(TIoMapResolver& r, TInfoSink& i, TVarLiveMap* in[EShLangCount], TVarLiveMap* out[EShLangCount],
     TSymbolValidater(TIoMapResolver& r, TInfoSink& i, TVarLiveMap* in[EShLangCount], TVarLiveMap* out[EShLangCount],
-                     TVarLiveMap* uniform[EShLangCount], bool& hadError)
-        : preStage(EShLangCount)
-        , currentStage(EShLangCount)
-        , nextStage(EShLangCount)
-        , resolver(r)
+                     TVarLiveMap* uniform[EShLangCount], bool& hadError, EProfile profile, int version)
+        : resolver(r)
         , infoSink(i)
         , infoSink(i)
         , hadError(hadError)
         , hadError(hadError)
+        , profile(profile)
+        , version(version)
     {
     {
         memcpy(inVarMaps, in, EShLangCount * (sizeof(TVarLiveMap*)));
         memcpy(inVarMaps, in, EShLangCount * (sizeof(TVarLiveMap*)));
         memcpy(outVarMaps, out, EShLangCount * (sizeof(TVarLiveMap*)));
         memcpy(outVarMaps, out, EShLangCount * (sizeof(TVarLiveMap*)));
         memcpy(uniformVarMap, uniform, EShLangCount * (sizeof(TVarLiveMap*)));
         memcpy(uniformVarMap, uniform, EShLangCount * (sizeof(TVarLiveMap*)));
+
+        std::map<TString, TString> anonymousMemberMap;
+        std::vector<TRange> usedUniformLocation;
+        std::vector<TString> usedUniformName;
+        usedUniformLocation.clear();
+        usedUniformName.clear();
+        for (int i = 0; i < EShLangCount; i++) {
+            if (uniformVarMap[i]) {
+                for (auto uniformVar : *uniformVarMap[i])
+                {
+                    TIntermSymbol* pSymbol = uniformVar.second.symbol;
+                    TQualifier qualifier = uniformVar.second.symbol->getQualifier();
+                    TString symbolName = pSymbol->getAccessName();
+
+                    // All the uniform needs multi-stage location check (block/default)
+                    int uniformLocation = qualifier.layoutLocation;
+
+                    if (uniformLocation != TQualifier::layoutLocationEnd) {
+                        // Total size of current uniform, could be block, struct or other types.
+                        int size = TIntermediate::computeTypeUniformLocationSize(pSymbol->getType());
+
+                        TRange locationRange(uniformLocation, uniformLocation + size - 1);
+
+                        // Combine location and component ranges
+                        int overlapLocation = -1;
+                        bool diffLocation = false;
+
+                        // Check for collisions, except for vertex inputs on desktop targeting OpenGL
+                        overlapLocation = checkLocationOverlap(locationRange, usedUniformLocation, symbolName, usedUniformName, diffLocation);
+
+                        // Overlap locations of uniforms, regardless of components (multi stages)
+                        if (overlapLocation == -1) {
+                            usedUniformLocation.push_back(locationRange);
+                            usedUniformName.push_back(symbolName);
+                        }
+                        else if (overlapLocation >= 0) {
+                            if (diffLocation == true) {
+                                TString err = ("Uniform location should be equal for same uniforms: " +std::to_string(overlapLocation)).c_str();
+                                infoSink.info.message(EPrefixInternalError, err.c_str());
+                                hadError = true;
+                                break;
+                            }
+                            else {
+                                TString err = ("Uniform location overlaps across stages: " + std::to_string(overlapLocation)).c_str();
+                                infoSink.info.message(EPrefixInternalError, err.c_str());
+                                hadError = true;
+                                break;
+                            }
+                        }
+                    }
+
+                    if ((uniformVar.second.symbol->getBasicType() == EbtBlock) &&
+                        IsAnonymous(uniformVar.second.symbol->getName()))
+                    {
+                        auto blockType = uniformVar.second.symbol->getType().getStruct();
+                        for (size_t memberIdx = 0; memberIdx < blockType->size(); ++memberIdx) {
+                            auto memberName = (*blockType)[memberIdx].type->getFieldName();
+                            if (anonymousMemberMap.find(memberName) != anonymousMemberMap.end())
+                            {
+                                if (anonymousMemberMap[memberName] != uniformVar.second.symbol->getType().getTypeName())
+                                {
+                                    TString err = "Invalid block member name: " + memberName;
+                                    infoSink.info.message(EPrefixInternalError, err.c_str());
+                                    hadError = true;
+                                    break;
+                                }
+                            }
+                            else
+                            {
+                                anonymousMemberMap[memberName] = uniformVar.second.symbol->getType().getTypeName();
+                            }
+                        }
+                    }
+                    if (hadError)
+                        break;
+                }
+            }
+        }
+    }
+
+    // In case we need to new an intermediate, which costs too much
+    int checkLocationOverlap(const TRange& locationRange, std::vector<TRange>& usedUniformLocation, const TString symbolName, std::vector<TString>& usedUniformName, bool& diffLocation)
+    {
+        for (size_t r = 0; r < usedUniformLocation.size(); ++r) {
+            if (usedUniformName[r] == symbolName) {
+                diffLocation = true;
+                return (usedUniformLocation[r].start == locationRange.start &&
+                        usedUniformLocation[r].last == locationRange.last)
+                       ? -2 : std::max(locationRange.start, usedUniformLocation[r].start);
+            }
+            if (locationRange.overlap(usedUniformLocation[r])) {
+                // there is a collision; pick one
+                return std::max(locationRange.start, usedUniformLocation[r].start);
+            }
+        }
+
+        return -1; // no collision
     }
     }
 
 
     inline void operator()(std::pair<const TString, TVarEntryInfo>& entKey) {
     inline void operator()(std::pair<const TString, TVarEntryInfo>& entKey) {
@@ -314,17 +436,23 @@ struct TSymbolValidater
         TIntermSymbol* base = ent1.symbol;
         TIntermSymbol* base = ent1.symbol;
         const TType& type = ent1.symbol->getType();
         const TType& type = ent1.symbol->getType();
         const TString& name = entKey.first;
         const TString& name = entKey.first;
-        EShLanguage stage = ent1.stage;
         TString mangleName1, mangleName2;
         TString mangleName1, mangleName2;
-        if (currentStage != stage) {
-            preStage = currentStage;
-            currentStage = stage;
-            nextStage = EShLangCount;
-            for (int i = currentStage + 1; i < EShLangCount; i++) {
-                if (inVarMaps[i] != nullptr) {
-                    nextStage = static_cast<EShLanguage>(i);
-                    break;
-                }
+        EShLanguage stage = ent1.stage;
+        EShLanguage preStage, currentStage, nextStage;
+
+        preStage = EShLangCount;
+        for (int i = stage - 1; i >= 0; i--) {
+            if (inVarMaps[i] != nullptr) {
+                preStage = static_cast<EShLanguage>(i);
+                break;
+            }
+        }
+        currentStage = stage;
+        nextStage = EShLangCount;
+        for (int i = stage + 1; i < EShLangCount; i++) {
+            if (inVarMaps[i] != nullptr) {
+                nextStage = static_cast<EShLanguage>(i);
+                break;
             }
             }
         }
         }
 
 
@@ -335,46 +463,86 @@ struct TSymbolValidater
             type.appendMangledName(mangleName1);
             type.appendMangledName(mangleName1);
         }
         }
 
 
+
+        // basic checking that symbols match
+        // more extensive checking in the link stage
         if (base->getQualifier().storage == EvqVaryingIn) {
         if (base->getQualifier().storage == EvqVaryingIn) {
             // validate stage in;
             // validate stage in;
             if (preStage == EShLangCount)
             if (preStage == EShLangCount)
                 return;
                 return;
-            if (name == "gl_PerVertex")
+            if (TSymbolTable::isBuiltInSymbol(base->getId()))
                 return;
                 return;
             if (outVarMaps[preStage] != nullptr) {
             if (outVarMaps[preStage] != nullptr) {
                 auto ent2 = outVarMaps[preStage]->find(name);
                 auto ent2 = outVarMaps[preStage]->find(name);
+                uint32_t location = base->getType().getQualifier().layoutLocation;
+                if (ent2 == outVarMaps[preStage]->end() &&
+                    location != glslang::TQualifier::layoutLocationEnd) {
+                    for (auto var = outVarMaps[preStage]->begin(); var != ent2; var++) {
+                        if (var->second.symbol->getType().getQualifier().layoutLocation == location) {
+                            ent2 = var;
+                            break;
+                        }
+                    }
+                }
                 if (ent2 != outVarMaps[preStage]->end()) {
                 if (ent2 != outVarMaps[preStage]->end()) {
+                    auto& type1 = base->getType();
+                    auto& type2 = ent2->second.symbol->getType();
+                    hadError = hadError || typeCheck(&type1, &type2, name.c_str(), false);
                     if (ent2->second.symbol->getType().getQualifier().isArrayedIo(preStage)) {
                     if (ent2->second.symbol->getType().getQualifier().isArrayedIo(preStage)) {
                         TType subType(ent2->second.symbol->getType(), 0);
                         TType subType(ent2->second.symbol->getType(), 0);
                         subType.appendMangledName(mangleName2);
                         subType.appendMangledName(mangleName2);
-                    }
-                    else {
+                    } else {
                         ent2->second.symbol->getType().appendMangledName(mangleName2);
                         ent2->second.symbol->getType().appendMangledName(mangleName2);
                     }
                     }
-                    if (mangleName1 == mangleName2)
+
+                    if (mangleName1 == mangleName2) {
+                        // For ES 3.0 only, other versions have no such restrictions
+                        // According to ES 3.0 spec: The type and presence of the interpolation qualifiers and
+                        // storage qualifiers  of variables with the same name declared in all linked shaders must
+                        // match, otherwise the link command will fail.
+                        if (profile == EEsProfile && version == 300) {
+                            // Don't need to check smooth qualifier, as it uses the default interpolation mode
+                            if (ent1.stage == EShLangFragment && type1.isBuiltIn() == false) {
+                                if (type1.getQualifier().flat != type2.getQualifier().flat ||
+                                    type1.getQualifier().nopersp != type2.getQualifier().nopersp) {
+                                    TString err = "Interpolation qualifier mismatch : " + entKey.first;
+                                    infoSink.info.message(EPrefixInternalError, err.c_str());
+                                    hadError = true;
+                                }
+                            }
+                        }
                         return;
                         return;
+                    }
                     else {
                     else {
                         TString err = "Invalid In/Out variable type : " + entKey.first;
                         TString err = "Invalid In/Out variable type : " + entKey.first;
                         infoSink.info.message(EPrefixInternalError, err.c_str());
                         infoSink.info.message(EPrefixInternalError, err.c_str());
                         hadError = true;
                         hadError = true;
                     }
                     }
                 }
                 }
+                else if (!base->getType().isBuiltIn()) {
+                    // According to spec: A link error is generated if any statically referenced input variable
+                    // or block does not have a matching output
+                    if (profile == EEsProfile && ent1.live) {
+                        hadError = true;
+                        TString errorStr = name + ": not been declare as a output variable in pre shader stage.";
+                        infoSink.info.message(EPrefixError, errorStr.c_str());
+                    }
+                }
                 return;
                 return;
             }
             }
         } else if (base->getQualifier().storage == EvqVaryingOut) {
         } else if (base->getQualifier().storage == EvqVaryingOut) {
             // validate stage out;
             // validate stage out;
             if (nextStage == EShLangCount)
             if (nextStage == EShLangCount)
                 return;
                 return;
-            if (name == "gl_PerVertex")
+            if (TSymbolTable::isBuiltInSymbol(base->getId()))
                 return;
                 return;
-            if (outVarMaps[nextStage] != nullptr) {
+            if (inVarMaps[nextStage] != nullptr) {
                 auto ent2 = inVarMaps[nextStage]->find(name);
                 auto ent2 = inVarMaps[nextStage]->find(name);
                 if (ent2 != inVarMaps[nextStage]->end()) {
                 if (ent2 != inVarMaps[nextStage]->end()) {
                     if (ent2->second.symbol->getType().getQualifier().isArrayedIo(nextStage)) {
                     if (ent2->second.symbol->getType().getQualifier().isArrayedIo(nextStage)) {
                         TType subType(ent2->second.symbol->getType(), 0);
                         TType subType(ent2->second.symbol->getType(), 0);
                         subType.appendMangledName(mangleName2);
                         subType.appendMangledName(mangleName2);
-                    }
-                    else {
+                    } else {
                         ent2->second.symbol->getType().appendMangledName(mangleName2);
                         ent2->second.symbol->getType().appendMangledName(mangleName2);
                     }
                     }
                     if (mangleName1 == mangleName2)
                     if (mangleName1 == mangleName2)
@@ -387,7 +555,7 @@ struct TSymbolValidater
                 }
                 }
                 return;
                 return;
             }
             }
-        } else if (base->getQualifier().isUniformOrBuffer() && ! base->getQualifier().isPushConstant()) {
+        } else if (base->getQualifier().isUniformOrBuffer() && !base->getQualifier().isPushConstant()) {
             // validate uniform type;
             // validate uniform type;
             for (int i = 0; i < EShLangCount; i++) {
             for (int i = 0; i < EShLangCount; i++) {
                 if (i != currentStage && outVarMaps[i] != nullptr) {
                 if (i != currentStage && outVarMaps[i] != nullptr) {
@@ -395,26 +563,174 @@ struct TSymbolValidater
                     if (ent2 != uniformVarMap[i]->end()) {
                     if (ent2 != uniformVarMap[i]->end()) {
                         ent2->second.symbol->getType().appendMangledName(mangleName2);
                         ent2->second.symbol->getType().appendMangledName(mangleName2);
                         if (mangleName1 != mangleName2) {
                         if (mangleName1 != mangleName2) {
+                            ent2->second.symbol->getType().sameElementType(type);
                             TString err = "Invalid Uniform variable type : " + entKey.first;
                             TString err = "Invalid Uniform variable type : " + entKey.first;
                             infoSink.info.message(EPrefixInternalError, err.c_str());
                             infoSink.info.message(EPrefixInternalError, err.c_str());
                             hadError = true;
                             hadError = true;
                         }
                         }
                         mangleName2.clear();
                         mangleName2.clear();
+
+                        // validate instance name of blocks
+                        if (hadError == false &&
+                            base->getType().getBasicType() == EbtBlock &&
+                            IsAnonymous(base->getName()) != IsAnonymous(ent2->second.symbol->getName())) {
+                            TString err = "Matched uniform block names must also either all be lacking "
+                                          "an instance name or all having an instance name: " + entKey.first;
+                            infoSink.info.message(EPrefixInternalError, err.c_str());
+                            hadError = true;
+                        }
+
+                        // validate uniform block member qualifier and member names
+                        auto& type1 = base->getType();
+                        auto& type2 = ent2->second.symbol->getType();
+                        if (hadError == false && base->getType().getBasicType() == EbtBlock) {
+                            hadError = hadError || typeCheck(&type1, &type2, name.c_str(), true);
+                        }
+                        else {
+                            hadError = hadError || typeCheck(&type1, &type2, name.c_str(), false);
+                        }
+                    }
+                    else if (base->getBasicType() == EbtBlock)
+                    {
+                        if (IsAnonymous(base->getName()))
+                        {
+                            // The name of anonymous block member can't same with default uniform variable.
+                            auto blockType1 = base->getType().getStruct();
+                            for (size_t memberIdx = 0; memberIdx < blockType1->size(); ++memberIdx) {
+                                auto memberName = (*blockType1)[memberIdx].type->getFieldName();
+                                if (uniformVarMap[i]->find(memberName) != uniformVarMap[i]->end())
+                                {
+                                    TString err = "Invalid Uniform variable name : " + memberName;
+                                    infoSink.info.message(EPrefixInternalError, err.c_str());
+                                    hadError = true;
+                                    break;
+                                }
+                            }
+                        }
                     }
                     }
                 }
                 }
             }
             }
         }
         }
     }
     }
+
     TVarLiveMap *inVarMaps[EShLangCount], *outVarMaps[EShLangCount], *uniformVarMap[EShLangCount];
     TVarLiveMap *inVarMaps[EShLangCount], *outVarMaps[EShLangCount], *uniformVarMap[EShLangCount];
-    // Use for mark pre stage, to get more interface symbol information.
-    EShLanguage preStage, currentStage, nextStage;
+
     // Use for mark current shader stage for resolver
     // Use for mark current shader stage for resolver
     TIoMapResolver& resolver;
     TIoMapResolver& resolver;
     TInfoSink& infoSink;
     TInfoSink& infoSink;
     bool& hadError;
     bool& hadError;
+    EProfile profile;
+    int version;
 
 
 private:
 private:
     TSymbolValidater& operator=(TSymbolValidater&) = delete;
     TSymbolValidater& operator=(TSymbolValidater&) = delete;
+
+    bool qualifierCheck(const TType* const type1, const TType* const type2, const std::string& name, bool isBlock)
+    {
+        bool hasError = false;
+        const TQualifier& qualifier1 = type1->getQualifier();
+        const TQualifier& qualifier2 = type2->getQualifier();
+
+        if (((isBlock == false) &&
+            (type1->getQualifier().storage == EvqUniform && type2->getQualifier().storage == EvqUniform)) ||
+            (type1->getQualifier().storage == EvqGlobal && type2->getQualifier().storage == EvqGlobal)) {
+            if (qualifier1.precision != qualifier2.precision) {
+                hasError = true;
+                std::string errorStr = name + ": have precision conflict cross stage.";
+                infoSink.info.message(EPrefixError, errorStr.c_str());
+            }
+            if (qualifier1.hasFormat() && qualifier2.hasFormat()) {
+                if (qualifier1.layoutFormat != qualifier2.layoutFormat) {
+                    hasError = true;
+                    std::string errorStr = name + ": have layout format conflict cross stage.";
+                    infoSink.info.message(EPrefixError, errorStr.c_str());
+                }
+
+            }
+        }
+
+        if (isBlock == true) {
+            if (qualifier1.layoutPacking != qualifier2.layoutPacking) {
+                hasError = true;
+                std::string errorStr = name + ": have layoutPacking conflict cross stage.";
+                infoSink.info.message(EPrefixError, errorStr.c_str());
+            }
+            if (qualifier1.layoutMatrix != qualifier2.layoutMatrix) {
+                hasError = true;
+                std::string errorStr = name + ": have layoutMatrix conflict cross stage.";
+                infoSink.info.message(EPrefixError, errorStr.c_str());
+            }
+            if (qualifier1.layoutOffset != qualifier2.layoutOffset) {
+                hasError = true;
+                std::string errorStr = name + ": have layoutOffset conflict cross stage.";
+                infoSink.info.message(EPrefixError, errorStr.c_str());
+            }
+            if (qualifier1.layoutAlign != qualifier2.layoutAlign) {
+                hasError = true;
+                std::string errorStr = name + ": have layoutAlign conflict cross stage.";
+                infoSink.info.message(EPrefixError, errorStr.c_str());
+            }
+        }
+
+        return hasError;
+    }
+
+    bool typeCheck(const TType* const type1, const TType* const type2, const std::string& name, bool isBlock)
+    {
+        bool hasError = false;
+        if (!(type1->isStruct() && type2->isStruct())) {
+            hasError = hasError || qualifierCheck(type1, type2, name, isBlock);
+        }
+        else {
+            if (type1->getBasicType() == EbtBlock && type2->getBasicType() == EbtBlock)
+                isBlock = true;
+            const TTypeList* typeList1 = type1->getStruct();
+            const TTypeList* typeList2 = type2->getStruct();
+
+            std::string newName = name;
+            size_t memberCount = typeList1->size();
+            size_t index2 = 0;
+            for (size_t index = 0; index < memberCount; index++, index2++) {
+                // Skip inactive member
+                if (typeList1->at(index).type->getBasicType() == EbtVoid)
+                    continue;
+                while (index2 < typeList2->size() && typeList2->at(index2).type->getBasicType() == EbtVoid) {
+                    ++index2;
+                }
+
+                // TypeList1 has more members in list
+                if (index2 == typeList2->size()) {
+                    std::string errorStr = name + ": struct mismatch.";
+                    infoSink.info.message(EPrefixError, errorStr.c_str());
+                    hasError = true;
+                    break;
+                }
+
+                if (typeList1->at(index).type->getFieldName() != typeList2->at(index2).type->getFieldName()) {
+                    std::string errorStr = name + ": member name mismatch.";
+                    infoSink.info.message(EPrefixError, errorStr.c_str());
+                    hasError = true;
+                }
+                else {
+                    newName = typeList1->at(index).type->getFieldName().c_str();
+                }
+                hasError = hasError || typeCheck(typeList1->at(index).type, typeList2->at(index2).type, newName, isBlock);
+            }
+
+            while (index2 < typeList2->size())
+            {
+                // TypeList2 has more members
+                if (typeList2->at(index2).type->getBasicType() != EbtVoid) {
+                    std::string errorStr = name + ": struct mismatch.";
+                    infoSink.info.message(EPrefixError, errorStr.c_str());
+                    hasError = true;
+                    break;
+                }
+                ++index2;
+            }
+        }
+        return hasError;
+    }
 };
 };
 
 
 struct TSlotCollector {
 struct TSlotCollector {
@@ -438,14 +754,18 @@ TDefaultIoResolverBase::TDefaultIoResolverBase(const TIntermediate& intermediate
     , nextOutputLocation(0)
     , nextOutputLocation(0)
 {
 {
     memset(stageMask, false, sizeof(bool) * (EShLangCount + 1));
     memset(stageMask, false, sizeof(bool) * (EShLangCount + 1));
+    memset(stageIntermediates, 0, sizeof(TIntermediate*) * (EShLangCount));
+    stageIntermediates[intermediate.getStage()] = &intermediate;
 }
 }
 
 
-int TDefaultIoResolverBase::getBaseBinding(TResourceType res, unsigned int set) const {
-    return selectBaseBinding(intermediate.getShiftBinding(res), intermediate.getShiftBindingForSet(res, set));
+int TDefaultIoResolverBase::getBaseBinding(EShLanguage stage, TResourceType res, unsigned int set) const {
+    return stageIntermediates[stage] ? selectBaseBinding(stageIntermediates[stage]->getShiftBinding(res), stageIntermediates[stage]->getShiftBindingForSet(res, set))
+                                     : selectBaseBinding(intermediate.getShiftBinding(res), intermediate.getShiftBindingForSet(res, set));
 }
 }
 
 
-const std::vector<std::string>& TDefaultIoResolverBase::getResourceSetBinding() const {
-    return intermediate.getResourceSetBinding();
+const std::vector<std::string>& TDefaultIoResolverBase::getResourceSetBinding(EShLanguage stage) const {
+    return stageIntermediates[stage] ? stageIntermediates[stage]->getResourceSetBinding()
+                                     : intermediate.getResourceSetBinding();
 }
 }
 
 
 bool TDefaultIoResolverBase::doAutoBindingMapping() const { return intermediate.getAutoMapBindings(); }
 bool TDefaultIoResolverBase::doAutoBindingMapping() const { return intermediate.getAutoMapBindings(); }
@@ -486,21 +806,21 @@ int TDefaultIoResolverBase::getFreeSlot(int set, int base, int size) {
     return reserveSlot(set, base, size);
     return reserveSlot(set, base, size);
 }
 }
 
 
-int TDefaultIoResolverBase::resolveSet(EShLanguage /*stage*/, TVarEntryInfo& ent) {
+int TDefaultIoResolverBase::resolveSet(EShLanguage stage, TVarEntryInfo& ent) {
     const TType& type = ent.symbol->getType();
     const TType& type = ent.symbol->getType();
     if (type.getQualifier().hasSet()) {
     if (type.getQualifier().hasSet()) {
         return ent.newSet = type.getQualifier().layoutSet;
         return ent.newSet = type.getQualifier().layoutSet;
     }
     }
     // If a command line or API option requested a single descriptor set, use that (if not overrided by spaceN)
     // If a command line or API option requested a single descriptor set, use that (if not overrided by spaceN)
-    if (getResourceSetBinding().size() == 1) {
-        return ent.newSet = atoi(getResourceSetBinding()[0].c_str());
+    if (getResourceSetBinding(stage).size() == 1) {
+        return ent.newSet = atoi(getResourceSetBinding(stage)[0].c_str());
     }
     }
     return ent.newSet = 0;
     return ent.newSet = 0;
 }
 }
 
 
 int TDefaultIoResolverBase::resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) {
 int TDefaultIoResolverBase::resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) {
     const TType& type = ent.symbol->getType();
     const TType& type = ent.symbol->getType();
-    const char* name = ent.symbol->getName().c_str();
+    const char* name =  ent.symbol->getAccessName().c_str();
     // kick out of not doing this
     // kick out of not doing this
     if (! doAutoLocationMapping()) {
     if (! doAutoLocationMapping()) {
         return ent.newLocation = -1;
         return ent.newLocation = -1;
@@ -609,12 +929,12 @@ TDefaultGlslIoResolver::TDefaultGlslIoResolver(const TIntermediate& intermediate
 
 
 int TDefaultGlslIoResolver::resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) {
 int TDefaultGlslIoResolver::resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) {
     const TType& type = ent.symbol->getType();
     const TType& type = ent.symbol->getType();
-    const TString& name = getAccessName(ent.symbol);
+    const TString& name = ent.symbol->getAccessName();
     if (currentStage != stage) {
     if (currentStage != stage) {
         preStage = currentStage;
         preStage = currentStage;
         currentStage = stage;
         currentStage = stage;
     }
     }
-    // kick out of not doing this
+    // kick out if not doing this
     if (! doAutoLocationMapping()) {
     if (! doAutoLocationMapping()) {
         return ent.newLocation = -1;
         return ent.newLocation = -1;
     }
     }
@@ -693,7 +1013,7 @@ int TDefaultGlslIoResolver::resolveInOutLocation(EShLanguage stage, TVarEntryInf
 
 
 int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) {
 int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) {
     const TType& type = ent.symbol->getType();
     const TType& type = ent.symbol->getType();
-    const TString& name = getAccessName(ent.symbol);
+    const TString& name = ent.symbol->getAccessName();
     // kick out of not doing this
     // kick out of not doing this
     if (! doAutoLocationMapping()) {
     if (! doAutoLocationMapping()) {
         return ent.newLocation = -1;
         return ent.newLocation = -1;
@@ -762,9 +1082,9 @@ int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEn
     return ent.newLocation = location;
     return ent.newLocation = location;
 }
 }
 
 
-int TDefaultGlslIoResolver::resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& ent) {
+int TDefaultGlslIoResolver::resolveBinding(EShLanguage stage, TVarEntryInfo& ent) {
     const TType& type = ent.symbol->getType();
     const TType& type = ent.symbol->getType();
-    const TString& name = getAccessName(ent.symbol);
+    const TString& name = ent.symbol->getAccessName();
     // On OpenGL arrays of opaque types take a separate binding for each element
     // On OpenGL arrays of opaque types take a separate binding for each element
     int numBindings = intermediate.getSpv().openGl != 0 && type.isSizedArray() ? type.getCumulativeArraySize() : 1;
     int numBindings = intermediate.getSpv().openGl != 0 && type.isSizedArray() ? type.getCumulativeArraySize() : 1;
     TResourceType resource = getResourceType(type);
     TResourceType resource = getResourceType(type);
@@ -775,30 +1095,32 @@ int TDefaultGlslIoResolver::resolveBinding(EShLanguage /*stage*/, TVarEntryInfo&
     // There is no 'set' qualifier in OpenGL shading language, each resource has its own
     // There is no 'set' qualifier in OpenGL shading language, each resource has its own
     // binding name space, so remap the 'set' to resource type which make each resource
     // binding name space, so remap the 'set' to resource type which make each resource
     // binding is valid from 0 to MAX_XXRESOURCE_BINDINGS
     // binding is valid from 0 to MAX_XXRESOURCE_BINDINGS
-    int set = resource;
+    int set = intermediate.getSpv().openGl != 0 ? resource : ent.newSet;
+    int resourceKey = set;
     if (resource < EResCount) {
     if (resource < EResCount) {
         if (type.getQualifier().hasBinding()) {
         if (type.getQualifier().hasBinding()) {
-            ent.newBinding = reserveSlot(set, getBaseBinding(resource, set) + type.getQualifier().layoutBinding, numBindings);
-            return ent.newBinding;
-        } else if (ent.live && doAutoBindingMapping()) {
+            int newBinding = reserveSlot(resourceKey, getBaseBinding(stage, resource, set) + type.getQualifier().layoutBinding, numBindings);
+            return ent.newBinding = newBinding;
+
+        } else {
             // The resource in current stage is not declared with binding, but it is possible declared
             // The resource in current stage is not declared with binding, but it is possible declared
             // with explicit binding in other stages, find the resourceSlotMap firstly to check whether
             // with explicit binding in other stages, find the resourceSlotMap firstly to check whether
             // the resource has binding, don't need to allocate if it already has a binding
             // the resource has binding, don't need to allocate if it already has a binding
             bool hasBinding = false;
             bool hasBinding = false;
-            if (! resourceSlotMap[resource].empty()) {
-                TVarSlotMap::iterator iter = resourceSlotMap[resource].find(name);
-                if (iter != resourceSlotMap[resource].end()) {
+            ent.newBinding = -1; // leave as -1 if it isn't set below
+
+            if (! resourceSlotMap[resourceKey].empty()) {
+                TVarSlotMap::iterator iter = resourceSlotMap[resourceKey].find(name);
+                if (iter != resourceSlotMap[resourceKey].end()) {
                     hasBinding = true;
                     hasBinding = true;
                     ent.newBinding = iter->second;
                     ent.newBinding = iter->second;
                 }
                 }
             }
             }
-            if (! hasBinding) {
-                TVarSlotMap varSlotMap;
+            if (!hasBinding && (ent.live && doAutoBindingMapping())) {
                 // find free slot, the caller did make sure it passes all vars with binding
                 // find free slot, the caller did make sure it passes all vars with binding
                 // first and now all are passed that do not have a binding and needs one
                 // first and now all are passed that do not have a binding and needs one
-                int binding = getFreeSlot(resource, getBaseBinding(resource, set), numBindings);
-                varSlotMap[name] = binding;
-                resourceSlotMap[resource] = varSlotMap;
+                int binding = getFreeSlot(resourceKey, getBaseBinding(stage, resource, set), numBindings);
+                resourceSlotMap[resourceKey][name] = binding;
                 ent.newBinding = binding;
                 ent.newBinding = binding;
             }
             }
             return ent.newBinding;
             return ent.newBinding;
@@ -839,7 +1161,7 @@ void TDefaultGlslIoResolver::endCollect(EShLanguage /*stage*/) {
 
 
 void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) {
 void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) {
     const TType& type = ent.symbol->getType();
     const TType& type = ent.symbol->getType();
-    const TString& name = getAccessName(ent.symbol);
+    const TString& name = ent.symbol->getAccessName();
     TStorageQualifier storage = type.getQualifier().storage;
     TStorageQualifier storage = type.getQualifier().storage;
     EShLanguage stage(EShLangCount);
     EShLanguage stage(EShLangCount);
     switch (storage) {
     switch (storage) {
@@ -899,17 +1221,21 @@ void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink&
 
 
 void TDefaultGlslIoResolver::reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) {
 void TDefaultGlslIoResolver::reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) {
     const TType& type = ent.symbol->getType();
     const TType& type = ent.symbol->getType();
-    const TString& name = getAccessName(ent.symbol);
-    int resource = getResourceType(type);
+    const TString& name = ent.symbol->getAccessName();
+    TResourceType resource = getResourceType(type);
+    int set = intermediate.getSpv().openGl != 0 ? resource : resolveSet(ent.stage, ent);
+    int resourceKey = set;
+
     if (type.getQualifier().hasBinding()) {
     if (type.getQualifier().hasBinding()) {
-        TVarSlotMap& varSlotMap = resourceSlotMap[resource];
+        TVarSlotMap& varSlotMap = resourceSlotMap[resourceKey];
         TVarSlotMap::iterator iter = varSlotMap.find(name);
         TVarSlotMap::iterator iter = varSlotMap.find(name);
-        int binding = type.getQualifier().layoutBinding;
+        int binding = type.getQualifier().layoutBinding + getBaseBinding(ent.stage, resource, set);
+
         if (iter == varSlotMap.end()) {
         if (iter == varSlotMap.end()) {
             // Reserve the slots for the ubo, ssbo and opaques who has explicit binding
             // Reserve the slots for the ubo, ssbo and opaques who has explicit binding
-            int numBindings = type.isSizedArray() ? type.getCumulativeArraySize() : 1;
+            int numBindings = intermediate.getSpv().openGl != 0 && type.isSizedArray() ? type.getCumulativeArraySize() : 1;
             varSlotMap[name] = binding;
             varSlotMap[name] = binding;
-            reserveSlot(resource, binding, numBindings);
+            reserveSlot(resourceKey, binding, numBindings);
         } else {
         } else {
             // Allocate binding by name for OpenGL driver, so the resource in different
             // Allocate binding by name for OpenGL driver, so the resource in different
             // stages should be declared with the same binding
             // stages should be declared with the same binding
@@ -922,13 +1248,6 @@ void TDefaultGlslIoResolver::reserverResourceSlot(TVarEntryInfo& ent, TInfoSink&
     }
     }
 }
 }
 
 
-const TString& TDefaultGlslIoResolver::getAccessName(const TIntermSymbol* symbol)
-{
-    return symbol->getBasicType() == EbtBlock ?
-        symbol->getType().getTypeName() :
-        symbol->getName();
-}
-
 //TDefaultGlslIoResolver end
 //TDefaultGlslIoResolver end
 
 
 /*
 /*
@@ -965,7 +1284,7 @@ struct TDefaultIoResolver : public TDefaultIoResolverBase {
         return EResCount;
         return EResCount;
     }
     }
 
 
-    int resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& ent) override {
+    int resolveBinding(EShLanguage stage, TVarEntryInfo& ent) override {
         const TType& type = ent.symbol->getType();
         const TType& type = ent.symbol->getType();
         const int set = getLayoutSet(type);
         const int set = getLayoutSet(type);
         // On OpenGL arrays of opaque types take a seperate binding for each element
         // On OpenGL arrays of opaque types take a seperate binding for each element
@@ -974,11 +1293,11 @@ struct TDefaultIoResolver : public TDefaultIoResolverBase {
         if (resource < EResCount) {
         if (resource < EResCount) {
             if (type.getQualifier().hasBinding()) {
             if (type.getQualifier().hasBinding()) {
                 return ent.newBinding = reserveSlot(
                 return ent.newBinding = reserveSlot(
-                           set, getBaseBinding(resource, set) + type.getQualifier().layoutBinding, numBindings);
+                           set, getBaseBinding(stage, resource, set) + type.getQualifier().layoutBinding, numBindings);
             } else if (ent.live && doAutoBindingMapping()) {
             } else if (ent.live && doAutoBindingMapping()) {
                 // find free slot, the caller did make sure it passes all vars with binding
                 // find free slot, the caller did make sure it passes all vars with binding
                 // first and now all are passed that do not have a binding and needs one
                 // first and now all are passed that do not have a binding and needs one
-                return ent.newBinding = getFreeSlot(set, getBaseBinding(resource, set), numBindings);
+                return ent.newBinding = getFreeSlot(set, getBaseBinding(stage, resource, set), numBindings);
             }
             }
         }
         }
         return ent.newBinding = -1;
         return ent.newBinding = -1;
@@ -1050,17 +1369,17 @@ struct TDefaultHlslIoResolver : public TDefaultIoResolverBase {
         return EResCount;
         return EResCount;
     }
     }
 
 
-    int resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& ent) override {
+    int resolveBinding(EShLanguage stage, TVarEntryInfo& ent) override {
         const TType& type = ent.symbol->getType();
         const TType& type = ent.symbol->getType();
         const int set = getLayoutSet(type);
         const int set = getLayoutSet(type);
         TResourceType resource = getResourceType(type);
         TResourceType resource = getResourceType(type);
         if (resource < EResCount) {
         if (resource < EResCount) {
             if (type.getQualifier().hasBinding()) {
             if (type.getQualifier().hasBinding()) {
-                return ent.newBinding = reserveSlot(set, getBaseBinding(resource, set) + type.getQualifier().layoutBinding);
+                return ent.newBinding = reserveSlot(set, getBaseBinding(stage, resource, set) + type.getQualifier().layoutBinding);
             } else if (ent.live && doAutoBindingMapping()) {
             } else if (ent.live && doAutoBindingMapping()) {
                 // find free slot, the caller did make sure it passes all vars with binding
                 // find free slot, the caller did make sure it passes all vars with binding
                 // first and now all are passed that do not have a binding and needs one
                 // first and now all are passed that do not have a binding and needs one
-                return ent.newBinding = getFreeSlot(set, getBaseBinding(resource, set));
+                return ent.newBinding = getFreeSlot(set, getBaseBinding(stage, resource, set));
             }
             }
         }
         }
         return ent.newBinding = -1;
         return ent.newBinding = -1;
@@ -1099,10 +1418,10 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TInfoSi
         else
         else
             resolver = &defaultResolver;
             resolver = &defaultResolver;
     }
     }
-    resolver->addStage(stage);
 #else
 #else
     resolver = &defaultResolver;
     resolver = &defaultResolver;
 #endif
 #endif
+    resolver->addStage(stage, intermediate);
 
 
     TVarLiveMap inVarMap, outVarMap, uniformVarMap;
     TVarLiveMap inVarMap, outVarMap, uniformVarMap;
     TVarLiveVector inVector, outVector, uniformVector;
     TVarLiveVector inVector, outVector, uniformVector;
@@ -1117,25 +1436,23 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TInfoSi
     }
     }
 
 
     // sort entries by priority. see TVarEntryInfo::TOrderByPriority for info.
     // sort entries by priority. see TVarEntryInfo::TOrderByPriority for info.
-    std::for_each(inVarMap.begin(), inVarMap.end(),
-                  [&inVector](TVarLivePair p) { inVector.push_back(p); });
+    for (auto& var : inVarMap) { inVector.push_back(var); }
     std::sort(inVector.begin(), inVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
     std::sort(inVector.begin(), inVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
         return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
         return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
     });
     });
-    std::for_each(outVarMap.begin(), outVarMap.end(),
-                  [&outVector](TVarLivePair p) { outVector.push_back(p); });
+    for (auto& var : outVarMap) { outVector.push_back(var); }
     std::sort(outVector.begin(), outVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
     std::sort(outVector.begin(), outVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
         return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
         return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
     });
     });
-    std::for_each(uniformVarMap.begin(), uniformVarMap.end(),
-                  [&uniformVector](TVarLivePair p) { uniformVector.push_back(p); });
+    for (auto& var : uniformVarMap) { uniformVector.push_back(var); }
     std::sort(uniformVector.begin(), uniformVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
     std::sort(uniformVector.begin(), uniformVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
         return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
         return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
     });
     });
     bool hadError = false;
     bool hadError = false;
+    TVarLiveMap* dummyUniformVarMap[EShLangCount] = {};
     TNotifyInOutAdaptor inOutNotify(stage, *resolver);
     TNotifyInOutAdaptor inOutNotify(stage, *resolver);
     TNotifyUniformAdaptor uniformNotify(stage, *resolver);
     TNotifyUniformAdaptor uniformNotify(stage, *resolver);
-    TResolverUniformAdaptor uniformResolve(stage, *resolver, infoSink, hadError);
+    TResolverUniformAdaptor uniformResolve(stage, *resolver, dummyUniformVarMap, infoSink, hadError);
     TResolverInOutAdaptor inOutResolve(stage, *resolver, infoSink, hadError);
     TResolverInOutAdaptor inOutResolve(stage, *resolver, infoSink, hadError);
     resolver->beginNotifications(stage);
     resolver->beginNotifications(stage);
     std::for_each(inVector.begin(), inVector.end(), inOutNotify);
     std::for_each(inVector.begin(), inVector.end(), inOutNotify);
@@ -1143,22 +1460,22 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TInfoSi
     std::for_each(uniformVector.begin(), uniformVector.end(), uniformNotify);
     std::for_each(uniformVector.begin(), uniformVector.end(), uniformNotify);
     resolver->endNotifications(stage);
     resolver->endNotifications(stage);
     resolver->beginResolve(stage);
     resolver->beginResolve(stage);
-    std::for_each(inVector.begin(), inVector.end(), inOutResolve);
+    for (auto& var : inVector) { inOutResolve(var); }
     std::for_each(inVector.begin(), inVector.end(), [&inVarMap](TVarLivePair p) {
     std::for_each(inVector.begin(), inVector.end(), [&inVarMap](TVarLivePair p) {
-        auto at = inVarMap.find(p.second.symbol->getName());
-        if (at != inVarMap.end())
+        auto at = inVarMap.find(p.second.symbol->getAccessName());
+        if (at != inVarMap.end() && p.second.id == at->second.id)
             at->second = p.second;
             at->second = p.second;
     });
     });
-    std::for_each(outVector.begin(), outVector.end(), inOutResolve);
+    for (auto& var : outVector) { inOutResolve(var); }
     std::for_each(outVector.begin(), outVector.end(), [&outVarMap](TVarLivePair p) {
     std::for_each(outVector.begin(), outVector.end(), [&outVarMap](TVarLivePair p) {
-        auto at = outVarMap.find(p.second.symbol->getName());
-        if (at != outVarMap.end())
+        auto at = outVarMap.find(p.second.symbol->getAccessName());
+        if (at != outVarMap.end() && p.second.id == at->second.id)
             at->second = p.second;
             at->second = p.second;
     });
     });
     std::for_each(uniformVector.begin(), uniformVector.end(), uniformResolve);
     std::for_each(uniformVector.begin(), uniformVector.end(), uniformResolve);
     std::for_each(uniformVector.begin(), uniformVector.end(), [&uniformVarMap](TVarLivePair p) {
     std::for_each(uniformVector.begin(), uniformVector.end(), [&uniformVarMap](TVarLivePair p) {
-        auto at = uniformVarMap.find(p.second.symbol->getName());
-        if (at != uniformVarMap.end())
+        auto at = uniformVarMap.find(p.second.symbol->getAccessName());
+        if (at != uniformVarMap.end() && p.second.id == at->second.id)
             at->second = p.second;
             at->second = p.second;
     });
     });
     resolver->endResolve(stage);
     resolver->endResolve(stage);
@@ -1174,9 +1491,14 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TInfoSi
 //
 //
 // Returns false if the input is too malformed to do this.
 // Returns false if the input is too malformed to do this.
 bool TGlslIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TInfoSink& infoSink, TIoMapResolver* resolver) {
 bool TGlslIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TInfoSink& infoSink, TIoMapResolver* resolver) {
+    bool somethingToDo = !intermediate.getResourceSetBinding().empty() ||
+        intermediate.getAutoMapBindings() ||
+        intermediate.getAutoMapLocations();
+
+    // Profile and version are use for symbol validate.
+    profile = intermediate.getProfile();
+    version = intermediate.getVersion();
 
 
-    bool somethingToDo = ! intermediate.getResourceSetBinding().empty() || intermediate.getAutoMapBindings() ||
-                         intermediate.getAutoMapLocations();
     // Restrict the stricter condition to further check 'somethingToDo' only if 'somethingToDo' has not been set, reduce
     // Restrict the stricter condition to further check 'somethingToDo' only if 'somethingToDo' has not been set, reduce
     // unnecessary or insignificant for-loop operation after 'somethingToDo' have been true.
     // unnecessary or insignificant for-loop operation after 'somethingToDo' have been true.
     for (int res = 0; (res < EResCount && !somethingToDo); ++res) {
     for (int res = 0; (res < EResCount && !somethingToDo); ++res) {
@@ -1195,10 +1517,21 @@ bool TGlslIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TIn
     }
     }
     // if no resolver is provided, use the default resolver with the given shifts and auto map settings
     // if no resolver is provided, use the default resolver with the given shifts and auto map settings
     TDefaultGlslIoResolver defaultResolver(intermediate);
     TDefaultGlslIoResolver defaultResolver(intermediate);
+#ifdef ENABLE_HLSL
+    TDefaultHlslIoResolver defaultHlslResolver(intermediate);
+    if (resolver == nullptr) {
+        // TODO: use a passed in IO mapper for this
+        if (intermediate.usingHlslIoMapping())
+            resolver = &defaultHlslResolver;
+        else
+            resolver = &defaultResolver;
+    }
+#else
     if (resolver == nullptr) {
     if (resolver == nullptr) {
         resolver = &defaultResolver;
         resolver = &defaultResolver;
     }
     }
-    resolver->addStage(stage);
+#endif
+    resolver->addStage(stage, intermediate);
     inVarMaps[stage] = new TVarLiveMap(); outVarMaps[stage] = new TVarLiveMap(); uniformVarMap[stage] = new TVarLiveMap();
     inVarMaps[stage] = new TVarLiveMap(); outVarMaps[stage] = new TVarLiveMap(); uniformVarMap[stage] = new TVarLiveMap();
     TVarGatherTraverser iter_binding_all(intermediate, true, *inVarMaps[stage], *outVarMaps[stage],
     TVarGatherTraverser iter_binding_all(intermediate, true, *inVarMaps[stage], *outVarMaps[stage],
                                          *uniformVarMap[stage]);
                                          *uniformVarMap[stage]);
@@ -1236,31 +1569,66 @@ bool TGlslIoMapper::doMap(TIoMapResolver* resolver, TInfoSink& infoSink) {
     resolver->endResolve(EShLangCount);
     resolver->endResolve(EShLangCount);
     if (!hadError) {
     if (!hadError) {
         //Resolve uniform location, ubo/ssbo/opaque bindings across stages
         //Resolve uniform location, ubo/ssbo/opaque bindings across stages
-        TResolverUniformAdaptor uniformResolve(EShLangCount, *resolver, infoSink, hadError);
+        TResolverUniformAdaptor uniformResolve(EShLangCount, *resolver, uniformVarMap, infoSink, hadError);
         TResolverInOutAdaptor inOutResolve(EShLangCount, *resolver, infoSink, hadError);
         TResolverInOutAdaptor inOutResolve(EShLangCount, *resolver, infoSink, hadError);
-        TSymbolValidater symbolValidater(*resolver, infoSink, inVarMaps, outVarMaps, uniformVarMap, hadError);
+        TSymbolValidater symbolValidater(*resolver, infoSink, inVarMaps,
+                                         outVarMaps, uniformVarMap, hadError, profile, version);
+
+        TVarLiveVector inVectors[EShLangCount];
+        TVarLiveVector outVectors[EShLangCount];
         TVarLiveVector uniformVector;
         TVarLiveVector uniformVector;
+
         resolver->beginResolve(EShLangCount);
         resolver->beginResolve(EShLangCount);
         for (int stage = EShLangVertex; stage < EShLangCount; stage++) {
         for (int stage = EShLangVertex; stage < EShLangCount; stage++) {
             if (inVarMaps[stage] != nullptr) {
             if (inVarMaps[stage] != nullptr) {
                 inOutResolve.setStage(EShLanguage(stage));
                 inOutResolve.setStage(EShLanguage(stage));
-                std::for_each(inVarMaps[stage]->begin(), inVarMaps[stage]->end(), symbolValidater);
-                std::for_each(inVarMaps[stage]->begin(), inVarMaps[stage]->end(), inOutResolve);
-                std::for_each(outVarMaps[stage]->begin(), outVarMaps[stage]->end(), symbolValidater);
-                std::for_each(outVarMaps[stage]->begin(), outVarMaps[stage]->end(), inOutResolve);
+
+                // copy vars into a sorted list
+                std::for_each(inVarMaps[stage]->begin(), inVarMaps[stage]->end(),
+                        [&inVectors, stage](TVarLivePair p) { inVectors[stage].push_back(p); });
+                std::sort(inVectors[stage].begin(), inVectors[stage].end(),
+                        [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
+                            return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
+                });
+
+                std::for_each(outVarMaps[stage]->begin(), outVarMaps[stage]->end(),
+                        [&outVectors, stage](TVarLivePair p) { outVectors[stage].push_back(p); });
+                std::sort(outVectors[stage].begin(), outVectors[stage].end(),
+                        [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
+                            return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
+                });
+
+                for (auto& var : inVectors[stage]) { symbolValidater(var); }
+                for (auto& var : inVectors[stage]) { inOutResolve(var); }
+                for (auto& var : outVectors[stage]) { symbolValidater(var); }
+                for (auto& var : outVectors[stage]) { inOutResolve(var); }
+
+                // copy results back into maps
+                std::for_each(inVectors[stage].begin(), inVectors[stage].end(),
+                    [this, stage](TVarLivePair p) {
+                        auto at = inVarMaps[stage]->find(p.first);
+                        if (at != inVarMaps[stage]->end())
+                            at->second = p.second;
+                });
+
+                std::for_each(outVectors[stage].begin(), outVectors[stage].end(),
+                    [this, stage](TVarLivePair p) {
+                        auto at = outVarMaps[stage]->find(p.first);
+                        if (at != outVarMaps[stage]->end())
+                            at->second = p.second;
+                });
+
             }
             }
             if (uniformVarMap[stage] != nullptr) {
             if (uniformVarMap[stage] != nullptr) {
                 uniformResolve.setStage(EShLanguage(stage));
                 uniformResolve.setStage(EShLanguage(stage));
-                // sort entries by priority. see TVarEntryInfo::TOrderByPriority for info.
-                std::for_each(uniformVarMap[stage]->begin(), uniformVarMap[stage]->end(),
-                              [&uniformVector](TVarLivePair p) { uniformVector.push_back(p); });
+                for (auto& var : *(uniformVarMap[stage])) { uniformVector.push_back(var); }
             }
             }
         }
         }
         std::sort(uniformVector.begin(), uniformVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
         std::sort(uniformVector.begin(), uniformVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
-            return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
+            return TVarEntryInfo::TOrderByPriorityAndLive()(p1.second, p2.second);
         });
         });
-        std::for_each(uniformVector.begin(), uniformVector.end(), symbolValidater);
-        std::for_each(uniformVector.begin(), uniformVector.end(), uniformResolve);
+        for (auto& var : uniformVector) { symbolValidater(var); }
+        for (auto& var : uniformVector) { uniformResolve(var); }
         std::sort(uniformVector.begin(), uniformVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
         std::sort(uniformVector.begin(), uniformVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
             return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
             return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
         });
         });
@@ -1269,14 +1637,18 @@ bool TGlslIoMapper::doMap(TIoMapResolver* resolver, TInfoSink& infoSink) {
             if (intermediates[stage] != nullptr) {
             if (intermediates[stage] != nullptr) {
                 // traverse each stage, set new location to each input/output and unifom symbol, set new binding to
                 // traverse each stage, set new location to each input/output and unifom symbol, set new binding to
                 // ubo, ssbo and opaque symbols
                 // ubo, ssbo and opaque symbols
-                TVarLiveMap** pUniformVarMap = uniformVarMap;
+                TVarLiveMap** pUniformVarMap = uniformResolve.uniformVarMap;
                 std::for_each(uniformVector.begin(), uniformVector.end(), [pUniformVarMap, stage](TVarLivePair p) {
                 std::for_each(uniformVector.begin(), uniformVector.end(), [pUniformVarMap, stage](TVarLivePair p) {
-                    auto at = pUniformVarMap[stage]->find(p.second.symbol->getName());
-                    if (at != pUniformVarMap[stage]->end())
+                    auto at = pUniformVarMap[stage]->find(p.second.symbol->getAccessName());
+                    if (at != pUniformVarMap[stage]->end() && at->second.id == p.second.id){
+                        int resolvedBinding = at->second.newBinding;
                         at->second = p.second;
                         at->second = p.second;
+                        if (resolvedBinding > 0)
+                            at->second.newBinding = resolvedBinding;
+                    }
                 });
                 });
                 TVarSetTraverser iter_iomap(*intermediates[stage], *inVarMaps[stage], *outVarMaps[stage],
                 TVarSetTraverser iter_iomap(*intermediates[stage], *inVarMaps[stage], *outVarMaps[stage],
-                                            *uniformVarMap[stage]);
+                                            *uniformResolve.uniformVarMap[stage]);
                 intermediates[stage]->getTreeRoot()->traverse(&iter_iomap);
                 intermediates[stage]->getTreeRoot()->traverse(&iter_iomap);
             }
             }
         }
         }

+ 46 - 10
src/libraries/glslang/glslang/MachineIndependent/iomapper.h

@@ -52,7 +52,7 @@ namespace glslang {
 
 
 class TIntermediate;
 class TIntermediate;
 struct TVarEntryInfo {
 struct TVarEntryInfo {
-    int id;
+    long long id;
     TIntermSymbol* symbol;
     TIntermSymbol* symbol;
     bool live;
     bool live;
     int newBinding;
     int newBinding;
@@ -87,6 +87,35 @@ struct TVarEntryInfo {
             return lPoints > rPoints;
             return lPoints > rPoints;
         }
         }
     };
     };
+
+    struct TOrderByPriorityAndLive {
+        // ordering:
+        // 1) do live variables first
+        // 2) has both binding and set
+        // 3) has binding but no set
+        // 4) has no binding but set
+        // 5) has no binding and no set
+        inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) {
+
+            const TQualifier& lq = l.symbol->getQualifier();
+            const TQualifier& rq = r.symbol->getQualifier();
+
+            // simple rules:
+            // has binding gives 2 points
+            // has set gives 1 point
+            // who has the most points is more important.
+            int lPoints = (lq.hasBinding() ? 2 : 0) + (lq.hasSet() ? 1 : 0);
+            int rPoints = (rq.hasBinding() ? 2 : 0) + (rq.hasSet() ? 1 : 0);
+
+            if (l.live != r.live)
+                return l.live > r.live;
+
+            if (lPoints != rPoints)
+                return lPoints > rPoints;
+
+            return l.id < r.id;
+        }
+    };
 };
 };
 
 
 // Base class for shared TIoMapResolver services, used by several derivations.
 // Base class for shared TIoMapResolver services, used by several derivations.
@@ -107,8 +136,8 @@ public:
     void endCollect(EShLanguage) override {}
     void endCollect(EShLanguage) override {}
     void reserverResourceSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {}
     void reserverResourceSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {}
     void reserverStorageSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {}
     void reserverStorageSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {}
-    int getBaseBinding(TResourceType res, unsigned int set) const;
-    const std::vector<std::string>& getResourceSetBinding() const;
+    int getBaseBinding(EShLanguage stage, TResourceType res, unsigned int set) const;
+    const std::vector<std::string>& getResourceSetBinding(EShLanguage stage) const;
     virtual TResourceType getResourceType(const glslang::TType& type) = 0;
     virtual TResourceType getResourceType(const glslang::TType& type) = 0;
     bool doAutoBindingMapping() const;
     bool doAutoBindingMapping() const;
     bool doAutoLocationMapping() const;
     bool doAutoLocationMapping() const;
@@ -122,9 +151,11 @@ public:
     int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) override;
     int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) override;
     int resolveInOutComponent(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
     int resolveInOutComponent(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
     int resolveInOutIndex(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
     int resolveInOutIndex(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
-    void addStage(EShLanguage stage) override {
-        if (stage < EShLangCount)
+    void addStage(EShLanguage stage, TIntermediate& stageIntermediate) override {
+        if (stage < EShLangCount) {
             stageMask[stage] = true;
             stageMask[stage] = true;
+            stageIntermediates[stage] = &stageIntermediate;
+        }
     }
     }
     uint32_t computeTypeLocationSize(const TType& type, EShLanguage stage);
     uint32_t computeTypeLocationSize(const TType& type, EShLanguage stage);
 
 
@@ -139,6 +170,8 @@ protected:
     int nextInputLocation;
     int nextInputLocation;
     int nextOutputLocation;
     int nextOutputLocation;
     bool stageMask[EShLangCount + 1];
     bool stageMask[EShLangCount + 1];
+    const TIntermediate* stageIntermediates[EShLangCount];
+
     // Return descriptor set specific base if there is one, and the generic base otherwise.
     // Return descriptor set specific base if there is one, and the generic base otherwise.
     int selectBaseBinding(int base, int descriptorSetBase) const {
     int selectBaseBinding(int base, int descriptorSetBase) const {
         return descriptorSetBase != -1 ? descriptorSetBase : base;
         return descriptorSetBase != -1 ? descriptorSetBase : base;
@@ -203,7 +236,6 @@ public:
     void endCollect(EShLanguage) override;
     void endCollect(EShLanguage) override;
     void reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) override;
     void reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) override;
     void reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) override;
     void reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) override;
-    const TString& getAccessName(const TIntermSymbol*);
     // in/out symbol and uniform symbol are stored in the same resourceSlotMap, the storage key is used to identify each type of symbol.
     // in/out symbol and uniform symbol are stored in the same resourceSlotMap, the storage key is used to identify each type of symbol.
     // We use stage and storage qualifier to construct a storage key. it can help us identify the same storage resource used in different stage.
     // We use stage and storage qualifier to construct a storage key. it can help us identify the same storage resource used in different stage.
     // if a resource is a program resource and we don't need know it usage stage, we can use same stage to build storage key.
     // if a resource is a program resource and we don't need know it usage stage, we can use same stage to build storage key.
@@ -263,10 +295,12 @@ public:
 class TGlslIoMapper : public TIoMapper {
 class TGlslIoMapper : public TIoMapper {
 public:
 public:
     TGlslIoMapper() {
     TGlslIoMapper() {
-        memset(inVarMaps,     0, sizeof(TVarLiveMap*)   * EShLangCount);
-        memset(outVarMaps,    0, sizeof(TVarLiveMap*)   * EShLangCount);
-        memset(uniformVarMap, 0, sizeof(TVarLiveMap*)   * EShLangCount);
-        memset(intermediates, 0, sizeof(TIntermediate*) * EShLangCount);
+        memset(inVarMaps,     0, sizeof(TVarLiveMap*)   * (EShLangCount + 1));
+        memset(outVarMaps,    0, sizeof(TVarLiveMap*)   * (EShLangCount + 1));
+        memset(uniformVarMap, 0, sizeof(TVarLiveMap*)   * (EShLangCount + 1));
+        memset(intermediates, 0, sizeof(TIntermediate*) * (EShLangCount + 1));
+        profile = ENoProfile;
+        version = 0;
     }
     }
     virtual ~TGlslIoMapper() {
     virtual ~TGlslIoMapper() {
         for (size_t stage = 0; stage < EShLangCount; stage++) {
         for (size_t stage = 0; stage < EShLangCount; stage++) {
@@ -293,6 +327,8 @@ public:
                 *uniformVarMap[EShLangCount];
                 *uniformVarMap[EShLangCount];
     TIntermediate* intermediates[EShLangCount];
     TIntermediate* intermediates[EShLangCount];
     bool hadError = false;
     bool hadError = false;
+    EProfile profile;
+    int version;
 };
 };
 
 
 } // end namespace glslang
 } // end namespace glslang

+ 3 - 3
src/libraries/glslang/glslang/MachineIndependent/limits.cpp

@@ -63,14 +63,14 @@ namespace glslang {
 
 
 class TInductiveTraverser : public TIntermTraverser {
 class TInductiveTraverser : public TIntermTraverser {
 public:
 public:
-    TInductiveTraverser(int id, TSymbolTable& st)
+    TInductiveTraverser(long long id, TSymbolTable& st)
     : loopId(id), symbolTable(st), bad(false)  { }
     : loopId(id), symbolTable(st), bad(false)  { }
 
 
     virtual bool visitBinary(TVisit, TIntermBinary* node);
     virtual bool visitBinary(TVisit, TIntermBinary* node);
     virtual bool visitUnary(TVisit, TIntermUnary* node);
     virtual bool visitUnary(TVisit, TIntermUnary* node);
     virtual bool visitAggregate(TVisit, TIntermAggregate* node);
     virtual bool visitAggregate(TVisit, TIntermAggregate* node);
 
 
-    int loopId;           // unique ID of the symbol that's the loop inductive variable
+    long long loopId;           // unique ID of the symbol that's the loop inductive variable
     TSymbolTable& symbolTable;
     TSymbolTable& symbolTable;
     bool bad;
     bool bad;
     TSourceLoc badLoc;
     TSourceLoc badLoc;
@@ -129,7 +129,7 @@ bool TInductiveTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* n
 //
 //
 // External function to call for loop check.
 // External function to call for loop check.
 //
 //
-void TParseContext::inductiveLoopBodyCheck(TIntermNode* body, int loopId, TSymbolTable& symbolTable)
+void TParseContext::inductiveLoopBodyCheck(TIntermNode* body, long long loopId, TSymbolTable& symbolTable)
 {
 {
     TInductiveTraverser it(loopId, symbolTable);
     TInductiveTraverser it(loopId, symbolTable);
 
 

+ 433 - 44
src/libraries/glslang/glslang/MachineIndependent/linkValidate.cpp

@@ -48,6 +48,7 @@
 
 
 #include "localintermediate.h"
 #include "localintermediate.h"
 #include "../Include/InfoSink.h"
 #include "../Include/InfoSink.h"
+#include "SymbolTable.h"
 
 
 namespace glslang {
 namespace glslang {
 
 
@@ -89,6 +90,56 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
 #endif
 #endif
 }
 }
 
 
+//
+// check that link objects between stages
+//
+void TIntermediate::mergeUniformObjects(TInfoSink& infoSink, TIntermediate& unit) {
+    if (unit.treeRoot == nullptr || treeRoot == nullptr)
+        return;
+
+    // Get the linker-object lists
+    TIntermSequence& linkerObjects = findLinkerObjects()->getSequence();
+    TIntermSequence unitLinkerObjects = unit.findLinkerObjects()->getSequence();
+
+    // filter unitLinkerObjects to only contain uniforms
+    auto end = std::remove_if(unitLinkerObjects.begin(), unitLinkerObjects.end(),
+        [](TIntermNode* node) {return node->getAsSymbolNode()->getQualifier().storage != EvqUniform &&
+                                      node->getAsSymbolNode()->getQualifier().storage != EvqBuffer; });
+    unitLinkerObjects.resize(end - unitLinkerObjects.begin());
+
+    // merge uniforms and do error checking
+    bool mergeExistingOnly = false;
+    mergeGlobalUniformBlocks(infoSink, unit, mergeExistingOnly);
+    mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects, unit.getStage());
+}
+
+//
+// do error checking on the shader boundary in / out vars 
+//
+void TIntermediate::checkStageIO(TInfoSink& infoSink, TIntermediate& unit) {
+    if (unit.treeRoot == nullptr || treeRoot == nullptr)
+        return;
+
+    // Get copies of the linker-object lists
+    TIntermSequence linkerObjects = findLinkerObjects()->getSequence();
+    TIntermSequence unitLinkerObjects = unit.findLinkerObjects()->getSequence();
+
+    // filter linkerObjects to only contain out variables
+    auto end = std::remove_if(linkerObjects.begin(), linkerObjects.end(),
+        [](TIntermNode* node) {return node->getAsSymbolNode()->getQualifier().storage != EvqVaryingOut; });
+    linkerObjects.resize(end - linkerObjects.begin());
+
+    // filter unitLinkerObjects to only contain in variables
+    auto unitEnd = std::remove_if(unitLinkerObjects.begin(), unitLinkerObjects.end(),
+        [](TIntermNode* node) {return node->getAsSymbolNode()->getQualifier().storage != EvqVaryingIn; });
+    unitLinkerObjects.resize(unitEnd - unitLinkerObjects.begin());
+
+    // do matching and error checking
+    mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects, unit.getStage());
+
+    // TODO: final check; make sure that any statically used `in` have matching `out` written to
+}
+
 void TIntermediate::mergeCallGraphs(TInfoSink& infoSink, TIntermediate& unit)
 void TIntermediate::mergeCallGraphs(TInfoSink& infoSink, TIntermediate& unit)
 {
 {
     if (unit.getNumEntryPoints() > 0) {
     if (unit.getNumEntryPoints() > 0) {
@@ -136,6 +187,7 @@ void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit)
     MERGE_MAX(spvVersion.vulkanGlsl);
     MERGE_MAX(spvVersion.vulkanGlsl);
     MERGE_MAX(spvVersion.vulkan);
     MERGE_MAX(spvVersion.vulkan);
     MERGE_MAX(spvVersion.openGl);
     MERGE_MAX(spvVersion.openGl);
+    MERGE_TRUE(spvVersion.vulkanRelaxed);
 
 
     numErrors += unit.getNumErrors();
     numErrors += unit.getNumErrors();
     // Only one push_constant is allowed, mergeLinkerObjects() will ensure the push_constant
     // Only one push_constant is allowed, mergeLinkerObjects() will ensure the push_constant
@@ -196,12 +248,14 @@ void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit)
     MERGE_TRUE(pointMode);
     MERGE_TRUE(pointMode);
 
 
     for (int i = 0; i < 3; ++i) {
     for (int i = 0; i < 3; ++i) {
-        if (!localSizeNotDefault[i] && unit.localSizeNotDefault[i]) {
-            localSize[i] = unit.localSize[i];
-            localSizeNotDefault[i] = true;
+        if (unit.localSizeNotDefault[i]) {
+            if (!localSizeNotDefault[i]) {
+                localSize[i] = unit.localSize[i];
+                localSizeNotDefault[i] = true;
+            }
+            else if (localSize[i] != unit.localSize[i])
+                error(infoSink, "Contradictory local size");
         }
         }
-        else if (localSize[i] != unit.localSize[i])
-            error(infoSink, "Contradictory local size");
 
 
         if (localSizeSpecId[i] == TQualifier::layoutNotSet)
         if (localSizeSpecId[i] == TQualifier::layoutNotSet)
             localSizeSpecId[i] = unit.localSizeSpecId[i];
             localSizeSpecId[i] = unit.localSizeSpecId[i];
@@ -304,12 +358,14 @@ void TIntermediate::mergeTrees(TInfoSink& infoSink, TIntermediate& unit)
     // Map by global name to unique ID to rationalize the same object having
     // Map by global name to unique ID to rationalize the same object having
     // differing IDs in different trees.
     // differing IDs in different trees.
     TIdMaps idMaps;
     TIdMaps idMaps;
-    int maxId;
-    seedIdMap(idMaps, maxId);
-    remapIds(idMaps, maxId + 1, unit);
+    long long idShift;
+    seedIdMap(idMaps, idShift);
+    remapIds(idMaps, idShift + 1, unit);
 
 
     mergeBodies(infoSink, globals, unitGlobals);
     mergeBodies(infoSink, globals, unitGlobals);
-    mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects);
+    bool mergeExistingOnly = false;
+    mergeGlobalUniformBlocks(infoSink, unit, mergeExistingOnly);
+    mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects, unit.getStage());
     ioAccessed.insert(unit.ioAccessed.begin(), unit.ioAccessed.end());
     ioAccessed.insert(unit.ioAccessed.begin(), unit.ioAccessed.end());
 }
 }
 
 
@@ -327,14 +383,14 @@ static const TString& getNameForIdMap(TIntermSymbol* symbol)
 
 
 
 
 // Traverser that seeds an ID map with all built-ins, and tracks the
 // Traverser that seeds an ID map with all built-ins, and tracks the
-// maximum ID used.
+// maximum ID used, currently using (maximum ID + 1) as new symbol id shift seed.
+// Level id will keep same after shifting.
 // (It would be nice to put this in a function, but that causes warnings
 // (It would be nice to put this in a function, but that causes warnings
 // on having no bodies for the copy-constructor/operator=.)
 // on having no bodies for the copy-constructor/operator=.)
 class TBuiltInIdTraverser : public TIntermTraverser {
 class TBuiltInIdTraverser : public TIntermTraverser {
 public:
 public:
-    TBuiltInIdTraverser(TIdMaps& idMaps) : idMaps(idMaps), maxId(0) { }
+    TBuiltInIdTraverser(TIdMaps& idMaps) : idMaps(idMaps), idShift(0) { }
     // If it's a built in, add it to the map.
     // If it's a built in, add it to the map.
-    // Track the max ID.
     virtual void visitSymbol(TIntermSymbol* symbol)
     virtual void visitSymbol(TIntermSymbol* symbol)
     {
     {
         const TQualifier& qualifier = symbol->getType().getQualifier();
         const TQualifier& qualifier = symbol->getType().getQualifier();
@@ -342,14 +398,16 @@ public:
             TShaderInterface si = symbol->getType().getShaderInterface();
             TShaderInterface si = symbol->getType().getShaderInterface();
             idMaps[si][getNameForIdMap(symbol)] = symbol->getId();
             idMaps[si][getNameForIdMap(symbol)] = symbol->getId();
         }
         }
-        maxId = std::max(maxId, symbol->getId());
+        idShift = (symbol->getId() & ~TSymbolTable::uniqueIdMask) |
+                std::max(idShift & TSymbolTable::uniqueIdMask,
+                         symbol->getId() & TSymbolTable::uniqueIdMask);
     }
     }
-    int getMaxId() const { return maxId; }
+    long long getIdShift() const { return idShift; }
 protected:
 protected:
     TBuiltInIdTraverser(TBuiltInIdTraverser&);
     TBuiltInIdTraverser(TBuiltInIdTraverser&);
     TBuiltInIdTraverser& operator=(TBuiltInIdTraverser&);
     TBuiltInIdTraverser& operator=(TBuiltInIdTraverser&);
     TIdMaps& idMaps;
     TIdMaps& idMaps;
-    int maxId;
+    long long idShift;
 };
 };
 
 
 // Traverser that seeds an ID map with non-builtins.
 // Traverser that seeds an ID map with non-builtins.
@@ -375,12 +433,12 @@ protected:
 };
 };
 
 
 // Initialize the the ID map with what we know of 'this' AST.
 // Initialize the the ID map with what we know of 'this' AST.
-void TIntermediate::seedIdMap(TIdMaps& idMaps, int& maxId)
+void TIntermediate::seedIdMap(TIdMaps& idMaps, long long& idShift)
 {
 {
     // all built-ins everywhere need to align on IDs and contribute to the max ID
     // all built-ins everywhere need to align on IDs and contribute to the max ID
     TBuiltInIdTraverser builtInIdTraverser(idMaps);
     TBuiltInIdTraverser builtInIdTraverser(idMaps);
     treeRoot->traverse(&builtInIdTraverser);
     treeRoot->traverse(&builtInIdTraverser);
-    maxId = builtInIdTraverser.getMaxId();
+    idShift = builtInIdTraverser.getIdShift() & TSymbolTable::uniqueIdMask;
 
 
     // user variables in the linker object list need to align on ids
     // user variables in the linker object list need to align on ids
     TUserIdTraverser userIdTraverser(idMaps);
     TUserIdTraverser userIdTraverser(idMaps);
@@ -392,7 +450,7 @@ void TIntermediate::seedIdMap(TIdMaps& idMaps, int& maxId)
 // on having no bodies for the copy-constructor/operator=.)
 // on having no bodies for the copy-constructor/operator=.)
 class TRemapIdTraverser : public TIntermTraverser {
 class TRemapIdTraverser : public TIntermTraverser {
 public:
 public:
-    TRemapIdTraverser(const TIdMaps& idMaps, int idShift) : idMaps(idMaps), idShift(idShift) { }
+    TRemapIdTraverser(const TIdMaps& idMaps, long long idShift) : idMaps(idMaps), idShift(idShift) { }
     // Do the mapping:
     // Do the mapping:
     //  - if the same symbol, adopt the 'this' ID
     //  - if the same symbol, adopt the 'this' ID
     //  - otherwise, ensure a unique ID by shifting to a new space
     //  - otherwise, ensure a unique ID by shifting to a new space
@@ -404,7 +462,9 @@ public:
             TShaderInterface si = symbol->getType().getShaderInterface();
             TShaderInterface si = symbol->getType().getShaderInterface();
             auto it = idMaps[si].find(getNameForIdMap(symbol));
             auto it = idMaps[si].find(getNameForIdMap(symbol));
             if (it != idMaps[si].end()) {
             if (it != idMaps[si].end()) {
-                symbol->changeId(it->second);
+                uint64_t id = (symbol->getId() & ~TSymbolTable::uniqueIdMask) |
+                    (it->second & TSymbolTable::uniqueIdMask);
+                symbol->changeId(id);
                 remapped = true;
                 remapped = true;
             }
             }
         }
         }
@@ -415,10 +475,10 @@ protected:
     TRemapIdTraverser(TRemapIdTraverser&);
     TRemapIdTraverser(TRemapIdTraverser&);
     TRemapIdTraverser& operator=(TRemapIdTraverser&);
     TRemapIdTraverser& operator=(TRemapIdTraverser&);
     const TIdMaps& idMaps;
     const TIdMaps& idMaps;
-    int idShift;
+    long long idShift;
 };
 };
 
 
-void TIntermediate::remapIds(const TIdMaps& idMaps, int idShift, TIntermediate& unit)
+void TIntermediate::remapIds(const TIdMaps& idMaps, long long idShift, TIntermediate& unit)
 {
 {
     // Remap all IDs to either share or be unique, as dictated by the idMap and idShift.
     // Remap all IDs to either share or be unique, as dictated by the idMap and idShift.
     TRemapIdTraverser idTraverser(idMaps, idShift);
     TRemapIdTraverser idTraverser(idMaps, idShift);
@@ -449,11 +509,193 @@ void TIntermediate::mergeBodies(TInfoSink& infoSink, TIntermSequence& globals, c
     globals.insert(globals.end() - 1, unitGlobals.begin(), unitGlobals.end() - 1);
     globals.insert(globals.end() - 1, unitGlobals.begin(), unitGlobals.end() - 1);
 }
 }
 
 
+static inline bool isSameInterface(TIntermSymbol* symbol, EShLanguage stage, TIntermSymbol* unitSymbol, EShLanguage unitStage) {
+    return // 1) same stage and same shader interface
+        (stage == unitStage && symbol->getType().getShaderInterface() == unitSymbol->getType().getShaderInterface()) ||
+        // 2) accross stages and both are uniform or buffer
+        (symbol->getQualifier().storage == EvqUniform  && unitSymbol->getQualifier().storage == EvqUniform) ||
+        (symbol->getQualifier().storage == EvqBuffer   && unitSymbol->getQualifier().storage == EvqBuffer) ||
+        // 3) in/out matched across stage boundary
+        (stage < unitStage && symbol->getQualifier().storage == EvqVaryingOut  && unitSymbol->getQualifier().storage == EvqVaryingIn) ||
+        (unitStage < stage && symbol->getQualifier().storage == EvqVaryingIn && unitSymbol->getQualifier().storage == EvqVaryingOut);
+}
+
+//
+// Global Unfiform block stores any default uniforms (i.e. uniforms without a block)
+// If two linked stages declare the same member, they are meant to be the same uniform
+// and need to be in the same block
+// merge the members of different stages to allow them to be linked properly
+// as a single block
+//
+void TIntermediate::mergeGlobalUniformBlocks(TInfoSink& infoSink, TIntermediate& unit, bool mergeExistingOnly)
+{
+    TIntermSequence& linkerObjects = findLinkerObjects()->getSequence();
+    TIntermSequence& unitLinkerObjects = unit.findLinkerObjects()->getSequence();
+
+    // build lists of default blocks from the intermediates
+    TIntermSequence defaultBlocks;
+    TIntermSequence unitDefaultBlocks;
+
+    auto filter = [](TIntermSequence& list, TIntermNode* node) {
+        if (node->getAsSymbolNode()->getQualifier().defaultBlock) {
+            list.push_back(node);
+        }
+    };
+
+    std::for_each(linkerObjects.begin(), linkerObjects.end(),
+        [&defaultBlocks, &filter](TIntermNode* node) {
+            filter(defaultBlocks, node);
+        });
+    std::for_each(unitLinkerObjects.begin(), unitLinkerObjects.end(),
+        [&unitDefaultBlocks, &filter](TIntermNode* node) {
+            filter(unitDefaultBlocks, node);
+    });
+
+    auto itUnitBlock = unitDefaultBlocks.begin();
+    for (; itUnitBlock != unitDefaultBlocks.end(); itUnitBlock++) {
+
+        bool add = !mergeExistingOnly;
+        auto itBlock = defaultBlocks.begin();
+
+        for (; itBlock != defaultBlocks.end(); itBlock++) {
+            TIntermSymbol* block = (*itBlock)->getAsSymbolNode();
+            TIntermSymbol* unitBlock = (*itUnitBlock)->getAsSymbolNode();
+
+            assert(block && unitBlock);
+
+            // if the two default blocks match, then merge their definitions
+            if (block->getType().getTypeName() == unitBlock->getType().getTypeName() &&
+                block->getQualifier().storage == unitBlock->getQualifier().storage) {
+                add = false;
+                mergeBlockDefinitions(infoSink, block, unitBlock, &unit);
+            }
+        }
+        if (add) {
+            // push back on original list; won't change the size of the list we're iterating over
+            linkerObjects.push_back(*itUnitBlock);
+        }
+    }
+}
+
+void TIntermediate::mergeBlockDefinitions(TInfoSink& infoSink, TIntermSymbol* block, TIntermSymbol* unitBlock, TIntermediate* unit) {
+    if (block->getType() == unitBlock->getType()) {
+        return;
+    }
+
+    if (block->getType().getTypeName() != unitBlock->getType().getTypeName() ||
+        block->getType().getBasicType() != unitBlock->getType().getBasicType() ||
+        block->getQualifier().storage != unitBlock->getQualifier().storage ||
+        block->getQualifier().layoutSet != unitBlock->getQualifier().layoutSet) {
+        // different block names likely means different blocks
+        return;
+    }
+
+    // merge the struct
+    // order of declarations doesn't matter and they matched based on member name
+    TTypeList* memberList = block->getType().getWritableStruct();
+    TTypeList* unitMemberList = unitBlock->getType().getWritableStruct();
+
+    // keep track of which members have changed position
+    // so we don't have to search the array again
+    std::map<unsigned int, unsigned int> memberIndexUpdates;
+
+    size_t memberListStartSize = memberList->size();
+    for (unsigned int i = 0; i < unitMemberList->size(); ++i) {
+        bool merge = true;
+        for (unsigned int j = 0; j < memberListStartSize; ++j) {
+            if ((*memberList)[j].type->getFieldName() == (*unitMemberList)[i].type->getFieldName()) {
+                merge = false;
+                const TType* memberType = (*memberList)[j].type;
+                const TType* unitMemberType = (*unitMemberList)[i].type;
+
+                // compare types
+                // don't need as many checks as when merging symbols, since
+                // initializers and most qualifiers are stripped when the member is moved into the block
+                if ((*memberType) != (*unitMemberType)) {
+                    error(infoSink, "Types must match:");
+                    infoSink.info << "    " << memberType->getFieldName() << ": ";
+                    infoSink.info << "\"" << memberType->getCompleteString() << "\" versus ";
+                    infoSink.info << "\"" << unitMemberType->getCompleteString() << "\"\n";
+                }
+
+                memberIndexUpdates[i] = j;
+            }
+        }
+        if (merge) {
+            memberList->push_back((*unitMemberList)[i]);
+            memberIndexUpdates[i] = (unsigned int)memberList->size() - 1;
+        }
+    }
+
+    TType unitType;
+    unitType.shallowCopy(unitBlock->getType());
+
+    // update symbol node in unit tree,
+    // and other nodes that may reference it
+    class TMergeBlockTraverser : public TIntermTraverser {
+    public:
+        TMergeBlockTraverser(const glslang::TType &type, const glslang::TType& unitType,
+                             glslang::TIntermediate& unit,
+                             const std::map<unsigned int, unsigned int>& memberIdxUpdates) :
+            newType(type), unitType(unitType), unit(unit), memberIndexUpdates(memberIdxUpdates)
+        { }
+        virtual ~TMergeBlockTraverser() { }
+
+        const glslang::TType& newType;          // type with modifications
+        const glslang::TType& unitType;         // copy of original type
+        glslang::TIntermediate& unit;           // intermediate that is being updated
+        const std::map<unsigned int, unsigned int>& memberIndexUpdates;
+
+        virtual void visitSymbol(TIntermSymbol* symbol)
+        {
+            glslang::TType& symType = symbol->getWritableType();
+
+            if (symType == unitType) {
+                // each symbol node has a local copy of the unitType
+                //  if merging involves changing properties that aren't shared objects
+                //  they should be updated in all instances
+
+                // e.g. the struct list is a ptr to an object, so it can be updated
+                // once, outside the traverser
+                //*symType.getWritableStruct() = *newType.getStruct();
+            }
+
+        }
+
+        virtual bool visitBinary(TVisit, glslang::TIntermBinary* node)
+        {
+            if (node->getOp() == EOpIndexDirectStruct && node->getLeft()->getType() == unitType) {
+                // this is a dereference to a member of the block since the
+                // member list changed, need to update this to point to the
+                // right index
+                assert(node->getRight()->getAsConstantUnion());
+
+                glslang::TIntermConstantUnion* constNode = node->getRight()->getAsConstantUnion();
+                unsigned int memberIdx = constNode->getConstArray()[0].getUConst();
+                unsigned int newIdx = memberIndexUpdates.at(memberIdx);
+                TIntermTyped* newConstNode = unit.addConstantUnion(newIdx, node->getRight()->getLoc());
+
+                node->setRight(newConstNode);
+                delete constNode;
+
+                return true;
+            }
+            return true;
+        }
+    } finalLinkTraverser(block->getType(), unitType, *unit, memberIndexUpdates);
+
+    // update the tree to use the new type
+    unit->getTreeRoot()->traverse(&finalLinkTraverser);
+
+    // update the member list
+    (*unitMemberList) = (*memberList);
+}
+
 //
 //
 // Merge the linker objects from unitLinkerObjects into linkerObjects.
 // Merge the linker objects from unitLinkerObjects into linkerObjects.
 // Duplication is expected and filtered out, but contradictions are an error.
 // Duplication is expected and filtered out, but contradictions are an error.
 //
 //
-void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects)
+void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects, EShLanguage unitStage)
 {
 {
     // Error check and merge the linker objects (duplicates should not be created)
     // Error check and merge the linker objects (duplicates should not be created)
     std::size_t initialNumLinkerObjects = linkerObjects.size();
     std::size_t initialNumLinkerObjects = linkerObjects.size();
@@ -468,7 +710,7 @@ void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& lin
             // If they are both blocks in the same shader interface,
             // If they are both blocks in the same shader interface,
             // match by the block-name, not the identifier name.
             // match by the block-name, not the identifier name.
             if (symbol->getType().getBasicType() == EbtBlock && unitSymbol->getType().getBasicType() == EbtBlock) {
             if (symbol->getType().getBasicType() == EbtBlock && unitSymbol->getType().getBasicType() == EbtBlock) {
-                if (symbol->getType().getShaderInterface() == unitSymbol->getType().getShaderInterface()) {
+                if (isSameInterface(symbol, getStage(), unitSymbol, unitStage)) {
                     isSameSymbol = symbol->getType().getTypeName() == unitSymbol->getType().getTypeName();
                     isSameSymbol = symbol->getType().getTypeName() == unitSymbol->getType().getTypeName();
                 }
                 }
             }
             }
@@ -488,18 +730,54 @@ void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& lin
                 if (! symbol->getQualifier().hasBinding() && unitSymbol->getQualifier().hasBinding())
                 if (! symbol->getQualifier().hasBinding() && unitSymbol->getQualifier().hasBinding())
                     symbol->getQualifier().layoutBinding = unitSymbol->getQualifier().layoutBinding;
                     symbol->getQualifier().layoutBinding = unitSymbol->getQualifier().layoutBinding;
 
 
+                // Similarly for location
+                if (!symbol->getQualifier().hasLocation() && unitSymbol->getQualifier().hasLocation()) {
+                    symbol->getQualifier().layoutLocation = unitSymbol->getQualifier().layoutLocation;
+                }
+
                 // Update implicit array sizes
                 // Update implicit array sizes
                 mergeImplicitArraySizes(symbol->getWritableType(), unitSymbol->getType());
                 mergeImplicitArraySizes(symbol->getWritableType(), unitSymbol->getType());
 
 
                 // Check for consistent types/qualification/initializers etc.
                 // Check for consistent types/qualification/initializers etc.
-                mergeErrorCheck(infoSink, *symbol, *unitSymbol, false);
+                mergeErrorCheck(infoSink, *symbol, *unitSymbol, unitStage);
             }
             }
             // If different symbols, verify they arn't push_constant since there can only be one per stage
             // If different symbols, verify they arn't push_constant since there can only be one per stage
-            else if (symbol->getQualifier().isPushConstant() && unitSymbol->getQualifier().isPushConstant())
+            else if (symbol->getQualifier().isPushConstant() && unitSymbol->getQualifier().isPushConstant() && getStage() == unitStage)
                 error(infoSink, "Only one push_constant block is allowed per stage");
                 error(infoSink, "Only one push_constant block is allowed per stage");
         }
         }
-        if (merge)
+        if (merge) {
             linkerObjects.push_back(unitLinkerObjects[unitLinkObj]);
             linkerObjects.push_back(unitLinkerObjects[unitLinkObj]);
+
+            // for anonymous blocks, check that their members don't conflict with other names
+            if (unitLinkerObjects[unitLinkObj]->getAsSymbolNode()->getBasicType() == EbtBlock &&
+                IsAnonymous(unitLinkerObjects[unitLinkObj]->getAsSymbolNode()->getName())) {
+                for (std::size_t linkObj = 0; linkObj < initialNumLinkerObjects; ++linkObj) {
+                    TIntermSymbol* symbol = linkerObjects[linkObj]->getAsSymbolNode();
+                    TIntermSymbol* unitSymbol = unitLinkerObjects[unitLinkObj]->getAsSymbolNode();
+                    assert(symbol && unitSymbol);
+
+                    auto checkName = [this, unitSymbol, &infoSink](const TString& name) {
+                        for (unsigned int i = 0; i < unitSymbol->getType().getStruct()->size(); ++i) {
+                            if (name == (*unitSymbol->getType().getStruct())[i].type->getFieldName()) {
+                                error(infoSink, "Anonymous member name used for global variable or other anonymous member: ");
+                                infoSink.info << (*unitSymbol->getType().getStruct())[i].type->getCompleteString() << "\n";
+                            }
+                        }
+                    };
+
+                    if (isSameInterface(symbol, getStage(), unitSymbol, unitStage)) {
+                        checkName(symbol->getName());
+
+                        // check members of other anonymous blocks
+                        if (symbol->getBasicType() == EbtBlock && IsAnonymous(symbol->getName())) {
+                            for (unsigned int i = 0; i < symbol->getType().getStruct()->size(); ++i) {
+                                checkName((*symbol->getType().getStruct())[i].type->getFieldName());
+                            }
+                        }
+                    }
+                }
+            }
+        }
     }
     }
 }
 }
 
 
@@ -531,26 +809,75 @@ void TIntermediate::mergeImplicitArraySizes(TType& type, const TType& unitType)
 //
 //
 // This function only does one of intra- or cross-stage matching per call.
 // This function only does one of intra- or cross-stage matching per call.
 //
 //
-void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& symbol, const TIntermSymbol& unitSymbol, bool crossStage)
+void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& symbol, const TIntermSymbol& unitSymbol, EShLanguage unitStage)
 {
 {
 #if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
 #if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
+    bool crossStage = getStage() != unitStage;
     bool writeTypeComparison = false;
     bool writeTypeComparison = false;
 
 
     // Types have to match
     // Types have to match
-    if (symbol.getType() != unitSymbol.getType()) {
+    {
         // but, we make an exception if one is an implicit array and the other is sized
         // but, we make an exception if one is an implicit array and the other is sized
-        if (! (symbol.getType().isArray() && unitSymbol.getType().isArray() &&
-                symbol.getType().sameElementType(unitSymbol.getType()) &&
-                (symbol.getType().isUnsizedArray() || unitSymbol.getType().isUnsizedArray()))) {
-            error(infoSink, "Types must match:");
+        // or if the array sizes differ because of the extra array dimension on some in/out boundaries
+        bool arraysMatch = false;
+        if (isIoResizeArray(symbol.getType(), getStage()) || isIoResizeArray(unitSymbol.getType(), unitStage)) {
+            // if the arrays have an extra dimension because of the stage.
+            // compare dimensions while ignoring the outer dimension
+            unsigned int firstDim = isIoResizeArray(symbol.getType(), getStage()) ? 1 : 0;
+            unsigned int numDim = symbol.getArraySizes()
+                ? symbol.getArraySizes()->getNumDims() : 0;
+            unsigned int unitFirstDim = isIoResizeArray(unitSymbol.getType(), unitStage) ? 1 : 0;
+            unsigned int unitNumDim = unitSymbol.getArraySizes()
+                ? unitSymbol.getArraySizes()->getNumDims() : 0;
+            arraysMatch = (numDim - firstDim) == (unitNumDim - unitFirstDim);
+            // check that array sizes match as well
+            for (unsigned int i = 0; i < (numDim - firstDim) && arraysMatch; i++) {
+                if (symbol.getArraySizes()->getDimSize(firstDim + i) !=
+                    unitSymbol.getArraySizes()->getDimSize(unitFirstDim + i)) {
+                    arraysMatch = false;
+                    break;
+                }
+            }
+        }
+        else {
+            arraysMatch = symbol.getType().sameArrayness(unitSymbol.getType()) ||
+                (symbol.getType().isArray() && unitSymbol.getType().isArray() &&
+                (symbol.getType().isUnsizedArray() || unitSymbol.getType().isUnsizedArray()));
+        }
+
+        if (!symbol.getType().sameElementType(unitSymbol.getType()) ||
+            !symbol.getType().sameTypeParameters(unitSymbol.getType()) ||
+            !arraysMatch ) {
             writeTypeComparison = true;
             writeTypeComparison = true;
+            error(infoSink, "Types must match:");
         }
         }
     }
     }
 
 
-    // Qualifiers have to (almost) match
+    // Interface block  member-wise layout qualifiers have to match
+    if (symbol.getType().getBasicType() == EbtBlock && unitSymbol.getType().getBasicType() == EbtBlock &&
+        symbol.getType().getStruct() && unitSymbol.getType().getStruct() &&
+        symbol.getType().sameStructType(unitSymbol.getType())) {
+        for (unsigned int i = 0; i < symbol.getType().getStruct()->size(); ++i) {
+            const TQualifier& qualifier = (*symbol.getType().getStruct())[i].type->getQualifier();
+            const TQualifier& unitQualifier = (*unitSymbol.getType().getStruct())[i].type->getQualifier();
+            if (qualifier.layoutMatrix     != unitQualifier.layoutMatrix ||
+                qualifier.layoutOffset     != unitQualifier.layoutOffset ||
+                qualifier.layoutAlign      != unitQualifier.layoutAlign ||
+                qualifier.layoutLocation   != unitQualifier.layoutLocation ||
+                qualifier.layoutComponent  != unitQualifier.layoutComponent) {
+                error(infoSink, "Interface block member layout qualifiers must match:");
+                writeTypeComparison = true;
+            }
+        }
+    }
 
 
+    bool isInOut = crossStage &&
+                   ((symbol.getQualifier().storage == EvqVaryingIn && unitSymbol.getQualifier().storage == EvqVaryingOut) ||
+                   (symbol.getQualifier().storage == EvqVaryingOut && unitSymbol.getQualifier().storage == EvqVaryingIn));
+
+    // Qualifiers have to (almost) match
     // Storage...
     // Storage...
-    if (symbol.getQualifier().storage != unitSymbol.getQualifier().storage) {
+    if (!isInOut && symbol.getQualifier().storage != unitSymbol.getQualifier().storage) {
         error(infoSink, "Storage qualifiers must match:");
         error(infoSink, "Storage qualifiers must match:");
         writeTypeComparison = true;
         writeTypeComparison = true;
     }
     }
@@ -572,7 +899,7 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
     }
     }
 
 
     // Precision...
     // Precision...
-    if (symbol.getQualifier().precision != unitSymbol.getQualifier().precision) {
+    if (!isInOut && symbol.getQualifier().precision != unitSymbol.getQualifier().precision) {
         error(infoSink, "Precision qualifiers must match:");
         error(infoSink, "Precision qualifiers must match:");
         writeTypeComparison = true;
         writeTypeComparison = true;
     }
     }
@@ -590,12 +917,16 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
     }
     }
 
 
     // Auxiliary and interpolation...
     // Auxiliary and interpolation...
-    if (symbol.getQualifier().centroid  != unitSymbol.getQualifier().centroid ||
+    // "interpolation qualification (e.g., flat) and auxiliary qualification (e.g. centroid) may differ.  
+    //  These mismatches are allowed between any pair of stages ...
+    //  those provided in the fragment shader supersede those provided in previous stages."
+    if (!crossStage &&
+        (symbol.getQualifier().centroid  != unitSymbol.getQualifier().centroid ||
         symbol.getQualifier().smooth    != unitSymbol.getQualifier().smooth ||
         symbol.getQualifier().smooth    != unitSymbol.getQualifier().smooth ||
         symbol.getQualifier().flat      != unitSymbol.getQualifier().flat ||
         symbol.getQualifier().flat      != unitSymbol.getQualifier().flat ||
         symbol.getQualifier().isSample()!= unitSymbol.getQualifier().isSample() ||
         symbol.getQualifier().isSample()!= unitSymbol.getQualifier().isSample() ||
         symbol.getQualifier().isPatch() != unitSymbol.getQualifier().isPatch() ||
         symbol.getQualifier().isPatch() != unitSymbol.getQualifier().isPatch() ||
-        symbol.getQualifier().isNonPerspective() != unitSymbol.getQualifier().isNonPerspective()) {
+        symbol.getQualifier().isNonPerspective() != unitSymbol.getQualifier().isNonPerspective())) {
         error(infoSink, "Interpolation and auxiliary storage qualifiers must match:");
         error(infoSink, "Interpolation and auxiliary storage qualifiers must match:");
         writeTypeComparison = true;
         writeTypeComparison = true;
     }
     }
@@ -651,6 +982,25 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
 #endif
 #endif
 }
 }
 
 
+void TIntermediate::sharedBlockCheck(TInfoSink& infoSink)
+{
+    bool has_shared_block = false;
+    bool has_shared_non_block = false;
+    TIntermSequence& linkObjects = findLinkerObjects()->getSequence();
+    for (size_t i = 0; i < linkObjects.size(); ++i) {
+        const TType& type = linkObjects[i]->getAsTyped()->getType();
+        const TQualifier& qualifier = type.getQualifier();
+        if (qualifier.storage == glslang::EvqShared) {
+            if (type.getBasicType() == glslang::EbtBlock)
+                has_shared_block = true;
+            else
+                has_shared_non_block = true;
+        }
+    }
+    if (has_shared_block && has_shared_non_block)
+        error(infoSink, "cannot mix use of shared variables inside and outside blocks");
+}
+
 //
 //
 // Do final link-time error checking of a complete (merged) intermediate representation.
 // Do final link-time error checking of a complete (merged) intermediate representation.
 // (Much error checking was done during merging).
 // (Much error checking was done during merging).
@@ -736,10 +1086,10 @@ void TIntermediate::finalCheck(TInfoSink& infoSink, bool keepUncalled)
 
 
         // "The resulting stride (implicit or explicit), when divided by 4, must be less than or equal to the
         // "The resulting stride (implicit or explicit), when divided by 4, must be less than or equal to the
         // implementation-dependent constant gl_MaxTransformFeedbackInterleavedComponents."
         // implementation-dependent constant gl_MaxTransformFeedbackInterleavedComponents."
-        if (xfbBuffers[b].stride > (unsigned int)(4 * resources.maxTransformFeedbackInterleavedComponents)) {
+        if (xfbBuffers[b].stride > (unsigned int)(4 * resources->maxTransformFeedbackInterleavedComponents)) {
             error(infoSink, "xfb_stride is too large:");
             error(infoSink, "xfb_stride is too large:");
             infoSink.info.prefix(EPrefixError);
             infoSink.info.prefix(EPrefixError);
-            infoSink.info << "    xfb_buffer " << (unsigned int)b << ", components (1/4 stride) needed are " << xfbBuffers[b].stride/4 << ", gl_MaxTransformFeedbackInterleavedComponents is " << resources.maxTransformFeedbackInterleavedComponents << "\n";
+            infoSink.info << "    xfb_buffer " << (unsigned int)b << ", components (1/4 stride) needed are " << xfbBuffers[b].stride/4 << ", gl_MaxTransformFeedbackInterleavedComponents is " << resources->maxTransformFeedbackInterleavedComponents << "\n";
         }
         }
     }
     }
 
 
@@ -776,6 +1126,7 @@ void TIntermediate::finalCheck(TInfoSink& infoSink, bool keepUncalled)
             error(infoSink, "post_depth_coverage requires early_fragment_tests");
             error(infoSink, "post_depth_coverage requires early_fragment_tests");
         break;
         break;
     case EShLangCompute:
     case EShLangCompute:
+        sharedBlockCheck(infoSink);
         break;
         break;
     case EShLangRayGen:
     case EShLangRayGen:
     case EShLangIntersect:
     case EShLangIntersect:
@@ -808,6 +1159,7 @@ void TIntermediate::finalCheck(TInfoSink& infoSink, bool keepUncalled)
     case EShLangTaskNV:
     case EShLangTaskNV:
         if (numTaskNVBlocks > 1)
         if (numTaskNVBlocks > 1)
             error(infoSink, "Only one taskNV interface block is allowed per shader");
             error(infoSink, "Only one taskNV interface block is allowed per shader");
+        sharedBlockCheck(infoSink);
         break;
         break;
     default:
     default:
         error(infoSink, "Unknown Stage.");
         error(infoSink, "Unknown Stage.");
@@ -1055,8 +1407,8 @@ bool TIntermediate::userOutputUsed() const
     return found;
     return found;
 }
 }
 
 
-// Accumulate locations used for inputs, outputs, and uniforms, and check for collisions
-// as the accumulation is done.
+// Accumulate locations used for inputs, outputs, and uniforms, payload and callable data
+// and check for collisions as the accumulation is done.
 //
 //
 // Returns < 0 if no collision, >= 0 if collision and the value returned is a colliding value.
 // Returns < 0 if no collision, >= 0 if collision and the value returned is a colliding value.
 //
 //
@@ -1068,6 +1420,7 @@ int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& typ
     typeCollision = false;
     typeCollision = false;
 
 
     int set;
     int set;
+    int setRT;
     if (qualifier.isPipeInput())
     if (qualifier.isPipeInput())
         set = 0;
         set = 0;
     else if (qualifier.isPipeOutput())
     else if (qualifier.isPipeOutput())
@@ -1076,11 +1429,17 @@ int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& typ
         set = 2;
         set = 2;
     else if (qualifier.storage == EvqBuffer)
     else if (qualifier.storage == EvqBuffer)
         set = 3;
         set = 3;
+    else if (qualifier.isAnyPayload())
+        setRT = 0;
+    else if (qualifier.isAnyCallable())
+        setRT = 1;
     else
     else
         return -1;
         return -1;
 
 
     int size;
     int size;
-    if (qualifier.isUniformOrBuffer() || qualifier.isTaskMemory()) {
+    if (qualifier.isAnyPayload() || qualifier.isAnyCallable()) {
+        size = 1;
+    } else if (qualifier.isUniformOrBuffer() || qualifier.isTaskMemory()) {
         if (type.isSizedArray())
         if (type.isSizedArray())
             size = type.getCumulativeArraySize();
             size = type.getCumulativeArraySize();
         else
         else
@@ -1108,10 +1467,17 @@ int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& typ
     // (A vertex shader input will show using only one location, even for a dvec3/4.)
     // (A vertex shader input will show using only one location, even for a dvec3/4.)
     //
     //
     // So, for the case of dvec3, we need two independent ioRanges.
     // So, for the case of dvec3, we need two independent ioRanges.
-
+    //
+    // For raytracing IO (payloads and callabledata) each declaration occupies a single
+    // slot irrespective of type.
     int collision = -1; // no collision
     int collision = -1; // no collision
 #ifndef GLSLANG_WEB
 #ifndef GLSLANG_WEB
-    if (size == 2 && type.getBasicType() == EbtDouble && type.getVectorSize() == 3 &&
+    if (qualifier.isAnyPayload() || qualifier.isAnyCallable()) {
+        TRange range(qualifier.layoutLocation, qualifier.layoutLocation);
+        collision = checkLocationRT(setRT, qualifier.layoutLocation);
+        if (collision < 0)
+            usedIoRT[setRT].push_back(range);
+    } else if (size == 2 && type.getBasicType() == EbtDouble && type.getVectorSize() == 3 &&
         (qualifier.isPipeInput() || qualifier.isPipeOutput())) {
         (qualifier.isPipeInput() || qualifier.isPipeOutput())) {
         // Dealing with dvec3 in/out split across two locations.
         // Dealing with dvec3 in/out split across two locations.
         // Need two io-ranges.
         // Need two io-ranges.
@@ -1187,6 +1553,16 @@ int TIntermediate::checkLocationRange(int set, const TIoRange& range, const TTyp
     return -1; // no collision
     return -1; // no collision
 }
 }
 
 
+int TIntermediate::checkLocationRT(int set, int location) {
+    TRange range(location, location);
+    for (size_t r = 0; r < usedIoRT[set].size(); ++r) {
+        if (range.overlap(usedIoRT[set][r])) {
+            return range.start;
+        }
+    }
+    return -1; // no collision
+}
+
 // Accumulate bindings and offsets, and check for collisions
 // Accumulate bindings and offsets, and check for collisions
 // as the accumulation is done.
 // as the accumulation is done.
 //
 //
@@ -1778,4 +2154,17 @@ int TIntermediate::computeBufferReferenceTypeSize(const TType& type)
     return size;
     return size;
 }
 }
 
 
+#ifndef GLSLANG_WEB
+bool TIntermediate::isIoResizeArray(const TType& type, EShLanguage language) {
+    return type.isArray() &&
+            ((language == EShLangGeometry    && type.getQualifier().storage == EvqVaryingIn) ||
+            (language == EShLangTessControl && type.getQualifier().storage == EvqVaryingOut &&
+                ! type.getQualifier().patch) ||
+            (language == EShLangFragment && type.getQualifier().storage == EvqVaryingIn &&
+                type.getQualifier().pervertexNV) ||
+            (language == EShLangMeshNV && type.getQualifier().storage == EvqVaryingOut &&
+                !type.getQualifier().perTaskNV));
+}
+#endif // not GLSLANG_WEB
+
 } // end namespace glslang
 } // end namespace glslang

+ 108 - 11
src/libraries/glslang/glslang/MachineIndependent/localintermediate.h

@@ -227,10 +227,10 @@ enum ComputeDerivativeMode {
 
 
 class TIdMaps {
 class TIdMaps {
 public:
 public:
-    TMap<TString, int>& operator[](int i) { return maps[i]; }
-    const TMap<TString, int>& operator[](int i) const { return maps[i]; }
+    TMap<TString, long long>& operator[](long long i) { return maps[i]; }
+    const TMap<TString, long long>& operator[](long long i) const { return maps[i]; }
 private:
 private:
-    TMap<TString, int> maps[EsiCount];
+    TMap<TString, long long> maps[EsiCount];
 };
 };
 
 
 class TNumericFeatures {
 class TNumericFeatures {
@@ -259,6 +259,23 @@ private:
     unsigned int features;
     unsigned int features;
 };
 };
 
 
+// MustBeAssigned wraps a T, asserting that it has been assigned with 
+// operator =() before attempting to read with operator T() or operator ->().
+// Used to catch cases where fields are read before they have been assigned.
+template<typename T>
+class MustBeAssigned
+{
+public:
+    MustBeAssigned() = default;
+    MustBeAssigned(const T& v) : value(v) {}
+    operator const T&() const { assert(isSet); return value; }
+    const T* operator ->() const { assert(isSet); return &value; }
+    MustBeAssigned& operator = (const T& v) { value = v; isSet = true; return *this; } 
+private:
+    T value;
+    bool isSet = false;
+};
+
 //
 //
 // Set of helper functions to help parse and build the tree.
 // Set of helper functions to help parse and build the tree.
 //
 //
@@ -270,11 +287,18 @@ public:
         profile(p), version(v),
         profile(p), version(v),
 #endif
 #endif
         treeRoot(0),
         treeRoot(0),
+        resources(TBuiltInResource{}),
         numEntryPoints(0), numErrors(0), numPushConstants(0), recursive(false),
         numEntryPoints(0), numErrors(0), numPushConstants(0), recursive(false),
         invertY(false),
         invertY(false),
         useStorageBuffer(false),
         useStorageBuffer(false),
         nanMinMaxClamp(false),
         nanMinMaxClamp(false),
-        depthReplacing(false)
+        depthReplacing(false),
+        uniqueId(0),
+        globalUniformBlockName(""),
+        atomicCounterBlockName(""),
+        globalUniformBlockSet(TQualifier::layoutSetEnd),
+        globalUniformBlockBinding(TQualifier::layoutBindingEnd),
+        atomicCounterBlockSet(TQualifier::layoutSetEnd)
 #ifndef GLSLANG_WEB
 #ifndef GLSLANG_WEB
         ,
         ,
         implicitThisName("@this"), implicitCounterName("@count"),
         implicitThisName("@this"), implicitCounterName("@count"),
@@ -398,6 +422,9 @@ public:
     EShLanguage getStage() const { return language; }
     EShLanguage getStage() const { return language; }
     void addRequestedExtension(const char* extension) { requestedExtensions.insert(extension); }
     void addRequestedExtension(const char* extension) { requestedExtensions.insert(extension); }
     const std::set<std::string>& getRequestedExtensions() const { return requestedExtensions; }
     const std::set<std::string>& getRequestedExtensions() const { return requestedExtensions; }
+    bool isRayTracingStage() const {
+        return language >= EShLangRayGen && language <= EShLangCallableNV;
+    }
 
 
     void setTreeRoot(TIntermNode* r) { treeRoot = r; }
     void setTreeRoot(TIntermNode* r) { treeRoot = r; }
     TIntermNode* getTreeRoot() const { return treeRoot; }
     TIntermNode* getTreeRoot() const { return treeRoot; }
@@ -406,6 +433,7 @@ public:
     int getNumErrors() const { return numErrors; }
     int getNumErrors() const { return numErrors; }
     void addPushConstantCount() { ++numPushConstants; }
     void addPushConstantCount() { ++numPushConstants; }
     void setLimits(const TBuiltInResource& r) { resources = r; }
     void setLimits(const TBuiltInResource& r) { resources = r; }
+    const TBuiltInResource& getLimits() const { return resources; }
 
 
     bool postProcess(TIntermNode*, EShLanguage);
     bool postProcess(TIntermNode*, EShLanguage);
     void removeTree();
     void removeTree();
@@ -512,6 +540,20 @@ public:
     // Linkage related
     // Linkage related
     void addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage, TSymbolTable&);
     void addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage, TSymbolTable&);
     void addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymbol&);
     void addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymbol&);
+    TIntermAggregate* findLinkerObjects() const;
+
+    void setGlobalUniformBlockName(const char* name) { globalUniformBlockName = std::string(name); }
+    const char* getGlobalUniformBlockName() const { return globalUniformBlockName.c_str(); }
+    void setGlobalUniformSet(unsigned int set) { globalUniformBlockSet = set; }
+    unsigned int getGlobalUniformSet() const { return globalUniformBlockSet; }
+    void setGlobalUniformBinding(unsigned int binding) { globalUniformBlockBinding = binding; }
+    unsigned int getGlobalUniformBinding() const { return globalUniformBlockBinding; }
+
+    void setAtomicCounterBlockName(const char* name) { atomicCounterBlockName = std::string(name); }
+    const char* getAtomicCounterBlockName() const { return atomicCounterBlockName.c_str(); }
+    void setAtomicCounterBlockSet(unsigned int set) { atomicCounterBlockSet = set; }
+    unsigned int getAtomicCounterBlockSet() const { return atomicCounterBlockSet; }
+
 
 
     void setUseStorageBuffer() { useStorageBuffer = true; }
     void setUseStorageBuffer() { useStorageBuffer = true; }
     bool usingStorageBuffer() const { return useStorageBuffer; }
     bool usingStorageBuffer() const { return useStorageBuffer; }
@@ -526,6 +568,11 @@ public:
         return true;
         return true;
     }
     }
     unsigned int getLocalSize(int dim) const { return localSize[dim]; }
     unsigned int getLocalSize(int dim) const { return localSize[dim]; }
+    bool isLocalSizeSet() const
+    {
+        // Return true if any component has been set (i.e. any component is not default).
+        return localSizeNotDefault[0] || localSizeNotDefault[1] || localSizeNotDefault[2];
+    }
     bool setLocalSizeSpecId(int dim, int id)
     bool setLocalSizeSpecId(int dim, int id)
     {
     {
         if (localSizeSpecId[dim] != TQualifier::layoutNotSet)
         if (localSizeSpecId[dim] != TQualifier::layoutNotSet)
@@ -534,6 +581,13 @@ public:
         return true;
         return true;
     }
     }
     int getLocalSizeSpecId(int dim) const { return localSizeSpecId[dim]; }
     int getLocalSizeSpecId(int dim) const { return localSizeSpecId[dim]; }
+    bool isLocalSizeSpecialized() const
+    {
+        // Return true if any component has been specialized.
+        return localSizeSpecId[0] != TQualifier::layoutNotSet ||
+               localSizeSpecId[1] != TQualifier::layoutNotSet ||
+               localSizeSpecId[2] != TQualifier::layoutNotSet;
+    }
 #ifdef GLSLANG_WEB
 #ifdef GLSLANG_WEB
     void output(TInfoSink&, bool tree) { }
     void output(TInfoSink&, bool tree) { }
 
 
@@ -812,6 +866,20 @@ public:
     bool getBinaryDoubleOutput() { return binaryDoubleOutput; }
     bool getBinaryDoubleOutput() { return binaryDoubleOutput; }
 #endif // GLSLANG_WEB
 #endif // GLSLANG_WEB
 
 
+    void addBlockStorageOverride(const char* nameStr, TBlockStorageClass backing)
+    {
+        std::string name(nameStr);
+        blockBackingOverrides[name] = backing;
+    }
+    TBlockStorageClass getBlockStorageOverride(const char* nameStr) const
+    {
+        std::string name = nameStr;
+        auto pos = blockBackingOverrides.find(name);
+        if (pos == blockBackingOverrides.end())
+            return EbsNone;
+        else
+            return pos->second;
+    }
 #ifdef ENABLE_HLSL
 #ifdef ENABLE_HLSL
     void setHlslFunctionality1() { hlslFunctionality1 = true; }
     void setHlslFunctionality1() { hlslFunctionality1 = true; }
     bool getHlslFunctionality1() const { return hlslFunctionality1; }
     bool getHlslFunctionality1() const { return hlslFunctionality1; }
@@ -835,10 +903,22 @@ public:
     bool usingHlslIoMapping() { return false; }
     bool usingHlslIoMapping() { return false; }
 #endif
 #endif
 
 
+    bool usingScalarBlockLayout() const {
+        for (auto extIt = requestedExtensions.begin(); extIt != requestedExtensions.end(); ++extIt) {
+            if (*extIt == E_GL_EXT_scalar_block_layout)
+                return true;
+        }
+        return false;
+    }
+
     void addToCallGraph(TInfoSink&, const TString& caller, const TString& callee);
     void addToCallGraph(TInfoSink&, const TString& caller, const TString& callee);
     void merge(TInfoSink&, TIntermediate&);
     void merge(TInfoSink&, TIntermediate&);
     void finalCheck(TInfoSink&, bool keepUncalled);
     void finalCheck(TInfoSink&, bool keepUncalled);
 
 
+    void mergeGlobalUniformBlocks(TInfoSink& infoSink, TIntermediate& unit, bool mergeExistingOnly);
+    void mergeUniformObjects(TInfoSink& infoSink, TIntermediate& unit);
+    void checkStageIO(TInfoSink&, TIntermediate&);
+
     bool buildConvertOp(TBasicType dst, TBasicType src, TOperator& convertOp) const;
     bool buildConvertOp(TBasicType dst, TBasicType src, TOperator& convertOp) const;
     TIntermTyped* createConversion(TBasicType convertTo, TIntermTyped* node) const;
     TIntermTyped* createConversion(TBasicType convertTo, TIntermTyped* node) const;
 
 
@@ -847,6 +927,7 @@ public:
 
 
     int addUsedLocation(const TQualifier&, const TType&, bool& typeCollision);
     int addUsedLocation(const TQualifier&, const TType&, bool& typeCollision);
     int checkLocationRange(int set, const TIoRange& range, const TType&, bool& typeCollision);
     int checkLocationRange(int set, const TIoRange& range, const TType&, bool& typeCollision);
+    int checkLocationRT(int set, int location);
     int addUsedOffsets(int binding, int offset, int numOffsets);
     int addUsedOffsets(int binding, int offset, int numOffsets);
     bool addUsedConstantId(int id);
     bool addUsedConstantId(int id);
     static int computeTypeLocationSize(const TType&, EShLanguage);
     static int computeTypeLocationSize(const TType&, EShLanguage);
@@ -861,6 +942,8 @@ public:
     static int getOffset(const TType& type, int index);
     static int getOffset(const TType& type, int index);
     static int getBlockSize(const TType& blockType);
     static int getBlockSize(const TType& blockType);
     static int computeBufferReferenceTypeSize(const TType&);
     static int computeBufferReferenceTypeSize(const TType&);
+    static bool isIoResizeArray(const TType& type, EShLanguage language);
+
     bool promote(TIntermOperator*);
     bool promote(TIntermOperator*);
     void setNanMinMaxClamp(bool setting) { nanMinMaxClamp = setting; }
     void setNanMinMaxClamp(bool setting) { nanMinMaxClamp = setting; }
     bool getNanMinMaxClamp() const { return nanMinMaxClamp; }
     bool getNanMinMaxClamp() const { return nanMinMaxClamp; }
@@ -879,6 +962,8 @@ public:
     void addProcess(const std::string& process) { processes.addProcess(process); }
     void addProcess(const std::string& process) { processes.addProcess(process); }
     void addProcessArgument(const std::string& arg) { processes.addArgument(arg); }
     void addProcessArgument(const std::string& arg) { processes.addArgument(arg); }
     const std::vector<std::string>& getProcesses() const { return processes.getProcesses(); }
     const std::vector<std::string>& getProcesses() const { return processes.getProcesses(); }
+    unsigned long long getUniqueId() const { return uniqueId; }
+    void setUniqueId(unsigned long long id) { uniqueId = id; }
 
 
     // Certain explicit conversions are allowed conditionally
     // Certain explicit conversions are allowed conditionally
 #ifdef GLSLANG_WEB
 #ifdef GLSLANG_WEB
@@ -907,22 +992,23 @@ public:
 #endif
 #endif
 
 
 protected:
 protected:
-    TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&);
+    TIntermSymbol* addSymbol(long long Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&);
     void error(TInfoSink& infoSink, const char*);
     void error(TInfoSink& infoSink, const char*);
     void warn(TInfoSink& infoSink, const char*);
     void warn(TInfoSink& infoSink, const char*);
     void mergeCallGraphs(TInfoSink&, TIntermediate&);
     void mergeCallGraphs(TInfoSink&, TIntermediate&);
     void mergeModes(TInfoSink&, TIntermediate&);
     void mergeModes(TInfoSink&, TIntermediate&);
     void mergeTrees(TInfoSink&, TIntermediate&);
     void mergeTrees(TInfoSink&, TIntermediate&);
-    void seedIdMap(TIdMaps& idMaps, int& maxId);
-    void remapIds(const TIdMaps& idMaps, int idShift, TIntermediate&);
+    void seedIdMap(TIdMaps& idMaps, long long& IdShift);
+    void remapIds(const TIdMaps& idMaps, long long idShift, TIntermediate&);
     void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals);
     void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals);
-    void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects);
+    void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects, EShLanguage);
+    void mergeBlockDefinitions(TInfoSink&, TIntermSymbol* block, TIntermSymbol* unitBlock, TIntermediate* unitRoot);
     void mergeImplicitArraySizes(TType&, const TType&);
     void mergeImplicitArraySizes(TType&, const TType&);
-    void mergeErrorCheck(TInfoSink&, const TIntermSymbol&, const TIntermSymbol&, bool crossStage);
+    void mergeErrorCheck(TInfoSink&, const TIntermSymbol&, const TIntermSymbol&, EShLanguage);
     void checkCallGraphCycles(TInfoSink&);
     void checkCallGraphCycles(TInfoSink&);
     void checkCallGraphBodies(TInfoSink&, bool keepUncalled);
     void checkCallGraphBodies(TInfoSink&, bool keepUncalled);
     void inOutLocationCheck(TInfoSink&);
     void inOutLocationCheck(TInfoSink&);
-    TIntermAggregate* findLinkerObjects() const;
+    void sharedBlockCheck(TInfoSink&);
     bool userOutputUsed() const;
     bool userOutputUsed() const;
     bool isSpecializationOperation(const TIntermOperator&) const;
     bool isSpecializationOperation(const TIntermOperator&) const;
     bool isNonuniformPropagating(TOperator) const;
     bool isNonuniformPropagating(TOperator) const;
@@ -955,7 +1041,7 @@ protected:
     SpvVersion spvVersion;
     SpvVersion spvVersion;
     TIntermNode* treeRoot;
     TIntermNode* treeRoot;
     std::set<std::string> requestedExtensions;  // cumulation of all enabled or required extensions; not connected to what subset of the shader used them
     std::set<std::string> requestedExtensions;  // cumulation of all enabled or required extensions; not connected to what subset of the shader used them
-    TBuiltInResource resources;
+    MustBeAssigned<TBuiltInResource> resources;
     int numEntryPoints;
     int numEntryPoints;
     int numErrors;
     int numErrors;
     int numPushConstants;
     int numPushConstants;
@@ -967,6 +1053,14 @@ protected:
     int localSize[3];
     int localSize[3];
     bool localSizeNotDefault[3];
     bool localSizeNotDefault[3];
     int localSizeSpecId[3];
     int localSizeSpecId[3];
+    unsigned long long uniqueId;
+
+    std::string globalUniformBlockName;
+    std::string atomicCounterBlockName;
+    unsigned int globalUniformBlockSet;
+    unsigned int globalUniformBlockBinding;
+    unsigned int atomicCounterBlockSet;
+
 #ifndef GLSLANG_WEB
 #ifndef GLSLANG_WEB
 public:
 public:
     const char* const implicitThisName;
     const char* const implicitThisName;
@@ -1027,10 +1121,13 @@ protected:
     int uniformLocationBase;
     int uniformLocationBase;
     TNumericFeatures numericFeatures;
     TNumericFeatures numericFeatures;
 #endif
 #endif
+    std::unordered_map<std::string, TBlockStorageClass> blockBackingOverrides;
 
 
     std::unordered_set<int> usedConstantId; // specialization constant ids used
     std::unordered_set<int> usedConstantId; // specialization constant ids used
     std::vector<TOffsetRange> usedAtomics;  // sets of bindings used by atomic counters
     std::vector<TOffsetRange> usedAtomics;  // sets of bindings used by atomic counters
     std::vector<TIoRange> usedIo[4];        // sets of used locations, one for each of in, out, uniform, and buffers
     std::vector<TIoRange> usedIo[4];        // sets of used locations, one for each of in, out, uniform, and buffers
+    std::vector<TRange> usedIoRT[2];        // sets of used location, one for rayPayload/rayPayloadIN and other
+                                            // for callableData/callableDataIn
     // set of names of statically read/written I/O that might need extra checking
     // set of names of statically read/written I/O that might need extra checking
     std::set<TString> ioAccessed;
     std::set<TString> ioAccessed;
     // source code of shader, useful as part of debug information
     // source code of shader, useful as part of debug information

+ 1 - 0
src/libraries/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp

@@ -455,6 +455,7 @@ int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, boo
                 token = scanToken(ppToken);
                 token = scanToken(ppToken);
             }
             }
         } else {
         } else {
+            token = tokenPaste(token, *ppToken);
             token = evalToToken(token, shortCircuit, res, err, ppToken);
             token = evalToToken(token, shortCircuit, res, err, ppToken);
             return eval(token, precedence, shortCircuit, res, err, ppToken);
             return eval(token, precedence, shortCircuit, res, err, ppToken);
         }
         }

+ 12 - 7
src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpTokens.cpp

@@ -658,14 +658,17 @@ public:
 
 
                 blocks.back().numMembers = countAggregateMembers(type);
                 blocks.back().numMembers = countAggregateMembers(type);
 
 
-                EShLanguageMask& stages = blocks.back().stages;
-                stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
+                if (updateStageMasks) {
+                    EShLanguageMask& stages = blocks.back().stages;
+                    stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
+                }
             }
             }
             else {
             else {
                 blockIndex = it->second;
                 blockIndex = it->second;
-
-                EShLanguageMask& stages = blocks[blockIndex].stages;
-                stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
+                if (updateStageMasks) {
+                    EShLanguageMask& stages = blocks[blockIndex].stages;
+                    stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
+                }
             }
             }
         }
         }
 
 
@@ -904,8 +907,8 @@ public:
             case EbtFloat16:    return GL_FLOAT16_VEC2_NV             + offset;
             case EbtFloat16:    return GL_FLOAT16_VEC2_NV             + offset;
             case EbtInt:        return GL_INT_VEC2                    + offset;
             case EbtInt:        return GL_INT_VEC2                    + offset;
             case EbtUint:       return GL_UNSIGNED_INT_VEC2           + offset;
             case EbtUint:       return GL_UNSIGNED_INT_VEC2           + offset;
-            case EbtInt64:      return GL_INT64_ARB                   + offset;
-            case EbtUint64:     return GL_UNSIGNED_INT64_ARB          + offset;
+            case EbtInt64:      return GL_INT64_VEC2_ARB              + offset;
+            case EbtUint64:     return GL_UNSIGNED_INT64_VEC2_ARB     + offset;
             case EbtBool:       return GL_BOOL_VEC2                   + offset;
             case EbtBool:       return GL_BOOL_VEC2                   + offset;
             case EbtAtomicUint: return GL_UNSIGNED_INT_ATOMIC_COUNTER + offset;
             case EbtAtomicUint: return GL_UNSIGNED_INT_ATOMIC_COUNTER + offset;
             default:            return 0;
             default:            return 0;
@@ -1135,6 +1138,8 @@ void TReflection::buildCounterIndices(const TIntermediate& intermediate)
         if (index >= 0)
         if (index >= 0)
             indexToUniformBlock[i].counterIndex = index;
             indexToUniformBlock[i].counterIndex = index;
     }
     }
+#else
+    (void)intermediate;
 #endif
 #endif
 }
 }
 
 

+ 25 - 3
src/libraries/glslang/glslang/Public/ShaderLang.h

@@ -167,7 +167,7 @@ typedef enum {
     EShTargetVulkan_1_1 = (1 << 22) | (1 << 12),      // Vulkan 1.1
     EShTargetVulkan_1_1 = (1 << 22) | (1 << 12),      // Vulkan 1.1
     EShTargetVulkan_1_2 = (1 << 22) | (2 << 12),      // Vulkan 1.2
     EShTargetVulkan_1_2 = (1 << 22) | (2 << 12),      // Vulkan 1.2
     EShTargetOpenGL_450 = 450,                        // OpenGL
     EShTargetOpenGL_450 = 450,                        // OpenGL
-    LAST_ELEMENT_MARKER(EShTargetClientVersionCount),
+    LAST_ELEMENT_MARKER(EShTargetClientVersionCount = 4),
 } EShTargetClientVersion;
 } EShTargetClientVersion;
 
 
 typedef EShTargetClientVersion EshTargetClientVersion;
 typedef EShTargetClientVersion EshTargetClientVersion;
@@ -179,7 +179,7 @@ typedef enum {
     EShTargetSpv_1_3 = (1 << 16) | (3 << 8),          // SPIR-V 1.3
     EShTargetSpv_1_3 = (1 << 16) | (3 << 8),          // SPIR-V 1.3
     EShTargetSpv_1_4 = (1 << 16) | (4 << 8),          // SPIR-V 1.4
     EShTargetSpv_1_4 = (1 << 16) | (4 << 8),          // SPIR-V 1.4
     EShTargetSpv_1_5 = (1 << 16) | (5 << 8),          // SPIR-V 1.5
     EShTargetSpv_1_5 = (1 << 16) | (5 << 8),          // SPIR-V 1.5
-    LAST_ELEMENT_MARKER(EShTargetLanguageVersionCount),
+    LAST_ELEMENT_MARKER(EShTargetLanguageVersionCount = 6),
 } EShTargetLanguageVersion;
 } EShTargetLanguageVersion;
 
 
 struct TInputLanguage {
 struct TInputLanguage {
@@ -187,6 +187,7 @@ struct TInputLanguage {
     EShLanguage stage;        // redundant information with other input, this one overrides when not EShSourceNone
     EShLanguage stage;        // redundant information with other input, this one overrides when not EShSourceNone
     EShClient dialect;
     EShClient dialect;
     int dialectVersion;       // version of client's language definition, not the client (when not EShClientNone)
     int dialectVersion;       // version of client's language definition, not the client (when not EShClientNone)
+    bool vulkanRulesRelaxed;
 };
 };
 
 
 struct TClient {
 struct TClient {
@@ -427,6 +428,14 @@ enum TResourceType {
     EResCount
     EResCount
 };
 };
 
 
+enum TBlockStorageClass
+{
+    EbsUniform = 0,
+    EbsStorageBuffer,
+    EbsPushConstant,
+    EbsNone,    // not a uniform or buffer variable
+    EbsCount,
+};
 
 
 // Make one TShader per shader that you will link into a program. Then
 // Make one TShader per shader that you will link into a program. Then
 //  - provide the shader through setStrings() or setStringsWithLengths()
 //  - provide the shader through setStrings() or setStringsWithLengths()
@@ -458,6 +467,7 @@ public:
     GLSLANG_EXPORT void setEntryPoint(const char* entryPoint);
     GLSLANG_EXPORT void setEntryPoint(const char* entryPoint);
     GLSLANG_EXPORT void setSourceEntryPoint(const char* sourceEntryPointName);
     GLSLANG_EXPORT void setSourceEntryPoint(const char* sourceEntryPointName);
     GLSLANG_EXPORT void addProcesses(const std::vector<std::string>&);
     GLSLANG_EXPORT void addProcesses(const std::vector<std::string>&);
+    GLSLANG_EXPORT void setUniqueId(unsigned long long id);
 
 
     // IO resolver binding data: see comments in ShaderLang.cpp
     // IO resolver binding data: see comments in ShaderLang.cpp
     GLSLANG_EXPORT void setShiftBinding(TResourceType res, unsigned int base);
     GLSLANG_EXPORT void setShiftBinding(TResourceType res, unsigned int base);
@@ -482,6 +492,14 @@ public:
     GLSLANG_EXPORT void setNoStorageFormat(bool useUnknownFormat);
     GLSLANG_EXPORT void setNoStorageFormat(bool useUnknownFormat);
     GLSLANG_EXPORT void setNanMinMaxClamp(bool nanMinMaxClamp);
     GLSLANG_EXPORT void setNanMinMaxClamp(bool nanMinMaxClamp);
     GLSLANG_EXPORT void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode);
     GLSLANG_EXPORT void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode);
+    GLSLANG_EXPORT void addBlockStorageOverride(const char* nameStr, glslang::TBlockStorageClass backing);
+
+    GLSLANG_EXPORT void setGlobalUniformBlockName(const char* name);
+    GLSLANG_EXPORT void setAtomicCounterBlockName(const char* name);
+    GLSLANG_EXPORT void setGlobalUniformSet(unsigned int set);
+    GLSLANG_EXPORT void setGlobalUniformBinding(unsigned int binding);
+    GLSLANG_EXPORT void setAtomicCounterBlockSet(unsigned int set);
+    GLSLANG_EXPORT void setAtomicCounterBlockBinding(unsigned int binding);
 
 
     // For setting up the environment (cleared to nothingness in the constructor).
     // For setting up the environment (cleared to nothingness in the constructor).
     // These must be called so that parsing is done for the right source language and
     // These must be called so that parsing is done for the right source language and
@@ -538,6 +556,9 @@ public:
     bool getEnvTargetHlslFunctionality1() const { return false; }
     bool getEnvTargetHlslFunctionality1() const { return false; }
 #endif
 #endif
 
 
+    void setEnvInputVulkanRulesRelaxed() { environment.input.vulkanRulesRelaxed = true; }
+    bool getEnvInputVulkanRulesRelaxed() const { return environment.input.vulkanRulesRelaxed; }
+
     // Interface to #include handlers.
     // Interface to #include handlers.
     //
     //
     // To support #include, a client of Glslang does the following:
     // To support #include, a client of Glslang does the following:
@@ -805,7 +826,7 @@ public:
     // Called by TSlotCollector to resolve resource locations or bindings
     // Called by TSlotCollector to resolve resource locations or bindings
     virtual void reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) = 0;
     virtual void reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) = 0;
     // Called by mapIO.addStage to set shader stage mask to mark a stage be added to this pipeline
     // Called by mapIO.addStage to set shader stage mask to mark a stage be added to this pipeline
-    virtual void addStage(EShLanguage stage) = 0;
+    virtual void addStage(EShLanguage stage, TIntermediate& stageIntermediate) = 0;
 };
 };
 
 
 #endif // !GLSLANG_WEB && !GLSLANG_ANGLE
 #endif // !GLSLANG_WEB && !GLSLANG_ANGLE
@@ -927,6 +948,7 @@ public:
 
 
 protected:
 protected:
     GLSLANG_EXPORT bool linkStage(EShLanguage, EShMessages);
     GLSLANG_EXPORT bool linkStage(EShLanguage, EShMessages);
+    GLSLANG_EXPORT bool crossStageCheck(EShMessages);
 
 
     TPoolAllocator* pool;
     TPoolAllocator* pool;
     std::list<TShader*> stages[EShLangCount];
     std::list<TShader*> stages[EShLangCount];

Some files were not shown because too many files changed in this diff