Browse Source

Update glslang

Alex Szpakowski 4 years ago
parent
commit
d083c87d74
59 changed files with 4410 additions and 2121 deletions
  1. 2 1
      CMakeLists.txt
  2. 4 6
      platform/xcode/liblove.xcodeproj/project.pbxproj
  3. 1 0
      src/libraries/glslang/SPIRV/GLSL.ext.EXT.h
  4. 5 2
      src/libraries/glslang/SPIRV/GLSL.ext.KHR.h
  5. 374 160
      src/libraries/glslang/SPIRV/GlslangToSpv.cpp
  6. 1 1
      src/libraries/glslang/SPIRV/GlslangToSpv.h
  7. 50 0
      src/libraries/glslang/SPIRV/NonSemanticDebugPrintf.h
  8. 12 1
      src/libraries/glslang/SPIRV/SPVRemapper.cpp
  9. 164 30
      src/libraries/glslang/SPIRV/SpvBuilder.cpp
  10. 101 37
      src/libraries/glslang/SPIRV/SpvBuilder.h
  11. 65 38
      src/libraries/glslang/SPIRV/SpvTools.cpp
  12. 11 5
      src/libraries/glslang/SPIRV/SpvTools.h
  13. 12 2
      src/libraries/glslang/SPIRV/disassemble.cpp
  14. 224 65
      src/libraries/glslang/SPIRV/doc.cpp
  15. 1 0
      src/libraries/glslang/SPIRV/doc.h
  16. 2 2
      src/libraries/glslang/SPIRV/hex_float.h
  17. 195 5
      src/libraries/glslang/SPIRV/spirv.hpp
  18. 24 3
      src/libraries/glslang/SPIRV/spvIR.h
  19. 51 39
      src/libraries/glslang/glslang/Include/BaseTypes.h
  20. 11 12
      src/libraries/glslang/glslang/Include/Common.h
  21. 1 1
      src/libraries/glslang/glslang/Include/ConstantUnion.h
  22. 1 0
      src/libraries/glslang/glslang/Include/ResourceLimits.h
  23. 50 10
      src/libraries/glslang/glslang/Include/Types.h
  24. 38 5
      src/libraries/glslang/glslang/Include/intermediate.h
  25. 10 1
      src/libraries/glslang/glslang/MachineIndependent/Constant.cpp
  26. 349 112
      src/libraries/glslang/glslang/MachineIndependent/Initialize.cpp
  27. 207 178
      src/libraries/glslang/glslang/MachineIndependent/Intermediate.cpp
  28. 34 4
      src/libraries/glslang/glslang/MachineIndependent/LiveTraverser.h
  29. 7 4
      src/libraries/glslang/glslang/MachineIndependent/ParseContextBase.cpp
  30. 431 131
      src/libraries/glslang/glslang/MachineIndependent/ParseHelper.cpp
  31. 10 1
      src/libraries/glslang/glslang/MachineIndependent/ParseHelper.h
  32. 42 12
      src/libraries/glslang/glslang/MachineIndependent/Scan.cpp
  33. 69 33
      src/libraries/glslang/glslang/MachineIndependent/ShaderLang.cpp
  34. 5 3
      src/libraries/glslang/glslang/MachineIndependent/SymbolTable.cpp
  35. 6 6
      src/libraries/glslang/glslang/MachineIndependent/SymbolTable.h
  36. 129 17
      src/libraries/glslang/glslang/MachineIndependent/Versions.cpp
  37. 22 2
      src/libraries/glslang/glslang/MachineIndependent/Versions.h
  38. 8 0
      src/libraries/glslang/glslang/MachineIndependent/gl_types.h
  39. 541 525
      src/libraries/glslang/glslang/MachineIndependent/glslang_tab.cpp
  40. 261 252
      src/libraries/glslang/glslang/MachineIndependent/glslang_tab.cpp.h
  41. 33 7
      src/libraries/glslang/glslang/MachineIndependent/intermOut.cpp
  42. 74 32
      src/libraries/glslang/glslang/MachineIndependent/iomapper.cpp
  43. 11 8
      src/libraries/glslang/glslang/MachineIndependent/iomapper.h
  44. 100 42
      src/libraries/glslang/glslang/MachineIndependent/linkValidate.cpp
  45. 101 47
      src/libraries/glslang/glslang/MachineIndependent/localintermediate.h
  46. 14 4
      src/libraries/glslang/glslang/MachineIndependent/parseConst.cpp
  47. 11 2
      src/libraries/glslang/glslang/MachineIndependent/parseVersions.h
  48. 29 7
      src/libraries/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp
  49. 2 1
      src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpContext.cpp
  50. 3 2
      src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpContext.h
  51. 76 6
      src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp
  52. 1 1
      src/libraries/glslang/glslang/MachineIndependent/propagateNoContraction.cpp
  53. 164 99
      src/libraries/glslang/glslang/MachineIndependent/reflection.cpp
  54. 2 2
      src/libraries/glslang/glslang/MachineIndependent/reflection.h
  55. 22 4
      src/libraries/glslang/glslang/OSDependent/Web/glslang.js.cpp
  56. 25 14
      src/libraries/glslang/glslang/OSDependent/Web/glslang.pre.js
  57. 179 133
      src/libraries/glslang/glslang/Public/ShaderLang.h
  58. 31 4
      src/libraries/glslang/glslang/build_info.h
  59. 1 0
      src/modules/graphics/ShaderStage.cpp

+ 2 - 1
CMakeLists.txt

@@ -1338,7 +1338,6 @@ set(LOVE_SRC_3P_GLSLANG_GLSLANG_MACHINEINDEPENDENT
 	src/libraries/glslang/glslang/MachineIndependent/ParseHelper.cpp
 	src/libraries/glslang/glslang/MachineIndependent/ParseHelper.h
 	src/libraries/glslang/glslang/MachineIndependent/parseVersions.h
-	src/libraries/glslang/glslang/MachineIndependent/pch.cpp
 	src/libraries/glslang/glslang/MachineIndependent/pch.h
 	src/libraries/glslang/glslang/MachineIndependent/PoolAlloc.cpp
 	src/libraries/glslang/glslang/MachineIndependent/propagateNoContraction.cpp
@@ -1379,6 +1378,7 @@ set(LOVE_SRC_3P_GLSLANG_GLSLANG_PUBLIC
 )
 
 set(LOVE_SRC_3P_GLSLANG_GLSLANG
+	src/libraries/glslang/glslang/build_info.h
 	${LOVE_SRC_3P_GLSLANG_GLSLANG_GENERICCODEGEN}
 	${LOVE_SRC_3P_GLSLANG_GLSLANG_INCLUDE}
 	${LOVE_SRC_3P_GLSLANG_GLSLANG_MACHINEINDEPENDENT}
@@ -1408,6 +1408,7 @@ set(LOVE_SRC_3P_GLSLANG_SPIRV
 	src/libraries/glslang/SPIRV/InReadableOrder.cpp
 	src/libraries/glslang/SPIRV/Logger.cpp
 	src/libraries/glslang/SPIRV/Logger.h
+	src/libraries/glslang/SPIRV/NonSemanticDebugPrintf.h
 	src/libraries/glslang/SPIRV/spirv.hpp
 	src/libraries/glslang/SPIRV/SpvBuilder.cpp
 	src/libraries/glslang/SPIRV/SpvBuilder.h

+ 4 - 6
platform/xcode/liblove.xcodeproj/project.pbxproj

@@ -795,8 +795,6 @@
 		FA1E88831DF363DB00E808AA /* Filter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA1E88811DF363DB00E808AA /* Filter.cpp */; };
 		FA1E88841DF363DB00E808AA /* Filter.h in Headers */ = {isa = PBXBuildFile; fileRef = FA1E88821DF363DB00E808AA /* Filter.h */; };
 		FA1E88851DF363E100E808AA /* Filter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA1E88811DF363DB00E808AA /* Filter.cpp */; };
-		FA24348421D401CB00B8918A /* pch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA24348021D401CB00B8918A /* pch.cpp */; };
-		FA24348521D401CB00B8918A /* pch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA24348021D401CB00B8918A /* pch.cpp */; };
 		FA24348621D401CB00B8918A /* attribute.h in Headers */ = {isa = PBXBuildFile; fileRef = FA24348121D401CB00B8918A /* attribute.h */; };
 		FA24348721D401CB00B8918A /* attribute.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA24348221D401CB00B8918A /* attribute.cpp */; };
 		FA24348821D401CB00B8918A /* attribute.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA24348221D401CB00B8918A /* attribute.cpp */; };
@@ -1799,7 +1797,6 @@
 		FA1E887D1DF363CD00E808AA /* Filter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Filter.h; sourceTree = "<group>"; };
 		FA1E88811DF363DB00E808AA /* Filter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Filter.cpp; sourceTree = "<group>"; };
 		FA1E88821DF363DB00E808AA /* Filter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Filter.h; sourceTree = "<group>"; };
-		FA24348021D401CB00B8918A /* pch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pch.cpp; sourceTree = "<group>"; };
 		FA24348121D401CB00B8918A /* attribute.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = attribute.h; sourceTree = "<group>"; };
 		FA24348221D401CB00B8918A /* attribute.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = attribute.cpp; sourceTree = "<group>"; };
 		FA24348321D401CB00B8918A /* pch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pch.h; sourceTree = "<group>"; };
@@ -2009,6 +2006,8 @@
 		FAE272501C05A15B00A67640 /* ParticleSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParticleSystem.cpp; sourceTree = "<group>"; };
 		FAE272511C05A15B00A67640 /* ParticleSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParticleSystem.h; sourceTree = "<group>"; };
 		FAE64A7D2071359C00BC7981 /* libfreetype.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libfreetype.a; sourceTree = "<group>"; };
+		FAEC22942534EE6700EBD925 /* NonSemanticDebugPrintf.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NonSemanticDebugPrintf.h; sourceTree = "<group>"; };
+		FAEC229F2534F25100EBD925 /* build_info.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = build_info.h; sourceTree = "<group>"; };
 		FAECA1B01F3164700095D008 /* CompressedSlice.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CompressedSlice.cpp; sourceTree = "<group>"; };
 		FAECA1B11F3164700095D008 /* CompressedSlice.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CompressedSlice.h; sourceTree = "<group>"; };
 		FAF13FC21E20934C00F898D2 /* CodeGen.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodeGen.cpp; sourceTree = "<group>"; };
@@ -3591,6 +3590,7 @@
 		FAF13FC01E20934C00F898D2 /* glslang */ = {
 			isa = PBXGroup;
 			children = (
+				FAEC229F2534F25100EBD925 /* build_info.h */,
 				FAF13FC11E20934C00F898D2 /* GenericCodeGen */,
 				FAF13FC41E20934C00F898D2 /* Include */,
 				FAF13FD21E20934C00F898D2 /* MachineIndependent */,
@@ -3654,7 +3654,6 @@
 				FAF13FE61E20934C00F898D2 /* ParseHelper.cpp */,
 				FAF13FE71E20934C00F898D2 /* ParseHelper.h */,
 				FAF13FE81E20934C00F898D2 /* parseVersions.h */,
-				FA24348021D401CB00B8918A /* pch.cpp */,
 				FA24348321D401CB00B8918A /* pch.h */,
 				FAF13FE91E20934C00F898D2 /* PoolAlloc.cpp */,
 				FAF13FEA1E20934C00F898D2 /* preprocessor */,
@@ -3743,6 +3742,7 @@
 				FAF6C9C623C2DE2900D7B5BC /* InReadableOrder.cpp */,
 				FAF6C9D523C2DE2900D7B5BC /* Logger.cpp */,
 				FAF6C9D723C2DE2900D7B5BC /* Logger.h */,
+				FAEC22942534EE6700EBD925 /* NonSemanticDebugPrintf.h */,
 				FAF6C9C923C2DE2900D7B5BC /* spirv.hpp */,
 				FAF6C9CA23C2DE2900D7B5BC /* SpvBuilder.cpp */,
 				FAF6C9C223C2DE2900D7B5BC /* SpvBuilder.h */,
@@ -4329,7 +4329,6 @@
 				FA91DA8C1F377C3900C80E33 /* deprecation.cpp in Sources */,
 				FA6A2B6B1F5F7F560074C308 /* DataView.cpp in Sources */,
 				FA0B7E401A95902C000E1D17 /* wrap_ChainShape.cpp in Sources */,
-				FA24348521D401CB00B8918A /* pch.cpp in Sources */,
 				FA0B7DEC1A95902C000E1D17 /* Cursor.cpp in Sources */,
 				FA0B7D871A95902C000E1D17 /* ImageData.cpp in Sources */,
 				FA0B7E101A95902C000E1D17 /* FrictionJoint.cpp in Sources */,
@@ -4728,7 +4727,6 @@
 				FA0B7DB71A95902C000E1D17 /* Joystick.cpp in Sources */,
 				FA0B7A321A958EA3000E1D17 /* b2Collision.cpp in Sources */,
 				FA91DA8B1F377C3900C80E33 /* deprecation.cpp in Sources */,
-				FA24348421D401CB00B8918A /* pch.cpp in Sources */,
 				FA0B7E3F1A95902C000E1D17 /* wrap_ChainShape.cpp in Sources */,
 				FA0B7DEB1A95902C000E1D17 /* Cursor.cpp in Sources */,
 				FA0B7D861A95902C000E1D17 /* ImageData.cpp in Sources */,

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

@@ -35,5 +35,6 @@ static const char* const E_SPV_EXT_shader_viewport_index_layer  = "SPV_EXT_shade
 static const char* const E_SPV_EXT_fragment_fully_covered = "SPV_EXT_fragment_fully_covered";
 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_shader_atomic_float_add = "SPV_EXT_shader_atomic_float_add";
 
 #endif  // #ifndef GLSLextEXT_H

+ 5 - 2
src/libraries/glslang/SPIRV/GLSL.ext.KHR.h

@@ -1,5 +1,6 @@
 /*
-** Copyright (c) 2014-2016 The Khronos Group Inc.
+** Copyright (c) 2014-2020 The Khronos Group Inc.
+** Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 **
 ** Permission is hereby granted, free of charge, to any person obtaining a copy
 ** of this software and/or associated documentation files (the "Materials"),
@@ -44,5 +45,7 @@ static const char* const E_SPV_EXT_physical_storage_buffer      = "SPV_EXT_physi
 static const char* const E_SPV_KHR_physical_storage_buffer      = "SPV_KHR_physical_storage_buffer";
 static const char* const E_SPV_EXT_fragment_shader_interlock    = "SPV_EXT_fragment_shader_interlock";
 static const char* const E_SPV_KHR_shader_clock                 = "SPV_KHR_shader_clock";
-
+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_query                    = "SPV_KHR_ray_query";
 #endif  // #ifndef GLSLextKHR_H

File diff suppressed because it is too large
+ 374 - 160
src/libraries/glslang/SPIRV/GlslangToSpv.cpp


+ 1 - 1
src/libraries/glslang/SPIRV/GlslangToSpv.h

@@ -69,4 +69,4 @@ std::string SpvBuildLogger::getAllMessages() const {
 
 } // end spv namespace
 
-#endif
+#endif

+ 50 - 0
src/libraries/glslang/SPIRV/NonSemanticDebugPrintf.h

@@ -0,0 +1,50 @@
+// Copyright (c) 2020 The Khronos Group Inc.
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+// 
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+//    https://www.khronos.org/registry/
+// 
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+// 
+
+#ifndef SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_
+#define SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+    NonSemanticDebugPrintfRevision = 1,
+    NonSemanticDebugPrintfRevision_BitWidthPadding = 0x7fffffff
+};
+
+enum NonSemanticDebugPrintfInstructions {
+    NonSemanticDebugPrintfDebugPrintf = 1,
+    NonSemanticDebugPrintfInstructionsMax = 0x7fffffff
+};
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_

+ 12 - 1
src/libraries/glslang/SPIRV/SPVRemapper.cpp

@@ -625,6 +625,9 @@ namespace spv {
                 break;
             }
 
+            case spv::OperandVariableLiteralStrings:
+                return nextInst;
+
             // Execution mode might have extra literal operands.  Skip them.
             case spv::OperandExecutionMode:
                 return nextInst;
@@ -827,7 +830,15 @@ namespace spv {
             [&](spv::Id& id) {
                 if (thisOpCode != spv::OpNop) {
                     ++idCounter;
-                    const std::uint32_t hashval = opCounter[thisOpCode] * thisOpCode * 50047 + idCounter + fnId * 117;
+                    const std::uint32_t hashval =
+                        // Explicitly cast operands to unsigned int to avoid integer
+                        // promotion to signed int followed by integer overflow,
+                        // which would result in undefined behavior.
+                        static_cast<unsigned int>(opCounter[thisOpCode])
+                        * thisOpCode
+                        * 50047
+                        + idCounter
+                        + static_cast<unsigned int>(fnId) * 117;
 
                     if (isOldIdUnmapped(id))
                         localId(id, nextUnusedId(hashval % softTypeIdLimit + firstMappedID));

+ 164 - 30
src/libraries/glslang/SPIRV/SpvBuilder.cpp

@@ -1,6 +1,7 @@
 //
 // Copyright (C) 2014-2015 LunarG, Inc.
 // Copyright (C) 2015-2018 Google, Inc.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 // All rights reserved.
 //
@@ -496,7 +497,8 @@ Id Builder::makeFunctionType(Id returnType, const std::vector<Id>& paramTypes)
     return type->getResultId();
 }
 
-Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format)
+Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, bool ms, unsigned sampled,
+    ImageFormat format)
 {
     assert(sampled == 1 || sampled == 2);
 
@@ -601,16 +603,31 @@ Id Builder::makeSampledImageType(Id imageType)
 }
 
 #ifndef GLSLANG_WEB
-Id Builder::makeAccelerationStructureNVType()
+Id Builder::makeAccelerationStructureType()
 {
     Instruction *type;
-    if (groupedTypes[OpTypeAccelerationStructureNV].size() == 0) {
-        type = new Instruction(getUniqueId(), NoType, OpTypeAccelerationStructureNV);
-        groupedTypes[OpTypeAccelerationStructureNV].push_back(type);
+    if (groupedTypes[OpTypeAccelerationStructureKHR].size() == 0) {
+        type = new Instruction(getUniqueId(), NoType, OpTypeAccelerationStructureKHR);
+        groupedTypes[OpTypeAccelerationStructureKHR].push_back(type);
         constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
         module.mapInstruction(type);
     } else {
-        type = groupedTypes[OpTypeAccelerationStructureNV].back();
+        type = groupedTypes[OpTypeAccelerationStructureKHR].back();
+    }
+
+    return type->getResultId();
+}
+
+Id Builder::makeRayQueryType()
+{
+    Instruction *type;
+    if (groupedTypes[OpTypeRayQueryProvisionalKHR].size() == 0) {
+        type = new Instruction(getUniqueId(), NoType, OpTypeRayQueryProvisionalKHR);
+        groupedTypes[OpTypeRayQueryProvisionalKHR].push_back(type);
+        constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
+        module.mapInstruction(type);
+    } else {
+        type = groupedTypes[OpTypeRayQueryProvisionalKHR].back();
     }
 
     return type->getResultId();
@@ -1166,6 +1183,28 @@ void Builder::addExecutionMode(Function* entryPoint, ExecutionMode mode, int val
     executionModes.push_back(std::unique_ptr<Instruction>(instr));
 }
 
+void Builder::addExecutionMode(Function* entryPoint, ExecutionMode mode, const std::vector<unsigned>& literals)
+{
+    Instruction* instr = new Instruction(OpExecutionMode);
+    instr->addIdOperand(entryPoint->getId());
+    instr->addImmediateOperand(mode);
+    for (auto literal : literals)
+        instr->addImmediateOperand(literal);
+
+    executionModes.push_back(std::unique_ptr<Instruction>(instr));
+}
+
+void Builder::addExecutionModeId(Function* entryPoint, ExecutionMode mode, const std::vector<Id>& operandIds)
+{
+    Instruction* instr = new Instruction(OpExecutionModeId);
+    instr->addIdOperand(entryPoint->getId());
+    instr->addImmediateOperand(mode);
+    for (auto operandId : operandIds)
+        instr->addIdOperand(operandId);
+
+    executionModes.push_back(std::unique_ptr<Instruction>(instr));
+}
+
 void Builder::addName(Id id, const char* string)
 {
     Instruction* name = new Instruction(OpName);
@@ -1204,7 +1243,7 @@ void Builder::addDecoration(Id id, Decoration decoration, const char* s)
     if (decoration == spv::DecorationMax)
         return;
 
-    Instruction* dec = new Instruction(OpDecorateStringGOOGLE);
+    Instruction* dec = new Instruction(OpDecorateString);
     dec->addIdOperand(id);
     dec->addImmediateOperand(decoration);
     dec->addStringOperand(s);
@@ -1212,6 +1251,34 @@ void Builder::addDecoration(Id id, Decoration decoration, const char* s)
     decorations.push_back(std::unique_ptr<Instruction>(dec));
 }
 
+void Builder::addDecoration(Id id, Decoration decoration, const std::vector<unsigned>& literals)
+{
+    if (decoration == spv::DecorationMax)
+        return;
+
+    Instruction* dec = new Instruction(OpDecorate);
+    dec->addIdOperand(id);
+    dec->addImmediateOperand(decoration);
+    for (auto literal : literals)
+        dec->addImmediateOperand(literal);
+
+    decorations.push_back(std::unique_ptr<Instruction>(dec));
+}
+
+void Builder::addDecoration(Id id, Decoration decoration, const std::vector<const char*>& strings)
+{
+    if (decoration == spv::DecorationMax)
+        return;
+
+    Instruction* dec = new Instruction(OpDecorateString);
+    dec->addIdOperand(id);
+    dec->addImmediateOperand(decoration);
+    for (auto string : strings)
+        dec->addStringOperand(string);
+
+    decorations.push_back(std::unique_ptr<Instruction>(dec));
+}
+
 void Builder::addDecorationId(Id id, Decoration decoration, Id idDecoration)
 {
     if (decoration == spv::DecorationMax)
@@ -1225,6 +1292,21 @@ void Builder::addDecorationId(Id id, Decoration decoration, Id idDecoration)
     decorations.push_back(std::unique_ptr<Instruction>(dec));
 }
 
+void Builder::addDecorationId(Id id, Decoration decoration, const std::vector<Id>& operandIds)
+{
+    if(decoration == spv::DecorationMax)
+        return;
+
+    Instruction* dec = new Instruction(OpDecorateId);
+    dec->addIdOperand(id);
+    dec->addImmediateOperand(decoration);
+
+    for (auto operandId : operandIds)
+        dec->addIdOperand(operandId);
+
+    decorations.push_back(std::unique_ptr<Instruction>(dec));
+}
+
 void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, int num)
 {
     if (decoration == spv::DecorationMax)
@@ -1254,6 +1336,36 @@ void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decorat
     decorations.push_back(std::unique_ptr<Instruction>(dec));
 }
 
+void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, const std::vector<unsigned>& literals)
+{
+    if (decoration == spv::DecorationMax)
+        return;
+
+    Instruction* dec = new Instruction(OpMemberDecorate);
+    dec->addIdOperand(id);
+    dec->addImmediateOperand(member);
+    dec->addImmediateOperand(decoration);
+    for (auto literal : literals)
+        dec->addImmediateOperand(literal);
+
+    decorations.push_back(std::unique_ptr<Instruction>(dec));
+}
+
+void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, const std::vector<const char*>& strings)
+{
+    if (decoration == spv::DecorationMax)
+        return;
+
+    Instruction* dec = new Instruction(OpMemberDecorateString);
+    dec->addIdOperand(id);
+    dec->addImmediateOperand(member);
+    dec->addImmediateOperand(decoration);
+    for (auto string : strings)
+        dec->addStringOperand(string);
+
+    decorations.push_back(std::unique_ptr<Instruction>(dec));
+}
+
 // Comments in header
 Function* Builder::makeEntryPoint(const char* entryPoint)
 {
@@ -1270,7 +1382,8 @@ Function* Builder::makeEntryPoint(const char* entryPoint)
 
 // Comments in header
 Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const char* name,
-                                     const std::vector<Id>& paramTypes, const std::vector<std::vector<Decoration>>& decorations, Block **entry)
+                                     const std::vector<Id>& paramTypes,
+                                     const std::vector<std::vector<Decoration>>& decorations, Block **entry)
 {
     // Make the function and initial instructions in it
     Id typeId = makeFunctionType(returnType, paramTypes);
@@ -1279,9 +1392,12 @@ Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const
 
     // Set up the precisions
     setPrecision(function->getId(), precision);
+    function->setReturnPrecision(precision);
     for (unsigned p = 0; p < (unsigned)decorations.size(); ++p) {
-        for (int d = 0; d < (int)decorations[p].size(); ++d)
+        for (int d = 0; d < (int)decorations[p].size(); ++d) {
             addDecoration(firstParamId + p, decorations[p][d]);
+            function->addParamPrecision(p, decorations[p][d]);
+        }
     }
 
     // CFG
@@ -1338,7 +1454,7 @@ void Builder::makeDiscard()
 }
 
 // Comments in header
-Id Builder::createVariable(StorageClass storageClass, Id type, const char* name, Id initializer)
+Id Builder::createVariable(Decoration precision, StorageClass storageClass, Id type, const char* name, Id initializer)
 {
     Id pointerType = makePointer(storageClass, type);
     Instruction* inst = new Instruction(getUniqueId(), pointerType, OpVariable);
@@ -1360,6 +1476,7 @@ Id Builder::createVariable(StorageClass storageClass, Id type, const char* name,
 
     if (name)
         addName(inst->getResultId(), name);
+    setPrecision(inst->getResultId(), precision);
 
     return inst->getResultId();
 }
@@ -1373,7 +1490,8 @@ Id Builder::createUndefined(Id type)
 }
 
 // av/vis/nonprivate are unnecessary and illegal for some storage classes.
-spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) const
+spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc)
+    const
 {
     switch (sc) {
     case spv::StorageClassUniform:
@@ -1392,7 +1510,8 @@ spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAc
 }
 
 // Comments in header
-void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
+void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope,
+    unsigned int alignment)
 {
     Instruction* store = new Instruction(OpStore);
     store->addIdOperand(lValue);
@@ -1414,7 +1533,8 @@ void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAcce
 }
 
 // Comments in header
-Id Builder::createLoad(Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
+Id Builder::createLoad(Id lValue, spv::Decoration precision, spv::MemoryAccessMask memoryAccess,
+    spv::Scope scope, unsigned int alignment)
 {
     Instruction* load = new Instruction(getUniqueId(), getDerefTypeId(lValue), OpLoad);
     load->addIdOperand(lValue);
@@ -1432,6 +1552,7 @@ Id Builder::createLoad(Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope
     }
 
     buildPoint->addInstruction(std::unique_ptr<Instruction>(load));
+    setPrecision(load->getResultId(), precision);
 
     return load->getResultId();
 }
@@ -1495,7 +1616,8 @@ Id Builder::createCompositeExtract(Id composite, Id typeId, unsigned index)
     // Generate code for spec constants if in spec constant operation
     // generation mode.
     if (generatingOpCodeForSpecConst) {
-        return createSpecConstantOp(OpCompositeExtract, typeId, std::vector<Id>(1, composite), std::vector<Id>(1, index));
+        return createSpecConstantOp(OpCompositeExtract, typeId, std::vector<Id>(1, composite),
+            std::vector<Id>(1, index));
     }
     Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract);
     extract->addIdOperand(composite);
@@ -1697,7 +1819,8 @@ Id Builder::createOp(Op opCode, Id typeId, const std::vector<IdImmediate>& opera
     return op->getResultId();
 }
 
-Id Builder::createSpecConstantOp(Op opCode, Id typeId, const std::vector<Id>& operands, const std::vector<unsigned>& literals)
+Id Builder::createSpecConstantOp(Op opCode, Id typeId, const std::vector<Id>& operands,
+    const std::vector<unsigned>& literals)
 {
     Instruction* op = new Instruction(getUniqueId(), typeId, OpSpecConstantOp);
     op->addImmediateOperand((unsigned) opCode);
@@ -2144,7 +2267,7 @@ Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, b
         Op op;
         switch (getMostBasicTypeClass(valueType)) {
         case OpTypeFloat:
-            op = equal ? OpFOrdEqual : OpFOrdNotEqual;
+            op = equal ? OpFOrdEqual : OpFUnordNotEqual;
             break;
         case OpTypeInt:
         default:
@@ -2187,7 +2310,8 @@ Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, b
         if (constituent == 0)
             resultId = subResultId;
         else
-            resultId = setPrecision(createBinOp(equal ? OpLogicalAnd : OpLogicalOr, boolType, resultId, subResultId), precision);
+            resultId = setPrecision(createBinOp(equal ? OpLogicalAnd : OpLogicalOr, boolType, resultId, subResultId),
+                                    precision);
     }
 
     return resultId;
@@ -2196,7 +2320,8 @@ Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, b
 // OpCompositeConstruct
 Id Builder::createCompositeConstruct(Id typeId, const std::vector<Id>& constituents)
 {
-    assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 && getNumTypeConstituents(typeId) == (int)constituents.size()));
+    assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 &&
+           getNumTypeConstituents(typeId) == (int)constituents.size()));
 
     if (generatingOpCodeForSpecConst) {
         // Sometime, even in spec-constant-op mode, the constant composite to be
@@ -2609,7 +2734,8 @@ void Builder::clearAccessChain()
 }
 
 // Comments in header
-void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment)
+void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType,
+    AccessChain::CoherentFlags coherentFlags, unsigned int alignment)
 {
     accessChain.coherentFlags |= coherentFlags;
     accessChain.alignment |= alignment;
@@ -2649,7 +2775,7 @@ void Builder::accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess, sp
     // If swizzle still exists, it is out-of-order or not full, we must load the target vector,
     // extract and insert elements to perform writeMask and/or swizzle.
     if (accessChain.swizzle.size() > 0) {
-        Id tempBaseId = createLoad(base);
+        Id tempBaseId = createLoad(base, spv::NoPrecision);
         source = createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, source, accessChain.swizzle);
     }
 
@@ -2663,7 +2789,8 @@ void Builder::accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess, sp
 }
 
 // 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 nonUniform, Id resultType,
+    spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
 {
     Id id;
 
@@ -2687,17 +2814,19 @@ Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resu
 
             if (constant) {
                 id = createCompositeExtract(accessChain.base, swizzleBase, indexes);
+                setPrecision(id, precision);
             } else {
                 Id lValue = NoResult;
-                if (spvVersion >= Spv_1_4) {
+                if (spvVersion >= Spv_1_4 && isValidInitializer(accessChain.base)) {
                     // make a new function variable for this r-value, using an initializer,
                     // and mark it as NonWritable so that downstream it can be detected as a lookup
                     // table
-                    lValue = createVariable(StorageClassFunction, getTypeId(accessChain.base), "indexable",
-                        accessChain.base);
+                    lValue = createVariable(NoPrecision, StorageClassFunction, getTypeId(accessChain.base),
+                        "indexable", accessChain.base);
                     addDecoration(lValue, DecorationNonWritable);
                 } else {
-                    lValue = createVariable(StorageClassFunction, getTypeId(accessChain.base), "indexable");
+                    lValue = createVariable(NoPrecision, StorageClassFunction, getTypeId(accessChain.base),
+                        "indexable");
                     // store into it
                     createStore(accessChain.base, lValue);
                 }
@@ -2706,9 +2835,8 @@ Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resu
                 accessChain.isRValue = false;
 
                 // load through the access chain
-                id = createLoad(collapseAccessChain());
+                id = createLoad(collapseAccessChain(), precision);
             }
-            setPrecision(id, precision);
         } else
             id = accessChain.base;  // no precision, it was set when this was defined
     } else {
@@ -2721,8 +2849,13 @@ Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resu
         }
 
         // load through the access chain
-        id = createLoad(collapseAccessChain(), memoryAccess, scope, alignment);
-        setPrecision(id, precision);
+        id = collapseAccessChain();
+        // Apply nonuniform both to the access chain and the loaded value.
+        // Buffer accesses need the access chain decorated, and this is where
+        // loaded image types get decorated. TODO: This should maybe move to
+        // createImageTextureFunctionCall.
+        addDecoration(id, nonUniform);
+        id = createLoad(id, precision, memoryAccess, scope, alignment);
         addDecoration(id, nonUniform);
     }
 
@@ -3075,7 +3208,8 @@ void Builder::dumpSourceInstructions(std::vector<unsigned int>& out) const
         dumpSourceInstructions(iItr->first, *iItr->second, out);
 }
 
-void Builder::dumpInstructions(std::vector<unsigned int>& out, const std::vector<std::unique_ptr<Instruction> >& instructions) const
+void Builder::dumpInstructions(std::vector<unsigned int>& out,
+    const std::vector<std::unique_ptr<Instruction> >& instructions) const
 {
     for (int i = 0; i < (int)instructions.size(); ++i) {
         instructions[i]->dump(out);

+ 101 - 37
src/libraries/glslang/SPIRV/SpvBuilder.h

@@ -1,7 +1,8 @@
 //
 // Copyright (C) 2014-2015 LunarG, Inc.
-// Copyright (C) 2015-2018 Google, Inc.
+// Copyright (C) 2015-2020 Google, Inc.
 // Copyright (C) 2017 ARM Limited.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 // All rights reserved.
 //
@@ -94,6 +95,7 @@ public:
         const char* file_c_str = str.c_str();
         fileString->addStringOperand(file_c_str);
         strings.push_back(std::unique_ptr<Instruction>(fileString));
+        module.mapInstruction(fileString);
         stringIds[file_c_str] = strId;
         return strId;
     }
@@ -181,7 +183,9 @@ public:
     Id makeCooperativeMatrixType(Id component, Id scope, Id rows, Id cols);
 
     // accelerationStructureNV type
-    Id makeAccelerationStructureNVType();
+    Id makeAccelerationStructureType();
+    // rayQueryEXT type
+    Id makeRayQueryType();
 
     // For querying about types.
     Id getTypeId(Id resultId) const { return module.getTypeId(resultId); }
@@ -196,7 +200,8 @@ public:
     Id getContainedTypeId(Id typeId) const;
     Id getContainedTypeId(Id typeId, int) const;
     StorageClass getTypeStorageClass(Id typeId) const { return module.getStorageClass(typeId); }
-    ImageFormat getImageTypeFormat(Id typeId) const { return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); }
+    ImageFormat getImageTypeFormat(Id typeId) const
+        { return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); }
 
     bool isPointer(Id resultId)      const { return isPointerType(getTypeId(resultId)); }
     bool isScalar(Id resultId)       const { return isScalarType(getTypeId(resultId)); }
@@ -206,12 +211,17 @@ public:
     bool isAggregate(Id resultId)    const { return isAggregateType(getTypeId(resultId)); }
     bool isSampledImage(Id resultId) const { return isSampledImageType(getTypeId(resultId)); }
 
-    bool isBoolType(Id typeId)               { return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); }
-    bool isIntType(Id typeId)          const { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) != 0; }
-    bool isUintType(Id typeId)         const { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; }
+    bool isBoolType(Id typeId)
+        { return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); }
+    bool isIntType(Id typeId)          const
+        { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) != 0; }
+    bool isUintType(Id typeId)         const
+        { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; }
     bool isFloatType(Id typeId)        const { return getTypeClass(typeId) == OpTypeFloat; }
     bool isPointerType(Id typeId)      const { return getTypeClass(typeId) == OpTypePointer; }
-    bool isScalarType(Id typeId)       const { return getTypeClass(typeId) == OpTypeFloat  || getTypeClass(typeId) == OpTypeInt || getTypeClass(typeId) == OpTypeBool; }
+    bool isScalarType(Id typeId)       const
+        { return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt ||
+          getTypeClass(typeId) == OpTypeBool; }
     bool isVectorType(Id typeId)       const { return getTypeClass(typeId) == OpTypeVector; }
     bool isMatrixType(Id typeId)       const { return getTypeClass(typeId) == OpTypeMatrix; }
     bool isStructType(Id typeId)       const { return getTypeClass(typeId) == OpTypeStruct; }
@@ -221,7 +231,8 @@ public:
 #else
     bool isCooperativeMatrixType(Id typeId)const { return getTypeClass(typeId) == OpTypeCooperativeMatrixNV; }
 #endif
-    bool isAggregateType(Id typeId)    const { return isArrayType(typeId) || isStructType(typeId) || isCooperativeMatrixType(typeId); }
+    bool isAggregateType(Id typeId)    const
+        { return isArrayType(typeId) || isStructType(typeId) || isCooperativeMatrixType(typeId); }
     bool isImageType(Id typeId)        const { return getTypeClass(typeId) == OpTypeImage; }
     bool isSamplerType(Id typeId)      const { return getTypeClass(typeId) == OpTypeSampler; }
     bool isSampledImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampledImage; }
@@ -233,9 +244,17 @@ public:
     bool isConstant(Id resultId) const { return isConstantOpCode(getOpCode(resultId)); }
     bool isConstantScalar(Id resultId) const { return getOpCode(resultId) == OpConstant; }
     bool isSpecConstant(Id resultId) const { return isSpecConstantOpCode(getOpCode(resultId)); }
-    unsigned int getConstantScalar(Id resultId) const { return module.getInstruction(resultId)->getImmediateOperand(0); }
+    unsigned int getConstantScalar(Id resultId) const
+        { return module.getInstruction(resultId)->getImmediateOperand(0); }
     StorageClass getStorageClass(Id resultId) const { return getTypeStorageClass(getTypeId(resultId)); }
 
+    bool isVariableOpCode(Op opcode) const { return opcode == OpVariable; }
+    bool isVariable(Id resultId) const { return isVariableOpCode(getOpCode(resultId)); }
+    bool isGlobalStorage(Id resultId) const { return getStorageClass(resultId) != StorageClassFunction; }
+    bool isGlobalVariable(Id resultId) const { return isVariable(resultId) && isGlobalStorage(resultId); }
+    // See if a resultId is valid for use as an initializer.
+    bool isValidInitializer(Id resultId) const { return isConstant(resultId) || isGlobalVariable(resultId); }
+
     int getScalarTypeWidth(Id typeId) const
     {
         Id scalarTypeId = getScalarTypeId(typeId);
@@ -275,14 +294,22 @@ public:
 
     // For making new constants (will return old constant if the requested one was already made).
     Id makeBoolConstant(bool b, bool specConstant = false);
-    Id makeInt8Constant(int i, bool specConstant = false)        { return makeIntConstant(makeIntType(8),  (unsigned)i, specConstant); }
-    Id makeUint8Constant(unsigned u, bool specConstant = false)  { return makeIntConstant(makeUintType(8),           u, specConstant); }
-    Id makeInt16Constant(int i, bool specConstant = false)       { return makeIntConstant(makeIntType(16),  (unsigned)i, specConstant); }
-    Id makeUint16Constant(unsigned u, bool specConstant = false) { return makeIntConstant(makeUintType(16),           u, specConstant); }
-    Id makeIntConstant(int i, bool specConstant = false)         { return makeIntConstant(makeIntType(32),  (unsigned)i, specConstant); }
-    Id makeUintConstant(unsigned u, bool specConstant = false)   { return makeIntConstant(makeUintType(32),           u, specConstant); }
-    Id makeInt64Constant(long long i, bool specConstant = false)            { return makeInt64Constant(makeIntType(64),  (unsigned long long)i, specConstant); }
-    Id makeUint64Constant(unsigned long long u, bool specConstant = false)  { return makeInt64Constant(makeUintType(64),                     u, specConstant); }
+    Id makeInt8Constant(int i, bool specConstant = false)
+        { return makeIntConstant(makeIntType(8),  (unsigned)i, specConstant); }
+    Id makeUint8Constant(unsigned u, bool specConstant = false)
+        { return makeIntConstant(makeUintType(8),           u, specConstant); }
+    Id makeInt16Constant(int i, bool specConstant = false)
+        { return makeIntConstant(makeIntType(16),  (unsigned)i, specConstant); }
+    Id makeUint16Constant(unsigned u, bool specConstant = false)
+        { return makeIntConstant(makeUintType(16),           u, specConstant); }
+    Id makeIntConstant(int i, bool specConstant = false)
+        { return makeIntConstant(makeIntType(32),  (unsigned)i, specConstant); }
+    Id makeUintConstant(unsigned u, bool specConstant = false)
+        { return makeIntConstant(makeUintType(32),           u, specConstant); }
+    Id makeInt64Constant(long long i, bool specConstant = false)
+        { return makeInt64Constant(makeIntType(64),  (unsigned long long)i, specConstant); }
+    Id makeUint64Constant(unsigned long long u, bool specConstant = false)
+        { return makeInt64Constant(makeUintType(64),                     u, specConstant); }
     Id makeFloatConstant(float f, bool specConstant = false);
     Id makeDoubleConstant(double d, bool specConstant = false);
     Id makeFloat16Constant(float f16, bool specConstant = false);
@@ -294,13 +321,20 @@ public:
     // Methods for adding information outside the CFG.
     Instruction* addEntryPoint(ExecutionModel, Function*, const char* name);
     void addExecutionMode(Function*, ExecutionMode mode, int value1 = -1, int value2 = -1, int value3 = -1);
+    void addExecutionMode(Function*, ExecutionMode mode, const std::vector<unsigned>& literals);
+    void addExecutionModeId(Function*, ExecutionMode mode, const std::vector<Id>& operandIds);
     void addName(Id, const char* name);
     void addMemberName(Id, int member, const char* name);
     void addDecoration(Id, Decoration, int num = -1);
     void addDecoration(Id, Decoration, const char*);
+    void addDecoration(Id, Decoration, const std::vector<unsigned>& literals);
+    void addDecoration(Id, Decoration, const std::vector<const char*>& strings);
     void addDecorationId(Id id, Decoration, Id idDecoration);
+    void addDecorationId(Id id, Decoration, const std::vector<Id>& operandIds);
     void addMemberDecoration(Id, unsigned int member, Decoration, int num = -1);
     void addMemberDecoration(Id, unsigned int member, Decoration, const char*);
+    void addMemberDecoration(Id, unsigned int member, Decoration, const std::vector<unsigned>& literals);
+    void addMemberDecoration(Id, unsigned int member, Decoration, const std::vector<const char*>& strings);
 
     // At the end of what block do the next create*() instructions go?
     void setBuildPoint(Block* bp) { buildPoint = bp; }
@@ -313,8 +347,8 @@ public:
     // Make a shader-style function, and create its entry block if entry is non-zero.
     // Return the function, pass back the entry.
     // The returned pointer is only valid for the lifetime of this builder.
-    Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name, const std::vector<Id>& paramTypes,
-                                const std::vector<std::vector<Decoration>>& precisions, Block **entry = 0);
+    Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name,
+        const std::vector<Id>& paramTypes, const std::vector<std::vector<Decoration>>& precisions, Block **entry = 0);
 
     // Create a return. An 'implicit' return is one not appearing in the source
     // code.  In the case of an implicit return, no post-return block is inserted.
@@ -327,16 +361,20 @@ public:
     void makeDiscard();
 
     // Create a global or function local or IO variable.
-    Id createVariable(StorageClass, Id type, const char* name = 0, Id initializer = NoResult);
+    Id createVariable(Decoration precision, StorageClass, Id type, const char* name = nullptr,
+        Id initializer = NoResult);
 
     // Create an intermediate with an undefined value.
     Id createUndefined(Id type);
 
     // Store into an Id and return the l-value
-    void createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
+    void createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone,
+        spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
 
     // Load from an Id and return it
-    Id createLoad(Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
+    Id createLoad(Id lValue, spv::Decoration precision,
+        spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone,
+        spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
 
     // Create an OpAccessChain instruction
     Id createAccessChain(StorageClass, Id base, const std::vector<Id>& offsets);
@@ -495,7 +533,7 @@ public:
     // recursion stack can hold the memory for it.
     //
     void makeSwitch(Id condition, unsigned int control, int numSegments, const std::vector<int>& caseValues,
-                    const std::vector<int>& valueToSegment, int defaultSegment, std::vector<Block*>& segmentBB); // return argument
+                    const std::vector<int>& valueToSegment, int defaultSegment, std::vector<Block*>& segmentBB);
 
     // Add a branch to the innermost switch's merge block.
     void addSwitchBreak();
@@ -512,7 +550,7 @@ public:
         Block &head, &body, &merge, &continue_target;
     private:
         LoopBlocks();
-        LoopBlocks& operator=(const LoopBlocks&);
+        LoopBlocks& operator=(const LoopBlocks&) = delete;
     };
 
     // Start a new loop and prepare the builder to generate code for it.  Until
@@ -569,10 +607,13 @@ public:
         std::vector<Id> indexChain;
         Id instr;                      // cache the instruction that generates this access chain
         std::vector<unsigned> swizzle; // each std::vector element selects the next GLSL component number
-        Id component;                  // a dynamic component index, can coexist with a swizzle, done after the swizzle, NoResult if not present
-        Id preSwizzleBaseType;         // dereferenced type, before swizzle or component is applied; NoType unless a swizzle or component is present
+        Id component;                  // a dynamic component index, can coexist with a swizzle,
+                                       // done after the swizzle, NoResult if not present
+        Id preSwizzleBaseType;         // dereferenced type, before swizzle or component is applied;
+                                       // NoType unless a swizzle or component is present
         bool isRValue;                 // true if 'base' is an r-value, otherwise, base is an l-value
-        unsigned int alignment;        // bitwise OR of alignment values passed in. Accumulates worst alignment. Only tracks base and (optional) component selection alignment.
+        unsigned int alignment;        // bitwise OR of alignment values passed in. Accumulates worst alignment.
+                                       // Only tracks base and (optional) component selection alignment.
 
         // Accumulate whether anything in the chain of structures has coherent decorations.
         struct CoherentFlags {
@@ -583,12 +624,17 @@ public:
             CoherentFlags operator |=(const CoherentFlags &other) { return *this; }
 #else
             bool isVolatile() const { return volatil; }
+            bool anyCoherent() const {
+                return coherent || devicecoherent || queuefamilycoherent || workgroupcoherent ||
+                    subgroupcoherent || shadercallcoherent;
+            }
 
             unsigned coherent : 1;
             unsigned devicecoherent : 1;
             unsigned queuefamilycoherent : 1;
             unsigned workgroupcoherent : 1;
             unsigned subgroupcoherent : 1;
+            unsigned shadercallcoherent : 1;
             unsigned nonprivate : 1;
             unsigned volatil : 1;
             unsigned isImage : 1;
@@ -599,6 +645,7 @@ public:
                 queuefamilycoherent = 0;
                 workgroupcoherent = 0;
                 subgroupcoherent = 0;
+                shadercallcoherent = 0;
                 nonprivate = 0;
                 volatil = 0;
                 isImage = 0;
@@ -610,6 +657,7 @@ public:
                 queuefamilycoherent |= other.queuefamilycoherent;
                 workgroupcoherent |= other.workgroupcoherent;
                 subgroupcoherent |= other.subgroupcoherent;
+                shadercallcoherent |= other.shadercallcoherent;
                 nonprivate |= other.nonprivate;
                 volatil |= other.volatil;
                 isImage |= other.isImage;
@@ -655,11 +703,13 @@ public:
     }
 
     // push new swizzle onto the end of any existing swizzle, merging into a single swizzle
-    void accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment);
+    void accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType,
+        AccessChain::CoherentFlags coherentFlags, unsigned int alignment);
 
     // push a dynamic component selection onto the access chain, only applicable with a
     // non-trivial swizzle or no swizzle
-    void accessChainPushComponent(Id component, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment)
+    void accessChainPushComponent(Id component, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags,
+        unsigned int alignment)
     {
         if (accessChain.swizzle.size() != 1) {
             accessChain.component = component;
@@ -671,10 +721,18 @@ public:
     }
 
     // use accessChain and swizzle to store value
-    void accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
+    void accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone,
+        spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
 
     // use accessChain and swizzle to load an r-value
-    Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
+    Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType,
+        spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax,
+            unsigned int alignment = 0);
+
+    // Return whether or not the access chain can be represented in SPIR-V
+    // as an l-value.
+    // E.g., a[3].yx cannot be, while a[3].y and a[3].y[x] can be.
+    bool isSpvLvalue() const { return accessChain.swizzle.size() <= 1; }
 
     // get the direct pointer for an l-value
     Id accessChainGetLValue();
@@ -703,7 +761,8 @@ public:
 
     void createBranch(Block* block);
     void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock);
-    void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control, const std::vector<unsigned int>& operands);
+    void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control,
+        const std::vector<unsigned int>& operands);
 
     // Sets to generate opcode for specialization constants.
     void setToSpecConstCodeGenMode() { generatingOpCodeForSpecConst = true; }
@@ -729,7 +788,8 @@ public:
     void dumpSourceInstructions(const spv::Id fileId, const std::string& text, std::vector<unsigned int>&) const;
     void dumpInstructions(std::vector<unsigned int>&, const std::vector<std::unique_ptr<Instruction> >&) const;
     void dumpModuleProcesses(std::vector<unsigned int>&) const;
-    spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) const;
+    spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc)
+        const;
 
     unsigned int spvVersion;     // the version of SPIR-V to emit in the header
     SourceLanguage source;
@@ -764,10 +824,14 @@ public:
     std::vector<std::unique_ptr<Instruction> > externals;
     std::vector<std::unique_ptr<Function> > functions;
 
-     // not output, internally used for quick & dirty canonical (unique) creation
-    std::unordered_map<unsigned int, std::vector<Instruction*>> groupedConstants;       // map type opcodes to constant inst.
-    std::unordered_map<unsigned int, std::vector<Instruction*>> groupedStructConstants; // map struct-id to constant instructions
-    std::unordered_map<unsigned int, std::vector<Instruction*>> groupedTypes;           // map type opcodes to type instructions
+    // not output, internally used for quick & dirty canonical (unique) creation
+
+    // map type opcodes to constant inst.
+    std::unordered_map<unsigned int, std::vector<Instruction*>> groupedConstants;
+    // map struct-id to constant instructions
+    std::unordered_map<unsigned int, std::vector<Instruction*>> groupedStructConstants;
+    // map type opcodes to type instructions
+    std::unordered_map<unsigned int, std::vector<Instruction*>> groupedTypes;
 
     // stack of switches
     std::stack<Block*> switchMerges;

+ 65 - 38
src/libraries/glslang/SPIRV/SpvTools.cpp

@@ -1,6 +1,6 @@
 //
 // Copyright (C) 2014-2016 LunarG, Inc.
-// Copyright (C) 2018 Google, Inc.
+// Copyright (C) 2018-2020 Google, Inc.
 //
 // All rights reserved.
 //
@@ -67,6 +67,8 @@ spv_target_env MapToSpirvToolsEnv(const SpvVersion& spvVersion, spv::SpvBuildLog
             logger->missingFunctionality("Target version for SPIRV-Tools validator");
             return spv_target_env::SPV_ENV_VULKAN_1_1;
         }
+    case glslang::EShTargetVulkan_1_2:
+        return spv_target_env::SPV_ENV_VULKAN_1_2;
     default:
         break;
     }
@@ -78,6 +80,39 @@ spv_target_env MapToSpirvToolsEnv(const SpvVersion& spvVersion, spv::SpvBuildLog
     return spv_target_env::SPV_ENV_UNIVERSAL_1_0;
 }
 
+// Callback passed to spvtools::Optimizer::SetMessageConsumer
+void OptimizerMesssageConsumer(spv_message_level_t level, const char *source,
+        const spv_position_t &position, const char *message)
+{
+    auto &out = std::cerr;
+    switch (level)
+    {
+    case SPV_MSG_FATAL:
+    case SPV_MSG_INTERNAL_ERROR:
+    case SPV_MSG_ERROR:
+        out << "error: ";
+        break;
+    case SPV_MSG_WARNING:
+        out << "warning: ";
+        break;
+    case SPV_MSG_INFO:
+    case SPV_MSG_DEBUG:
+        out << "info: ";
+        break;
+    default:
+        break;
+    }
+    if (source)
+    {
+        out << source << ":";
+    }
+    out << position.line << ":" << position.column << ":" << position.index << ":";
+    if (message)
+    {
+        out << " " << message;
+    }
+    out << std::endl;
+}
 
 // Use the SPIRV-Tools disassembler to print SPIR-V.
 void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv)
@@ -126,45 +161,14 @@ void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector<
     spvContextDestroy(context);
 }
 
-// Apply the SPIRV-Tools optimizer to generated SPIR-V, for the purpose of
-// legalizing HLSL SPIR-V.
-void SpirvToolsLegalize(const glslang::TIntermediate&, std::vector<unsigned int>& spirv,
-                        spv::SpvBuildLogger*, const SpvOptions* options)
+// Apply the SPIRV-Tools optimizer to generated SPIR-V.  HLSL SPIR-V is legalized in the process.
+void SpirvToolsTransform(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
+                         spv::SpvBuildLogger* logger, const SpvOptions* options)
 {
-    spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2;
+    spv_target_env target_env = MapToSpirvToolsEnv(intermediate.getSpv(), logger);
 
     spvtools::Optimizer optimizer(target_env);
-    optimizer.SetMessageConsumer(
-        [](spv_message_level_t level, const char *source, const spv_position_t &position, const char *message) {
-            auto &out = std::cerr;
-            switch (level)
-            {
-            case SPV_MSG_FATAL:
-            case SPV_MSG_INTERNAL_ERROR:
-            case SPV_MSG_ERROR:
-                out << "error: ";
-                break;
-            case SPV_MSG_WARNING:
-                out << "warning: ";
-                break;
-            case SPV_MSG_INFO:
-            case SPV_MSG_DEBUG:
-                out << "info: ";
-                break;
-            default:
-                break;
-            }
-            if (source)
-            {
-                out << source << ":";
-            }
-            out << position.line << ":" << position.column << ":" << position.index << ":";
-            if (message)
-            {
-                out << " " << message;
-            }
-            out << std::endl;
-        });
+    optimizer.SetMessageConsumer(OptimizerMesssageConsumer);
 
     // If debug (specifically source line info) is being generated, propagate
     // line information into all SPIR-V instructions. This avoids loss of
@@ -173,6 +177,9 @@ void SpirvToolsLegalize(const glslang::TIntermediate&, std::vector<unsigned int>
     if (options->generateDebugInfo) {
         optimizer.RegisterPass(spvtools::CreatePropagateLineInfoPass());
     }
+    else if (options->stripDebugInfo) {
+        optimizer.RegisterPass(spvtools::CreateStripDebugInfoPass());
+    }
     optimizer.RegisterPass(spvtools::CreateWrapOpKillPass());
     optimizer.RegisterPass(spvtools::CreateDeadBranchElimPass());
     optimizer.RegisterPass(spvtools::CreateMergeReturnPass());
@@ -205,7 +212,27 @@ void SpirvToolsLegalize(const glslang::TIntermediate&, std::vector<unsigned int>
     }
 
     spvtools::OptimizerOptions spvOptOptions;
-    spvOptOptions.set_run_validator(false); // The validator may run as a seperate step later on
+    optimizer.SetTargetEnv(MapToSpirvToolsEnv(intermediate.getSpv(), logger));
+    spvOptOptions.set_run_validator(false); // The validator may run as a separate step later on
+    optimizer.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions);
+}
+
+// Apply the SPIRV-Tools optimizer to strip debug info from SPIR-V.  This is implicitly done by
+// SpirvToolsTransform if spvOptions->stripDebugInfo is set, but can be called separately if
+// optimization is disabled.
+void SpirvToolsStripDebugInfo(const glslang::TIntermediate& intermediate,
+        std::vector<unsigned int>& spirv, spv::SpvBuildLogger* logger)
+{
+    spv_target_env target_env = MapToSpirvToolsEnv(intermediate.getSpv(), logger);
+
+    spvtools::Optimizer optimizer(target_env);
+    optimizer.SetMessageConsumer(OptimizerMesssageConsumer);
+
+    optimizer.RegisterPass(spvtools::CreateStripDebugInfoPass());
+
+    spvtools::OptimizerOptions spvOptOptions;
+    optimizer.SetTargetEnv(MapToSpirvToolsEnv(intermediate.getSpv(), logger));
+    spvOptOptions.set_run_validator(false); // The validator may run as a separate step later on
     optimizer.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions);
 }
 

+ 11 - 5
src/libraries/glslang/SPIRV/SpvTools.h

@@ -52,9 +52,10 @@
 namespace glslang {
 
 struct SpvOptions {
-    SpvOptions() : generateDebugInfo(false), disableOptimizer(true),
+    SpvOptions() : generateDebugInfo(false), stripDebugInfo(false), disableOptimizer(true),
         optimizeSize(false), disassemble(false), validate(false) { }
     bool generateDebugInfo;
+    bool stripDebugInfo;
     bool disableOptimizer;
     bool optimizeSize;
     bool disassemble;
@@ -70,10 +71,15 @@ void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& s
 void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
                         spv::SpvBuildLogger*, bool prelegalization);
 
-// Apply the SPIRV-Tools optimizer to generated SPIR-V, for the purpose of
-// legalizing HLSL SPIR-V.
-void SpirvToolsLegalize(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
-                        spv::SpvBuildLogger*, const SpvOptions*);
+// Apply the SPIRV-Tools optimizer to generated SPIR-V.  HLSL SPIR-V is legalized in the process.
+void SpirvToolsTransform(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
+                         spv::SpvBuildLogger*, const SpvOptions*);
+
+// Apply the SPIRV-Tools optimizer to strip debug info from SPIR-V.  This is implicitly done by
+// SpirvToolsTransform if spvOptions->stripDebugInfo is set, but can be called separately if
+// optimization is disabled.
+void SpirvToolsStripDebugInfo(const glslang::TIntermediate& intermediate,
+        std::vector<unsigned int>& spirv, spv::SpvBuildLogger*);
 
 #endif
 

+ 12 - 2
src/libraries/glslang/SPIRV/disassemble.cpp

@@ -46,7 +46,6 @@
 
 #include "disassemble.h"
 #include "doc.h"
-#include "SpvTools.h"
 
 namespace spv {
     extern "C" {
@@ -75,6 +74,7 @@ enum ExtInstSet {
     GLSLextAMDInst,
     GLSLextNVInst,
     OpenCLExtInst,
+    NonSemanticDebugPrintfExtInst,
 };
 
 // Container class for a single instance of a SPIR-V stream, with methods for disassembly.
@@ -480,8 +480,12 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
             if (opCode == OpExtInst) {
                 ExtInstSet extInstSet = GLSL450Inst;
                 const char* name = idDescriptor[stream[word - 2]].c_str();
-                if (0 == memcmp("OpenCL", name, 6)) {
+                if (strcmp("OpenCL.std", name) == 0) {
                     extInstSet = OpenCLExtInst;
+                } else if (strcmp("OpenCL.DebugInfo.100", name) == 0) {
+                    extInstSet = OpenCLExtInst;
+                } else if (strcmp("NonSemantic.DebugPrintf", name) == 0) {
+                    extInstSet = NonSemanticDebugPrintfExtInst;
                 } else if (strcmp(spv::E_SPV_AMD_shader_ballot, name) == 0 ||
                            strcmp(spv::E_SPV_AMD_shader_trinary_minmax, name) == 0 ||
                            strcmp(spv::E_SPV_AMD_shader_explicit_vertex_parameter, name) == 0 ||
@@ -505,6 +509,8 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
                 }
                 else if (extInstSet == GLSLextNVInst) {
                     out << "(" << GLSLextNVGetDebugNames(name, entrypoint) << ")";
+                } else if (extInstSet == NonSemanticDebugPrintfExtInst) {
+                    out << "(DebugPrintf)";
                 }
             }
             break;
@@ -512,6 +518,10 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
         case OperandLiteralString:
             numOperands -= disassembleString();
             break;
+        case OperandVariableLiteralStrings:
+            while (numOperands > 0)
+                numOperands -= disassembleString();
+            return;
         case OperandMemoryAccess:
             outputMask(OperandMemoryAccess, stream[word++]);
             --numOperands;

+ 224 - 65
src/libraries/glslang/SPIRV/doc.cpp

@@ -1,5 +1,6 @@
 //
 // Copyright (C) 2014-2015 LunarG, Inc.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 // All rights reserved.
 //
@@ -99,12 +100,12 @@ const char* ExecutionModelString(int model)
 
     default: return "Bad";
 
-    case ExecutionModelRayGenerationNV: return "RayGenerationNV";
-    case ExecutionModelIntersectionNV:  return "IntersectionNV";
-    case ExecutionModelAnyHitNV:        return "AnyHitNV";
-    case ExecutionModelClosestHitNV:    return "ClosestHitNV";
-    case ExecutionModelMissNV:          return "MissNV";
-    case ExecutionModelCallableNV:      return "CallableNV";
+    case ExecutionModelRayGenerationKHR: return "RayGenerationKHR";
+    case ExecutionModelIntersectionKHR:  return "IntersectionKHR";
+    case ExecutionModelAnyHitKHR:        return "AnyHitKHR";
+    case ExecutionModelClosestHitKHR:    return "ClosestHitKHR";
+    case ExecutionModelMissKHR:          return "MissKHR";
+    case ExecutionModelCallableKHR:      return "CallableKHR";
     }
 }
 
@@ -133,7 +134,7 @@ const char* MemoryString(int mem)
     }
 }
 
-const int ExecutionModeCeiling = 33;
+const int ExecutionModeCeiling = 40;
 
 const char* ExecutionModeString(int mode)
 {
@@ -172,7 +173,21 @@ const char* ExecutionModeString(int mode)
     case 31: return "ContractionOff";
     case 32: return "Bad";
 
-    case 4446:  return "PostDepthCoverage";
+    case ExecutionModeInitializer:              return "Initializer";
+    case ExecutionModeFinalizer:                return "Finalizer";
+    case ExecutionModeSubgroupSize:             return "SubgroupSize";
+    case ExecutionModeSubgroupsPerWorkgroup:    return "SubgroupsPerWorkgroup";
+    case ExecutionModeSubgroupsPerWorkgroupId:  return "SubgroupsPerWorkgroupId";
+    case ExecutionModeLocalSizeId:              return "LocalSizeId";
+    case ExecutionModeLocalSizeHintId:          return "LocalSizeHintId";
+
+    case ExecutionModePostDepthCoverage:        return "PostDepthCoverage";
+    case ExecutionModeDenormPreserve:           return "DenormPreserve";
+    case ExecutionModeDenormFlushToZero:        return "DenormFlushToZero";
+    case ExecutionModeSignedZeroInfNanPreserve: return "SignedZeroInfNanPreserve";
+    case ExecutionModeRoundingModeRTE:          return "RoundingModeRTE";
+    case ExecutionModeRoundingModeRTZ:          return "RoundingModeRTZ";
+    case ExecutionModeStencilRefReplacingEXT:   return "StencilRefReplacingEXT";
 
     case ExecutionModeOutputLinesNV:            return "OutputLinesNV";
     case ExecutionModeOutputPrimitivesNV:       return "OutputPrimitivesNV";
@@ -187,6 +202,11 @@ const char* ExecutionModeString(int mode)
     case ExecutionModeShadingRateInterlockOrderedEXT:   return "ShadingRateInterlockOrderedEXT";
     case ExecutionModeShadingRateInterlockUnorderedEXT: return "ShadingRateInterlockUnorderedEXT";
 
+    case ExecutionModeMaxWorkgroupSizeINTEL:    return "MaxWorkgroupSizeINTEL";
+    case ExecutionModeMaxWorkDimINTEL:          return "MaxWorkDimINTEL";
+    case ExecutionModeNoGlobalOffsetINTEL:      return "NoGlobalOffsetINTEL";
+    case ExecutionModeNumSIMDWorkitemsINTEL:    return "NumSIMDWorkitemsINTEL";
+
     case ExecutionModeCeiling:
     default: return "Bad";
     }
@@ -209,12 +229,12 @@ const char* StorageClassString(int StorageClass)
     case 11: return "Image";
     case 12: return "StorageBuffer";
 
-    case StorageClassRayPayloadNV:            return "RayPayloadNV";
-    case StorageClassHitAttributeNV:          return "HitAttributeNV";
-    case StorageClassIncomingRayPayloadNV:    return "IncomingRayPayloadNV";
-    case StorageClassShaderRecordBufferNV:    return "ShaderRecordBufferNV";
-    case StorageClassCallableDataNV:          return "CallableDataNV";
-    case StorageClassIncomingCallableDataNV:  return "IncomingCallableDataNV";
+    case StorageClassRayPayloadKHR:            return "RayPayloadKHR";
+    case StorageClassHitAttributeKHR:          return "HitAttributeKHR";
+    case StorageClassIncomingRayPayloadKHR:    return "IncomingRayPayloadKHR";
+    case StorageClassShaderRecordBufferKHR:    return "ShaderRecordBufferKHR";
+    case StorageClassCallableDataKHR:          return "CallableDataKHR";
+    case StorageClassIncomingCallableDataKHR:  return "IncomingCallableDataKHR";
 
     case StorageClassPhysicalStorageBufferEXT: return "PhysicalStorageBufferEXT";
 
@@ -361,32 +381,33 @@ const char* BuiltInString(int builtIn)
     case 4996: return "BaryCoordSmoothCentroidAMD";
     case 4997: return "BaryCoordSmoothSampleAMD";
     case 4998: return "BaryCoordPullModelAMD";
-    case BuiltInLaunchIdNV:                 return "LaunchIdNV";
-    case BuiltInLaunchSizeNV:               return "LaunchSizeNV";
-    case BuiltInWorldRayOriginNV:           return "WorldRayOriginNV";
-    case BuiltInWorldRayDirectionNV:        return "WorldRayDirectionNV";
-    case BuiltInObjectRayOriginNV:          return "ObjectRayOriginNV";
-    case BuiltInObjectRayDirectionNV:       return "ObjectRayDirectionNV";
-    case BuiltInRayTminNV:                  return "RayTminNV";
-    case BuiltInRayTmaxNV:                  return "RayTmaxNV";
-    case BuiltInInstanceCustomIndexNV:      return "InstanceCustomIndexNV";
-    case BuiltInObjectToWorldNV:            return "ObjectToWorldNV";
-    case BuiltInWorldToObjectNV:            return "WorldToObjectNV";
-    case BuiltInHitTNV:                     return "HitTNV";
-    case BuiltInHitKindNV:                  return "HitKindNV";
-    case BuiltInIncomingRayFlagsNV:         return "IncomingRayFlagsNV";
-    case BuiltInViewportMaskNV:             return "ViewportMaskNV";
-    case BuiltInSecondaryPositionNV:        return "SecondaryPositionNV";
-    case BuiltInSecondaryViewportMaskNV:    return "SecondaryViewportMaskNV";
-    case BuiltInPositionPerViewNV:          return "PositionPerViewNV";
-    case BuiltInViewportMaskPerViewNV:      return "ViewportMaskPerViewNV";
+    case BuiltInLaunchIdKHR:                 return "LaunchIdKHR";
+    case BuiltInLaunchSizeKHR:               return "LaunchSizeKHR";
+    case BuiltInWorldRayOriginKHR:           return "WorldRayOriginKHR";
+    case BuiltInWorldRayDirectionKHR:        return "WorldRayDirectionKHR";
+    case BuiltInObjectRayOriginKHR:          return "ObjectRayOriginKHR";
+    case BuiltInObjectRayDirectionKHR:       return "ObjectRayDirectionKHR";
+    case BuiltInRayTminKHR:                  return "RayTminKHR";
+    case BuiltInRayTmaxKHR:                  return "RayTmaxKHR";
+    case BuiltInInstanceCustomIndexKHR:      return "InstanceCustomIndexKHR";
+    case BuiltInRayGeometryIndexKHR:         return "RayGeometryIndexKHR";
+    case BuiltInObjectToWorldKHR:            return "ObjectToWorldKHR";
+    case BuiltInWorldToObjectKHR:            return "WorldToObjectKHR";
+    case BuiltInHitTKHR:                     return "HitTKHR";
+    case BuiltInHitKindKHR:                  return "HitKindKHR";
+    case BuiltInIncomingRayFlagsKHR:         return "IncomingRayFlagsKHR";
+    case BuiltInViewportMaskNV:              return "ViewportMaskNV";
+    case BuiltInSecondaryPositionNV:         return "SecondaryPositionNV";
+    case BuiltInSecondaryViewportMaskNV:     return "SecondaryViewportMaskNV";
+    case BuiltInPositionPerViewNV:           return "PositionPerViewNV";
+    case BuiltInViewportMaskPerViewNV:       return "ViewportMaskPerViewNV";
 //    case BuiltInFragmentSizeNV:             return "FragmentSizeNV";        // superseded by BuiltInFragSizeEXT
 //    case BuiltInInvocationsPerPixelNV:      return "InvocationsPerPixelNV"; // superseded by BuiltInFragInvocationCountEXT
-    case BuiltInBaryCoordNV:                return "BaryCoordNV";
-    case BuiltInBaryCoordNoPerspNV:         return "BaryCoordNoPerspNV";
+    case BuiltInBaryCoordNV:                 return "BaryCoordNV";
+    case BuiltInBaryCoordNoPerspNV:          return "BaryCoordNoPerspNV";
 
-    case BuiltInFragSizeEXT:                return "FragSizeEXT";
-    case BuiltInFragInvocationCountEXT:     return "FragInvocationCountEXT";
+    case BuiltInFragSizeEXT:                 return "FragSizeEXT";
+    case BuiltInFragInvocationCountEXT:      return "FragInvocationCountEXT";
 
     case 5264: return "FullyCoveredEXT";
 
@@ -890,6 +911,9 @@ const char* CapabilityString(int info)
     case CapabilityPerViewAttributesNV:             return "PerViewAttributesNV";
     case CapabilityGroupNonUniformPartitionedNV:    return "GroupNonUniformPartitionedNV";
     case CapabilityRayTracingNV:                    return "RayTracingNV";
+    case CapabilityRayTracingProvisionalKHR:        return "RayTracingProvisionalKHR";
+    case CapabilityRayQueryProvisionalKHR:          return "RayQueryProvisionalKHR";
+    case CapabilityRayTraversalPrimitiveCullingProvisionalKHR: return "RayTraversalPrimitiveCullingProvisionalKHR";
     case CapabilityComputeDerivativeGroupQuadsNV:   return "ComputeDerivativeGroupQuadsNV";
     case CapabilityComputeDerivativeGroupLinearNV:  return "ComputeDerivativeGroupLinearNV";
     case CapabilityFragmentBarycentricNV:           return "FragmentBarycentricNV";
@@ -933,6 +957,9 @@ const char* CapabilityString(int info)
 
     case CapabilityIntegerFunctions2INTEL:              return "CapabilityIntegerFunctions2INTEL";
 
+    case CapabilityAtomicFloat32AddEXT:                     return "AtomicFloat32AddEXT";
+    case CapabilityAtomicFloat64AddEXT:                     return "AtomicFloat64AddEXT";
+
     default: return "Bad";
     }
 }
@@ -1264,6 +1291,7 @@ const char* OpcodeString(int op)
     case 320: return "OpImageSparseRead";
 
     case OpModuleProcessed: return "OpModuleProcessed";
+    case OpExecutionModeId: return "OpExecutionModeId";
     case OpDecorateId:      return "OpDecorateId";
 
     case 333: return "OpGroupNonUniformElect";
@@ -1308,6 +1336,8 @@ const char* OpcodeString(int op)
     case 4430: return "OpSubgroupAllEqualKHR";
     case 4432: return "OpSubgroupReadInvocationKHR";
 
+    case OpAtomicFAddEXT: return "OpAtomicFAddEXT";
+
     case 5000: return "OpGroupIAddNonUniformAMD";
     case 5001: return "OpGroupFAddNonUniformAMD";
     case 5002: return "OpGroupFMinNonUniformAMD";
@@ -1326,15 +1356,40 @@ const char* OpcodeString(int op)
     case OpMemberDecorateStringGOOGLE: return "OpMemberDecorateStringGOOGLE";
 
     case OpGroupNonUniformPartitionNV:       return "OpGroupNonUniformPartitionNV";
-    case OpReportIntersectionNV:             return "OpReportIntersectionNV";
-    case OpIgnoreIntersectionNV:             return "OpIgnoreIntersectionNV";
-    case OpTerminateRayNV:                   return "OpTerminateRayNV";
-    case OpTraceNV:                          return "OpTraceNV";
-    case OpTypeAccelerationStructureNV:      return "OpTypeAccelerationStructureNV";
-    case OpExecuteCallableNV:                return "OpExecuteCallableNV";
+    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 OpWritePackedPrimitiveIndices4x8NV: return "OpWritePackedPrimitiveIndices4x8NV";
 
+    case OpTypeRayQueryProvisionalKHR:                                        return "OpTypeRayQueryProvisionalKHR";
+    case OpRayQueryInitializeKHR:                                             return "OpRayQueryInitializeKHR";
+    case OpRayQueryTerminateKHR:                                              return "OpRayQueryTerminateKHR";
+    case OpRayQueryGenerateIntersectionKHR:                                   return "OpRayQueryGenerateIntersectionKHR";
+    case OpRayQueryConfirmIntersectionKHR:                                    return "OpRayQueryConfirmIntersectionKHR";
+    case OpRayQueryProceedKHR:                                                return "OpRayQueryProceedKHR";
+    case OpRayQueryGetIntersectionTypeKHR:                                    return "OpRayQueryGetIntersectionTypeKHR";
+    case OpRayQueryGetRayTMinKHR:                                             return "OpRayQueryGetRayTMinKHR";
+    case OpRayQueryGetRayFlagsKHR:                                            return "OpRayQueryGetRayFlagsKHR";
+    case OpRayQueryGetIntersectionTKHR:                                       return "OpRayQueryGetIntersectionTKHR";
+    case OpRayQueryGetIntersectionInstanceCustomIndexKHR:                     return "OpRayQueryGetIntersectionInstanceCustomIndexKHR";
+    case OpRayQueryGetIntersectionInstanceIdKHR:                              return "OpRayQueryGetIntersectionInstanceIdKHR";
+    case OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR:  return "OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR";
+    case OpRayQueryGetIntersectionGeometryIndexKHR:                           return "OpRayQueryGetIntersectionGeometryIndexKHR";
+    case OpRayQueryGetIntersectionPrimitiveIndexKHR:                          return "OpRayQueryGetIntersectionPrimitiveIndexKHR";
+    case OpRayQueryGetIntersectionBarycentricsKHR:                            return "OpRayQueryGetIntersectionBarycentricsKHR";
+    case OpRayQueryGetIntersectionFrontFaceKHR:                               return "OpRayQueryGetIntersectionFrontFaceKHR";
+    case OpRayQueryGetIntersectionCandidateAABBOpaqueKHR:                     return "OpRayQueryGetIntersectionCandidateAABBOpaqueKHR";
+    case OpRayQueryGetIntersectionObjectRayDirectionKHR:                      return "OpRayQueryGetIntersectionObjectRayDirectionKHR";
+    case OpRayQueryGetIntersectionObjectRayOriginKHR:                         return "OpRayQueryGetIntersectionObjectRayOriginKHR";
+    case OpRayQueryGetWorldRayDirectionKHR:                                   return "OpRayQueryGetWorldRayDirectionKHR";
+    case OpRayQueryGetWorldRayOriginKHR:                                      return "OpRayQueryGetWorldRayOriginKHR";
+    case OpRayQueryGetIntersectionObjectToWorldKHR:                           return "OpRayQueryGetIntersectionObjectToWorldKHR";
+    case OpRayQueryGetIntersectionWorldToObjectKHR:                           return "OpRayQueryGetIntersectionWorldToObjectKHR";
+
     case OpTypeCooperativeMatrixNV:         return "OpTypeCooperativeMatrixNV";
     case OpCooperativeMatrixLoadNV:         return "OpCooperativeMatrixLoadNV";
     case OpCooperativeMatrixStoreNV:        return "OpCooperativeMatrixStoreNV";
@@ -1388,6 +1443,7 @@ void Parameterize()
     InstructionDesc[OpMemoryModel].setResultAndType(false, false);
     InstructionDesc[OpEntryPoint].setResultAndType(false, false);
     InstructionDesc[OpExecutionMode].setResultAndType(false, false);
+    InstructionDesc[OpExecutionModeId].setResultAndType(false, false);
     InstructionDesc[OpTypeVoid].setResultAndType(true, false);
     InstructionDesc[OpTypeBool].setResultAndType(true, false);
     InstructionDesc[OpTypeInt].setResultAndType(true, false);
@@ -1574,6 +1630,10 @@ void Parameterize()
     InstructionDesc[OpExecutionMode].operands.push(OperandExecutionMode, "'Mode'");
     InstructionDesc[OpExecutionMode].operands.push(OperandOptionalLiteral, "See <<Execution_Mode,Execution Mode>>");
 
+    InstructionDesc[OpExecutionModeId].operands.push(OperandId, "'Entry Point'");
+    InstructionDesc[OpExecutionModeId].operands.push(OperandExecutionMode, "'Mode'");
+    InstructionDesc[OpExecutionModeId].operands.push(OperandVariableIds, "See <<Execution_Mode,Execution Mode>>");
+
     InstructionDesc[OpTypeInt].operands.push(OperandLiteralNumber, "'Width'");
     InstructionDesc[OpTypeInt].operands.push(OperandLiteralNumber, "'Signedness'");
 
@@ -1667,7 +1727,7 @@ void Parameterize()
 
     InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandId, "'Target'");
     InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandDecoration, "");
-    InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandLiteralString, "'Literal String'");
+    InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandVariableLiteralStrings, "'Literal Strings'");
 
     InstructionDesc[OpMemberDecorate].operands.push(OperandId, "'Structure Type'");
     InstructionDesc[OpMemberDecorate].operands.push(OperandLiteralNumber, "'Member'");
@@ -1677,7 +1737,7 @@ void Parameterize()
     InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandId, "'Structure Type'");
     InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandLiteralNumber, "'Member'");
     InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandDecoration, "");
-    InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandLiteralString, "'Literal String'");
+    InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandVariableLiteralStrings, "'Literal Strings'");
 
     InstructionDesc[OpGroupDecorate].operands.push(OperandId, "'Decoration Group'");
     InstructionDesc[OpGroupDecorate].operands.push(OperandVariableIds, "'Targets'");
@@ -2230,6 +2290,11 @@ void Parameterize()
     InstructionDesc[OpAtomicIAdd].operands.push(OperandMemorySemantics, "'Semantics'");
     InstructionDesc[OpAtomicIAdd].operands.push(OperandId, "'Value'");
 
+    InstructionDesc[OpAtomicFAddEXT].operands.push(OperandId, "'Pointer'");
+    InstructionDesc[OpAtomicFAddEXT].operands.push(OperandScope, "'Scope'");
+    InstructionDesc[OpAtomicFAddEXT].operands.push(OperandMemorySemantics, "'Semantics'");
+    InstructionDesc[OpAtomicFAddEXT].operands.push(OperandId, "'Value'");
+
     InstructionDesc[OpAtomicISub].operands.push(OperandId, "'Pointer'");
     InstructionDesc[OpAtomicISub].operands.push(OperandScope, "'Scope'");
     InstructionDesc[OpAtomicISub].operands.push(OperandMemorySemantics, "'Semantics'");
@@ -2694,31 +2759,125 @@ void Parameterize()
 
     InstructionDesc[OpGroupNonUniformPartitionNV].operands.push(OperandId, "X");
 
-    InstructionDesc[OpTypeAccelerationStructureNV].setResultAndType(true, false);
+    InstructionDesc[OpTypeAccelerationStructureKHR].setResultAndType(true, false);
 
-    InstructionDesc[OpTraceNV].operands.push(OperandId, "'NV 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, "'NV Acceleration Structure'");
+    InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Ray Flags'");
+    InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Cull Mask'");
+    InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'SBT Record Offset'");
+    InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'SBT Record Stride'");
+    InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Miss Index'");
+    InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Ray Origin'");
+    InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'TMin'");
+    InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Ray Direction'");
+    InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'TMax'");
+    InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Payload'");
+    InstructionDesc[OpTraceRayKHR].setResultAndType(false, false);
 
-    InstructionDesc[OpReportIntersectionNV].operands.push(OperandId, "'Hit Parameter'");
-    InstructionDesc[OpReportIntersectionNV].operands.push(OperandId, "'Hit Kind'");
+    InstructionDesc[OpReportIntersectionKHR].operands.push(OperandId, "'Hit Parameter'");
+    InstructionDesc[OpReportIntersectionKHR].operands.push(OperandId, "'Hit Kind'");
 
-    InstructionDesc[OpIgnoreIntersectionNV].setResultAndType(false, false);
+    InstructionDesc[OpIgnoreIntersectionKHR].setResultAndType(false, false);
 
-    InstructionDesc[OpTerminateRayNV].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, "CallableData ID");
+    InstructionDesc[OpExecuteCallableKHR].setResultAndType(false, false);
+
+    // Ray Query
+    InstructionDesc[OpTypeAccelerationStructureKHR].setResultAndType(true, false);
+    InstructionDesc[OpTypeRayQueryProvisionalKHR].setResultAndType(true, false);
+
+    InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'AccelerationS'");
+    InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'RayFlags'");
+    InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'CullMask'");
+    InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Origin'");
+    InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Tmin'");
+    InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Direction'");
+    InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Tmax'");
+    InstructionDesc[OpRayQueryInitializeKHR].setResultAndType(false, false);
+
+    InstructionDesc[OpRayQueryTerminateKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryTerminateKHR].setResultAndType(false, false);
+
+    InstructionDesc[OpRayQueryGenerateIntersectionKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGenerateIntersectionKHR].operands.push(OperandId, "'THit'");
+    InstructionDesc[OpRayQueryGenerateIntersectionKHR].setResultAndType(false, false);
+
+    InstructionDesc[OpRayQueryConfirmIntersectionKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryConfirmIntersectionKHR].setResultAndType(false, false);
+
+    InstructionDesc[OpRayQueryProceedKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryProceedKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionTypeKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionTypeKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionTypeKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetRayTMinKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetRayTMinKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetRayFlagsKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetRayFlagsKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionTKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionTKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionTKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionInstanceCustomIndexKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionInstanceCustomIndexKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionInstanceCustomIndexKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionInstanceIdKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionInstanceIdKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionInstanceIdKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionGeometryIndexKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionGeometryIndexKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionGeometryIndexKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionPrimitiveIndexKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionPrimitiveIndexKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionPrimitiveIndexKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionBarycentricsKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionBarycentricsKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionBarycentricsKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionFrontFaceKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionFrontFaceKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionFrontFaceKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionCandidateAABBOpaqueKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionCandidateAABBOpaqueKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionObjectRayDirectionKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionObjectRayDirectionKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionObjectRayDirectionKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionObjectRayOriginKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionObjectRayOriginKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionObjectRayOriginKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetWorldRayDirectionKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetWorldRayDirectionKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetWorldRayOriginKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetWorldRayOriginKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionObjectToWorldKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionObjectToWorldKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionObjectToWorldKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionWorldToObjectKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionWorldToObjectKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionWorldToObjectKHR].setResultAndType(true, true);
 
     InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Sampled Image'");
     InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Coordinate'");

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

@@ -125,6 +125,7 @@ enum OperandClass {
     OperandVariableLiteralId,
     OperandLiteralNumber,
     OperandLiteralString,
+    OperandVariableLiteralStrings,
     OperandSource,
     OperandExecutionModel,
     OperandAddressing,

+ 2 - 2
src/libraries/glslang/SPIRV/hex_float.h

@@ -784,8 +784,8 @@ inline std::istream& ParseNormalFloat(std::istream& is, bool negate_value,
   if (val.isInfinity()) {
     // Fail the parse.  Emulate standard behaviour by setting the value to
     // the closest normal value, and set the fail bit on the stream.
-    value.set_value((value.isNegative() | negate_value) ? T::lowest()
-                                                        : T::max());
+    value.set_value((value.isNegative() || negate_value) ? T::lowest()
+                                                         : T::max());
     is.setstate(std::ios_base::failbit);
   }
   return is;

+ 195 - 5
src/libraries/glslang/SPIRV/spirv.hpp

@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2019 The Khronos Group Inc.
+// Copyright (c) 2014-2020 The Khronos Group Inc.
 // 
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and/or associated documentation files (the "Materials"),
@@ -49,12 +49,12 @@ namespace spv {
 
 typedef unsigned int Id;
 
-#define SPV_VERSION 0x10400
-#define SPV_REVISION 1
+#define SPV_VERSION 0x10500
+#define SPV_REVISION 3
 
 static const unsigned int MagicNumber = 0x07230203;
-static const unsigned int Version = 0x00010400;
-static const unsigned int Revision = 1;
+static const unsigned int Version = 0x00010500;
+static const unsigned int Revision = 3;
 static const unsigned int OpCodeMask = 0xffff;
 static const unsigned int WordCountShift = 16;
 
@@ -78,11 +78,17 @@ enum ExecutionModel {
     ExecutionModelKernel = 6,
     ExecutionModelTaskNV = 5267,
     ExecutionModelMeshNV = 5268,
+    ExecutionModelRayGenerationKHR = 5313,
     ExecutionModelRayGenerationNV = 5313,
+    ExecutionModelIntersectionKHR = 5314,
     ExecutionModelIntersectionNV = 5314,
+    ExecutionModelAnyHitKHR = 5315,
     ExecutionModelAnyHitNV = 5315,
+    ExecutionModelClosestHitKHR = 5316,
     ExecutionModelClosestHitNV = 5316,
+    ExecutionModelMissKHR = 5317,
     ExecutionModelMissNV = 5317,
+    ExecutionModelCallableKHR = 5318,
     ExecutionModelCallableNV = 5318,
     ExecutionModelMax = 0x7fffffff,
 };
@@ -162,6 +168,10 @@ enum ExecutionMode {
     ExecutionModeSampleInterlockUnorderedEXT = 5369,
     ExecutionModeShadingRateInterlockOrderedEXT = 5370,
     ExecutionModeShadingRateInterlockUnorderedEXT = 5371,
+    ExecutionModeMaxWorkgroupSizeINTEL = 5893,
+    ExecutionModeMaxWorkDimINTEL = 5894,
+    ExecutionModeNoGlobalOffsetINTEL = 5895,
+    ExecutionModeNumSIMDWorkitemsINTEL = 5896,
     ExecutionModeMax = 0x7fffffff,
 };
 
@@ -179,14 +189,21 @@ enum StorageClass {
     StorageClassAtomicCounter = 10,
     StorageClassImage = 11,
     StorageClassStorageBuffer = 12,
+    StorageClassCallableDataKHR = 5328,
     StorageClassCallableDataNV = 5328,
+    StorageClassIncomingCallableDataKHR = 5329,
     StorageClassIncomingCallableDataNV = 5329,
+    StorageClassRayPayloadKHR = 5338,
     StorageClassRayPayloadNV = 5338,
+    StorageClassHitAttributeKHR = 5339,
     StorageClassHitAttributeNV = 5339,
+    StorageClassIncomingRayPayloadKHR = 5342,
     StorageClassIncomingRayPayloadNV = 5342,
+    StorageClassShaderRecordBufferKHR = 5343,
     StorageClassShaderRecordBufferNV = 5343,
     StorageClassPhysicalStorageBuffer = 5349,
     StorageClassPhysicalStorageBufferEXT = 5349,
+    StorageClassCodeSectionINTEL = 5605,
     StorageClassMax = 0x7fffffff,
 };
 
@@ -465,11 +482,24 @@ enum Decoration {
     DecorationRestrictPointerEXT = 5355,
     DecorationAliasedPointer = 5356,
     DecorationAliasedPointerEXT = 5356,
+    DecorationReferencedIndirectlyINTEL = 5602,
     DecorationCounterBuffer = 5634,
     DecorationHlslCounterBufferGOOGLE = 5634,
     DecorationHlslSemanticGOOGLE = 5635,
     DecorationUserSemantic = 5635,
     DecorationUserTypeGOOGLE = 5636,
+    DecorationRegisterINTEL = 5825,
+    DecorationMemoryINTEL = 5826,
+    DecorationNumbanksINTEL = 5827,
+    DecorationBankwidthINTEL = 5828,
+    DecorationMaxPrivateCopiesINTEL = 5829,
+    DecorationSinglepumpINTEL = 5830,
+    DecorationDoublepumpINTEL = 5831,
+    DecorationMaxReplicatesINTEL = 5832,
+    DecorationSimpleDualPortINTEL = 5833,
+    DecorationMergeINTEL = 5834,
+    DecorationBankBitsINTEL = 5835,
+    DecorationForcePow2DepthINTEL = 5836,
     DecorationMax = 0x7fffffff,
 };
 
@@ -558,20 +588,35 @@ enum BuiltIn {
     BuiltInFragmentSizeNV = 5292,
     BuiltInFragInvocationCountEXT = 5293,
     BuiltInInvocationsPerPixelNV = 5293,
+    BuiltInLaunchIdKHR = 5319,
     BuiltInLaunchIdNV = 5319,
+    BuiltInLaunchSizeKHR = 5320,
     BuiltInLaunchSizeNV = 5320,
+    BuiltInWorldRayOriginKHR = 5321,
     BuiltInWorldRayOriginNV = 5321,
+    BuiltInWorldRayDirectionKHR = 5322,
     BuiltInWorldRayDirectionNV = 5322,
+    BuiltInObjectRayOriginKHR = 5323,
     BuiltInObjectRayOriginNV = 5323,
+    BuiltInObjectRayDirectionKHR = 5324,
     BuiltInObjectRayDirectionNV = 5324,
+    BuiltInRayTminKHR = 5325,
     BuiltInRayTminNV = 5325,
+    BuiltInRayTmaxKHR = 5326,
     BuiltInRayTmaxNV = 5326,
+    BuiltInInstanceCustomIndexKHR = 5327,
     BuiltInInstanceCustomIndexNV = 5327,
+    BuiltInObjectToWorldKHR = 5330,
     BuiltInObjectToWorldNV = 5330,
+    BuiltInWorldToObjectKHR = 5331,
     BuiltInWorldToObjectNV = 5331,
+    BuiltInHitTKHR = 5332,
     BuiltInHitTNV = 5332,
+    BuiltInHitKindKHR = 5333,
     BuiltInHitKindNV = 5333,
+    BuiltInIncomingRayFlagsKHR = 5351,
     BuiltInIncomingRayFlagsNV = 5351,
+    BuiltInRayGeometryIndexKHR = 5352,
     BuiltInWarpsPerSMNV = 5374,
     BuiltInSMCountNV = 5375,
     BuiltInWarpIDNV = 5376,
@@ -601,6 +646,13 @@ enum LoopControlShift {
     LoopControlIterationMultipleShift = 6,
     LoopControlPeelCountShift = 7,
     LoopControlPartialCountShift = 8,
+    LoopControlInitiationIntervalINTELShift = 16,
+    LoopControlMaxConcurrencyINTELShift = 17,
+    LoopControlDependencyArrayINTELShift = 18,
+    LoopControlPipelineEnableINTELShift = 19,
+    LoopControlLoopCoalesceINTELShift = 20,
+    LoopControlMaxInterleavingINTELShift = 21,
+    LoopControlSpeculatedIterationsINTELShift = 22,
     LoopControlMax = 0x7fffffff,
 };
 
@@ -615,6 +667,13 @@ enum LoopControlMask {
     LoopControlIterationMultipleMask = 0x00000040,
     LoopControlPeelCountMask = 0x00000080,
     LoopControlPartialCountMask = 0x00000100,
+    LoopControlInitiationIntervalINTELMask = 0x00010000,
+    LoopControlMaxConcurrencyINTELMask = 0x00020000,
+    LoopControlDependencyArrayINTELMask = 0x00040000,
+    LoopControlPipelineEnableINTELMask = 0x00080000,
+    LoopControlLoopCoalesceINTELMask = 0x00100000,
+    LoopControlMaxInterleavingINTELMask = 0x00200000,
+    LoopControlSpeculatedIterationsINTELMask = 0x00400000,
 };
 
 enum FunctionControlShift {
@@ -709,6 +768,7 @@ enum Scope {
     ScopeInvocation = 4,
     ScopeQueueFamily = 5,
     ScopeQueueFamilyKHR = 5,
+    ScopeShaderCallKHR = 6,
     ScopeMax = 0x7fffffff,
 };
 
@@ -833,6 +893,8 @@ enum Capability {
     CapabilitySignedZeroInfNanPreserve = 4466,
     CapabilityRoundingModeRTE = 4467,
     CapabilityRoundingModeRTZ = 4468,
+    CapabilityRayQueryProvisionalKHR = 4471,
+    CapabilityRayTraversalPrimitiveCullingProvisionalKHR = 4478,
     CapabilityFloat16ImageAMD = 5008,
     CapabilityImageGatherBiasLodAMD = 5009,
     CapabilityFragmentMaskAMD = 5010,
@@ -886,6 +948,7 @@ enum Capability {
     CapabilityPhysicalStorageBufferAddresses = 5347,
     CapabilityPhysicalStorageBufferAddressesEXT = 5347,
     CapabilityComputeDerivativeGroupLinearNV = 5350,
+    CapabilityRayTracingProvisionalKHR = 5353,
     CapabilityCooperativeMatrixNV = 5357,
     CapabilityFragmentShaderSampleInterlockEXT = 5363,
     CapabilityFragmentShaderShadingRateInterlockEXT = 5372,
@@ -897,12 +960,70 @@ enum Capability {
     CapabilitySubgroupImageBlockIOINTEL = 5570,
     CapabilitySubgroupImageMediaBlockIOINTEL = 5579,
     CapabilityIntegerFunctions2INTEL = 5584,
+    CapabilityFunctionPointersINTEL = 5603,
+    CapabilityIndirectReferencesINTEL = 5604,
     CapabilitySubgroupAvcMotionEstimationINTEL = 5696,
     CapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697,
     CapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698,
+    CapabilityFPGAMemoryAttributesINTEL = 5824,
+    CapabilityUnstructuredLoopControlsINTEL = 5886,
+    CapabilityFPGALoopControlsINTEL = 5888,
+    CapabilityKernelAttributesINTEL = 5892,
+    CapabilityFPGAKernelAttributesINTEL = 5897,
+    CapabilityBlockingPipesINTEL = 5945,
+    CapabilityFPGARegINTEL = 5948,
+    CapabilityAtomicFloat32AddEXT = 6033,
+    CapabilityAtomicFloat64AddEXT = 6034,
     CapabilityMax = 0x7fffffff,
 };
 
+enum RayFlagsShift {
+    RayFlagsOpaqueKHRShift = 0,
+    RayFlagsNoOpaqueKHRShift = 1,
+    RayFlagsTerminateOnFirstHitKHRShift = 2,
+    RayFlagsSkipClosestHitShaderKHRShift = 3,
+    RayFlagsCullBackFacingTrianglesKHRShift = 4,
+    RayFlagsCullFrontFacingTrianglesKHRShift = 5,
+    RayFlagsCullOpaqueKHRShift = 6,
+    RayFlagsCullNoOpaqueKHRShift = 7,
+    RayFlagsSkipTrianglesKHRShift = 8,
+    RayFlagsSkipAABBsKHRShift = 9,
+    RayFlagsMax = 0x7fffffff,
+};
+
+enum RayFlagsMask {
+    RayFlagsMaskNone = 0,
+    RayFlagsOpaqueKHRMask = 0x00000001,
+    RayFlagsNoOpaqueKHRMask = 0x00000002,
+    RayFlagsTerminateOnFirstHitKHRMask = 0x00000004,
+    RayFlagsSkipClosestHitShaderKHRMask = 0x00000008,
+    RayFlagsCullBackFacingTrianglesKHRMask = 0x00000010,
+    RayFlagsCullFrontFacingTrianglesKHRMask = 0x00000020,
+    RayFlagsCullOpaqueKHRMask = 0x00000040,
+    RayFlagsCullNoOpaqueKHRMask = 0x00000080,
+    RayFlagsSkipTrianglesKHRMask = 0x00000100,
+    RayFlagsSkipAABBsKHRMask = 0x00000200,
+};
+
+enum RayQueryIntersection {
+    RayQueryIntersectionRayQueryCandidateIntersectionKHR = 0,
+    RayQueryIntersectionRayQueryCommittedIntersectionKHR = 1,
+    RayQueryIntersectionMax = 0x7fffffff,
+};
+
+enum RayQueryCommittedIntersectionType {
+    RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionNoneKHR = 0,
+    RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionTriangleKHR = 1,
+    RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionGeneratedKHR = 2,
+    RayQueryCommittedIntersectionTypeMax = 0x7fffffff,
+};
+
+enum RayQueryCandidateIntersectionType {
+    RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionTriangleKHR = 0,
+    RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionAABBKHR = 1,
+    RayQueryCandidateIntersectionTypeMax = 0x7fffffff,
+};
+
 enum Op {
     OpNop = 0,
     OpUndef = 1,
@@ -1254,6 +1375,13 @@ enum Op {
     OpSubgroupAnyKHR = 4429,
     OpSubgroupAllEqualKHR = 4430,
     OpSubgroupReadInvocationKHR = 4432,
+    OpTypeRayQueryProvisionalKHR = 4472,
+    OpRayQueryInitializeKHR = 4473,
+    OpRayQueryTerminateKHR = 4474,
+    OpRayQueryGenerateIntersectionKHR = 4475,
+    OpRayQueryConfirmIntersectionKHR = 4476,
+    OpRayQueryProceedKHR = 4477,
+    OpRayQueryGetIntersectionTypeKHR = 4479,
     OpGroupIAddNonUniformAMD = 5000,
     OpGroupFAddNonUniformAMD = 5001,
     OpGroupFMinNonUniformAMD = 5002,
@@ -1268,11 +1396,17 @@ enum Op {
     OpImageSampleFootprintNV = 5283,
     OpGroupNonUniformPartitionNV = 5296,
     OpWritePackedPrimitiveIndices4x8NV = 5299,
+    OpReportIntersectionKHR = 5334,
     OpReportIntersectionNV = 5334,
+    OpIgnoreIntersectionKHR = 5335,
     OpIgnoreIntersectionNV = 5335,
+    OpTerminateRayKHR = 5336,
     OpTerminateRayNV = 5336,
     OpTraceNV = 5337,
+    OpTraceRayKHR = 5337,
+    OpTypeAccelerationStructureKHR = 5341,
     OpTypeAccelerationStructureNV = 5341,
+    OpExecuteCallableKHR = 5344,
     OpExecuteCallableNV = 5344,
     OpTypeCooperativeMatrixNV = 5358,
     OpCooperativeMatrixLoadNV = 5359,
@@ -1307,6 +1441,8 @@ enum Op {
     OpUSubSatINTEL = 5596,
     OpIMul32x16INTEL = 5597,
     OpUMul32x16INTEL = 5598,
+    OpFunctionPointerINTEL = 5600,
+    OpFunctionPointerCallINTEL = 5601,
     OpDecorateString = 5632,
     OpDecorateStringGOOGLE = 5632,
     OpMemberDecorateString = 5633,
@@ -1429,6 +1565,28 @@ enum Op {
     OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814,
     OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815,
     OpSubgroupAvcSicGetInterRawSadsINTEL = 5816,
+    OpLoopControlINTEL = 5887,
+    OpReadPipeBlockingINTEL = 5946,
+    OpWritePipeBlockingINTEL = 5947,
+    OpFPGARegINTEL = 5949,
+    OpRayQueryGetRayTMinKHR = 6016,
+    OpRayQueryGetRayFlagsKHR = 6017,
+    OpRayQueryGetIntersectionTKHR = 6018,
+    OpRayQueryGetIntersectionInstanceCustomIndexKHR = 6019,
+    OpRayQueryGetIntersectionInstanceIdKHR = 6020,
+    OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR = 6021,
+    OpRayQueryGetIntersectionGeometryIndexKHR = 6022,
+    OpRayQueryGetIntersectionPrimitiveIndexKHR = 6023,
+    OpRayQueryGetIntersectionBarycentricsKHR = 6024,
+    OpRayQueryGetIntersectionFrontFaceKHR = 6025,
+    OpRayQueryGetIntersectionCandidateAABBOpaqueKHR = 6026,
+    OpRayQueryGetIntersectionObjectRayDirectionKHR = 6027,
+    OpRayQueryGetIntersectionObjectRayOriginKHR = 6028,
+    OpRayQueryGetWorldRayDirectionKHR = 6029,
+    OpRayQueryGetWorldRayOriginKHR = 6030,
+    OpRayQueryGetIntersectionObjectToWorldKHR = 6031,
+    OpRayQueryGetIntersectionWorldToObjectKHR = 6032,
+    OpAtomicFAddEXT = 6035,
     OpMax = 0x7fffffff,
 };
 
@@ -1787,6 +1945,13 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
     case OpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break;
     case OpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break;
     case OpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break;
+    case OpTypeRayQueryProvisionalKHR: *hasResult = true; *hasResultType = false; break;
+    case OpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break;
+    case OpRayQueryTerminateKHR: *hasResult = false; *hasResultType = false; break;
+    case OpRayQueryGenerateIntersectionKHR: *hasResult = false; *hasResultType = false; break;
+    case OpRayQueryConfirmIntersectionKHR: *hasResult = false; *hasResultType = false; break;
+    case OpRayQueryProceedKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionTypeKHR: *hasResult = true; *hasResultType = true; break;
     case OpGroupIAddNonUniformAMD: *hasResult = true; *hasResultType = true; break;
     case OpGroupFAddNonUniformAMD: *hasResult = true; *hasResultType = true; break;
     case OpGroupFMinNonUniformAMD: *hasResult = true; *hasResultType = true; break;
@@ -1840,6 +2005,8 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
     case OpUSubSatINTEL: *hasResult = true; *hasResultType = true; break;
     case OpIMul32x16INTEL: *hasResult = true; *hasResultType = true; break;
     case OpUMul32x16INTEL: *hasResult = true; *hasResultType = true; break;
+    case OpFunctionPointerINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpFunctionPointerCallINTEL: *hasResult = true; *hasResultType = true; break;
     case OpDecorateString: *hasResult = false; *hasResultType = false; break;
     case OpMemberDecorateString: *hasResult = false; *hasResultType = false; break;
     case OpVmeImageINTEL: *hasResult = true; *hasResultType = true; break;
@@ -1960,6 +2127,28 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
     case OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: *hasResult = true; *hasResultType = true; break;
     case OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: *hasResult = true; *hasResultType = true; break;
     case OpSubgroupAvcSicGetInterRawSadsINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpLoopControlINTEL: *hasResult = false; *hasResultType = false; break;
+    case OpReadPipeBlockingINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpWritePipeBlockingINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpFPGARegINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetRayTMinKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetRayFlagsKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionTKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionInstanceCustomIndexKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionInstanceIdKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionGeometryIndexKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionPrimitiveIndexKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionBarycentricsKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionFrontFaceKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionCandidateAABBOpaqueKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionObjectRayDirectionKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionObjectRayOriginKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetWorldRayDirectionKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetWorldRayOriginKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionObjectToWorldKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionWorldToObjectKHR: *hasResult = true; *hasResultType = true; break;
+    case OpAtomicFAddEXT: *hasResult = true; *hasResultType = true; break;
     }
 }
 #endif /* SPV_ENABLE_UTILITY_CODE */
@@ -1974,6 +2163,7 @@ inline FunctionControlMask operator|(FunctionControlMask a, FunctionControlMask
 inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(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 RayFlagsMask operator|(RayFlagsMask a, RayFlagsMask b) { return RayFlagsMask(unsigned(a) | unsigned(b)); }
 
 }  // end namespace spv
 

+ 24 - 3
src/libraries/glslang/SPIRV/spvIR.h

@@ -55,6 +55,7 @@
 #include <iostream>
 #include <memory>
 #include <vector>
+#include <set>
 
 namespace spv {
 
@@ -235,8 +236,7 @@ public:
         assert(instructions.size() > 0);
         instructions.resize(1);
         successors.clear();
-        Instruction* unreachable = new Instruction(OpUnreachable);
-        addInstruction(std::unique_ptr<Instruction>(unreachable));
+        addInstruction(std::unique_ptr<Instruction>(new Instruction(OpUnreachable)));
     }
     // Change this block into a canonical dead continue target branching to the
     // given header ID.  Delete instructions as necessary.  A canonical dead continue
@@ -352,10 +352,28 @@ public:
     const std::vector<Block*>& getBlocks() const { return blocks; }
     void addLocalVariable(std::unique_ptr<Instruction> inst);
     Id getReturnType() const { return functionInstruction.getTypeId(); }
+    void setReturnPrecision(Decoration precision)
+    {
+        if (precision == DecorationRelaxedPrecision)
+            reducedPrecisionReturn = true;
+    }
+    Decoration getReturnPrecision() const
+        { return reducedPrecisionReturn ? DecorationRelaxedPrecision : NoPrecision; }
 
     void setImplicitThis() { implicitThis = true; }
     bool hasImplicitThis() const { return implicitThis; }
 
+    void addParamPrecision(unsigned param, Decoration precision)
+    {
+        if (precision == DecorationRelaxedPrecision)
+            reducedPrecisionParams.insert(param);
+    }
+    Decoration getParamPrecision(unsigned param) const
+    {
+        return reducedPrecisionParams.find(param) != reducedPrecisionParams.end() ?
+            DecorationRelaxedPrecision : NoPrecision;
+    }
+
     void dump(std::vector<unsigned int>& out) const
     {
         // OpFunction
@@ -380,6 +398,8 @@ protected:
     std::vector<Instruction*> parameterInstructions;
     std::vector<Block*> blocks;
     bool implicitThis;  // true if this is a member function expecting to be passed a 'this' as the first argument
+    bool reducedPrecisionReturn;
+    std::set<int> reducedPrecisionParams;  // list of parameter indexes that need a relaxed precision arg
 };
 
 //
@@ -440,7 +460,8 @@ protected:
 // - the OpFunction instruction
 // - all the OpFunctionParameter instructions
 __inline Function::Function(Id id, Id resultType, Id functionType, Id firstParamId, Module& parent)
-    : parent(parent), functionInstruction(id, resultType, OpFunction), implicitThis(false)
+    : parent(parent), functionInstruction(id, resultType, OpFunction), implicitThis(false),
+      reducedPrecisionReturn(false)
 {
     // OpFunction
     functionInstruction.addImmediateOperand(FunctionControlMaskNone);

+ 51 - 39
src/libraries/glslang/glslang/Include/BaseTypes.h

@@ -2,6 +2,7 @@
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2012-2013 LunarG, Inc.
 // Copyright (C) 2017 ARM Limited.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 // All rights reserved.
 //
@@ -61,8 +62,9 @@ enum TBasicType {
     EbtSampler,
     EbtStruct,
     EbtBlock,
-    EbtAccStructNV,
+    EbtAccStruct,
     EbtReference,
+    EbtRayQuery,
 
     // HLSL types that live only temporarily.
     EbtString,
@@ -90,11 +92,11 @@ enum TStorageQualifier {
     EvqBuffer,        // read/write, shared with app
     EvqShared,        // compute shader's read/write 'shared' qualifier
 
-    EvqPayloadNV,
-    EvqPayloadInNV,
-    EvqHitAttrNV,
-    EvqCallableDataNV,
-    EvqCallableDataInNV,
+    EvqPayload,
+    EvqPayloadIn,
+    EvqHitAttr,
+    EvqCallableData,
+    EvqCallableDataIn,
 
     // parameters
     EvqIn,            // also, for 'in' in the grammar before we know if it's a pipeline input or an 'in' parameter
@@ -229,6 +231,9 @@ enum TBuiltInVariable {
     EbvFragSizeEXT,
     EbvFragInvocationCountEXT,
 
+    EbvSecondaryFragDataEXT,
+    EbvSecondaryFragColorEXT,
+
     EbvViewportMaskNV,
     EbvSecondaryPositionNV,
     EbvSecondaryViewportMaskNV,
@@ -238,20 +243,23 @@ enum TBuiltInVariable {
     EbvFragmentSizeNV,
     EbvInvocationsPerPixelNV,
     // ray tracing
-    EbvLaunchIdNV,
-    EbvLaunchSizeNV,
-    EbvInstanceCustomIndexNV,
-    EbvWorldRayOriginNV,
-    EbvWorldRayDirectionNV,
-    EbvObjectRayOriginNV,
-    EbvObjectRayDirectionNV,
-    EbvRayTminNV,
-    EbvRayTmaxNV,
-    EbvHitTNV,
-    EbvHitKindNV,
-    EbvObjectToWorldNV,
-    EbvWorldToObjectNV,
-    EbvIncomingRayFlagsNV,
+    EbvLaunchId,
+    EbvLaunchSize,
+    EbvInstanceCustomIndex,
+    EbvGeometryIndex,
+    EbvWorldRayOrigin,
+    EbvWorldRayDirection,
+    EbvObjectRayOrigin,
+    EbvObjectRayDirection,
+    EbvRayTmin,
+    EbvRayTmax,
+    EbvHitT,
+    EbvHitKind,
+    EbvObjectToWorld,
+    EbvObjectToWorld3x4,
+    EbvWorldToObject,
+    EbvWorldToObject3x4,
+    EbvIncomingRayFlags,
     // barycentrics
     EbvBaryCoordNV,
     EbvBaryCoordNoPerspNV,
@@ -328,11 +336,11 @@ __inline const char* GetStorageQualifierString(TStorageQualifier q)
     case EvqPointCoord:     return "gl_PointCoord";  break;
     case EvqFragColor:      return "fragColor";      break;
     case EvqFragDepth:      return "gl_FragDepth";   break;
-    case EvqPayloadNV:        return "rayPayloadNV";     break;
-    case EvqPayloadInNV:      return "rayPayloadInNV";   break;
-    case EvqHitAttrNV:        return "hitAttributeNV";   break;
-    case EvqCallableDataNV:   return "callableDataNV";   break;
-    case EvqCallableDataInNV: return "callableDataInNV"; break;
+    case EvqPayload:        return "rayPayloadNV";     break;
+    case EvqPayloadIn:      return "rayPayloadInNV";   break;
+    case EvqHitAttr:        return "hitAttributeNV";   break;
+    case EvqCallableData:   return "callableDataNV";   break;
+    case EvqCallableDataIn: return "callableDataInNV"; break;
     default:                return "unknown qualifier";
     }
 }
@@ -428,6 +436,9 @@ __inline const char* GetBuiltInVariableString(TBuiltInVariable v)
     case EbvFragSizeEXT:                return "FragSizeEXT";
     case EbvFragInvocationCountEXT:     return "FragInvocationCountEXT";
 
+    case EbvSecondaryFragDataEXT:       return "SecondaryFragDataEXT";
+    case EbvSecondaryFragColorEXT:      return "SecondaryFragColorEXT";
+
     case EbvViewportMaskNV:             return "ViewportMaskNV";
     case EbvSecondaryPositionNV:        return "SecondaryPositionNV";
     case EbvSecondaryViewportMaskNV:    return "SecondaryViewportMaskNV";
@@ -436,20 +447,21 @@ __inline const char* GetBuiltInVariableString(TBuiltInVariable v)
     case EbvFragFullyCoveredNV:         return "FragFullyCoveredNV";
     case EbvFragmentSizeNV:             return "FragmentSizeNV";
     case EbvInvocationsPerPixelNV:      return "InvocationsPerPixelNV";
-    case EbvLaunchIdNV:                 return "LaunchIdNV";
-    case EbvLaunchSizeNV:               return "LaunchSizeNV";
-    case EbvInstanceCustomIndexNV:      return "InstanceCustomIndexNV";
-    case EbvWorldRayOriginNV:           return "WorldRayOriginNV";
-    case EbvWorldRayDirectionNV:        return "WorldRayDirectionNV";
-    case EbvObjectRayOriginNV:          return "ObjectRayOriginNV";
-    case EbvObjectRayDirectionNV:       return "ObjectRayDirectionNV";
-    case EbvRayTminNV:                  return "ObjectRayTminNV";
-    case EbvRayTmaxNV:                  return "ObjectRayTmaxNV";
-    case EbvHitTNV:                     return "HitTNV";
-    case EbvHitKindNV:                  return "HitKindNV";
-    case EbvIncomingRayFlagsNV:         return "IncomingRayFlagsNV";
-    case EbvObjectToWorldNV:            return "ObjectToWorldNV";
-    case EbvWorldToObjectNV:            return "WorldToObjectNV";
+    case EbvLaunchId:                   return "LaunchIdNV";
+    case EbvLaunchSize:                 return "LaunchSizeNV";
+    case EbvInstanceCustomIndex:        return "InstanceCustomIndexNV";
+    case EbvGeometryIndex:              return "GeometryIndexEXT";
+    case EbvWorldRayOrigin:             return "WorldRayOriginNV";
+    case EbvWorldRayDirection:          return "WorldRayDirectionNV";
+    case EbvObjectRayOrigin:            return "ObjectRayOriginNV";
+    case EbvObjectRayDirection:         return "ObjectRayDirectionNV";
+    case EbvRayTmin:                    return "ObjectRayTminNV";
+    case EbvRayTmax:                    return "ObjectRayTmaxNV";
+    case EbvHitT:                       return "HitTNV";
+    case EbvHitKind:                    return "HitKindNV";
+    case EbvIncomingRayFlags:           return "IncomingRayFlagsNV";
+    case EbvObjectToWorld:              return "ObjectToWorldNV";
+    case EbvWorldToObject:              return "WorldToObjectNV";
 
     case EbvBaryCoordNV:                return "BaryCoordNV";
     case EbvBaryCoordNoPerspNV:         return "BaryCoordNoPerspNV";

+ 11 - 12
src/libraries/glslang/glslang/Include/Common.h

@@ -37,6 +37,17 @@
 #ifndef _COMMON_INCLUDED_
 #define _COMMON_INCLUDED_
 
+#include <algorithm>
+#include <cassert>
+#include <cstdio>
+#include <cstdlib>
+#include <list>
+#include <map>
+#include <set>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
 
 #if defined(__ANDROID__) || (defined(_MSC_VER) && _MSC_VER < 1700)
 #include <sstream>
@@ -93,18 +104,6 @@ std::string to_string(const T& val) {
     #pragma warning(disable : 4201) // nameless union
 #endif
 
-#include <set>
-#include <unordered_set>
-#include <vector>
-#include <map>
-#include <unordered_map>
-#include <list>
-#include <algorithm>
-#include <string>
-#include <cstdio>
-#include <cstdlib>
-#include <cassert>
-
 #include "PoolAlloc.h"
 
 //

+ 1 - 1
src/libraries/glslang/glslang/Include/ConstantUnion.h

@@ -921,7 +921,7 @@ public:
         else
             unionArray =  new TConstUnionVector(size);
     }
-    TConstUnionArray(const TConstUnionArray& a) : unionArray(a.unionArray) { }
+    TConstUnionArray(const TConstUnionArray& a) = default;
     TConstUnionArray(const TConstUnionArray& a, int start, int size)
     {
         unionArray = new TConstUnionVector(size);

+ 1 - 0
src/libraries/glslang/glslang/Include/ResourceLimits.h

@@ -142,6 +142,7 @@ struct TBuiltInResource {
     int maxTaskWorkGroupSizeY_NV;
     int maxTaskWorkGroupSizeZ_NV;
     int maxMeshViewCountNV;
+    int maxDualSourceDrawBuffersEXT;
 
     TLimits limits;
 };

+ 50 - 10
src/libraries/glslang/glslang/Include/Types.h

@@ -3,6 +3,7 @@
 // Copyright (C) 2012-2016 LunarG, Inc.
 // Copyright (C) 2015-2016 Google, Inc.
 // Copyright (C) 2017 ARM Limited.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 // All rights reserved.
 //
@@ -472,6 +473,18 @@ enum TInterlockOrdering {
     EioCount,
 };
 
+enum TShaderInterface
+{
+    // Includes both uniform blocks and buffer blocks
+    EsiUniform = 0,
+    EsiInput,
+    EsiOutput,
+    EsiNone,
+
+    EsiCount
+};
+
+
 class TQualifier {
 public:
     static const int layoutNotSet = -1;
@@ -532,6 +545,7 @@ public:
         queuefamilycoherent = false;
         workgroupcoherent = false;
         subgroupcoherent  = false;
+        shadercallcoherent = false;
         nonprivate = false;
         volatil      = false;
         restrict     = false;
@@ -553,6 +567,7 @@ public:
     // having a constant_id is not sufficient: expressions have no id, but are still specConstant
     bool specConstant : 1;
     bool nonUniform   : 1;
+    bool explicitOffset   : 1;
 
 #ifdef GLSLANG_WEB
     bool isWriteOnly() const { return false; }
@@ -590,6 +605,7 @@ public:
     bool queuefamilycoherent : 1;
     bool workgroupcoherent : 1;
     bool subgroupcoherent  : 1;
+    bool shadercallcoherent : 1;
     bool nonprivate   : 1;
     bool isWriteOnly() const { return writeonly; }
     bool isReadOnly() const { return readonly; }
@@ -599,11 +615,11 @@ public:
     bool isSample() const { return sample; }
     bool isMemory() const
     {
-        return subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly || nonprivate;
+        return shadercallcoherent || subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly || nonprivate;
     }
     bool isMemoryQualifierImageAndSSBOOnly() const
     {
-        return subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly;
+        return shadercallcoherent || subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly;
     }
     bool bufferReferenceNeedsVulkanMemoryModel() const
     {
@@ -773,7 +789,7 @@ public:
         layoutViewportRelative = false;
         // -2048 as the default value indicating layoutSecondaryViewportRelative is not set
         layoutSecondaryViewportRelativeOffset = -2048;
-        layoutShaderRecordNV = false;
+        layoutShaderRecord = false;
         layoutBufferReferenceAlign = layoutBufferReferenceAlignEnd;
         layoutFormat = ElfNone;
 #endif
@@ -812,7 +828,7 @@ public:
                hasAnyLocation() ||
                hasStream() ||
                hasFormat() ||
-               isShaderRecordNV() ||
+               isShaderRecord() ||
                isPushConstant() ||
                hasBufferReference();
     }
@@ -871,7 +887,7 @@ public:
     bool layoutPassthrough;
     bool layoutViewportRelative;
     int layoutSecondaryViewportRelativeOffset;
-    bool layoutShaderRecordNV;
+    bool layoutShaderRecord;
 #endif
 
     bool hasUniformLayout() const
@@ -942,7 +958,7 @@ public:
     bool hasAttachment() const { return false; }
     TLayoutFormat getFormat() const { return ElfNone; }
     bool isPushConstant() const { return false; }
-    bool isShaderRecordNV() const { return false; }
+    bool isShaderRecord() const { return false; }
     bool hasBufferReference() const { return false; }
     bool hasBufferReferenceAlign() const { return false; }
     bool isNonUniform() const { return false; }
@@ -993,7 +1009,7 @@ public:
     }
     TLayoutFormat getFormat() const { return layoutFormat; }
     bool isPushConstant() const { return layoutPushConstant; }
-    bool isShaderRecordNV() const { return layoutShaderRecordNV; }
+    bool isShaderRecord() const { return layoutShaderRecord; }
     bool hasBufferReference() const { return layoutBufferReference; }
     bool hasBufferReferenceAlign() const
     {
@@ -1219,6 +1235,7 @@ struct TShaderQualifiers {
     bool layoutDerivativeGroupQuads;    // true if layout derivative_group_quadsNV set
     bool layoutDerivativeGroupLinear;   // true if layout derivative_group_linearNV set
     int primitives;                     // mesh shader "max_primitives"DerivativeGroupLinear;   // true if layout derivative_group_linearNV set
+    bool layoutPrimitiveCulling;        // true if layout primitive_culling set
     TLayoutDepth getDepth() const { return layoutDepth; }
 #else
     TLayoutDepth getDepth() const { return EldNone; }
@@ -1252,6 +1269,7 @@ struct TShaderQualifiers {
         layoutOverrideCoverage      = false;
         layoutDerivativeGroupQuads  = false;
         layoutDerivativeGroupLinear = false;
+        layoutPrimitiveCulling      = false;
         primitives                  = TQualifier::layoutNotSet;
         interlockOrdering = EioNone;
 #endif
@@ -1315,6 +1333,8 @@ struct TShaderQualifiers {
             primitives = src.primitives;
         if (src.interlockOrdering != EioNone)
             interlockOrdering = src.interlockOrdering;
+        if (src.layoutPrimitiveCulling)
+            layoutPrimitiveCulling = src.layoutPrimitiveCulling;
 #endif
     }
 };
@@ -1612,6 +1632,23 @@ public:
         assert(fieldName);
         return *fieldName;
     }
+    TShaderInterface getShaderInterface() const
+    {
+        if (basicType != EbtBlock)
+            return EsiNone;
+
+        switch (qualifier.storage) {
+        default:
+            return EsiNone;
+        case EvqVaryingIn:
+            return EsiInput;
+        case EvqVaryingOut:
+            return EsiOutput;
+        case EvqUniform:
+        case EvqBuffer:
+            return EsiUniform;
+        }
+    }
 
     virtual TBasicType getBasicType() const { return basicType; }
     virtual const TSampler& getSampler() const { return sampler; }
@@ -1670,7 +1707,7 @@ public:
     }
     virtual bool isOpaque() const { return basicType == EbtSampler
 #ifndef GLSLANG_WEB
-         || basicType == EbtAtomicUint || basicType == EbtAccStructNV
+         || basicType == EbtAtomicUint || basicType == EbtAccStruct || basicType == EbtRayQuery
 #endif
         ; }
     virtual bool isBuiltIn() const { return getQualifier().builtIn != EbvNone; }
@@ -1946,7 +1983,8 @@ public:
         case EbtAtomicUint:        return "atomic_uint";
         case EbtStruct:            return "structure";
         case EbtBlock:             return "block";
-        case EbtAccStructNV:       return "accelerationStructureNV";
+        case EbtAccStruct:         return "accelerationStructureNV";
+        case EbtRayQuery:          return "rayQueryEXT";
         case EbtReference:         return "reference";
 #endif
         default:                   return "unknown type";
@@ -2056,7 +2094,7 @@ public:
                     appendStr(" layoutSecondaryViewportRelativeOffset=");
                     appendInt(qualifier.layoutSecondaryViewportRelativeOffset);
                 }
-                if (qualifier.layoutShaderRecordNV)
+                if (qualifier.layoutShaderRecord)
                     appendStr(" shaderRecordNV");
 
                 appendStr(")");
@@ -2099,6 +2137,8 @@ public:
             appendStr(" workgroupcoherent");
         if (qualifier.subgroupcoherent)
             appendStr(" subgroupcoherent");
+        if (qualifier.shadercallcoherent)
+            appendStr(" shadercallcoherent");
         if (qualifier.nonprivate)
             appendStr(" nonprivate");
         if (qualifier.volatil)

+ 38 - 5
src/libraries/glslang/glslang/Include/intermediate.h

@@ -2,6 +2,7 @@
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2012-2016 LunarG, Inc.
 // Copyright (C) 2017 ARM Limited.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 // All rights reserved.
 //
@@ -621,6 +622,8 @@ enum TOperator {
 
     EOpIsHelperInvocation,
 
+    EOpDebugPrintf,
+
     //
     // Branch
     //
@@ -908,12 +911,41 @@ enum TOperator {
     EOpAverageRounded,
     EOpMul32x16,
 
-    EOpTraceNV,
-    EOpReportIntersectionNV,
-    EOpIgnoreIntersectionNV,
-    EOpTerminateRayNV,
-    EOpExecuteCallableNV,
+    EOpTrace,
+    EOpReportIntersection,
+    EOpIgnoreIntersection,
+    EOpTerminateRay,
+    EOpExecuteCallable,
     EOpWritePackedPrimitiveIndices4x8NV,
+
+    //
+    // GL_EXT_ray_query operations
+    //
+
+    EOpRayQueryInitialize,
+    EOpRayQueryTerminate,
+    EOpRayQueryGenerateIntersection,
+    EOpRayQueryConfirmIntersection,
+    EOpRayQueryProceed,
+    EOpRayQueryGetIntersectionType,
+    EOpRayQueryGetRayTMin,
+    EOpRayQueryGetRayFlags,
+    EOpRayQueryGetIntersectionT,
+    EOpRayQueryGetIntersectionInstanceCustomIndex,
+    EOpRayQueryGetIntersectionInstanceId,
+    EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset,
+    EOpRayQueryGetIntersectionGeometryIndex,
+    EOpRayQueryGetIntersectionPrimitiveIndex,
+    EOpRayQueryGetIntersectionBarycentrics,
+    EOpRayQueryGetIntersectionFrontFace,
+    EOpRayQueryGetIntersectionCandidateAABBOpaque,
+    EOpRayQueryGetIntersectionObjectRayDirection,
+    EOpRayQueryGetIntersectionObjectRayOrigin,
+    EOpRayQueryGetWorldRayDirection,
+    EOpRayQueryGetWorldRayOrigin,
+    EOpRayQueryGetIntersectionObjectToWorld,
+    EOpRayQueryGetIntersectionWorldToObject,
+
     //
     // HLSL operations
     //
@@ -1199,6 +1231,7 @@ public:
     TOperator getFlowOp() const { return flowOp; }
     TIntermTyped* getExpression() const { return expression; }
     void setExpression(TIntermTyped* pExpression) { expression = pExpression; }
+    void updatePrecision(TPrecisionQualifier parentPrecision);
 protected:
     TOperator flowOp;
     TIntermTyped* expression;

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

@@ -2,7 +2,7 @@
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2012-2013 LunarG, Inc.
 // Copyright (C) 2017 ARM Limited.
-// Copyright (C) 2018 Google, Inc.
+// Copyright (C) 2018-2020 Google, Inc.
 //
 // All rights reserved.
 //
@@ -1012,6 +1012,7 @@ TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode)
     case EOpMin:
     case EOpMax:
     case EOpMix:
+    case EOpMod:
     case EOpClamp:
     case EOpLessThan:
     case EOpGreaterThan:
@@ -1074,6 +1075,14 @@ TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode)
             case EOpPow:
                 newConstArray[comp].setDConst(pow(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
                 break;
+            case EOpMod:
+            {
+                double arg0 = childConstUnions[0][arg0comp].getDConst();
+                double arg1 = childConstUnions[1][arg1comp].getDConst();
+                double result = arg0 - arg1 * floor(arg0 / arg1);
+                newConstArray[comp].setDConst(result);
+                break;
+            }
             case EOpMin:
                 switch(children[0]->getAsTyped()->getBasicType()) {
                 case EbtFloat16:

File diff suppressed because it is too large
+ 349 - 112
src/libraries/glslang/glslang/MachineIndependent/Initialize.cpp


+ 207 - 178
src/libraries/glslang/glslang/MachineIndependent/Intermediate.cpp

@@ -1,7 +1,7 @@
 //
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2012-2015 LunarG, Inc.
-// Copyright (C) 2015-2018 Google, Inc.
+// Copyright (C) 2015-2020 Google, Inc.
 // Copyright (C) 2017 ARM Limited.
 //
 // All rights reserved.
@@ -113,14 +113,14 @@ TIntermSymbol* TIntermediate::addSymbol(const TType& type, const TSourceLoc& loc
 //
 // Returns nullptr if the working conversions and promotions could not be found.
 //
-TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc)
+TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& loc)
 {
     // No operations work on blocks
     if (left->getType().getBasicType() == EbtBlock || right->getType().getBasicType() == EbtBlock)
         return nullptr;
 
     // Convert "reference +/- int" and "reference - reference" to integer math
-    if ((op == EOpAdd || op == EOpSub) && extensionRequested(E_GL_EXT_buffer_reference2)) {
+    if (op == EOpAdd || op == EOpSub) {
 
         // No addressing math on struct with unsized array.
         if ((left->isReference() && left->getType().getReferentType()->containsUnsizedArray()) ||
@@ -140,43 +140,44 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
             node = addBuiltInFunctionCall(loc, EOpConvUint64ToPtr, true, node, referenceType);
             return node;
         }
+    }
 
-        if (op == EOpAdd && right->isReference() && isTypeInt(left->getBasicType())) {
-            const TType& referenceType = right->getType();
-            TIntermConstantUnion* size = addConstantUnion((unsigned long long)computeBufferReferenceTypeSize(right->getType()), loc, true);
-            right = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, right, TType(EbtUint64));
+    if (op == EOpAdd && right->isReference() && isTypeInt(left->getBasicType())) {
+        const TType& referenceType = right->getType();
+        TIntermConstantUnion* size =
+            addConstantUnion((unsigned long long)computeBufferReferenceTypeSize(right->getType()), loc, true);
+        right = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, right, TType(EbtUint64));
 
-            left  = createConversion(EbtInt64, left);
-            left  = addBinaryMath(EOpMul, left, size, loc);
+        left  = createConversion(EbtInt64, left);
+        left  = addBinaryMath(EOpMul, left, size, loc);
 
-            TIntermTyped *node = addBinaryMath(op, left, right, loc);
-            node = addBuiltInFunctionCall(loc, EOpConvUint64ToPtr, true, node, referenceType);
-            return node;
-        }
+        TIntermTyped *node = addBinaryMath(op, left, right, loc);
+        node = addBuiltInFunctionCall(loc, EOpConvUint64ToPtr, true, node, referenceType);
+        return node;
+    }
 
-        if (op == EOpSub && left->isReference() && right->isReference()) {
-            TIntermConstantUnion* size = addConstantUnion((long long)computeBufferReferenceTypeSize(left->getType()), loc, true);
+    if (op == EOpSub && left->isReference() && right->isReference()) {
+        TIntermConstantUnion* size =
+            addConstantUnion((long long)computeBufferReferenceTypeSize(left->getType()), loc, true);
 
-            left = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, left, TType(EbtUint64));
-            right = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, right, TType(EbtUint64));
+        left = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, left, TType(EbtUint64));
+        right = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, right, TType(EbtUint64));
 
-            left = addBuiltInFunctionCall(loc, EOpConvUint64ToInt64, true, left, TType(EbtInt64));
-            right = addBuiltInFunctionCall(loc, EOpConvUint64ToInt64, true, right, TType(EbtInt64));
+        left = addBuiltInFunctionCall(loc, EOpConvUint64ToInt64, true, left, TType(EbtInt64));
+        right = addBuiltInFunctionCall(loc, EOpConvUint64ToInt64, true, right, TType(EbtInt64));
 
-            left = addBinaryMath(EOpSub, left, right, loc);
+        left = addBinaryMath(EOpSub, left, right, loc);
 
-            TIntermTyped *node = addBinaryMath(EOpDiv, left, size, loc);
-            return node;
-        }
-
-        // No other math operators supported on references
-        if (left->isReference() || right->isReference()) {
-            return nullptr;
-        }
+        TIntermTyped *node = addBinaryMath(EOpDiv, left, size, loc);
+        return node;
     }
 
+    // No other math operators supported on references
+    if (left->isReference() || right->isReference())
+        return nullptr;
+
     // Try converting the children's base types to compatible types.
-    auto children = addConversion(op, left, right);
+    auto children = addPairConversion(op, left, right);
     left = std::get<0>(children);
     right = std::get<1>(children);
 
@@ -226,13 +227,12 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
 //
 // Low level: add binary node (no promotions or other argument modifications)
 //
-TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc) const
+TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right,
+    const TSourceLoc& loc) const
 {
     // build the node
     TIntermBinary* node = new TIntermBinary(op);
-    if (loc.line == 0)
-        loc = left->getLoc();
-    node->setLoc(loc);
+    node->setLoc(loc.line != 0 ? loc : left->getLoc());
     node->setLeft(left);
     node->setRight(right);
 
@@ -242,7 +242,8 @@ TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TI
 //
 // like non-type form, but sets node's type.
 //
-TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc, const TType& type) const
+TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right,
+    const TSourceLoc& loc, const TType& type) const
 {
     TIntermBinary* node = addBinaryNode(op, left, right, loc);
     node->setType(type);
@@ -252,12 +253,10 @@ TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TI
 //
 // Low level: add unary node (no promotions or other argument modifications)
 //
-TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc loc) const
+TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, const TSourceLoc& loc) const
 {
     TIntermUnary* node = new TIntermUnary(op);
-    if (loc.line == 0)
-        loc = child->getLoc();
-    node->setLoc(loc);
+    node->setLoc(loc.line != 0 ? loc : child->getLoc());
     node->setOperand(child);
 
     return node;
@@ -266,7 +265,8 @@ TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, TSo
 //
 // like non-type form, but sets node's type.
 //
-TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc loc, const TType& type) const
+TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, const TSourceLoc& loc, const TType& type)
+    const
 {
     TIntermUnary* node = addUnaryNode(op, child, loc);
     node->setType(type);
@@ -281,7 +281,8 @@ TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, TSo
 // Returns nullptr if the 'right' type could not be converted to match the 'left' type,
 // or the resulting operation cannot be properly promoted.
 //
-TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc)
+TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right,
+    const TSourceLoc& loc)
 {
     // No block assignment
     if (left->getType().getBasicType() == EbtBlock || right->getType().getBasicType() == EbtBlock)
@@ -290,9 +291,7 @@ TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TInterm
     // Convert "reference += int" to "reference = reference + int". We need this because the
     // "reference + int" calculation involves a cast back to the original type, which makes it
     // not an lvalue.
-    if ((op == EOpAddAssign || op == EOpSubAssign) && left->isReference() &&
-        extensionRequested(E_GL_EXT_buffer_reference2)) {
-
+    if ((op == EOpAddAssign || op == EOpSubAssign) && left->isReference()) {
         if (!(right->getType().isScalar() && right->getType().isIntegerDomain()))
             return nullptr;
 
@@ -338,7 +337,8 @@ TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TInterm
 // Returns the added node.
 // The caller should set the type of the returned node.
 //
-TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc loc)
+TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index,
+    const TSourceLoc& loc)
 {
     // caller should set the type
     return addBinaryNode(op, base, index, loc);
@@ -349,7 +349,8 @@ TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermT
 //
 // Returns the added node.
 //
-TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, TSourceLoc loc)
+TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child,
+    const TSourceLoc& loc)
 {
     if (child == 0)
         return nullptr;
@@ -495,7 +496,8 @@ TIntermTyped* TIntermediate::addBuiltInFunctionCall(const TSourceLoc& loc, TOper
 // Returns an aggregate node, which could be the one passed in if
 // it was already an aggregate.
 //
-TIntermTyped* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TType& type, TSourceLoc loc)
+TIntermTyped* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TType& type,
+    const TSourceLoc& loc)
 {
     TIntermAggregate* aggNode;
 
@@ -510,8 +512,6 @@ TIntermTyped* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator o
             //
             aggNode = new TIntermAggregate();
             aggNode->getSequence().push_back(node);
-            if (loc.line == 0)
-                loc = node->getLoc();
         }
     } else
         aggNode = new TIntermAggregate();
@@ -520,8 +520,8 @@ TIntermTyped* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator o
     // Set the operator.
     //
     aggNode->setOperator(op);
-    if (loc.line != 0)
-        aggNode->setLoc(loc);
+    if (loc.line != 0 || node != nullptr)
+        aggNode->setLoc(loc.line != 0 ? loc : node->getLoc());
 
     aggNode->setType(type);
 
@@ -538,7 +538,7 @@ bool TIntermediate::isConversionAllowed(TOperator op, TIntermTyped* node) const
         return false;
     case EbtAtomicUint:
     case EbtSampler:
-    case EbtAccStructNV:
+    case EbtAccStruct:
         // opaque types can be passed to functions
         if (op == EOpFunction)
             break;
@@ -819,22 +819,25 @@ TIntermTyped* TIntermediate::createConversion(TBasicType convertTo, TIntermTyped
                                   node->getBasicType() == EbtFloat ||
                                   node->getBasicType() == EbtDouble);
 
-    if (! getArithemeticInt8Enabled()) {
-        if (((convertTo == EbtInt8 || convertTo == EbtUint8) && ! convertFromIntTypes) ||
-            ((node->getBasicType() == EbtInt8 || node->getBasicType() == EbtUint8) && ! convertToIntTypes))
+    if (((convertTo == EbtInt8 || convertTo == EbtUint8) && ! convertFromIntTypes) ||
+        ((node->getBasicType() == EbtInt8 || node->getBasicType() == EbtUint8) && ! convertToIntTypes)) {
+        if (! getArithemeticInt8Enabled()) {
             return nullptr;
+        }
     }
 
-    if (! getArithemeticInt16Enabled()) {
-        if (((convertTo == EbtInt16 || convertTo == EbtUint16) && ! convertFromIntTypes) ||
-            ((node->getBasicType() == EbtInt16 || node->getBasicType() == EbtUint16) && ! convertToIntTypes))
+    if (((convertTo == EbtInt16 || convertTo == EbtUint16) && ! convertFromIntTypes) ||
+        ((node->getBasicType() == EbtInt16 || node->getBasicType() == EbtUint16) && ! convertToIntTypes)) {
+        if (! getArithemeticInt16Enabled()) {
             return nullptr;
+        }
     }
 
-    if (! getArithemeticFloat16Enabled()) {
-        if ((convertTo == EbtFloat16 && ! convertFromFloatTypes) ||
-            (node->getBasicType() == EbtFloat16 && ! convertToFloatTypes))
+    if ((convertTo == EbtFloat16 && ! convertFromFloatTypes) ||
+        (node->getBasicType() == EbtFloat16 && ! convertToFloatTypes)) {
+        if (! getArithemeticFloat16Enabled()) {
             return nullptr;
+        }
     }
 #endif
 
@@ -887,7 +890,7 @@ TIntermTyped* TIntermediate::addConversion(TBasicType convertTo, TIntermTyped* n
 // Returns the converted pair of nodes.
 // Returns <nullptr, nullptr> when there is no conversion.
 std::tuple<TIntermTyped*, TIntermTyped*>
-TIntermediate::addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1)
+TIntermediate::addPairConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1)
 {
     if (!isConversionAllowed(op, node0) || !isConversionAllowed(op, node1))
         return std::make_tuple(nullptr, nullptr);
@@ -940,7 +943,7 @@ TIntermediate::addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* no
         if (node0->getBasicType() == node1->getBasicType())
             return std::make_tuple(node0, node1);
 
-        promoteTo = getConversionDestinatonType(node0->getBasicType(), node1->getBasicType(), op);
+        promoteTo = getConversionDestinationType(node0->getBasicType(), node1->getBasicType(), op);
         if (std::get<0>(promoteTo) == EbtNumTypes || std::get<1>(promoteTo) == EbtNumTypes)
             return std::make_tuple(nullptr, nullptr);
 
@@ -1040,64 +1043,30 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
     // Note: callers are responsible for other aspects of shape,
     // like vector and matrix sizes.
 
-    TBasicType promoteTo;
-    // GL_EXT_shader_16bit_storage can't do OpConstantComposite with
-    // 16-bit types, so disable promotion for those types.
-    bool canPromoteConstant = true;
-
     switch (op) {
     //
     // Explicit conversions (unary operations)
     //
     case EOpConstructBool:
-        promoteTo = EbtBool;
-        break;
     case EOpConstructFloat:
-        promoteTo = EbtFloat;
-        break;
     case EOpConstructInt:
-        promoteTo = EbtInt;
-        break;
     case EOpConstructUint:
-        promoteTo = EbtUint;
-        break;
 #ifndef GLSLANG_WEB
     case EOpConstructDouble:
-        promoteTo = EbtDouble;
-        break;
     case EOpConstructFloat16:
-        promoteTo = EbtFloat16;
-        canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
-                             extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float16);
-        break;
     case EOpConstructInt8:
-        promoteTo = EbtInt8;
-        canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
-                             extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8);
-        break;
     case EOpConstructUint8:
-        promoteTo = EbtUint8;
-        canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
-                             extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8);
-        break;
     case EOpConstructInt16:
-        promoteTo = EbtInt16;
-        canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
-                             extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16);
-        break;
     case EOpConstructUint16:
-        promoteTo = EbtUint16;
-        canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
-                             extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16);
-        break;
     case EOpConstructInt64:
-        promoteTo = EbtInt64;
-        break;
     case EOpConstructUint64:
-        promoteTo = EbtUint64;
         break;
+
 #endif
 
+    //
+    // Implicit conversions
+    //
     case EOpLogicalNot:
 
     case EOpFunctionCall:
@@ -1152,9 +1121,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
         if (type.getBasicType() == node->getType().getBasicType())
             return node;
 
-        if (canImplicitlyPromote(node->getBasicType(), type.getBasicType(), op))
-            promoteTo = type.getBasicType();
-        else
+        if (! canImplicitlyPromote(node->getBasicType(), type.getBasicType(), op))
             return nullptr;
         break;
 
@@ -1164,9 +1131,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
     case EOpLeftShiftAssign:
     case EOpRightShiftAssign:
     {
-        if (getSource() == EShSourceHlsl && node->getType().getBasicType() == EbtBool)
-            promoteTo = type.getBasicType();
-        else {
+        if (!(getSource() == EShSourceHlsl && node->getType().getBasicType() == EbtBool)) {
             if (isTypeInt(type.getBasicType()) && isTypeInt(node->getBasicType()))
                 return node;
             else
@@ -1184,13 +1149,44 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
             return nullptr;
     }
 
+    bool canPromoteConstant = true;
+#ifndef GLSLANG_WEB
+    // GL_EXT_shader_16bit_storage can't do OpConstantComposite with
+    // 16-bit types, so disable promotion for those types.
+    // Many issues with this, from JohnK:
+    //  - this isn't really right to discuss SPIR-V here
+    //  - this could easily be entirely about scalars, so is overstepping
+    //  - we should be looking at what the shader asked for, and saying whether or
+    //    not it can be done, in the parser, by calling requireExtensions(), not
+    //    changing language sementics on the fly by asking what extensions are in use
+    //  - at the time of this writing (14-Aug-2020), no test results are changed by this.
+    switch (op) {
+    case EOpConstructFloat16:
+        canPromoteConstant = numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) ||
+                             numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_float16);
+        break;
+    case EOpConstructInt8:
+    case EOpConstructUint8:
+        canPromoteConstant = numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) ||
+                             numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int8);
+        break;
+    case EOpConstructInt16:
+    case EOpConstructUint16:
+        canPromoteConstant = numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) ||
+                             numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int16);
+        break;
+    default:
+        break;
+    }
+#endif
+
     if (canPromoteConstant && node->getAsConstantUnion())
-        return promoteConstantUnion(promoteTo, node->getAsConstantUnion());
+        return promoteConstantUnion(type.getBasicType(), node->getAsConstantUnion());
 
     //
     // Add a new newNode for the conversion.
     //
-    TIntermTyped* newNode = createConversion(promoteTo, node);
+    TIntermTyped* newNode = createConversion(type.getBasicType(), node);
 
     return newNode;
 }
@@ -1620,7 +1616,7 @@ bool TIntermediate::isFPIntegralConversion(TBasicType from, TBasicType to) const
 //
 bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperator op) const
 {
-    if (isEsProfile() || version == 110)
+    if ((isEsProfile() && version < 310 ) || version == 110)
         return false;
 
     if (from == to)
@@ -1659,46 +1655,51 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
         }
     }
 
-    bool explicitTypesEnabled = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
-                                extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8) ||
-                                extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16) ||
-                                extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int32) ||
-                                extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int64) ||
-                                extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float16) ||
-                                extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float32) ||
-                                extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float64);
-
-    if (explicitTypesEnabled) {
-        // integral promotions
-        if (isIntegralPromotion(from, to)) {
-            return true;
-        }
-
-        // floating-point promotions
-        if (isFPPromotion(from, to)) {
-            return true;
-        }
-
-        // integral conversions
-        if (isIntegralConversion(from, to)) {
+    if (getSource() == EShSourceHlsl) {
+        // HLSL
+        if (from == EbtBool && (to == EbtInt || to == EbtUint || to == EbtFloat))
             return true;
-        }
-
-        // floating-point conversions
-        if (isFPConversion(from, to)) {
-           return true;
-        }
-
-        // floating-integral conversions
-        if (isFPIntegralConversion(from, to)) {
-           return true;
-        }
-
-        // hlsl supported conversions
-        if (getSource() == EShSourceHlsl) {
-            if (from == EbtBool && (to == EbtInt || to == EbtUint || to == EbtFloat))
+    } else {
+        // GLSL
+        if (isIntegralPromotion(from, to) ||
+            isFPPromotion(from, to) ||
+            isIntegralConversion(from, to) ||
+            isFPConversion(from, to) ||
+            isFPIntegralConversion(from, to)) {
+
+            if (numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) ||
+                numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int8) ||
+                numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int16) ||
+                numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int32) ||
+                numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int64) ||
+                numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_float16) ||
+                numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_float32) ||
+                numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_float64)) {
                 return true;
+            }
         }
+    }
+
+    if (isEsProfile()) {
+        switch (to) {
+            case EbtFloat:
+                switch (from) {
+                case EbtInt:
+                case EbtUint:
+                    return numericFeatures.contains(TNumericFeatures::shader_implicit_conversions);
+                default:
+                    return false;
+                }
+            case EbtUint:
+                switch (from) {
+                case EbtInt:
+                    return numericFeatures.contains(TNumericFeatures::shader_implicit_conversions);
+                default:
+                    return false;
+                }
+            default:
+                return false;
+        }        
     } else {
         switch (to) {
         case EbtDouble:
@@ -1708,13 +1709,14 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
             case EbtInt64:
             case EbtUint64:
             case EbtFloat:
-            case EbtDouble:
-                return true;
+                return version >= 400 || numericFeatures.contains(TNumericFeatures::gpu_shader_fp64);
             case EbtInt16:
             case EbtUint16:
-                return extensionRequested(E_GL_AMD_gpu_shader_int16);
+                return (version >= 400 || numericFeatures.contains(TNumericFeatures::gpu_shader_fp64)) &&
+                                          numericFeatures.contains(TNumericFeatures::gpu_shader_int16);
             case EbtFloat16:
-                return extensionRequested(E_GL_AMD_gpu_shader_half_float);
+                return (version >= 400 || numericFeatures.contains(TNumericFeatures::gpu_shader_fp64)) &&
+                                          numericFeatures.contains(TNumericFeatures::gpu_shader_half_float);
             default:
                 return false;
            }
@@ -1722,16 +1724,14 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
             switch (from) {
             case EbtInt:
             case EbtUint:
-            case EbtFloat:
                  return true;
             case EbtBool:
                  return getSource() == EShSourceHlsl;
             case EbtInt16:
             case EbtUint16:
-                return extensionRequested(E_GL_AMD_gpu_shader_int16);
+                return numericFeatures.contains(TNumericFeatures::gpu_shader_int16);
             case EbtFloat16:
-                return 
-                    extensionRequested(E_GL_AMD_gpu_shader_half_float) ||
+                return numericFeatures.contains(TNumericFeatures::gpu_shader_half_float) ||
                     getSource() == EShSourceHlsl;
             default:
                  return false;
@@ -1739,25 +1739,21 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
         case EbtUint:
             switch (from) {
             case EbtInt:
-                 return version >= 400 || getSource() == EShSourceHlsl;
-            case EbtUint:
-                return true;
+                return version >= 400 || getSource() == EShSourceHlsl;
             case EbtBool:
                 return getSource() == EShSourceHlsl;
             case EbtInt16:
             case EbtUint16:
-                return extensionRequested(E_GL_AMD_gpu_shader_int16);
+                return numericFeatures.contains(TNumericFeatures::gpu_shader_int16);
             default:
                 return false;
             }
         case EbtInt:
             switch (from) {
-            case EbtInt:
-                return true;
             case EbtBool:
                 return getSource() == EShSourceHlsl;
             case EbtInt16:
-                return extensionRequested(E_GL_AMD_gpu_shader_int16);
+                return numericFeatures.contains(TNumericFeatures::gpu_shader_int16);
             default:
                 return false;
             }
@@ -1766,21 +1762,19 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
             case EbtInt:
             case EbtUint:
             case EbtInt64:
-            case EbtUint64:
                 return true;
             case EbtInt16:
             case EbtUint16:
-                return extensionRequested(E_GL_AMD_gpu_shader_int16);
+                return numericFeatures.contains(TNumericFeatures::gpu_shader_int16);
             default:
                 return false;
             }
         case EbtInt64:
             switch (from) {
             case EbtInt:
-            case EbtInt64:
                 return true;
             case EbtInt16:
-                return extensionRequested(E_GL_AMD_gpu_shader_int16);
+                return numericFeatures.contains(TNumericFeatures::gpu_shader_int16);
             default:
                 return false;
             }
@@ -1788,9 +1782,7 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
             switch (from) {
             case EbtInt16:
             case EbtUint16:
-                return extensionRequested(E_GL_AMD_gpu_shader_int16);
-            case EbtFloat16:
-                return extensionRequested(E_GL_AMD_gpu_shader_half_float);
+                return numericFeatures.contains(TNumericFeatures::gpu_shader_int16);
             default:
                 break;
             }
@@ -1798,8 +1790,7 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
         case EbtUint16:
             switch (from) {
             case EbtInt16:
-            case EbtUint16:
-                return extensionRequested(E_GL_AMD_gpu_shader_int16);
+                return numericFeatures.contains(TNumericFeatures::gpu_shader_int16);
             default:
                 break;
             }
@@ -1926,12 +1917,14 @@ static TBasicType getCorrespondingUnsignedType(TBasicType type)
 //        integer type corresponding to the type of the operand with signed
 //        integer type.
 
-std::tuple<TBasicType, TBasicType> TIntermediate::getConversionDestinatonType(TBasicType type0, TBasicType type1, TOperator op) const
+std::tuple<TBasicType, TBasicType> TIntermediate::getConversionDestinationType(TBasicType type0, TBasicType type1, TOperator op) const
 {
     TBasicType res0 = EbtNumTypes;
     TBasicType res1 = EbtNumTypes;
 
-    if (isEsProfile() || version == 110)
+    if ((isEsProfile() && 
+        (version < 310 || !numericFeatures.contains(TNumericFeatures::shader_implicit_conversions))) || 
+        version == 110)
         return std::make_tuple(res0, res1);
 
     if (getSource() == EShSourceHlsl) {
@@ -2463,7 +2456,7 @@ TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* true
     //
     // Get compatible types.
     //
-    auto children = addConversion(EOpSequence, trueBlock, falseBlock);
+    auto children = addPairConversion(EOpSequence, trueBlock, falseBlock);
     trueBlock = std::get<0>(children);
     falseBlock = std::get<1>(children);
 
@@ -2750,6 +2743,22 @@ TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expres
     return node;
 }
 
+// Propagate precision from formal function return type to actual return type,
+// and on to its subtree.
+void TIntermBranch::updatePrecision(TPrecisionQualifier parentPrecision)
+{
+    TIntermTyped* exp = getExpression();
+    if (exp == nullptr)
+        return;
+
+    if (exp->getBasicType() == EbtInt || exp->getBasicType() == EbtUint ||
+        exp->getBasicType() == EbtFloat || exp->getBasicType() == EbtFloat16) {
+        if (parentPrecision != EpqNone && exp->getQualifier().precision == EpqNone) {
+            exp->propagatePrecision(parentPrecision);
+        }
+    }
+}
+
 //
 // This is to be executed after the final root is put on top by the parsing
 // process.
@@ -2774,6 +2783,9 @@ bool TIntermediate::postProcess(TIntermNode* root, EShLanguage /*language*/)
     case EShTexSampTransUpgradeTextureRemoveSampler:
         performTextureUpgradeAndSamplerRemovalTransformation(root);
         break;
+    case EShTexSampTransCount:
+        assert(0);
+        break;
     }
 #endif
 
@@ -3234,10 +3246,17 @@ bool TIntermediate::promoteUnary(TIntermUnary& node)
 
             return false;
         break;
-
     default:
-        if (operand->getBasicType() != EbtFloat)
+        // HLSL uses this path for initial function signature finding for built-ins
+        // taking a single argument, which generally don't participate in
+        // operator-based type promotion (type conversion will occur later).
+        // For now, scalar argument cases are relying on the setType() call below.
+        if (getSource() == EShSourceHlsl)
+            break;
 
+        // GLSL only allows integer arguments for the cases identified above in the
+        // case statements.
+        if (operand->getBasicType() != EbtFloat)
             return false;
     }
 
@@ -3247,9 +3266,11 @@ bool TIntermediate::promoteUnary(TIntermUnary& node)
     return true;
 }
 
+// Propagate precision qualifiers *up* from children to parent.
 void TIntermUnary::updatePrecision()
 {
-    if (getBasicType() == EbtInt || getBasicType() == EbtUint || getBasicType() == EbtFloat || getBasicType() == EbtFloat16) {
+    if (getBasicType() == EbtInt || getBasicType() == EbtUint ||
+        getBasicType() == EbtFloat || getBasicType() == EbtFloat16) {
         if (operand->getQualifier().precision > getQualifier().precision)
             getQualifier().precision = operand->getQualifier().precision;
     }
@@ -3745,9 +3766,12 @@ bool TIntermediate::promoteAggregate(TIntermAggregate& node)
     return false;
 }
 
+// Propagate precision qualifiers *up* from children to parent, and then
+// back *down* again to the children's subtrees.
 void TIntermBinary::updatePrecision()
 {
-    if (getBasicType() == EbtInt || getBasicType() == EbtUint || getBasicType() == EbtFloat || getBasicType() == EbtFloat16) {
+     if (getBasicType() == EbtInt || getBasicType() == EbtUint ||
+         getBasicType() == EbtFloat || getBasicType() == EbtFloat16) {
         getQualifier().precision = std::max(right->getQualifier().precision, left->getQualifier().precision);
         if (getQualifier().precision != EpqNone) {
             left->propagatePrecision(getQualifier().precision);
@@ -3756,9 +3780,14 @@ void TIntermBinary::updatePrecision()
     }
 }
 
+// Recursively propagate precision qualifiers *down* the subtree of the current node,
+// until reaching a node that already has a precision qualifier or otherwise does
+// not participate in precision propagation.
 void TIntermTyped::propagatePrecision(TPrecisionQualifier newPrecision)
 {
-    if (getQualifier().precision != EpqNone || (getBasicType() != EbtInt && getBasicType() != EbtUint && getBasicType() != EbtFloat && getBasicType() != EbtFloat16))
+    if (getQualifier().precision != EpqNone ||
+        (getBasicType() != EbtInt && getBasicType() != EbtUint &&
+         getBasicType() != EbtFloat && getBasicType() != EbtFloat16))
         return;
 
     getQualifier().precision = newPrecision;

+ 34 - 4
src/libraries/glslang/glslang/MachineIndependent/LiveTraverser.h

@@ -74,14 +74,33 @@ public:
         for (unsigned int f = 0; f < globals.size(); ++f) {
             TIntermAggregate* candidate = globals[f]->getAsAggregate();
             if (candidate && candidate->getOp() == EOpFunction && candidate->getName() == name) {
-                functions.push_back(candidate);
+                destinations.push_back(candidate);
                 break;
             }
         }
     }
 
-    typedef std::list<TIntermAggregate*> TFunctionStack;
-    TFunctionStack functions;
+    void pushGlobalReference(const TString& name)
+    {
+        TIntermSequence& globals = intermediate.getTreeRoot()->getAsAggregate()->getSequence();
+        for (unsigned int f = 0; f < globals.size(); ++f) {
+            TIntermAggregate* candidate = globals[f]->getAsAggregate();
+            if (candidate && candidate->getOp() == EOpSequence &&
+                candidate->getSequence().size() == 1 &&
+                candidate->getSequence()[0]->getAsBinaryNode()) {
+                TIntermBinary* binary = candidate->getSequence()[0]->getAsBinaryNode();
+                TIntermSymbol* symbol = binary->getLeft()->getAsSymbolNode();
+                if (symbol && symbol->getQualifier().storage == EvqGlobal &&
+                    symbol->getName() == name) {
+                    destinations.push_back(candidate);
+                    break;
+                }
+            }
+        }
+    }
+
+    typedef std::list<TIntermAggregate*> TDestinationStack;
+    TDestinationStack destinations;
 
 protected:
     // To catch which function calls are not dead, and hence which functions must be visited.
@@ -117,16 +136,27 @@ protected:
     // and only visit each function once.
     void addFunctionCall(TIntermAggregate* call)
     {
-        // // just use the map to ensure we process each function at most once
+        // just use the map to ensure we process each function at most once
         if (liveFunctions.find(call->getName()) == liveFunctions.end()) {
             liveFunctions.insert(call->getName());
             pushFunction(call->getName());
         }
     }
 
+    void addGlobalReference(const TString& name)
+    {
+        // just use the map to ensure we process each global at most once
+        if (liveGlobals.find(name) == liveGlobals.end()) {
+            liveGlobals.insert(name);
+            pushGlobalReference(name);
+        }
+    }
+
     const TIntermediate& intermediate;
     typedef std::unordered_set<TString> TLiveFunctions;
     TLiveFunctions liveFunctions;
+    typedef std::unordered_set<TString> TLiveGlobals;
+    TLiveGlobals liveGlobals;
     bool traverseAll;
 
 private:

+ 7 - 4
src/libraries/glslang/glslang/MachineIndependent/ParseContextBase.cpp

@@ -157,11 +157,11 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op,
     case EvqBuffer:
         if (node->getQualifier().isReadOnly())
             message = "can't modify a readonly buffer";
-        if (node->getQualifier().isShaderRecordNV())
+        if (node->getQualifier().isShaderRecord())
             message = "can't modify a shaderrecordnv qualified buffer";
         break;
-    case EvqHitAttrNV:
-        if (language != EShLangIntersectNV)
+    case EvqHitAttr:
+        if (language != EShLangIntersect)
             message = "cannot modify hitAttributeNV in this stage";
         break;
 #endif
@@ -181,9 +181,12 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op,
         case EbtAtomicUint:
             message = "can't modify an atomic_uint";
             break;
-        case EbtAccStructNV:
+        case EbtAccStruct:
             message = "can't modify accelerationStructureNV";
             break;
+        case EbtRayQuery:
+            message = "can't modify rayQueryEXT";
+            break;
 #endif
         default:
             break;

+ 431 - 131
src/libraries/glslang/glslang/MachineIndependent/ParseHelper.cpp

@@ -3,6 +3,7 @@
 // Copyright (C) 2012-2015 LunarG, Inc.
 // Copyright (C) 2015-2018 Google, Inc.
 // Copyright (C) 2017, 2019 ARM Limited.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 // All rights reserved.
 //
@@ -245,7 +246,9 @@ void TParseContext::handlePragma(const TSourceLoc& loc, const TVector<TString>&
         else if (tokens[2].compare("off") == 0)
             contextPragma.optimize = false;
         else {
-            error(loc, "\"on\" or \"off\" expected after '(' for 'optimize' pragma", "#pragma", "");
+            if(relaxedErrors())
+                //  If an implementation does not recognize the tokens following #pragma, then it will ignore that pragma.
+                warn(loc, "\"on\" or \"off\" expected after '(' for 'optimize' pragma", "#pragma", "");
             return;
         }
 
@@ -269,7 +272,9 @@ void TParseContext::handlePragma(const TSourceLoc& loc, const TVector<TString>&
         else if (tokens[2].compare("off") == 0)
             contextPragma.debug = false;
         else {
-            error(loc, "\"on\" or \"off\" expected after '(' for 'debug' pragma", "#pragma", "");
+            if(relaxedErrors())
+                //  If an implementation does not recognize the tokens following #pragma, then it will ignore that pragma.
+                warn(loc, "\"on\" or \"off\" expected after '(' for 'debug' pragma", "#pragma", "");
             return;
         }
 
@@ -427,8 +432,18 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn
 #ifndef GLSLANG_WEB
     if (base->isReference() && ! base->isArray()) {
         requireExtensions(loc, 1, &E_GL_EXT_buffer_reference2, "buffer reference indexing");
-        result = intermediate.addBinaryMath(EOpAdd, base, index, loc);
-        result->setType(base->getType());
+        if (base->getType().getReferentType()->containsUnsizedArray()) {
+            error(loc, "cannot index reference to buffer containing an unsized array", "", "");
+            result = nullptr;
+        } else {
+            result = intermediate.addBinaryMath(EOpAdd, base, index, loc);
+            if (result != nullptr)
+                result->setType(base->getType());
+        }
+        if (result == nullptr) {
+            error(loc, "cannot index buffer reference", "", "");
+            result = intermediate.addConstantUnion(0.0, EbtFloat, loc);
+        }
         return result;
     }
     if (base->getAsSymbolNode() && isIoResizeArray(base->getType()))
@@ -740,8 +755,11 @@ TIntermTyped* TParseContext::handleBinaryMath(const TSourceLoc& loc, const char*
     }
 
     TIntermTyped* result = nullptr;
-    if (allowed)
+    if (allowed) {
+        if ((left->isReference() || right->isReference()))
+            requireExtensions(loc, 1, &E_GL_EXT_buffer_reference2, "buffer reference math");
         result = intermediate.addBinaryMath(op, left, right, loc);
+    }
 
     if (result == nullptr)
         binaryOpError(loc, str, left->getCompleteString(), right->getCompleteString());
@@ -821,50 +839,7 @@ TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TInterm
     TIntermTyped* result = base;
     if ((base->isVector() || base->isScalar()) &&
         (base->isFloatingDomain() || base->isIntegerDomain() || base->getBasicType() == EbtBool)) {
-        if (base->isScalar()) {
-            const char* dotFeature = "scalar swizzle";
-            requireProfile(loc, ~EEsProfile, dotFeature);
-            profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, dotFeature);
-        }
-
-        TSwizzleSelectors<TVectorSelector> selectors;
-        parseSwizzleSelector(loc, field, base->getVectorSize(), selectors);
-
-        if (base->isVector() && selectors.size() != 1 && base->getType().contains16BitFloat())
-            requireFloat16Arithmetic(loc, ".", "can't swizzle types containing float16");
-        if (base->isVector() && selectors.size() != 1 && base->getType().contains16BitInt())
-            requireInt16Arithmetic(loc, ".", "can't swizzle types containing (u)int16");
-        if (base->isVector() && selectors.size() != 1 && base->getType().contains8BitInt())
-            requireInt8Arithmetic(loc, ".", "can't swizzle types containing (u)int8");
-
-        if (base->isScalar()) {
-            if (selectors.size() == 1)
-                return result;
-            else {
-                TType type(base->getBasicType(), EvqTemporary, selectors.size());
-                // Swizzle operations propagate specialization-constantness
-                if (base->getQualifier().isSpecConstant())
-                    type.getQualifier().makeSpecConstant();
-                return addConstructor(loc, base, type);
-            }
-        }
-
-        if (base->getType().getQualifier().isFrontEndConstant())
-            result = intermediate.foldSwizzle(base, selectors, loc);
-        else {
-            if (selectors.size() == 1) {
-                TIntermTyped* index = intermediate.addConstantUnion(selectors[0], loc);
-                result = intermediate.addIndex(EOpIndexDirect, base, index, loc);
-                result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision));
-            } else {
-                TIntermTyped* index = intermediate.addSwizzle(selectors, loc);
-                result = intermediate.addIndex(EOpVectorSwizzle, base, index, loc);
-                result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision, selectors.size()));
-            }
-            // Swizzle operations propagate specialization-constantness
-            if (base->getType().getQualifier().isSpecConstant())
-                result->getWritableType().getQualifier().makeSpecConstant();
-        }
+        result = handleDotSwizzle(loc, base, field);
     } else if (base->isStruct() || base->isReference()) {
         const TTypeList* fields = base->isReference() ?
                                   base->getType().getReferentType()->getStruct() :
@@ -905,6 +880,60 @@ TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TInterm
     return result;
 }
 
+//
+// Handle seeing a base.swizzle, a subset of base.identifier in the grammar.
+//
+TIntermTyped* TParseContext::handleDotSwizzle(const TSourceLoc& loc, TIntermTyped* base, const TString& field)
+{
+    TIntermTyped* result = base;
+    if (base->isScalar()) {
+        const char* dotFeature = "scalar swizzle";
+        requireProfile(loc, ~EEsProfile, dotFeature);
+        profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, dotFeature);
+    }
+
+    TSwizzleSelectors<TVectorSelector> selectors;
+    parseSwizzleSelector(loc, field, base->getVectorSize(), selectors);
+
+    if (base->isVector() && selectors.size() != 1 && base->getType().contains16BitFloat())
+        requireFloat16Arithmetic(loc, ".", "can't swizzle types containing float16");
+    if (base->isVector() && selectors.size() != 1 && base->getType().contains16BitInt())
+        requireInt16Arithmetic(loc, ".", "can't swizzle types containing (u)int16");
+    if (base->isVector() && selectors.size() != 1 && base->getType().contains8BitInt())
+        requireInt8Arithmetic(loc, ".", "can't swizzle types containing (u)int8");
+
+    if (base->isScalar()) {
+        if (selectors.size() == 1)
+            return result;
+        else {
+            TType type(base->getBasicType(), EvqTemporary, selectors.size());
+            // Swizzle operations propagate specialization-constantness
+            if (base->getQualifier().isSpecConstant())
+                type.getQualifier().makeSpecConstant();
+            return addConstructor(loc, base, type);
+        }
+    }
+
+    if (base->getType().getQualifier().isFrontEndConstant())
+        result = intermediate.foldSwizzle(base, selectors, loc);
+    else {
+        if (selectors.size() == 1) {
+            TIntermTyped* index = intermediate.addConstantUnion(selectors[0], loc);
+            result = intermediate.addIndex(EOpIndexDirect, base, index, loc);
+            result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision));
+        } else {
+            TIntermTyped* index = intermediate.addSwizzle(selectors, loc);
+            result = intermediate.addIndex(EOpVectorSwizzle, base, index, loc);
+            result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision, selectors.size()));
+        }
+        // Swizzle operations propagate specialization-constantness
+        if (base->getType().getQualifier().isSpecConstant())
+            result->getWritableType().getQualifier().makeSpecConstant();
+    }
+
+    return result;
+}
+
 void TParseContext::blockMemberExtensionCheck(const TSourceLoc& loc, const TIntermTyped* base, int member, const TString& memberName)
 {
     // a block that needs extension checking is either 'base', or if arrayed,
@@ -1273,7 +1302,7 @@ TIntermTyped* TParseContext::handleBuiltInFunctionCall(TSourceLoc loc, TIntermNo
     TIntermTyped *result = intermediate.addBuiltInFunctionCall(loc, function.getBuiltInOp(),
                                                                function.getParamCount() == 1,
                                                                arguments, function.getType());
-    if (obeyPrecisionQualifiers())
+    if (result != nullptr && obeyPrecisionQualifiers())
         computeBuiltinPrecisions(*result, function);
 
     if (result == nullptr) {
@@ -1353,6 +1382,9 @@ void TParseContext::computeBuiltinPrecisions(TIntermTyped& node, const TFunction
         case EOpInterpolateAtSample:
             numArgs = 1;
             break;
+        case EOpDebugPrintf:
+            numArgs = 0;
+            break;
         default:
             break;
         }
@@ -1390,23 +1422,28 @@ TIntermNode* TParseContext::handleReturnValue(const TSourceLoc& loc, TIntermType
 #endif
 
     functionReturnsValue = true;
+    TIntermBranch* branch = nullptr;
     if (currentFunctionType->getBasicType() == EbtVoid) {
         error(loc, "void function cannot return a value", "return", "");
-        return intermediate.addBranch(EOpReturn, loc);
+        branch = intermediate.addBranch(EOpReturn, loc);
     } else if (*currentFunctionType != value->getType()) {
         TIntermTyped* converted = intermediate.addConversion(EOpReturn, *currentFunctionType, value);
         if (converted) {
             if (*currentFunctionType != converted->getType())
                 error(loc, "cannot convert return value to function return type", "return", "");
             if (version < 420)
-                warn(loc, "type conversion on return values was not explicitly allowed until version 420", "return", "");
-            return intermediate.addBranch(EOpReturn, converted, loc);
+                warn(loc, "type conversion on return values was not explicitly allowed until version 420",
+                     "return", "");
+            branch = intermediate.addBranch(EOpReturn, converted, loc);
         } else {
             error(loc, "type does not match, or is not convertible to, the function's return type", "return", "");
-            return intermediate.addBranch(EOpReturn, value, loc);
+            branch = intermediate.addBranch(EOpReturn, value, loc);
         }
     } else
-        return intermediate.addBranch(EOpReturn, value, loc);
+        branch = intermediate.addBranch(EOpReturn, value, loc);
+
+    branch->updatePrecision(currentFunctionType->getQualifier().precision);
+    return branch;
 }
 
 // See if the operation is being done in an illegal location.
@@ -1650,6 +1687,14 @@ TIntermTyped* TParseContext::addOutputArgumentConversions(const TFunction& funct
 #endif
 }
 
+TIntermTyped* TParseContext::addAssign(const TSourceLoc& loc, TOperator op, TIntermTyped* left, TIntermTyped* right)
+{
+    if ((op == EOpAddAssign || op == EOpSubAssign) && left->isReference())
+        requireExtensions(loc, 1, &E_GL_EXT_buffer_reference2, "+= and -= on a buffer reference");
+
+    return intermediate.addAssign(op, left, right, loc);
+}
+
 void TParseContext::memorySemanticsCheck(const TSourceLoc& loc, const TFunction& fnCandidate, const TIntermOperator& callNode)
 {
     const TIntermSequence* argp = &callNode.getAsAggregate()->getSequence();
@@ -1672,6 +1717,9 @@ void TParseContext::memorySemanticsCheck(const TSourceLoc& loc, const TFunction&
     unsigned int semantics = 0, storageClassSemantics = 0;
     unsigned int semantics2 = 0, storageClassSemantics2 = 0;
 
+    const TIntermTyped* arg0 = (*argp)[0]->getAsTyped();
+    const bool isMS = arg0->getBasicType() == EbtSampler && arg0->getType().getSampler().isMultiSample();
+
     // Grab the semantics and storage class semantics from the operands, based on opcode
     switch (callNode.getOp()) {
     case EOpAtomicAdd:
@@ -1704,18 +1752,18 @@ void TParseContext::memorySemanticsCheck(const TSourceLoc& loc, const TFunction&
     case EOpImageAtomicXor:
     case EOpImageAtomicExchange:
     case EOpImageAtomicStore:
-        storageClassSemantics = (*argp)[4]->getAsConstantUnion()->getConstArray()[0].getIConst();
-        semantics = (*argp)[5]->getAsConstantUnion()->getConstArray()[0].getIConst();
+        storageClassSemantics = (*argp)[isMS ? 5 : 4]->getAsConstantUnion()->getConstArray()[0].getIConst();
+        semantics = (*argp)[isMS ? 6 : 5]->getAsConstantUnion()->getConstArray()[0].getIConst();
         break;
     case EOpImageAtomicLoad:
-        storageClassSemantics = (*argp)[3]->getAsConstantUnion()->getConstArray()[0].getIConst();
-        semantics = (*argp)[4]->getAsConstantUnion()->getConstArray()[0].getIConst();
+        storageClassSemantics = (*argp)[isMS ? 4 : 3]->getAsConstantUnion()->getConstArray()[0].getIConst();
+        semantics = (*argp)[isMS ? 5 : 4]->getAsConstantUnion()->getConstArray()[0].getIConst();
         break;
     case EOpImageAtomicCompSwap:
-        storageClassSemantics = (*argp)[5]->getAsConstantUnion()->getConstArray()[0].getIConst();
-        semantics = (*argp)[6]->getAsConstantUnion()->getConstArray()[0].getIConst();
-        storageClassSemantics2 = (*argp)[7]->getAsConstantUnion()->getConstArray()[0].getIConst();
-        semantics2 = (*argp)[8]->getAsConstantUnion()->getConstArray()[0].getIConst();
+        storageClassSemantics = (*argp)[isMS ? 6 : 5]->getAsConstantUnion()->getConstArray()[0].getIConst();
+        semantics = (*argp)[isMS ? 7 : 6]->getAsConstantUnion()->getConstArray()[0].getIConst();
+        storageClassSemantics2 = (*argp)[isMS ? 8 : 7]->getAsConstantUnion()->getConstArray()[0].getIConst();
+        semantics2 = (*argp)[isMS ? 9 : 8]->getAsConstantUnion()->getConstArray()[0].getIConst();
         break;
 
     case EOpBarrier:
@@ -2006,18 +2054,20 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
         if (arg > 0) {
 
 #ifndef GLSLANG_WEB
-            bool f16ShadowCompare = (*argp)[1]->getAsTyped()->getBasicType() == EbtFloat16 && arg0->getType().getSampler().shadow;
+            bool f16ShadowCompare = (*argp)[1]->getAsTyped()->getBasicType() == EbtFloat16 &&
+                                    arg0->getType().getSampler().shadow;
             if (f16ShadowCompare)
                 ++arg;
 #endif
-            if (! (*argp)[arg]->getAsConstantUnion())
+            if (! (*argp)[arg]->getAsTyped()->getQualifier().isConstant())
                 error(loc, "argument must be compile-time constant", "texel offset", "");
-            else {
+            else if ((*argp)[arg]->getAsConstantUnion()) {
                 const TType& type = (*argp)[arg]->getAsTyped()->getType();
                 for (int c = 0; c < type.getVectorSize(); ++c) {
                     int offset = (*argp)[arg]->getAsConstantUnion()->getConstArray()[c].getIConst();
                     if (offset > resources.maxProgramTexelOffset || offset < resources.minProgramTexelOffset)
-                        error(loc, "value is out of range:", "texel offset", "[gl_MinProgramTexelOffset, gl_MaxProgramTexelOffset]");
+                        error(loc, "value is out of range:", "texel offset",
+                              "[gl_MinProgramTexelOffset, gl_MaxProgramTexelOffset]");
                 }
             }
         }
@@ -2026,15 +2076,32 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
     }
 
 #ifndef GLSLANG_WEB
-    case EOpTraceNV:
+    case EOpTrace:
         if (!(*argp)[10]->getAsConstantUnion())
             error(loc, "argument must be compile-time constant", "payload number", "");
         break;
-    case EOpExecuteCallableNV:
+    case EOpExecuteCallable:
         if (!(*argp)[1]->getAsConstantUnion())
             error(loc, "argument must be compile-time constant", "callable data number", "");
         break;
 
+    case EOpRayQueryGetIntersectionType:
+    case EOpRayQueryGetIntersectionT:
+    case EOpRayQueryGetIntersectionInstanceCustomIndex:
+    case EOpRayQueryGetIntersectionInstanceId:
+    case EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset:
+    case EOpRayQueryGetIntersectionGeometryIndex:
+    case EOpRayQueryGetIntersectionPrimitiveIndex:
+    case EOpRayQueryGetIntersectionBarycentrics:
+    case EOpRayQueryGetIntersectionFrontFace:
+    case EOpRayQueryGetIntersectionObjectRayDirection:
+    case EOpRayQueryGetIntersectionObjectRayOrigin:
+    case EOpRayQueryGetIntersectionObjectToWorld:
+    case EOpRayQueryGetIntersectionWorldToObject:
+        if (!(*argp)[1]->getAsConstantUnion())
+            error(loc, "argument must be compile-time constant", "committed", "");
+        break;
+
     case EOpTextureQuerySamples:
     case EOpImageQuerySamples:
         // GL_ARB_shader_texture_image_samples
@@ -2058,7 +2125,14 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
             if (imageType.getQualifier().getFormat() != ElfR32i && imageType.getQualifier().getFormat() != ElfR32ui)
                 error(loc, "only supported on image with format r32i or r32ui", fnCandidate.getName().c_str(), "");
         } else {
-            if (fnCandidate.getName().compare(0, 19, "imageAtomicExchange") != 0)
+            bool isImageAtomicOnFloatAllowed = ((fnCandidate.getName().compare(0, 14, "imageAtomicAdd") == 0) ||
+                (fnCandidate.getName().compare(0, 15, "imageAtomicLoad") == 0) ||
+                (fnCandidate.getName().compare(0, 16, "imageAtomicStore") == 0) ||
+                (fnCandidate.getName().compare(0, 19, "imageAtomicExchange") == 0));
+            if (imageType.getSampler().type == EbtFloat && isImageAtomicOnFloatAllowed &&
+                (fnCandidate.getName().compare(0, 19, "imageAtomicExchange") != 0)) // imageAtomicExchange doesn't require GL_EXT_shader_atomic_float
+                requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float, fnCandidate.getName().c_str());
+            if (!isImageAtomicOnFloatAllowed)
                 error(loc, "only supported on integer images", fnCandidate.getName().c_str(), "");
             else if (imageType.getQualifier().getFormat() != ElfR32f && isEsProfile())
                 error(loc, "only supported on image with format r32f", fnCandidate.getName().c_str(), "");
@@ -2087,10 +2161,18 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
         if (argp->size() > 3) {
             requireExtensions(loc, 1, &E_GL_KHR_memory_scope_semantics, fnCandidate.getName().c_str());
             memorySemanticsCheck(loc, fnCandidate, callNode);
+            if ((callNode.getOp() == EOpAtomicAdd || callNode.getOp() == EOpAtomicExchange ||
+                callNode.getOp() == EOpAtomicLoad || callNode.getOp() == EOpAtomicStore) &&
+                (arg0->getType().isFloatingDomain())) {
+                requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float, fnCandidate.getName().c_str());
+            }
         } else if (arg0->getType().getBasicType() == EbtInt64 || arg0->getType().getBasicType() == EbtUint64) {
             const char* const extensions[2] = { E_GL_NV_shader_atomic_int64,
                                                 E_GL_EXT_shader_atomic_int64 };
             requireExtensions(loc, 2, extensions, fnCandidate.getName().c_str());
+        } else if ((callNode.getOp() == EOpAtomicAdd || callNode.getOp() == EOpAtomicExchange) &&
+                   (arg0->getType().isFloatingDomain())) {
+            requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float, fnCandidate.getName().c_str());
         }
         break;
     }
@@ -2172,6 +2254,28 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
             memorySemanticsCheck(loc, fnCandidate, callNode);
         }
         break;
+
+    case EOpMix:
+        if (profile == EEsProfile && version < 310) {
+            // Look for specific signatures
+            if ((*argp)[0]->getAsTyped()->getBasicType() != EbtFloat &&
+                (*argp)[1]->getAsTyped()->getBasicType() != EbtFloat &&
+                (*argp)[2]->getAsTyped()->getBasicType() == EbtBool) {
+                requireExtensions(loc, 1, &E_GL_EXT_shader_integer_mix, "specific signature of builtin mix");
+            }
+        }
+
+        if (profile != EEsProfile && version < 450) {
+            if ((*argp)[0]->getAsTyped()->getBasicType() != EbtFloat && 
+                (*argp)[0]->getAsTyped()->getBasicType() != EbtDouble &&
+                (*argp)[1]->getAsTyped()->getBasicType() != EbtFloat &&
+                (*argp)[1]->getAsTyped()->getBasicType() != EbtDouble &&
+                (*argp)[2]->getAsTyped()->getBasicType() == EbtBool) {
+                requireExtensions(loc, 1, &E_GL_EXT_shader_integer_mix, fnCandidate.getName().c_str());
+            }
+        }
+
+        break;
 #endif
 
     default:
@@ -2698,7 +2802,10 @@ void TParseContext::reservedPpErrorCheck(const TSourceLoc& loc, const char* iden
     if (strncmp(identifier, "GL_", 3) == 0)
         ppError(loc, "names beginning with \"GL_\" can't be (un)defined:", op,  identifier);
     else if (strncmp(identifier, "defined", 8) == 0)
-        ppError(loc, "\"defined\" can't be (un)defined:", op,  identifier);
+        if (relaxedErrors())
+            ppWarn(loc, "\"defined\" is (un)defined:", op,  identifier);
+        else
+            ppError(loc, "\"defined\" can't be (un)defined:", op,  identifier);
     else if (strstr(identifier, "__") != 0) {
         if (isEsProfile() && version >= 300 &&
             (strcmp(identifier, "__LINE__") == 0 ||
@@ -2706,7 +2813,7 @@ void TParseContext::reservedPpErrorCheck(const TSourceLoc& loc, const char* iden
              strcmp(identifier, "__VERSION__") == 0))
             ppError(loc, "predefined names can't be (un)defined:", op,  identifier);
         else {
-            if (isEsProfile() && version < 300)
+            if (isEsProfile() && version < 300 && !relaxedErrors())
                 ppError(loc, "names containing consecutive underscores are reserved, and an error if version < 300:", op, identifier);
             else
                 ppWarn(loc, "names containing consecutive underscores are reserved:", op, identifier);
@@ -3083,7 +3190,7 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
         error(loc, "constructor argument does not have a type", "constructor", "");
         return true;
     }
-    if (op != EOpConstructStruct && typed->getBasicType() == EbtSampler) {
+    if (op != EOpConstructStruct && op != EOpConstructNonuniform && typed->getBasicType() == EbtSampler) {
         error(loc, "cannot convert a sampler", "constructor", "");
         return true;
     }
@@ -3128,7 +3235,7 @@ bool TParseContext::constructorTextureSamplerError(const TSourceLoc& loc, const
     if (function[0].type->getBasicType() != EbtSampler ||
         ! function[0].type->getSampler().isTexture() ||
         function[0].type->isArray()) {
-        error(loc, "sampler-constructor first argument must be a scalar textureXXX type", token, "");
+        error(loc, "sampler-constructor first argument must be a scalar *texture* type", token, "");
         return true;
     }
     // simulate the first argument's impact on the result type, so it can be compared with the encapsulated operator!=()
@@ -3136,7 +3243,8 @@ bool TParseContext::constructorTextureSamplerError(const TSourceLoc& loc, const
     texture.setCombined(false);
     texture.shadow = false;
     if (texture != function[0].type->getSampler()) {
-        error(loc, "sampler-constructor first argument must match type and dimensionality of constructor type", token, "");
+        error(loc, "sampler-constructor first argument must be a *texture* type"
+                   " matching the dimensionality and sampled type of the constructor", token, "");
         return true;
     }
 
@@ -3146,7 +3254,7 @@ bool TParseContext::constructorTextureSamplerError(const TSourceLoc& loc, const
     if (  function[1].type->getBasicType() != EbtSampler ||
         ! function[1].type->getSampler().isPureSampler() ||
           function[1].type->isArray()) {
-        error(loc, "sampler-constructor second argument must be a scalar type 'sampler'", token, "");
+        error(loc, "sampler-constructor second argument must be a scalar sampler or samplerShadow", token, "");
         return true;
     }
 
@@ -3222,14 +3330,14 @@ void TParseContext::atomicUintCheck(const TSourceLoc& loc, const TType& type, co
         error(loc, "atomic_uints can only be used in uniform variables or function parameters:", type.getBasicTypeString().c_str(), identifier.c_str());
 }
 
-void TParseContext::accStructNVCheck(const TSourceLoc& loc, const TType& type, const TString& identifier)
+void TParseContext::accStructCheck(const TSourceLoc& loc, const TType& type, const TString& identifier)
 {
     if (type.getQualifier().storage == EvqUniform)
         return;
 
-    if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtAccStructNV))
+    if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtAccStruct))
         error(loc, "non-uniform struct contains an accelerationStructureNV:", type.getBasicTypeString().c_str(), identifier.c_str());
-    else if (type.getBasicType() == EbtAccStructNV && type.getQualifier().storage != EvqUniform)
+    else if (type.getBasicType() == EbtAccStruct && type.getQualifier().storage != EvqUniform)
         error(loc, "accelerationStructureNV can only be used in uniform variables or function parameters:",
             type.getBasicTypeString().c_str(), identifier.c_str());
 
@@ -3327,6 +3435,11 @@ void TParseContext::globalQualifierTypeCheck(const TSourceLoc& loc, const TQuali
         !qualifier.hasBufferReference())
         error(loc, "buffers can be declared only as blocks", "buffer", "");
 
+    if (qualifier.storage != EvqVaryingIn && publicType.basicType == EbtDouble &&
+        extensionTurnedOn(E_GL_ARB_vertex_attrib_64bit) && language == EShLangVertex &&
+        version < 400) {
+        profileRequires(loc, ECoreProfile | ECompatibilityProfile, 410, E_GL_ARB_gpu_shader_fp64, "vertex-shader `double` type");
+    }
     if (qualifier.storage != EvqVaryingIn && qualifier.storage != EvqVaryingOut)
         return;
 
@@ -3377,7 +3490,7 @@ void TParseContext::globalQualifierTypeCheck(const TSourceLoc& loc, const TQuali
                 profileRequires(loc, ENoProfile, 150, nullptr, "vertex input arrays");
             }
             if (publicType.basicType == EbtDouble)
-                profileRequires(loc, ~EEsProfile, 410, nullptr, "vertex-shader `double` type input");
+                profileRequires(loc, ~EEsProfile, 410, E_GL_ARB_vertex_attrib_64bit, "vertex-shader `double` type input");
             if (qualifier.isAuxiliary() || qualifier.isInterpolation() || qualifier.isMemory() || qualifier.invariant)
                 error(loc, "vertex input cannot be further qualified", "", "");
             break;
@@ -3513,12 +3626,14 @@ void TParseContext::mergeQualifiers(const TSourceLoc& loc, TQualifier& dst, cons
         dst.precision = src.precision;
 
 #ifndef GLSLANG_WEB
-    if (!force && ((src.coherent && (dst.devicecoherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.subgroupcoherent)) ||
-                   (src.devicecoherent && (dst.coherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.subgroupcoherent)) ||
-                   (src.queuefamilycoherent && (dst.coherent || dst.devicecoherent || dst.workgroupcoherent || dst.subgroupcoherent)) ||
-                   (src.workgroupcoherent && (dst.coherent || dst.devicecoherent || dst.queuefamilycoherent || dst.subgroupcoherent)) ||
-                   (src.subgroupcoherent  && (dst.coherent || dst.devicecoherent || dst.queuefamilycoherent || dst.workgroupcoherent)))) {
-        error(loc, "only one coherent/devicecoherent/queuefamilycoherent/workgroupcoherent/subgroupcoherent qualifier allowed", GetPrecisionQualifierString(src.precision), "");
+    if (!force && ((src.coherent && (dst.devicecoherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.subgroupcoherent || dst.shadercallcoherent)) ||
+                   (src.devicecoherent && (dst.coherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.subgroupcoherent || dst.shadercallcoherent)) ||
+                   (src.queuefamilycoherent && (dst.coherent || dst.devicecoherent || dst.workgroupcoherent || dst.subgroupcoherent || dst.shadercallcoherent)) ||
+                   (src.workgroupcoherent && (dst.coherent || dst.devicecoherent || dst.queuefamilycoherent || dst.subgroupcoherent || dst.shadercallcoherent)) ||
+                   (src.subgroupcoherent  && (dst.coherent || dst.devicecoherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.shadercallcoherent)) ||
+                   (src.shadercallcoherent && (dst.coherent || dst.devicecoherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.subgroupcoherent)))) {
+        error(loc, "only one coherent/devicecoherent/queuefamilycoherent/workgroupcoherent/subgroupcoherent/shadercallcoherent qualifier allowed", 
+            GetPrecisionQualifierString(src.precision), "");
     }
 #endif
     // Layout qualifiers
@@ -3546,6 +3661,7 @@ void TParseContext::mergeQualifiers(const TSourceLoc& loc, TQualifier& dst, cons
     MERGE_SINGLETON(queuefamilycoherent);
     MERGE_SINGLETON(workgroupcoherent);
     MERGE_SINGLETON(subgroupcoherent);
+    MERGE_SINGLETON(shadercallcoherent);
     MERGE_SINGLETON(nonprivate);
     MERGE_SINGLETON(volatil);
     MERGE_SINGLETON(restrict);
@@ -3983,7 +4099,7 @@ void TParseContext::checkRuntimeSizable(const TSourceLoc& loc, const TIntermType
     }
 
     // check for additional things allowed by GL_EXT_nonuniform_qualifier
-    if (base.getBasicType() == EbtSampler || base.getBasicType() == EbtAccStructNV ||
+    if (base.getBasicType() == EbtSampler || base.getBasicType() == EbtAccStruct || base.getBasicType() == EbtRayQuery ||
         (base.getBasicType() == EbtBlock && base.getType().getQualifier().isUniformOrBuffer()))
         requireExtensions(loc, 1, &E_GL_EXT_nonuniform_qualifier, "variable index");
     else
@@ -4487,6 +4603,7 @@ void TParseContext::paramCheckFix(const TSourceLoc& loc, const TQualifier& quali
         type.getQualifier().queuefamilycoherent  = qualifier.queuefamilycoherent;
         type.getQualifier().workgroupcoherent  = qualifier.workgroupcoherent;
         type.getQualifier().subgroupcoherent  = qualifier.subgroupcoherent;
+        type.getQualifier().shadercallcoherent = qualifier.shadercallcoherent;
         type.getQualifier().nonprivate = qualifier.nonprivate;
         type.getQualifier().readonly  = qualifier.readonly;
         type.getQualifier().writeonly = qualifier.writeonly;
@@ -4868,7 +4985,7 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
 #ifndef GLSLANG_WEB
     if (id == TQualifier::getLayoutPackingString(ElpStd430)) {
         requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, "std430");
-        profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, nullptr, "std430");
+        profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, E_GL_ARB_shader_storage_buffer_object, "std430");
         profileRequires(loc, EEsProfile, 310, nullptr, "std430");
         publicType.qualifier.layoutPacking = ElpStd430;
         return;
@@ -5067,13 +5184,19 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
             return;
         }
     } else {
-        if (language == EShLangRayGenNV || language == EShLangIntersectNV ||
-        language == EShLangAnyHitNV || language == EShLangClosestHitNV ||
-        language == EShLangMissNV || language == EShLangCallableNV) {
-            if (id == "shaderrecordnv") {
-                publicType.qualifier.layoutShaderRecordNV = true;
+        if (language == EShLangRayGen || language == EShLangIntersect ||
+        language == EShLangAnyHit || language == EShLangClosestHit ||
+        language == EShLangMiss || language == EShLangCallable) {
+            if (id == "shaderrecordnv" || id == "shaderrecordext") {
+                if (id == "shaderrecordnv") {
+                    requireExtensions(loc, 1, &E_GL_NV_ray_tracing, "shader record NV");
+                } else {
+                    requireExtensions(loc, 1, &E_GL_EXT_ray_tracing, "shader record EXT");
+                }
+                publicType.qualifier.layoutShaderRecord = true;
                 return;
             }
+
         }
     }
     if (language == EShLangCompute) {
@@ -5088,6 +5211,12 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
             }
         }
     }
+
+    if (id == "primitive_culling") {
+        requireExtensions(loc, 1, &E_GL_EXT_ray_flags_primitive_culling, "primitive culling");
+        publicType.shaderQualifiers.layoutPrimitiveCulling = true;
+        return;
+    }
 #endif
 
     error(loc, "unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4)", id.c_str(), "");
@@ -5135,6 +5264,7 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
             profileRequires(loc, EEsProfile, 310, nullptr, feature);
         }
         publicType.qualifier.layoutOffset = value;
+        publicType.qualifier.explicitOffset = true;
         if (nonLiteral)
             error(loc, "needs a literal integer", "offset", "");
         return;
@@ -5347,10 +5477,10 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
 
     case EShLangFragment:
         if (id == "index") {
-            requireProfile(loc, ECompatibilityProfile | ECoreProfile, "index layout qualifier on fragment output");
+            requireProfile(loc, ECompatibilityProfile | ECoreProfile | EEsProfile, "index layout qualifier on fragment output");
             const char* exts[2] = { E_GL_ARB_separate_shader_objects, E_GL_ARB_explicit_attrib_location };
             profileRequires(loc, ECompatibilityProfile | ECoreProfile, 330, 2, exts, "index layout qualifier on fragment output");
-
+            profileRequires(loc, EEsProfile ,310, E_GL_EXT_blend_func_extended, "index layout qualifier on fragment output");
             // "It is also a compile-time error if a fragment shader sets a layout index to less than 0 or greater than 1."
             if (value < 0 || value > 1) {
                 value = 0;
@@ -5514,8 +5644,8 @@ void TParseContext::mergeObjectLayoutQualifiers(TQualifier& dst, const TQualifie
             dst.layoutViewportRelative = true;
         if (src.layoutSecondaryViewportRelativeOffset != -2048)
             dst.layoutSecondaryViewportRelativeOffset = src.layoutSecondaryViewportRelativeOffset;
-        if (src.layoutShaderRecordNV)
-            dst.layoutShaderRecordNV = true;
+        if (src.layoutShaderRecord)
+            dst.layoutShaderRecord = true;
         if (src.pervertexNV)
             dst.pervertexNV = true;
 #endif
@@ -5583,7 +5713,7 @@ void TParseContext::layoutObjectCheck(const TSourceLoc& loc, const TSymbol& symb
                     error(loc, "cannot specify on a variable declaration", "align", "");
                 if (qualifier.isPushConstant())
                     error(loc, "can only specify on a uniform block", "push_constant", "");
-                if (qualifier.isShaderRecordNV())
+                if (qualifier.isShaderRecord())
                     error(loc, "can only specify on a buffer block", "shaderRecordNV", "");
             }
             break;
@@ -5657,11 +5787,11 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
                 error(loc, "cannot apply to uniform or buffer block", "location", "");
             break;
 #ifndef GLSLANG_WEB
-        case EvqPayloadNV:
-        case EvqPayloadInNV:
-        case EvqHitAttrNV:
-        case EvqCallableDataNV:
-        case EvqCallableDataInNV:
+        case EvqPayload:
+        case EvqPayloadIn:
+        case EvqHitAttr:
+        case EvqCallableData:
+        case EvqCallableDataIn:
             break;
 #endif
         default:
@@ -5684,6 +5814,8 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
         int repeated = intermediate.addXfbBufferOffset(type);
         if (repeated >= 0)
             error(loc, "overlapping offsets at", "xfb_offset", "offset %d in buffer %d", repeated, qualifier.layoutXfbBuffer);
+        if (type.isUnsizedArray())
+            error(loc, "unsized array", "xfb_offset", "in buffer %d", qualifier.layoutXfbBuffer);
 
         // "The offset must be a multiple of the size of the first component of the first
         // qualified variable or block member, or a compile-time error results. Further, if applied to an aggregate
@@ -5756,7 +5888,7 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
         if (spvVersion.spv > 0) {
             if (qualifier.isUniformOrBuffer()) {
                 if (type.getBasicType() == EbtBlock && !qualifier.isPushConstant() &&
-                       !qualifier.isShaderRecordNV() &&
+                       !qualifier.isShaderRecord() &&
                        !qualifier.hasAttachment() &&
                        !qualifier.hasBufferReference())
                     error(loc, "uniform/buffer blocks require layout(binding=X)", "binding", "");
@@ -5813,7 +5945,7 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
     if (qualifier.hasBufferReference() && type.getBasicType() != EbtBlock)
         error(loc, "can only be used with a block", "buffer_reference", "");
 
-    if (qualifier.isShaderRecordNV() && type.getBasicType() != EbtBlock)
+    if (qualifier.isShaderRecord() && type.getBasicType() != EbtBlock)
         error(loc, "can only be used with a block", "shaderRecordNV", "");
 
     // input attachment
@@ -5958,7 +6090,7 @@ void TParseContext::layoutQualifierCheck(const TSourceLoc& loc, const TQualifier
         if (qualifier.storage != EvqBuffer)
             error(loc, "can only be used with buffer", "buffer_reference", "");
     }
-    if (qualifier.isShaderRecordNV()) {
+    if (qualifier.isShaderRecord()) {
         if (qualifier.storage != EvqBuffer)
             error(loc, "can only be used with a buffer", "shaderRecordNV", "");
         if (qualifier.hasBinding())
@@ -5967,7 +6099,7 @@ void TParseContext::layoutQualifierCheck(const TSourceLoc& loc, const TQualifier
             error(loc, "cannot be used with shaderRecordNV", "set", "");
 
     }
-    if (qualifier.storage == EvqHitAttrNV && qualifier.hasLayout()) {
+    if (qualifier.storage == EvqHitAttr && qualifier.hasLayout()) {
         error(loc, "cannot apply layout qualifiers to hitAttributeNV variable", "hitAttributeNV", "");
     }
 }
@@ -6018,6 +6150,8 @@ void TParseContext::checkNoShaderLayouts(const TSourceLoc& loc, const TShaderQua
         error(loc, message, "num_views", "");
     if (shaderQualifiers.interlockOrdering != EioNone)
         error(loc, message, TQualifier::getInterlockOrderingString(shaderQualifiers.interlockOrdering), "");
+    if (shaderQualifiers.layoutPrimitiveCulling)
+        error(loc, "can only be applied as standalone", "primitive_culling", "");
 #endif
 }
 
@@ -6079,6 +6213,15 @@ const TFunction* TParseContext::findFunction(const TSourceLoc& loc, const TFunct
 #endif
 
     const TFunction* function = nullptr;
+
+    // debugPrintfEXT has var args and is in the symbol table as "debugPrintfEXT()",
+    // mangled to "debugPrintfEXT("
+    if (call.getName() == "debugPrintfEXT") {
+        TSymbol* symbol = symbolTable.find("debugPrintfEXT(", &builtIn);
+        if (symbol)
+            return symbol->getAsFunction();
+    }
+
     bool explicitTypesEnabled = extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
                                 extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int8) ||
                                 extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int16) ||
@@ -6088,7 +6231,10 @@ const TFunction* TParseContext::findFunction(const TSourceLoc& loc, const TFunct
                                 extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float32) ||
                                 extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float64);
 
-    if (isEsProfile() || version < 120)
+    if (isEsProfile())
+        function = (extensionTurnedOn(E_GL_EXT_shader_implicit_conversions) && version >= 310) ?
+                    findFunction120(loc, call, builtIn) : findFunctionExact(loc, call, builtIn);
+    else if (version < 120)
         function = findFunctionExact(loc, call, builtIn);
     else if (version < 400)
         function = extensionTurnedOn(E_GL_ARB_gpu_shader_fp64) ? findFunction400(loc, call, builtIn) : findFunction120(loc, call, builtIn);
@@ -6422,6 +6568,12 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden
     type.copyArrayInnerSizes(publicType.arraySizes);
     arrayOfArrayVersionCheck(loc, type.getArraySizes());
 
+    if (initializer) {
+        if (type.getBasicType() == EbtRayQuery) {
+            error(loc, "ray queries can only be initialized by using the rayQueryInitializeEXT intrinsic:", "=", identifier.c_str());
+        }
+    }
+
     if (type.isCoopMat()) {
         intermediate.setUseVulkanMemoryModel();
         intermediate.setUseStorageBuffer();
@@ -6461,7 +6613,7 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden
     transparentOpaqueCheck(loc, type, identifier);
 #ifndef GLSLANG_WEB
     atomicUintCheck(loc, type, identifier);
-    accStructNVCheck(loc, type, identifier);
+    accStructCheck(loc, type, identifier);
     checkAndResizeMeshViewDim(loc, type, /*isBlockMember*/ false);
 #endif
     if (type.getQualifier().storage == EvqConst && type.containsReference()) {
@@ -7177,6 +7329,8 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T
         if (!node->getType().isCoopMat()) {
             if (type.getBasicType() != node->getType().getBasicType()) {
                 node = intermediate.addConversion(type.getBasicType(), node);
+                if (node == nullptr)
+                    return nullptr;
             }
             node = intermediate.setAggregateOperator(node, EOpConstructCooperativeMatrix, type, node->getLoc());
         } else {
@@ -7355,8 +7509,8 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
             arraySizesCheck(memberLoc, currentBlockQualifier, memberType.getArraySizes(), nullptr, member == typeList.size() - 1);
         if (memberQualifier.hasOffset()) {
             if (spvVersion.spv == 0) {
-                requireProfile(memberLoc, ~EEsProfile, "offset on block member");
-                profileRequires(memberLoc, ~EEsProfile, 440, E_GL_ARB_enhanced_layouts, "offset on block member");
+                profileRequires(memberLoc, ~EEsProfile, 440, E_GL_ARB_enhanced_layouts, "\"offset\" on block member");
+                profileRequires(memberLoc, EEsProfile, 300, E_GL_ARB_enhanced_layouts, "\"offset\" on block member");
             }
         }
 
@@ -7395,7 +7549,7 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
     // Special case for "push_constant uniform", which has a default of std430,
     // contrary to normal uniform defaults, and can't have a default tracked for it.
     if ((currentBlockQualifier.isPushConstant() && !currentBlockQualifier.hasPacking()) ||
-        (currentBlockQualifier.isShaderRecordNV() && !currentBlockQualifier.hasPacking()))
+        (currentBlockQualifier.isShaderRecord() && !currentBlockQualifier.hasPacking()))
         currentBlockQualifier.layoutPacking = ElpStd430;
 
     // Special case for "taskNV in/out", which has a default of std430,
@@ -7495,6 +7649,8 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
     fixBlockLocations(loc, currentBlockQualifier, typeList, memberWithLocation, memberWithoutLocation);
     fixXfbOffsets(currentBlockQualifier, typeList);
     fixBlockUniformOffsets(currentBlockQualifier, typeList);
+    fixBlockUniformLayoutMatrix(currentBlockQualifier, &typeList, nullptr);
+    fixBlockUniformLayoutPacking(currentBlockQualifier, &typeList, nullptr);
     for (unsigned int member = 0; member < typeList.size(); ++member)
         layoutTypeCheck(typeList[member].loc, *typeList[member].type);
 
@@ -7612,6 +7768,7 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
 // with a particular stage.
 void TParseContext::blockStageIoCheck(const TSourceLoc& loc, const TQualifier& qualifier)
 {
+    const char *extsrt[2] = { E_GL_NV_ray_tracing, E_GL_EXT_ray_tracing };
     switch (qualifier.storage) {
     case EvqUniform:
         profileRequires(loc, EEsProfile, 300, nullptr, "uniform block");
@@ -7621,7 +7778,7 @@ void TParseContext::blockStageIoCheck(const TSourceLoc& loc, const TQualifier& q
         break;
     case EvqBuffer:
         requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, "buffer block");
-        profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, nullptr, "buffer block");
+        profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, E_GL_ARB_shader_storage_buffer_object, "buffer block");
         profileRequires(loc, EEsProfile, 310, nullptr, "buffer block");
         break;
     case EvqVaryingIn:
@@ -7650,28 +7807,28 @@ void TParseContext::blockStageIoCheck(const TSourceLoc& loc, const TQualifier& q
         }
         break;
 #ifndef GLSLANG_WEB
-    case EvqPayloadNV:
-        profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "rayPayloadNV block");
-        requireStage(loc, (EShLanguageMask)(EShLangRayGenNVMask | EShLangAnyHitNVMask | EShLangClosestHitNVMask | EShLangMissNVMask),
+    case EvqPayload:
+        profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "rayPayloadNV block");
+        requireStage(loc, (EShLanguageMask)(EShLangRayGenMask | EShLangAnyHitMask | EShLangClosestHitMask | EShLangMissMask),
             "rayPayloadNV block");
         break;
-    case EvqPayloadInNV:
-        profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "rayPayloadInNV block");
-        requireStage(loc, (EShLanguageMask)(EShLangAnyHitNVMask | EShLangClosestHitNVMask | EShLangMissNVMask),
+    case EvqPayloadIn:
+        profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "rayPayloadInNV block");
+        requireStage(loc, (EShLanguageMask)(EShLangAnyHitMask | EShLangClosestHitMask | EShLangMissMask),
             "rayPayloadInNV block");
         break;
-    case EvqHitAttrNV:
-        profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "hitAttributeNV block");
-        requireStage(loc, (EShLanguageMask)(EShLangIntersectNVMask | EShLangAnyHitNVMask | EShLangClosestHitNVMask), "hitAttributeNV block");
+    case EvqHitAttr:
+        profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "hitAttributeNV block");
+        requireStage(loc, (EShLanguageMask)(EShLangIntersectMask | EShLangAnyHitMask | EShLangClosestHitMask), "hitAttributeNV block");
         break;
-    case EvqCallableDataNV:
-        profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "callableDataNV block");
-        requireStage(loc, (EShLanguageMask)(EShLangRayGenNVMask | EShLangClosestHitNVMask | EShLangMissNVMask | EShLangCallableNVMask),
+    case EvqCallableData:
+        profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "callableDataNV block");
+        requireStage(loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask | EShLangMissMask | EShLangCallableMask),
             "callableDataNV block");
         break;
-    case EvqCallableDataInNV:
-        profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "callableDataInNV block");
-        requireStage(loc, (EShLanguageMask)(EShLangCallableNVMask), "callableDataInNV block");
+    case EvqCallableDataIn:
+        profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "callableDataInNV block");
+        requireStage(loc, (EShLanguageMask)(EShLangCallableMask), "callableDataInNV block");
         break;
 #endif
     default:
@@ -7710,8 +7867,8 @@ void TParseContext::blockQualifierCheck(const TSourceLoc& loc, const TQualifier&
         error(loc, "cannot use invariant qualifier on an interface block", "invariant", "");
     if (qualifier.isPushConstant())
         intermediate.addPushConstantCount();
-    if (qualifier.isShaderRecordNV())
-        intermediate.addShaderRecordNVCount();
+    if (qualifier.isShaderRecord())
+        intermediate.addShaderRecordCount();
     if (qualifier.isTaskMemory())
         intermediate.addTaskNVCount();
 }
@@ -7864,6 +8021,101 @@ void TParseContext::fixBlockUniformOffsets(TQualifier& qualifier, TTypeList& typ
     }
 }
 
+//
+// Spread LayoutMatrix to uniform block member, if a uniform block member is a struct,
+// we need spread LayoutMatrix to this struct member too. and keep this rule for recursive.
+//
+void TParseContext::fixBlockUniformLayoutMatrix(TQualifier& qualifier, TTypeList* originTypeList,
+                                                TTypeList* tmpTypeList)
+{
+    assert(tmpTypeList == nullptr || originTypeList->size() == tmpTypeList->size());
+    for (unsigned int member = 0; member < originTypeList->size(); ++member) {
+        if (qualifier.layoutPacking != ElpNone) {
+            if (tmpTypeList == nullptr) {
+                if (((*originTypeList)[member].type->isMatrix() ||
+                     (*originTypeList)[member].type->getBasicType() == EbtStruct) &&
+                    (*originTypeList)[member].type->getQualifier().layoutMatrix == ElmNone) {
+                    (*originTypeList)[member].type->getQualifier().layoutMatrix = qualifier.layoutMatrix;
+                }
+            } else {
+                if (((*tmpTypeList)[member].type->isMatrix() ||
+                     (*tmpTypeList)[member].type->getBasicType() == EbtStruct) &&
+                    (*tmpTypeList)[member].type->getQualifier().layoutMatrix == ElmNone) {
+                    (*tmpTypeList)[member].type->getQualifier().layoutMatrix = qualifier.layoutMatrix;
+                }
+            }
+        }
+
+        if ((*originTypeList)[member].type->getBasicType() == EbtStruct) {
+            TQualifier* memberQualifier = nullptr;
+            // block member can be declare a matrix style, so it should be update to the member's style
+            if ((*originTypeList)[member].type->getQualifier().layoutMatrix == ElmNone) {
+                memberQualifier = &qualifier;
+            } else {
+                memberQualifier = &((*originTypeList)[member].type->getQualifier());
+            }
+
+            const TType* tmpType = tmpTypeList == nullptr ?
+                (*originTypeList)[member].type->clone() : (*tmpTypeList)[member].type;
+
+            fixBlockUniformLayoutMatrix(*memberQualifier, (*originTypeList)[member].type->getWritableStruct(),
+                                        tmpType->getWritableStruct());
+
+            const TTypeList* structure = recordStructCopy(matrixFixRecord, (*originTypeList)[member].type, tmpType);
+
+            if (tmpTypeList == nullptr) {
+                (*originTypeList)[member].type->setStruct(const_cast<TTypeList*>(structure));
+            }
+            if (tmpTypeList != nullptr) {
+                (*tmpTypeList)[member].type->setStruct(const_cast<TTypeList*>(structure));
+            }
+        }
+    }
+}
+
+//
+// Spread LayoutPacking to block member, if a  block member is a struct, we need spread LayoutPacking to
+// this struct member too. and keep this rule for recursive.
+//
+void TParseContext::fixBlockUniformLayoutPacking(TQualifier& qualifier, TTypeList* originTypeList,
+                                                 TTypeList* tmpTypeList)
+{
+    assert(tmpTypeList == nullptr || originTypeList->size() == tmpTypeList->size());
+    for (unsigned int member = 0; member < originTypeList->size(); ++member) {
+        if (qualifier.layoutPacking != ElpNone) {
+            if (tmpTypeList == nullptr) {
+                if ((*originTypeList)[member].type->getQualifier().layoutPacking == ElpNone) {
+                    (*originTypeList)[member].type->getQualifier().layoutPacking = qualifier.layoutPacking;
+                }
+            } else {
+                if ((*tmpTypeList)[member].type->getQualifier().layoutPacking == ElpNone) {
+                    (*tmpTypeList)[member].type->getQualifier().layoutPacking = qualifier.layoutPacking;
+                }
+            }
+        }
+
+        if ((*originTypeList)[member].type->getBasicType() == EbtStruct) {
+            // Deep copy the type in pool.
+            // Because, struct use in different block may have different layout qualifier.
+            // We have to new a object to distinguish between them.
+            const TType* tmpType = tmpTypeList == nullptr ?
+                (*originTypeList)[member].type->clone() : (*tmpTypeList)[member].type;
+
+            fixBlockUniformLayoutPacking(qualifier, (*originTypeList)[member].type->getWritableStruct(),
+                                         tmpType->getWritableStruct());
+
+            const TTypeList* structure = recordStructCopy(packingFixRecord, (*originTypeList)[member].type, tmpType);
+
+            if (tmpTypeList == nullptr) {
+                (*originTypeList)[member].type->setStruct(const_cast<TTypeList*>(structure));
+            }
+            if (tmpTypeList != nullptr) {
+                (*tmpTypeList)[member].type->setStruct(const_cast<TTypeList*>(structure));
+            }
+        }
+    }
+}
+
 // For an identifier that is already declared, add more qualification to it.
 void TParseContext::addQualifierToExisting(const TSourceLoc& loc, TQualifier qualifier, const TString& identifier)
 {
@@ -8172,6 +8424,16 @@ void TParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, con
     {
         checkIoArraysConsistency(loc);
     }
+
+    if (publicType.shaderQualifiers.layoutPrimitiveCulling) {
+        if (publicType.qualifier.storage != EvqTemporary)
+            error(loc, "layout qualifier can not have storage qualifiers", "primitive_culling","", "");
+        else {
+            intermediate.setLayoutPrimitiveCulling();
+        }
+        // Exit early as further checks are not valid
+        return;
+    }
 #endif 
     const TQualifier& qualifier = publicType.qualifier;
 
@@ -8233,7 +8495,7 @@ void TParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, con
         error(loc, "cannot declare a default, can only be used on a block", "buffer_reference", "");
     if (qualifier.hasSpecConstantId())
         error(loc, "cannot declare a default, can only be used on a scalar", "constant_id", "");
-    if (qualifier.isShaderRecordNV())
+    if (qualifier.isShaderRecord())
         error(loc, "cannot declare a default, can only be used on a block", "shaderRecordNV", "");
 }
 
@@ -8322,5 +8584,43 @@ TIntermNode* TParseContext::addSwitch(const TSourceLoc& loc, TIntermTyped* expre
     return switchNode;
 }
 
+//
+// When a struct used in block, and has it's own layout packing, layout matrix,
+// record the origin structure of a struct to map, and Record the structure copy to the copy table,
+//
+const TTypeList* TParseContext::recordStructCopy(TStructRecord& record, const TType* originType, const TType* tmpType)
+{
+    size_t memberCount = tmpType->getStruct()->size();
+    size_t originHash = 0, tmpHash = 0;
+    std::hash<size_t> hasher;
+    for (size_t i = 0; i < memberCount; i++) {
+        size_t originMemberHash = hasher(originType->getStruct()->at(i).type->getQualifier().layoutPacking +
+                                         originType->getStruct()->at(i).type->getQualifier().layoutMatrix);
+        size_t tmpMemberHash = hasher(tmpType->getStruct()->at(i).type->getQualifier().layoutPacking +
+                                      tmpType->getStruct()->at(i).type->getQualifier().layoutMatrix);
+        originHash = hasher((originHash ^ originMemberHash) << 1);
+        tmpHash = hasher((tmpHash ^ tmpMemberHash) << 1);
+    }
+    const TTypeList* originStruct = originType->getStruct();
+    const TTypeList* tmpStruct = tmpType->getStruct();
+    if (originHash != tmpHash) {
+        auto fixRecords = record.find(originStruct);
+        if (fixRecords != record.end()) {
+            auto fixRecord = fixRecords->second.find(tmpHash);
+            if (fixRecord != fixRecords->second.end()) {
+                return fixRecord->second;
+            } else {
+                record[originStruct][tmpHash] = tmpStruct;
+                return tmpStruct;
+            }
+        } else {
+            record[originStruct] = std::map<size_t, const TTypeList*>();
+            record[originStruct][tmpHash] = tmpStruct;
+            return tmpStruct;
+        }
+    }
+    return originStruct;
+}
+
 } // end namespace glslang
 

+ 10 - 1
src/libraries/glslang/glslang/MachineIndependent/ParseHelper.h

@@ -68,6 +68,7 @@ class TScanContext;
 class TPpContext;
 
 typedef std::set<int> TIdSetType;
+typedef std::map<const TTypeList*, std::map<size_t, const TTypeList*>> TStructRecord;
 
 //
 // Sharable code (as well as what's in TParseVersions) across
@@ -83,6 +84,7 @@ public:
             scopeMangler("::"),
             symbolTable(symbolTable),
             statementNestingLevel(0), loopNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0),
+            currentFunctionType(nullptr),
             postEntryPointReturn(false),
             contextPragma(true, false),
             beginInvocationInterlockCount(0), endInvocationInterlockCount(0),
@@ -315,6 +317,7 @@ public:
     TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right);
     TIntermTyped* handleUnaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* childNode);
     TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field);
+    TIntermTyped* handleDotSwizzle(const TSourceLoc&, TIntermTyped* base, const TString& field);
     void blockMemberExtensionCheck(const TSourceLoc&, const TIntermTyped* base, int member, const TString& memberName);
     TFunction* handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype);
     TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&);
@@ -326,6 +329,7 @@ public:
     TIntermTyped* handleLengthMethod(const TSourceLoc&, TFunction*, TIntermNode*);
     void addInputArgumentConversions(const TFunction&, TIntermNode*&) const;
     TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermAggregate&) const;
+    TIntermTyped* addAssign(const TSourceLoc&, TOperator op, TIntermTyped* left, TIntermTyped* right);
     void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&);
     void nonOpBuiltInCheck(const TSourceLoc&, const TFunction&, TIntermAggregate&);
     void userFunctionCallCheck(const TSourceLoc&, TIntermAggregate&);
@@ -358,7 +362,7 @@ public:
     void boolCheck(const TSourceLoc&, const TPublicType&);
     void samplerCheck(const TSourceLoc&, const TType&, const TString& identifier, TIntermTyped* initializer);
     void atomicUintCheck(const TSourceLoc&, const TType&, const TString& identifier);
-    void accStructNVCheck(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 memberQualifierCheck(glslang::TPublicType&);
     void globalQualifierFixCheck(const TSourceLoc&, TQualifier&);
@@ -417,12 +421,15 @@ public:
     void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation);
     void fixXfbOffsets(TQualifier&, TTypeList&);
     void fixBlockUniformOffsets(TQualifier&, TTypeList&);
+    void fixBlockUniformLayoutMatrix(TQualifier&, TTypeList*, TTypeList*);
+    void fixBlockUniformLayoutPacking(TQualifier&, TTypeList*, TTypeList*);
     void addQualifierToExisting(const TSourceLoc&, TQualifier, const TString& identifier);
     void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&);
     void invariantCheck(const TSourceLoc&, const TQualifier&);
     void updateStandaloneQualifierDefaults(const TSourceLoc&, const TPublicType&);
     void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode);
     TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body);
+    const TTypeList* recordStructCopy(TStructRecord&, const TType*, const TType*);
 
 #ifndef GLSLANG_WEB
     TAttributeType attributeFromName(const TString& name) const;
@@ -483,6 +490,8 @@ protected:
     bool anyIndexLimits;
     TIdSetType inductiveLoopIds;
     TVector<TIntermTyped*> needsIndexLimitationChecking;
+    TStructRecord matrixFixRecord;
+    TStructRecord packingFixRecord;
 
     //
     // Geometry shader input arrays:

+ 42 - 12
src/libraries/glslang/glslang/MachineIndependent/Scan.cpp

@@ -2,6 +2,8 @@
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2013 LunarG, Inc.
 // Copyright (C) 2017 ARM Limited.
+// Copyright (C) 2020 Google, Inc.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 // All rights reserved.
 //
@@ -187,17 +189,15 @@ bool TInputScanner::scanVersion(int& version, EProfile& profile, bool& notFirstT
         if (lookingInMiddle) {
             notFirstToken = true;
             // make forward progress by finishing off the current line plus extra new lines
-            if (peek() == '\n' || peek() == '\r') {
-                while (peek() == '\n' || peek() == '\r')
-                    get();
-            } else
+            if (peek() != '\n' && peek() != '\r') {
                 do {
                     c = get();
                 } while (c != EndOfInput && c != '\n' && c != '\r');
-                while (peek() == '\n' || peek() == '\r')
-                    get();
-                if (peek() == EndOfInput)
-                    return true;
+            }
+            while (peek() == '\n' || peek() == '\r')
+                get();
+            if (peek() == EndOfInput)
+                return true;
         }
         lookingInMiddle = true;
 
@@ -416,6 +416,7 @@ void TScanContext::fillInKeywordMap()
     (*KeywordMap)["queuefamilycoherent"] =     QUEUEFAMILYCOHERENT;
     (*KeywordMap)["workgroupcoherent"] =       WORKGROUPCOHERENT;
     (*KeywordMap)["subgroupcoherent"] =        SUBGROUPCOHERENT;
+    (*KeywordMap)["shadercallcoherent"] =      SHADERCALLCOHERENT;
     (*KeywordMap)["nonprivate"] =              NONPRIVATE;
     (*KeywordMap)["restrict"] =                RESTRICT;
     (*KeywordMap)["readonly"] =                READONLY;
@@ -704,11 +705,18 @@ void TScanContext::fillInKeywordMap()
     (*KeywordMap)["precise"] =                 PRECISE;
 
     (*KeywordMap)["rayPayloadNV"] =            PAYLOADNV;
+    (*KeywordMap)["rayPayloadEXT"] =           PAYLOADEXT;
     (*KeywordMap)["rayPayloadInNV"] =          PAYLOADINNV;
+    (*KeywordMap)["rayPayloadInEXT"] =         PAYLOADINEXT;
     (*KeywordMap)["hitAttributeNV"] =          HITATTRNV;
+    (*KeywordMap)["hitAttributeEXT"] =         HITATTREXT;
     (*KeywordMap)["callableDataNV"] =          CALLDATANV;
+    (*KeywordMap)["callableDataEXT"] =         CALLDATAEXT;
     (*KeywordMap)["callableDataInNV"] =        CALLDATAINNV;
+    (*KeywordMap)["callableDataInEXT"] =       CALLDATAINEXT;
     (*KeywordMap)["accelerationStructureNV"] = ACCSTRUCTNV;
+    (*KeywordMap)["accelerationStructureEXT"]   = ACCSTRUCTEXT;
+    (*KeywordMap)["rayQueryEXT"] =              RAYQUERYEXT;
     (*KeywordMap)["perprimitiveNV"] =          PERPRIMITIVENV;
     (*KeywordMap)["perviewNV"] =               PERVIEWNV;
     (*KeywordMap)["taskNV"] =                  PERTASKNV;
@@ -843,6 +851,7 @@ int TScanContext::tokenize(TPpContext* pp, TParserToken& token)
             parseContext.error(loc, "not supported", "::", "");
             break;
 
+        case PpAtomConstString:        parserToken->sType.lex.string = NewPoolTString(tokenText);     return STRING_LITERAL;
         case PpAtomConstInt:           parserToken->sType.lex.i    = ppToken.ival;       return INTCONSTANT;
         case PpAtomConstUint:          parserToken->sType.lex.i    = ppToken.ival;       return UINTCONSTANT;
         case PpAtomConstFloat:         parserToken->sType.lex.d    = ppToken.dval;       return FLOATCONSTANT;
@@ -908,7 +917,8 @@ int TScanContext::tokenizeIdentifier()
     case BUFFER:
         afterBuffer = true;
         if ((parseContext.isEsProfile() && parseContext.version < 310) ||
-            (!parseContext.isEsProfile() && parseContext.version < 430))
+            (!parseContext.isEsProfile() && (parseContext.version < 430 &&
+            !parseContext.extensionTurnedOn(E_GL_ARB_shader_storage_buffer_object))))
             return identifierOrType();
         return keyword;
 
@@ -1014,6 +1024,23 @@ int TScanContext::tokenizeIdentifier()
             parseContext.extensionTurnedOn(E_GL_NV_ray_tracing))
             return keyword;
         return identifierOrType();
+    case PAYLOADEXT:
+    case PAYLOADINEXT:
+    case HITATTREXT:
+    case CALLDATAEXT:
+    case CALLDATAINEXT:
+    case ACCSTRUCTEXT:
+        if (parseContext.symbolTable.atBuiltInLevel() ||
+            parseContext.extensionTurnedOn(E_GL_EXT_ray_tracing) ||
+            parseContext.extensionTurnedOn(E_GL_EXT_ray_query))
+            return keyword;
+        return identifierOrType();
+    case RAYQUERYEXT:
+        if (parseContext.symbolTable.atBuiltInLevel() ||
+            (!parseContext.isEsProfile() && parseContext.version >= 460
+                 && parseContext.extensionTurnedOn(E_GL_EXT_ray_query)))
+            return keyword;
+        return identifierOrType();
     case ATOMIC_UINT:
         if ((parseContext.isEsProfile() && parseContext.version >= 310) ||
             parseContext.extensionTurnedOn(E_GL_ARB_shader_atomic_counters))
@@ -1025,6 +1052,7 @@ int TScanContext::tokenizeIdentifier()
     case QUEUEFAMILYCOHERENT:
     case WORKGROUPCOHERENT:
     case SUBGROUPCOHERENT:
+    case SHADERCALLCOHERENT:
     case NONPRIVATE:
     case RESTRICT:
     case READONLY:
@@ -1168,8 +1196,8 @@ int TScanContext::tokenizeIdentifier()
         afterType = true;
         if (parseContext.isEsProfile() || parseContext.version < 150 ||
             (!parseContext.symbolTable.atBuiltInLevel() &&
-              parseContext.version < 400 &&
-             !parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_fp64)))
+              (parseContext.version < 400 && !parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_fp64) &&
+              (parseContext.version < 410 && !parseContext.extensionTurnedOn(E_GL_ARB_vertex_attrib_64bit)))))
             reservedWord();
         return keyword;
 
@@ -1764,7 +1792,9 @@ int TScanContext::dMat()
 
     if (!parseContext.isEsProfile() && (parseContext.version >= 400 ||
         parseContext.symbolTable.atBuiltInLevel() ||
-        (parseContext.version >= 150 && parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_fp64))))
+        (parseContext.version >= 150 && parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_fp64)) ||
+        (parseContext.version >= 150 && parseContext.extensionTurnedOn(E_GL_ARB_vertex_attrib_64bit)
+         && parseContext.language == EShLangVertex)))
         return keyword;
 
     if (parseContext.isForwardCompatible())

+ 69 - 33
src/libraries/glslang/glslang/MachineIndependent/ShaderLang.cpp

@@ -1,7 +1,7 @@
 //
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2013-2016 LunarG, Inc.
-// Copyright (C) 2015-2018 Google, Inc.
+// Copyright (C) 2015-2020 Google, Inc.
 //
 // All rights reserved.
 //
@@ -51,9 +51,9 @@
 #include "ScanContext.h"
 
 #ifdef ENABLE_HLSL
-#include "../../hlsl/hlslParseHelper.h"
-#include "../../hlsl/hlslParseables.h"
-#include "../../hlsl/hlslScanContext.h"
+#include "../HLSL/hlslParseHelper.h"
+#include "../HLSL/hlslParseables.h"
+#include "../HLSL/hlslScanContext.h"
 #endif
 
 #include "../Include/ShHandle.h"
@@ -72,6 +72,9 @@
 // token to print ", but none of that seems appropriate for this file.
 #include "preprocessor/PpTokens.h"
 
+// Build-time generated includes
+#include "../../glslang/build_info.h"
+
 namespace { // anonymous namespace for file-local functions and symbols
 
 // Total number of successful initializers of glslang: a refcount
@@ -291,6 +294,9 @@ void InitializeStageSymbolTable(TBuiltInParseables& builtInParseables, int versi
 #ifdef GLSLANG_WEB
     profile = EEsProfile;
     version = 310;
+#elif defined(GLSLANG_ANGLE)
+    profile = ECoreProfile;
+    version = 450;
 #endif
 
     (*symbolTables[language]).adoptLevels(*commonTable[CommonIndex(profile, language)]);
@@ -312,6 +318,9 @@ bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable,  TS
 #ifdef GLSLANG_WEB
     profile = EEsProfile;
     version = 310;
+#elif defined(GLSLANG_ANGLE)
+    profile = ECoreProfile;
+    version = 450;
 #endif
 
     std::unique_ptr<TBuiltInParseables> builtInParseables(CreateBuiltInParseables(infoSink, source));
@@ -351,7 +360,6 @@ bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable,  TS
         (profile == EEsProfile && version >= 310))
         InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangGeometry, source,
                                    infoSink, commonTable, symbolTables);
-#endif
 
     // check for compute
     if ((profile != EEsProfile && version >= 420) ||
@@ -359,19 +367,20 @@ bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable,  TS
         InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCompute, source,
                                    infoSink, commonTable, symbolTables);
 
+#ifndef GLSLANG_ANGLE
     // check for ray tracing stages
     if (profile != EEsProfile && version >= 450) {
-        InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangRayGenNV, source,
+        InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangRayGen, source,
             infoSink, commonTable, symbolTables);
-        InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangIntersectNV, source,
+        InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangIntersect, source,
             infoSink, commonTable, symbolTables);
-        InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangAnyHitNV, source,
+        InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangAnyHit, source,
             infoSink, commonTable, symbolTables);
-        InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangClosestHitNV, source,
+        InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangClosestHit, source,
             infoSink, commonTable, symbolTables);
-        InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangMissNV, source,
+        InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangMiss, source,
             infoSink, commonTable, symbolTables);
-        InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCallableNV, source,
+        InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCallable, source,
             infoSink, commonTable, symbolTables);
     }
 
@@ -386,6 +395,8 @@ bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable,  TS
         (profile == EEsProfile && version >= 320))
         InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangTaskNV, source,
                                    infoSink, commonTable, symbolTables);
+#endif // !GLSLANG_ANGLE
+#endif // !GLSLANG_WEB
 
     return true;
 }
@@ -487,7 +498,7 @@ void SetupBuiltinSymbolTable(int version, EProfile profile, const SpvVersion& sp
 // Function to Print all builtins
 void DumpBuiltinSymbolTable(TInfoSink& infoSink, const TSymbolTable& symbolTable)
 {
-#ifndef GLSLANG_WEB
+#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
     infoSink.debug << "BuiltinSymbolTable {\n";
 
     symbolTable.dump(infoSink, true);
@@ -591,7 +602,7 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo
         break;
     }
 
-#ifndef GLSLANG_WEB
+#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
     // Correct for stage type...
     switch (stage) {
     case EShLangGeometry:
@@ -623,12 +634,12 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo
             version = profile == EEsProfile ? 310 : 420;
         }
         break;
-    case EShLangRayGenNV:
-    case EShLangIntersectNV:
-    case EShLangAnyHitNV:
-    case EShLangClosestHitNV:
-    case EShLangMissNV:
-    case EShLangCallableNV:
+    case EShLangRayGen:
+    case EShLangIntersect:
+    case EShLangAnyHit:
+    case EShLangClosestHit:
+    case EShLangMiss:
+    case EShLangCallable:
         if (profile == EEsProfile || version < 460) {
             correct = false;
             infoSink.info.message(EPrefixError, "#version: ray tracing shaders require non-es profile with version 460 or above");
@@ -716,6 +727,9 @@ void TranslateEnvironment(const TEnvironment* environment, EShMessages& messages
             case EShClientOpenGL:
                 spvVersion.openGl = environment->input.dialectVersion;
                 break;
+            case EShClientCount:
+                assert(0);
+                break;
             }
             switch (environment->input.languageFamily) {
             case EShSourceNone:
@@ -728,6 +742,9 @@ void TranslateEnvironment(const TEnvironment* environment, EShMessages& messages
                 source = EShSourceHlsl;
                 messages = static_cast<EShMessages>(messages | EShMsgReadHlsl);
                 break;
+            case EShSourceCount:
+                assert(0);
+                break;
             }
         }
 
@@ -861,7 +878,7 @@ bool ProcessDeferred(
                                 : userInput.scanVersion(version, profile, versionNotFirstToken);
     bool versionNotFound = version == 0;
     if (forceDefaultVersionAndProfile && source == EShSourceGlsl) {
-#ifndef GLSLANG_WEB
+#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
         if (! (messages & EShMsgSuppressWarnings) && ! versionNotFound &&
             (version != defaultVersion || profile != defaultProfile)) {
             compiler->infoSink.info << "Warning, (version, profile) forced to be ("
@@ -884,10 +901,13 @@ bool ProcessDeferred(
 #ifdef GLSLANG_WEB
     profile = EEsProfile;
     version = 310;
+#elif defined(GLSLANG_ANGLE)
+    profile = ECoreProfile;
+    version = 450;
 #endif
 
     bool versionWillBeError = (versionNotFound || (profile == EEsProfile && version >= 300 && versionNotFirst));
-#ifndef GLSLANG_WEB
+#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
     bool warnVersionNotFirst = false;
     if (! versionWillBeError && versionNotFirstToken) {
         if (messages & EShMsgRelaxedErrors)
@@ -957,7 +977,7 @@ bool ProcessDeferred(
     parseContext->setLimits(*resources);
     if (! goodVersion)
         parseContext->addError();
-#ifndef GLSLANG_WEB
+#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
     if (warnVersionNotFirst) {
         TSourceLoc loc;
         loc.init();
@@ -994,7 +1014,7 @@ bool ProcessDeferred(
     return success;
 }
 
-#ifndef GLSLANG_WEB
+#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
 
 // Responsible for keeping track of the most recent source string and line in
 // the preprocessor and outputting newlines appropriately if the source string
@@ -1217,14 +1237,16 @@ struct DoFullParse{
             parseContext.infoSink.info << parseContext.getNumErrors() << " compilation errors.  No code generated.\n\n";
         }
 
+#ifndef GLSLANG_ANGLE
         if (messages & EShMsgAST)
             intermediate.output(parseContext.infoSink, true);
+#endif
 
         return success;
     }
 };
 
-#ifndef GLSLANG_WEB
+#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
 // Take a single compilation unit, and run the preprocessor on it.
 // Return: True if there were no issues found in preprocessing,
 //         False if during preprocessing any unknown version, pragmas or
@@ -1678,19 +1700,29 @@ int ShGetUniformLocation(const ShHandle handle, const char* name)
 
 namespace glslang {
 
-#include "../Include/revision.h"
+Version GetVersion()
+{
+    Version version;
+    version.major = GLSLANG_VERSION_MAJOR;
+    version.minor = GLSLANG_VERSION_MINOR;
+    version.patch = GLSLANG_VERSION_PATCH;
+    version.flavor = GLSLANG_VERSION_FLAVOR;
+    return version;
+}
 
 #define QUOTE(s) #s
 #define STR(n) QUOTE(n)
 
 const char* GetEsslVersionString()
 {
-    return "OpenGL ES GLSL 3.20 glslang Khronos. " STR(GLSLANG_MINOR_VERSION) "." STR(GLSLANG_PATCH_LEVEL);
+    return "OpenGL ES GLSL 3.20 glslang Khronos. " STR(GLSLANG_VERSION_MAJOR) "." STR(GLSLANG_VERSION_MINOR) "." STR(
+        GLSLANG_VERSION_PATCH) GLSLANG_VERSION_FLAVOR;
 }
 
 const char* GetGlslVersionString()
 {
-    return "4.60 glslang Khronos. " STR(GLSLANG_MINOR_VERSION) "." STR(GLSLANG_PATCH_LEVEL);
+    return "4.60 glslang Khronos. " STR(GLSLANG_VERSION_MAJOR) "." STR(GLSLANG_VERSION_MINOR) "." STR(
+        GLSLANG_VERSION_PATCH) GLSLANG_VERSION_FLAVOR;
 }
 
 int GetKhronosToolId()
@@ -1771,6 +1803,8 @@ void TShader::setSourceEntryPoint(const char* name)
     sourceEntryPointName = name;
 }
 
+// Log initial settings and transforms.
+// See comment for class TProcesses.
 void TShader::addProcesses(const std::vector<std::string>& p)
 {
     intermediate->addProcesses(p);
@@ -1852,7 +1886,7 @@ bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion
                            &environment);
 }
 
-#ifndef GLSLANG_WEB
+#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
 // Fill in a string with the result of preprocessing ShaderStrings
 // Returns true if all extensions, pragmas and version strings were valid.
 //
@@ -1890,7 +1924,7 @@ const char* TShader::getInfoDebugLog()
 }
 
 TProgram::TProgram() :
-#ifndef GLSLANG_WEB
+#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
     reflection(0),
 #endif
     linked(false)
@@ -1906,7 +1940,7 @@ TProgram::TProgram() :
 TProgram::~TProgram()
 {
     delete infoSink;
-#ifndef GLSLANG_WEB
+#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
     delete reflection;
 #endif
 
@@ -1953,7 +1987,7 @@ bool TProgram::linkStage(EShLanguage stage, EShMessages messages)
     if (stages[stage].size() == 0)
         return true;
 
-#ifndef GLSLANG_WEB
+#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
     int numEsShaders = 0, numNonEsShaders = 0;
     for (auto it = stages[stage].begin(); it != stages[stage].end(); ++it) {
         if ((*it)->intermediate->getProfile() == EEsProfile) {
@@ -2007,8 +2041,10 @@ bool TProgram::linkStage(EShLanguage stage, EShMessages messages)
 #endif
     intermediate[stage]->finalCheck(*infoSink, (messages & EShMsgKeepUncalled) != 0);
 
+#ifndef GLSLANG_ANGLE
     if (messages & EShMsgAST)
         intermediate[stage]->output(*infoSink, true);
+#endif
 
     return intermediate[stage]->getNumErrors() == 0;
 }
@@ -2023,7 +2059,7 @@ const char* TProgram::getInfoDebugLog()
     return infoSink->debug.c_str();
 }
 
-#ifndef GLSLANG_WEB
+#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
 
 //
 // Reflection implementation.
@@ -2105,6 +2141,6 @@ bool TProgram::mapIO(TIoMapResolver* pResolver, TIoMapper* pIoMapper)
     return ioMapper->doMap(pResolver, *infoSink);
 }
 
-#endif // GLSLANG_WEB
+#endif // !GLSLANG_WEB && !GLSLANG_ANGLE
 
 } // end namespace glslang

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

@@ -3,6 +3,7 @@
 // Copyright (C) 2012-2013 LunarG, Inc.
 // Copyright (C) 2017 ARM Limited.
 // Copyright (C) 2015-2018 Google, Inc.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 // All rights reserved.
 //
@@ -74,7 +75,8 @@ void TType::buildMangledName(TString& mangledName) const
     case EbtInt64:              mangledName += "i64";    break;
     case EbtUint64:             mangledName += "u64";    break;
     case EbtAtomicUint:         mangledName += "au";     break;
-    case EbtAccStructNV:        mangledName += "asnv";   break;
+    case EbtAccStruct:          mangledName += "as";     break;
+    case EbtRayQuery:           mangledName += "rq";     break;
 #endif
     case EbtSampler:
         switch (sampler.type) {
@@ -120,7 +122,7 @@ void TType::buildMangledName(TString& mangledName) const
             mangledName += "-tx-struct";
 
             char text[16]; // plenty enough space for the small integers.
-            snprintf(text, sizeof(text), "%d-", sampler.getStructReturnIndex());
+            snprintf(text, sizeof(text), "%u-", sampler.getStructReturnIndex());
             mangledName += text;
         } else {
             switch (sampler.getVectorSize()) {
@@ -176,7 +178,7 @@ void TType::buildMangledName(TString& mangledName) const
     }
 }
 
-#ifndef GLSLANG_WEB
+#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
 
 //
 // Dump functions.

+ 6 - 6
src/libraries/glslang/glslang/MachineIndependent/SymbolTable.h

@@ -117,7 +117,7 @@ public:
     virtual int getNumExtensions() const { return extensions == nullptr ? 0 : (int)extensions->size(); }
     virtual const char** getExtensions() const { return extensions->data(); }
 
-#ifndef GLSLANG_WEB
+#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
     virtual void dump(TInfoSink& infoSink, bool complete = false) const = 0;
     void dumpExtensions(TInfoSink& infoSink) const;
 #endif
@@ -196,7 +196,7 @@ public:
     }
     virtual const char** getMemberExtensions(int member) const { return (*memberExtensions)[member].data(); }
 
-#ifndef GLSLANG_WEB
+#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
     virtual void dump(TInfoSink& infoSink, bool complete = false) const;
 #endif
 
@@ -319,7 +319,7 @@ public:
     virtual TParameter& operator[](int i) { assert(writable); return parameters[i]; }
     virtual const TParameter& operator[](int i) const { return parameters[i]; }
 
-#ifndef GLSLANG_WEB
+#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
     virtual void dump(TInfoSink& infoSink, bool complete = false) const override;
 #endif
 
@@ -381,7 +381,7 @@ public:
     virtual const char** getExtensions() const override { return anonContainer.getMemberExtensions(memberNumber); }
 
     virtual int getAnonId() const { return anonId; }
-#ifndef GLSLANG_WEB
+#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
     virtual void dump(TInfoSink& infoSink, bool complete = false) const override;
 #endif
 
@@ -551,7 +551,7 @@ public:
 
     void relateToOperator(const char* name, TOperator op);
     void setFunctionExtensions(const char* name, int num, const char* const extensions[]);
-#ifndef GLSLANG_WEB
+#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
     void dump(TInfoSink& infoSink, bool complete = false) const;
 #endif
     TSymbolTableLevel* clone() const;
@@ -854,7 +854,7 @@ public:
     }
 
     int getMaxSymbolId() { return uniqueId; }
-#ifndef GLSLANG_WEB
+#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
     void dump(TInfoSink& infoSink, bool complete = false) const;
 #endif
     void copyTable(const TSymbolTable& copyOf);

+ 129 - 17
src/libraries/glslang/glslang/MachineIndependent/Versions.cpp

@@ -2,7 +2,8 @@
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2012-2013 LunarG, Inc.
 // Copyright (C) 2017 ARM Limited.
-// Copyright (C) 2015-2018 Google, Inc.
+// Copyright (C) 2015-2020 Google, Inc.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 // All rights reserved.
 //
@@ -63,6 +64,7 @@
 //        checkDeprecated()
 //        requireNotRemoved()
 //        requireExtensions()
+//        extensionRequires()
 //
 //    Typically, only the first two calls are needed.  They go into a code path that
 //    implements Feature F, and will log the proper error/warning messages.  Parsing
@@ -77,9 +79,11 @@
 //     const char* const XXX_extension_X = "XXX_extension_X";
 //
 // 2) Add extension initialization to TParseVersions::initializeExtensionBehavior(),
-//    the first function below:
+//    the first function below and optionally a entry to extensionData for additional
+//    error checks:
 //
 //     extensionBehavior[XXX_extension_X] = EBhDisable;
+//     (Optional) exts[] = {XXX_extension_X, EShTargetSpv_1_4}
 //
 // 3) Add any preprocessor directives etc. in the next function, TParseVersions::getPreamble():
 //
@@ -139,6 +143,8 @@
 //    set of extensions that both enable them and are necessary, given the version of the symbol
 //    table. (There is a different symbol table for each version.)
 //
+// 7) If the extension has additional requirements like minimum SPIR-V version required, add them
+//    to extensionRequires()
 
 #include "parseVersions.h"
 #include "localintermediate.h"
@@ -154,6 +160,20 @@ namespace glslang {
 //
 void TParseVersions::initializeExtensionBehavior()
 {
+    typedef struct {
+        const char *const extensionName;
+        EShTargetLanguageVersion minSpvVersion;
+    } extensionData;
+
+    const extensionData exts[] = { {E_GL_EXT_ray_tracing, EShTargetSpv_1_4} };
+
+    for (size_t ii = 0; ii < sizeof(exts) / sizeof(exts[0]); ii++) {
+        // Add only extensions which require > spv1.0 to save space in map
+        if (exts[ii].minSpvVersion > EShTargetSpv_1_0) {
+            extensionMinSpv[E_GL_EXT_ray_tracing] = exts[ii].minSpvVersion;
+        }
+    }
+
     extensionBehavior[E_GL_OES_texture_3D]                   = EBhDisable;
     extensionBehavior[E_GL_OES_standard_derivatives]         = EBhDisable;
     extensionBehavior[E_GL_EXT_frag_depth]                   = EBhDisable;
@@ -197,6 +217,12 @@ void TParseVersions::initializeExtensionBehavior()
     extensionBehavior[E_GL_ARB_shader_clock]                 = EBhDisable;
     extensionBehavior[E_GL_ARB_uniform_buffer_object]        = EBhDisable;
     extensionBehavior[E_GL_ARB_sample_shading]               = EBhDisable;
+    extensionBehavior[E_GL_ARB_shader_bit_encoding]          = EBhDisable;
+    extensionBehavior[E_GL_ARB_shader_image_size]            = EBhDisable;
+    extensionBehavior[E_GL_ARB_shader_storage_buffer_object] = EBhDisable;
+    extensionBehavior[E_GL_ARB_shading_language_packing]     = EBhDisable;
+    extensionBehavior[E_GL_ARB_texture_query_lod]            = EBhDisable;
+    extensionBehavior[E_GL_ARB_vertex_attrib_64bit]          = EBhDisable;
 
     extensionBehavior[E_GL_KHR_shader_subgroup_basic]            = EBhDisable;
     extensionBehavior[E_GL_KHR_shader_subgroup_vote]             = EBhDisable;
@@ -222,6 +248,7 @@ void TParseVersions::initializeExtensionBehavior()
     extensionBehavior[E_GL_EXT_buffer_reference2]                       = EBhDisable;
     extensionBehavior[E_GL_EXT_buffer_reference_uvec2]                  = EBhDisable;
     extensionBehavior[E_GL_EXT_demote_to_helper_invocation]             = EBhDisable;
+    extensionBehavior[E_GL_EXT_debug_printf]                            = EBhDisable;
 
     extensionBehavior[E_GL_EXT_shader_16bit_storage]                    = EBhDisable;
     extensionBehavior[E_GL_EXT_shader_8bit_storage]                     = EBhDisable;
@@ -290,11 +317,17 @@ void TParseVersions::initializeExtensionBehavior()
     extensionBehavior[E_GL_OES_tessellation_point_size]  = EBhDisable;
     extensionBehavior[E_GL_OES_texture_buffer]           = EBhDisable;
     extensionBehavior[E_GL_OES_texture_cube_map_array]   = EBhDisable;
+    extensionBehavior[E_GL_EXT_shader_integer_mix]       = EBhDisable;
 
     // EXT extensions
-    extensionBehavior[E_GL_EXT_device_group]             = EBhDisable;
-    extensionBehavior[E_GL_EXT_multiview]                = EBhDisable;
-    extensionBehavior[E_GL_EXT_shader_realtime_clock]    = EBhDisable;
+    extensionBehavior[E_GL_EXT_device_group]                = EBhDisable;
+    extensionBehavior[E_GL_EXT_multiview]                   = EBhDisable;
+    extensionBehavior[E_GL_EXT_shader_realtime_clock]       = EBhDisable;
+    extensionBehavior[E_GL_EXT_ray_tracing]                 = EBhDisable;
+    extensionBehavior[E_GL_EXT_ray_query]                   = EBhDisable;
+    extensionBehavior[E_GL_EXT_ray_flags_primitive_culling] = EBhDisable;
+    extensionBehavior[E_GL_EXT_blend_func_extended]         = EBhDisable;
+    extensionBehavior[E_GL_EXT_shader_implicit_conversions] = EBhDisable;
 
     // OVR extensions
     extensionBehavior[E_GL_OVR_multiview]                = EBhDisable;
@@ -315,7 +348,9 @@ void TParseVersions::initializeExtensionBehavior()
     extensionBehavior[E_GL_EXT_shader_subgroup_extended_types_int16]   = EBhDisable;
     extensionBehavior[E_GL_EXT_shader_subgroup_extended_types_int64]   = EBhDisable;
     extensionBehavior[E_GL_EXT_shader_subgroup_extended_types_float16] = EBhDisable;
+    extensionBehavior[E_GL_EXT_shader_atomic_float]                    = EBhDisable;
 }
+
 #endif // GLSLANG_WEB
 
 // Get code that is not part of a shared symbol table, is specific to this shader,
@@ -354,6 +389,9 @@ void TParseVersions::getPreamble(std::string& preamble)
             "#define GL_EXT_tessellation_point_size 1\n"
             "#define GL_EXT_texture_buffer 1\n"
             "#define GL_EXT_texture_cube_map_array 1\n"
+            "#define GL_EXT_shader_implicit_conversions 1\n"
+            "#define GL_EXT_shader_integer_mix 1\n"
+            "#define GL_EXT_blend_func_extended 1\n"
 
             // OES matching AEP
             "#define GL_OES_geometry_shader 1\n"
@@ -403,10 +441,16 @@ void TParseVersions::getPreamble(std::string& preamble)
             "#define GL_ARB_sparse_texture_clamp 1\n"
             "#define GL_ARB_shader_stencil_export 1\n"
             "#define GL_ARB_sample_shading 1\n"
+            "#define GL_ARB_shader_image_size 1\n"
+            "#define GL_ARB_shading_language_packing 1\n"
 //            "#define GL_ARB_cull_distance 1\n"    // present for 4.5, but need extension control over block members
             "#define GL_ARB_post_depth_coverage 1\n"
             "#define GL_ARB_fragment_shader_interlock 1\n"
             "#define GL_ARB_uniform_buffer_object 1\n"
+            "#define GL_ARB_shader_bit_encoding 1\n"
+            "#define GL_ARB_shader_storage_buffer_object 1\n"
+            "#define GL_ARB_texture_query_lod 1\n"
+            "#define GL_ARB_vertex_attrib_64bit 1\n"
             "#define GL_EXT_shader_non_constant_global_initializers 1\n"
             "#define GL_EXT_shader_image_load_formatted 1\n"
             "#define GL_EXT_post_depth_coverage 1\n"
@@ -421,6 +465,7 @@ void TParseVersions::getPreamble(std::string& preamble)
             "#define GL_EXT_buffer_reference2 1\n"
             "#define GL_EXT_buffer_reference_uvec2 1\n"
             "#define GL_EXT_demote_to_helper_invocation 1\n"
+            "#define GL_EXT_debug_printf 1\n"
 
             // GL_KHR_shader_subgroup
             "#define GL_KHR_shader_subgroup_basic 1\n"
@@ -432,8 +477,11 @@ void TParseVersions::getPreamble(std::string& preamble)
             "#define GL_KHR_shader_subgroup_clustered 1\n"
             "#define GL_KHR_shader_subgroup_quad 1\n"
 
-            "#define E_GL_EXT_shader_atomic_int64 1\n"
-            "#define E_GL_EXT_shader_realtime_clock 1\n"
+            "#define GL_EXT_shader_atomic_int64 1\n"
+            "#define GL_EXT_shader_realtime_clock 1\n"
+            "#define GL_EXT_ray_tracing 1\n"
+            "#define GL_EXT_ray_query 1\n"
+            "#define GL_EXT_ray_flags_primitive_culling 1\n"
 
             "#define GL_AMD_shader_ballot 1\n"
             "#define GL_AMD_shader_trinary_minmax 1\n"
@@ -476,6 +524,8 @@ void TParseVersions::getPreamble(std::string& preamble)
             "#define GL_EXT_shader_subgroup_extended_types_int16 1\n"
             "#define GL_EXT_shader_subgroup_extended_types_int64 1\n"
             "#define GL_EXT_shader_subgroup_extended_types_float16 1\n"
+
+            "#define GL_EXT_shader_atomic_float 1\n"
             ;
 
         if (version >= 150) {
@@ -547,12 +597,12 @@ const char* StageName(EShLanguage stage)
     case EShLangTessControl:    return "tessellation control";
     case EShLangTessEvaluation: return "tessellation evaluation";
     case EShLangGeometry:       return "geometry";
-    case EShLangRayGenNV:       return "ray-generation";
-    case EShLangIntersectNV:    return "intersection";
-    case EShLangAnyHitNV:       return "any-hit";
-    case EShLangClosestHitNV:   return "closest-hit";
-    case EShLangMissNV:         return "miss";
-    case EShLangCallableNV:     return "callable";
+    case EShLangRayGen:         return "ray-generation";
+    case EShLangIntersect:      return "intersection";
+    case EShLangAnyHit:         return "any-hit";
+    case EShLangClosestHit:     return "closest-hit";
+    case EShLangMiss:           return "miss";
+    case EShLangCallable:       return "callable";
     case EShLangMeshNV:         return "mesh";
     case EShLangTaskNV:         return "task";
 #endif
@@ -715,7 +765,8 @@ bool TParseVersions::checkExtensionsRequested(const TSourceLoc& loc, int numExte
 // Use when there are no profile/version to check, it's just an error if one of the
 // extensions is not present.
 //
-void TParseVersions::requireExtensions(const TSourceLoc& loc, int numExtensions, const char* const extensions[], const char* featureDesc)
+void TParseVersions::requireExtensions(const TSourceLoc& loc, int numExtensions, const char* const extensions[],
+    const char* featureDesc)
 {
     if (checkExtensionsRequested(loc, numExtensions, extensions, featureDesc))
         return;
@@ -734,7 +785,8 @@ void TParseVersions::requireExtensions(const TSourceLoc& loc, int numExtensions,
 // Use by preprocessor when there are no profile/version to check, it's just an error if one of the
 // extensions is not present.
 //
-void TParseVersions::ppRequireExtensions(const TSourceLoc& loc, int numExtensions, const char* const extensions[], const char* featureDesc)
+void TParseVersions::ppRequireExtensions(const TSourceLoc& loc, int numExtensions, const char* const extensions[],
+    const char* featureDesc)
 {
     if (checkExtensionsRequested(loc, numExtensions, extensions, featureDesc))
         return;
@@ -800,10 +852,14 @@ void TParseVersions::updateExtensionBehavior(int line, const char* extension, co
         error(getCurrentLoc(), "behavior not supported:", "#extension", behaviorString);
         return;
     }
+    bool on = behavior != EBhDisable;
 
     // check if extension is used with correct shader stage
     checkExtensionStage(getCurrentLoc(), extension);
 
+    // check if extension has additional requirements
+    extensionRequires(getCurrentLoc(), extension ,behaviorString);
+
     // update the requested extension
     updateExtensionBehavior(extension, behavior);
 
@@ -866,6 +922,32 @@ void TParseVersions::updateExtensionBehavior(int line, const char* extension, co
         updateExtensionBehavior(line, "GL_EXT_shader_explicit_arithmetic_types_int64", behaviorString);
     else if (strcmp(extension, "GL_EXT_shader_subgroup_extended_types_float16") == 0)
         updateExtensionBehavior(line, "GL_EXT_shader_explicit_arithmetic_types_float16", behaviorString);
+
+    // see if we need to update the numeric features
+    else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types") == 0)
+        intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types, on);
+    else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types_int8") == 0)
+        intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types_int8, on);
+    else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types_int16") == 0)
+        intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types_int16, on);
+    else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types_int32") == 0)
+        intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types_int32, on);
+    else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types_int64") == 0)
+        intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types_int64, on);
+    else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types_float16") == 0)
+        intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types_float16, on);
+    else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types_float32") == 0)
+        intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types_float32, on);
+    else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types_float64") == 0)
+        intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types_float64, on);
+    else if (strcmp(extension, "GL_EXT_shader_implicit_conversions") == 0)
+        intermediate.updateNumericFeature(TNumericFeatures::shader_implicit_conversions, on);
+    else if (strcmp(extension, "GL_ARB_gpu_shader_fp64") == 0)
+        intermediate.updateNumericFeature(TNumericFeatures::gpu_shader_fp64, on);
+    else if (strcmp(extension, "GL_AMD_gpu_shader_int16") == 0)
+        intermediate.updateNumericFeature(TNumericFeatures::gpu_shader_int16, on);
+    else if (strcmp(extension, "GL_AMD_gpu_shader_half_float") == 0)
+        intermediate.updateNumericFeature(TNumericFeatures::gpu_shader_half_float, on);
 }
 
 void TParseVersions::updateExtensionBehavior(const char* extension, TExtensionBehavior behavior)
@@ -901,7 +983,7 @@ void TParseVersions::updateExtensionBehavior(const char* extension, TExtensionBe
         } else {
             if (iter->second == EBhDisablePartial)
                 warn(getCurrentLoc(), "extension is only partially supported:", "#extension", extension);
-            if (behavior == EBhEnable || behavior == EBhRequire)
+            if (behavior != EBhDisable)
                 intermediate.addRequestedExtension(extension);
             iter->second = behavior;
         }
@@ -920,6 +1002,24 @@ void TParseVersions::checkExtensionStage(const TSourceLoc& loc, const char * con
     }
 }
 
+// Check if extension has additional requirements
+void TParseVersions::extensionRequires(const TSourceLoc &loc, const char * const extension, const char *behaviorString)
+{
+    bool isEnabled = false;
+    if (!strcmp("require", behaviorString))
+        isEnabled = true;
+    else if (!strcmp("enable", behaviorString))
+        isEnabled = true;
+
+    if (isEnabled) {
+        unsigned int minSpvVersion = 0;
+        auto iter = extensionMinSpv.find(TString(extension));
+        if (iter != extensionMinSpv.end())
+            minSpvVersion = iter->second;
+        requireSpv(loc, extension, minSpvVersion);
+    }
+}
+
 // Call for any operation needing full GLSL integer data-type support.
 void TParseVersions::fullIntegerCheck(const TSourceLoc& loc, const char* op)
 {
@@ -930,8 +1030,13 @@ void TParseVersions::fullIntegerCheck(const TSourceLoc& loc, const char* op)
 // Call for any operation needing GLSL double data-type support.
 void TParseVersions::doubleCheck(const TSourceLoc& loc, const char* op)
 {
+
     //requireProfile(loc, ECoreProfile | ECompatibilityProfile, op);
-    profileRequires(loc, ECoreProfile | ECompatibilityProfile, 400, E_GL_ARB_gpu_shader_fp64, op);
+    if (language == EShLangVertex) {
+        const char* const f64_Extensions[] = {E_GL_ARB_gpu_shader_fp64, E_GL_ARB_vertex_attrib_64bit};
+        profileRequires(loc, ECoreProfile | ECompatibilityProfile, 400, 2, f64_Extensions, op);
+    } else
+        profileRequires(loc, ECoreProfile | ECompatibilityProfile, 400, E_GL_ARB_gpu_shader_fp64, op);
 }
 
 // Call for any operation needing GLSL float16 data-type support.
@@ -1172,5 +1277,12 @@ void TParseVersions::requireSpv(const TSourceLoc& loc, const char* op)
         error(loc, "only allowed when generating SPIR-V", op, "");
 #endif
 }
+void TParseVersions::requireSpv(const TSourceLoc& loc, const char *op, unsigned int version)
+{
+#ifndef GLSLANG_WEB
+    if (spvVersion.spv < version)
+        error(loc, "not supported for current targeted SPIR-V version", op, "");
+#endif
+}
 
 } // end namespace glslang

+ 22 - 2
src/libraries/glslang/glslang/MachineIndependent/Versions.h

@@ -3,6 +3,7 @@
 // Copyright (C) 2012-2013 LunarG, Inc.
 // Copyright (C) 2017 ARM Limited.
 // Copyright (C) 2015-2018 Google, Inc.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 // All rights reserved.
 //
@@ -35,9 +36,12 @@
 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 // POSSIBILITY OF SUCH DAMAGE.
 //
+
 #ifndef _VERSIONS_INCLUDED_
 #define _VERSIONS_INCLUDED_
 
+#define LAST_ELEMENT_MARKER(x) x
+
 //
 // Help manage multiple profiles, versions, extensions etc.
 //
@@ -49,12 +53,13 @@
 // Don't maintain an ordinal set of enums (0,1,2,3...) to avoid all possible
 // defects from mixing the two different forms.
 //
-typedef enum {
+typedef enum : unsigned {
     EBadProfile           = 0,
     ENoProfile            = (1 << 0), // only for desktop, before profiles showed up
     ECoreProfile          = (1 << 1),
     ECompatibilityProfile = (1 << 2),
-    EEsProfile            = (1 << 3)
+    EEsProfile            = (1 << 3),
+    LAST_ELEMENT_MARKER(EProfileCount),
 } EProfile;
 
 namespace glslang {
@@ -149,6 +154,12 @@ const char* const E_GL_ARB_fragment_shader_interlock    = "GL_ARB_fragment_shade
 const char* const E_GL_ARB_shader_clock                 = "GL_ARB_shader_clock";
 const char* const E_GL_ARB_uniform_buffer_object        = "GL_ARB_uniform_buffer_object";
 const char* const E_GL_ARB_sample_shading               = "GL_ARB_sample_shading";
+const char* const E_GL_ARB_shader_bit_encoding          = "GL_ARB_shader_bit_encoding";
+const char* const E_GL_ARB_shader_image_size            = "GL_ARB_shader_image_size";
+const char* const E_GL_ARB_shader_storage_buffer_object = "GL_ARB_shader_storage_buffer_object";
+const char* const E_GL_ARB_shading_language_packing     = "GL_ARB_shading_language_packing";
+const char* const E_GL_ARB_texture_query_lod            = "GL_ARB_texture_query_lod";
+const char* const E_GL_ARB_vertex_attrib_64bit          = "GL_ARB_vertex_attrib_64bit";
 
 const char* const E_GL_KHR_shader_subgroup_basic            = "GL_KHR_shader_subgroup_basic";
 const char* const E_GL_KHR_shader_subgroup_vote             = "GL_KHR_shader_subgroup_vote";
@@ -183,6 +194,12 @@ const char* const E_GL_EXT_buffer_reference2                = "GL_EXT_buffer_ref
 const char* const E_GL_EXT_buffer_reference_uvec2           = "GL_EXT_buffer_reference_uvec2";
 const char* const E_GL_EXT_demote_to_helper_invocation      = "GL_EXT_demote_to_helper_invocation";
 const char* const E_GL_EXT_shader_realtime_clock            = "GL_EXT_shader_realtime_clock";
+const char* const E_GL_EXT_debug_printf                     = "GL_EXT_debug_printf";
+const char* const E_GL_EXT_ray_tracing                      = "GL_EXT_ray_tracing";
+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_blend_func_extended              = "GL_EXT_blend_func_extended";
+const char* const E_GL_EXT_shader_implicit_conversions      = "GL_EXT_shader_implicit_conversions";
 
 // Arrays of extensions for the above viewportEXTs duplications
 
@@ -254,6 +271,7 @@ const char* const E_GL_EXT_tessellation_shader                  = "GL_EXT_tessel
 const char* const E_GL_EXT_tessellation_point_size              = "GL_EXT_tessellation_point_size";
 const char* const E_GL_EXT_texture_buffer                       = "GL_EXT_texture_buffer";
 const char* const E_GL_EXT_texture_cube_map_array               = "GL_EXT_texture_cube_map_array";
+const char* const E_GL_EXT_shader_integer_mix                   = "GL_EXT_shader_integer_mix"; 
 
 // OES matching AEP
 const char* const E_GL_OES_geometry_shader                      = "GL_OES_geometry_shader";
@@ -281,6 +299,8 @@ const char* const E_GL_EXT_shader_subgroup_extended_types_int16   = "GL_EXT_shad
 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_atomic_float = "GL_EXT_shader_atomic_float";
+
 // Arrays of extensions for the above AEP duplications
 
 const char* const AEP_geometry_shader[] = { E_GL_EXT_geometry_shader, E_GL_OES_geometry_shader };

+ 8 - 0
src/libraries/glslang/glslang/MachineIndependent/gl_types.h

@@ -52,6 +52,14 @@
 #define GL_UNSIGNED_INT64_VEC2_ARB        0x8FE5
 #define GL_UNSIGNED_INT64_VEC3_ARB        0x8FE6
 #define GL_UNSIGNED_INT64_VEC4_ARB        0x8FE7
+#define GL_UNSIGNED_INT16_VEC2_NV         0x8FF1
+#define GL_UNSIGNED_INT16_VEC3_NV         0x8FF2
+#define GL_UNSIGNED_INT16_VEC4_NV         0x8FF3
+
+#define GL_INT16_NV                       0x8FE4
+#define GL_INT16_VEC2_NV                  0x8FE5
+#define GL_INT16_VEC3_NV                  0x8FE6
+#define GL_INT16_VEC4_NV                  0x8FE7
 
 #define GL_BOOL                           0x8B56
 #define GL_BOOL_VEC2                      0x8B57

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


+ 261 - 252
src/libraries/glslang/glslang/MachineIndependent/glslang_tab.cpp.h

@@ -203,256 +203,265 @@ extern int yydebug;
     F64MAT4X4 = 413,
     ATOMIC_UINT = 414,
     ACCSTRUCTNV = 415,
-    FCOOPMATNV = 416,
-    ICOOPMATNV = 417,
-    UCOOPMATNV = 418,
-    SAMPLERCUBEARRAY = 419,
-    SAMPLERCUBEARRAYSHADOW = 420,
-    ISAMPLERCUBEARRAY = 421,
-    USAMPLERCUBEARRAY = 422,
-    SAMPLER1D = 423,
-    SAMPLER1DARRAY = 424,
-    SAMPLER1DARRAYSHADOW = 425,
-    ISAMPLER1D = 426,
-    SAMPLER1DSHADOW = 427,
-    SAMPLER2DRECT = 428,
-    SAMPLER2DRECTSHADOW = 429,
-    ISAMPLER2DRECT = 430,
-    USAMPLER2DRECT = 431,
-    SAMPLERBUFFER = 432,
-    ISAMPLERBUFFER = 433,
-    USAMPLERBUFFER = 434,
-    SAMPLER2DMS = 435,
-    ISAMPLER2DMS = 436,
-    USAMPLER2DMS = 437,
-    SAMPLER2DMSARRAY = 438,
-    ISAMPLER2DMSARRAY = 439,
-    USAMPLER2DMSARRAY = 440,
-    SAMPLEREXTERNALOES = 441,
-    SAMPLEREXTERNAL2DY2YEXT = 442,
-    ISAMPLER1DARRAY = 443,
-    USAMPLER1D = 444,
-    USAMPLER1DARRAY = 445,
-    F16SAMPLER1D = 446,
-    F16SAMPLER2D = 447,
-    F16SAMPLER3D = 448,
-    F16SAMPLER2DRECT = 449,
-    F16SAMPLERCUBE = 450,
-    F16SAMPLER1DARRAY = 451,
-    F16SAMPLER2DARRAY = 452,
-    F16SAMPLERCUBEARRAY = 453,
-    F16SAMPLERBUFFER = 454,
-    F16SAMPLER2DMS = 455,
-    F16SAMPLER2DMSARRAY = 456,
-    F16SAMPLER1DSHADOW = 457,
-    F16SAMPLER2DSHADOW = 458,
-    F16SAMPLER1DARRAYSHADOW = 459,
-    F16SAMPLER2DARRAYSHADOW = 460,
-    F16SAMPLER2DRECTSHADOW = 461,
-    F16SAMPLERCUBESHADOW = 462,
-    F16SAMPLERCUBEARRAYSHADOW = 463,
-    IMAGE1D = 464,
-    IIMAGE1D = 465,
-    UIMAGE1D = 466,
-    IMAGE2D = 467,
-    IIMAGE2D = 468,
-    UIMAGE2D = 469,
-    IMAGE3D = 470,
-    IIMAGE3D = 471,
-    UIMAGE3D = 472,
-    IMAGE2DRECT = 473,
-    IIMAGE2DRECT = 474,
-    UIMAGE2DRECT = 475,
-    IMAGECUBE = 476,
-    IIMAGECUBE = 477,
-    UIMAGECUBE = 478,
-    IMAGEBUFFER = 479,
-    IIMAGEBUFFER = 480,
-    UIMAGEBUFFER = 481,
-    IMAGE1DARRAY = 482,
-    IIMAGE1DARRAY = 483,
-    UIMAGE1DARRAY = 484,
-    IMAGE2DARRAY = 485,
-    IIMAGE2DARRAY = 486,
-    UIMAGE2DARRAY = 487,
-    IMAGECUBEARRAY = 488,
-    IIMAGECUBEARRAY = 489,
-    UIMAGECUBEARRAY = 490,
-    IMAGE2DMS = 491,
-    IIMAGE2DMS = 492,
-    UIMAGE2DMS = 493,
-    IMAGE2DMSARRAY = 494,
-    IIMAGE2DMSARRAY = 495,
-    UIMAGE2DMSARRAY = 496,
-    F16IMAGE1D = 497,
-    F16IMAGE2D = 498,
-    F16IMAGE3D = 499,
-    F16IMAGE2DRECT = 500,
-    F16IMAGECUBE = 501,
-    F16IMAGE1DARRAY = 502,
-    F16IMAGE2DARRAY = 503,
-    F16IMAGECUBEARRAY = 504,
-    F16IMAGEBUFFER = 505,
-    F16IMAGE2DMS = 506,
-    F16IMAGE2DMSARRAY = 507,
-    TEXTURECUBEARRAY = 508,
-    ITEXTURECUBEARRAY = 509,
-    UTEXTURECUBEARRAY = 510,
-    TEXTURE1D = 511,
-    ITEXTURE1D = 512,
-    UTEXTURE1D = 513,
-    TEXTURE1DARRAY = 514,
-    ITEXTURE1DARRAY = 515,
-    UTEXTURE1DARRAY = 516,
-    TEXTURE2DRECT = 517,
-    ITEXTURE2DRECT = 518,
-    UTEXTURE2DRECT = 519,
-    TEXTUREBUFFER = 520,
-    ITEXTUREBUFFER = 521,
-    UTEXTUREBUFFER = 522,
-    TEXTURE2DMS = 523,
-    ITEXTURE2DMS = 524,
-    UTEXTURE2DMS = 525,
-    TEXTURE2DMSARRAY = 526,
-    ITEXTURE2DMSARRAY = 527,
-    UTEXTURE2DMSARRAY = 528,
-    F16TEXTURE1D = 529,
-    F16TEXTURE2D = 530,
-    F16TEXTURE3D = 531,
-    F16TEXTURE2DRECT = 532,
-    F16TEXTURECUBE = 533,
-    F16TEXTURE1DARRAY = 534,
-    F16TEXTURE2DARRAY = 535,
-    F16TEXTURECUBEARRAY = 536,
-    F16TEXTUREBUFFER = 537,
-    F16TEXTURE2DMS = 538,
-    F16TEXTURE2DMSARRAY = 539,
-    SUBPASSINPUT = 540,
-    SUBPASSINPUTMS = 541,
-    ISUBPASSINPUT = 542,
-    ISUBPASSINPUTMS = 543,
-    USUBPASSINPUT = 544,
-    USUBPASSINPUTMS = 545,
-    F16SUBPASSINPUT = 546,
-    F16SUBPASSINPUTMS = 547,
-    LEFT_OP = 548,
-    RIGHT_OP = 549,
-    INC_OP = 550,
-    DEC_OP = 551,
-    LE_OP = 552,
-    GE_OP = 553,
-    EQ_OP = 554,
-    NE_OP = 555,
-    AND_OP = 556,
-    OR_OP = 557,
-    XOR_OP = 558,
-    MUL_ASSIGN = 559,
-    DIV_ASSIGN = 560,
-    ADD_ASSIGN = 561,
-    MOD_ASSIGN = 562,
-    LEFT_ASSIGN = 563,
-    RIGHT_ASSIGN = 564,
-    AND_ASSIGN = 565,
-    XOR_ASSIGN = 566,
-    OR_ASSIGN = 567,
-    SUB_ASSIGN = 568,
-    LEFT_PAREN = 569,
-    RIGHT_PAREN = 570,
-    LEFT_BRACKET = 571,
-    RIGHT_BRACKET = 572,
-    LEFT_BRACE = 573,
-    RIGHT_BRACE = 574,
-    DOT = 575,
-    COMMA = 576,
-    COLON = 577,
-    EQUAL = 578,
-    SEMICOLON = 579,
-    BANG = 580,
-    DASH = 581,
-    TILDE = 582,
-    PLUS = 583,
-    STAR = 584,
-    SLASH = 585,
-    PERCENT = 586,
-    LEFT_ANGLE = 587,
-    RIGHT_ANGLE = 588,
-    VERTICAL_BAR = 589,
-    CARET = 590,
-    AMPERSAND = 591,
-    QUESTION = 592,
-    INVARIANT = 593,
-    HIGH_PRECISION = 594,
-    MEDIUM_PRECISION = 595,
-    LOW_PRECISION = 596,
-    PRECISION = 597,
-    PACKED = 598,
-    RESOURCE = 599,
-    SUPERP = 600,
-    FLOATCONSTANT = 601,
-    INTCONSTANT = 602,
-    UINTCONSTANT = 603,
-    BOOLCONSTANT = 604,
-    IDENTIFIER = 605,
-    TYPE_NAME = 606,
-    CENTROID = 607,
-    IN = 608,
-    OUT = 609,
-    INOUT = 610,
-    STRUCT = 611,
-    VOID = 612,
-    WHILE = 613,
-    BREAK = 614,
-    CONTINUE = 615,
-    DO = 616,
-    ELSE = 617,
-    FOR = 618,
-    IF = 619,
-    DISCARD = 620,
-    RETURN = 621,
-    SWITCH = 622,
-    CASE = 623,
-    DEFAULT = 624,
-    UNIFORM = 625,
-    SHARED = 626,
-    BUFFER = 627,
-    FLAT = 628,
-    SMOOTH = 629,
-    LAYOUT = 630,
-    DOUBLECONSTANT = 631,
-    INT16CONSTANT = 632,
-    UINT16CONSTANT = 633,
-    FLOAT16CONSTANT = 634,
-    INT32CONSTANT = 635,
-    UINT32CONSTANT = 636,
-    INT64CONSTANT = 637,
-    UINT64CONSTANT = 638,
-    SUBROUTINE = 639,
-    DEMOTE = 640,
-    PAYLOADNV = 641,
-    PAYLOADINNV = 642,
-    HITATTRNV = 643,
-    CALLDATANV = 644,
-    CALLDATAINNV = 645,
-    PATCH = 646,
-    SAMPLE = 647,
-    NONUNIFORM = 648,
-    COHERENT = 649,
-    VOLATILE = 650,
-    RESTRICT = 651,
-    READONLY = 652,
-    WRITEONLY = 653,
-    DEVICECOHERENT = 654,
-    QUEUEFAMILYCOHERENT = 655,
-    WORKGROUPCOHERENT = 656,
-    SUBGROUPCOHERENT = 657,
-    NONPRIVATE = 658,
-    NOPERSPECTIVE = 659,
-    EXPLICITINTERPAMD = 660,
-    PERVERTEXNV = 661,
-    PERPRIMITIVENV = 662,
-    PERVIEWNV = 663,
-    PERTASKNV = 664,
-    PRECISE = 665
+    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
   };
 #endif
 
@@ -461,7 +470,7 @@ extern int yydebug;
 
 union YYSTYPE
 {
-#line 96 "MachineIndependent/glslang.y" /* yacc.c:1909  */
+#line 97 "MachineIndependent/glslang.y" /* yacc.c:1909  */
 
     struct {
         glslang::TSourceLoc loc;
@@ -497,7 +506,7 @@ union YYSTYPE
         glslang::TArraySizes* typeParameters;
     } interm;
 
-#line 501 "MachineIndependent/glslang_tab.cpp.h" /* yacc.c:1909  */
+#line 510 "MachineIndependent/glslang_tab.cpp.h" /* yacc.c:1909  */
 };
 
 typedef union YYSTYPE YYSTYPE;

+ 33 - 7
src/libraries/glslang/glslang/MachineIndependent/intermOut.cpp

@@ -2,6 +2,7 @@
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2012-2016 LunarG, Inc.
 // Copyright (C) 2017 ARM Limited.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 // All rights reserved.
 //
@@ -35,7 +36,7 @@
 // POSSIBILITY OF SUCH DAMAGE.
 //
 
-#ifndef GLSLANG_WEB
+#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
 
 #include "localintermediate.h"
 #include "../Include/InfoSink.h"
@@ -1078,18 +1079,43 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
     case EOpSubpassLoad:   out.debug << "subpassLoad";   break;
     case EOpSubpassLoadMS: out.debug << "subpassLoadMS"; break;
 
-    case EOpTraceNV:                          out.debug << "traceNV"; break;
-    case EOpReportIntersectionNV:             out.debug << "reportIntersectionNV"; break;
-    case EOpIgnoreIntersectionNV:             out.debug << "ignoreIntersectionNV"; break;
-    case EOpTerminateRayNV:                   out.debug << "terminateRayNV"; break;
-    case EOpExecuteCallableNV:                out.debug << "executeCallableNV"; break;
+    case EOpTrace:                            out.debug << "traceNV"; 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 EOpWritePackedPrimitiveIndices4x8NV: out.debug << "writePackedPrimitiveIndices4x8NV"; break;
 
+    case EOpRayQueryInitialize:                                            out.debug << "rayQueryInitializeEXT"; break;
+    case EOpRayQueryTerminate:                                             out.debug << "rayQueryTerminateEXT"; break;
+    case EOpRayQueryGenerateIntersection:                                  out.debug << "rayQueryGenerateIntersectionEXT"; break;
+    case EOpRayQueryConfirmIntersection:                                   out.debug << "rayQueryConfirmIntersectionEXT"; break;
+    case EOpRayQueryProceed:                                               out.debug << "rayQueryProceedEXT"; break;
+    case EOpRayQueryGetIntersectionType:                                   out.debug << "rayQueryGetIntersectionTypeEXT"; break;
+    case EOpRayQueryGetRayTMin:                                            out.debug << "rayQueryGetRayTMinEXT"; break;
+    case EOpRayQueryGetRayFlags:                                           out.debug << "rayQueryGetRayFlagsEXT"; break;
+    case EOpRayQueryGetIntersectionT:                                      out.debug << "rayQueryGetIntersectionTEXT"; break;
+    case EOpRayQueryGetIntersectionInstanceCustomIndex:                    out.debug << "rayQueryGetIntersectionInstanceCustomIndexEXT"; break;
+    case EOpRayQueryGetIntersectionInstanceId:                             out.debug << "rayQueryGetIntersectionInstanceIdEXT"; break;
+    case EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset: out.debug << "rayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetEXT"; break;
+    case EOpRayQueryGetIntersectionGeometryIndex:                          out.debug << "rayQueryGetIntersectionGeometryIndexEXT"; break;
+    case EOpRayQueryGetIntersectionPrimitiveIndex:                         out.debug << "rayQueryGetIntersectionPrimitiveIndexEXT"; break;
+    case EOpRayQueryGetIntersectionBarycentrics:                           out.debug << "rayQueryGetIntersectionBarycentricsEXT"; break;
+    case EOpRayQueryGetIntersectionFrontFace:                              out.debug << "rayQueryGetIntersectionFrontFaceEXT"; break;
+    case EOpRayQueryGetIntersectionCandidateAABBOpaque:                    out.debug << "rayQueryGetIntersectionCandidateAABBOpaqueEXT"; break;
+    case EOpRayQueryGetIntersectionObjectRayDirection:                     out.debug << "rayQueryGetIntersectionObjectRayDirectionEXT"; break;
+    case EOpRayQueryGetIntersectionObjectRayOrigin:                        out.debug << "rayQueryGetIntersectionObjectRayOriginEXT"; break;
+    case EOpRayQueryGetWorldRayDirection:                                  out.debug << "rayQueryGetWorldRayDirectionEXT"; break;
+    case EOpRayQueryGetWorldRayOrigin:                                     out.debug << "rayQueryGetWorldRayOriginEXT"; break;
+    case EOpRayQueryGetIntersectionObjectToWorld:                          out.debug << "rayQueryGetIntersectionObjectToWorldEXT"; break;
+    case EOpRayQueryGetIntersectionWorldToObject:                          out.debug << "rayQueryGetIntersectionWorldToObjectEXT"; break;
+
     case EOpCooperativeMatrixLoad:  out.debug << "Load cooperative matrix";  break;
     case EOpCooperativeMatrixStore:  out.debug << "Store cooperative matrix";  break;
     case EOpCooperativeMatrixMulAdd: out.debug << "MulAdd cooperative matrices"; break;
 
     case EOpIsHelperInvocation: out.debug << "IsHelperInvocation"; break;
+    case EOpDebugPrintf:  out.debug << "Debug printf";  break;
 
     default: out.debug.message(EPrefixError, "Bad aggregation op");
     }
@@ -1536,4 +1562,4 @@ void TIntermediate::output(TInfoSink& infoSink, bool tree)
 
 } // end namespace glslang
 
-#endif // not GLSLANG_WEB
+#endif // !GLSLANG_WEB && !GLSLANG_ANGLE

+ 74 - 32
src/libraries/glslang/glslang/MachineIndependent/iomapper.cpp

@@ -33,7 +33,7 @@
 // POSSIBILITY OF SUCH DAMAGE.
 //
 
-#ifndef GLSLANG_WEB
+#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
 
 #include "../Include/Common.h"
 #include "../Include/InfoSink.h"
@@ -79,6 +79,11 @@ public:
             target = &outputList;
         else if (base->getQualifier().isUniformOrBuffer() && !base->getQualifier().isPushConstant())
             target = &uniformList;
+        // 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
+        else if (base->getQualifier().storage == EvqGlobal)
+            addGlobalReference(base->getName());
+
         if (target) {
             TVarEntryInfo ent = {base->getId(), base, ! traverseAll};
             ent.stage = intermediate.getStage();
@@ -161,7 +166,7 @@ struct TNotifyUniformAdaptor
     }
 
 private:
-    TNotifyUniformAdaptor& operator=(TNotifyUniformAdaptor&);
+    TNotifyUniformAdaptor& operator=(TNotifyUniformAdaptor&) = delete;
 };
 
 struct TNotifyInOutAdaptor
@@ -180,7 +185,7 @@ struct TNotifyInOutAdaptor
     }
 
 private:
-    TNotifyInOutAdaptor& operator=(TNotifyInOutAdaptor&);
+    TNotifyInOutAdaptor& operator=(TNotifyInOutAdaptor&) = delete;
 };
 
 struct TResolverUniformAdaptor {
@@ -236,7 +241,7 @@ struct TResolverUniformAdaptor {
     bool&           error;
 
 private:
-    TResolverUniformAdaptor& operator=(TResolverUniformAdaptor&);
+    TResolverUniformAdaptor& operator=(TResolverUniformAdaptor&) = delete;
 };
 
 struct TResolverInOutAdaptor {
@@ -283,7 +288,7 @@ struct TResolverInOutAdaptor {
     bool&           error;
 
 private:
-    TResolverInOutAdaptor& operator=(TResolverInOutAdaptor&);
+    TResolverInOutAdaptor& operator=(TResolverInOutAdaptor&) = delete;
 };
 
 // The class is used for reserving explicit uniform locations and ubo/ssbo/opaque bindings
@@ -309,26 +314,43 @@ struct TSymbolValidater
         TIntermSymbol* base = ent1.symbol;
         const TType& type = ent1.symbol->getType();
         const TString& name = entKey.first;
-        TString mangleName1, mangleName2;
-        type.appendMangledName(mangleName1);
         EShLanguage stage = ent1.stage;
+        TString mangleName1, mangleName2;
         if (currentStage != stage) {
             preStage = currentStage;
             currentStage = stage;
             nextStage = EShLangCount;
             for (int i = currentStage + 1; i < EShLangCount; i++) {
-                if (inVarMaps[i] != nullptr)
+                if (inVarMaps[i] != nullptr) {
                     nextStage = static_cast<EShLanguage>(i);
+                    break;
+                }
             }
         }
+
+        if (type.getQualifier().isArrayedIo(stage)) {
+            TType subType(type, 0);
+            subType.appendMangledName(mangleName1);
+        } else {
+            type.appendMangledName(mangleName1);
+        }
+
         if (base->getQualifier().storage == EvqVaryingIn) {
             // validate stage in;
             if (preStage == EShLangCount)
                 return;
+            if (name == "gl_PerVertex")
+                return;
             if (outVarMaps[preStage] != nullptr) {
                 auto ent2 = outVarMaps[preStage]->find(name);
                 if (ent2 != outVarMaps[preStage]->end()) {
-                    ent2->second.symbol->getType().appendMangledName(mangleName2);
+                    if (ent2->second.symbol->getType().getQualifier().isArrayedIo(preStage)) {
+                        TType subType(ent2->second.symbol->getType(), 0);
+                        subType.appendMangledName(mangleName2);
+                    }
+                    else {
+                        ent2->second.symbol->getType().appendMangledName(mangleName2);
+                    }
                     if (mangleName1 == mangleName2)
                         return;
                     else {
@@ -343,10 +365,18 @@ struct TSymbolValidater
             // validate stage out;
             if (nextStage == EShLangCount)
                 return;
+            if (name == "gl_PerVertex")
+                return;
             if (outVarMaps[nextStage] != nullptr) {
                 auto ent2 = inVarMaps[nextStage]->find(name);
                 if (ent2 != inVarMaps[nextStage]->end()) {
-                    ent2->second.symbol->getType().appendMangledName(mangleName2);
+                    if (ent2->second.symbol->getType().getQualifier().isArrayedIo(nextStage)) {
+                        TType subType(ent2->second.symbol->getType(), 0);
+                        subType.appendMangledName(mangleName2);
+                    }
+                    else {
+                        ent2->second.symbol->getType().appendMangledName(mangleName2);
+                    }
                     if (mangleName1 == mangleName2)
                         return;
                     else {
@@ -384,7 +414,7 @@ struct TSymbolValidater
     bool& hadError;
 
 private:
-    TSymbolValidater& operator=(TSymbolValidater&);
+    TSymbolValidater& operator=(TSymbolValidater&) = delete;
 };
 
 struct TSlotCollector {
@@ -398,7 +428,7 @@ struct TSlotCollector {
     TInfoSink& infoSink;
 
 private:
-    TSlotCollector& operator=(TSlotCollector&);
+    TSlotCollector& operator=(TSlotCollector&) = delete;
 };
 
 TDefaultIoResolverBase::TDefaultIoResolverBase(const TIntermediate& intermediate)
@@ -579,7 +609,7 @@ TDefaultGlslIoResolver::TDefaultGlslIoResolver(const TIntermediate& intermediate
 
 int TDefaultGlslIoResolver::resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) {
     const TType& type = ent.symbol->getType();
-    const TString& name = ent.symbol->getName();
+    const TString& name = getAccessName(ent.symbol);
     if (currentStage != stage) {
         preStage = currentStage;
         currentStage = stage;
@@ -627,7 +657,7 @@ int TDefaultGlslIoResolver::resolveInOutLocation(EShLanguage stage, TVarEntryInf
         TVarSlotMap::iterator iter = storageSlotMap[resourceKey].find(name);
         if (iter != storageSlotMap[resourceKey].end()) {
             // If interface resource be found, set it has location and this symbol's new location
-            // equal the symbol's explicit location declarated in pre or next stage.
+            // equal the symbol's explicit location declaration in pre or next stage.
             //
             // vs:    out vec4 a;
             // fs:    layout(..., location = 3,...) in vec4 a;
@@ -663,7 +693,7 @@ int TDefaultGlslIoResolver::resolveInOutLocation(EShLanguage stage, TVarEntryInf
 
 int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) {
     const TType& type = ent.symbol->getType();
-    const TString& name = ent.symbol->getName();
+    const TString& name = getAccessName(ent.symbol);
     // kick out of not doing this
     if (! doAutoLocationMapping()) {
         return ent.newLocation = -1;
@@ -706,7 +736,7 @@ int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEn
         TVarSlotMap::iterator iter = slotMap.find(name);
         if (iter != slotMap.end()) {
             // If uniform resource be found, set it has location and this symbol's new location
-            // equal the uniform's explicit location declarated in other stage.
+            // equal the uniform's explicit location declaration in other stage.
             //
             // vs:    uniform vec4 a;
             // fs:    layout(..., location = 3,...) uniform vec4 a;
@@ -714,7 +744,7 @@ int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEn
             location = iter->second;
         }
         if (! hasLocation) {
-            // No explicit location declaraten in other stage.
+            // No explicit location declaration in other stage.
             // So we should find a new slot for this uniform.
             //
             // vs:    uniform vec4 a;
@@ -723,7 +753,7 @@ int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEn
             storageSlotMap[resourceKey][name] = location;
         }
     } else {
-        // the first uniform declarated in a program.
+        // the first uniform declaration in a program.
         TVarSlotMap varSlotMap;
         location = getFreeSlot(resourceKey, 0, size);
         varSlotMap[name] = location;
@@ -734,8 +764,8 @@ int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEn
 
 int TDefaultGlslIoResolver::resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& ent) {
     const TType& type = ent.symbol->getType();
-    const TString& name = ent.symbol->getName();
-    // On OpenGL arrays of opaque types take a seperate binding for each element
+    const TString& name = getAccessName(ent.symbol);
+    // On OpenGL arrays of opaque types take a separate binding for each element
     int numBindings = intermediate.getSpv().openGl != 0 && type.isSizedArray() ? type.getCumulativeArraySize() : 1;
     TResourceType resource = getResourceType(type);
     // don't need to handle uniform symbol, it will be handled in resolveUniformLocation
@@ -809,7 +839,7 @@ void TDefaultGlslIoResolver::endCollect(EShLanguage /*stage*/) {
 
 void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) {
     const TType& type = ent.symbol->getType();
-    const TString& name = ent.symbol->getName();
+    const TString& name = getAccessName(ent.symbol);
     TStorageQualifier storage = type.getQualifier().storage;
     EShLanguage stage(EShLangCount);
     switch (storage) {
@@ -831,6 +861,7 @@ void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink&
                 if (iter->second != location) {
                     TString errorMsg = "Invalid location: " + name;
                     infoSink.info.message(EPrefixInternalError, errorMsg.c_str());
+                    hasError = true;
                 }
             }
         }
@@ -856,6 +887,7 @@ void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink&
                 if (iter->second != location) {
                     TString errorMsg = "Invalid location: " + name;
                     infoSink.info.message(EPrefixInternalError, errorMsg.c_str());
+                    hasError = true;
                 }
             }
         }
@@ -867,7 +899,7 @@ void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink&
 
 void TDefaultGlslIoResolver::reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) {
     const TType& type = ent.symbol->getType();
-    const TString& name = ent.symbol->getName();
+    const TString& name = getAccessName(ent.symbol);
     int resource = getResourceType(type);
     if (type.getQualifier().hasBinding()) {
         TVarSlotMap& varSlotMap = resourceSlotMap[resource];
@@ -884,11 +916,19 @@ void TDefaultGlslIoResolver::reserverResourceSlot(TVarEntryInfo& ent, TInfoSink&
             if (iter->second != binding) {
                 TString errorMsg = "Invalid binding: " + name;
                 infoSink.info.message(EPrefixInternalError, errorMsg.c_str());
+                hasError = true;
             }
         }
     }
 }
 
+const TString& TDefaultGlslIoResolver::getAccessName(const TIntermSymbol* symbol)
+{
+    return symbol->getBasicType() == EbtBlock ?
+        symbol->getType().getTypeName() :
+        symbol->getName();
+}
+
 //TDefaultGlslIoResolver end
 
 /*
@@ -1070,11 +1110,12 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TInfoSi
     TVarGatherTraverser iter_binding_live(intermediate, false, inVarMap, outVarMap, uniformVarMap);
     root->traverse(&iter_binding_all);
     iter_binding_live.pushFunction(intermediate.getEntryPointMangledName().c_str());
-    while (! iter_binding_live.functions.empty()) {
-        TIntermNode* function = iter_binding_live.functions.back();
-        iter_binding_live.functions.pop_back();
-        function->traverse(&iter_binding_live);
+    while (! iter_binding_live.destinations.empty()) {
+        TIntermNode* destination = iter_binding_live.destinations.back();
+        iter_binding_live.destinations.pop_back();
+        destination->traverse(&iter_binding_live);
     }
+
     // sort entries by priority. see TVarEntryInfo::TOrderByPriority for info.
     std::for_each(inVarMap.begin(), inVarMap.end(),
                   [&inVector](TVarLivePair p) { inVector.push_back(p); });
@@ -1158,18 +1199,19 @@ bool TGlslIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TIn
         resolver = &defaultResolver;
     }
     resolver->addStage(stage);
-    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],
                                          *uniformVarMap[stage]);
     TVarGatherTraverser iter_binding_live(intermediate, false, *inVarMaps[stage], *outVarMaps[stage],
                                           *uniformVarMap[stage]);
     root->traverse(&iter_binding_all);
     iter_binding_live.pushFunction(intermediate.getEntryPointMangledName().c_str());
-    while (! iter_binding_live.functions.empty()) {
-        TIntermNode* function = iter_binding_live.functions.back();
-        iter_binding_live.functions.pop_back();
-        function->traverse(&iter_binding_live);
+    while (! iter_binding_live.destinations.empty()) {
+        TIntermNode* destination = iter_binding_live.destinations.back();
+        iter_binding_live.destinations.pop_back();
+        destination->traverse(&iter_binding_live);
     }
+
     TNotifyInOutAdaptor inOutNotify(stage, *resolver);
     TNotifyUniformAdaptor uniformNotify(stage, *resolver);
     // Resolve current stage input symbol location with previous stage output here,
@@ -1246,4 +1288,4 @@ bool TGlslIoMapper::doMap(TIoMapResolver* resolver, TInfoSink& infoSink) {
 
 } // end namespace glslang
 
-#endif // GLSLANG_WEB
+#endif // !GLSLANG_WEB && !GLSLANG_ANGLE

+ 11 - 8
src/libraries/glslang/glslang/MachineIndependent/iomapper.h

@@ -33,7 +33,7 @@
 // POSSIBILITY OF SUCH DAMAGE.
 //
 
-#ifndef GLSLANG_WEB
+#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
 
 #ifndef _IOMAPPER_INCLUDED
 #define _IOMAPPER_INCLUDED
@@ -129,6 +129,7 @@ public:
     uint32_t computeTypeLocationSize(const TType& type, EShLanguage stage);
 
     TSlotSetMap slots;
+    bool hasError = false;
 
 protected:
     TDefaultIoResolverBase(TDefaultIoResolverBase&);
@@ -185,7 +186,7 @@ protected:
     }
 };
 
-// Defaulf I/O resolver for OpenGL
+// Default I/O resolver for OpenGL
 struct TDefaultGlslIoResolver : public TDefaultIoResolverBase {
 public:
     typedef std::map<TString, int> TVarSlotMap;  // <resourceName, location/binding>
@@ -202,6 +203,7 @@ public:
     void endCollect(EShLanguage) override;
     void reserverStorageSlot(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.
     // 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.
@@ -237,12 +239,13 @@ typedef std::map<TString, TVarEntryInfo> TVarLiveMap;
 // In the future, if the vc++ compiler can handle such a situation,
 // this part of the code will be removed.
 struct TVarLivePair : std::pair<const TString, TVarEntryInfo> {
-    TVarLivePair(std::pair<const TString, TVarEntryInfo>& _Right) : pair(_Right.first, _Right.second) {}
+    TVarLivePair(const std::pair<const TString, TVarEntryInfo>& _Right) : pair(_Right.first, _Right.second) {}
     TVarLivePair& operator=(const TVarLivePair& _Right) {
         const_cast<TString&>(first) = _Right.first;
         second = _Right.second;
         return (*this);
     }
+    TVarLivePair(const TVarLivePair& src) : pair(src) { }
 };
 typedef std::vector<TVarLivePair> TVarLiveVector;
 
@@ -260,10 +263,10 @@ public:
 class TGlslIoMapper : public TIoMapper {
 public:
     TGlslIoMapper() {
-        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));
+        memset(inVarMaps,     0, sizeof(TVarLiveMap*)   * EShLangCount);
+        memset(outVarMaps,    0, sizeof(TVarLiveMap*)   * EShLangCount);
+        memset(uniformVarMap, 0, sizeof(TVarLiveMap*)   * EShLangCount);
+        memset(intermediates, 0, sizeof(TIntermediate*) * EShLangCount);
     }
     virtual ~TGlslIoMapper() {
         for (size_t stage = 0; stage < EShLangCount; stage++) {
@@ -296,4 +299,4 @@ public:
 
 #endif // _IOMAPPER_INCLUDED
 
-#endif //  GLSLANG_WEB
+#endif // !GLSLANG_WEB && !GLSLANG_ANGLE

+ 100 - 42
src/libraries/glslang/glslang/MachineIndependent/linkValidate.cpp

@@ -82,7 +82,7 @@ void TIntermediate::warn(TInfoSink& infoSink, const char* message)
 //
 void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
 {
-#ifndef GLSLANG_WEB
+#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
     mergeCallGraphs(infoSink, unit);
     mergeModes(infoSink, unit);
     mergeTrees(infoSink, unit);
@@ -104,7 +104,7 @@ void TIntermediate::mergeCallGraphs(TInfoSink& infoSink, TIntermediate& unit)
     callGraph.insert(callGraph.end(), unit.callGraph.begin(), unit.callGraph.end());
 }
 
-#ifndef GLSLANG_WEB
+#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
 
 #define MERGE_MAX(member) member = std::max(member, unit.member)
 #define MERGE_TRUE(member) if (unit.member) member = unit.member;
@@ -138,7 +138,11 @@ void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit)
     MERGE_MAX(spvVersion.openGl);
 
     numErrors += unit.getNumErrors();
-    numPushConstants += unit.numPushConstants;
+    // Only one push_constant is allowed, mergeLinkerObjects() will ensure the push_constant
+    // is the same for all units.
+    if (numPushConstants > 1 || unit.numPushConstants > 1)
+        error(infoSink, "Only one push_constant block is allowed per stage");
+    numPushConstants = std::min(numPushConstants + unit.numPushConstants, 1);
 
     if (unit.invocations != TQualifier::layoutNotSet) {
         if (invocations == TQualifier::layoutNotSet)
@@ -149,7 +153,7 @@ void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit)
 
     if (vertices == TQualifier::layoutNotSet)
         vertices = unit.vertices;
-    else if (vertices != unit.vertices) {
+    else if (unit.vertices != TQualifier::layoutNotSet && vertices != unit.vertices) {
         if (language == EShLangGeometry || language == EShLangMeshNV)
             error(infoSink, "Contradictory layout max_vertices values");
         else if (language == EShLangTessControl)
@@ -168,12 +172,12 @@ void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit)
 
     if (inputPrimitive == ElgNone)
         inputPrimitive = unit.inputPrimitive;
-    else if (inputPrimitive != unit.inputPrimitive)
+    else if (unit.inputPrimitive != ElgNone && inputPrimitive != unit.inputPrimitive)
         error(infoSink, "Contradictory input layout primitives");
 
     if (outputPrimitive == ElgNone)
         outputPrimitive = unit.outputPrimitive;
-    else if (outputPrimitive != unit.outputPrimitive)
+    else if (unit.outputPrimitive != ElgNone && outputPrimitive != unit.outputPrimitive)
         error(infoSink, "Contradictory output layout primitives");
 
     if (originUpperLeft != unit.originUpperLeft || pixelCenterInteger != unit.pixelCenterInteger)
@@ -286,7 +290,7 @@ void TIntermediate::mergeTrees(TInfoSink& infoSink, TIntermediate& unit)
     }
 
     // Getting this far means we have two existing trees to merge...
-    numShaderRecordNVBlocks += unit.numShaderRecordNVBlocks;
+    numShaderRecordBlocks += unit.numShaderRecordBlocks;
     numTaskNVBlocks += unit.numTaskNVBlocks;
 
     // Get the top-level globals of each unit
@@ -299,10 +303,10 @@ void TIntermediate::mergeTrees(TInfoSink& infoSink, TIntermediate& unit)
 
     // Map by global name to unique ID to rationalize the same object having
     // differing IDs in different trees.
-    TMap<TString, int> idMap;
+    TIdMaps idMaps;
     int maxId;
-    seedIdMap(idMap, maxId);
-    remapIds(idMap, maxId + 1, unit);
+    seedIdMap(idMaps, maxId);
+    remapIds(idMaps, maxId + 1, unit);
 
     mergeBodies(infoSink, globals, unitGlobals);
     mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects);
@@ -311,27 +315,40 @@ void TIntermediate::mergeTrees(TInfoSink& infoSink, TIntermediate& unit)
 
 #endif
 
+static const TString& getNameForIdMap(TIntermSymbol* symbol)
+{
+    TShaderInterface si = symbol->getType().getShaderInterface();
+    if (si == EsiNone)
+        return symbol->getName();
+    else
+        return symbol->getType().getTypeName();
+}
+
+
+
 // Traverser that seeds an ID map with all built-ins, and tracks the
 // maximum ID used.
 // (It would be nice to put this in a function, but that causes warnings
 // on having no bodies for the copy-constructor/operator=.)
 class TBuiltInIdTraverser : public TIntermTraverser {
 public:
-    TBuiltInIdTraverser(TMap<TString, int>& idMap) : idMap(idMap), maxId(0) { }
+    TBuiltInIdTraverser(TIdMaps& idMaps) : idMaps(idMaps), maxId(0) { }
     // If it's a built in, add it to the map.
     // Track the max ID.
     virtual void visitSymbol(TIntermSymbol* symbol)
     {
         const TQualifier& qualifier = symbol->getType().getQualifier();
-        if (qualifier.builtIn != EbvNone)
-            idMap[symbol->getName()] = symbol->getId();
+        if (qualifier.builtIn != EbvNone) {
+            TShaderInterface si = symbol->getType().getShaderInterface();
+            idMaps[si][getNameForIdMap(symbol)] = symbol->getId();
+        }
         maxId = std::max(maxId, symbol->getId());
     }
     int getMaxId() const { return maxId; }
 protected:
     TBuiltInIdTraverser(TBuiltInIdTraverser&);
     TBuiltInIdTraverser& operator=(TBuiltInIdTraverser&);
-    TMap<TString, int>& idMap;
+    TIdMaps& idMaps;
     int maxId;
 };
 
@@ -340,31 +357,33 @@ protected:
 // on having no bodies for the copy-constructor/operator=.)
 class TUserIdTraverser : public TIntermTraverser {
 public:
-    TUserIdTraverser(TMap<TString, int>& idMap) : idMap(idMap) { }
+    TUserIdTraverser(TIdMaps& idMaps) : idMaps(idMaps) { }
     // If its a non-built-in global, add it to the map.
     virtual void visitSymbol(TIntermSymbol* symbol)
     {
         const TQualifier& qualifier = symbol->getType().getQualifier();
-        if (qualifier.builtIn == EbvNone)
-            idMap[symbol->getName()] = symbol->getId();
+        if (qualifier.builtIn == EbvNone) {
+            TShaderInterface si = symbol->getType().getShaderInterface();
+            idMaps[si][getNameForIdMap(symbol)] = symbol->getId();
+        }
     }
 
 protected:
     TUserIdTraverser(TUserIdTraverser&);
     TUserIdTraverser& operator=(TUserIdTraverser&);
-    TMap<TString, int>& idMap; // over biggest id
+    TIdMaps& idMaps; // over biggest id
 };
 
 // Initialize the the ID map with what we know of 'this' AST.
-void TIntermediate::seedIdMap(TMap<TString, int>& idMap, int& maxId)
+void TIntermediate::seedIdMap(TIdMaps& idMaps, int& maxId)
 {
     // all built-ins everywhere need to align on IDs and contribute to the max ID
-    TBuiltInIdTraverser builtInIdTraverser(idMap);
+    TBuiltInIdTraverser builtInIdTraverser(idMaps);
     treeRoot->traverse(&builtInIdTraverser);
     maxId = builtInIdTraverser.getMaxId();
 
     // user variables in the linker object list need to align on ids
-    TUserIdTraverser userIdTraverser(idMap);
+    TUserIdTraverser userIdTraverser(idMaps);
     findLinkerObjects()->traverse(&userIdTraverser);
 }
 
@@ -373,7 +392,7 @@ void TIntermediate::seedIdMap(TMap<TString, int>& idMap, int& maxId)
 // on having no bodies for the copy-constructor/operator=.)
 class TRemapIdTraverser : public TIntermTraverser {
 public:
-    TRemapIdTraverser(const TMap<TString, int>& idMap, int idShift) : idMap(idMap), idShift(idShift) { }
+    TRemapIdTraverser(const TIdMaps& idMaps, int idShift) : idMaps(idMaps), idShift(idShift) { }
     // Do the mapping:
     //  - if the same symbol, adopt the 'this' ID
     //  - otherwise, ensure a unique ID by shifting to a new space
@@ -382,8 +401,9 @@ public:
         const TQualifier& qualifier = symbol->getType().getQualifier();
         bool remapped = false;
         if (qualifier.isLinkable() || qualifier.builtIn != EbvNone) {
-            auto it = idMap.find(symbol->getName());
-            if (it != idMap.end()) {
+            TShaderInterface si = symbol->getType().getShaderInterface();
+            auto it = idMaps[si].find(getNameForIdMap(symbol));
+            if (it != idMaps[si].end()) {
                 symbol->changeId(it->second);
                 remapped = true;
             }
@@ -394,14 +414,14 @@ public:
 protected:
     TRemapIdTraverser(TRemapIdTraverser&);
     TRemapIdTraverser& operator=(TRemapIdTraverser&);
-    const TMap<TString, int>& idMap;
+    const TIdMaps& idMaps;
     int idShift;
 };
 
-void TIntermediate::remapIds(const TMap<TString, int>& idMap, int idShift, TIntermediate& unit)
+void TIntermediate::remapIds(const TIdMaps& idMaps, int idShift, TIntermediate& unit)
 {
     // Remap all IDs to either share or be unique, as dictated by the idMap and idShift.
-    TRemapIdTraverser idTraverser(idMap, idShift);
+    TRemapIdTraverser idTraverser(idMaps, idShift);
     unit.getTreeRoot()->traverse(&idTraverser);
 }
 
@@ -443,7 +463,19 @@ void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& lin
             TIntermSymbol* symbol = linkerObjects[linkObj]->getAsSymbolNode();
             TIntermSymbol* unitSymbol = unitLinkerObjects[unitLinkObj]->getAsSymbolNode();
             assert(symbol && unitSymbol);
-            if (symbol->getName() == unitSymbol->getName()) {
+
+            bool isSameSymbol = false;
+            // If they are both blocks in the same shader interface,
+            // match by the block-name, not the identifier name.
+            if (symbol->getType().getBasicType() == EbtBlock && unitSymbol->getType().getBasicType() == EbtBlock) {
+                if (symbol->getType().getShaderInterface() == unitSymbol->getType().getShaderInterface()) {
+                    isSameSymbol = symbol->getType().getTypeName() == unitSymbol->getType().getTypeName();
+                }
+            }
+            else if (symbol->getName() == unitSymbol->getName())
+                isSameSymbol = true;
+
+            if (isSameSymbol) {
                 // filter out copy
                 merge = false;
 
@@ -462,6 +494,9 @@ void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& lin
                 // Check for consistent types/qualification/initializers etc.
                 mergeErrorCheck(infoSink, *symbol, *unitSymbol, false);
             }
+            // 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())
+                error(infoSink, "Only one push_constant block is allowed per stage");
         }
         if (merge)
             linkerObjects.push_back(unitLinkerObjects[unitLinkObj]);
@@ -498,7 +533,7 @@ void TIntermediate::mergeImplicitArraySizes(TType& type, const TType& unitType)
 //
 void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& symbol, const TIntermSymbol& unitSymbol, bool crossStage)
 {
-#ifndef GLSLANG_WEB
+#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
     bool writeTypeComparison = false;
 
     // Types have to match
@@ -520,6 +555,22 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
         writeTypeComparison = true;
     }
 
+    // Uniform and buffer blocks must either both have an instance name, or
+    // must both be anonymous. The names don't need to match though.
+    if (symbol.getQualifier().isUniformOrBuffer() &&
+        (IsAnonymous(symbol.getName()) != IsAnonymous(unitSymbol.getName()))) {
+        error(infoSink, "Matched Uniform or Storage blocks must all be anonymous,"
+                        " or all be named:");
+        writeTypeComparison = true;
+    }
+
+    if (symbol.getQualifier().storage == unitSymbol.getQualifier().storage &&
+        (IsAnonymous(symbol.getName()) != IsAnonymous(unitSymbol.getName()) ||
+         (!IsAnonymous(symbol.getName()) && symbol.getName() != unitSymbol.getName()))) {
+        warn(infoSink, "Matched shader interfaces are using different instance names.");
+        writeTypeComparison = true;
+    }
+
     // Precision...
     if (symbol.getQualifier().precision != unitSymbol.getQualifier().precision) {
         error(infoSink, "Precision qualifiers must match:");
@@ -555,6 +606,7 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
         symbol.getQualifier().queuefamilycoherent  != unitSymbol.getQualifier().queuefamilycoherent ||
         symbol.getQualifier().workgroupcoherent != unitSymbol.getQualifier().workgroupcoherent ||
         symbol.getQualifier().subgroupcoherent  != unitSymbol.getQualifier().subgroupcoherent ||
+        symbol.getQualifier().shadercallcoherent!= unitSymbol.getQualifier().shadercallcoherent ||
         symbol.getQualifier().nonprivate        != unitSymbol.getQualifier().nonprivate ||
         symbol.getQualifier().volatil           != unitSymbol.getQualifier().volatil ||
         symbol.getQualifier().restrict          != unitSymbol.getQualifier().restrict ||
@@ -589,9 +641,13 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
         }
     }
 
-    if (writeTypeComparison)
-        infoSink.info << "    " << symbol.getName() << ": \"" << symbol.getType().getCompleteString() << "\" versus \"" <<
-                                                             unitSymbol.getType().getCompleteString() << "\"\n";
+    if (writeTypeComparison) {
+        infoSink.info << "    " << symbol.getName() << ": \"" << symbol.getType().getCompleteString() << "\" versus ";
+        if (symbol.getName() != unitSymbol.getName())
+            infoSink.info << unitSymbol.getName() << ": ";
+
+        infoSink.info << "\"" << unitSymbol.getType().getCompleteString() << "\"\n";
+    }
 #endif
 }
 
@@ -721,13 +777,13 @@ void TIntermediate::finalCheck(TInfoSink& infoSink, bool keepUncalled)
         break;
     case EShLangCompute:
         break;
-    case EShLangRayGenNV:
-    case EShLangIntersectNV:
-    case EShLangAnyHitNV:
-    case EShLangClosestHitNV:
-    case EShLangMissNV:
-    case EShLangCallableNV:
-        if (numShaderRecordNVBlocks > 1)
+    case EShLangRayGen:
+    case EShLangIntersect:
+    case EShLangAnyHit:
+    case EShLangClosestHit:
+    case EShLangMiss:
+    case EShLangCallable:
+        if (numShaderRecordBlocks > 1)
             error(infoSink, "Only one shaderRecordNV buffer block is allowed per stage");
         break;
     case EShLangMeshNV:
@@ -1306,9 +1362,9 @@ unsigned int TIntermediate::computeTypeXfbSize(const TType& type, bool& contains
     // that component's size.  Aggregate types are flattened down to the component
     // level to get this sequence of components."
 
-    if (type.isArray()) {
+    if (type.isSizedArray()) {
         // TODO: perf: this can be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness
-        assert(type.isSizedArray());
+        // Unsized array use to xfb should be a compile error.
         TType elementType(type, 0);
         return type.getOuterArraySize() * computeTypeXfbSize(elementType, contains64BitType, contains16BitType, contains16BitType);
     }
@@ -1494,7 +1550,9 @@ int TIntermediate::getBaseAlignment(const TType& type, int& size, int& stride, T
         RoundToPow2(size, alignment);
         stride = size;  // uses full matrix size for stride of an array of matrices (not quite what rule 6/8, but what's expected)
                         // uses the assumption for rule 10 in the comment above
-        size = stride * type.getOuterArraySize();
+        // use one element to represent the last member of SSBO which is unsized array
+        int arraySize = (type.isUnsizedArray() && (type.getOuterArraySize() == 0)) ? 1 : type.getOuterArraySize();
+        size = stride * arraySize;
         return alignment;
     }
 

+ 101 - 47
src/libraries/glslang/glslang/MachineIndependent/localintermediate.h

@@ -162,7 +162,10 @@ struct TXfbBuffer {
 #endif
 
 // Track a set of strings describing how the module was processed.
-// Using the form:
+// This includes command line options, transforms, etc., ideally inclusive enough
+// to reproduce the steps used to transform the input source to the output.
+// E.g., see SPIR-V OpModuleProcessed.
+// Each "process" or "transform" uses is expressed in the form:
 //   process arg0 arg1 arg2 ...
 //   process arg0 arg1 arg2 ...
 // where everything is textual, and there can be zero or more arguments
@@ -222,6 +225,40 @@ enum ComputeDerivativeMode {
     LayoutDerivativeGroupLinear,  // derivative_group_linearNV
 };
 
+class TIdMaps {
+public:
+    TMap<TString, int>& operator[](int i) { return maps[i]; }
+    const TMap<TString, int>& operator[](int i) const { return maps[i]; }
+private:
+    TMap<TString, int> maps[EsiCount];
+};
+
+class TNumericFeatures {
+public:
+    TNumericFeatures() : features(0) { }
+    TNumericFeatures(const TNumericFeatures&) = delete;
+    TNumericFeatures& operator=(const TNumericFeatures&) = delete;
+    typedef enum : unsigned int {
+        shader_explicit_arithmetic_types          = 1 << 0,
+        shader_explicit_arithmetic_types_int8     = 1 << 1,
+        shader_explicit_arithmetic_types_int16    = 1 << 2,
+        shader_explicit_arithmetic_types_int32    = 1 << 3,
+        shader_explicit_arithmetic_types_int64    = 1 << 4,
+        shader_explicit_arithmetic_types_float16  = 1 << 5,
+        shader_explicit_arithmetic_types_float32  = 1 << 6,
+        shader_explicit_arithmetic_types_float64  = 1 << 7,
+        shader_implicit_conversions               = 1 << 8,
+        gpu_shader_fp64                           = 1 << 9,
+        gpu_shader_int16                          = 1 << 10,
+        gpu_shader_half_float                     = 1 << 11,
+    } feature;
+    void insert(feature f) { features |= f; }
+    void erase(feature f) { features &= ~f; }
+    bool contains(feature f) const { return (features & f) != 0; }
+private:
+    unsigned int features;
+};
+
 //
 // Set of helper functions to help parse and build the tree.
 //
@@ -229,7 +266,10 @@ class TIntermediate {
 public:
     explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) :
         language(l),
-        profile(p), version(v), treeRoot(0),
+#ifndef GLSLANG_ANGLE
+        profile(p), version(v),
+#endif
+        treeRoot(0),
         numEntryPoints(0), numErrors(0), numPushConstants(0), recursive(false),
         invertY(false),
         useStorageBuffer(false),
@@ -244,15 +284,16 @@ public:
         inputPrimitive(ElgNone), outputPrimitive(ElgNone),
         pixelCenterInteger(false), originUpperLeft(false),
         vertexSpacing(EvsNone), vertexOrder(EvoNone), interlockOrdering(EioNone), pointMode(false), earlyFragmentTests(false),
-        postDepthCoverage(false), depthLayout(EldNone), 
+        postDepthCoverage(false), depthLayout(EldNone),
         hlslFunctionality1(false),
         blendEquations(0), xfbMode(false), multiStream(false),
         layoutOverrideCoverage(false),
         geoPassthroughEXT(false),
-        numShaderRecordNVBlocks(0),
+        numShaderRecordBlocks(0),
         computeDerivativeMode(LayoutDerivativeNone),
         primitives(TQualifier::layoutNotSet),
         numTaskNVBlocks(0),
+        layoutPrimitiveCulling(false),
         autoMapBindings(false),
         autoMapLocations(false),
         flattenUniformArrays(false),
@@ -282,9 +323,20 @@ public:
 #endif
     }
 
-    void setVersion(int v) { version = v; }
+    void setVersion(int v)
+    {
+#ifndef GLSLANG_ANGLE
+        version = v;
+#endif
+    }
+    void setProfile(EProfile p)
+    {
+#ifndef GLSLANG_ANGLE
+        profile = p;
+#endif
+    }
+
     int getVersion() const { return version; }
-    void setProfile(EProfile p) { profile = p; }
     EProfile getProfile() const { return profile; }
     void setSpv(const SpvVersion& s)
     {
@@ -332,6 +384,9 @@ public:
         case EShTargetVulkan_1_1:
             processes.addProcess("target-env vulkan1.1");
             break;
+        case EShTargetVulkan_1_2:
+            processes.addProcess("target-env vulkan1.2");
+            break;
         default:
             processes.addProcess("target-env vulkanUnknown");
             break;
@@ -377,7 +432,7 @@ public:
     void setSource(EShSource s) { source = s; }
     EShSource getSource() const { return source; }
 #else
-    void setSource(EShSource s) { assert(s == EShSourceGlsl); }
+    void setSource(EShSource s) { assert(s == EShSourceGlsl); (void)s; }
     EShSource getSource() const { return EShSourceGlsl; }
 #endif
 
@@ -388,15 +443,15 @@ public:
     TIntermSymbol* addSymbol(const TType&, const TSourceLoc&);
     TIntermSymbol* addSymbol(const TIntermSymbol&);
     TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*);
-    std::tuple<TIntermTyped*, TIntermTyped*> addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1);
+    std::tuple<TIntermTyped*, TIntermTyped*> addPairConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1);
     TIntermTyped* addUniShapeConversion(TOperator, const TType&, TIntermTyped*);
     TIntermTyped* addConversion(TBasicType convertTo, TIntermTyped* node) const;
     void addBiShapeConversion(TOperator, TIntermTyped*& lhsNode, TIntermTyped*& rhsNode);
     TIntermTyped* addShapeConversion(const TType&, TIntermTyped*);
-    TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
-    TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
-    TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc);
-    TIntermTyped* addUnaryMath(TOperator, TIntermTyped* child, TSourceLoc);
+    TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
+    TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
+    TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc&);
+    TIntermTyped* addUnaryMath(TOperator, TIntermTyped* child, const TSourceLoc&);
     TIntermTyped* addBuiltInFunctionCall(const TSourceLoc& line, TOperator, bool unary, TIntermNode*, const TType& returnType);
     bool canImplicitlyPromote(TBasicType from, TBasicType to, TOperator op = EOpNull) const;
     bool isIntegralPromotion(TBasicType from, TBasicType to) const;
@@ -410,7 +465,7 @@ public:
     TIntermAggregate* makeAggregate(TIntermNode* node);
     TIntermAggregate* makeAggregate(TIntermNode* node, const TSourceLoc&);
     TIntermAggregate* makeAggregate(const TSourceLoc&);
-    TIntermTyped* setAggregateOperator(TIntermNode*, TOperator, const TType& type, TSourceLoc);
+    TIntermTyped* setAggregateOperator(TIntermNode*, TOperator, const TType& type, const TSourceLoc&);
     bool areAllChildConst(TIntermAggregate* aggrNode);
     TIntermSelection* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&);
     TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&);
@@ -439,10 +494,11 @@ public:
 
     // Low level functions to add nodes (no conversions or other higher level transformations)
     // If a type is provided, the node's type will be set to it.
-    TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc) const;
-    TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc, const TType&) const;
-    TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc) const;
-    TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc, const TType&) const;
+    TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&) const;
+    TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&,
+        const TType&) const;
+    TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, const TSourceLoc&) const;
+    TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, const TSourceLoc&, const TType&) const;
 
     // Constant folding (in Constant.cpp)
     TIntermTyped* fold(TIntermAggregate* aggrNode);
@@ -457,11 +513,7 @@ public:
     void addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage, TSymbolTable&);
     void addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymbol&);
 
-    void setUseStorageBuffer()
-    {
-        useStorageBuffer = true;
-        processes.addProcess("use-storage-buffer");
-    }
+    void setUseStorageBuffer() { useStorageBuffer = true; }
     bool usingStorageBuffer() const { return useStorageBuffer; }
     void setDepthReplacing() { depthReplacing = true; }
     bool isDepthReplacing() const { return depthReplacing; }
@@ -500,7 +552,7 @@ public:
     bool getAutoMapBindings() const { return false; }
     bool getAutoMapLocations() const { return false; }
     int getNumPushConstants() const { return 0; }
-    void addShaderRecordNVCount() { }
+    void addShaderRecordCount() { }
     void addTaskNVCount() { }
     void setUseVulkanMemoryModel() { }
     bool usingVulkanMemoryModel() const { return false; }
@@ -580,7 +632,7 @@ public:
             processes.addProcess("flatten-uniform-arrays");
     }
     bool getFlattenUniformArrays() const { return flattenUniformArrays; }
-#endif 
+#endif
     void setNoStorageFormat(bool b)
     {
         useUnknownFormat = b;
@@ -617,7 +669,7 @@ public:
 
     void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { textureSamplerTransformMode = mode; }
     int getNumPushConstants() const { return numPushConstants; }
-    void addShaderRecordNVCount() { ++numShaderRecordNVBlocks; }
+    void addShaderRecordCount() { ++numShaderRecordBlocks; }
     void addTaskNVCount() { ++numTaskNVBlocks; }
 
     bool setInvocations(int i)
@@ -720,6 +772,8 @@ public:
     void setLayoutDerivativeMode(ComputeDerivativeMode mode) { computeDerivativeMode = mode; }
     bool hasLayoutDerivativeModeNone() const { return computeDerivativeMode != LayoutDerivativeNone; }
     ComputeDerivativeMode getLayoutDerivativeModeNone() const { return computeDerivativeMode; }
+    void setLayoutPrimitiveCulling() { layoutPrimitiveCulling = true; }
+    bool getLayoutPrimitiveCulling() const { return layoutPrimitiveCulling; }
     bool setPrimitives(int m)
     {
         if (primitives != TQualifier::layoutNotSet)
@@ -831,22 +885,25 @@ public:
     bool getArithemeticInt8Enabled() const { return false; }
     bool getArithemeticInt16Enabled() const { return false; }
     bool getArithemeticFloat16Enabled() const { return false; }
+    void updateNumericFeature(TNumericFeatures::feature f, bool on) { }
 #else
     bool getArithemeticInt8Enabled() const {
-        return extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
-               extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8);
+        return numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) ||
+               numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int8);
     }
     bool getArithemeticInt16Enabled() const {
-        return extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
-               extensionRequested(E_GL_AMD_gpu_shader_int16) ||
-               extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16);
+        return numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) ||
+               numericFeatures.contains(TNumericFeatures::gpu_shader_int16) ||
+               numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int16);
     }
 
     bool getArithemeticFloat16Enabled() const {
-        return extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
-               extensionRequested(E_GL_AMD_gpu_shader_half_float) ||
-               extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float16);
+        return numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) ||
+               numericFeatures.contains(TNumericFeatures::gpu_shader_half_float) ||
+               numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_float16);
     }
+    void updateNumericFeature(TNumericFeatures::feature f, bool on)
+        { on ? numericFeatures.insert(f) : numericFeatures.erase(f); }
 #endif
 
 protected:
@@ -856,8 +913,8 @@ protected:
     void mergeCallGraphs(TInfoSink&, TIntermediate&);
     void mergeModes(TInfoSink&, TIntermediate&);
     void mergeTrees(TInfoSink&, TIntermediate&);
-    void seedIdMap(TMap<TString, int>& idMap, int& maxId);
-    void remapIds(const TMap<TString, int>& idMap, int idShift, TIntermediate&);
+    void seedIdMap(TIdMaps& idMaps, int& maxId);
+    void remapIds(const TIdMaps& idMaps, int idShift, TIntermediate&);
     void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals);
     void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects);
     void mergeImplicitArraySizes(TType&, const TType&);
@@ -878,17 +935,7 @@ protected:
     bool specConstantPropagates(const TIntermTyped&, const TIntermTyped&);
     void performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root);
     bool isConversionAllowed(TOperator op, TIntermTyped* node) const;
-    std::tuple<TBasicType, TBasicType> getConversionDestinatonType(TBasicType type0, TBasicType type1, TOperator op) const;
-
-    // JohnK: I think this function should go away.
-    // This data structure is just a log to pass on to back ends.
-    // Versioning and extensions are handled in Version.cpp, with a rich
-    // set of functions for querying stages, versions, extension enable/disabled, etc.
-#ifdef GLSLANG_WEB
-    bool extensionRequested(const char *extension) const { return false; }
-#else
-    bool extensionRequested(const char *extension) const {return requestedExtensions.find(extension) != requestedExtensions.end();}
-#endif
+    std::tuple<TBasicType, TBasicType> getConversionDestinationType(TBasicType type0, TBasicType type1, TOperator op) const;
 
     static const char* getResourceName(TResourceType);
 
@@ -898,8 +945,13 @@ protected:
     typedef std::list<TCall> TGraph;
     TGraph callGraph;
 
+#ifdef GLSLANG_ANGLE
+    const EProfile profile = ECoreProfile;
+    const int version = 450;
+#else
     EProfile profile;                           // source profile
     int version;                                // source version
+#endif
     SpvVersion spvVersion;
     TIntermNode* treeRoot;
     std::set<std::string> requestedExtensions;  // cumulation of all enabled or required extensions; not connected to what subset of the shader used them
@@ -942,10 +994,11 @@ protected:
     bool multiStream;
     bool layoutOverrideCoverage;
     bool geoPassthroughEXT;
-    int numShaderRecordNVBlocks;
+    int numShaderRecordBlocks;
     ComputeDerivativeMode computeDerivativeMode;
     int primitives;
     int numTaskNVBlocks;
+    bool layoutPrimitiveCulling;
 
     // Base shift values
     std::array<unsigned int, EResCount> shiftBinding;
@@ -972,6 +1025,7 @@ protected:
 
     std::unordered_map<std::string, int> uniformLocationOverrides;
     int uniformLocationBase;
+    TNumericFeatures numericFeatures;
 #endif
 
     std::unordered_set<int> usedConstantId; // specialization constant ids used

+ 14 - 4
src/libraries/glslang/glslang/MachineIndependent/parseConst.cpp

@@ -165,17 +165,27 @@ void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
                     }
                 }
             } else {
-                // matrix from vector
+                // matrix from vector or scalar
                 int count = 0;
                 const int startIndex = index;
                 int nodeComps = node->getType().computeNumComponents();
                 for (int i = startIndex; i < endIndex; i++) {
                     if (i >= instanceSize)
                         return;
-                    if (i == startIndex || (i - startIndex) % (matrixRows + 1) == 0 )
+                    if (nodeComps == 1) {
+                        // If there is a single scalar parameter to a matrix
+                        // constructor, it is used to initialize all the
+                        // components on the matrix's diagonal, with the
+                        // remaining components initialized to 0.0.
+                        if (i == startIndex || (i - startIndex) % (matrixRows + 1) == 0 )
+                            leftUnionArray[i] = rightUnionArray[count];
+                        else
+                            leftUnionArray[i].setDConst(0.0);
+                    } else {
+                        // construct the matrix in column-major order, from
+                        // the components provided, in order
                         leftUnionArray[i] = rightUnionArray[count];
-                    else
-                        leftUnionArray[i].setDConst(0.0);
+                    }
 
                     index++;
 

+ 11 - 2
src/libraries/glslang/glslang/MachineIndependent/parseVersions.h

@@ -58,7 +58,7 @@ public:
                    const SpvVersion& spvVersion, EShLanguage language, TInfoSink& infoSink,
                    bool forwardCompatible, EShMessages messages)
         :
-#ifndef GLSLANG_WEB
+#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
         forwardCompatible(forwardCompatible),
         profile(profile),
 #endif
@@ -101,6 +101,7 @@ public:
     void updateExtensionBehavior(int line, const char* const extension, const char* behavior) { }
     void updateExtensionBehavior(const char* const extension, TExtensionBehavior) { }
     void checkExtensionStage(const TSourceLoc&, const char* const extension) { }
+    void extensionRequires(const TSourceLoc&, const char* const extension, const char* behavior) { }
     void fullIntegerCheck(const TSourceLoc&, const char* op) { }
     void doubleCheck(const TSourceLoc&, const char* op) { }
     bool float16Arithmetic() { return false; }
@@ -115,9 +116,14 @@ public:
     bool relaxedErrors()    const { return false; }
     bool suppressWarnings() const { return true; }
     bool isForwardCompatible() const { return false; }
+#else
+#ifdef GLSLANG_ANGLE
+    const bool forwardCompatible = true;
+    const EProfile profile = ECoreProfile;
 #else
     bool forwardCompatible;      // true if errors are to be given for use of deprecated features
     EProfile profile;            // the declared profile in the shader (core by default)
+#endif
     bool isEsProfile() const { return profile == EEsProfile; }
     void requireProfile(const TSourceLoc& loc, int profileMask, const char* featureDesc);
     void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, int numExtensions,
@@ -139,6 +145,7 @@ public:
     virtual bool checkExtensionsRequested(const TSourceLoc&, int numExtensions, const char* const extensions[],
         const char* featureDesc);
     virtual void checkExtensionStage(const TSourceLoc&, const char* const extension);
+    virtual void extensionRequires(const TSourceLoc&, const char* const extension, const char* behavior);
     virtual void fullIntegerCheck(const TSourceLoc&, const char* op);
 
     virtual void unimplemented(const TSourceLoc&, const char* featureDesc);
@@ -170,6 +177,7 @@ public:
     virtual void vulkanRemoved(const TSourceLoc&, const char* op);
     virtual void requireVulkan(const TSourceLoc&, const char* op);
     virtual void requireSpv(const TSourceLoc&, const char* op);
+    virtual void requireSpv(const TSourceLoc&, const char *op, unsigned int version);
 
 
 #if defined(GLSLANG_WEB) && !defined(GLSLANG_WEB_DEVEL)
@@ -221,7 +229,8 @@ public:
     TIntermediate& intermediate; // helper for making and hooking up pieces of the parse tree
 
 protected:
-    TMap<TString, TExtensionBehavior> extensionBehavior;    // for each extension string, what its current behavior is set to
+    TMap<TString, TExtensionBehavior> extensionBehavior;    // for each extension string, what its current behavior is
+    TMap<TString, unsigned int> extensionMinSpv;            // for each extension string, store minimum spirv required
     EShMessages messages;        // errors/warnings/rule-sets
     int numErrors;               // number of compile-time errors encountered
     TInputScanner* currentScanner;

+ 29 - 7
src/libraries/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp

@@ -422,10 +422,10 @@ int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, boo
             if (! parseContext.isReadingHLSL() && isMacroInput()) {
                 if (parseContext.relaxedErrors())
                     parseContext.ppWarn(ppToken->loc, "nonportable when expanded from macros for preprocessor expression",
-                                                      "defined", "");
+                        "defined", "");
                 else
                     parseContext.ppError(ppToken->loc, "cannot use in preprocessor expression when expanded from macros",
-                                                       "defined", "");
+                        "defined", "");
             }
             bool needclose = 0;
             token = scanToken(ppToken);
@@ -621,14 +621,25 @@ int TPpContext::CPPinclude(TPpToken* ppToken)
 {
     const TSourceLoc directiveLoc = ppToken->loc;
     bool startWithLocalSearch = true; // to additionally include the extra "" paths
-    int token = scanToken(ppToken);
+    int token;
 
-    // handle <header-name>-style #include
-    if (token == '<') {
+    // Find the first non-whitespace char after #include
+    int ch = getChar();
+    while (ch == ' ' || ch == '\t') {
+        ch = getChar();
+    }
+    if (ch == '<') {
+        // <header-name> style
         startWithLocalSearch = false;
         token = scanHeaderName(ppToken, '>');
+    } else if (ch == '"') {
+        // "header-name" style
+        token = scanHeaderName(ppToken, '"');
+    } else {
+        // unexpected, get the full token to generate the error
+        ungetChar();
+        token = scanToken(ppToken);
     }
-    // otherwise ppToken already has the header name and it was "header-name" style
 
     if (token != PpAtomConstString) {
         parseContext.ppError(directiveLoc, "must be followed by a header name", "#include", "");
@@ -711,7 +722,9 @@ int TPpContext::CPPline(TPpToken* ppToken)
     const char* sourceName = nullptr; // Optional source file name.
     bool lineErr = false;
     bool fileErr = false;
+    disableEscapeSequences = true;
     token = eval(token, MIN_PRECEDENCE, false, lineRes, lineErr, ppToken);
+    disableEscapeSequences = false;
     if (! lineErr) {
         lineToken = lineRes;
         if (token == '\n')
@@ -754,7 +767,9 @@ int TPpContext::CPPline(TPpToken* ppToken)
 // Handle #error
 int TPpContext::CPPerror(TPpToken* ppToken)
 {
+    disableEscapeSequences = true;
     int token = scanToken(ppToken);
+    disableEscapeSequences = false;
     std::string message;
     TSourceLoc loc = ppToken->loc;
 
@@ -1169,7 +1184,9 @@ MacroExpandResult TPpContext::MacroExpand(TPpToken* ppToken, bool expandUndef, b
     int macroAtom = atomStrings.getAtom(ppToken->name);
     switch (macroAtom) {
     case PpAtomLineMacro:
-        ppToken->ival = parseContext.getCurrentLoc().line;
+        // Arguments which are macro have been replaced in the first stage.
+        if (ppToken->ival == 0)
+            ppToken->ival = parseContext.getCurrentLoc().line;
         snprintf(ppToken->name, sizeof(ppToken->name), "%d", ppToken->ival);
         UngetToken(PpAtomConstInt, ppToken);
         return MacroExpandStarted;
@@ -1270,6 +1287,11 @@ MacroExpandResult TPpContext::MacroExpand(TPpToken* ppToken, bool expandUndef, b
                     nestStack.push_back('}');
                 else if (nestStack.size() > 0 && token == nestStack.back())
                     nestStack.pop_back();
+
+                //Macro replacement list is expanded in the last stage.
+                if (atomStrings.getAtom(ppToken->name) == PpAtomLineMacro)
+                    ppToken->ival = parseContext.getCurrentLoc().line;
+
                 in->args[arg]->putToken(token, ppToken);
                 tokenRecorded = true;
             }

+ 2 - 1
src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpContext.cpp

@@ -87,7 +87,8 @@ namespace glslang {
 TPpContext::TPpContext(TParseContextBase& pc, const std::string& rootFileName, TShader::Includer& inclr) :
     preamble(0), strings(0), previous_token('\n'), parseContext(pc), includer(inclr), inComment(false),
     rootFileName(rootFileName),
-    currentSourceFile(rootFileName)
+    currentSourceFile(rootFileName),
+    disableEscapeSequences(false)
 {
     ifdepth = 0;
     for (elsetracker = 0; elsetracker < maxIfNesting; elsetracker++)

+ 3 - 2
src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpContext.h

@@ -105,13 +105,13 @@ public:
     }
 
     // Used for comparing macro definitions, so checks what is relevant for that.
-    bool operator==(const TPpToken& right)
+    bool operator==(const TPpToken& right) const
     {
         return space == right.space &&
                ival == right.ival && dval == right.dval && i64val == right.i64val &&
                strncmp(name, right.name, MaxTokenLength) == 0;
     }
-    bool operator!=(const TPpToken& right) { return ! operator==(right); }
+    bool operator!=(const TPpToken& right) const { return ! operator==(right); }
 
     TSourceLoc loc;
     // True if a space (for white space or a removed comment) should also be
@@ -695,6 +695,7 @@ protected:
     std::string currentSourceFile;
 
     std::istringstream strtodStream;
+    bool disableEscapeSequences;
 };
 
 } // end namespace glslang

+ 76 - 6
src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp

@@ -1026,12 +1026,80 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
         case '\'':
             return pp->characterLiteral(ppToken);
         case '"':
-            // TODO: If this gets enhanced to handle escape sequences, or
-            // anything that is different than what #include needs, then
-            // #include needs to use scanHeaderName() for this.
+            // #include uses scanHeaderName() to ignore these escape sequences.
             ch = getch();
             while (ch != '"' && ch != '\n' && ch != EndOfInput) {
                 if (len < MaxTokenLength) {
+                    if (ch == '\\' && !pp->disableEscapeSequences) {
+                        int nextCh = getch();
+                        switch (nextCh) {
+                        case '\'': ch = 0x27; break;
+                        case '"':  ch = 0x22; break;
+                        case '?':  ch = 0x3f; break;
+                        case '\\': ch = 0x5c; break;
+                        case 'a':  ch = 0x07; break;
+                        case 'b':  ch = 0x08; break;
+                        case 'f':  ch = 0x0c; break;
+                        case 'n':  ch = 0x0a; break;
+                        case 'r':  ch = 0x0d; break;
+                        case 't':  ch = 0x09; break;
+                        case 'v':  ch = 0x0b; break;
+                        case 'x': 
+                            // Hex value, arbitrary number of characters. Terminated by the first
+                            // non-hex digit
+                            {
+                                int numDigits = 0;
+                                ch = 0;
+                                while (true) {
+                                    nextCh = getch();
+                                    if (nextCh >= '0' && nextCh <= '9')
+                                        nextCh -= '0';
+                                    else if (nextCh >= 'A' && nextCh <= 'F')
+                                        nextCh -= 'A' - 10;
+                                    else if (nextCh >= 'a' && nextCh <= 'f')
+                                        nextCh -= 'a' - 10;
+                                    else {
+                                        ungetch();
+                                        break;
+                                    }
+                                    numDigits++;
+                                    ch = ch * 0x10 + nextCh;
+                                }
+                                if (numDigits == 0) {
+                                    pp->parseContext.ppError(ppToken->loc, "Expected hex value in escape sequence", "string", "");
+                                }
+                                break;
+                            }
+                        case '0':
+                        case '1':
+                        case '2':
+                        case '3':
+                        case '4':
+                        case '5':
+                        case '6':
+                        case '7':
+                            // Octal value, up to three octal digits
+                            {
+                                int numDigits = 1;
+                                ch = nextCh - '0';
+                                while (numDigits < 3) {
+                                    nextCh = getch();
+                                    if (nextCh >= '0' && nextCh <= '7')
+                                        nextCh -= '0';
+                                    else {
+                                        ungetch();
+                                        break;
+                                    }
+                                    numDigits++;
+                                    ch = ch * 8 + nextCh;
+                                }
+                                break;
+                            }
+                        default:
+                            pp->parseContext.ppError(ppToken->loc, "Invalid escape sequence", "string", "");
+                            break;
+                        }
+                    }
                     ppToken->name[len] = (char)ch;
                     len++;
                     ch = getch();
@@ -1120,10 +1188,12 @@ int TPpContext::tokenize(TPpToken& ppToken)
                 continue;
             break;
         case PpAtomConstString:
+            // HLSL allows string literals.
+            // GLSL allows string literals with GL_EXT_debug_printf.
             if (ifdepth == 0 && parseContext.intermediate.getSource() != EShSourceHlsl) {
-                // HLSL allows string literals.
-                parseContext.ppError(ppToken.loc, "string literals not supported", "\"\"", "");
-                continue;
+                parseContext.requireExtensions(ppToken.loc, 1, &E_GL_EXT_debug_printf, "string literal");
+                if (!parseContext.extensionTurnedOn(E_GL_EXT_debug_printf))
+                    continue;
             }
             break;
         case '\'':

+ 1 - 1
src/libraries/glslang/glslang/MachineIndependent/propagateNoContraction.cpp

@@ -867,4 +867,4 @@ void PropagateNoContraction(const glslang::TIntermediate& intermediate)
 }
 };
 
-#endif // GLSLANG_WEB
+#endif // GLSLANG_WEB

+ 164 - 99
src/libraries/glslang/glslang/MachineIndependent/reflection.cpp

@@ -33,7 +33,7 @@
 // POSSIBILITY OF SUCH DAMAGE.
 //
 
-#ifndef GLSLANG_WEB
+#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
 
 #include "../Include/Common.h"
 #include "reflection.h"
@@ -77,10 +77,10 @@ namespace glslang {
 // This is in the glslang namespace directly so it can be a friend of TReflection.
 //
 
-class TReflectionTraverser : public TLiveTraverser {
+class TReflectionTraverser : public TIntermTraverser {
 public:
     TReflectionTraverser(const TIntermediate& i, TReflection& r) :
-         TLiveTraverser(i), reflection(r) { }
+	                     TIntermTraverser(), intermediate(i), reflection(r), updateStageMasks(true) { }
 
     virtual bool visitBinary(TVisit, TIntermBinary* node);
     virtual void visitSymbol(TIntermSymbol* base);
@@ -92,11 +92,28 @@ public:
         if (processedDerefs.find(&base) == processedDerefs.end()) {
             processedDerefs.insert(&base);
 
+            int blockIndex = -1;
+            int offset     = -1;
+            TList<TIntermBinary*> derefs;
+            TString baseName = base.getName();
+
+            if (base.getType().getBasicType() == EbtBlock) {
+                offset = 0;
+                bool anonymous = IsAnonymous(baseName);
+                const TString& blockName = base.getType().getTypeName();
+
+                if (!anonymous)
+                    baseName = blockName;
+                else
+                    baseName = "";
+
+                blockIndex = addBlockName(blockName, base.getType(), intermediate.getBlockSize(base.getType()));
+            }
+
             // Use a degenerate (empty) set of dereferences to immediately put as at the end of
             // the dereference change expected by blowUpActiveAggregate.
-            TList<TIntermBinary*> derefs;
-            blowUpActiveAggregate(base.getType(), base.getName(), derefs, derefs.end(), -1, -1, 0, 0,
-                                  base.getQualifier().storage, true);
+            blowUpActiveAggregate(base.getType(), baseName, derefs, derefs.end(), offset, blockIndex, 0, -1, 0,
+                                    base.getQualifier().storage, updateStageMasks);
         }
     }
 
@@ -155,9 +172,9 @@ public:
     void getOffsets(const TType& type, TVector<int>& offsets)
     {
         const TTypeList& memberList = *type.getStruct();
-
         int memberSize = 0;
         int offset = 0;
+
         for (size_t m = 0; m < offsets.size(); ++m) {
             // if the user supplied an offset, snap to it now
             if (memberList[m].type->getQualifier().hasOffset())
@@ -233,7 +250,7 @@ public:
     // A value of 0 for arraySize will mean to use the full array's size.
     void blowUpActiveAggregate(const TType& baseType, const TString& baseName, const TList<TIntermBinary*>& derefs,
                                TList<TIntermBinary*>::const_iterator deref, int offset, int blockIndex, int arraySize,
-                               int topLevelArrayStride, TStorageQualifier baseStorage, bool active)
+                               int topLevelArraySize, int topLevelArrayStride, TStorageQualifier baseStorage, bool active)
     {
         // when strictArraySuffix is enabled, we closely follow the rules from ARB_program_interface_query.
         // Broadly:
@@ -262,14 +279,15 @@ public:
                 // Visit all the indices of this array, and for each one add on the remaining dereferencing
                 for (int i = 0; i < std::max(visitNode->getLeft()->getType().getOuterArraySize(), 1); ++i) {
                     TString newBaseName = name;
-                    if (strictArraySuffix && blockParent)
+                    if (terminalType->getBasicType() == EbtBlock) {}
+                    else if (strictArraySuffix && blockParent)
                         newBaseName.append(TString("[0]"));
                     else if (strictArraySuffix || baseType.getBasicType() != EbtBlock)
                         newBaseName.append(TString("[") + String(i) + "]");
                     TList<TIntermBinary*>::const_iterator nextDeref = deref;
                     ++nextDeref;
                     blowUpActiveAggregate(*terminalType, newBaseName, derefs, nextDeref, offset, blockIndex, arraySize,
-                                          topLevelArrayStride, baseStorage, active);
+                                          topLevelArraySize, topLevelArrayStride, baseStorage, active);
 
                     if (offset >= 0)
                         offset += stride;
@@ -282,9 +300,10 @@ public:
                 int stride = getArrayStride(baseType, visitNode->getLeft()->getType());
 
                 index = visitNode->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst();
-                if (strictArraySuffix && blockParent) {
+                if (terminalType->getBasicType() == EbtBlock) {}
+                else if (strictArraySuffix && blockParent)
                     name.append(TString("[0]"));
-                } else if (strictArraySuffix || baseType.getBasicType() != EbtBlock) {
+                else if (strictArraySuffix || baseType.getBasicType() != EbtBlock) {
                     name.append(TString("[") + String(index) + "]");
 
                     if (offset >= 0)
@@ -294,7 +313,10 @@ public:
                 if (topLevelArrayStride == 0)
                     topLevelArrayStride = stride;
 
-                blockParent = false;
+                // expand top-level arrays in blocks with [0] suffix
+                if (topLevelArrayStride != 0 && visitNode->getLeft()->getType().isArray()) {
+                    blockParent = false;
+                }
                 break;
             }
             case EOpIndexDirectStruct:
@@ -304,6 +326,12 @@ public:
                 if (name.size() > 0)
                     name.append(".");
                 name.append((*visitNode->getLeft()->getType().getStruct())[index].type->getFieldName());
+
+                // expand non top-level arrays with [x] suffix
+                if (visitNode->getLeft()->getType().getBasicType() != EbtBlock && terminalType->isArray())
+                {
+                    blockParent = false;
+                }
                 break;
             default:
                 break;
@@ -323,24 +351,27 @@ public:
                 if (offset >= 0)
                     stride = getArrayStride(baseType, *terminalType);
 
-                if (topLevelArrayStride == 0)
-                    topLevelArrayStride = stride;
-
                 int arrayIterateSize = std::max(terminalType->getOuterArraySize(), 1);
 
                 // for top-level arrays in blocks, only expand [0] to avoid explosion of items
-                if (strictArraySuffix && blockParent)
+                if ((strictArraySuffix && blockParent) ||
+                    ((topLevelArraySize == arrayIterateSize) && (topLevelArrayStride == 0))) {
                     arrayIterateSize = 1;
+                }
+
+                if (topLevelArrayStride == 0)
+                    topLevelArrayStride = stride;
 
                 for (int i = 0; i < arrayIterateSize; ++i) {
                     TString newBaseName = name;
-                    newBaseName.append(TString("[") + String(i) + "]");
+                    if (terminalType->getBasicType() != EbtBlock)
+                        newBaseName.append(TString("[") + String(i) + "]");
                     TType derefType(*terminalType, 0);
                     if (offset >= 0)
                         offset = baseOffset + stride * i;
 
                     blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), offset, blockIndex, 0,
-                                          topLevelArrayStride, baseStorage, active);
+                                          topLevelArraySize, topLevelArrayStride, baseStorage, active);
                 }
             } else {
                 // Visit all members of this aggregate, and for each one,
@@ -369,8 +400,31 @@ public:
                         arrayStride = getArrayStride(baseType, derefType);
                     }
 
-                    blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), offset, blockIndex, 0,
-                                          arrayStride, baseStorage, active);
+                    if (topLevelArraySize == -1 && arrayStride == 0 && blockParent)
+                        topLevelArraySize = 1;
+
+                    if (strictArraySuffix && blockParent) {
+                        // if this member is an array, store the top-level array stride but start the explosion from
+                        // the inner struct type.
+                        if (derefType.isArray() && derefType.isStruct()) {
+                            newBaseName.append("[0]");
+                            auto dimSize = derefType.isUnsizedArray() ? 0 : derefType.getArraySizes()->getDimSize(0);
+                            blowUpActiveAggregate(TType(derefType, 0), newBaseName, derefs, derefs.end(), memberOffsets[i],
+                                blockIndex, 0, dimSize, arrayStride, terminalType->getQualifier().storage, false);
+                        }
+                        else if (derefType.isArray()) {
+                            auto dimSize = derefType.isUnsizedArray() ? 0 : derefType.getArraySizes()->getDimSize(0);
+                            blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), memberOffsets[i], blockIndex,
+                                0, dimSize, 0, terminalType->getQualifier().storage, false);
+                        }
+                        else {
+                            blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), memberOffsets[i], blockIndex,
+                                0, 1, 0, terminalType->getQualifier().storage, false);
+                        }
+                    } else {
+                        blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), offset, blockIndex, 0,
+                                              topLevelArraySize, arrayStride, baseStorage, active);
+                    }
                 }
             }
 
@@ -406,6 +460,7 @@ public:
             if ((reflection.options & EShReflectionSeparateBuffers) && terminalType->isAtomic())
                 reflection.atomicCounterUniformIndices.push_back(uniformIndex);
 
+            variables.back().topLevelArraySize = topLevelArraySize;
             variables.back().topLevelArrayStride = topLevelArrayStride;
             
             if ((reflection.options & EShReflectionAllBlockVariables) && active) {
@@ -537,65 +592,17 @@ public:
             if (! anonymous)
                 baseName = blockName;
 
-            if (base->getType().isArray()) {
-                TType derefType(base->getType(), 0);
-
-                assert(! anonymous);
-                for (int e = 0; e < base->getType().getCumulativeArraySize(); ++e)
-                    blockIndex = addBlockName(blockName + "[" + String(e) + "]", derefType,
-                                              intermediate.getBlockSize(base->getType()));
-                baseName.append(TString("[0]"));
-            } else
-                blockIndex = addBlockName(blockName, base->getType(), intermediate.getBlockSize(base->getType()));
+            blockIndex = addBlockName(blockName, base->getType(), intermediate.getBlockSize(base->getType()));
 
             if (reflection.options & EShReflectionAllBlockVariables) {
                 // Use a degenerate (empty) set of dereferences to immediately put as at the end of
                 // the dereference change expected by blowUpActiveAggregate.
                 TList<TIntermBinary*> derefs;
 
-                // because we don't have any derefs, the first thing blowUpActiveAggregate will do is iterate over each
-                // member in the struct definition. This will lose any information about whether the parent was a buffer
-                // block. So if we're using strict array rules which don't expand the first child of a buffer block we
-                // instead iterate over the children here.
-                const bool strictArraySuffix = (reflection.options & EShReflectionStrictArraySuffix);
-                bool blockParent = (base->getType().getBasicType() == EbtBlock && base->getQualifier().storage == EvqBuffer);
-
-                if (strictArraySuffix && blockParent) {
-                    TType structDerefType(base->getType(), 0);
-
-                    const TType &structType = base->getType().isArray() ? structDerefType : base->getType();
-                    const TTypeList& typeList = *structType.getStruct();
-
-                    TVector<int> memberOffsets;
-
-                    memberOffsets.resize(typeList.size());
-                    getOffsets(structType, memberOffsets);
-
-                    for (int i = 0; i < (int)typeList.size(); ++i) {
-                        TType derefType(structType, i);
-                        TString name = baseName;
-                        if (name.size() > 0)
-                            name.append(".");
-                        name.append(typeList[i].type->getFieldName());
-
-                        // if this member is an array, store the top-level array stride but start the explosion from
-                        // the inner struct type.
-                        if (derefType.isArray() && derefType.isStruct()) {
-                            name.append("[0]");
-                            blowUpActiveAggregate(TType(derefType, 0), name, derefs, derefs.end(), memberOffsets[i],
-                                                  blockIndex, 0, getArrayStride(structType, derefType),
-                                                  base->getQualifier().storage, false);
-                        } else {
-                            blowUpActiveAggregate(derefType, name, derefs, derefs.end(), memberOffsets[i], blockIndex,
-                                                  0, 0, base->getQualifier().storage, false);
-                        }
-                    }
-                } else {
-                    // otherwise - if we're not using strict array suffix rules, or this isn't a block so we are
-                    // expanding root arrays anyway, just start the iteration from the base block type.
-                    blowUpActiveAggregate(base->getType(), baseName, derefs, derefs.end(), 0, blockIndex, 0, 0,
+                // otherwise - if we're not using strict array suffix rules, or this isn't a block so we are
+                // expanding root arrays anyway, just start the iteration from the base block type.
+                blowUpActiveAggregate(base->getType(), baseName, derefs, derefs.end(), 0, blockIndex, 0, -1, 0,
                                           base->getQualifier().storage, false);
-                }
             }
         }
 
@@ -626,30 +633,40 @@ public:
             else
                 baseName = base->getName();
         }
-        blowUpActiveAggregate(base->getType(), baseName, derefs, derefs.begin(), offset, blockIndex, arraySize, 0,
+        blowUpActiveAggregate(base->getType(), baseName, derefs, derefs.begin(), offset, blockIndex, arraySize, -1, 0,
                               base->getQualifier().storage, true);
     }
 
     int addBlockName(const TString& name, const TType& type, int size)
     {
-        TReflection::TMapIndexToReflection& blocks = reflection.GetBlockMapForStorage(type.getQualifier().storage);
+        int blockIndex = 0;
+        if (type.isArray()) {
+            TType derefType(type, 0);
+            for (int e = 0; e < type.getOuterArraySize(); ++e) {
+                int memberBlockIndex = addBlockName(name + "[" + String(e) + "]", derefType, size);
+                if (e == 0)
+                    blockIndex = memberBlockIndex;
+            }
+        } else {
+            TReflection::TMapIndexToReflection& blocks = reflection.GetBlockMapForStorage(type.getQualifier().storage);
 
-        int blockIndex;
-        TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name.c_str());
-        if (reflection.nameToIndex.find(name.c_str()) == reflection.nameToIndex.end()) {
-            blockIndex = (int)blocks.size();
-            reflection.nameToIndex[name.c_str()] = blockIndex;
-            blocks.push_back(TObjectReflection(name.c_str(), type, -1, -1, size, -1));
+            TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name.c_str());
+            if (reflection.nameToIndex.find(name.c_str()) == reflection.nameToIndex.end()) {
+                blockIndex = (int)blocks.size();
+                reflection.nameToIndex[name.c_str()] = blockIndex;
+                blocks.push_back(TObjectReflection(name.c_str(), type, -1, -1, size, blockIndex));
 
-            blocks.back().numMembers = countAggregateMembers(type);
+                blocks.back().numMembers = countAggregateMembers(type);
 
-            EShLanguageMask& stages = blocks.back().stages;
-            stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
-        } else {
-            blockIndex = it->second;
+                EShLanguageMask& stages = blocks.back().stages;
+                stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
+            }
+            else {
+                blockIndex = it->second;
 
-            EShLanguageMask& stages = blocks[blockIndex].stages;
-            stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
+                EShLanguageMask& stages = blocks[blockIndex].stages;
+                stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
+            }
         }
 
         return blockIndex;
@@ -995,8 +1012,10 @@ public:
         return type.isArray() ? type.getOuterArraySize() : 1;
     }
 
+    const TIntermediate& intermediate;
     TReflection& reflection;
     std::set<const TIntermNode*> processedDerefs;
+    bool updateStageMasks;
 
 protected:
     TReflectionTraverser(TReflectionTraverser&);
@@ -1029,7 +1048,21 @@ bool TReflectionTraverser::visitBinary(TVisit /* visit */, TIntermBinary* node)
 // To reflect non-dereferenced objects.
 void TReflectionTraverser::visitSymbol(TIntermSymbol* base)
 {
-    if (base->getQualifier().storage == EvqUniform)
+    if (base->getQualifier().storage == EvqUniform) {
+        if (base->getBasicType() == EbtBlock) {
+            if (reflection.options & EShReflectionSharedStd140UBO) {
+                addUniform(*base);
+            }
+        } else {
+            addUniform(*base);
+        }
+    }
+
+    // #TODO add std140/layout active rules for ssbo, same with ubo.
+    // Storage buffer blocks will be collected and expanding in this part.
+    if((reflection.options & EShReflectionSharedStd140SSBO) &&
+       (base->getQualifier().storage == EvqBuffer && base->getBasicType() == EbtBlock &&
+        (base->getQualifier().layoutPacking == ElpStd140 || base->getQualifier().layoutPacking == ElpShared)))
         addUniform(*base);
 
     if ((intermediate.getStage() == reflection.firstStage && base->getQualifier().isPipeInput()) ||
@@ -1135,15 +1168,47 @@ bool TReflection::addStage(EShLanguage stage, const TIntermediate& intermediate)
 
     TReflectionTraverser it(intermediate, *this);
 
-    // put the entry point on the list of functions to process
-    it.pushFunction(intermediate.getEntryPointMangledName().c_str());
-
-    // process all the functions
-    while (! it.functions.empty()) {
-        TIntermNode* function = it.functions.back();
-        it.functions.pop_back();
-        function->traverse(&it);
+    for (auto& sequnence : intermediate.getTreeRoot()->getAsAggregate()->getSequence()) {
+        if (sequnence->getAsAggregate() != nullptr) {
+            if (sequnence->getAsAggregate()->getOp() == glslang::EOpLinkerObjects) {
+                it.updateStageMasks = false;
+                TIntermAggregate* linkerObjects = sequnence->getAsAggregate();
+                for (auto& sequnence : linkerObjects->getSequence()) {
+                    auto pNode = sequnence->getAsSymbolNode();
+                    if (pNode != nullptr) {
+                        if ((pNode->getQualifier().storage == EvqUniform &&
+                            (options & EShReflectionSharedStd140UBO)) ||
+                           (pNode->getQualifier().storage == EvqBuffer &&
+                            (options & EShReflectionSharedStd140SSBO))) {
+                            // collect std140 and shared uniform block form AST
+                            if ((pNode->getBasicType() == EbtBlock) &&
+                                ((pNode->getQualifier().layoutPacking == ElpStd140) ||
+                                 (pNode->getQualifier().layoutPacking == ElpShared))) {
+                                   pNode->traverse(&it);
+                            }
+                        }
+                        else if ((options & EShReflectionAllIOVariables) &&
+                            (pNode->getQualifier().isPipeInput() || pNode->getQualifier().isPipeOutput()))
+                        {
+                            pNode->traverse(&it);
+                        }
+                    }
+                }
+            } else {
+                // This traverser will travers all function in AST.
+                // If we want reflect uncalled function, we need set linke message EShMsgKeepUncalled.
+                // When EShMsgKeepUncalled been set to true, all function will be keep in AST, even it is a uncalled function.
+                // This will keep some uniform variables in reflection, if those uniform variables is used in these uncalled function.
+                //
+                // If we just want reflect only live node, we can use a default link message or set EShMsgKeepUncalled false.
+                // When linke message not been set EShMsgKeepUncalled, linker won't keep uncalled function in AST.
+                // So, travers all function node can equivalent to travers live function.
+                it.updateStageMasks = true;
+                sequnence->getAsAggregate()->traverse(&it);
+            }
+        }
     }
+    it.updateStageMasks = true;
 
     buildCounterIndices(intermediate);
     buildUniformStageMask(intermediate);
@@ -1188,7 +1253,7 @@ void TReflection::dump()
 
         for (int dim=0; dim<3; ++dim)
             if (getLocalSize(dim) > 1)
-                printf("Local size %s: %d\n", axis[dim], getLocalSize(dim));
+                printf("Local size %s: %u\n", axis[dim], getLocalSize(dim));
 
         printf("\n");
     }
@@ -1201,4 +1266,4 @@ void TReflection::dump()
 
 } // end namespace glslang
 
-#endif // GLSLANG_WEB
+#endif // !GLSLANG_WEB && !GLSLANG_ANGLE

+ 2 - 2
src/libraries/glslang/glslang/MachineIndependent/reflection.h

@@ -33,7 +33,7 @@
 // POSSIBILITY OF SUCH DAMAGE.
 //
 
-#ifndef GLSLANG_WEB
+#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
 
 #ifndef _REFLECTION_INCLUDED
 #define _REFLECTION_INCLUDED
@@ -220,4 +220,4 @@ protected:
 
 #endif // _REFLECTION_INCLUDED
 
-#endif // GLSLANG_WEB
+#endif // !GLSLANG_WEB && !GLSLANG_ANGLE

+ 22 - 4
src/libraries/glslang/glslang/OSDependent/Web/glslang.js.cpp

@@ -141,6 +141,7 @@ const TBuiltInResource DefaultTBuiltInResource = {
     /* .maxTaskWorkGroupSizeY_NV = */ 1,
     /* .maxTaskWorkGroupSizeZ_NV = */ 1,
     /* .maxMeshViewCountNV = */ 4,
+    /* .maxDualSourceDrawBuffersEXT = */ 1,
 
     /* .limits = */ {
         /* .nonInductiveForLoops = */ 1,
@@ -176,7 +177,12 @@ extern "C" {
  * If null, the compilation failed.
  */
 EMSCRIPTEN_KEEPALIVE
-void* convert_glsl_to_spirv(const char* glsl, int stage_int, bool gen_debug, uint32_t** spirv, size_t* spirv_len)
+void* convert_glsl_to_spirv(const char* glsl,
+                            int stage_int,
+                            bool gen_debug,
+                            glslang::EShTargetLanguageVersion spirv_version,
+                            uint32_t** spirv,
+                            size_t* spirv_len)
 {
     if (glsl == nullptr) {
         fprintf(stderr, "Input pointer null\n");
@@ -194,6 +200,18 @@ void* convert_glsl_to_spirv(const char* glsl, int stage_int, bool gen_debug, uin
         return nullptr;
     }
     EShLanguage stage = static_cast<EShLanguage>(stage_int);
+    switch (spirv_version) {
+        case glslang::EShTargetSpv_1_0:
+        case glslang::EShTargetSpv_1_1:
+        case glslang::EShTargetSpv_1_2:
+        case glslang::EShTargetSpv_1_3:
+        case glslang::EShTargetSpv_1_4:
+        case glslang::EShTargetSpv_1_5:
+            break;
+        default:
+            fprintf(stderr, "Invalid SPIR-V version number\n");
+            return nullptr;
+    }
 
     if (!initialized) {
         glslang::InitializeProcess();
@@ -203,8 +221,8 @@ void* convert_glsl_to_spirv(const char* glsl, int stage_int, bool gen_debug, uin
     glslang::TShader shader(stage);
     shader.setStrings(&glsl, 1);
     shader.setEnvInput(glslang::EShSourceGlsl, stage, glslang::EShClientVulkan, 100);
-    shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_1);
-    shader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_3);
+    shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_0);
+    shader.setEnvTarget(glslang::EShTargetSpv, spirv_version);
     if (!shader.parse(&DefaultTBuiltInResource, 100, true, EShMsgDefault)) {
         fprintf(stderr, "Parse failed\n");
         fprintf(stderr, "%s\n", shader.getInfoLog());
@@ -260,7 +278,7 @@ void main() { })";
     uint32_t* output;
     size_t output_len;
 
-    void* id = convert_glsl_to_spirv(input, 4, false, &output, &output_len);
+    void* id = convert_glsl_to_spirv(input, 4, false, glslang::EShTargetSpv_1_0, &output, &output_len);
     assert(output != nullptr);
     assert(output_len != 0);
     destroy_output_buffer(id);

+ 25 - 14
src/libraries/glslang/glslang/OSDependent/Web/glslang.pre.js

@@ -1,23 +1,34 @@
-Module['compileGLSLZeroCopy'] = function(glsl, shader_stage, gen_debug) {
+Module['compileGLSLZeroCopy'] = function(glsl, shader_stage, gen_debug, spirv_version) {
     gen_debug = !!gen_debug;
 
-    var shader_stage_int;
-    if (shader_stage === 'vertex') {
-        shader_stage_int = 0;
-    } else if (shader_stage === 'fragment') {
-        shader_stage_int = 4;
-    } else if (shader_stage === 'compute') {
-        shader_stage_int = 5;
-    } else {
-        throw new Error("shader_stage must be 'vertex', 'fragment', or 'compute'");
+    var shader_stage_int; // EShLanguage
+    switch (shader_stage) {
+        case 'vertex':   shader_stage_int = 0; break;
+        case 'fragment': shader_stage_int = 4; break;
+        case 'compute':  shader_stage_int = 5; break;
+        default:
+            throw new Error("shader_stage must be 'vertex', 'fragment', or 'compute'.");
+    }
+
+    spirv_version = spirv_version || '1.0';
+    var spirv_version_int; // EShTargetLanguageVersion
+    switch (spirv_version) {
+        case '1.0': spirv_version_int = (1 << 16) | (0 << 8); break;
+        case '1.1': spirv_version_int = (1 << 16) | (1 << 8); break;
+        case '1.2': spirv_version_int = (1 << 16) | (2 << 8); break;
+        case '1.3': spirv_version_int = (1 << 16) | (3 << 8); break;
+        case '1.4': spirv_version_int = (1 << 16) | (4 << 8); break;
+        case '1.5': spirv_version_int = (1 << 16) | (5 << 8); break;
+        default:
+            throw new Error("spirv_version must be '1.0' ~ '1.5'.");
     }
 
     var p_output = Module['_malloc'](4);
     var p_output_len = Module['_malloc'](4);
     var id = ccall('convert_glsl_to_spirv',
         'number',
-        ['string', 'number', 'boolean', 'number', 'number'],
-        [glsl, shader_stage_int, gen_debug, p_output, p_output_len]);
+        ['string', 'number', 'boolean', 'number', 'number', 'number'],
+        [glsl, shader_stage_int, gen_debug, spirv_version_int, p_output, p_output_len]);
     var output = getValue(p_output, 'i32');
     var output_len = getValue(p_output_len, 'i32');
     Module['_free'](p_output);
@@ -37,8 +48,8 @@ Module['compileGLSLZeroCopy'] = function(glsl, shader_stage, gen_debug) {
     return ret;
 };
 
-Module['compileGLSL'] = function(glsl, shader_stage, gen_debug) {
-    var compiled = Module['compileGLSLZeroCopy'](glsl, shader_stage, gen_debug);
+Module['compileGLSL'] = function(glsl, shader_stage, gen_debug, spirv_version) {
+    var compiled = Module['compileGLSLZeroCopy'](glsl, shader_stage, gen_debug, spirv_version);
     var ret = compiled['data'].slice()
     compiled['free']();
     return ret;

+ 179 - 133
src/libraries/glslang/glslang/Public/ShaderLang.h

@@ -44,16 +44,25 @@
 #include <vector>
 
 #ifdef _WIN32
-#define C_DECL __cdecl
-//#ifdef SH_EXPORTING
-//    #define SH_IMPORT_EXPORT __declspec(dllexport)
-//#else
-//    #define SH_IMPORT_EXPORT __declspec(dllimport)
-//#endif
-#define SH_IMPORT_EXPORT
+    #define C_DECL __cdecl
 #else
-#define SH_IMPORT_EXPORT
-#define C_DECL
+    #define C_DECL
+#endif
+
+#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
 
 //
@@ -65,22 +74,17 @@
     extern "C" {
 #endif
 
-// This should always increase, as some paths to do not consume
-// a more major number.
-// It should increment by one when new functionality is added.
-#define GLSLANG_MINOR_VERSION 13
-
 //
 // Call before doing any other compiler/linker operations.
 //
 // (Call once per process, not once per thread.)
 //
-SH_IMPORT_EXPORT int ShInitialize();
+GLSLANG_EXPORT int ShInitialize();
 
 //
 // Call this at process shutdown to clean up memory.
 //
-SH_IMPORT_EXPORT int ShFinalize();
+GLSLANG_EXPORT int ShFinalize();
 
 //
 // Types of languages the compiler can consume.
@@ -92,32 +96,45 @@ typedef enum {
     EShLangGeometry,
     EShLangFragment,
     EShLangCompute,
-    EShLangRayGenNV,
-    EShLangIntersectNV,
-    EShLangAnyHitNV,
-    EShLangClosestHitNV,
-    EShLangMissNV,
-    EShLangCallableNV,
+    EShLangRayGen,
+    EShLangRayGenNV = EShLangRayGen,
+    EShLangIntersect,
+    EShLangIntersectNV = EShLangIntersect,
+    EShLangAnyHit,
+    EShLangAnyHitNV = EShLangAnyHit,
+    EShLangClosestHit,
+    EShLangClosestHitNV = EShLangClosestHit,
+    EShLangMiss,
+    EShLangMissNV = EShLangMiss,
+    EShLangCallable,
+    EShLangCallableNV = EShLangCallable,
     EShLangTaskNV,
     EShLangMeshNV,
-    EShLangCount,
+    LAST_ELEMENT_MARKER(EShLangCount),
 } EShLanguage;         // would be better as stage, but this is ancient now
 
-typedef enum {
+typedef enum : unsigned {
     EShLangVertexMask         = (1 << EShLangVertex),
     EShLangTessControlMask    = (1 << EShLangTessControl),
     EShLangTessEvaluationMask = (1 << EShLangTessEvaluation),
     EShLangGeometryMask       = (1 << EShLangGeometry),
     EShLangFragmentMask       = (1 << EShLangFragment),
     EShLangComputeMask        = (1 << EShLangCompute),
-    EShLangRayGenNVMask       = (1 << EShLangRayGenNV),
-    EShLangIntersectNVMask    = (1 << EShLangIntersectNV),
-    EShLangAnyHitNVMask       = (1 << EShLangAnyHitNV),
-    EShLangClosestHitNVMask   = (1 << EShLangClosestHitNV),
-    EShLangMissNVMask         = (1 << EShLangMissNV),
-    EShLangCallableNVMask     = (1 << EShLangCallableNV),
+    EShLangRayGenMask         = (1 << EShLangRayGen),
+    EShLangRayGenNVMask       = EShLangRayGenMask,
+    EShLangIntersectMask      = (1 << EShLangIntersect),
+    EShLangIntersectNVMask    = EShLangIntersectMask,
+    EShLangAnyHitMask         = (1 << EShLangAnyHit),
+    EShLangAnyHitNVMask       = EShLangAnyHitMask,
+    EShLangClosestHitMask     = (1 << EShLangClosestHit),
+    EShLangClosestHitNVMask   = EShLangClosestHitMask,
+    EShLangMissMask           = (1 << EShLangMiss),
+    EShLangMissNVMask         = EShLangMissMask,
+    EShLangCallableMask       = (1 << EShLangCallable),
+    EShLangCallableNVMask     = EShLangCallableMask,
     EShLangTaskNVMask         = (1 << EShLangTaskNV),
     EShLangMeshNVMask         = (1 << EShLangMeshNV),
+    LAST_ELEMENT_MARKER(EShLanguageMaskCount),
 } EShLanguageMask;
 
 namespace glslang {
@@ -128,24 +145,29 @@ typedef enum {
     EShSourceNone,
     EShSourceGlsl,               // GLSL, includes ESSL (OpenGL ES GLSL)
     EShSourceHlsl,               // HLSL
+    LAST_ELEMENT_MARKER(EShSourceCount),
 } EShSource;                     // if EShLanguage were EShStage, this could be EShLanguage instead
 
 typedef enum {
     EShClientNone,               // use when there is no client, e.g. for validation
     EShClientVulkan,
     EShClientOpenGL,
+    LAST_ELEMENT_MARKER(EShClientCount),
 } EShClient;
 
 typedef enum {
     EShTargetNone,
     EShTargetSpv,                 // SPIR-V (preferred spelling)
     EshTargetSpv = EShTargetSpv,  // legacy spelling
+    LAST_ELEMENT_MARKER(EShTargetCount),
 } EShTargetLanguage;
 
 typedef enum {
     EShTargetVulkan_1_0 = (1 << 22),                  // Vulkan 1.0
     EShTargetVulkan_1_1 = (1 << 22) | (1 << 12),      // Vulkan 1.1
+    EShTargetVulkan_1_2 = (1 << 22) | (2 << 12),      // Vulkan 1.2
     EShTargetOpenGL_450 = 450,                        // OpenGL
+    LAST_ELEMENT_MARKER(EShTargetClientVersionCount),
 } EShTargetClientVersion;
 
 typedef EShTargetClientVersion EshTargetClientVersion;
@@ -157,6 +179,7 @@ typedef enum {
     EShTargetSpv_1_3 = (1 << 16) | (3 << 8),          // SPIR-V 1.3
     EShTargetSpv_1_4 = (1 << 16) | (4 << 8),          // SPIR-V 1.4
     EShTargetSpv_1_5 = (1 << 16) | (5 << 8),          // SPIR-V 1.5
+    LAST_ELEMENT_MARKER(EShTargetLanguageVersionCount),
 } EShTargetLanguageVersion;
 
 struct TInputLanguage {
@@ -186,7 +209,7 @@ struct TEnvironment {
     TTarget target;           // what to generate
 };
 
-const char* StageName(EShLanguage);
+GLSLANG_EXPORT const char* StageName(EShLanguage);
 
 } // end namespace glslang
 
@@ -206,6 +229,7 @@ typedef enum {
     EShOptNone,
     EShOptSimple,       // Optimizations that can be done quickly
     EShOptFull,         // Optimizations that will take more time
+    LAST_ELEMENT_MARKER(EshOptLevelCount),
 } EShOptimizationLevel;
 
 //
@@ -214,12 +238,13 @@ typedef enum {
 typedef enum {
     EShTexSampTransKeep,   // keep textures and samplers as is (default)
     EShTexSampTransUpgradeTextureRemoveSampler,  // change texture w/o embeded sampler into sampled texture and throw away all samplers
+    LAST_ELEMENT_MARKER(EShTexSampTransCount),
 } EShTextureSamplerTransformMode;
 
 //
 // Message choices for what errors and warnings are given.
 //
-enum EShMessages {
+enum EShMessages : unsigned {
     EShMsgDefault          = 0,         // default is to give all required errors and extra warnings
     EShMsgRelaxedErrors    = (1 << 0),  // be liberal in accepting input
     EShMsgSuppressWarnings = (1 << 1),  // suppress all warnings, except those required by the specification
@@ -234,21 +259,26 @@ enum EShMessages {
     EShMsgDebugInfo        = (1 << 10), // save debug information
     EShMsgHlslEnable16BitTypes  = (1 << 11), // enable use of 16-bit types in SPIR-V for HLSL
     EShMsgHlslLegalization  = (1 << 12), // enable HLSL Legalization messages
-    EShMsgHlslDX9Compatible = (1 << 13), // enable HLSL DX9 compatible mode (right now only for samplers)
+    EShMsgHlslDX9Compatible = (1 << 13), // enable HLSL DX9 compatible mode (for samplers and semantics)
     EShMsgBuiltinSymbolTable = (1 << 14), // print the builtin symbol table
+    LAST_ELEMENT_MARKER(EShMsgCount),
 };
 
 //
 // Options for building reflection
 //
 typedef enum {
-    EShReflectionDefault           = 0,        // default is original behaviour before options were added
-    EShReflectionStrictArraySuffix = (1 << 0), // reflection will follow stricter rules for array-of-structs suffixes
-    EShReflectionBasicArraySuffix  = (1 << 1), // arrays of basic types will be appended with [0] as in GL reflection
-    EShReflectionIntermediateIO    = (1 << 2), // reflect inputs and outputs to program, even with no vertex shader
-    EShReflectionSeparateBuffers   = (1 << 3), // buffer variables and buffer blocks are reflected separately
-    EShReflectionAllBlockVariables = (1 << 4), // reflect all variables in blocks, even if they are inactive
-    EShReflectionUnwrapIOBlocks    = (1 << 5), // unwrap input/output blocks the same as with uniform blocks
+    EShReflectionDefault            = 0,        // default is original behaviour before options were added
+    EShReflectionStrictArraySuffix  = (1 << 0), // reflection will follow stricter rules for array-of-structs suffixes
+    EShReflectionBasicArraySuffix   = (1 << 1), // arrays of basic types will be appended with [0] as in GL reflection
+    EShReflectionIntermediateIO     = (1 << 2), // reflect inputs and outputs to program, even with no vertex shader
+    EShReflectionSeparateBuffers    = (1 << 3), // buffer variables and buffer blocks are reflected separately
+    EShReflectionAllBlockVariables  = (1 << 4), // reflect all variables in blocks, even if they are inactive
+    EShReflectionUnwrapIOBlocks     = (1 << 5), // unwrap input/output blocks the same as with uniform blocks
+    EShReflectionAllIOVariables     = (1 << 6), // reflect all input/output variables, even if they are inactive
+    EShReflectionSharedStd140SSBO   = (1 << 7), // Apply std140/shared rules for ubo to ssbo
+    EShReflectionSharedStd140UBO    = (1 << 8), // Apply std140/shared rules for ubo to ssbo
+    LAST_ELEMENT_MARKER(EShReflectionCount),
 } EShReflectionOptions;
 
 //
@@ -280,10 +310,10 @@ typedef void* ShHandle;
 // Driver calls these to create and destroy compiler/linker
 // objects.
 //
-SH_IMPORT_EXPORT ShHandle ShConstructCompiler(const EShLanguage, int debugOptions);  // one per shader
-SH_IMPORT_EXPORT ShHandle ShConstructLinker(const EShExecutable, int debugOptions);  // one per shader pair
-SH_IMPORT_EXPORT ShHandle ShConstructUniformMap();                 // one per uniform namespace (currently entire program object)
-SH_IMPORT_EXPORT void ShDestruct(ShHandle);
+GLSLANG_EXPORT ShHandle ShConstructCompiler(const EShLanguage, int debugOptions);  // one per shader
+GLSLANG_EXPORT ShHandle ShConstructLinker(const EShExecutable, int debugOptions);  // one per shader pair
+GLSLANG_EXPORT ShHandle ShConstructUniformMap();                 // one per uniform namespace (currently entire program object)
+GLSLANG_EXPORT void ShDestruct(ShHandle);
 
 //
 // The return value of ShCompile is boolean, non-zero indicating
@@ -292,7 +322,7 @@ SH_IMPORT_EXPORT void ShDestruct(ShHandle);
 // The info-log should be written by ShCompile into
 // ShHandle, so it can answer future queries.
 //
-SH_IMPORT_EXPORT int ShCompile(
+GLSLANG_EXPORT int ShCompile(
     const ShHandle,
     const char* const shaderStrings[],
     const int numStrings,
@@ -305,7 +335,7 @@ SH_IMPORT_EXPORT int ShCompile(
     EShMessages messages = EShMsgDefault // warnings and errors
     );
 
-SH_IMPORT_EXPORT int ShLinkExt(
+GLSLANG_EXPORT int ShLinkExt(
     const ShHandle,               // linker object
     const ShHandle h[],           // compiler objects to link together
     const int numHandles);
@@ -314,26 +344,26 @@ SH_IMPORT_EXPORT int ShLinkExt(
 // ShSetEncrpytionMethod is a place-holder for specifying
 // how source code is encrypted.
 //
-SH_IMPORT_EXPORT void ShSetEncryptionMethod(ShHandle);
+GLSLANG_EXPORT void ShSetEncryptionMethod(ShHandle);
 
 //
 // All the following return 0 if the information is not
 // available in the object passed down, or the object is bad.
 //
-SH_IMPORT_EXPORT const char* ShGetInfoLog(const ShHandle);
-SH_IMPORT_EXPORT const void* ShGetExecutable(const ShHandle);
-SH_IMPORT_EXPORT int ShSetVirtualAttributeBindings(const ShHandle, const ShBindingTable*);   // to detect user aliasing
-SH_IMPORT_EXPORT int ShSetFixedAttributeBindings(const ShHandle, const ShBindingTable*);     // to force any physical mappings
+GLSLANG_EXPORT const char* ShGetInfoLog(const ShHandle);
+GLSLANG_EXPORT const void* ShGetExecutable(const ShHandle);
+GLSLANG_EXPORT int ShSetVirtualAttributeBindings(const ShHandle, const ShBindingTable*);   // to detect user aliasing
+GLSLANG_EXPORT int ShSetFixedAttributeBindings(const ShHandle, const ShBindingTable*);     // to force any physical mappings
 //
 // Tell the linker to never assign a vertex attribute to this list of physical attributes
 //
-SH_IMPORT_EXPORT int ShExcludeAttributes(const ShHandle, int *attributes, int count);
+GLSLANG_EXPORT int ShExcludeAttributes(const ShHandle, int *attributes, int count);
 
 //
 // Returns the location ID of the named uniform.
 // Returns -1 if error.
 //
-SH_IMPORT_EXPORT int ShGetUniformLocation(const ShHandle uniformMap, const char* name);
+GLSLANG_EXPORT int ShGetUniformLocation(const ShHandle uniformMap, const char* name);
 
 #ifdef __cplusplus
     }  // end extern "C"
@@ -364,19 +394,27 @@ class TInfoSink;
 
 namespace glslang {
 
-const char* GetEsslVersionString();
-const char* GetGlslVersionString();
-int GetKhronosToolId();
+struct Version {
+    int major;
+    int minor;
+    int patch;
+    const char* flavor;
+};
+
+GLSLANG_EXPORT Version GetVersion();
+GLSLANG_EXPORT const char* GetEsslVersionString();
+GLSLANG_EXPORT const char* GetGlslVersionString();
+GLSLANG_EXPORT int GetKhronosToolId();
 
 class TIntermediate;
 class TProgram;
 class TPoolAllocator;
 
 // Call this exactly once per process before using anything else
-bool InitializeProcess();
+GLSLANG_EXPORT bool InitializeProcess();
 
 // Call once per process to tear down everything
-void FinalizeProcess();
+GLSLANG_EXPORT void FinalizeProcess();
 
 // Resource type for IO resolver
 enum TResourceType {
@@ -389,11 +427,14 @@ enum TResourceType {
     EResCount
 };
 
+
 // Make one TShader per shader that you will link into a program. Then
 //  - provide the shader through setStrings() or setStringsWithLengths()
 //  - optionally call setEnv*(), see below for more detail
 //  - optionally use setPreamble() to set a special shader string that will be
 //    processed before all others but won't affect the validity of #version
+//  - optionally call addProcesses() for each setting/transform,
+//    see comment for class TProcesses
 //  - call parse(): source language and target environment must be selected
 //    either by correct setting of EShMessages sent to parse(), or by
 //    explicitly calling setEnv*()
@@ -406,40 +447,41 @@ enum TResourceType {
 //
 class TShader {
 public:
-    explicit TShader(EShLanguage);
-    virtual ~TShader();
-    void setStrings(const char* const* s, int n);
-    void setStringsWithLengths(const char* const* s, const int* l, int n);
-    void setStringsWithLengthsAndNames(
+    GLSLANG_EXPORT explicit TShader(EShLanguage);
+    GLSLANG_EXPORT virtual ~TShader();
+    GLSLANG_EXPORT void setStrings(const char* const* s, int n);
+    GLSLANG_EXPORT void setStringsWithLengths(
+        const char* const* s, const int* l, int n);
+    GLSLANG_EXPORT void setStringsWithLengthsAndNames(
         const char* const* s, const int* l, const char* const* names, int n);
     void setPreamble(const char* s) { preamble = s; }
-    void setEntryPoint(const char* entryPoint);
-    void setSourceEntryPoint(const char* sourceEntryPointName);
-    void addProcesses(const std::vector<std::string>&);
+    GLSLANG_EXPORT void setEntryPoint(const char* entryPoint);
+    GLSLANG_EXPORT void setSourceEntryPoint(const char* sourceEntryPointName);
+    GLSLANG_EXPORT void addProcesses(const std::vector<std::string>&);
 
     // IO resolver binding data: see comments in ShaderLang.cpp
-    void setShiftBinding(TResourceType res, unsigned int base);
-    void setShiftSamplerBinding(unsigned int base);  // DEPRECATED: use setShiftBinding
-    void setShiftTextureBinding(unsigned int base);  // DEPRECATED: use setShiftBinding
-    void setShiftImageBinding(unsigned int base);    // DEPRECATED: use setShiftBinding
-    void setShiftUboBinding(unsigned int base);      // DEPRECATED: use setShiftBinding
-    void setShiftUavBinding(unsigned int base);      // DEPRECATED: use setShiftBinding
-    void setShiftCbufferBinding(unsigned int base);  // synonym for setShiftUboBinding
-    void setShiftSsboBinding(unsigned int base);     // DEPRECATED: use setShiftBinding
-    void setShiftBindingForSet(TResourceType res, unsigned int base, unsigned int set);
-    void setResourceSetBinding(const std::vector<std::string>& base);
-    void setAutoMapBindings(bool map);
-    void setAutoMapLocations(bool map);
-    void addUniformLocationOverride(const char* name, int loc);
-    void setUniformLocationBase(int base);
-    void setInvertY(bool invert);
+    GLSLANG_EXPORT void setShiftBinding(TResourceType res, unsigned int base);
+    GLSLANG_EXPORT void setShiftSamplerBinding(unsigned int base);  // DEPRECATED: use setShiftBinding
+    GLSLANG_EXPORT void setShiftTextureBinding(unsigned int base);  // DEPRECATED: use setShiftBinding
+    GLSLANG_EXPORT void setShiftImageBinding(unsigned int base);    // DEPRECATED: use setShiftBinding
+    GLSLANG_EXPORT void setShiftUboBinding(unsigned int base);      // DEPRECATED: use setShiftBinding
+    GLSLANG_EXPORT void setShiftUavBinding(unsigned int base);      // DEPRECATED: use setShiftBinding
+    GLSLANG_EXPORT void setShiftCbufferBinding(unsigned int base);  // synonym for setShiftUboBinding
+    GLSLANG_EXPORT void setShiftSsboBinding(unsigned int base);     // DEPRECATED: use setShiftBinding
+    GLSLANG_EXPORT void setShiftBindingForSet(TResourceType res, unsigned int base, unsigned int set);
+    GLSLANG_EXPORT void setResourceSetBinding(const std::vector<std::string>& base);
+    GLSLANG_EXPORT void setAutoMapBindings(bool map);
+    GLSLANG_EXPORT void setAutoMapLocations(bool map);
+    GLSLANG_EXPORT void addUniformLocationOverride(const char* name, int loc);
+    GLSLANG_EXPORT void setUniformLocationBase(int base);
+    GLSLANG_EXPORT void setInvertY(bool invert);
 #ifdef ENABLE_HLSL
-    void setHlslIoMapping(bool hlslIoMap);
-    void setFlattenUniformArrays(bool flatten);
+    GLSLANG_EXPORT void setHlslIoMapping(bool hlslIoMap);
+    GLSLANG_EXPORT void setFlattenUniformArrays(bool flatten);
 #endif
-    void setNoStorageFormat(bool useUnknownFormat);
-    void setNanMinMaxClamp(bool nanMinMaxClamp);
-    void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode);
+    GLSLANG_EXPORT void setNoStorageFormat(bool useUnknownFormat);
+    GLSLANG_EXPORT void setNanMinMaxClamp(bool nanMinMaxClamp);
+    GLSLANG_EXPORT void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode);
 
     // 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
@@ -579,8 +621,10 @@ public:
         virtual void releaseInclude(IncludeResult*) override { }
     };
 
-    bool parse(const TBuiltInResource*, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile,
-               bool forwardCompatible, EShMessages, Includer&);
+    GLSLANG_EXPORT bool parse(
+        const TBuiltInResource*, int defaultVersion, EProfile defaultProfile,
+        bool forceDefaultVersionAndProfile, bool forwardCompatible,
+        EShMessages, Includer&);
 
     bool parse(const TBuiltInResource* res, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile,
                bool forwardCompatible, EShMessages messages)
@@ -603,13 +647,14 @@ public:
 
     // NOTE: Doing just preprocessing to obtain a correct preprocessed shader string
     // is not an officially supported or fully working path.
-    bool preprocess(const TBuiltInResource* builtInResources,
-                    int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile,
-                    bool forwardCompatible, EShMessages message, std::string* outputString,
-                    Includer& includer);
-
-    const char* getInfoLog();
-    const char* getInfoDebugLog();
+    GLSLANG_EXPORT bool preprocess(
+        const TBuiltInResource* builtInResources, int defaultVersion,
+        EProfile defaultProfile, bool forceDefaultVersionAndProfile,
+        bool forwardCompatible, EShMessages message, std::string* outputString,
+        Includer& includer);
+
+    GLSLANG_EXPORT const char* getInfoLog();
+    GLSLANG_EXPORT const char* getInfoDebugLog();
     EShLanguage getStage() const { return stage; }
     TIntermediate* getIntermediate() const { return intermediate; }
 
@@ -628,11 +673,11 @@ protected:
     // stringNames is the optional names for all the strings. If stringNames
     // is null, then none of the strings has name. If a certain element in
     // stringNames is null, then the corresponding string does not have name.
-    const char* const* strings;
+    const char* const* strings;      // explicit code to compile, see previous comment
     const int* lengths;
     const char* const* stringNames;
-    const char* preamble;
-    int numStrings;
+    int numStrings;                  // size of the above arrays
+    const char* preamble;            // string of implicit code to compile before the explicitly provided code
 
     // a function in the source string can be renamed FROM this TO the name given in setEntryPoint.
     std::string sourceEntryPointName;
@@ -645,7 +690,7 @@ private:
     TShader& operator=(TShader&);
 };
 
-#ifndef GLSLANG_WEB
+#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
 
 //
 // A reflection database and its interface, consistent with the OpenGL API reflection queries.
@@ -654,11 +699,11 @@ private:
 // Data needed for just a single object at the granularity exchanged by the reflection API
 class TObjectReflection {
 public:
-    TObjectReflection(const std::string& pName, const TType& pType, int pOffset, int pGLDefineType, int pSize, int pIndex);
+    GLSLANG_EXPORT TObjectReflection(const std::string& pName, const TType& pType, int pOffset, int pGLDefineType, int pSize, int pIndex);
 
-    const TType* getType() const { return type; }
-    int getBinding() const;
-    void dump() const;
+    GLSLANG_EXPORT const TType* getType() const { return type; }
+    GLSLANG_EXPORT int getBinding() const;
+    GLSLANG_EXPORT void dump() const;
     static TObjectReflection badReflection() { return TObjectReflection(); }
 
     std::string name;
@@ -669,6 +714,7 @@ public:
     int counterIndex;
     int numMembers;
     int arrayStride;            // stride of an array variable
+    int topLevelArraySize;      // size of the top-level variable in a storage buffer member
     int topLevelArrayStride;    // stride of the top-level variable in a storage buffer member
     EShLanguageMask stages;
 
@@ -762,7 +808,7 @@ public:
     virtual void addStage(EShLanguage stage) = 0;
 };
 
-#endif // GLSLANG_WEB
+#endif // !GLSLANG_WEB && !GLSLANG_ANGLE
 
 // Make one TProgram per set of shaders that will get linked together.  Add all
 // the shaders that are to be linked together.  After calling shader.parse()
@@ -772,40 +818,40 @@ public:
 //
 class TProgram {
 public:
-    TProgram();
-    virtual ~TProgram();
+    GLSLANG_EXPORT TProgram();
+    GLSLANG_EXPORT virtual ~TProgram();
     void addShader(TShader* shader) { stages[shader->stage].push_back(shader); }
     std::list<TShader*>& getShaders(EShLanguage stage) { return stages[stage]; }
     // Link Validation interface
-    bool link(EShMessages);
-    const char* getInfoLog();
-    const char* getInfoDebugLog();
+    GLSLANG_EXPORT bool link(EShMessages);
+    GLSLANG_EXPORT const char* getInfoLog();
+    GLSLANG_EXPORT const char* getInfoDebugLog();
 
     TIntermediate* getIntermediate(EShLanguage stage) const { return intermediate[stage]; }
 
-#ifndef GLSLANG_WEB
+#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
 
     // Reflection Interface
 
     // call first, to do liveness analysis, index mapping, etc.; returns false on failure
-    bool buildReflection(int opts = EShReflectionDefault);
-    unsigned getLocalSize(int dim) const;                  // return dim'th local size
-    int getReflectionIndex(const char *name) const;
-    int getReflectionPipeIOIndex(const char* name, const bool inOrOut) const;
-    int getNumUniformVariables() const;
-    const TObjectReflection& getUniform(int index) const;
-    int getNumUniformBlocks() const;
-    const TObjectReflection& getUniformBlock(int index) const;
-    int getNumPipeInputs() const;
-    const TObjectReflection& getPipeInput(int index) const;
-    int getNumPipeOutputs() const;
-    const TObjectReflection& getPipeOutput(int index) const;
-    int getNumBufferVariables() const;
-    const TObjectReflection& getBufferVariable(int index) const;
-    int getNumBufferBlocks() const;
-    const TObjectReflection& getBufferBlock(int index) const;
-    int getNumAtomicCounters() const;
-    const TObjectReflection& getAtomicCounter(int index) const;
+    GLSLANG_EXPORT bool buildReflection(int opts = EShReflectionDefault);
+    GLSLANG_EXPORT unsigned getLocalSize(int dim) const;                  // return dim'th local size
+    GLSLANG_EXPORT int getReflectionIndex(const char *name) const;
+    GLSLANG_EXPORT int getReflectionPipeIOIndex(const char* name, const bool inOrOut) const;
+    GLSLANG_EXPORT int getNumUniformVariables() const;
+    GLSLANG_EXPORT const TObjectReflection& getUniform(int index) const;
+    GLSLANG_EXPORT int getNumUniformBlocks() const;
+    GLSLANG_EXPORT const TObjectReflection& getUniformBlock(int index) const;
+    GLSLANG_EXPORT int getNumPipeInputs() const;
+    GLSLANG_EXPORT const TObjectReflection& getPipeInput(int index) const;
+    GLSLANG_EXPORT int getNumPipeOutputs() const;
+    GLSLANG_EXPORT const TObjectReflection& getPipeOutput(int index) const;
+    GLSLANG_EXPORT int getNumBufferVariables() const;
+    GLSLANG_EXPORT const TObjectReflection& getBufferVariable(int index) const;
+    GLSLANG_EXPORT int getNumBufferBlocks() const;
+    GLSLANG_EXPORT const TObjectReflection& getBufferBlock(int index) const;
+    GLSLANG_EXPORT int getNumAtomicCounters() const;
+    GLSLANG_EXPORT const TObjectReflection& getAtomicCounter(int index) const;
 
     // Legacy Reflection Interface - expressed in terms of above interface
 
@@ -872,22 +918,22 @@ public:
     // returns a TType*
     const TType *getAttributeTType(int index) const    { return getPipeInput(index).getType(); }
 
-    void dumpReflection();
+    GLSLANG_EXPORT void dumpReflection();
     // I/O mapping: apply base offsets and map live unbound variables
     // If resolver is not provided it uses the previous approach
     // and respects auto assignment and offsets.
-    bool mapIO(TIoMapResolver* pResolver = nullptr, TIoMapper* pIoMapper = nullptr);
-#endif
+    GLSLANG_EXPORT bool mapIO(TIoMapResolver* pResolver = nullptr, TIoMapper* pIoMapper = nullptr);
+#endif // !GLSLANG_WEB && !GLSLANG_ANGLE
 
 protected:
-    bool linkStage(EShLanguage, EShMessages);
+    GLSLANG_EXPORT bool linkStage(EShLanguage, EShMessages);
 
     TPoolAllocator* pool;
     std::list<TShader*> stages[EShLangCount];
     TIntermediate* intermediate[EShLangCount];
     bool newedIntermediate[EShLangCount];      // track which intermediate were "new" versus reusing a singleton unit in a stage
     TInfoSink* infoSink;
-#ifndef GLSLANG_WEB
+#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
     TReflection* reflection;
 #endif
     bool linked;

+ 31 - 4
src/libraries/glslang/glslang/MachineIndependent/pch.cpp → src/libraries/glslang/glslang/build_info.h

@@ -1,5 +1,5 @@
+// Copyright (C) 2020 The Khronos Group Inc.
 //
-// Copyright (C) 2018 The Khronos Group Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -14,7 +14,7 @@
 //    disclaimer in the documentation and/or other materials provided
 //    with the distribution.
 //
-//    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+//    Neither the name of The Khronos Group Inc. nor the names of its
 //    contributors may be used to endorse or promote products derived
 //    from this software without specific prior written permission.
 //
@@ -30,6 +30,33 @@
 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 // POSSIBILITY OF SUCH DAMAGE.
-//
 
-#include "pch.h"
+#ifndef GLSLANG_BUILD_INFO
+#define GLSLANG_BUILD_INFO
+
+#define GLSLANG_VERSION_MAJOR 11
+#define GLSLANG_VERSION_MINOR 0
+#define GLSLANG_VERSION_PATCH 0
+#define GLSLANG_VERSION_FLAVOR ""
+
+#define GLSLANG_VERSION_GREATER_THAN(major, minor, patch) \
+    (((major) > GLSLANG_VERSION_MAJOR) || ((major) == GLSLANG_VERSION_MAJOR && \
+    (((minor) > GLSLANG_VERSION_MINOR) || ((minor) == GLSLANG_VERSION_MINOR && \
+     ((patch) > GLSLANG_VERSION_PATCH)))))
+
+#define GLSLANG_VERSION_GREATER_OR_EQUAL_TO(major, minor, patch) \
+    (((major) > GLSLANG_VERSION_MAJOR) || ((major) == GLSLANG_VERSION_MAJOR && \
+    (((minor) > GLSLANG_VERSION_MINOR) || ((minor) == GLSLANG_VERSION_MINOR && \
+     ((patch) >= GLSLANG_VERSION_PATCH)))))
+
+#define GLSLANG_VERSION_LESS_THAN(major, minor, patch) \
+    (((major) < GLSLANG_VERSION_MAJOR) || ((major) == GLSLANG_VERSION_MAJOR && \
+    (((minor) < GLSLANG_VERSION_MINOR) || ((minor) == GLSLANG_VERSION_MINOR && \
+     ((patch) < GLSLANG_VERSION_PATCH)))))
+
+#define GLSLANG_VERSION_LESS_OR_EQUAL_TO(major, minor, patch) \
+    (((major) < GLSLANG_VERSION_MAJOR) || ((major) == GLSLANG_VERSION_MAJOR && \
+    (((minor) < GLSLANG_VERSION_MINOR) || ((minor) == GLSLANG_VERSION_MINOR && \
+     ((patch) <= GLSLANG_VERSION_PATCH)))))
+
+#endif // GLSLANG_BUILD_INFO

+ 1 - 0
src/modules/graphics/ShaderStage.cpp

@@ -118,6 +118,7 @@ static const TBuiltInResource defaultTBuiltInResource = {
 	/* .maxTaskWorkGroupSizeY_NV = */ 1,
 	/* .maxTaskWorkGroupSizeZ_NV = */ 1,
 	/* .maxMeshViewCountNV = */ 4,
+	/* .maxDualSourceDrawBuffersEXT = */ 1,
 	/* .limits = */ {
 		/* .nonInductiveForLoops = */ 1,
 		/* .whileLoops = */ 1,

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