Browse Source

update glslang

Alex Szpakowski 6 years ago
parent
commit
a91a0a9431
48 changed files with 8317 additions and 2365 deletions
  1. 4 0
      CMakeLists.txt
  2. 20 0
      platform/xcode/liblove.xcodeproj/project.pbxproj
  3. 163 7
      src/libraries/glslang/glslang/Include/BaseTypes.h
  4. 45 29
      src/libraries/glslang/glslang/Include/Common.h
  5. 337 24
      src/libraries/glslang/glslang/Include/ConstantUnion.h
  6. 1 2
      src/libraries/glslang/glslang/Include/PoolAlloc.h
  7. 9 0
      src/libraries/glslang/glslang/Include/ResourceLimits.h
  8. 268 99
      src/libraries/glslang/glslang/Include/Types.h
  9. 21 11
      src/libraries/glslang/glslang/Include/arrays.h
  10. 374 135
      src/libraries/glslang/glslang/Include/intermediate.h
  11. 1 4
      src/libraries/glslang/glslang/Include/revision.h
  12. 435 89
      src/libraries/glslang/glslang/MachineIndependent/Constant.cpp
  13. 1334 8
      src/libraries/glslang/glslang/MachineIndependent/Initialize.cpp
  14. 0 2
      src/libraries/glslang/glslang/MachineIndependent/Initialize.h
  15. 492 336
      src/libraries/glslang/glslang/MachineIndependent/Intermediate.cpp
  16. 14 2
      src/libraries/glslang/glslang/MachineIndependent/ParseContextBase.cpp
  17. 558 99
      src/libraries/glslang/glslang/MachineIndependent/ParseHelper.cpp
  18. 33 14
      src/libraries/glslang/glslang/MachineIndependent/ParseHelper.h
  19. 365 34
      src/libraries/glslang/glslang/MachineIndependent/Scan.cpp
  20. 7 5
      src/libraries/glslang/glslang/MachineIndependent/Scan.h
  21. 5 1
      src/libraries/glslang/glslang/MachineIndependent/ScanContext.h
  22. 144 60
      src/libraries/glslang/glslang/MachineIndependent/ShaderLang.cpp
  23. 12 6
      src/libraries/glslang/glslang/MachineIndependent/SymbolTable.cpp
  24. 1 0
      src/libraries/glslang/glslang/MachineIndependent/SymbolTable.h
  25. 325 20
      src/libraries/glslang/glslang/MachineIndependent/Versions.cpp
  26. 46 4
      src/libraries/glslang/glslang/MachineIndependent/Versions.h
  27. 257 0
      src/libraries/glslang/glslang/MachineIndependent/attribute.cpp
  28. 102 0
      src/libraries/glslang/glslang/MachineIndependent/attribute.h
  29. 34 0
      src/libraries/glslang/glslang/MachineIndependent/gl_types.h
  30. 589 408
      src/libraries/glslang/glslang/MachineIndependent/glslang_tab.cpp
  31. 408 297
      src/libraries/glslang/glslang/MachineIndependent/glslang_tab.cpp.h
  32. 483 138
      src/libraries/glslang/glslang/MachineIndependent/intermOut.cpp
  33. 79 39
      src/libraries/glslang/glslang/MachineIndependent/iomapper.cpp
  34. 454 90
      src/libraries/glslang/glslang/MachineIndependent/linkValidate.cpp
  35. 133 29
      src/libraries/glslang/glslang/MachineIndependent/localintermediate.h
  36. 21 3
      src/libraries/glslang/glslang/MachineIndependent/parseVersions.h
  37. 35 0
      src/libraries/glslang/glslang/MachineIndependent/pch.cpp
  38. 49 0
      src/libraries/glslang/glslang/MachineIndependent/pch.h
  39. 82 53
      src/libraries/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp
  40. 4 0
      src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpContext.cpp
  41. 31 17
      src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpContext.h
  42. 293 152
      src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp
  43. 94 119
      src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpTokens.cpp
  44. 0 2
      src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpTokens.h
  45. 70 11
      src/libraries/glslang/glslang/MachineIndependent/reflection.cpp
  46. 7 5
      src/libraries/glslang/glslang/MachineIndependent/reflection.h
  47. 69 11
      src/libraries/glslang/glslang/Public/ShaderLang.h
  48. 9 0
      src/modules/graphics/ShaderStage.cpp

+ 4 - 0
CMakeLists.txt

@@ -1339,6 +1339,8 @@ set(LOVE_SRC_3P_GLSLANG_GLSLANG_MACHINEINDEPENDENT_PREPROCESSOR
 
 
 set(LOVE_SRC_3P_GLSLANG_GLSLANG_MACHINEINDEPENDENT
 set(LOVE_SRC_3P_GLSLANG_GLSLANG_MACHINEINDEPENDENT
 	${LOVE_SRC_3P_GLSLANG_GLSLANG_MACHINEINDEPENDENT_PREPROCESSOR}
 	${LOVE_SRC_3P_GLSLANG_GLSLANG_MACHINEINDEPENDENT_PREPROCESSOR}
+	src/libraries/glslang/glslang/MachineIndependent/attribute.cpp
+	src/libraries/glslang/glslang/MachineIndependent/attribute.h
 	src/libraries/glslang/glslang/MachineIndependent/Constant.cpp
 	src/libraries/glslang/glslang/MachineIndependent/Constant.cpp
 	src/libraries/glslang/glslang/MachineIndependent/gl_types.h
 	src/libraries/glslang/glslang/MachineIndependent/gl_types.h
 	src/libraries/glslang/glslang/MachineIndependent/glslang_tab.cpp
 	src/libraries/glslang/glslang/MachineIndependent/glslang_tab.cpp
@@ -1360,6 +1362,8 @@ set(LOVE_SRC_3P_GLSLANG_GLSLANG_MACHINEINDEPENDENT
 	src/libraries/glslang/glslang/MachineIndependent/ParseHelper.cpp
 	src/libraries/glslang/glslang/MachineIndependent/ParseHelper.cpp
 	src/libraries/glslang/glslang/MachineIndependent/ParseHelper.h
 	src/libraries/glslang/glslang/MachineIndependent/ParseHelper.h
 	src/libraries/glslang/glslang/MachineIndependent/parseVersions.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/PoolAlloc.cpp
 	src/libraries/glslang/glslang/MachineIndependent/propagateNoContraction.cpp
 	src/libraries/glslang/glslang/MachineIndependent/propagateNoContraction.cpp
 	src/libraries/glslang/glslang/MachineIndependent/propagateNoContraction.h
 	src/libraries/glslang/glslang/MachineIndependent/propagateNoContraction.h

+ 20 - 0
platform/xcode/liblove.xcodeproj/project.pbxproj

@@ -813,6 +813,12 @@
 		FA1E88831DF363DB00E808AA /* Filter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA1E88811DF363DB00E808AA /* Filter.cpp */; };
 		FA1E88831DF363DB00E808AA /* Filter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA1E88811DF363DB00E808AA /* Filter.cpp */; };
 		FA1E88841DF363DB00E808AA /* Filter.h in Headers */ = {isa = PBXBuildFile; fileRef = FA1E88821DF363DB00E808AA /* Filter.h */; };
 		FA1E88841DF363DB00E808AA /* Filter.h in Headers */ = {isa = PBXBuildFile; fileRef = FA1E88821DF363DB00E808AA /* Filter.h */; };
 		FA1E88851DF363E100E808AA /* Filter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA1E88811DF363DB00E808AA /* Filter.cpp */; };
 		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 */; };
+		FA24348921D401CB00B8918A /* pch.h in Headers */ = {isa = PBXBuildFile; fileRef = FA24348321D401CB00B8918A /* pch.h */; };
 		FA27B39D1B498151008A9DCE /* Video.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA27B38A1B498151008A9DCE /* Video.cpp */; };
 		FA27B39D1B498151008A9DCE /* Video.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA27B38A1B498151008A9DCE /* Video.cpp */; };
 		FA27B39E1B498151008A9DCE /* Video.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA27B38A1B498151008A9DCE /* Video.cpp */; };
 		FA27B39E1B498151008A9DCE /* Video.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA27B38A1B498151008A9DCE /* Video.cpp */; };
 		FA27B39F1B498151008A9DCE /* Video.h in Headers */ = {isa = PBXBuildFile; fileRef = FA27B38B1B498151008A9DCE /* Video.h */; };
 		FA27B39F1B498151008A9DCE /* Video.h in Headers */ = {isa = PBXBuildFile; fileRef = FA27B38B1B498151008A9DCE /* Video.h */; };
@@ -1785,6 +1791,10 @@
 		FA1E887D1DF363CD00E808AA /* Filter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Filter.h; sourceTree = "<group>"; };
 		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>"; };
 		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>"; };
 		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>"; };
 		FA27B38A1B498151008A9DCE /* Video.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Video.cpp; sourceTree = "<group>"; };
 		FA27B38A1B498151008A9DCE /* Video.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Video.cpp; sourceTree = "<group>"; };
 		FA27B38B1B498151008A9DCE /* Video.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Video.h; sourceTree = "<group>"; };
 		FA27B38B1B498151008A9DCE /* Video.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Video.h; sourceTree = "<group>"; };
 		FA27B3931B498151008A9DCE /* Video.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Video.h; sourceTree = "<group>"; };
 		FA27B3931B498151008A9DCE /* Video.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Video.h; sourceTree = "<group>"; };
@@ -3583,6 +3593,8 @@
 		FAF13FD21E20934C00F898D2 /* MachineIndependent */ = {
 		FAF13FD21E20934C00F898D2 /* MachineIndependent */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
+				FA24348221D401CB00B8918A /* attribute.cpp */,
+				FA24348121D401CB00B8918A /* attribute.h */,
 				FAF13FD31E20934C00F898D2 /* Constant.cpp */,
 				FAF13FD31E20934C00F898D2 /* Constant.cpp */,
 				FAF13FD41E20934C00F898D2 /* gl_types.h */,
 				FAF13FD41E20934C00F898D2 /* gl_types.h */,
 				FAF13FD61E20934C00F898D2 /* glslang_tab.cpp */,
 				FAF13FD61E20934C00F898D2 /* glslang_tab.cpp */,
@@ -3604,6 +3616,8 @@
 				FAF13FE61E20934C00F898D2 /* ParseHelper.cpp */,
 				FAF13FE61E20934C00F898D2 /* ParseHelper.cpp */,
 				FAF13FE71E20934C00F898D2 /* ParseHelper.h */,
 				FAF13FE71E20934C00F898D2 /* ParseHelper.h */,
 				FAF13FE81E20934C00F898D2 /* parseVersions.h */,
 				FAF13FE81E20934C00F898D2 /* parseVersions.h */,
+				FA24348021D401CB00B8918A /* pch.cpp */,
+				FA24348321D401CB00B8918A /* pch.h */,
 				FAF13FE91E20934C00F898D2 /* PoolAlloc.cpp */,
 				FAF13FE91E20934C00F898D2 /* PoolAlloc.cpp */,
 				FAF13FEA1E20934C00F898D2 /* preprocessor */,
 				FAF13FEA1E20934C00F898D2 /* preprocessor */,
 				FAF13FF41E20934C00F898D2 /* propagateNoContraction.cpp */,
 				FAF13FF41E20934C00F898D2 /* propagateNoContraction.cpp */,
@@ -3812,6 +3826,7 @@
 				FAF1405A1E20934C00F898D2 /* ConstantUnion.h in Headers */,
 				FAF1405A1E20934C00F898D2 /* ConstantUnion.h in Headers */,
 				FAF140A51E20934C00F898D2 /* Scan.h in Headers */,
 				FAF140A51E20934C00F898D2 /* Scan.h in Headers */,
 				FA0B7CE11A95902C000E1D17 /* Source.h in Headers */,
 				FA0B7CE11A95902C000E1D17 /* Source.h in Headers */,
+				FA24348621D401CB00B8918A /* attribute.h in Headers */,
 				FA1BA0AE1E16F9EE00AA2803 /* wrap_Canvas.h in Headers */,
 				FA1BA0AE1E16F9EE00AA2803 /* wrap_Canvas.h in Headers */,
 				FAF140901E20934C00F898D2 /* PpContext.h in Headers */,
 				FAF140901E20934C00F898D2 /* PpContext.h in Headers */,
 				FA0B7E621A95902C000E1D17 /* wrap_Physics.h in Headers */,
 				FA0B7E621A95902C000E1D17 /* wrap_Physics.h in Headers */,
@@ -3991,6 +4006,7 @@
 				FA0B7D111A95902C000E1D17 /* BMFontRasterizer.h in Headers */,
 				FA0B7D111A95902C000E1D17 /* BMFontRasterizer.h in Headers */,
 				217DFBE61D9F6D490055D849 /* http.lua.h in Headers */,
 				217DFBE61D9F6D490055D849 /* http.lua.h in Headers */,
 				FA0B7E3E1A95902C000E1D17 /* wrap_Body.h in Headers */,
 				FA0B7E3E1A95902C000E1D17 /* wrap_Body.h in Headers */,
+				FA24348921D401CB00B8918A /* pch.h in Headers */,
 				FAF140991E20934C00F898D2 /* PpTokens.h in Headers */,
 				FAF140991E20934C00F898D2 /* PpTokens.h in Headers */,
 				FA0B7A571A958EA3000E1D17 /* b2Settings.h in Headers */,
 				FA0B7A571A958EA3000E1D17 /* b2Settings.h in Headers */,
 				FAF1405B1E20934C00F898D2 /* InfoSink.h in Headers */,
 				FAF1405B1E20934C00F898D2 /* InfoSink.h in Headers */,
@@ -4227,6 +4243,7 @@
 				FA91DA8C1F377C3900C80E33 /* deprecation.cpp in Sources */,
 				FA91DA8C1F377C3900C80E33 /* deprecation.cpp in Sources */,
 				FA6A2B6B1F5F7F560074C308 /* DataView.cpp in Sources */,
 				FA6A2B6B1F5F7F560074C308 /* DataView.cpp in Sources */,
 				FA0B7E401A95902C000E1D17 /* wrap_ChainShape.cpp in Sources */,
 				FA0B7E401A95902C000E1D17 /* wrap_ChainShape.cpp in Sources */,
+				FA24348521D401CB00B8918A /* pch.cpp in Sources */,
 				FA0B7DEC1A95902C000E1D17 /* Cursor.cpp in Sources */,
 				FA0B7DEC1A95902C000E1D17 /* Cursor.cpp in Sources */,
 				FA0B7D871A95902C000E1D17 /* ImageData.cpp in Sources */,
 				FA0B7D871A95902C000E1D17 /* ImageData.cpp in Sources */,
 				FA0B7E101A95902C000E1D17 /* FrictionJoint.cpp in Sources */,
 				FA0B7E101A95902C000E1D17 /* FrictionJoint.cpp in Sources */,
@@ -4302,6 +4319,7 @@
 				FA0B7CDD1A95902C000E1D17 /* Source.cpp in Sources */,
 				FA0B7CDD1A95902C000E1D17 /* Source.cpp in Sources */,
 				FA0B7DC51A95902C000E1D17 /* wrap_JoystickModule.cpp in Sources */,
 				FA0B7DC51A95902C000E1D17 /* wrap_JoystickModule.cpp in Sources */,
 				FA0B7E701A95902C000E1D17 /* wrap_RopeJoint.cpp in Sources */,
 				FA0B7E701A95902C000E1D17 /* wrap_RopeJoint.cpp in Sources */,
+				FA24348821D401CB00B8918A /* attribute.cpp in Sources */,
 				FACA02FC1F5E39810084B28F /* wrap_CompressedData.cpp in Sources */,
 				FACA02FC1F5E39810084B28F /* wrap_CompressedData.cpp in Sources */,
 				FAF140AD1E20934C00F898D2 /* Versions.cpp in Sources */,
 				FAF140AD1E20934C00F898D2 /* Versions.cpp in Sources */,
 				FA0B7A7B1A958EA3000E1D17 /* b2Contact.cpp in Sources */,
 				FA0B7A7B1A958EA3000E1D17 /* b2Contact.cpp in Sources */,
@@ -4617,6 +4635,7 @@
 				FA0B7DB71A95902C000E1D17 /* Joystick.cpp in Sources */,
 				FA0B7DB71A95902C000E1D17 /* Joystick.cpp in Sources */,
 				FA0B7A321A958EA3000E1D17 /* b2Collision.cpp in Sources */,
 				FA0B7A321A958EA3000E1D17 /* b2Collision.cpp in Sources */,
 				FA91DA8B1F377C3900C80E33 /* deprecation.cpp in Sources */,
 				FA91DA8B1F377C3900C80E33 /* deprecation.cpp in Sources */,
+				FA24348421D401CB00B8918A /* pch.cpp in Sources */,
 				FA0B7E3F1A95902C000E1D17 /* wrap_ChainShape.cpp in Sources */,
 				FA0B7E3F1A95902C000E1D17 /* wrap_ChainShape.cpp in Sources */,
 				FA0B7DEB1A95902C000E1D17 /* Cursor.cpp in Sources */,
 				FA0B7DEB1A95902C000E1D17 /* Cursor.cpp in Sources */,
 				FA0B7D861A95902C000E1D17 /* ImageData.cpp in Sources */,
 				FA0B7D861A95902C000E1D17 /* ImageData.cpp in Sources */,
@@ -4692,6 +4711,7 @@
 				FA0B7CDC1A95902C000E1D17 /* Source.cpp in Sources */,
 				FA0B7CDC1A95902C000E1D17 /* Source.cpp in Sources */,
 				FA0B7DC41A95902C000E1D17 /* wrap_JoystickModule.cpp in Sources */,
 				FA0B7DC41A95902C000E1D17 /* wrap_JoystickModule.cpp in Sources */,
 				FA0B7E6F1A95902C000E1D17 /* wrap_RopeJoint.cpp in Sources */,
 				FA0B7E6F1A95902C000E1D17 /* wrap_RopeJoint.cpp in Sources */,
+				FA24348721D401CB00B8918A /* attribute.cpp in Sources */,
 				FA0B7AB51A958EA3000E1D17 /* ddsparse.cpp in Sources */,
 				FA0B7AB51A958EA3000E1D17 /* ddsparse.cpp in Sources */,
 				FACA02F41F5E396B0084B28F /* wrap_CompressedData.cpp in Sources */,
 				FACA02F41F5E396B0084B28F /* wrap_CompressedData.cpp in Sources */,
 				FAF140AC1E20934C00F898D2 /* Versions.cpp in Sources */,
 				FAF140AC1E20934C00F898D2 /* Versions.cpp in Sources */,

+ 163 - 7
src/libraries/glslang/glslang/Include/BaseTypes.h

@@ -1,6 +1,7 @@
 //
 //
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2012-2013 LunarG, Inc.
 // Copyright (C) 2012-2013 LunarG, Inc.
+// Copyright (C) 2017 ARM Limited.
 //
 //
 // All rights reserved.
 // All rights reserved.
 //
 //
@@ -46,23 +47,25 @@ enum TBasicType {
     EbtVoid,
     EbtVoid,
     EbtFloat,
     EbtFloat,
     EbtDouble,
     EbtDouble,
-#ifdef AMD_EXTENSIONS
     EbtFloat16,
     EbtFloat16,
-#endif
+    EbtInt8,
+    EbtUint8,
+    EbtInt16,
+    EbtUint16,
     EbtInt,
     EbtInt,
     EbtUint,
     EbtUint,
     EbtInt64,
     EbtInt64,
     EbtUint64,
     EbtUint64,
-#ifdef AMD_EXTENSIONS
-    EbtInt16,
-    EbtUint16,
-#endif
     EbtBool,
     EbtBool,
     EbtAtomicUint,
     EbtAtomicUint,
     EbtSampler,
     EbtSampler,
     EbtStruct,
     EbtStruct,
     EbtBlock,
     EbtBlock,
 
 
+#ifdef NV_EXTENSIONS
+    EbtAccStructNV,
+#endif
+
     // HLSL types that live only temporarily.
     // HLSL types that live only temporarily.
     EbtString,
     EbtString,
 
 
@@ -89,6 +92,14 @@ enum TStorageQualifier {
     EvqBuffer,        // read/write, shared with app
     EvqBuffer,        // read/write, shared with app
     EvqShared,        // compute shader's read/write 'shared' qualifier
     EvqShared,        // compute shader's read/write 'shared' qualifier
 
 
+#ifdef NV_EXTENSIONS
+    EvqPayloadNV,
+    EvqPayloadInNV,
+    EvqHitAttrNV,
+    EvqCallableDataNV,
+    EvqCallableDataInNV,
+#endif
+
     // parameters
     // parameters
     EvqIn,            // also, for 'in' in the grammar before we know if it's a pipeline input or an 'in' parameter
     EvqIn,            // also, for 'in' in the grammar before we know if it's a pipeline input or an 'in' parameter
     EvqOut,           // also, for 'out' in the grammar before we know if it's a pipeline output or an 'out' parameter
     EvqOut,           // also, for 'out' in the grammar before we know if it's a pipeline output or an 'out' parameter
@@ -141,6 +152,8 @@ enum TBuiltInVariable {
     EbvLocalInvocationId,
     EbvLocalInvocationId,
     EbvGlobalInvocationId,
     EbvGlobalInvocationId,
     EbvLocalInvocationIndex,
     EbvLocalInvocationIndex,
+    EbvNumSubgroups,
+    EbvSubgroupID,
     EbvSubGroupSize,
     EbvSubGroupSize,
     EbvSubGroupInvocation,
     EbvSubGroupInvocation,
     EbvSubGroupEqMask,
     EbvSubGroupEqMask,
@@ -148,6 +161,13 @@ enum TBuiltInVariable {
     EbvSubGroupGtMask,
     EbvSubGroupGtMask,
     EbvSubGroupLeMask,
     EbvSubGroupLeMask,
     EbvSubGroupLtMask,
     EbvSubGroupLtMask,
+    EbvSubgroupSize2,
+    EbvSubgroupInvocation2,
+    EbvSubgroupEqMask2,
+    EbvSubgroupGeMask2,
+    EbvSubgroupGtMask2,
+    EbvSubgroupLeMask2,
+    EbvSubgroupLtMask2,
     EbvVertexId,
     EbvVertexId,
     EbvInstanceId,
     EbvInstanceId,
     EbvVertexIndex,
     EbvVertexIndex,
@@ -212,6 +232,9 @@ enum TBuiltInVariable {
     EbvViewIndex,
     EbvViewIndex,
     EbvDeviceIndex,
     EbvDeviceIndex,
 
 
+    EbvFragSizeEXT,
+    EbvFragInvocationCountEXT,
+
 #ifdef NV_EXTENSIONS
 #ifdef NV_EXTENSIONS
     EbvViewportMaskNV,
     EbvViewportMaskNV,
     EbvSecondaryPositionNV,
     EbvSecondaryPositionNV,
@@ -219,6 +242,33 @@ enum TBuiltInVariable {
     EbvPositionPerViewNV,
     EbvPositionPerViewNV,
     EbvViewportMaskPerViewNV,
     EbvViewportMaskPerViewNV,
     EbvFragFullyCoveredNV,
     EbvFragFullyCoveredNV,
+    EbvFragmentSizeNV,
+    EbvInvocationsPerPixelNV,
+    // raytracing
+    EbvLaunchIdNV,
+    EbvLaunchSizeNV,
+    EbvInstanceCustomIndexNV,
+    EbvWorldRayOriginNV,
+    EbvWorldRayDirectionNV,
+    EbvObjectRayOriginNV,
+    EbvObjectRayDirectionNV,
+    EbvRayTminNV,
+    EbvRayTmaxNV,
+    EbvHitTNV,
+    EbvHitKindNV,
+    EbvObjectToWorldNV,
+    EbvWorldToObjectNV,
+    EbvIncomingRayFlagsNV,
+    EbvBaryCoordNV,
+    EbvBaryCoordNoPerspNV,
+    EbvTaskCountNV,
+    EbvPrimitiveCountNV,
+    EbvPrimitiveIndicesNV,
+    EbvClipDistancePerViewNV,
+    EbvCullDistancePerViewNV,
+    EbvLayerPerViewNV,
+    EbvMeshViewCountNV,
+    EbvMeshViewIndicesNV,
 #endif 
 #endif 
 
 
     // HLSL built-ins that live only temporarily, until they get remapped
     // HLSL built-ins that live only temporarily, until they get remapped
@@ -265,6 +315,13 @@ __inline const char* GetStorageQualifierString(TStorageQualifier q)
     case EvqPointCoord:     return "gl_PointCoord";  break;
     case EvqPointCoord:     return "gl_PointCoord";  break;
     case EvqFragColor:      return "fragColor";      break;
     case EvqFragColor:      return "fragColor";      break;
     case EvqFragDepth:      return "gl_FragDepth";   break;
     case EvqFragDepth:      return "gl_FragDepth";   break;
+#ifdef NV_EXTENSIONS
+    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;
+#endif
     default:                return "unknown qualifier";
     default:                return "unknown qualifier";
     }
     }
 }
 }
@@ -350,6 +407,9 @@ __inline const char* GetBuiltInVariableString(TBuiltInVariable v)
     case EbvViewIndex:                  return "ViewIndex";
     case EbvViewIndex:                  return "ViewIndex";
     case EbvDeviceIndex:                return "DeviceIndex";
     case EbvDeviceIndex:                return "DeviceIndex";
 
 
+    case EbvFragSizeEXT:                return "FragSizeEXT";
+    case EbvFragInvocationCountEXT:     return "FragInvocationCountEXT";
+
 #ifdef NV_EXTENSIONS
 #ifdef NV_EXTENSIONS
     case EbvViewportMaskNV:             return "ViewportMaskNV";
     case EbvViewportMaskNV:             return "ViewportMaskNV";
     case EbvSecondaryPositionNV:        return "SecondaryPositionNV";
     case EbvSecondaryPositionNV:        return "SecondaryPositionNV";
@@ -357,6 +417,33 @@ __inline const char* GetBuiltInVariableString(TBuiltInVariable v)
     case EbvPositionPerViewNV:          return "PositionPerViewNV";
     case EbvPositionPerViewNV:          return "PositionPerViewNV";
     case EbvViewportMaskPerViewNV:      return "ViewportMaskPerViewNV";
     case EbvViewportMaskPerViewNV:      return "ViewportMaskPerViewNV";
     case EbvFragFullyCoveredNV:         return "FragFullyCoveredNV";
     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 EbvBaryCoordNV:                return "BaryCoordNV";
+    case EbvBaryCoordNoPerspNV:         return "BaryCoordNoPerspNV";
+    case EbvTaskCountNV:                return "TaskCountNV";
+    case EbvPrimitiveCountNV:           return "PrimitiveCountNV";
+    case EbvPrimitiveIndicesNV:         return "PrimitiveIndicesNV";
+    case EbvClipDistancePerViewNV:      return "ClipDistancePerViewNV";
+    case EbvCullDistancePerViewNV:      return "CullDistancePerViewNV";
+    case EbvLayerPerViewNV:             return "LayerPerViewNV";
+    case EbvMeshViewCountNV:            return "MeshViewCountNV";
+    case EbvMeshViewIndicesNV:          return "MeshViewIndicesNV";
 #endif 
 #endif 
     default:                      return "unknown built-in variable";
     default:                      return "unknown built-in variable";
     }
     }
@@ -373,7 +460,7 @@ enum TPrecisionQualifier {
 
 
 __inline const char* GetPrecisionQualifierString(TPrecisionQualifier p)
 __inline const char* GetPrecisionQualifierString(TPrecisionQualifier p)
 {
 {
-    switch(p) {
+    switch (p) {
     case EpqNone:   return "";        break;
     case EpqNone:   return "";        break;
     case EpqLow:    return "lowp";    break;
     case EpqLow:    return "lowp";    break;
     case EpqMedium: return "mediump"; break;
     case EpqMedium: return "mediump"; break;
@@ -382,6 +469,75 @@ __inline const char* GetPrecisionQualifierString(TPrecisionQualifier p)
     }
     }
 }
 }
 
 
+__inline bool isTypeSignedInt(TBasicType type)
+{
+    switch (type) {
+    case EbtInt8:
+    case EbtInt16:
+    case EbtInt:
+    case EbtInt64:
+        return true;
+    default:
+        return false;
+    }
+}
+
+__inline bool isTypeUnsignedInt(TBasicType type)
+{
+    switch (type) {
+    case EbtUint8:
+    case EbtUint16:
+    case EbtUint:
+    case EbtUint64:
+        return true;
+    default:
+        return false;
+    }
+}
+
+__inline bool isTypeInt(TBasicType type)
+{
+    return isTypeSignedInt(type) || isTypeUnsignedInt(type);
+}
+
+__inline bool isTypeFloat(TBasicType type)
+{
+    switch (type) {
+    case EbtFloat:
+    case EbtDouble:
+    case EbtFloat16:
+        return true;
+    default:
+        return false;
+    }
+}
+
+__inline int getTypeRank(TBasicType type) {
+    int res = -1;
+    switch(type) {
+    case EbtInt8:
+    case EbtUint8:
+        res = 0;
+        break;
+    case EbtInt16:
+    case EbtUint16:
+        res = 1;
+        break;
+    case EbtInt:
+    case EbtUint:
+        res = 2;
+        break;
+    case EbtInt64:
+    case EbtUint64:
+        res = 3;
+        break;
+    default:
+        assert(false);
+        break;
+    }
+    return res;
+}
+
 } // end namespace glslang
 } // end namespace glslang
 
 
 #endif // _BASICTYPES_INCLUDED_
 #endif // _BASICTYPES_INCLUDED_

+ 45 - 29
src/libraries/glslang/glslang/Include/Common.h

@@ -37,9 +37,24 @@
 #ifndef _COMMON_INCLUDED_
 #ifndef _COMMON_INCLUDED_
 #define _COMMON_INCLUDED_
 #define _COMMON_INCLUDED_
 
 
+
+#if defined(__ANDROID__) || _MSC_VER < 1700
+#include <sstream>
+namespace std {
+template<typename T>
+std::string to_string(const T& val) {
+  std::ostringstream os;
+  os << val;
+  return os.str();
+}
+}
+#endif
+
 #if (defined(_MSC_VER) && _MSC_VER < 1900 /*vs2015*/) || defined MINGW_HAS_SECURE_API
 #if (defined(_MSC_VER) && _MSC_VER < 1900 /*vs2015*/) || defined MINGW_HAS_SECURE_API
     #include <basetsd.h>
     #include <basetsd.h>
+    #ifndef snprintf
     #define snprintf sprintf_s
     #define snprintf sprintf_s
+    #endif
     #define safe_vsprintf(buf,max,format,args) vsnprintf_s((buf), (max), (max), (format), (args))
     #define safe_vsprintf(buf,max,format,args) vsnprintf_s((buf), (max), (max), (format), (args))
 #elif defined (solaris)
 #elif defined (solaris)
     #define safe_vsprintf(buf,max,format,args) vsnprintf((buf), (max), (format), (args))
     #define safe_vsprintf(buf,max,format,args) vsnprintf((buf), (max), (format), (args))
@@ -51,31 +66,20 @@
     #define UINT_PTR uintptr_t
     #define UINT_PTR uintptr_t
 #endif
 #endif
 
 
-#if defined(__ANDROID__) || _MSC_VER < 1700
-#include <sstream>
-namespace std {
-template<typename T>
-std::string to_string(const T& val) {
-  std::ostringstream os;
-  os << val;
-  return os.str();
-}
-}
-#endif
-
 #if defined(_MSC_VER) && _MSC_VER < 1800
 #if defined(_MSC_VER) && _MSC_VER < 1800
-inline long long int strtoll (const char* str, char** endptr, int base)
-{
-  return _strtoi64(str, endptr, base);
-}
-inline unsigned long long int strtoull (const char* str, char** endptr, int base)
-{
-  return _strtoui64(str, endptr, base);
-}
-inline long long int atoll (const char* str)
-{
-  return strtoll(str, NULL, 10);
-}
+    #include <stdlib.h>
+    inline long long int strtoll (const char* str, char** endptr, int base)
+    {
+        return _strtoi64(str, endptr, base);
+    }
+    inline unsigned long long int strtoull (const char* str, char** endptr, int base)
+    {
+        return _strtoui64(str, endptr, base);
+    }
+    inline long long int atoll (const char* str)
+    {
+        return strtoll(str, NULL, 10);
+    }
 #endif
 #endif
 
 
 #if defined(_MSC_VER)
 #if defined(_MSC_VER)
@@ -155,7 +159,7 @@ inline TString* NewPoolTString(const char* s)
     return new(memory) TString(s);
     return new(memory) TString(s);
 }
 }
 
 
-template<class T> inline T* NewPoolObject(T)
+template<class T> inline T* NewPoolObject(T*)
 {
 {
     return new(GetThreadPoolAllocator().allocate(sizeof(T))) T;
     return new(GetThreadPoolAllocator().allocate(sizeof(T))) T;
 }
 }
@@ -225,16 +229,28 @@ inline const TString String(const int i, const int /*base*/ = 10)
 #endif
 #endif
 
 
 struct TSourceLoc {
 struct TSourceLoc {
-    void init() { name = nullptr; string = 0; line = 0; column = 0; }
+    void init()
+    {
+        name = nullptr; string = 0; line = 0; column = 0;
+    }
     void init(int stringNum) { init(); string = stringNum; }
     void init(int stringNum) { init(); string = stringNum; }
     // Returns the name if it exists. Otherwise, returns the string number.
     // Returns the name if it exists. Otherwise, returns the string number.
     std::string getStringNameOrNum(bool quoteStringName = true) const
     std::string getStringNameOrNum(bool quoteStringName = true) const
     {
     {
-        if (name != nullptr)
-            return quoteStringName ? ("\"" + std::string(name) + "\"") : name;
+        if (name != nullptr) {
+            TString qstr = quoteStringName ? ("\"" + *name + "\"") : *name;
+            std::string ret_str(qstr.c_str());
+            return ret_str;
+        }
         return std::to_string((long long)string);
         return std::to_string((long long)string);
     }
     }
-    const char* name; // descriptive name for this string
+    const char* getFilename() const
+    {
+        if (name == nullptr)
+            return nullptr;
+        return name->c_str();
+    }
+    TString* name; // descriptive name for this string
     int string;
     int string;
     int line;
     int line;
     int column;
     int column;

+ 337 - 24
src/libraries/glslang/glslang/Include/ConstantUnion.h

@@ -1,6 +1,7 @@
 //
 //
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2013 LunarG, Inc.
 // Copyright (C) 2013 LunarG, Inc.
+// Copyright (C) 2017 ARM Limited.
 //
 //
 // All rights reserved.
 // All rights reserved.
 //
 //
@@ -37,6 +38,9 @@
 #ifndef _CONSTANT_UNION_INCLUDED_
 #ifndef _CONSTANT_UNION_INCLUDED_
 #define _CONSTANT_UNION_INCLUDED_
 #define _CONSTANT_UNION_INCLUDED_
 
 
+#include "../Include/Common.h"
+#include "../Include/BaseTypes.h"
+
 namespace glslang {
 namespace glslang {
 
 
 class TConstUnion {
 class TConstUnion {
@@ -45,6 +49,30 @@ public:
 
 
     TConstUnion() : iConst(0), type(EbtInt) { }
     TConstUnion() : iConst(0), type(EbtInt) { }
 
 
+    void setI8Const(signed char i)
+    {
+       i8Const = i;
+       type = EbtInt8;
+    }
+
+    void setU8Const(unsigned char u)
+    {
+       u8Const = u;
+       type = EbtUint8;
+    }
+
+    void setI16Const(signed short i)
+    {
+       i16Const = i;
+       type = EbtInt16;
+    }
+
+    void setU16Const(unsigned short u)
+    {
+       u16Const = u;
+       type = EbtUint16;
+    }
+
     void setIConst(int i)
     void setIConst(int i)
     {
     {
         iConst = i;
         iConst = i;
@@ -87,6 +115,10 @@ public:
         type = EbtString;
         type = EbtString;
     }
     }
 
 
+    signed char        getI8Const() const  { return i8Const; }
+    unsigned char      getU8Const() const  { return u8Const; }
+    signed short       getI16Const() const { return i16Const; }
+    unsigned short     getU16Const() const { return u16Const; }
     int                getIConst() const   { return iConst; }
     int                getIConst() const   { return iConst; }
     unsigned int       getUConst() const   { return uConst; }
     unsigned int       getUConst() const   { return uConst; }
     long long          getI64Const() const { return i64Const; }
     long long          getI64Const() const { return i64Const; }
@@ -95,6 +127,38 @@ public:
     bool               getBConst() const   { return bConst; }
     bool               getBConst() const   { return bConst; }
     const TString*     getSConst() const   { return sConst; }
     const TString*     getSConst() const   { return sConst; }
 
 
+    bool operator==(const signed char i) const
+    {
+        if (i == i8Const)
+            return true;
+
+        return false;
+    }
+
+    bool operator==(const unsigned char u) const
+    {
+        if (u == u8Const)
+            return true;
+
+        return false;
+    }
+
+   bool operator==(const signed short i) const
+    {
+        if (i == i16Const)
+            return true;
+
+        return false;
+    }
+
+    bool operator==(const unsigned short u) const
+    {
+        if (u == u16Const)
+            return true;
+
+        return false;
+    }
+
     bool operator==(const int i) const
     bool operator==(const int i) const
     {
     {
         if (i == iConst)
         if (i == iConst)
@@ -149,6 +213,26 @@ public:
             return false;
             return false;
 
 
         switch (type) {
         switch (type) {
+        case EbtInt16:
+            if (constant.i16Const == i16Const)
+                return true;
+
+            break;
+         case EbtUint16:
+            if (constant.u16Const == u16Const)
+                return true;
+
+            break;
+        case EbtInt8:
+            if (constant.i8Const == i8Const)
+                return true;
+
+            break;
+         case EbtUint8:
+            if (constant.u8Const == u8Const)
+                return true;
+
+            break;
         case EbtInt:
         case EbtInt:
             if (constant.iConst == iConst)
             if (constant.iConst == iConst)
                 return true;
                 return true;
@@ -186,6 +270,26 @@ public:
         return false;
         return false;
     }
     }
 
 
+    bool operator!=(const signed char i) const
+    {
+        return !operator==(i);
+    }
+
+    bool operator!=(const unsigned char u) const
+    {
+        return !operator==(u);
+    }
+
+    bool operator!=(const signed short i) const
+    {
+        return !operator==(i);
+    }
+
+    bool operator!=(const unsigned short u) const
+    {
+        return !operator==(u);
+    }
+
     bool operator!=(const int i) const
     bool operator!=(const int i) const
     {
     {
         return !operator==(i);
         return !operator==(i);
@@ -225,6 +329,26 @@ public:
     {
     {
         assert(type == constant.type);
         assert(type == constant.type);
         switch (type) {
         switch (type) {
+        case EbtInt8:
+            if (i8Const > constant.i8Const)
+                return true;
+
+            return false;
+        case EbtUint8:
+            if (u8Const > constant.u8Const)
+                return true;
+
+            return false;
+        case EbtInt16:
+            if (i16Const > constant.i16Const)
+                return true;
+
+            return false;
+        case EbtUint16:
+            if (u16Const > constant.u16Const)
+                return true;
+
+            return false;
         case EbtInt:
         case EbtInt:
             if (iConst > constant.iConst)
             if (iConst > constant.iConst)
                 return true;
                 return true;
@@ -260,6 +384,26 @@ public:
     {
     {
         assert(type == constant.type);
         assert(type == constant.type);
         switch (type) {
         switch (type) {
+        case EbtInt8:
+            if (i8Const < constant.i8Const)
+                return true;
+
+            return false;
+        case EbtUint8:
+            if (u8Const < constant.u8Const)
+                return true;
+
+            return false;
+       case EbtInt16:
+            if (i16Const < constant.i16Const)
+                return true;
+
+            return false;
+        case EbtUint16:
+            if (u16Const < constant.u16Const)
+                return true;
+
+            return false;
         case EbtInt:
         case EbtInt:
             if (iConst < constant.iConst)
             if (iConst < constant.iConst)
                 return true;
                 return true;
@@ -296,9 +440,13 @@ public:
         TConstUnion returnValue;
         TConstUnion returnValue;
         assert(type == constant.type);
         assert(type == constant.type);
         switch (type) {
         switch (type) {
-        case EbtInt: returnValue.setIConst(iConst + constant.iConst); break;
-        case EbtInt64: returnValue.setI64Const(i64Const + constant.i64Const); break;
-        case EbtUint: returnValue.setUConst(uConst + constant.uConst); break;
+        case EbtInt8:   returnValue.setI8Const(i8Const + constant.i8Const); break;
+        case EbtInt16:  returnValue.setI16Const(i16Const + constant.i16Const); break;
+        case EbtInt:    returnValue.setIConst(iConst + constant.iConst); break;
+        case EbtInt64:  returnValue.setI64Const(i64Const + constant.i64Const); break;
+        case EbtUint8:  returnValue.setU8Const(u8Const + constant.u8Const); break;
+        case EbtUint16: returnValue.setU16Const(u16Const + constant.u16Const); break;
+        case EbtUint:   returnValue.setUConst(uConst + constant.uConst); break;
         case EbtUint64: returnValue.setU64Const(u64Const + constant.u64Const); break;
         case EbtUint64: returnValue.setU64Const(u64Const + constant.u64Const); break;
         case EbtDouble: returnValue.setDConst(dConst + constant.dConst); break;
         case EbtDouble: returnValue.setDConst(dConst + constant.dConst); break;
         default: assert(false && "Default missing");
         default: assert(false && "Default missing");
@@ -312,9 +460,13 @@ public:
         TConstUnion returnValue;
         TConstUnion returnValue;
         assert(type == constant.type);
         assert(type == constant.type);
         switch (type) {
         switch (type) {
-        case EbtInt: returnValue.setIConst(iConst - constant.iConst); break;
-        case EbtInt64: returnValue.setI64Const(i64Const - constant.i64Const); break;
-        case EbtUint: returnValue.setUConst(uConst - constant.uConst); break;
+        case EbtInt8:   returnValue.setI8Const(i8Const - constant.i8Const); break;
+        case EbtInt16:  returnValue.setI16Const(i16Const - constant.i16Const); break;
+        case EbtInt:    returnValue.setIConst(iConst - constant.iConst); break;
+        case EbtInt64:  returnValue.setI64Const(i64Const - constant.i64Const); break;
+        case EbtUint8:  returnValue.setU8Const(u8Const - constant.u8Const); break;
+        case EbtUint16: returnValue.setU16Const(u16Const - constant.u16Const); break;
+        case EbtUint:   returnValue.setUConst(uConst - constant.uConst); break;
         case EbtUint64: returnValue.setU64Const(u64Const - constant.u64Const); break;
         case EbtUint64: returnValue.setU64Const(u64Const - constant.u64Const); break;
         case EbtDouble: returnValue.setDConst(dConst - constant.dConst); break;
         case EbtDouble: returnValue.setDConst(dConst - constant.dConst); break;
         default: assert(false && "Default missing");
         default: assert(false && "Default missing");
@@ -328,9 +480,13 @@ public:
         TConstUnion returnValue;
         TConstUnion returnValue;
         assert(type == constant.type);
         assert(type == constant.type);
         switch (type) {
         switch (type) {
-        case EbtInt: returnValue.setIConst(iConst * constant.iConst); break;
-        case EbtInt64: returnValue.setI64Const(i64Const * constant.i64Const); break;
-        case EbtUint: returnValue.setUConst(uConst * constant.uConst); break;
+        case EbtInt8:   returnValue.setI8Const(i8Const * constant.i8Const); break;
+        case EbtInt16:  returnValue.setI16Const(i16Const * constant.i16Const); break;
+        case EbtInt:    returnValue.setIConst(iConst * constant.iConst); break;
+        case EbtInt64:  returnValue.setI64Const(i64Const * constant.i64Const); break;
+        case EbtUint8:  returnValue.setU8Const(u8Const * constant.u8Const); break;
+        case EbtUint16: returnValue.setU16Const(u16Const * constant.u16Const); break;
+        case EbtUint:   returnValue.setUConst(uConst * constant.uConst); break;
         case EbtUint64: returnValue.setU64Const(u64Const * constant.u64Const); break;
         case EbtUint64: returnValue.setU64Const(u64Const * constant.u64Const); break;
         case EbtDouble: returnValue.setDConst(dConst * constant.dConst); break;
         case EbtDouble: returnValue.setDConst(dConst * constant.dConst); break;
         default: assert(false && "Default missing");
         default: assert(false && "Default missing");
@@ -344,9 +500,13 @@ public:
         TConstUnion returnValue;
         TConstUnion returnValue;
         assert(type == constant.type);
         assert(type == constant.type);
         switch (type) {
         switch (type) {
-        case EbtInt: returnValue.setIConst(iConst % constant.iConst); break;
-        case EbtInt64: returnValue.setI64Const(i64Const % constant.i64Const); break;
-        case EbtUint: returnValue.setUConst(uConst % constant.uConst); break;
+        case EbtInt8:   returnValue.setI8Const(i8Const % constant.i8Const); break;
+        case EbtInt16:  returnValue.setI8Const(i8Const % constant.i16Const); break;
+        case EbtInt:    returnValue.setIConst(iConst % constant.iConst); break;
+        case EbtInt64:  returnValue.setI64Const(i64Const % constant.i64Const); break;
+        case EbtUint8:  returnValue.setU8Const(u8Const % constant.u8Const); break;
+        case EbtUint16: returnValue.setU16Const(u16Const % constant.u16Const); break;
+        case EbtUint:   returnValue.setUConst(uConst % constant.uConst); break;
         case EbtUint64: returnValue.setU64Const(u64Const % constant.u64Const); break;
         case EbtUint64: returnValue.setU64Const(u64Const % constant.u64Const); break;
         default:     assert(false && "Default missing");
         default:     assert(false && "Default missing");
         }
         }
@@ -358,8 +518,64 @@ public:
     {
     {
         TConstUnion returnValue;
         TConstUnion returnValue;
         switch (type) {
         switch (type) {
+        case EbtInt8:
+            switch (constant.type) {
+            case EbtInt8:   returnValue.setI8Const(i8Const >> constant.i8Const);  break;
+            case EbtUint8:  returnValue.setI8Const(i8Const >> constant.u8Const);  break;
+            case EbtInt16:  returnValue.setI8Const(i8Const >> constant.i16Const); break;
+            case EbtUint16: returnValue.setI8Const(i8Const >> constant.u16Const); break;
+            case EbtInt:    returnValue.setI8Const(i8Const >> constant.iConst);   break;
+            case EbtUint:   returnValue.setI8Const(i8Const >> constant.uConst);   break;
+            case EbtInt64:  returnValue.setI8Const(i8Const >> constant.i64Const); break;
+            case EbtUint64: returnValue.setI8Const(i8Const >> constant.u64Const); break;
+            default:       assert(false && "Default missing");
+            }
+            break;
+        case EbtUint8:
+            switch (constant.type) {
+            case EbtInt8:   returnValue.setU8Const(u8Const >> constant.i8Const);  break;
+            case EbtUint8:  returnValue.setU8Const(u8Const >> constant.u8Const);  break;
+            case EbtInt16:  returnValue.setU8Const(u8Const >> constant.i16Const); break;
+            case EbtUint16: returnValue.setU8Const(u8Const >> constant.u16Const); break;
+            case EbtInt:    returnValue.setU8Const(u8Const >> constant.iConst);   break;
+            case EbtUint:   returnValue.setU8Const(u8Const >> constant.uConst);   break;
+            case EbtInt64:  returnValue.setU8Const(u8Const >> constant.i64Const); break;
+            case EbtUint64: returnValue.setU8Const(u8Const >> constant.u64Const); break;
+            default:       assert(false && "Default missing");
+            }
+            break;
+        case EbtInt16:
+            switch (constant.type) {
+            case EbtInt8:   returnValue.setI16Const(i16Const >> constant.i8Const);  break;
+            case EbtUint8:  returnValue.setI16Const(i16Const >> constant.u8Const);  break;
+            case EbtInt16:  returnValue.setI16Const(i16Const >> constant.i16Const); break;
+            case EbtUint16: returnValue.setI16Const(i16Const >> constant.u16Const); break;
+            case EbtInt:    returnValue.setI16Const(i16Const >> constant.iConst);   break;
+            case EbtUint:   returnValue.setI16Const(i16Const >> constant.uConst);   break;
+            case EbtInt64:  returnValue.setI16Const(i16Const >> constant.i64Const); break;
+            case EbtUint64: returnValue.setI16Const(i16Const >> constant.u64Const); break;
+            default:       assert(false && "Default missing");
+            }
+            break;
+        case EbtUint16:
+            switch (constant.type) {
+            case EbtInt8:   returnValue.setU16Const(u16Const >> constant.i8Const);  break;
+            case EbtUint8:  returnValue.setU16Const(u16Const >> constant.u8Const);  break;
+            case EbtInt16:  returnValue.setU16Const(u16Const >> constant.i16Const); break;
+            case EbtUint16: returnValue.setU16Const(u16Const >> constant.u16Const); break;
+            case EbtInt:    returnValue.setU16Const(u16Const >> constant.iConst);   break;
+            case EbtUint:   returnValue.setU16Const(u16Const >> constant.uConst);   break;
+            case EbtInt64:  returnValue.setU16Const(u16Const >> constant.i64Const); break;
+            case EbtUint64: returnValue.setU16Const(u16Const >> constant.u64Const); break;
+            default:       assert(false && "Default missing");
+            }
+            break;
         case EbtInt:
         case EbtInt:
             switch (constant.type) {
             switch (constant.type) {
+            case EbtInt8:   returnValue.setIConst(iConst >> constant.i8Const);  break;
+            case EbtUint8:  returnValue.setIConst(iConst >> constant.u8Const);  break;
+            case EbtInt16:  returnValue.setIConst(iConst >> constant.i16Const); break;
+            case EbtUint16: returnValue.setIConst(iConst >> constant.u16Const); break;
             case EbtInt:    returnValue.setIConst(iConst >> constant.iConst);   break;
             case EbtInt:    returnValue.setIConst(iConst >> constant.iConst);   break;
             case EbtUint:   returnValue.setIConst(iConst >> constant.uConst);   break;
             case EbtUint:   returnValue.setIConst(iConst >> constant.uConst);   break;
             case EbtInt64:  returnValue.setIConst(iConst >> constant.i64Const); break;
             case EbtInt64:  returnValue.setIConst(iConst >> constant.i64Const); break;
@@ -369,6 +585,10 @@ public:
             break;
             break;
         case EbtUint:
         case EbtUint:
             switch (constant.type) {
             switch (constant.type) {
+            case EbtInt8:   returnValue.setUConst(uConst >> constant.i8Const);  break;
+            case EbtUint8:  returnValue.setUConst(uConst >> constant.u8Const);  break;
+            case EbtInt16:  returnValue.setUConst(uConst >> constant.i16Const); break;
+            case EbtUint16: returnValue.setUConst(uConst >> constant.u16Const); break;
             case EbtInt:    returnValue.setUConst(uConst >> constant.iConst);   break;
             case EbtInt:    returnValue.setUConst(uConst >> constant.iConst);   break;
             case EbtUint:   returnValue.setUConst(uConst >> constant.uConst);   break;
             case EbtUint:   returnValue.setUConst(uConst >> constant.uConst);   break;
             case EbtInt64:  returnValue.setUConst(uConst >> constant.i64Const); break;
             case EbtInt64:  returnValue.setUConst(uConst >> constant.i64Const); break;
@@ -378,6 +598,10 @@ public:
             break;
             break;
          case EbtInt64:
          case EbtInt64:
             switch (constant.type) {
             switch (constant.type) {
+            case EbtInt8:   returnValue.setI64Const(i64Const >> constant.i8Const);  break;
+            case EbtUint8:  returnValue.setI64Const(i64Const >> constant.u8Const);  break;
+            case EbtInt16:  returnValue.setI64Const(i64Const >> constant.i16Const); break;
+            case EbtUint16: returnValue.setI64Const(i64Const >> constant.u16Const); break;
             case EbtInt:    returnValue.setI64Const(i64Const >> constant.iConst);   break;
             case EbtInt:    returnValue.setI64Const(i64Const >> constant.iConst);   break;
             case EbtUint:   returnValue.setI64Const(i64Const >> constant.uConst);   break;
             case EbtUint:   returnValue.setI64Const(i64Const >> constant.uConst);   break;
             case EbtInt64:  returnValue.setI64Const(i64Const >> constant.i64Const); break;
             case EbtInt64:  returnValue.setI64Const(i64Const >> constant.i64Const); break;
@@ -387,6 +611,10 @@ public:
             break;
             break;
         case EbtUint64:
         case EbtUint64:
             switch (constant.type) {
             switch (constant.type) {
+            case EbtInt8:   returnValue.setU64Const(u64Const >> constant.i8Const);  break;
+            case EbtUint8:  returnValue.setU64Const(u64Const >> constant.u8Const);  break;
+            case EbtInt16:  returnValue.setU64Const(u64Const >> constant.i16Const); break;
+            case EbtUint16: returnValue.setU64Const(u64Const >> constant.u16Const); break;
             case EbtInt:    returnValue.setU64Const(u64Const >> constant.iConst);   break;
             case EbtInt:    returnValue.setU64Const(u64Const >> constant.iConst);   break;
             case EbtUint:   returnValue.setU64Const(u64Const >> constant.uConst);   break;
             case EbtUint:   returnValue.setU64Const(u64Const >> constant.uConst);   break;
             case EbtInt64:  returnValue.setU64Const(u64Const >> constant.i64Const); break;
             case EbtInt64:  returnValue.setU64Const(u64Const >> constant.i64Const); break;
@@ -404,8 +632,64 @@ public:
     {
     {
         TConstUnion returnValue;
         TConstUnion returnValue;
         switch (type) {
         switch (type) {
+        case EbtInt8:
+            switch (constant.type) {
+            case EbtInt8:   returnValue.setI8Const(i8Const << constant.i8Const);  break;
+            case EbtUint8:  returnValue.setI8Const(i8Const << constant.u8Const);  break;
+            case EbtInt16:  returnValue.setI8Const(i8Const << constant.i16Const); break;
+            case EbtUint16: returnValue.setI8Const(i8Const << constant.u16Const); break;
+            case EbtInt:    returnValue.setI8Const(i8Const << constant.iConst);   break;
+            case EbtUint:   returnValue.setI8Const(i8Const << constant.uConst);   break;
+            case EbtInt64:  returnValue.setI8Const(i8Const << constant.i64Const); break;
+            case EbtUint64: returnValue.setI8Const(i8Const << constant.u64Const); break;
+            default:       assert(false && "Default missing");
+            }
+            break;
+        case EbtUint8:
+            switch (constant.type) {
+            case EbtInt8:   returnValue.setU8Const(u8Const << constant.i8Const);  break;
+            case EbtUint8:  returnValue.setU8Const(u8Const << constant.u8Const);  break;
+            case EbtInt16:  returnValue.setU8Const(u8Const << constant.i16Const); break;
+            case EbtUint16: returnValue.setU8Const(u8Const << constant.u16Const); break;
+            case EbtInt:    returnValue.setU8Const(u8Const << constant.iConst);   break;
+            case EbtUint:   returnValue.setU8Const(u8Const << constant.uConst);   break;
+            case EbtInt64:  returnValue.setU8Const(u8Const << constant.i64Const); break;
+            case EbtUint64: returnValue.setU8Const(u8Const << constant.u64Const); break;
+            default:       assert(false && "Default missing");
+            }
+            break;
+        case EbtInt16:
+            switch (constant.type) {
+            case EbtInt8:   returnValue.setI16Const(i16Const << constant.i8Const);  break;
+            case EbtUint8:  returnValue.setI16Const(i16Const << constant.u8Const);  break;
+            case EbtInt16:  returnValue.setI16Const(i16Const << constant.i16Const); break;
+            case EbtUint16: returnValue.setI16Const(i16Const << constant.u16Const); break;
+            case EbtInt:    returnValue.setI16Const(i16Const << constant.iConst);   break;
+            case EbtUint:   returnValue.setI16Const(i16Const << constant.uConst);   break;
+            case EbtInt64:  returnValue.setI16Const(i16Const << constant.i64Const); break;
+            case EbtUint64: returnValue.setI16Const(i16Const << constant.u64Const); break;
+            default:       assert(false && "Default missing");
+            }
+            break;
+        case EbtUint16:
+            switch (constant.type) {
+            case EbtInt8:   returnValue.setU16Const(u16Const << constant.i8Const);  break;
+            case EbtUint8:  returnValue.setU16Const(u16Const << constant.u8Const);  break;
+            case EbtInt16:  returnValue.setU16Const(u16Const << constant.i16Const); break;
+            case EbtUint16: returnValue.setU16Const(u16Const << constant.u16Const); break;
+            case EbtInt:    returnValue.setU16Const(u16Const << constant.iConst);   break;
+            case EbtUint:   returnValue.setU16Const(u16Const << constant.uConst);   break;
+            case EbtInt64:  returnValue.setU16Const(u16Const << constant.i64Const); break;
+            case EbtUint64: returnValue.setU16Const(u16Const << constant.u64Const); break;
+            default:       assert(false && "Default missing");
+            }
+            break;
         case EbtInt:
         case EbtInt:
             switch (constant.type) {
             switch (constant.type) {
+            case EbtInt8:   returnValue.setIConst(iConst << constant.i8Const);  break;
+            case EbtUint8:  returnValue.setIConst(iConst << constant.u8Const);  break;
+            case EbtInt16:  returnValue.setIConst(iConst << constant.i16Const); break;
+            case EbtUint16: returnValue.setIConst(iConst << constant.u16Const); break;
             case EbtInt:    returnValue.setIConst(iConst << constant.iConst);   break;
             case EbtInt:    returnValue.setIConst(iConst << constant.iConst);   break;
             case EbtUint:   returnValue.setIConst(iConst << constant.uConst);   break;
             case EbtUint:   returnValue.setIConst(iConst << constant.uConst);   break;
             case EbtInt64:  returnValue.setIConst(iConst << constant.i64Const); break;
             case EbtInt64:  returnValue.setIConst(iConst << constant.i64Const); break;
@@ -415,6 +699,10 @@ public:
             break;
             break;
         case EbtUint:
         case EbtUint:
             switch (constant.type) {
             switch (constant.type) {
+            case EbtInt8:   returnValue.setUConst(uConst << constant.i8Const);  break;
+            case EbtUint8:  returnValue.setUConst(uConst << constant.u8Const);  break;
+            case EbtInt16:  returnValue.setUConst(uConst << constant.i16Const); break;
+            case EbtUint16: returnValue.setUConst(uConst << constant.u16Const); break;
             case EbtInt:    returnValue.setUConst(uConst << constant.iConst);   break;
             case EbtInt:    returnValue.setUConst(uConst << constant.iConst);   break;
             case EbtUint:   returnValue.setUConst(uConst << constant.uConst);   break;
             case EbtUint:   returnValue.setUConst(uConst << constant.uConst);   break;
             case EbtInt64:  returnValue.setUConst(uConst << constant.i64Const); break;
             case EbtInt64:  returnValue.setUConst(uConst << constant.i64Const); break;
@@ -422,8 +710,12 @@ public:
             default:       assert(false && "Default missing");
             default:       assert(false && "Default missing");
             }
             }
             break;
             break;
-        case EbtInt64:
+         case EbtInt64:
             switch (constant.type) {
             switch (constant.type) {
+            case EbtInt8:   returnValue.setI64Const(i64Const << constant.i8Const);  break;
+            case EbtUint8:  returnValue.setI64Const(i64Const << constant.u8Const);  break;
+            case EbtInt16:  returnValue.setI64Const(i64Const << constant.i16Const); break;
+            case EbtUint16: returnValue.setI64Const(i64Const << constant.u16Const); break;
             case EbtInt:    returnValue.setI64Const(i64Const << constant.iConst);   break;
             case EbtInt:    returnValue.setI64Const(i64Const << constant.iConst);   break;
             case EbtUint:   returnValue.setI64Const(i64Const << constant.uConst);   break;
             case EbtUint:   returnValue.setI64Const(i64Const << constant.uConst);   break;
             case EbtInt64:  returnValue.setI64Const(i64Const << constant.i64Const); break;
             case EbtInt64:  returnValue.setI64Const(i64Const << constant.i64Const); break;
@@ -433,6 +725,10 @@ public:
             break;
             break;
         case EbtUint64:
         case EbtUint64:
             switch (constant.type) {
             switch (constant.type) {
+            case EbtInt8:   returnValue.setU64Const(u64Const << constant.i8Const);  break;
+            case EbtUint8:  returnValue.setU64Const(u64Const << constant.u8Const);  break;
+            case EbtInt16:  returnValue.setU64Const(u64Const << constant.i16Const); break;
+            case EbtUint16: returnValue.setU64Const(u64Const << constant.u16Const); break;
             case EbtInt:    returnValue.setU64Const(u64Const << constant.iConst);   break;
             case EbtInt:    returnValue.setU64Const(u64Const << constant.iConst);   break;
             case EbtUint:   returnValue.setU64Const(u64Const << constant.uConst);   break;
             case EbtUint:   returnValue.setU64Const(u64Const << constant.uConst);   break;
             case EbtInt64:  returnValue.setU64Const(u64Const << constant.i64Const); break;
             case EbtInt64:  returnValue.setU64Const(u64Const << constant.i64Const); break;
@@ -451,8 +747,12 @@ public:
         TConstUnion returnValue;
         TConstUnion returnValue;
         assert(type == constant.type);
         assert(type == constant.type);
         switch (type) {
         switch (type) {
-        case EbtInt:  returnValue.setIConst(iConst & constant.iConst); break;
-        case EbtUint: returnValue.setUConst(uConst & constant.uConst); break;
+        case EbtInt8:   returnValue.setI8Const(i8Const & constant.i8Const); break;
+        case EbtUint8:  returnValue.setU8Const(u8Const & constant.u8Const); break;
+        case EbtInt16:  returnValue.setI16Const(i16Const & constant.i16Const); break;
+        case EbtUint16: returnValue.setU16Const(u16Const & constant.u16Const); break;
+        case EbtInt:    returnValue.setIConst(iConst & constant.iConst); break;
+        case EbtUint:   returnValue.setUConst(uConst & constant.uConst); break;
         case EbtInt64:  returnValue.setI64Const(i64Const & constant.i64Const); break;
         case EbtInt64:  returnValue.setI64Const(i64Const & constant.i64Const); break;
         case EbtUint64: returnValue.setU64Const(u64Const & constant.u64Const); break;
         case EbtUint64: returnValue.setU64Const(u64Const & constant.u64Const); break;
         default:     assert(false && "Default missing");
         default:     assert(false && "Default missing");
@@ -466,8 +766,12 @@ public:
         TConstUnion returnValue;
         TConstUnion returnValue;
         assert(type == constant.type);
         assert(type == constant.type);
         switch (type) {
         switch (type) {
-        case EbtInt:  returnValue.setIConst(iConst | constant.iConst); break;
-        case EbtUint: returnValue.setUConst(uConst | constant.uConst); break;
+        case EbtInt8:   returnValue.setI8Const(i8Const | constant.i8Const); break;
+        case EbtUint8:  returnValue.setU8Const(u8Const | constant.u8Const); break;
+        case EbtInt16:  returnValue.setI16Const(i16Const | constant.i16Const); break;
+        case EbtUint16: returnValue.setU16Const(u16Const | constant.u16Const); break;
+        case EbtInt:    returnValue.setIConst(iConst | constant.iConst); break;
+        case EbtUint:   returnValue.setUConst(uConst | constant.uConst); break;
         case EbtInt64:  returnValue.setI64Const(i64Const | constant.i64Const); break;
         case EbtInt64:  returnValue.setI64Const(i64Const | constant.i64Const); break;
         case EbtUint64: returnValue.setU64Const(u64Const | constant.u64Const); break;
         case EbtUint64: returnValue.setU64Const(u64Const | constant.u64Const); break;
         default:     assert(false && "Default missing");
         default:     assert(false && "Default missing");
@@ -481,8 +785,12 @@ public:
         TConstUnion returnValue;
         TConstUnion returnValue;
         assert(type == constant.type);
         assert(type == constant.type);
         switch (type) {
         switch (type) {
-        case EbtInt:  returnValue.setIConst(iConst ^ constant.iConst); break;
-        case EbtUint: returnValue.setUConst(uConst ^ constant.uConst); break;
+        case EbtInt8:   returnValue.setI8Const(i8Const ^ constant.i8Const); break;
+        case EbtUint8:  returnValue.setU8Const(u8Const ^ constant.u8Const); break;
+        case EbtInt16:  returnValue.setI16Const(i16Const ^ constant.i16Const); break;
+        case EbtUint16: returnValue.setU16Const(u16Const ^ constant.u16Const); break;
+        case EbtInt:    returnValue.setIConst(iConst ^ constant.iConst); break;
+        case EbtUint:   returnValue.setUConst(uConst ^ constant.uConst); break;
         case EbtInt64:  returnValue.setI64Const(i64Const ^ constant.i64Const); break;
         case EbtInt64:  returnValue.setI64Const(i64Const ^ constant.i64Const); break;
         case EbtUint64: returnValue.setU64Const(u64Const ^ constant.u64Const); break;
         case EbtUint64: returnValue.setU64Const(u64Const ^ constant.u64Const); break;
         default:     assert(false && "Default missing");
         default:     assert(false && "Default missing");
@@ -495,8 +803,12 @@ public:
     {
     {
         TConstUnion returnValue;
         TConstUnion returnValue;
         switch (type) {
         switch (type) {
-        case EbtInt:  returnValue.setIConst(~iConst); break;
-        case EbtUint: returnValue.setUConst(~uConst); break;
+        case EbtInt8:   returnValue.setI8Const(~i8Const); break;
+        case EbtUint8:  returnValue.setU8Const(~u8Const); break;
+        case EbtInt16:  returnValue.setI16Const(~i16Const); break;
+        case EbtUint16: returnValue.setU16Const(~u16Const); break;
+        case EbtInt:    returnValue.setIConst(~iConst); break;
+        case EbtUint:   returnValue.setUConst(~uConst); break;
         case EbtInt64:  returnValue.setI64Const(~i64Const); break;
         case EbtInt64:  returnValue.setI64Const(~i64Const); break;
         case EbtUint64: returnValue.setU64Const(~u64Const); break;
         case EbtUint64: returnValue.setU64Const(~u64Const); break;
         default:     assert(false && "Default missing");
         default:     assert(false && "Default missing");
@@ -533,6 +845,10 @@ public:
 
 
 private:
 private:
     union  {
     union  {
+        signed char        i8Const;     // used for i8vec, scalar int8s
+        unsigned char      u8Const;     // used for u8vec, scalar uint8s
+        signed short       i16Const;    // used for i16vec, scalar int16s
+        unsigned short     u16Const;    // used for u16vec, scalar uint16s
         int                iConst;      // used for ivec, scalar ints
         int                iConst;      // used for ivec, scalar ints
         unsigned int       uConst;      // used for uvec, scalar uints
         unsigned int       uConst;      // used for uvec, scalar uints
         long long          i64Const;    // used for i64vec, scalar int64s
         long long          i64Const;    // used for i64vec, scalar int64s
@@ -595,9 +911,6 @@ public:
         if (! unionArray || ! rhs.unionArray)
         if (! unionArray || ! rhs.unionArray)
             return false;
             return false;
 
 
-        if (! unionArray || ! rhs.unionArray)
-            return false;
-
         return *unionArray == *rhs.unionArray;
         return *unionArray == *rhs.unionArray;
     }
     }
     bool operator!=(const TConstUnionArray& rhs) const { return ! operator==(rhs); }
     bool operator!=(const TConstUnionArray& rhs) const { return ! operator==(rhs); }

+ 1 - 2
src/libraries/glslang/glslang/Include/PoolAlloc.h

@@ -281,8 +281,6 @@ public:
     pool_allocator(TPoolAllocator& a) : allocator(a) { }
     pool_allocator(TPoolAllocator& a) : allocator(a) { }
     pool_allocator(const pool_allocator<T>& p) : allocator(p.allocator) { }
     pool_allocator(const pool_allocator<T>& p) : allocator(p.allocator) { }
 
 
-    pool_allocator& operator=(const pool_allocator&) { return *this; }
-
     template<class Other>
     template<class Other>
         pool_allocator(const pool_allocator<Other>& p) : allocator(p.getAllocator()) { }
         pool_allocator(const pool_allocator<Other>& p) : allocator(p.getAllocator()) { }
 
 
@@ -310,6 +308,7 @@ public:
     TPoolAllocator& getAllocator() const { return allocator; }
     TPoolAllocator& getAllocator() const { return allocator; }
 
 
 protected:
 protected:
+    pool_allocator& operator=(const pool_allocator&) { return *this; }
     TPoolAllocator& allocator;
     TPoolAllocator& allocator;
 };
 };
 
 

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

@@ -133,6 +133,15 @@ struct TBuiltInResource {
     int maxCullDistances;
     int maxCullDistances;
     int maxCombinedClipAndCullDistances;
     int maxCombinedClipAndCullDistances;
     int maxSamples;
     int maxSamples;
+    int maxMeshOutputVerticesNV;
+    int maxMeshOutputPrimitivesNV;
+    int maxMeshWorkGroupSizeX_NV;
+    int maxMeshWorkGroupSizeY_NV;
+    int maxMeshWorkGroupSizeZ_NV;
+    int maxTaskWorkGroupSizeX_NV;
+    int maxTaskWorkGroupSizeY_NV;
+    int maxTaskWorkGroupSizeZ_NV;
+    int maxMeshViewCountNV;
 
 
     TLimits limits;
     TLimits limits;
 };
 };

+ 268 - 99
src/libraries/glslang/glslang/Include/Types.h

@@ -2,6 +2,7 @@
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2012-2016 LunarG, Inc.
 // Copyright (C) 2012-2016 LunarG, Inc.
 // Copyright (C) 2015-2016 Google, Inc.
 // Copyright (C) 2015-2016 Google, Inc.
+// Copyright (C) 2017 ARM Limited.
 //
 //
 // All rights reserved.
 // All rights reserved.
 //
 //
@@ -204,9 +205,18 @@ struct TSampler {   // misnomer now; includes images, textures without sampler,
         }
         }
 
 
         switch (type) {
         switch (type) {
-        case EbtFloat:               break;
-        case EbtInt:  s.append("i"); break;
-        case EbtUint: s.append("u"); break;
+        case EbtFloat:                   break;
+#ifdef AMD_EXTENSIONS
+        case EbtFloat16: s.append("f16"); break;
+#endif
+        case EbtInt8:   s.append("i8");  break;
+        case EbtUint16: s.append("u8");  break;
+        case EbtInt16:  s.append("i16"); break;
+        case EbtUint8:  s.append("u16"); break;
+        case EbtInt:    s.append("i");   break;
+        case EbtUint:   s.append("u");   break;
+        case EbtInt64:  s.append("i64"); break;
+        case EbtUint64: s.append("u64"); break;
         default:  break;  // some compilers want this
         default:  break;  // some compilers want this
         }
         }
         if (image) {
         if (image) {
@@ -267,6 +277,7 @@ enum TLayoutPacking {
     ElpStd140,
     ElpStd140,
     ElpStd430,
     ElpStd430,
     ElpPacked,
     ElpPacked,
+    ElpScalar,
     ElpCount        // If expanding, see bitfield width below
     ElpCount        // If expanding, see bitfield width below
 };
 };
 
 
@@ -427,6 +438,7 @@ public:
         clearInterstage();
         clearInterstage();
         clearMemory();
         clearMemory();
         specConstant = false;
         specConstant = false;
+        nonUniform = false;
         clearLayout();
         clearLayout();
     }
     }
 
 
@@ -445,12 +457,23 @@ public:
         nopersp      = false;
         nopersp      = false;
 #ifdef AMD_EXTENSIONS
 #ifdef AMD_EXTENSIONS
         explicitInterp = false;
         explicitInterp = false;
+#endif
+#ifdef NV_EXTENSIONS
+        pervertexNV = false;
+        perPrimitiveNV = false;
+        perViewNV = false;
+        perTaskNV = false;
 #endif
 #endif
     }
     }
 
 
     void clearMemory()
     void clearMemory()
     {
     {
         coherent     = false;
         coherent     = false;
+        devicecoherent = false;
+        queuefamilycoherent = false;
+        workgroupcoherent = false;
+        subgroupcoherent  = false;
+        nonprivate = false;
         volatil      = false;
         volatil      = false;
         restrict     = false;
         restrict     = false;
         readonly     = false;
         readonly     = false;
@@ -460,7 +483,7 @@ public:
     // Drop just the storage qualification, which perhaps should
     // Drop just the storage qualification, which perhaps should
     // never be done, as it is fundamentally inconsistent, but need to
     // never be done, as it is fundamentally inconsistent, but need to
     // explore what downstream consumers need.
     // explore what downstream consumers need.
-    // E.g., in a deference, it is an inconsistency between:
+    // E.g., in a dereference, it is an inconsistency between:
     // A) partially dereferenced resource is still in the storage class it started in
     // A) partially dereferenced resource is still in the storage class it started in
     // B) partially dereferenced resource is a new temporary object
     // B) partially dereferenced resource is a new temporary object
     // If A, then nothing should change, if B, then everything should change, but this is half way.
     // If A, then nothing should change, if B, then everything should change, but this is half way.
@@ -468,6 +491,7 @@ public:
     {
     {
         storage      = EvqTemporary;
         storage      = EvqTemporary;
         specConstant = false;
         specConstant = false;
+        nonUniform   = false;
     }
     }
 
 
     const char*         semanticName;
     const char*         semanticName;
@@ -483,20 +507,37 @@ public:
     bool nopersp      : 1;
     bool nopersp      : 1;
 #ifdef AMD_EXTENSIONS
 #ifdef AMD_EXTENSIONS
     bool explicitInterp : 1;
     bool explicitInterp : 1;
+#endif
+#ifdef NV_EXTENSIONS
+    bool pervertexNV  : 1;
+    bool perPrimitiveNV : 1;
+    bool perViewNV : 1;
+    bool perTaskNV : 1;
 #endif
 #endif
     bool patch        : 1;
     bool patch        : 1;
     bool sample       : 1;
     bool sample       : 1;
     bool coherent     : 1;
     bool coherent     : 1;
+    bool devicecoherent : 1;
+    bool queuefamilycoherent : 1;
+    bool workgroupcoherent : 1;
+    bool subgroupcoherent  : 1;
+    bool nonprivate   : 1;
     bool volatil      : 1;
     bool volatil      : 1;
     bool restrict     : 1;
     bool restrict     : 1;
     bool readonly     : 1;
     bool readonly     : 1;
     bool writeonly    : 1;
     bool writeonly    : 1;
     bool specConstant : 1;  // having a constant_id is not sufficient: expressions have no id, but are still specConstant
     bool specConstant : 1;  // having a constant_id is not sufficient: expressions have no id, but are still specConstant
+    bool nonUniform   : 1;
 
 
     bool isMemory() const
     bool isMemory() const
     {
     {
-        return coherent || volatil || restrict || readonly || writeonly;
+        return subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly || nonprivate;
+    }
+    bool isMemoryQualifierImageAndSSBOOnly() const
+    {
+        return subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly;
     }
     }
+
     bool isInterpolation() const
     bool isInterpolation() const
     {
     {
 #ifdef AMD_EXTENSIONS
 #ifdef AMD_EXTENSIONS
@@ -505,9 +546,21 @@ public:
         return flat || smooth || nopersp;
         return flat || smooth || nopersp;
 #endif
 #endif
     }
     }
+
+#ifdef AMD_EXTENSIONS
+    bool isExplicitInterpolation() const
+    {
+        return explicitInterp;
+    }
+#endif
+
     bool isAuxiliary() const
     bool isAuxiliary() const
     {
     {
+#ifdef NV_EXTENSIONS
+        return centroid || patch || sample || pervertexNV;
+#else
         return centroid || patch || sample;
         return centroid || patch || sample;
+#endif
     }
     }
 
 
     bool isPipeInput() const
     bool isPipeInput() const
@@ -574,6 +627,33 @@ public:
         }
         }
     }
     }
 
 
+    bool isPerPrimitive() const
+    {
+#ifdef NV_EXTENSIONS
+        return perPrimitiveNV;
+#else
+        return false;
+#endif
+    }
+
+    bool isPerView() const
+    {
+#ifdef NV_EXTENSIONS
+        return perViewNV;
+#else
+        return false;
+#endif
+    }
+
+    bool isTaskMemory() const
+    {
+#ifdef NV_EXTENSIONS
+        return perTaskNV;
+#else
+        return false;
+#endif
+    }
+
     bool isIo() const
     bool isIo() const
     {
     {
         switch (storage) {
         switch (storage) {
@@ -597,6 +677,22 @@ public:
         }
         }
     }
     }
 
 
+    // non-built-in symbols that might link between compilation units
+    bool isLinkable() const
+    {
+        switch (storage) {
+        case EvqGlobal:
+        case EvqVaryingIn:
+        case EvqVaryingOut:
+        case EvqUniform:
+        case EvqBuffer:
+        case EvqShared:
+            return true;
+        default:
+            return false;
+        }
+    }
+
     // True if this type of IO is supposed to be arrayed with extra level for per-vertex data
     // True if this type of IO is supposed to be arrayed with extra level for per-vertex data
     bool isArrayedIo(EShLanguage language) const
     bool isArrayedIo(EShLanguage language) const
     {
     {
@@ -607,6 +703,13 @@ public:
             return ! patch && (isPipeInput() || isPipeOutput());
             return ! patch && (isPipeInput() || isPipeOutput());
         case EShLangTessEvaluation:
         case EShLangTessEvaluation:
             return ! patch && isPipeInput();
             return ! patch && isPipeInput();
+#ifdef NV_EXTENSIONS
+        case EShLangFragment:
+            return pervertexNV && isPipeInput();
+        case EShLangMeshNV:
+            return ! perTaskNV && isPipeOutput();
+#endif
+
         default:
         default:
             return false;
             return false;
         }
         }
@@ -623,6 +726,7 @@ public:
         layoutViewportRelative = false;
         layoutViewportRelative = false;
         // -2048 as the default value indicating layoutSecondaryViewportRelative is not set
         // -2048 as the default value indicating layoutSecondaryViewportRelative is not set
         layoutSecondaryViewportRelativeOffset = -2048;
         layoutSecondaryViewportRelativeOffset = -2048;
+        layoutShaderRecordNV = false;
 #endif
 #endif
 
 
         clearInterstageLayout();
         clearInterstageLayout();
@@ -656,6 +760,9 @@ public:
                hasAnyLocation() ||
                hasAnyLocation() ||
                hasStream() ||
                hasStream() ||
                hasFormat() ||
                hasFormat() ||
+#ifdef NV_EXTENSIONS
+               layoutShaderRecordNV ||
+#endif
                layoutPushConstant;
                layoutPushConstant;
     }
     }
     bool hasLayout() const
     bool hasLayout() const
@@ -668,40 +775,40 @@ public:
     int layoutOffset;
     int layoutOffset;
     int layoutAlign;
     int layoutAlign;
 
 
-                 unsigned int layoutLocation            :12;
-    static const unsigned int layoutLocationEnd    =  0xFFF;
+                 unsigned int layoutLocation             : 12;
+    static const unsigned int layoutLocationEnd      =  0xFFF;
 
 
-                 unsigned int layoutComponent           : 3;
-    static const unsigned int layoutComponentEnd    =     4;
+                 unsigned int layoutComponent            :  3;
+    static const unsigned int layoutComponentEnd      =     4;
 
 
-                 unsigned int layoutSet                 : 7;
-    static const unsigned int layoutSetEnd         =   0x3F;
+                 unsigned int layoutSet                  :  7;
+    static const unsigned int layoutSetEnd           =   0x3F;
 
 
-                 unsigned int layoutBinding            : 16;
-    static const unsigned int layoutBindingEnd    =  0xFFFF;
+                 unsigned int layoutBinding              : 16;
+    static const unsigned int layoutBindingEnd      =  0xFFFF;
 
 
-                 unsigned int layoutIndex              :  8;
-    static const unsigned int layoutIndexEnd    =      0xFF;
+                 unsigned int layoutIndex                :  8;
+    static const unsigned int layoutIndexEnd      =      0xFF;
 
 
-                 unsigned int layoutStream              : 8;
-    static const unsigned int layoutStreamEnd    =     0xFF;
+                 unsigned int layoutStream               :  8;
+    static const unsigned int layoutStreamEnd      =     0xFF;
 
 
-                 unsigned int layoutXfbBuffer           : 4;
-    static const unsigned int layoutXfbBufferEnd    =   0xF;
+                 unsigned int layoutXfbBuffer            :  4;
+    static const unsigned int layoutXfbBufferEnd      =   0xF;
 
 
-                 unsigned int layoutXfbStride          : 10;
-    static const unsigned int layoutXfbStrideEnd    = 0x3FF;
+                 unsigned int layoutXfbStride            : 14;
+    static const unsigned int layoutXfbStrideEnd     = 0x3FFF;
 
 
-                 unsigned int layoutXfbOffset          : 10;
-    static const unsigned int layoutXfbOffsetEnd    = 0x3FF;
+                 unsigned int layoutXfbOffset            : 13;
+    static const unsigned int layoutXfbOffsetEnd     = 0x1FFF;
 
 
-                 unsigned int layoutAttachment          : 8;  // for input_attachment_index
-    static const unsigned int layoutAttachmentEnd    = 0XFF;
+                 unsigned int layoutAttachment           :  8;  // for input_attachment_index
+    static const unsigned int layoutAttachmentEnd      = 0XFF;
 
 
                  unsigned int layoutSpecConstantId       : 11;
                  unsigned int layoutSpecConstantId       : 11;
     static const unsigned int layoutSpecConstantIdEnd = 0x7FF;
     static const unsigned int layoutSpecConstantIdEnd = 0x7FF;
 
 
-    TLayoutFormat layoutFormat                         :  8;
+    TLayoutFormat layoutFormat                           :  8;
 
 
     bool layoutPushConstant;
     bool layoutPushConstant;
 
 
@@ -709,6 +816,7 @@ public:
     bool layoutPassthrough;
     bool layoutPassthrough;
     bool layoutViewportRelative;
     bool layoutViewportRelative;
     int layoutSecondaryViewportRelativeOffset;
     int layoutSecondaryViewportRelativeOffset;
+    bool layoutShaderRecordNV;
 #endif
 #endif
 
 
     bool hasUniformLayout() const
     bool hasUniformLayout() const
@@ -817,6 +925,10 @@ public:
         // true front-end constant.
         // true front-end constant.
         return specConstant;
         return specConstant;
     }
     }
+    bool isNonUniform() const
+    {
+        return nonUniform;
+    }
     bool isFrontEndConstant() const
     bool isFrontEndConstant() const
     {
     {
         // True if the front-end knows the final constant value.
         // True if the front-end knows the final constant value.
@@ -840,6 +952,7 @@ public:
         case ElpShared:   return "shared";
         case ElpShared:   return "shared";
         case ElpStd140:   return "std140";
         case ElpStd140:   return "std140";
         case ElpStd430:   return "std430";
         case ElpStd430:   return "std430";
+        case ElpScalar:   return "scalar";
         default:          return "none";
         default:          return "none";
         }
         }
     }
     }
@@ -982,7 +1095,7 @@ struct TShaderQualifiers {
     bool pixelCenterInteger;  // fragment shader
     bool pixelCenterInteger;  // fragment shader
     bool originUpperLeft;     // fragment shader
     bool originUpperLeft;     // fragment shader
     int invocations;
     int invocations;
-    int vertices;             // both for tessellation "vertices" and geometry "max_vertices"
+    int vertices;             // for tessellation "vertices", geometry & mesh "max_vertices"
     TVertexSpacing spacing;
     TVertexSpacing spacing;
     TVertexOrder order;
     TVertexOrder order;
     bool pointMode;
     bool pointMode;
@@ -995,7 +1108,10 @@ struct TShaderQualifiers {
     int numViews;             // multiview extenstions
     int numViews;             // multiview extenstions
 
 
 #ifdef NV_EXTENSIONS
 #ifdef NV_EXTENSIONS
-    bool layoutOverrideCoverage;    // true if layout override_coverage set
+    bool layoutOverrideCoverage;        // true if layout override_coverage set
+    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
 #endif
 #endif
 
 
     void init()
     void init()
@@ -1020,7 +1136,10 @@ struct TShaderQualifiers {
         blendEquation = false;
         blendEquation = false;
         numViews = TQualifier::layoutNotSet;
         numViews = TQualifier::layoutNotSet;
 #ifdef NV_EXTENSIONS
 #ifdef NV_EXTENSIONS
-        layoutOverrideCoverage = false;
+        layoutOverrideCoverage      = false;
+        layoutDerivativeGroupQuads  = false;
+        layoutDerivativeGroupLinear = false;
+        primitives                  = TQualifier::layoutNotSet;
 #endif
 #endif
     }
     }
 
 
@@ -1065,6 +1184,12 @@ struct TShaderQualifiers {
 #ifdef NV_EXTENSIONS
 #ifdef NV_EXTENSIONS
         if (src.layoutOverrideCoverage)
         if (src.layoutOverrideCoverage)
             layoutOverrideCoverage = src.layoutOverrideCoverage;
             layoutOverrideCoverage = src.layoutOverrideCoverage;
+        if (src.layoutDerivativeGroupQuads)
+            layoutDerivativeGroupQuads = src.layoutDerivativeGroupQuads;
+        if (src.layoutDerivativeGroupLinear)
+            layoutDerivativeGroupLinear = src.layoutDerivativeGroupLinear;
+        if (src.primitives != TQualifier::layoutNotSet)
+            primitives = src.primitives;
 #endif
 #endif
     }
     }
 };
 };
@@ -1299,31 +1424,9 @@ public:
 
 
     void makeVector() { vector1 = true; }
     void makeVector() { vector1 = true; }
 
 
-    // Merge type from parent, where a parentType is at the beginning of a declaration,
-    // establishing some characteristics for all subsequent names, while this type
-    // is on the individual names.
-    void mergeType(const TPublicType& parentType)
-    {
-        // arrayness is currently the only child aspect that has to be preserved
-        basicType = parentType.basicType;
-        vectorSize = parentType.vectorSize;
-        matrixCols = parentType.matrixCols;
-        matrixRows = parentType.matrixRows;
-        vector1 = false;                      // TPublicType is only GLSL which so far has no vec1
-        qualifier = parentType.qualifier;
-        sampler = parentType.sampler;
-        if (parentType.arraySizes)
-            newArraySizes(*parentType.arraySizes);
-        if (parentType.userDef) {
-            structure = parentType.userDef->getWritableStruct();
-            setTypeName(parentType.userDef->getTypeName());
-        }
-    }
-
     virtual void hideMember() { basicType = EbtVoid; vectorSize = 1; }
     virtual void hideMember() { basicType = EbtVoid; vectorSize = 1; }
     virtual bool hiddenMember() const { return basicType == EbtVoid; }
     virtual bool hiddenMember() const { return basicType == EbtVoid; }
 
 
-    virtual void setTypeName(const TString& n) { typeName = NewPoolTString(n.c_str()); }
     virtual void setFieldName(const TString& n) { fieldName = NewPoolTString(n.c_str()); }
     virtual void setFieldName(const TString& n) { fieldName = NewPoolTString(n.c_str()); }
     virtual const TString& getTypeName() const
     virtual const TString& getTypeName() const
     {
     {
@@ -1353,33 +1456,31 @@ public:
     virtual bool isArrayOfArrays() const { return arraySizes != nullptr && arraySizes->getNumDims() > 1; }
     virtual bool isArrayOfArrays() const { return arraySizes != nullptr && arraySizes->getNumDims() > 1; }
     virtual int getImplicitArraySize() const { return arraySizes->getImplicitSize(); }
     virtual int getImplicitArraySize() const { return arraySizes->getImplicitSize(); }
     virtual const TArraySizes* getArraySizes() const { return arraySizes; }
     virtual const TArraySizes* getArraySizes() const { return arraySizes; }
-    virtual       TArraySizes& getArraySizes()       { assert(arraySizes != nullptr); return *arraySizes; }
+    virtual       TArraySizes* getArraySizes()       { return arraySizes; }
 
 
     virtual bool isScalar() const { return ! isVector() && ! isMatrix() && ! isStruct() && ! isArray(); }
     virtual bool isScalar() const { return ! isVector() && ! isMatrix() && ! isStruct() && ! isArray(); }
     virtual bool isScalarOrVec1() const { return isScalar() || vector1; }
     virtual bool isScalarOrVec1() const { return isScalar() || vector1; }
     virtual bool isVector() const { return vectorSize > 1 || vector1; }
     virtual bool isVector() const { return vectorSize > 1 || vector1; }
     virtual bool isMatrix() const { return matrixCols ? true : false; }
     virtual bool isMatrix() const { return matrixCols ? true : false; }
     virtual bool isArray()  const { return arraySizes != nullptr; }
     virtual bool isArray()  const { return arraySizes != nullptr; }
-    virtual bool isExplicitlySizedArray() const { return isArray() && getOuterArraySize() != UnsizedArraySize; }
-    virtual bool isImplicitlySizedArray() const { return isArray() && getOuterArraySize() == UnsizedArraySize && qualifier.storage != EvqBuffer; }
-    virtual bool isRuntimeSizedArray()    const { return isArray() && getOuterArraySize() == UnsizedArraySize && qualifier.storage == EvqBuffer; }
+    virtual bool isSizedArray() const { return isArray() && arraySizes->isSized(); }
+    virtual bool isUnsizedArray() const { return isArray() && !arraySizes->isSized(); }
+    virtual bool isArrayVariablyIndexed() const { assert(isArray()); return arraySizes->isVariablyIndexed(); }
+    virtual void setArrayVariablyIndexed() { assert(isArray()); arraySizes->setVariablyIndexed(); }
+    virtual void updateImplicitArraySize(int size) { assert(isArray()); arraySizes->updateImplicitSize(size); }
     virtual bool isStruct() const { return structure != nullptr; }
     virtual bool isStruct() const { return structure != nullptr; }
-#ifdef AMD_EXTENSIONS
     virtual bool isFloatingDomain() const { return basicType == EbtFloat || basicType == EbtDouble || basicType == EbtFloat16; }
     virtual bool isFloatingDomain() const { return basicType == EbtFloat || basicType == EbtDouble || basicType == EbtFloat16; }
-#else
-    virtual bool isFloatingDomain() const { return basicType == EbtFloat || basicType == EbtDouble; }
-#endif
     virtual bool isIntegerDomain() const
     virtual bool isIntegerDomain() const
     {
     {
         switch (basicType) {
         switch (basicType) {
+        case EbtInt8:
+        case EbtUint8:
+        case EbtInt16:
+        case EbtUint16:
         case EbtInt:
         case EbtInt:
         case EbtUint:
         case EbtUint:
         case EbtInt64:
         case EbtInt64:
         case EbtUint64:
         case EbtUint64:
-#ifdef AMD_EXTENSIONS
-        case EbtInt16:
-        case EbtUint16:
-#endif
         case EbtAtomicUint:
         case EbtAtomicUint:
             return true;
             return true;
         default:
         default:
@@ -1387,15 +1488,20 @@ public:
         }
         }
         return false;
         return false;
     }
     }
-    virtual bool isOpaque() const { return basicType == EbtSampler || basicType == EbtAtomicUint; }
+    virtual bool isOpaque() const { return basicType == EbtSampler || basicType == EbtAtomicUint
+#ifdef NV_EXTENSIONS
+        || basicType == EbtAccStructNV
+#endif
+        ; }
     virtual bool isBuiltIn() const { return getQualifier().builtIn != EbvNone; }
     virtual bool isBuiltIn() const { return getQualifier().builtIn != EbvNone; }
 
 
     // "Image" is a superset of "Subpass"
     // "Image" is a superset of "Subpass"
-    virtual bool isImage() const   { return basicType == EbtSampler && getSampler().isImage(); }
+    virtual bool isImage()   const { return basicType == EbtSampler && getSampler().isImage(); }
     virtual bool isSubpass() const { return basicType == EbtSampler && getSampler().isSubpass(); }
     virtual bool isSubpass() const { return basicType == EbtSampler && getSampler().isSubpass(); }
+    virtual bool isTexture() const { return basicType == EbtSampler && getSampler().isTexture(); }
 
 
     // return true if this type contains any subtype which satisfies the given predicate.
     // return true if this type contains any subtype which satisfies the given predicate.
-    template <typename P> 
+    template <typename P>
     bool contains(P predicate) const
     bool contains(P predicate) const
     {
     {
         if (predicate(this))
         if (predicate(this))
@@ -1424,10 +1530,10 @@ public:
         return contains([this](const TType* t) { return t != this && t->isStruct(); } );
         return contains([this](const TType* t) { return t != this && t->isStruct(); } );
     }
     }
 
 
-    // Recursively check the structure for any implicitly-sized arrays, needed for triggering a copyUp().
-    virtual bool containsImplicitlySizedArray() const
+    // Recursively check the structure for any unsized arrays, needed for triggering a copyUp().
+    virtual bool containsUnsizedArray() const
     {
     {
-        return contains([](const TType* t) { return t->isImplicitlySizedArray(); } );
+        return contains([](const TType* t) { return t->isUnsizedArray(); } );
     }
     }
 
 
     virtual bool containsOpaque() const
     virtual bool containsOpaque() const
@@ -1448,17 +1554,15 @@ public:
             case EbtVoid:
             case EbtVoid:
             case EbtFloat:
             case EbtFloat:
             case EbtDouble:
             case EbtDouble:
-#ifdef AMD_EXTENSIONS
             case EbtFloat16:
             case EbtFloat16:
-#endif
+            case EbtInt8:
+            case EbtUint8:
+            case EbtInt16:
+            case EbtUint16:
             case EbtInt:
             case EbtInt:
             case EbtUint:
             case EbtUint:
             case EbtInt64:
             case EbtInt64:
             case EbtUint64:
             case EbtUint64:
-#ifdef AMD_EXTENSIONS
-            case EbtInt16:
-            case EbtUint16:
-#endif
             case EbtBool:
             case EbtBool:
                 return true;
                 return true;
             default:
             default:
@@ -1474,6 +1578,16 @@ public:
         return contains([](const TType* t) { return t->isArray() && t->arraySizes->isOuterSpecialization(); } );
         return contains([](const TType* t) { return t->isArray() && t->arraySizes->isOuterSpecialization(); } );
     }
     }
 
 
+    virtual bool contains16BitInt() const
+    {
+        return containsBasicType(EbtInt16) || containsBasicType(EbtUint16);
+    }
+
+    virtual bool contains8BitInt() const
+    {
+        return containsBasicType(EbtInt8) || containsBasicType(EbtUint8);
+    }
+
     // Array editing methods.  Array descriptors can be shared across
     // Array editing methods.  Array descriptors can be shared across
     // type instances.  This allows all uses of the same array
     // type instances.  This allows all uses of the same array
     // to be updated at once.  E.g., all nodes can be explicitly sized
     // to be updated at once.  E.g., all nodes can be explicitly sized
@@ -1493,34 +1607,56 @@ public:
         assert(type.arraySizes != nullptr);
         assert(type.arraySizes != nullptr);
         *arraySizes = *type.arraySizes;
         *arraySizes = *type.arraySizes;
     }
     }
-    void newArraySizes(const TArraySizes& s)
+    void copyArraySizes(const TArraySizes& s)
     {
     {
         // For setting a fresh new set of array sizes, not yet worrying about sharing.
         // For setting a fresh new set of array sizes, not yet worrying about sharing.
         arraySizes = new TArraySizes;
         arraySizes = new TArraySizes;
         *arraySizes = s;
         *arraySizes = s;
     }
     }
+    void transferArraySizes(TArraySizes* s)
+    {
+        // For setting an already allocated set of sizes that this type can use
+        // (no copy made).
+        arraySizes = s;
+    }
     void clearArraySizes()
     void clearArraySizes()
     {
     {
-        arraySizes = 0;
+        arraySizes = nullptr;
     }
     }
-    void addArrayOuterSizes(const TArraySizes& s)
+
+    // Add inner array sizes, to any existing sizes, via copy; the
+    // sizes passed in can still be reused for other purposes.
+    void copyArrayInnerSizes(const TArraySizes* s)
     {
     {
-        if (arraySizes == nullptr)
-            newArraySizes(s);
-        else
-            arraySizes->addOuterSizes(s);
+        if (s != nullptr) {
+            if (arraySizes == nullptr)
+                copyArraySizes(*s);
+            else
+                arraySizes->addInnerSizes(*s);
+        }
     }
     }
     void changeOuterArraySize(int s) { arraySizes->changeOuterSize(s); }
     void changeOuterArraySize(int s) { arraySizes->changeOuterSize(s); }
-    void setImplicitArraySize(int s) { arraySizes->setImplicitSize(s); }
 
 
-    // Recursively make the implicit array size the explicit array size, through the type tree.
-    void adoptImplicitArraySizes()
+    // Recursively make the implicit array size the explicit array size.
+    // Expicit arrays are compile-time or link-time sized, never run-time sized.
+    // Sometimes, policy calls for an array to be run-time sized even if it was
+    // never variably indexed: Don't turn a 'skipNonvariablyIndexed' array into
+    // an explicit array.
+    void adoptImplicitArraySizes(bool skipNonvariablyIndexed)
     {
     {
-        if (isImplicitlySizedArray())
+        if (isUnsizedArray() && !(skipNonvariablyIndexed || isArrayVariablyIndexed()))
             changeOuterArraySize(getImplicitArraySize());
             changeOuterArraySize(getImplicitArraySize());
-        if (isStruct()) {
-            for (int i = 0; i < (int)structure->size(); ++i)
-                (*structure)[i].type->adoptImplicitArraySizes();
+#ifdef NV_EXTENSIONS
+        // For multi-dim per-view arrays, set unsized inner dimension size to 1
+        if (qualifier.isPerView() && arraySizes && arraySizes->isInnerUnsized())
+            arraySizes->clearInnerUnsized();
+#endif
+        if (isStruct() && structure->size() > 0) {
+            int lastMember = (int)structure->size() - 1;
+            for (int i = 0; i < lastMember; ++i)
+                (*structure)[i].type->adoptImplicitArraySizes(false);
+            // implement the "last member of an SSBO" policy
+            (*structure)[lastMember].type->adoptImplicitArraySizes(getQualifier().storage == EvqBuffer);
         }
         }
     }
     }
 
 
@@ -1535,22 +1671,23 @@ public:
         case EbtVoid:              return "void";
         case EbtVoid:              return "void";
         case EbtFloat:             return "float";
         case EbtFloat:             return "float";
         case EbtDouble:            return "double";
         case EbtDouble:            return "double";
-#ifdef AMD_EXTENSIONS
         case EbtFloat16:           return "float16_t";
         case EbtFloat16:           return "float16_t";
-#endif
+        case EbtInt8:              return "int8_t";
+        case EbtUint8:             return "uint8_t";
+        case EbtInt16:             return "int16_t";
+        case EbtUint16:            return "uint16_t";
         case EbtInt:               return "int";
         case EbtInt:               return "int";
         case EbtUint:              return "uint";
         case EbtUint:              return "uint";
         case EbtInt64:             return "int64_t";
         case EbtInt64:             return "int64_t";
         case EbtUint64:            return "uint64_t";
         case EbtUint64:            return "uint64_t";
-#ifdef AMD_EXTENSIONS
-        case EbtInt16:             return "int16_t";
-        case EbtUint16:            return "uint16_t";
-#endif
         case EbtBool:              return "bool";
         case EbtBool:              return "bool";
         case EbtAtomicUint:        return "atomic_uint";
         case EbtAtomicUint:        return "atomic_uint";
         case EbtSampler:           return "sampler/image";
         case EbtSampler:           return "sampler/image";
         case EbtStruct:            return "structure";
         case EbtStruct:            return "structure";
         case EbtBlock:             return "block";
         case EbtBlock:             return "block";
+#ifdef NV_EXTENSIONS
+        case EbtAccStructNV:       return "accelerationStructureNV";
+#endif
         default:                   return "unknown type";
         default:                   return "unknown type";
         }
         }
     }
     }
@@ -1646,6 +1783,8 @@ public:
                     appendStr(" layoutSecondaryViewportRelativeOffset=");
                     appendStr(" layoutSecondaryViewportRelativeOffset=");
                     appendInt(qualifier.layoutSecondaryViewportRelativeOffset);
                     appendInt(qualifier.layoutSecondaryViewportRelativeOffset);
                 }
                 }
+                if (qualifier.layoutShaderRecordNV)
+                    appendStr(" shaderRecordNV");
 #endif
 #endif
 
 
                 appendStr(")");
                 appendStr(")");
@@ -1667,6 +1806,16 @@ public:
 #ifdef AMD_EXTENSIONS
 #ifdef AMD_EXTENSIONS
         if (qualifier.explicitInterp)
         if (qualifier.explicitInterp)
             appendStr(" __explicitInterpAMD");
             appendStr(" __explicitInterpAMD");
+#endif
+#ifdef NV_EXTENSIONS
+        if (qualifier.pervertexNV)
+            appendStr(" pervertexNV");
+        if (qualifier.perPrimitiveNV)
+            appendStr(" perprimitiveNV");
+        if (qualifier.perViewNV)
+            appendStr(" perviewNV");
+        if (qualifier.perTaskNV)
+            appendStr(" taskNV");
 #endif
 #endif
         if (qualifier.patch)
         if (qualifier.patch)
             appendStr(" patch");
             appendStr(" patch");
@@ -1674,6 +1823,16 @@ public:
             appendStr(" sample");
             appendStr(" sample");
         if (qualifier.coherent)
         if (qualifier.coherent)
             appendStr(" coherent");
             appendStr(" coherent");
+        if (qualifier.devicecoherent)
+            appendStr(" devicecoherent");
+        if (qualifier.queuefamilycoherent)
+            appendStr(" queuefamilycoherent");
+        if (qualifier.workgroupcoherent)
+            appendStr(" workgroupcoherent");
+        if (qualifier.subgroupcoherent)
+            appendStr(" subgroupcoherent");
+        if (qualifier.nonprivate)
+            appendStr(" nonprivate");
         if (qualifier.volatil)
         if (qualifier.volatil)
             appendStr(" volatile");
             appendStr(" volatile");
         if (qualifier.restrict)
         if (qualifier.restrict)
@@ -1684,16 +1843,26 @@ public:
             appendStr(" writeonly");
             appendStr(" writeonly");
         if (qualifier.specConstant)
         if (qualifier.specConstant)
             appendStr(" specialization-constant");
             appendStr(" specialization-constant");
+        if (qualifier.nonUniform)
+            appendStr(" nonuniform");
         appendStr(" ");
         appendStr(" ");
         appendStr(getStorageQualifierString());
         appendStr(getStorageQualifierString());
         if (isArray()) {
         if (isArray()) {
             for(int i = 0; i < (int)arraySizes->getNumDims(); ++i) {
             for(int i = 0; i < (int)arraySizes->getNumDims(); ++i) {
                 int size = arraySizes->getDimSize(i);
                 int size = arraySizes->getDimSize(i);
-                if (size == 0)
-                    appendStr(" implicitly-sized array of");
+                if (size == UnsizedArraySize && i == 0 && arraySizes->isVariablyIndexed())
+                    appendStr(" runtime-sized array of");
                 else {
                 else {
-                    appendStr(" ");
-                    appendInt(arraySizes->getDimSize(i));
+                    if (size == UnsizedArraySize) {
+                        appendStr(" unsized");
+                        if (i == 0) {
+                            appendStr(" ");
+                            appendInt(arraySizes->getImplicitSize());
+                        }
+                    } else {
+                        appendStr(" ");
+                        appendInt(arraySizes->getDimSize(i));
+                    }
                     appendStr("-element array of");
                     appendStr("-element array of");
                 }
                 }
             }
             }

+ 21 - 11
src/libraries/glslang/glslang/Include/arrays.h

@@ -41,6 +41,8 @@
 #ifndef _ARRAYS_INCLUDED
 #ifndef _ARRAYS_INCLUDED
 #define _ARRAYS_INCLUDED
 #define _ARRAYS_INCLUDED
 
 
+#include <algorithm>
+
 namespace glslang {
 namespace glslang {
 
 
 // This is used to mean there is no size yet (unsized), it is waiting to get a size from somewhere else.
 // This is used to mean there is no size yet (unsized), it is waiting to get a size from somewhere else.
@@ -130,10 +132,10 @@ struct TSmallArrayVector {
         sizes->push_back(pair);
         sizes->push_back(pair);
     }
     }
 
 
-    void push_front(const TSmallArrayVector& newDims)
+    void push_back(const TSmallArrayVector& newDims)
     {
     {
         alloc();
         alloc();
-        sizes->insert(sizes->begin(), newDims.sizes->begin(), newDims.sizes->end());
+        sizes->insert(sizes->end(), newDims.sizes->begin(), newDims.sizes->end());
     }
     }
 
 
     void pop_front()
     void pop_front()
@@ -220,12 +222,13 @@ protected:
 struct TArraySizes {
 struct TArraySizes {
     POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
     POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
 
 
-    TArraySizes() : implicitArraySize(1) { }
+    TArraySizes() : implicitArraySize(1), variablyIndexed(false) { }
 
 
     // For breaking into two non-shared copies, independently modifiable.
     // For breaking into two non-shared copies, independently modifiable.
     TArraySizes& operator=(const TArraySizes& from)
     TArraySizes& operator=(const TArraySizes& from)
     {
     {
         implicitArraySize = from.implicitArraySize;
         implicitArraySize = from.implicitArraySize;
+        variablyIndexed = from.variablyIndexed;
         sizes = from.sizes;
         sizes = from.sizes;
 
 
         return *this;
         return *this;
@@ -252,10 +255,11 @@ struct TArraySizes {
     void addInnerSize(int s) { addInnerSize((unsigned)s, nullptr); }
     void addInnerSize(int s) { addInnerSize((unsigned)s, nullptr); }
     void addInnerSize(int s, TIntermTyped* n) { sizes.push_back((unsigned)s, n); }
     void addInnerSize(int s, TIntermTyped* n) { sizes.push_back((unsigned)s, n); }
     void addInnerSize(TArraySize pair) { sizes.push_back(pair.size, pair.node); }
     void addInnerSize(TArraySize pair) { sizes.push_back(pair.size, pair.node); }
+    void addInnerSizes(const TArraySizes& s) { sizes.push_back(s.sizes); }
     void changeOuterSize(int s) { sizes.changeFront((unsigned)s); }
     void changeOuterSize(int s) { sizes.changeFront((unsigned)s); }
-    int getImplicitSize() const { return (int)implicitArraySize; }
-    void setImplicitSize(int s) { implicitArraySize = s; }
-    bool isInnerImplicit() const
+    int getImplicitSize() const { return implicitArraySize; }
+    void updateImplicitSize(int s) { implicitArraySize = std::max(implicitArraySize, s); }
+    bool isInnerUnsized() const
     {
     {
         for (int d = 1; d < sizes.size(); ++d) {
         for (int d = 1; d < sizes.size(); ++d) {
             if (sizes.getDimSize(d) == (unsigned)UnsizedArraySize)
             if (sizes.getDimSize(d) == (unsigned)UnsizedArraySize)
@@ -264,7 +268,7 @@ struct TArraySizes {
 
 
         return false;
         return false;
     }
     }
-    bool clearInnerImplicit()
+    bool clearInnerUnsized()
     {
     {
         for (int d = 1; d < sizes.size(); ++d) {
         for (int d = 1; d < sizes.size(); ++d) {
             if (sizes.getDimSize(d) == (unsigned)UnsizedArraySize)
             if (sizes.getDimSize(d) == (unsigned)UnsizedArraySize)
@@ -287,8 +291,8 @@ struct TArraySizes {
         return sizes.getDimNode(0) != nullptr;
         return sizes.getDimNode(0) != nullptr;
     }
     }
 
 
-    bool isImplicit() const { return getOuterSize() == UnsizedArraySize || isInnerImplicit(); }
-    void addOuterSizes(const TArraySizes& s) { sizes.push_front(s.sizes); }
+    bool hasUnsized() const { return getOuterSize() == UnsizedArraySize || isInnerUnsized(); }
+    bool isSized() const { return getOuterSize() != UnsizedArraySize; }
     void dereference() { sizes.pop_front(); }
     void dereference() { sizes.pop_front(); }
     void copyDereferenced(const TArraySizes& rhs)
     void copyDereferenced(const TArraySizes& rhs)
     {
     {
@@ -311,6 +315,9 @@ struct TArraySizes {
         return true;
         return true;
     }
     }
 
 
+    void setVariablyIndexed() { variablyIndexed = true; }
+    bool isVariablyIndexed() const { return variablyIndexed; }
+
     bool operator==(const TArraySizes& rhs) { return sizes == rhs.sizes; }
     bool operator==(const TArraySizes& rhs) { return sizes == rhs.sizes; }
     bool operator!=(const TArraySizes& rhs) { return sizes != rhs.sizes; }
     bool operator!=(const TArraySizes& rhs) { return sizes != rhs.sizes; }
 
 
@@ -319,9 +326,12 @@ protected:
 
 
     TArraySizes(const TArraySizes&);
     TArraySizes(const TArraySizes&);
 
 
-    // for tracking maximum referenced index, before an explicit size is given
-    // applies only to the outer-most dimension
+    // For tracking maximum referenced compile-time constant index.
+    // Applies only to the outer-most dimension. Potentially becomes
+    // the implicit size of the array, if not variably indexed and
+    // otherwise legal.
     int implicitArraySize;
     int implicitArraySize;
+    bool variablyIndexed;  // true if array is indexed with a non compile-time constant
 };
 };
 
 
 } // end namespace glslang
 } // end namespace glslang

+ 374 - 135
src/libraries/glslang/glslang/Include/intermediate.h

@@ -1,6 +1,7 @@
 //
 //
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2012-2016 LunarG, Inc.
 // Copyright (C) 2012-2016 LunarG, Inc.
+// Copyright (C) 2017 ARM Limited.
 //
 //
 // All rights reserved.
 // All rights reserved.
 //
 //
@@ -46,7 +47,7 @@
 #ifndef __INTERMEDIATE_H
 #ifndef __INTERMEDIATE_H
 #define __INTERMEDIATE_H
 #define __INTERMEDIATE_H
 
 
-#if _MSC_VER >= 1900
+#if defined(_MSC_VER) && _MSC_VER >= 1900
     #pragma warning(disable : 4464) // relative include path contains '..'
     #pragma warning(disable : 4464) // relative include path contains '..'
     #pragma warning(disable : 5026) // 'glslang::TIntermUnary': move constructor was implicitly defined as deleted
     #pragma warning(disable : 5026) // 'glslang::TIntermUnary': move constructor was implicitly defined as deleted
 #endif
 #endif
@@ -84,100 +85,189 @@ enum TOperator {
     EOpPreIncrement,
     EOpPreIncrement,
     EOpPreDecrement,
     EOpPreDecrement,
 
 
+    // (u)int* -> bool
+    EOpConvInt8ToBool,
+    EOpConvUint8ToBool,
+    EOpConvInt16ToBool,
+    EOpConvUint16ToBool,
     EOpConvIntToBool,
     EOpConvIntToBool,
     EOpConvUintToBool,
     EOpConvUintToBool,
-    EOpConvFloatToBool,
-    EOpConvDoubleToBool,
     EOpConvInt64ToBool,
     EOpConvInt64ToBool,
     EOpConvUint64ToBool,
     EOpConvUint64ToBool,
-    EOpConvBoolToFloat,
-    EOpConvIntToFloat,
-    EOpConvUintToFloat,
-    EOpConvDoubleToFloat,
-    EOpConvInt64ToFloat,
-    EOpConvUint64ToFloat,
-    EOpConvUintToInt,
-    EOpConvFloatToInt,
+
+    // float* -> bool
+    EOpConvFloat16ToBool,
+    EOpConvFloatToBool,
+    EOpConvDoubleToBool,
+
+    // bool -> (u)int*
+    EOpConvBoolToInt8,
+    EOpConvBoolToUint8,
+    EOpConvBoolToInt16,
+    EOpConvBoolToUint16,
     EOpConvBoolToInt,
     EOpConvBoolToInt,
-    EOpConvDoubleToInt,
-    EOpConvInt64ToInt,
-    EOpConvUint64ToInt,
-    EOpConvIntToUint,
-    EOpConvFloatToUint,
     EOpConvBoolToUint,
     EOpConvBoolToUint,
-    EOpConvDoubleToUint,
-    EOpConvInt64ToUint,
-    EOpConvUint64ToUint,
-    EOpConvIntToDouble,
-    EOpConvUintToDouble,
-    EOpConvFloatToDouble,
-    EOpConvBoolToDouble,
-    EOpConvInt64ToDouble,
-    EOpConvUint64ToDouble,
     EOpConvBoolToInt64,
     EOpConvBoolToInt64,
-    EOpConvIntToInt64,
-    EOpConvUintToInt64,
-    EOpConvFloatToInt64,
-    EOpConvDoubleToInt64,
-    EOpConvUint64ToInt64,
     EOpConvBoolToUint64,
     EOpConvBoolToUint64,
+
+    // bool -> float*
+    EOpConvBoolToFloat16,
+    EOpConvBoolToFloat,
+    EOpConvBoolToDouble,
+
+    // int8_t -> (u)int*
+    EOpConvInt8ToInt16,
+    EOpConvInt8ToInt,
+    EOpConvInt8ToInt64,
+    EOpConvInt8ToUint8,
+    EOpConvInt8ToUint16,
+    EOpConvInt8ToUint,
+    EOpConvInt8ToUint64,
+
+    // uint8_t -> (u)int*
+    EOpConvUint8ToInt8,
+    EOpConvUint8ToInt16,
+    EOpConvUint8ToInt,
+    EOpConvUint8ToInt64,
+    EOpConvUint8ToUint16,
+    EOpConvUint8ToUint,
+    EOpConvUint8ToUint64,
+
+    // int8_t -> float*
+    EOpConvInt8ToFloat16,
+    EOpConvInt8ToFloat,
+    EOpConvInt8ToDouble,
+
+    // uint8_t -> float*
+    EOpConvUint8ToFloat16,
+    EOpConvUint8ToFloat,
+    EOpConvUint8ToDouble,
+
+    // int16_t -> (u)int*
+    EOpConvInt16ToInt8,
+    EOpConvInt16ToInt,
+    EOpConvInt16ToInt64,
+    EOpConvInt16ToUint8,
+    EOpConvInt16ToUint16,
+    EOpConvInt16ToUint,
+    EOpConvInt16ToUint64,
+
+    // uint16_t -> (u)int*
+    EOpConvUint16ToInt8,
+    EOpConvUint16ToInt16,
+    EOpConvUint16ToInt,
+    EOpConvUint16ToInt64,
+    EOpConvUint16ToUint8,
+    EOpConvUint16ToUint,
+    EOpConvUint16ToUint64,
+
+    // int16_t -> float*
+    EOpConvInt16ToFloat16,
+    EOpConvInt16ToFloat,
+    EOpConvInt16ToDouble,
+
+    // uint16_t -> float*
+    EOpConvUint16ToFloat16,
+    EOpConvUint16ToFloat,
+    EOpConvUint16ToDouble,
+
+    // int32_t -> (u)int*
+    EOpConvIntToInt8,
+    EOpConvIntToInt16,
+    EOpConvIntToInt64,
+    EOpConvIntToUint8,
+    EOpConvIntToUint16,
+    EOpConvIntToUint,
     EOpConvIntToUint64,
     EOpConvIntToUint64,
+
+    // uint32_t -> (u)int*
+    EOpConvUintToInt8,
+    EOpConvUintToInt16,
+    EOpConvUintToInt,
+    EOpConvUintToInt64,
+    EOpConvUintToUint8,
+    EOpConvUintToUint16,
     EOpConvUintToUint64,
     EOpConvUintToUint64,
-    EOpConvFloatToUint64,
-    EOpConvDoubleToUint64,
-    EOpConvInt64ToUint64,
-#ifdef AMD_EXTENSIONS
-    EOpConvBoolToFloat16,
+
+    // int32_t -> float*
     EOpConvIntToFloat16,
     EOpConvIntToFloat16,
+    EOpConvIntToFloat,
+    EOpConvIntToDouble,
+
+    // uint32_t -> float*
     EOpConvUintToFloat16,
     EOpConvUintToFloat16,
-    EOpConvFloatToFloat16,
-    EOpConvDoubleToFloat16,
+    EOpConvUintToFloat,
+    EOpConvUintToDouble,
+
+    // int64_t -> (u)int*
+    EOpConvInt64ToInt8,
+    EOpConvInt64ToInt16,
+    EOpConvInt64ToInt,
+    EOpConvInt64ToUint8,
+    EOpConvInt64ToUint16,
+    EOpConvInt64ToUint,
+    EOpConvInt64ToUint64,
+
+    // uint64_t -> (u)int*
+    EOpConvUint64ToInt8,
+    EOpConvUint64ToInt16,
+    EOpConvUint64ToInt,
+    EOpConvUint64ToInt64,
+    EOpConvUint64ToUint8,
+    EOpConvUint64ToUint16,
+    EOpConvUint64ToUint,
+
+    // int64_t -> float*
     EOpConvInt64ToFloat16,
     EOpConvInt64ToFloat16,
+    EOpConvInt64ToFloat,
+    EOpConvInt64ToDouble,
+
+    // uint64_t -> float*
     EOpConvUint64ToFloat16,
     EOpConvUint64ToFloat16,
-    EOpConvFloat16ToBool,
+    EOpConvUint64ToFloat,
+    EOpConvUint64ToDouble,
+
+    // float16_t -> (u)int*
+    EOpConvFloat16ToInt8,
+    EOpConvFloat16ToInt16,
     EOpConvFloat16ToInt,
     EOpConvFloat16ToInt,
+    EOpConvFloat16ToInt64,
+    EOpConvFloat16ToUint8,
+    EOpConvFloat16ToUint16,
     EOpConvFloat16ToUint,
     EOpConvFloat16ToUint,
+    EOpConvFloat16ToUint64,
+
+    // float16_t -> float*
     EOpConvFloat16ToFloat,
     EOpConvFloat16ToFloat,
     EOpConvFloat16ToDouble,
     EOpConvFloat16ToDouble,
-    EOpConvFloat16ToInt64,
-    EOpConvFloat16ToUint64,
 
 
-    EOpConvBoolToInt16,
-    EOpConvIntToInt16,
-    EOpConvUintToInt16,
+    // float -> (u)int*
+    EOpConvFloatToInt8,
     EOpConvFloatToInt16,
     EOpConvFloatToInt16,
-    EOpConvDoubleToInt16,
-    EOpConvFloat16ToInt16,
-    EOpConvInt64ToInt16,
-    EOpConvUint64ToInt16,
-    EOpConvUint16ToInt16,
-    EOpConvInt16ToBool,
-    EOpConvInt16ToInt,
-    EOpConvInt16ToUint,
-    EOpConvInt16ToFloat,
-    EOpConvInt16ToDouble,
-    EOpConvInt16ToFloat16,
-    EOpConvInt16ToInt64,
-    EOpConvInt16ToUint64,
-
-    EOpConvBoolToUint16,
-    EOpConvIntToUint16,
-    EOpConvUintToUint16,
+    EOpConvFloatToInt,
+    EOpConvFloatToInt64,
+    EOpConvFloatToUint8,
     EOpConvFloatToUint16,
     EOpConvFloatToUint16,
+    EOpConvFloatToUint,
+    EOpConvFloatToUint64,
+
+    // float -> float*
+    EOpConvFloatToFloat16,
+    EOpConvFloatToDouble,
+
+    // float64 _t-> (u)int*
+    EOpConvDoubleToInt8,
+    EOpConvDoubleToInt16,
+    EOpConvDoubleToInt,
+    EOpConvDoubleToInt64,
+    EOpConvDoubleToUint8,
     EOpConvDoubleToUint16,
     EOpConvDoubleToUint16,
-    EOpConvFloat16ToUint16,
-    EOpConvInt64ToUint16,
-    EOpConvUint64ToUint16,
-    EOpConvInt16ToUint16,
-    EOpConvUint16ToBool,
-    EOpConvUint16ToInt,
-    EOpConvUint16ToUint,
-    EOpConvUint16ToFloat,
-    EOpConvUint16ToDouble,
-    EOpConvUint16ToFloat16,
-    EOpConvUint16ToInt64,
-    EOpConvUint16ToUint64,
-#endif
+    EOpConvDoubleToUint,
+    EOpConvDoubleToUint64,
+
+    // float64_t -> float*
+    EOpConvDoubleToFloat16,
+    EOpConvDoubleToFloat,
 
 
     //
     //
     // binary operations
     // binary operations
@@ -280,12 +370,10 @@ enum TOperator {
     EOpDoubleBitsToUint64,
     EOpDoubleBitsToUint64,
     EOpInt64BitsToDouble,
     EOpInt64BitsToDouble,
     EOpUint64BitsToDouble,
     EOpUint64BitsToDouble,
-#ifdef AMD_EXTENSIONS
     EOpFloat16BitsToInt16,
     EOpFloat16BitsToInt16,
     EOpFloat16BitsToUint16,
     EOpFloat16BitsToUint16,
     EOpInt16BitsToFloat16,
     EOpInt16BitsToFloat16,
     EOpUint16BitsToFloat16,
     EOpUint16BitsToFloat16,
-#endif
     EOpPackSnorm2x16,
     EOpPackSnorm2x16,
     EOpUnpackSnorm2x16,
     EOpUnpackSnorm2x16,
     EOpPackUnorm2x16,
     EOpPackUnorm2x16,
@@ -302,7 +390,6 @@ enum TOperator {
     EOpUnpackInt2x32,
     EOpUnpackInt2x32,
     EOpPackUint2x32,
     EOpPackUint2x32,
     EOpUnpackUint2x32,
     EOpUnpackUint2x32,
-#ifdef AMD_EXTENSIONS
     EOpPackFloat2x16,
     EOpPackFloat2x16,
     EOpUnpackFloat2x16,
     EOpUnpackFloat2x16,
     EOpPackInt2x16,
     EOpPackInt2x16,
@@ -313,7 +400,12 @@ enum TOperator {
     EOpUnpackInt4x16,
     EOpUnpackInt4x16,
     EOpPackUint4x16,
     EOpPackUint4x16,
     EOpUnpackUint4x16,
     EOpUnpackUint4x16,
-#endif
+    EOpPack16,
+    EOpPack32,
+    EOpPack64,
+    EOpUnpack32,
+    EOpUnpack16,
+    EOpUnpack8,
 
 
     EOpLength,
     EOpLength,
     EOpDistance,
     EOpDistance,
@@ -379,6 +471,90 @@ enum TOperator {
     EOpAllInvocations,
     EOpAllInvocations,
     EOpAllInvocationsEqual,
     EOpAllInvocationsEqual,
 
 
+    EOpSubgroupGuardStart,
+    EOpSubgroupBarrier,
+    EOpSubgroupMemoryBarrier,
+    EOpSubgroupMemoryBarrierBuffer,
+    EOpSubgroupMemoryBarrierImage,
+    EOpSubgroupMemoryBarrierShared, // compute only
+    EOpSubgroupElect,
+    EOpSubgroupAll,
+    EOpSubgroupAny,
+    EOpSubgroupAllEqual,
+    EOpSubgroupBroadcast,
+    EOpSubgroupBroadcastFirst,
+    EOpSubgroupBallot,
+    EOpSubgroupInverseBallot,
+    EOpSubgroupBallotBitExtract,
+    EOpSubgroupBallotBitCount,
+    EOpSubgroupBallotInclusiveBitCount,
+    EOpSubgroupBallotExclusiveBitCount,
+    EOpSubgroupBallotFindLSB,
+    EOpSubgroupBallotFindMSB,
+    EOpSubgroupShuffle,
+    EOpSubgroupShuffleXor,
+    EOpSubgroupShuffleUp,
+    EOpSubgroupShuffleDown,
+    EOpSubgroupAdd,
+    EOpSubgroupMul,
+    EOpSubgroupMin,
+    EOpSubgroupMax,
+    EOpSubgroupAnd,
+    EOpSubgroupOr,
+    EOpSubgroupXor,
+    EOpSubgroupInclusiveAdd,
+    EOpSubgroupInclusiveMul,
+    EOpSubgroupInclusiveMin,
+    EOpSubgroupInclusiveMax,
+    EOpSubgroupInclusiveAnd,
+    EOpSubgroupInclusiveOr,
+    EOpSubgroupInclusiveXor,
+    EOpSubgroupExclusiveAdd,
+    EOpSubgroupExclusiveMul,
+    EOpSubgroupExclusiveMin,
+    EOpSubgroupExclusiveMax,
+    EOpSubgroupExclusiveAnd,
+    EOpSubgroupExclusiveOr,
+    EOpSubgroupExclusiveXor,
+    EOpSubgroupClusteredAdd,
+    EOpSubgroupClusteredMul,
+    EOpSubgroupClusteredMin,
+    EOpSubgroupClusteredMax,
+    EOpSubgroupClusteredAnd,
+    EOpSubgroupClusteredOr,
+    EOpSubgroupClusteredXor,
+    EOpSubgroupQuadBroadcast,
+    EOpSubgroupQuadSwapHorizontal,
+    EOpSubgroupQuadSwapVertical,
+    EOpSubgroupQuadSwapDiagonal,
+
+#ifdef NV_EXTENSIONS
+    EOpSubgroupPartition,
+    EOpSubgroupPartitionedAdd,
+    EOpSubgroupPartitionedMul,
+    EOpSubgroupPartitionedMin,
+    EOpSubgroupPartitionedMax,
+    EOpSubgroupPartitionedAnd,
+    EOpSubgroupPartitionedOr,
+    EOpSubgroupPartitionedXor,
+    EOpSubgroupPartitionedInclusiveAdd,
+    EOpSubgroupPartitionedInclusiveMul,
+    EOpSubgroupPartitionedInclusiveMin,
+    EOpSubgroupPartitionedInclusiveMax,
+    EOpSubgroupPartitionedInclusiveAnd,
+    EOpSubgroupPartitionedInclusiveOr,
+    EOpSubgroupPartitionedInclusiveXor,
+    EOpSubgroupPartitionedExclusiveAdd,
+    EOpSubgroupPartitionedExclusiveMul,
+    EOpSubgroupPartitionedExclusiveMin,
+    EOpSubgroupPartitionedExclusiveMax,
+    EOpSubgroupPartitionedExclusiveAnd,
+    EOpSubgroupPartitionedExclusiveOr,
+    EOpSubgroupPartitionedExclusiveXor,
+#endif
+
+    EOpSubgroupGuardStop,
+
 #ifdef AMD_EXTENSIONS
 #ifdef AMD_EXTENSIONS
     EOpMinInvocations,
     EOpMinInvocations,
     EOpMaxInvocations,
     EOpMaxInvocations,
@@ -416,6 +592,8 @@ enum TOperator {
     EOpAtomicXor,
     EOpAtomicXor,
     EOpAtomicExchange,
     EOpAtomicExchange,
     EOpAtomicCompSwap,
     EOpAtomicCompSwap,
+    EOpAtomicLoad,
+    EOpAtomicStore,
 
 
     EOpAtomicCounterIncrement, // results in pre-increment value
     EOpAtomicCounterIncrement, // results in pre-increment value
     EOpAtomicCounterDecrement, // results in post-decrement value
     EOpAtomicCounterDecrement, // results in post-decrement value
@@ -451,32 +629,36 @@ enum TOperator {
     EOpConstructGuardStart,
     EOpConstructGuardStart,
     EOpConstructInt,          // these first scalar forms also identify what implicit conversion is needed
     EOpConstructInt,          // these first scalar forms also identify what implicit conversion is needed
     EOpConstructUint,
     EOpConstructUint,
-    EOpConstructInt64,
-    EOpConstructUint64,
-#ifdef AMD_EXTENSIONS
+    EOpConstructInt8,
+    EOpConstructUint8,
     EOpConstructInt16,
     EOpConstructInt16,
     EOpConstructUint16,
     EOpConstructUint16,
-#endif
+    EOpConstructInt64,
+    EOpConstructUint64,
     EOpConstructBool,
     EOpConstructBool,
     EOpConstructFloat,
     EOpConstructFloat,
     EOpConstructDouble,
     EOpConstructDouble,
-#ifdef AMD_EXTENSIONS
-    EOpConstructFloat16,
-#endif
     EOpConstructVec2,
     EOpConstructVec2,
     EOpConstructVec3,
     EOpConstructVec3,
     EOpConstructVec4,
     EOpConstructVec4,
     EOpConstructDVec2,
     EOpConstructDVec2,
     EOpConstructDVec3,
     EOpConstructDVec3,
     EOpConstructDVec4,
     EOpConstructDVec4,
-#ifdef AMD_EXTENSIONS
-    EOpConstructF16Vec2,
-    EOpConstructF16Vec3,
-    EOpConstructF16Vec4,
-#endif
     EOpConstructBVec2,
     EOpConstructBVec2,
     EOpConstructBVec3,
     EOpConstructBVec3,
     EOpConstructBVec4,
     EOpConstructBVec4,
+    EOpConstructI8Vec2,
+    EOpConstructI8Vec3,
+    EOpConstructI8Vec4,
+    EOpConstructU8Vec2,
+    EOpConstructU8Vec3,
+    EOpConstructU8Vec4,
+    EOpConstructI16Vec2,
+    EOpConstructI16Vec3,
+    EOpConstructI16Vec4,
+    EOpConstructU16Vec2,
+    EOpConstructU16Vec3,
+    EOpConstructU16Vec4,
     EOpConstructIVec2,
     EOpConstructIVec2,
     EOpConstructIVec3,
     EOpConstructIVec3,
     EOpConstructIVec4,
     EOpConstructIVec4,
@@ -489,14 +671,6 @@ enum TOperator {
     EOpConstructU64Vec2,
     EOpConstructU64Vec2,
     EOpConstructU64Vec3,
     EOpConstructU64Vec3,
     EOpConstructU64Vec4,
     EOpConstructU64Vec4,
-#ifdef AMD_EXTENSIONS
-    EOpConstructI16Vec2,
-    EOpConstructI16Vec3,
-    EOpConstructI16Vec4,
-    EOpConstructU16Vec2,
-    EOpConstructU16Vec3,
-    EOpConstructU16Vec4,
-#endif
     EOpConstructMat2x2,
     EOpConstructMat2x2,
     EOpConstructMat2x3,
     EOpConstructMat2x3,
     EOpConstructMat2x4,
     EOpConstructMat2x4,
@@ -542,7 +716,10 @@ enum TOperator {
     EOpConstructBMat4x2,
     EOpConstructBMat4x2,
     EOpConstructBMat4x3,
     EOpConstructBMat4x3,
     EOpConstructBMat4x4,
     EOpConstructBMat4x4,
-#ifdef AMD_EXTENSIONS
+    EOpConstructFloat16,
+    EOpConstructF16Vec2,
+    EOpConstructF16Vec3,
+    EOpConstructF16Vec4,
     EOpConstructF16Mat2x2,
     EOpConstructF16Mat2x2,
     EOpConstructF16Mat2x3,
     EOpConstructF16Mat2x3,
     EOpConstructF16Mat2x4,
     EOpConstructF16Mat2x4,
@@ -552,9 +729,9 @@ enum TOperator {
     EOpConstructF16Mat4x2,
     EOpConstructF16Mat4x2,
     EOpConstructF16Mat4x3,
     EOpConstructF16Mat4x3,
     EOpConstructF16Mat4x4,
     EOpConstructF16Mat4x4,
-#endif
     EOpConstructStruct,
     EOpConstructStruct,
     EOpConstructTextureSampler,
     EOpConstructTextureSampler,
+    EOpConstructNonuniform,     // expected to be transformed away, not present in final AST
     EOpConstructGuardEnd,
     EOpConstructGuardEnd,
 
 
     //
     //
@@ -581,7 +758,11 @@ enum TOperator {
     // Array operators
     // Array operators
     //
     //
 
 
-    EOpArrayLength,      // "Array" distinguishes from length(v) built-in function, but it applies to vectors and matrices as well.
+    // Can apply to arrays, vectors, or matrices.
+    // Can be decomposed to a constant at compile time, but this does not always happen,
+    // due to link-time effects. So, consumer can expect either a link-time sized or
+    // run-time sized array.
+    EOpArrayLength,
 
 
     //
     //
     // Image operations
     // Image operations
@@ -605,6 +786,8 @@ enum TOperator {
     EOpImageAtomicXor,
     EOpImageAtomicXor,
     EOpImageAtomicExchange,
     EOpImageAtomicExchange,
     EOpImageAtomicCompSwap,
     EOpImageAtomicCompSwap,
+    EOpImageAtomicLoad,
+    EOpImageAtomicStore,
 
 
     EOpSubpassLoad,
     EOpSubpassLoad,
     EOpSubpassLoadMS,
     EOpSubpassLoadMS,
@@ -682,6 +865,16 @@ enum TOperator {
 #endif
 #endif
 
 
     EOpSparseTextureGuardEnd,
     EOpSparseTextureGuardEnd,
+
+#ifdef NV_EXTENSIONS
+    EOpImageFootprintGuardBegin,
+    EOpImageSampleFootprintNV,
+    EOpImageSampleFootprintClampNV,
+    EOpImageSampleFootprintLodNV,
+    EOpImageSampleFootprintGradNV,
+    EOpImageSampleFootprintGradClampNV,
+    EOpImageFootprintGuardEnd,
+#endif
     EOpSamplingGuardEnd,
     EOpSamplingGuardEnd,
     EOpTextureGuardEnd,
     EOpTextureGuardEnd,
 
 
@@ -700,6 +893,14 @@ enum TOperator {
     EOpFindLSB,
     EOpFindLSB,
     EOpFindMSB,
     EOpFindMSB,
 
 
+#ifdef NV_EXTENSIONS
+    EOpTraceNV,
+    EOpReportIntersectionNV,
+    EOpIgnoreIntersectionNV,
+    EOpTerminateRayNV,
+    EOpExecuteCallableNV,
+    EOpWritePackedPrimitiveIndices4x8NV,
+#endif
     //
     //
     // HLSL operations
     // HLSL operations
     //
     //
@@ -777,6 +978,12 @@ enum TOperator {
 
 
     // matrix
     // matrix
     EOpMatrixSwizzle,                    // select multiple matrix components (non-column)
     EOpMatrixSwizzle,                    // select multiple matrix components (non-column)
+
+    // SM6 wave ops
+    EOpWaveGetLaneCount,                 // Will decompose to gl_SubgroupSize.
+    EOpWaveGetLaneIndex,                 // Will decompose to gl_SubgroupInvocationID.
+    EOpWaveActiveCountBits,              // Will decompose to subgroupBallotBitCount(subgroupBallot()).
+    EOpWavePrefixCountBits,              // Will decompose to subgroupBallotInclusiveBitCount(subgroupBallot()).
 };
 };
 
 
 class TIntermTraverser;
 class TIntermTraverser;
@@ -819,7 +1026,7 @@ public:
     virtual       glslang::TIntermMethod*        getAsMethodNode()          { return 0; }
     virtual       glslang::TIntermMethod*        getAsMethodNode()          { return 0; }
     virtual       glslang::TIntermSymbol*        getAsSymbolNode()          { return 0; }
     virtual       glslang::TIntermSymbol*        getAsSymbolNode()          { return 0; }
     virtual       glslang::TIntermBranch*        getAsBranchNode()          { return 0; }
     virtual       glslang::TIntermBranch*        getAsBranchNode()          { return 0; }
-	virtual       glslang::TIntermLoop*          getAsLoopNode()            { return 0; }
+    virtual       glslang::TIntermLoop*          getAsLoopNode()            { return 0; }
 
 
     virtual const glslang::TIntermTyped*         getAsTyped()         const { return 0; }
     virtual const glslang::TIntermTyped*         getAsTyped()         const { return 0; }
     virtual const glslang::TIntermOperator*      getAsOperator()      const { return 0; }
     virtual const glslang::TIntermOperator*      getAsOperator()      const { return 0; }
@@ -832,7 +1039,7 @@ public:
     virtual const glslang::TIntermMethod*        getAsMethodNode()    const { return 0; }
     virtual const glslang::TIntermMethod*        getAsMethodNode()    const { return 0; }
     virtual const glslang::TIntermSymbol*        getAsSymbolNode()    const { return 0; }
     virtual const glslang::TIntermSymbol*        getAsSymbolNode()    const { return 0; }
     virtual const glslang::TIntermBranch*        getAsBranchNode()    const { return 0; }
     virtual const glslang::TIntermBranch*        getAsBranchNode()    const { return 0; }
-	virtual const glslang::TIntermLoop*          getAsLoopNode()      const { return 0; }
+    virtual const glslang::TIntermLoop*          getAsLoopNode()      const { return 0; }
     virtual ~TIntermNode() { }
     virtual ~TIntermNode() { }
 
 
 protected:
 protected:
@@ -885,24 +1092,6 @@ protected:
     TType type;
     TType type;
 };
 };
 
 
-//
-// Selection control hints
-//
-enum TSelectionControl {
-    ESelectionControlNone,
-    ESelectionControlFlatten,
-    ESelectionControlDontFlatten,
-};
-
-//
-// Loop control hints
-//
-enum TLoopControl {
-    ELoopControlNone,
-    ELoopControlUnroll,
-    ELoopControlDontUnroll,
-};
-
 //
 //
 // Handle for, do-while, and while loops.
 // Handle for, do-while, and while loops.
 //
 //
@@ -913,26 +1102,36 @@ public:
         test(aTest),
         test(aTest),
         terminal(aTerminal),
         terminal(aTerminal),
         first(testFirst),
         first(testFirst),
-        control(ELoopControlNone)
+        unroll(false),
+        dontUnroll(false),
+        dependency(0)
     { }
     { }
 
 
-	virtual       TIntermLoop* getAsLoopNode() { return this; }
-	virtual const TIntermLoop* getAsLoopNode() const { return this; }
+    virtual       TIntermLoop* getAsLoopNode() { return this; }
+    virtual const TIntermLoop* getAsLoopNode() const { return this; }
     virtual void traverse(TIntermTraverser*);
     virtual void traverse(TIntermTraverser*);
     TIntermNode*  getBody() const { return body; }
     TIntermNode*  getBody() const { return body; }
     TIntermTyped* getTest() const { return test; }
     TIntermTyped* getTest() const { return test; }
     TIntermTyped* getTerminal() const { return terminal; }
     TIntermTyped* getTerminal() const { return terminal; }
     bool testFirst() const { return first; }
     bool testFirst() const { return first; }
 
 
-    void setLoopControl(TLoopControl c) { control = c; }
-    TLoopControl getLoopControl() const { return control; }
+    void setUnroll()     { unroll = true; }
+    void setDontUnroll() { dontUnroll = true; }
+    bool getUnroll()     const { return unroll; }
+    bool getDontUnroll() const { return dontUnroll; }
+
+    static const unsigned int dependencyInfinite = 0xFFFFFFFF;
+    void setLoopDependency(int d) { dependency = d; }
+    int getLoopDependency() const { return dependency; }
 
 
 protected:
 protected:
     TIntermNode* body;       // code to loop over
     TIntermNode* body;       // code to loop over
     TIntermTyped* test;      // exit condition associated with loop, could be 0 for 'for' loops
     TIntermTyped* test;      // exit condition associated with loop, could be 0 for 'for' loops
     TIntermTyped* terminal;  // exists for for-loops
     TIntermTyped* terminal;  // exists for for-loops
     bool first;              // true for while and for, not for do-while
     bool first;              // true for while and for, not for do-while
-    TLoopControl control;    // loop control hint
+    bool unroll;             // true if unroll requested
+    bool dontUnroll;         // true if request to not unroll
+    unsigned int dependency; // loop dependency hint; 0 means not set or unknown
 };
 };
 
 
 //
 //
@@ -987,6 +1186,7 @@ public:
         constSubtree(nullptr)
         constSubtree(nullptr)
           { name = n; }
           { name = n; }
     virtual int getId() const { return id; }
     virtual int getId() const { return id; }
+    virtual void changeId(int i) { id = i; }
     virtual const TString& getName() const { return name; }
     virtual const TString& getName() const { return name; }
     virtual void traverse(TIntermTraverser*);
     virtual void traverse(TIntermTraverser*);
     virtual       TIntermSymbol* getAsSymbolNode()       { return this; }
     virtual       TIntermSymbol* getAsSymbolNode()       { return this; }
@@ -1066,6 +1266,9 @@ public:
     bool isSampling() const { return op > EOpSamplingGuardBegin && op < EOpSamplingGuardEnd; }
     bool isSampling() const { return op > EOpSamplingGuardBegin && op < EOpSamplingGuardEnd; }
     bool isImage()    const { return op > EOpImageGuardBegin    && op < EOpImageGuardEnd; }
     bool isImage()    const { return op > EOpImageGuardBegin    && op < EOpImageGuardEnd; }
     bool isSparseTexture() const { return op > EOpSparseTextureGuardBegin && op < EOpSparseTextureGuardEnd; }
     bool isSparseTexture() const { return op > EOpSparseTextureGuardBegin && op < EOpSparseTextureGuardEnd; }
+#ifdef NV_EXTENSIONS
+    bool isImageFootprint() const { return op > EOpImageFootprintGuardBegin && op < EOpImageFootprintGuardEnd; }
+#endif
     bool isSparseImage()   const { return op == EOpSparseImageLoad; }
     bool isSparseImage()   const { return op == EOpSparseImageLoad; }
 
 
     void setOperationPrecision(TPrecisionQualifier p) { operationPrecision = p; }
     void setOperationPrecision(TPrecisionQualifier p) { operationPrecision = p; }
@@ -1238,6 +1441,23 @@ public:
             cracked.subpass = sampler.dim == EsdSubpass;
             cracked.subpass = sampler.dim == EsdSubpass;
             cracked.fragMask = true;
             cracked.fragMask = true;
             break;
             break;
+#endif
+#ifdef NV_EXTENSIONS
+        case EOpImageSampleFootprintNV:
+            break;
+        case EOpImageSampleFootprintClampNV:
+            cracked.lodClamp = true;
+            break;
+        case EOpImageSampleFootprintLodNV:
+            cracked.lod = true;
+            break;
+        case EOpImageSampleFootprintGradNV:
+            cracked.grad = true;
+            break;
+        case EOpImageSampleFootprintGradClampNV:
+            cracked.lodClamp = true;
+            cracked.grad = true;
+            break;
 #endif
 #endif
         case EOpSubpassLoad:
         case EOpSubpassLoad:
         case EOpSubpassLoadMS:
         case EOpSubpassLoadMS:
@@ -1343,22 +1563,35 @@ protected:
 class TIntermSelection : public TIntermTyped {
 class TIntermSelection : public TIntermTyped {
 public:
 public:
     TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) :
     TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) :
-        TIntermTyped(EbtVoid), condition(cond), trueBlock(trueB), falseBlock(falseB), control(ESelectionControlNone) {}
+        TIntermTyped(EbtVoid), condition(cond), trueBlock(trueB), falseBlock(falseB),
+        shortCircuit(true),
+        flatten(false), dontFlatten(false) {}
     TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) :
     TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) :
-        TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB), control(ESelectionControlNone) {}
+        TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB),
+        shortCircuit(true),
+        flatten(false), dontFlatten(false) {}
     virtual void traverse(TIntermTraverser*);
     virtual void traverse(TIntermTraverser*);
     virtual TIntermTyped* getCondition() const { return condition; }
     virtual TIntermTyped* getCondition() const { return condition; }
     virtual TIntermNode* getTrueBlock() const { return trueBlock; }
     virtual TIntermNode* getTrueBlock() const { return trueBlock; }
     virtual TIntermNode* getFalseBlock() const { return falseBlock; }
     virtual TIntermNode* getFalseBlock() const { return falseBlock; }
     virtual       TIntermSelection* getAsSelectionNode()       { return this; }
     virtual       TIntermSelection* getAsSelectionNode()       { return this; }
     virtual const TIntermSelection* getAsSelectionNode() const { return this; }
     virtual const TIntermSelection* getAsSelectionNode() const { return this; }
-    void setSelectionControl(TSelectionControl c) { control = c; }
-    TSelectionControl getSelectionControl() const { return control; }
+
+    void setNoShortCircuit() { shortCircuit = false; }
+    bool getShortCircuit() const { return shortCircuit; }
+
+    void setFlatten()     { flatten = true; }
+    void setDontFlatten() { dontFlatten = true; }
+    bool getFlatten()     const { return flatten; }
+    bool getDontFlatten() const { return dontFlatten; }
+
 protected:
 protected:
     TIntermTyped* condition;
     TIntermTyped* condition;
     TIntermNode* trueBlock;
     TIntermNode* trueBlock;
     TIntermNode* falseBlock;
     TIntermNode* falseBlock;
-    TSelectionControl control;    // selection control hint
+    bool shortCircuit; // normally all if-then-else and all GLSL ?: short-circuit, but HLSL ?: does not
+    bool flatten;      // true if flatten requested
+    bool dontFlatten;  // true if requested to not flatten
 };
 };
 
 
 //
 //
@@ -1369,18 +1602,24 @@ protected:
 //
 //
 class TIntermSwitch : public TIntermNode {
 class TIntermSwitch : public TIntermNode {
 public:
 public:
-    TIntermSwitch(TIntermTyped* cond, TIntermAggregate* b) : condition(cond), body(b), control(ESelectionControlNone) { }
+    TIntermSwitch(TIntermTyped* cond, TIntermAggregate* b) : condition(cond), body(b),
+        flatten(false), dontFlatten(false) {}
     virtual void traverse(TIntermTraverser*);
     virtual void traverse(TIntermTraverser*);
     virtual TIntermNode* getCondition() const { return condition; }
     virtual TIntermNode* getCondition() const { return condition; }
     virtual TIntermAggregate* getBody() const { return body; }
     virtual TIntermAggregate* getBody() const { return body; }
     virtual       TIntermSwitch* getAsSwitchNode()       { return this; }
     virtual       TIntermSwitch* getAsSwitchNode()       { return this; }
     virtual const TIntermSwitch* getAsSwitchNode() const { return this; }
     virtual const TIntermSwitch* getAsSwitchNode() const { return this; }
-    void setSelectionControl(TSelectionControl c) { control = c; }
-    TSelectionControl getSelectionControl() const { return control; }
+
+    void setFlatten()     { flatten = true; }
+    void setDontFlatten() { dontFlatten = true; }
+    bool getFlatten()     const { return flatten; }
+    bool getDontFlatten() const { return dontFlatten; }
+
 protected:
 protected:
     TIntermTyped* condition;
     TIntermTyped* condition;
     TIntermAggregate* body;
     TIntermAggregate* body;
-    TSelectionControl control;    // selection control hint
+    bool flatten;     // true if flatten requested
+    bool dontFlatten; // true if requested to not flatten
 };
 };
 
 
 enum TVisit
 enum TVisit

+ 1 - 4
src/libraries/glslang/glslang/Include/revision.h

@@ -1,6 +1,3 @@
 // This header is generated by the make-revision script.
 // This header is generated by the make-revision script.
-// For the version, it uses the latest git tag followed by the number of commits.
-// For the date, it uses the current date (when then script is run).
 
 
-#define GLSLANG_REVISION "Overload400-PrecQual.2000"
-#define GLSLANG_DATE "12-Apr-2017"
+#define GLSLANG_PATCH_LEVEL 3009

+ 435 - 89
src/libraries/glslang/glslang/MachineIndependent/Constant.cpp

@@ -1,6 +1,8 @@
 //
 //
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2012-2013 LunarG, Inc.
 // Copyright (C) 2012-2013 LunarG, Inc.
+// Copyright (C) 2017 ARM Limited.
+// Copyright (C) 2018 Google, Inc.
 //
 //
 // All rights reserved.
 // All rights reserved.
 //
 //
@@ -177,60 +179,79 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TIntermTyped* right
             switch (getType().getBasicType()) {
             switch (getType().getBasicType()) {
             case EbtDouble:
             case EbtDouble:
             case EbtFloat:
             case EbtFloat:
-#ifdef AMD_EXTENSIONS
             case EbtFloat16:
             case EbtFloat16:
-#endif
-                newConstArray[i].setDConst(leftUnionArray[i].getDConst() / rightUnionArray[i].getDConst());
+                if (rightUnionArray[i].getDConst() != 0.0)
+                    newConstArray[i].setDConst(leftUnionArray[i].getDConst() / rightUnionArray[i].getDConst());
+                else if (leftUnionArray[i].getDConst() > 0.0)
+                    newConstArray[i].setDConst((double)INFINITY);
+                else if (leftUnionArray[i].getDConst() < 0.0)
+                    newConstArray[i].setDConst(-(double)INFINITY);
+                else
+                    newConstArray[i].setDConst((double)NAN);
+                break;
+            case EbtInt8:
+                if (rightUnionArray[i] == (signed char)0)
+                    newConstArray[i].setI8Const((signed char)0x7F);
+                else if (rightUnionArray[i].getI8Const() == (signed char)-1 && leftUnionArray[i].getI8Const() == (signed char)-0x80)
+                    newConstArray[i].setI8Const((signed char)-0x80);
+                else
+                    newConstArray[i].setI8Const(leftUnionArray[i].getI8Const() / rightUnionArray[i].getI8Const());
+                break;
+
+            case EbtUint8:
+                if (rightUnionArray[i] == (unsigned char)0u)
+                    newConstArray[i].setU8Const((unsigned char)0xFFu);
+                else
+                    newConstArray[i].setU8Const(leftUnionArray[i].getU8Const() / rightUnionArray[i].getU8Const());
+                break;
+
+           case EbtInt16:
+                if (rightUnionArray[i] == (signed short)0)
+                    newConstArray[i].setI16Const((signed short)0x7FFF);
+                else if (rightUnionArray[i].getI16Const() == (signed short)-1 && leftUnionArray[i].getI16Const() == (signed short)-0x8000)
+                    newConstArray[i].setI16Const((signed short)-0x8000);
+                else
+                    newConstArray[i].setI16Const(leftUnionArray[i].getI16Const() / rightUnionArray[i].getI16Const());
+                break;
+
+            case EbtUint16:
+                if (rightUnionArray[i] == (unsigned short)0u)
+                    newConstArray[i].setU16Const((unsigned short)0xFFFFu);
+                else
+                    newConstArray[i].setU16Const(leftUnionArray[i].getU16Const() / rightUnionArray[i].getU16Const());
                 break;
                 break;
 
 
             case EbtInt:
             case EbtInt:
                 if (rightUnionArray[i] == 0)
                 if (rightUnionArray[i] == 0)
                     newConstArray[i].setIConst(0x7FFFFFFF);
                     newConstArray[i].setIConst(0x7FFFFFFF);
-                else if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == (int)0x80000000)
-                    newConstArray[i].setIConst(0x80000000);
+                else if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == (int)-0x80000000ll)
+                    newConstArray[i].setIConst((int)-0x80000000ll);
                 else
                 else
                     newConstArray[i].setIConst(leftUnionArray[i].getIConst() / rightUnionArray[i].getIConst());
                     newConstArray[i].setIConst(leftUnionArray[i].getIConst() / rightUnionArray[i].getIConst());
                 break;
                 break;
 
 
             case EbtUint:
             case EbtUint:
-                if (rightUnionArray[i] == 0) {
+                if (rightUnionArray[i] == 0u)
                     newConstArray[i].setUConst(0xFFFFFFFFu);
                     newConstArray[i].setUConst(0xFFFFFFFFu);
-                } else
+                else
                     newConstArray[i].setUConst(leftUnionArray[i].getUConst() / rightUnionArray[i].getUConst());
                     newConstArray[i].setUConst(leftUnionArray[i].getUConst() / rightUnionArray[i].getUConst());
                 break;
                 break;
 
 
             case EbtInt64:
             case EbtInt64:
-                if (rightUnionArray[i] == 0)
+                if (rightUnionArray[i] == 0ll)
                     newConstArray[i].setI64Const(0x7FFFFFFFFFFFFFFFll);
                     newConstArray[i].setI64Const(0x7FFFFFFFFFFFFFFFll);
-                else if (rightUnionArray[i].getI64Const() == -1 && leftUnionArray[i].getI64Const() == (long long)0x8000000000000000)
-                    newConstArray[i].setI64Const(0x8000000000000000);
+                else if (rightUnionArray[i].getI64Const() == -1 && leftUnionArray[i].getI64Const() == (long long)-0x8000000000000000ll)
+                    newConstArray[i].setI64Const((long long)-0x8000000000000000ll);
                 else
                 else
                     newConstArray[i].setI64Const(leftUnionArray[i].getI64Const() / rightUnionArray[i].getI64Const());
                     newConstArray[i].setI64Const(leftUnionArray[i].getI64Const() / rightUnionArray[i].getI64Const());
                 break;
                 break;
 
 
             case EbtUint64:
             case EbtUint64:
-                if (rightUnionArray[i] == 0) {
+                if (rightUnionArray[i] == 0ull)
                     newConstArray[i].setU64Const(0xFFFFFFFFFFFFFFFFull);
                     newConstArray[i].setU64Const(0xFFFFFFFFFFFFFFFFull);
-                } else
-                    newConstArray[i].setU64Const(leftUnionArray[i].getU64Const() / rightUnionArray[i].getU64Const());
-                break;
-#ifdef AMD_EXTENSIONS
-            case EbtInt16:
-                if (rightUnionArray[i] == 0)
-                    newConstArray[i].setIConst(0x7FFF);
-                else if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == (int)0x8000)
-                    newConstArray[i].setIConst(0x8000);
                 else
                 else
-                    newConstArray[i].setIConst(leftUnionArray[i].getIConst() / rightUnionArray[i].getIConst());
-                break;
-
-            case EbtUint16:
-                if (rightUnionArray[i] == 0) {
-                    newConstArray[i].setUConst(0xFFFFu);
-                } else
-                    newConstArray[i].setUConst(leftUnionArray[i].getUConst() / rightUnionArray[i].getUConst());
+                    newConstArray[i].setU64Const(leftUnionArray[i].getU64Const() / rightUnionArray[i].getU64Const());
                 break;
                 break;
-#endif
             default:
             default:
                 return 0;
                 return 0;
             }
             }
@@ -411,6 +432,12 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType)
         resultSize = 2;
         resultSize = 2;
         break;
         break;
 
 
+    case EOpPack16:
+    case EOpPack32:
+    case EOpPack64:
+    case EOpUnpack32:
+    case EOpUnpack16:
+    case EOpUnpack8:
     case EOpNormalize:
     case EOpNormalize:
         componentWise = false;
         componentWise = false;
         resultSize = objectSize;
         resultSize = objectSize;
@@ -469,6 +496,12 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType)
     case EOpPackSnorm2x16:
     case EOpPackSnorm2x16:
     case EOpPackUnorm2x16:
     case EOpPackUnorm2x16:
     case EOpPackHalf2x16:
     case EOpPackHalf2x16:
+    case EOpPack16:
+    case EOpPack32:
+    case EOpPack64:
+    case EOpUnpack32:
+    case EOpUnpack16:
+    case EOpUnpack8:
 
 
     case EOpUnpackSnorm2x16:
     case EOpUnpackSnorm2x16:
     case EOpUnpackUnorm2x16:
     case EOpUnpackUnorm2x16:
@@ -494,17 +527,13 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType)
         case EOpNegative:
         case EOpNegative:
             switch (getType().getBasicType()) {
             switch (getType().getBasicType()) {
             case EbtDouble:
             case EbtDouble:
-#ifdef AMD_EXTENSIONS
             case EbtFloat16:
             case EbtFloat16:
-#endif
             case EbtFloat: newConstArray[i].setDConst(-unionArray[i].getDConst()); break;
             case EbtFloat: newConstArray[i].setDConst(-unionArray[i].getDConst()); break;
-#ifdef AMD_EXTENSIONS
-            case EbtInt16:
-#endif
+            case EbtInt8:  newConstArray[i].setI8Const(-unionArray[i].getI8Const()); break;
+            case EbtUint8: newConstArray[i].setU8Const(static_cast<unsigned int>(-static_cast<signed int>(unionArray[i].getU8Const())));  break;
+            case EbtInt16: newConstArray[i].setI16Const(-unionArray[i].getI16Const()); break;
+            case EbtUint16:newConstArray[i].setU16Const(static_cast<unsigned int>(-static_cast<signed int>(unionArray[i].getU16Const())));  break;
             case EbtInt:   newConstArray[i].setIConst(-unionArray[i].getIConst()); break;
             case EbtInt:   newConstArray[i].setIConst(-unionArray[i].getIConst()); break;
-#ifdef AMD_EXTENSIONS
-            case EbtUint16:
-#endif
             case EbtUint:  newConstArray[i].setUConst(static_cast<unsigned int>(-static_cast<int>(unionArray[i].getUConst())));  break;
             case EbtUint:  newConstArray[i].setUConst(static_cast<unsigned int>(-static_cast<int>(unionArray[i].getUConst())));  break;
             case EbtInt64: newConstArray[i].setI64Const(-unionArray[i].getI64Const()); break;
             case EbtInt64: newConstArray[i].setI64Const(-unionArray[i].getI64Const()); break;
             case EbtUint64: newConstArray[i].setU64Const(static_cast<unsigned long long>(-static_cast<long long>(unionArray[i].getU64Const())));  break;
             case EbtUint64: newConstArray[i].setU64Const(static_cast<unsigned long long>(-static_cast<long long>(unionArray[i].getU64Const())));  break;
@@ -642,6 +671,279 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType)
             break;
             break;
         }
         }
 
 
+        case EOpConvInt8ToBool:
+            newConstArray[i].setBConst(unionArray[i].getI8Const() != 0); break;
+        case EOpConvUint8ToBool:
+            newConstArray[i].setBConst(unionArray[i].getU8Const() != 0); break;
+        case EOpConvInt16ToBool:
+            newConstArray[i].setBConst(unionArray[i].getI16Const() != 0); break;
+        case EOpConvUint16ToBool:
+            newConstArray[i].setBConst(unionArray[i].getU16Const() != 0); break;
+        case EOpConvIntToBool:
+            newConstArray[i].setBConst(unionArray[i].getIConst() != 0); break;
+        case EOpConvUintToBool:
+            newConstArray[i].setBConst(unionArray[i].getUConst() != 0); break;
+        case EOpConvInt64ToBool:
+            newConstArray[i].setBConst(unionArray[i].getI64Const() != 0); break;
+        case EOpConvUint64ToBool:
+            newConstArray[i].setBConst(unionArray[i].getI64Const() != 0); break;
+        case EOpConvFloat16ToBool:
+            newConstArray[i].setBConst(unionArray[i].getDConst() != 0); break;
+        case EOpConvFloatToBool:
+            newConstArray[i].setBConst(unionArray[i].getDConst() != 0); break;
+        case EOpConvDoubleToBool:
+            newConstArray[i].setBConst(unionArray[i].getDConst() != 0); break;
+
+        case EOpConvBoolToInt8:
+            newConstArray[i].setI8Const(unionArray[i].getBConst()); break;
+        case EOpConvBoolToUint8:
+            newConstArray[i].setU8Const(unionArray[i].getBConst()); break;
+        case EOpConvBoolToInt16:
+            newConstArray[i].setI16Const(unionArray[i].getBConst()); break;
+        case EOpConvBoolToUint16:
+            newConstArray[i].setU16Const(unionArray[i].getBConst()); break;
+        case EOpConvBoolToInt:
+            newConstArray[i].setIConst(unionArray[i].getBConst()); break;
+        case EOpConvBoolToUint:
+            newConstArray[i].setUConst(unionArray[i].getBConst()); break;
+        case EOpConvBoolToInt64:
+            newConstArray[i].setI64Const(unionArray[i].getBConst()); break;
+        case EOpConvBoolToUint64:
+            newConstArray[i].setU64Const(unionArray[i].getBConst()); break;
+        case EOpConvBoolToFloat16:
+            newConstArray[i].setDConst(unionArray[i].getBConst()); break;
+        case EOpConvBoolToFloat:
+            newConstArray[i].setDConst(unionArray[i].getBConst()); break;
+        case EOpConvBoolToDouble:
+            newConstArray[i].setDConst(unionArray[i].getBConst()); break;
+
+        case EOpConvInt8ToInt16:
+            newConstArray[i].setI16Const(unionArray[i].getI8Const()); break;
+        case EOpConvInt8ToInt:
+            newConstArray[i].setIConst(unionArray[i].getI8Const()); break;
+        case EOpConvInt8ToInt64:
+            newConstArray[i].setI64Const(unionArray[i].getI8Const()); break;
+        case EOpConvInt8ToUint8:
+            newConstArray[i].setU8Const(unionArray[i].getI8Const()); break;
+        case EOpConvInt8ToUint16:
+            newConstArray[i].setU16Const(unionArray[i].getI8Const()); break;
+        case EOpConvInt8ToUint:
+            newConstArray[i].setUConst(unionArray[i].getI8Const()); break;
+        case EOpConvInt8ToUint64:
+            newConstArray[i].setU64Const(unionArray[i].getI8Const()); break;
+        case EOpConvUint8ToInt8:
+            newConstArray[i].setI8Const(unionArray[i].getU8Const()); break;
+        case EOpConvUint8ToInt16:
+            newConstArray[i].setI16Const(unionArray[i].getU8Const()); break;
+        case EOpConvUint8ToInt:
+            newConstArray[i].setIConst(unionArray[i].getU8Const()); break;
+        case EOpConvUint8ToInt64:
+            newConstArray[i].setI64Const(unionArray[i].getU8Const()); break;
+        case EOpConvUint8ToUint16:
+            newConstArray[i].setU16Const(unionArray[i].getU8Const()); break;
+        case EOpConvUint8ToUint:
+            newConstArray[i].setUConst(unionArray[i].getU8Const()); break;
+        case EOpConvUint8ToUint64:
+            newConstArray[i].setU64Const(unionArray[i].getU8Const()); break;
+        case EOpConvInt8ToFloat16:
+            newConstArray[i].setDConst(unionArray[i].getI8Const()); break;
+        case EOpConvInt8ToFloat:
+            newConstArray[i].setDConst(unionArray[i].getI8Const()); break;
+        case EOpConvInt8ToDouble:
+            newConstArray[i].setDConst(unionArray[i].getI8Const()); break;
+        case EOpConvUint8ToFloat16:
+            newConstArray[i].setDConst(unionArray[i].getU8Const()); break;
+        case EOpConvUint8ToFloat:
+            newConstArray[i].setDConst(unionArray[i].getU8Const()); break;
+        case EOpConvUint8ToDouble:
+            newConstArray[i].setDConst(unionArray[i].getU8Const()); break;
+
+        case EOpConvInt16ToInt8:
+            newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getI16Const())); break;
+        case EOpConvInt16ToInt:
+            newConstArray[i].setIConst(unionArray[i].getI16Const()); break;
+        case EOpConvInt16ToInt64:
+            newConstArray[i].setI64Const(unionArray[i].getI16Const()); break;
+        case EOpConvInt16ToUint8:
+            newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getI16Const())); break;
+        case EOpConvInt16ToUint16:
+            newConstArray[i].setU16Const(unionArray[i].getI16Const()); break;
+        case EOpConvInt16ToUint:
+            newConstArray[i].setUConst(unionArray[i].getI16Const()); break;
+        case EOpConvInt16ToUint64:
+            newConstArray[i].setU64Const(unionArray[i].getI16Const()); break;
+        case EOpConvUint16ToInt8:
+            newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getU16Const())); break;
+        case EOpConvUint16ToInt16:
+            newConstArray[i].setI16Const(unionArray[i].getU16Const()); break;
+        case EOpConvUint16ToInt:
+            newConstArray[i].setIConst(unionArray[i].getU16Const()); break;
+        case EOpConvUint16ToInt64:
+            newConstArray[i].setI64Const(unionArray[i].getU16Const()); break;
+        case EOpConvUint16ToUint8:
+            newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getU16Const())); break;
+
+        case EOpConvUint16ToUint:
+            newConstArray[i].setUConst(unionArray[i].getU16Const()); break;
+        case EOpConvUint16ToUint64:
+            newConstArray[i].setU64Const(unionArray[i].getU16Const()); break;
+        case EOpConvInt16ToFloat16:
+            newConstArray[i].setDConst(unionArray[i].getI16Const()); break;
+        case EOpConvInt16ToFloat:
+            newConstArray[i].setDConst(unionArray[i].getI16Const()); break;
+        case EOpConvInt16ToDouble:
+            newConstArray[i].setDConst(unionArray[i].getI16Const()); break;
+        case EOpConvUint16ToFloat16:
+            newConstArray[i].setDConst(unionArray[i].getU16Const()); break;
+        case EOpConvUint16ToFloat:
+            newConstArray[i].setDConst(unionArray[i].getU16Const()); break;
+        case EOpConvUint16ToDouble:
+            newConstArray[i].setDConst(unionArray[i].getU16Const()); break;
+
+        case EOpConvIntToInt8:
+            newConstArray[i].setI8Const((signed char)unionArray[i].getIConst()); break;
+        case EOpConvIntToInt16:
+            newConstArray[i].setI16Const((signed short)unionArray[i].getIConst()); break;
+        case EOpConvIntToInt64:
+            newConstArray[i].setI64Const(unionArray[i].getIConst()); break;
+        case EOpConvIntToUint8:
+            newConstArray[i].setU8Const((unsigned char)unionArray[i].getIConst()); break;
+        case EOpConvIntToUint16:
+            newConstArray[i].setU16Const((unsigned char)unionArray[i].getIConst()); break;
+        case EOpConvIntToUint:
+            newConstArray[i].setUConst(unionArray[i].getIConst()); break;
+        case EOpConvIntToUint64:
+            newConstArray[i].setU64Const(unionArray[i].getIConst()); break;
+
+        case EOpConvUintToInt8:
+            newConstArray[i].setI8Const((signed char)unionArray[i].getUConst()); break;
+        case EOpConvUintToInt16:
+            newConstArray[i].setI16Const((signed short)unionArray[i].getUConst()); break;
+        case EOpConvUintToInt:
+            newConstArray[i].setIConst(unionArray[i].getUConst()); break;
+        case EOpConvUintToInt64:
+            newConstArray[i].setI64Const(unionArray[i].getUConst()); break;
+        case EOpConvUintToUint8:
+            newConstArray[i].setU8Const((unsigned char)unionArray[i].getUConst()); break;
+        case EOpConvUintToUint16:
+            newConstArray[i].setU16Const((unsigned short)unionArray[i].getUConst()); break;
+        case EOpConvUintToUint64:
+            newConstArray[i].setU64Const(unionArray[i].getUConst()); break;
+        case EOpConvIntToFloat16:
+            newConstArray[i].setDConst(unionArray[i].getIConst()); break;
+        case EOpConvIntToFloat:
+            newConstArray[i].setDConst(unionArray[i].getIConst()); break;
+        case EOpConvIntToDouble:
+            newConstArray[i].setDConst(unionArray[i].getIConst()); break;
+        case EOpConvUintToFloat16:
+            newConstArray[i].setDConst(unionArray[i].getUConst()); break;
+        case EOpConvUintToFloat:
+            newConstArray[i].setDConst(unionArray[i].getUConst()); break;
+        case EOpConvUintToDouble:
+            newConstArray[i].setDConst(unionArray[i].getUConst()); break;
+        case EOpConvInt64ToInt8:
+            newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getI64Const())); break;
+        case EOpConvInt64ToInt16:
+            newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getI64Const())); break;
+        case EOpConvInt64ToInt:
+            newConstArray[i].setIConst(static_cast<int>(unionArray[i].getI64Const())); break;
+        case EOpConvInt64ToUint8:
+            newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getI64Const())); break;
+        case EOpConvInt64ToUint16:
+            newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getI64Const())); break;
+        case EOpConvInt64ToUint:
+            newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getI64Const())); break;
+        case EOpConvInt64ToUint64:
+            newConstArray[i].setU64Const(unionArray[i].getI64Const()); break;
+        case EOpConvUint64ToInt8:
+            newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getU64Const())); break;
+        case EOpConvUint64ToInt16:
+            newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getU64Const())); break;
+        case EOpConvUint64ToInt:
+            newConstArray[i].setIConst(static_cast<int>(unionArray[i].getU64Const())); break;
+        case EOpConvUint64ToInt64:
+            newConstArray[i].setI64Const(unionArray[i].getU64Const()); break;
+        case EOpConvUint64ToUint8:
+            newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getU64Const())); break;
+        case EOpConvUint64ToUint16:
+            newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getU64Const())); break;
+        case EOpConvUint64ToUint:
+            newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getU64Const())); break;
+        case EOpConvInt64ToFloat16:
+            newConstArray[i].setDConst(static_cast<double>(unionArray[i].getI64Const())); break;
+        case EOpConvInt64ToFloat:
+            newConstArray[i].setDConst(static_cast<double>(unionArray[i].getI64Const())); break;
+        case EOpConvInt64ToDouble:
+            newConstArray[i].setDConst(static_cast<double>(unionArray[i].getI64Const())); break;
+        case EOpConvUint64ToFloat16:
+            newConstArray[i].setDConst(static_cast<double>(unionArray[i].getU64Const())); break;
+        case EOpConvUint64ToFloat:
+            newConstArray[i].setDConst(static_cast<double>(unionArray[i].getU64Const())); break;
+        case EOpConvUint64ToDouble:
+            newConstArray[i].setDConst(static_cast<double>(unionArray[i].getU64Const())); break;
+        case EOpConvFloat16ToInt8:
+            newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getDConst())); break;
+        case EOpConvFloat16ToInt16:
+            newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getDConst())); break;
+        case EOpConvFloat16ToInt:
+            newConstArray[i].setIConst(static_cast<int>(unionArray[i].getDConst())); break;
+        case EOpConvFloat16ToInt64:
+            newConstArray[i].setI64Const(static_cast<long long>(unionArray[i].getDConst())); break;
+        case EOpConvFloat16ToUint8:
+            newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getDConst())); break;
+        case EOpConvFloat16ToUint16:
+            newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getDConst())); break;
+        case EOpConvFloat16ToUint:
+            newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getDConst())); break;
+        case EOpConvFloat16ToUint64:
+            newConstArray[i].setU64Const(static_cast<unsigned long long>(unionArray[i].getDConst())); break;
+        case EOpConvFloat16ToFloat:
+            newConstArray[i].setDConst(unionArray[i].getDConst()); break;
+        case EOpConvFloat16ToDouble:
+            newConstArray[i].setDConst(unionArray[i].getDConst()); break;
+        case EOpConvFloatToInt8:
+            newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getDConst())); break;
+        case EOpConvFloatToInt16:
+            newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getDConst())); break;
+        case EOpConvFloatToInt:
+            newConstArray[i].setIConst(static_cast<int>(unionArray[i].getDConst())); break;
+        case EOpConvFloatToInt64:
+            newConstArray[i].setI64Const(static_cast<long long>(unionArray[i].getDConst())); break;
+        case EOpConvFloatToUint8:
+            newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getDConst())); break;
+        case EOpConvFloatToUint16:
+            newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getDConst())); break;
+        case EOpConvFloatToUint:
+            newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getDConst())); break;
+        case EOpConvFloatToUint64:
+            newConstArray[i].setU64Const(static_cast<unsigned long long>(unionArray[i].getDConst())); break;
+        case EOpConvFloatToFloat16:
+            newConstArray[i].setDConst(unionArray[i].getDConst()); break;
+        case EOpConvFloatToDouble:
+            newConstArray[i].setDConst(unionArray[i].getDConst()); break;
+        case EOpConvDoubleToInt8:
+            newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getDConst())); break;
+        case EOpConvDoubleToInt16:
+            newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getDConst())); break;
+        case EOpConvDoubleToInt:
+            newConstArray[i].setIConst(static_cast<int>(unionArray[i].getDConst())); break;
+        case EOpConvDoubleToInt64:
+            newConstArray[i].setI64Const(static_cast<long long>(unionArray[i].getDConst())); break;
+        case EOpConvDoubleToUint8:
+            newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getDConst())); break;
+        case EOpConvDoubleToUint16:
+            newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getDConst())); break;
+        case EOpConvDoubleToUint:
+            newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getDConst())); break;
+        case EOpConvDoubleToUint64:
+            newConstArray[i].setU64Const(static_cast<unsigned long long>(unionArray[i].getDConst())); break;
+        case EOpConvDoubleToFloat16:
+            newConstArray[i].setDConst(unionArray[i].getDConst()); break;
+        case EOpConvDoubleToFloat:
+            newConstArray[i].setDConst(unionArray[i].getDConst()); break;
+
+
+
         // TODO: 3.0 Functionality: unary constant folding: the rest of the ops have to be fleshed out
         // TODO: 3.0 Functionality: unary constant folding: the rest of the ops have to be fleshed out
 
 
         case EOpSinh:
         case EOpSinh:
@@ -659,13 +961,10 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType)
         case EOpDoubleBitsToUint64:
         case EOpDoubleBitsToUint64:
         case EOpInt64BitsToDouble:
         case EOpInt64BitsToDouble:
         case EOpUint64BitsToDouble:
         case EOpUint64BitsToDouble:
-#ifdef AMD_EXTENSIONS
         case EOpFloat16BitsToInt16:
         case EOpFloat16BitsToInt16:
         case EOpFloat16BitsToUint16:
         case EOpFloat16BitsToUint16:
         case EOpInt16BitsToFloat16:
         case EOpInt16BitsToFloat16:
         case EOpUint16BitsToFloat16:
         case EOpUint16BitsToFloat16:
-#endif
-
         default:
         default:
             return 0;
             return 0;
         }
         }
@@ -749,20 +1048,6 @@ TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode)
     for (unsigned int arg = 0; arg < children.size(); ++arg)
     for (unsigned int arg = 0; arg < children.size(); ++arg)
         childConstUnions.push_back(children[arg]->getAsConstantUnion()->getConstArray());
         childConstUnions.push_back(children[arg]->getAsConstantUnion()->getConstArray());
 
 
-    // Second, do the actual folding
-
-    bool isFloatingPoint = children[0]->getAsTyped()->getBasicType() == EbtFloat ||
-#ifdef AMD_EXTENSIONS
-                           children[0]->getAsTyped()->getBasicType() == EbtFloat16 ||
-#endif
-                           children[0]->getAsTyped()->getBasicType() == EbtDouble;
-    bool isSigned = children[0]->getAsTyped()->getBasicType() == EbtInt ||
-#ifdef AMD_EXTENSIONS
-                    children[0]->getAsTyped()->getBasicType() == EbtInt16 ||
-#endif
-                    children[0]->getAsTyped()->getBasicType() == EbtInt64;
-    bool isInt64 = children[0]->getAsTyped()->getBasicType() == EbtInt64 ||
-                   children[0]->getAsTyped()->getBasicType() == EbtUint64;
     if (componentwise) {
     if (componentwise) {
         for (int comp = 0; comp < objectSize; comp++) {
         for (int comp = 0; comp < objectSize; comp++) {
 
 
@@ -783,53 +1068,114 @@ TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode)
                 newConstArray[comp].setDConst(pow(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
                 newConstArray[comp].setDConst(pow(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
                 break;
                 break;
             case EOpMin:
             case EOpMin:
-                if (isFloatingPoint)
+                switch(children[0]->getAsTyped()->getBasicType()) {
+                case EbtFloat16:
+                case EbtFloat:
+                case EbtDouble:
                     newConstArray[comp].setDConst(std::min(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
                     newConstArray[comp].setDConst(std::min(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
-                else if (isSigned) {
-                    if (isInt64)
-                        newConstArray[comp].setI64Const(std::min(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()));
-                    else
-                        newConstArray[comp].setIConst(std::min(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()));
-                } else {
-                    if (isInt64)
-                        newConstArray[comp].setU64Const(std::min(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()));
-                    else
-                        newConstArray[comp].setUConst(std::min(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()));
+                    break;
+                case EbtInt8:
+                    newConstArray[comp].setI8Const(std::min(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const()));
+                    break;
+                case EbtUint8:
+                    newConstArray[comp].setU8Const(std::min(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const()));
+                    break;
+                case EbtInt16:
+                    newConstArray[comp].setI16Const(std::min(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const()));
+                    break;
+                case EbtUint16:
+                    newConstArray[comp].setU16Const(std::min(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const()));
+                    break;
+                case EbtInt:
+                    newConstArray[comp].setIConst(std::min(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()));
+                    break;
+                case EbtUint:
+                    newConstArray[comp].setUConst(std::min(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()));
+                    break;
+                case EbtInt64:
+                    newConstArray[comp].setI64Const(std::min(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()));
+                    break;
+                case EbtUint64:
+                    newConstArray[comp].setU64Const(std::min(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()));
+                    break;
+                default: assert(false && "Default missing");
                 }
                 }
                 break;
                 break;
             case EOpMax:
             case EOpMax:
-                if (isFloatingPoint)
+                switch(children[0]->getAsTyped()->getBasicType()) {
+                case EbtFloat16:
+                case EbtFloat:
+                case EbtDouble:
                     newConstArray[comp].setDConst(std::max(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
                     newConstArray[comp].setDConst(std::max(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
-                else if (isSigned) {
-                    if (isInt64)
-                        newConstArray[comp].setI64Const(std::max(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()));
-                    else
-                        newConstArray[comp].setIConst(std::max(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()));
-                } else {
-                    if (isInt64)
-                        newConstArray[comp].setU64Const(std::max(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()));
-                    else
-                        newConstArray[comp].setUConst(std::max(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()));
+                    break;
+                case EbtInt8:
+                    newConstArray[comp].setI8Const(std::max(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const()));
+                    break;
+                case EbtUint8:
+                    newConstArray[comp].setU8Const(std::max(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const()));
+                    break;
+                case EbtInt16:
+                    newConstArray[comp].setI16Const(std::max(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const()));
+                    break;
+                case EbtUint16:
+                    newConstArray[comp].setU16Const(std::max(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const()));
+                    break;
+                case EbtInt:
+                    newConstArray[comp].setIConst(std::max(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()));
+                    break;
+                case EbtUint:
+                    newConstArray[comp].setUConst(std::max(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()));
+                    break;
+                case EbtInt64:
+                    newConstArray[comp].setI64Const(std::max(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()));
+                    break;
+                case EbtUint64:
+                    newConstArray[comp].setU64Const(std::max(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()));
+                    break;
+                default: assert(false && "Default missing");
                 }
                 }
                 break;
                 break;
             case EOpClamp:
             case EOpClamp:
-                if (isFloatingPoint)
+                switch(children[0]->getAsTyped()->getBasicType()) {
+                case EbtFloat16:
+                case EbtFloat:
+                case EbtDouble:
                     newConstArray[comp].setDConst(std::min(std::max(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()),
                     newConstArray[comp].setDConst(std::min(std::max(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()),
                                                                                                                childConstUnions[2][arg2comp].getDConst()));
                                                                                                                childConstUnions[2][arg2comp].getDConst()));
-                else if (isSigned) {
-                    if (isInt64)
-                        newConstArray[comp].setI64Const(std::min(std::max(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()),
-                                                                                                                       childConstUnions[2][arg2comp].getI64Const()));
-                    else
-                        newConstArray[comp].setIConst(std::min(std::max(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()),
+                    break;
+                case EbtInt8:
+                    newConstArray[comp].setI8Const(std::min(std::max(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const()),
+                                                                                                                   childConstUnions[2][arg2comp].getI8Const()));
+                    break;
+                case EbtUint8:
+                     newConstArray[comp].setU8Const(std::min(std::max(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const()),
+                                                                                                                   childConstUnions[2][arg2comp].getU8Const()));
+                    break;
+                case EbtInt16:
+                    newConstArray[comp].setI16Const(std::min(std::max(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const()),
+                                                                                                                   childConstUnions[2][arg2comp].getI16Const()));
+                    break;
+                case EbtUint16:
+                    newConstArray[comp].setU16Const(std::min(std::max(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const()),
+                                                                                                                   childConstUnions[2][arg2comp].getU16Const()));
+                    break;
+                case EbtInt:
+                    newConstArray[comp].setIConst(std::min(std::max(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()),
                                                                                                                    childConstUnions[2][arg2comp].getIConst()));
                                                                                                                    childConstUnions[2][arg2comp].getIConst()));
-                } else {
-                    if (isInt64)
-                        newConstArray[comp].setU64Const(std::min(std::max(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()),
-                                                                                                                       childConstUnions[2][arg2comp].getU64Const()));
-                    else
-                        newConstArray[comp].setUConst(std::min(std::max(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()),
+                    break;
+                case EbtUint:
+                    newConstArray[comp].setUConst(std::min(std::max(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()),
                                                                                                                    childConstUnions[2][arg2comp].getUConst()));
                                                                                                                    childConstUnions[2][arg2comp].getUConst()));
+                    break;
+                case EbtInt64:
+                    newConstArray[comp].setI64Const(std::min(std::max(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()),
+                                                                                                                       childConstUnions[2][arg2comp].getI64Const()));
+                    break;
+                case EbtUint64:
+                    newConstArray[comp].setU64Const(std::min(std::max(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()),
+                                                                                                                       childConstUnions[2][arg2comp].getU64Const()));
+                    break;
+                default: assert(false && "Default missing");
                 }
                 }
                 break;
                 break;
             case EOpLessThan:
             case EOpLessThan:

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


+ 0 - 2
src/libraries/glslang/glslang/MachineIndependent/Initialize.h

@@ -67,7 +67,6 @@ public:
     virtual const TString& getStageString(EShLanguage language) const { return stageBuiltins[language]; }
     virtual const TString& getStageString(EShLanguage language) const { return stageBuiltins[language]; }
 
 
     virtual void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable) = 0;
     virtual void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable) = 0;
-
     virtual void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources) = 0;
     virtual void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources) = 0;
 
 
 protected:
 protected:
@@ -89,7 +88,6 @@ public:
     void initialize(const TBuiltInResource& resources, int version, EProfile, const SpvVersion& spvVersion, EShLanguage);
     void initialize(const TBuiltInResource& resources, int version, EProfile, const SpvVersion& spvVersion, EShLanguage);
 
 
     void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable);
     void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable);
-
     void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources);
     void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources);
 
 
 protected:
 protected:

File diff suppressed because it is too large
+ 492 - 336
src/libraries/glslang/glslang/MachineIndependent/Intermediate.cpp


+ 14 - 2
src/libraries/glslang/glslang/MachineIndependent/ParseContextBase.cpp

@@ -153,6 +153,12 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op,
         if (node->getQualifier().readonly)
         if (node->getQualifier().readonly)
             message = "can't modify a readonly buffer";
             message = "can't modify a readonly buffer";
         break;
         break;
+#ifdef NV_EXTENSIONS
+    case EvqHitAttrNV:
+        if (language != EShLangIntersectNV)
+            message = "cannot modify hitAttributeNV in this stage";
+        break;
+#endif
 
 
     default:
     default:
         //
         //
@@ -168,6 +174,11 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op,
         case EbtVoid:
         case EbtVoid:
             message = "can't modify void";
             message = "can't modify void";
             break;
             break;
+#ifdef NV_EXTENSIONS
+        case EbtAccStructNV:
+            message = "can't modify accelerationStructureNV";
+            break;
+#endif
         default:
         default:
             break;
             break;
         }
         }
@@ -228,6 +239,7 @@ void TParseContextBase::rValueErrorCheck(const TSourceLoc& loc, const char* op,
 // must still be valid.
 // must still be valid.
 // It is okay if the symbol's type will be subsequently edited;
 // It is okay if the symbol's type will be subsequently edited;
 // the modifications will be tracked.
 // the modifications will be tracked.
+// Order is preserved, to avoid creating novel forward references.
 void TParseContextBase::trackLinkage(TSymbol& symbol)
 void TParseContextBase::trackLinkage(TSymbol& symbol)
 {
 {
     if (!parsingBuiltins)
     if (!parsingBuiltins)
@@ -242,7 +254,7 @@ void TParseContextBase::checkIndex(const TSourceLoc& loc, const TType& type, int
         error(loc, "", "[", "index out of range '%d'", index);
         error(loc, "", "[", "index out of range '%d'", index);
         index = 0;
         index = 0;
     } else if (type.isArray()) {
     } else if (type.isArray()) {
-        if (type.isExplicitlySizedArray() && index >= type.getOuterArraySize()) {
+        if (type.isSizedArray() && index >= type.getOuterArraySize()) {
             error(loc, "", "[", "array index out of range '%d'", index);
             error(loc, "", "[", "array index out of range '%d'", index);
             index = type.getOuterArraySize() - 1;
             index = type.getOuterArraySize() - 1;
         }
         }
@@ -602,7 +614,7 @@ void TParseContextBase::finish()
     if (parsingBuiltins)
     if (parsingBuiltins)
         return;
         return;
 
 
-    // Transfer the linkage symbols to AST nodes
+    // Transfer the linkage symbols to AST nodes, preserving order.
     TIntermAggregate* linkage = new TIntermAggregate;
     TIntermAggregate* linkage = new TIntermAggregate;
     for (auto i = linkageSymbols.begin(); i != linkageSymbols.end(); ++i)
     for (auto i = linkageSymbols.begin(); i != linkageSymbols.end(); ++i)
         intermediate.addSymbolLinkageNode(linkage, **i);
         intermediate.addSymbolLinkageNode(linkage, **i);

File diff suppressed because it is too large
+ 558 - 99
src/libraries/glslang/glslang/MachineIndependent/ParseHelper.cpp


+ 33 - 14
src/libraries/glslang/glslang/MachineIndependent/ParseHelper.h

@@ -1,6 +1,7 @@
 //
 //
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2012-2013 LunarG, Inc.
 // Copyright (C) 2012-2013 LunarG, Inc.
+// Copyright (C) 2015-2018 Google, Inc.
 //
 //
 // All rights reserved.
 // All rights reserved.
 //
 //
@@ -44,13 +45,15 @@
 #ifndef _PARSER_HELPER_INCLUDED_
 #ifndef _PARSER_HELPER_INCLUDED_
 #define _PARSER_HELPER_INCLUDED_
 #define _PARSER_HELPER_INCLUDED_
 
 
+#include <cstdarg>
+#include <functional>
+
 #include "parseVersions.h"
 #include "parseVersions.h"
 #include "../Include/ShHandle.h"
 #include "../Include/ShHandle.h"
 #include "SymbolTable.h"
 #include "SymbolTable.h"
 #include "localintermediate.h"
 #include "localintermediate.h"
 #include "Scan.h"
 #include "Scan.h"
-#include <cstdarg>
-#include <functional>
+#include "attribute.h"
 
 
 namespace glslang {
 namespace glslang {
 
 
@@ -185,7 +188,7 @@ protected:
     TParseContextBase& operator=(TParseContextBase&);
     TParseContextBase& operator=(TParseContextBase&);
 
 
     const bool parsingBuiltins;       // true if parsing built-in symbols/functions
     const bool parsingBuiltins;       // true if parsing built-in symbols/functions
-    TVector<TSymbol*> linkageSymbols; // these need to be transferred to 'linkage', after all editing is done
+    TVector<TSymbol*> linkageSymbols; // will be transferred to 'linkage', after all editing is done, order preserving
     TScanContext* scanContext;
     TScanContext* scanContext;
     TPpContext* ppContext;
     TPpContext* ppContext;
     TBuiltInResource resources;
     TBuiltInResource resources;
@@ -296,8 +299,8 @@ public:
     void fixIoArraySize(const TSourceLoc&, TType&);
     void fixIoArraySize(const TSourceLoc&, TType&);
     void ioArrayCheck(const TSourceLoc&, const TType&, const TString& identifier);
     void ioArrayCheck(const TSourceLoc&, const TType&, const TString& identifier);
     void handleIoResizeArrayAccess(const TSourceLoc&, TIntermTyped* base);
     void handleIoResizeArrayAccess(const TSourceLoc&, TIntermTyped* base);
-    void checkIoArraysConsistency(const TSourceLoc&, bool tailOnly = false);
-    int getIoArrayImplicitSize() const;
+    void checkIoArraysConsistency(const TSourceLoc&, bool tailOnly = false, bool isPerPrimitive = false);
+    int getIoArrayImplicitSize(bool isPerPrimitive = false) const;
     void checkIoArrayConsistency(const TSourceLoc&, int requiredSize, const char* feature, TType&, const TString&);
     void checkIoArrayConsistency(const TSourceLoc&, int requiredSize, const char* feature, TType&, const TString&);
 
 
     TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right);
     TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right);
@@ -307,7 +310,7 @@ public:
     TFunction* handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype);
     TFunction* handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype);
     TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&);
     TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&);
     TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*);
     TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*);
-    TIntermTyped* handleBuiltInFunctionCall(TSourceLoc, TIntermNode& arguments, const TFunction& function);
+    TIntermTyped* handleBuiltInFunctionCall(TSourceLoc, TIntermNode* arguments, const TFunction& function);
     void computeBuiltinPrecisions(TIntermTyped&, const TFunction&);
     void computeBuiltinPrecisions(TIntermTyped&, const TFunction&);
     TIntermNode* handleReturnValue(const TSourceLoc&, TIntermTyped*);
     TIntermNode* handleReturnValue(const TSourceLoc&, TIntermTyped*);
     void checkLocation(const TSourceLoc&, TOperator);
     void checkLocation(const TSourceLoc&, TOperator);
@@ -321,6 +324,7 @@ public:
     TFunction* handleConstructorCall(const TSourceLoc&, const TPublicType&);
     TFunction* handleConstructorCall(const TSourceLoc&, const TPublicType&);
     void handlePrecisionQualifier(const TSourceLoc&, TQualifier&, TPrecisionQualifier);
     void handlePrecisionQualifier(const TSourceLoc&, TQualifier&, TPrecisionQualifier);
     void checkPrecisionQualifier(const TSourceLoc&, TPrecisionQualifier);
     void checkPrecisionQualifier(const TSourceLoc&, TPrecisionQualifier);
+    void memorySemanticsCheck(const TSourceLoc&, const TFunction&, const TIntermOperator& callNode);
 
 
     void assignError(const TSourceLoc&, const char* op, TString left, TString right);
     void assignError(const TSourceLoc&, const char* op, TString left, TString right);
     void unaryOpError(const TSourceLoc&, const char* op, TString operand);
     void unaryOpError(const TSourceLoc&, const char* op, TString operand);
@@ -338,17 +342,16 @@ public:
     bool arrayError(const TSourceLoc&, const TType&);
     bool arrayError(const TSourceLoc&, const TType&);
     void arraySizeRequiredCheck(const TSourceLoc&, const TArraySizes&);
     void arraySizeRequiredCheck(const TSourceLoc&, const TArraySizes&);
     void structArrayCheck(const TSourceLoc&, const TType& structure);
     void structArrayCheck(const TSourceLoc&, const TType& structure);
-    void arraySizesCheck(const TSourceLoc&, const TQualifier&, TArraySizes*, bool initializer, bool lastMember);
-    void arrayOfArrayVersionCheck(const TSourceLoc&);
-    void arrayDimCheck(const TSourceLoc&, const TArraySizes* sizes1, const TArraySizes* sizes2);
-    void arrayDimCheck(const TSourceLoc&, const TType*, const TArraySizes*);
-    void arrayDimMerge(TType& type, const TArraySizes* sizes);
+    void arraySizesCheck(const TSourceLoc&, const TQualifier&, TArraySizes*, const TIntermTyped* initializer, bool lastMember);
+    void arrayOfArrayVersionCheck(const TSourceLoc&, const TArraySizes*);
     bool voidErrorCheck(const TSourceLoc&, const TString&, TBasicType);
     bool voidErrorCheck(const TSourceLoc&, const TString&, TBasicType);
     void boolCheck(const TSourceLoc&, const TIntermTyped*);
     void boolCheck(const TSourceLoc&, const TIntermTyped*);
     void boolCheck(const TSourceLoc&, const TPublicType&);
     void boolCheck(const TSourceLoc&, const TPublicType&);
     void samplerCheck(const TSourceLoc&, const TType&, const TString& identifier, TIntermTyped* initializer);
     void samplerCheck(const TSourceLoc&, const TType&, const TString& identifier, TIntermTyped* initializer);
     void atomicUintCheck(const TSourceLoc&, const TType&, const TString& identifier);
     void atomicUintCheck(const TSourceLoc&, const TType&, const TString& identifier);
+    void accStructNVCheck(const TSourceLoc & loc, const TType & type, const TString & identifier);
     void transparentOpaqueCheck(const TSourceLoc&, const TType&, const TString& identifier);
     void transparentOpaqueCheck(const TSourceLoc&, const TType&, const TString& identifier);
+    void memberQualifierCheck(glslang::TPublicType&);
     void globalQualifierFixCheck(const TSourceLoc&, TQualifier&);
     void globalQualifierFixCheck(const TSourceLoc&, TQualifier&);
     void globalQualifierTypeCheck(const TSourceLoc&, const TQualifier&, const TPublicType&);
     void globalQualifierTypeCheck(const TSourceLoc&, const TQualifier&, const TPublicType&);
     bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType);
     bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType);
@@ -361,12 +364,13 @@ public:
     bool containsFieldWithBasicType(const TType& type ,TBasicType basicType);
     bool containsFieldWithBasicType(const TType& type ,TBasicType basicType);
     TSymbol* redeclareBuiltinVariable(const TSourceLoc&, const TString&, const TQualifier&, const TShaderQualifiers&);
     TSymbol* redeclareBuiltinVariable(const TSourceLoc&, const TString&, const TQualifier&, const TShaderQualifiers&);
     void redeclareBuiltinBlock(const TSourceLoc&, TTypeList& typeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes);
     void redeclareBuiltinBlock(const TSourceLoc&, TTypeList& typeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes);
-    void paramCheckFix(const TSourceLoc&, const TStorageQualifier&, TType& type);
+    void paramCheckFixStorage(const TSourceLoc&, const TStorageQualifier&, TType& type);
     void paramCheckFix(const TSourceLoc&, const TQualifier&, TType& type);
     void paramCheckFix(const TSourceLoc&, const TQualifier&, TType& type);
     void nestedBlockCheck(const TSourceLoc&);
     void nestedBlockCheck(const TSourceLoc&);
     void nestedStructCheck(const TSourceLoc&);
     void nestedStructCheck(const TSourceLoc&);
     void arrayObjectCheck(const TSourceLoc&, const TType&, const char* op);
     void arrayObjectCheck(const TSourceLoc&, const TType&, const char* op);
     void opaqueCheck(const TSourceLoc&, const TType&, const char* op);
     void opaqueCheck(const TSourceLoc&, const TType&, const char* op);
+    void storage16BitAssignmentCheck(const TSourceLoc&, const TType&, const char* op);
     void specializationCheck(const TSourceLoc&, const TType&, const char* op);
     void specializationCheck(const TSourceLoc&, const TType&, const char* op);
     void structTypeCheck(const TSourceLoc&, TPublicType&);
     void structTypeCheck(const TSourceLoc&, TPublicType&);
     void inductiveLoopCheck(const TSourceLoc&, TIntermNode* init, TIntermLoop* loop);
     void inductiveLoopCheck(const TSourceLoc&, TIntermNode* init, TIntermLoop* loop);
@@ -390,6 +394,7 @@ public:
     const TFunction* findFunctionExact(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
     const TFunction* findFunctionExact(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
     const TFunction* findFunction120(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
     const TFunction* findFunction120(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
     const TFunction* findFunction400(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
     const TFunction* findFunction400(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
+    const TFunction* findFunctionExplicitTypes(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
     void declareTypeDefaults(const TSourceLoc&, const TPublicType&);
     void declareTypeDefaults(const TSourceLoc&, const TPublicType&);
     TIntermNode* declareVariable(const TSourceLoc&, TString& identifier, const TPublicType&, TArraySizes* typeArray = 0, TIntermTyped* initializer = 0);
     TIntermNode* declareVariable(const TSourceLoc&, TString& identifier, const TPublicType&, TArraySizes* typeArray = 0, TIntermTyped* initializer = 0);
     TIntermTyped* addConstructor(const TSourceLoc&, TIntermNode*, const TType&);
     TIntermTyped* addConstructor(const TSourceLoc&, TIntermNode*, const TType&);
@@ -399,7 +404,7 @@ public:
     void blockStageIoCheck(const TSourceLoc&, const TQualifier&);
     void blockStageIoCheck(const TSourceLoc&, const TQualifier&);
     void blockQualifierCheck(const TSourceLoc&, const TQualifier&, bool instanceName);
     void blockQualifierCheck(const TSourceLoc&, const TQualifier&, bool instanceName);
     void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation);
     void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation);
-    void fixBlockXfbOffsets(TQualifier&, TTypeList&);
+    void fixXfbOffsets(TQualifier&, TTypeList&);
     void fixBlockUniformOffsets(TQualifier&, TTypeList&);
     void fixBlockUniformOffsets(TQualifier&, TTypeList&);
     void addQualifierToExisting(const TSourceLoc&, TQualifier, const TString& identifier);
     void addQualifierToExisting(const TSourceLoc&, TQualifier, const TString& identifier);
     void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&);
     void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&);
@@ -408,7 +413,19 @@ public:
     void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode);
     void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode);
     TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body);
     TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body);
 
 
-    void updateImplicitArraySize(const TSourceLoc&, TIntermNode*, int index);
+    TAttributeType attributeFromName(const TString& name) const;
+    TAttributes* makeAttributes(const TString& identifier) const;
+    TAttributes* makeAttributes(const TString& identifier, TIntermNode* node) const;
+    TAttributes* mergeAttributes(TAttributes*, TAttributes*) const;
+
+    // Determine selection control from attributes
+    void handleSelectionAttributes(const TAttributes& attributes, TIntermNode*);
+    void handleSwitchAttributes(const TAttributes& attributes, TIntermNode*);
+
+    // Determine loop control from attributes
+    void handleLoopAttributes(const TAttributes& attributes, TIntermNode*);
+
+    void resizeMeshViewDimension(const TSourceLoc&, TType&);
 
 
 protected:
 protected:
     void nonInitConstCheck(const TSourceLoc&, TString& identifier, TType& type);
     void nonInitConstCheck(const TSourceLoc&, TString& identifier, TType& type);
@@ -416,6 +433,8 @@ protected:
     TVariable* makeInternalVariable(const char* name, const TType&) const;
     TVariable* makeInternalVariable(const char* name, const TType&) const;
     TVariable* declareNonArray(const TSourceLoc&, const TString& identifier, const TType&);
     TVariable* declareNonArray(const TSourceLoc&, const TString& identifier, const TType&);
     void declareArray(const TSourceLoc&, const TString& identifier, const TType&, TSymbol*&);
     void declareArray(const TSourceLoc&, const TString& identifier, const TType&, TSymbol*&);
+    void checkRuntimeSizable(const TSourceLoc&, const TIntermTyped&);
+    bool isRuntimeLength(const TIntermTyped&) const;
     TIntermNode* executeInitializer(const TSourceLoc&, TIntermTyped* initializer, TVariable* variable);
     TIntermNode* executeInitializer(const TSourceLoc&, TIntermTyped* initializer, TVariable* variable);
     TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer);
     TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer);
     void finish() override;
     void finish() override;

+ 365 - 34
src/libraries/glslang/glslang/MachineIndependent/Scan.cpp

@@ -1,6 +1,7 @@
 //
 //
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2013 LunarG, Inc.
 // Copyright (C) 2013 LunarG, Inc.
+// Copyright (C) 2017 ARM Limited.
 //
 //
 // All rights reserved.
 // All rights reserved.
 //
 //
@@ -45,6 +46,7 @@
 #include "../Include/Types.h"
 #include "../Include/Types.h"
 #include "SymbolTable.h"
 #include "SymbolTable.h"
 #include "ParseHelper.h"
 #include "ParseHelper.h"
+#include "attribute.h"
 #include "glslang_tab.cpp.h"
 #include "glslang_tab.cpp.h"
 #include "ScanContext.h"
 #include "ScanContext.h"
 #include "Scan.h"
 #include "Scan.h"
@@ -339,6 +341,7 @@ void TScanContext::fillInKeywordMap()
 
 
     (*KeywordMap)["const"] =                   CONST;
     (*KeywordMap)["const"] =                   CONST;
     (*KeywordMap)["uniform"] =                 UNIFORM;
     (*KeywordMap)["uniform"] =                 UNIFORM;
+    (*KeywordMap)["nonuniformEXT"] =           NONUNIFORM;
     (*KeywordMap)["in"] =                      IN;
     (*KeywordMap)["in"] =                      IN;
     (*KeywordMap)["out"] =                     OUT;
     (*KeywordMap)["out"] =                     OUT;
     (*KeywordMap)["inout"] =                   INOUT;
     (*KeywordMap)["inout"] =                   INOUT;
@@ -377,6 +380,11 @@ void TScanContext::fillInKeywordMap()
     (*KeywordMap)["varying"] =                 VARYING;
     (*KeywordMap)["varying"] =                 VARYING;
     (*KeywordMap)["buffer"] =                  BUFFER;
     (*KeywordMap)["buffer"] =                  BUFFER;
     (*KeywordMap)["coherent"] =                COHERENT;
     (*KeywordMap)["coherent"] =                COHERENT;
+    (*KeywordMap)["devicecoherent"] =          DEVICECOHERENT;
+    (*KeywordMap)["queuefamilycoherent"] =     QUEUEFAMILYCOHERENT;
+    (*KeywordMap)["workgroupcoherent"] =       WORKGROUPCOHERENT;
+    (*KeywordMap)["subgroupcoherent"] =        SUBGROUPCOHERENT;
+    (*KeywordMap)["nonprivate"] =              NONPRIVATE;
     (*KeywordMap)["restrict"] =                RESTRICT;
     (*KeywordMap)["restrict"] =                RESTRICT;
     (*KeywordMap)["readonly"] =                READONLY;
     (*KeywordMap)["readonly"] =                READONLY;
     (*KeywordMap)["writeonly"] =               WRITEONLY;
     (*KeywordMap)["writeonly"] =               WRITEONLY;
@@ -463,16 +471,34 @@ void TScanContext::fillInKeywordMap()
     (*KeywordMap)["u64vec3"] =                 U64VEC3;
     (*KeywordMap)["u64vec3"] =                 U64VEC3;
     (*KeywordMap)["u64vec4"] =                 U64VEC4;
     (*KeywordMap)["u64vec4"] =                 U64VEC4;
 
 
-#ifdef AMD_EXTENSIONS
+    // GL_EXT_shader_explicit_arithmetic_types
+    (*KeywordMap)["int8_t"] =                  INT8_T;
+    (*KeywordMap)["i8vec2"] =                  I8VEC2;
+    (*KeywordMap)["i8vec3"] =                  I8VEC3;
+    (*KeywordMap)["i8vec4"] =                  I8VEC4;
+    (*KeywordMap)["uint8_t"] =                 UINT8_T;
+    (*KeywordMap)["u8vec2"] =                  U8VEC2;
+    (*KeywordMap)["u8vec3"] =                  U8VEC3;
+    (*KeywordMap)["u8vec4"] =                  U8VEC4;
+
     (*KeywordMap)["int16_t"] =                 INT16_T;
     (*KeywordMap)["int16_t"] =                 INT16_T;
-    (*KeywordMap)["uint16_t"] =                UINT16_T;
     (*KeywordMap)["i16vec2"] =                 I16VEC2;
     (*KeywordMap)["i16vec2"] =                 I16VEC2;
     (*KeywordMap)["i16vec3"] =                 I16VEC3;
     (*KeywordMap)["i16vec3"] =                 I16VEC3;
     (*KeywordMap)["i16vec4"] =                 I16VEC4;
     (*KeywordMap)["i16vec4"] =                 I16VEC4;
+    (*KeywordMap)["uint16_t"] =                UINT16_T;
     (*KeywordMap)["u16vec2"] =                 U16VEC2;
     (*KeywordMap)["u16vec2"] =                 U16VEC2;
     (*KeywordMap)["u16vec3"] =                 U16VEC3;
     (*KeywordMap)["u16vec3"] =                 U16VEC3;
     (*KeywordMap)["u16vec4"] =                 U16VEC4;
     (*KeywordMap)["u16vec4"] =                 U16VEC4;
 
 
+    (*KeywordMap)["int32_t"] =                 INT32_T;
+    (*KeywordMap)["i32vec2"] =                 I32VEC2;
+    (*KeywordMap)["i32vec3"] =                 I32VEC3;
+    (*KeywordMap)["i32vec4"] =                 I32VEC4;
+    (*KeywordMap)["uint32_t"] =                UINT32_T;
+    (*KeywordMap)["u32vec2"] =                 U32VEC2;
+    (*KeywordMap)["u32vec3"] =                 U32VEC3;
+    (*KeywordMap)["u32vec4"] =                 U32VEC4;
+
     (*KeywordMap)["float16_t"] =               FLOAT16_T;
     (*KeywordMap)["float16_t"] =               FLOAT16_T;
     (*KeywordMap)["f16vec2"] =                 F16VEC2;
     (*KeywordMap)["f16vec2"] =                 F16VEC2;
     (*KeywordMap)["f16vec3"] =                 F16VEC3;
     (*KeywordMap)["f16vec3"] =                 F16VEC3;
@@ -489,7 +515,39 @@ void TScanContext::fillInKeywordMap()
     (*KeywordMap)["f16mat4x2"] =               F16MAT4X2;
     (*KeywordMap)["f16mat4x2"] =               F16MAT4X2;
     (*KeywordMap)["f16mat4x3"] =               F16MAT4X3;
     (*KeywordMap)["f16mat4x3"] =               F16MAT4X3;
     (*KeywordMap)["f16mat4x4"] =               F16MAT4X4;
     (*KeywordMap)["f16mat4x4"] =               F16MAT4X4;
-#endif
+
+    (*KeywordMap)["float32_t"] =               FLOAT32_T;
+    (*KeywordMap)["f32vec2"] =                 F32VEC2;
+    (*KeywordMap)["f32vec3"] =                 F32VEC3;
+    (*KeywordMap)["f32vec4"] =                 F32VEC4;
+    (*KeywordMap)["f32mat2"] =                 F32MAT2;
+    (*KeywordMap)["f32mat3"] =                 F32MAT3;
+    (*KeywordMap)["f32mat4"] =                 F32MAT4;
+    (*KeywordMap)["f32mat2x2"] =               F32MAT2X2;
+    (*KeywordMap)["f32mat2x3"] =               F32MAT2X3;
+    (*KeywordMap)["f32mat2x4"] =               F32MAT2X4;
+    (*KeywordMap)["f32mat3x2"] =               F32MAT3X2;
+    (*KeywordMap)["f32mat3x3"] =               F32MAT3X3;
+    (*KeywordMap)["f32mat3x4"] =               F32MAT3X4;
+    (*KeywordMap)["f32mat4x2"] =               F32MAT4X2;
+    (*KeywordMap)["f32mat4x3"] =               F32MAT4X3;
+    (*KeywordMap)["f32mat4x4"] =               F32MAT4X4;
+    (*KeywordMap)["float64_t"] =               FLOAT64_T;
+    (*KeywordMap)["f64vec2"] =                 F64VEC2;
+    (*KeywordMap)["f64vec3"] =                 F64VEC3;
+    (*KeywordMap)["f64vec4"] =                 F64VEC4;
+    (*KeywordMap)["f64mat2"] =                 F64MAT2;
+    (*KeywordMap)["f64mat3"] =                 F64MAT3;
+    (*KeywordMap)["f64mat4"] =                 F64MAT4;
+    (*KeywordMap)["f64mat2x2"] =               F64MAT2X2;
+    (*KeywordMap)["f64mat2x3"] =               F64MAT2X3;
+    (*KeywordMap)["f64mat2x4"] =               F64MAT2X4;
+    (*KeywordMap)["f64mat3x2"] =               F64MAT3X2;
+    (*KeywordMap)["f64mat3x3"] =               F64MAT3X3;
+    (*KeywordMap)["f64mat3x4"] =               F64MAT3X4;
+    (*KeywordMap)["f64mat4x2"] =               F64MAT4X2;
+    (*KeywordMap)["f64mat4x3"] =               F64MAT4X3;
+    (*KeywordMap)["f64mat4x4"] =               F64MAT4X4;
 
 
     (*KeywordMap)["sampler2D"] =               SAMPLER2D;
     (*KeywordMap)["sampler2D"] =               SAMPLER2D;
     (*KeywordMap)["samplerCube"] =             SAMPLERCUBE;
     (*KeywordMap)["samplerCube"] =             SAMPLERCUBE;
@@ -578,19 +636,82 @@ void TScanContext::fillInKeywordMap()
     (*KeywordMap)["usubpassInput"] =           USUBPASSINPUT;
     (*KeywordMap)["usubpassInput"] =           USUBPASSINPUT;
     (*KeywordMap)["usubpassInputMS"] =         USUBPASSINPUTMS;
     (*KeywordMap)["usubpassInputMS"] =         USUBPASSINPUTMS;
 
 
+#ifdef AMD_EXTENSIONS
+    (*KeywordMap)["f16sampler1D"] =                 F16SAMPLER1D;
+    (*KeywordMap)["f16sampler2D"] =                 F16SAMPLER2D;
+    (*KeywordMap)["f16sampler3D"] =                 F16SAMPLER3D;
+    (*KeywordMap)["f16sampler2DRect"] =             F16SAMPLER2DRECT;
+    (*KeywordMap)["f16samplerCube"] =               F16SAMPLERCUBE;
+    (*KeywordMap)["f16sampler1DArray"] =            F16SAMPLER1DARRAY;
+    (*KeywordMap)["f16sampler2DArray"] =            F16SAMPLER2DARRAY;
+    (*KeywordMap)["f16samplerCubeArray"] =          F16SAMPLERCUBEARRAY;
+    (*KeywordMap)["f16samplerBuffer"] =             F16SAMPLERBUFFER;
+    (*KeywordMap)["f16sampler2DMS"] =               F16SAMPLER2DMS;
+    (*KeywordMap)["f16sampler2DMSArray"] =          F16SAMPLER2DMSARRAY;
+    (*KeywordMap)["f16sampler1DShadow"] =           F16SAMPLER1DSHADOW;
+    (*KeywordMap)["f16sampler2DShadow"] =           F16SAMPLER2DSHADOW;
+    (*KeywordMap)["f16sampler2DRectShadow"] =       F16SAMPLER2DRECTSHADOW;
+    (*KeywordMap)["f16samplerCubeShadow"] =         F16SAMPLERCUBESHADOW;
+    (*KeywordMap)["f16sampler1DArrayShadow"] =      F16SAMPLER1DARRAYSHADOW;
+    (*KeywordMap)["f16sampler2DArrayShadow"] =      F16SAMPLER2DARRAYSHADOW;
+    (*KeywordMap)["f16samplerCubeArrayShadow"] =    F16SAMPLERCUBEARRAYSHADOW;
+
+    (*KeywordMap)["f16image1D"] =                   F16IMAGE1D;
+    (*KeywordMap)["f16image2D"] =                   F16IMAGE2D;
+    (*KeywordMap)["f16image3D"] =                   F16IMAGE3D;
+    (*KeywordMap)["f16image2DRect"] =               F16IMAGE2DRECT;
+    (*KeywordMap)["f16imageCube"] =                 F16IMAGECUBE;
+    (*KeywordMap)["f16image1DArray"] =              F16IMAGE1DARRAY;
+    (*KeywordMap)["f16image2DArray"] =              F16IMAGE2DARRAY;
+    (*KeywordMap)["f16imageCubeArray"] =            F16IMAGECUBEARRAY;
+    (*KeywordMap)["f16imageBuffer"] =               F16IMAGEBUFFER;
+    (*KeywordMap)["f16image2DMS"] =                 F16IMAGE2DMS;
+    (*KeywordMap)["f16image2DMSArray"] =            F16IMAGE2DMSARRAY;
+
+    (*KeywordMap)["f16texture1D"] =                 F16TEXTURE1D;
+    (*KeywordMap)["f16texture2D"] =                 F16TEXTURE2D;
+    (*KeywordMap)["f16texture3D"] =                 F16TEXTURE3D;
+    (*KeywordMap)["f16texture2DRect"] =             F16TEXTURE2DRECT;
+    (*KeywordMap)["f16textureCube"] =               F16TEXTURECUBE;
+    (*KeywordMap)["f16texture1DArray"] =            F16TEXTURE1DARRAY;
+    (*KeywordMap)["f16texture2DArray"] =            F16TEXTURE2DARRAY;
+    (*KeywordMap)["f16textureCubeArray"] =          F16TEXTURECUBEARRAY;
+    (*KeywordMap)["f16textureBuffer"] =             F16TEXTUREBUFFER;
+    (*KeywordMap)["f16texture2DMS"] =               F16TEXTURE2DMS;
+    (*KeywordMap)["f16texture2DMSArray"] =          F16TEXTURE2DMSARRAY;
+
+    (*KeywordMap)["f16subpassInput"] =              F16SUBPASSINPUT;
+    (*KeywordMap)["f16subpassInputMS"] =            F16SUBPASSINPUTMS;
+#endif
+
     (*KeywordMap)["noperspective"] =           NOPERSPECTIVE;
     (*KeywordMap)["noperspective"] =           NOPERSPECTIVE;
     (*KeywordMap)["smooth"] =                  SMOOTH;
     (*KeywordMap)["smooth"] =                  SMOOTH;
     (*KeywordMap)["flat"] =                    FLAT;
     (*KeywordMap)["flat"] =                    FLAT;
 #ifdef AMD_EXTENSIONS
 #ifdef AMD_EXTENSIONS
-    (*KeywordMap)["__explicitInterpAMD"] =     __EXPLICITINTERPAMD;
+    (*KeywordMap)["__explicitInterpAMD"] =     EXPLICITINTERPAMD;
 #endif
 #endif
     (*KeywordMap)["centroid"] =                CENTROID;
     (*KeywordMap)["centroid"] =                CENTROID;
+#ifdef NV_EXTENSIONS
+    (*KeywordMap)["pervertexNV"] =             PERVERTEXNV;
+#endif
     (*KeywordMap)["precise"] =                 PRECISE;
     (*KeywordMap)["precise"] =                 PRECISE;
     (*KeywordMap)["invariant"] =               INVARIANT;
     (*KeywordMap)["invariant"] =               INVARIANT;
     (*KeywordMap)["packed"] =                  PACKED;
     (*KeywordMap)["packed"] =                  PACKED;
     (*KeywordMap)["resource"] =                RESOURCE;
     (*KeywordMap)["resource"] =                RESOURCE;
     (*KeywordMap)["superp"] =                  SUPERP;
     (*KeywordMap)["superp"] =                  SUPERP;
 
 
+#ifdef NV_EXTENSIONS
+    (*KeywordMap)["rayPayloadNV"] =            PAYLOADNV;
+    (*KeywordMap)["rayPayloadInNV"] =          PAYLOADINNV;
+    (*KeywordMap)["hitAttributeNV"] =          HITATTRNV;
+    (*KeywordMap)["callableDataNV"] =          CALLDATANV;
+    (*KeywordMap)["callableDataInNV"] =        CALLDATAINNV;
+    (*KeywordMap)["accelerationStructureNV"] = ACCSTRUCTNV;
+    (*KeywordMap)["perprimitiveNV"] =          PERPRIMITIVENV;
+    (*KeywordMap)["perviewNV"] =               PERVIEWNV;
+    (*KeywordMap)["taskNV"] =                  PERTASKNV;
+#endif
+
     ReservedSet = new std::unordered_set<const char*, str_hash, str_eq>;
     ReservedSet = new std::unordered_set<const char*, str_hash, str_eq>;
 
 
     ReservedSet->insert("common");
     ReservedSet->insert("common");
@@ -677,7 +798,7 @@ int TScanContext::tokenize(TPpContext* pp, TParserToken& token)
         case '?':                       return QUESTION;
         case '?':                       return QUESTION;
         case '[':                       return LEFT_BRACKET;
         case '[':                       return LEFT_BRACKET;
         case ']':                       return RIGHT_BRACKET;
         case ']':                       return RIGHT_BRACKET;
-        case '{':                       return LEFT_BRACE;
+        case '{':  afterStruct = false; return LEFT_BRACE;
         case '}':                       return RIGHT_BRACE;
         case '}':                       return RIGHT_BRACE;
         case '\\':
         case '\\':
             parseContext.error(loc, "illegal use of escape character", "\\", "");
             parseContext.error(loc, "illegal use of escape character", "\\", "");
@@ -714,19 +835,15 @@ int TScanContext::tokenize(TPpContext* pp, TParserToken& token)
             parseContext.error(loc, "not supported", "::", "");
             parseContext.error(loc, "not supported", "::", "");
             break;
             break;
 
 
-        case PpAtomConstInt:           parserToken->sType.lex.i   = ppToken.ival;       return INTCONSTANT;
-        case PpAtomConstUint:          parserToken->sType.lex.i   = ppToken.ival;       return UINTCONSTANT;
-        case PpAtomConstInt64:         parserToken->sType.lex.i64 = ppToken.i64val;     return INT64CONSTANT;
-        case PpAtomConstUint64:        parserToken->sType.lex.i64 = ppToken.i64val;     return UINT64CONSTANT;
-#ifdef AMD_EXTENSIONS
-        case PpAtomConstInt16:         parserToken->sType.lex.i   = ppToken.ival;       return INT16CONSTANT;
-        case PpAtomConstUint16:        parserToken->sType.lex.i   = ppToken.ival;       return UINT16CONSTANT;
-#endif
-        case PpAtomConstFloat:         parserToken->sType.lex.d   = ppToken.dval;       return FLOATCONSTANT;
-        case PpAtomConstDouble:        parserToken->sType.lex.d   = ppToken.dval;       return DOUBLECONSTANT;
-#ifdef AMD_EXTENSIONS
-        case PpAtomConstFloat16:       parserToken->sType.lex.d   = ppToken.dval;       return FLOAT16CONSTANT;
-#endif
+        case PpAtomConstInt:           parserToken->sType.lex.i    = ppToken.ival;       return INTCONSTANT;
+        case PpAtomConstUint:          parserToken->sType.lex.i    = ppToken.ival;       return UINTCONSTANT;
+        case PpAtomConstInt16:         parserToken->sType.lex.i    = ppToken.ival;       return INT16CONSTANT;
+        case PpAtomConstUint16:        parserToken->sType.lex.i    = ppToken.ival;       return UINT16CONSTANT;
+        case PpAtomConstInt64:         parserToken->sType.lex.i64  = ppToken.i64val;     return INT64CONSTANT;
+        case PpAtomConstUint64:        parserToken->sType.lex.i64  = ppToken.i64val;     return UINT64CONSTANT;
+        case PpAtomConstFloat:         parserToken->sType.lex.d    = ppToken.dval;       return FLOATCONSTANT;
+        case PpAtomConstDouble:        parserToken->sType.lex.d    = ppToken.dval;       return DOUBLECONSTANT;
+        case PpAtomConstFloat16:       parserToken->sType.lex.d    = ppToken.dval;       return FLOAT16CONSTANT;
         case PpAtomIdentifier:
         case PpAtomIdentifier:
         {
         {
             int token = tokenizeIdentifier();
             int token = tokenizeIdentifier();
@@ -764,7 +881,6 @@ int TScanContext::tokenizeIdentifier()
     case IN:
     case IN:
     case OUT:
     case OUT:
     case INOUT:
     case INOUT:
-    case STRUCT:
     case BREAK:
     case BREAK:
     case CONTINUE:
     case CONTINUE:
     case DO:
     case DO:
@@ -777,6 +893,16 @@ int TScanContext::tokenizeIdentifier()
     case CASE:
     case CASE:
         return keyword;
         return keyword;
 
 
+    case STRUCT:
+        afterStruct = true;
+        return keyword;
+
+    case NONUNIFORM:
+        if (parseContext.extensionTurnedOn(E_GL_EXT_nonuniform_qualifier))
+            return keyword;
+        else
+            return identifierOrType();
+
     case SWITCH:
     case SWITCH:
     case DEFAULT:
     case DEFAULT:
         if ((parseContext.profile == EEsProfile && parseContext.version < 300) ||
         if ((parseContext.profile == EEsProfile && parseContext.version < 300) ||
@@ -824,6 +950,20 @@ int TScanContext::tokenizeIdentifier()
             return identifierOrType();
             return identifierOrType();
         return keyword;
         return keyword;
 
 
+#ifdef NV_EXTENSIONS
+    case PAYLOADNV:
+    case PAYLOADINNV:
+    case HITATTRNV:
+    case CALLDATANV:
+    case CALLDATAINNV:
+    case ACCSTRUCTNV:
+        if (parseContext.symbolTable.atBuiltInLevel() ||
+            (parseContext.profile != EEsProfile && parseContext.version >= 460
+                 && parseContext.extensionTurnedOn(E_GL_NV_ray_tracing)))
+            return keyword;
+        return identifierOrType();
+#endif
+
     case ATOMIC_UINT:
     case ATOMIC_UINT:
         if ((parseContext.profile == EEsProfile && parseContext.version >= 310) ||
         if ((parseContext.profile == EEsProfile && parseContext.version >= 310) ||
             parseContext.extensionTurnedOn(E_GL_ARB_shader_atomic_counters))
             parseContext.extensionTurnedOn(E_GL_ARB_shader_atomic_counters))
@@ -831,6 +971,11 @@ int TScanContext::tokenizeIdentifier()
         return es30ReservedFromGLSL(420);
         return es30ReservedFromGLSL(420);
 
 
     case COHERENT:
     case COHERENT:
+    case DEVICECOHERENT:
+    case QUEUEFAMILYCOHERENT:
+    case WORKGROUPCOHERENT:
+    case SUBGROUPCOHERENT:
+    case NONPRIVATE:
     case RESTRICT:
     case RESTRICT:
     case READONLY:
     case READONLY:
     case WRITEONLY:
     case WRITEONLY:
@@ -841,7 +986,8 @@ int TScanContext::tokenizeIdentifier()
     case VOLATILE:
     case VOLATILE:
         if (parseContext.profile == EEsProfile && parseContext.version >= 310)
         if (parseContext.profile == EEsProfile && parseContext.version >= 310)
             return keyword;
             return keyword;
-        if (! parseContext.symbolTable.atBuiltInLevel() && (parseContext.profile == EEsProfile || (parseContext.version < 420 && ! parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store))))
+        if (! parseContext.symbolTable.atBuiltInLevel() && (parseContext.profile == EEsProfile ||
+            (parseContext.version < 420 && ! parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store))))
             reservedWord();
             reservedWord();
         return keyword;
         return keyword;
 
 
@@ -865,7 +1011,7 @@ int TScanContext::tokenizeIdentifier()
     case PATCH:
     case PATCH:
         if (parseContext.symbolTable.atBuiltInLevel() ||
         if (parseContext.symbolTable.atBuiltInLevel() ||
             (parseContext.profile == EEsProfile &&
             (parseContext.profile == EEsProfile &&
-             (parseContext.version >= 320 || 
+             (parseContext.version >= 320 ||
               parseContext.extensionsTurnedOn(Num_AEP_tessellation_shader, AEP_tessellation_shader))) ||
               parseContext.extensionsTurnedOn(Num_AEP_tessellation_shader, AEP_tessellation_shader))) ||
             (parseContext.profile != EEsProfile && parseContext.extensionTurnedOn(E_GL_ARB_tessellation_shader)))
             (parseContext.profile != EEsProfile && parseContext.extensionTurnedOn(E_GL_ARB_tessellation_shader)))
             return keyword;
             return keyword;
@@ -985,12 +1131,30 @@ int TScanContext::tokenizeIdentifier()
     case U64VEC4:
     case U64VEC4:
         afterType = true;
         afterType = true;
         if (parseContext.symbolTable.atBuiltInLevel() ||
         if (parseContext.symbolTable.atBuiltInLevel() ||
-            (parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_int64) &&
-             parseContext.profile != EEsProfile && parseContext.version >= 450))
+            (parseContext.profile != EEsProfile && parseContext.version >= 450 &&
+             (parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_int64) ||
+              parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
+              parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int64))))
+            return keyword;
+        return identifierOrType();
+
+    case INT8_T:
+    case UINT8_T:
+    case I8VEC2:
+    case I8VEC3:
+    case I8VEC4:
+    case U8VEC2:
+    case U8VEC3:
+    case U8VEC4:
+        afterType = true;
+        if (parseContext.symbolTable.atBuiltInLevel() ||
+            ((parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
+              parseContext.extensionTurnedOn(E_GL_EXT_shader_8bit_storage) ||
+              parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int8)) &&
+              parseContext.profile != EEsProfile && parseContext.version >= 450))
             return keyword;
             return keyword;
         return identifierOrType();
         return identifierOrType();
 
 
-#ifdef AMD_EXTENSIONS
     case INT16_T:
     case INT16_T:
     case UINT16_T:
     case UINT16_T:
     case I16VEC2:
     case I16VEC2:
@@ -1001,15 +1165,97 @@ int TScanContext::tokenizeIdentifier()
     case U16VEC4:
     case U16VEC4:
         afterType = true;
         afterType = true;
         if (parseContext.symbolTable.atBuiltInLevel() ||
         if (parseContext.symbolTable.atBuiltInLevel() ||
-            (parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_int16) &&
+            (parseContext.profile != EEsProfile && parseContext.version >= 450 &&
+             (
+#ifdef AMD_EXTENSIONS
+              parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_int16) ||
+#endif
+              parseContext.extensionTurnedOn(E_GL_EXT_shader_16bit_storage) ||
+              parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
+              parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int16))))
+            return keyword;
+        return identifierOrType();
+    case INT32_T:
+    case UINT32_T:
+    case I32VEC2:
+    case I32VEC3:
+    case I32VEC4:
+    case U32VEC2:
+    case U32VEC3:
+    case U32VEC4:
+        afterType = true;
+        if (parseContext.symbolTable.atBuiltInLevel() ||
+           ((parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
+             parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int32)) &&
              parseContext.profile != EEsProfile && parseContext.version >= 450))
              parseContext.profile != EEsProfile && parseContext.version >= 450))
             return keyword;
             return keyword;
         return identifierOrType();
         return identifierOrType();
+    case FLOAT32_T:
+    case F32VEC2:
+    case F32VEC3:
+    case F32VEC4:
+    case F32MAT2:
+    case F32MAT3:
+    case F32MAT4:
+    case F32MAT2X2:
+    case F32MAT2X3:
+    case F32MAT2X4:
+    case F32MAT3X2:
+    case F32MAT3X3:
+    case F32MAT3X4:
+    case F32MAT4X2:
+    case F32MAT4X3:
+    case F32MAT4X4:
+        afterType = true;
+        if (parseContext.symbolTable.atBuiltInLevel() ||
+            ((parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
+              parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float32)) &&
+              parseContext.profile != EEsProfile && parseContext.version >= 450))
+            return keyword;
+        return identifierOrType();
+
+    case FLOAT64_T:
+    case F64VEC2:
+    case F64VEC3:
+    case F64VEC4:
+    case F64MAT2:
+    case F64MAT3:
+    case F64MAT4:
+    case F64MAT2X2:
+    case F64MAT2X3:
+    case F64MAT2X4:
+    case F64MAT3X2:
+    case F64MAT3X3:
+    case F64MAT3X4:
+    case F64MAT4X2:
+    case F64MAT4X3:
+    case F64MAT4X4:
+        afterType = true;
+        if (parseContext.symbolTable.atBuiltInLevel() ||
+            ((parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
+              parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float64)) &&
+              parseContext.profile != EEsProfile && parseContext.version >= 450))
+            return keyword;
+        return identifierOrType();
 
 
     case FLOAT16_T:
     case FLOAT16_T:
     case F16VEC2:
     case F16VEC2:
     case F16VEC3:
     case F16VEC3:
     case F16VEC4:
     case F16VEC4:
+        afterType = true;
+        if (parseContext.symbolTable.atBuiltInLevel() ||
+            (parseContext.profile != EEsProfile && parseContext.version >= 450 &&
+             (
+#ifdef AMD_EXTENSIONS
+              parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float) ||
+#endif
+              parseContext.extensionTurnedOn(E_GL_EXT_shader_16bit_storage) ||
+              parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
+              parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float16))))
+            return keyword;
+
+        return identifierOrType();
+
     case F16MAT2:
     case F16MAT2:
     case F16MAT3:
     case F16MAT3:
     case F16MAT4:
     case F16MAT4:
@@ -1024,11 +1270,16 @@ int TScanContext::tokenizeIdentifier()
     case F16MAT4X4:
     case F16MAT4X4:
         afterType = true;
         afterType = true;
         if (parseContext.symbolTable.atBuiltInLevel() ||
         if (parseContext.symbolTable.atBuiltInLevel() ||
-            (parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float) &&
-             parseContext.profile != EEsProfile && parseContext.version >= 450))
+            (parseContext.profile != EEsProfile && parseContext.version >= 450 &&
+             (
+#ifdef AMD_EXTENSIONS
+              parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float) ||
+#endif
+              parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
+              parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float16))))
             return keyword;
             return keyword;
+
         return identifierOrType();
         return identifierOrType();
-#endif
 
 
     case SAMPLERCUBEARRAY:
     case SAMPLERCUBEARRAY:
     case SAMPLERCUBEARRAYSHADOW:
     case SAMPLERCUBEARRAYSHADOW:
@@ -1112,7 +1363,7 @@ int TScanContext::tokenizeIdentifier()
     case SAMPLER3D:
     case SAMPLER3D:
         afterType = true;
         afterType = true;
         if (parseContext.profile == EEsProfile && parseContext.version < 300) {
         if (parseContext.profile == EEsProfile && parseContext.version < 300) {
-            if (! parseContext.extensionTurnedOn(E_GL_OES_texture_3D))
+            if (!parseContext.extensionTurnedOn(E_GL_OES_texture_3D))
                 reservedWord();
                 reservedWord();
         }
         }
         return keyword;
         return keyword;
@@ -1212,7 +1463,7 @@ int TScanContext::tokenizeIdentifier()
     case TEXTURE1DARRAY:
     case TEXTURE1DARRAY:
     case SAMPLER:
     case SAMPLER:
     case SAMPLERSHADOW:
     case SAMPLERSHADOW:
-        if (parseContext.spvVersion.vulkan >= 100)
+        if (parseContext.spvVersion.vulkan > 0)
             return keyword;
             return keyword;
         else
         else
             return identifierOrType();
             return identifierOrType();
@@ -1223,12 +1474,71 @@ int TScanContext::tokenizeIdentifier()
     case ISUBPASSINPUTMS:
     case ISUBPASSINPUTMS:
     case USUBPASSINPUT:
     case USUBPASSINPUT:
     case USUBPASSINPUTMS:
     case USUBPASSINPUTMS:
-        if (parseContext.spvVersion.vulkan >= 100)
+        if (parseContext.spvVersion.vulkan > 0)
             return keyword;
             return keyword;
         else
         else
             return identifierOrType();
             return identifierOrType();
 
 
+#ifdef AMD_EXTENSIONS
+    case F16SAMPLER1D:
+    case F16SAMPLER2D:
+    case F16SAMPLER3D:
+    case F16SAMPLER2DRECT:
+    case F16SAMPLERCUBE:
+    case F16SAMPLER1DARRAY:
+    case F16SAMPLER2DARRAY:
+    case F16SAMPLERCUBEARRAY:
+    case F16SAMPLERBUFFER:
+    case F16SAMPLER2DMS:
+    case F16SAMPLER2DMSARRAY:
+    case F16SAMPLER1DSHADOW:
+    case F16SAMPLER2DSHADOW:
+    case F16SAMPLER1DARRAYSHADOW:
+    case F16SAMPLER2DARRAYSHADOW:
+    case F16SAMPLER2DRECTSHADOW:
+    case F16SAMPLERCUBESHADOW:
+    case F16SAMPLERCUBEARRAYSHADOW:
+
+    case F16IMAGE1D:
+    case F16IMAGE2D:
+    case F16IMAGE3D:
+    case F16IMAGE2DRECT:
+    case F16IMAGECUBE:
+    case F16IMAGE1DARRAY:
+    case F16IMAGE2DARRAY:
+    case F16IMAGECUBEARRAY:
+    case F16IMAGEBUFFER:
+    case F16IMAGE2DMS:
+    case F16IMAGE2DMSARRAY:
+
+    case F16TEXTURE1D:
+    case F16TEXTURE2D:
+    case F16TEXTURE3D:
+    case F16TEXTURE2DRECT:
+    case F16TEXTURECUBE:
+    case F16TEXTURE1DARRAY:
+    case F16TEXTURE2DARRAY:
+    case F16TEXTURECUBEARRAY:
+    case F16TEXTUREBUFFER:
+    case F16TEXTURE2DMS:
+    case F16TEXTURE2DMSARRAY:
+
+    case F16SUBPASSINPUT:
+    case F16SUBPASSINPUTMS:
+        afterType = true;
+        if (parseContext.symbolTable.atBuiltInLevel() ||
+            (parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float_fetch) &&
+             parseContext.profile != EEsProfile && parseContext.version >= 450))
+            return keyword;
+        return identifierOrType();
+#endif
+
     case NOPERSPECTIVE:
     case NOPERSPECTIVE:
+#ifdef NV_EXTENSIONS
+        if (parseContext.profile == EEsProfile && parseContext.version >= 300 &&
+            parseContext.extensionTurnedOn(E_GL_NV_shader_noperspective_interpolation))
+            return keyword;
+#endif
         return es30ReservedFromGLSL(130);
         return es30ReservedFromGLSL(130);
 
 
     case SMOOTH:
     case SMOOTH:
@@ -1238,13 +1548,22 @@ int TScanContext::tokenizeIdentifier()
         return keyword;
         return keyword;
 
 
 #ifdef AMD_EXTENSIONS
 #ifdef AMD_EXTENSIONS
-    case __EXPLICITINTERPAMD:
+    case EXPLICITINTERPAMD:
         if (parseContext.profile != EEsProfile && parseContext.version >= 450 &&
         if (parseContext.profile != EEsProfile && parseContext.version >= 450 &&
             parseContext.extensionTurnedOn(E_GL_AMD_shader_explicit_vertex_parameter))
             parseContext.extensionTurnedOn(E_GL_AMD_shader_explicit_vertex_parameter))
             return keyword;
             return keyword;
         return identifierOrType();
         return identifierOrType();
 #endif
 #endif
 
 
+#ifdef NV_EXTENSIONS
+    case PERVERTEXNV:
+        if (((parseContext.profile != EEsProfile && parseContext.version >= 450) ||
+            (parseContext.profile == EEsProfile && parseContext.version >= 320)) &&
+            parseContext.extensionTurnedOn(E_GL_NV_fragment_shader_barycentric))
+            return keyword;
+        return identifierOrType();
+#endif
+
     case FLAT:
     case FLAT:
         if (parseContext.profile == EEsProfile && parseContext.version < 300)
         if (parseContext.profile == EEsProfile && parseContext.version < 300)
             reservedWord();
             reservedWord();
@@ -1291,6 +1610,17 @@ int TScanContext::tokenizeIdentifier()
         return identifierOrReserved(reserved);
         return identifierOrReserved(reserved);
     }
     }
 
 
+#ifdef NV_EXTENSIONS
+    case PERPRIMITIVENV:
+    case PERVIEWNV:
+    case PERTASKNV:
+        if ((parseContext.profile != EEsProfile && parseContext.version >= 450) ||
+            (parseContext.profile == EEsProfile && parseContext.version >= 320) ||
+            parseContext.extensionTurnedOn(E_GL_NV_mesh_shader))
+            return keyword;
+        return identifierOrType();
+#endif
+
     default:
     default:
         parseContext.infoSink.info.message(EPrefixInternalError, "Unknown glslang keyword", loc);
         parseContext.infoSink.info.message(EPrefixInternalError, "Unknown glslang keyword", loc);
         return 0;
         return 0;
@@ -1304,7 +1634,7 @@ int TScanContext::identifierOrType()
         return IDENTIFIER;
         return IDENTIFIER;
 
 
     parserToken->sType.lex.symbol = parseContext.symbolTable.find(*parserToken->sType.lex.string);
     parserToken->sType.lex.symbol = parseContext.symbolTable.find(*parserToken->sType.lex.string);
-    if (afterType == false && parserToken->sType.lex.symbol) {
+    if ((afterType == false && afterStruct == false) && parserToken->sType.lex.symbol != nullptr) {
         if (const TVariable* variable = parserToken->sType.lex.symbol->getAsVariable()) {
         if (const TVariable* variable = parserToken->sType.lex.symbol->getAsVariable()) {
             if (variable->isUserType()) {
             if (variable->isUserType()) {
                 afterType = true;
                 afterType = true;
@@ -1422,7 +1752,8 @@ int TScanContext::dMat()
 int TScanContext::firstGenerationImage(bool inEs310)
 int TScanContext::firstGenerationImage(bool inEs310)
 {
 {
     if (parseContext.symbolTable.atBuiltInLevel() ||
     if (parseContext.symbolTable.atBuiltInLevel() ||
-        (parseContext.profile != EEsProfile && (parseContext.version >= 420 || parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store))) ||
+        (parseContext.profile != EEsProfile && (parseContext.version >= 420 ||
+         parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store))) ||
         (inEs310 && parseContext.profile == EEsProfile && parseContext.version >= 310))
         (inEs310 && parseContext.profile == EEsProfile && parseContext.version >= 310))
         return keyword;
         return keyword;
 
 

+ 7 - 5
src/libraries/glslang/glslang/MachineIndependent/Scan.h

@@ -65,7 +65,7 @@ public:
         }
         }
         if (names != nullptr) {
         if (names != nullptr) {
             for (int i = 0; i < numSources; ++i)
             for (int i = 0; i < numSources; ++i)
-                loc[i].name = names[i];
+                loc[i].name = names[i] != nullptr ? NewPoolTString(names[i]) : nullptr;
         }
         }
         loc[currentSource].line = 1;
         loc[currentSource].line = 1;
         logicalSourceLoc.init(1);
         logicalSourceLoc.init(1);
@@ -170,16 +170,18 @@ public:
     // for #line override in filename based parsing
     // for #line override in filename based parsing
     void setFile(const char* filename)
     void setFile(const char* filename)
     {
     {
-        logicalSourceLoc.name = filename;
-        loc[getLastValidSourceIndex()].name = filename;
+        TString* fn_tstr = NewPoolTString(filename);
+        logicalSourceLoc.name = fn_tstr;
+        loc[getLastValidSourceIndex()].name = fn_tstr;
     }
     }
 
 
     void setFile(const char* filename, int i)
     void setFile(const char* filename, int i)
     {
     {
+        TString* fn_tstr = NewPoolTString(filename);
         if (i == getLastValidSourceIndex()) {
         if (i == getLastValidSourceIndex()) {
-            logicalSourceLoc.name = filename;
+            logicalSourceLoc.name = fn_tstr;
         }
         }
-        loc[i].name = filename;
+        loc[i].name = fn_tstr;
     }
     }
 
 
     void setString(int newString)
     void setString(int newString)

+ 5 - 1
src/libraries/glslang/glslang/MachineIndependent/ScanContext.h

@@ -50,7 +50,10 @@ class TParserToken;
 
 
 class TScanContext {
 class TScanContext {
 public:
 public:
-    explicit TScanContext(TParseContextBase& pc) : parseContext(pc), afterType(false), field(false) { }
+    explicit TScanContext(TParseContextBase& pc) :
+        parseContext(pc),
+        afterType(false), afterStruct(false),
+        field(false) { }
     virtual ~TScanContext() { }
     virtual ~TScanContext() { }
 
 
     static void fillInKeywordMap();
     static void fillInKeywordMap();
@@ -76,6 +79,7 @@ protected:
 
 
     TParseContextBase& parseContext;
     TParseContextBase& parseContext;
     bool afterType;           // true if we've recognized a type, so can only be looking for an identifier
     bool afterType;           // true if we've recognized a type, so can only be looking for an identifier
+    bool afterStruct;         // true if we've recognized the STRUCT keyword, so can only be looking for an identifier
     bool field;               // true if we're on a field, right after a '.'
     bool field;               // true if we're on a field, right after a '.'
     TSourceLoc loc;
     TSourceLoc loc;
     TParserToken* parserToken;
     TParserToken* parserToken;

+ 144 - 60
src/libraries/glslang/glslang/MachineIndependent/ShaderLang.cpp

@@ -1,7 +1,7 @@
 //
 //
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2013-2016 LunarG, Inc.
 // Copyright (C) 2013-2016 LunarG, Inc.
-// Copyright (C) 2015-2017 Google, Inc.
+// Copyright (C) 2015-2018 Google, Inc.
 //
 //
 // All rights reserved.
 // All rights reserved.
 //
 //
@@ -67,6 +67,11 @@
 #include "iomapper.h"
 #include "iomapper.h"
 #include "Initialize.h"
 #include "Initialize.h"
 
 
+// TODO: this really shouldn't be here, it is only because of the trial addition
+// of printing pre-processed tokens, which requires knowing the string literal
+// token to print ", but none of that seems appropriate for this file.
+#include "preprocessor/PpTokens.h"
+
 namespace { // anonymous namespace for file-local functions and symbols
 namespace { // anonymous namespace for file-local functions and symbols
 
 
 // Total number of successful initializers of glslang: a refcount
 // Total number of successful initializers of glslang: a refcount
@@ -342,6 +347,36 @@ bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable,  TS
         InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCompute, source,
         InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCompute, source,
                                    infoSink, commonTable, symbolTables);
                                    infoSink, commonTable, symbolTables);
 
 
+#ifdef NV_EXTENSIONS
+    // check for ray tracing stages
+    if (profile != EEsProfile && version >= 450) {
+        InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangRayGenNV, source,
+            infoSink, commonTable, symbolTables);
+        InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangIntersectNV, source,
+            infoSink, commonTable, symbolTables);
+        InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangAnyHitNV, source,
+            infoSink, commonTable, symbolTables);
+        InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangClosestHitNV, source,
+            infoSink, commonTable, symbolTables);
+        InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangMissNV, source,
+            infoSink, commonTable, symbolTables);
+        InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCallableNV, source,
+            infoSink, commonTable, symbolTables);
+    }
+
+    // check for mesh
+    if ((profile != EEsProfile && version >= 450) ||
+        (profile == EEsProfile && version >= 320))
+        InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangMeshNV, source,
+                                   infoSink, commonTable, symbolTables);
+
+    // check for task
+    if ((profile != EEsProfile && version >= 450) ||
+        (profile == EEsProfile && version >= 320))
+        InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangTaskNV, source,
+                                   infoSink, commonTable, symbolTables);
+#endif
+
     return true;
     return true;
 }
 }
 
 
@@ -565,6 +600,28 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo
             version = profile == EEsProfile ? 310 : 420;
             version = profile == EEsProfile ? 310 : 420;
         }
         }
         break;
         break;
+#ifdef NV_EXTENSIONS
+    case EShLangRayGenNV:
+    case EShLangIntersectNV:
+    case EShLangAnyHitNV:
+    case EShLangClosestHitNV:
+    case EShLangMissNV:
+    case EShLangCallableNV:
+        if (profile == EEsProfile || version < 460) {
+            correct = false;
+            infoSink.info.message(EPrefixError, "#version: ray tracing shaders require non-es profile with version 460 or above");
+            version = 460;
+        }
+        break;
+    case EShLangMeshNV:
+    case EShLangTaskNV:
+        if ((profile == EEsProfile && version < 320) ||
+            (profile != EEsProfile && version < 450)) {
+            correct = false;
+            infoSink.info.message(EPrefixError, "#version: mesh/task shaders require es profile with version 320 or above, or non-es profile with version 450 or above");
+            version = profile == EEsProfile ? 320 : 450;
+        }
+#endif
     default:
     default:
         break;
         break;
     }
     }
@@ -578,7 +635,7 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo
     if (spvVersion.spv != 0) {
     if (spvVersion.spv != 0) {
         switch (profile) {
         switch (profile) {
         case  EEsProfile:
         case  EEsProfile:
-            if (spvVersion.vulkan >= 100 && version < 310) {
+            if (spvVersion.vulkan > 0 && version < 310) {
                 correct = false;
                 correct = false;
                 infoSink.info.message(EPrefixError, "#version: ES shaders for Vulkan SPIR-V require version 310 or higher");
                 infoSink.info.message(EPrefixError, "#version: ES shaders for Vulkan SPIR-V require version 310 or higher");
                 version = 310;
                 version = 310;
@@ -593,7 +650,7 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo
             infoSink.info.message(EPrefixError, "#version: compilation for SPIR-V does not support the compatibility profile");
             infoSink.info.message(EPrefixError, "#version: compilation for SPIR-V does not support the compatibility profile");
             break;
             break;
         default:
         default:
-            if (spvVersion.vulkan >= 100 && version < 140) {
+            if (spvVersion.vulkan > 0 && version < 140) {
                 correct = false;
                 correct = false;
                 infoSink.info.message(EPrefixError, "#version: Desktop shaders for Vulkan SPIR-V require version 140 or higher");
                 infoSink.info.message(EPrefixError, "#version: Desktop shaders for Vulkan SPIR-V require version 140 or higher");
                 version = 140;
                 version = 140;
@@ -619,9 +676,9 @@ void TranslateEnvironment(const TEnvironment* environment, EShMessages& messages
 {
 {
     // Set up environmental defaults, first ignoring 'environment'.
     // Set up environmental defaults, first ignoring 'environment'.
     if (messages & EShMsgSpvRules)
     if (messages & EShMsgSpvRules)
-        spvVersion.spv = 0x00010000;
+        spvVersion.spv = EShTargetSpv_1_0;
     if (messages & EShMsgVulkanRules) {
     if (messages & EShMsgVulkanRules) {
-        spvVersion.vulkan = 100;
+        spvVersion.vulkan = EShTargetVulkan_1_0;
         spvVersion.vulkanGlsl = 100;
         spvVersion.vulkanGlsl = 100;
     } else if (spvVersion.spv != 0)
     } else if (spvVersion.spv != 0)
         spvVersion.openGl = 100;
         spvVersion.openGl = 100;
@@ -744,9 +801,9 @@ bool ProcessDeferred(
     const int numPre = 2;
     const int numPre = 2;
     const int numPost = requireNonempty? 1 : 0;
     const int numPost = requireNonempty? 1 : 0;
     const int numTotal = numPre + numStrings + numPost;
     const int numTotal = numPre + numStrings + numPost;
-    size_t* lengths = new size_t[numTotal];
-    const char** strings = new const char*[numTotal];
-    const char** names = new const char*[numTotal];
+    std::unique_ptr<size_t[]> lengths(new size_t[numTotal]);
+    std::unique_ptr<const char*[]> strings(new const char*[numTotal]);
+    std::unique_ptr<const char*[]> names(new const char*[numTotal]);
     for (int s = 0; s < numStrings; ++s) {
     for (int s = 0; s < numStrings; ++s) {
         strings[s + numPre] = shaderStrings[s];
         strings[s + numPre] = shaderStrings[s];
         if (inputLengths == nullptr || inputLengths[s] < 0)
         if (inputLengths == nullptr || inputLengths[s] < 0)
@@ -768,6 +825,8 @@ bool ProcessDeferred(
     SpvVersion spvVersion;
     SpvVersion spvVersion;
     EShLanguage stage = compiler->getLanguage();
     EShLanguage stage = compiler->getLanguage();
     TranslateEnvironment(environment, messages, source, stage, spvVersion);
     TranslateEnvironment(environment, messages, source, stage, spvVersion);
+    if (environment != nullptr && environment->target.hlslFunctionality1)
+        intermediate.setHlslFunctionality1();
 
 
     // First, without using the preprocessor or parser, find the #version, so we know what
     // First, without using the preprocessor or parser, find the #version, so we know what
     // symbol tables, processing rules, etc. to set up.  This does not need the extra strings
     // symbol tables, processing rules, etc. to set up.  This does not need the extra strings
@@ -814,7 +873,7 @@ bool ProcessDeferred(
     intermediate.setProfile(profile);
     intermediate.setProfile(profile);
     intermediate.setSpv(spvVersion);
     intermediate.setSpv(spvVersion);
     RecordProcesses(intermediate, messages, sourceEntryPointName);
     RecordProcesses(intermediate, messages, sourceEntryPointName);
-    if (spvVersion.vulkan >= 100)
+    if (spvVersion.vulkan > 0)
         intermediate.setOriginUpperLeft();
         intermediate.setOriginUpperLeft();
     if ((messages & EShMsgHlslOffsets) || source == EShSourceHlsl)
     if ((messages & EShMsgHlslOffsets) || source == EShSourceHlsl)
         intermediate.setHlslOffsets();
         intermediate.setHlslOffsets();
@@ -832,25 +891,24 @@ bool ProcessDeferred(
                                                   [stage];
                                                   [stage];
 
 
     // Dynamically allocate the symbol table so we can control when it is deallocated WRT the pool.
     // Dynamically allocate the symbol table so we can control when it is deallocated WRT the pool.
-    TSymbolTable* symbolTableMemory = new TSymbolTable;
-    TSymbolTable& symbolTable = *symbolTableMemory;
+    std::unique_ptr<TSymbolTable> symbolTable(new TSymbolTable);
     if (cachedTable)
     if (cachedTable)
-        symbolTable.adoptLevels(*cachedTable);
+        symbolTable->adoptLevels(*cachedTable);
 
 
     // Add built-in symbols that are potentially context dependent;
     // Add built-in symbols that are potentially context dependent;
     // they get popped again further down.
     // they get popped again further down.
-    if (! AddContextSpecificSymbols(resources, compiler->infoSink, symbolTable, version, profile, spvVersion,
-                                    stage, source))
+    if (! AddContextSpecificSymbols(resources, compiler->infoSink, *symbolTable, version, profile, spvVersion,
+                                    stage, source)) {
         return false;
         return false;
+    }
 
 
     //
     //
     // Now we can process the full shader under proper symbols and rules.
     // Now we can process the full shader under proper symbols and rules.
     //
     //
 
 
-    TParseContextBase* parseContext = CreateParseContext(symbolTable, intermediate, version, profile, source,
-                                                         stage, compiler->infoSink,
-                                                         spvVersion, forwardCompatible, messages, false, sourceEntryPointName);
-
+    std::unique_ptr<TParseContextBase> parseContext(CreateParseContext(*symbolTable, intermediate, version, profile, source,
+                                                    stage, compiler->infoSink,
+                                                    spvVersion, forwardCompatible, messages, false, sourceEntryPointName));
     TPpContext ppContext(*parseContext, names[numPre] ? names[numPre] : "", includer);
     TPpContext ppContext(*parseContext, names[numPre] ? names[numPre] : "", includer);
 
 
     // only GLSL (bison triggered, really) needs an externally set scan context
     // only GLSL (bison triggered, really) needs an externally set scan context
@@ -886,23 +944,14 @@ bool ProcessDeferred(
         lengths[postIndex] = strlen(strings[numStrings + numPre]);
         lengths[postIndex] = strlen(strings[numStrings + numPre]);
         names[postIndex] = nullptr;
         names[postIndex] = nullptr;
     }
     }
-    TInputScanner fullInput(numStrings + numPre + numPost, strings, lengths, names, numPre, numPost);
+    TInputScanner fullInput(numStrings + numPre + numPost, strings.get(), lengths.get(), names.get(), numPre, numPost);
 
 
     // Push a new symbol allocation scope that will get used for the shader's globals.
     // Push a new symbol allocation scope that will get used for the shader's globals.
-    symbolTable.push();
+    symbolTable->push();
 
 
     bool success = processingContext(*parseContext, ppContext, fullInput,
     bool success = processingContext(*parseContext, ppContext, fullInput,
-                                     versionWillBeError, symbolTable,
+                                     versionWillBeError, *symbolTable,
                                      intermediate, optLevel, messages);
                                      intermediate, optLevel, messages);
-
-    // Clean up the symbol table. The AST is self-sufficient now.
-    delete symbolTableMemory;
-
-    delete parseContext;
-    delete [] lengths;
-    delete [] strings;
-    delete [] names;
-
     return success;
     return success;
 }
 }
 
 
@@ -912,7 +961,7 @@ bool ProcessDeferred(
 class SourceLineSynchronizer {
 class SourceLineSynchronizer {
 public:
 public:
     SourceLineSynchronizer(const std::function<int()>& lastSourceIndex,
     SourceLineSynchronizer(const std::function<int()>& lastSourceIndex,
-                           std::stringstream* output)
+                           std::string* output)
       : getLastSourceIndex(lastSourceIndex), output(output), lastSource(-1), lastLine(0) {}
       : getLastSourceIndex(lastSourceIndex), output(output), lastSource(-1), lastLine(0) {}
 //    SourceLineSynchronizer(const SourceLineSynchronizer&) = delete;
 //    SourceLineSynchronizer(const SourceLineSynchronizer&) = delete;
 //    SourceLineSynchronizer& operator=(const SourceLineSynchronizer&) = delete;
 //    SourceLineSynchronizer& operator=(const SourceLineSynchronizer&) = delete;
@@ -927,7 +976,7 @@ public:
             // used. We also need to output a newline to separate the output
             // used. We also need to output a newline to separate the output
             // from the previous source string (if there is one).
             // from the previous source string (if there is one).
             if (lastSource != -1 || lastLine != 0)
             if (lastSource != -1 || lastLine != 0)
-                *output << std::endl;
+                *output += '\n';
             lastSource = getLastSourceIndex();
             lastSource = getLastSourceIndex();
             lastLine = -1;
             lastLine = -1;
             return true;
             return true;
@@ -942,7 +991,7 @@ public:
         syncToMostRecentString();
         syncToMostRecentString();
         const bool newLineStarted = lastLine < tokenLine;
         const bool newLineStarted = lastLine < tokenLine;
         for (; lastLine < tokenLine; ++lastLine) {
         for (; lastLine < tokenLine; ++lastLine) {
-            if (lastLine > 0) *output << std::endl;
+            if (lastLine > 0) *output += '\n';
         }
         }
         return newLineStarted;
         return newLineStarted;
     }
     }
@@ -956,8 +1005,8 @@ private:
     // A function for getting the index of the last valid source string we've
     // A function for getting the index of the last valid source string we've
     // read tokens from.
     // read tokens from.
     const std::function<int()> getLastSourceIndex;
     const std::function<int()> getLastSourceIndex;
-    // output stream for newlines.
-    std::stringstream* output;
+    // output string for newlines.
+    std::string* output;
     // lastSource is the source string index (starting from 0) of the last token
     // lastSource is the source string index (starting from 0) of the last token
     // processed. It is tracked in order for newlines to be inserted when a new
     // processed. It is tracked in order for newlines to be inserted when a new
     // source string starts. -1 means we haven't started processing any source
     // source string starts. -1 means we haven't started processing any source
@@ -973,6 +1022,8 @@ private:
 // DoPreprocessing is a valid ProcessingContext template argument,
 // DoPreprocessing is a valid ProcessingContext template argument,
 // which only performs the preprocessing step of compilation.
 // which only performs the preprocessing step of compilation.
 // It places the result in the "string" argument to its constructor.
 // It places the result in the "string" argument to its constructor.
+//
+// This is not an officially supported or fully working path.
 struct DoPreprocessing {
 struct DoPreprocessing {
     explicit DoPreprocessing(std::string* string): outputString(string) {}
     explicit DoPreprocessing(std::string* string): outputString(string) {}
     bool operator()(TParseContextBase& parseContext, TPpContext& ppContext,
     bool operator()(TParseContextBase& parseContext, TPpContext& ppContext,
@@ -988,27 +1039,33 @@ struct DoPreprocessing {
         parseContext.setScanner(&input);
         parseContext.setScanner(&input);
         ppContext.setInput(input, versionWillBeError);
         ppContext.setInput(input, versionWillBeError);
 
 
-        std::stringstream outputStream;
+        std::string outputBuffer;
         SourceLineSynchronizer lineSync(
         SourceLineSynchronizer lineSync(
-            std::bind(&TInputScanner::getLastValidSourceIndex, &input), &outputStream);
+            std::bind(&TInputScanner::getLastValidSourceIndex, &input), &outputBuffer);
 
 
-        parseContext.setExtensionCallback([&lineSync, &outputStream](
+        parseContext.setExtensionCallback([&lineSync, &outputBuffer](
             int line, const char* extension, const char* behavior) {
             int line, const char* extension, const char* behavior) {
                 lineSync.syncToLine(line);
                 lineSync.syncToLine(line);
-                outputStream << "#extension " << extension << " : " << behavior;
+                outputBuffer += "#extension ";
+                outputBuffer += extension;
+                outputBuffer += " : ";
+                outputBuffer += behavior;
         });
         });
 
 
-        parseContext.setLineCallback([&lineSync, &outputStream, &parseContext](
+        parseContext.setLineCallback([&lineSync, &outputBuffer, &parseContext](
             int curLineNum, int newLineNum, bool hasSource, int sourceNum, const char* sourceName) {
             int curLineNum, int newLineNum, bool hasSource, int sourceNum, const char* sourceName) {
             // SourceNum is the number of the source-string that is being parsed.
             // SourceNum is the number of the source-string that is being parsed.
             lineSync.syncToLine(curLineNum);
             lineSync.syncToLine(curLineNum);
-            outputStream << "#line " << newLineNum;
+            outputBuffer += "#line ";
+            outputBuffer += std::to_string(newLineNum);
             if (hasSource) {
             if (hasSource) {
-                outputStream << " ";
+                outputBuffer += ' ';
                 if (sourceName != nullptr) {
                 if (sourceName != nullptr) {
-                    outputStream << "\"" << sourceName << "\"";
+                    outputBuffer += '\"';
+                    outputBuffer += sourceName;
+                    outputBuffer += '\"';
                 } else {
                 } else {
-                    outputStream << sourceNum;
+                    outputBuffer += std::to_string(sourceNum);
                 }
                 }
             }
             }
             if (parseContext.lineDirectiveShouldSetNextLine()) {
             if (parseContext.lineDirectiveShouldSetNextLine()) {
@@ -1016,33 +1073,36 @@ struct DoPreprocessing {
                 // directive. So the new line number for the current line is
                 // directive. So the new line number for the current line is
                 newLineNum -= 1;
                 newLineNum -= 1;
             }
             }
-            outputStream << std::endl;
+            outputBuffer += '\n';
             // And we are at the next line of the #line directive now.
             // And we are at the next line of the #line directive now.
             lineSync.setLineNum(newLineNum + 1);
             lineSync.setLineNum(newLineNum + 1);
         });
         });
 
 
         parseContext.setVersionCallback(
         parseContext.setVersionCallback(
-            [&lineSync, &outputStream](int line, int version, const char* str) {
+            [&lineSync, &outputBuffer](int line, int version, const char* str) {
                 lineSync.syncToLine(line);
                 lineSync.syncToLine(line);
-                outputStream << "#version " << version;
+                outputBuffer += "#version ";
+                outputBuffer += std::to_string(version);
                 if (str) {
                 if (str) {
-                    outputStream << " " << str;
+                    outputBuffer += ' ';
+                    outputBuffer += str;
                 }
                 }
             });
             });
 
 
-        parseContext.setPragmaCallback([&lineSync, &outputStream](
+        parseContext.setPragmaCallback([&lineSync, &outputBuffer](
             int line, const glslang::TVector<glslang::TString>& ops) {
             int line, const glslang::TVector<glslang::TString>& ops) {
                 lineSync.syncToLine(line);
                 lineSync.syncToLine(line);
-                outputStream << "#pragma ";
+                outputBuffer += "#pragma ";
                 for(size_t i = 0; i < ops.size(); ++i) {
                 for(size_t i = 0; i < ops.size(); ++i) {
-                    outputStream << ops[i];
+                    outputBuffer += ops[i].c_str();
                 }
                 }
         });
         });
 
 
-        parseContext.setErrorCallback([&lineSync, &outputStream](
+        parseContext.setErrorCallback([&lineSync, &outputBuffer](
             int line, const char* errorMessage) {
             int line, const char* errorMessage) {
                 lineSync.syncToLine(line);
                 lineSync.syncToLine(line);
-                outputStream << "#error " << errorMessage;
+                outputBuffer += "#error ";
+                outputBuffer += errorMessage;
         });
         });
 
 
         int lastToken = EndOfInput; // lastToken records the last token processed.
         int lastToken = EndOfInput; // lastToken records the last token processed.
@@ -1058,7 +1118,7 @@ struct DoPreprocessing {
                 // Don't emit whitespace onto empty lines.
                 // Don't emit whitespace onto empty lines.
                 // Copy any whitespace characters at the start of a line
                 // Copy any whitespace characters at the start of a line
                 // from the input to the output.
                 // from the input to the output.
-                outputStream << std::string(ppToken.loc.column - 1, ' ');
+                outputBuffer += std::string(ppToken.loc.column - 1, ' ');
             }
             }
 
 
             // Output a space in between tokens, but not at the start of a line,
             // Output a space in between tokens, but not at the start of a line,
@@ -1068,13 +1128,17 @@ struct DoPreprocessing {
                 (unNeededSpaceTokens.find((char)token) == std::string::npos) &&
                 (unNeededSpaceTokens.find((char)token) == std::string::npos) &&
                 (unNeededSpaceTokens.find((char)lastToken) == std::string::npos) &&
                 (unNeededSpaceTokens.find((char)lastToken) == std::string::npos) &&
                 (noSpaceBeforeTokens.find((char)token) == std::string::npos)) {
                 (noSpaceBeforeTokens.find((char)token) == std::string::npos)) {
-                outputStream << " ";
+                outputBuffer += ' ';
             }
             }
             lastToken = token;
             lastToken = token;
-            outputStream << ppToken.name;
+            if (token == PpAtomConstString)
+                outputBuffer += "\"";
+            outputBuffer += ppToken.name;
+            if (token == PpAtomConstString)
+                outputBuffer += "\"";
         } while (true);
         } while (true);
-        outputStream << std::endl;
-        *outputString = outputStream.str();
+        outputBuffer += '\n';
+        *outputString = std::move(outputBuffer);
 
 
         bool success = true;
         bool success = true;
         if (parseContext.getNumErrors() > 0) {
         if (parseContext.getNumErrors() > 0) {
@@ -1121,6 +1185,9 @@ struct DoFullParse{
 // Return: True if there were no issues found in preprocessing,
 // Return: True if there were no issues found in preprocessing,
 //         False if during preprocessing any unknown version, pragmas or
 //         False if during preprocessing any unknown version, pragmas or
 //         extensions were found.
 //         extensions were found.
+//
+// NOTE: Doing just preprocessing to obtain a correct preprocessed shader string
+// is not an officially supported or fully working path.
 bool PreprocessDeferred(
 bool PreprocessDeferred(
     TCompiler* compiler,
     TCompiler* compiler,
     const char* const shaderStrings[],
     const char* const shaderStrings[],
@@ -1568,14 +1635,17 @@ namespace glslang {
 
 
 #include "../Include/revision.h"
 #include "../Include/revision.h"
 
 
+#define QUOTE(s) #s
+#define STR(n) QUOTE(n)
+
 const char* GetEsslVersionString()
 const char* GetEsslVersionString()
 {
 {
-    return "OpenGL ES GLSL 3.20 glslang Khronos." GLSLANG_REVISION " " GLSLANG_DATE;
+    return "OpenGL ES GLSL 3.20 glslang Khronos. " STR(GLSLANG_MINOR_VERSION) "." STR(GLSLANG_PATCH_LEVEL);
 }
 }
 
 
 const char* GetGlslVersionString()
 const char* GetGlslVersionString()
 {
 {
-    return "4.60 glslang Khronos." GLSLANG_REVISION " " GLSLANG_DATE;
+    return "4.60 glslang Khronos. " STR(GLSLANG_MINOR_VERSION) "." STR(GLSLANG_PATCH_LEVEL);
 }
 }
 
 
 int GetKhronosToolId()
 int GetKhronosToolId()
@@ -1612,6 +1682,7 @@ TShader::TShader(EShLanguage s)
     environment.input.dialect = EShClientNone;
     environment.input.dialect = EShClientNone;
     environment.client.client = EShClientNone;
     environment.client.client = EShClientNone;
     environment.target.language = EShTargetNone;
     environment.target.language = EShTargetNone;
+    environment.target.hlslFunctionality1 = false;
 }
 }
 
 
 TShader::~TShader()
 TShader::~TShader()
@@ -1690,6 +1761,14 @@ void TShader::setAutoMapBindings(bool map)              { intermediate->setAutoM
 void TShader::setInvertY(bool invert)                   { intermediate->setInvertY(invert); }
 void TShader::setInvertY(bool invert)                   { intermediate->setInvertY(invert); }
 // Fragile: currently within one stage: simple auto-assignment of location
 // Fragile: currently within one stage: simple auto-assignment of location
 void TShader::setAutoMapLocations(bool map)             { intermediate->setAutoMapLocations(map); }
 void TShader::setAutoMapLocations(bool map)             { intermediate->setAutoMapLocations(map); }
+void TShader::addUniformLocationOverride(const char* name, int loc)
+{
+    intermediate->addUniformLocationOverride(name, loc);
+}
+void TShader::setUniformLocationBase(int base)
+{
+    intermediate->setUniformLocationBase(base);
+}
 // See comment above TDefaultHlslIoMapper in iomapper.cpp:
 // See comment above TDefaultHlslIoMapper in iomapper.cpp:
 void TShader::setHlslIoMapping(bool hlslIoMap)          { intermediate->setHlslIoMapping(hlslIoMap); }
 void TShader::setHlslIoMapping(bool hlslIoMap)          { intermediate->setHlslIoMapping(hlslIoMap); }
 void TShader::setFlattenUniformArrays(bool flatten)     { intermediate->setFlattenUniformArrays(flatten); }
 void TShader::setFlattenUniformArrays(bool flatten)     { intermediate->setFlattenUniformArrays(flatten); }
@@ -1721,6 +1800,9 @@ bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion
 
 
 // Fill in a string with the result of preprocessing ShaderStrings
 // Fill in a string with the result of preprocessing ShaderStrings
 // Returns true if all extensions, pragmas and version strings were valid.
 // Returns true if all extensions, pragmas and version strings were valid.
+//
+// NOTE: Doing just preprocessing to obtain a correct preprocessed shader string
+// is not an officially supported or fully working path.
 bool TShader::preprocess(const TBuiltInResource* builtInResources,
 bool TShader::preprocess(const TBuiltInResource* builtInResources,
                          int defaultVersion, EProfile defaultProfile,
                          int defaultVersion, EProfile defaultProfile,
                          bool forceDefaultVersionAndProfile,
                          bool forceDefaultVersionAndProfile,
@@ -1905,6 +1987,8 @@ const char* TProgram::getUniformBlockName(int index) const   { return reflection
 int TProgram::getUniformBlockSize(int index) const           { return reflection->getUniformBlock(index).size; }
 int TProgram::getUniformBlockSize(int index) const           { return reflection->getUniformBlock(index).size; }
 int TProgram::getUniformIndex(const char* name) const        { return reflection->getIndex(name); }
 int TProgram::getUniformIndex(const char* name) const        { return reflection->getIndex(name); }
 int TProgram::getUniformBinding(int index) const             { return reflection->getUniform(index).getBinding(); }
 int TProgram::getUniformBinding(int index) const             { return reflection->getUniform(index).getBinding(); }
+EShLanguageMask TProgram::getUniformStages(int index) const  { return reflection->getUniform(index).stages; }
+int TProgram::getUniformBlockBinding(int index) const        { return reflection->getUniformBlock(index).getBinding(); }
 int TProgram::getUniformBlockIndex(int index) const          { return reflection->getUniform(index).index; }
 int TProgram::getUniformBlockIndex(int index) const          { return reflection->getUniform(index).index; }
 int TProgram::getUniformBlockCounterIndex(int index) const   { return reflection->getUniformBlock(index).counterIndex; }
 int TProgram::getUniformBlockCounterIndex(int index) const   { return reflection->getUniformBlock(index).counterIndex; }
 int TProgram::getUniformType(int index) const                { return reflection->getUniform(index).glDefineType; }
 int TProgram::getUniformType(int index) const                { return reflection->getUniform(index).glDefineType; }

+ 12 - 6
src/libraries/glslang/glslang/MachineIndependent/SymbolTable.cpp

@@ -1,6 +1,8 @@
 //
 //
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2012-2013 LunarG, Inc.
 // Copyright (C) 2012-2013 LunarG, Inc.
+// Copyright (C) 2017 ARM Limited.
+// Copyright (C) 2015-2018 Google, Inc.
 //
 //
 // All rights reserved.
 // All rights reserved.
 //
 //
@@ -60,21 +62,25 @@ void TType::buildMangledName(TString& mangledName) const
     switch (basicType) {
     switch (basicType) {
     case EbtFloat:              mangledName += 'f';      break;
     case EbtFloat:              mangledName += 'f';      break;
     case EbtDouble:             mangledName += 'd';      break;
     case EbtDouble:             mangledName += 'd';      break;
-#ifdef AMD_EXTENSIONS
     case EbtFloat16:            mangledName += "f16";    break;
     case EbtFloat16:            mangledName += "f16";    break;
-#endif
     case EbtInt:                mangledName += 'i';      break;
     case EbtInt:                mangledName += 'i';      break;
     case EbtUint:               mangledName += 'u';      break;
     case EbtUint:               mangledName += 'u';      break;
-    case EbtInt64:              mangledName += "i64";    break;
-    case EbtUint64:             mangledName += "u64";    break;
-#ifdef AMD_EXTENSIONS
+    case EbtInt8:               mangledName += "i8";     break;
+    case EbtUint8:              mangledName += "u8";     break;
     case EbtInt16:              mangledName += "i16";    break;
     case EbtInt16:              mangledName += "i16";    break;
     case EbtUint16:             mangledName += "u16";    break;
     case EbtUint16:             mangledName += "u16";    break;
-#endif
+    case EbtInt64:              mangledName += "i64";    break;
+    case EbtUint64:             mangledName += "u64";    break;
     case EbtBool:               mangledName += 'b';      break;
     case EbtBool:               mangledName += 'b';      break;
     case EbtAtomicUint:         mangledName += "au";     break;
     case EbtAtomicUint:         mangledName += "au";     break;
+#ifdef NV_EXTENSIONS
+    case EbtAccStructNV:        mangledName += "asnv";   break;
+#endif
     case EbtSampler:
     case EbtSampler:
         switch (sampler.type) {
         switch (sampler.type) {
+#ifdef AMD_EXTENSIONS
+        case EbtFloat16: mangledName += "f16"; break;
+#endif
         case EbtInt:   mangledName += "i"; break;
         case EbtInt:   mangledName += "i"; break;
         case EbtUint:  mangledName += "u"; break;
         case EbtUint:  mangledName += "u"; break;
         default: break; // some compilers want this
         default: break; // some compilers want this

+ 1 - 0
src/libraries/glslang/glslang/MachineIndependent/SymbolTable.h

@@ -1,6 +1,7 @@
 //
 //
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2013 LunarG, Inc.
 // Copyright (C) 2013 LunarG, Inc.
+// Copyright (C) 2015-2018 Google, Inc.
 //
 //
 // All rights reserved.
 // All rights reserved.
 //
 //

+ 325 - 20
src/libraries/glslang/glslang/MachineIndependent/Versions.cpp

@@ -1,6 +1,8 @@
 //
 //
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2012-2013 LunarG, Inc.
 // Copyright (C) 2012-2013 LunarG, Inc.
+// Copyright (C) 2017 ARM Limited.
+// Copyright (C) 2015-2018 Google, Inc.
 //
 //
 // All rights reserved.
 // All rights reserved.
 //
 //
@@ -186,9 +188,29 @@ void TParseVersions::initializeExtensionBehavior()
     extensionBehavior[E_GL_ARB_post_depth_coverage]          = EBhDisable;
     extensionBehavior[E_GL_ARB_post_depth_coverage]          = EBhDisable;
     extensionBehavior[E_GL_ARB_shader_viewport_layer_array]  = EBhDisable;
     extensionBehavior[E_GL_ARB_shader_viewport_layer_array]  = EBhDisable;
 
 
+    extensionBehavior[E_GL_KHR_shader_subgroup_basic]            = EBhDisable;
+    extensionBehavior[E_GL_KHR_shader_subgroup_vote]             = EBhDisable;
+    extensionBehavior[E_GL_KHR_shader_subgroup_arithmetic]       = EBhDisable;
+    extensionBehavior[E_GL_KHR_shader_subgroup_ballot]           = EBhDisable;
+    extensionBehavior[E_GL_KHR_shader_subgroup_shuffle]          = EBhDisable;
+    extensionBehavior[E_GL_KHR_shader_subgroup_shuffle_relative] = EBhDisable;
+    extensionBehavior[E_GL_KHR_shader_subgroup_clustered]        = EBhDisable;
+    extensionBehavior[E_GL_KHR_shader_subgroup_quad]             = EBhDisable;
+    extensionBehavior[E_GL_KHR_memory_scope_semantics]           = EBhDisable;
+
+    extensionBehavior[E_GL_EXT_shader_atomic_int64]              = EBhDisable;
+
     extensionBehavior[E_GL_EXT_shader_non_constant_global_initializers] = EBhDisable;
     extensionBehavior[E_GL_EXT_shader_non_constant_global_initializers] = EBhDisable;
     extensionBehavior[E_GL_EXT_shader_image_load_formatted]             = EBhDisable;
     extensionBehavior[E_GL_EXT_shader_image_load_formatted]             = EBhDisable;
     extensionBehavior[E_GL_EXT_post_depth_coverage]                     = EBhDisable;
     extensionBehavior[E_GL_EXT_post_depth_coverage]                     = EBhDisable;
+    extensionBehavior[E_GL_EXT_control_flow_attributes]                 = EBhDisable;
+    extensionBehavior[E_GL_EXT_nonuniform_qualifier]                    = EBhDisable;
+    extensionBehavior[E_GL_EXT_samplerless_texture_functions]           = EBhDisable;
+    extensionBehavior[E_GL_EXT_scalar_block_layout]                     = EBhDisable;
+    extensionBehavior[E_GL_EXT_fragment_invocation_density]             = EBhDisable;
+
+    extensionBehavior[E_GL_EXT_shader_16bit_storage]                    = EBhDisable;
+    extensionBehavior[E_GL_EXT_shader_8bit_storage]                     = EBhDisable;
 
 
     // #line and #include
     // #line and #include
     extensionBehavior[E_GL_GOOGLE_cpp_style_line_directive]          = EBhDisable;
     extensionBehavior[E_GL_GOOGLE_cpp_style_line_directive]          = EBhDisable;
@@ -204,6 +226,7 @@ void TParseVersions::initializeExtensionBehavior()
     extensionBehavior[E_GL_AMD_gpu_shader_int16]                     = EBhDisable;
     extensionBehavior[E_GL_AMD_gpu_shader_int16]                     = EBhDisable;
     extensionBehavior[E_GL_AMD_shader_image_load_store_lod]          = EBhDisable;
     extensionBehavior[E_GL_AMD_shader_image_load_store_lod]          = EBhDisable;
     extensionBehavior[E_GL_AMD_shader_fragment_mask]                 = EBhDisable;
     extensionBehavior[E_GL_AMD_shader_fragment_mask]                 = EBhDisable;
+    extensionBehavior[E_GL_AMD_gpu_shader_half_float_fetch]          = EBhDisable;
 #endif
 #endif
 
 
 #ifdef NV_EXTENSIONS
 #ifdef NV_EXTENSIONS
@@ -214,6 +237,14 @@ void TParseVersions::initializeExtensionBehavior()
     extensionBehavior[E_GL_NVX_multiview_per_view_attributes]        = EBhDisable;
     extensionBehavior[E_GL_NVX_multiview_per_view_attributes]        = EBhDisable;
     extensionBehavior[E_GL_NV_shader_atomic_int64]                   = EBhDisable;
     extensionBehavior[E_GL_NV_shader_atomic_int64]                   = EBhDisable;
     extensionBehavior[E_GL_NV_conservative_raster_underestimation]   = EBhDisable;
     extensionBehavior[E_GL_NV_conservative_raster_underestimation]   = EBhDisable;
+    extensionBehavior[E_GL_NV_shader_noperspective_interpolation]    = EBhDisable;
+    extensionBehavior[E_GL_NV_shader_subgroup_partitioned]           = EBhDisable;
+    extensionBehavior[E_GL_NV_shading_rate_image]                    = EBhDisable;
+    extensionBehavior[E_GL_NV_ray_tracing]                           = EBhDisable;
+    extensionBehavior[E_GL_NV_fragment_shader_barycentric]           = EBhDisable;
+    extensionBehavior[E_GL_NV_compute_shader_derivatives]            = EBhDisable;
+    extensionBehavior[E_GL_NV_shader_texture_footprint]              = EBhDisable;
+    extensionBehavior[E_GL_NV_mesh_shader]                           = EBhDisable;
 #endif
 #endif
 
 
     // AEP
     // AEP
@@ -251,6 +282,16 @@ void TParseVersions::initializeExtensionBehavior()
     // OVR extensions
     // OVR extensions
     extensionBehavior[E_GL_OVR_multiview]                = EBhDisable;
     extensionBehavior[E_GL_OVR_multiview]                = EBhDisable;
     extensionBehavior[E_GL_OVR_multiview2]               = EBhDisable;
     extensionBehavior[E_GL_OVR_multiview2]               = EBhDisable;
+
+    // explicit types
+    extensionBehavior[E_GL_EXT_shader_explicit_arithmetic_types]         = EBhDisable;
+    extensionBehavior[E_GL_EXT_shader_explicit_arithmetic_types_int8]    = EBhDisable;
+    extensionBehavior[E_GL_EXT_shader_explicit_arithmetic_types_int16]   = EBhDisable;
+    extensionBehavior[E_GL_EXT_shader_explicit_arithmetic_types_int32]   = EBhDisable;
+    extensionBehavior[E_GL_EXT_shader_explicit_arithmetic_types_int64]   = EBhDisable;
+    extensionBehavior[E_GL_EXT_shader_explicit_arithmetic_types_float16] = EBhDisable;
+    extensionBehavior[E_GL_EXT_shader_explicit_arithmetic_types_float32] = EBhDisable;
+    extensionBehavior[E_GL_EXT_shader_explicit_arithmetic_types_float64] = EBhDisable;
 }
 }
 
 
 // Get code that is not part of a shared symbol table, is specific to this shader,
 // Get code that is not part of a shared symbol table, is specific to this shader,
@@ -299,6 +340,13 @@ void TParseVersions::getPreamble(std::string& preamble)
             "#define GL_OES_texture_cube_map_array 1\n"
             "#define GL_OES_texture_cube_map_array 1\n"
             "#define GL_EXT_shader_non_constant_global_initializers 1\n"
             "#define GL_EXT_shader_non_constant_global_initializers 1\n"
             ;
             ;
+
+#ifdef NV_EXTENSIONS
+            if (profile == EEsProfile && version >= 300) {
+                preamble += "#define GL_NV_shader_noperspective_interpolation 1\n";
+            }
+#endif
+
     } else {
     } else {
         preamble =
         preamble =
             "#define GL_FRAGMENT_PRECISION_HIGH 1\n"
             "#define GL_FRAGMENT_PRECISION_HIGH 1\n"
@@ -331,6 +379,25 @@ void TParseVersions::getPreamble(std::string& preamble)
             "#define GL_EXT_shader_non_constant_global_initializers 1\n"
             "#define GL_EXT_shader_non_constant_global_initializers 1\n"
             "#define GL_EXT_shader_image_load_formatted 1\n"
             "#define GL_EXT_shader_image_load_formatted 1\n"
             "#define GL_EXT_post_depth_coverage 1\n"
             "#define GL_EXT_post_depth_coverage 1\n"
+            "#define GL_EXT_control_flow_attributes 1\n"
+            "#define GL_EXT_nonuniform_qualifier 1\n"
+            "#define GL_EXT_shader_16bit_storage 1\n"
+            "#define GL_EXT_shader_8bit_storage 1\n"
+            "#define GL_EXT_samplerless_texture_functions 1\n"
+            "#define GL_EXT_scalar_block_layout 1\n"
+            "#define GL_EXT_fragment_invocation_density 1\n"
+
+            // GL_KHR_shader_subgroup
+            "#define GL_KHR_shader_subgroup_basic 1\n"
+            "#define GL_KHR_shader_subgroup_vote 1\n"
+            "#define GL_KHR_shader_subgroup_arithmetic 1\n"
+            "#define GL_KHR_shader_subgroup_ballot 1\n"
+            "#define GL_KHR_shader_subgroup_shuffle 1\n"
+            "#define GL_KHR_shader_subgroup_shuffle_relative 1\n"
+            "#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"
 
 
 #ifdef AMD_EXTENSIONS
 #ifdef AMD_EXTENSIONS
             "#define GL_AMD_shader_ballot 1\n"
             "#define GL_AMD_shader_ballot 1\n"
@@ -342,6 +409,7 @@ void TParseVersions::getPreamble(std::string& preamble)
             "#define GL_AMD_gpu_shader_int16 1\n"
             "#define GL_AMD_gpu_shader_int16 1\n"
             "#define GL_AMD_shader_image_load_store_lod 1\n"
             "#define GL_AMD_shader_image_load_store_lod 1\n"
             "#define GL_AMD_shader_fragment_mask 1\n"
             "#define GL_AMD_shader_fragment_mask 1\n"
+            "#define GL_AMD_gpu_shader_half_float_fetch 1\n"
 #endif
 #endif
 
 
 #ifdef NV_EXTENSIONS
 #ifdef NV_EXTENSIONS
@@ -350,7 +418,22 @@ void TParseVersions::getPreamble(std::string& preamble)
             "#define GL_NV_viewport_array2 1\n"
             "#define GL_NV_viewport_array2 1\n"
             "#define GL_NV_shader_atomic_int64 1\n"
             "#define GL_NV_shader_atomic_int64 1\n"
             "#define GL_NV_conservative_raster_underestimation 1\n"
             "#define GL_NV_conservative_raster_underestimation 1\n"
+            "#define GL_NV_shader_subgroup_partitioned 1\n"
+            "#define GL_NV_shading_rate_image 1\n"
+            "#define GL_NV_ray_tracing 1\n"
+            "#define GL_NV_fragment_shader_barycentric 1\n"
+            "#define GL_NV_compute_shader_derivatives 1\n"
+            "#define GL_NV_shader_texture_footprint 1\n"
+            "#define GL_NV_mesh_shader 1\n"
 #endif
 #endif
+            "#define GL_EXT_shader_explicit_arithmetic_types 1\n"
+            "#define GL_EXT_shader_explicit_arithmetic_types_int8 1\n"
+            "#define GL_EXT_shader_explicit_arithmetic_types_int16 1\n"
+            "#define GL_EXT_shader_explicit_arithmetic_types_int32 1\n"
+            "#define GL_EXT_shader_explicit_arithmetic_types_int64 1\n"
+            "#define GL_EXT_shader_explicit_arithmetic_types_float16 1\n"
+            "#define GL_EXT_shader_explicit_arithmetic_types_float32 1\n"
+            "#define GL_EXT_shader_explicit_arithmetic_types_float64 1\n"
             ;
             ;
 
 
         if (version >= 150) {
         if (version >= 150) {
@@ -429,6 +512,16 @@ const char* StageName(EShLanguage stage)
     case EShLangGeometry:       return "geometry";
     case EShLangGeometry:       return "geometry";
     case EShLangFragment:       return "fragment";
     case EShLangFragment:       return "fragment";
     case EShLangCompute:        return "compute";
     case EShLangCompute:        return "compute";
+#ifdef NV_EXTENSIONS
+    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 EShLangMeshNV:         return "mesh";
+    case EShLangTaskNV:         return "task";
+#endif
     default:                    return "unknown stage";
     default:                    return "unknown stage";
     }
     }
 }
 }
@@ -573,7 +666,8 @@ bool TParseVersions::checkExtensionsRequested(const TSourceLoc& loc, int numExte
 //
 //
 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;
+    if (checkExtensionsRequested(loc, numExtensions, extensions, featureDesc))
+        return;
 
 
     // If we get this far, give errors explaining what extensions are needed
     // If we get this far, give errors explaining what extensions are needed
     if (numExtensions == 1)
     if (numExtensions == 1)
@@ -591,7 +685,8 @@ void TParseVersions::requireExtensions(const TSourceLoc& loc, int numExtensions,
 //
 //
 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;
+    if (checkExtensionsRequested(loc, numExtensions, extensions, featureDesc))
+        return;
 
 
     // If we get this far, give errors explaining what extensions are needed
     // If we get this far, give errors explaining what extensions are needed
     if (numExtensions == 1)
     if (numExtensions == 1)
@@ -629,7 +724,8 @@ bool TParseVersions::extensionTurnedOn(const char* const extension)
 bool TParseVersions::extensionsTurnedOn(int numExtensions, const char* const extensions[])
 bool TParseVersions::extensionsTurnedOn(int numExtensions, const char* const extensions[])
 {
 {
     for (int i = 0; i < numExtensions; ++i) {
     for (int i = 0; i < numExtensions; ++i) {
-        if (extensionTurnedOn(extensions[i])) return true;
+        if (extensionTurnedOn(extensions[i]))
+            return true;
     }
     }
     return false;
     return false;
 }
 }
@@ -654,6 +750,9 @@ void TParseVersions::updateExtensionBehavior(int line, const char* extension, co
         return;
         return;
     }
     }
 
 
+    // check if extension is used with correct shader stage
+    checkExtensionStage(getCurrentLoc(), extension);
+
     // update the requested extension
     // update the requested extension
     updateExtensionBehavior(extension, behavior);
     updateExtensionBehavior(extension, behavior);
 
 
@@ -685,6 +784,25 @@ void TParseVersions::updateExtensionBehavior(int line, const char* extension, co
         updateExtensionBehavior(line, "GL_OES_shader_io_blocks", behaviorString);
         updateExtensionBehavior(line, "GL_OES_shader_io_blocks", behaviorString);
     else if (strcmp(extension, "GL_GOOGLE_include_directive") == 0)
     else if (strcmp(extension, "GL_GOOGLE_include_directive") == 0)
         updateExtensionBehavior(line, "GL_GOOGLE_cpp_style_line_directive", behaviorString);
         updateExtensionBehavior(line, "GL_GOOGLE_cpp_style_line_directive", behaviorString);
+    // subgroup_* to subgroup_basic
+    else if (strcmp(extension, "GL_KHR_shader_subgroup_vote") == 0)
+        updateExtensionBehavior(line, "GL_KHR_shader_subgroup_basic", behaviorString);
+    else if (strcmp(extension, "GL_KHR_shader_subgroup_arithmetic") == 0)
+        updateExtensionBehavior(line, "GL_KHR_shader_subgroup_basic", behaviorString);
+    else if (strcmp(extension, "GL_KHR_shader_subgroup_ballot") == 0)
+        updateExtensionBehavior(line, "GL_KHR_shader_subgroup_basic", behaviorString);
+    else if (strcmp(extension, "GL_KHR_shader_subgroup_shuffle") == 0)
+        updateExtensionBehavior(line, "GL_KHR_shader_subgroup_basic", behaviorString);
+    else if (strcmp(extension, "GL_KHR_shader_subgroup_shuffle_relative") == 0)
+        updateExtensionBehavior(line, "GL_KHR_shader_subgroup_basic", behaviorString);
+    else if (strcmp(extension, "GL_KHR_shader_subgroup_clustered") == 0)
+        updateExtensionBehavior(line, "GL_KHR_shader_subgroup_basic", behaviorString);
+    else if (strcmp(extension, "GL_KHR_shader_subgroup_quad") == 0)
+        updateExtensionBehavior(line, "GL_KHR_shader_subgroup_basic", behaviorString);
+#ifdef NV_EXTENSIONS
+    else if (strcmp(extension, "GL_NV_shader_subgroup_partitioned") == 0)
+        updateExtensionBehavior(line, "GL_KHR_shader_subgroup_basic", behaviorString);
+#endif
 }
 }
 
 
 void TParseVersions::updateExtensionBehavior(const char* extension, TExtensionBehavior behavior)
 void TParseVersions::updateExtensionBehavior(const char* extension, TExtensionBehavior behavior)
@@ -727,6 +845,20 @@ void TParseVersions::updateExtensionBehavior(const char* extension, TExtensionBe
     }
     }
 }
 }
 
 
+// Check if extension is used with correct shader stage.
+void TParseVersions::checkExtensionStage(const TSourceLoc& loc, const char * const extension)
+{
+#ifdef NV_EXTENSIONS
+    // GL_NV_mesh_shader extension is only allowed in task/mesh shaders
+    if (strcmp(extension, "GL_NV_mesh_shader") == 0) {
+        requireStage(loc, (EShLanguageMask)(EShLangTaskNVMask | EShLangMeshNVMask | EShLangFragmentMask),
+                     "#extension GL_NV_mesh_shader");
+        profileRequires(loc, ECoreProfile, 450, 0, "#extension GL_NV_mesh_shader");
+        profileRequires(loc, EEsProfile, 320, 0, "#extension GL_NV_mesh_shader");
+    }
+#endif
+}
+
 // Call for any operation needing full GLSL integer data-type support.
 // Call for any operation needing full GLSL integer data-type support.
 void TParseVersions::fullIntegerCheck(const TSourceLoc& loc, const char* op)
 void TParseVersions::fullIntegerCheck(const TSourceLoc& loc, const char* op)
 {
 {
@@ -738,42 +870,215 @@ void TParseVersions::fullIntegerCheck(const TSourceLoc& loc, const char* op)
 void TParseVersions::doubleCheck(const TSourceLoc& loc, const char* op)
 void TParseVersions::doubleCheck(const TSourceLoc& loc, const char* op)
 {
 {
     requireProfile(loc, ECoreProfile | ECompatibilityProfile, op);
     requireProfile(loc, ECoreProfile | ECompatibilityProfile, op);
-    profileRequires(loc, ECoreProfile, 400, nullptr, op);
-    profileRequires(loc, ECompatibilityProfile, 400, nullptr, op);
+    profileRequires(loc, ECoreProfile | ECompatibilityProfile, 400, nullptr, op);
+}
+
+// Call for any operation needing GLSL float16 data-type support.
+void TParseVersions::float16Check(const TSourceLoc& loc, const char* op, bool builtIn)
+{
+    if (!builtIn) {
+        const char* const extensions[] = {
+#if AMD_EXTENSIONS
+                                           E_GL_AMD_gpu_shader_half_float,
+#endif
+                                           E_GL_EXT_shader_explicit_arithmetic_types,
+                                           E_GL_EXT_shader_explicit_arithmetic_types_float16};
+        requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, op);
+    }
+}
+
+bool TParseVersions::float16Arithmetic()
+{
+    const char* const extensions[] = {
+#if AMD_EXTENSIONS
+                                       E_GL_AMD_gpu_shader_half_float,
+#endif
+                                       E_GL_EXT_shader_explicit_arithmetic_types,
+                                       E_GL_EXT_shader_explicit_arithmetic_types_float16};
+    return extensionsTurnedOn(sizeof(extensions)/sizeof(extensions[0]), extensions);
+}
+
+bool TParseVersions::int16Arithmetic()
+{
+    const char* const extensions[] = {
+#if AMD_EXTENSIONS
+                                       E_GL_AMD_gpu_shader_int16,
+#endif
+                                       E_GL_EXT_shader_explicit_arithmetic_types,
+                                       E_GL_EXT_shader_explicit_arithmetic_types_int16};
+    return extensionsTurnedOn(sizeof(extensions)/sizeof(extensions[0]), extensions);
+}
+
+bool TParseVersions::int8Arithmetic()
+{
+    const char* const extensions[] = {
+                                       E_GL_EXT_shader_explicit_arithmetic_types,
+                                       E_GL_EXT_shader_explicit_arithmetic_types_int8};
+    return extensionsTurnedOn(sizeof(extensions)/sizeof(extensions[0]), extensions);
+}
+
+void TParseVersions::requireFloat16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc)
+{
+    TString combined;
+    combined = op;
+    combined += ": ";
+    combined += featureDesc;
+
+    const char* const extensions[] = {
+#if AMD_EXTENSIONS
+                                       E_GL_AMD_gpu_shader_half_float,
+#endif
+                                       E_GL_EXT_shader_explicit_arithmetic_types,
+                                       E_GL_EXT_shader_explicit_arithmetic_types_float16};
+    requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, combined.c_str());
+}
+
+void TParseVersions::requireInt16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc)
+{
+    TString combined;
+    combined = op;
+    combined += ": ";
+    combined += featureDesc;
+
+    const char* const extensions[] = {
+#if AMD_EXTENSIONS
+                                       E_GL_AMD_gpu_shader_int16,
+#endif
+                                       E_GL_EXT_shader_explicit_arithmetic_types,
+                                       E_GL_EXT_shader_explicit_arithmetic_types_int16};
+    requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, combined.c_str());
+}
+
+void TParseVersions::requireInt8Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc)
+{
+    TString combined;
+    combined = op;
+    combined += ": ";
+    combined += featureDesc;
+
+    const char* const extensions[] = {
+                                       E_GL_EXT_shader_explicit_arithmetic_types,
+                                       E_GL_EXT_shader_explicit_arithmetic_types_int8};
+    requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, combined.c_str());
+}
+
+void TParseVersions::float16ScalarVectorCheck(const TSourceLoc& loc, const char* op, bool builtIn)
+{
+    if (!builtIn) {
+        const char* const extensions[] = {
+#if AMD_EXTENSIONS
+                                           E_GL_AMD_gpu_shader_half_float,
+#endif
+                                           E_GL_EXT_shader_16bit_storage,
+                                           E_GL_EXT_shader_explicit_arithmetic_types,
+                                           E_GL_EXT_shader_explicit_arithmetic_types_float16};
+        requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, op);
+    }
+}
+
+// Call for any operation needing GLSL float32 data-type support.
+void TParseVersions::explicitFloat32Check(const TSourceLoc& loc, const char* op, bool builtIn)
+{
+    if (!builtIn) {
+        const char* const extensions[2] = {E_GL_EXT_shader_explicit_arithmetic_types,
+                                           E_GL_EXT_shader_explicit_arithmetic_types_float32};
+        requireExtensions(loc, 2, extensions, op);
+    }
+}
+
+// Call for any operation needing GLSL float64 data-type support.
+void TParseVersions::explicitFloat64Check(const TSourceLoc& loc, const char* op, bool builtIn)
+{
+    if (!builtIn) {
+        const char* const extensions[2] = {E_GL_EXT_shader_explicit_arithmetic_types,
+                                           E_GL_EXT_shader_explicit_arithmetic_types_float64};
+        requireExtensions(loc, 2, extensions, op);
+        requireProfile(loc, ECoreProfile | ECompatibilityProfile, op);
+        profileRequires(loc, ECoreProfile | ECompatibilityProfile, 400, nullptr, op);
+    }
+}
+
+// Call for any operation needing GLSL explicit int8 data-type support.
+void TParseVersions::explicitInt8Check(const TSourceLoc& loc, const char* op, bool builtIn)
+{
+    if (! builtIn) {
+        const char* const extensions[2] = {E_GL_EXT_shader_explicit_arithmetic_types,
+                                           E_GL_EXT_shader_explicit_arithmetic_types_int8};
+        requireExtensions(loc, 2, extensions, op);
+    }
 }
 }
 
 
 #ifdef AMD_EXTENSIONS
 #ifdef AMD_EXTENSIONS
-// Call for any operation needing GLSL 16-bit integer data-type support.
-void TParseVersions::int16Check(const TSourceLoc& loc, const char* op, bool builtIn)
+// Call for any operation needing GLSL float16 opaque-type support
+void TParseVersions::float16OpaqueCheck(const TSourceLoc& loc, const char* op, bool builtIn)
 {
 {
     if (! builtIn) {
     if (! builtIn) {
-        requireExtensions(loc, 1, &E_GL_AMD_gpu_shader_int16, "shader int16");
+        requireExtensions(loc, 1, &E_GL_AMD_gpu_shader_half_float_fetch, op);
         requireProfile(loc, ECoreProfile | ECompatibilityProfile, op);
         requireProfile(loc, ECoreProfile | ECompatibilityProfile, op);
-        profileRequires(loc, ECoreProfile, 450, nullptr, op);
-        profileRequires(loc, ECompatibilityProfile, 450, nullptr, op);
+        profileRequires(loc, ECoreProfile | ECompatibilityProfile, 400, nullptr, op);
     }
     }
 }
 }
+#endif
 
 
-// Call for any operation needing GLSL float16 data-type support.
-void TParseVersions::float16Check(const TSourceLoc& loc, const char* op, bool builtIn)
+// Call for any operation needing GLSL explicit int16 data-type support.
+void TParseVersions::explicitInt16Check(const TSourceLoc& loc, const char* op, bool builtIn)
 {
 {
     if (! builtIn) {
     if (! builtIn) {
-        requireExtensions(loc, 1, &E_GL_AMD_gpu_shader_half_float, "shader half float");
-        requireProfile(loc, ECoreProfile | ECompatibilityProfile, op);
-        profileRequires(loc, ECoreProfile, 450, nullptr, op);
-        profileRequires(loc, ECompatibilityProfile, 450, nullptr, op);
+    	const char* const extensions[] = {
+#if AMD_EXTENSIONS
+                                           E_GL_AMD_gpu_shader_int16,
+#endif
+                                           E_GL_EXT_shader_explicit_arithmetic_types,
+                                           E_GL_EXT_shader_explicit_arithmetic_types_int16};
+        requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, op);
     }
     }
 }
 }
+
+void TParseVersions::int16ScalarVectorCheck(const TSourceLoc& loc, const char* op, bool builtIn)
+{
+    if (! builtIn) {
+    	const char* const extensions[] = {
+#if AMD_EXTENSIONS
+                                           E_GL_AMD_gpu_shader_int16,
 #endif
 #endif
+                                           E_GL_EXT_shader_16bit_storage,
+                                           E_GL_EXT_shader_explicit_arithmetic_types,
+                                           E_GL_EXT_shader_explicit_arithmetic_types_int16};
+        requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, op);
+    }
+}
+
+void TParseVersions::int8ScalarVectorCheck(const TSourceLoc& loc, const char* op, bool builtIn)
+{
+    if (! builtIn) {
+    	const char* const extensions[] = {
+                                           E_GL_EXT_shader_8bit_storage,
+                                           E_GL_EXT_shader_explicit_arithmetic_types,
+                                           E_GL_EXT_shader_explicit_arithmetic_types_int8};
+        requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, op);
+    }
+}
+
+// Call for any operation needing GLSL explicit int32 data-type support.
+void TParseVersions::explicitInt32Check(const TSourceLoc& loc, const char* op, bool builtIn)
+{
+    if (! builtIn) {
+        const char* const extensions[2] = {E_GL_EXT_shader_explicit_arithmetic_types,
+                                           E_GL_EXT_shader_explicit_arithmetic_types_int32};
+        requireExtensions(loc, 2, extensions, op);
+    }
+}
 
 
 // Call for any operation needing GLSL 64-bit integer data-type support.
 // Call for any operation needing GLSL 64-bit integer data-type support.
 void TParseVersions::int64Check(const TSourceLoc& loc, const char* op, bool builtIn)
 void TParseVersions::int64Check(const TSourceLoc& loc, const char* op, bool builtIn)
 {
 {
     if (! builtIn) {
     if (! builtIn) {
-        requireExtensions(loc, 1, &E_GL_ARB_gpu_shader_int64, "shader int64");
+        const char* const extensions[3] = {E_GL_ARB_gpu_shader_int64,
+                                           E_GL_EXT_shader_explicit_arithmetic_types,
+                                           E_GL_EXT_shader_explicit_arithmetic_types_int64};
+        requireExtensions(loc, 3, extensions, op);
         requireProfile(loc, ECoreProfile | ECompatibilityProfile, op);
         requireProfile(loc, ECoreProfile | ECompatibilityProfile, op);
-        profileRequires(loc, ECoreProfile, 450, nullptr, op);
-        profileRequires(loc, ECompatibilityProfile, 450, nullptr, op);
+        profileRequires(loc, ECoreProfile | ECompatibilityProfile, 400, nullptr, op);
     }
     }
 }
 }
 
 
@@ -787,7 +1092,7 @@ void TParseVersions::spvRemoved(const TSourceLoc& loc, const char* op)
 // Call for any operation removed because Vulkan SPIR-V is being generated.
 // Call for any operation removed because Vulkan SPIR-V is being generated.
 void TParseVersions::vulkanRemoved(const TSourceLoc& loc, const char* op)
 void TParseVersions::vulkanRemoved(const TSourceLoc& loc, const char* op)
 {
 {
-    if (spvVersion.vulkan >= 100)
+    if (spvVersion.vulkan > 0)
         error(loc, "not allowed when using GLSL for Vulkan", op, "");
         error(loc, "not allowed when using GLSL for Vulkan", op, "");
 }
 }
 
 

+ 46 - 4
src/libraries/glslang/glslang/MachineIndependent/Versions.h

@@ -1,6 +1,8 @@
 //
 //
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2012-2013 LunarG, Inc.
 // Copyright (C) 2012-2013 LunarG, Inc.
+// Copyright (C) 2017 ARM Limited.
+// Copyright (C) 2015-2018 Google, Inc.
 //
 //
 // All rights reserved.
 // All rights reserved.
 //
 //
@@ -83,7 +85,7 @@ struct SpvVersion {
     SpvVersion() : spv(0), vulkanGlsl(0), vulkan(0), openGl(0) {}
     SpvVersion() : spv(0), vulkanGlsl(0), vulkan(0), openGl(0) {}
     unsigned int spv; // the version of SPIR-V to target, as defined by "word 1" of the SPIR-V binary header
     unsigned int spv; // the version of SPIR-V to target, as defined by "word 1" of the SPIR-V binary header
     int vulkanGlsl;   // the version of GLSL semantics for Vulkan, from GL_KHR_vulkan_glsl, for "#define VULKAN XXX"
     int vulkanGlsl;   // the version of GLSL semantics for Vulkan, from GL_KHR_vulkan_glsl, for "#define VULKAN XXX"
-    int vulkan;       // the version of Vulkan, for which SPIR-V execution environment rules to use (100 means 1.0)
+    int vulkan;       // the version of Vulkan, for which SPIR-V execution environment rules to use
     int openGl;       // the version of GLSL semantics for OpenGL, from GL_ARB_gl_spirv, for "#define GL_SPIRV XXX"
     int openGl;       // the version of GLSL semantics for OpenGL, from GL_ARB_gl_spirv, for "#define GL_SPIRV XXX"
 };
 };
 
 
@@ -140,13 +142,34 @@ const char* const E_GL_ARB_shader_stencil_export        = "GL_ARB_shader_stencil
 const char* const E_GL_ARB_post_depth_coverage          = "GL_ARB_post_depth_coverage";
 const char* const E_GL_ARB_post_depth_coverage          = "GL_ARB_post_depth_coverage";
 const char* const E_GL_ARB_shader_viewport_layer_array  = "GL_ARB_shader_viewport_layer_array";
 const char* const E_GL_ARB_shader_viewport_layer_array  = "GL_ARB_shader_viewport_layer_array";
 
 
+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";
+const char* const E_GL_KHR_shader_subgroup_arithmetic       = "GL_KHR_shader_subgroup_arithmetic";
+const char* const E_GL_KHR_shader_subgroup_ballot           = "GL_KHR_shader_subgroup_ballot";
+const char* const E_GL_KHR_shader_subgroup_shuffle          = "GL_KHR_shader_subgroup_shuffle";
+const char* const E_GL_KHR_shader_subgroup_shuffle_relative = "GL_KHR_shader_subgroup_shuffle_relative";
+const char* const E_GL_KHR_shader_subgroup_clustered        = "GL_KHR_shader_subgroup_clustered";
+const char* const E_GL_KHR_shader_subgroup_quad             = "GL_KHR_shader_subgroup_quad";
+const char* const E_GL_KHR_memory_scope_semantics           = "GL_KHR_memory_scope_semantics";
+
+const char* const E_GL_EXT_shader_atomic_int64              = "GL_EXT_shader_atomic_int64";
+
 const char* const E_GL_EXT_shader_non_constant_global_initializers = "GL_EXT_shader_non_constant_global_initializers";
 const char* const E_GL_EXT_shader_non_constant_global_initializers = "GL_EXT_shader_non_constant_global_initializers";
 const char* const E_GL_EXT_shader_image_load_formatted = "GL_EXT_shader_image_load_formatted";
 const char* const E_GL_EXT_shader_image_load_formatted = "GL_EXT_shader_image_load_formatted";
 
 
+const char* const E_GL_EXT_shader_16bit_storage             = "GL_EXT_shader_16bit_storage";
+const char* const E_GL_EXT_shader_8bit_storage              = "GL_EXT_shader_8bit_storage";
+
+
 // EXT extensions
 // EXT extensions
-const char* const E_GL_EXT_device_group                 = "GL_EXT_device_group";
-const char* const E_GL_EXT_multiview                    = "GL_EXT_multiview";
-const char* const E_GL_EXT_post_depth_coverage          = "GL_EXT_post_depth_coverage";
+const char* const E_GL_EXT_device_group                     = "GL_EXT_device_group";
+const char* const E_GL_EXT_multiview                        = "GL_EXT_multiview";
+const char* const E_GL_EXT_post_depth_coverage              = "GL_EXT_post_depth_coverage";
+const char* const E_GL_EXT_control_flow_attributes          = "GL_EXT_control_flow_attributes";
+const char* const E_GL_EXT_nonuniform_qualifier             = "GL_EXT_nonuniform_qualifier";
+const char* const E_GL_EXT_samplerless_texture_functions    = "GL_EXT_samplerless_texture_functions";
+const char* const E_GL_EXT_scalar_block_layout              = "GL_EXT_scalar_block_layout";
+const char* const E_GL_EXT_fragment_invocation_density      = "GL_EXT_fragment_invocation_density";
 
 
 // Arrays of extensions for the above viewportEXTs duplications
 // Arrays of extensions for the above viewportEXTs duplications
 
 
@@ -174,6 +197,7 @@ const char* const E_GL_AMD_texture_gather_bias_lod              = "GL_AMD_textur
 const char* const E_GL_AMD_gpu_shader_int16                     = "GL_AMD_gpu_shader_int16";
 const char* const E_GL_AMD_gpu_shader_int16                     = "GL_AMD_gpu_shader_int16";
 const char* const E_GL_AMD_shader_image_load_store_lod          = "GL_AMD_shader_image_load_store_lod";
 const char* const E_GL_AMD_shader_image_load_store_lod          = "GL_AMD_shader_image_load_store_lod";
 const char* const E_GL_AMD_shader_fragment_mask                 = "GL_AMD_shader_fragment_mask";
 const char* const E_GL_AMD_shader_fragment_mask                 = "GL_AMD_shader_fragment_mask";
+const char* const E_GL_AMD_gpu_shader_half_float_fetch          = "GL_AMD_gpu_shader_half_float_fetch";
 #endif
 #endif
 
 
 #ifdef NV_EXTENSIONS
 #ifdef NV_EXTENSIONS
@@ -185,6 +209,14 @@ const char* const E_GL_NV_stereo_view_rendering                 = "GL_NV_stereo_
 const char* const E_GL_NVX_multiview_per_view_attributes        = "GL_NVX_multiview_per_view_attributes";
 const char* const E_GL_NVX_multiview_per_view_attributes        = "GL_NVX_multiview_per_view_attributes";
 const char* const E_GL_NV_shader_atomic_int64                   = "GL_NV_shader_atomic_int64";
 const char* const E_GL_NV_shader_atomic_int64                   = "GL_NV_shader_atomic_int64";
 const char* const E_GL_NV_conservative_raster_underestimation   = "GL_NV_conservative_raster_underestimation";
 const char* const E_GL_NV_conservative_raster_underestimation   = "GL_NV_conservative_raster_underestimation";
+const char* const E_GL_NV_shader_noperspective_interpolation    = "GL_NV_shader_noperspective_interpolation";
+const char* const E_GL_NV_shader_subgroup_partitioned           = "GL_NV_shader_subgroup_partitioned";
+const char* const E_GL_NV_shading_rate_image                    = "GL_NV_shading_rate_image";
+const char* const E_GL_NV_ray_tracing                           = "GL_NV_ray_tracing";
+const char* const E_GL_NV_fragment_shader_barycentric           = "GL_NV_fragment_shader_barycentric";
+const char* const E_GL_NV_compute_shader_derivatives            = "GL_NV_compute_shader_derivatives";
+const char* const E_GL_NV_shader_texture_footprint              = "GL_NV_shader_texture_footprint";
+const char* const E_GL_NV_mesh_shader                           = "GL_NV_mesh_shader";
 
 
 // Arrays of extensions for the above viewportEXTs duplications
 // Arrays of extensions for the above viewportEXTs duplications
 
 
@@ -220,6 +252,16 @@ const char* const E_GL_OES_tessellation_point_size              = "GL_OES_tessel
 const char* const E_GL_OES_texture_buffer                       = "GL_OES_texture_buffer";
 const char* const E_GL_OES_texture_buffer                       = "GL_OES_texture_buffer";
 const char* const E_GL_OES_texture_cube_map_array               = "GL_OES_texture_cube_map_array";
 const char* const E_GL_OES_texture_cube_map_array               = "GL_OES_texture_cube_map_array";
 
 
+// KHX
+const char* const E_GL_EXT_shader_explicit_arithmetic_types          = "GL_EXT_shader_explicit_arithmetic_types";
+const char* const E_GL_EXT_shader_explicit_arithmetic_types_int8     = "GL_EXT_shader_explicit_arithmetic_types_int8";
+const char* const E_GL_EXT_shader_explicit_arithmetic_types_int16    = "GL_EXT_shader_explicit_arithmetic_types_int16";
+const char* const E_GL_EXT_shader_explicit_arithmetic_types_int32    = "GL_EXT_shader_explicit_arithmetic_types_int32";
+const char* const E_GL_EXT_shader_explicit_arithmetic_types_int64    = "GL_EXT_shader_explicit_arithmetic_types_int64";
+const char* const E_GL_EXT_shader_explicit_arithmetic_types_float16  = "GL_EXT_shader_explicit_arithmetic_types_float16";
+const char* const E_GL_EXT_shader_explicit_arithmetic_types_float32  = "GL_EXT_shader_explicit_arithmetic_types_float32";
+const char* const E_GL_EXT_shader_explicit_arithmetic_types_float64  = "GL_EXT_shader_explicit_arithmetic_types_float64";
+
 // Arrays of extensions for the above AEP duplications
 // Arrays of extensions for the above AEP duplications
 
 
 const char* const AEP_geometry_shader[] = { E_GL_EXT_geometry_shader, E_GL_OES_geometry_shader };
 const char* const AEP_geometry_shader[] = { E_GL_EXT_geometry_shader, E_GL_OES_geometry_shader };

+ 257 - 0
src/libraries/glslang/glslang/MachineIndependent/attribute.cpp

@@ -0,0 +1,257 @@
+//
+// Copyright (C) 2017 LunarG, Inc.
+// Copyright (C) 2018 Google, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+//    Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+//
+//    Redistributions in binary form must reproduce the above
+//    copyright notice, this list of conditions and the following
+//    disclaimer in the documentation and/or other materials provided
+//    with the distribution.
+//
+//    Neither the name of Google, Inc., nor the names of its
+//    contributors may be used to endorse or promote products derived
+//    from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include "attribute.h"
+#include "../Include/intermediate.h"
+#include "ParseHelper.h"
+
+namespace glslang {
+
+// extract integers out of attribute arguments stored in attribute aggregate
+bool TAttributeArgs::getInt(int& value, int argNum) const 
+{
+    const TConstUnion* intConst = getConstUnion(EbtInt, argNum);
+
+    if (intConst == nullptr)
+        return false;
+
+    value = intConst->getIConst();
+    return true;
+}
+
+// extract strings out of attribute arguments stored in attribute aggregate.
+// convert to lower case if converToLower is true (for case-insensitive compare convenience)
+bool TAttributeArgs::getString(TString& value, int argNum, bool convertToLower) const 
+{
+    const TConstUnion* stringConst = getConstUnion(EbtString, argNum);
+
+    if (stringConst == nullptr)
+        return false;
+
+    value = *stringConst->getSConst();
+
+    // Convenience.
+    if (convertToLower)
+        std::transform(value.begin(), value.end(), value.begin(), ::tolower);
+
+    return true;
+}
+
+// How many arguments were supplied?
+int TAttributeArgs::size() const
+{
+    return args == nullptr ? 0 : (int)args->getSequence().size();
+}
+
+// Helper to get attribute const union.  Returns nullptr on failure.
+const TConstUnion* TAttributeArgs::getConstUnion(TBasicType basicType, int argNum) const
+{
+    if (args == nullptr)
+        return nullptr;
+
+    if (argNum >= (int)args->getSequence().size())
+        return nullptr;
+
+    const TConstUnion* constVal = &args->getSequence()[argNum]->getAsConstantUnion()->getConstArray()[0];
+    if (constVal == nullptr || constVal->getType() != basicType)
+        return nullptr;
+
+    return constVal;
+}
+
+// Implementation of TParseContext parts of attributes
+TAttributeType TParseContext::attributeFromName(const TString& name) const
+{
+    if (name == "branch" || name == "dont_flatten")
+        return EatBranch;
+    else if (name == "flatten")
+        return EatFlatten;
+    else if (name == "unroll")
+        return EatUnroll;
+    else if (name == "loop" || name == "dont_unroll")
+        return EatLoop;
+    else if (name == "dependency_infinite")
+        return EatDependencyInfinite;
+    else if (name == "dependency_length")
+        return EatDependencyLength;
+    else
+        return EatNone;
+}
+
+// Make an initial leaf for the grammar from a no-argument attribute
+TAttributes* TParseContext::makeAttributes(const TString& identifier) const
+{
+    TAttributes *attributes = nullptr;
+    attributes = NewPoolObject(attributes);
+    TAttributeArgs args = { attributeFromName(identifier), nullptr };
+    attributes->push_back(args);
+    return attributes;
+}
+
+// Make an initial leaf for the grammar from a one-argument attribute
+TAttributes* TParseContext::makeAttributes(const TString& identifier, TIntermNode* node) const
+{
+    TAttributes *attributes = nullptr;
+    attributes = NewPoolObject(attributes);
+
+    // for now, node is always a simple single expression, but other code expects
+    // a list, so make it so
+    TIntermAggregate* agg = intermediate.makeAggregate(node);
+    TAttributeArgs args = { attributeFromName(identifier), agg };
+    attributes->push_back(args);
+    return attributes;
+}
+
+// Merge two sets of attributes into a single set.
+// The second argument is destructively consumed.
+TAttributes* TParseContext::mergeAttributes(TAttributes* attr1, TAttributes* attr2) const
+{
+    attr1->splice(attr1->end(), *attr2);
+    return attr1;
+}
+
+//
+// Selection attributes
+//
+void TParseContext::handleSelectionAttributes(const TAttributes& attributes, TIntermNode* node)
+{
+    TIntermSelection* selection = node->getAsSelectionNode();
+    if (selection == nullptr)
+        return;
+
+    for (auto it = attributes.begin(); it != attributes.end(); ++it) {
+        if (it->size() > 0) {
+            warn(node->getLoc(), "attribute with arguments not recognized, skipping", "", "");
+            continue;
+        }
+
+        switch (it->name) {
+        case EatFlatten:
+            selection->setFlatten();
+            break;
+        case EatBranch:
+            selection->setDontFlatten();
+            break;
+        default:
+            warn(node->getLoc(), "attribute does not apply to a selection", "", "");
+            break;
+        }
+    }
+}
+
+//
+// Switch attributes
+//
+void TParseContext::handleSwitchAttributes(const TAttributes& attributes, TIntermNode* node)
+{
+    TIntermSwitch* selection = node->getAsSwitchNode();
+    if (selection == nullptr)
+        return;
+
+    for (auto it = attributes.begin(); it != attributes.end(); ++it) {
+        if (it->size() > 0) {
+            warn(node->getLoc(), "attribute with arguments not recognized, skipping", "", "");
+            continue;
+        }
+
+        switch (it->name) {
+        case EatFlatten:
+            selection->setFlatten();
+            break;
+        case EatBranch:
+            selection->setDontFlatten();
+            break;
+        default:
+            warn(node->getLoc(), "attribute does not apply to a switch", "", "");
+            break;
+        }
+    }
+}
+
+//
+// Loop attributes
+//
+void TParseContext::handleLoopAttributes(const TAttributes& attributes, TIntermNode* node)
+{
+    TIntermLoop* loop = node->getAsLoopNode();
+    if (loop == nullptr) {
+        // the actual loop might be part of a sequence
+        TIntermAggregate* agg = node->getAsAggregate();
+        if (agg == nullptr)
+            return;
+        for (auto it = agg->getSequence().begin(); it != agg->getSequence().end(); ++it) {
+            loop = (*it)->getAsLoopNode();
+            if (loop != nullptr)
+                break;
+        }
+        if (loop == nullptr)
+            return;
+    }
+
+    for (auto it = attributes.begin(); it != attributes.end(); ++it) {
+        if (it->name != EatDependencyLength && it->size() > 0) {
+            warn(node->getLoc(), "attribute with arguments not recognized, skipping", "", "");
+            continue;
+        }
+
+        int value;
+        switch (it->name) {
+        case EatUnroll:
+            loop->setUnroll();
+            break;
+        case EatLoop:
+            loop->setDontUnroll();
+            break;
+        case EatDependencyInfinite:
+            loop->setLoopDependency(TIntermLoop::dependencyInfinite);
+            break;
+        case EatDependencyLength:
+            if (it->size() == 1 && it->getInt(value)) {
+                if (value <= 0)
+                    error(node->getLoc(), "must be positive", "dependency_length", "");
+                loop->setLoopDependency(value);
+            } else
+                warn(node->getLoc(), "expected a single integer argument", "dependency_length", "");
+            break;
+        default:
+            warn(node->getLoc(), "attribute does not apply to a loop", "", "");
+            break;
+        }
+    }
+}
+
+
+} // end namespace glslang

+ 102 - 0
src/libraries/glslang/glslang/MachineIndependent/attribute.h

@@ -0,0 +1,102 @@
+//
+// Copyright (C) 2017 LunarG, Inc.
+// Copyright (C) 2018 Google, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+//    Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+//
+//    Redistributions in binary form must reproduce the above
+//    copyright notice, this list of conditions and the following
+//    disclaimer in the documentation and/or other materials provided
+//    with the distribution.
+//
+//    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+//    contributors may be used to endorse or promote products derived
+//    from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef _ATTRIBUTE_INCLUDED_
+#define _ATTRIBUTE_INCLUDED_
+
+#include "../Include/Common.h"
+#include "../Include/ConstantUnion.h"
+
+namespace glslang {
+
+    enum TAttributeType {
+        EatNone,
+        EatAllow_uav_condition,
+        EatBranch,
+        EatCall,
+        EatDomain,
+        EatEarlyDepthStencil,
+        EatFastOpt,
+        EatFlatten,
+        EatForceCase,
+        EatInstance,
+        EatMaxTessFactor,
+        EatNumThreads,
+        EatMaxVertexCount,
+        EatOutputControlPoints,
+        EatOutputTopology,
+        EatPartitioning,
+        EatPatchConstantFunc,
+        EatPatchSize,
+        EatUnroll,
+        EatLoop,
+        EatBinding,
+        EatGlobalBinding,
+        EatLocation,
+        EatInputAttachment,
+        EatBuiltIn,
+        EatPushConstant,
+        EatConstantId,
+        EatDependencyInfinite,
+        EatDependencyLength
+    };
+
+    class TIntermAggregate;
+
+    struct TAttributeArgs {
+        TAttributeType name;
+        const TIntermAggregate* args;
+
+        // Obtain attribute as integer
+        // Return false if it cannot be obtained
+        bool getInt(int& value, int argNum = 0) const;
+
+        // Obtain attribute as string, with optional to-lower transform
+        // Return false if it cannot be obtained
+        bool getString(TString& value, int argNum = 0, bool convertToLower = true) const;
+
+        // How many arguments were provided to the attribute?
+        int size() const;
+
+    protected:
+        const TConstUnion* getConstUnion(TBasicType basicType, int argNum) const;
+    };
+
+    typedef TList<TAttributeArgs> TAttributes;
+
+} // end namespace glslang
+
+#endif // _ATTRIBUTE_INCLUDED_

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

@@ -117,6 +117,40 @@
 #define GL_SAMPLER_CUBE_MAP_ARRAY_ARB     0x900C
 #define GL_SAMPLER_CUBE_MAP_ARRAY_ARB     0x900C
 #define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_ARB 0x900D
 #define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_ARB 0x900D
 
 
+#ifdef AMD_EXTENSIONS
+#define GL_FLOAT16_SAMPLER_1D_AMD                       0x91CE
+#define GL_FLOAT16_SAMPLER_2D_AMD                       0x91CF
+#define GL_FLOAT16_SAMPLER_3D_AMD                       0x91D0
+#define GL_FLOAT16_SAMPLER_CUBE_AMD                     0x91D1
+#define GL_FLOAT16_SAMPLER_2D_RECT_AMD                  0x91D2
+#define GL_FLOAT16_SAMPLER_1D_ARRAY_AMD                 0x91D3
+#define GL_FLOAT16_SAMPLER_2D_ARRAY_AMD                 0x91D4
+#define GL_FLOAT16_SAMPLER_CUBE_MAP_ARRAY_AMD           0x91D5
+#define GL_FLOAT16_SAMPLER_BUFFER_AMD                   0x91D6
+#define GL_FLOAT16_SAMPLER_2D_MULTISAMPLE_AMD           0x91D7
+#define GL_FLOAT16_SAMPLER_2D_MULTISAMPLE_ARRAY_AMD     0x91D8
+
+#define GL_FLOAT16_SAMPLER_1D_SHADOW_AMD                0x91D9
+#define GL_FLOAT16_SAMPLER_2D_SHADOW_AMD                0x91DA
+#define GL_FLOAT16_SAMPLER_2D_RECT_SHADOW_AMD           0x91DB
+#define GL_FLOAT16_SAMPLER_1D_ARRAY_SHADOW_AMD          0x91DC
+#define GL_FLOAT16_SAMPLER_2D_ARRAY_SHADOW_AMD          0x91DD
+#define GL_FLOAT16_SAMPLER_CUBE_SHADOW_AMD              0x91DE
+#define GL_FLOAT16_SAMPLER_CUBE_MAP_ARRAY_SHADOW_AMD    0x91DF
+
+#define GL_FLOAT16_IMAGE_1D_AMD                         0x91E0
+#define GL_FLOAT16_IMAGE_2D_AMD                         0x91E1
+#define GL_FLOAT16_IMAGE_3D_AMD                         0x91E2
+#define GL_FLOAT16_IMAGE_2D_RECT_AMD                    0x91E3
+#define GL_FLOAT16_IMAGE_CUBE_AMD                       0x91E4
+#define GL_FLOAT16_IMAGE_1D_ARRAY_AMD                   0x91E5
+#define GL_FLOAT16_IMAGE_2D_ARRAY_AMD                   0x91E6
+#define GL_FLOAT16_IMAGE_CUBE_MAP_ARRAY_AMD             0x91E7
+#define GL_FLOAT16_IMAGE_BUFFER_AMD                     0x91E8
+#define GL_FLOAT16_IMAGE_2D_MULTISAMPLE_AMD             0x91E9
+#define GL_FLOAT16_IMAGE_2D_MULTISAMPLE_ARRAY_AMD       0x91EA
+#endif
+
 #define GL_INT_SAMPLER_1D                 0x8DC9
 #define GL_INT_SAMPLER_1D                 0x8DC9
 #define GL_INT_SAMPLER_2D                 0x8DCA
 #define GL_INT_SAMPLER_2D                 0x8DCA
 #define GL_INT_SAMPLER_3D                 0x8DCB
 #define GL_INT_SAMPLER_3D                 0x8DCB

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


+ 408 - 297
src/libraries/glslang/glslang/MachineIndependent/glslang_tab.cpp.h

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

+ 483 - 138
src/libraries/glslang/glslang/MachineIndependent/intermOut.cpp

@@ -1,6 +1,7 @@
 //
 //
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2012-2016 LunarG, Inc.
 // Copyright (C) 2012-2016 LunarG, Inc.
+// Copyright (C) 2017 ARM Limited.
 //
 //
 // All rights reserved.
 // All rights reserved.
 //
 //
@@ -92,7 +93,13 @@ namespace glslang {
 //
 //
 class TOutputTraverser : public TIntermTraverser {
 class TOutputTraverser : public TIntermTraverser {
 public:
 public:
-    TOutputTraverser(TInfoSink& i) : infoSink(i) { }
+    TOutputTraverser(TInfoSink& i) : infoSink(i), extraOutput(NoExtraOutput) { }
+
+    enum EExtraOutput {
+        NoExtraOutput,
+        BinaryDoubleOutput
+    };
+    void setDoubleOutput(EExtraOutput extra) { extraOutput = extra; }
 
 
     virtual bool visitBinary(TVisit, TIntermBinary* node);
     virtual bool visitBinary(TVisit, TIntermBinary* node);
     virtual bool visitUnary(TVisit, TIntermUnary* node);
     virtual bool visitUnary(TVisit, TIntermUnary* node);
@@ -108,6 +115,8 @@ public:
 protected:
 protected:
     TOutputTraverser(TOutputTraverser&);
     TOutputTraverser(TOutputTraverser&);
     TOutputTraverser& operator=(TOutputTraverser&);
     TOutputTraverser& operator=(TOutputTraverser&);
+
+    EExtraOutput extraOutput;
 };
 };
 
 
 //
 //
@@ -224,48 +233,192 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
     case EOpPreIncrement:   out.debug << "Pre-Increment";        break;
     case EOpPreIncrement:   out.debug << "Pre-Increment";        break;
     case EOpPreDecrement:   out.debug << "Pre-Decrement";        break;
     case EOpPreDecrement:   out.debug << "Pre-Decrement";        break;
 
 
+    // * -> bool
+    case EOpConvInt8ToBool:    out.debug << "Convert int8_t to bool";  break;
+    case EOpConvUint8ToBool:   out.debug << "Convert uint8_t to bool"; break;
+    case EOpConvInt16ToBool:   out.debug << "Convert int16_t to bool"; break;
+    case EOpConvUint16ToBool:  out.debug << "Convert uint16_t to bool";break;
     case EOpConvIntToBool:     out.debug << "Convert int to bool";     break;
     case EOpConvIntToBool:     out.debug << "Convert int to bool";     break;
     case EOpConvUintToBool:    out.debug << "Convert uint to bool";    break;
     case EOpConvUintToBool:    out.debug << "Convert uint to bool";    break;
-    case EOpConvFloatToBool:   out.debug << "Convert float to bool";   break;
-    case EOpConvDoubleToBool:  out.debug << "Convert double to bool";  break;
     case EOpConvInt64ToBool:   out.debug << "Convert int64 to bool";   break;
     case EOpConvInt64ToBool:   out.debug << "Convert int64 to bool";   break;
     case EOpConvUint64ToBool:  out.debug << "Convert uint64 to bool";  break;
     case EOpConvUint64ToBool:  out.debug << "Convert uint64 to bool";  break;
-    case EOpConvIntToFloat:    out.debug << "Convert int to float";    break;
-    case EOpConvUintToFloat:   out.debug << "Convert uint to float";   break;
-    case EOpConvDoubleToFloat: out.debug << "Convert double to float"; break;
-    case EOpConvInt64ToFloat:  out.debug << "Convert int64 to float";  break;
-    case EOpConvUint64ToFloat: out.debug << "Convert uint64 to float"; break;
-    case EOpConvBoolToFloat:   out.debug << "Convert bool to float";   break;
-    case EOpConvUintToInt:     out.debug << "Convert uint to int";     break;
-    case EOpConvFloatToInt:    out.debug << "Convert float to int";    break;
-    case EOpConvDoubleToInt:   out.debug << "Convert double to int";   break;
-    case EOpConvBoolToInt:     out.debug << "Convert bool to int";     break;
-    case EOpConvInt64ToInt:    out.debug << "Convert int64 to int";    break;
-    case EOpConvUint64ToInt:   out.debug << "Convert uint64 to int";   break;
-    case EOpConvIntToUint:     out.debug << "Convert int to uint";     break;
-    case EOpConvFloatToUint:   out.debug << "Convert float to uint";   break;
-    case EOpConvDoubleToUint:  out.debug << "Convert double to uint";  break;
+    case EOpConvFloat16ToBool: out.debug << "Convert float16_t to bool";   break;
+    case EOpConvFloatToBool:   out.debug << "Convert float to bool";   break;
+    case EOpConvDoubleToBool:  out.debug << "Convert double to bool";  break;
+
+    // bool -> *
+    case EOpConvBoolToInt8:    out.debug << "Convert bool to int8_t";  break;
+    case EOpConvBoolToUint8:   out.debug << "Convert bool to uint8_t"; break;
+    case EOpConvBoolToInt16:   out.debug << "Convert bool to in16t_t"; break;
+    case EOpConvBoolToUint16:  out.debug << "Convert bool to uint16_t";break;
+    case EOpConvBoolToInt:     out.debug << "Convert bool to int"  ;   break;
     case EOpConvBoolToUint:    out.debug << "Convert bool to uint";    break;
     case EOpConvBoolToUint:    out.debug << "Convert bool to uint";    break;
-    case EOpConvInt64ToUint:   out.debug << "Convert int64 to uint";   break;
-    case EOpConvUint64ToUint:  out.debug << "Convert uint64 to uint";  break;
+    case EOpConvBoolToInt64:   out.debug << "Convert bool to int64"; break;
+    case EOpConvBoolToUint64:  out.debug << "Convert bool to uint64";break;
+    case EOpConvBoolToFloat16: out.debug << "Convert bool to float16_t";   break;
+    case EOpConvBoolToFloat:   out.debug << "Convert bool to float";   break;
+    case EOpConvBoolToDouble:  out.debug << "Convert bool to double";   break;
+
+    // int8_t -> (u)int*
+    case EOpConvInt8ToInt16:   out.debug << "Convert int8_t to int16_t";break;
+    case EOpConvInt8ToInt:     out.debug << "Convert int8_t to int";    break;
+    case EOpConvInt8ToInt64:   out.debug << "Convert int8_t to int64";   break;
+    case EOpConvInt8ToUint8:   out.debug << "Convert int8_t to uint8_t";break;
+    case EOpConvInt8ToUint16:  out.debug << "Convert int8_t to uint16_t";break;
+    case EOpConvInt8ToUint:    out.debug << "Convert int8_t to uint";    break;
+    case EOpConvInt8ToUint64:  out.debug << "Convert int8_t to uint64";   break;
+
+    // uint8_t -> (u)int*
+    case EOpConvUint8ToInt8:    out.debug << "Convert uint8_t to int8_t";break;
+    case EOpConvUint8ToInt16:   out.debug << "Convert uint8_t to int16_t";break;
+    case EOpConvUint8ToInt:     out.debug << "Convert uint8_t to int";    break;
+    case EOpConvUint8ToInt64:   out.debug << "Convert uint8_t to int64";   break;
+    case EOpConvUint8ToUint16:  out.debug << "Convert uint8_t to uint16_t";break;
+    case EOpConvUint8ToUint:    out.debug << "Convert uint8_t to uint";    break;
+    case EOpConvUint8ToUint64:  out.debug << "Convert uint8_t to uint64";   break;
+
+    // int8_t -> float*
+    case EOpConvInt8ToFloat16:  out.debug << "Convert int8_t to float16_t";break;
+    case EOpConvInt8ToFloat:    out.debug << "Convert int8_t to float";    break;
+    case EOpConvInt8ToDouble:   out.debug << "Convert int8_t to double";   break;
+
+    // uint8_t -> float*
+    case EOpConvUint8ToFloat16: out.debug << "Convert uint8_t to float16_t";break;
+    case EOpConvUint8ToFloat:   out.debug << "Convert uint8_t to float";    break;
+    case EOpConvUint8ToDouble:  out.debug << "Convert uint8_t to double";   break;
+
+    // int16_t -> (u)int*
+    case EOpConvInt16ToInt8:    out.debug << "Convert int16_t to int8_t";break;
+    case EOpConvInt16ToInt:     out.debug << "Convert int16_t to int";    break;
+    case EOpConvInt16ToInt64:   out.debug << "Convert int16_t to int64";   break;
+    case EOpConvInt16ToUint8:   out.debug << "Convert int16_t to uint8_t";break;
+    case EOpConvInt16ToUint16:  out.debug << "Convert int16_t to uint16_t";break;
+    case EOpConvInt16ToUint:    out.debug << "Convert int16_t to uint";    break;
+    case EOpConvInt16ToUint64:  out.debug << "Convert int16_t to uint64";   break;
+
+    // int16_t -> float*
+    case EOpConvInt16ToFloat16:  out.debug << "Convert int16_t to float16_t";break;
+    case EOpConvInt16ToFloat:    out.debug << "Convert int16_t to float";    break;
+    case EOpConvInt16ToDouble:   out.debug << "Convert int16_t to double";   break;
+
+    // uint16_t -> (u)int*
+    case EOpConvUint16ToInt8:    out.debug << "Convert uint16_t to int8_t";break;
+    case EOpConvUint16ToInt16:   out.debug << "Convert uint16_t to int16_t";break;
+    case EOpConvUint16ToInt:     out.debug << "Convert uint16_t to int";    break;
+    case EOpConvUint16ToInt64:   out.debug << "Convert uint16_t to int64";   break;
+    case EOpConvUint16ToUint8:   out.debug << "Convert uint16_t to uint8_t";break;
+    case EOpConvUint16ToUint:    out.debug << "Convert uint16_t to uint";    break;
+    case EOpConvUint16ToUint64:  out.debug << "Convert uint16_t to uint64";   break;
+
+    // uint16_t -> float*
+    case EOpConvUint16ToFloat16: out.debug << "Convert uint16_t to float16_t";break;
+    case EOpConvUint16ToFloat:   out.debug << "Convert uint16_t to float";    break;
+    case EOpConvUint16ToDouble:  out.debug << "Convert uint16_t to double";   break;
+
+    // int32_t -> (u)int*
+    case EOpConvIntToInt8:    out.debug << "Convert int to int8_t";break;
+    case EOpConvIntToInt16:   out.debug << "Convert int to int16_t";break;
+    case EOpConvIntToInt64:   out.debug << "Convert int to int64";   break;
+    case EOpConvIntToUint8:   out.debug << "Convert int to uint8_t";break;
+    case EOpConvIntToUint16:  out.debug << "Convert int to uint16_t";break;
+    case EOpConvIntToUint:    out.debug << "Convert int to uint";    break;
+    case EOpConvIntToUint64:  out.debug << "Convert int to uint64";   break;
+
+    // int32_t -> float*
+    case EOpConvIntToFloat16:  out.debug << "Convert int to float16_t";break;
+    case EOpConvIntToFloat:    out.debug << "Convert int to float";    break;
     case EOpConvIntToDouble:   out.debug << "Convert int to double";   break;
     case EOpConvIntToDouble:   out.debug << "Convert int to double";   break;
-    case EOpConvUintToDouble:  out.debug << "Convert uint to double";  break;
-    case EOpConvFloatToDouble: out.debug << "Convert float to double"; break;
-    case EOpConvBoolToDouble:  out.debug << "Convert bool to double";  break;
-    case EOpConvInt64ToDouble: out.debug << "Convert int64 to double"; break;
-    case EOpConvUint64ToDouble: out.debug << "Convert uint64 to double";  break;
-    case EOpConvBoolToInt64:   out.debug << "Convert bool to int64";   break;
-    case EOpConvIntToInt64:    out.debug << "Convert int to int64";    break;
+
+    // uint32_t -> (u)int*
+    case EOpConvUintToInt8:    out.debug << "Convert uint to int8_t";break;
+    case EOpConvUintToInt16:   out.debug << "Convert uint to int16_t";break;
+    case EOpConvUintToInt:     out.debug << "Convert uint to int";break;
     case EOpConvUintToInt64:   out.debug << "Convert uint to int64";   break;
     case EOpConvUintToInt64:   out.debug << "Convert uint to int64";   break;
-    case EOpConvFloatToInt64:  out.debug << "Convert float to int64";  break;
-    case EOpConvDoubleToInt64: out.debug << "Convert double to int64"; break;
-    case EOpConvUint64ToInt64: out.debug << "Convert uint64 to int64"; break;
-    case EOpConvBoolToUint64:  out.debug << "Convert bool to uint64";  break;
-    case EOpConvIntToUint64:   out.debug << "Convert int to uint64";   break;
-    case EOpConvUintToUint64:  out.debug << "Convert uint to uint64";  break;
+    case EOpConvUintToUint8:   out.debug << "Convert uint to uint8_t";break;
+    case EOpConvUintToUint16:  out.debug << "Convert uint to uint16_t";break;
+    case EOpConvUintToUint64:  out.debug << "Convert uint to uint64";   break;
+
+    // uint32_t -> float*
+    case EOpConvUintToFloat16: out.debug << "Convert uint to float16_t";break;
+    case EOpConvUintToFloat:   out.debug << "Convert uint to float";    break;
+    case EOpConvUintToDouble:  out.debug << "Convert uint to double";   break;
+
+    // int64 -> (u)int*
+    case EOpConvInt64ToInt8:    out.debug << "Convert int64 to int8_t";  break;
+    case EOpConvInt64ToInt16:   out.debug << "Convert int64 to int16_t"; break;
+    case EOpConvInt64ToInt:     out.debug << "Convert int64 to int";   break;
+    case EOpConvInt64ToUint8:   out.debug << "Convert int64 to uint8_t";break;
+    case EOpConvInt64ToUint16:  out.debug << "Convert int64 to uint16_t";break;
+    case EOpConvInt64ToUint:    out.debug << "Convert int64 to uint";    break;
+    case EOpConvInt64ToUint64:  out.debug << "Convert int64 to uint64";   break;
+
+     // int64 -> float*
+    case EOpConvInt64ToFloat16:  out.debug << "Convert int64 to float16_t";break;
+    case EOpConvInt64ToFloat:    out.debug << "Convert int64 to float";    break;
+    case EOpConvInt64ToDouble:   out.debug << "Convert int64 to double";   break;
+
+    // uint64 -> (u)int*
+    case EOpConvUint64ToInt8:    out.debug << "Convert uint64 to int8_t";break;
+    case EOpConvUint64ToInt16:   out.debug << "Convert uint64 to int16_t";break;
+    case EOpConvUint64ToInt:     out.debug << "Convert uint64 to int";    break;
+    case EOpConvUint64ToInt64:   out.debug << "Convert uint64 to int64";   break;
+    case EOpConvUint64ToUint8:   out.debug << "Convert uint64 to uint8_t";break;
+    case EOpConvUint64ToUint16:  out.debug << "Convert uint64 to uint16";    break;
+    case EOpConvUint64ToUint:    out.debug << "Convert uint64 to uint";   break;
+
+    // uint64 -> float*
+    case EOpConvUint64ToFloat16: out.debug << "Convert uint64 to float16_t";break;
+    case EOpConvUint64ToFloat:   out.debug << "Convert uint64 to float";    break;
+    case EOpConvUint64ToDouble:  out.debug << "Convert uint64 to double";   break;
+
+    // float16_t -> int*
+    case EOpConvFloat16ToInt8:  out.debug << "Convert float16_t to int8_t"; break;
+    case EOpConvFloat16ToInt16: out.debug << "Convert float16_t to int16_t"; break;
+    case EOpConvFloat16ToInt:   out.debug << "Convert float16_t to int"; break;
+    case EOpConvFloat16ToInt64: out.debug << "Convert float16_t to int64"; break;
+
+    // float16_t -> uint*
+    case EOpConvFloat16ToUint8:  out.debug << "Convert float16_t to uint8_t"; break;
+    case EOpConvFloat16ToUint16: out.debug << "Convert float16_t to uint16_t"; break;
+    case EOpConvFloat16ToUint:   out.debug << "Convert float16_t to uint"; break;
+    case EOpConvFloat16ToUint64: out.debug << "Convert float16_t to uint64"; break;
+
+    // float16_t -> float*
+    case EOpConvFloat16ToFloat:  out.debug << "Convert float16_t to float"; break;
+    case EOpConvFloat16ToDouble: out.debug << "Convert float16_t to double"; break;
+
+    // float32 -> float*
+    case EOpConvFloatToFloat16: out.debug << "Convert float to float16_t"; break;
+    case EOpConvFloatToDouble:  out.debug << "Convert float to double"; break;
+
+    // float32_t -> int*
+    case EOpConvFloatToInt8:  out.debug << "Convert float to int8_t"; break;
+    case EOpConvFloatToInt16: out.debug << "Convert float to int16_t"; break;
+    case EOpConvFloatToInt:   out.debug << "Convert float to int"; break;
+    case EOpConvFloatToInt64: out.debug << "Convert float to int64"; break;
+
+    // float32_t -> uint*
+    case EOpConvFloatToUint8:  out.debug << "Convert float to uint8_t"; break;
+    case EOpConvFloatToUint16: out.debug << "Convert float to uint16_t"; break;
+    case EOpConvFloatToUint:   out.debug << "Convert float to uint"; break;
     case EOpConvFloatToUint64: out.debug << "Convert float to uint64"; break;
     case EOpConvFloatToUint64: out.debug << "Convert float to uint64"; break;
+
+    // double -> float*
+    case EOpConvDoubleToFloat16: out.debug << "Convert double to float16_t"; break;
+    case EOpConvDoubleToFloat:   out.debug << "Convert double to float"; break;
+
+    // double -> int*
+    case EOpConvDoubleToInt8:  out.debug << "Convert double to int8_t"; break;
+    case EOpConvDoubleToInt16: out.debug << "Convert double to int16_t"; break;
+    case EOpConvDoubleToInt:   out.debug << "Convert double to int"; break;
+    case EOpConvDoubleToInt64: out.debug << "Convert double to int64"; break;
+
+    // float32_t -> uint*
+    case EOpConvDoubleToUint8:  out.debug << "Convert double to uint8_t"; break;
+    case EOpConvDoubleToUint16: out.debug << "Convert double to uint16_t"; break;
+    case EOpConvDoubleToUint:   out.debug << "Convert double to uint"; break;
     case EOpConvDoubleToUint64: out.debug << "Convert double to uint64"; break;
     case EOpConvDoubleToUint64: out.debug << "Convert double to uint64"; break;
-    case EOpConvInt64ToUint64: out.debug << "Convert uint64 to uint64"; break;
+
 
 
     case EOpRadians:        out.debug << "radians";              break;
     case EOpRadians:        out.debug << "radians";              break;
     case EOpDegrees:        out.debug << "degrees";              break;
     case EOpDegrees:        out.debug << "degrees";              break;
@@ -309,12 +462,10 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
     case EOpDoubleBitsToUint64: out.debug << "doubleBitsToUint64"; break;
     case EOpDoubleBitsToUint64: out.debug << "doubleBitsToUint64"; break;
     case EOpInt64BitsToDouble:  out.debug << "int64BitsToDouble";  break;
     case EOpInt64BitsToDouble:  out.debug << "int64BitsToDouble";  break;
     case EOpUint64BitsToDouble: out.debug << "uint64BitsToDouble"; break;
     case EOpUint64BitsToDouble: out.debug << "uint64BitsToDouble"; break;
-#ifdef AMD_EXTENSIONS
     case EOpFloat16BitsToInt16:  out.debug << "float16BitsToInt16";  break;
     case EOpFloat16BitsToInt16:  out.debug << "float16BitsToInt16";  break;
     case EOpFloat16BitsToUint16: out.debug << "float16BitsToUint16"; break;
     case EOpFloat16BitsToUint16: out.debug << "float16BitsToUint16"; break;
     case EOpInt16BitsToFloat16:  out.debug << "int16BitsToFloat16";  break;
     case EOpInt16BitsToFloat16:  out.debug << "int16BitsToFloat16";  break;
     case EOpUint16BitsToFloat16: out.debug << "uint16BitsToFloat16"; break;
     case EOpUint16BitsToFloat16: out.debug << "uint16BitsToFloat16"; break;
-#endif
 
 
     case EOpPackSnorm2x16:  out.debug << "packSnorm2x16";        break;
     case EOpPackSnorm2x16:  out.debug << "packSnorm2x16";        break;
     case EOpUnpackSnorm2x16:out.debug << "unpackSnorm2x16";      break;
     case EOpUnpackSnorm2x16:out.debug << "unpackSnorm2x16";      break;
@@ -322,6 +473,12 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
     case EOpUnpackUnorm2x16:out.debug << "unpackUnorm2x16";      break;
     case EOpUnpackUnorm2x16:out.debug << "unpackUnorm2x16";      break;
     case EOpPackHalf2x16:   out.debug << "packHalf2x16";         break;
     case EOpPackHalf2x16:   out.debug << "packHalf2x16";         break;
     case EOpUnpackHalf2x16: out.debug << "unpackHalf2x16";       break;
     case EOpUnpackHalf2x16: out.debug << "unpackHalf2x16";       break;
+    case EOpPack16:           out.debug << "pack16";                 break;
+    case EOpPack32:           out.debug << "pack32";                 break;
+    case EOpPack64:           out.debug << "pack64";                 break;
+    case EOpUnpack32:         out.debug << "unpack32";               break;
+    case EOpUnpack16:         out.debug << "unpack16";               break;
+    case EOpUnpack8:          out.debug << "unpack8";               break;
 
 
     case EOpPackSnorm4x8:     out.debug << "PackSnorm4x8";       break;
     case EOpPackSnorm4x8:     out.debug << "PackSnorm4x8";       break;
     case EOpUnpackSnorm4x8:   out.debug << "UnpackSnorm4x8";     break;
     case EOpUnpackSnorm4x8:   out.debug << "UnpackSnorm4x8";     break;
@@ -335,7 +492,6 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
     case EOpPackUint2x32:     out.debug << "packUint2x32";       break;
     case EOpPackUint2x32:     out.debug << "packUint2x32";       break;
     case EOpUnpackUint2x32:   out.debug << "unpackUint2x32";     break;
     case EOpUnpackUint2x32:   out.debug << "unpackUint2x32";     break;
 
 
-#ifdef AMD_EXTENSIONS
     case EOpPackInt2x16:      out.debug << "packInt2x16";        break;
     case EOpPackInt2x16:      out.debug << "packInt2x16";        break;
     case EOpUnpackInt2x16:    out.debug << "unpackInt2x16";      break;
     case EOpUnpackInt2x16:    out.debug << "unpackInt2x16";      break;
     case EOpPackUint2x16:     out.debug << "packUint2x16";       break;
     case EOpPackUint2x16:     out.debug << "packUint2x16";       break;
@@ -345,10 +501,8 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
     case EOpUnpackInt4x16:    out.debug << "unpackInt4x16";      break;
     case EOpUnpackInt4x16:    out.debug << "unpackInt4x16";      break;
     case EOpPackUint4x16:     out.debug << "packUint4x16";       break;
     case EOpPackUint4x16:     out.debug << "packUint4x16";       break;
     case EOpUnpackUint4x16:   out.debug << "unpackUint4x16";     break;
     case EOpUnpackUint4x16:   out.debug << "unpackUint4x16";     break;
-
     case EOpPackFloat2x16:    out.debug << "packFloat2x16";      break;
     case EOpPackFloat2x16:    out.debug << "packFloat2x16";      break;
     case EOpUnpackFloat2x16:  out.debug << "unpackFloat2x16";    break;
     case EOpUnpackFloat2x16:  out.debug << "unpackFloat2x16";    break;
-#endif
 
 
     case EOpLength:         out.debug << "length";               break;
     case EOpLength:         out.debug << "length";               break;
     case EOpNormalize:      out.debug << "normalize";            break;
     case EOpNormalize:      out.debug << "normalize";            break;
@@ -402,6 +556,82 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
     case EOpAllInvocations:         out.debug << "allInvocations";        break;
     case EOpAllInvocations:         out.debug << "allInvocations";        break;
     case EOpAllInvocationsEqual:    out.debug << "allInvocationsEqual";   break;
     case EOpAllInvocationsEqual:    out.debug << "allInvocationsEqual";   break;
 
 
+    case EOpSubgroupElect:                   out.debug << "subgroupElect";                   break;
+    case EOpSubgroupAll:                     out.debug << "subgroupAll";                     break;
+    case EOpSubgroupAny:                     out.debug << "subgroupAny";                     break;
+    case EOpSubgroupAllEqual:                out.debug << "subgroupAllEqual";                break;
+    case EOpSubgroupBroadcast:               out.debug << "subgroupBroadcast";               break;
+    case EOpSubgroupBroadcastFirst:          out.debug << "subgroupBroadcastFirst";          break;
+    case EOpSubgroupBallot:                  out.debug << "subgroupBallot";                  break;
+    case EOpSubgroupInverseBallot:           out.debug << "subgroupInverseBallot";           break;
+    case EOpSubgroupBallotBitExtract:        out.debug << "subgroupBallotBitExtract";        break;
+    case EOpSubgroupBallotBitCount:          out.debug << "subgroupBallotBitCount";          break;
+    case EOpSubgroupBallotInclusiveBitCount: out.debug << "subgroupBallotInclusiveBitCount"; break;
+    case EOpSubgroupBallotExclusiveBitCount: out.debug << "subgroupBallotExclusiveBitCount"; break;
+    case EOpSubgroupBallotFindLSB:           out.debug << "subgroupBallotFindLSB";           break;
+    case EOpSubgroupBallotFindMSB:           out.debug << "subgroupBallotFindMSB";           break;
+    case EOpSubgroupShuffle:                 out.debug << "subgroupShuffle";                 break;
+    case EOpSubgroupShuffleXor:              out.debug << "subgroupShuffleXor";              break;
+    case EOpSubgroupShuffleUp:               out.debug << "subgroupShuffleUp";               break;
+    case EOpSubgroupShuffleDown:             out.debug << "subgroupShuffleDown";             break;
+    case EOpSubgroupAdd:                     out.debug << "subgroupAdd";                     break;
+    case EOpSubgroupMul:                     out.debug << "subgroupMul";                     break;
+    case EOpSubgroupMin:                     out.debug << "subgroupMin";                     break;
+    case EOpSubgroupMax:                     out.debug << "subgroupMax";                     break;
+    case EOpSubgroupAnd:                     out.debug << "subgroupAnd";                     break;
+    case EOpSubgroupOr:                      out.debug << "subgroupOr";                      break;
+    case EOpSubgroupXor:                     out.debug << "subgroupXor";                     break;
+    case EOpSubgroupInclusiveAdd:            out.debug << "subgroupInclusiveAdd";            break;
+    case EOpSubgroupInclusiveMul:            out.debug << "subgroupInclusiveMul";            break;
+    case EOpSubgroupInclusiveMin:            out.debug << "subgroupInclusiveMin";            break;
+    case EOpSubgroupInclusiveMax:            out.debug << "subgroupInclusiveMax";            break;
+    case EOpSubgroupInclusiveAnd:            out.debug << "subgroupInclusiveAnd";            break;
+    case EOpSubgroupInclusiveOr:             out.debug << "subgroupInclusiveOr";             break;
+    case EOpSubgroupInclusiveXor:            out.debug << "subgroupInclusiveXor";            break;
+    case EOpSubgroupExclusiveAdd:            out.debug << "subgroupExclusiveAdd";            break;
+    case EOpSubgroupExclusiveMul:            out.debug << "subgroupExclusiveMul";            break;
+    case EOpSubgroupExclusiveMin:            out.debug << "subgroupExclusiveMin";            break;
+    case EOpSubgroupExclusiveMax:            out.debug << "subgroupExclusiveMax";            break;
+    case EOpSubgroupExclusiveAnd:            out.debug << "subgroupExclusiveAnd";            break;
+    case EOpSubgroupExclusiveOr:             out.debug << "subgroupExclusiveOr";             break;
+    case EOpSubgroupExclusiveXor:            out.debug << "subgroupExclusiveXor";            break;
+    case EOpSubgroupClusteredAdd:            out.debug << "subgroupClusteredAdd";            break;
+    case EOpSubgroupClusteredMul:            out.debug << "subgroupClusteredMul";            break;
+    case EOpSubgroupClusteredMin:            out.debug << "subgroupClusteredMin";            break;
+    case EOpSubgroupClusteredMax:            out.debug << "subgroupClusteredMax";            break;
+    case EOpSubgroupClusteredAnd:            out.debug << "subgroupClusteredAnd";            break;
+    case EOpSubgroupClusteredOr:             out.debug << "subgroupClusteredOr";             break;
+    case EOpSubgroupClusteredXor:            out.debug << "subgroupClusteredXor";            break;
+    case EOpSubgroupQuadBroadcast:           out.debug << "subgroupQuadBroadcast";           break;
+    case EOpSubgroupQuadSwapHorizontal:      out.debug << "subgroupQuadSwapHorizontal";      break;
+    case EOpSubgroupQuadSwapVertical:        out.debug << "subgroupQuadSwapVertical";        break;
+    case EOpSubgroupQuadSwapDiagonal:        out.debug << "subgroupQuadSwapDiagonal";        break;
+
+#ifdef NV_EXTENSIONS
+    case EOpSubgroupPartition:                          out.debug << "subgroupPartitionNV";                          break;
+    case EOpSubgroupPartitionedAdd:                     out.debug << "subgroupPartitionedAddNV";                     break;
+    case EOpSubgroupPartitionedMul:                     out.debug << "subgroupPartitionedMulNV";                     break;
+    case EOpSubgroupPartitionedMin:                     out.debug << "subgroupPartitionedMinNV";                     break;
+    case EOpSubgroupPartitionedMax:                     out.debug << "subgroupPartitionedMaxNV";                     break;
+    case EOpSubgroupPartitionedAnd:                     out.debug << "subgroupPartitionedAndNV";                     break;
+    case EOpSubgroupPartitionedOr:                      out.debug << "subgroupPartitionedOrNV";                      break;
+    case EOpSubgroupPartitionedXor:                     out.debug << "subgroupPartitionedXorNV";                     break;
+    case EOpSubgroupPartitionedInclusiveAdd:            out.debug << "subgroupPartitionedInclusiveAddNV";            break;
+    case EOpSubgroupPartitionedInclusiveMul:            out.debug << "subgroupPartitionedInclusiveMulNV";            break;
+    case EOpSubgroupPartitionedInclusiveMin:            out.debug << "subgroupPartitionedInclusiveMinNV";            break;
+    case EOpSubgroupPartitionedInclusiveMax:            out.debug << "subgroupPartitionedInclusiveMaxNV";            break;
+    case EOpSubgroupPartitionedInclusiveAnd:            out.debug << "subgroupPartitionedInclusiveAndNV";            break;
+    case EOpSubgroupPartitionedInclusiveOr:             out.debug << "subgroupPartitionedInclusiveOrNV";             break;
+    case EOpSubgroupPartitionedInclusiveXor:            out.debug << "subgroupPartitionedInclusiveXorNV";            break;
+    case EOpSubgroupPartitionedExclusiveAdd:            out.debug << "subgroupPartitionedExclusiveAddNV";            break;
+    case EOpSubgroupPartitionedExclusiveMul:            out.debug << "subgroupPartitionedExclusiveMulNV";            break;
+    case EOpSubgroupPartitionedExclusiveMin:            out.debug << "subgroupPartitionedExclusiveMinNV";            break;
+    case EOpSubgroupPartitionedExclusiveMax:            out.debug << "subgroupPartitionedExclusiveMaxNV";            break;
+    case EOpSubgroupPartitionedExclusiveAnd:            out.debug << "subgroupPartitionedExclusiveAndNV";            break;
+    case EOpSubgroupPartitionedExclusiveOr:             out.debug << "subgroupPartitionedExclusiveOrNV";             break;
+    case EOpSubgroupPartitionedExclusiveXor:            out.debug << "subgroupPartitionedExclusiveXorNV";            break;
+#endif
+
     case EOpClip:                   out.debug << "clip";                  break;
     case EOpClip:                   out.debug << "clip";                  break;
     case EOpIsFinite:               out.debug << "isfinite";              break;
     case EOpIsFinite:               out.debug << "isfinite";              break;
     case EOpLog10:                  out.debug << "log10";                 break;
     case EOpLog10:                  out.debug << "log10";                 break;
@@ -434,62 +664,11 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
 
 
     case EOpMbcnt:                  out.debug << "mbcnt";                       break;
     case EOpMbcnt:                  out.debug << "mbcnt";                       break;
 
 
-    case EOpCubeFaceIndex:          out.debug << "cubeFaceIndex";               break;
-    case EOpCubeFaceCoord:          out.debug << "cubeFaceCoord";               break;
-
     case EOpFragmentMaskFetch:      out.debug << "fragmentMaskFetchAMD";        break;
     case EOpFragmentMaskFetch:      out.debug << "fragmentMaskFetchAMD";        break;
     case EOpFragmentFetch:          out.debug << "fragmentFetchAMD";            break;
     case EOpFragmentFetch:          out.debug << "fragmentFetchAMD";            break;
 
 
-    case EOpConvBoolToFloat16:      out.debug << "Convert bool to float16";     break;
-    case EOpConvIntToFloat16:       out.debug << "Convert int to float16";      break;
-    case EOpConvUintToFloat16:      out.debug << "Convert uint to float16";     break;
-    case EOpConvFloatToFloat16:     out.debug << "Convert float to float16";    break;
-    case EOpConvDoubleToFloat16:    out.debug << "Convert double to float16";   break;
-    case EOpConvInt64ToFloat16:     out.debug << "Convert int64 to float16";    break;
-    case EOpConvUint64ToFloat16:    out.debug << "Convert uint64 to float16";   break;
-    case EOpConvFloat16ToBool:      out.debug << "Convert float16 to bool";     break;
-    case EOpConvFloat16ToInt:       out.debug << "Convert float16 to int";      break;
-    case EOpConvFloat16ToUint:      out.debug << "Convert float16 to uint";     break;
-    case EOpConvFloat16ToFloat:     out.debug << "Convert float16 to float";    break;
-    case EOpConvFloat16ToDouble:    out.debug << "Convert float16 to double";   break;
-    case EOpConvFloat16ToInt64:     out.debug << "Convert float16 to int64";    break;
-    case EOpConvFloat16ToUint64:    out.debug << "Convert float16 to uint64";   break;
-
-    case EOpConvBoolToInt16:        out.debug << "Convert bool to int16";       break;
-    case EOpConvIntToInt16:         out.debug << "Convert int to int16";        break;
-    case EOpConvUintToInt16:        out.debug << "Convert uint to int16";       break;
-    case EOpConvFloatToInt16:       out.debug << "Convert float to int16";      break;
-    case EOpConvDoubleToInt16:      out.debug << "Convert double to int16";     break;
-    case EOpConvFloat16ToInt16:     out.debug << "Convert float16 to int16";    break;
-    case EOpConvInt64ToInt16:       out.debug << "Convert int64 to int16";      break;
-    case EOpConvUint64ToInt16:      out.debug << "Convert uint64 to int16";     break;
-    case EOpConvUint16ToInt16:      out.debug << "Convert uint16 to int16";     break;
-    case EOpConvInt16ToBool:        out.debug << "Convert int16 to bool";       break;
-    case EOpConvInt16ToInt:         out.debug << "Convert int16 to int";        break;
-    case EOpConvInt16ToUint:        out.debug << "Convert int16 to uint";       break;
-    case EOpConvInt16ToFloat:       out.debug << "Convert int16 to float";      break;
-    case EOpConvInt16ToDouble:      out.debug << "Convert int16 to double";     break;
-    case EOpConvInt16ToFloat16:     out.debug << "Convert int16 to float16";    break;
-    case EOpConvInt16ToInt64:       out.debug << "Convert int16 to int64";      break;
-    case EOpConvInt16ToUint64:      out.debug << "Convert int16 to uint64";     break;
-
-    case EOpConvBoolToUint16:       out.debug << "Convert bool to uint16";      break;
-    case EOpConvIntToUint16:        out.debug << "Convert int to uint16";       break;
-    case EOpConvUintToUint16:       out.debug << "Convert uint to uint16";      break;
-    case EOpConvFloatToUint16:      out.debug << "Convert float to uint16";     break;
-    case EOpConvDoubleToUint16:     out.debug << "Convert double to uint16";    break;
-    case EOpConvFloat16ToUint16:    out.debug << "Convert float16 to uint16";   break;
-    case EOpConvInt64ToUint16:      out.debug << "Convert int64 to uint16";     break;
-    case EOpConvUint64ToUint16:     out.debug << "Convert uint64 to uint16";    break;
-    case EOpConvInt16ToUint16:      out.debug << "Convert int16 to uint16";     break;
-    case EOpConvUint16ToBool:       out.debug << "Convert uint16 to bool";      break;
-    case EOpConvUint16ToInt:        out.debug << "Convert uint16 to int";       break;
-    case EOpConvUint16ToUint:       out.debug << "Convert uint16 to uint";      break;
-    case EOpConvUint16ToFloat:      out.debug << "Convert uint16 to float";     break;
-    case EOpConvUint16ToDouble:     out.debug << "Convert uint16 to double";    break;
-    case EOpConvUint16ToFloat16:    out.debug << "Convert uint16 to float16";   break;
-    case EOpConvUint16ToInt64:      out.debug << "Convert uint16 to int64";     break;
-    case EOpConvUint16ToUint64:     out.debug << "Convert uint16 to uint64";    break;
+    case EOpCubeFaceIndex:          out.debug << "cubeFaceIndex";               break;
+    case EOpCubeFaceCoord:          out.debug << "cubeFaceCoord";               break;
 #endif
 #endif
 
 
     case EOpSubpassLoad:   out.debug << "subpassLoad";   break;
     case EOpSubpassLoad:   out.debug << "subpassLoad";   break;
@@ -537,23 +716,30 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
     case EOpConstructBVec2: out.debug << "Construct bvec2"; break;
     case EOpConstructBVec2: out.debug << "Construct bvec2"; break;
     case EOpConstructBVec3: out.debug << "Construct bvec3"; break;
     case EOpConstructBVec3: out.debug << "Construct bvec3"; break;
     case EOpConstructBVec4: out.debug << "Construct bvec4"; break;
     case EOpConstructBVec4: out.debug << "Construct bvec4"; break;
+    case EOpConstructInt8:   out.debug << "Construct int8_t";   break;
+    case EOpConstructI8Vec2: out.debug << "Construct i8vec2"; break;
+    case EOpConstructI8Vec3: out.debug << "Construct i8vec3"; break;
+    case EOpConstructI8Vec4: out.debug << "Construct i8vec4"; break;
     case EOpConstructInt:   out.debug << "Construct int";   break;
     case EOpConstructInt:   out.debug << "Construct int";   break;
     case EOpConstructIVec2: out.debug << "Construct ivec2"; break;
     case EOpConstructIVec2: out.debug << "Construct ivec2"; break;
     case EOpConstructIVec3: out.debug << "Construct ivec3"; break;
     case EOpConstructIVec3: out.debug << "Construct ivec3"; break;
     case EOpConstructIVec4: out.debug << "Construct ivec4"; break;
     case EOpConstructIVec4: out.debug << "Construct ivec4"; break;
+    case EOpConstructUint8:    out.debug << "Construct uint8_t";    break;
+    case EOpConstructU8Vec2:   out.debug << "Construct u8vec2";   break;
+    case EOpConstructU8Vec3:   out.debug << "Construct u8vec3";   break;
+    case EOpConstructU8Vec4:   out.debug << "Construct u8vec4";   break;
     case EOpConstructUint:    out.debug << "Construct uint";    break;
     case EOpConstructUint:    out.debug << "Construct uint";    break;
     case EOpConstructUVec2:   out.debug << "Construct uvec2";   break;
     case EOpConstructUVec2:   out.debug << "Construct uvec2";   break;
     case EOpConstructUVec3:   out.debug << "Construct uvec3";   break;
     case EOpConstructUVec3:   out.debug << "Construct uvec3";   break;
     case EOpConstructUVec4:   out.debug << "Construct uvec4";   break;
     case EOpConstructUVec4:   out.debug << "Construct uvec4";   break;
-    case EOpConstructInt64:   out.debug << "Construct int64_t"; break;
+    case EOpConstructInt64:   out.debug << "Construct int64"; break;
     case EOpConstructI64Vec2: out.debug << "Construct i64vec2"; break;
     case EOpConstructI64Vec2: out.debug << "Construct i64vec2"; break;
     case EOpConstructI64Vec3: out.debug << "Construct i64vec3"; break;
     case EOpConstructI64Vec3: out.debug << "Construct i64vec3"; break;
     case EOpConstructI64Vec4: out.debug << "Construct i64vec4"; break;
     case EOpConstructI64Vec4: out.debug << "Construct i64vec4"; break;
-    case EOpConstructUint64:  out.debug << "Construct uint64_t"; break;
+    case EOpConstructUint64:  out.debug << "Construct uint64"; break;
     case EOpConstructU64Vec2: out.debug << "Construct u64vec2"; break;
     case EOpConstructU64Vec2: out.debug << "Construct u64vec2"; break;
     case EOpConstructU64Vec3: out.debug << "Construct u64vec3"; break;
     case EOpConstructU64Vec3: out.debug << "Construct u64vec3"; break;
     case EOpConstructU64Vec4: out.debug << "Construct u64vec4"; break;
     case EOpConstructU64Vec4: out.debug << "Construct u64vec4"; break;
-#ifdef AMD_EXTENSIONS
     case EOpConstructInt16:   out.debug << "Construct int16_t"; break;
     case EOpConstructInt16:   out.debug << "Construct int16_t"; break;
     case EOpConstructI16Vec2: out.debug << "Construct i16vec2"; break;
     case EOpConstructI16Vec2: out.debug << "Construct i16vec2"; break;
     case EOpConstructI16Vec3: out.debug << "Construct i16vec3"; break;
     case EOpConstructI16Vec3: out.debug << "Construct i16vec3"; break;
@@ -562,7 +748,6 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
     case EOpConstructU16Vec2: out.debug << "Construct u16vec2"; break;
     case EOpConstructU16Vec2: out.debug << "Construct u16vec2"; break;
     case EOpConstructU16Vec3: out.debug << "Construct u16vec3"; break;
     case EOpConstructU16Vec3: out.debug << "Construct u16vec3"; break;
     case EOpConstructU16Vec4: out.debug << "Construct u16vec4"; break;
     case EOpConstructU16Vec4: out.debug << "Construct u16vec4"; break;
-#endif
     case EOpConstructMat2x2:  out.debug << "Construct mat2";    break;
     case EOpConstructMat2x2:  out.debug << "Construct mat2";    break;
     case EOpConstructMat2x3:  out.debug << "Construct mat2x3";  break;
     case EOpConstructMat2x3:  out.debug << "Construct mat2x3";  break;
     case EOpConstructMat2x4:  out.debug << "Construct mat2x4";  break;
     case EOpConstructMat2x4:  out.debug << "Construct mat2x4";  break;
@@ -608,7 +793,6 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
     case EOpConstructBMat4x2: out.debug << "Construct bmat4x2"; break;
     case EOpConstructBMat4x2: out.debug << "Construct bmat4x2"; break;
     case EOpConstructBMat4x3: out.debug << "Construct bmat4x3"; break;
     case EOpConstructBMat4x3: out.debug << "Construct bmat4x3"; break;
     case EOpConstructBMat4x4: out.debug << "Construct bmat4";   break;
     case EOpConstructBMat4x4: out.debug << "Construct bmat4";   break;
-#ifdef AMD_EXTENSIONS
     case EOpConstructFloat16:   out.debug << "Construct float16_t"; break;
     case EOpConstructFloat16:   out.debug << "Construct float16_t"; break;
     case EOpConstructF16Vec2:   out.debug << "Construct f16vec2";   break;
     case EOpConstructF16Vec2:   out.debug << "Construct f16vec2";   break;
     case EOpConstructF16Vec3:   out.debug << "Construct f16vec3";   break;
     case EOpConstructF16Vec3:   out.debug << "Construct f16vec3";   break;
@@ -622,7 +806,6 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
     case EOpConstructF16Mat4x2: out.debug << "Construct f16mat4x2"; break;
     case EOpConstructF16Mat4x2: out.debug << "Construct f16mat4x2"; break;
     case EOpConstructF16Mat4x3: out.debug << "Construct f16mat4x3"; break;
     case EOpConstructF16Mat4x3: out.debug << "Construct f16mat4x3"; break;
     case EOpConstructF16Mat4x4: out.debug << "Construct f16mat4";   break;
     case EOpConstructF16Mat4x4: out.debug << "Construct f16mat4";   break;
-#endif
     case EOpConstructStruct:  out.debug << "Construct structure";  break;
     case EOpConstructStruct:  out.debug << "Construct structure";  break;
     case EOpConstructTextureSampler: out.debug << "Construct combined texture-sampler"; break;
     case EOpConstructTextureSampler: out.debug << "Construct combined texture-sampler"; break;
 
 
@@ -688,6 +871,8 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
     case EOpAtomicXor:                  out.debug << "AtomicXor";             break;
     case EOpAtomicXor:                  out.debug << "AtomicXor";             break;
     case EOpAtomicExchange:             out.debug << "AtomicExchange";        break;
     case EOpAtomicExchange:             out.debug << "AtomicExchange";        break;
     case EOpAtomicCompSwap:             out.debug << "AtomicCompSwap";        break;
     case EOpAtomicCompSwap:             out.debug << "AtomicCompSwap";        break;
+    case EOpAtomicLoad:                 out.debug << "AtomicLoad";            break;
+    case EOpAtomicStore:                out.debug << "AtomicStore";           break;
 
 
     case EOpAtomicCounterAdd:           out.debug << "AtomicCounterAdd";      break;
     case EOpAtomicCounterAdd:           out.debug << "AtomicCounterAdd";      break;
     case EOpAtomicCounterSubtract:      out.debug << "AtomicCounterSubtract"; break;
     case EOpAtomicCounterSubtract:      out.debug << "AtomicCounterSubtract"; break;
@@ -711,6 +896,8 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
     case EOpImageAtomicXor:             out.debug << "imageAtomicXor";        break;
     case EOpImageAtomicXor:             out.debug << "imageAtomicXor";        break;
     case EOpImageAtomicExchange:        out.debug << "imageAtomicExchange";   break;
     case EOpImageAtomicExchange:        out.debug << "imageAtomicExchange";   break;
     case EOpImageAtomicCompSwap:        out.debug << "imageAtomicCompSwap";   break;
     case EOpImageAtomicCompSwap:        out.debug << "imageAtomicCompSwap";   break;
+    case EOpImageAtomicLoad:            out.debug << "imageAtomicLoad";       break;
+    case EOpImageAtomicStore:           out.debug << "imageAtomicStore";      break;
 #ifdef AMD_EXTENSIONS
 #ifdef AMD_EXTENSIONS
     case EOpImageLoadLod:               out.debug << "imageLoadLod";          break;
     case EOpImageLoadLod:               out.debug << "imageLoadLod";          break;
     case EOpImageStoreLod:              out.debug << "imageStoreLod";         break;
     case EOpImageStoreLod:              out.debug << "imageStoreLod";         break;
@@ -769,7 +956,13 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
     case EOpSparseTextureGatherLodOffsets:  out.debug << "sparseTextureGatherLodOffsets";   break;
     case EOpSparseTextureGatherLodOffsets:  out.debug << "sparseTextureGatherLodOffsets";   break;
     case EOpSparseImageLoadLod:             out.debug << "sparseImageLoadLod";              break;
     case EOpSparseImageLoadLod:             out.debug << "sparseImageLoadLod";              break;
 #endif
 #endif
-
+#ifdef NV_EXTENSIONS
+    case EOpImageSampleFootprintNV:             out.debug << "imageSampleFootprintNV";          break;
+    case EOpImageSampleFootprintClampNV:        out.debug << "imageSampleFootprintClampNV";     break;
+    case EOpImageSampleFootprintLodNV:          out.debug << "imageSampleFootprintLodNV";       break;
+    case EOpImageSampleFootprintGradNV:         out.debug << "imageSampleFootprintGradNV";      break;
+    case EOpImageSampleFootprintGradClampNV:    out.debug << "mageSampleFootprintGradClampNV";  break;
+#endif
     case EOpAddCarry:                   out.debug << "addCarry";              break;
     case EOpAddCarry:                   out.debug << "addCarry";              break;
     case EOpSubBorrow:                  out.debug << "subBorrow";             break;
     case EOpSubBorrow:                  out.debug << "subBorrow";             break;
     case EOpUMulExtended:               out.debug << "uMulExtended";          break;
     case EOpUMulExtended:               out.debug << "uMulExtended";          break;
@@ -796,9 +989,74 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
     case EOpWorkgroupMemoryBarrier:           out.debug << "WorkgroupMemoryBarrier";           break;
     case EOpWorkgroupMemoryBarrier:           out.debug << "WorkgroupMemoryBarrier";           break;
     case EOpWorkgroupMemoryBarrierWithGroupSync: out.debug << "WorkgroupMemoryBarrierWithGroupSync"; break;
     case EOpWorkgroupMemoryBarrierWithGroupSync: out.debug << "WorkgroupMemoryBarrierWithGroupSync"; break;
 
 
+    case EOpSubgroupBarrier:                 out.debug << "subgroupBarrier"; break;
+    case EOpSubgroupMemoryBarrier:           out.debug << "subgroupMemoryBarrier"; break;
+    case EOpSubgroupMemoryBarrierBuffer:     out.debug << "subgroupMemoryBarrierBuffer"; break;
+    case EOpSubgroupMemoryBarrierImage:      out.debug << "subgroupMemoryBarrierImage";   break;
+    case EOpSubgroupMemoryBarrierShared:     out.debug << "subgroupMemoryBarrierShared"; break;
+    case EOpSubgroupElect:                   out.debug << "subgroupElect"; break;
+    case EOpSubgroupAll:                     out.debug << "subgroupAll"; break;
+    case EOpSubgroupAny:                     out.debug << "subgroupAny"; break;
+    case EOpSubgroupAllEqual:                out.debug << "subgroupAllEqual"; break;
+    case EOpSubgroupBroadcast:               out.debug << "subgroupBroadcast"; break;
+    case EOpSubgroupBroadcastFirst:          out.debug << "subgroupBroadcastFirst"; break;
+    case EOpSubgroupBallot:                  out.debug << "subgroupBallot"; break;
+    case EOpSubgroupInverseBallot:           out.debug << "subgroupInverseBallot"; break;
+    case EOpSubgroupBallotBitExtract:        out.debug << "subgroupBallotBitExtract"; break;
+    case EOpSubgroupBallotBitCount:          out.debug << "subgroupBallotBitCount"; break;
+    case EOpSubgroupBallotInclusiveBitCount: out.debug << "subgroupBallotInclusiveBitCount"; break;
+    case EOpSubgroupBallotExclusiveBitCount: out.debug << "subgroupBallotExclusiveBitCount"; break;
+    case EOpSubgroupBallotFindLSB:           out.debug << "subgroupBallotFindLSB"; break;
+    case EOpSubgroupBallotFindMSB:           out.debug << "subgroupBallotFindMSB"; break;
+    case EOpSubgroupShuffle:                 out.debug << "subgroupShuffle"; break;
+    case EOpSubgroupShuffleXor:              out.debug << "subgroupShuffleXor"; break;
+    case EOpSubgroupShuffleUp:               out.debug << "subgroupShuffleUp"; break;
+    case EOpSubgroupShuffleDown:             out.debug << "subgroupShuffleDown"; break;
+    case EOpSubgroupAdd:                     out.debug << "subgroupAdd"; break;
+    case EOpSubgroupMul:                     out.debug << "subgroupMul"; break;
+    case EOpSubgroupMin:                     out.debug << "subgroupMin"; break;
+    case EOpSubgroupMax:                     out.debug << "subgroupMax"; break;
+    case EOpSubgroupAnd:                     out.debug << "subgroupAnd"; break;
+    case EOpSubgroupOr:                      out.debug << "subgroupOr"; break;
+    case EOpSubgroupXor:                     out.debug << "subgroupXor"; break;
+    case EOpSubgroupInclusiveAdd:            out.debug << "subgroupInclusiveAdd"; break;
+    case EOpSubgroupInclusiveMul:            out.debug << "subgroupInclusiveMul"; break;
+    case EOpSubgroupInclusiveMin:            out.debug << "subgroupInclusiveMin"; break;
+    case EOpSubgroupInclusiveMax:            out.debug << "subgroupInclusiveMax"; break;
+    case EOpSubgroupInclusiveAnd:            out.debug << "subgroupInclusiveAnd"; break;
+    case EOpSubgroupInclusiveOr:             out.debug << "subgroupInclusiveOr"; break;
+    case EOpSubgroupInclusiveXor:            out.debug << "subgroupInclusiveXor"; break;
+    case EOpSubgroupExclusiveAdd:            out.debug << "subgroupExclusiveAdd"; break;
+    case EOpSubgroupExclusiveMul:            out.debug << "subgroupExclusiveMul"; break;
+    case EOpSubgroupExclusiveMin:            out.debug << "subgroupExclusiveMin"; break;
+    case EOpSubgroupExclusiveMax:            out.debug << "subgroupExclusiveMax"; break;
+    case EOpSubgroupExclusiveAnd:            out.debug << "subgroupExclusiveAnd"; break;
+    case EOpSubgroupExclusiveOr:             out.debug << "subgroupExclusiveOr"; break;
+    case EOpSubgroupExclusiveXor:            out.debug << "subgroupExclusiveXor"; break;
+    case EOpSubgroupClusteredAdd:            out.debug << "subgroupClusteredAdd"; break;
+    case EOpSubgroupClusteredMul:            out.debug << "subgroupClusteredMul"; break;
+    case EOpSubgroupClusteredMin:            out.debug << "subgroupClusteredMin"; break;
+    case EOpSubgroupClusteredMax:            out.debug << "subgroupClusteredMax"; break;
+    case EOpSubgroupClusteredAnd:            out.debug << "subgroupClusteredAnd"; break;
+    case EOpSubgroupClusteredOr:             out.debug << "subgroupClusteredOr"; break;
+    case EOpSubgroupClusteredXor:            out.debug << "subgroupClusteredXor"; break;
+    case EOpSubgroupQuadBroadcast:           out.debug << "subgroupQuadBroadcast"; break;
+    case EOpSubgroupQuadSwapHorizontal:      out.debug << "subgroupQuadSwapHorizontal"; break;
+    case EOpSubgroupQuadSwapVertical:        out.debug << "subgroupQuadSwapVertical"; break;
+    case EOpSubgroupQuadSwapDiagonal:        out.debug << "subgroupQuadSwapDiagonal"; break;
+
     case EOpSubpassLoad:   out.debug << "subpassLoad";   break;
     case EOpSubpassLoad:   out.debug << "subpassLoad";   break;
     case EOpSubpassLoadMS: out.debug << "subpassLoadMS"; break;
     case EOpSubpassLoadMS: out.debug << "subpassLoadMS"; break;
 
 
+#ifdef NV_EXTENSIONS
+    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 EOpWritePackedPrimitiveIndices4x8NV: out.debug << "writePackedPrimitiveIndices4x8NV"; break;
+#endif
+
     default: out.debug.message(EPrefixError, "Bad aggregation op");
     default: out.debug.message(EPrefixError, "Bad aggregation op");
     }
     }
 
 
@@ -817,7 +1075,15 @@ bool TOutputTraverser::visitSelection(TVisit /* visit */, TIntermSelection* node
     OutputTreeText(out, node, depth);
     OutputTreeText(out, node, depth);
 
 
     out.debug << "Test condition and select";
     out.debug << "Test condition and select";
-    out.debug << " (" << node->getCompleteString() << ")\n";
+    out.debug << " (" << node->getCompleteString() << ")";
+
+    if (node->getShortCircuit() == false)
+        out.debug << ": no shortcircuit";
+    if (node->getFlatten())
+        out.debug << ": Flatten";
+    if (node->getDontFlatten())
+        out.debug << ": DontFlatten";
+    out.debug << "\n";
 
 
     ++depth;
     ++depth;
 
 
@@ -843,7 +1109,61 @@ bool TOutputTraverser::visitSelection(TVisit /* visit */, TIntermSelection* node
     return false;
     return false;
 }
 }
 
 
-static void OutputConstantUnion(TInfoSink& out, const TIntermTyped* node, const TConstUnionArray& constUnion, int depth)
+// Print infinities and NaNs, and numbers in a portable way.
+// Goals:
+//   - portable (across IEEE 754 platforms)
+//   - shows all possible IEEE values
+//   - shows simple numbers in a simple way, e.g., no leading/trailing 0s
+//   - shows all digits, no premature rounding
+static void OutputDouble(TInfoSink& out, double value, TOutputTraverser::EExtraOutput extra)
+{
+    if (IsInfinity(value)) {
+        if (value < 0)
+            out.debug << "-1.#INF";
+        else
+            out.debug << "+1.#INF";
+    } else if (IsNan(value))
+        out.debug << "1.#IND";
+    else {
+        const int maxSize = 340;
+        char buf[maxSize];
+        const char* format = "%f";
+        if (fabs(value) > 0.0 && (fabs(value) < 1e-5 || fabs(value) > 1e12))
+            format = "%-.13e";
+        int len = snprintf(buf, maxSize, format, value);
+        assert(len < maxSize);
+
+        // remove a leading zero in the 100s slot in exponent; it is not portable
+        // pattern:   XX...XXXe+0XX or XX...XXXe-0XX
+        if (len > 5) {
+            if (buf[len-5] == 'e' && (buf[len-4] == '+' || buf[len-4] == '-') && buf[len-3] == '0') {
+                buf[len-3] = buf[len-2];
+                buf[len-2] = buf[len-1];
+                buf[len-1] = '\0';
+            }
+        }
+
+        out.debug << buf;
+
+        switch (extra) {
+        case TOutputTraverser::BinaryDoubleOutput:
+        {
+            out.debug << " : ";
+            long long b = *reinterpret_cast<long long*>(&value);
+            for (size_t i = 0; i < 8 * sizeof(value); ++i, ++b) {
+                out.debug << ((b & 0x8000000000000000) != 0 ? "1" : "0");
+                b <<= 1;
+            }
+            break;
+        }
+        default:
+            break;
+        }
+    }
+}
+
+static void OutputConstantUnion(TInfoSink& out, const TIntermTyped* node, const TConstUnionArray& constUnion,
+    TOutputTraverser::EExtraOutput extra, int depth)
 {
 {
     int size = node->getType().computeNumComponents();
     int size = node->getType().computeNumComponents();
 
 
@@ -862,84 +1182,82 @@ static void OutputConstantUnion(TInfoSink& out, const TIntermTyped* node, const
             break;
             break;
         case EbtFloat:
         case EbtFloat:
         case EbtDouble:
         case EbtDouble:
-#ifdef AMD_EXTENSIONS
         case EbtFloat16:
         case EbtFloat16:
-#endif
+            OutputDouble(out, constUnion[i].getDConst(), extra);
+            out.debug << "\n";
+            break;
+        case EbtInt8:
             {
             {
-                const double value = constUnion[i].getDConst();
-                // Print infinities and NaNs in a portable way.
-                if (IsInfinity(value)) {
-                    if (value < 0)
-                        out.debug << "-1.#INF\n";
-                    else
-                        out.debug << "+1.#INF\n";
-                } else if (IsNan(value))
-                    out.debug << "1.#IND\n";
-                else {
-                    const int maxSize = 300;
-                    char buf[maxSize];
-                    snprintf(buf, maxSize, "%f", value);
-
-                    out.debug << buf << "\n";
-                }
+                const int maxSize = 300;
+                char buf[maxSize];
+                snprintf(buf, maxSize, "%d (%s)", constUnion[i].getI8Const(), "const int8_t");
+
+                out.debug << buf << "\n";
             }
             }
             break;
             break;
-        case EbtInt:
+        case EbtUint8:
             {
             {
                 const int maxSize = 300;
                 const int maxSize = 300;
                 char buf[maxSize];
                 char buf[maxSize];
-                snprintf(buf, maxSize, "%d (%s)", constUnion[i].getIConst(), "const int");
+                snprintf(buf, maxSize, "%u (%s)", constUnion[i].getU8Const(), "const uint8_t");
 
 
                 out.debug << buf << "\n";
                 out.debug << buf << "\n";
             }
             }
             break;
             break;
-        case EbtUint:
+        case EbtInt16:
             {
             {
                 const int maxSize = 300;
                 const int maxSize = 300;
                 char buf[maxSize];
                 char buf[maxSize];
-                snprintf(buf, maxSize, "%u (%s)", constUnion[i].getUConst(), "const uint");
+                snprintf(buf, maxSize, "%d (%s)", constUnion[i].getI16Const(), "const int16_t");
 
 
                 out.debug << buf << "\n";
                 out.debug << buf << "\n";
             }
             }
             break;
             break;
-        case EbtInt64:
+        case EbtUint16:
             {
             {
                 const int maxSize = 300;
                 const int maxSize = 300;
                 char buf[maxSize];
                 char buf[maxSize];
-                snprintf(buf, maxSize, "%lld (%s)", constUnion[i].getI64Const(), "const int64_t");
+                snprintf(buf, maxSize, "%u (%s)", constUnion[i].getU16Const(), "const uint16_t");
 
 
                 out.debug << buf << "\n";
                 out.debug << buf << "\n";
             }
             }
             break;
             break;
-        case EbtUint64:
+        case EbtInt:
             {
             {
                 const int maxSize = 300;
                 const int maxSize = 300;
                 char buf[maxSize];
                 char buf[maxSize];
-                snprintf(buf, maxSize, "%llu (%s)", constUnion[i].getU64Const(), "const uint64_t");
+                snprintf(buf, maxSize, "%d (%s)", constUnion[i].getIConst(), "const int");
 
 
                 out.debug << buf << "\n";
                 out.debug << buf << "\n";
             }
             }
             break;
             break;
-#ifdef AMD_EXTENSIONS
-        case EbtInt16:
+        case EbtUint:
             {
             {
                 const int maxSize = 300;
                 const int maxSize = 300;
                 char buf[maxSize];
                 char buf[maxSize];
-                snprintf(buf, maxSize, "%d (%s)", constUnion[i].getIConst(), "const int16_t");
+                snprintf(buf, maxSize, "%u (%s)", constUnion[i].getUConst(), "const uint");
 
 
                 out.debug << buf << "\n";
                 out.debug << buf << "\n";
             }
             }
             break;
             break;
-        case EbtUint16:
+        case EbtInt64:
             {
             {
                 const int maxSize = 300;
                 const int maxSize = 300;
                 char buf[maxSize];
                 char buf[maxSize];
-                snprintf(buf, maxSize, "%u (%s)", constUnion[i].getUConst(), "const uint16_t");
+                snprintf(buf, maxSize, "%lld (%s)", constUnion[i].getI64Const(), "const int64_t");
+
+                out.debug << buf << "\n";
+            }
+            break;
+        case EbtUint64:
+            {
+                const int maxSize = 300;
+                char buf[maxSize];
+                snprintf(buf, maxSize, "%llu (%s)", constUnion[i].getU64Const(), "const uint64_t");
 
 
                 out.debug << buf << "\n";
                 out.debug << buf << "\n";
             }
             }
             break;
             break;
-#endif
         default:
         default:
             out.info.message(EPrefixInternalError, "Unknown constant", node->getLoc());
             out.info.message(EPrefixInternalError, "Unknown constant", node->getLoc());
             break;
             break;
@@ -952,7 +1270,7 @@ void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node)
     OutputTreeText(infoSink, node, depth);
     OutputTreeText(infoSink, node, depth);
     infoSink.debug << "Constant:\n";
     infoSink.debug << "Constant:\n";
 
 
-    OutputConstantUnion(infoSink, node, node->getConstArray(), depth + 1);
+    OutputConstantUnion(infoSink, node, node->getConstArray(), extraOutput, depth + 1);
 }
 }
 
 
 void TOutputTraverser::visitSymbol(TIntermSymbol* node)
 void TOutputTraverser::visitSymbol(TIntermSymbol* node)
@@ -962,7 +1280,7 @@ void TOutputTraverser::visitSymbol(TIntermSymbol* node)
     infoSink.debug << "'" << node->getName() << "' (" << node->getCompleteString() << ")\n";
     infoSink.debug << "'" << node->getName() << "' (" << node->getCompleteString() << ")\n";
 
 
     if (! node->getConstArray().empty())
     if (! node->getConstArray().empty())
-        OutputConstantUnion(infoSink, node, node->getConstArray(), depth + 1);
+        OutputConstantUnion(infoSink, node, node->getConstArray(), extraOutput, depth + 1);
     else if (node->getConstSubtree()) {
     else if (node->getConstSubtree()) {
         incrementDepth(node);
         incrementDepth(node);
         node->getConstSubtree()->traverse(this);
         node->getConstSubtree()->traverse(this);
@@ -979,7 +1297,17 @@ bool TOutputTraverser::visitLoop(TVisit /* visit */, TIntermLoop* node)
     out.debug << "Loop with condition ";
     out.debug << "Loop with condition ";
     if (! node->testFirst())
     if (! node->testFirst())
         out.debug << "not ";
         out.debug << "not ";
-    out.debug << "tested first\n";
+    out.debug << "tested first";
+
+    if (node->getUnroll())
+        out.debug << ": Unroll";
+    if (node->getDontUnroll())
+        out.debug << ": DontUnroll";
+    if (node->getLoopDependency()) {
+        out.debug << ": Dependency ";
+        out.debug << node->getLoopDependency();
+    }
+    out.debug << "\n";
 
 
     ++depth;
     ++depth;
 
 
@@ -1040,7 +1368,13 @@ bool TOutputTraverser::visitSwitch(TVisit /* visit */, TIntermSwitch* node)
     TInfoSink& out = infoSink;
     TInfoSink& out = infoSink;
 
 
     OutputTreeText(out, node, depth);
     OutputTreeText(out, node, depth);
-    out.debug << "switch\n";
+    out.debug << "switch";
+
+    if (node->getFlatten())
+        out.debug << ": Flatten";
+    if (node->getDontFlatten())
+        out.debug << ": DontFlatten";
+    out.debug << "\n";
 
 
     OutputTreeText(out, node, depth);
     OutputTreeText(out, node, depth);
     out.debug << "condition\n";
     out.debug << "condition\n";
@@ -1126,6 +1460,16 @@ void TIntermediate::output(TInfoSink& infoSink, bool tree)
         }
         }
         break;
         break;
 
 
+#ifdef NV_EXTENSIONS
+    case EShLangMeshNV:
+        infoSink.debug << "max_vertices = " << vertices << "\n";
+        infoSink.debug << "max_primitives = " << primitives << "\n";
+        infoSink.debug << "output primitive = " << TQualifier::getGeometryString(outputPrimitive) << "\n";
+        // Fall through
+
+    case EShLangTaskNV:
+        // Fall through
+#endif
     case EShLangCompute:
     case EShLangCompute:
         infoSink.debug << "local_size = (" << localSize[0] << ", " << localSize[1] << ", " << localSize[2] << ")\n";
         infoSink.debug << "local_size = (" << localSize[0] << ", " << localSize[1] << ", " << localSize[2] << ")\n";
         {
         {
@@ -1148,7 +1492,8 @@ void TIntermediate::output(TInfoSink& infoSink, bool tree)
         return;
         return;
 
 
     TOutputTraverser it(infoSink);
     TOutputTraverser it(infoSink);
-
+    if (getBinaryDoubleOutput())
+        it.setDoubleOutput(TOutputTraverser::BinaryDoubleOutput);
     treeRoot->traverse(&it);
     treeRoot->traverse(&it);
 }
 }
 
 

+ 79 - 39
src/libraries/glslang/glslang/MachineIndependent/iomapper.cpp

@@ -132,7 +132,7 @@ public:
             target = &inputList;
             target = &inputList;
         else if (base->getQualifier().storage == EvqVaryingOut)
         else if (base->getQualifier().storage == EvqVaryingOut)
             target = &outputList;
             target = &outputList;
-        else if (base->getQualifier().isUniformOrBuffer())
+        else if (base->getQualifier().isUniformOrBuffer() && !base->getQualifier().layoutPushConstant)
             target = &uniformList;
             target = &uniformList;
 
 
         if (target) {
         if (target) {
@@ -331,8 +331,14 @@ struct TResolverInOutAdaptor
                                                       ent.symbol->getType(),
                                                       ent.symbol->getType(),
                                                       ent.live);
                                                       ent.live);
         } else {
         } else {
-            TString errorMsg = "Invalid shader In/Out variable semantic: ";
-            errorMsg += ent.symbol->getType().getQualifier().semanticName;
+            TString errorMsg;
+            if (ent.symbol->getType().getQualifier().semanticName != nullptr) {
+                errorMsg = "Invalid shader In/Out variable semantic: ";
+                errorMsg += ent.symbol->getType().getQualifier().semanticName;
+            } else {
+                errorMsg = "Invalid shader In/Out variable: ";
+                errorMsg += ent.symbol->getName();
+            }
             infoSink.info.message(EPrefixInternalError, errorMsg.c_str());
             infoSink.info.message(EPrefixInternalError, errorMsg.c_str());
             error = true;
             error = true;
         }
         }
@@ -353,7 +359,9 @@ struct TDefaultIoResolverBase : public glslang::TIoMapResolver
 {
 {
     TDefaultIoResolverBase(const TIntermediate &intermediate) :
     TDefaultIoResolverBase(const TIntermediate &intermediate) :
         intermediate(intermediate),
         intermediate(intermediate),
-        nextUniformLocation(0)
+        nextUniformLocation(intermediate.getUniformLocationBase()),
+        nextInputLocation(0),
+        nextOutputLocation(0)
     { }
     { }
 
 
     int getBaseBinding(TResourceType res, unsigned int set) const {
     int getBaseBinding(TResourceType res, unsigned int set) const {
@@ -381,29 +389,34 @@ struct TDefaultIoResolverBase : public glslang::TIoMapResolver
         return !(at != slots[set].end() && *at == slot);
         return !(at != slots[set].end() && *at == slot);
     }
     }
 
 
-    int reserveSlot(int set, int slot)
+    int reserveSlot(int set, int slot, int size = 1)
     {
     {
         TSlotSet::iterator at = findSlot(set, slot);
         TSlotSet::iterator at = findSlot(set, slot);
 
 
         // tolerate aliasing, by not double-recording aliases
         // tolerate aliasing, by not double-recording aliases
         // (policy about appropriateness of the alias is higher up)
         // (policy about appropriateness of the alias is higher up)
-        if (at == slots[set].end() || *at != slot)
-            slots[set].insert(at, slot);
+        for (int i = 0; i < size; i++) {
+                if (at == slots[set].end() || *at != slot + i)
+                        at = slots[set].insert(at, slot + i);
+                ++at;
+        }
 
 
         return slot;
         return slot;
     }
     }
 
 
-    int getFreeSlot(int set, int base)
+    int getFreeSlot(int set, int base, int size = 1)
     {
     {
         TSlotSet::iterator at = findSlot(set, base);
         TSlotSet::iterator at = findSlot(set, base);
         if (at == slots[set].end())
         if (at == slots[set].end())
-            return reserveSlot(set, base);
+            return reserveSlot(set, base, size);
 
 
-        // look in locksteps, if they not match, then there is a free slot
-        for (; at != slots[set].end(); ++at, ++base)
-            if (*at != base)
+        // look for a big enough gap
+        for (; at != slots[set].end(); ++at) {
+            if (*at - base >= size)
                 break;
                 break;
-        return reserveSlot(set, base);
+            base = *at + 1;
+        }
+        return reserveSlot(set, base, size);
     }
     }
 
 
     virtual bool validateBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool /*is_live*/) override = 0;
     virtual bool validateBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool /*is_live*/) override = 0;
@@ -421,7 +434,7 @@ struct TDefaultIoResolverBase : public glslang::TIoMapResolver
 
 
         return 0;
         return 0;
     }
     }
-    int resolveUniformLocation(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool /*is_live*/) override
+    int resolveUniformLocation(EShLanguage /*stage*/, const char* name, const glslang::TType& type, bool /*is_live*/) override
     {
     {
         // kick out of not doing this
         // kick out of not doing this
         if (!doAutoLocationMapping())
         if (!doAutoLocationMapping())
@@ -429,7 +442,9 @@ struct TDefaultIoResolverBase : public glslang::TIoMapResolver
 
 
         // no locations added if already present, a built-in variable, a block, or an opaque
         // no locations added if already present, a built-in variable, a block, or an opaque
         if (type.getQualifier().hasLocation() || type.isBuiltIn() ||
         if (type.getQualifier().hasLocation() || type.isBuiltIn() ||
-            type.getBasicType() == EbtBlock || type.containsOpaque())
+            type.getBasicType() == EbtBlock ||
+            type.getBasicType() == EbtAtomicUint ||
+            (type.containsOpaque() && intermediate.getSpv().openGl == 0))
             return -1;
             return -1;
 
 
         // no locations on blocks of built-in variables
         // no locations on blocks of built-in variables
@@ -440,13 +455,21 @@ struct TDefaultIoResolverBase : public glslang::TIoMapResolver
                 return -1;
                 return -1;
         }
         }
 
 
-        return nextUniformLocation++;
+        int location = intermediate.getUniformLocationOverride(name);
+        if (location != -1)
+            return location;
+
+        location = nextUniformLocation;
+
+        nextUniformLocation += TIntermediate::computeTypeUniformLocationSize(type);
+
+        return location;
     }
     }
     bool validateInOut(EShLanguage /*stage*/, const char* /*name*/, const TType& /*type*/, bool /*is_live*/) override
     bool validateInOut(EShLanguage /*stage*/, const char* /*name*/, const TType& /*type*/, bool /*is_live*/) override
     {
     {
         return true;
         return true;
     }
     }
-    int resolveInOutLocation(EShLanguage /*stage*/, const char* /*name*/, const TType& type, bool /*is_live*/) override
+    int resolveInOutLocation(EShLanguage stage, const char* /*name*/, const TType& type, bool /*is_live*/) override
     {
     {
         // kick out of not doing this
         // kick out of not doing this
         if (!doAutoLocationMapping())
         if (!doAutoLocationMapping())
@@ -464,14 +487,24 @@ struct TDefaultIoResolverBase : public glslang::TIoMapResolver
                 return -1;
                 return -1;
         }
         }
 
 
-        // Placeholder.
-        // TODO: It would be nice to flesh this out using 
-        // intermediate->computeTypeLocationSize(type), or functions that call it like
-        // intermediate->addUsedLocation()
-        // These in turn would want the intermediate, which is not available here, but
-        // is available in many places, and a lot of copying from it could be saved if
-        // it were just available.
-        return 0;
+        // point to the right input or output location counter
+        int& nextLocation = type.getQualifier().isPipeInput() ? nextInputLocation : nextOutputLocation;
+
+        // Placeholder. This does not do proper cross-stage lining up, nor
+        // work with mixed location/no-location declarations.
+        int location = nextLocation;
+        int typeLocationSize;
+        // Don’t take into account the outer-most array if the stage’s
+        // interface is automatically an array.
+        if (type.getQualifier().isArrayedIo(stage)) {
+                TType elementType(type, 0);
+                typeLocationSize = TIntermediate::computeTypeLocationSize(elementType, stage);
+        } else {
+                typeLocationSize = TIntermediate::computeTypeLocationSize(type, stage);
+        }
+        nextLocation += typeLocationSize;
+
+        return location;
     }
     }
     int resolveInOutComponent(EShLanguage /*stage*/, const char* /*name*/, const TType& /*type*/, bool /*is_live*/) override
     int resolveInOutComponent(EShLanguage /*stage*/, const char* /*name*/, const TType& /*type*/, bool /*is_live*/) override
     {
     {
@@ -490,8 +523,13 @@ struct TDefaultIoResolverBase : public glslang::TIoMapResolver
     void endResolve(EShLanguage) override {}
     void endResolve(EShLanguage) override {}
 
 
 protected:
 protected:
+    TDefaultIoResolverBase(TDefaultIoResolverBase&);
+    TDefaultIoResolverBase& operator=(TDefaultIoResolverBase&);
+
     const TIntermediate &intermediate;
     const TIntermediate &intermediate;
     int nextUniformLocation;
     int nextUniformLocation;
+    int nextInputLocation;
+    int nextOutputLocation;
 
 
     // Return descriptor set specific base if there is one, and the generic base otherwise.
     // Return descriptor set specific base if there is one, and the generic base otherwise.
     int selectBaseBinding(int base, int descriptorSetBase) const {
     int selectBaseBinding(int base, int descriptorSetBase) const {
@@ -541,40 +579,42 @@ struct TDefaultIoResolver : public TDefaultIoResolverBase
     int resolveBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool is_live) override
     int resolveBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool is_live) override
     {
     {
         const int set = getLayoutSet(type);
         const int set = getLayoutSet(type);
+        // On OpenGL arrays of opaque types take a seperate binding for each element
+        int numBindings = intermediate.getSpv().openGl != 0 && type.isSizedArray() ? type.getCumulativeArraySize() : 1;
 
 
         if (type.getQualifier().hasBinding()) {
         if (type.getQualifier().hasBinding()) {
             if (isImageType(type))
             if (isImageType(type))
-                return reserveSlot(set, getBaseBinding(EResImage, set) + type.getQualifier().layoutBinding);
+                return reserveSlot(set, getBaseBinding(EResImage, set) + type.getQualifier().layoutBinding, numBindings);
 
 
             if (isTextureType(type))
             if (isTextureType(type))
-                return reserveSlot(set, getBaseBinding(EResTexture, set) + type.getQualifier().layoutBinding);
+                return reserveSlot(set, getBaseBinding(EResTexture, set) + type.getQualifier().layoutBinding, numBindings);
 
 
             if (isSsboType(type))
             if (isSsboType(type))
-                return reserveSlot(set, getBaseBinding(EResSsbo, set) + type.getQualifier().layoutBinding);
+                return reserveSlot(set, getBaseBinding(EResSsbo, set) + type.getQualifier().layoutBinding, numBindings);
 
 
             if (isSamplerType(type))
             if (isSamplerType(type))
-                return reserveSlot(set, getBaseBinding(EResSampler, set) + type.getQualifier().layoutBinding);
+                return reserveSlot(set, getBaseBinding(EResSampler, set) + type.getQualifier().layoutBinding, numBindings);
 
 
             if (isUboType(type))
             if (isUboType(type))
-                return reserveSlot(set, getBaseBinding(EResUbo, set) + type.getQualifier().layoutBinding);
+                return reserveSlot(set, getBaseBinding(EResUbo, set) + type.getQualifier().layoutBinding, numBindings);
         } else if (is_live && doAutoBindingMapping()) {
         } else if (is_live && doAutoBindingMapping()) {
             // find free slot, the caller did make sure it passes all vars with binding
             // find free slot, the caller did make sure it passes all vars with binding
             // first and now all are passed that do not have a binding and needs one
             // first and now all are passed that do not have a binding and needs one
 
 
             if (isImageType(type))
             if (isImageType(type))
-                return getFreeSlot(set, getBaseBinding(EResImage, set));
+                return getFreeSlot(set, getBaseBinding(EResImage, set), numBindings);
 
 
             if (isTextureType(type))
             if (isTextureType(type))
-                return getFreeSlot(set, getBaseBinding(EResTexture, set));
+                return getFreeSlot(set, getBaseBinding(EResTexture, set), numBindings);
 
 
             if (isSsboType(type))
             if (isSsboType(type))
-                return getFreeSlot(set, getBaseBinding(EResSsbo, set));
+                return getFreeSlot(set, getBaseBinding(EResSsbo, set), numBindings);
 
 
             if (isSamplerType(type))
             if (isSamplerType(type))
-                return getFreeSlot(set, getBaseBinding(EResSampler, set));
+                return getFreeSlot(set, getBaseBinding(EResSampler, set), numBindings);
 
 
             if (isUboType(type))
             if (isUboType(type))
-                return getFreeSlot(set, getBaseBinding(EResUbo, set));
+                return getFreeSlot(set, getBaseBinding(EResUbo, set), numBindings);
         }
         }
 
 
         return -1;
         return -1;
@@ -593,7 +633,7 @@ protected:
 /********************************************************************************
 /********************************************************************************
 The following IO resolver maps types in HLSL register space, as follows:
 The following IO resolver maps types in HLSL register space, as follows:
 
 
-t  for shader resource views (SRV)
+t - for shader resource views (SRV)
    TEXTURE1D
    TEXTURE1D
    TEXTURE1DARRAY
    TEXTURE1DARRAY
    TEXTURE2D
    TEXTURE2D
@@ -608,7 +648,7 @@ t – for shader resource views (SRV)
    BUFFER
    BUFFER
    TBUFFER
    TBUFFER
     
     
-s  for samplers
+s - for samplers
    SAMPLER
    SAMPLER
    SAMPLER1D
    SAMPLER1D
    SAMPLER2D
    SAMPLER2D
@@ -617,7 +657,7 @@ s – for samplers
    SAMPLERSTATE
    SAMPLERSTATE
    SAMPLERCOMPARISONSTATE
    SAMPLERCOMPARISONSTATE
 
 
-u  for unordered access views (UAV)
+u - for unordered access views (UAV)
    RWBYTEADDRESSBUFFER
    RWBYTEADDRESSBUFFER
    RWSTRUCTUREDBUFFER
    RWSTRUCTUREDBUFFER
    APPENDSTRUCTUREDBUFFER
    APPENDSTRUCTUREDBUFFER
@@ -629,7 +669,7 @@ u – for unordered access views (UAV)
    RWTEXTURE2DARRAY
    RWTEXTURE2DARRAY
    RWTEXTURE3D
    RWTEXTURE3D
 
 
-b  for constant buffer views (CBV)
+b - for constant buffer views (CBV)
    CBUFFER
    CBUFFER
    CONSTANTBUFFER
    CONSTANTBUFFER
  ********************************************************************************/
  ********************************************************************************/

+ 454 - 90
src/libraries/glslang/glslang/MachineIndependent/linkValidate.cpp

@@ -1,5 +1,7 @@
 //
 //
 // Copyright (C) 2013 LunarG, Inc.
 // Copyright (C) 2013 LunarG, Inc.
+// Copyright (C) 2017 ARM Limited.
+// Copyright (C) 2015-2018 Google, Inc.
 //
 //
 // All rights reserved.
 // All rights reserved.
 //
 //
@@ -76,12 +78,13 @@ void TIntermediate::warn(TInfoSink& infoSink, const char* message)
 //
 //
 void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
 void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
 {
 {
-    if (source == EShSourceNone)
-        source = unit.source;
-
-    if (source != unit.source)
-        error(infoSink, "can't link compilation units from different source languages");
+    mergeCallGraphs(infoSink, unit);
+    mergeModes(infoSink, unit);
+    mergeTrees(infoSink, unit);
+}
 
 
+void TIntermediate::mergeCallGraphs(TInfoSink& infoSink, TIntermediate& unit)
+{
     if (unit.getNumEntryPoints() > 0) {
     if (unit.getNumEntryPoints() > 0) {
         if (getNumEntryPoints() > 0)
         if (getNumEntryPoints() > 0)
             error(infoSink, "can't handle multiple entry points per stage");
             error(infoSink, "can't handle multiple entry points per stage");
@@ -91,46 +94,88 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
         }
         }
     }
     }
     numEntryPoints += unit.getNumEntryPoints();
     numEntryPoints += unit.getNumEntryPoints();
-    numErrors += unit.getNumErrors();
-    numPushConstants += unit.numPushConstants;
+
     callGraph.insert(callGraph.end(), unit.callGraph.begin(), unit.callGraph.end());
     callGraph.insert(callGraph.end(), unit.callGraph.begin(), unit.callGraph.end());
+}
 
 
-    if (originUpperLeft != unit.originUpperLeft || pixelCenterInteger != unit.pixelCenterInteger)
-        error(infoSink, "gl_FragCoord redeclarations must match across shaders");
+#define MERGE_MAX(member) member = std::max(member, unit.member)
+#define MERGE_TRUE(member) if (unit.member) member = unit.member;
 
 
-    if (! earlyFragmentTests)
-        earlyFragmentTests = unit.earlyFragmentTests;
+void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit)
+{
+    if (language != unit.language)
+        error(infoSink, "stages must match when linking into a single stage");
 
 
-    if (!postDepthCoverage)
-        postDepthCoverage = unit.postDepthCoverage;
+    if (source == EShSourceNone)
+        source = unit.source;
+    if (source != unit.source)
+        error(infoSink, "can't link compilation units from different source languages");
 
 
-    if (depthLayout == EldNone)
-        depthLayout = unit.depthLayout;
-    else if (depthLayout != unit.depthLayout)
-        error(infoSink, "Contradictory depth layouts");
+    if (treeRoot == nullptr) {
+        profile = unit.profile;
+        version = unit.version;
+        requestedExtensions = unit.requestedExtensions;
+    } else {
+        if ((profile == EEsProfile) != (unit.profile == EEsProfile))
+            error(infoSink, "Cannot cross link ES and desktop profiles");
+        else if (unit.profile == ECompatibilityProfile)
+            profile = ECompatibilityProfile;
+        version = std::max(version, unit.version);
+        requestedExtensions.insert(unit.requestedExtensions.begin(), unit.requestedExtensions.end());
+    }
 
 
-    blendEquations |= unit.blendEquations;
+    MERGE_MAX(spvVersion.spv);
+    MERGE_MAX(spvVersion.vulkanGlsl);
+    MERGE_MAX(spvVersion.vulkan);
+    MERGE_MAX(spvVersion.openGl);
 
 
-    if (inputPrimitive == ElgNone)
-        inputPrimitive = unit.inputPrimitive;
-    else if (inputPrimitive != unit.inputPrimitive)
-        error(infoSink, "Contradictory input layout primitives");
+    numErrors += unit.getNumErrors();
+    numPushConstants += unit.numPushConstants;
 
 
-    if (outputPrimitive == ElgNone)
-        outputPrimitive = unit.outputPrimitive;
-    else if (outputPrimitive != unit.outputPrimitive)
-        error(infoSink, "Contradictory output layout primitives");
+    if (unit.invocations != TQualifier::layoutNotSet) {
+        if (invocations == TQualifier::layoutNotSet)
+            invocations = unit.invocations;
+        else if (invocations != unit.invocations)
+            error(infoSink, "number of invocations must match between compilation units");
+    }
 
 
     if (vertices == TQualifier::layoutNotSet)
     if (vertices == TQualifier::layoutNotSet)
         vertices = unit.vertices;
         vertices = unit.vertices;
     else if (vertices != unit.vertices) {
     else if (vertices != unit.vertices) {
-        if (language == EShLangGeometry)
+        if (language == EShLangGeometry
+#ifdef NV_EXTENSIONS
+            || language == EShLangMeshNV
+#endif
+            )
             error(infoSink, "Contradictory layout max_vertices values");
             error(infoSink, "Contradictory layout max_vertices values");
         else if (language == EShLangTessControl)
         else if (language == EShLangTessControl)
             error(infoSink, "Contradictory layout vertices values");
             error(infoSink, "Contradictory layout vertices values");
         else
         else
             assert(0);
             assert(0);
     }
     }
+#ifdef NV_EXTENSIONS
+    if (primitives == TQualifier::layoutNotSet)
+        primitives = unit.primitives;
+    else if (primitives != unit.primitives) {
+        if (language == EShLangMeshNV)
+            error(infoSink, "Contradictory layout max_primitives values");
+        else
+            assert(0);
+    }
+#endif
+
+    if (inputPrimitive == ElgNone)
+        inputPrimitive = unit.inputPrimitive;
+    else if (inputPrimitive != unit.inputPrimitive)
+        error(infoSink, "Contradictory input layout primitives");
+
+    if (outputPrimitive == ElgNone)
+        outputPrimitive = unit.outputPrimitive;
+    else if (outputPrimitive != unit.outputPrimitive)
+        error(infoSink, "Contradictory output layout primitives");
+
+    if (originUpperLeft != unit.originUpperLeft || pixelCenterInteger != unit.pixelCenterInteger)
+        error(infoSink, "gl_FragCoord redeclarations must match across shaders");
 
 
     if (vertexSpacing == EvsNone)
     if (vertexSpacing == EvsNone)
         vertexSpacing = unit.vertexSpacing;
         vertexSpacing = unit.vertexSpacing;
@@ -142,8 +187,7 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
     else if (vertexOrder != unit.vertexOrder)
     else if (vertexOrder != unit.vertexOrder)
         error(infoSink, "Contradictory triangle ordering");
         error(infoSink, "Contradictory triangle ordering");
 
 
-    if (unit.pointMode)
-        pointMode = true;
+    MERGE_TRUE(pointMode);
 
 
     for (int i = 0; i < 3; ++i) {
     for (int i = 0; i < 3; ++i) {
         if (localSize[i] > 1)
         if (localSize[i] > 1)
@@ -157,8 +201,21 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
             error(infoSink, "Contradictory local size specialization ids");
             error(infoSink, "Contradictory local size specialization ids");
     }
     }
 
 
-    if (unit.xfbMode)
-        xfbMode = true;
+    MERGE_TRUE(earlyFragmentTests);
+    MERGE_TRUE(postDepthCoverage);
+
+    if (depthLayout == EldNone)
+        depthLayout = unit.depthLayout;
+    else if (depthLayout != unit.depthLayout)
+        error(infoSink, "Contradictory depth layouts");
+
+    MERGE_TRUE(depthReplacing);
+    MERGE_TRUE(hlslFunctionality1);
+
+    blendEquations |= unit.blendEquations;
+
+    MERGE_TRUE(xfbMode);
+
     for (size_t b = 0; b < xfbBuffers.size(); ++b) {
     for (size_t b = 0; b < xfbBuffers.size(); ++b) {
         if (xfbBuffers[b].stride == TQualifier::layoutXfbStrideEnd)
         if (xfbBuffers[b].stride == TQualifier::layoutXfbStrideEnd)
             xfbBuffers[b].stride = unit.xfbBuffers[b].stride;
             xfbBuffers[b].stride = unit.xfbBuffers[b].stride;
@@ -170,35 +227,181 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
         // TODO: 4.4 link: enhanced layouts: compare ranges
         // TODO: 4.4 link: enhanced layouts: compare ranges
     }
     }
 
 
-    if (unit.treeRoot == 0)
+    MERGE_TRUE(multiStream);
+
+#ifdef NV_EXTENSIONS
+    MERGE_TRUE(layoutOverrideCoverage);
+    MERGE_TRUE(geoPassthroughEXT);
+#endif
+
+    for (unsigned int i = 0; i < unit.shiftBinding.size(); ++i) {
+        if (unit.shiftBinding[i] > 0)
+            setShiftBinding((TResourceType)i, unit.shiftBinding[i]);
+    }
+
+    for (unsigned int i = 0; i < unit.shiftBindingForSet.size(); ++i) {
+        for (auto it = unit.shiftBindingForSet[i].begin(); it != unit.shiftBindingForSet[i].end(); ++it)
+            setShiftBindingForSet((TResourceType)i, it->second, it->first);
+    }
+
+    resourceSetBinding.insert(resourceSetBinding.end(), unit.resourceSetBinding.begin(), unit.resourceSetBinding.end());
+
+    MERGE_TRUE(autoMapBindings);
+    MERGE_TRUE(autoMapLocations);
+    MERGE_TRUE(invertY);
+    MERGE_TRUE(flattenUniformArrays);
+    MERGE_TRUE(useUnknownFormat);
+    MERGE_TRUE(hlslOffsets);
+    MERGE_TRUE(useStorageBuffer);
+    MERGE_TRUE(hlslIoMapping);
+
+    // TODO: sourceFile
+    // TODO: sourceText
+    // TODO: processes
+
+    MERGE_TRUE(needToLegalize);
+    MERGE_TRUE(binaryDoubleOutput);
+}
+
+//
+// Merge the 'unit' AST into 'this' AST.
+// That includes rationalizing the unique IDs, which were set up independently,
+// and might have overlaps that are not the same symbol, or might have different
+// IDs for what should be the same shared symbol.
+//
+void TIntermediate::mergeTrees(TInfoSink& infoSink, TIntermediate& unit)
+{
+    if (unit.treeRoot == nullptr)
         return;
         return;
 
 
-    if (treeRoot == 0) {
+    if (treeRoot == nullptr) {
         treeRoot = unit.treeRoot;
         treeRoot = unit.treeRoot;
-        version = unit.version;
-        requestedExtensions = unit.requestedExtensions;
         return;
         return;
     }
     }
 
 
     // Getting this far means we have two existing trees to merge...
     // Getting this far means we have two existing trees to merge...
+#ifdef NV_EXTENSIONS
+    numShaderRecordNVBlocks += unit.numShaderRecordNVBlocks;
+#endif
 
 
-    version = std::max(version, unit.version);
-    requestedExtensions.insert(unit.requestedExtensions.begin(), unit.requestedExtensions.end());
+#ifdef NV_EXTENSIONS
+    numTaskNVBlocks += unit.numTaskNVBlocks;
+#endif
 
 
     // Get the top-level globals of each unit
     // Get the top-level globals of each unit
     TIntermSequence& globals = treeRoot->getAsAggregate()->getSequence();
     TIntermSequence& globals = treeRoot->getAsAggregate()->getSequence();
     TIntermSequence& unitGlobals = unit.treeRoot->getAsAggregate()->getSequence();
     TIntermSequence& unitGlobals = unit.treeRoot->getAsAggregate()->getSequence();
 
 
     // Get the linker-object lists
     // Get the linker-object lists
-    TIntermSequence& linkerObjects = findLinkerObjects();
-    TIntermSequence& unitLinkerObjects = unit.findLinkerObjects();
+    TIntermSequence& linkerObjects = findLinkerObjects()->getSequence();
+    const TIntermSequence& unitLinkerObjects = unit.findLinkerObjects()->getSequence();
+
+    // Map by global name to unique ID to rationalize the same object having
+    // differing IDs in different trees.
+    TMap<TString, int> idMap;
+    int maxId;
+    seedIdMap(idMap, maxId);
+    remapIds(idMap, maxId + 1, unit);
 
 
     mergeBodies(infoSink, globals, unitGlobals);
     mergeBodies(infoSink, globals, unitGlobals);
     mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects);
     mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects);
-
     ioAccessed.insert(unit.ioAccessed.begin(), unit.ioAccessed.end());
     ioAccessed.insert(unit.ioAccessed.begin(), unit.ioAccessed.end());
 }
 }
 
 
+// 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) { }
+    // 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();
+        maxId = std::max(maxId, symbol->getId());
+    }
+    int getMaxId() const { return maxId; }
+protected:
+    TBuiltInIdTraverser(TBuiltInIdTraverser&);
+    TBuiltInIdTraverser& operator=(TBuiltInIdTraverser&);
+    TMap<TString, int>& idMap;
+    int maxId;
+};
+
+// Traverser that seeds an ID map with non-builtins.
+// (It would be nice to put this in a function, but that causes warnings
+// on having no bodies for the copy-constructor/operator=.)
+class TUserIdTraverser : public TIntermTraverser {
+public:
+    TUserIdTraverser(TMap<TString, int>& idMap) : idMap(idMap) { }
+    // 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();
+    }
+
+protected:
+    TUserIdTraverser(TUserIdTraverser&);
+    TUserIdTraverser& operator=(TUserIdTraverser&);
+    TMap<TString, int>& idMap; // over biggest id
+};
+
+// Initialize the the ID map with what we know of 'this' AST.
+void TIntermediate::seedIdMap(TMap<TString, int>& idMap, int& maxId)
+{
+    // all built-ins everywhere need to align on IDs and contribute to the max ID
+    TBuiltInIdTraverser builtInIdTraverser(idMap);
+    treeRoot->traverse(&builtInIdTraverser);
+    maxId = builtInIdTraverser.getMaxId();
+
+    // user variables in the linker object list need to align on ids
+    TUserIdTraverser userIdTraverser(idMap);
+    findLinkerObjects()->traverse(&userIdTraverser);
+}
+
+// Traverser to map an AST ID to what was known from the seeding AST.
+// (It would be nice to put this in a function, but that causes warnings
+// 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) { }
+    // Do the mapping:
+    //  - if the same symbol, adopt the 'this' ID
+    //  - otherwise, ensure a unique ID by shifting to a new space
+    virtual void visitSymbol(TIntermSymbol* symbol)
+    {
+        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()) {
+                symbol->changeId(it->second);
+                remapped = true;
+            }
+        }
+        if (!remapped)
+            symbol->changeId(symbol->getId() + idShift);
+    }
+protected:
+    TRemapIdTraverser(TRemapIdTraverser&);
+    TRemapIdTraverser& operator=(TRemapIdTraverser&);
+    const TMap<TString, int>& idMap;
+    int idShift;
+};
+
+void TIntermediate::remapIds(const TMap<TString, int>& idMap, int idShift, TIntermediate& unit)
+{
+    // Remap all IDs to either share or be unique, as dictated by the idMap and idShift.
+    TRemapIdTraverser idTraverser(idMap, idShift);
+    unit.getTreeRoot()->traverse(&idTraverser);
+}
+
 //
 //
 // Merge the function bodies and global-level initializers from unitGlobals into globals.
 // Merge the function bodies and global-level initializers from unitGlobals into globals.
 // Will error check duplication of function bodies for the same signature.
 // Will error check duplication of function bodies for the same signature.
@@ -267,10 +470,13 @@ void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& lin
 // Recursively merge the implicit array sizes through the objects' respective type trees.
 // Recursively merge the implicit array sizes through the objects' respective type trees.
 void TIntermediate::mergeImplicitArraySizes(TType& type, const TType& unitType)
 void TIntermediate::mergeImplicitArraySizes(TType& type, const TType& unitType)
 {
 {
-    if (type.isImplicitlySizedArray() && unitType.isArray()) {
-        int newImplicitArraySize = unitType.isImplicitlySizedArray() ? unitType.getImplicitArraySize() : unitType.getOuterArraySize();
-        if (newImplicitArraySize > type.getImplicitArraySize ())
-            type.setImplicitArraySize(newImplicitArraySize);
+    if (type.isUnsizedArray()) {
+        if (unitType.isUnsizedArray()) {
+            type.updateImplicitArraySize(unitType.getImplicitArraySize());
+            if (unitType.isArrayVariablyIndexed())
+                type.setArrayVariablyIndexed();
+        } else if (unitType.isSizedArray())
+            type.changeOuterArraySize(unitType.getOuterArraySize());
     }
     }
 
 
     // Type mismatches are caught and reported after this, just be careful for now.
     // Type mismatches are caught and reported after this, just be careful for now.
@@ -293,8 +499,13 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
 
 
     // Types have to match
     // Types have to match
     if (symbol.getType() != unitSymbol.getType()) {
     if (symbol.getType() != unitSymbol.getType()) {
-        error(infoSink, "Types must match:");
-        writeTypeComparison = true;
+        // but, we make an exception if one is an implicit array and the other is sized
+        if (! (symbol.getType().isArray() && unitSymbol.getType().isArray() &&
+                symbol.getType().sameElementType(unitSymbol.getType()) &&
+                (symbol.getType().isUnsizedArray() || unitSymbol.getType().isUnsizedArray()))) {
+            error(infoSink, "Types must match:");
+            writeTypeComparison = true;
+        }
     }
     }
 
 
     // Qualifiers have to (almost) match
     // Qualifiers have to (almost) match
@@ -335,11 +546,16 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
     }
     }
 
 
     // Memory...
     // Memory...
-    if (symbol.getQualifier().coherent  != unitSymbol.getQualifier().coherent ||
-        symbol.getQualifier().volatil   != unitSymbol.getQualifier().volatil ||
-        symbol.getQualifier().restrict  != unitSymbol.getQualifier().restrict ||
-        symbol.getQualifier().readonly  != unitSymbol.getQualifier().readonly ||
-        symbol.getQualifier().writeonly != unitSymbol.getQualifier().writeonly) {
+    if (symbol.getQualifier().coherent          != unitSymbol.getQualifier().coherent ||
+        symbol.getQualifier().devicecoherent    != unitSymbol.getQualifier().devicecoherent ||
+        symbol.getQualifier().queuefamilycoherent  != unitSymbol.getQualifier().queuefamilycoherent ||
+        symbol.getQualifier().workgroupcoherent != unitSymbol.getQualifier().workgroupcoherent ||
+        symbol.getQualifier().subgroupcoherent  != unitSymbol.getQualifier().subgroupcoherent ||
+        symbol.getQualifier().nonprivate        != unitSymbol.getQualifier().nonprivate ||
+        symbol.getQualifier().volatil           != unitSymbol.getQualifier().volatil ||
+        symbol.getQualifier().restrict          != unitSymbol.getQualifier().restrict ||
+        symbol.getQualifier().readonly          != unitSymbol.getQualifier().readonly ||
+        symbol.getQualifier().writeonly         != unitSymbol.getQualifier().writeonly) {
         error(infoSink, "Memory qualifiers must match:");
         error(infoSink, "Memory qualifiers must match:");
         writeTypeComparison = true;
         writeTypeComparison = true;
     }
     }
@@ -474,17 +690,9 @@ void TIntermediate::finalCheck(TInfoSink& infoSink, bool keepUncalled)
     case EShLangGeometry:
     case EShLangGeometry:
         if (inputPrimitive == ElgNone)
         if (inputPrimitive == ElgNone)
             error(infoSink, "At least one shader must specify an input layout primitive");
             error(infoSink, "At least one shader must specify an input layout primitive");
-        if (outputPrimitive == ElgNone
-#ifdef NV_EXTENSIONS
-            && !getGeoPassthroughEXT()
-#endif
-            )
+        if (outputPrimitive == ElgNone)
             error(infoSink, "At least one shader must specify an output layout primitive");
             error(infoSink, "At least one shader must specify an output layout primitive");
-        if (vertices == TQualifier::layoutNotSet
-#ifdef NV_EXTENSIONS
-            && !getGeoPassthroughEXT()
-#endif
-           )
+        if (vertices == TQualifier::layoutNotSet)
             error(infoSink, "At least one shader must specify a layout(max_vertices = value)");
             error(infoSink, "At least one shader must specify a layout(max_vertices = value)");
         break;
         break;
     case EShLangFragment:
     case EShLangFragment:
@@ -496,6 +704,42 @@ void TIntermediate::finalCheck(TInfoSink& infoSink, bool keepUncalled)
         break;
         break;
     case EShLangCompute:
     case EShLangCompute:
         break;
         break;
+
+#ifdef NV_EXTENSIONS
+    case EShLangRayGenNV:
+    case EShLangIntersectNV:
+    case EShLangAnyHitNV:
+    case EShLangClosestHitNV:
+    case EShLangMissNV:
+    case EShLangCallableNV:
+        if (numShaderRecordNVBlocks > 1)
+            error(infoSink, "Only one shaderRecordNV buffer block is allowed per stage");
+        break;
+    case EShLangMeshNV:
+        // NV_mesh_shader doesn't allow use of both single-view and per-view builtins.
+        if (inIoAccessed("gl_Position") && inIoAccessed("gl_PositionPerViewNV"))
+            error(infoSink, "Can only use one of gl_Position or gl_PositionPerViewNV");
+        if (inIoAccessed("gl_ClipDistance") && inIoAccessed("gl_ClipDistancePerViewNV"))
+            error(infoSink, "Can only use one of gl_ClipDistance or gl_ClipDistancePerViewNV");
+        if (inIoAccessed("gl_CullDistance") && inIoAccessed("gl_CullDistancePerViewNV"))
+            error(infoSink, "Can only use one of gl_CullDistance or gl_CullDistancePerViewNV");
+        if (inIoAccessed("gl_Layer") && inIoAccessed("gl_LayerPerViewNV"))
+            error(infoSink, "Can only use one of gl_Layer or gl_LayerPerViewNV");
+        if (inIoAccessed("gl_ViewportMask") && inIoAccessed("gl_ViewportMaskPerViewNV"))
+            error(infoSink, "Can only use one of gl_ViewportMask or gl_ViewportMaskPerViewNV");
+        if (outputPrimitive == ElgNone)
+            error(infoSink, "At least one shader must specify an output layout primitive");
+        if (vertices == TQualifier::layoutNotSet)
+            error(infoSink, "At least one shader must specify a layout(max_vertices = value)");
+        if (primitives == TQualifier::layoutNotSet)
+            error(infoSink, "At least one shader must specify a layout(max_primitives = value)");
+        // fall through
+    case EShLangTaskNV:
+        if (numTaskNVBlocks > 1)
+            error(infoSink, "Only one taskNV interface block is allowed per shader");
+        break;
+#endif
+
     default:
     default:
         error(infoSink, "Unknown Stage.");
         error(infoSink, "Unknown Stage.");
         break;
         break;
@@ -510,7 +754,9 @@ void TIntermediate::finalCheck(TInfoSink& infoSink, bool keepUncalled)
         virtual void visitSymbol(TIntermSymbol* symbol)
         virtual void visitSymbol(TIntermSymbol* symbol)
         {
         {
             // Implicitly size arrays.
             // Implicitly size arrays.
-            symbol->getWritableType().adoptImplicitArraySizes();
+            // If an unsized array is left as unsized, it effectively
+            // becomes run-time sized.
+            symbol->getWritableType().adoptImplicitArraySizes(false);
         }
         }
     } finalLinkTraverser;
     } finalLinkTraverser;
 
 
@@ -688,7 +934,7 @@ void TIntermediate::inOutLocationCheck(TInfoSink& infoSink)
 
 
     // TODO: linker functionality: location collision checking
     // TODO: linker functionality: location collision checking
 
 
-    TIntermSequence& linkObjects = findLinkerObjects();
+    TIntermSequence& linkObjects = findLinkerObjects()->getSequence();
     for (size_t i = 0; i < linkObjects.size(); ++i) {
     for (size_t i = 0; i < linkObjects.size(); ++i) {
         const TType& type = linkObjects[i]->getAsTyped()->getType();
         const TType& type = linkObjects[i]->getAsTyped()->getType();
         const TQualifier& qualifier = type.getQualifier();
         const TQualifier& qualifier = type.getQualifier();
@@ -707,7 +953,7 @@ void TIntermediate::inOutLocationCheck(TInfoSink& infoSink)
     }
     }
 }
 }
 
 
-TIntermSequence& TIntermediate::findLinkerObjects() const
+TIntermAggregate* TIntermediate::findLinkerObjects() const
 {
 {
     // Get the top-level globals
     // Get the top-level globals
     TIntermSequence& globals = treeRoot->getAsAggregate()->getSequence();
     TIntermSequence& globals = treeRoot->getAsAggregate()->getSequence();
@@ -715,7 +961,7 @@ TIntermSequence& TIntermediate::findLinkerObjects() const
     // Get the last member of the sequences, expected to be the linker-object lists
     // Get the last member of the sequences, expected to be the linker-object lists
     assert(globals.back()->getAsAggregate()->getOp() == EOpLinkerObjects);
     assert(globals.back()->getAsAggregate()->getOp() == EOpLinkerObjects);
 
 
-    return globals.back()->getAsAggregate()->getSequence();
+    return globals.back()->getAsAggregate();
 }
 }
 
 
 // See if a variable was both a user-declared output and used.
 // See if a variable was both a user-declared output and used.
@@ -723,7 +969,7 @@ TIntermSequence& TIntermediate::findLinkerObjects() const
 // is more useful, and perhaps the spec should be changed to reflect that.
 // is more useful, and perhaps the spec should be changed to reflect that.
 bool TIntermediate::userOutputUsed() const
 bool TIntermediate::userOutputUsed() const
 {
 {
-    const TIntermSequence& linkerObjects = findLinkerObjects();
+    const TIntermSequence& linkerObjects = findLinkerObjects()->getSequence();
 
 
     bool found = false;
     bool found = false;
     for (size_t i = 0; i < linkerObjects.size(); ++i) {
     for (size_t i = 0; i < linkerObjects.size(); ++i) {
@@ -764,8 +1010,8 @@ int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& typ
         return -1;
         return -1;
 
 
     int size;
     int size;
-    if (qualifier.isUniformOrBuffer()) {
-        if (type.isExplicitlySizedArray())
+    if (qualifier.isUniformOrBuffer() || qualifier.isTaskMemory()) {
+        if (type.isSizedArray())
             size = type.getCumulativeArraySize();
             size = type.getCumulativeArraySize();
         else
         else
             size = 1;
             size = 1;
@@ -773,9 +1019,9 @@ int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& typ
         // Strip off the outer array dimension for those having an extra one.
         // Strip off the outer array dimension for those having an extra one.
         if (type.isArray() && qualifier.isArrayedIo(language)) {
         if (type.isArray() && qualifier.isArrayedIo(language)) {
             TType elementType(type, 0);
             TType elementType(type, 0);
-            size = computeTypeLocationSize(elementType);
+            size = computeTypeLocationSize(elementType, language);
         } else
         } else
-            size = computeTypeLocationSize(type);
+            size = computeTypeLocationSize(type, language);
     }
     }
 
 
     // Locations, and components within locations.
     // Locations, and components within locations.
@@ -836,8 +1082,8 @@ int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& typ
         // combine location and component ranges
         // combine location and component ranges
         TIoRange range(locationRange, componentRange, type.getBasicType(), qualifier.hasIndex() ? qualifier.layoutIndex : 0);
         TIoRange range(locationRange, componentRange, type.getBasicType(), qualifier.hasIndex() ? qualifier.layoutIndex : 0);
 
 
-        // check for collisions, except for vertex inputs on desktop
-        if (! (profile != EEsProfile && language == EShLangVertex && qualifier.isPipeInput()))
+        // check for collisions, except for vertex inputs on desktop targeting OpenGL
+        if (! (profile != EEsProfile && language == EShLangVertex && qualifier.isPipeInput()) || spvVersion.vulkan > 0)
             collision = checkLocationRange(set, range, type, typeCollision);
             collision = checkLocationRange(set, range, type, typeCollision);
 
 
         if (collision < 0)
         if (collision < 0)
@@ -907,18 +1153,27 @@ bool TIntermediate::addUsedConstantId(int id)
 
 
 // Recursively figure out how many locations are used up by an input or output type.
 // Recursively figure out how many locations are used up by an input or output type.
 // Return the size of type, as measured by "locations".
 // Return the size of type, as measured by "locations".
-int TIntermediate::computeTypeLocationSize(const TType& type) const
+int TIntermediate::computeTypeLocationSize(const TType& type, EShLanguage stage)
 {
 {
     // "If the declared input is an array of size n and each element takes m locations, it will be assigned m * n
     // "If the declared input is an array of size n and each element takes m locations, it will be assigned m * n
     // consecutive locations..."
     // consecutive locations..."
     if (type.isArray()) {
     if (type.isArray()) {
         // TODO: perf: this can be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness
         // TODO: perf: this can be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness
+        // TODO: are there valid cases of having an unsized array with a location?  If so, running this code too early.
         TType elementType(type, 0);
         TType elementType(type, 0);
-        if (type.isImplicitlySizedArray()) {
-            // TODO: are there valid cases of having an implicitly-sized array with a location?  If so, running this code too early.
-            return computeTypeLocationSize(elementType);
-        } else
-            return type.getOuterArraySize() * computeTypeLocationSize(elementType);
+        if (type.isSizedArray()
+#ifdef NV_EXTENSIONS
+            && !type.getQualifier().isPerView()
+#endif
+            )
+            return type.getOuterArraySize() * computeTypeLocationSize(elementType, stage);
+        else {
+#ifdef NV_EXTENSIONS
+            // unset perViewNV attributes for arrayed per-view outputs: "perviewNV vec4 v[MAX_VIEWS][3];"
+            elementType.getQualifier().perViewNV = false;
+#endif
+            return computeTypeLocationSize(elementType, stage);
+        }
     }
     }
 
 
     // "The locations consumed by block and structure members are determined by applying the rules above
     // "The locations consumed by block and structure members are determined by applying the rules above
@@ -927,7 +1182,7 @@ int TIntermediate::computeTypeLocationSize(const TType& type) const
         int size = 0;
         int size = 0;
         for (int member = 0; member < (int)type.getStruct()->size(); ++member) {
         for (int member = 0; member < (int)type.getStruct()->size(); ++member) {
             TType memberType(type, member);
             TType memberType(type, member);
-            size += computeTypeLocationSize(memberType);
+            size += computeTypeLocationSize(memberType, stage);
         }
         }
         return size;
         return size;
     }
     }
@@ -941,7 +1196,7 @@ int TIntermediate::computeTypeLocationSize(const TType& type) const
     if (type.isScalar())
     if (type.isScalar())
         return 1;
         return 1;
     if (type.isVector()) {
     if (type.isVector()) {
-        if (language == EShLangVertex && type.getQualifier().isPipeInput())
+        if (stage == EShLangVertex && type.getQualifier().isPipeInput())
             return 1;
             return 1;
         if (type.getBasicType() == EbtDouble && type.getVectorSize() > 2)
         if (type.getBasicType() == EbtDouble && type.getVectorSize() > 2)
             return 2;
             return 2;
@@ -954,13 +1209,44 @@ int TIntermediate::computeTypeLocationSize(const TType& type) const
     // for an n-element array of m-component vectors..."
     // for an n-element array of m-component vectors..."
     if (type.isMatrix()) {
     if (type.isMatrix()) {
         TType columnType(type, 0);
         TType columnType(type, 0);
-        return type.getMatrixCols() * computeTypeLocationSize(columnType);
+        return type.getMatrixCols() * computeTypeLocationSize(columnType, stage);
     }
     }
 
 
     assert(0);
     assert(0);
     return 1;
     return 1;
 }
 }
 
 
+// Same as computeTypeLocationSize but for uniforms
+int TIntermediate::computeTypeUniformLocationSize(const TType& type)
+{
+    // "Individual elements of a uniform array are assigned
+    // consecutive locations with the first element taking location
+    // location."
+    if (type.isArray()) {
+        // TODO: perf: this can be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness
+        TType elementType(type, 0);
+        if (type.isSizedArray()) {
+            return type.getOuterArraySize() * computeTypeUniformLocationSize(elementType);
+        } else {
+            // TODO: are there valid cases of having an implicitly-sized array with a location?  If so, running this code too early.
+            return computeTypeUniformLocationSize(elementType);
+        }
+    }
+
+    // "Each subsequent inner-most member or element gets incremental
+    // locations for the entire structure or array."
+    if (type.isStruct()) {
+        int size = 0;
+        for (int member = 0; member < (int)type.getStruct()->size(); ++member) {
+            TType memberType(type, member);
+            size += computeTypeUniformLocationSize(memberType);
+        }
+        return size;
+    }
+
+    return 1;
+}
+
 // Accumulate xfb buffer ranges and check for collisions as the accumulation is done.
 // Accumulate xfb buffer ranges and check for collisions as the accumulation is done.
 //
 //
 // Returns < 0 if no collision, >= 0 if collision and the value returned is a colliding value.
 // Returns < 0 if no collision, >= 0 if collision and the value returned is a colliding value.
@@ -1005,7 +1291,7 @@ unsigned int TIntermediate::computeTypeXfbSize(const TType& type, bool& contains
 
 
     if (type.isArray()) {
     if (type.isArray()) {
         // TODO: perf: this can be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness
         // TODO: perf: this can be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness
-        assert(type.isExplicitlySizedArray());
+        assert(type.isSizedArray());
         TType elementType(type, 0);
         TType elementType(type, 0);
         return type.getOuterArraySize() * computeTypeXfbSize(elementType, containsDouble);
         return type.getOuterArraySize() * computeTypeXfbSize(elementType, containsDouble);
     }
     }
@@ -1064,11 +1350,11 @@ int TIntermediate::getBaseAlignmentScalar(const TType& type, int& size)
     case EbtInt64:
     case EbtInt64:
     case EbtUint64:
     case EbtUint64:
     case EbtDouble:  size = 8; return 8;
     case EbtDouble:  size = 8; return 8;
-#ifdef AMD_EXTENSIONS
-    case EbtInt16:
-    case EbtUint16:
     case EbtFloat16: size = 2; return 2;
     case EbtFloat16: size = 2; return 2;
-#endif
+    case EbtInt8:
+    case EbtUint8:   size = 1; return 1;
+    case EbtInt16:
+    case EbtUint16:  size = 2; return 2;
     default:         size = 4; return 4;
     default:         size = 4; return 4;
     }
     }
 }
 }
@@ -1087,10 +1373,11 @@ int TIntermediate::getBaseAlignmentScalar(const TType& type, int& size)
 // stride comes from the flattening down to vectors.
 // stride comes from the flattening down to vectors.
 //
 //
 // Return value is the alignment of the type.
 // Return value is the alignment of the type.
-int TIntermediate::getBaseAlignment(const TType& type, int& size, int& stride, bool std140, bool rowMajor)
+int TIntermediate::getBaseAlignment(const TType& type, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor)
 {
 {
     int alignment;
     int alignment;
 
 
+    bool std140 = layoutPacking == glslang::ElpStd140;
     // When using the std140 storage layout, structures will be laid out in buffer
     // When using the std140 storage layout, structures will be laid out in buffer
     // storage with its members stored in monotonically increasing order based on their
     // storage with its members stored in monotonically increasing order based on their
     // location in the declaration. A structure and each structure member have a base
     // location in the declaration. A structure and each structure member have a base
@@ -1154,7 +1441,7 @@ int TIntermediate::getBaseAlignment(const TType& type, int& size, int& stride, b
     if (type.isArray()) {
     if (type.isArray()) {
         // TODO: perf: this might be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness
         // TODO: perf: this might be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness
         TType derefType(type, 0);
         TType derefType(type, 0);
-        alignment = getBaseAlignment(derefType, size, dummyStride, std140, rowMajor);
+        alignment = getBaseAlignment(derefType, size, dummyStride, layoutPacking, rowMajor);
         if (std140)
         if (std140)
             alignment = std::max(baseAlignmentVec4Std140, alignment);
             alignment = std::max(baseAlignmentVec4Std140, alignment);
         RoundToPow2(size, alignment);
         RoundToPow2(size, alignment);
@@ -1174,7 +1461,7 @@ int TIntermediate::getBaseAlignment(const TType& type, int& size, int& stride, b
             int memberSize;
             int memberSize;
             // modify just the children's view of matrix layout, if there is one for this member
             // modify just the children's view of matrix layout, if there is one for this member
             TLayoutMatrix subMatrixLayout = memberList[m].type->getQualifier().layoutMatrix;
             TLayoutMatrix subMatrixLayout = memberList[m].type->getQualifier().layoutMatrix;
-            int memberAlignment = getBaseAlignment(*memberList[m].type, memberSize, dummyStride, std140,
+            int memberAlignment = getBaseAlignment(*memberList[m].type, memberSize, dummyStride, layoutPacking,
                                                    (subMatrixLayout != ElmNone) ? (subMatrixLayout == ElmRowMajor) : rowMajor);
                                                    (subMatrixLayout != ElmNone) ? (subMatrixLayout == ElmRowMajor) : rowMajor);
             maxAlignment = std::max(maxAlignment, memberAlignment);
             maxAlignment = std::max(maxAlignment, memberAlignment);
             RoundToPow2(size, memberAlignment);
             RoundToPow2(size, memberAlignment);
@@ -1197,6 +1484,8 @@ int TIntermediate::getBaseAlignment(const TType& type, int& size, int& stride, b
     if (type.isVector()) {
     if (type.isVector()) {
         int scalarAlign = getBaseAlignmentScalar(type, size);
         int scalarAlign = getBaseAlignmentScalar(type, size);
         switch (type.getVectorSize()) {
         switch (type.getVectorSize()) {
+        case 1: // HLSL has this, GLSL does not
+            return scalarAlign;
         case 2:
         case 2:
             size *= 2;
             size *= 2;
             return 2 * scalarAlign;
             return 2 * scalarAlign;
@@ -1211,7 +1500,7 @@ int TIntermediate::getBaseAlignment(const TType& type, int& size, int& stride, b
         // rule 5: deref to row, not to column, meaning the size of vector is num columns instead of num rows
         // rule 5: deref to row, not to column, meaning the size of vector is num columns instead of num rows
         TType derefType(type, 0, rowMajor);
         TType derefType(type, 0, rowMajor);
 
 
-        alignment = getBaseAlignment(derefType, size, dummyStride, std140, rowMajor);
+        alignment = getBaseAlignment(derefType, size, dummyStride, layoutPacking, rowMajor);
         if (std140)
         if (std140)
             alignment = std::max(baseAlignmentVec4Std140, alignment);
             alignment = std::max(baseAlignmentVec4Std140, alignment);
         RoundToPow2(size, alignment);
         RoundToPow2(size, alignment);
@@ -1239,4 +1528,79 @@ bool TIntermediate::improperStraddle(const TType& type, int size, int offset)
                       : offset % 16 != 0;
                       : offset % 16 != 0;
 }
 }
 
 
+int TIntermediate::getScalarAlignment(const TType& type, int& size, int& stride, bool rowMajor)
+{
+    int alignment;
+
+    stride = 0;
+    int dummyStride;
+
+    if (type.isArray()) {
+        TType derefType(type, 0);
+        alignment = getScalarAlignment(derefType, size, dummyStride, rowMajor);
+
+        stride = size;
+        RoundToPow2(stride, alignment);
+
+        size = stride * (type.getOuterArraySize() - 1) + size;
+        return alignment;
+    }
+
+    if (type.getBasicType() == EbtStruct) {
+        const TTypeList& memberList = *type.getStruct();
+
+        size = 0;
+        int maxAlignment = 0;
+        for (size_t m = 0; m < memberList.size(); ++m) {
+            int memberSize;
+            // modify just the children's view of matrix layout, if there is one for this member
+            TLayoutMatrix subMatrixLayout = memberList[m].type->getQualifier().layoutMatrix;
+            int memberAlignment = getScalarAlignment(*memberList[m].type, memberSize, dummyStride,
+                                                     (subMatrixLayout != ElmNone) ? (subMatrixLayout == ElmRowMajor) : rowMajor);
+            maxAlignment = std::max(maxAlignment, memberAlignment);
+            RoundToPow2(size, memberAlignment);
+            size += memberSize;
+        }
+
+        return maxAlignment;
+    }
+
+    if (type.isScalar())
+        return getBaseAlignmentScalar(type, size);
+
+    if (type.isVector()) {
+        int scalarAlign = getBaseAlignmentScalar(type, size);
+        
+        size *= type.getVectorSize();
+        return scalarAlign;
+    }
+
+    if (type.isMatrix()) {
+        TType derefType(type, 0, rowMajor);
+
+        alignment = getScalarAlignment(derefType, size, dummyStride, rowMajor);
+
+        stride = size;  // use intra-matrix stride for stride of a just a matrix
+        if (rowMajor)
+            size = stride * type.getMatrixRows();
+        else
+            size = stride * type.getMatrixCols();
+
+        return alignment;
+    }
+
+    assert(0);  // all cases should be covered above
+    size = 1;
+    return 1;    
+}
+
+int TIntermediate::getMemberAlignment(const TType& type, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor)
+{
+    if (layoutPacking == glslang::ElpScalar) {
+        return getScalarAlignment(type, size, stride, rowMajor);
+    } else {
+        return getBaseAlignment(type, size, stride, layoutPacking, rowMajor);
+    }
+}
+
 } // end namespace glslang
 } // end namespace glslang

+ 133 - 29
src/libraries/glslang/glslang/MachineIndependent/localintermediate.h

@@ -1,6 +1,9 @@
 //
 //
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2016 LunarG, Inc.
 // Copyright (C) 2016 LunarG, Inc.
+// Copyright (C) 2017 ARM Limited.
+// Copyright (C) 2015-2018 Google, Inc.
+//
 // All rights reserved.
 // All rights reserved.
 //
 //
 // Redistribution and use in source and binary forms, with or without
 // Redistribution and use in source and binary forms, with or without
@@ -40,6 +43,8 @@
 #include "../Public/ShaderLang.h"
 #include "../Public/ShaderLang.h"
 #include "Versions.h"
 #include "Versions.h"
 
 
+#include <string>
+#include <vector>
 #include <algorithm>
 #include <algorithm>
 #include <set>
 #include <set>
 #include <array>
 #include <array>
@@ -78,7 +83,7 @@ public:
         assert(i < MaxSwizzleSelectors);
         assert(i < MaxSwizzleSelectors);
         return components[i];
         return components[i];
     }
     }
-    
+
 private:
 private:
     int size_;
     int size_;
     selectorType components[MaxSwizzleSelectors];
     selectorType components[MaxSwizzleSelectors];
@@ -203,13 +208,24 @@ class TSymbolTable;
 class TSymbol;
 class TSymbol;
 class TVariable;
 class TVariable;
 
 
+#ifdef NV_EXTENSIONS
+//
+// Texture and Sampler transformation mode.
+//
+enum ComputeDerivativeMode {
+    LayoutDerivativeNone,         // default layout as SPV_NV_compute_shader_derivatives not enabled
+    LayoutDerivativeGroupQuads,   // derivative_group_quadsNV
+    LayoutDerivativeGroupLinear,  // derivative_group_linearNV
+};
+#endif
+
 //
 //
 // Set of helper functions to help parse and build the tree.
 // Set of helper functions to help parse and build the tree.
 //
 //
 class TIntermediate {
 class TIntermediate {
 public:
 public:
     explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) :
     explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) :
-        implicitThisName("@this"),
+        implicitThisName("@this"), implicitCounterName("@count"),
         language(l), source(EShSourceNone), profile(p), version(v), treeRoot(0),
         language(l), source(EShSourceNone), profile(p), version(v), treeRoot(0),
         numEntryPoints(0), numErrors(0), numPushConstants(0), recursive(false),
         numEntryPoints(0), numErrors(0), numPushConstants(0), recursive(false),
         invocations(TQualifier::layoutNotSet), vertices(TQualifier::layoutNotSet),
         invocations(TQualifier::layoutNotSet), vertices(TQualifier::layoutNotSet),
@@ -217,10 +233,15 @@ public:
         pixelCenterInteger(false), originUpperLeft(false),
         pixelCenterInteger(false), originUpperLeft(false),
         vertexSpacing(EvsNone), vertexOrder(EvoNone), pointMode(false), earlyFragmentTests(false),
         vertexSpacing(EvsNone), vertexOrder(EvoNone), pointMode(false), earlyFragmentTests(false),
         postDepthCoverage(false), depthLayout(EldNone), depthReplacing(false),
         postDepthCoverage(false), depthLayout(EldNone), depthReplacing(false),
+        hlslFunctionality1(false),
         blendEquations(0), xfbMode(false), multiStream(false),
         blendEquations(0), xfbMode(false), multiStream(false),
 #ifdef NV_EXTENSIONS
 #ifdef NV_EXTENSIONS
         layoutOverrideCoverage(false),
         layoutOverrideCoverage(false),
         geoPassthroughEXT(false),
         geoPassthroughEXT(false),
+        numShaderRecordNVBlocks(0),
+        computeDerivativeMode(LayoutDerivativeNone),
+        primitives(TQualifier::layoutNotSet),
+        numTaskNVBlocks(0),
 #endif
 #endif
         autoMapBindings(false),
         autoMapBindings(false),
         autoMapLocations(false),
         autoMapLocations(false),
@@ -229,9 +250,12 @@ public:
         useUnknownFormat(false),
         useUnknownFormat(false),
         hlslOffsets(false),
         hlslOffsets(false),
         useStorageBuffer(false),
         useStorageBuffer(false),
+        useVulkanMemoryModel(false),
         hlslIoMapping(false),
         hlslIoMapping(false),
         textureSamplerTransformMode(EShTexSampTransKeep),
         textureSamplerTransformMode(EShTexSampTransKeep),
-        needToLegalize(false)
+        needToLegalize(false),
+        binaryDoubleOutput(false),
+        uniformLocationBase(0)
     {
     {
         localSize[0] = 1;
         localSize[0] = 1;
         localSize[1] = 1;
         localSize[1] = 1;
@@ -346,7 +370,7 @@ public:
         if (hlslOffsets)
         if (hlslOffsets)
             processes.addProcess("hlsl-offsets");
             processes.addProcess("hlsl-offsets");
     }
     }
-    bool usingHlslOFfsets() const { return hlslOffsets; }
+    bool usingHlslOffsets() const { return hlslOffsets; }
     void setUseStorageBuffer()
     void setUseStorageBuffer()
     {
     {
         useStorageBuffer = true;
         useStorageBuffer = true;
@@ -360,6 +384,19 @@ public:
             processes.addProcess("hlsl-iomap");
             processes.addProcess("hlsl-iomap");
     }
     }
     bool usingHlslIoMapping() { return hlslIoMapping; }
     bool usingHlslIoMapping() { return hlslIoMapping; }
+    void setUseVulkanMemoryModel()
+    {
+        useVulkanMemoryModel = true;
+        processes.addProcess("use-vulkan-memory-model");
+    }
+    bool usingVulkanMemoryModel() const { return useVulkanMemoryModel; }
+
+    template<class T> T addCounterBufferName(const T& name) const { return name + implicitCounterName; }
+    bool hasCounterBufferName(const TString& name) const {
+        size_t len = strlen(implicitCounterName);
+        return name.size() > len &&
+               name.compare(name.size() - len, len, implicitCounterName) == 0;
+    }
 
 
     void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { textureSamplerTransformMode = mode; }
     void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { textureSamplerTransformMode = mode; }
 
 
@@ -378,7 +415,7 @@ public:
             processes.addProcess("client opengl100");
             processes.addProcess("client opengl100");
 
 
         // target-environment processes
         // target-environment processes
-        if (spvVersion.vulkan == 100)
+        if (spvVersion.vulkan > 0)
             processes.addProcess("target-env vulkan1.0");
             processes.addProcess("target-env vulkan1.0");
         else if (spvVersion.vulkan > 0)
         else if (spvVersion.vulkan > 0)
             processes.addProcess("target-env vulkanUnknown");
             processes.addProcess("target-env vulkanUnknown");
@@ -396,6 +433,11 @@ public:
     int getNumEntryPoints() const { return numEntryPoints; }
     int getNumEntryPoints() const { return numEntryPoints; }
     int getNumErrors() const { return numErrors; }
     int getNumErrors() const { return numErrors; }
     void addPushConstantCount() { ++numPushConstants; }
     void addPushConstantCount() { ++numPushConstants; }
+#ifdef NV_EXTENSIONS
+    void addShaderRecordNVCount() { ++numShaderRecordNVBlocks; }
+    void addTaskNVCount() { ++numTaskNVBlocks; }
+#endif
+
     bool isRecursive() const { return recursive; }
     bool isRecursive() const { return recursive; }
 
 
     TIntermSymbol* addSymbol(const TVariable&);
     TIntermSymbol* addSymbol(const TVariable&);
@@ -403,6 +445,7 @@ public:
     TIntermSymbol* addSymbol(const TType&, const TSourceLoc&);
     TIntermSymbol* addSymbol(const TType&, const TSourceLoc&);
     TIntermSymbol* addSymbol(const TIntermSymbol&);
     TIntermSymbol* addSymbol(const TIntermSymbol&);
     TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*) const;
     TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*) const;
+    std::tuple<TIntermTyped*, TIntermTyped*> addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1) const;
     TIntermTyped* addUniShapeConversion(TOperator, const TType&, TIntermTyped*);
     TIntermTyped* addUniShapeConversion(TOperator, const TType&, TIntermTyped*);
     void addBiShapeConversion(TOperator, TIntermTyped*& lhsNode, TIntermTyped*& rhsNode);
     void addBiShapeConversion(TOperator, TIntermTyped*& lhsNode, TIntermTyped*& rhsNode);
     TIntermTyped* addShapeConversion(const TType&, TIntermTyped*);
     TIntermTyped* addShapeConversion(const TType&, TIntermTyped*);
@@ -412,6 +455,11 @@ public:
     TIntermTyped* addUnaryMath(TOperator, TIntermTyped* child, TSourceLoc);
     TIntermTyped* addUnaryMath(TOperator, TIntermTyped* child, TSourceLoc);
     TIntermTyped* addBuiltInFunctionCall(const TSourceLoc& line, TOperator, bool unary, TIntermNode*, const TType& returnType);
     TIntermTyped* addBuiltInFunctionCall(const TSourceLoc& line, TOperator, bool unary, TIntermNode*, const TType& returnType);
     bool canImplicitlyPromote(TBasicType from, TBasicType to, TOperator op = EOpNull) const;
     bool canImplicitlyPromote(TBasicType from, TBasicType to, TOperator op = EOpNull) const;
+    bool isIntegralPromotion(TBasicType from, TBasicType to) const;
+    bool isFPPromotion(TBasicType from, TBasicType to) const;
+    bool isIntegralConversion(TBasicType from, TBasicType to) const;
+    bool isFPConversion(TBasicType from, TBasicType to) const;
+    bool isFPIntegralConversion(TBasicType from, TBasicType to) const;
     TOperator mapTypeToConstructorOp(const TType&) const;
     TOperator mapTypeToConstructorOp(const TType&) const;
     TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right);
     TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right);
     TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc&);
     TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc&);
@@ -420,27 +468,27 @@ public:
     TIntermAggregate* makeAggregate(const TSourceLoc&);
     TIntermAggregate* makeAggregate(const TSourceLoc&);
     TIntermTyped* setAggregateOperator(TIntermNode*, TOperator, const TType& type, TSourceLoc);
     TIntermTyped* setAggregateOperator(TIntermNode*, TOperator, const TType& type, TSourceLoc);
     bool areAllChildConst(TIntermAggregate* aggrNode);
     bool areAllChildConst(TIntermAggregate* aggrNode);
-    TIntermTyped* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&, TSelectionControl = ESelectionControlNone);
-    TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&, TSelectionControl = ESelectionControlNone);
+    TIntermSelection* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&);
+    TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&);
     TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
     TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
     TIntermTyped* addMethod(TIntermTyped*, const TType&, const TString*, const TSourceLoc&);
     TIntermTyped* addMethod(TIntermTyped*, const TType&, const TString*, const TSourceLoc&);
     TIntermConstantUnion* addConstantUnion(const TConstUnionArray&, const TType&, const TSourceLoc&, bool literal = false) const;
     TIntermConstantUnion* addConstantUnion(const TConstUnionArray&, const TType&, const TSourceLoc&, bool literal = false) const;
+    TIntermConstantUnion* addConstantUnion(signed char, const TSourceLoc&, bool literal = false) const;
+    TIntermConstantUnion* addConstantUnion(unsigned char, const TSourceLoc&, bool literal = false) const;
+    TIntermConstantUnion* addConstantUnion(signed short, const TSourceLoc&, bool literal = false) const;
+    TIntermConstantUnion* addConstantUnion(unsigned short, const TSourceLoc&, bool literal = false) const;
     TIntermConstantUnion* addConstantUnion(int, const TSourceLoc&, bool literal = false) const;
     TIntermConstantUnion* addConstantUnion(int, const TSourceLoc&, bool literal = false) const;
     TIntermConstantUnion* addConstantUnion(unsigned int, const TSourceLoc&, bool literal = false) const;
     TIntermConstantUnion* addConstantUnion(unsigned int, const TSourceLoc&, bool literal = false) const;
     TIntermConstantUnion* addConstantUnion(long long, const TSourceLoc&, bool literal = false) const;
     TIntermConstantUnion* addConstantUnion(long long, const TSourceLoc&, bool literal = false) const;
     TIntermConstantUnion* addConstantUnion(unsigned long long, const TSourceLoc&, bool literal = false) const;
     TIntermConstantUnion* addConstantUnion(unsigned long long, const TSourceLoc&, bool literal = false) const;
-#ifdef AMD_EXTENSIONS
-    TIntermConstantUnion* addConstantUnion(short, const TSourceLoc&, bool literal = false) const;
-    TIntermConstantUnion* addConstantUnion(unsigned short, const TSourceLoc&, bool literal = false) const;
-    
-#endif
     TIntermConstantUnion* addConstantUnion(bool, const TSourceLoc&, bool literal = false) const;
     TIntermConstantUnion* addConstantUnion(bool, const TSourceLoc&, bool literal = false) const;
     TIntermConstantUnion* addConstantUnion(double, TBasicType, const TSourceLoc&, bool literal = false) const;
     TIntermConstantUnion* addConstantUnion(double, TBasicType, const TSourceLoc&, bool literal = false) const;
     TIntermConstantUnion* addConstantUnion(const TString*, const TSourceLoc&, bool literal = false) const;
     TIntermConstantUnion* addConstantUnion(const TString*, const TSourceLoc&, bool literal = false) const;
     TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) const;
     TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) const;
     bool parseConstTree(TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false);
     bool parseConstTree(TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false);
-    TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&, TLoopControl = ELoopControlNone);
-    TIntermAggregate* addForLoop(TIntermNode*, TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&, TLoopControl = ELoopControlNone);
+    TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&);
+    TIntermAggregate* addForLoop(TIntermNode*, TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst,
+        const TSourceLoc&, TIntermLoop*&);
     TIntermBranch* addBranch(TOperator, const TSourceLoc&);
     TIntermBranch* addBranch(TOperator, const TSourceLoc&);
     TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&);
     TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&);
     template<typename selectorType> TIntermTyped* addSwizzle(TSwizzleSelectors<selectorType>&, const TSourceLoc&);
     template<typename selectorType> TIntermTyped* addSwizzle(TSwizzleSelectors<selectorType>&, const TSourceLoc&);
@@ -452,9 +500,6 @@ public:
     TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc) const;
     TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc) const;
     TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc, const TType&) const;
     TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc, const TType&) const;
 
 
-    // Add conversion from node's type to given basic type.
-    TIntermTyped* convertToBasicType(TOperator op, TBasicType basicType, TIntermTyped* node) const;
-
     // Constant folding (in Constant.cpp)
     // Constant folding (in Constant.cpp)
     TIntermTyped* fold(TIntermAggregate* aggrNode);
     TIntermTyped* fold(TIntermAggregate* aggrNode);
     TIntermTyped* foldConstructor(TIntermAggregate* aggrNode);
     TIntermTyped* foldConstructor(TIntermAggregate* aggrNode);
@@ -560,6 +605,9 @@ public:
     void setDepthReplacing() { depthReplacing = true; }
     void setDepthReplacing() { depthReplacing = true; }
     bool isDepthReplacing() const { return depthReplacing; }
     bool isDepthReplacing() const { return depthReplacing; }
 
 
+    void setHlslFunctionality1() { hlslFunctionality1 = true; }
+    bool getHlslFunctionality1() const { return hlslFunctionality1; }
+
     void addBlendEquation(TBlendEquationShift b) { blendEquations |= (1 << b); }
     void addBlendEquation(TBlendEquationShift b) { blendEquations |= (1 << b); }
     unsigned int getBlendEquations() const { return blendEquations; }
     unsigned int getBlendEquations() const { return blendEquations; }
 
 
@@ -574,7 +622,8 @@ public:
     int checkLocationRange(int set, const TIoRange& range, const TType&, bool& typeCollision);
     int checkLocationRange(int set, const TIoRange& range, const TType&, bool& typeCollision);
     int addUsedOffsets(int binding, int offset, int numOffsets);
     int addUsedOffsets(int binding, int offset, int numOffsets);
     bool addUsedConstantId(int id);
     bool addUsedConstantId(int id);
-    int computeTypeLocationSize(const TType&) const;
+    static int computeTypeLocationSize(const TType&, EShLanguage);
+    static int computeTypeUniformLocationSize(const TType&);
 
 
     bool setXfbBufferStride(int buffer, unsigned stride)
     bool setXfbBufferStride(int buffer, unsigned stride)
     {
     {
@@ -587,7 +636,9 @@ public:
     int addXfbBufferOffset(const TType&);
     int addXfbBufferOffset(const TType&);
     unsigned int computeTypeXfbSize(const TType&, bool& containsDouble) const;
     unsigned int computeTypeXfbSize(const TType&, bool& containsDouble) const;
     static int getBaseAlignmentScalar(const TType&, int& size);
     static int getBaseAlignmentScalar(const TType&, int& size);
-    static int getBaseAlignment(const TType&, int& size, int& stride, bool std140, bool rowMajor);
+    static int getBaseAlignment(const TType&, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor);
+    static int getScalarAlignment(const TType&, int& size, int& stride, bool rowMajor);
+    static int getMemberAlignment(const TType&, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor);
     static bool improperStraddle(const TType& type, int size, int offset);
     static bool improperStraddle(const TType& type, int size, int offset);
     bool promote(TIntermOperator*);
     bool promote(TIntermOperator*);
 
 
@@ -596,6 +647,16 @@ public:
     bool getLayoutOverrideCoverage() const { return layoutOverrideCoverage; }
     bool getLayoutOverrideCoverage() const { return layoutOverrideCoverage; }
     void setGeoPassthroughEXT() { geoPassthroughEXT = true; }
     void setGeoPassthroughEXT() { geoPassthroughEXT = true; }
     bool getGeoPassthroughEXT() const { return geoPassthroughEXT; }
     bool getGeoPassthroughEXT() const { return geoPassthroughEXT; }
+    void setLayoutDerivativeMode(ComputeDerivativeMode mode) { computeDerivativeMode = mode; }
+    ComputeDerivativeMode getLayoutDerivativeModeNone() const { return computeDerivativeMode; }
+    bool setPrimitives(int m)
+    {
+        if (primitives != TQualifier::layoutNotSet)
+            return primitives == m;
+        primitives = m;
+        return true;
+    }
+    int getPrimitives() const { return primitives; }
 #endif
 #endif
 
 
     const char* addSemanticName(const TString& name)
     const char* addSemanticName(const TString& name)
@@ -603,11 +664,12 @@ public:
         return semanticNameSet.insert(name).first->c_str();
         return semanticNameSet.insert(name).first->c_str();
     }
     }
 
 
-    void setSourceFile(const char* file) { sourceFile = file; }
+    void setSourceFile(const char* file) { if (file != nullptr) sourceFile = file; }
     const std::string& getSourceFile() const { return sourceFile; }
     const std::string& getSourceFile() const { return sourceFile; }
     void addSourceText(const char* text) { sourceText = sourceText + text; }
     void addSourceText(const char* text) { sourceText = sourceText + text; }
     const std::string& getSourceText() const { return sourceText; }
     const std::string& getSourceText() const { return sourceText; }
-    void addProcesses(const std::vector<std::string>& p) {
+    void addProcesses(const std::vector<std::string>& p)
+    {
         for (int i = 0; i < (int)p.size(); ++i)
         for (int i = 0; i < (int)p.size(); ++i)
             processes.addProcess(p[i]);
             processes.addProcess(p[i]);
     }
     }
@@ -615,15 +677,43 @@ public:
     void addProcessArgument(const std::string& arg) { processes.addArgument(arg); }
     void addProcessArgument(const std::string& arg) { processes.addArgument(arg); }
     const std::vector<std::string>& getProcesses() const { return processes.getProcesses(); }
     const std::vector<std::string>& getProcesses() const { return processes.getProcesses(); }
 
 
+    void addUniformLocationOverride(const char* nameStr, int location)
+    {
+        std::string name = nameStr;
+        uniformLocationOverrides[name] = location;
+    }
+
+    int getUniformLocationOverride(const char* nameStr) const
+    {
+        std::string name = nameStr;
+        auto pos = uniformLocationOverrides.find(name);
+        if (pos == uniformLocationOverrides.end())
+            return -1;
+        else
+            return pos->second;
+    }
+
+    void setUniformLocationBase(int base) { uniformLocationBase = base; }
+    int getUniformLocationBase() const { return uniformLocationBase; }
+
     void setNeedsLegalization() { needToLegalize = true; }
     void setNeedsLegalization() { needToLegalize = true; }
     bool needsLegalization() const { return needToLegalize; }
     bool needsLegalization() const { return needToLegalize; }
 
 
+    void setBinaryDoubleOutput() { binaryDoubleOutput = true; }
+    bool getBinaryDoubleOutput() { return binaryDoubleOutput; }
+
     const char* const implicitThisName;
     const char* const implicitThisName;
+    const char* const implicitCounterName;
 
 
 protected:
 protected:
     TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&);
     TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&);
     void error(TInfoSink& infoSink, const char*);
     void error(TInfoSink& infoSink, const char*);
     void warn(TInfoSink& infoSink, const char*);
     void warn(TInfoSink& infoSink, const char*);
+    void mergeCallGraphs(TInfoSink&, TIntermediate&);
+    void 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 mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals);
     void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals);
     void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects);
     void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects);
     void mergeImplicitArraySizes(TType&, const TType&);
     void mergeImplicitArraySizes(TType&, const TType&);
@@ -631,9 +721,10 @@ protected:
     void checkCallGraphCycles(TInfoSink&);
     void checkCallGraphCycles(TInfoSink&);
     void checkCallGraphBodies(TInfoSink&, bool keepUncalled);
     void checkCallGraphBodies(TInfoSink&, bool keepUncalled);
     void inOutLocationCheck(TInfoSink&);
     void inOutLocationCheck(TInfoSink&);
-    TIntermSequence& findLinkerObjects() const;
+    TIntermAggregate* findLinkerObjects() const;
     bool userOutputUsed() const;
     bool userOutputUsed() const;
     bool isSpecializationOperation(const TIntermOperator&) const;
     bool isSpecializationOperation(const TIntermOperator&) const;
+    bool isNonuniformPropagating(TOperator) const;
     bool promoteUnary(TIntermUnary&);
     bool promoteUnary(TIntermUnary&);
     bool promoteBinary(TIntermBinary&);
     bool promoteBinary(TIntermBinary&);
     void addSymbolLinkageNode(TIntermAggregate*& linkage, TSymbolTable&, const TString&);
     void addSymbolLinkageNode(TIntermAggregate*& linkage, TSymbolTable&, const TString&);
@@ -642,15 +733,21 @@ protected:
     void pushSelector(TIntermSequence&, const TMatrixSelector&, const TSourceLoc&);
     void pushSelector(TIntermSequence&, const TMatrixSelector&, const TSourceLoc&);
     bool specConstantPropagates(const TIntermTyped&, const TIntermTyped&);
     bool specConstantPropagates(const TIntermTyped&, const TIntermTyped&);
     void performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root);
     void performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root);
+    bool isConversionAllowed(TOperator op, TIntermTyped* node) const;
+    TIntermTyped* createConversion(TBasicType convertTo, TIntermTyped* node) const;
+    std::tuple<TBasicType, TBasicType> getConversionDestinatonType(TBasicType type0, TBasicType type1, TOperator op) const;
+    bool extensionRequested(const char *extension) const {return requestedExtensions.find(extension) != requestedExtensions.end();}
     static const char* getResourceName(TResourceType);
     static const char* getResourceName(TResourceType);
 
 
     const EShLanguage language;  // stage, known at construction time
     const EShLanguage language;  // stage, known at construction time
     EShSource source;            // source language, known a bit later
     EShSource source;            // source language, known a bit later
     std::string entryPointName;
     std::string entryPointName;
     std::string entryPointMangledName;
     std::string entryPointMangledName;
+    typedef std::list<TCall> TGraph;
+    TGraph callGraph;
 
 
-    EProfile profile;
-    int version;
+    EProfile profile;                           // source profile
+    int version;                                // source version
     SpvVersion spvVersion;
     SpvVersion spvVersion;
     TIntermNode* treeRoot;
     TIntermNode* treeRoot;
     std::set<std::string> requestedExtensions;  // cumulation of all enabled or required extensions; not connected to what subset of the shader used them
     std::set<std::string> requestedExtensions;  // cumulation of all enabled or required extensions; not connected to what subset of the shader used them
@@ -674,20 +771,26 @@ protected:
     bool postDepthCoverage;
     bool postDepthCoverage;
     TLayoutDepth depthLayout;
     TLayoutDepth depthLayout;
     bool depthReplacing;
     bool depthReplacing;
+    bool hlslFunctionality1;
     int blendEquations;        // an 'or'ing of masks of shifts of TBlendEquationShift
     int blendEquations;        // an 'or'ing of masks of shifts of TBlendEquationShift
     bool xfbMode;
     bool xfbMode;
+    std::vector<TXfbBuffer> xfbBuffers;     // all the data we need to track per xfb buffer
     bool multiStream;
     bool multiStream;
 
 
 #ifdef NV_EXTENSIONS
 #ifdef NV_EXTENSIONS
     bool layoutOverrideCoverage;
     bool layoutOverrideCoverage;
     bool geoPassthroughEXT;
     bool geoPassthroughEXT;
+    int numShaderRecordNVBlocks;
+    ComputeDerivativeMode computeDerivativeMode;
+    int primitives;
+    int numTaskNVBlocks;
 #endif
 #endif
 
 
     // Base shift values
     // Base shift values
     std::array<unsigned int, EResCount> shiftBinding;
     std::array<unsigned int, EResCount> shiftBinding;
 
 
     // Per-descriptor-set shift values
     // Per-descriptor-set shift values
-    std::array<std::map<int, int>, EResCount>  shiftBindingForSet;
+    std::array<std::map<int, int>, EResCount> shiftBindingForSet;
 
 
     std::vector<std::string> resourceSetBinding;
     std::vector<std::string> resourceSetBinding;
     bool autoMapBindings;
     bool autoMapBindings;
@@ -697,15 +800,12 @@ protected:
     bool useUnknownFormat;
     bool useUnknownFormat;
     bool hlslOffsets;
     bool hlslOffsets;
     bool useStorageBuffer;
     bool useStorageBuffer;
+    bool useVulkanMemoryModel;
     bool hlslIoMapping;
     bool hlslIoMapping;
 
 
-    typedef std::list<TCall> TGraph;
-    TGraph callGraph;
-
     std::set<TString> ioAccessed;           // set of names of statically read/written I/O that might need extra checking
     std::set<TString> ioAccessed;           // set of names of statically read/written I/O that might need extra checking
     std::vector<TIoRange> usedIo[4];        // sets of used locations, one for each of in, out, uniform, and buffers
     std::vector<TIoRange> usedIo[4];        // sets of used locations, one for each of in, out, uniform, and buffers
     std::vector<TOffsetRange> usedAtomics;  // sets of bindings used by atomic counters
     std::vector<TOffsetRange> usedAtomics;  // sets of bindings used by atomic counters
-    std::vector<TXfbBuffer> xfbBuffers;     // all the data we need to track per xfb buffer
     std::unordered_set<int> usedConstantId; // specialization constant ids used
     std::unordered_set<int> usedConstantId; // specialization constant ids used
     std::set<TString> semanticNameSet;
     std::set<TString> semanticNameSet;
 
 
@@ -719,6 +819,10 @@ protected:
     TProcesses processes;
     TProcesses processes;
 
 
     bool needToLegalize;
     bool needToLegalize;
+    bool binaryDoubleOutput;
+
+    std::unordered_map<std::string, int> uniformLocationOverrides;
+    int uniformLocationBase;
 
 
 private:
 private:
     void operator=(TIntermediate&); // prevent assignments
     void operator=(TIntermediate&); // prevent assignments

+ 21 - 3
src/libraries/glslang/glslang/MachineIndependent/parseVersions.h

@@ -1,5 +1,6 @@
 //
 //
-// Copyright (C) 2016 Google, Inc.
+// Copyright (C) 2015-2018 Google, Inc.
+// Copyright (C) 2017 ARM Limited.
 //
 //
 // All rights reserved.
 // All rights reserved.
 //
 //
@@ -77,17 +78,32 @@ public:
     virtual void updateExtensionBehavior(int line, const char* const extension, const char* behavior);
     virtual void updateExtensionBehavior(int line, const char* const extension, const char* behavior);
     virtual void fullIntegerCheck(const TSourceLoc&, const char* op);
     virtual void fullIntegerCheck(const TSourceLoc&, const char* op);
     virtual void doubleCheck(const TSourceLoc&, const char* op);
     virtual void doubleCheck(const TSourceLoc&, const char* op);
-#ifdef AMD_EXTENSIONS
-    virtual void int16Check(const TSourceLoc& loc, const char* op, bool builtIn = false);
     virtual void float16Check(const TSourceLoc&, const char* op, bool builtIn = false);
     virtual void float16Check(const TSourceLoc&, const char* op, bool builtIn = false);
+    virtual void float16ScalarVectorCheck(const TSourceLoc&, const char* op, bool builtIn = false);
+    virtual bool float16Arithmetic();
+    virtual void requireFloat16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc);
+    virtual void int16ScalarVectorCheck(const TSourceLoc&, const char* op, bool builtIn = false);
+    virtual bool int16Arithmetic();
+    virtual void requireInt16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc);
+    virtual void int8ScalarVectorCheck(const TSourceLoc&, const char* op, bool builtIn = false);
+    virtual bool int8Arithmetic();
+    virtual void requireInt8Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc);
+#ifdef AMD_EXTENSIONS
+    virtual void float16OpaqueCheck(const TSourceLoc&, const char* op, bool builtIn = false);
 #endif
 #endif
     virtual void int64Check(const TSourceLoc&, const char* op, bool builtIn = false);
     virtual void int64Check(const TSourceLoc&, const char* op, bool builtIn = false);
+    virtual void explicitInt8Check(const TSourceLoc&, const char* op, bool builtIn = false);
+    virtual void explicitInt16Check(const TSourceLoc&, const char* op, bool builtIn = false);
+    virtual void explicitInt32Check(const TSourceLoc&, const char* op, bool builtIn = false);
+    virtual void explicitFloat32Check(const TSourceLoc&, const char* op, bool builtIn = false);
+    virtual void explicitFloat64Check(const TSourceLoc&, const char* op, bool builtIn = false);
     virtual void spvRemoved(const TSourceLoc&, const char* op);
     virtual void spvRemoved(const TSourceLoc&, const char* op);
     virtual void vulkanRemoved(const TSourceLoc&, const char* op);
     virtual void vulkanRemoved(const TSourceLoc&, const char* op);
     virtual void requireVulkan(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);
     virtual bool checkExtensionsRequested(const TSourceLoc&, int numExtensions, const char* const extensions[], const char* featureDesc);
     virtual bool checkExtensionsRequested(const TSourceLoc&, int numExtensions, const char* const extensions[], const char* featureDesc);
     virtual void updateExtensionBehavior(const char* const extension, TExtensionBehavior);
     virtual void updateExtensionBehavior(const char* const extension, TExtensionBehavior);
+    virtual void checkExtensionStage(const TSourceLoc&, const char* const extension);
 
 
     virtual void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken,
     virtual void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken,
         const char* szExtraInfoFormat, ...) = 0;
         const char* szExtraInfoFormat, ...) = 0;
@@ -113,6 +129,8 @@ public:
     bool relaxedErrors()    const { return (messages & EShMsgRelaxedErrors) != 0; }
     bool relaxedErrors()    const { return (messages & EShMsgRelaxedErrors) != 0; }
     bool suppressWarnings() const { return (messages & EShMsgSuppressWarnings) != 0; }
     bool suppressWarnings() const { return (messages & EShMsgSuppressWarnings) != 0; }
     bool isReadingHLSL()    const { return (messages & EShMsgReadHlsl) == EShMsgReadHlsl; }
     bool isReadingHLSL()    const { return (messages & EShMsgReadHlsl) == EShMsgReadHlsl; }
+    bool hlslEnable16BitTypes() const { return (messages & EShMsgHlslEnable16BitTypes) != 0; }
+    bool hlslDX9Compatible() const { return (messages & EShMsgHlslDX9Compatible) != 0; }
 
 
     TInfoSink& infoSink;
     TInfoSink& infoSink;
 
 

+ 35 - 0
src/libraries/glslang/glslang/MachineIndependent/pch.cpp

@@ -0,0 +1,35 @@
+//
+// Copyright (C) 2018 The Khronos Group Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+//    Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+//
+//    Redistributions in binary form must reproduce the above
+//    copyright notice, this list of conditions and the following
+//    disclaimer in the documentation and/or other materials provided
+//    with the distribution.
+//
+//    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+//    contributors may be used to endorse or promote products derived
+//    from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include "pch.h"

+ 49 - 0
src/libraries/glslang/glslang/MachineIndependent/pch.h

@@ -0,0 +1,49 @@
+#ifndef _PCH_H
+#define _PCH_H
+//
+// Copyright (C) 2018 The Khronos Group Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+//    Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+//
+//    Redistributions in binary form must reproduce the above
+//    copyright notice, this list of conditions and the following
+//    disclaimer in the documentation and/or other materials provided
+//    with the distribution.
+//
+//    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+//    contributors may be used to endorse or promote products derived
+//    from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+#include <sstream>
+#include <cstdlib>
+#include <cstring>
+#include <cctype>
+#include <climits>
+#include <iostream>
+#include <sstream>
+#include <memory>
+#include "SymbolTable.h"
+#include "ParseHelper.h"
+#include "Scan.h"
+#include "ScanContext.h"
+
+#endif /* _PCH_H */

+ 82 - 53
src/libraries/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp

@@ -1,6 +1,7 @@
 //
 //
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2013 LunarG, Inc.
 // Copyright (C) 2013 LunarG, Inc.
+// Copyright (C) 2015-2018 Google, Inc.
 // All rights reserved.
 // All rights reserved.
 //
 //
 // Redistribution and use in source and binary forms, with or without
 // Redistribution and use in source and binary forms, with or without
@@ -109,11 +110,12 @@ int TPpContext::CPPdefine(TPpToken* ppToken)
 
 
     // save the macro name
     // save the macro name
     const int defAtom = atomStrings.getAddAtom(ppToken->name);
     const int defAtom = atomStrings.getAddAtom(ppToken->name);
+    TSourceLoc defineLoc = ppToken->loc; // because ppToken might go to the next line before we report errors
 
 
     // gather parameters to the macro, between (...)
     // gather parameters to the macro, between (...)
     token = scanToken(ppToken);
     token = scanToken(ppToken);
-    if (token == '(' && ! ppToken->space) {
-        mac.emptyArgs = 1;
+    if (token == '(' && !ppToken->space) {
+        mac.functionLike = 1;
         do {
         do {
             token = scanToken(ppToken);
             token = scanToken(ppToken);
             if (mac.args.size() == 0 && token == ')')
             if (mac.args.size() == 0 && token == ')')
@@ -123,7 +125,6 @@ int TPpContext::CPPdefine(TPpToken* ppToken)
 
 
                 return token;
                 return token;
             }
             }
-            mac.emptyArgs = 0;
             const int argAtom = atomStrings.getAddAtom(ppToken->name);
             const int argAtom = atomStrings.getAddAtom(ppToken->name);
 
 
             // check for duplication of parameter name
             // check for duplication of parameter name
@@ -149,7 +150,6 @@ int TPpContext::CPPdefine(TPpToken* ppToken)
     }
     }
 
 
     // record the definition of the macro
     // record the definition of the macro
-    TSourceLoc defineLoc = ppToken->loc; // because ppToken is going to go to the next line before we report errors
     while (token != '\n' && token != EndOfInput) {
     while (token != '\n' && token != EndOfInput) {
         mac.body.putToken(token, ppToken);
         mac.body.putToken(token, ppToken);
         token = scanToken(ppToken);
         token = scanToken(ppToken);
@@ -164,7 +164,9 @@ int TPpContext::CPPdefine(TPpToken* ppToken)
             // Already defined -- need to make sure they are identical:
             // Already defined -- need to make sure they are identical:
             // "Two replacement lists are identical if and only if the preprocessing tokens in both have the same number,
             // "Two replacement lists are identical if and only if the preprocessing tokens in both have the same number,
             // ordering, spelling, and white-space separation, where all white-space separations are considered identical."
             // ordering, spelling, and white-space separation, where all white-space separations are considered identical."
-            if (existing->args.size() != mac.args.size() || existing->emptyArgs != mac.emptyArgs)
+            if (existing->functionLike != mac.functionLike)
+                parseContext.ppError(defineLoc, "Macro redefined; function-like versus object-like:", "#define", atomStrings.getString(defAtom));
+            else if (existing->args.size() != mac.args.size())
                 parseContext.ppError(defineLoc, "Macro redefined; different number of arguments:", "#define", atomStrings.getString(defAtom));
                 parseContext.ppError(defineLoc, "Macro redefined; different number of arguments:", "#define", atomStrings.getString(defAtom));
             else {
             else {
                 if (existing->args != mac.args)
                 if (existing->args != mac.args)
@@ -515,15 +517,16 @@ int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, boo
 int TPpContext::evalToToken(int token, bool shortCircuit, int& res, bool& err, TPpToken* ppToken)
 int TPpContext::evalToToken(int token, bool shortCircuit, int& res, bool& err, TPpToken* ppToken)
 {
 {
     while (token == PpAtomIdentifier && strcmp("defined", ppToken->name) != 0) {
     while (token == PpAtomIdentifier && strcmp("defined", ppToken->name) != 0) {
-        int macroReturn = MacroExpand(ppToken, true, false);
-        if (macroReturn == 0) {
+        switch (MacroExpand(ppToken, true, false)) {
+        case MacroExpandNotStarted:
+        case MacroExpandError:
             parseContext.ppError(ppToken->loc, "can't evaluate expression", "preprocessor evaluation", "");
             parseContext.ppError(ppToken->loc, "can't evaluate expression", "preprocessor evaluation", "");
             err = true;
             err = true;
             res = 0;
             res = 0;
-            token = scanToken(ppToken);
             break;
             break;
-        }
-        if (macroReturn == -1) {
+        case MacroExpandStarted:
+            break;
+        case MacroExpandUndef:
             if (! shortCircuit && parseContext.profile == EEsProfile) {
             if (! shortCircuit && parseContext.profile == EEsProfile) {
                 const char* message = "undefined macro in expression not allowed in es profile";
                 const char* message = "undefined macro in expression not allowed in es profile";
                 if (parseContext.relaxedErrors())
                 if (parseContext.relaxedErrors())
@@ -531,8 +534,11 @@ int TPpContext::evalToToken(int token, bool shortCircuit, int& res, bool& err, T
                 else
                 else
                     parseContext.ppError(ppToken->loc, message, "preprocessor evaluation", ppToken->name);
                     parseContext.ppError(ppToken->loc, message, "preprocessor evaluation", ppToken->name);
             }
             }
+            break;
         }
         }
         token = scanToken(ppToken);
         token = scanToken(ppToken);
+        if (err)
+            break;
     }
     }
 
 
     return token;
     return token;
@@ -731,12 +737,10 @@ int TPpContext::CPPerror(TPpToken* ppToken)
     TSourceLoc loc = ppToken->loc;
     TSourceLoc loc = ppToken->loc;
 
 
     while (token != '\n' && token != EndOfInput) {
     while (token != '\n' && token != EndOfInput) {
-        if (token == PpAtomConstInt   || token == PpAtomConstUint   ||
+        if (token == PpAtomConstInt16 || token == PpAtomConstUint16 ||
+            token == PpAtomConstInt   || token == PpAtomConstUint   ||
             token == PpAtomConstInt64 || token == PpAtomConstUint64 ||
             token == PpAtomConstInt64 || token == PpAtomConstUint64 ||
-#ifdef AMD_EXTENSIONS
-            token == PpAtomConstInt16 || token == PpAtomConstUint16 ||
             token == PpAtomConstFloat16 ||
             token == PpAtomConstFloat16 ||
-#endif
             token == PpAtomConstFloat || token == PpAtomConstDouble) {
             token == PpAtomConstFloat || token == PpAtomConstDouble) {
                 message.append(ppToken->name);
                 message.append(ppToken->name);
         } else if (token == PpAtomIdentifier || token == PpAtomConstString) {
         } else if (token == PpAtomIdentifier || token == PpAtomConstString) {
@@ -775,9 +779,7 @@ int TPpContext::CPPpragma(TPpToken* ppToken)
 #endif
 #endif
         case PpAtomConstFloat:
         case PpAtomConstFloat:
         case PpAtomConstDouble:
         case PpAtomConstDouble:
-#ifdef AMD_EXTENSIONS
         case PpAtomConstFloat16:
         case PpAtomConstFloat16:
-#endif
             tokens.push_back(ppToken->name);
             tokens.push_back(ppToken->name);
             break;
             break;
         default:
         default:
@@ -1015,15 +1017,25 @@ TPpContext::TokenStream* TPpContext::PrescanMacroArg(TokenStream& arg, TPpToken*
     int token;
     int token;
     while ((token = scanToken(ppToken)) != tMarkerInput::marker && token != EndOfInput) {
     while ((token = scanToken(ppToken)) != tMarkerInput::marker && token != EndOfInput) {
         token = tokenPaste(token, *ppToken);
         token = tokenPaste(token, *ppToken);
+        if (token == PpAtomIdentifier) {
+            switch (MacroExpand(ppToken, false, newLineOkay)) {
+            case MacroExpandNotStarted:
+                break;
+            case MacroExpandError:
+                token = EndOfInput;
+                break;
+            case MacroExpandStarted:
+            case MacroExpandUndef:
+                continue;
+            }
+        }
         if (token == tMarkerInput::marker || token == EndOfInput)
         if (token == tMarkerInput::marker || token == EndOfInput)
             break;
             break;
-        if (token == PpAtomIdentifier && MacroExpand(ppToken, false, newLineOkay) != 0)
-            continue;
         expandedArg->putToken(token, ppToken);
         expandedArg->putToken(token, ppToken);
     }
     }
 
 
     if (token == EndOfInput) {
     if (token == EndOfInput) {
-        // MacroExpand ate the marker, so had bad input, recover
+        // Error, or MacroExpand ate the marker, so had bad input, recover
         delete expandedArg;
         delete expandedArg;
         expandedArg = nullptr;
         expandedArg = nullptr;
     } else {
     } else {
@@ -1110,7 +1122,8 @@ int TPpContext::tZeroInput::scan(TPpToken* ppToken)
     if (done)
     if (done)
         return EndOfInput;
         return EndOfInput;
 
 
-    strcpy(ppToken->name, "0");
+    ppToken->name[0] = '0';
+    ppToken->name[1] = 0;
     ppToken->ival = 0;
     ppToken->ival = 0;
     ppToken->space = false;
     ppToken->space = false;
     done = true;
     done = true;
@@ -1119,14 +1132,18 @@ int TPpContext::tZeroInput::scan(TPpToken* ppToken)
 }
 }
 
 
 //
 //
-// Check a token to see if it is a macro that should be expanded.
-// If it is, and defined, push a tInput that will produce the appropriate expansion
-// and return 1.
-// If it is, but undefined, and expandUndef is requested, push a tInput that will
-// expand to 0 and return -1.
-// Otherwise, return 0 to indicate no expansion, which is not necessarily an error.
+// Check a token to see if it is a macro that should be expanded:
+// - If it is, and defined, push a tInput that will produce the appropriate
+//   expansion and return MacroExpandStarted.
+// - If it is, but undefined, and expandUndef is requested, push a tInput
+//   that will expand to 0 and return MacroExpandUndef.
+// - Otherwise, there is no expansion, and there are two cases:
+//   * It might be okay there is no expansion, and no specific error was
+//     detected. Returns MacroExpandNotStarted.
+//   * The expansion was started, but could not be completed, due to an error
+//     that cannot be recovered from. Returns MacroExpandError.
 //
 //
-int TPpContext::MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOkay)
+MacroExpandResult TPpContext::MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOkay)
 {
 {
     ppToken->space = false;
     ppToken->space = false;
     int macroAtom = atomStrings.getAtom(ppToken->name);
     int macroAtom = atomStrings.getAtom(ppToken->name);
@@ -1135,7 +1152,7 @@ int TPpContext::MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOka
         ppToken->ival = parseContext.getCurrentLoc().line;
         ppToken->ival = parseContext.getCurrentLoc().line;
         snprintf(ppToken->name, sizeof(ppToken->name), "%d", ppToken->ival);
         snprintf(ppToken->name, sizeof(ppToken->name), "%d", ppToken->ival);
         UngetToken(PpAtomConstInt, ppToken);
         UngetToken(PpAtomConstInt, ppToken);
-        return 1;
+        return MacroExpandStarted;
 
 
     case PpAtomFileMacro: {
     case PpAtomFileMacro: {
         if (parseContext.getCurrentLoc().name)
         if (parseContext.getCurrentLoc().name)
@@ -1143,50 +1160,55 @@ int TPpContext::MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOka
         ppToken->ival = parseContext.getCurrentLoc().string;
         ppToken->ival = parseContext.getCurrentLoc().string;
         snprintf(ppToken->name, sizeof(ppToken->name), "%s", ppToken->loc.getStringNameOrNum().c_str());
         snprintf(ppToken->name, sizeof(ppToken->name), "%s", ppToken->loc.getStringNameOrNum().c_str());
         UngetToken(PpAtomConstInt, ppToken);
         UngetToken(PpAtomConstInt, ppToken);
-        return 1;
+        return MacroExpandStarted;
     }
     }
 
 
     case PpAtomVersionMacro:
     case PpAtomVersionMacro:
         ppToken->ival = parseContext.version;
         ppToken->ival = parseContext.version;
         snprintf(ppToken->name, sizeof(ppToken->name), "%d", ppToken->ival);
         snprintf(ppToken->name, sizeof(ppToken->name), "%d", ppToken->ival);
         UngetToken(PpAtomConstInt, ppToken);
         UngetToken(PpAtomConstInt, ppToken);
-        return 1;
+        return MacroExpandStarted;
 
 
     default:
     default:
         break;
         break;
     }
     }
 
 
     MacroSymbol* macro = macroAtom == 0 ? nullptr : lookupMacroDef(macroAtom);
     MacroSymbol* macro = macroAtom == 0 ? nullptr : lookupMacroDef(macroAtom);
-    int depth = 0;
 
 
     // no recursive expansions
     // no recursive expansions
     if (macro != nullptr && macro->busy)
     if (macro != nullptr && macro->busy)
-        return 0;
+        return MacroExpandNotStarted;
 
 
     // not expanding undefined macros
     // not expanding undefined macros
     if ((macro == nullptr || macro->undef) && ! expandUndef)
     if ((macro == nullptr || macro->undef) && ! expandUndef)
-        return 0;
+        return MacroExpandNotStarted;
 
 
     // 0 is the value of an undefined macro
     // 0 is the value of an undefined macro
     if ((macro == nullptr || macro->undef) && expandUndef) {
     if ((macro == nullptr || macro->undef) && expandUndef) {
         pushInput(new tZeroInput(this));
         pushInput(new tZeroInput(this));
-        return -1;
+        return MacroExpandUndef;
     }
     }
 
 
     tMacroInput *in = new tMacroInput(this);
     tMacroInput *in = new tMacroInput(this);
 
 
     TSourceLoc loc = ppToken->loc;  // in case we go to the next line before discovering the error
     TSourceLoc loc = ppToken->loc;  // in case we go to the next line before discovering the error
     in->mac = macro;
     in->mac = macro;
-    if (macro->args.size() > 0 || macro->emptyArgs) {
-        int token = scanToken(ppToken);
+    if (macro->functionLike) {
+        // We don't know yet if this will be a successful call of a
+        // function-like macro; need to look for a '(', but without trashing
+        // the passed in ppToken, until we know we are no longer speculative.
+        TPpToken parenToken;
+        int token = scanToken(&parenToken);
         if (newLineOkay) {
         if (newLineOkay) {
             while (token == '\n')
             while (token == '\n')
-                token = scanToken(ppToken);
+                token = scanToken(&parenToken);
         }
         }
         if (token != '(') {
         if (token != '(') {
-            UngetToken(token, ppToken);
+            // Function-like macro called with object-like syntax: okay, don't expand.
+            // (We ate exactly one token that might not be white space; put it back.
+            UngetToken(token, &parenToken);
             delete in;
             delete in;
-            return 0;
+            return MacroExpandNotStarted;
         }
         }
         in->args.resize(in->mac->args.size());
         in->args.resize(in->mac->args.size());
         for (size_t i = 0; i < in->mac->args.size(); i++)
         for (size_t i = 0; i < in->mac->args.size(); i++)
@@ -1197,39 +1219,44 @@ int TPpContext::MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOka
         size_t arg = 0;
         size_t arg = 0;
         bool tokenRecorded = false;
         bool tokenRecorded = false;
         do {
         do {
-            depth = 0;
-            while (1) {
+            TVector<char> nestStack;
+            while (true) {
                 token = scanToken(ppToken);
                 token = scanToken(ppToken);
                 if (token == EndOfInput || token == tMarkerInput::marker) {
                 if (token == EndOfInput || token == tMarkerInput::marker) {
                     parseContext.ppError(loc, "End of input in macro", "macro expansion", atomStrings.getString(macroAtom));
                     parseContext.ppError(loc, "End of input in macro", "macro expansion", atomStrings.getString(macroAtom));
                     delete in;
                     delete in;
-                    return 0;
+                    return MacroExpandError;
                 }
                 }
                 if (token == '\n') {
                 if (token == '\n') {
                     if (! newLineOkay) {
                     if (! newLineOkay) {
                         parseContext.ppError(loc, "End of line in macro substitution:", "macro expansion", atomStrings.getString(macroAtom));
                         parseContext.ppError(loc, "End of line in macro substitution:", "macro expansion", atomStrings.getString(macroAtom));
                         delete in;
                         delete in;
-                        return 0;
+                        return MacroExpandError;
                     }
                     }
                     continue;
                     continue;
                 }
                 }
                 if (token == '#') {
                 if (token == '#') {
                     parseContext.ppError(ppToken->loc, "unexpected '#'", "macro expansion", atomStrings.getString(macroAtom));
                     parseContext.ppError(ppToken->loc, "unexpected '#'", "macro expansion", atomStrings.getString(macroAtom));
                     delete in;
                     delete in;
-                    return 0;
+                    return MacroExpandError;
                 }
                 }
                 if (in->mac->args.size() == 0 && token != ')')
                 if (in->mac->args.size() == 0 && token != ')')
                     break;
                     break;
-                if (depth == 0 && (token == ',' || token == ')'))
+                if (nestStack.size() == 0 && (token == ',' || token == ')'))
                     break;
                     break;
                 if (token == '(')
                 if (token == '(')
-                    depth++;
-                if (token == ')')
-                    depth--;
+                    nestStack.push_back(')');
+                else if (token == '{' && parseContext.isReadingHLSL())
+                    nestStack.push_back('}');
+                else if (nestStack.size() > 0 && token == nestStack.back())
+                    nestStack.pop_back();
                 in->args[arg]->putToken(token, ppToken);
                 in->args[arg]->putToken(token, ppToken);
                 tokenRecorded = true;
                 tokenRecorded = true;
             }
             }
+            // end of single argument scan
+
             if (token == ')') {
             if (token == ')') {
+                // closing paren of call
                 if (in->mac->args.size() == 1 && tokenRecorded == 0)
                 if (in->mac->args.size() == 1 && tokenRecorded == 0)
                     break;
                     break;
                 arg++;
                 arg++;
@@ -1237,23 +1264,25 @@ int TPpContext::MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOka
             }
             }
             arg++;
             arg++;
         } while (arg < in->mac->args.size());
         } while (arg < in->mac->args.size());
+        // end of all arguments scan
 
 
         if (arg < in->mac->args.size())
         if (arg < in->mac->args.size())
             parseContext.ppError(loc, "Too few args in Macro", "macro expansion", atomStrings.getString(macroAtom));
             parseContext.ppError(loc, "Too few args in Macro", "macro expansion", atomStrings.getString(macroAtom));
         else if (token != ')') {
         else if (token != ')') {
-            depth=0;
+            // Error recover code; find end of call, if possible
+            int depth = 0;
             while (token != EndOfInput && (depth > 0 || token != ')')) {
             while (token != EndOfInput && (depth > 0 || token != ')')) {
-                if (token == ')')
+                if (token == ')' || token == '}')
                     depth--;
                     depth--;
                 token = scanToken(ppToken);
                 token = scanToken(ppToken);
-                if (token == '(')
+                if (token == '(' || token == '{')
                     depth++;
                     depth++;
             }
             }
 
 
             if (token == EndOfInput) {
             if (token == EndOfInput) {
                 parseContext.ppError(loc, "End of input in macro", "macro expansion", atomStrings.getString(macroAtom));
                 parseContext.ppError(loc, "End of input in macro", "macro expansion", atomStrings.getString(macroAtom));
                 delete in;
                 delete in;
-                return 0;
+                return MacroExpandError;
             }
             }
             parseContext.ppError(loc, "Too many args in macro", "macro expansion", atomStrings.getString(macroAtom));
             parseContext.ppError(loc, "Too many args in macro", "macro expansion", atomStrings.getString(macroAtom));
         }
         }
@@ -1268,7 +1297,7 @@ int TPpContext::MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOka
     macro->busy = 1;
     macro->busy = 1;
     macro->body.reset();
     macro->body.reset();
 
 
-    return 1;
+    return MacroExpandStarted;
 }
 }
 
 
 } // end namespace glslang
 } // end namespace glslang

+ 4 - 0
src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpContext.cpp

@@ -1,6 +1,7 @@
 //
 //
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2013 LunarG, Inc.
 // Copyright (C) 2013 LunarG, Inc.
+// Copyright (C) 2015-2018 Google, Inc.
 // All rights reserved.
 // All rights reserved.
 //
 //
 // Redistribution and use in source and binary forms, with or without
 // Redistribution and use in source and binary forms, with or without
@@ -77,6 +78,7 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 \****************************************************************************/
 \****************************************************************************/
 
 
 #include <cstdlib>
 #include <cstdlib>
+#include <locale>
 
 
 #include "PpContext.h"
 #include "PpContext.h"
 
 
@@ -91,6 +93,8 @@ TPpContext::TPpContext(TParseContextBase& pc, const std::string& rootFileName, T
     for (elsetracker = 0; elsetracker < maxIfNesting; elsetracker++)
     for (elsetracker = 0; elsetracker < maxIfNesting; elsetracker++)
         elseSeen[elsetracker] = false;
         elseSeen[elsetracker] = false;
     elsetracker = 0;
     elsetracker = 0;
+
+    strtodStream.imbue(std::locale::classic());
 }
 }
 
 
 TPpContext::~TPpContext()
 TPpContext::~TPpContext()

+ 31 - 17
src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpContext.h

@@ -1,5 +1,6 @@
 //
 //
 // Copyright (C) 2013 LunarG, Inc.
 // Copyright (C) 2013 LunarG, Inc.
+// Copyright (C) 2015-2018 Google, Inc.
 // All rights reserved.
 // All rights reserved.
 //
 //
 // Redistribution and use in source and binary forms, with or without
 // Redistribution and use in source and binary forms, with or without
@@ -80,6 +81,7 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 #include <stack>
 #include <stack>
 #include <unordered_map>
 #include <unordered_map>
+#include <sstream>
 
 
 #include "../ParseHelper.h"
 #include "../ParseHelper.h"
 
 
@@ -92,13 +94,16 @@ namespace glslang {
 
 
 class TPpToken {
 class TPpToken {
 public:
 public:
-    TPpToken() : space(false), i64val(0)
+    TPpToken() { clear(); }
+    void clear()
     {
     {
+        space = false;
+        i64val = 0;
         loc.init();
         loc.init();
         name[0] = 0;
         name[0] = 0;
     }
     }
 
 
-    // This is used for comparing macro definitions, so checks what is relevant for that.
+    // Used for comparing macro definitions, so checks what is relevant for that.
     bool operator==(const TPpToken& right)
     bool operator==(const TPpToken& right)
     {
     {
         return space == right.space &&
         return space == right.space &&
@@ -108,15 +113,17 @@ public:
     bool operator!=(const TPpToken& right) { return ! operator==(right); }
     bool operator!=(const TPpToken& right) { return ! operator==(right); }
 
 
     TSourceLoc loc;
     TSourceLoc loc;
-    bool space;  // true if a space (for white space or a removed comment) should also be recognized, in front of the token returned
-
+    // True if a space (for white space or a removed comment) should also be
+    // recognized, in front of the token returned:
+    bool space;
+    // Numeric value of the token:
     union {
     union {
         int ival;
         int ival;
         double dval;
         double dval;
         long long i64val;
         long long i64val;
     };
     };
-
-    char   name[MaxTokenLength + 1];
+    // Text string of the token:
+    char name[MaxTokenLength + 1];
 };
 };
 
 
 class TStringAtomMap {
 class TStringAtomMap {
@@ -177,6 +184,13 @@ protected:
 
 
 class TInputScanner;
 class TInputScanner;
 
 
+enum MacroExpandResult {
+    MacroExpandNotStarted, // macro not expanded, which might not be an error
+    MacroExpandError,      // a clear error occurred while expanding, no expansion
+    MacroExpandStarted,    // macro expansion process has started
+    MacroExpandUndef       // macro is undefined and will be expanded
+};
+
 // This class is the result of turning a huge pile of C code communicating through globals
 // This class is the result of turning a huge pile of C code communicating through globals
 // into a class.  This was done to allowing instancing to attain thread safety.
 // into a class.  This was done to allowing instancing to attain thread safety.
 // Don't expect too much in terms of OO design.
 // Don't expect too much in terms of OO design.
@@ -254,12 +268,12 @@ public:
     //
     //
 
 
     struct MacroSymbol {
     struct MacroSymbol {
-        MacroSymbol() : emptyArgs(0), busy(0), undef(0) { }
+        MacroSymbol() : functionLike(0), busy(0), undef(0) { }
         TVector<int> args;
         TVector<int> args;
         TokenStream body;
         TokenStream body;
-        unsigned emptyArgs : 1;
-        unsigned busy      : 1;
-        unsigned undef     : 1;
+        unsigned functionLike : 1;  // 0 means object-like, 1 means function-like
+        unsigned busy         : 1;
+        unsigned undef        : 1;
     };
     };
 
 
     typedef TMap<int, MacroSymbol> TSymbolMap;
     typedef TMap<int, MacroSymbol> TSymbolMap;
@@ -394,7 +408,7 @@ protected:
     int readCPPline(TPpToken * ppToken);
     int readCPPline(TPpToken * ppToken);
     int scanHeaderName(TPpToken* ppToken, char delimit);
     int scanHeaderName(TPpToken* ppToken, char delimit);
     TokenStream* PrescanMacroArg(TokenStream&, TPpToken*, bool newLineOkay);
     TokenStream* PrescanMacroArg(TokenStream&, TPpToken*, bool newLineOkay);
-    int MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOkay);
+    MacroExpandResult MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOkay);
 
 
     //
     //
     // From PpTokens.cpp
     // From PpTokens.cpp
@@ -520,7 +534,7 @@ protected:
               prologue_(prologue),
               prologue_(prologue),
               epilogue_(epilogue),
               epilogue_(epilogue),
               includedFile_(includedFile),
               includedFile_(includedFile),
-              scanner(3, strings, lengths, names, 0, 0, true),
+              scanner(3, strings, lengths, nullptr, 0, 0, true),
               prevScanner(nullptr),
               prevScanner(nullptr),
               stringInput(pp, scanner)
               stringInput(pp, scanner)
         {
         {
@@ -535,9 +549,9 @@ protected:
               scanner.setLine(startLoc.line);
               scanner.setLine(startLoc.line);
               scanner.setString(startLoc.string);
               scanner.setString(startLoc.string);
 
 
-              scanner.setFile(startLoc.name, 0);
-              scanner.setFile(startLoc.name, 1);
-              scanner.setFile(startLoc.name, 2);
+              scanner.setFile(startLoc.name->c_str(), 0);
+              scanner.setFile(startLoc.name->c_str(), 1);
+              scanner.setFile(startLoc.name->c_str(), 2);
         }
         }
 
 
         // tInput methods:
         // tInput methods:
@@ -577,8 +591,6 @@ protected:
         const char* strings[3];
         const char* strings[3];
         // Length of str_, passed to scanner constructor.
         // Length of str_, passed to scanner constructor.
         size_t lengths[3];
         size_t lengths[3];
-        // String names
-        const char* names[3];
         // Scans over str_.
         // Scans over str_.
         TInputScanner scanner;
         TInputScanner scanner;
         // The previous effective scanner before the scanner in this instance
         // The previous effective scanner before the scanner in this instance
@@ -615,6 +627,8 @@ protected:
     std::string rootFileName;
     std::string rootFileName;
     std::stack<TShader::Includer::IncludeResult*> includeStack;
     std::stack<TShader::Includer::IncludeResult*> includeStack;
     std::string currentSourceFile;
     std::string currentSourceFile;
+
+    std::istringstream strtodStream;
 };
 };
 
 
 } // end namespace glslang
 } // end namespace glslang

+ 293 - 152
src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp

@@ -1,6 +1,9 @@
 //
 //
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2013 LunarG, Inc.
 // Copyright (C) 2013 LunarG, Inc.
+// Copyright (C) 2017 ARM Limited.
+// Copyright (C) 2015-2018 Google, Inc.
+//
 // All rights reserved.
 // All rights reserved.
 //
 //
 // Redistribution and use in source and binary forms, with or without
 // Redistribution and use in source and binary forms, with or without
@@ -101,34 +104,39 @@ namespace glslang {
 
 
 int TPpContext::lFloatConst(int len, int ch, TPpToken* ppToken)
 int TPpContext::lFloatConst(int len, int ch, TPpToken* ppToken)
 {
 {
-    bool HasDecimalOrExponent = false;
-    int isDouble = 0;
-    bool generateFloat16 = false;
-    bool acceptFloat16 = parseContext.intermediate.getSource() == EShSourceHlsl;
-    bool isFloat16 = false;
-    bool requireHF = false;
-#ifdef AMD_EXTENSIONS
-    if (parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float)) {
-        acceptFloat16 = true;
-        generateFloat16 = true;
-        requireHF = true;
-    }
-#endif
-
     const auto saveName = [&](int ch) {
     const auto saveName = [&](int ch) {
         if (len <= MaxTokenLength)
         if (len <= MaxTokenLength)
             ppToken->name[len++] = static_cast<char>(ch);
             ppToken->name[len++] = static_cast<char>(ch);
     };
     };
 
 
-    // Decimal:
+    // find the range of non-zero digits before the decimal point
+    int startNonZero = 0;
+    while (startNonZero < len && ppToken->name[startNonZero] == '0')
+        ++startNonZero;
+    int endNonZero = len;
+    while (endNonZero > startNonZero && ppToken->name[endNonZero-1] == '0')
+        --endNonZero;
+    int numWholeNumberDigits = endNonZero - startNonZero;
+
+    // accumulate the range's value
+    bool fastPath = numWholeNumberDigits <= 15;  // when the number gets too complex, set to false
+    unsigned long long wholeNumber = 0;
+    if (fastPath) {
+        for (int i = startNonZero; i < endNonZero; ++i)
+            wholeNumber = wholeNumber * 10 + (ppToken->name[i] - '0');
+    }
+    int decimalShift = len - endNonZero;
 
 
+    // Decimal point:
+    bool hasDecimalOrExponent = false;
     if (ch == '.') {
     if (ch == '.') {
-        HasDecimalOrExponent = true;
+        hasDecimalOrExponent = true;
         saveName(ch);
         saveName(ch);
         ch = getChar();
         ch = getChar();
+        int firstDecimal = len;
 
 
         // 1.#INF or -1.#INF
         // 1.#INF or -1.#INF
-        if (parseContext.intermediate.getSource() == EShSourceHlsl && ch == '#') {
+        if (ch == '#' && (ifdepth > 0 || parseContext.intermediate.getSource() == EShSourceHlsl)) {
             if ((len <  2) ||
             if ((len <  2) ||
                 (len == 2 && ppToken->name[0] != '1') ||
                 (len == 2 && ppToken->name[0] != '1') ||
                 (len == 3 && ppToken->name[1] != '1' && !(ppToken->name[0] == '-' || ppToken->name[0] == '+')) ||
                 (len == 3 && ppToken->name[1] != '1' && !(ppToken->name[0] == '-' || ppToken->name[0] == '+')) ||
@@ -155,55 +163,118 @@ int TPpContext::lFloatConst(int len, int ch, TPpToken* ppToken)
             }
             }
         }
         }
 
 
+        // Consume leading-zero digits after the decimal point
+        while (ch == '0') {
+            saveName(ch);
+            ch = getChar();
+        }
+        int startNonZeroDecimal = len;
+        int endNonZeroDecimal = len;
+
+        // Consume remaining digits, up to the exponent
         while (ch >= '0' && ch <= '9') {
         while (ch >= '0' && ch <= '9') {
             saveName(ch);
             saveName(ch);
+            if (ch != '0')
+                endNonZeroDecimal = len;
             ch = getChar();
             ch = getChar();
         }
         }
+
+        // Compute accumulation up to the last non-zero digit
+        if (endNonZeroDecimal > startNonZeroDecimal) {
+            numWholeNumberDigits += endNonZeroDecimal - endNonZero - 1; // don't include the "."
+            if (numWholeNumberDigits > 15)
+                fastPath = false;
+            if (fastPath) {
+                for (int i = endNonZero; i < endNonZeroDecimal; ++i) {
+                    if (ppToken->name[i] != '.')
+                        wholeNumber = wholeNumber * 10 + (ppToken->name[i] - '0');
+                }
+            }
+            decimalShift = firstDecimal - endNonZeroDecimal;
+        }
     }
     }
 
 
     // Exponent:
     // Exponent:
-
-    if (ch == 'e' || ch == 'E') {
-        HasDecimalOrExponent = true;
-        saveName(ch);
-        ch = getChar();
-        if (ch == '+' || ch == '-') {
+    bool negativeExponent = false;
+    double exponentValue = 0.0;
+    int exponent = 0;
+    {
+        if (ch == 'e' || ch == 'E') {
+            hasDecimalOrExponent = true;
             saveName(ch);
             saveName(ch);
             ch = getChar();
             ch = getChar();
-        }
-        if (ch >= '0' && ch <= '9') {
-            while (ch >= '0' && ch <= '9') {
+            if (ch == '+' || ch == '-') {
+                negativeExponent = ch == '-';
                 saveName(ch);
                 saveName(ch);
                 ch = getChar();
                 ch = getChar();
             }
             }
-        } else {
-            parseContext.ppError(ppToken->loc, "bad character in float exponent", "", "");
+            if (ch >= '0' && ch <= '9') {
+                while (ch >= '0' && ch <= '9') {
+                    exponent = exponent * 10 + (ch - '0');
+                    saveName(ch);
+                    ch = getChar();
+                }
+            } else {
+                parseContext.ppError(ppToken->loc, "bad character in float exponent", "", "");
+            }
+        }
+
+        // Compensate for location of decimal
+        if (negativeExponent)
+            exponent -= decimalShift;
+        else {
+            exponent += decimalShift;
+            if (exponent < 0) {
+                negativeExponent = true;
+                exponent = -exponent;
+            }
+        }
+        if (exponent > 22)
+            fastPath = false;
+
+        if (fastPath) {
+            // Compute the floating-point value of the exponent
+            exponentValue = 1.0;
+            if (exponent > 0) {
+                double expFactor = 10;
+                while (exponent > 0) {
+                    if (exponent & 0x1)
+                        exponentValue *= expFactor;
+                    expFactor *= expFactor;
+                    exponent >>= 1;
+                }
+            }
         }
         }
     }
     }
 
 
     // Suffix:
     // Suffix:
-
+    bool isDouble = false;
+    bool isFloat16 = false;
     if (ch == 'l' || ch == 'L') {
     if (ch == 'l' || ch == 'L') {
-        parseContext.doubleCheck(ppToken->loc, "double floating-point suffix");
-        if (! HasDecimalOrExponent)
+        if (ifdepth == 0 && parseContext.intermediate.getSource() == EShSourceGlsl)
+            parseContext.doubleCheck(ppToken->loc, "double floating-point suffix");
+        if (ifdepth == 0 && !hasDecimalOrExponent)
             parseContext.ppError(ppToken->loc, "float literal needs a decimal point or exponent", "", "");
             parseContext.ppError(ppToken->loc, "float literal needs a decimal point or exponent", "", "");
-        int ch2 = getChar();
-        if (ch2 != 'f' && ch2 != 'F') {
-            ungetChar();
-            ungetChar();
-        } else {
+        if (parseContext.intermediate.getSource() == EShSourceGlsl) {
+            int ch2 = getChar();
+            if (ch2 != 'f' && ch2 != 'F') {
+                ungetChar();
+                ungetChar();
+            } else {
+                saveName(ch);
+                saveName(ch2);
+                isDouble = true;
+            }
+        } else if (parseContext.intermediate.getSource() == EShSourceHlsl) {
             saveName(ch);
             saveName(ch);
-            saveName(ch2);
-            isDouble = 1;
+            isDouble = true;
         }
         }
-    } else if (acceptFloat16 && (ch == 'h' || ch == 'H')) {
-#ifdef AMD_EXTENSIONS
-        if (generateFloat16)
+    } else if (ch == 'h' || ch == 'H') {
+        if (ifdepth == 0 && parseContext.intermediate.getSource() == EShSourceGlsl)
             parseContext.float16Check(ppToken->loc, "half floating-point suffix");
             parseContext.float16Check(ppToken->loc, "half floating-point suffix");
-#endif
-        if (!HasDecimalOrExponent)
+        if (ifdepth == 0 && !hasDecimalOrExponent)
             parseContext.ppError(ppToken->loc, "float literal needs a decimal point or exponent", "", "");
             parseContext.ppError(ppToken->loc, "float literal needs a decimal point or exponent", "", "");
-        if (requireHF) {
+        if (parseContext.intermediate.getSource() == EShSourceGlsl) {
             int ch2 = getChar();
             int ch2 = getChar();
             if (ch2 != 'f' && ch2 != 'F') {
             if (ch2 != 'f' && ch2 != 'F') {
                 ungetChar();
                 ungetChar();
@@ -211,23 +282,24 @@ int TPpContext::lFloatConst(int len, int ch, TPpToken* ppToken)
             } else {
             } else {
                 saveName(ch);
                 saveName(ch);
                 saveName(ch2);
                 saveName(ch2);
-                isFloat16 = generateFloat16;
+                isFloat16 = true;
             }
             }
-        } else {
+        } else if (parseContext.intermediate.getSource() == EShSourceHlsl) {
             saveName(ch);
             saveName(ch);
-            isFloat16 = generateFloat16;
+            isFloat16 = true;
         }
         }
     } else if (ch == 'f' || ch == 'F') {
     } else if (ch == 'f' || ch == 'F') {
-        parseContext.profileRequires(ppToken->loc,  EEsProfile, 300, nullptr, "floating-point suffix");
-        if (! parseContext.relaxedErrors())
+        if (ifdepth == 0)
+            parseContext.profileRequires(ppToken->loc,  EEsProfile, 300, nullptr, "floating-point suffix");
+        if (ifdepth == 0 && !parseContext.relaxedErrors())
             parseContext.profileRequires(ppToken->loc, ~EEsProfile, 120, nullptr, "floating-point suffix");
             parseContext.profileRequires(ppToken->loc, ~EEsProfile, 120, nullptr, "floating-point suffix");
-        if (! HasDecimalOrExponent)
+        if (ifdepth == 0 && !hasDecimalOrExponent)
             parseContext.ppError(ppToken->loc, "float literal needs a decimal point or exponent", "", "");
             parseContext.ppError(ppToken->loc, "float literal needs a decimal point or exponent", "", "");
         saveName(ch);
         saveName(ch);
     } else
     } else
         ungetChar();
         ungetChar();
 
 
-    // Patch up the name, length, etc.
+    // Patch up the name and length for overflow
 
 
     if (len > MaxTokenLength) {
     if (len > MaxTokenLength) {
         len = MaxTokenLength;
         len = MaxTokenLength;
@@ -235,8 +307,45 @@ int TPpContext::lFloatConst(int len, int ch, TPpToken* ppToken)
     }
     }
     ppToken->name[len] = '\0';
     ppToken->name[len] = '\0';
 
 
-    // Get the numerical value
-    ppToken->dval = strtod(ppToken->name, nullptr);
+    // Compute the numerical value
+    if (fastPath) {
+        // compute the floating-point value of the exponent
+        if (exponentValue == 0.0)
+            ppToken->dval = (double)wholeNumber;
+        else if (negativeExponent)
+            ppToken->dval = (double)wholeNumber / exponentValue;
+        else
+            ppToken->dval = (double)wholeNumber * exponentValue;
+    } else {
+        // slow path
+        ppToken->dval = 0.0;
+
+        // remove suffix
+        TString numstr(ppToken->name);
+        if (numstr.back() == 'f' || numstr.back() == 'F')
+            numstr.pop_back();
+        if (numstr.back() == 'h' || numstr.back() == 'H')
+            numstr.pop_back();
+        if (numstr.back() == 'l' || numstr.back() == 'L')
+            numstr.pop_back();
+
+        // use platform library
+        strtodStream.clear();
+        strtodStream.str(numstr.c_str());
+        strtodStream >> ppToken->dval;
+        if (strtodStream.fail()) {
+            // Assume failure combined with a large exponent was overflow, in
+            // an attempt to set INF.
+            if (!negativeExponent && exponent + numWholeNumberDigits > 300)
+                ppToken->i64val = 0x7ff0000000000000; // +Infinity
+            // Assume failure combined with a small exponent was overflow.
+            if (negativeExponent && exponent + numWholeNumberDigits > 300)
+                ppToken->dval = 0.0;
+            // Unknown reason for failure. Theory is that either
+            //  - the 0.0 is still there, or
+            //  - something reasonable was written that is better than 0.0
+        }
+    }
 
 
     // Return the right token type
     // Return the right token type
     if (isDouble)
     if (isDouble)
@@ -333,19 +442,23 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
     int ch = 0;
     int ch = 0;
     int ii = 0;
     int ii = 0;
     unsigned long long ival = 0;
     unsigned long long ival = 0;
-    bool enableInt64 = pp->parseContext.version >= 450 && pp->parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_int64);
-#ifdef AMD_EXTENSIONS
-    bool enableInt16 = pp->parseContext.version >= 450 && pp->parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_int16);
-#endif
-    bool acceptHalf = pp->parseContext.intermediate.getSource() == EShSourceHlsl;
-#ifdef AMD_EXTENSIONS
-    if (pp->parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float))
-        acceptHalf = true;
-#endif
-
     const auto floatingPointChar = [&](int ch) { return ch == '.' || ch == 'e' || ch == 'E' ||
     const auto floatingPointChar = [&](int ch) { return ch == '.' || ch == 'e' || ch == 'E' ||
                                                                      ch == 'f' || ch == 'F' ||
                                                                      ch == 'f' || ch == 'F' ||
-                                                     (acceptHalf && (ch == 'h' || ch == 'H')); };
+                                                                     ch == 'h' || ch == 'H'; };
+
+    static const char* const Int64_Extensions[] = {
+        E_GL_ARB_gpu_shader_int64,
+        E_GL_EXT_shader_explicit_arithmetic_types,
+        E_GL_EXT_shader_explicit_arithmetic_types_int64 };
+    static const int Num_Int64_Extensions = sizeof(Int64_Extensions) / sizeof(Int64_Extensions[0]);
+
+    static const char* const Int16_Extensions[] = {
+#ifdef AMD_EXTENSIONS
+        E_GL_AMD_gpu_shader_int16,
+#endif
+        E_GL_EXT_shader_explicit_arithmetic_types,
+        E_GL_EXT_shader_explicit_arithmetic_types_int16 };
+    static const int Num_Int16_Extensions = sizeof(Int16_Extensions) / sizeof(Int16_Extensions[0]);
 
 
     ppToken->ival = 0;
     ppToken->ival = 0;
     ppToken->i64val = 0;
     ppToken->i64val = 0;
@@ -409,9 +522,7 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
 
 
                 bool isUnsigned = false;
                 bool isUnsigned = false;
                 bool isInt64 = false;
                 bool isInt64 = false;
-#ifdef AMD_EXTENSIONS
                 bool isInt16 = false;
                 bool isInt16 = false;
-#endif
                 ppToken->name[len++] = (char)ch;
                 ppToken->name[len++] = (char)ch;
                 ch = getch();
                 ch = getch();
                 if ((ch >= '0' && ch <= '9') ||
                 if ((ch >= '0' && ch <= '9') ||
@@ -420,7 +531,7 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
 
 
                     ival = 0;
                     ival = 0;
                     do {
                     do {
-                        if (len < MaxTokenLength && (ival <= 0x0fffffffu || (enableInt64 && ival <= 0x0fffffffffffffffull))) {
+                        if (len < MaxTokenLength && ival <= 0x0fffffffffffffffull) {
                             ppToken->name[len++] = (char)ch;
                             ppToken->name[len++] = (char)ch;
                             if (ch >= '0' && ch <= '9') {
                             if (ch >= '0' && ch <= '9') {
                                 ii = ch - '0';
                                 ii = ch - '0';
@@ -453,33 +564,31 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
                         ppToken->name[len++] = (char)ch;
                         ppToken->name[len++] = (char)ch;
                     isUnsigned = true;
                     isUnsigned = true;
 
 
-                    if (enableInt64) {
-                        int nextCh = getch();
-                        if ((ch == 'u' && nextCh == 'l') || (ch == 'U' && nextCh == 'L')) {
-                            if (len < MaxTokenLength)
-                                ppToken->name[len++] = (char)nextCh;
-                            isInt64 = true;
-                        } else
-                            ungetch();
-                    }
+                    int nextCh = getch();
+                    if (nextCh == 'l' || nextCh == 'L') {
+                        if (len < MaxTokenLength)
+                            ppToken->name[len++] = (char)nextCh;
+                        isInt64 = true;
+                    } else
+                        ungetch();
 
 
 #ifdef AMD_EXTENSIONS
 #ifdef AMD_EXTENSIONS
-                    if (enableInt16) {
-                        int nextCh = getch();
-                        if ((ch == 'u' && nextCh == 's') || (ch == 'U' && nextCh == 'S')) {
-                            if (len < MaxTokenLength)
-                                ppToken->name[len++] = (char)nextCh;
-                            isInt16 = true;
-                        } else
-                            ungetch();
-                    }
+                    nextCh = getch();
+                    if ((nextCh == 's' || nextCh == 'S') &&
+                            pp->parseContext.intermediate.getSource() == EShSourceGlsl) {
+                        if (len < MaxTokenLength)
+                            ppToken->name[len++] = (char)nextCh;
+                        isInt16 = true;
+                    } else
+                        ungetch();
 #endif
 #endif
-                } else if (enableInt64 && (ch == 'l' || ch == 'L')) {
+                } else if (ch == 'l' || ch == 'L') {
                     if (len < MaxTokenLength)
                     if (len < MaxTokenLength)
                         ppToken->name[len++] = (char)ch;
                         ppToken->name[len++] = (char)ch;
                     isInt64 = true;
                     isInt64 = true;
 #ifdef AMD_EXTENSIONS
 #ifdef AMD_EXTENSIONS
-                } else if (enableInt16 && (ch == 's' || ch == 'S')) {
+                } else if ((ch == 's' || ch == 'S') &&
+                           pp->parseContext.intermediate.getSource() == EShSourceGlsl) {
                     if (len < MaxTokenLength)
                     if (len < MaxTokenLength)
                         ppToken->name[len++] = (char)ch;
                         ppToken->name[len++] = (char)ch;
                     isInt16 = true;
                     isInt16 = true;
@@ -488,15 +597,29 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
                     ungetch();
                     ungetch();
                 ppToken->name[len] = '\0';
                 ppToken->name[len] = '\0';
 
 
-                if (isInt64) {
+                if (isInt64 && pp->parseContext.intermediate.getSource() == EShSourceGlsl) {
+                    if (pp->ifdepth == 0) {
+                        pp->parseContext.requireProfile(ppToken->loc, ~EEsProfile,
+                                                        "64-bit hexadecimal literal");
+                        pp->parseContext.profileRequires(ppToken->loc, ~EEsProfile, 0,
+                            Num_Int64_Extensions, Int64_Extensions, "64-bit hexadecimal literal");
+                    }
                     ppToken->i64val = ival;
                     ppToken->i64val = ival;
                     return isUnsigned ? PpAtomConstUint64 : PpAtomConstInt64;
                     return isUnsigned ? PpAtomConstUint64 : PpAtomConstInt64;
-#ifdef AMD_EXTENSIONS
                 } else if (isInt16) {
                 } else if (isInt16) {
+                    if (pp->ifdepth == 0) {
+                        if (pp->parseContext.intermediate.getSource() == EShSourceGlsl) {
+                            pp->parseContext.requireProfile(ppToken->loc, ~EEsProfile,
+                                                             "16-bit hexadecimal literal");
+                            pp->parseContext.profileRequires(ppToken->loc, ~EEsProfile, 0,
+                                Num_Int16_Extensions, Int16_Extensions, "16-bit hexadecimal literal");
+                        }
+                    }
                     ppToken->ival = (int)ival;
                     ppToken->ival = (int)ival;
                     return isUnsigned ? PpAtomConstUint16 : PpAtomConstInt16;
                     return isUnsigned ? PpAtomConstUint16 : PpAtomConstInt16;
-#endif
                 } else {
                 } else {
+                    if (ival > 0xffffffffu && !AlreadyComplained)
+                        pp->parseContext.ppError(ppToken->loc, "hexadecimal literal too big", "", "");
                     ppToken->ival = (int)ival;
                     ppToken->ival = (int)ival;
                     return isUnsigned ? PpAtomConstUint : PpAtomConstInt;
                     return isUnsigned ? PpAtomConstUint : PpAtomConstInt;
                 }
                 }
@@ -505,9 +628,7 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
 
 
                 bool isUnsigned = false;
                 bool isUnsigned = false;
                 bool isInt64 = false;
                 bool isInt64 = false;
-#ifdef AMD_EXTENSIONS
                 bool isInt16 = false;
                 bool isInt16 = false;
-#endif
                 bool octalOverflow = false;
                 bool octalOverflow = false;
                 bool nonOctal = false;
                 bool nonOctal = false;
                 ival = 0;
                 ival = 0;
@@ -520,7 +641,7 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
                         pp->parseContext.ppError(ppToken->loc, "numeric literal too long", "", "");
                         pp->parseContext.ppError(ppToken->loc, "numeric literal too long", "", "");
                         AlreadyComplained = 1;
                         AlreadyComplained = 1;
                     }
                     }
-                    if (ival <= 0x1fffffffu || (enableInt64 && ival <= 0x1fffffffffffffffull)) {
+                    if (ival <= 0x1fffffffffffffffull) {
                         ii = ch - '0';
                         ii = ch - '0';
                         ival = (ival << 3) | ii;
                         ival = (ival << 3) | ii;
                     } else
                     } else
@@ -553,33 +674,31 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
                         ppToken->name[len++] = (char)ch;
                         ppToken->name[len++] = (char)ch;
                     isUnsigned = true;
                     isUnsigned = true;
 
 
-                    if (enableInt64) {
-                        int nextCh = getch();
-                        if ((ch == 'u' && nextCh == 'l') || (ch == 'U' && nextCh == 'L')) {
-                            if (len < MaxTokenLength)
-                                ppToken->name[len++] = (char)nextCh;
-                            isInt64 = true;
-                        } else
-                            ungetch();
-                    }
+                    int nextCh = getch();
+                    if (nextCh == 'l' || nextCh == 'L') {
+                        if (len < MaxTokenLength)
+                            ppToken->name[len++] = (char)nextCh;
+                        isInt64 = true;
+                    } else
+                        ungetch();
 
 
 #ifdef AMD_EXTENSIONS
 #ifdef AMD_EXTENSIONS
-                    if (enableInt16) {
-                        int nextCh = getch();
-                        if ((ch == 'u' && nextCh == 's') || (ch == 'U' && nextCh == 'S')) {
-                            if (len < MaxTokenLength)
-                                ppToken->name[len++] = (char)nextCh;
-                            isInt16 = true;
-                        } else
-                            ungetch();
-                    }
+                    nextCh = getch();
+                    if ((nextCh == 's' || nextCh == 'S') && 
+                                pp->parseContext.intermediate.getSource() == EShSourceGlsl) {
+                        if (len < MaxTokenLength)
+                            ppToken->name[len++] = (char)nextCh;
+                        isInt16 = true;
+                    } else
+                        ungetch();
 #endif
 #endif
-                } else if (enableInt64 && (ch == 'l' || ch == 'L')) {
+                } else if (ch == 'l' || ch == 'L') {
                     if (len < MaxTokenLength)
                     if (len < MaxTokenLength)
                         ppToken->name[len++] = (char)ch;
                         ppToken->name[len++] = (char)ch;
                     isInt64 = true;
                     isInt64 = true;
 #ifdef AMD_EXTENSIONS
 #ifdef AMD_EXTENSIONS
-                } else if (enableInt16 && (ch == 's' || ch == 'S')) {
+                } else if ((ch == 's' || ch == 'S') && 
+                                pp->parseContext.intermediate.getSource() == EShSourceGlsl) {
                     if (len < MaxTokenLength)
                     if (len < MaxTokenLength)
                         ppToken->name[len++] = (char)ch;
                         ppToken->name[len++] = (char)ch;
                     isInt16 = true;
                     isInt16 = true;
@@ -588,17 +707,32 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
                     ungetch();
                     ungetch();
                 ppToken->name[len] = '\0';
                 ppToken->name[len] = '\0';
 
 
+                if (!isInt64 && ival > 0xffffffffu)
+                    octalOverflow = true;
+
                 if (octalOverflow)
                 if (octalOverflow)
                     pp->parseContext.ppError(ppToken->loc, "octal literal too big", "", "");
                     pp->parseContext.ppError(ppToken->loc, "octal literal too big", "", "");
 
 
-                if (isInt64) {
+                if (isInt64 && pp->parseContext.intermediate.getSource() == EShSourceGlsl) {
+                    if (pp->ifdepth == 0) {
+                        pp->parseContext.requireProfile(ppToken->loc, ~EEsProfile,
+                                                        "64-bit octal literal");
+                        pp->parseContext.profileRequires(ppToken->loc, ~EEsProfile, 0,
+                            Num_Int64_Extensions, Int64_Extensions, "64-bit octal literal");
+                    }
                     ppToken->i64val = ival;
                     ppToken->i64val = ival;
                     return isUnsigned ? PpAtomConstUint64 : PpAtomConstInt64;
                     return isUnsigned ? PpAtomConstUint64 : PpAtomConstInt64;
-#ifdef AMD_EXTENSIONS
                 } else if (isInt16) {
                 } else if (isInt16) {
+                    if (pp->ifdepth == 0) {
+                        if (pp->parseContext.intermediate.getSource() == EShSourceGlsl) {
+                            pp->parseContext.requireProfile(ppToken->loc, ~EEsProfile,
+                                                            "16-bit octal literal");
+                            pp->parseContext.profileRequires(ppToken->loc, ~EEsProfile, 0,
+                                Num_Int16_Extensions, Int16_Extensions, "16-bit octal literal");
+                        }
+                    }
                     ppToken->ival = (int)ival;
                     ppToken->ival = (int)ival;
                     return isUnsigned ? PpAtomConstUint16 : PpAtomConstInt16;
                     return isUnsigned ? PpAtomConstUint16 : PpAtomConstInt16;
-#endif
                 } else {
                 } else {
                     ppToken->ival = (int)ival;
                     ppToken->ival = (int)ival;
                     return isUnsigned ? PpAtomConstUint : PpAtomConstInt;
                     return isUnsigned ? PpAtomConstUint : PpAtomConstInt;
@@ -625,41 +759,37 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
                 int numericLen = len;
                 int numericLen = len;
                 bool isUnsigned = false;
                 bool isUnsigned = false;
                 bool isInt64 = false;
                 bool isInt64 = false;
-#ifdef AMD_EXTENSIONS
                 bool isInt16 = false;
                 bool isInt16 = false;
-#endif
                 if (ch == 'u' || ch == 'U') {
                 if (ch == 'u' || ch == 'U') {
                     if (len < MaxTokenLength)
                     if (len < MaxTokenLength)
                         ppToken->name[len++] = (char)ch;
                         ppToken->name[len++] = (char)ch;
                     isUnsigned = true;
                     isUnsigned = true;
 
 
-                    if (enableInt64) {
-                        int nextCh = getch();
-                        if ((ch == 'u' && nextCh == 'l') || (ch == 'U' && nextCh == 'L')) {
-                            if (len < MaxTokenLength)
-                                ppToken->name[len++] = (char)nextCh;
-                            isInt64 = true;
-                        } else
-                            ungetch();
-                    }
+                    int nextCh = getch();
+                    if (nextCh == 'l' || nextCh == 'L') {
+                        if (len < MaxTokenLength)
+                            ppToken->name[len++] = (char)nextCh;
+                        isInt64 = true;
+                    } else
+                        ungetch();
 
 
 #ifdef AMD_EXTENSIONS
 #ifdef AMD_EXTENSIONS
-                    if (enableInt16) {
-                        int nextCh = getch();
-                        if ((ch == 'u' && nextCh == 's') || (ch == 'U' && nextCh == 'S')) {
-                            if (len < MaxTokenLength)
-                                ppToken->name[len++] = (char)nextCh;
-                            isInt16 = true;
-                        } else
-                            ungetch();
-                    }
+                    nextCh = getch();
+                    if ((nextCh == 's' || nextCh == 'S') &&
+                                pp->parseContext.intermediate.getSource() == EShSourceGlsl) {
+                        if (len < MaxTokenLength)
+                            ppToken->name[len++] = (char)nextCh;
+                        isInt16 = true;
+                    } else
+                        ungetch();
 #endif
 #endif
-                } else if (enableInt64 && (ch == 'l' || ch == 'L')) {
+                } else if (ch == 'l' || ch == 'L') {
                     if (len < MaxTokenLength)
                     if (len < MaxTokenLength)
                         ppToken->name[len++] = (char)ch;
                         ppToken->name[len++] = (char)ch;
                     isInt64 = true;
                     isInt64 = true;
 #ifdef AMD_EXTENSIONS
 #ifdef AMD_EXTENSIONS
-                } else if (enableInt16 && (ch == 's' || ch == 'S')) {
+                } else if ((ch == 's' || ch == 'S') &&
+                                pp->parseContext.intermediate.getSource() == EShSourceGlsl) {
                     if (len < MaxTokenLength)
                     if (len < MaxTokenLength)
                         ppToken->name[len++] = (char)ch;
                         ppToken->name[len++] = (char)ch;
                     isInt16 = true;
                     isInt16 = true;
@@ -673,19 +803,15 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
                 const unsigned remainderMaxInt = 0xFFFFFFFFu - 10 * oneTenthMaxInt;
                 const unsigned remainderMaxInt = 0xFFFFFFFFu - 10 * oneTenthMaxInt;
                 const unsigned long long oneTenthMaxInt64  = 0xFFFFFFFFFFFFFFFFull / 10;
                 const unsigned long long oneTenthMaxInt64  = 0xFFFFFFFFFFFFFFFFull / 10;
                 const unsigned long long remainderMaxInt64 = 0xFFFFFFFFFFFFFFFFull - 10 * oneTenthMaxInt64;
                 const unsigned long long remainderMaxInt64 = 0xFFFFFFFFFFFFFFFFull - 10 * oneTenthMaxInt64;
-#ifdef AMD_EXTENSIONS
                 const unsigned short oneTenthMaxInt16  = 0xFFFFu / 10;
                 const unsigned short oneTenthMaxInt16  = 0xFFFFu / 10;
                 const unsigned short remainderMaxInt16 = 0xFFFFu - 10 * oneTenthMaxInt16;
                 const unsigned short remainderMaxInt16 = 0xFFFFu - 10 * oneTenthMaxInt16;
-#endif
                 for (int i = 0; i < numericLen; i++) {
                 for (int i = 0; i < numericLen; i++) {
                     ch = ppToken->name[i] - '0';
                     ch = ppToken->name[i] - '0';
                     bool overflow = false;
                     bool overflow = false;
                     if (isInt64)
                     if (isInt64)
                         overflow = (ival > oneTenthMaxInt64 || (ival == oneTenthMaxInt64 && (unsigned long long)ch > remainderMaxInt64));
                         overflow = (ival > oneTenthMaxInt64 || (ival == oneTenthMaxInt64 && (unsigned long long)ch > remainderMaxInt64));
-#ifdef AMD_EXTENSIONS
                     else if (isInt16)
                     else if (isInt16)
                         overflow = (ival > oneTenthMaxInt16 || (ival == oneTenthMaxInt16 && (unsigned short)ch > remainderMaxInt16));
                         overflow = (ival > oneTenthMaxInt16 || (ival == oneTenthMaxInt16 && (unsigned short)ch > remainderMaxInt16));
-#endif
                     else
                     else
                         overflow = (ival > oneTenthMaxInt || (ival == oneTenthMaxInt && (unsigned)ch > remainderMaxInt));
                         overflow = (ival > oneTenthMaxInt || (ival == oneTenthMaxInt && (unsigned)ch > remainderMaxInt));
                     if (overflow) {
                     if (overflow) {
@@ -696,14 +822,24 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
                         ival = ival * 10 + ch;
                         ival = ival * 10 + ch;
                 }
                 }
 
 
-                if (isInt64) {
+                if (isInt64 && pp->parseContext.intermediate.getSource() == EShSourceGlsl) {
+                    if (pp->ifdepth == 0) {
+                        pp->parseContext.requireProfile(ppToken->loc, ~EEsProfile,
+                                                        "64-bit literal");
+                        pp->parseContext.profileRequires(ppToken->loc, ~EEsProfile, 0,
+                            Num_Int64_Extensions, Int64_Extensions, "64-bit literal");
+                    }
                     ppToken->i64val = ival;
                     ppToken->i64val = ival;
                     return isUnsigned ? PpAtomConstUint64 : PpAtomConstInt64;
                     return isUnsigned ? PpAtomConstUint64 : PpAtomConstInt64;
-#ifdef AMD_EXTENSIONS
                 } else if (isInt16) {
                 } else if (isInt16) {
+                    if (pp->ifdepth == 0 && pp->parseContext.intermediate.getSource() == EShSourceGlsl) {
+                        pp->parseContext.requireProfile(ppToken->loc, ~EEsProfile,
+                                                        "16-bit  literal");
+                        pp->parseContext.profileRequires(ppToken->loc, ~EEsProfile, 0,
+                            Num_Int16_Extensions, Int16_Extensions, "16-bit literal");
+                    }
                     ppToken->ival = (int)ival;
                     ppToken->ival = (int)ival;
                     return isUnsigned ? PpAtomConstUint16 : PpAtomConstInt16;
                     return isUnsigned ? PpAtomConstUint16 : PpAtomConstInt16;
-#endif
                 } else {
                 } else {
                     ppToken->ival = (int)ival;
                     ppToken->ival = (int)ival;
                     return isUnsigned ? PpAtomConstUint : PpAtomConstInt;
                     return isUnsigned ? PpAtomConstUint : PpAtomConstInt;
@@ -943,8 +1079,17 @@ int TPpContext::tokenize(TPpToken& ppToken)
             continue;
             continue;
 
 
         // expand macros
         // expand macros
-        if (token == PpAtomIdentifier && MacroExpand(&ppToken, false, true) != 0)
-            continue;
+        if (token == PpAtomIdentifier) {
+            switch (MacroExpand(&ppToken, false, true)) {
+            case MacroExpandNotStarted:
+                break;
+            case MacroExpandError:
+                return EndOfInput;
+            case MacroExpandStarted:
+            case MacroExpandUndef:
+                continue;
+            }
+        }
 
 
         switch (token) {
         switch (token) {
         case PpAtomIdentifier:
         case PpAtomIdentifier:
@@ -953,19 +1098,15 @@ int TPpContext::tokenize(TPpToken& ppToken)
         case PpAtomConstFloat:
         case PpAtomConstFloat:
         case PpAtomConstInt64:
         case PpAtomConstInt64:
         case PpAtomConstUint64:
         case PpAtomConstUint64:
-#ifdef AMD_EXTENSIONS
         case PpAtomConstInt16:
         case PpAtomConstInt16:
         case PpAtomConstUint16:
         case PpAtomConstUint16:
-#endif
         case PpAtomConstDouble:
         case PpAtomConstDouble:
-#ifdef AMD_EXTENSIONS
         case PpAtomConstFloat16:
         case PpAtomConstFloat16:
-#endif
             if (ppToken.name[0] == '\0')
             if (ppToken.name[0] == '\0')
                 continue;
                 continue;
             break;
             break;
         case PpAtomConstString:
         case PpAtomConstString:
-            if (parseContext.intermediate.getSource() != EShSourceHlsl) {
+            if (ifdepth == 0 && parseContext.intermediate.getSource() != EShSourceHlsl) {
                 // HLSL allows string literals.
                 // HLSL allows string literals.
                 parseContext.ppError(ppToken.loc, "string literals not supported", "\"\"", "");
                 parseContext.ppError(ppToken.loc, "string literals not supported", "\"\"", "");
                 continue;
                 continue;

+ 94 - 119
src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpTokens.cpp

@@ -1,6 +1,8 @@
 //
 //
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2013 LunarG, Inc.
 // Copyright (C) 2013 LunarG, Inc.
+// Copyright (C) 2015-2018 Google, Inc.
+//
 // All rights reserved.
 // All rights reserved.
 //
 //
 // Redistribution and use in source and binary forms, with or without
 // Redistribution and use in source and binary forms, with or without
@@ -97,6 +99,56 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 namespace glslang {
 namespace glslang {
 
 
+
+namespace {
+
+    // When recording (and playing back) should the backing name string
+    // be saved (restored)?
+    bool SaveName(int atom)
+    {
+        switch (atom) {
+        case PpAtomIdentifier:
+        case PpAtomConstString:
+        case PpAtomConstInt:
+        case PpAtomConstUint:
+        case PpAtomConstInt64:
+        case PpAtomConstUint64:
+    #ifdef AMD_EXTENSIONS
+        case PpAtomConstInt16:
+        case PpAtomConstUint16:
+    #endif
+        case PpAtomConstFloat:
+        case PpAtomConstDouble:
+        case PpAtomConstFloat16:
+            return true;
+        default:
+            return false;
+        }
+    }
+
+    // When recording (and playing back) should the numeric value
+    // be saved (restored)?
+    bool SaveValue(int atom)
+    {
+        switch (atom) {
+        case PpAtomConstInt:
+        case PpAtomConstUint:
+        case PpAtomConstInt64:
+        case PpAtomConstUint64:
+    #ifdef AMD_EXTENSIONS
+        case PpAtomConstInt16:
+        case PpAtomConstUint16:
+    #endif
+        case PpAtomConstFloat:
+        case PpAtomConstDouble:
+        case PpAtomConstFloat16:
+            return true;
+        default:
+            return false;
+        }
+    }
+}
+
 // push onto back of stream
 // push onto back of stream
 void TPpContext::TokenStream::putSubtoken(char subtoken)
 void TPpContext::TokenStream::putSubtoken(char subtoken)
 {
 {
@@ -121,44 +173,25 @@ void TPpContext::TokenStream::ungetSubtoken()
 
 
 // Add a complete token (including backing string) to the end of a list
 // Add a complete token (including backing string) to the end of a list
 // for later playback.
 // for later playback.
-void TPpContext::TokenStream::putToken(int token, TPpToken* ppToken)
+void TPpContext::TokenStream::putToken(int atom, TPpToken* ppToken)
 {
 {
-    const char* s;
-    char* str = NULL;
+    // save the atom
+    assert((atom & ~0xff) == 0);
+    putSubtoken(static_cast<char>(atom));
 
 
-    assert((token & ~0xff) == 0);
-    putSubtoken(static_cast<char>(token));
-
-    switch (token) {
-    case PpAtomIdentifier:
-    case PpAtomConstString:
-        s = ppToken->name;
+    // save the backing name string
+    if (SaveName(atom)) {
+        const char* s = ppToken->name;
         while (*s)
         while (*s)
             putSubtoken(*s++);
             putSubtoken(*s++);
         putSubtoken(0);
         putSubtoken(0);
-        break;
-    case PpAtomConstInt:
-    case PpAtomConstUint:
-    case PpAtomConstInt64:
-    case PpAtomConstUint64:
-#ifdef AMD_EXTENSIONS
-    case PpAtomConstInt16:
-    case PpAtomConstUint16:
-#endif
-    case PpAtomConstFloat:
-    case PpAtomConstDouble:
-#ifdef AMD_EXTENSIONS
-    case PpAtomConstFloat16:
-#endif
-        str = ppToken->name;
-        while (*str) {
-            putSubtoken(*str);
-            str++;
-        }
-        putSubtoken(0);
-        break;
-    default:
-        break;
+    }
+
+    // save the numeric value
+    if (SaveValue(atom)) {
+        const char* n = reinterpret_cast<const char*>(&ppToken->i64val);
+        for (size_t i = 0; i < sizeof(ppToken->i64val); ++i)
+            putSubtoken(*n++);
     }
     }
 }
 }
 
 
@@ -166,40 +199,19 @@ void TPpContext::TokenStream::putToken(int token, TPpToken* ppToken)
 // (Not the source stream, but a stream used to hold a tokenized macro).
 // (Not the source stream, but a stream used to hold a tokenized macro).
 int TPpContext::TokenStream::getToken(TParseContextBase& parseContext, TPpToken *ppToken)
 int TPpContext::TokenStream::getToken(TParseContextBase& parseContext, TPpToken *ppToken)
 {
 {
-    int len;
-    int ch;
+    // get the atom
+    int atom = getSubtoken();
+    if (atom == EndOfInput)
+        return atom;
 
 
-    int subtoken = getSubtoken();
+    // init the token
+    ppToken->clear();
     ppToken->loc = parseContext.getCurrentLoc();
     ppToken->loc = parseContext.getCurrentLoc();
-    switch (subtoken) {
-    case '#':
-        // Check for ##, unless the current # is the last character
-        if (current < data.size()) {
-            if (getSubtoken() == '#') {
-                parseContext.requireProfile(ppToken->loc, ~EEsProfile, "token pasting (##)");
-                parseContext.profileRequires(ppToken->loc, ~EEsProfile, 130, 0, "token pasting (##)");
-                subtoken = PpAtomPaste;
-            } else
-                ungetSubtoken();
-        }
-        break;
-    case PpAtomConstString:
-    case PpAtomIdentifier:
-    case PpAtomConstFloat:
-    case PpAtomConstDouble:
-#ifdef AMD_EXTENSIONS
-    case PpAtomConstFloat16:
-#endif
-    case PpAtomConstInt:
-    case PpAtomConstUint:
-    case PpAtomConstInt64:
-    case PpAtomConstUint64:
-#ifdef AMD_EXTENSIONS
-    case PpAtomConstInt16:
-    case PpAtomConstUint16:
-#endif
-        len = 0;
-        ch = getSubtoken();
+
+    // get the backing name string
+    if (SaveName(atom)) {
+        int ch = getSubtoken();
+        int len = 0;
         while (ch != 0 && ch != EndOfInput) {
         while (ch != 0 && ch != EndOfInput) {
             if (len < MaxTokenLength) {
             if (len < MaxTokenLength) {
                 ppToken->name[len] = (char)ch;
                 ppToken->name[len] = (char)ch;
@@ -211,65 +223,28 @@ int TPpContext::TokenStream::getToken(TParseContextBase& parseContext, TPpToken
             }
             }
         }
         }
         ppToken->name[len] = 0;
         ppToken->name[len] = 0;
+    }
 
 
-        switch (subtoken) {
-        case PpAtomIdentifier:
-            break;
-        case PpAtomConstString:
-            break;
-        case PpAtomConstFloat:
-        case PpAtomConstDouble:
-#ifdef AMD_EXTENSIONS
-        case PpAtomConstFloat16:
-#endif
-            ppToken->dval = atof(ppToken->name);
-            break;
-        case PpAtomConstInt:
-#ifdef AMD_EXTENSIONS
-        case PpAtomConstInt16:
-#endif
-            if (len > 0 && ppToken->name[0] == '0') {
-                if (len > 1 && (ppToken->name[1] == 'x' || ppToken->name[1] == 'X'))
-                    ppToken->ival = (int)strtol(ppToken->name, 0, 16);
-                else
-                    ppToken->ival = (int)strtol(ppToken->name, 0, 8);
-            } else
-                ppToken->ival = atoi(ppToken->name);
-            break;
-        case PpAtomConstUint:
-#ifdef AMD_EXTENSIONS
-        case PpAtomConstUint16:
-#endif
-            if (len > 0 && ppToken->name[0] == '0') {
-                if (len > 1 && (ppToken->name[1] == 'x' || ppToken->name[1] == 'X'))
-                    ppToken->ival = (int)strtoul(ppToken->name, 0, 16);
-                else
-                    ppToken->ival = (int)strtoul(ppToken->name, 0, 8);
-            } else
-                ppToken->ival = (int)strtoul(ppToken->name, 0, 10);
-            break;
-        case PpAtomConstInt64:
-            if (len > 0 && ppToken->name[0] == '0') {
-                if (len > 1 && (ppToken->name[1] == 'x' || ppToken->name[1] == 'X'))
-                    ppToken->i64val = strtoll(ppToken->name, nullptr, 16);
-                else
-                    ppToken->i64val = strtoll(ppToken->name, nullptr, 8);
-            } else
-                ppToken->i64val = atoll(ppToken->name);
-            break;
-        case PpAtomConstUint64:
-            if (len > 0 && ppToken->name[0] == '0') {
-                if (len > 1 && (ppToken->name[1] == 'x' || ppToken->name[1] == 'X'))
-                    ppToken->i64val = (long long)strtoull(ppToken->name, nullptr, 16);
-                else
-                    ppToken->i64val = (long long)strtoull(ppToken->name, nullptr, 8);
+    // Check for ##, unless the current # is the last character
+    if (atom == '#') {
+        if (current < data.size()) {
+            if (getSubtoken() == '#') {
+                parseContext.requireProfile(ppToken->loc, ~EEsProfile, "token pasting (##)");
+                parseContext.profileRequires(ppToken->loc, ~EEsProfile, 130, 0, "token pasting (##)");
+                atom = PpAtomPaste;
             } else
             } else
-                ppToken->i64val = (long long)strtoull(ppToken->name, 0, 10);
-            break;
+                ungetSubtoken();
         }
         }
     }
     }
 
 
-    return subtoken;
+    // get the numeric value
+    if (SaveValue(atom)) {
+        char* n = reinterpret_cast<char*>(&ppToken->i64val);
+        for (size_t i = 0; i < sizeof(ppToken->i64val); ++i)
+            *n++ = (char)getSubtoken();
+    }
+
+    return atom;
 }
 }
 
 
 // We are pasting if
 // We are pasting if

+ 0 - 2
src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpTokens.h

@@ -127,10 +127,8 @@ enum EFixedAtoms {
     PpAtomConstUint,
     PpAtomConstUint,
     PpAtomConstInt64,
     PpAtomConstInt64,
     PpAtomConstUint64,
     PpAtomConstUint64,
-#ifdef AMD_EXTENSIONS
     PpAtomConstInt16,
     PpAtomConstInt16,
     PpAtomConstUint16,
     PpAtomConstUint16,
-#endif
     PpAtomConstFloat,
     PpAtomConstFloat,
     PpAtomConstDouble,
     PpAtomConstDouble,
     PpAtomConstFloat16,
     PpAtomConstFloat16,

+ 70 - 11
src/libraries/glslang/glslang/MachineIndependent/reflection.cpp

@@ -131,11 +131,11 @@ public:
         for (int m = 0; m <= index; ++m) {
         for (int m = 0; m <= index; ++m) {
             // modify just the children's view of matrix layout, if there is one for this member
             // modify just the children's view of matrix layout, if there is one for this member
             TLayoutMatrix subMatrixLayout = memberList[m].type->getQualifier().layoutMatrix;
             TLayoutMatrix subMatrixLayout = memberList[m].type->getQualifier().layoutMatrix;
-            int memberAlignment = intermediate.getBaseAlignment(*memberList[m].type, memberSize, dummyStride,
-                                                                type.getQualifier().layoutPacking == ElpStd140,
-                                                                subMatrixLayout != ElmNone
-                                                                    ? subMatrixLayout == ElmRowMajor
-                                                                    : type.getQualifier().layoutMatrix == ElmRowMajor);
+            int memberAlignment = intermediate.getMemberAlignment(*memberList[m].type, memberSize, dummyStride,
+                                                                  type.getQualifier().layoutPacking,
+                                                                  subMatrixLayout != ElmNone
+                                                                      ? subMatrixLayout == ElmRowMajor
+                                                                      : type.getQualifier().layoutMatrix == ElmRowMajor);
             RoundToPow2(offset, memberAlignment);
             RoundToPow2(offset, memberAlignment);
             if (m < index)
             if (m < index)
                 offset += memberSize;
                 offset += memberSize;
@@ -154,9 +154,9 @@ public:
 
 
         int lastMemberSize;
         int lastMemberSize;
         int dummyStride;
         int dummyStride;
-        intermediate.getBaseAlignment(*memberList[lastIndex].type, lastMemberSize, dummyStride,
-                                      blockType.getQualifier().layoutPacking == ElpStd140,
-                                      blockType.getQualifier().layoutMatrix == ElmRowMajor);
+        intermediate.getMemberAlignment(*memberList[lastIndex].type, lastMemberSize, dummyStride,
+                                        blockType.getQualifier().layoutPacking,
+                                        blockType.getQualifier().layoutMatrix == ElmRowMajor);
 
 
         return lastOffset + lastMemberSize;
         return lastOffset + lastMemberSize;
     }
     }
@@ -415,6 +415,36 @@ public:
                 case EsdBuffer:
                 case EsdBuffer:
                     return GL_SAMPLER_BUFFER;
                     return GL_SAMPLER_BUFFER;
                 }
                 }
+#ifdef AMD_EXTENSIONS
+            case EbtFloat16:
+                switch ((int)sampler.dim) {
+                case Esd1D:
+                    switch ((int)sampler.shadow) {
+                    case false: return sampler.arrayed ? GL_FLOAT16_SAMPLER_1D_ARRAY_AMD : GL_FLOAT16_SAMPLER_1D_AMD;
+                    case true:  return sampler.arrayed ? GL_FLOAT16_SAMPLER_1D_ARRAY_SHADOW_AMD : GL_FLOAT16_SAMPLER_1D_SHADOW_AMD;
+                    }
+                case Esd2D:
+                    switch ((int)sampler.ms) {
+                    case false:
+                        switch ((int)sampler.shadow) {
+                        case false: return sampler.arrayed ? GL_FLOAT16_SAMPLER_2D_ARRAY_AMD : GL_FLOAT16_SAMPLER_2D_AMD;
+                        case true:  return sampler.arrayed ? GL_FLOAT16_SAMPLER_2D_ARRAY_SHADOW_AMD : GL_FLOAT16_SAMPLER_2D_SHADOW_AMD;
+                        }
+                    case true:      return sampler.arrayed ? GL_FLOAT16_SAMPLER_2D_MULTISAMPLE_ARRAY_AMD : GL_FLOAT16_SAMPLER_2D_MULTISAMPLE_AMD;
+                    }
+                case Esd3D:
+                    return GL_FLOAT16_SAMPLER_3D_AMD;
+                case EsdCube:
+                    switch ((int)sampler.shadow) {
+                    case false: return sampler.arrayed ? GL_FLOAT16_SAMPLER_CUBE_MAP_ARRAY_AMD : GL_FLOAT16_SAMPLER_CUBE_AMD;
+                    case true:  return sampler.arrayed ? GL_FLOAT16_SAMPLER_CUBE_MAP_ARRAY_SHADOW_AMD : GL_FLOAT16_SAMPLER_CUBE_SHADOW_AMD;
+                    }
+                case EsdRect:
+                    return sampler.shadow ? GL_FLOAT16_SAMPLER_2D_RECT_SHADOW_AMD : GL_FLOAT16_SAMPLER_2D_RECT_AMD;
+                case EsdBuffer:
+                    return GL_FLOAT16_SAMPLER_BUFFER_AMD;
+                }
+#endif
             case EbtInt:
             case EbtInt:
                 switch ((int)sampler.dim) {
                 switch ((int)sampler.dim) {
                 case Esd1D:
                 case Esd1D:
@@ -477,6 +507,26 @@ public:
                 case EsdBuffer:
                 case EsdBuffer:
                     return GL_IMAGE_BUFFER;
                     return GL_IMAGE_BUFFER;
                 }
                 }
+#ifdef AMD_EXTENSIONS
+            case EbtFloat16:
+                switch ((int)sampler.dim) {
+                case Esd1D:
+                    return sampler.arrayed ? GL_FLOAT16_IMAGE_1D_ARRAY_AMD : GL_FLOAT16_IMAGE_1D_AMD;
+                case Esd2D:
+                    switch ((int)sampler.ms) {
+                    case false:     return sampler.arrayed ? GL_FLOAT16_IMAGE_2D_ARRAY_AMD : GL_FLOAT16_IMAGE_2D_AMD;
+                    case true:      return sampler.arrayed ? GL_FLOAT16_IMAGE_2D_MULTISAMPLE_ARRAY_AMD : GL_FLOAT16_IMAGE_2D_MULTISAMPLE_AMD;
+                    }
+                case Esd3D:
+                    return GL_FLOAT16_IMAGE_3D_AMD;
+                case EsdCube:
+                    return sampler.arrayed ? GL_FLOAT16_IMAGE_CUBE_MAP_ARRAY_AMD : GL_FLOAT16_IMAGE_CUBE_AMD;
+                case EsdRect:
+                    return GL_FLOAT16_IMAGE_2D_RECT_AMD;
+                case EsdBuffer:
+                    return GL_FLOAT16_IMAGE_BUFFER_AMD;
+                }
+#endif
             case EbtInt:
             case EbtInt:
                 switch ((int)sampler.dim) {
                 switch ((int)sampler.dim) {
                 case Esd1D:
                 case Esd1D:
@@ -716,11 +766,11 @@ void TReflection::buildAttributeReflection(EShLanguage stage, const TIntermediat
 }
 }
 
 
 // build counter block index associations for buffers
 // build counter block index associations for buffers
-void TReflection::buildCounterIndices()
+void TReflection::buildCounterIndices(const TIntermediate& intermediate)
 {
 {
     // search for ones that have counters
     // search for ones that have counters
     for (int i = 0; i < int(indexToUniformBlock.size()); ++i) {
     for (int i = 0; i < int(indexToUniformBlock.size()); ++i) {
-        const TString counterName(indexToUniformBlock[i].name + "@count");
+        const TString counterName(intermediate.addCounterBufferName(indexToUniformBlock[i].name));
         const int index = getIndex(counterName);
         const int index = getIndex(counterName);
 
 
         if (index >= 0)
         if (index >= 0)
@@ -728,6 +778,14 @@ void TReflection::buildCounterIndices()
     }
     }
 }
 }
 
 
+// build Shader Stages mask for all uniforms
+void TReflection::buildUniformStageMask(const TIntermediate& intermediate)
+{
+    for (int i = 0; i < int(indexToUniform.size()); ++i) {
+        indexToUniform[i].stages = static_cast<EShLanguageMask>(indexToUniform[i].stages | 1 << intermediate.getStage());
+    }
+}
+
 // Merge live symbols from 'intermediate' into the existing reflection database.
 // Merge live symbols from 'intermediate' into the existing reflection database.
 //
 //
 // Returns false if the input is too malformed to do this.
 // Returns false if the input is too malformed to do this.
@@ -752,7 +810,8 @@ bool TReflection::addStage(EShLanguage stage, const TIntermediate& intermediate)
         function->traverse(&it);
         function->traverse(&it);
     }
     }
 
 
-    buildCounterIndices();
+    buildCounterIndices(intermediate);
+    buildUniformStageMask(intermediate);
 
 
     return true;
     return true;
 }
 }

+ 7 - 5
src/libraries/glslang/glslang/MachineIndependent/reflection.h

@@ -57,9 +57,9 @@ class TObjectReflection {
 public:
 public:
     TObjectReflection(const TString& pName, const TType& pType, int pOffset, int pGLDefineType, int pSize, int pIndex) :
     TObjectReflection(const TString& pName, const TType& pType, int pOffset, int pGLDefineType, int pSize, int pIndex) :
         name(pName), offset(pOffset),
         name(pName), offset(pOffset),
-        glDefineType(pGLDefineType), size(pSize), index(pIndex), counterIndex(-1), type(pType.clone()) { }
+        glDefineType(pGLDefineType), size(pSize), index(pIndex), counterIndex(-1), stages(EShLanguageMask(0)), type(pType.clone()) { }
 
 
-    const TType* const getType() const { return type; }
+    const TType* getType() const { return type; }
     int getBinding() const
     int getBinding() const
     {
     {
         if (type == nullptr || !type->getQualifier().hasBinding())
         if (type == nullptr || !type->getQualifier().hasBinding())
@@ -68,8 +68,8 @@ public:
     }
     }
     void dump() const
     void dump() const
     {
     {
-        printf("%s: offset %d, type %x, size %d, index %d, binding %d",
-               name.c_str(), offset, glDefineType, size, index, getBinding() );
+        printf("%s: offset %d, type %x, size %d, index %d, binding %d, stages %d",
+               name.c_str(), offset, glDefineType, size, index, getBinding(), stages );
 
 
         if (counterIndex != -1)
         if (counterIndex != -1)
             printf(", counter %d", counterIndex);
             printf(", counter %d", counterIndex);
@@ -84,6 +84,7 @@ public:
     int size;         // data size in bytes for a block, array size for a (non-block) object that's an array
     int size;         // data size in bytes for a block, array size for a (non-block) object that's an array
     int index;
     int index;
     int counterIndex;
     int counterIndex;
+    EShLanguageMask stages;
 
 
 protected:
 protected:
     TObjectReflection() : offset(-1), glDefineType(-1), size(-1), index(-1), type(nullptr) { }
     TObjectReflection() : offset(-1), glDefineType(-1), size(-1), index(-1), type(nullptr) { }
@@ -156,7 +157,8 @@ public:
 protected:
 protected:
     friend class glslang::TReflectionTraverser;
     friend class glslang::TReflectionTraverser;
 
 
-    void buildCounterIndices();
+    void buildCounterIndices(const TIntermediate&);
+    void buildUniformStageMask(const TIntermediate& intermediate);
     void buildAttributeReflection(EShLanguage, const TIntermediate&);
     void buildAttributeReflection(EShLanguage, const TIntermediate&);
 
 
     // Need a TString hash: typedef std::unordered_map<TString, int> TNameToIndex;
     // Need a TString hash: typedef std::unordered_map<TString, int> TNameToIndex;

+ 69 - 11
src/libraries/glslang/glslang/Public/ShaderLang.h

@@ -1,6 +1,7 @@
 //
 //
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2013-2016 LunarG, Inc.
 // Copyright (C) 2013-2016 LunarG, Inc.
+// Copyright (C) 2015-2018 Google, Inc.
 //
 //
 // All rights reserved.
 // All rights reserved.
 //
 //
@@ -67,6 +68,11 @@
     extern "C" {
     extern "C" {
 #endif
 #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 11
+
 //
 //
 // Call before doing any other compiler/linker operations.
 // Call before doing any other compiler/linker operations.
 //
 //
@@ -89,6 +95,14 @@ typedef enum {
     EShLangGeometry,
     EShLangGeometry,
     EShLangFragment,
     EShLangFragment,
     EShLangCompute,
     EShLangCompute,
+    EShLangRayGenNV,
+    EShLangIntersectNV,
+    EShLangAnyHitNV,
+    EShLangClosestHitNV,
+    EShLangMissNV,
+    EShLangCallableNV,
+    EShLangTaskNV,
+    EShLangMeshNV,
     EShLangCount,
     EShLangCount,
 } EShLanguage;         // would be better as stage, but this is ancient now
 } EShLanguage;         // would be better as stage, but this is ancient now
 
 
@@ -99,6 +113,14 @@ typedef enum {
     EShLangGeometryMask       = (1 << EShLangGeometry),
     EShLangGeometryMask       = (1 << EShLangGeometry),
     EShLangFragmentMask       = (1 << EShLangFragment),
     EShLangFragmentMask       = (1 << EShLangFragment),
     EShLangComputeMask        = (1 << EShLangCompute),
     EShLangComputeMask        = (1 << EShLangCompute),
+    EShLangRayGenNVMask       = (1 << EShLangRayGenNV),
+    EShLangIntersectNVMask    = (1 << EShLangIntersectNV),
+    EShLangAnyHitNVMask       = (1 << EShLangAnyHitNV),
+    EShLangClosestHitNVMask   = (1 << EShLangClosestHitNV),
+    EShLangMissNVMask         = (1 << EShLangMissNV),
+    EShLangCallableNVMask     = (1 << EShLangCallableNV),
+    EShLangTaskNVMask         = (1 << EShLangTaskNV),
+    EShLangMeshNVMask         = (1 << EShLangMeshNV),
 } EShLanguageMask;
 } EShLanguageMask;
 
 
 namespace glslang {
 namespace glslang {
@@ -119,9 +141,26 @@ typedef enum {
 
 
 typedef enum {
 typedef enum {
     EShTargetNone,
     EShTargetNone,
-    EshTargetSpv,
+    EShTargetSpv,                 // preferred spelling
+    EshTargetSpv = EShTargetSpv,  // legacy spelling
 } EShTargetLanguage;
 } EShTargetLanguage;
 
 
+typedef enum {
+    EShTargetVulkan_1_0 = (1 << 22),
+    EShTargetVulkan_1_1 = (1 << 22) | (1 << 12),
+    EShTargetOpenGL_450 = 450,
+} EShTargetClientVersion;
+
+typedef EShTargetClientVersion EshTargetClientVersion;
+
+typedef enum {
+    EShTargetSpv_1_0 = (1 << 16),
+    EShTargetSpv_1_1 = (1 << 16) | (1 << 8),
+    EShTargetSpv_1_2 = (1 << 16) | (2 << 8),
+    EShTargetSpv_1_3 = (1 << 16) | (3 << 8),
+    EShTargetSpv_1_4 = (1 << 16) | (4 << 8),
+} EShTargetLanguageVersion;
+
 struct TInputLanguage {
 struct TInputLanguage {
     EShSource languageFamily; // redundant information with other input, this one overrides when not EShSourceNone
     EShSource languageFamily; // redundant information with other input, this one overrides when not EShSourceNone
     EShLanguage stage;        // redundant information with other input, this one overrides when not EShSourceNone
     EShLanguage stage;        // redundant information with other input, this one overrides when not EShSourceNone
@@ -131,12 +170,13 @@ struct TInputLanguage {
 
 
 struct TClient {
 struct TClient {
     EShClient client;
     EShClient client;
-    int version;              // version of client itself (not the client's input dialect)
+    EShTargetClientVersion version;   // version of client itself (not the client's input dialect)
 };
 };
 
 
 struct TTarget {
 struct TTarget {
     EShTargetLanguage language;
     EShTargetLanguage language;
-    unsigned int version;     // the version to target, if SPIR-V, defined by "word 1" of the SPIR-V binary header
+    EShTargetLanguageVersion version; // version to target, if SPIR-V, defined by "word 1" of the SPIR-V header
+    bool hlslFunctionality1;          // can target hlsl_functionality1 extension(s)
 };
 };
 
 
 // All source/client/target versions and settings.
 // All source/client/target versions and settings.
@@ -194,6 +234,9 @@ enum EShMessages {
     EShMsgKeepUncalled     = (1 << 8),  // for testing, don't eliminate uncalled functions
     EShMsgKeepUncalled     = (1 << 8),  // for testing, don't eliminate uncalled functions
     EShMsgHlslOffsets      = (1 << 9),  // allow block offsets to follow HLSL rules instead of GLSL rules
     EShMsgHlslOffsets      = (1 << 9),  // allow block offsets to follow HLSL rules instead of GLSL rules
     EShMsgDebugInfo        = (1 << 10), // save debug information
     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)
 };
 };
 
 
 //
 //
@@ -334,11 +377,15 @@ enum TResourceType {
     EResCount
     EResCount
 };
 };
 
 
-// Make one TShader per shader that you will link into a program.  Then provide
-// the shader through setStrings() or setStringsWithLengths(), then call parse(),
-// then query the info logs.
-// Optionally use setPreamble() to set a special shader string that will be
-// processed before all others but won't affect the validity of #version.
+// 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
+//  - call parse(): source language and target environment must be selected
+//    either by correct setting of EShMessages sent to parse(), or by
+//    explicitly calling setEnv*()
+//  - query the info logs
 //
 //
 // N.B.: Does not yet support having the same TShader instance being linked into
 // N.B.: Does not yet support having the same TShader instance being linked into
 // multiple programs.
 // multiple programs.
@@ -371,13 +418,18 @@ public:
     void setResourceSetBinding(const std::vector<std::string>& base);
     void setResourceSetBinding(const std::vector<std::string>& base);
     void setAutoMapBindings(bool map);
     void setAutoMapBindings(bool map);
     void setAutoMapLocations(bool map);
     void setAutoMapLocations(bool map);
+    void addUniformLocationOverride(const char* name, int loc);
+    void setUniformLocationBase(int base);
     void setInvertY(bool invert);
     void setInvertY(bool invert);
     void setHlslIoMapping(bool hlslIoMap);
     void setHlslIoMapping(bool hlslIoMap);
     void setFlattenUniformArrays(bool flatten);
     void setFlattenUniformArrays(bool flatten);
     void setNoStorageFormat(bool useUnknownFormat);
     void setNoStorageFormat(bool useUnknownFormat);
     void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode);
     void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode);
 
 
-    // For setting up the environment (initialized in the constructor):
+    // For setting up the environment (cleared to nothingness in the constructor).
+    // These must be called so that parsing is done for the right source language and
+    // target environment, either indirectly through TranslateEnvironment() based on
+    // EShMessages et. al., or directly by the user.
     void setEnvInput(EShSource lang, EShLanguage envStage, EShClient client, int version)
     void setEnvInput(EShSource lang, EShLanguage envStage, EShClient client, int version)
     {
     {
         environment.input.languageFamily = lang;
         environment.input.languageFamily = lang;
@@ -385,16 +437,18 @@ public:
         environment.input.dialect = client;
         environment.input.dialect = client;
         environment.input.dialectVersion = version;
         environment.input.dialectVersion = version;
     }
     }
-    void setEnvClient(EShClient client, int version)
+    void setEnvClient(EShClient client, EShTargetClientVersion version)
     {
     {
         environment.client.client = client;
         environment.client.client = client;
         environment.client.version = version;
         environment.client.version = version;
     }
     }
-    void setEnvTarget(EShTargetLanguage lang, unsigned int version)
+    void setEnvTarget(EShTargetLanguage lang, EShTargetLanguageVersion version)
     {
     {
         environment.target.language = lang;
         environment.target.language = lang;
         environment.target.version = version;
         environment.target.version = version;
     }
     }
+    void setEnvTargetHlslFunctionality1() { environment.target.hlslFunctionality1 = true; }
+    bool getEnvTargetHlslFunctionality1() const { return environment.target.hlslFunctionality1; }
 
 
     // Interface to #include handlers.
     // Interface to #include handlers.
     //
     //
@@ -501,6 +555,8 @@ public:
         return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages, includer);
         return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages, includer);
     }
     }
 
 
+    // 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,
     bool preprocess(const TBuiltInResource* builtInResources,
                     int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile,
                     int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile,
                     bool forwardCompatible, EShMessages message, std::string* outputString,
                     bool forwardCompatible, EShMessages message, std::string* outputString,
@@ -640,6 +696,8 @@ public:
     int getUniformBlockSize(int blockIndex) const;         // can be used for glGetActiveUniformBlockiv(UNIFORM_BLOCK_DATA_SIZE)
     int getUniformBlockSize(int blockIndex) const;         // can be used for glGetActiveUniformBlockiv(UNIFORM_BLOCK_DATA_SIZE)
     int getUniformIndex(const char* name) const;           // can be used for glGetUniformIndices()
     int getUniformIndex(const char* name) const;           // can be used for glGetUniformIndices()
     int getUniformBinding(int index) const;                // returns the binding number
     int getUniformBinding(int index) const;                // returns the binding number
+    EShLanguageMask getUniformStages(int index) const;     // returns Shaders Stages where a Uniform is present
+    int getUniformBlockBinding(int index) const;           // returns the block binding number
     int getUniformBlockIndex(int index) const;             // can be used for glGetActiveUniformsiv(GL_UNIFORM_BLOCK_INDEX)
     int getUniformBlockIndex(int index) const;             // can be used for glGetActiveUniformsiv(GL_UNIFORM_BLOCK_INDEX)
     int getUniformBlockCounterIndex(int index) const;      // returns block index of associated counter.
     int getUniformBlockCounterIndex(int index) const;      // returns block index of associated counter.
     int getUniformType(int index) const;                   // can be used for glGetActiveUniformsiv(GL_UNIFORM_TYPE)
     int getUniformType(int index) const;                   // can be used for glGetActiveUniformsiv(GL_UNIFORM_TYPE)

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

@@ -109,6 +109,15 @@ static const TBuiltInResource defaultTBuiltInResource = {
 	/* .MaxCullDistances = */ 8,
 	/* .MaxCullDistances = */ 8,
 	/* .MaxCombinedClipAndCullDistances = */ 8,
 	/* .MaxCombinedClipAndCullDistances = */ 8,
 	/* .MaxSamples = */ 32,
 	/* .MaxSamples = */ 32,
+	/* .maxMeshOutputVerticesNV = */ 256,
+	/* .maxMeshOutputPrimitivesNV = */ 512,
+	/* .maxMeshWorkGroupSizeX_NV = */ 32,
+	/* .maxMeshWorkGroupSizeY_NV = */ 1,
+	/* .maxMeshWorkGroupSizeZ_NV = */ 1,
+	/* .maxTaskWorkGroupSizeX_NV = */ 32,
+	/* .maxTaskWorkGroupSizeY_NV = */ 1,
+	/* .maxTaskWorkGroupSizeZ_NV = */ 1,
+	/* .maxMeshViewCountNV = */ 4,
 	/* .limits = */ {
 	/* .limits = */ {
 		/* .nonInductiveForLoops = */ 1,
 		/* .nonInductiveForLoops = */ 1,
 		/* .whileLoops = */ 1,
 		/* .whileLoops = */ 1,

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