Browse Source

Update glslang.

Alex Szpakowski 7 years ago
parent
commit
54c09c910a
36 changed files with 2282 additions and 992 deletions
  1. 22 12
      src/libraries/glslang/OGLCompilersDLL/InitializeDll.cpp
  2. 2 2
      src/libraries/glslang/OGLCompilersDLL/InitializeDll.h
  3. 6 1
      src/libraries/glslang/glslang/GenericCodeGen/CodeGen.cpp
  4. 10 2
      src/libraries/glslang/glslang/Include/Common.h
  5. 0 3
      src/libraries/glslang/glslang/Include/ConstantUnion.h
  6. 1 8
      src/libraries/glslang/glslang/Include/PoolAlloc.h
  7. 5 2
      src/libraries/glslang/glslang/Include/ResourceLimits.h
  8. 66 57
      src/libraries/glslang/glslang/Include/Types.h
  9. 9 0
      src/libraries/glslang/glslang/Include/arrays.h
  10. 86 11
      src/libraries/glslang/glslang/Include/intermediate.h
  11. 26 2
      src/libraries/glslang/glslang/Include/revision.h
  12. 320 49
      src/libraries/glslang/glslang/MachineIndependent/InfoSink.cpp
  13. 63 16
      src/libraries/glslang/glslang/MachineIndependent/Initialize.h
  14. 29 0
      src/libraries/glslang/glslang/MachineIndependent/LiveTraverser.h
  15. 166 93
      src/libraries/glslang/glslang/MachineIndependent/ParseHelper.cpp
  16. 32 11
      src/libraries/glslang/glslang/MachineIndependent/ParseHelper.h
  17. 16 46
      src/libraries/glslang/glslang/MachineIndependent/PoolAlloc.cpp
  18. 26 12
      src/libraries/glslang/glslang/MachineIndependent/RemoveTree.cpp
  19. 8 9
      src/libraries/glslang/glslang/MachineIndependent/Scan.h
  20. 241 94
      src/libraries/glslang/glslang/MachineIndependent/ScanContext.h
  21. 14 5
      src/libraries/glslang/glslang/MachineIndependent/SymbolTable.cpp
  22. 34 6
      src/libraries/glslang/glslang/MachineIndependent/SymbolTable.h
  23. 33 7
      src/libraries/glslang/glslang/MachineIndependent/Versions.h
  24. 507 358
      src/libraries/glslang/glslang/MachineIndependent/gl_types.h
  25. 3 5
      src/libraries/glslang/glslang/MachineIndependent/glslang_tab.cpp.h
  26. 32 4
      src/libraries/glslang/glslang/MachineIndependent/intermOut.cpp
  27. 117 64
      src/libraries/glslang/glslang/MachineIndependent/iomapper.cpp
  28. 10 2
      src/libraries/glslang/glslang/MachineIndependent/iomapper.h
  29. 211 46
      src/libraries/glslang/glslang/MachineIndependent/localintermediate.h
  30. 33 21
      src/libraries/glslang/glslang/MachineIndependent/parseConst.cpp
  31. 1 1
      src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpAtom.cpp
  32. 6 3
      src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp
  33. 22 12
      src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpTokens.cpp
  34. 10 11
      src/libraries/glslang/glslang/MachineIndependent/reflection.h
  35. 13 0
      src/libraries/glslang/glslang/OSDependent/Unix/ossource.cpp
  36. 102 17
      src/libraries/glslang/glslang/OSDependent/Windows/main.cpp

+ 22 - 12
src/libraries/glslang/OGLCompilersDLL/InitializeDll.cpp

@@ -38,13 +38,17 @@
 
 
 #include "InitializeDll.h"
 #include "InitializeDll.h"
 #include "../glslang/Include/InitializeGlobals.h"
 #include "../glslang/Include/InitializeGlobals.h"
-
 #include "../glslang/Public/ShaderLang.h"
 #include "../glslang/Public/ShaderLang.h"
+#include "../glslang/Include/PoolAlloc.h"
 
 
 namespace glslang {
 namespace glslang {
 
 
 OS_TLSIndex ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
 OS_TLSIndex ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
 
 
+// Per-process initialization.
+// Needs to be called at least once before parsing, etc. is done.
+// Will also do thread initialization for the calling thread; other
+// threads will need to do that explicitly.
 bool InitProcess()
 bool InitProcess()
 {
 {
     glslang::GetGlobalLock();
     glslang::GetGlobalLock();
@@ -85,7 +89,9 @@ bool InitProcess()
     return true;
     return true;
 }
 }
 
 
-
+// Per-thread scoped initialization.
+// Must be called at least once by each new thread sharing the
+// symbol tables, etc., needed to parse.
 bool InitThread()
 bool InitThread()
 {
 {
     //
     //
@@ -99,17 +105,21 @@ bool InitThread()
     if (OS_GetTLSValue(ThreadInitializeIndex) != 0)
     if (OS_GetTLSValue(ThreadInitializeIndex) != 0)
         return true;
         return true;
 
 
-    InitializeMemoryPools();
-
     if (! OS_SetTLSValue(ThreadInitializeIndex, (void *)1)) {
     if (! OS_SetTLSValue(ThreadInitializeIndex, (void *)1)) {
         assert(0 && "InitThread(): Unable to set init flag.");
         assert(0 && "InitThread(): Unable to set init flag.");
         return false;
         return false;
     }
     }
 
 
+    glslang::SetThreadPoolAllocator(nullptr);
+
     return true;
     return true;
 }
 }
 
 
-
+// Not necessary to call this: InitThread() is reentrant, and the need
+// to do per thread tear down has been removed.
+//
+// This is kept, with memory management removed, to satisfy any exiting
+// calls to it that rely on it.
 bool DetachThread()
 bool DetachThread()
 {
 {
     bool success = true;
     bool success = true;
@@ -125,14 +135,18 @@ bool DetachThread()
             assert(0 && "DetachThread(): Unable to clear init flag.");
             assert(0 && "DetachThread(): Unable to clear init flag.");
             success = false;
             success = false;
         }
         }
-
-        FreeGlobalPools();
-
     }
     }
 
 
     return success;
     return success;
 }
 }
 
 
+// Not necessary to call this: InitProcess() is reentrant.
+//
+// This is kept, with memory management removed, to satisfy any exiting
+// calls to it that rely on it.
+//
+// Users of glslang should call shFinalize() or glslang::FinalizeProcess() for
+// process-scoped memory tear down.
 bool DetachProcess()
 bool DetachProcess()
 {
 {
     bool success = true;
     bool success = true;
@@ -140,12 +154,8 @@ bool DetachProcess()
     if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX)
     if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX)
         return true;
         return true;
 
 
-    ShFinalize();
-
     success = DetachThread();
     success = DetachThread();
 
 
-    FreePoolIndex();
-
     OS_FreeTLSIndex(ThreadInitializeIndex);
     OS_FreeTLSIndex(ThreadInitializeIndex);
     ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
     ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
 
 

+ 2 - 2
src/libraries/glslang/OGLCompilersDLL/InitializeDll.h

@@ -40,8 +40,8 @@ namespace glslang {
 
 
 bool InitProcess();
 bool InitProcess();
 bool InitThread();
 bool InitThread();
-bool DetachThread();
-bool DetachProcess();
+bool DetachThread();  // not called from standalone, perhaps other tools rely on parts of it
+bool DetachProcess(); // not called from standalone, perhaps other tools rely on parts of it
 
 
 } // end namespace glslang
 } // end namespace glslang
 
 

+ 6 - 1
src/libraries/glslang/glslang/GenericCodeGen/CodeGen.cpp

@@ -193,10 +193,12 @@ enum TBuiltInVariable {
     EbvFragColor,
     EbvFragColor,
     EbvFragData,
     EbvFragData,
     EbvFragDepth,
     EbvFragDepth,
+    EbvFragStencilRef,
     EbvSampleId,
     EbvSampleId,
     EbvSamplePosition,
     EbvSamplePosition,
     EbvSampleMask,
     EbvSampleMask,
     EbvHelperInvocation,
     EbvHelperInvocation,
+
 #ifdef AMD_EXTENSIONS
 #ifdef AMD_EXTENSIONS
     EbvBaryCoordNoPersp,
     EbvBaryCoordNoPersp,
     EbvBaryCoordNoPerspCentroid,
     EbvBaryCoordNoPerspCentroid,
@@ -216,13 +218,13 @@ enum TBuiltInVariable {
     EbvSecondaryViewportMaskNV,
     EbvSecondaryViewportMaskNV,
     EbvPositionPerViewNV,
     EbvPositionPerViewNV,
     EbvViewportMaskPerViewNV,
     EbvViewportMaskPerViewNV,
+    EbvFragFullyCoveredNV,
 #endif 
 #endif 
 
 
     // HLSL built-ins that live only temporarily, until they get remapped
     // HLSL built-ins that live only temporarily, until they get remapped
     // to one of the above.
     // to one of the above.
     EbvFragDepthGreater,
     EbvFragDepthGreater,
     EbvFragDepthLesser,
     EbvFragDepthLesser,
-    EbvStencilRef,
     EbvGsOutputStream,
     EbvGsOutputStream,
     EbvOutputPatch,
     EbvOutputPatch,
     EbvInputPatch,
     EbvInputPatch,
@@ -329,10 +331,12 @@ __inline const char* GetBuiltInVariableString(TBuiltInVariable v)
     case EbvFragColor:            return "FragColor";
     case EbvFragColor:            return "FragColor";
     case EbvFragData:             return "FragData";
     case EbvFragData:             return "FragData";
     case EbvFragDepth:            return "FragDepth";
     case EbvFragDepth:            return "FragDepth";
+    case EbvFragStencilRef:       return "FragStencilRef";
     case EbvSampleId:             return "SampleId";
     case EbvSampleId:             return "SampleId";
     case EbvSamplePosition:       return "SamplePosition";
     case EbvSamplePosition:       return "SamplePosition";
     case EbvSampleMask:           return "SampleMaskIn";
     case EbvSampleMask:           return "SampleMaskIn";
     case EbvHelperInvocation:     return "HelperInvocation";
     case EbvHelperInvocation:     return "HelperInvocation";
+
 #ifdef AMD_EXTENSIONS
 #ifdef AMD_EXTENSIONS
     case EbvBaryCoordNoPersp:           return "BaryCoordNoPersp";
     case EbvBaryCoordNoPersp:           return "BaryCoordNoPersp";
     case EbvBaryCoordNoPerspCentroid:   return "BaryCoordNoPerspCentroid";
     case EbvBaryCoordNoPerspCentroid:   return "BaryCoordNoPerspCentroid";
@@ -352,6 +356,7 @@ __inline const char* GetBuiltInVariableString(TBuiltInVariable v)
     case EbvSecondaryViewportMaskNV:    return "SecondaryViewportMaskNV";
     case EbvSecondaryViewportMaskNV:    return "SecondaryViewportMaskNV";
     case EbvPositionPerViewNV:          return "PositionPerViewNV";
     case EbvPositionPerViewNV:          return "PositionPerViewNV";
     case EbvViewportMaskPerViewNV:      return "ViewportMaskPerViewNV";
     case EbvViewportMaskPerViewNV:      return "ViewportMaskPerViewNV";
+    case EbvFragFullyCoveredNV:         return "FragFullyCoveredNV";
 #endif 
 #endif 
     default:                      return "unknown built-in variable";
     default:                      return "unknown built-in variable";
     }
     }

+ 10 - 2
src/libraries/glslang/glslang/Include/Common.h

@@ -63,7 +63,7 @@ std::string to_string(const T& val) {
 }
 }
 #endif
 #endif
 
 
-#if defined(_MSC_VER) && _MSC_VER < 1700
+#if defined(_MSC_VER) && _MSC_VER < 1800
 inline long long int strtoll (const char* str, char** endptr, int base)
 inline long long int strtoll (const char* str, char** endptr, int base)
 {
 {
   return _strtoi64(str, endptr, base);
   return _strtoi64(str, endptr, base);
@@ -78,6 +78,10 @@ inline long long int atoll (const char* str)
 }
 }
 #endif
 #endif
 
 
+#if defined(_MSC_VER)
+#define strdup _strdup
+#endif
+
 /* windows only pragma */
 /* windows only pragma */
 #ifdef _MSC_VER
 #ifdef _MSC_VER
     #pragma warning(disable : 4786) // Don't warn about too long identifiers
     #pragma warning(disable : 4786) // Don't warn about too long identifiers
@@ -222,6 +226,7 @@ inline const TString String(const int i, const int /*base*/ = 10)
 
 
 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; }
     // 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
     {
     {
@@ -235,7 +240,10 @@ struct TSourceLoc {
     int column;
     int column;
 };
 };
 
 
-typedef TMap<TString, TString> TPragmaTable;
+class TPragmaTable : public TMap<TString, TString> {
+public:
+    POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
+};
 
 
 const int MaxTokenLength = 1024;
 const int MaxTokenLength = 1024;
 
 

+ 0 - 3
src/libraries/glslang/glslang/Include/ConstantUnion.h

@@ -37,10 +37,7 @@
 
 
 namespace glslang {
 namespace glslang {
 
 
-void InitializeMemoryPools();
-void FreeGlobalPools();
 bool InitializePoolIndex();
 bool InitializePoolIndex();
-void FreePoolIndex();
 
 
 } // end namespace glslang
 } // end namespace glslang
 
 

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

@@ -250,15 +250,8 @@ private:
 // different times.  But a simple use is to have a global pop
 // different times.  But a simple use is to have a global pop
 // with everyone using the same global allocator.
 // with everyone using the same global allocator.
 //
 //
-typedef TPoolAllocator* PoolAllocatorPointer;
 extern TPoolAllocator& GetThreadPoolAllocator();
 extern TPoolAllocator& GetThreadPoolAllocator();
-
-struct TThreadMemoryPools
-{
-    TPoolAllocator* threadPoolAllocator;
-};
-
-void SetThreadPoolAllocator(TPoolAllocator& poolAllocator);
+void SetThreadPoolAllocator(TPoolAllocator* poolAllocator);
 
 
 //
 //
 // This STL compatible allocator is intended to be used as the allocator
 // This STL compatible allocator is intended to be used as the allocator

+ 5 - 2
src/libraries/glslang/glslang/Include/ResourceLimits.h

@@ -56,11 +56,14 @@ class TUniformMap;
 //
 //
 class TShHandleBase {
 class TShHandleBase {
 public:
 public:
-    TShHandleBase() { }
-    virtual ~TShHandleBase() { }
+    TShHandleBase() { pool = new glslang::TPoolAllocator; }
+    virtual ~TShHandleBase() { delete pool; }
     virtual TCompiler* getAsCompiler() { return 0; }
     virtual TCompiler* getAsCompiler() { return 0; }
     virtual TLinker* getAsLinker() { return 0; }
     virtual TLinker* getAsLinker() { return 0; }
     virtual TUniformMap* getAsUniformMap() { return 0; }
     virtual TUniformMap* getAsUniformMap() { return 0; }
+    virtual glslang::TPoolAllocator* getPool() const { return pool; }
+private:
+    glslang::TPoolAllocator* pool;
 };
 };
 
 
 //
 //

+ 66 - 57
src/libraries/glslang/glslang/Include/Types.h

@@ -80,7 +80,19 @@ struct TSampler {   // misnomer now; includes images, textures without sampler,
     bool   combined : 1;  // true means texture is combined with a sampler, false means texture with no sampler
     bool   combined : 1;  // true means texture is combined with a sampler, false means texture with no sampler
     bool    sampler : 1;  // true means a pure sampler, other fields should be clear()
     bool    sampler : 1;  // true means a pure sampler, other fields should be clear()
     bool   external : 1;  // GL_OES_EGL_image_external
     bool   external : 1;  // GL_OES_EGL_image_external
-    unsigned int vectorSize : 3;  // return vector size.  TODO: support arbitrary types.
+    unsigned int vectorSize : 3;  // vector return type size.
+
+    // Some languages support structures as sample results.  Storing the whole structure in the
+    // TSampler is too large, so there is an index to a separate table.
+    static const unsigned structReturnIndexBits = 4;                        // number of index bits to use.
+    static const unsigned structReturnSlots = (1<<structReturnIndexBits)-1; // number of valid values
+    static const unsigned noReturnStruct = structReturnSlots;               // value if no return struct type.
+
+    // Index into a language specific table of texture return structures.
+    unsigned int structReturnIndex : structReturnIndexBits;
+
+    // Encapsulate getting members' vector sizes packed into the vectorSize bitfield.
+    unsigned int getVectorSize() const { return vectorSize; }
 
 
     bool isImage()       const { return image && dim != EsdSubpass; }
     bool isImage()       const { return image && dim != EsdSubpass; }
     bool isSubpass()     const { return dim == EsdSubpass; }
     bool isSubpass()     const { return dim == EsdSubpass; }
@@ -90,6 +102,7 @@ struct TSampler {   // misnomer now; includes images, textures without sampler,
     bool isShadow()      const { return shadow; }
     bool isShadow()      const { return shadow; }
     bool isArrayed()     const { return arrayed; }
     bool isArrayed()     const { return arrayed; }
     bool isMultiSample() const { return ms; }
     bool isMultiSample() const { return ms; }
+    bool hasReturnStruct() const { return structReturnIndex != noReturnStruct; }
 
 
     void clear()
     void clear()
     {
     {
@@ -102,6 +115,9 @@ struct TSampler {   // misnomer now; includes images, textures without sampler,
         combined = false;
         combined = false;
         sampler = false;
         sampler = false;
         external = false;
         external = false;
+        structReturnIndex = noReturnStruct;
+
+        // by default, returns a single vec4;
         vectorSize = 4;
         vectorSize = 4;
     }
     }
 
 
@@ -160,16 +176,17 @@ struct TSampler {   // misnomer now; includes images, textures without sampler,
 
 
     bool operator==(const TSampler& right) const
     bool operator==(const TSampler& right) const
     {
     {
-        return type == right.type &&
-                dim == right.dim &&
-            arrayed == right.arrayed &&
-             shadow == right.shadow &&
-                 ms == right.ms &&
-              image == right.image &&
-           combined == right.combined &&
-            sampler == right.sampler &&
-           external == right.external &&
-         vectorSize == right.vectorSize;
+        return      type == right.type &&
+                     dim == right.dim &&
+                 arrayed == right.arrayed &&
+                  shadow == right.shadow &&
+                      ms == right.ms &&
+                   image == right.image &&
+                combined == right.combined &&
+                 sampler == right.sampler &&
+                external == right.external &&
+              vectorSize == right.vectorSize &&
+       structReturnIndex == right.structReturnIndex;            
     }
     }
 
 
     bool operator!=(const TSampler& right) const
     bool operator!=(const TSampler& right) const
@@ -633,15 +650,19 @@ public:
         layoutXfbOffset = layoutXfbOffsetEnd;
         layoutXfbOffset = layoutXfbOffsetEnd;
     }
     }
 
 
-    bool hasLayout() const
+    bool hasNonXfbLayout() const
     {
     {
         return hasUniformLayout() ||
         return hasUniformLayout() ||
                hasAnyLocation() ||
                hasAnyLocation() ||
                hasStream() ||
                hasStream() ||
-               hasXfb() ||
                hasFormat() ||
                hasFormat() ||
                layoutPushConstant;
                layoutPushConstant;
     }
     }
+    bool hasLayout() const
+    {
+        return hasNonXfbLayout() ||
+               hasXfb();
+    }
     TLayoutMatrix  layoutMatrix  : 3;
     TLayoutMatrix  layoutMatrix  : 3;
     TLayoutPacking layoutPacking : 4;
     TLayoutPacking layoutPacking : 4;
     int layoutOffset;
     int layoutOffset;
@@ -968,8 +989,10 @@ struct TShaderQualifiers {
     int localSize[3];         // compute shader
     int localSize[3];         // compute shader
     int localSizeSpecId[3];   // compute shader specialization id for gl_WorkGroupSize
     int localSizeSpecId[3];   // compute shader specialization id for gl_WorkGroupSize
     bool earlyFragmentTests;  // fragment input
     bool earlyFragmentTests;  // fragment input
+    bool postDepthCoverage;   // fragment input
     TLayoutDepth layoutDepth;
     TLayoutDepth layoutDepth;
     bool blendEquation;       // true if any blend equation was specified
     bool blendEquation;       // true if any blend equation was specified
+    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
@@ -992,8 +1015,10 @@ struct TShaderQualifiers {
         localSizeSpecId[1] = TQualifier::layoutNotSet;
         localSizeSpecId[1] = TQualifier::layoutNotSet;
         localSizeSpecId[2] = TQualifier::layoutNotSet;
         localSizeSpecId[2] = TQualifier::layoutNotSet;
         earlyFragmentTests = false;
         earlyFragmentTests = false;
+        postDepthCoverage = false;
         layoutDepth = EldNone;
         layoutDepth = EldNone;
         blendEquation = false;
         blendEquation = false;
+        numViews = TQualifier::layoutNotSet;
 #ifdef NV_EXTENSIONS
 #ifdef NV_EXTENSIONS
         layoutOverrideCoverage = false;
         layoutOverrideCoverage = false;
 #endif
 #endif
@@ -1029,10 +1054,14 @@ struct TShaderQualifiers {
         }
         }
         if (src.earlyFragmentTests)
         if (src.earlyFragmentTests)
             earlyFragmentTests = true;
             earlyFragmentTests = true;
+        if (src.postDepthCoverage)
+            postDepthCoverage = true;
         if (src.layoutDepth)
         if (src.layoutDepth)
             layoutDepth = src.layoutDepth;
             layoutDepth = src.layoutDepth;
         if (src.blendEquation)
         if (src.blendEquation)
             blendEquation = src.blendEquation;
             blendEquation = src.blendEquation;
+        if (src.numViews != TQualifier::layoutNotSet)
+            numViews = src.numViews;
 #ifdef NV_EXTENSIONS
 #ifdef NV_EXTENSIONS
         if (src.layoutOverrideCoverage)
         if (src.layoutOverrideCoverage)
             layoutOverrideCoverage = src.layoutOverrideCoverage;
             layoutOverrideCoverage = src.layoutOverrideCoverage;
@@ -1127,6 +1156,7 @@ public:
                                 sampler.clear();
                                 sampler.clear();
                                 qualifier.clear();
                                 qualifier.clear();
                                 qualifier.storage = q;
                                 qualifier.storage = q;
+                                assert(!(isMatrix() && vectorSize != 0));  // prevent vectorSize != 0 on matrices
                             }
                             }
     // for explicit precision qualifier
     // for explicit precision qualifier
     TType(TBasicType t, TStorageQualifier q, TPrecisionQualifier p, int vs = 1, int mc = 0, int mr = 0,
     TType(TBasicType t, TStorageQualifier q, TPrecisionQualifier p, int vs = 1, int mc = 0, int mr = 0,
@@ -1139,6 +1169,7 @@ public:
                                 qualifier.storage = q;
                                 qualifier.storage = q;
                                 qualifier.precision = p;
                                 qualifier.precision = p;
                                 assert(p >= EpqNone && p <= EpqHigh);
                                 assert(p >= EpqNone && p <= EpqHigh);
+                                assert(!(isMatrix() && vectorSize != 0));  // prevent vectorSize != 0 on matrices
                             }
                             }
     // for turning a TPublicType into a TType, using a shallow copy
     // for turning a TPublicType into a TType, using a shallow copy
     explicit TType(const TPublicType& p) :
     explicit TType(const TPublicType& p) :
@@ -1338,53 +1369,31 @@ public:
 #else
 #else
     virtual bool isFloatingDomain() const { return basicType == EbtFloat || basicType == EbtDouble; }
     virtual bool isFloatingDomain() const { return basicType == EbtFloat || basicType == EbtDouble; }
 #endif
 #endif
-
-    virtual bool isOpaque() const { return basicType == EbtSampler || basicType == EbtAtomicUint; }
-
-    // "Image" is a superset of "Subpass"
-    virtual bool isImage() const   { return basicType == EbtSampler && getSampler().isImage(); }
-    virtual bool isSubpass() const { return basicType == EbtSampler && getSampler().isSubpass(); }
-
-    virtual bool isBuiltInInterstageIO(EShLanguage language) const
+    virtual bool isIntegerDomain() const
     {
     {
-        return isPerVertexAndBuiltIn(language) || isLooseAndBuiltIn(language);
-    }
-
-    // Return true if this is an interstage IO builtin
-    virtual bool isPerVertexAndBuiltIn(EShLanguage language) const
-    {
-        if (language == EShLangFragment)
-            return false;
-
-        // Any non-fragment stage
-        switch (getQualifier().builtIn) {
-        case EbvPosition:
-        case EbvPointSize:
-        case EbvClipDistance:
-        case EbvCullDistance:
-#ifdef NV_EXTENSIONS
-        case EbvLayer:
-        case EbvViewportMaskNV:
-        case EbvSecondaryPositionNV:
-        case EbvSecondaryViewportMaskNV:
-        case EbvPositionPerViewNV:
-        case EbvViewportMaskPerViewNV:
+        switch (basicType) {
+        case EbtInt:
+        case EbtUint:
+        case EbtInt64:
+        case EbtUint64:
+#ifdef AMD_EXTENSIONS
+        case EbtInt16:
+        case EbtUint16:
 #endif
 #endif
+        case EbtAtomicUint:
             return true;
             return true;
         default:
         default:
-            return false;
+            break;
         }
         }
+        return false;
     }
     }
+    virtual bool isOpaque() const { return basicType == EbtSampler || basicType == EbtAtomicUint; }
+    virtual bool isBuiltIn() const { return getQualifier().builtIn != EbvNone; }
 
 
-    // Return true if this is a loose builtin
-    virtual bool isLooseAndBuiltIn(EShLanguage language) const
-    {
-        if (getQualifier().builtIn == EbvNone)
-            return false;
+    // "Image" is a superset of "Subpass"
+    virtual bool isImage() const   { return basicType == EbtSampler && getSampler().isImage(); }
+    virtual bool isSubpass() const { return basicType == EbtSampler && getSampler().isSubpass(); }
 
 
-        return !isPerVertexAndBuiltIn(language);
-    }
-    
     // 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
@@ -1426,10 +1435,10 @@ public:
         return contains([](const TType* t) { return t->isOpaque(); } );
         return contains([](const TType* t) { return t->isOpaque(); } );
     }
     }
 
 
-    // Recursively checks if the type contains an interstage IO builtin
-    virtual bool containsBuiltInInterstageIO(EShLanguage language) const
+    // Recursively checks if the type contains a built-in variable
+    virtual bool containsBuiltIn() const
     {
     {
-        return contains([language](const TType* t) { return t->isBuiltInInterstageIO(language); } );
+        return contains([](const TType* t) { return t->isBuiltIn(); } );
     }
     }
 
 
     virtual bool containsNonOpaque() const
     virtual bool containsNonOpaque() const
@@ -1451,9 +1460,9 @@ public:
             case EbtUint16:
             case EbtUint16:
 #endif
 #endif
             case EbtBool:
             case EbtBool:
-            return true;
+                return true;
             default:
             default:
-            return false;
+                return false;
             }
             }
         };
         };
 
 

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

@@ -264,6 +264,15 @@ struct TArraySizes {
 
 
         return false;
         return false;
     }
     }
+    bool clearInnerImplicit()
+    {
+        for (int d = 1; d < sizes.size(); ++d) {
+            if (sizes.getDimSize(d) == (unsigned)UnsizedArraySize)
+                setDimSize(d, 1);
+        }
+
+        return false;
+    }
     bool isInnerSpecialization() const
     bool isInnerSpecialization() const
     {
     {
         for (int d = 1; d < sizes.size(); ++d) {
         for (int d = 1; d < sizes.size(); ++d) {

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

@@ -417,9 +417,18 @@ enum TOperator {
     EOpAtomicExchange,
     EOpAtomicExchange,
     EOpAtomicCompSwap,
     EOpAtomicCompSwap,
 
 
-    EOpAtomicCounterIncrement,
-    EOpAtomicCounterDecrement,
+    EOpAtomicCounterIncrement, // results in pre-increment value
+    EOpAtomicCounterDecrement, // results in post-decrement value
     EOpAtomicCounter,
     EOpAtomicCounter,
+    EOpAtomicCounterAdd,
+    EOpAtomicCounterSubtract,
+    EOpAtomicCounterMin,
+    EOpAtomicCounterMax,
+    EOpAtomicCounterAnd,
+    EOpAtomicCounterOr,
+    EOpAtomicCounterXor,
+    EOpAtomicCounterExchange,
+    EOpAtomicCounterCompSwap,
 
 
     EOpAny,
     EOpAny,
     EOpAll,
     EOpAll,
@@ -584,6 +593,10 @@ enum TOperator {
     EOpImageQuerySamples,
     EOpImageQuerySamples,
     EOpImageLoad,
     EOpImageLoad,
     EOpImageStore,
     EOpImageStore,
+#ifdef AMD_EXTENSIONS
+    EOpImageLoadLod,
+    EOpImageStoreLod,
+#endif
     EOpImageAtomicAdd,
     EOpImageAtomicAdd,
     EOpImageAtomicMin,
     EOpImageAtomicMin,
     EOpImageAtomicMax,
     EOpImageAtomicMax,
@@ -596,6 +609,9 @@ enum TOperator {
     EOpSubpassLoad,
     EOpSubpassLoad,
     EOpSubpassLoadMS,
     EOpSubpassLoadMS,
     EOpSparseImageLoad,
     EOpSparseImageLoad,
+#ifdef AMD_EXTENSIONS
+    EOpSparseImageLoadLod,
+#endif
 
 
     EOpImageGuardEnd,
     EOpImageGuardEnd,
 
 
@@ -637,6 +653,8 @@ enum TOperator {
     EOpTextureGatherLod,
     EOpTextureGatherLod,
     EOpTextureGatherLodOffset,
     EOpTextureGatherLodOffset,
     EOpTextureGatherLodOffsets,
     EOpTextureGatherLodOffsets,
+    EOpFragmentMaskFetch,
+    EOpFragmentFetch,
 #endif
 #endif
 
 
     EOpSparseTextureGuardBegin,
     EOpSparseTextureGuardBegin,
@@ -704,7 +722,8 @@ enum TOperator {
     EOpInterlockedOr,       // ...
     EOpInterlockedOr,       // ...
     EOpInterlockedXor,      // ...
     EOpInterlockedXor,      // ...
     EOpAllMemoryBarrierWithGroupSync,    // memory barriers without non-hlsl AST equivalents
     EOpAllMemoryBarrierWithGroupSync,    // memory barriers without non-hlsl AST equivalents
-    EOpGroupMemoryBarrierWithGroupSync,  // ...
+    EOpDeviceMemoryBarrier,              // ...
+    EOpDeviceMemoryBarrierWithGroupSync, // ...
     EOpWorkgroupMemoryBarrier,           // ...
     EOpWorkgroupMemoryBarrier,           // ...
     EOpWorkgroupMemoryBarrierWithGroupSync, // ...
     EOpWorkgroupMemoryBarrierWithGroupSync, // ...
     EOpEvaluateAttributeSnapped,         // InterpolateAtOffset with int position on 16x16 grid
     EOpEvaluateAttributeSnapped,         // InterpolateAtOffset with int position on 16x16 grid
@@ -772,6 +791,7 @@ class TIntermBranch;
 class TIntermTyped;
 class TIntermTyped;
 class TIntermMethod;
 class TIntermMethod;
 class TIntermSymbol;
 class TIntermSymbol;
+class TIntermLoop;
 
 
 } // end namespace glslang
 } // end namespace glslang
 
 
@@ -799,6 +819,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 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; }
@@ -811,6 +832,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 ~TIntermNode() { }
     virtual ~TIntermNode() { }
 
 
 protected:
 protected:
@@ -854,6 +876,8 @@ public:
     virtual bool isVector() const { return type.isVector(); }
     virtual bool isVector() const { return type.isVector(); }
     virtual bool isScalar() const { return type.isScalar(); }
     virtual bool isScalar() const { return type.isScalar(); }
     virtual bool isStruct() const { return type.isStruct(); }
     virtual bool isStruct() const { return type.isStruct(); }
+    virtual bool isFloatingDomain() const { return type.isFloatingDomain(); }
+    virtual bool isIntegerDomain() const { return type.isIntegerDomain(); }
     TString getCompleteString() const { return type.getCompleteString(); }
     TString getCompleteString() const { return type.getCompleteString(); }
 
 
 protected:
 protected:
@@ -861,6 +885,15 @@ protected:
     TType type;
     TType type;
 };
 };
 
 
+//
+// Selection control hints
+//
+enum TSelectionControl {
+    ESelectionControlNone,
+    ESelectionControlFlatten,
+    ESelectionControlDontFlatten,
+};
+
 //
 //
 // Loop control hints
 // Loop control hints
 //
 //
@@ -883,6 +916,8 @@ public:
         control(ELoopControlNone)
         control(ELoopControlNone)
     { }
     { }
 
 
+	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; }
@@ -945,7 +980,11 @@ public:
     // per process threadPoolAllocator, then it causes increased memory usage per compile
     // per process threadPoolAllocator, then it causes increased memory usage per compile
     // it is essential to use "symbol = sym" to assign to symbol
     // it is essential to use "symbol = sym" to assign to symbol
     TIntermSymbol(int i, const TString& n, const TType& t)
     TIntermSymbol(int i, const TString& n, const TType& t)
-        : TIntermTyped(t), id(i), constSubtree(nullptr)
+        : TIntermTyped(t), id(i),
+#ifdef ENABLE_HLSL
+        flattenSubset(-1),
+#endif
+        constSubtree(nullptr)
           { name = n; }
           { name = n; }
     virtual int getId() const { return id; }
     virtual int getId() const { return id; }
     virtual const TString& getName() const { return name; }
     virtual const TString& getName() const { return name; }
@@ -956,9 +995,20 @@ public:
     const TConstUnionArray& getConstArray() const { return constArray; }
     const TConstUnionArray& getConstArray() const { return constArray; }
     void setConstSubtree(TIntermTyped* subtree) { constSubtree = subtree; }
     void setConstSubtree(TIntermTyped* subtree) { constSubtree = subtree; }
     TIntermTyped* getConstSubtree() const { return constSubtree; }
     TIntermTyped* getConstSubtree() const { return constSubtree; }
+#ifdef ENABLE_HLSL
+    void setFlattenSubset(int subset) { flattenSubset = subset; }
+    int getFlattenSubset() const { return flattenSubset; } // -1 means full object
+#endif
+
+    // This is meant for cases where a node has already been constructed, and
+    // later on, it becomes necessary to switch to a different symbol.
+    virtual void switchId(int newId) { id = newId; }
 
 
 protected:
 protected:
     int id;                      // the unique id of the symbol this node represents
     int id;                      // the unique id of the symbol this node represents
+#ifdef ENABLE_HLSL
+    int flattenSubset;           // how deeply the flattened object rooted at id has been dereferenced
+#endif
     TString name;                // the name of the symbol this node represents
     TString name;                // the name of the symbol this node represents
     TConstUnionArray constArray; // if the symbol is a front-end compile-time constant, this is its value
     TConstUnionArray constArray; // if the symbol is a front-end compile-time constant, this is its value
     TIntermTyped* constSubtree;
     TIntermTyped* constSubtree;
@@ -996,6 +1046,9 @@ struct TCrackedTextureOp {
     bool grad;
     bool grad;
     bool subpass;
     bool subpass;
     bool lodClamp;
     bool lodClamp;
+#ifdef AMD_EXTENSIONS
+    bool fragMask;
+#endif
 };
 };
 
 
 //
 //
@@ -1043,6 +1096,9 @@ public:
         cracked.grad = false;
         cracked.grad = false;
         cracked.subpass = false;
         cracked.subpass = false;
         cracked.lodClamp = false;
         cracked.lodClamp = false;
+#ifdef AMD_EXTENSIONS
+        cracked.fragMask = false;
+#endif
 
 
         switch (op) {
         switch (op) {
         case EOpImageQuerySize:
         case EOpImageQuerySize:
@@ -1169,6 +1225,19 @@ public:
             cracked.offsets = true;
             cracked.offsets = true;
             cracked.lod     = true;
             cracked.lod     = true;
             break;
             break;
+        case EOpImageLoadLod:
+        case EOpImageStoreLod:
+        case EOpSparseImageLoadLod:
+            cracked.lod = true;
+            break;
+        case EOpFragmentMaskFetch:
+            cracked.subpass = sampler.dim == EsdSubpass;
+            cracked.fragMask = true;
+            break;
+        case EOpFragmentFetch:
+            cracked.subpass = sampler.dim == EsdSubpass;
+            cracked.fragMask = true;
+            break;
 #endif
 #endif
         case EOpSubpassLoad:
         case EOpSubpassLoad:
         case EOpSubpassLoadMS:
         case EOpSubpassLoadMS:
@@ -1229,14 +1298,14 @@ protected:
 };
 };
 
 
 typedef TVector<TIntermNode*> TIntermSequence;
 typedef TVector<TIntermNode*> TIntermSequence;
-typedef TVector<int> TQualifierList;
+typedef TVector<TStorageQualifier> TQualifierList;
 //
 //
 // Nodes that operate on an arbitrary sized set of children.
 // Nodes that operate on an arbitrary sized set of children.
 //
 //
 class TIntermAggregate : public TIntermOperator {
 class TIntermAggregate : public TIntermOperator {
 public:
 public:
-    TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), pragmaTable(0) { }
-    TIntermAggregate(TOperator o) : TIntermOperator(o), pragmaTable(0) { }
+    TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), pragmaTable(nullptr) { }
+    TIntermAggregate(TOperator o) : TIntermOperator(o), pragmaTable(nullptr) { }
     ~TIntermAggregate() { delete pragmaTable; }
     ~TIntermAggregate() { delete pragmaTable; }
     virtual       TIntermAggregate* getAsAggregate()       { return this; }
     virtual       TIntermAggregate* getAsAggregate()       { return this; }
     virtual const TIntermAggregate* getAsAggregate() const { return this; }
     virtual const TIntermAggregate* getAsAggregate() const { return this; }
@@ -1254,7 +1323,7 @@ public:
     void setDebug(bool d) { debug = d; }
     void setDebug(bool d) { debug = d; }
     bool getOptimize() const { return optimize; }
     bool getOptimize() const { return optimize; }
     bool getDebug() const { return debug; }
     bool getDebug() const { return debug; }
-    void addToPragmaTable(const TPragmaTable& pTable);
+    void setPragmaTable(const TPragmaTable& pTable);
     const TPragmaTable& getPragmaTable() const { return *pragmaTable; }
     const TPragmaTable& getPragmaTable() const { return *pragmaTable; }
 protected:
 protected:
     TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
     TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
@@ -1274,19 +1343,22 @@ 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) {}
+        TIntermTyped(EbtVoid), condition(cond), trueBlock(trueB), falseBlock(falseB), control(ESelectionControlNone) {}
     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) {}
+        TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB), control(ESelectionControlNone) {}
     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; }
 protected:
 protected:
     TIntermTyped* condition;
     TIntermTyped* condition;
     TIntermNode* trueBlock;
     TIntermNode* trueBlock;
     TIntermNode* falseBlock;
     TIntermNode* falseBlock;
+    TSelectionControl control;    // selection control hint
 };
 };
 
 
 //
 //
@@ -1297,15 +1369,18 @@ protected:
 //
 //
 class TIntermSwitch : public TIntermNode {
 class TIntermSwitch : public TIntermNode {
 public:
 public:
-    TIntermSwitch(TIntermTyped* cond, TIntermAggregate* b) : condition(cond), body(b) { }
+    TIntermSwitch(TIntermTyped* cond, TIntermAggregate* b) : condition(cond), body(b), control(ESelectionControlNone) { }
     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; }
 protected:
 protected:
     TIntermTyped* condition;
     TIntermTyped* condition;
     TIntermAggregate* body;
     TIntermAggregate* body;
+    TSelectionControl control;    // selection control hint
 };
 };
 
 
 enum TVisit
 enum TVisit

+ 26 - 2
src/libraries/glslang/glslang/Include/revision.h

@@ -38,6 +38,7 @@
 #include <cmath>
 #include <cmath>
 #include <cfloat>
 #include <cfloat>
 #include <cstdlib>
 #include <cstdlib>
+#include <climits>
 
 
 namespace {
 namespace {
 
 
@@ -263,8 +264,31 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TIntermTyped* right
         for (int i = 0; i < newComps; i++) {
         for (int i = 0; i < newComps; i++) {
             if (rightUnionArray[i] == 0)
             if (rightUnionArray[i] == 0)
                 newConstArray[i] = leftUnionArray[i];
                 newConstArray[i] = leftUnionArray[i];
-            else
-                newConstArray[i] = leftUnionArray[i] % rightUnionArray[i];
+            else {
+                switch (getType().getBasicType()) {
+                case EbtInt:
+                    if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == INT_MIN) {
+                        newConstArray[i].setIConst(0);
+                        break;
+                    } else goto modulo_default;
+
+                case EbtInt64:
+                    if (rightUnionArray[i].getI64Const() == -1 && leftUnionArray[i].getI64Const() == LLONG_MIN) {
+                        newConstArray[i].setI64Const(0);
+                        break;
+                    } else goto modulo_default;
+#ifdef AMD_EXTENSIONS
+                case EbtInt16:
+                    if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == SHRT_MIN) {
+                        newConstArray[i].setIConst(0);
+                        break;
+                    } else goto modulo_default;
+#endif
+                default:
+                modulo_default:
+                    newConstArray[i] = leftUnionArray[i] % rightUnionArray[i];
+                }
+            }
         }
         }
         break;
         break;
 
 

+ 320 - 49
src/libraries/glslang/glslang/MachineIndependent/InfoSink.cpp

@@ -1,7 +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) 2015-2016 Google, Inc.
+// Copyright (C) 2015-2017 Google, Inc.
 //
 //
 // All rights reserved.
 // All rights reserved.
 //
 //
@@ -923,6 +923,32 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
             "\n");
             "\n");
     }
     }
 
 
+#ifdef NV_EXTENSIONS
+    if (profile != EEsProfile && version >= 440) {
+        commonBuiltins.append(
+            "uint64_t atomicMin(coherent volatile inout uint64_t, uint64_t);"
+            " int64_t atomicMin(coherent volatile inout  int64_t,  int64_t);"
+
+            "uint64_t atomicMax(coherent volatile inout uint64_t, uint64_t);"
+            " int64_t atomicMax(coherent volatile inout  int64_t,  int64_t);"
+
+            "uint64_t atomicAnd(coherent volatile inout uint64_t, uint64_t);"
+            " int64_t atomicAnd(coherent volatile inout  int64_t,  int64_t);"
+
+            "uint64_t atomicOr (coherent volatile inout uint64_t, uint64_t);"
+            " int64_t atomicOr (coherent volatile inout  int64_t,  int64_t);"
+
+            "uint64_t atomicXor(coherent volatile inout uint64_t, uint64_t);"
+            " int64_t atomicXor(coherent volatile inout  int64_t,  int64_t);"
+
+            " int64_t atomicAdd(coherent volatile inout int64_t, int64_t);"
+            " int64_t atomicExchange(coherent volatile inout int64_t, int64_t);"
+            " int64_t atomicCompSwap(coherent volatile inout int64_t, int64_t, int64_t);"
+
+            "\n");
+    }
+#endif
+
     if ((profile == EEsProfile && version >= 310) ||
     if ((profile == EEsProfile && version >= 310) ||
         (profile != EEsProfile && version >= 450)) {
         (profile != EEsProfile && version >= 450)) {
         commonBuiltins.append(
         commonBuiltins.append(
@@ -1330,15 +1356,33 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
 
 
     if (profile == EEsProfile) {
     if (profile == EEsProfile) {
         if (spvVersion.spv == 0) {
         if (spvVersion.spv == 0) {
+            if (version < 300) {
+                commonBuiltins.append(
+                    "vec4 texture2D(samplerExternalOES, vec2 coord);" // GL_OES_EGL_image_external
+                    "vec4 texture2DProj(samplerExternalOES, vec3);"   // GL_OES_EGL_image_external
+                    "vec4 texture2DProj(samplerExternalOES, vec4);"   // GL_OES_EGL_image_external
+                "\n");
+            } else {
+                commonBuiltins.append(
+                    "highp ivec2 textureSize(samplerExternalOES, int lod);"   // GL_OES_EGL_image_external_essl3
+                    "vec4 texture(samplerExternalOES, vec2);"                 // GL_OES_EGL_image_external_essl3
+                    "vec4 texture(samplerExternalOES, vec2, float bias);"     // GL_OES_EGL_image_external_essl3
+                    "vec4 textureProj(samplerExternalOES, vec3);"             // GL_OES_EGL_image_external_essl3
+                    "vec4 textureProj(samplerExternalOES, vec3, float bias);" // GL_OES_EGL_image_external_essl3
+                    "vec4 textureProj(samplerExternalOES, vec4);"             // GL_OES_EGL_image_external_essl3
+                    "vec4 textureProj(samplerExternalOES, vec4, float bias);" // GL_OES_EGL_image_external_essl3
+                    "vec4 texelFetch(samplerExternalOES, ivec2, int lod);"    // GL_OES_EGL_image_external_essl3
+                "\n");
+            }
             commonBuiltins.append(
             commonBuiltins.append(
-                "vec4 texture2D(samplerExternalOES, vec2 coord);"  // GL_OES_EGL_image_external, caught by keyword check
-                "vec4 texture2DProj(samplerExternalOES, vec3);"    // GL_OES_EGL_image_external, caught by keyword check
-                "vec4 texture2DProj(samplerExternalOES, vec4);"    // GL_OES_EGL_image_external, caught by keyword check
                 "vec4 texture2DGradEXT(sampler2D, vec2, vec2, vec2);"      // GL_EXT_shader_texture_lod
                 "vec4 texture2DGradEXT(sampler2D, vec2, vec2, vec2);"      // GL_EXT_shader_texture_lod
                 "vec4 texture2DProjGradEXT(sampler2D, vec3, vec2, vec2);"  // GL_EXT_shader_texture_lod
                 "vec4 texture2DProjGradEXT(sampler2D, vec3, vec2, vec2);"  // GL_EXT_shader_texture_lod
                 "vec4 texture2DProjGradEXT(sampler2D, vec4, vec2, vec2);"  // GL_EXT_shader_texture_lod
                 "vec4 texture2DProjGradEXT(sampler2D, vec4, vec2, vec2);"  // GL_EXT_shader_texture_lod
                 "vec4 textureCubeGradEXT(samplerCube, vec3, vec3, vec3);"  // GL_EXT_shader_texture_lod
                 "vec4 textureCubeGradEXT(samplerCube, vec3, vec3, vec3);"  // GL_EXT_shader_texture_lod
 
 
+                "float shadow2DEXT(sampler2DShadow, vec3);"     // GL_EXT_shadow_samplers
+                "float shadow2DProjEXT(sampler2DShadow, vec4);" // GL_EXT_shadow_samplers
+
                 "\n");
                 "\n");
         }
         }
     }
     }
@@ -1346,7 +1390,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
     //
     //
     // Noise functions.
     // Noise functions.
     //
     //
-    if (profile != EEsProfile) {
+    if (spvVersion.spv == 0 && profile != EEsProfile) {
         commonBuiltins.append(
         commonBuiltins.append(
             "float noise1(float x);"
             "float noise1(float x);"
             "float noise1(vec2  x);"
             "float noise1(vec2  x);"
@@ -1378,9 +1422,23 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
         if ((profile != EEsProfile && version >= 300) ||
         if ((profile != EEsProfile && version >= 300) ||
             (profile == EEsProfile && version >= 310)) {
             (profile == EEsProfile && version >= 310)) {
             commonBuiltins.append(
             commonBuiltins.append(
-                "uint atomicCounterIncrement(atomic_uint x);"
-                "uint atomicCounterDecrement(atomic_uint x);"
-                "uint atomicCounter(atomic_uint x);"
+                "uint atomicCounterIncrement(atomic_uint);"
+                "uint atomicCounterDecrement(atomic_uint);"
+                "uint atomicCounter(atomic_uint);"
+
+                "\n");
+        }
+        if (profile != EEsProfile && version >= 460) {
+            commonBuiltins.append(
+                "uint atomicCounterAdd(atomic_uint, uint);"
+                "uint atomicCounterSubtract(atomic_uint, uint);"
+                "uint atomicCounterMin(atomic_uint, uint);"
+                "uint atomicCounterMax(atomic_uint, uint);"
+                "uint atomicCounterAnd(atomic_uint, uint);"
+                "uint atomicCounterOr(atomic_uint, uint);"
+                "uint atomicCounterXor(atomic_uint, uint);"
+                "uint atomicCounterExchange(atomic_uint, uint);"
+                "uint atomicCounterCompSwap(atomic_uint, uint, uint);"
 
 
                 "\n");
                 "\n");
         }
         }
@@ -1565,7 +1623,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
             "\n");
             "\n");
     }
     }
 
 
-        // GL_ARB_shader_group_vote
+    // GL_ARB_shader_group_vote
     if (profile != EEsProfile && version >= 430) {
     if (profile != EEsProfile && version >= 430) {
         commonBuiltins.append(
         commonBuiltins.append(
             "bool anyInvocationARB(bool);"
             "bool anyInvocationARB(bool);"
@@ -1575,6 +1633,15 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
             "\n");
             "\n");
     }
     }
 
 
+    if (profile != EEsProfile && version >= 460) {
+        commonBuiltins.append(
+            "bool anyInvocation(bool);"
+            "bool allInvocations(bool);"
+            "bool allInvocationsEqual(bool);"
+
+            "\n");
+    }
+
 #ifdef AMD_EXTENSIONS
 #ifdef AMD_EXTENSIONS
     // GL_AMD_shader_ballot
     // GL_AMD_shader_ballot
     if (profile != EEsProfile && version >= 450) {
     if (profile != EEsProfile && version >= 450) {
@@ -2263,7 +2330,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
     if (profile != EEsProfile && version >= 450) {
     if (profile != EEsProfile && version >= 450) {
         commonBuiltins.append(
         commonBuiltins.append(
             "float cubeFaceIndexAMD(vec3);"
             "float cubeFaceIndexAMD(vec3);"
-            "vec2 cubeFaceCoordAMD(vec3);"
+            "vec2  cubeFaceCoordAMD(vec3);"
             "uint64_t timeAMD();"
             "uint64_t timeAMD();"
 
 
             "\n");
             "\n");
@@ -2767,6 +2834,29 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
 
 
             "\n");
             "\n");
     }
     }
+
+    // GL_AMD_shader_fragment_mask
+    if (profile != EEsProfile && version >= 450) {
+        commonBuiltins.append(
+            "uint fragmentMaskFetchAMD(sampler2DMS,       ivec2);"
+            "uint fragmentMaskFetchAMD(isampler2DMS,      ivec2);"
+            "uint fragmentMaskFetchAMD(usampler2DMS,      ivec2);"
+
+            "uint fragmentMaskFetchAMD(sampler2DMSArray,  ivec3);"
+            "uint fragmentMaskFetchAMD(isampler2DMSArray, ivec3);"
+            "uint fragmentMaskFetchAMD(usampler2DMSArray, ivec3);"
+
+            "vec4  fragmentFetchAMD(sampler2DMS,       ivec2, uint);"
+            "ivec4 fragmentFetchAMD(isampler2DMS,      ivec2, uint);"
+            "uvec4 fragmentFetchAMD(usampler2DMS,      ivec2, uint);"
+
+            "vec4  fragmentFetchAMD(sampler2DMSArray,  ivec3, uint);"
+            "ivec4 fragmentFetchAMD(isampler2DMSArray, ivec3, uint);"
+            "uvec4 fragmentFetchAMD(usampler2DMSArray, ivec3, uint);"
+
+            "\n");
+    }
+
 #endif
 #endif
 
 
     //============================================================================
     //============================================================================
@@ -3115,6 +3205,20 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
 
 
             "\n");
             "\n");
     }
     }
+
+    // GL_AMD_shader_fragment_mask
+    if (profile != EEsProfile && version >= 450 && spvVersion.vulkan >= 100) {
+        stageBuiltins[EShLangFragment].append(
+            "uint fragmentMaskFetchAMD(subpassInputMS);"
+            "uint fragmentMaskFetchAMD(isubpassInputMS);"
+            "uint fragmentMaskFetchAMD(usubpassInputMS);"
+
+            "vec4  fragmentFetchAMD(subpassInputMS,  uint);"
+            "ivec4 fragmentFetchAMD(isubpassInputMS, uint);"
+            "uvec4 fragmentFetchAMD(usubpassInputMS, uint);"
+
+            "\n");
+        }
 #endif
 #endif
 
 
     //============================================================================
     //============================================================================
@@ -3414,12 +3518,23 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
                 "in int gl_DrawIDARB;"
                 "in int gl_DrawIDARB;"
                 );
                 );
         }
         }
+        if (version >= 410) {
+            stageBuiltins[EShLangVertex].append(
+                "out int gl_ViewportIndex;"
+                "out int gl_Layer;"
+                );
+        }
+        if (version >= 460) {
+            stageBuiltins[EShLangVertex].append(
+                "in int gl_BaseVertex;"
+                "in int gl_BaseInstance;"
+                "in int gl_DrawID;"
+                );
+        }
 
 
 #ifdef NV_EXTENSIONS
 #ifdef NV_EXTENSIONS
         if (version >= 450)
         if (version >= 450)
             stageBuiltins[EShLangVertex].append(
             stageBuiltins[EShLangVertex].append(
-                "out int gl_ViewportIndex;"
-                "out int gl_Layer;"
                 "out int gl_ViewportMask[];"             // GL_NV_viewport_array2
                 "out int gl_ViewportMask[];"             // GL_NV_viewport_array2
                 "out int gl_SecondaryViewportMaskNV[];"  // GL_NV_stereo_view_rendering
                 "out int gl_SecondaryViewportMaskNV[];"  // GL_NV_stereo_view_rendering
                 "out vec4 gl_SecondaryPositionNV;"       // GL_NV_stereo_view_rendering
                 "out vec4 gl_SecondaryPositionNV;"       // GL_NV_stereo_view_rendering
@@ -3469,6 +3584,12 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
             "\n");
             "\n");
     }
     }
 
 
+    if (version >= 300 /* both ES and non-ES */) {
+        stageBuiltins[EShLangVertex].append(
+            "in highp uint gl_ViewID_OVR;"     // GL_OVR_multiview, GL_OVR_multiview2
+            "\n");
+    }
+
 
 
     //============================================================================
     //============================================================================
     //
     //
@@ -3530,6 +3651,11 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
             "out int gl_PrimitiveID;"
             "out int gl_PrimitiveID;"
             "out int gl_Layer;");
             "out int gl_Layer;");
 
 
+        if (version >= 150)
+            stageBuiltins[EShLangGeometry].append(
+            "out int gl_ViewportIndex;"
+            );
+
         if (profile == ECompatibilityProfile && version < 400)
         if (profile == ECompatibilityProfile && version < 400)
             stageBuiltins[EShLangGeometry].append(
             stageBuiltins[EShLangGeometry].append(
             "out vec4 gl_ClipVertex;"
             "out vec4 gl_ClipVertex;"
@@ -3539,11 +3665,6 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
             stageBuiltins[EShLangGeometry].append(
             stageBuiltins[EShLangGeometry].append(
             "in int gl_InvocationID;"
             "in int gl_InvocationID;"
             );
             );
-        // GL_ARB_viewport_array
-        if (version >= 150)
-            stageBuiltins[EShLangGeometry].append(
-            "out int gl_ViewportIndex;"
-            );
 
 
 #ifdef NV_EXTENSIONS
 #ifdef NV_EXTENSIONS
         if (version >= 450)
         if (version >= 450)
@@ -3620,8 +3741,6 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
             stageBuiltins[EShLangTessControl].append(
             stageBuiltins[EShLangTessControl].append(
                 "float gl_CullDistance[];"
                 "float gl_CullDistance[];"
 #ifdef NV_EXTENSIONS
 #ifdef NV_EXTENSIONS
-                "int  gl_ViewportIndex;"
-                "int  gl_Layer;"
                 "int  gl_ViewportMask[];"             // GL_NV_viewport_array2
                 "int  gl_ViewportMask[];"             // GL_NV_viewport_array2
                 "vec4 gl_SecondaryPositionNV;"        // GL_NV_stereo_view_rendering
                 "vec4 gl_SecondaryPositionNV;"        // GL_NV_stereo_view_rendering
                 "int  gl_SecondaryViewportMaskNV[];"  // GL_NV_stereo_view_rendering
                 "int  gl_SecondaryViewportMaskNV[];"  // GL_NV_stereo_view_rendering
@@ -3635,6 +3754,13 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
             "patch out float gl_TessLevelOuter[4];"
             "patch out float gl_TessLevelOuter[4];"
             "patch out float gl_TessLevelInner[2];"
             "patch out float gl_TessLevelInner[2];"
             "\n");
             "\n");
+
+        if (version >= 410)
+            stageBuiltins[EShLangTessControl].append(
+                "out int gl_ViewportIndex;"
+                "out int gl_Layer;"
+                "\n");
+
     } else {
     } else {
         // Note:  "in gl_PerVertex {...} gl_in[gl_MaxPatchVertices];" is declared in initialize() below,
         // Note:  "in gl_PerVertex {...} gl_in[gl_MaxPatchVertices];" is declared in initialize() below,
         // as it depends on the resource sizing of gl_MaxPatchVertices.
         // as it depends on the resource sizing of gl_MaxPatchVertices.
@@ -3706,11 +3832,15 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
             "};"
             "};"
             "\n");
             "\n");
 
 
+        if (version >= 410)
+            stageBuiltins[EShLangTessEvaluation].append(
+                "out int gl_ViewportIndex;"
+                "out int gl_Layer;"
+                "\n");
+
 #ifdef NV_EXTENSIONS
 #ifdef NV_EXTENSIONS
         if (version >= 450)
         if (version >= 450)
             stageBuiltins[EShLangTessEvaluation].append(
             stageBuiltins[EShLangTessEvaluation].append(
-                "out int  gl_ViewportIndex;"
-                "out int  gl_Layer;"
                 "out int  gl_ViewportMask[];"             // GL_NV_viewport_array2
                 "out int  gl_ViewportMask[];"             // GL_NV_viewport_array2
                 "out vec4 gl_SecondaryPositionNV;"        // GL_NV_stereo_view_rendering
                 "out vec4 gl_SecondaryPositionNV;"        // GL_NV_stereo_view_rendering
                 "out int  gl_SecondaryViewportMaskNV[];"  // GL_NV_stereo_view_rendering
                 "out int  gl_SecondaryViewportMaskNV[];"  // GL_NV_stereo_view_rendering
@@ -3765,6 +3895,10 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
             stageBuiltins[EShLangFragment].append(
             stageBuiltins[EShLangFragment].append(
                 "vec2 gl_PointCoord;"  // needs qualifier fixed later
                 "vec2 gl_PointCoord;"  // needs qualifier fixed later
                 );
                 );
+        if (version >= 140)
+            stageBuiltins[EShLangFragment].append(
+                "out int gl_FragStencilRefARB;"
+                );
         if (IncludeLegacy(version, profile, spvVersion) || (! ForwardCompatibility && version < 420))
         if (IncludeLegacy(version, profile, spvVersion) || (! ForwardCompatibility && version < 420))
             stageBuiltins[EShLangFragment].append(
             stageBuiltins[EShLangFragment].append(
                 "vec4 gl_FragColor;"   // needs qualifier fixed later
                 "vec4 gl_FragColor;"   // needs qualifier fixed later
@@ -3844,6 +3978,13 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
                 "in vec3 gl_BaryCoordPullModelAMD;"
                 "in vec3 gl_BaryCoordPullModelAMD;"
                 );
                 );
 #endif
 #endif
+
+#ifdef NV_EXTENSIONS
+        if (version >= 430)
+            stageBuiltins[EShLangFragment].append(
+                "in bool gl_FragFullyCoveredNV;"
+                );
+#endif
     } else {
     } else {
         // ES profile
         // ES profile
 
 
@@ -3913,6 +4054,12 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
             "\n");
             "\n");
     }
     }
 
 
+    if (version >= 300 /* both ES and non-ES */) {
+        stageBuiltins[EShLangFragment].append(
+            "flat in highp uint gl_ViewID_OVR;"     // GL_OVR_multiview, GL_OVR_multiview2
+            "\n");
+    }
+
     // printf("%s\n", commonBuiltins.c_str());
     // printf("%s\n", commonBuiltins.c_str());
     // printf("%s\n", stageBuiltins[EShLangFragment].c_str());
     // printf("%s\n", stageBuiltins[EShLangFragment].c_str());
 }
 }
@@ -4204,6 +4351,43 @@ void TBuiltIns::addImageFunctions(TSampler sampler, const TString& typeName, int
             }
             }
         }
         }
     }
     }
+
+#ifdef AMD_EXTENSIONS
+    if (sampler.dim == EsdRect || sampler.dim == EsdBuffer || sampler.shadow || sampler.ms)
+        return;
+
+    if (profile == EEsProfile || version < 450)
+        return;
+
+    TString imageLodParams = typeName;
+    if (dims == 1)
+        imageLodParams.append(", int");
+    else {
+        imageLodParams.append(", ivec");
+        imageLodParams.append(postfixes[dims]);
+    }
+    imageLodParams.append(", int");
+
+    commonBuiltins.append(prefixes[sampler.type]);
+    commonBuiltins.append("vec4 imageLoadLodAMD(readonly volatile coherent ");
+    commonBuiltins.append(imageLodParams);
+    commonBuiltins.append(");\n");
+
+    commonBuiltins.append("void imageStoreLodAMD(writeonly volatile coherent ");
+    commonBuiltins.append(imageLodParams);
+    commonBuiltins.append(", ");
+    commonBuiltins.append(prefixes[sampler.type]);
+    commonBuiltins.append("vec4);\n");
+
+    if (sampler.dim != Esd1D) {
+        commonBuiltins.append("int sparseImageLoadLodAMD(readonly volatile coherent ");
+        commonBuiltins.append(imageLodParams);
+        commonBuiltins.append(", out ");
+        commonBuiltins.append(prefixes[sampler.type]);
+        commonBuiltins.append("vec4");
+        commonBuiltins.append(");\n");
+    }
+#endif
 }
 }
 
 
 //
 //
@@ -5212,16 +5396,19 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
     switch(language) {
     switch(language) {
     case EShLangVertex:
     case EShLangVertex:
         if (profile != EEsProfile) {
         if (profile != EEsProfile) {
-            symbolTable.setVariableExtensions("gl_BaseVertexARB",   1, &E_GL_ARB_shader_draw_parameters);
-            symbolTable.setVariableExtensions("gl_BaseInstanceARB", 1, &E_GL_ARB_shader_draw_parameters);
-            symbolTable.setVariableExtensions("gl_DrawIDARB",       1, &E_GL_ARB_shader_draw_parameters);
-
-            BuiltInVariable("gl_BaseVertexARB",   EbvBaseVertex,   symbolTable);
-            BuiltInVariable("gl_BaseInstanceARB", EbvBaseInstance, symbolTable);
-            BuiltInVariable("gl_DrawIDARB",       EbvDrawId,       symbolTable);
-        }
-
-        if (profile != EEsProfile) {
+            if (version >= 440) {
+                symbolTable.setVariableExtensions("gl_BaseVertexARB",   1, &E_GL_ARB_shader_draw_parameters);
+                symbolTable.setVariableExtensions("gl_BaseInstanceARB", 1, &E_GL_ARB_shader_draw_parameters);
+                symbolTable.setVariableExtensions("gl_DrawIDARB",       1, &E_GL_ARB_shader_draw_parameters);
+                BuiltInVariable("gl_BaseVertexARB",   EbvBaseVertex,   symbolTable);
+                BuiltInVariable("gl_BaseInstanceARB", EbvBaseInstance, symbolTable);
+                BuiltInVariable("gl_DrawIDARB",       EbvDrawId,       symbolTable);
+            }
+            if (version >= 460) {
+                BuiltInVariable("gl_BaseVertex",   EbvBaseVertex,   symbolTable);
+                BuiltInVariable("gl_BaseInstance", EbvBaseInstance, symbolTable);
+                BuiltInVariable("gl_DrawID",       EbvDrawId,       symbolTable);
+            }
             symbolTable.setVariableExtensions("gl_SubGroupSizeARB",       1, &E_GL_ARB_shader_ballot);
             symbolTable.setVariableExtensions("gl_SubGroupSizeARB",       1, &E_GL_ARB_shader_ballot);
             symbolTable.setVariableExtensions("gl_SubGroupInvocationARB", 1, &E_GL_ARB_shader_ballot);
             symbolTable.setVariableExtensions("gl_SubGroupInvocationARB", 1, &E_GL_ARB_shader_ballot);
             symbolTable.setVariableExtensions("gl_SubGroupEqMaskARB",     1, &E_GL_ARB_shader_ballot);
             symbolTable.setVariableExtensions("gl_SubGroupEqMaskARB",     1, &E_GL_ARB_shader_ballot);
@@ -5245,9 +5432,11 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
                 // Treat "gl_SubGroupSizeARB" as shader input instead of uniform for Vulkan
                 // Treat "gl_SubGroupSizeARB" as shader input instead of uniform for Vulkan
                 SpecialQualifier("gl_SubGroupSizeARB", EvqVaryingIn, EbvSubGroupSize, symbolTable);
                 SpecialQualifier("gl_SubGroupSizeARB", EvqVaryingIn, EbvSubGroupSize, symbolTable);
 
 
-            symbolTable.setFunctionExtensions("anyInvocationARB",       1, &E_GL_ARB_shader_group_vote);
-            symbolTable.setFunctionExtensions("allInvocationsARB",      1, &E_GL_ARB_shader_group_vote);
-            symbolTable.setFunctionExtensions("allInvocationsEqualARB", 1, &E_GL_ARB_shader_group_vote);
+            if (version >= 430) {
+                symbolTable.setFunctionExtensions("anyInvocationARB",       1, &E_GL_ARB_shader_group_vote);
+                symbolTable.setFunctionExtensions("allInvocationsARB",      1, &E_GL_ARB_shader_group_vote);
+                symbolTable.setFunctionExtensions("allInvocationsEqualARB", 1, &E_GL_ARB_shader_group_vote);
+            }
         }
         }
 
 
 #ifdef AMD_EXTENSIONS
 #ifdef AMD_EXTENSIONS
@@ -5288,6 +5477,11 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
             symbolTable.setFunctionExtensions("cubeFaceCoordAMD", 1, &E_GL_AMD_gcn_shader);
             symbolTable.setFunctionExtensions("cubeFaceCoordAMD", 1, &E_GL_AMD_gcn_shader);
             symbolTable.setFunctionExtensions("timeAMD",          1, &E_GL_AMD_gcn_shader);
             symbolTable.setFunctionExtensions("timeAMD",          1, &E_GL_AMD_gcn_shader);
         }
         }
+
+        if (profile != EEsProfile) {
+            symbolTable.setFunctionExtensions("fragmentMaskFetchAMD", 1, &E_GL_AMD_shader_fragment_mask);
+            symbolTable.setFunctionExtensions("fragmentFetchAMD",     1, &E_GL_AMD_shader_fragment_mask);
+        }
 #endif
 #endif
 
 
         // Compatibility variables, vertex only
         // Compatibility variables, vertex only
@@ -5312,13 +5506,14 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
                 symbolTable.setFunctionExtensions("texture2DGradEXT",     1, &E_GL_EXT_shader_texture_lod);
                 symbolTable.setFunctionExtensions("texture2DGradEXT",     1, &E_GL_EXT_shader_texture_lod);
                 symbolTable.setFunctionExtensions("texture2DProjGradEXT", 1, &E_GL_EXT_shader_texture_lod);
                 symbolTable.setFunctionExtensions("texture2DProjGradEXT", 1, &E_GL_EXT_shader_texture_lod);
                 symbolTable.setFunctionExtensions("textureCubeGradEXT",   1, &E_GL_EXT_shader_texture_lod);
                 symbolTable.setFunctionExtensions("textureCubeGradEXT",   1, &E_GL_EXT_shader_texture_lod);
-                symbolTable.setFunctionExtensions("textureGatherOffsets", Num_AEP_gpu_shader5, AEP_gpu_shader5);
+                if (version == 310)
+                    symbolTable.setFunctionExtensions("textureGatherOffsets", Num_AEP_gpu_shader5, AEP_gpu_shader5);
             }
             }
-            if (version >= 310)
+            if (version == 310)
                 symbolTable.setFunctionExtensions("fma", Num_AEP_gpu_shader5, AEP_gpu_shader5);
                 symbolTable.setFunctionExtensions("fma", Num_AEP_gpu_shader5, AEP_gpu_shader5);
         }
         }
 
 
-        if (profile == EEsProfile) {
+        if (profile == EEsProfile && version < 320) {
             symbolTable.setFunctionExtensions("imageAtomicAdd",      1, &E_GL_OES_shader_image_atomic);
             symbolTable.setFunctionExtensions("imageAtomicAdd",      1, &E_GL_OES_shader_image_atomic);
             symbolTable.setFunctionExtensions("imageAtomicMin",      1, &E_GL_OES_shader_image_atomic);
             symbolTable.setFunctionExtensions("imageAtomicMin",      1, &E_GL_OES_shader_image_atomic);
             symbolTable.setFunctionExtensions("imageAtomicMax",      1, &E_GL_OES_shader_image_atomic);
             symbolTable.setFunctionExtensions("imageAtomicMax",      1, &E_GL_OES_shader_image_atomic);
@@ -5339,12 +5534,24 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
             BuiltInVariable("gl_InstanceIndex", EbvInstanceIndex, symbolTable);
             BuiltInVariable("gl_InstanceIndex", EbvInstanceIndex, symbolTable);
         }
         }
 
 
+        if (version >= 300 /* both ES and non-ES */) {
+            symbolTable.setVariableExtensions("gl_ViewID_OVR", Num_OVR_multiview_EXTs, OVR_multiview_EXTs);
+            BuiltInVariable("gl_ViewID_OVR", EbvViewIndex, symbolTable);
+        }
+
+        if (profile == EEsProfile) {
+            symbolTable.setFunctionExtensions("shadow2DEXT",        1, &E_GL_EXT_shadow_samplers);
+            symbolTable.setFunctionExtensions("shadow2DProjEXT",    1, &E_GL_EXT_shadow_samplers);
+        }
+
         // Fall through
         // Fall through
 
 
     case EShLangTessControl:
     case EShLangTessControl:
         if (profile == EEsProfile && version >= 310) {
         if (profile == EEsProfile && version >= 310) {
-            symbolTable.setVariableExtensions("gl_BoundingBoxOES", Num_AEP_primitive_bounding_box, AEP_primitive_bounding_box);
             BuiltInVariable("gl_BoundingBoxOES", EbvBoundingBox, symbolTable);
             BuiltInVariable("gl_BoundingBoxOES", EbvBoundingBox, symbolTable);
+            if (version < 320)
+                symbolTable.setVariableExtensions("gl_BoundingBoxOES", Num_AEP_primitive_bounding_box,
+                                                  AEP_primitive_bounding_box);
         }
         }
 
 
         // Fall through
         // Fall through
@@ -5378,6 +5585,14 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
             symbolTable.setVariableExtensions("gl_Layer",         Num_viewportEXTs, viewportEXTs);
             symbolTable.setVariableExtensions("gl_Layer",         Num_viewportEXTs, viewportEXTs);
             symbolTable.setVariableExtensions("gl_ViewportIndex", Num_viewportEXTs, viewportEXTs);
             symbolTable.setVariableExtensions("gl_ViewportIndex", Num_viewportEXTs, viewportEXTs);
         }
         }
+#else
+        if (language != EShLangGeometry && version >= 410) {
+            symbolTable.setVariableExtensions("gl_Layer",         1, &E_GL_ARB_shader_viewport_layer_array);
+            symbolTable.setVariableExtensions("gl_ViewportIndex", 1, &E_GL_ARB_shader_viewport_layer_array);
+        }
+#endif
+
+#ifdef NV_EXTENSIONS
         symbolTable.setVariableExtensions("gl_ViewportMask",            1, &E_GL_NV_viewport_array2);
         symbolTable.setVariableExtensions("gl_ViewportMask",            1, &E_GL_NV_viewport_array2);
         symbolTable.setVariableExtensions("gl_SecondaryPositionNV",     1, &E_GL_NV_stereo_view_rendering);
         symbolTable.setVariableExtensions("gl_SecondaryPositionNV",     1, &E_GL_NV_stereo_view_rendering);
         symbolTable.setVariableExtensions("gl_SecondaryViewportMaskNV", 1, &E_GL_NV_stereo_view_rendering);
         symbolTable.setVariableExtensions("gl_SecondaryViewportMaskNV", 1, &E_GL_NV_stereo_view_rendering);
@@ -5394,8 +5609,6 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
             BuiltInVariable("gl_in", "gl_SecondaryPositionNV", EbvSecondaryPositionNV, symbolTable);
             BuiltInVariable("gl_in", "gl_SecondaryPositionNV", EbvSecondaryPositionNV, symbolTable);
             BuiltInVariable("gl_in", "gl_PositionPerViewNV",   EbvPositionPerViewNV,   symbolTable);
             BuiltInVariable("gl_in", "gl_PositionPerViewNV",   EbvPositionPerViewNV,   symbolTable);
         }
         }
-        BuiltInVariable("gl_out", "gl_Layer",                   EbvLayer,                   symbolTable);
-        BuiltInVariable("gl_out", "gl_ViewportIndex",           EbvViewportIndex,           symbolTable);
         BuiltInVariable("gl_out", "gl_ViewportMask",            EbvViewportMaskNV,          symbolTable);
         BuiltInVariable("gl_out", "gl_ViewportMask",            EbvViewportMaskNV,          symbolTable);
         BuiltInVariable("gl_out", "gl_SecondaryPositionNV",     EbvSecondaryPositionNV,     symbolTable);
         BuiltInVariable("gl_out", "gl_SecondaryPositionNV",     EbvSecondaryPositionNV,     symbolTable);
         BuiltInVariable("gl_out", "gl_SecondaryViewportMaskNV", EbvSecondaryViewportMaskNV, symbolTable);
         BuiltInVariable("gl_out", "gl_SecondaryViewportMaskNV", EbvSecondaryViewportMaskNV, symbolTable);
@@ -5480,13 +5693,18 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
         BuiltInVariable("gl_CullDistance",    EbvCullDistance,   symbolTable);
         BuiltInVariable("gl_CullDistance",    EbvCullDistance,   symbolTable);
         BuiltInVariable("gl_PrimitiveID",     EbvPrimitiveId,    symbolTable);
         BuiltInVariable("gl_PrimitiveID",     EbvPrimitiveId,    symbolTable);
 
 
+        if (profile != EEsProfile && version >= 140) {
+            symbolTable.setVariableExtensions("gl_FragStencilRefARB", 1, &E_GL_ARB_shader_stencil_export);
+            BuiltInVariable("gl_FragStencilRefARB", EbvFragStencilRef, symbolTable);
+        }
+
         if ((profile != EEsProfile && version >= 400) ||
         if ((profile != EEsProfile && version >= 400) ||
             (profile == EEsProfile && version >= 310)) {
             (profile == EEsProfile && version >= 310)) {
             BuiltInVariable("gl_SampleID",        EbvSampleId,       symbolTable);
             BuiltInVariable("gl_SampleID",        EbvSampleId,       symbolTable);
             BuiltInVariable("gl_SamplePosition",  EbvSamplePosition, symbolTable);
             BuiltInVariable("gl_SamplePosition",  EbvSamplePosition, symbolTable);
             BuiltInVariable("gl_SampleMaskIn",    EbvSampleMask,     symbolTable);
             BuiltInVariable("gl_SampleMaskIn",    EbvSampleMask,     symbolTable);
             BuiltInVariable("gl_SampleMask",      EbvSampleMask,     symbolTable);
             BuiltInVariable("gl_SampleMask",      EbvSampleMask,     symbolTable);
-            if (profile == EEsProfile) {
+            if (profile == EEsProfile && version < 320) {
                 symbolTable.setVariableExtensions("gl_SampleID",       1, &E_GL_OES_sample_variables);
                 symbolTable.setVariableExtensions("gl_SampleID",       1, &E_GL_OES_sample_variables);
                 symbolTable.setVariableExtensions("gl_SamplePosition", 1, &E_GL_OES_sample_variables);
                 symbolTable.setVariableExtensions("gl_SamplePosition", 1, &E_GL_OES_sample_variables);
                 symbolTable.setVariableExtensions("gl_SampleMaskIn",   1, &E_GL_OES_sample_variables);
                 symbolTable.setVariableExtensions("gl_SampleMaskIn",   1, &E_GL_OES_sample_variables);
@@ -5520,14 +5738,15 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
                 symbolTable.setFunctionExtensions("texture2DGradEXT",     1, &E_GL_EXT_shader_texture_lod);
                 symbolTable.setFunctionExtensions("texture2DGradEXT",     1, &E_GL_EXT_shader_texture_lod);
                 symbolTable.setFunctionExtensions("texture2DProjGradEXT", 1, &E_GL_EXT_shader_texture_lod);
                 symbolTable.setFunctionExtensions("texture2DProjGradEXT", 1, &E_GL_EXT_shader_texture_lod);
                 symbolTable.setFunctionExtensions("textureCubeGradEXT",   1, &E_GL_EXT_shader_texture_lod);
                 symbolTable.setFunctionExtensions("textureCubeGradEXT",   1, &E_GL_EXT_shader_texture_lod);
-                symbolTable.setFunctionExtensions("textureGatherOffsets", Num_AEP_gpu_shader5, AEP_gpu_shader5);
+                if (version < 320)
+                    symbolTable.setFunctionExtensions("textureGatherOffsets", Num_AEP_gpu_shader5, AEP_gpu_shader5);
             }
             }
             if (version == 100) {
             if (version == 100) {
                 symbolTable.setFunctionExtensions("dFdx",   1, &E_GL_OES_standard_derivatives);
                 symbolTable.setFunctionExtensions("dFdx",   1, &E_GL_OES_standard_derivatives);
                 symbolTable.setFunctionExtensions("dFdy",   1, &E_GL_OES_standard_derivatives);
                 symbolTable.setFunctionExtensions("dFdy",   1, &E_GL_OES_standard_derivatives);
                 symbolTable.setFunctionExtensions("fwidth", 1, &E_GL_OES_standard_derivatives);
                 symbolTable.setFunctionExtensions("fwidth", 1, &E_GL_OES_standard_derivatives);
             }
             }
-            if (version >= 310) {
+            if (version == 310) {
                 symbolTable.setFunctionExtensions("fma", Num_AEP_gpu_shader5, AEP_gpu_shader5);
                 symbolTable.setFunctionExtensions("fma", Num_AEP_gpu_shader5, AEP_gpu_shader5);
                 symbolTable.setFunctionExtensions("interpolateAtCentroid", 1, &E_GL_OES_shader_multisample_interpolation);
                 symbolTable.setFunctionExtensions("interpolateAtCentroid", 1, &E_GL_OES_shader_multisample_interpolation);
                 symbolTable.setFunctionExtensions("interpolateAtSample",   1, &E_GL_OES_shader_multisample_interpolation);
                 symbolTable.setFunctionExtensions("interpolateAtSample",   1, &E_GL_OES_shader_multisample_interpolation);
@@ -5673,16 +5892,30 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
             symbolTable.setFunctionExtensions("sparseTextureGatherLodOffsetAMD",    1, &E_GL_AMD_texture_gather_bias_lod);
             symbolTable.setFunctionExtensions("sparseTextureGatherLodOffsetAMD",    1, &E_GL_AMD_texture_gather_bias_lod);
             symbolTable.setFunctionExtensions("sparseTextureGatherLodOffsetsAMD",   1, &E_GL_AMD_texture_gather_bias_lod);
             symbolTable.setFunctionExtensions("sparseTextureGatherLodOffsetsAMD",   1, &E_GL_AMD_texture_gather_bias_lod);
         }
         }
+
+        // E_GL_AMD_shader_image_load_store_lod
+        if (profile != EEsProfile) {
+            symbolTable.setFunctionExtensions("imageLoadLodAMD",        1, &E_GL_AMD_shader_image_load_store_lod);
+            symbolTable.setFunctionExtensions("imageStoreLodAMD",       1, &E_GL_AMD_shader_image_load_store_lod);
+            symbolTable.setFunctionExtensions("sparseImageLoadLodAMD",  1, &E_GL_AMD_shader_image_load_store_lod);
+        }
+#endif
+
+#ifdef NV_EXTENSIONS
+        if (profile != EEsProfile && version >= 430) {
+            symbolTable.setVariableExtensions("gl_FragFullyCoveredNV", 1, &E_GL_NV_conservative_raster_underestimation);
+            BuiltInVariable("gl_FragFullyCoveredNV", EbvFragFullyCoveredNV, symbolTable);
+        }
 #endif
 #endif
 
 
         symbolTable.setVariableExtensions("gl_FragDepthEXT", 1, &E_GL_EXT_frag_depth);
         symbolTable.setVariableExtensions("gl_FragDepthEXT", 1, &E_GL_EXT_frag_depth);
 
 
-        if (profile == EEsProfile) {
+        if (profile == EEsProfile && version < 320) {
             symbolTable.setVariableExtensions("gl_PrimitiveID",  Num_AEP_geometry_shader, AEP_geometry_shader);
             symbolTable.setVariableExtensions("gl_PrimitiveID",  Num_AEP_geometry_shader, AEP_geometry_shader);
             symbolTable.setVariableExtensions("gl_Layer",        Num_AEP_geometry_shader, AEP_geometry_shader);
             symbolTable.setVariableExtensions("gl_Layer",        Num_AEP_geometry_shader, AEP_geometry_shader);
         }
         }
 
 
-        if (profile == EEsProfile) {
+        if (profile == EEsProfile && version < 320) {
             symbolTable.setFunctionExtensions("imageAtomicAdd",      1, &E_GL_OES_shader_image_atomic);
             symbolTable.setFunctionExtensions("imageAtomicAdd",      1, &E_GL_OES_shader_image_atomic);
             symbolTable.setFunctionExtensions("imageAtomicMin",      1, &E_GL_OES_shader_image_atomic);
             symbolTable.setFunctionExtensions("imageAtomicMin",      1, &E_GL_OES_shader_image_atomic);
             symbolTable.setFunctionExtensions("imageAtomicMax",      1, &E_GL_OES_shader_image_atomic);
             symbolTable.setFunctionExtensions("imageAtomicMax",      1, &E_GL_OES_shader_image_atomic);
@@ -5697,6 +5930,15 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
         BuiltInVariable("gl_DeviceIndex", EbvDeviceIndex, symbolTable);
         BuiltInVariable("gl_DeviceIndex", EbvDeviceIndex, symbolTable);
         symbolTable.setVariableExtensions("gl_ViewIndex", 1, &E_GL_EXT_multiview);
         symbolTable.setVariableExtensions("gl_ViewIndex", 1, &E_GL_EXT_multiview);
         BuiltInVariable("gl_ViewIndex", EbvViewIndex, symbolTable);
         BuiltInVariable("gl_ViewIndex", EbvViewIndex, symbolTable);
+        if (version >= 300 /* both ES and non-ES */) {
+            symbolTable.setVariableExtensions("gl_ViewID_OVR", Num_OVR_multiview_EXTs, OVR_multiview_EXTs);
+            BuiltInVariable("gl_ViewID_OVR", EbvViewIndex, symbolTable);
+        }
+
+        if (profile == EEsProfile) {
+            symbolTable.setFunctionExtensions("shadow2DEXT",        1, &E_GL_EXT_shadow_samplers);
+            symbolTable.setFunctionExtensions("shadow2DProjEXT",    1, &E_GL_EXT_shadow_samplers);
+        }
         break;
         break;
 
 
     case EShLangCompute:
     case EShLangCompute:
@@ -5898,6 +6140,18 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
     symbolTable.relateToOperator("atomicCounterDecrement", EOpAtomicCounterDecrement);
     symbolTable.relateToOperator("atomicCounterDecrement", EOpAtomicCounterDecrement);
     symbolTable.relateToOperator("atomicCounter",          EOpAtomicCounter);
     symbolTable.relateToOperator("atomicCounter",          EOpAtomicCounter);
 
 
+    if (profile != EEsProfile && version >= 460) {
+        symbolTable.relateToOperator("atomicCounterAdd",      EOpAtomicCounterAdd);
+        symbolTable.relateToOperator("atomicCounterSubtract", EOpAtomicCounterSubtract);
+        symbolTable.relateToOperator("atomicCounterMin",      EOpAtomicCounterMin);
+        symbolTable.relateToOperator("atomicCounterMax",      EOpAtomicCounterMax);
+        symbolTable.relateToOperator("atomicCounterAnd",      EOpAtomicCounterAnd);
+        symbolTable.relateToOperator("atomicCounterOr",       EOpAtomicCounterOr);
+        symbolTable.relateToOperator("atomicCounterXor",      EOpAtomicCounterXor);
+        symbolTable.relateToOperator("atomicCounterExchange", EOpAtomicCounterExchange);
+        symbolTable.relateToOperator("atomicCounterCompSwap", EOpAtomicCounterCompSwap);
+    }
+
     symbolTable.relateToOperator("fma",               EOpFma);
     symbolTable.relateToOperator("fma",               EOpFma);
     symbolTable.relateToOperator("frexp",             EOpFrexp);
     symbolTable.relateToOperator("frexp",             EOpFrexp);
     symbolTable.relateToOperator("ldexp",             EOpLdexp);
     symbolTable.relateToOperator("ldexp",             EOpLdexp);
@@ -6049,10 +6303,16 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
             symbolTable.relateToOperator("readInvocationARB",               EOpReadInvocation);
             symbolTable.relateToOperator("readInvocationARB",               EOpReadInvocation);
             symbolTable.relateToOperator("readFirstInvocationARB",          EOpReadFirstInvocation);
             symbolTable.relateToOperator("readFirstInvocationARB",          EOpReadFirstInvocation);
 
 
-            symbolTable.relateToOperator("anyInvocationARB",                EOpAnyInvocation);
-            symbolTable.relateToOperator("allInvocationsARB",               EOpAllInvocations);
-            symbolTable.relateToOperator("allInvocationsEqualARB",          EOpAllInvocationsEqual);
-
+            if (version >= 430) {
+                symbolTable.relateToOperator("anyInvocationARB",            EOpAnyInvocation);
+                symbolTable.relateToOperator("allInvocationsARB",           EOpAllInvocations);
+                symbolTable.relateToOperator("allInvocationsEqualARB",      EOpAllInvocationsEqual);
+            }
+            if (version >= 460) {
+                symbolTable.relateToOperator("anyInvocation",               EOpAnyInvocation);
+                symbolTable.relateToOperator("allInvocations",              EOpAllInvocations);
+                symbolTable.relateToOperator("allInvocationsEqual",         EOpAllInvocationsEqual);
+            }
 #ifdef AMD_EXTENSIONS
 #ifdef AMD_EXTENSIONS
             symbolTable.relateToOperator("minInvocationsAMD",                           EOpMinInvocations);
             symbolTable.relateToOperator("minInvocationsAMD",                           EOpMinInvocations);
             symbolTable.relateToOperator("maxInvocationsAMD",                           EOpMaxInvocations);
             symbolTable.relateToOperator("maxInvocationsAMD",                           EOpMaxInvocations);
@@ -6091,8 +6351,19 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
             symbolTable.relateToOperator("sparseTextureGatherLodAMD",           EOpSparseTextureGatherLod);
             symbolTable.relateToOperator("sparseTextureGatherLodAMD",           EOpSparseTextureGatherLod);
             symbolTable.relateToOperator("sparseTextureGatherLodOffsetAMD",     EOpSparseTextureGatherLodOffset);
             symbolTable.relateToOperator("sparseTextureGatherLodOffsetAMD",     EOpSparseTextureGatherLodOffset);
             symbolTable.relateToOperator("sparseTextureGatherLodOffsetsAMD",    EOpSparseTextureGatherLodOffsets);
             symbolTable.relateToOperator("sparseTextureGatherLodOffsetsAMD",    EOpSparseTextureGatherLodOffsets);
+
+            symbolTable.relateToOperator("imageLoadLodAMD",                     EOpImageLoadLod);
+            symbolTable.relateToOperator("imageStoreLodAMD",                    EOpImageStoreLod);
+            symbolTable.relateToOperator("sparseImageLoadLodAMD",               EOpSparseImageLoadLod);
+
+            symbolTable.relateToOperator("fragmentMaskFetchAMD",                EOpFragmentMaskFetch);
+            symbolTable.relateToOperator("fragmentFetchAMD",                    EOpFragmentFetch);
 #endif
 #endif
         }
         }
+        if (profile == EEsProfile) {
+            symbolTable.relateToOperator("shadow2DEXT",              EOpTexture);
+            symbolTable.relateToOperator("shadow2DProjEXT",          EOpTextureProj);
+        }
     }
     }
 
 
     switch(language) {
     switch(language) {

+ 63 - 16
src/libraries/glslang/glslang/MachineIndependent/Initialize.h

@@ -1043,6 +1043,32 @@ TIntermTyped* TIntermediate::addShapeConversion(const TType& type, TIntermTyped*
     // The new node that handles the conversion
     // The new node that handles the conversion
     TOperator constructorOp = mapTypeToConstructorOp(type);
     TOperator constructorOp = mapTypeToConstructorOp(type);
 
 
+    // HLSL has custom semantics for scalar->mat shape conversions.
+    if (source == EShSourceHlsl) {
+        if (node->getType().isScalarOrVec1() && type.isMatrix()) {
+
+            // HLSL semantics: the scalar (or vec1) is replicated to every component of the matrix.  Left to its
+            // own devices, the constructor from a scalar would populate the diagonal.  This forces replication
+            // to every matrix element.
+
+            // Note that if the node is complex (e.g, a function call), we don't want to duplicate it here
+            // repeatedly, so we copy it to a temp, then use the temp.
+            const int matSize = type.getMatrixRows() * type.getMatrixCols();
+            TIntermAggregate* rhsAggregate = new TIntermAggregate();
+
+            const bool isSimple = (node->getAsSymbolNode() != nullptr) || (node->getAsConstantUnion() != nullptr);
+
+            if (!isSimple) {
+                assert(0); // TODO: use node replicator service when available.
+            }
+            
+            for (int x=0; x<matSize; ++x)
+                rhsAggregate->getSequence().push_back(node);
+
+            return setAggregateOperator(rhsAggregate, constructorOp, type, node->getLoc());
+        }
+    }
+
     // scalar -> vector or vec1 -> vector or
     // scalar -> vector or vec1 -> vector or
     // vector -> scalar or
     // vector -> scalar or
     // bigger vector -> smaller vector
     // bigger vector -> smaller vector
@@ -1588,7 +1614,7 @@ TIntermAggregate* TIntermediate::makeAggregate(const TSourceLoc& loc)
 //
 //
 // Returns the selection node created.
 // Returns the selection node created.
 //
 //
-TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc& loc)
+TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc& loc, TSelectionControl control)
 {
 {
     //
     //
     // Don't prune the false path for compile-time constants; it's needed
     // Don't prune the false path for compile-time constants; it's needed
@@ -1597,6 +1623,7 @@ TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair no
 
 
     TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
     TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
     node->setLoc(loc);
     node->setLoc(loc);
+    node->setSelectionControl(control);
 
 
     return node;
     return node;
 }
 }
@@ -1639,12 +1666,12 @@ TIntermTyped* TIntermediate::addMethod(TIntermTyped* object, const TType& type,
 //
 //
 // Returns the selection node created, or nullptr if one could not be.
 // Returns the selection node created, or nullptr if one could not be.
 //
 //
-TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc& loc)
+TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc& loc, TSelectionControl control)
 {
 {
     // If it's void, go to the if-then-else selection()
     // If it's void, go to the if-then-else selection()
     if (trueBlock->getBasicType() == EbtVoid && falseBlock->getBasicType() == EbtVoid) {
     if (trueBlock->getBasicType() == EbtVoid && falseBlock->getBasicType() == EbtVoid) {
         TIntermNodePair pair = { trueBlock, falseBlock };
         TIntermNodePair pair = { trueBlock, falseBlock };
-        return addSelection(cond, pair, loc);
+        return addSelection(cond, pair, loc, control);
     }
     }
 
 
     //
     //
@@ -2447,6 +2474,11 @@ bool TIntermediate::promoteBinary(TIntermBinary& node)
                 return false;
                 return false;
             node.setLeft(left);
             node.setLeft(left);
             node.setRight(right);
             node.setRight(right);
+
+            // Update the original base assumption on result type..
+            node.setType(left->getType());
+            node.getWritableType().getQualifier().clear();
+
             break;
             break;
 
 
         default:
         default:
@@ -3143,10 +3175,10 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC
                             node->getLoc());
                             node->getLoc());
 }
 }
 
 
-void TIntermAggregate::addToPragmaTable(const TPragmaTable& pTable)
+void TIntermAggregate::setPragmaTable(const TPragmaTable& pTable)
 {
 {
-    assert(!pragmaTable);
-    pragmaTable = new TPragmaTable();
+    assert(pragmaTable == nullptr);
+    pragmaTable = new TPragmaTable;
     *pragmaTable = pTable;
     *pragmaTable = pTable;
 }
 }
 
 
@@ -3160,6 +3192,11 @@ bool TIntermediate::specConstantPropagates(const TIntermTyped& node1, const TInt
 }
 }
 
 
 struct TextureUpgradeAndSamplerRemovalTransform : public TIntermTraverser {
 struct TextureUpgradeAndSamplerRemovalTransform : public TIntermTraverser {
+    void visitSymbol(TIntermSymbol* symbol) override {
+        if (symbol->getBasicType() == EbtSampler && symbol->getType().getSampler().isTexture()) {
+            symbol->getWritableType().getSampler().combined = true;
+        }
+    }
     bool visitAggregate(TVisit, TIntermAggregate* ag) override {
     bool visitAggregate(TVisit, TIntermAggregate* ag) override {
         using namespace std;
         using namespace std;
         TIntermSequence& seq = ag->getSequence();
         TIntermSequence& seq = ag->getSequence();
@@ -3173,17 +3210,11 @@ struct TextureUpgradeAndSamplerRemovalTransform : public TIntermTraverser {
         });
         });
         seq.erase(newEnd, seq.end());
         seq.erase(newEnd, seq.end());
         // replace constructors with sampler/textures
         // replace constructors with sampler/textures
-        // update textures into sampled textures
         for_each(seq.begin(), seq.end(), [](TIntermNode*& node) {
         for_each(seq.begin(), seq.end(), [](TIntermNode*& node) {
-            TIntermSymbol* symbol = node->getAsSymbolNode();
-            if (!symbol) {
-                TIntermAggregate *constructor = node->getAsAggregate();
-                if (constructor && constructor->getOp() == EOpConstructTextureSampler) {
-                    if (!constructor->getSequence().empty())
-                        node = constructor->getSequence()[0];
-                }
-            } else if (symbol->getBasicType() == EbtSampler && symbol->getType().getSampler().isTexture()) {
-                symbol->getWritableType().getSampler().combined = true;
+            TIntermAggregate *constructor = node->getAsAggregate();
+            if (constructor && constructor->getOp() == EOpConstructTextureSampler) {
+                if (!constructor->getSequence().empty())
+                    node = constructor->getSequence()[0];
             }
             }
         });
         });
         return true;
         return true;
@@ -3196,4 +3227,20 @@ void TIntermediate::performTextureUpgradeAndSamplerRemovalTransformation(TInterm
     root->traverse(&transform);
     root->traverse(&transform);
 }
 }
 
 
+const char* TIntermediate::getResourceName(TResourceType res)
+{
+    switch (res) {
+    case EResSampler: return "shift-sampler-binding";
+    case EResTexture: return "shift-texture-binding";
+    case EResImage:   return "shift-image-binding";
+    case EResUbo:     return "shift-UBO-binding";
+    case EResSsbo:    return "shift-ssbo-binding";
+    case EResUav:     return "shift-uav-binding";
+    default:
+        assert(0); // internal error: should only be called with valid resource types.
+        return nullptr;
+    }
+}
+
+
 } // end namespace glslang
 } // end namespace glslang

+ 29 - 0
src/libraries/glslang/glslang/MachineIndependent/LiveTraverser.h

@@ -234,6 +234,31 @@ void TParseContextBase::trackLinkage(TSymbol& symbol)
         linkageSymbols.push_back(&symbol);
         linkageSymbols.push_back(&symbol);
 }
 }
 
 
+// Ensure index is in bounds, correct if necessary.
+// Give an error if not.
+void TParseContextBase::checkIndex(const TSourceLoc& loc, const TType& type, int& index)
+{
+    if (index < 0) {
+        error(loc, "", "[", "index out of range '%d'", index);
+        index = 0;
+    } else if (type.isArray()) {
+        if (type.isExplicitlySizedArray() && index >= type.getOuterArraySize()) {
+            error(loc, "", "[", "array index out of range '%d'", index);
+            index = type.getOuterArraySize() - 1;
+        }
+    } else if (type.isVector()) {
+        if (index >= type.getVectorSize()) {
+            error(loc, "", "[", "vector index out of range '%d'", index);
+            index = type.getVectorSize() - 1;
+        }
+    } else if (type.isMatrix()) {
+        if (index >= type.getMatrixCols()) {
+            error(loc, "", "[", "matrix index out of range '%d'", index);
+            index = type.getMatrixCols() - 1;
+        }
+    }
+}
+
 // Make a shared symbol have a non-shared version that can be edited by the current
 // Make a shared symbol have a non-shared version that can be edited by the current
 // compile, such that editing its type will not change the shared version and will
 // compile, such that editing its type will not change the shared version and will
 // effect all nodes already sharing it (non-shallow type),
 // effect all nodes already sharing it (non-shallow type),
@@ -544,6 +569,10 @@ void TParseContextBase::growGlobalUniformBlock(const TSourceLoc& loc, TType& mem
         firstNewMember = 0;
         firstNewMember = 0;
     }
     }
 
 
+    // Update with binding and set
+    globalUniformBlock->getWritableType().getQualifier().layoutBinding = globalUniformBinding;
+    globalUniformBlock->getWritableType().getQualifier().layoutSet = globalUniformSet;
+
     // Add the requested member as a member to the global block.
     // Add the requested member as a member to the global block.
     TType* type = new TType;
     TType* type = new TType;
     type->shallowCopy(memberType);
     type->shallowCopy(memberType);

+ 166 - 93
src/libraries/glslang/glslang/MachineIndependent/ParseHelper.cpp

@@ -49,8 +49,10 @@ namespace glslang {
 
 
 TParseContext::TParseContext(TSymbolTable& symbolTable, TIntermediate& interm, bool parsingBuiltins,
 TParseContext::TParseContext(TSymbolTable& symbolTable, TIntermediate& interm, bool parsingBuiltins,
                              int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language,
                              int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language,
-                             TInfoSink& infoSink, bool forwardCompatible, EShMessages messages) :
-            TParseContextBase(symbolTable, interm, parsingBuiltins, version, profile, spvVersion, language, infoSink, forwardCompatible, messages),
+                             TInfoSink& infoSink, bool forwardCompatible, EShMessages messages,
+                             const TString* entryPoint) :
+            TParseContextBase(symbolTable, interm, parsingBuiltins, version, profile, spvVersion, language,
+                              infoSink, forwardCompatible, messages, entryPoint),
             inMain(false),
             inMain(false),
             blockName(nullptr),
             blockName(nullptr),
             limits(resources.limits),
             limits(resources.limits),
@@ -87,6 +89,9 @@ TParseContext::TParseContext(TSymbolTable& symbolTable, TIntermediate& interm, b
 
 
     if (language == EShLangGeometry)
     if (language == EShLangGeometry)
         globalOutputDefaults.layoutStream = 0;
         globalOutputDefaults.layoutStream = 0;
+
+    if (entryPoint != nullptr && entryPoint->size() > 0 && *entryPoint != "main")
+        infoSink.info.message(EPrefixError, "Source entry point must be \"main\"");
 }
 }
 
 
 TParseContext::~TParseContext()
 TParseContext::~TParseContext()
@@ -121,11 +126,6 @@ void TParseContext::setPrecisionDefaults()
             sampler.set(EbtFloat, Esd2D);
             sampler.set(EbtFloat, Esd2D);
             sampler.external = true;
             sampler.external = true;
             defaultSamplerPrecision[computeSamplerTypeIndex(sampler)] = EpqLow;
             defaultSamplerPrecision[computeSamplerTypeIndex(sampler)] = EpqLow;
-        } else {
-            // Non-ES profile
-            // All default to highp.
-            for (int type = 0; type < maxSamplerIndex; ++type)
-                defaultSamplerPrecision[type] = EpqHigh;
         }
         }
 
 
         // If we are parsing built-in computational variables/functions, it is meaningful to record
         // If we are parsing built-in computational variables/functions, it is meaningful to record
@@ -141,6 +141,13 @@ void TParseContext::setPrecisionDefaults()
                 defaultPrecision[EbtUint] = EpqHigh;
                 defaultPrecision[EbtUint] = EpqHigh;
                 defaultPrecision[EbtFloat] = EpqHigh;
                 defaultPrecision[EbtFloat] = EpqHigh;
             }
             }
+
+            if (profile != EEsProfile) {
+                // Non-ES profile
+                // All sampler precisions default to highp.
+                for (int type = 0; type < maxSamplerIndex; ++type)
+                    defaultSamplerPrecision[type] = EpqHigh;
+            }
         }
         }
 
 
         defaultPrecision[EbtSampler] = EpqLow;
         defaultPrecision[EbtSampler] = EpqLow;
@@ -382,7 +389,8 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn
                 if (base->getQualifier().storage == EvqBuffer)
                 if (base->getQualifier().storage == EvqBuffer)
                     requireProfile(base->getLoc(), ~EEsProfile, "variable indexing buffer block array");
                     requireProfile(base->getLoc(), ~EEsProfile, "variable indexing buffer block array");
                 else if (base->getQualifier().storage == EvqUniform)
                 else if (base->getQualifier().storage == EvqUniform)
-                    profileRequires(base->getLoc(), EEsProfile, 0, Num_AEP_gpu_shader5, AEP_gpu_shader5, "variable indexing uniform block array");
+                    profileRequires(base->getLoc(), EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5,
+                                    "variable indexing uniform block array");
                 else {
                 else {
                     // input/output blocks either don't exist or can be variable indexed
                     // input/output blocks either don't exist or can be variable indexed
                 }
                 }
@@ -391,7 +399,7 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn
             else if (base->getBasicType() == EbtSampler && version >= 130) {
             else if (base->getBasicType() == EbtSampler && version >= 130) {
                 const char* explanation = "variable indexing sampler array";
                 const char* explanation = "variable indexing sampler array";
                 requireProfile(base->getLoc(), EEsProfile | ECoreProfile | ECompatibilityProfile, explanation);
                 requireProfile(base->getLoc(), EEsProfile | ECoreProfile | ECompatibilityProfile, explanation);
-                profileRequires(base->getLoc(), EEsProfile, 0, Num_AEP_gpu_shader5, AEP_gpu_shader5, explanation);
+                profileRequires(base->getLoc(), EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5, explanation);
                 profileRequires(base->getLoc(), ECoreProfile | ECompatibilityProfile, 400, nullptr, explanation);
                 profileRequires(base->getLoc(), ECoreProfile | ECompatibilityProfile, 400, nullptr, explanation);
             }
             }
 
 
@@ -423,29 +431,6 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn
     return result;
     return result;
 }
 }
 
 
-void TParseContext::checkIndex(const TSourceLoc& loc, const TType& type, int& index)
-{
-    if (index < 0) {
-        error(loc, "", "[", "index out of range '%d'", index);
-        index = 0;
-    } else if (type.isArray()) {
-        if (type.isExplicitlySizedArray() && index >= type.getOuterArraySize()) {
-            error(loc, "", "[", "array index out of range '%d'", index);
-            index = type.getOuterArraySize() - 1;
-        }
-    } else if (type.isVector()) {
-        if (index >= type.getVectorSize()) {
-            error(loc, "", "[", "vector index out of range '%d'", index);
-            index = type.getVectorSize() - 1;
-        }
-    } else if (type.isMatrix()) {
-        if (index >= type.getMatrixCols()) {
-            error(loc, "", "[", "matrix index out of range '%d'", index);
-            index = type.getMatrixCols() - 1;
-        }
-    }
-}
-
 // for ES 2.0 (version 100) limitations for almost all index operations except vertex-shader uniforms
 // for ES 2.0 (version 100) limitations for almost all index operations except vertex-shader uniforms
 void TParseContext::handleIndexLimits(const TSourceLoc& /*loc*/, TIntermTyped* base, TIntermTyped* index)
 void TParseContext::handleIndexLimits(const TSourceLoc& /*loc*/, TIntermTyped* base, TIntermTyped* index)
 {
 {
@@ -680,7 +665,8 @@ TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TInterm
     // leaving swizzles and struct/block dereferences.
     // leaving swizzles and struct/block dereferences.
 
 
     TIntermTyped* result = base;
     TIntermTyped* result = base;
-    if (base->isVector() || base->isScalar()) {
+    if ((base->isVector() || base->isScalar()) &&
+        (base->isFloatingDomain() || base->isIntegerDomain() || base->getBasicType() == EbtBool)) {
         if (base->isScalar()) {
         if (base->isScalar()) {
             const char* dotFeature = "scalar swizzle";
             const char* dotFeature = "scalar swizzle";
             requireProfile(loc, ~EEsProfile, dotFeature);
             requireProfile(loc, ~EEsProfile, dotFeature);
@@ -1142,7 +1128,13 @@ void TParseContext::computeBuiltinPrecisions(TIntermTyped& node, const TFunction
             operationPrecision = std::max(operationPrecision, function[arg].type->getQualifier().precision);
             operationPrecision = std::max(operationPrecision, function[arg].type->getQualifier().precision);
         }
         }
         // compute the result precision
         // compute the result precision
+#ifdef AMD_EXTENSIONS
+        if (agg->isSampling() ||
+            agg->getOp() == EOpImageLoad || agg->getOp() == EOpImageStore ||
+            agg->getOp() == EOpImageLoadLod || agg->getOp() == EOpImageStoreLod)
+#else
         if (agg->isSampling() || agg->getOp() == EOpImageLoad || agg->getOp() == EOpImageStore)
         if (agg->isSampling() || agg->getOp() == EOpImageLoad || agg->getOp() == EOpImageStore)
+#endif
             resultPrecision = sequence[0]->getAsTyped()->getQualifier().precision;
             resultPrecision = sequence[0]->getAsTyped()->getQualifier().precision;
         else if (function.getType().getBasicType() != EbtBool)
         else if (function.getType().getBasicType() != EbtBool)
             resultPrecision = function.getType().getQualifier().precision == EpqNone ?
             resultPrecision = function.getType().getQualifier().precision == EpqNone ?
@@ -1385,8 +1377,9 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
         unaryArg = callNode.getAsUnaryNode()->getOperand();
         unaryArg = callNode.getAsUnaryNode()->getOperand();
         arg0 = unaryArg;
         arg0 = unaryArg;
     }
     }
-    const TIntermSequence& aggArgs = *argp;  // only valid when unaryArg is nullptr
 
 
+    TString featureString;
+    const char* feature = nullptr;
     switch (callNode.getOp()) {
     switch (callNode.getOp()) {
     case EOpTextureGather:
     case EOpTextureGather:
     case EOpTextureGatherOffset:
     case EOpTextureGatherOffset:
@@ -1395,8 +1388,8 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
         // Figure out which variants are allowed by what extensions,
         // Figure out which variants are allowed by what extensions,
         // and what arguments must be constant for which situations.
         // and what arguments must be constant for which situations.
 
 
-        TString featureString = fnCandidate.getName() + "(...)";
-        const char* feature = featureString.c_str();
+        featureString = fnCandidate.getName() + "(...)";
+        feature = featureString.c_str();
         profileRequires(loc, EEsProfile, 310, nullptr, feature);
         profileRequires(loc, EEsProfile, 310, nullptr, feature);
         int compArg = -1;  // track which argument, if any, is the constant component argument
         int compArg = -1;  // track which argument, if any, is the constant component argument
         switch (callNode.getOp()) {
         switch (callNode.getOp()) {
@@ -1416,8 +1409,9 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
                 profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_texture_gather, feature);
                 profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_texture_gather, feature);
             else
             else
                 profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature);
                 profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature);
-            if (! aggArgs[fnCandidate[0].type->getSampler().shadow ? 3 : 2]->getAsConstantUnion())
-                profileRequires(loc, EEsProfile, 0, Num_AEP_gpu_shader5, AEP_gpu_shader5, "non-constant offset argument");
+            if (! (*argp)[fnCandidate[0].type->getSampler().shadow ? 3 : 2]->getAsConstantUnion())
+                profileRequires(loc, EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5,
+                                "non-constant offset argument");
             if (! fnCandidate[0].type->getSampler().shadow)
             if (! fnCandidate[0].type->getSampler().shadow)
                 compArg = 3;
                 compArg = 3;
             break;
             break;
@@ -1426,7 +1420,7 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
             if (! fnCandidate[0].type->getSampler().shadow)
             if (! fnCandidate[0].type->getSampler().shadow)
                 compArg = 3;
                 compArg = 3;
             // check for constant offsets
             // check for constant offsets
-            if (! aggArgs[fnCandidate[0].type->getSampler().shadow ? 3 : 2]->getAsConstantUnion())
+            if (! (*argp)[fnCandidate[0].type->getSampler().shadow ? 3 : 2]->getAsConstantUnion())
                 error(loc, "must be a compile-time constant:", feature, "offsets argument");
                 error(loc, "must be a compile-time constant:", feature, "offsets argument");
             break;
             break;
         default:
         default:
@@ -1434,8 +1428,8 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
         }
         }
 
 
         if (compArg > 0 && compArg < fnCandidate.getParamCount()) {
         if (compArg > 0 && compArg < fnCandidate.getParamCount()) {
-            if (aggArgs[compArg]->getAsConstantUnion()) {
-                int value = aggArgs[compArg]->getAsConstantUnion()->getConstArray()[0].getIConst();
+            if ((*argp)[compArg]->getAsConstantUnion()) {
+                int value = (*argp)[compArg]->getAsConstantUnion()->getConstArray()[0].getIConst();
                 if (value < 0 || value > 3)
                 if (value < 0 || value > 3)
                     error(loc, "must be 0, 1, 2, or 3:", feature, "component argument");
                     error(loc, "must be 0, 1, 2, or 3:", feature, "component argument");
             } else
             } else
@@ -1451,8 +1445,8 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
             bias = fnCandidate.getParamCount() > 4;
             bias = fnCandidate.getParamCount() > 4;
 
 
         if (bias) {
         if (bias) {
-            TString biasFeatureString = fnCandidate.getName() + "with bias argument";
-            const char* feature = biasFeatureString.c_str();
+            featureString = fnCandidate.getName() + "with bias argument";
+            feature = featureString.c_str();
             profileRequires(loc, ~EEsProfile, 450, nullptr, feature);
             profileRequires(loc, ~EEsProfile, 450, nullptr, feature);
             requireExtensions(loc, 1, &E_GL_AMD_texture_gather_bias_lod, feature);
             requireExtensions(loc, 1, &E_GL_AMD_texture_gather_bias_lod, feature);
         }
         }
@@ -1474,8 +1468,8 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
             bias = fnCandidate.getParamCount() > 5;
             bias = fnCandidate.getParamCount() > 5;
 
 
         if (bias) {
         if (bias) {
-            TString featureString = fnCandidate.getName() + "with bias argument";
-            const char* feature = featureString.c_str();
+            featureString = fnCandidate.getName() + "with bias argument";
+            feature = featureString.c_str();
             profileRequires(loc, ~EEsProfile, 450, nullptr, feature);
             profileRequires(loc, ~EEsProfile, 450, nullptr, feature);
             requireExtensions(loc, 1, &E_GL_AMD_texture_gather_bias_lod, feature);
             requireExtensions(loc, 1, &E_GL_AMD_texture_gather_bias_lod, feature);
         }
         }
@@ -1517,12 +1511,12 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
         }
         }
 
 
         if (arg > 0) {
         if (arg > 0) {
-            if (! aggArgs[arg]->getAsConstantUnion())
+            if (! (*argp)[arg]->getAsConstantUnion())
                 error(loc, "argument must be compile-time constant", "texel offset", "");
                 error(loc, "argument must be compile-time constant", "texel offset", "");
             else {
             else {
-                const TType& type = aggArgs[arg]->getAsTyped()->getType();
+                const TType& type = (*argp)[arg]->getAsTyped()->getType();
                 for (int c = 0; c < type.getVectorSize(); ++c) {
                 for (int c = 0; c < type.getVectorSize(); ++c) {
-                    int offset = aggArgs[arg]->getAsConstantUnion()->getConstArray()[c].getIConst();
+                    int offset = (*argp)[arg]->getAsConstantUnion()->getConstArray()[c].getIConst();
                     if (offset > resources.maxProgramTexelOffset || offset < resources.minProgramTexelOffset)
                     if (offset > resources.maxProgramTexelOffset || offset < resources.minProgramTexelOffset)
                         error(loc, "value is out of range:", "texel offset", "[gl_MinProgramTexelOffset, gl_MaxProgramTexelOffset]");
                         error(loc, "value is out of range:", "texel offset", "[gl_MinProgramTexelOffset, gl_MaxProgramTexelOffset]");
                 }
                 }
@@ -1562,6 +1556,23 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
         break;
         break;
     }
     }
 
 
+#ifdef NV_EXTENSIONS
+    case EOpAtomicAdd:
+    case EOpAtomicMin:
+    case EOpAtomicMax:
+    case EOpAtomicAnd:
+    case EOpAtomicOr:
+    case EOpAtomicXor:
+    case EOpAtomicExchange:
+    case EOpAtomicCompSwap:
+    {
+        if (arg0->getType().getBasicType() == EbtInt64 || arg0->getType().getBasicType() == EbtUint64)
+            requireExtensions(loc, 1, &E_GL_NV_shader_atomic_int64, fnCandidate.getName().c_str());
+
+        break;
+    }
+#endif
+
     case EOpInterpolateAtCentroid:
     case EOpInterpolateAtCentroid:
     case EOpInterpolateAtSample:
     case EOpInterpolateAtSample:
     case EOpInterpolateAtOffset:
     case EOpInterpolateAtOffset:
@@ -1631,7 +1642,8 @@ void TParseContext::nonOpBuiltInCheck(const TSourceLoc& loc, const TFunction& fn
                     profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature);
                     profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature);
                 int offsetArg = fnCandidate[0].type->getSampler().shadow ? 3 : 2;
                 int offsetArg = fnCandidate[0].type->getSampler().shadow ? 3 : 2;
                 if (! callNode.getSequence()[offsetArg]->getAsConstantUnion())
                 if (! callNode.getSequence()[offsetArg]->getAsConstantUnion())
-                    profileRequires(loc, EEsProfile, 0, Num_AEP_gpu_shader5, AEP_gpu_shader5, "non-constant offset argument");
+                    profileRequires(loc, EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5,
+                                    "non-constant offset argument");
                 if (! fnCandidate[0].type->getSampler().shadow)
                 if (! fnCandidate[0].type->getSampler().shadow)
                     compArg = 3;
                     compArg = 3;
             } else if (fnCandidate.getName().compare("textureGatherOffsets") == 0) {
             } else if (fnCandidate.getName().compare("textureGatherOffsets") == 0) {
@@ -2448,6 +2460,16 @@ void TParseContext::boolCheck(const TSourceLoc& loc, const TPublicType& pType)
 
 
 void TParseContext::samplerCheck(const TSourceLoc& loc, const TType& type, const TString& identifier, TIntermTyped* /*initializer*/)
 void TParseContext::samplerCheck(const TSourceLoc& loc, const TType& type, const TString& identifier, TIntermTyped* /*initializer*/)
 {
 {
+    // Check that the appropriate extension is enabled if external sampler is used.
+    // There are two extensions. The correct one must be used based on GLSL version.
+    if (type.getBasicType() == EbtSampler && type.getSampler().external) {
+        if (version < 300) {
+            requireExtensions(loc, 1, &E_GL_OES_EGL_image_external, "samplerExternalOES");
+        } else {
+            requireExtensions(loc, 1, &E_GL_OES_EGL_image_external_essl3, "samplerExternalOES");
+        }
+    }
+
     if (type.getQualifier().storage == EvqUniform)
     if (type.getQualifier().storage == EvqUniform)
         return;
         return;
 
 
@@ -2472,16 +2494,22 @@ void TParseContext::atomicUintCheck(const TSourceLoc& loc, const TType& type, co
         error(loc, "atomic_uints can only be used in uniform variables or function parameters:", type.getBasicTypeString().c_str(), identifier.c_str());
         error(loc, "atomic_uints can only be used in uniform variables or function parameters:", type.getBasicTypeString().c_str(), identifier.c_str());
 }
 }
 
 
-void TParseContext::transparentCheck(const TSourceLoc& loc, const TType& type, const TString& /*identifier*/)
+void TParseContext::transparentOpaqueCheck(const TSourceLoc& loc, const TType& type, const TString& identifier)
 {
 {
     if (parsingBuiltins)
     if (parsingBuiltins)
         return;
         return;
 
 
-    // Vulkan doesn't allow transparent uniforms outside of blocks
-    if (spvVersion.vulkan == 0 || type.getQualifier().storage != EvqUniform)
+    if (type.getQualifier().storage != EvqUniform)
         return;
         return;
-    if (type.containsNonOpaque())
-        vulkanRemoved(loc, "non-opaque uniforms outside a block");
+
+    if (type.containsNonOpaque()) {
+        // Vulkan doesn't allow transparent uniforms outside of blocks
+        if (spvVersion.vulkan > 0)
+            vulkanRemoved(loc, "non-opaque uniforms outside a block");
+        // OpenGL wants locations on these (unless they are getting automapped)
+        if (spvVersion.openGl > 0 && !type.getQualifier().hasLocation() && !intermediate.getAutoMapLocations())
+            error(loc, "non-opaque uniform variables need a layout(location=L)", identifier.c_str(), "");
+    }
 }
 }
 
 
 //
 //
@@ -2534,7 +2562,7 @@ void TParseContext::globalQualifierTypeCheck(const TSourceLoc& loc, const TQuali
 
 
     // now, knowing it is a shader in/out, do all the in/out semantic checks
     // now, knowing it is a shader in/out, do all the in/out semantic checks
 
 
-    if (publicType.basicType == EbtBool) {
+    if (publicType.basicType == EbtBool && !parsingBuiltins) {
         error(loc, "cannot be bool", GetStorageQualifierString(qualifier.storage), "");
         error(loc, "cannot be bool", GetStorageQualifierString(qualifier.storage), "");
         return;
         return;
     }
     }
@@ -2976,7 +3004,7 @@ void TParseContext::structArrayCheck(const TSourceLoc& /*loc*/, const TType& typ
     }
     }
 }
 }
 
 
-void TParseContext::arraySizesCheck(const TSourceLoc& loc, const TQualifier& qualifier, const TArraySizes* arraySizes, bool initializer, bool lastMember)
+void TParseContext::arraySizesCheck(const TSourceLoc& loc, const TQualifier& qualifier, TArraySizes* arraySizes, bool initializer, bool lastMember)
 {
 {
     assert(arraySizes);
     assert(arraySizes);
 
 
@@ -2989,8 +3017,10 @@ void TParseContext::arraySizesCheck(const TSourceLoc& loc, const TQualifier& qua
         return;
         return;
 
 
     // No environment allows any non-outer-dimension to be implicitly sized
     // No environment allows any non-outer-dimension to be implicitly sized
-    if (arraySizes->isInnerImplicit())
+    if (arraySizes->isInnerImplicit()) {
         error(loc, "only outermost dimension of an array of arrays can be implicitly sized", "[]", "");
         error(loc, "only outermost dimension of an array of arrays can be implicitly sized", "[]", "");
+        arraySizes->clearInnerImplicit();
+    }
 
 
     if (arraySizes->isInnerSpecialization())
     if (arraySizes->isInnerSpecialization())
         error(loc, "only outermost dimension of an array of arrays can be a specialization constant", "[]", "");
         error(loc, "only outermost dimension of an array of arrays can be a specialization constant", "[]", "");
@@ -3010,19 +3040,22 @@ void TParseContext::arraySizesCheck(const TSourceLoc& loc, const TQualifier& qua
     switch (language) {
     switch (language) {
     case EShLangGeometry:
     case EShLangGeometry:
         if (qualifier.storage == EvqVaryingIn)
         if (qualifier.storage == EvqVaryingIn)
-            if (extensionsTurnedOn(Num_AEP_geometry_shader, AEP_geometry_shader))
+            if ((profile == EEsProfile && version >= 320) ||
+                extensionsTurnedOn(Num_AEP_geometry_shader, AEP_geometry_shader))
                 return;
                 return;
         break;
         break;
     case EShLangTessControl:
     case EShLangTessControl:
         if ( qualifier.storage == EvqVaryingIn ||
         if ( qualifier.storage == EvqVaryingIn ||
             (qualifier.storage == EvqVaryingOut && ! qualifier.patch))
             (qualifier.storage == EvqVaryingOut && ! qualifier.patch))
-            if (extensionsTurnedOn(Num_AEP_tessellation_shader, AEP_tessellation_shader))
+            if ((profile == EEsProfile && version >= 320) ||
+                extensionsTurnedOn(Num_AEP_tessellation_shader, AEP_tessellation_shader))
                 return;
                 return;
         break;
         break;
     case EShLangTessEvaluation:
     case EShLangTessEvaluation:
         if ((qualifier.storage == EvqVaryingIn && ! qualifier.patch) ||
         if ((qualifier.storage == EvqVaryingIn && ! qualifier.patch) ||
              qualifier.storage == EvqVaryingOut)
              qualifier.storage == EvqVaryingOut)
-            if (extensionsTurnedOn(Num_AEP_tessellation_shader, AEP_tessellation_shader))
+            if ((profile == EEsProfile && version >= 320) ||
+                extensionsTurnedOn(Num_AEP_tessellation_shader, AEP_tessellation_shader))
                 return;
                 return;
         break;
         break;
     default:
     default:
@@ -3261,7 +3294,8 @@ TSymbol* TParseContext::redeclareBuiltinVariable(const TSourceLoc& loc, const TS
         return nullptr;
         return nullptr;
 
 
     bool nonEsRedecls = (profile != EEsProfile && (version >= 130 || identifier == "gl_TexCoord"));
     bool nonEsRedecls = (profile != EEsProfile && (version >= 130 || identifier == "gl_TexCoord"));
-    bool    esRedecls = (profile == EEsProfile && extensionsTurnedOn(Num_AEP_shader_io_blocks, AEP_shader_io_blocks));
+    bool    esRedecls = (profile == EEsProfile &&
+                         (version >= 320 || extensionsTurnedOn(Num_AEP_shader_io_blocks, AEP_shader_io_blocks)));
     if (! esRedecls && ! nonEsRedecls)
     if (! esRedecls && ! nonEsRedecls)
         return nullptr;
         return nullptr;
 
 
@@ -3400,7 +3434,7 @@ TSymbol* TParseContext::redeclareBuiltinVariable(const TSourceLoc& loc, const TS
 void TParseContext::redeclareBuiltinBlock(const TSourceLoc& loc, TTypeList& newTypeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes)
 void TParseContext::redeclareBuiltinBlock(const TSourceLoc& loc, TTypeList& newTypeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes)
 {
 {
     const char* feature = "built-in block redeclaration";
     const char* feature = "built-in block redeclaration";
-    profileRequires(loc, EEsProfile, 0, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, feature);
+    profileRequires(loc, EEsProfile, 320, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, feature);
     profileRequires(loc, ~EEsProfile, 410, E_GL_ARB_separate_shader_objects, feature);
     profileRequires(loc, ~EEsProfile, 410, E_GL_ARB_separate_shader_objects, feature);
 
 
     if (blockName != "gl_PerVertex" && blockName != "gl_PerFragment") {
     if (blockName != "gl_PerVertex" && blockName != "gl_PerFragment") {
@@ -3446,17 +3480,24 @@ void TParseContext::redeclareBuiltinBlock(const TSourceLoc& loc, TTypeList& newT
         return;
         return;
     }
     }
 
 
+    // Fix XFB stuff up, it applies to the order of the redeclaration, not
+    // the order of the original members.
+    if (currentBlockQualifier.storage == EvqVaryingOut && globalOutputDefaults.hasXfbBuffer()) {
+        currentBlockQualifier.layoutXfbBuffer = globalOutputDefaults.layoutXfbBuffer;
+        fixBlockXfbOffsets(currentBlockQualifier, newTypeList);
+    }
+
     // Edit and error check the container against the redeclaration
     // Edit and error check the container against the redeclaration
     //  - remove unused members
     //  - remove unused members
     //  - ensure remaining qualifiers/types match
     //  - ensure remaining qualifiers/types match
+
     TType& type = block->getWritableType();
     TType& type = block->getWritableType();
 
 
 #ifdef NV_EXTENSIONS
 #ifdef NV_EXTENSIONS
     // if gl_PerVertex is redeclared for the purpose of passing through "gl_Position"
     // if gl_PerVertex is redeclared for the purpose of passing through "gl_Position"
-    // for passthrough purpose, the redclared block should have the same qualifers as
+    // for passthrough purpose, the redeclared block should have the same qualifers as
     // the current one
     // the current one
-    if (currentBlockQualifier.layoutPassthrough)
-    {
+    if (currentBlockQualifier.layoutPassthrough) {
         type.getQualifier().layoutPassthrough = currentBlockQualifier.layoutPassthrough;
         type.getQualifier().layoutPassthrough = currentBlockQualifier.layoutPassthrough;
         type.getQualifier().storage = currentBlockQualifier.storage;
         type.getQualifier().storage = currentBlockQualifier.storage;
         type.getQualifier().layoutStream = currentBlockQualifier.layoutStream;
         type.getQualifier().layoutStream = currentBlockQualifier.layoutStream;
@@ -3497,10 +3538,12 @@ void TParseContext::redeclareBuiltinBlock(const TSourceLoc& loc, TTypeList& newT
                 arrayLimitCheck(loc, member->type->getFieldName(), newType.getOuterArraySize());
                 arrayLimitCheck(loc, member->type->getFieldName(), newType.getOuterArraySize());
             if (newType.getQualifier().isMemory())
             if (newType.getQualifier().isMemory())
                 error(memberLoc, "cannot add memory qualifier to redeclared block member", member->type->getFieldName().c_str(), "");
                 error(memberLoc, "cannot add memory qualifier to redeclared block member", member->type->getFieldName().c_str(), "");
-            if (newType.getQualifier().hasLayout())
-                error(memberLoc, "cannot add layout to redeclared block member", member->type->getFieldName().c_str(), "");
+            if (newType.getQualifier().hasNonXfbLayout())
+                error(memberLoc, "cannot add non-XFB layout to redeclared block member", member->type->getFieldName().c_str(), "");
             if (newType.getQualifier().patch)
             if (newType.getQualifier().patch)
                 error(memberLoc, "cannot add patch to redeclared block member", member->type->getFieldName().c_str(), "");
                 error(memberLoc, "cannot add patch to redeclared block member", member->type->getFieldName().c_str(), "");
+            if (newType.getQualifier().hasXfbBuffer() && newType.getQualifier().layoutXfbBuffer != currentBlockQualifier.layoutXfbBuffer)
+                error(memberLoc, "member cannot contradict block (or what block inherited from global)", "xfb_buffer", "");
             oldType.getQualifier().centroid = newType.getQualifier().centroid;
             oldType.getQualifier().centroid = newType.getQualifier().centroid;
             oldType.getQualifier().sample = newType.getQualifier().sample;
             oldType.getQualifier().sample = newType.getQualifier().sample;
             oldType.getQualifier().invariant = newType.getQualifier().invariant;
             oldType.getQualifier().invariant = newType.getQualifier().invariant;
@@ -3508,15 +3551,9 @@ void TParseContext::redeclareBuiltinBlock(const TSourceLoc& loc, TTypeList& newT
             oldType.getQualifier().smooth = newType.getQualifier().smooth;
             oldType.getQualifier().smooth = newType.getQualifier().smooth;
             oldType.getQualifier().flat = newType.getQualifier().flat;
             oldType.getQualifier().flat = newType.getQualifier().flat;
             oldType.getQualifier().nopersp = newType.getQualifier().nopersp;
             oldType.getQualifier().nopersp = newType.getQualifier().nopersp;
-
-#ifdef NV_EXTENSIONS
-            if (member->type->getFieldName() == "gl_Layer") {
-                if (!newType.getQualifier().layoutViewportRelative && newType.getQualifier().layoutSecondaryViewportRelativeOffset == -2048)
-                    error(loc, "redeclaration only allowed for viewport_relative or secondary_view_offset layout", "redeclaration", member->type->getFieldName().c_str());
-                oldType.getQualifier().layoutViewportRelative = newType.getQualifier().layoutViewportRelative;
-                oldType.getQualifier().layoutSecondaryViewportRelativeOffset = newType.getQualifier().layoutSecondaryViewportRelativeOffset;
-            }
-#endif
+            oldType.getQualifier().layoutXfbOffset = newType.getQualifier().layoutXfbOffset;
+            if (oldType.getQualifier().layoutXfbOffset != TQualifier::layoutXfbBufferEnd)
+                type.getQualifier().layoutXfbBuffer = currentBlockQualifier.layoutXfbBuffer;
             if (oldType.isImplicitlySizedArray() && newType.isExplicitlySizedArray())
             if (oldType.isImplicitlySizedArray() && newType.isExplicitlySizedArray())
                 oldType.changeOuterArraySize(newType.getOuterArraySize());
                 oldType.changeOuterArraySize(newType.getOuterArraySize());
 
 
@@ -4014,6 +4051,14 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
             publicType.shaderQualifiers.earlyFragmentTests = true;
             publicType.shaderQualifiers.earlyFragmentTests = true;
             return;
             return;
         }
         }
+        if (id == "post_depth_coverage") {
+            requireExtensions(loc, Num_post_depth_coverageEXTs, post_depth_coverageEXTs, "post depth coverage");
+            if (extensionTurnedOn(E_GL_ARB_post_depth_coverage)) {
+                publicType.shaderQualifiers.earlyFragmentTests = true;
+            }
+            publicType.shaderQualifiers.postDepthCoverage = true;
+            return;
+        }
         for (TLayoutDepth depth = (TLayoutDepth)(EldNone + 1); depth < EldCount; depth = (TLayoutDepth)(depth+1)) {
         for (TLayoutDepth depth = (TLayoutDepth)(EldNone + 1); depth < EldCount; depth = (TLayoutDepth)(depth+1)) {
             if (id == TQualifier::getLayoutDepthString(depth)) {
             if (id == TQualifier::getLayoutDepthString(depth)) {
                 requireProfile(loc, ECoreProfile | ECompatibilityProfile, "depth layout qualifier");
                 requireProfile(loc, ECoreProfile | ECompatibilityProfile, "depth layout qualifier");
@@ -4026,7 +4071,8 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
             bool found = false;
             bool found = false;
             for (TBlendEquationShift be = (TBlendEquationShift)0; be < EBlendCount; be = (TBlendEquationShift)(be + 1)) {
             for (TBlendEquationShift be = (TBlendEquationShift)0; be < EBlendCount; be = (TBlendEquationShift)(be + 1)) {
                 if (id == TQualifier::getBlendEquationString(be)) {
                 if (id == TQualifier::getBlendEquationString(be)) {
-                    requireExtensions(loc, 1, &E_GL_KHR_blend_equation_advanced, "blend equation");
+                    profileRequires(loc, EEsProfile, 320, E_GL_KHR_blend_equation_advanced, "blend equation");
+                    profileRequires(loc, ~EEsProfile, 0, E_GL_KHR_blend_equation_advanced, "blend equation");
                     intermediate.addBlendEquation(be);
                     intermediate.addBlendEquation(be);
                     publicType.shaderQualifiers.blendEquation = true;
                     publicType.shaderQualifiers.blendEquation = true;
                     found = true;
                     found = true;
@@ -4205,6 +4251,11 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
         }
         }
         return;
         return;
     }
     }
+    if (id == "num_views") {
+        requireExtensions(loc, Num_OVR_multiview_EXTs, OVR_multiview_EXTs, "num_views");
+        publicType.shaderQualifiers.numViews = value;
+        return;
+    }
 
 
 #if NV_EXTENSIONS
 #if NV_EXTENSIONS
     if (language == EShLangVertex ||
     if (language == EShLangVertex ||
@@ -4425,8 +4476,8 @@ void TParseContext::layoutObjectCheck(const TSourceLoc& loc, const TSymbol& symb
         switch (qualifier.storage) {
         switch (qualifier.storage) {
         case EvqVaryingIn:
         case EvqVaryingIn:
         case EvqVaryingOut:
         case EvqVaryingOut:
-            if (type.getBasicType() != EbtBlock || 
-                (!(*type.getStruct())[0].type->getQualifier().hasLocation() && 
+            if (type.getBasicType() != EbtBlock ||
+                (!(*type.getStruct())[0].type->getQualifier().hasLocation() &&
                   (*type.getStruct())[0].type->getQualifier().builtIn == EbvNone))
                   (*type.getStruct())[0].type->getQualifier().builtIn == EbvNone))
                 error(loc, "SPIR-V requires location for user input/output", "location", "");
                 error(loc, "SPIR-V requires location for user input/output", "location", "");
             break;
             break;
@@ -4518,6 +4569,8 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
             break;
             break;
         case EvqUniform:
         case EvqUniform:
         case EvqBuffer:
         case EvqBuffer:
+            if (type.getBasicType() == EbtBlock)
+                error(loc, "cannot apply to uniform or buffer block", "location", "");
             break;
             break;
         default:
         default:
             error(loc, "can only apply to uniform, buffer, in, or out storage qualifiers", "location", "");
             error(loc, "can only apply to uniform, buffer, in, or out storage qualifiers", "location", "");
@@ -4578,7 +4631,7 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
                 } else
                 } else
                     lastBinding += type.getCumulativeArraySize();
                     lastBinding += type.getCumulativeArraySize();
             }
             }
-            if (lastBinding >= resources.maxCombinedTextureImageUnits)
+            if (spvVersion.vulkan == 0 && lastBinding >= resources.maxCombinedTextureImageUnits)
                 error(loc, "sampler binding not less than gl_MaxCombinedTextureImageUnits", "binding", type.isArray() ? "(using array)" : "");
                 error(loc, "sampler binding not less than gl_MaxCombinedTextureImageUnits", "binding", type.isArray() ? "(using array)" : "");
         }
         }
         if (type.getBasicType() == EbtAtomicUint) {
         if (type.getBasicType() == EbtAtomicUint) {
@@ -4777,8 +4830,24 @@ void TParseContext::checkNoShaderLayouts(const TSourceLoc& loc, const TShaderQua
 
 
     if (shaderQualifiers.geometry != ElgNone)
     if (shaderQualifiers.geometry != ElgNone)
         error(loc, message, TQualifier::getGeometryString(shaderQualifiers.geometry), "");
         error(loc, message, TQualifier::getGeometryString(shaderQualifiers.geometry), "");
+    if (shaderQualifiers.spacing != EvsNone)
+        error(loc, message, TQualifier::getVertexSpacingString(shaderQualifiers.spacing), "");
+    if (shaderQualifiers.order != EvoNone)
+        error(loc, message, TQualifier::getVertexOrderString(shaderQualifiers.order), "");
+    if (shaderQualifiers.pointMode)
+        error(loc, message, "point_mode", "");
     if (shaderQualifiers.invocations != TQualifier::layoutNotSet)
     if (shaderQualifiers.invocations != TQualifier::layoutNotSet)
         error(loc, message, "invocations", "");
         error(loc, message, "invocations", "");
+    if (shaderQualifiers.earlyFragmentTests)
+        error(loc, message, "early_fragment_tests", "");
+    if (shaderQualifiers.postDepthCoverage)
+        error(loc, message, "post_depth_coverage", "");
+    for (int i = 0; i < 3; ++i) {
+        if (shaderQualifiers.localSize[i] > 1)
+            error(loc, message, "local_size", "");
+        if (shaderQualifiers.localSizeSpecId[i] != TQualifier::layoutNotSet)
+            error(loc, message, "local_size id", "");
+    }
     if (shaderQualifiers.vertices != TQualifier::layoutNotSet) {
     if (shaderQualifiers.vertices != TQualifier::layoutNotSet) {
         if (language == EShLangGeometry)
         if (language == EShLangGeometry)
             error(loc, message, "max_vertices", "");
             error(loc, message, "max_vertices", "");
@@ -4787,15 +4856,10 @@ void TParseContext::checkNoShaderLayouts(const TSourceLoc& loc, const TShaderQua
         else
         else
             assert(0);
             assert(0);
     }
     }
-    for (int i = 0; i < 3; ++i) {
-        if (shaderQualifiers.localSize[i] > 1)
-            error(loc, message, "local_size", "");
-        if (shaderQualifiers.localSizeSpecId[i] != TQualifier::layoutNotSet)
-            error(loc, message, "local_size id", "");
-    }
     if (shaderQualifiers.blendEquation)
     if (shaderQualifiers.blendEquation)
         error(loc, message, "blend equation", "");
         error(loc, message, "blend equation", "");
-    // TBD: correctness: are any of these missing?  pixelCenterInteger, originUpperLeft, spacing, order, pointmode, earlyfragment, depth
+    if (shaderQualifiers.numViews != TQualifier::layoutNotSet)
+        error(loc, message, "num_views", "");
 }
 }
 
 
 // Correct and/or advance an object's offset layout qualifier.
 // Correct and/or advance an object's offset layout qualifier.
@@ -4816,7 +4880,7 @@ void TParseContext::fixOffset(const TSourceLoc& loc, TSymbol& symbol)
             // Check for overlap
             // Check for overlap
             int numOffsets = 4;
             int numOffsets = 4;
             if (symbol.getType().isArray()) {
             if (symbol.getType().isArray()) {
-                if (symbol.getType().isExplicitlySizedArray())
+                if (symbol.getType().isExplicitlySizedArray() && ! symbol.getType().getArraySizes()->isInnerImplicit())
                     numOffsets *= symbol.getType().getCumulativeArraySize();
                     numOffsets *= symbol.getType().getCumulativeArraySize();
                 else {
                 else {
                     // "It is a compile-time error to declare an unsized array of atomic_uint."
                     // "It is a compile-time error to declare an unsized array of atomic_uint."
@@ -5083,7 +5147,7 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden
 
 
     samplerCheck(loc, type, identifier, initializer);
     samplerCheck(loc, type, identifier, initializer);
     atomicUintCheck(loc, type, identifier);
     atomicUintCheck(loc, type, identifier);
-    transparentCheck(loc, type, identifier);
+    transparentOpaqueCheck(loc, type, identifier);
 
 
     if (identifier != "gl_FragCoord" && (publicType.shaderQualifiers.originUpperLeft || publicType.shaderQualifiers.pixelCenterInteger))
     if (identifier != "gl_FragCoord" && (publicType.shaderQualifiers.originUpperLeft || publicType.shaderQualifiers.pixelCenterInteger))
         error(loc, "can only apply origin_upper_left and pixel_center_origin to gl_FragCoord", "layout qualifier", "");
         error(loc, "can only apply origin_upper_left and pixel_center_origin to gl_FragCoord", "layout qualifier", "");
@@ -5425,6 +5489,9 @@ TIntermTyped* TParseContext::convertInitializerList(const TSourceLoc& loc, const
 // Test for the correctness of the parameters passed to various constructor functions
 // Test for the correctness of the parameters passed to various constructor functions
 // and also convert them to the right data type, if allowed and required.
 // and also convert them to the right data type, if allowed and required.
 //
 //
+// 'node' is what to construct from.
+// 'type' is what type to construct.
+//
 // Returns nullptr for an error or the constructed node (aggregate or typed) for no error.
 // Returns nullptr for an error or the constructed node (aggregate or typed) for no error.
 //
 //
 TIntermTyped* TParseContext::addConstructor(const TSourceLoc& loc, TIntermNode* node, const TType& type)
 TIntermTyped* TParseContext::addConstructor(const TSourceLoc& loc, TIntermNode* node, const TType& type)
@@ -5454,7 +5521,7 @@ TIntermTyped* TParseContext::addConstructor(const TSourceLoc& loc, TIntermNode*
 
 
     bool singleArg;
     bool singleArg;
     if (aggrNode) {
     if (aggrNode) {
-        if (aggrNode->getOp() != EOpNull || aggrNode->getSequence().size() == 1)
+        if (aggrNode->getOp() != EOpNull)
             singleArg = true;
             singleArg = true;
         else
         else
             singleArg = false;
             singleArg = false;
@@ -5774,7 +5841,7 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
             case EvqVaryingOut:
             case EvqVaryingOut:
                 requireProfile(memberLoc, ECoreProfile | ECompatibilityProfile | EEsProfile, feature);
                 requireProfile(memberLoc, ECoreProfile | ECompatibilityProfile | EEsProfile, feature);
                 profileRequires(memberLoc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, feature);
                 profileRequires(memberLoc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, feature);
-                profileRequires(memberLoc, EEsProfile, 0, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, feature);
+                profileRequires(memberLoc, EEsProfile, 320, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, feature);
                 memberWithLocation = true;
                 memberWithLocation = true;
                 break;
                 break;
             default:
             default:
@@ -5898,14 +5965,14 @@ void TParseContext::blockStageIoCheck(const TSourceLoc& loc, const TQualifier& q
         // "Compute shaders do not permit user-defined input variables..."
         // "Compute shaders do not permit user-defined input variables..."
         requireStage(loc, (EShLanguageMask)(EShLangTessControlMask|EShLangTessEvaluationMask|EShLangGeometryMask|EShLangFragmentMask), "input block");
         requireStage(loc, (EShLanguageMask)(EShLangTessControlMask|EShLangTessEvaluationMask|EShLangGeometryMask|EShLangFragmentMask), "input block");
         if (language == EShLangFragment)
         if (language == EShLangFragment)
-            profileRequires(loc, EEsProfile, 0, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, "fragment input block");
+            profileRequires(loc, EEsProfile, 320, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, "fragment input block");
         break;
         break;
     case EvqVaryingOut:
     case EvqVaryingOut:
         profileRequires(loc, ~EEsProfile, 150, E_GL_ARB_separate_shader_objects, "output block");
         profileRequires(loc, ~EEsProfile, 150, E_GL_ARB_separate_shader_objects, "output block");
         requireStage(loc, (EShLanguageMask)(EShLangVertexMask|EShLangTessControlMask|EShLangTessEvaluationMask|EShLangGeometryMask), "output block");
         requireStage(loc, (EShLanguageMask)(EShLangVertexMask|EShLangTessControlMask|EShLangTessEvaluationMask|EShLangGeometryMask), "output block");
         // ES 310 can have a block before shader_io is turned on, so skip this test for built-ins
         // ES 310 can have a block before shader_io is turned on, so skip this test for built-ins
         if (language == EShLangVertex && ! parsingBuiltins)
         if (language == EShLangVertex && ! parsingBuiltins)
-            profileRequires(loc, EEsProfile, 0, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, "vertex output block");
+            profileRequires(loc, EEsProfile, 320, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, "vertex output block");
         break;
         break;
     default:
     default:
         error(loc, "only uniform, buffer, in, or out blocks are supported", blockName->c_str(), "");
         error(loc, "only uniform, buffer, in, or out blocks are supported", blockName->c_str(), "");
@@ -6271,6 +6338,12 @@ void TParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, con
         else
         else
             error(loc, "can only apply to 'in'", "early_fragment_tests", "");
             error(loc, "can only apply to 'in'", "early_fragment_tests", "");
     }
     }
+    if (publicType.shaderQualifiers.postDepthCoverage) {
+        if (publicType.qualifier.storage == EvqVaryingIn)
+            intermediate.setPostDepthCoverage();
+        else
+            error(loc, "can only apply to 'in'", "post_coverage_coverage", "");
+    }
     if (publicType.shaderQualifiers.blendEquation) {
     if (publicType.shaderQualifiers.blendEquation) {
         if (publicType.qualifier.storage != EvqVaryingOut)
         if (publicType.qualifier.storage != EvqVaryingOut)
             error(loc, "can only apply to 'out'", "blend equation", "");
             error(loc, "can only apply to 'out'", "blend equation", "");

+ 32 - 11
src/libraries/glslang/glslang/MachineIndependent/ParseHelper.h

@@ -74,16 +74,23 @@ class TParseContextBase : public TParseVersions {
 public:
 public:
     TParseContextBase(TSymbolTable& symbolTable, TIntermediate& interm, bool parsingBuiltins, int version,
     TParseContextBase(TSymbolTable& symbolTable, TIntermediate& interm, bool parsingBuiltins, int version,
                       EProfile profile, const SpvVersion& spvVersion, EShLanguage language,
                       EProfile profile, const SpvVersion& spvVersion, EShLanguage language,
-                      TInfoSink& infoSink, bool forwardCompatible, EShMessages messages)
+                      TInfoSink& infoSink, bool forwardCompatible, EShMessages messages,
+                      const TString* entryPoint = nullptr)
           : TParseVersions(interm, version, profile, spvVersion, language, infoSink, forwardCompatible, messages),
           : TParseVersions(interm, version, profile, spvVersion, language, infoSink, forwardCompatible, messages),
+            scopeMangler("::"),
             symbolTable(symbolTable),
             symbolTable(symbolTable),
             statementNestingLevel(0), loopNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0),
             statementNestingLevel(0), loopNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0),
             postEntryPointReturn(false),
             postEntryPointReturn(false),
             contextPragma(true, false),
             contextPragma(true, false),
-            limits(resources.limits),
             parsingBuiltins(parsingBuiltins), scanContext(nullptr), ppContext(nullptr),
             parsingBuiltins(parsingBuiltins), scanContext(nullptr), ppContext(nullptr),
-            globalUniformBlock(nullptr)
-    { }
+            limits(resources.limits),
+            globalUniformBlock(nullptr),
+            globalUniformBinding(TQualifier::layoutBindingEnd),
+            globalUniformSet(TQualifier::layoutSetEnd)
+    {
+        if (entryPoint != nullptr)
+            sourceEntryPointName = *entryPoint;
+    }
     virtual ~TParseContextBase() { }
     virtual ~TParseContextBase() { }
 
 
     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,
@@ -97,6 +104,8 @@ public:
 
 
     virtual void setLimits(const TBuiltInResource&) = 0;
     virtual void setLimits(const TBuiltInResource&) = 0;
 
 
+    void checkIndex(const TSourceLoc&, const TType&, int& index);
+
     EShLanguage getLanguage() const { return language; }
     EShLanguage getLanguage() const { return language; }
     void setScanContext(TScanContext* c) { scanContext = c; }
     void setScanContext(TScanContext* c) { scanContext = c; }
     TScanContext* getScanContext() const { return scanContext; }
     TScanContext* getScanContext() const { return scanContext; }
@@ -140,10 +149,19 @@ public:
     // Manage the global uniform block (default uniforms in GLSL, $Global in HLSL)
     // Manage the global uniform block (default uniforms in GLSL, $Global in HLSL)
     virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr);
     virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr);
 
 
+    // Potentially rename shader entry point function
+    void renameShaderFunction(TString*& name) const
+    {
+        // Replace the entry point name given in the shader with the real entry point name,
+        // if there is a substitution.
+        if (name != nullptr && *name == sourceEntryPointName && intermediate.getEntryPointName().size() > 0)
+            name = NewPoolTString(intermediate.getEntryPointName().c_str());
+    }
+
     virtual bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*);
     virtual bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*);
     virtual void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*);
     virtual void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*);
 
 
-    const char* const scopeMangler = "::";
+    const char* const scopeMangler;
 
 
     // Basic parsing state, easily accessible to the grammar
     // Basic parsing state, easily accessible to the grammar
 
 
@@ -172,6 +190,7 @@ protected:
     TPpContext* ppContext;
     TPpContext* ppContext;
     TBuiltInResource resources;
     TBuiltInResource resources;
     TLimits& limits;
     TLimits& limits;
+    TString sourceEntryPointName;
 
 
     // These, if set, will be called when a line, pragma ... is preprocessed.
     // These, if set, will be called when a line, pragma ... is preprocessed.
     // They will be called with any parameters to the original directive.
     // They will be called with any parameters to the original directive.
@@ -191,8 +210,10 @@ protected:
                                       TSwizzleSelectors<TVectorSelector>&);
                                       TSwizzleSelectors<TVectorSelector>&);
 
 
     // Manage the global uniform block (default uniforms in GLSL, $Global in HLSL)
     // Manage the global uniform block (default uniforms in GLSL, $Global in HLSL)
-    TVariable* globalUniformBlock;   // the actual block, inserted into the symbol table
-    int firstNewMember;              // the index of the first member not yet inserted into the symbol table
+    TVariable* globalUniformBlock;     // the actual block, inserted into the symbol table
+    unsigned int globalUniformBinding; // the block's binding number
+    unsigned int globalUniformSet;     // the block's set number
+    int firstNewMember;                // the index of the first member not yet inserted into the symbol table
     // override this to set the language-specific name
     // override this to set the language-specific name
     virtual const char* getGlobalUniformBlockName() const { return ""; }
     virtual const char* getGlobalUniformBlockName() const { return ""; }
     virtual void setUniformBlockDefaults(TType&) const { }
     virtual void setUniformBlockDefaults(TType&) const { }
@@ -248,7 +269,8 @@ protected:
 class TParseContext : public TParseContextBase {
 class TParseContext : public TParseContextBase {
 public:
 public:
     TParseContext(TSymbolTable&, TIntermediate&, bool parsingBuiltins, int version, EProfile, const SpvVersion& spvVersion, EShLanguage, TInfoSink&,
     TParseContext(TSymbolTable&, TIntermediate&, bool parsingBuiltins, int version, EProfile, const SpvVersion& spvVersion, EShLanguage, TInfoSink&,
-                  bool forwardCompatible = false, EShMessages messages = EShMsgDefault);
+                  bool forwardCompatible = false, EShMessages messages = EShMsgDefault,
+                  const TString* entryPoint = nullptr);
     virtual ~TParseContext();
     virtual ~TParseContext();
 
 
     bool obeyPrecisionQualifiers() const { return precisionManager.respectingPrecisionQualifiers(); };
     bool obeyPrecisionQualifiers() const { return precisionManager.respectingPrecisionQualifiers(); };
@@ -267,7 +289,6 @@ public:
     void handlePragma(const TSourceLoc&, const TVector<TString>&) override;
     void handlePragma(const TSourceLoc&, const TVector<TString>&) override;
     TIntermTyped* handleVariable(const TSourceLoc&, TSymbol* symbol, const TString* string);
     TIntermTyped* handleVariable(const TSourceLoc&, TSymbol* symbol, const TString* string);
     TIntermTyped* handleBracketDereference(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index);
     TIntermTyped* handleBracketDereference(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index);
-    void checkIndex(const TSourceLoc&, const TType&, int& index);
     void handleIndexLimits(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index);
     void handleIndexLimits(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index);
 
 
     void makeEditable(TSymbol*&) override;
     void makeEditable(TSymbol*&) override;
@@ -317,7 +338,7 @@ 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&, const TArraySizes*, bool initializer, bool lastMember);
+    void arraySizesCheck(const TSourceLoc&, const TQualifier&, TArraySizes*, bool initializer, bool lastMember);
     void arrayOfArrayVersionCheck(const TSourceLoc&);
     void arrayOfArrayVersionCheck(const TSourceLoc&);
     void arrayDimCheck(const TSourceLoc&, const TArraySizes* sizes1, const TArraySizes* sizes2);
     void arrayDimCheck(const TSourceLoc&, const TArraySizes* sizes1, const TArraySizes* sizes2);
     void arrayDimCheck(const TSourceLoc&, const TType*, const TArraySizes*);
     void arrayDimCheck(const TSourceLoc&, const TType*, const TArraySizes*);
@@ -327,7 +348,7 @@ public:
     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 transparentCheck(const TSourceLoc&, const TType&, const TString& identifier);
+    void transparentOpaqueCheck(const TSourceLoc&, const TType&, const TString& identifier);
     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);

+ 16 - 46
src/libraries/glslang/glslang/MachineIndependent/PoolAlloc.cpp

@@ -40,35 +40,22 @@
 
 
 namespace glslang {
 namespace glslang {
 
 
+// Process-wide TLS index
 OS_TLSIndex PoolIndex;
 OS_TLSIndex PoolIndex;
 
 
-void InitializeMemoryPools()
+// Return the thread-specific current pool.
+TPoolAllocator& GetThreadPoolAllocator()
 {
 {
-    TThreadMemoryPools* pools = static_cast<TThreadMemoryPools*>(OS_GetTLSValue(PoolIndex));
-    if (pools)
-        return;
-
-    TPoolAllocator *threadPoolAllocator = new TPoolAllocator();
-
-    TThreadMemoryPools* threadData = new TThreadMemoryPools();
-
-    threadData->threadPoolAllocator = threadPoolAllocator;
-
-    OS_SetTLSValue(PoolIndex, threadData);
+    return *static_cast<TPoolAllocator*>(OS_GetTLSValue(PoolIndex));
 }
 }
 
 
-void FreeGlobalPools()
+// Set the thread-specific current pool.
+void SetThreadPoolAllocator(TPoolAllocator* poolAllocator)
 {
 {
-    // Release the allocated memory for this thread.
-    TThreadMemoryPools* globalPools = static_cast<TThreadMemoryPools*>(OS_GetTLSValue(PoolIndex));
-    if (! globalPools)
-        return;
-
-    GetThreadPoolAllocator().popAll();
-    delete &GetThreadPoolAllocator();
-    delete globalPools;
+    OS_SetTLSValue(PoolIndex, poolAllocator);
 }
 }
 
 
+// Process-wide set up of the TLS pool storage.
 bool InitializePoolIndex()
 bool InitializePoolIndex()
 {
 {
     // Allocate a TLS index.
     // Allocate a TLS index.
@@ -78,26 +65,6 @@ bool InitializePoolIndex()
     return true;
     return true;
 }
 }
 
 
-void FreePoolIndex()
-{
-    // Release the TLS index.
-    OS_FreeTLSIndex(PoolIndex);
-}
-
-TPoolAllocator& GetThreadPoolAllocator()
-{
-    TThreadMemoryPools* threadData = static_cast<TThreadMemoryPools*>(OS_GetTLSValue(PoolIndex));
-
-    return *threadData->threadPoolAllocator;
-}
-
-void SetThreadPoolAllocator(TPoolAllocator& poolAllocator)
-{
-    TThreadMemoryPools* threadData = static_cast<TThreadMemoryPools*>(OS_GetTLSValue(PoolIndex));
-
-    threadData->threadPoolAllocator = &poolAllocator;
-}
-
 //
 //
 // Implement the functionality of the TPoolAllocator class, which
 // Implement the functionality of the TPoolAllocator class, which
 // is documented in PoolAlloc.h.
 // is documented in PoolAlloc.h.
@@ -234,13 +201,16 @@ void TPoolAllocator::pop()
     currentPageOffset = stack.back().offset;
     currentPageOffset = stack.back().offset;
 
 
     while (inUseList != page) {
     while (inUseList != page) {
-        // invoke destructor to free allocation list
-        inUseList->~tHeader();
-
         tHeader* nextInUse = inUseList->nextPage;
         tHeader* nextInUse = inUseList->nextPage;
-        if (inUseList->pageCount > 1)
+        size_t pageCount = inUseList->pageCount;
+
+        // This technically ends the lifetime of the header as C++ object,
+        // but we will still control the memory and reuse it.
+        inUseList->~tHeader(); // currently, just a debug allocation checker
+
+        if (pageCount > 1) {
             delete [] reinterpret_cast<char*>(inUseList);
             delete [] reinterpret_cast<char*>(inUseList);
-        else {
+        } else {
             inUseList->nextPage = freeList;
             inUseList->nextPage = freeList;
             freeList = inUseList;
             freeList = inUseList;
         }
         }

+ 26 - 12
src/libraries/glslang/glslang/MachineIndependent/RemoveTree.cpp

@@ -864,14 +864,17 @@ int TScanContext::tokenizeIdentifier()
 
 
     case PATCH:
     case PATCH:
         if (parseContext.symbolTable.atBuiltInLevel() ||
         if (parseContext.symbolTable.atBuiltInLevel() ||
-            (parseContext.profile == EEsProfile && parseContext.extensionsTurnedOn(Num_AEP_tessellation_shader, AEP_tessellation_shader)) ||
+            (parseContext.profile == EEsProfile &&
+             (parseContext.version >= 320 || 
+              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;
 
 
         return es30ReservedFromGLSL(400);
         return es30ReservedFromGLSL(400);
 
 
     case SAMPLE:
     case SAMPLE:
-        if (parseContext.extensionsTurnedOn(1, &E_GL_OES_shader_multisample_interpolation))
+        if ((parseContext.profile == EEsProfile && parseContext.version >= 320) ||
+            parseContext.extensionsTurnedOn(1, &E_GL_OES_shader_multisample_interpolation))
             return keyword;
             return keyword;
         return es30ReservedFromGLSL(400);
         return es30ReservedFromGLSL(400);
 
 
@@ -925,7 +928,8 @@ int TScanContext::tokenizeIdentifier()
     case IIMAGEBUFFER:
     case IIMAGEBUFFER:
     case UIMAGEBUFFER:
     case UIMAGEBUFFER:
         afterType = true;
         afterType = true;
-        if (parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer))
+        if ((parseContext.profile == EEsProfile && parseContext.version >= 320) ||
+            parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer))
             return keyword;
             return keyword;
         return firstGenerationImage(false);
         return firstGenerationImage(false);
 
 
@@ -948,7 +952,8 @@ int TScanContext::tokenizeIdentifier()
     case IIMAGECUBEARRAY:
     case IIMAGECUBEARRAY:
     case UIMAGECUBEARRAY:
     case UIMAGECUBEARRAY:
         afterType = true;
         afterType = true;
-        if (parseContext.extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array))
+        if ((parseContext.profile == EEsProfile && parseContext.version >= 320) ||
+            parseContext.extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array))
             return keyword;
             return keyword;
         return secondGenerationImage();
         return secondGenerationImage();
 
 
@@ -1030,7 +1035,8 @@ int TScanContext::tokenizeIdentifier()
     case ISAMPLERCUBEARRAY:
     case ISAMPLERCUBEARRAY:
     case USAMPLERCUBEARRAY:
     case USAMPLERCUBEARRAY:
         afterType = true;
         afterType = true;
-        if (parseContext.extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array))
+        if ((parseContext.profile == EEsProfile && parseContext.version >= 320) ||
+            parseContext.extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array))
             return keyword;
             return keyword;
         if (parseContext.profile == EEsProfile || (parseContext.version < 400 && ! parseContext.extensionTurnedOn(E_GL_ARB_texture_cube_map_array)))
         if (parseContext.profile == EEsProfile || (parseContext.version < 400 && ! parseContext.extensionTurnedOn(E_GL_ARB_texture_cube_map_array)))
             reservedWord();
             reservedWord();
@@ -1066,14 +1072,16 @@ int TScanContext::tokenizeIdentifier()
 
 
     case SAMPLERBUFFER:
     case SAMPLERBUFFER:
         afterType = true;
         afterType = true;
-        if (parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer))
+        if ((parseContext.profile == EEsProfile && parseContext.version >= 320) ||
+            parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer))
             return keyword;
             return keyword;
         return es30ReservedFromGLSL(130);
         return es30ReservedFromGLSL(130);
 
 
     case ISAMPLERBUFFER:
     case ISAMPLERBUFFER:
     case USAMPLERBUFFER:
     case USAMPLERBUFFER:
         afterType = true;
         afterType = true;
-        if (parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer))
+        if ((parseContext.profile == EEsProfile && parseContext.version >= 320) ||
+            parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer))
             return keyword;
             return keyword;
         return es30ReservedFromGLSL(140);
         return es30ReservedFromGLSL(140);
 
 
@@ -1089,7 +1097,8 @@ int TScanContext::tokenizeIdentifier()
     case ISAMPLER2DMSARRAY:
     case ISAMPLER2DMSARRAY:
     case USAMPLER2DMSARRAY:
     case USAMPLER2DMSARRAY:
         afterType = true;
         afterType = true;
-        if (parseContext.extensionsTurnedOn(1, &E_GL_OES_texture_storage_multisample_2d_array))
+        if ((parseContext.profile == EEsProfile && parseContext.version >= 320) ||
+            parseContext.extensionsTurnedOn(1, &E_GL_OES_texture_storage_multisample_2d_array))
             return keyword;
             return keyword;
         return es30ReservedFromGLSL(150);
         return es30ReservedFromGLSL(150);
 
 
@@ -1110,8 +1119,10 @@ int TScanContext::tokenizeIdentifier()
 
 
     case SAMPLER2DSHADOW:
     case SAMPLER2DSHADOW:
         afterType = true;
         afterType = true;
-        if (parseContext.profile == EEsProfile && parseContext.version < 300)
-            reservedWord();
+        if (parseContext.profile == EEsProfile && parseContext.version < 300) {
+            if (!parseContext.extensionTurnedOn(E_GL_EXT_shadow_samplers))
+                reservedWord();
+        }
         return keyword;
         return keyword;
 
 
     case SAMPLER1DARRAY:
     case SAMPLER1DARRAY:
@@ -1160,7 +1171,9 @@ int TScanContext::tokenizeIdentifier()
 
 
     case SAMPLEREXTERNALOES:
     case SAMPLEREXTERNALOES:
         afterType = true;
         afterType = true;
-        if (parseContext.symbolTable.atBuiltInLevel() || parseContext.extensionTurnedOn(E_GL_OES_EGL_image_external))
+        if (parseContext.symbolTable.atBuiltInLevel() ||
+            parseContext.extensionTurnedOn(E_GL_OES_EGL_image_external) ||
+            parseContext.extensionTurnedOn(E_GL_OES_EGL_image_external_essl3))
             return keyword;
             return keyword;
         return identifierOrType();
         return identifierOrType();
 
 
@@ -1245,7 +1258,8 @@ int TScanContext::tokenizeIdentifier()
         return keyword;
         return keyword;
 
 
     case PRECISE:
     case PRECISE:
-        if ((parseContext.profile == EEsProfile && parseContext.extensionsTurnedOn(Num_AEP_gpu_shader5, AEP_gpu_shader5)) ||
+        if ((parseContext.profile == EEsProfile &&
+             (parseContext.version >= 320 || parseContext.extensionsTurnedOn(Num_AEP_gpu_shader5, AEP_gpu_shader5))) ||
             (parseContext.profile != EEsProfile && parseContext.version >= 400))
             (parseContext.profile != EEsProfile && parseContext.version >= 400))
             return keyword;
             return keyword;
         if (parseContext.profile == EEsProfile && parseContext.version == 310) {
         if (parseContext.profile == EEsProfile && parseContext.version == 310) {

+ 8 - 9
src/libraries/glslang/glslang/MachineIndependent/Scan.h

@@ -51,25 +51,24 @@ const int EndOfInput = -1;
 //
 //
 class TInputScanner {
 class TInputScanner {
 public:
 public:
-    TInputScanner(int n, const char* const s[], size_t L[], const char* const* names = nullptr, int b = 0, int f = 0, bool single = false) :
+    TInputScanner(int n, const char* const s[], size_t L[], const char* const* names = nullptr,
+                  int b = 0, int f = 0, bool single = false) :
         numSources(n),
         numSources(n),
-        sources(reinterpret_cast<const unsigned char* const *>(s)), // up to this point, common usage is "char*", but now we need positive 8-bit characters
-        lengths(L), currentSource(0), currentChar(0), stringBias(b), finale(f), singleLogical(single), endOfFileReached(false)
+         // up to this point, common usage is "char*", but now we need positive 8-bit characters
+        sources(reinterpret_cast<const unsigned char* const *>(s)),
+        lengths(L), currentSource(0), currentChar(0), stringBias(b), finale(f), singleLogical(single),
+        endOfFileReached(false)
     {
     {
         loc = new TSourceLoc[numSources];
         loc = new TSourceLoc[numSources];
         for (int i = 0; i < numSources; ++i) {
         for (int i = 0; i < numSources; ++i) {
-            loc[i].init();
+            loc[i].init(i - stringBias);
         }
         }
         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];
         }
         }
-        loc[currentSource].string = -stringBias;
         loc[currentSource].line = 1;
         loc[currentSource].line = 1;
-        loc[currentSource].column = 0;
-        logicalSourceLoc.string = 0;
-        logicalSourceLoc.line = 1;
-        logicalSourceLoc.column = 0;
+        logicalSourceLoc.init(1);
         logicalSourceLoc.name = loc[0].name;
         logicalSourceLoc.name = loc[0].name;
     }
     }
 
 

+ 241 - 94
src/libraries/glslang/glslang/MachineIndependent/ScanContext.h

@@ -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-2016 Google, Inc.
+// Copyright (C) 2015-2017 Google, Inc.
 //
 //
 // All rights reserved.
 // All rights reserved.
 //
 //
@@ -69,6 +69,10 @@
 
 
 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
+// Shared global; access should be protected by a global mutex/critical section.
+int NumberOfClients = 0;
+
 using namespace glslang;
 using namespace glslang;
 
 
 // Create a language specific version of parseables.
 // Create a language specific version of parseables.
@@ -91,18 +95,16 @@ TParseContextBase* CreateParseContext(TSymbolTable& symbolTable, TIntermediate&
                                       int version, EProfile profile, EShSource source,
                                       int version, EProfile profile, EShSource source,
                                       EShLanguage language, TInfoSink& infoSink,
                                       EShLanguage language, TInfoSink& infoSink,
                                       SpvVersion spvVersion, bool forwardCompatible, EShMessages messages,
                                       SpvVersion spvVersion, bool forwardCompatible, EShMessages messages,
-                                      bool parsingBuiltIns, const std::string sourceEntryPointName = "")
+                                      bool parsingBuiltIns, std::string sourceEntryPointName = "")
 {
 {
-#ifndef ENABLE_HLSL
-    (void)sourceEntryPointName; // Unused argument.
-#endif
-
     switch (source) {
     switch (source) {
-    case EShSourceGlsl:
-        intermediate.setEntryPointName("main");
+    case EShSourceGlsl: {
+        if (sourceEntryPointName.size() == 0)
+            intermediate.setEntryPointName("main");
+        TString entryPoint = sourceEntryPointName.c_str();
         return new TParseContext(symbolTable, intermediate, parsingBuiltIns, version, profile, spvVersion,
         return new TParseContext(symbolTable, intermediate, parsingBuiltIns, version, profile, spvVersion,
-                                 language, infoSink, forwardCompatible, messages);
-
+                                 language, infoSink, forwardCompatible, messages, &entryPoint);
+    }
 #ifdef ENABLE_HLSL
 #ifdef ENABLE_HLSL
     case EShSourceHlsl:
     case EShSourceHlsl:
         return new HlslParseContext(symbolTable, intermediate, parsingBuiltIns, version, profile, spvVersion,
         return new HlslParseContext(symbolTable, intermediate, parsingBuiltIns, version, profile, spvVersion,
@@ -116,7 +118,7 @@ TParseContextBase* CreateParseContext(TSymbolTable& symbolTable, TIntermediate&
 
 
 // Local mapping functions for making arrays of symbol tables....
 // Local mapping functions for making arrays of symbol tables....
 
 
-const int VersionCount = 15;  // index range in MapVersionToIndex
+const int VersionCount = 17;  // index range in MapVersionToIndex
 
 
 int MapVersionToIndex(int version)
 int MapVersionToIndex(int version)
 {
 {
@@ -138,7 +140,10 @@ int MapVersionToIndex(int version)
     case 440: index = 12; break;
     case 440: index = 12; break;
     case 310: index = 13; break;
     case 310: index = 13; break;
     case 450: index = 14; break;
     case 450: index = 14; break;
-    default:              break;
+    case 500: index =  0; break; // HLSL
+    case 320: index = 15; break;
+    case 460: index = 16; break;
+    default:  assert(0);  break;
     }
     }
 
 
     assert(index < VersionCount);
     assert(index < VersionCount);
@@ -216,7 +221,7 @@ enum EPrecisionClass {
 TSymbolTable* CommonSymbolTable[VersionCount][SpvVersionCount][ProfileCount][SourceCount][EPcCount] = {};
 TSymbolTable* CommonSymbolTable[VersionCount][SpvVersionCount][ProfileCount][SourceCount][EPcCount] = {};
 TSymbolTable* SharedSymbolTables[VersionCount][SpvVersionCount][ProfileCount][SourceCount][EShLangCount] = {};
 TSymbolTable* SharedSymbolTables[VersionCount][SpvVersionCount][ProfileCount][SourceCount][EShLangCount] = {};
 
 
-TPoolAllocator* PerProcessGPA = 0;
+TPoolAllocator* PerProcessGPA = nullptr;
 
 
 //
 //
 // Parse and add to the given symbol table the content of the given shader string.
 // Parse and add to the given symbol table the content of the given shader string.
@@ -360,7 +365,7 @@ bool AddContextSpecificSymbols(const TBuiltInResource* resources, TInfoSink& inf
 // pool allocator intact, so:
 // pool allocator intact, so:
 //  - Switch to a new pool for parsing the built-ins
 //  - Switch to a new pool for parsing the built-ins
 //  - Do the parsing, which builds the symbol table, using the new pool
 //  - Do the parsing, which builds the symbol table, using the new pool
-//  - Switch to the process-global pool to save a copy the resulting symbol table
+//  - Switch to the process-global pool to save a copy of the resulting symbol table
 //  - Free up the new pool used to parse the built-ins
 //  - Free up the new pool used to parse the built-ins
 //  - Switch back to the original thread's pool
 //  - Switch back to the original thread's pool
 //
 //
@@ -387,8 +392,8 @@ void SetupBuiltinSymbolTable(int version, EProfile profile, const SpvVersion& sp
 
 
     // Switch to a new pool
     // Switch to a new pool
     TPoolAllocator& previousAllocator = GetThreadPoolAllocator();
     TPoolAllocator& previousAllocator = GetThreadPoolAllocator();
-    TPoolAllocator* builtInPoolAllocator = new TPoolAllocator();
-    SetThreadPoolAllocator(*builtInPoolAllocator);
+    TPoolAllocator* builtInPoolAllocator = new TPoolAllocator;
+    SetThreadPoolAllocator(builtInPoolAllocator);
 
 
     // Dynamically allocate the local symbol tables so we can control when they are deallocated WRT when the pool is popped.
     // Dynamically allocate the local symbol tables so we can control when they are deallocated WRT when the pool is popped.
     TSymbolTable* commonTable[EPcCount];
     TSymbolTable* commonTable[EPcCount];
@@ -402,7 +407,7 @@ void SetupBuiltinSymbolTable(int version, EProfile profile, const SpvVersion& sp
     InitializeSymbolTables(infoSink, commonTable, stageTables, version, profile, spvVersion, source);
     InitializeSymbolTables(infoSink, commonTable, stageTables, version, profile, spvVersion, source);
 
 
     // Switch to the process-global pool
     // Switch to the process-global pool
-    SetThreadPoolAllocator(*PerProcessGPA);
+    SetThreadPoolAllocator(PerProcessGPA);
 
 
     // Copy the local symbol tables from the new pool to the global tables using the process-global pool
     // Copy the local symbol tables from the new pool to the global tables using the process-global pool
     for (int precClass = 0; precClass < EPcCount; ++precClass) {
     for (int precClass = 0; precClass < EPcCount; ++precClass) {
@@ -429,7 +434,7 @@ void SetupBuiltinSymbolTable(int version, EProfile profile, const SpvVersion& sp
         delete stageTables[stage];
         delete stageTables[stage];
 
 
     delete builtInPoolAllocator;
     delete builtInPoolAllocator;
-    SetThreadPoolAllocator(previousAllocator);
+    SetThreadPoolAllocator(&previousAllocator);
 
 
     glslang::ReleaseGlobalLock();
     glslang::ReleaseGlobalLock();
 }
 }
@@ -447,7 +452,7 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo
         return correct;
         return correct;
     }
     }
 
 
-    // Get a good version...
+    // Get a version...
     if (version == 0) {
     if (version == 0) {
         version = defaultVersion;
         version = defaultVersion;
         // infoSink.info.message(EPrefixWarning, "#version: statement missing; use #version on first line of shader");
         // infoSink.info.message(EPrefixWarning, "#version: statement missing; use #version on first line of shader");
@@ -455,9 +460,9 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo
 
 
     // Get a good profile...
     // Get a good profile...
     if (profile == ENoProfile) {
     if (profile == ENoProfile) {
-        if (version == 300 || version == 310) {
+        if (version == 300 || version == 310 || version == 320) {
             correct = false;
             correct = false;
-            infoSink.info.message(EPrefixError, "#version: versions 300 and 310 require specifying the 'es' profile");
+            infoSink.info.message(EPrefixError, "#version: versions 300, 310, and 320 require specifying the 'es' profile");
             profile = EEsProfile;
             profile = EEsProfile;
         } else if (version == 100)
         } else if (version == 100)
             profile = EEsProfile;
             profile = EEsProfile;
@@ -474,16 +479,16 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo
                 profile = EEsProfile;
                 profile = EEsProfile;
             else
             else
                 profile = ENoProfile;
                 profile = ENoProfile;
-        } else if (version == 300 || version == 310) {
+        } else if (version == 300 || version == 310 || version == 320) {
             if (profile != EEsProfile) {
             if (profile != EEsProfile) {
                 correct = false;
                 correct = false;
-                infoSink.info.message(EPrefixError, "#version: versions 300 and 310 support only the es profile");
+                infoSink.info.message(EPrefixError, "#version: versions 300, 310, and 320 support only the es profile");
             }
             }
             profile = EEsProfile;
             profile = EEsProfile;
         } else {
         } else {
             if (profile == EEsProfile) {
             if (profile == EEsProfile) {
                 correct = false;
                 correct = false;
-                infoSink.info.message(EPrefixError, "#version: only version 300 and 310 support the es profile");
+                infoSink.info.message(EPrefixError, "#version: only version 300, 310, and 320 support the es profile");
                 if (version >= FirstProfileVersion)
                 if (version >= FirstProfileVersion)
                     profile = ECoreProfile;
                     profile = ECoreProfile;
                 else
                 else
@@ -493,6 +498,42 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo
         }
         }
     }
     }
 
 
+    // Fix version...
+    switch (version) {
+    // ES versions
+    case 100: break;
+    case 300: break;
+    case 310: break;
+    case 320: break;
+
+    // desktop versions
+    case 110: break;
+    case 120: break;
+    case 130: break;
+    case 140: break;
+    case 150: break;
+    case 330: break;
+    case 400: break;
+    case 410: break;
+    case 420: break;
+    case 430: break;
+    case 440: break;
+    case 450: break;
+    case 460: break;
+
+    // unknown version
+    default:
+        correct = false;
+        infoSink.info.message(EPrefixError, "version not supported");
+        if (profile == EEsProfile)
+            version = 310;
+        else {
+            version = 450;
+            profile = ECoreProfile;
+        }
+        break;
+    }
+
     // Correct for stage type...
     // Correct for stage type...
     switch (stage) {
     switch (stage) {
     case EShLangGeometry:
     case EShLangGeometry:
@@ -569,6 +610,89 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo
     return correct;
     return correct;
 }
 }
 
 
+// There are multiple paths in for setting environment stuff.
+// TEnvironment takes precedence, for what it sets, so sort all this out.
+// Ideally, the internal code could be made to use TEnvironment, but for
+// now, translate it to the historically used parameters.
+void TranslateEnvironment(const TEnvironment* environment, EShMessages& messages, EShSource& source,
+                          EShLanguage& stage, SpvVersion& spvVersion)
+{
+    // Set up environmental defaults, first ignoring 'environment'.
+    if (messages & EShMsgSpvRules)
+        spvVersion.spv = 0x00010000;
+    if (messages & EShMsgVulkanRules) {
+        spvVersion.vulkan = 100;
+        spvVersion.vulkanGlsl = 100;
+    } else if (spvVersion.spv != 0)
+        spvVersion.openGl = 100;
+
+    // Now, override, based on any content set in 'environment'.
+    // 'environment' must be cleared to ESh*None settings when items
+    // are not being set.
+    if (environment != nullptr) {
+        // input language
+        if (environment->input.languageFamily != EShSourceNone) {
+            stage = environment->input.stage;
+            switch (environment->input.dialect) {
+            case EShClientNone:
+                break;
+            case EShClientVulkan:
+                spvVersion.vulkanGlsl = environment->input.dialectVersion;
+                break;
+            case EShClientOpenGL:
+                spvVersion.openGl = environment->input.dialectVersion;
+                break;
+            }
+            switch (environment->input.languageFamily) {
+            case EShSourceNone:
+                break;
+            case EShSourceGlsl:
+                source = EShSourceGlsl;
+                messages = static_cast<EShMessages>(messages & ~EShMsgReadHlsl);
+                break;
+            case EShSourceHlsl:
+                source = EShSourceHlsl;
+                messages = static_cast<EShMessages>(messages | EShMsgReadHlsl);
+                break;
+            }
+        }
+
+        // client
+        switch (environment->client.client) {
+        case EShClientVulkan:
+            spvVersion.vulkan = environment->client.version;
+            break;
+        default:
+            break;
+        }
+
+        // generated code
+        switch (environment->target.language) {
+        case EshTargetSpv:
+            spvVersion.spv = environment->target.version;
+            break;
+        default:
+            break;
+        }
+    }
+}
+
+// Most processes are recorded when set in the intermediate representation,
+// These are the few that are not.
+void RecordProcesses(TIntermediate& intermediate, EShMessages messages, const std::string& sourceEntryPointName)
+{
+    if ((messages & EShMsgRelaxedErrors) != 0)
+        intermediate.addProcess("relaxed-errors");
+    if ((messages & EShMsgSuppressWarnings) != 0)
+        intermediate.addProcess("suppress-warnings");
+    if ((messages & EShMsgKeepUncalled) != 0)
+        intermediate.addProcess("keep-uncalled");
+    if (sourceEntryPointName.size() > 0) {
+        intermediate.addProcess("source-entrypoint");
+        intermediate.addProcessArgument(sourceEntryPointName);
+    }
+}
+
 // This is the common setup and cleanup code for PreprocessDeferred and
 // This is the common setup and cleanup code for PreprocessDeferred and
 // CompileDeferred.
 // CompileDeferred.
 // It takes any callable with a signature of
 // It takes any callable with a signature of
@@ -588,7 +712,7 @@ bool ProcessDeferred(
     const char* customPreamble,
     const char* customPreamble,
     const EShOptimizationLevel optLevel,
     const EShOptimizationLevel optLevel,
     const TBuiltInResource* resources,
     const TBuiltInResource* resources,
-    int defaultVersion,         // use 100 for ES environment, 110 for desktop; this is the GLSL version, not SPIR-V or Vulkan
+    int defaultVersion,  // use 100 for ES environment, 110 for desktop; this is the GLSL version, not SPIR-V or Vulkan
     EProfile defaultProfile,
     EProfile defaultProfile,
     // set version/profile to defaultVersion/defaultProfile regardless of the #version
     // set version/profile to defaultVersion/defaultProfile regardless of the #version
     // directive in the source code
     // directive in the source code
@@ -599,12 +723,9 @@ bool ProcessDeferred(
     ProcessingContext& processingContext,
     ProcessingContext& processingContext,
     bool requireNonempty,
     bool requireNonempty,
     TShader::Includer& includer,
     TShader::Includer& includer,
-    const std::string sourceEntryPointName = ""
-    )
+    const std::string sourceEntryPointName = "",
+    const TEnvironment* environment = nullptr)  // optional way of fully setting all versions, overriding the above
 {
 {
-    if (! InitThread())
-        return false;
-
     // This must be undone (.pop()) by the caller, after it finishes consuming the created tree.
     // This must be undone (.pop()) by the caller, after it finishes consuming the created tree.
     GetThreadPoolAllocator().push();
     GetThreadPoolAllocator().push();
 
 
@@ -628,7 +749,7 @@ bool ProcessDeferred(
     const char** names = new const char*[numTotal];
     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 == 0 || inputLengths[s] < 0)
+        if (inputLengths == nullptr || inputLengths[s] < 0)
             lengths[s + numPre] = strlen(shaderStrings[s]);
             lengths[s + numPre] = strlen(shaderStrings[s]);
         else
         else
             lengths[s + numPre] = inputLengths[s];
             lengths[s + numPre] = inputLengths[s];
@@ -641,16 +762,25 @@ bool ProcessDeferred(
             names[s + numPre] = nullptr;
             names[s + numPre] = nullptr;
     }
     }
 
 
+    // Get all the stages, languages, clients, and other environment
+    // stuff sorted out.
+    EShSource source = (messages & EShMsgReadHlsl) != 0 ? EShSourceHlsl : EShSourceGlsl;
+    SpvVersion spvVersion;
+    EShLanguage stage = compiler->getLanguage();
+    TranslateEnvironment(environment, messages, source, stage, spvVersion);
+
     // 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
-    // outlined above, just the user shader.
-    glslang::TInputScanner userInput(numStrings, &strings[numPre], &lengths[numPre]);  // no preamble
+    // outlined above, just the user shader, after the system and user preambles.
+    glslang::TInputScanner userInput(numStrings, &strings[numPre], &lengths[numPre]);
     int version = 0;
     int version = 0;
     EProfile profile = ENoProfile;
     EProfile profile = ENoProfile;
     bool versionNotFirstToken = false;
     bool versionNotFirstToken = false;
-    bool versionNotFirst = (messages & EShMsgReadHlsl) ? true : userInput.scanVersion(version, profile, versionNotFirstToken);
+    bool versionNotFirst = (source == EShSourceHlsl)
+                                ? true
+                                : userInput.scanVersion(version, profile, versionNotFirstToken);
     bool versionNotFound = version == 0;
     bool versionNotFound = version == 0;
-    if (forceDefaultVersionAndProfile && (messages & EShMsgReadHlsl) == 0) {
+    if (forceDefaultVersionAndProfile && source == EShSourceGlsl) {
         if (! (messages & EShMsgSuppressWarnings) && ! versionNotFound &&
         if (! (messages & EShMsgSuppressWarnings) && ! versionNotFound &&
             (version != defaultVersion || profile != defaultProfile)) {
             (version != defaultVersion || profile != defaultProfile)) {
             compiler->infoSink.info << "Warning, (version, profile) forced to be ("
             compiler->infoSink.info << "Warning, (version, profile) forced to be ("
@@ -667,15 +797,9 @@ bool ProcessDeferred(
         version = defaultVersion;
         version = defaultVersion;
         profile = defaultProfile;
         profile = defaultProfile;
     }
     }
-    SpvVersion spvVersion;
-    if (messages & EShMsgSpvRules)
-        spvVersion.spv = 0x00010000;    // TODO: eventually have this come from the outside
-    EShSource source = (messages & EShMsgReadHlsl) ? EShSourceHlsl : EShSourceGlsl;
-    if (messages & EShMsgVulkanRules)
-        spvVersion.vulkan = 100;     // TODO: eventually have this come from the outside
-    else if (spvVersion.spv != 0)
-        spvVersion.openGl = 100;     // TODO: eventually have this come from the outside
-    bool goodVersion = DeduceVersionProfile(compiler->infoSink, compiler->getLanguage(), versionNotFirst, defaultVersion, source, version, profile, spvVersion);
+
+    bool goodVersion = DeduceVersionProfile(compiler->infoSink, stage,
+                                            versionNotFirst, defaultVersion, source, version, profile, spvVersion);
     bool versionWillBeError = (versionNotFound || (profile == EEsProfile && version >= 300 && versionNotFirst));
     bool versionWillBeError = (versionNotFound || (profile == EEsProfile && version >= 300 && versionNotFirst));
     bool warnVersionNotFirst = false;
     bool warnVersionNotFirst = false;
     if (! versionWillBeError && versionNotFirstToken) {
     if (! versionWillBeError && versionNotFirstToken) {
@@ -689,14 +813,15 @@ bool ProcessDeferred(
     intermediate.setVersion(version);
     intermediate.setVersion(version);
     intermediate.setProfile(profile);
     intermediate.setProfile(profile);
     intermediate.setSpv(spvVersion);
     intermediate.setSpv(spvVersion);
+    RecordProcesses(intermediate, messages, sourceEntryPointName);
     if (spvVersion.vulkan >= 100)
     if (spvVersion.vulkan >= 100)
         intermediate.setOriginUpperLeft();
         intermediate.setOriginUpperLeft();
-    if ((messages & EShMsgHlslOffsets) || (messages & EShMsgReadHlsl))
+    if ((messages & EShMsgHlslOffsets) || source == EShSourceHlsl)
         intermediate.setHlslOffsets();
         intermediate.setHlslOffsets();
     if (messages & EShMsgDebugInfo) {
     if (messages & EShMsgDebugInfo) {
         intermediate.setSourceFile(names[numPre]);
         intermediate.setSourceFile(names[numPre]);
         for (int s = 0; s < numStrings; ++s)
         for (int s = 0; s < numStrings; ++s)
-            intermediate.addSourceText(strings[numPre]);
+            intermediate.addSourceText(strings[numPre + s]);
     }
     }
     SetupBuiltinSymbolTable(version, profile, spvVersion, source);
     SetupBuiltinSymbolTable(version, profile, spvVersion, source);
 
 
@@ -704,7 +829,7 @@ bool ProcessDeferred(
                                                   [MapSpvVersionToIndex(spvVersion)]
                                                   [MapSpvVersionToIndex(spvVersion)]
                                                   [MapProfileToIndex(profile)]
                                                   [MapProfileToIndex(profile)]
                                                   [MapSourceToIndex(source)]
                                                   [MapSourceToIndex(source)]
-                                                  [compiler->getLanguage()];
+                                                  [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* symbolTableMemory = new TSymbolTable;
@@ -715,7 +840,7 @@ bool ProcessDeferred(
     // Add built-in symbols that are potentially context dependent;
     // Add built-in symbols that are potentially context dependent;
     // they get popped again further down.
     // they get popped again further down.
     if (! AddContextSpecificSymbols(resources, compiler->infoSink, symbolTable, version, profile, spvVersion,
     if (! AddContextSpecificSymbols(resources, compiler->infoSink, symbolTable, version, profile, spvVersion,
-                                    compiler->getLanguage(), source))
+                                    stage, source))
         return false;
         return false;
 
 
     //
     //
@@ -723,14 +848,14 @@ bool ProcessDeferred(
     //
     //
 
 
     TParseContextBase* parseContext = CreateParseContext(symbolTable, intermediate, version, profile, source,
     TParseContextBase* parseContext = CreateParseContext(symbolTable, intermediate, version, profile, source,
-                                                         compiler->getLanguage(), compiler->infoSink,
+                                                         stage, compiler->infoSink,
                                                          spvVersion, forwardCompatible, messages, false, sourceEntryPointName);
                                                          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
     glslang::TScanContext scanContext(*parseContext);
     glslang::TScanContext scanContext(*parseContext);
-    if ((messages & EShMsgReadHlsl) == 0)
+    if (source == EShSourceGlsl)
         parseContext->setScanContext(&scanContext);
         parseContext->setScanContext(&scanContext);
 
 
     parseContext->setPpContext(&ppContext);
     parseContext->setPpContext(&ppContext);
@@ -1049,14 +1174,15 @@ bool CompileDeferred(
     EShMessages messages,       // warnings/errors/AST; things to print out
     EShMessages messages,       // warnings/errors/AST; things to print out
     TIntermediate& intermediate,// returned tree, etc.
     TIntermediate& intermediate,// returned tree, etc.
     TShader::Includer& includer,
     TShader::Includer& includer,
-    const std::string sourceEntryPointName = "")
+    const std::string sourceEntryPointName = "",
+    TEnvironment* environment = nullptr)
 {
 {
     DoFullParse parser;
     DoFullParse parser;
     return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames,
     return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames,
                            preamble, optLevel, resources, defaultVersion,
                            preamble, optLevel, resources, defaultVersion,
                            defaultProfile, forceDefaultVersionAndProfile,
                            defaultProfile, forceDefaultVersionAndProfile,
                            forwardCompatible, messages, intermediate, parser,
                            forwardCompatible, messages, intermediate, parser,
-                           true, includer, sourceEntryPointName);
+                           true, includer, sourceEntryPointName, environment);
 }
 }
 
 
 } // end anonymous namespace for local functions
 } // end anonymous namespace for local functions
@@ -1071,7 +1197,11 @@ int ShInitialize()
     if (! InitProcess())
     if (! InitProcess())
         return 0;
         return 0;
 
 
-    if (! PerProcessGPA)
+    glslang::GetGlobalLock();
+    ++NumberOfClients;
+    glslang::ReleaseGlobalLock();
+
+    if (PerProcessGPA == nullptr)
         PerProcessGPA = new TPoolAllocator();
         PerProcessGPA = new TPoolAllocator();
 
 
     glslang::TScanContext::fillInKeywordMap();
     glslang::TScanContext::fillInKeywordMap();
@@ -1137,6 +1267,14 @@ void ShDestruct(ShHandle handle)
 //
 //
 int __fastcall ShFinalize()
 int __fastcall ShFinalize()
 {
 {
+    glslang::GetGlobalLock();
+    --NumberOfClients;
+    assert(NumberOfClients >= 0);
+    bool finalize = NumberOfClients == 0;
+    glslang::ReleaseGlobalLock();
+    if (! finalize)
+        return 1;
+
     for (int version = 0; version < VersionCount; ++version) {
     for (int version = 0; version < VersionCount; ++version) {
         for (int spvVersion = 0; spvVersion < SpvVersionCount; ++spvVersion) {
         for (int spvVersion = 0; spvVersion < SpvVersionCount; ++spvVersion) {
             for (int p = 0; p < ProfileCount; ++p) {
             for (int p = 0; p < ProfileCount; ++p) {
@@ -1163,10 +1301,9 @@ int __fastcall ShFinalize()
         }
         }
     }
     }
 
 
-    if (PerProcessGPA) {
-        PerProcessGPA->popAll();
+    if (PerProcessGPA != nullptr) {
         delete PerProcessGPA;
         delete PerProcessGPA;
-        PerProcessGPA = 0;
+        PerProcessGPA = nullptr;
     }
     }
 
 
     glslang::TScanContext::deleteKeywordMap();
     glslang::TScanContext::deleteKeywordMap();
@@ -1207,6 +1344,8 @@ int ShCompile(
     if (compiler == 0)
     if (compiler == 0)
         return 0;
         return 0;
 
 
+    SetThreadPoolAllocator(compiler->getPool());
+
     compiler->infoSink.info.erase();
     compiler->infoSink.info.erase();
     compiler->infoSink.debug.erase();
     compiler->infoSink.debug.erase();
 
 
@@ -1264,6 +1403,8 @@ int ShLinkExt(
     TShHandleBase* base = reinterpret_cast<TShHandleBase*>(linkHandle);
     TShHandleBase* base = reinterpret_cast<TShHandleBase*>(linkHandle);
     TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
     TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
 
 
+    SetThreadPoolAllocator(linker->getPool());
+
     if (linker == 0)
     if (linker == 0)
         return 0;
         return 0;
 
 
@@ -1298,9 +1439,6 @@ void ShSetEncryptionMethod(ShHandle handle)
 //
 //
 const char* ShGetInfoLog(const ShHandle handle)
 const char* ShGetInfoLog(const ShHandle handle)
 {
 {
-    if (!InitThread())
-        return 0;
-
     if (handle == 0)
     if (handle == 0)
         return 0;
         return 0;
 
 
@@ -1324,9 +1462,6 @@ const char* ShGetInfoLog(const ShHandle handle)
 //
 //
 const void* ShGetExecutable(const ShHandle handle)
 const void* ShGetExecutable(const ShHandle handle)
 {
 {
-    if (!InitThread())
-        return 0;
-
     if (handle == 0)
     if (handle == 0)
         return 0;
         return 0;
 
 
@@ -1349,9 +1484,6 @@ const void* ShGetExecutable(const ShHandle handle)
 //
 //
 int ShSetVirtualAttributeBindings(const ShHandle handle, const ShBindingTable* table)
 int ShSetVirtualAttributeBindings(const ShHandle handle, const ShBindingTable* table)
 {
 {
-    if (!InitThread())
-        return 0;
-
     if (handle == 0)
     if (handle == 0)
         return 0;
         return 0;
 
 
@@ -1371,9 +1503,6 @@ int ShSetVirtualAttributeBindings(const ShHandle handle, const ShBindingTable* t
 //
 //
 int ShSetFixedAttributeBindings(const ShHandle handle, const ShBindingTable* table)
 int ShSetFixedAttributeBindings(const ShHandle handle, const ShBindingTable* table)
 {
 {
-    if (!InitThread())
-        return 0;
-
     if (handle == 0)
     if (handle == 0)
         return 0;
         return 0;
 
 
@@ -1392,9 +1521,6 @@ int ShSetFixedAttributeBindings(const ShHandle handle, const ShBindingTable* tab
 //
 //
 int ShExcludeAttributes(const ShHandle handle, int *attributes, int count)
 int ShExcludeAttributes(const ShHandle handle, int *attributes, int count)
 {
 {
-    if (!InitThread())
-        return 0;
-
     if (handle == 0)
     if (handle == 0)
         return 0;
         return 0;
 
 
@@ -1416,9 +1542,6 @@ int ShExcludeAttributes(const ShHandle handle, int *attributes, int count)
 //
 //
 int ShGetUniformLocation(const ShHandle handle, const char* name)
 int ShGetUniformLocation(const ShHandle handle, const char* name)
 {
 {
-    if (!InitThread())
-        return 0;
-
     if (handle == 0)
     if (handle == 0)
         return -1;
         return -1;
 
 
@@ -1447,12 +1570,12 @@ namespace glslang {
 
 
 const char* GetEsslVersionString()
 const char* GetEsslVersionString()
 {
 {
-    return "OpenGL ES GLSL 3.00 glslang LunarG Khronos." GLSLANG_REVISION " " GLSLANG_DATE;
+    return "OpenGL ES GLSL 3.20 glslang Khronos." GLSLANG_REVISION " " GLSLANG_DATE;
 }
 }
 
 
 const char* GetGlslVersionString()
 const char* GetGlslVersionString()
 {
 {
-    return "4.20 glslang LunarG Khronos." GLSLANG_REVISION " " GLSLANG_DATE;
+    return "4.60 glslang Khronos." GLSLANG_REVISION " " GLSLANG_DATE;
 }
 }
 
 
 int GetKhronosToolId()
 int GetKhronosToolId()
@@ -1477,11 +1600,18 @@ public:
 };
 };
 
 
 TShader::TShader(EShLanguage s)
 TShader::TShader(EShLanguage s)
-    : pool(0), stage(s), lengths(nullptr), stringNames(nullptr), preamble("")
+    : stage(s), lengths(nullptr), stringNames(nullptr), preamble("")
 {
 {
+    pool = new TPoolAllocator;
     infoSink = new TInfoSink;
     infoSink = new TInfoSink;
     compiler = new TDeferredCompiler(stage, *infoSink);
     compiler = new TDeferredCompiler(stage, *infoSink);
     intermediate = new TIntermediate(s);
     intermediate = new TIntermediate(s);
+
+    // clear environment (avoid constructors in them for use in a C interface)
+    environment.input.languageFamily = EShSourceNone;
+    environment.input.dialect = EShClientNone;
+    environment.client.client = EShClientNone;
+    environment.target.language = EShTargetNone;
 }
 }
 
 
 TShader::~TShader()
 TShader::~TShader()
@@ -1525,24 +1655,41 @@ void TShader::setSourceEntryPoint(const char* name)
     sourceEntryPointName = name;
     sourceEntryPointName = name;
 }
 }
 
 
+void TShader::addProcesses(const std::vector<std::string>& p)
+{
+    intermediate->addProcesses(p);
+}
+
+// Set binding base for given resource type
+void TShader::setShiftBinding(TResourceType res, unsigned int base) {
+    intermediate->setShiftBinding(res, base);
+}
+
+// Set binding base for given resource type for a given binding set.
+void TShader::setShiftBindingForSet(TResourceType res, unsigned int base, unsigned int set) {
+    intermediate->setShiftBindingForSet(res, base, set);
+}
+
 // Set binding base for sampler types
 // Set binding base for sampler types
-void TShader::setShiftSamplerBinding(unsigned int base) { intermediate->setShiftSamplerBinding(base); }
+void TShader::setShiftSamplerBinding(unsigned int base) { setShiftBinding(EResSampler, base); }
 // Set binding base for texture types (SRV)
 // Set binding base for texture types (SRV)
-void TShader::setShiftTextureBinding(unsigned int base) { intermediate->setShiftTextureBinding(base); }
+void TShader::setShiftTextureBinding(unsigned int base) { setShiftBinding(EResTexture, base); }
 // Set binding base for image types
 // Set binding base for image types
-void TShader::setShiftImageBinding(unsigned int base)   { intermediate->setShiftImageBinding(base); }
+void TShader::setShiftImageBinding(unsigned int base)   { setShiftBinding(EResImage, base); }
 // Set binding base for uniform buffer objects (CBV)
 // Set binding base for uniform buffer objects (CBV)
-void TShader::setShiftUboBinding(unsigned int base)     { intermediate->setShiftUboBinding(base); }
+void TShader::setShiftUboBinding(unsigned int base)     { setShiftBinding(EResUbo, base); }
 // Synonym for setShiftUboBinding, to match HLSL language.
 // Synonym for setShiftUboBinding, to match HLSL language.
-void TShader::setShiftCbufferBinding(unsigned int base) { intermediate->setShiftUboBinding(base); }
+void TShader::setShiftCbufferBinding(unsigned int base) { setShiftBinding(EResUbo, base); }
 // Set binding base for UAV (unordered access view)
 // Set binding base for UAV (unordered access view)
-void TShader::setShiftUavBinding(unsigned int base)     { intermediate->setShiftUavBinding(base); }
+void TShader::setShiftUavBinding(unsigned int base)     { setShiftBinding(EResUav, base); }
 // Set binding base for SSBOs
 // Set binding base for SSBOs
-void TShader::setShiftSsboBinding(unsigned int base)    { intermediate->setShiftSsboBinding(base); }
+void TShader::setShiftSsboBinding(unsigned int base)    { setShiftBinding(EResSsbo, base); }
 // Enables binding automapping using TIoMapper
 // Enables binding automapping using TIoMapper
 void TShader::setAutoMapBindings(bool map)              { intermediate->setAutoMapBindings(map); }
 void TShader::setAutoMapBindings(bool map)              { intermediate->setAutoMapBindings(map); }
+// Enables position.Y output negation in vertex shader
+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); }
 // 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); }
@@ -1560,16 +1707,16 @@ bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion
 {
 {
     if (! InitThread())
     if (! InitThread())
         return false;
         return false;
+    SetThreadPoolAllocator(pool);
 
 
-    pool = new TPoolAllocator();
-    SetThreadPoolAllocator(*pool);
     if (! preamble)
     if (! preamble)
         preamble = "";
         preamble = "";
 
 
     return CompileDeferred(compiler, strings, numStrings, lengths, stringNames,
     return CompileDeferred(compiler, strings, numStrings, lengths, stringNames,
                            preamble, EShOptNone, builtInResources, defaultVersion,
                            preamble, EShOptNone, builtInResources, defaultVersion,
                            defaultProfile, forceDefaultVersionAndProfile,
                            defaultProfile, forceDefaultVersionAndProfile,
-                           forwardCompatible, messages, *intermediate, includer, sourceEntryPointName);
+                           forwardCompatible, messages, *intermediate, includer, sourceEntryPointName,
+                           &environment);
 }
 }
 
 
 // Fill in a string with the result of preprocessing ShaderStrings
 // Fill in a string with the result of preprocessing ShaderStrings
@@ -1583,9 +1730,8 @@ bool TShader::preprocess(const TBuiltInResource* builtInResources,
 {
 {
     if (! InitThread())
     if (! InitThread())
         return false;
         return false;
+    SetThreadPoolAllocator(pool);
 
 
-    pool = new TPoolAllocator();
-    SetThreadPoolAllocator(*pool);
     if (! preamble)
     if (! preamble)
         preamble = "";
         preamble = "";
 
 
@@ -1605,8 +1751,9 @@ const char* TShader::getInfoDebugLog()
     return infoSink->debug.c_str();
     return infoSink->debug.c_str();
 }
 }
 
 
-TProgram::TProgram() : pool(0), reflection(0), ioMapper(nullptr), linked(false)
+TProgram::TProgram() : reflection(0), ioMapper(nullptr), linked(false)
 {
 {
+    pool = new TPoolAllocator;
     infoSink = new TInfoSink;
     infoSink = new TInfoSink;
     for (int s = 0; s < EShLangCount; ++s) {
     for (int s = 0; s < EShLangCount; ++s) {
         intermediate[s] = 0;
         intermediate[s] = 0;
@@ -1641,8 +1788,7 @@ bool TProgram::link(EShMessages messages)
 
 
     bool error = false;
     bool error = false;
 
 
-    pool = new TPoolAllocator();
-    SetThreadPoolAllocator(*pool);
+    SetThreadPoolAllocator(pool);
 
 
     for (int s = 0; s < EShLangCount; ++s) {
     for (int s = 0; s < EShLangCount; ++s) {
         if (! linkStage((EShLanguage)s, messages))
         if (! linkStage((EShLanguage)s, messages))
@@ -1758,6 +1904,7 @@ const char* TProgram::getUniformName(int index) const        { return reflection
 const char* TProgram::getUniformBlockName(int index) const   { return reflection->getUniformBlock(index).name.c_str(); }
 const char* TProgram::getUniformBlockName(int index) const   { return reflection->getUniformBlock(index).name.c_str(); }
 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::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; }

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

@@ -104,11 +104,20 @@ void TType::buildMangledName(TString& mangledName) const
         default: break; // some compilers want this
         default: break; // some compilers want this
         }
         }
 
 
-        switch (sampler.vectorSize) {
-        case 1: mangledName += "1"; break;
-        case 2: mangledName += "2"; break;
-        case 3: mangledName += "3"; break;
-        case 4: break; // default to prior name mangle behavior
+        if (sampler.hasReturnStruct()) {
+            // Name mangle for sampler return struct uses struct table index.
+            mangledName += "-tx-struct";
+
+            char text[16]; // plenty enough space for the small integers.
+            snprintf(text, sizeof(text), "%d-", sampler.structReturnIndex);
+            mangledName += text;
+        } else {
+            switch (sampler.getVectorSize()) {
+            case 1: mangledName += "1"; break;
+            case 2: mangledName += "2"; break;
+            case 3: mangledName += "3"; break;
+            case 4: break; // default to prior name mangle behavior
+            }
         }
         }
 
 
         if (sampler.ms)
         if (sampler.ms)

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

@@ -154,9 +154,10 @@ void TParseVersions::initializeExtensionBehavior()
     extensionBehavior[E_GL_OES_standard_derivatives]         = EBhDisable;
     extensionBehavior[E_GL_OES_standard_derivatives]         = EBhDisable;
     extensionBehavior[E_GL_EXT_frag_depth]                   = EBhDisable;
     extensionBehavior[E_GL_EXT_frag_depth]                   = EBhDisable;
     extensionBehavior[E_GL_OES_EGL_image_external]           = EBhDisable;
     extensionBehavior[E_GL_OES_EGL_image_external]           = EBhDisable;
+    extensionBehavior[E_GL_OES_EGL_image_external_essl3]     = EBhDisable;
     extensionBehavior[E_GL_EXT_shader_texture_lod]           = EBhDisable;
     extensionBehavior[E_GL_EXT_shader_texture_lod]           = EBhDisable;
-
     extensionBehavior[E_GL_EXT_texture_array]                = EBhDisable;
     extensionBehavior[E_GL_EXT_texture_array]                = EBhDisable;
+    extensionBehavior[E_GL_EXT_shadow_samplers]              = EBhDisable;
     extensionBehavior[E_GL_ARB_texture_rectangle]            = EBhDisable;
     extensionBehavior[E_GL_ARB_texture_rectangle]            = EBhDisable;
     extensionBehavior[E_GL_3DL_array_objects]                = EBhDisable;
     extensionBehavior[E_GL_3DL_array_objects]                = EBhDisable;
     extensionBehavior[E_GL_ARB_shading_language_420pack]     = EBhDisable;
     extensionBehavior[E_GL_ARB_shading_language_420pack]     = EBhDisable;
@@ -180,10 +181,14 @@ void TParseVersions::initializeExtensionBehavior()
     extensionBehavior[E_GL_ARB_shader_ballot]                = EBhDisable;
     extensionBehavior[E_GL_ARB_shader_ballot]                = EBhDisable;
     extensionBehavior[E_GL_ARB_sparse_texture2]              = EBhDisable;
     extensionBehavior[E_GL_ARB_sparse_texture2]              = EBhDisable;
     extensionBehavior[E_GL_ARB_sparse_texture_clamp]         = EBhDisable;
     extensionBehavior[E_GL_ARB_sparse_texture_clamp]         = EBhDisable;
+    extensionBehavior[E_GL_ARB_shader_stencil_export]        = EBhDisable;
 //    extensionBehavior[E_GL_ARB_cull_distance]                = EBhDisable;    // present for 4.5, but need extension control over block members
 //    extensionBehavior[E_GL_ARB_cull_distance]                = EBhDisable;    // present for 4.5, but need extension control over block members
+    extensionBehavior[E_GL_ARB_post_depth_coverage]          = EBhDisable;
+    extensionBehavior[E_GL_ARB_shader_viewport_layer_array]  = 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;
 
 
     // #line and #include
     // #line and #include
     extensionBehavior[E_GL_GOOGLE_cpp_style_line_directive]          = EBhDisable;
     extensionBehavior[E_GL_GOOGLE_cpp_style_line_directive]          = EBhDisable;
@@ -197,15 +202,18 @@ void TParseVersions::initializeExtensionBehavior()
     extensionBehavior[E_GL_AMD_gpu_shader_half_float]                = EBhDisable;
     extensionBehavior[E_GL_AMD_gpu_shader_half_float]                = EBhDisable;
     extensionBehavior[E_GL_AMD_texture_gather_bias_lod]              = EBhDisable;
     extensionBehavior[E_GL_AMD_texture_gather_bias_lod]              = EBhDisable;
     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_fragment_mask]                 = EBhDisable;
 #endif
 #endif
 
 
 #ifdef NV_EXTENSIONS
 #ifdef NV_EXTENSIONS
     extensionBehavior[E_GL_NV_sample_mask_override_coverage]         = EBhDisable;
     extensionBehavior[E_GL_NV_sample_mask_override_coverage]         = EBhDisable;
     extensionBehavior[E_SPV_NV_geometry_shader_passthrough]          = EBhDisable;
     extensionBehavior[E_SPV_NV_geometry_shader_passthrough]          = EBhDisable;
-    extensionBehavior[E_GL_ARB_shader_viewport_layer_array]          = EBhDisable;
     extensionBehavior[E_GL_NV_viewport_array2]                       = EBhDisable;
     extensionBehavior[E_GL_NV_viewport_array2]                       = EBhDisable;
     extensionBehavior[E_GL_NV_stereo_view_rendering]                 = EBhDisable;
     extensionBehavior[E_GL_NV_stereo_view_rendering]                 = EBhDisable;
     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_conservative_raster_underestimation]   = EBhDisable;
 #endif
 #endif
 
 
     // AEP
     // AEP
@@ -239,6 +247,10 @@ void TParseVersions::initializeExtensionBehavior()
     // EXT extensions
     // EXT extensions
     extensionBehavior[E_GL_EXT_device_group]             = EBhDisable;
     extensionBehavior[E_GL_EXT_device_group]             = EBhDisable;
     extensionBehavior[E_GL_EXT_multiview]                = EBhDisable;
     extensionBehavior[E_GL_EXT_multiview]                = EBhDisable;
+
+    // OVR extensions
+    extensionBehavior[E_GL_OVR_multiview]                = EBhDisable;
+    extensionBehavior[E_GL_OVR_multiview2]               = 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,
@@ -254,7 +266,9 @@ void TParseVersions::getPreamble(std::string& preamble)
             "#define GL_OES_standard_derivatives 1\n"
             "#define GL_OES_standard_derivatives 1\n"
             "#define GL_EXT_frag_depth 1\n"
             "#define GL_EXT_frag_depth 1\n"
             "#define GL_OES_EGL_image_external 1\n"
             "#define GL_OES_EGL_image_external 1\n"
+            "#define GL_OES_EGL_image_external_essl3 1\n"
             "#define GL_EXT_shader_texture_lod 1\n"
             "#define GL_EXT_shader_texture_lod 1\n"
+            "#define GL_EXT_shadow_samplers 1\n"
 
 
             // AEP
             // AEP
             "#define GL_ANDROID_extension_pack_es31a 1\n"
             "#define GL_ANDROID_extension_pack_es31a 1\n"
@@ -311,9 +325,12 @@ void TParseVersions::getPreamble(std::string& preamble)
             "#define GL_ARB_shader_ballot 1\n"
             "#define GL_ARB_shader_ballot 1\n"
             "#define GL_ARB_sparse_texture2 1\n"
             "#define GL_ARB_sparse_texture2 1\n"
             "#define GL_ARB_sparse_texture_clamp 1\n"
             "#define GL_ARB_sparse_texture_clamp 1\n"
+            "#define GL_ARB_shader_stencil_export 1\n"
 //            "#define GL_ARB_cull_distance 1\n"    // present for 4.5, but need extension control over block members
 //            "#define GL_ARB_cull_distance 1\n"    // present for 4.5, but need extension control over block members
+            "#define GL_ARB_post_depth_coverage 1\n"
             "#define GL_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"
 
 
 #ifdef AMD_EXTENSIONS
 #ifdef AMD_EXTENSIONS
             "#define GL_AMD_shader_ballot 1\n"
             "#define GL_AMD_shader_ballot 1\n"
@@ -323,12 +340,16 @@ void TParseVersions::getPreamble(std::string& preamble)
             "#define GL_AMD_gpu_shader_half_float 1\n"
             "#define GL_AMD_gpu_shader_half_float 1\n"
             "#define GL_AMD_texture_gather_bias_lod 1\n"
             "#define GL_AMD_texture_gather_bias_lod 1\n"
             "#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_fragment_mask 1\n"
 #endif
 #endif
 
 
 #ifdef NV_EXTENSIONS
 #ifdef NV_EXTENSIONS
             "#define GL_NV_sample_mask_override_coverage 1\n"
             "#define GL_NV_sample_mask_override_coverage 1\n"
             "#define GL_NV_geometry_shader_passthrough 1\n"
             "#define GL_NV_geometry_shader_passthrough 1\n"
             "#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_conservative_raster_underestimation 1\n"
 #endif
 #endif
             ;
             ;
 
 
@@ -343,12 +364,19 @@ void TParseVersions::getPreamble(std::string& preamble)
 
 
     if ((profile != EEsProfile && version >= 140) ||
     if ((profile != EEsProfile && version >= 140) ||
         (profile == EEsProfile && version >= 310)) {
         (profile == EEsProfile && version >= 310)) {
-        preamble += 
+        preamble +=
             "#define GL_EXT_device_group 1\n"
             "#define GL_EXT_device_group 1\n"
             "#define GL_EXT_multiview 1\n"
             "#define GL_EXT_multiview 1\n"
             ;
             ;
     }
     }
 
 
+    if (version >= 300 /* both ES and non-ES */) {
+        preamble +=
+            "#define GL_OVR_multiview 1\n"
+            "#define GL_OVR_multiview2 1\n"
+            ;
+    }
+
     // #line and #include
     // #line and #include
     preamble +=
     preamble +=
             "#define GL_GOOGLE_cpp_style_line_directive 1\n"
             "#define GL_GOOGLE_cpp_style_line_directive 1\n"
@@ -358,9 +386,9 @@ void TParseVersions::getPreamble(std::string& preamble)
     // #define VULKAN XXXX
     // #define VULKAN XXXX
     const int numberBufSize = 12;
     const int numberBufSize = 12;
     char numberBuf[numberBufSize];
     char numberBuf[numberBufSize];
-    if (spvVersion.vulkan > 0) {
+    if (spvVersion.vulkanGlsl > 0) {
         preamble += "#define VULKAN ";
         preamble += "#define VULKAN ";
-        snprintf(numberBuf, numberBufSize, "%d", spvVersion.vulkan);
+        snprintf(numberBuf, numberBufSize, "%d", spvVersion.vulkanGlsl);
         preamble += numberBuf;
         preamble += numberBuf;
         preamble += "\n";
         preamble += "\n";
     }
     }

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

@@ -72,14 +72,19 @@ inline const char* ProfileName(EProfile profile)
 }
 }
 
 
 //
 //
-// SPIR-V has versions for multiple things; tie them together.
-// 0 means a target or rule set is not enabled.
+// What source rules, validation rules, target language, etc. are needed
+// desired for SPIR-V?
+//
+// 0 means a target or rule set is not enabled (ignore rules from that entity).
+// Non-0 means to apply semantic rules arising from that version of its rule set.
+// The union of all requested rule sets will be applied.
 //
 //
 struct SpvVersion {
 struct SpvVersion {
-    SpvVersion() : spv(0), vulkan(0), openGl(0) {}
-    unsigned int spv; // the version of the targeted SPIR-V, as defined by SPIR-V in word 1 of the SPIR-V binary header
-    int vulkan;       // the version of semantics for Vulkan; e.g., for GLSL from KHR_vulkan_glsl "#define VULKAN"
-    int openGl;       // the version of semantics for OpenGL; e.g., for GLSL from KHR_vulkan_glsl "#define GL_SPIRV"
+    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
+    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 openGl;       // the version of GLSL semantics for OpenGL, from GL_ARB_gl_spirv, for "#define GL_SPIRV XXX"
 };
 };
 
 
 //
 //
@@ -102,7 +107,9 @@ const char* const E_GL_OES_texture_3D                   = "GL_OES_texture_3D";
 const char* const E_GL_OES_standard_derivatives         = "GL_OES_standard_derivatives";
 const char* const E_GL_OES_standard_derivatives         = "GL_OES_standard_derivatives";
 const char* const E_GL_EXT_frag_depth                   = "GL_EXT_frag_depth";
 const char* const E_GL_EXT_frag_depth                   = "GL_EXT_frag_depth";
 const char* const E_GL_OES_EGL_image_external           = "GL_OES_EGL_image_external";
 const char* const E_GL_OES_EGL_image_external           = "GL_OES_EGL_image_external";
+const char* const E_GL_OES_EGL_image_external_essl3     = "GL_OES_EGL_image_external_essl3";
 const char* const E_GL_EXT_shader_texture_lod           = "GL_EXT_shader_texture_lod";
 const char* const E_GL_EXT_shader_texture_lod           = "GL_EXT_shader_texture_lod";
+const char* const E_GL_EXT_shadow_samplers              = "GL_EXT_shadow_samplers";
 
 
 const char* const E_GL_EXT_texture_array                = "GL_EXT_texture_array";
 const char* const E_GL_EXT_texture_array                = "GL_EXT_texture_array";
 const char* const E_GL_ARB_texture_rectangle            = "GL_ARB_texture_rectangle";
 const char* const E_GL_ARB_texture_rectangle            = "GL_ARB_texture_rectangle";
@@ -128,7 +135,10 @@ const char* const E_GL_ARB_gpu_shader_int64             = "GL_ARB_gpu_shader_int
 const char* const E_GL_ARB_shader_ballot                = "GL_ARB_shader_ballot";
 const char* const E_GL_ARB_shader_ballot                = "GL_ARB_shader_ballot";
 const char* const E_GL_ARB_sparse_texture2              = "GL_ARB_sparse_texture2";
 const char* const E_GL_ARB_sparse_texture2              = "GL_ARB_sparse_texture2";
 const char* const E_GL_ARB_sparse_texture_clamp         = "GL_ARB_sparse_texture_clamp";
 const char* const E_GL_ARB_sparse_texture_clamp         = "GL_ARB_sparse_texture_clamp";
+const char* const E_GL_ARB_shader_stencil_export        = "GL_ARB_shader_stencil_export";
 // const char* const E_GL_ARB_cull_distance            = "GL_ARB_cull_distance";  // present for 4.5, but need extension control over block members
 // const char* const E_GL_ARB_cull_distance            = "GL_ARB_cull_distance";  // present for 4.5, but need extension control over block members
+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_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";
@@ -136,6 +146,19 @@ const char* const E_GL_EXT_shader_image_load_formatted = "GL_EXT_shader_image_lo
 // EXT extensions
 // EXT extensions
 const char* const E_GL_EXT_device_group                 = "GL_EXT_device_group";
 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_multiview                    = "GL_EXT_multiview";
+const char* const E_GL_EXT_post_depth_coverage          = "GL_EXT_post_depth_coverage";
+
+// Arrays of extensions for the above viewportEXTs duplications
+
+const char* const post_depth_coverageEXTs[] = { E_GL_ARB_post_depth_coverage, E_GL_EXT_post_depth_coverage };
+const int Num_post_depth_coverageEXTs = sizeof(post_depth_coverageEXTs) / sizeof(post_depth_coverageEXTs[0]);
+
+// OVR extensions
+const char* const E_GL_OVR_multiview                    = "GL_OVR_multiview";
+const char* const E_GL_OVR_multiview2                   = "GL_OVR_multiview2";
+
+const char* const OVR_multiview_EXTs[] = { E_GL_OVR_multiview, E_GL_OVR_multiview2 };
+const int Num_OVR_multiview_EXTs = sizeof(OVR_multiview_EXTs) / sizeof(OVR_multiview_EXTs[0]);
 
 
 // #line and #include
 // #line and #include
 const char* const E_GL_GOOGLE_cpp_style_line_directive          = "GL_GOOGLE_cpp_style_line_directive";
 const char* const E_GL_GOOGLE_cpp_style_line_directive          = "GL_GOOGLE_cpp_style_line_directive";
@@ -149,16 +172,19 @@ const char* const E_GL_AMD_gcn_shader                           = "GL_AMD_gcn_sh
 const char* const E_GL_AMD_gpu_shader_half_float                = "GL_AMD_gpu_shader_half_float";
 const char* const E_GL_AMD_gpu_shader_half_float                = "GL_AMD_gpu_shader_half_float";
 const char* const E_GL_AMD_texture_gather_bias_lod              = "GL_AMD_texture_gather_bias_lod";
 const char* const E_GL_AMD_texture_gather_bias_lod              = "GL_AMD_texture_gather_bias_lod";
 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_fragment_mask                 = "GL_AMD_shader_fragment_mask";
 #endif
 #endif
 
 
 #ifdef NV_EXTENSIONS
 #ifdef NV_EXTENSIONS
 
 
 const char* const E_GL_NV_sample_mask_override_coverage         = "GL_NV_sample_mask_override_coverage";
 const char* const E_GL_NV_sample_mask_override_coverage         = "GL_NV_sample_mask_override_coverage";
 const char* const E_SPV_NV_geometry_shader_passthrough          = "GL_NV_geometry_shader_passthrough";
 const char* const E_SPV_NV_geometry_shader_passthrough          = "GL_NV_geometry_shader_passthrough";
-const char* const E_GL_ARB_shader_viewport_layer_array          = "GL_ARB_shader_viewport_layer_array";
 const char* const E_GL_NV_viewport_array2                       = "GL_NV_viewport_array2";
 const char* const E_GL_NV_viewport_array2                       = "GL_NV_viewport_array2";
 const char* const E_GL_NV_stereo_view_rendering                 = "GL_NV_stereo_view_rendering";
 const char* const E_GL_NV_stereo_view_rendering                 = "GL_NV_stereo_view_rendering";
 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_conservative_raster_underestimation   = "GL_NV_conservative_raster_underestimation";
 
 
 // Arrays of extensions for the above viewportEXTs duplications
 // Arrays of extensions for the above viewportEXTs duplications
 
 

File diff suppressed because it is too large
+ 507 - 358
src/libraries/glslang/glslang/MachineIndependent/gl_types.h


+ 3 - 5
src/libraries/glslang/glslang/MachineIndependent/glslang_tab.cpp.h

@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 3.0.4.  */
+/* A Bison parser, made by GNU Bison 3.0.  */
 
 
 /* Bison interface for Yacc-like parsers in C
 /* Bison interface for Yacc-like parsers in C
 
 
-   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+   Copyright (C) 1984, 1989-1990, 2000-2013 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
@@ -345,7 +345,7 @@ extern int yydebug;
 
 
 /* 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 68 "MachineIndependent/glslang.y" /* yacc.c:1909  */
@@ -384,8 +384,6 @@ union YYSTYPE
 
 
 #line 386 "MachineIndependent/glslang_tab.cpp.h" /* yacc.c:1909  */
 #line 386 "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

+ 32 - 4
src/libraries/glslang/glslang/MachineIndependent/intermOut.cpp

@@ -196,6 +196,7 @@ bool TOutputTraverser::visitBinary(TVisit /* visit */, TIntermBinary* node)
     case EOpLogicalOr:  out.debug << "logical-or";   break;
     case EOpLogicalOr:  out.debug << "logical-or";   break;
     case EOpLogicalXor: out.debug << "logical-xor"; break;
     case EOpLogicalXor: out.debug << "logical-xor"; break;
     case EOpLogicalAnd: out.debug << "logical-and"; break;
     case EOpLogicalAnd: out.debug << "logical-and"; break;
+
     default: out.debug << "<unknown op>";
     default: out.debug << "<unknown op>";
     }
     }
 
 
@@ -431,10 +432,13 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
     case EOpMaxInvocationsExclusiveScanNonUniform:  out.debug << "maxInvocationsExclusiveScanNonUniform";   break;
     case EOpMaxInvocationsExclusiveScanNonUniform:  out.debug << "maxInvocationsExclusiveScanNonUniform";   break;
     case EOpAddInvocationsExclusiveScanNonUniform:  out.debug << "addInvocationsExclusiveScanNonUniform";   break;
     case EOpAddInvocationsExclusiveScanNonUniform:  out.debug << "addInvocationsExclusiveScanNonUniform";   break;
 
 
-    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 EOpCubeFaceIndex:          out.debug << "cubeFaceIndex";         break;
-    case EOpCubeFaceCoord:          out.debug << "cubeFaceCoord";         break;
+    case EOpFragmentMaskFetch:      out.debug << "fragmentMaskFetchAMD";        break;
+    case EOpFragmentFetch:          out.debug << "fragmentFetchAMD";            break;
 
 
     case EOpConvBoolToFloat16:      out.debug << "Convert bool to float16";     break;
     case EOpConvBoolToFloat16:      out.debug << "Convert bool to float16";     break;
     case EOpConvIntToFloat16:       out.debug << "Convert int to float16";      break;
     case EOpConvIntToFloat16:       out.debug << "Convert int to float16";      break;
@@ -488,6 +492,9 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
     case EOpConvUint16ToUint64:     out.debug << "Convert uint16 to uint64";    break;
     case EOpConvUint16ToUint64:     out.debug << "Convert uint16 to uint64";    break;
 #endif
 #endif
 
 
+    case EOpSubpassLoad:   out.debug << "subpassLoad";   break;
+    case EOpSubpassLoadMS: out.debug << "subpassLoadMS"; break;
+
     default: out.debug.message(EPrefixError, "Bad unary op");
     default: out.debug.message(EPrefixError, "Bad unary op");
     }
     }
 
 
@@ -682,6 +689,16 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
     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 EOpAtomicCounterAdd:           out.debug << "AtomicCounterAdd";      break;
+    case EOpAtomicCounterSubtract:      out.debug << "AtomicCounterSubtract"; break;
+    case EOpAtomicCounterMin:           out.debug << "AtomicCounterMin";      break;
+    case EOpAtomicCounterMax:           out.debug << "AtomicCounterMax";      break;
+    case EOpAtomicCounterAnd:           out.debug << "AtomicCounterAnd";      break;
+    case EOpAtomicCounterOr:            out.debug << "AtomicCounterOr";       break;
+    case EOpAtomicCounterXor:           out.debug << "AtomicCounterXor";      break;
+    case EOpAtomicCounterExchange:      out.debug << "AtomicCounterExchange"; break;
+    case EOpAtomicCounterCompSwap:      out.debug << "AtomicCounterCompSwap"; break;
+
     case EOpImageQuerySize:             out.debug << "imageQuerySize";        break;
     case EOpImageQuerySize:             out.debug << "imageQuerySize";        break;
     case EOpImageQuerySamples:          out.debug << "imageQuerySamples";     break;
     case EOpImageQuerySamples:          out.debug << "imageQuerySamples";     break;
     case EOpImageLoad:                  out.debug << "imageLoad";             break;
     case EOpImageLoad:                  out.debug << "imageLoad";             break;
@@ -694,6 +711,10 @@ 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;
+#ifdef AMD_EXTENSIONS
+    case EOpImageLoadLod:               out.debug << "imageLoadLod";          break;
+    case EOpImageStoreLod:              out.debug << "imageStoreLod";         break;
+#endif
 
 
     case EOpTextureQuerySize:           out.debug << "textureSize";           break;
     case EOpTextureQuerySize:           out.debug << "textureSize";           break;
     case EOpTextureQueryLod:            out.debug << "textureQueryLod";       break;
     case EOpTextureQueryLod:            out.debug << "textureQueryLod";       break;
@@ -746,6 +767,7 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
     case EOpSparseTextureGatherLod:         out.debug << "sparseTextureGatherLod";          break;
     case EOpSparseTextureGatherLod:         out.debug << "sparseTextureGatherLod";          break;
     case EOpSparseTextureGatherLodOffset:   out.debug << "sparseTextureGatherLodOffset";    break;
     case EOpSparseTextureGatherLodOffset:   out.debug << "sparseTextureGatherLodOffset";    break;
     case EOpSparseTextureGatherLodOffsets:  out.debug << "sparseTextureGatherLodOffsets";   break;
     case EOpSparseTextureGatherLodOffsets:  out.debug << "sparseTextureGatherLodOffsets";   break;
+    case EOpSparseImageLoadLod:             out.debug << "sparseImageLoadLod";              break;
 #endif
 #endif
 
 
     case EOpAddCarry:                   out.debug << "addCarry";              break;
     case EOpAddCarry:                   out.debug << "addCarry";              break;
@@ -769,10 +791,14 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
     case EOpGenMul:                     out.debug << "mul";                   break;
     case EOpGenMul:                     out.debug << "mul";                   break;
 
 
     case EOpAllMemoryBarrierWithGroupSync:    out.debug << "AllMemoryBarrierWithGroupSync";    break;
     case EOpAllMemoryBarrierWithGroupSync:    out.debug << "AllMemoryBarrierWithGroupSync";    break;
-    case EOpGroupMemoryBarrierWithGroupSync: out.debug << "GroupMemoryBarrierWithGroupSync"; break;
+    case EOpDeviceMemoryBarrier:              out.debug << "DeviceMemoryBarrier";              break;
+    case EOpDeviceMemoryBarrierWithGroupSync: out.debug << "DeviceMemoryBarrierWithGroupSync"; break;
     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 EOpSubpassLoad:   out.debug << "subpassLoad";   break;
+    case EOpSubpassLoadMS: out.debug << "subpassLoadMS"; break;
+
     default: out.debug.message(EPrefixError, "Bad aggregation op");
     default: out.debug.message(EPrefixError, "Bad aggregation op");
     }
     }
 
 
@@ -1085,6 +1111,8 @@ void TIntermediate::output(TInfoSink& infoSink, bool tree)
             infoSink.debug << "gl_FragCoord origin is upper left\n";
             infoSink.debug << "gl_FragCoord origin is upper left\n";
         if (earlyFragmentTests)
         if (earlyFragmentTests)
             infoSink.debug << "using early_fragment_tests\n";
             infoSink.debug << "using early_fragment_tests\n";
+        if (postDepthCoverage)
+            infoSink.debug << "using post_depth_coverage\n";
         if (depthLayout != EldNone)
         if (depthLayout != EldNone)
             infoSink.debug << "using " << TQualifier::getLayoutDepthString(depthLayout) << "\n";
             infoSink.debug << "using " << TQualifier::getLayoutDepthString(depthLayout) << "\n";
         if (blendEquations != 0) {
         if (blendEquations != 0) {

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

@@ -253,10 +253,14 @@ struct TResolverUniformAdaptor
         ent.newBinding = -1;
         ent.newBinding = -1;
         ent.newSet = -1;
         ent.newSet = -1;
         ent.newIndex = -1;
         ent.newIndex = -1;
-        const bool isValid = resolver.validateBinding(stage, ent.symbol->getName().c_str(), ent.symbol->getType(), ent.live);
+        const bool isValid = resolver.validateBinding(stage, ent.symbol->getName().c_str(), ent.symbol->getType(),
+                                                             ent.live);
         if (isValid) {
         if (isValid) {
-            ent.newBinding = resolver.resolveBinding(stage, ent.symbol->getName().c_str(), ent.symbol->getType(), ent.live);
+            ent.newBinding = resolver.resolveBinding(stage, ent.symbol->getName().c_str(), ent.symbol->getType(),
+                                                            ent.live);
             ent.newSet = resolver.resolveSet(stage, ent.symbol->getName().c_str(), ent.symbol->getType(), ent.live);
             ent.newSet = resolver.resolveSet(stage, ent.symbol->getName().c_str(), ent.symbol->getType(), ent.live);
+            ent.newLocation = resolver.resolveUniformLocation(stage, ent.symbol->getName().c_str(),
+                                                                     ent.symbol->getType(), ent.live);
 
 
             if (ent.newBinding != -1) {
             if (ent.newBinding != -1) {
                 if (ent.newBinding >= int(TQualifier::layoutBindingEnd)) {
                 if (ent.newBinding >= int(TQualifier::layoutBindingEnd)) {
@@ -347,15 +351,21 @@ private:
 // Base class for shared TIoMapResolver services, used by several derivations.
 // Base class for shared TIoMapResolver services, used by several derivations.
 struct TDefaultIoResolverBase : public glslang::TIoMapResolver
 struct TDefaultIoResolverBase : public glslang::TIoMapResolver
 {
 {
-    int baseSamplerBinding;
-    int baseTextureBinding;
-    int baseImageBinding;
-    int baseUboBinding;
-    int baseSsboBinding;
-    int baseUavBinding;
-    std::vector<std::string> baseResourceSetBinding;
-    bool doAutoBindingMapping;
-    bool doAutoLocationMapping;
+    TDefaultIoResolverBase(const TIntermediate &intermediate) :
+        intermediate(intermediate),
+        nextUniformLocation(0)
+    { }
+
+    int getBaseBinding(TResourceType res, unsigned int set) const {
+        return selectBaseBinding(intermediate.getShiftBinding(res), 
+                                 intermediate.getShiftBindingForSet(res, set));
+    }
+
+    const std::vector<std::string>& getResourceSetBinding() const { return intermediate.getResourceSetBinding(); }
+
+    bool doAutoBindingMapping() const { return intermediate.getAutoMapBindings(); }
+    bool doAutoLocationMapping() const { return intermediate.getAutoMapLocations(); }
+
     typedef std::vector<int> TSlotSet;
     typedef std::vector<int> TSlotSet;
     typedef std::unordered_map<int, TSlotSet> TSlotSetMap;
     typedef std::unordered_map<int, TSlotSet> TSlotSetMap;
     TSlotSetMap slots;
     TSlotSetMap slots;
@@ -404,18 +414,56 @@ struct TDefaultIoResolverBase : public glslang::TIoMapResolver
     {
     {
         if (type.getQualifier().hasSet())
         if (type.getQualifier().hasSet())
             return type.getQualifier().layoutSet;
             return type.getQualifier().layoutSet;
+
+        // If a command line or API option requested a single descriptor set, use that (if not overrided by spaceN)
+        if (getResourceSetBinding().size() == 1)
+            return atoi(getResourceSetBinding()[0].c_str());
+
         return 0;
         return 0;
     }
     }
+    int resolveUniformLocation(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool /*is_live*/) override
+    {
+        // kick out of not doing this
+        if (!doAutoLocationMapping())
+            return -1;
+
+        // no locations added if already present, a built-in variable, a block, or an opaque
+        if (type.getQualifier().hasLocation() || type.isBuiltIn() ||
+            type.getBasicType() == EbtBlock || type.containsOpaque())
+            return -1;
 
 
+        // no locations on blocks of built-in variables
+        if (type.isStruct()) {
+            if (type.getStruct()->size() < 1)
+                return -1;
+            if ((*type.getStruct())[0].type->isBuiltIn())
+                return -1;
+        }
+
+        return nextUniformLocation++;
+    }
     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
     {
     {
-        if (!doAutoLocationMapping || type.getQualifier().hasLocation())
+        // kick out of not doing this
+        if (!doAutoLocationMapping())
             return -1;
             return -1;
 
 
+        // no locations added if already present, or a built-in variable
+        if (type.getQualifier().hasLocation() || type.isBuiltIn())
+            return -1;
+
+        // no locations on blocks of built-in variables
+        if (type.isStruct()) {
+            if (type.getStruct()->size() < 1)
+                return -1;
+            if ((*type.getStruct())[0].type->isBuiltIn())
+                return -1;
+        }
+
         // Placeholder.
         // Placeholder.
         // TODO: It would be nice to flesh this out using 
         // TODO: It would be nice to flesh this out using 
         // intermediate->computeTypeLocationSize(type), or functions that call it like
         // intermediate->computeTypeLocationSize(type), or functions that call it like
@@ -436,9 +484,20 @@ struct TDefaultIoResolverBase : public glslang::TIoMapResolver
 
 
     void notifyBinding(EShLanguage, const char* /*name*/, const TType&, bool /*is_live*/) override {}
     void notifyBinding(EShLanguage, const char* /*name*/, const TType&, bool /*is_live*/) override {}
     void notifyInOut(EShLanguage, const char* /*name*/, const TType&, bool /*is_live*/) override {}
     void notifyInOut(EShLanguage, const char* /*name*/, const TType&, bool /*is_live*/) override {}
-    void endNotifications() override {}
+    void endNotifications(EShLanguage) override {}
+    void beginNotifications(EShLanguage) override {}
+    void beginResolve(EShLanguage) override {}
+    void endResolve(EShLanguage) override {}
 
 
 protected:
 protected:
+    const TIntermediate &intermediate;
+    int nextUniformLocation;
+
+    // Return descriptor set specific base if there is one, and the generic base otherwise.
+    int selectBaseBinding(int base, int descriptorSetBase) const {
+        return descriptorSetBase != -1 ? descriptorSetBase : base;
+    }
+
     static int getLayoutSet(const glslang::TType& type) {
     static int getLayoutSet(const glslang::TType& type) {
         if (type.getQualifier().hasSet())
         if (type.getQualifier().hasSet())
             return type.getQualifier().layoutSet;
             return type.getQualifier().layoutSet;
@@ -451,7 +510,8 @@ protected:
     }
     }
 
 
     static bool isTextureType(const glslang::TType& type) {
     static bool isTextureType(const glslang::TType& type) {
-        return type.getBasicType() == glslang::EbtSampler && type.getSampler().isTexture();
+        return (type.getBasicType() == glslang::EbtSampler && 
+                (type.getSampler().isTexture() || type.getSampler().isSubpass()));
     }
     }
 
 
     static bool isUboType(const glslang::TType& type) {
     static bool isUboType(const glslang::TType& type) {
@@ -471,6 +531,8 @@ protected:
  */
  */
 struct TDefaultIoResolver : public TDefaultIoResolverBase
 struct TDefaultIoResolver : public TDefaultIoResolverBase
 {
 {
+    TDefaultIoResolver(const TIntermediate &intermediate) : TDefaultIoResolverBase(intermediate) { }
+
     bool validateBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& /*type*/, bool /*is_live*/) override
     bool validateBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& /*type*/, bool /*is_live*/) override
     {
     {
         return true;
         return true;
@@ -482,37 +544,37 @@ struct TDefaultIoResolver : public TDefaultIoResolverBase
 
 
         if (type.getQualifier().hasBinding()) {
         if (type.getQualifier().hasBinding()) {
             if (isImageType(type))
             if (isImageType(type))
-                return reserveSlot(set, baseImageBinding + type.getQualifier().layoutBinding);
+                return reserveSlot(set, getBaseBinding(EResImage, set) + type.getQualifier().layoutBinding);
 
 
             if (isTextureType(type))
             if (isTextureType(type))
-                return reserveSlot(set, baseTextureBinding + type.getQualifier().layoutBinding);
+                return reserveSlot(set, getBaseBinding(EResTexture, set) + type.getQualifier().layoutBinding);
 
 
             if (isSsboType(type))
             if (isSsboType(type))
-                return reserveSlot(set, baseSsboBinding + type.getQualifier().layoutBinding);
+                return reserveSlot(set, getBaseBinding(EResSsbo, set) + type.getQualifier().layoutBinding);
 
 
             if (isSamplerType(type))
             if (isSamplerType(type))
-                return reserveSlot(set, baseSamplerBinding + type.getQualifier().layoutBinding);
+                return reserveSlot(set, getBaseBinding(EResSampler, set) + type.getQualifier().layoutBinding);
 
 
             if (isUboType(type))
             if (isUboType(type))
-                return reserveSlot(set, baseUboBinding + type.getQualifier().layoutBinding);
-        } else if (is_live && doAutoBindingMapping) {
+                return reserveSlot(set, getBaseBinding(EResUbo, set) + type.getQualifier().layoutBinding);
+        } 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, baseImageBinding);
+                return getFreeSlot(set, getBaseBinding(EResImage, set));
 
 
             if (isTextureType(type))
             if (isTextureType(type))
-                return getFreeSlot(set, baseTextureBinding);
+                return getFreeSlot(set, getBaseBinding(EResTexture, set));
 
 
             if (isSsboType(type))
             if (isSsboType(type))
-                return getFreeSlot(set, baseSsboBinding);
+                return getFreeSlot(set, getBaseBinding(EResSsbo, set));
 
 
             if (isSamplerType(type))
             if (isSamplerType(type))
-                return getFreeSlot(set, baseSamplerBinding);
+                return getFreeSlot(set, getBaseBinding(EResSampler, set));
 
 
             if (isUboType(type))
             if (isUboType(type))
-                return getFreeSlot(set, baseUboBinding);
+                return getFreeSlot(set, getBaseBinding(EResUbo, set));
         }
         }
 
 
         return -1;
         return -1;
@@ -573,6 +635,8 @@ b – for constant buffer views (CBV)
  ********************************************************************************/
  ********************************************************************************/
 struct TDefaultHlslIoResolver : public TDefaultIoResolverBase
 struct TDefaultHlslIoResolver : public TDefaultIoResolverBase
 {
 {
+    TDefaultHlslIoResolver(const TIntermediate &intermediate) : TDefaultIoResolverBase(intermediate) { }
+
     bool validateBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& /*type*/, bool /*is_live*/) override
     bool validateBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& /*type*/, bool /*is_live*/) override
     {
     {
         return true;
         return true;
@@ -584,31 +648,31 @@ struct TDefaultHlslIoResolver : public TDefaultIoResolverBase
 
 
         if (type.getQualifier().hasBinding()) {
         if (type.getQualifier().hasBinding()) {
             if (isUavType(type))
             if (isUavType(type))
-                return reserveSlot(set, baseUavBinding + type.getQualifier().layoutBinding);
+                return reserveSlot(set, getBaseBinding(EResUav, set) + type.getQualifier().layoutBinding);
 
 
             if (isSrvType(type))
             if (isSrvType(type))
-                return reserveSlot(set, baseTextureBinding + type.getQualifier().layoutBinding);
+                return reserveSlot(set, getBaseBinding(EResTexture, set) + type.getQualifier().layoutBinding);
 
 
             if (isSamplerType(type))
             if (isSamplerType(type))
-                return reserveSlot(set, baseSamplerBinding + type.getQualifier().layoutBinding);
+                return reserveSlot(set, getBaseBinding(EResSampler, set) + type.getQualifier().layoutBinding);
 
 
             if (isUboType(type))
             if (isUboType(type))
-                return reserveSlot(set, baseUboBinding + type.getQualifier().layoutBinding);
-        } else if (is_live && doAutoBindingMapping) {
+                return reserveSlot(set, getBaseBinding(EResUbo, set) + type.getQualifier().layoutBinding);
+        } 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 (isUavType(type))
             if (isUavType(type))
-                return getFreeSlot(set, baseUavBinding);
+                return getFreeSlot(set, getBaseBinding(EResUav, set));
 
 
             if (isSrvType(type))
             if (isSrvType(type))
-                return getFreeSlot(set, baseTextureBinding);
+                return getFreeSlot(set, getBaseBinding(EResTexture, set));
 
 
             if (isSamplerType(type))
             if (isSamplerType(type))
-                return getFreeSlot(set, baseSamplerBinding);
+                return getFreeSlot(set, getBaseBinding(EResSampler, set));
 
 
             if (isUboType(type))
             if (isUboType(type))
-                return getFreeSlot(set, baseUboBinding);
+                return getFreeSlot(set, getBaseBinding(EResUbo, set));
         }
         }
 
 
         return -1;
         return -1;
@@ -637,17 +701,17 @@ protected:
 // Returns false if the input is too malformed to do this.
 // Returns false if the input is too malformed to do this.
 bool TIoMapper::addStage(EShLanguage stage, TIntermediate &intermediate, TInfoSink &infoSink, TIoMapResolver *resolver)
 bool TIoMapper::addStage(EShLanguage stage, TIntermediate &intermediate, TInfoSink &infoSink, TIoMapResolver *resolver)
 {
 {
-    // Trivial return if there is nothing to do.
-    if (intermediate.getShiftSamplerBinding() == 0 &&
-        intermediate.getShiftTextureBinding() == 0 &&
-        intermediate.getShiftImageBinding() == 0 &&
-        intermediate.getShiftUboBinding() == 0 &&
-        intermediate.getShiftSsboBinding() == 0 &&
-        intermediate.getShiftUavBinding() == 0 &&
-        intermediate.getResourceSetBinding().empty() &&
-        intermediate.getAutoMapBindings() == false &&
-        intermediate.getAutoMapLocations() == false &&
-        resolver == nullptr)
+    bool somethingToDo = !intermediate.getResourceSetBinding().empty() ||
+        intermediate.getAutoMapBindings() ||
+        intermediate.getAutoMapLocations();
+
+    for (int res = 0; res < EResCount; ++res) {
+        somethingToDo = somethingToDo ||
+            (intermediate.getShiftBinding(TResourceType(res)) != 0) ||
+            intermediate.hasShiftBindingForSet(TResourceType(res));
+    }
+
+    if (!somethingToDo && resolver == nullptr)
         return true;
         return true;
 
 
     if (intermediate.getNumEntryPoints() != 1 || intermediate.isRecursive())
     if (intermediate.getNumEntryPoints() != 1 || intermediate.isRecursive())
@@ -658,29 +722,15 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate &intermediate, TInfoSi
         return false;
         return false;
 
 
     // if no resolver is provided, use the default resolver with the given shifts and auto map settings
     // if no resolver is provided, use the default resolver with the given shifts and auto map settings
-    TDefaultIoResolver defaultResolver;
-    TDefaultHlslIoResolver defaultHlslResolver;
+    TDefaultIoResolver defaultResolver(intermediate);
+    TDefaultHlslIoResolver defaultHlslResolver(intermediate);
 
 
     if (resolver == nullptr) {
     if (resolver == nullptr) {
-        TDefaultIoResolverBase* resolverBase;
-
         // TODO: use a passed in IO mapper for this
         // TODO: use a passed in IO mapper for this
         if (intermediate.usingHlslIoMapping())
         if (intermediate.usingHlslIoMapping())
-            resolverBase = &defaultHlslResolver;
+            resolver = &defaultHlslResolver;
         else
         else
-            resolverBase = &defaultResolver;
-
-        resolverBase->baseSamplerBinding = intermediate.getShiftSamplerBinding();
-        resolverBase->baseTextureBinding = intermediate.getShiftTextureBinding();
-        resolverBase->baseImageBinding = intermediate.getShiftImageBinding();
-        resolverBase->baseUboBinding = intermediate.getShiftUboBinding();
-        resolverBase->baseSsboBinding = intermediate.getShiftSsboBinding();
-        resolverBase->baseUavBinding = intermediate.getShiftUavBinding();
-        resolverBase->baseResourceSetBinding = intermediate.getResourceSetBinding();
-        resolverBase->doAutoBindingMapping = intermediate.getAutoMapBindings();
-        resolverBase->doAutoLocationMapping = intermediate.getAutoMapLocations();
-
-        resolver = resolverBase;
+            resolver = &defaultResolver;
     }
     }
 
 
     TVarLiveMap inVarMap, outVarMap, uniformVarMap;
     TVarLiveMap inVarMap, outVarMap, uniformVarMap;
@@ -704,13 +754,16 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate &intermediate, TInfoSi
     TNotifyUniformAdaptor uniformNotify(stage, *resolver);
     TNotifyUniformAdaptor uniformNotify(stage, *resolver);
     TResolverUniformAdaptor uniformResolve(stage, *resolver, infoSink, hadError, intermediate);
     TResolverUniformAdaptor uniformResolve(stage, *resolver, infoSink, hadError, intermediate);
     TResolverInOutAdaptor inOutResolve(stage, *resolver, infoSink, hadError, intermediate);
     TResolverInOutAdaptor inOutResolve(stage, *resolver, infoSink, hadError, intermediate);
+    resolver->beginNotifications(stage);
     std::for_each(inVarMap.begin(), inVarMap.end(), inOutNotify);
     std::for_each(inVarMap.begin(), inVarMap.end(), inOutNotify);
     std::for_each(outVarMap.begin(), outVarMap.end(), inOutNotify);
     std::for_each(outVarMap.begin(), outVarMap.end(), inOutNotify);
     std::for_each(uniformVarMap.begin(), uniformVarMap.end(), uniformNotify);
     std::for_each(uniformVarMap.begin(), uniformVarMap.end(), uniformNotify);
-    resolver->endNotifications();
+    resolver->endNotifications(stage);
+    resolver->beginResolve(stage);
     std::for_each(inVarMap.begin(), inVarMap.end(), inOutResolve);
     std::for_each(inVarMap.begin(), inVarMap.end(), inOutResolve);
     std::for_each(outVarMap.begin(), outVarMap.end(), inOutResolve);
     std::for_each(outVarMap.begin(), outVarMap.end(), inOutResolve);
     std::for_each(uniformVarMap.begin(), uniformVarMap.end(), uniformResolve);
     std::for_each(uniformVarMap.begin(), uniformVarMap.end(), uniformResolve);
+    resolver->endResolve(stage);
 
 
     if (!hadError) {
     if (!hadError) {
         // sort by id again, so we can use lower bound to find entries
         // sort by id again, so we can use lower bound to find entries

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

@@ -101,6 +101,9 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
     if (! earlyFragmentTests)
     if (! earlyFragmentTests)
         earlyFragmentTests = unit.earlyFragmentTests;
         earlyFragmentTests = unit.earlyFragmentTests;
 
 
+    if (!postDepthCoverage)
+        postDepthCoverage = unit.postDepthCoverage;
+
     if (depthLayout == EldNone)
     if (depthLayout == EldNone)
         depthLayout = unit.depthLayout;
         depthLayout = unit.depthLayout;
     else if (depthLayout != unit.depthLayout)
     else if (depthLayout != unit.depthLayout)
@@ -459,9 +462,9 @@ void TIntermediate::finalCheck(TInfoSink& infoSink, bool keepUncalled)
             error(infoSink, "At least one shader must specify an output layout(vertices=...)");
             error(infoSink, "At least one shader must specify an output layout(vertices=...)");
         break;
         break;
     case EShLangTessEvaluation:
     case EShLangTessEvaluation:
-        if (inputPrimitive == ElgNone)
-            error(infoSink, "At least one shader must specify an input layout primitive");
         if (source == EShSourceGlsl) {
         if (source == EShSourceGlsl) {
+            if (inputPrimitive == ElgNone)
+                error(infoSink, "At least one shader must specify an input layout primitive");
             if (vertexSpacing == EvsNone)
             if (vertexSpacing == EvsNone)
                 vertexSpacing = EvsEqual;
                 vertexSpacing = EvsEqual;
             if (vertexOrder == EvoNone)
             if (vertexOrder == EvoNone)
@@ -485,6 +488,11 @@ void TIntermediate::finalCheck(TInfoSink& infoSink, bool keepUncalled)
             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:
+        // for GL_ARB_post_depth_coverage, EarlyFragmentTest is set automatically in 
+        // ParseHelper.cpp. So if we reach here, this must be GL_EXT_post_depth_coverage 
+        // requiring explicit early_fragment_tests
+        if (getPostDepthCoverage() && !getEarlyFragmentTests())
+            error(infoSink, "post_depth_coverage requires early_fragment_tests");
         break;
         break;
     case EShLangCompute:
     case EShLangCompute:
         break;
         break;

+ 211 - 46
src/libraries/glslang/glslang/MachineIndependent/localintermediate.h

@@ -42,6 +42,7 @@
 
 
 #include <algorithm>
 #include <algorithm>
 #include <set>
 #include <set>
+#include <array>
 
 
 class TInfoSink;
 class TInfoSink;
 
 
@@ -150,6 +151,54 @@ struct TXfbBuffer {
     bool containsDouble;
     bool containsDouble;
 };
 };
 
 
+// Track a set of strings describing how the module was processed.
+// Using the form:
+//   process arg0 arg1 arg2 ...
+//   process arg0 arg1 arg2 ...
+// where everything is textual, and there can be zero or more arguments
+class TProcesses {
+public:
+    TProcesses() {}
+    ~TProcesses() {}
+
+    void addProcess(const char* process)
+    {
+        processes.push_back(process);
+    }
+    void addProcess(const std::string& process)
+    {
+        processes.push_back(process);
+    }
+    void addArgument(int arg)
+    {
+        processes.back().append(" ");
+        std::string argString = std::to_string(arg);
+        processes.back().append(argString);
+    }
+    void addArgument(const char* arg)
+    {
+        processes.back().append(" ");
+        processes.back().append(arg);
+    }
+    void addArgument(const std::string& arg)
+    {
+        processes.back().append(" ");
+        processes.back().append(arg);
+    }
+    void addIfNonZero(const char* process, int value)
+    {
+        if (value != 0) {
+            addProcess(process);
+            addArgument(value);
+        }
+    }
+
+    const std::vector<std::string>& getProcesses() const { return processes; }
+
+private:
+    std::vector<std::string> processes;
+};
+
 class TSymbolTable;
 class TSymbolTable;
 class TSymbol;
 class TSymbol;
 class TVariable;
 class TVariable;
@@ -160,30 +209,29 @@ class TVariable;
 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"),
         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), inputPrimitive(ElgNone), outputPrimitive(ElgNone),
+        invocations(TQualifier::layoutNotSet), vertices(TQualifier::layoutNotSet),
+        inputPrimitive(ElgNone), outputPrimitive(ElgNone),
         pixelCenterInteger(false), originUpperLeft(false),
         pixelCenterInteger(false), originUpperLeft(false),
-        vertexSpacing(EvsNone), vertexOrder(EvoNone), pointMode(false), earlyFragmentTests(false), depthLayout(EldNone), depthReplacing(false), blendEquations(0),
-        xfbMode(false), multiStream(false),
+        vertexSpacing(EvsNone), vertexOrder(EvoNone), pointMode(false), earlyFragmentTests(false),
+        postDepthCoverage(false), depthLayout(EldNone), depthReplacing(false),
+        blendEquations(0), xfbMode(false), multiStream(false),
 #ifdef NV_EXTENSIONS
 #ifdef NV_EXTENSIONS
         layoutOverrideCoverage(false),
         layoutOverrideCoverage(false),
         geoPassthroughEXT(false),
         geoPassthroughEXT(false),
 #endif
 #endif
-        shiftSamplerBinding(0),
-        shiftTextureBinding(0),
-        shiftImageBinding(0),
-        shiftUboBinding(0),
-        shiftSsboBinding(0),
-        shiftUavBinding(0),
         autoMapBindings(false),
         autoMapBindings(false),
         autoMapLocations(false),
         autoMapLocations(false),
+        invertY(false),
         flattenUniformArrays(false),
         flattenUniformArrays(false),
         useUnknownFormat(false),
         useUnknownFormat(false),
         hlslOffsets(false),
         hlslOffsets(false),
         useStorageBuffer(false),
         useStorageBuffer(false),
         hlslIoMapping(false),
         hlslIoMapping(false),
-        textureSamplerTransformMode(EShTexSampTransKeep)
+        textureSamplerTransformMode(EShTexSampTransKeep),
+        needToLegalize(false)
     {
     {
         localSize[0] = 1;
         localSize[0] = 1;
         localSize[1] = 1;
         localSize[1] = 1;
@@ -192,6 +240,8 @@ public:
         localSizeSpecId[1] = TQualifier::layoutNotSet;
         localSizeSpecId[1] = TQualifier::layoutNotSet;
         localSizeSpecId[2] = TQualifier::layoutNotSet;
         localSizeSpecId[2] = TQualifier::layoutNotSet;
         xfbBuffers.resize(TQualifier::layoutXfbBufferEnd);
         xfbBuffers.resize(TQualifier::layoutXfbBufferEnd);
+
+        shiftBinding.fill(0);
     }
     }
     void setLimits(const TBuiltInResource& r) { resources = r; }
     void setLimits(const TBuiltInResource& r) { resources = r; }
 
 
@@ -201,46 +251,140 @@ public:
 
 
     void setSource(EShSource s) { source = s; }
     void setSource(EShSource s) { source = s; }
     EShSource getSource() const { return source; }
     EShSource getSource() const { return source; }
-    void setEntryPointName(const char* ep) { entryPointName = ep; }
+    void setEntryPointName(const char* ep)
+    {
+        entryPointName = ep;
+        processes.addProcess("entry-point");
+        processes.addArgument(entryPointName);
+    }
     void setEntryPointMangledName(const char* ep) { entryPointMangledName = ep; }
     void setEntryPointMangledName(const char* ep) { entryPointMangledName = ep; }
     const std::string& getEntryPointName() const { return entryPointName; }
     const std::string& getEntryPointName() const { return entryPointName; }
     const std::string& getEntryPointMangledName() const { return entryPointMangledName; }
     const std::string& getEntryPointMangledName() const { return entryPointMangledName; }
 
 
-    void setShiftSamplerBinding(unsigned int shift) { shiftSamplerBinding = shift; }
-    unsigned int getShiftSamplerBinding() const { return shiftSamplerBinding; }
-    void setShiftTextureBinding(unsigned int shift) { shiftTextureBinding = shift; }
-    unsigned int getShiftTextureBinding() const { return shiftTextureBinding; }
-    void setShiftImageBinding(unsigned int shift) { shiftImageBinding = shift; }
-    unsigned int getShiftImageBinding() const { return shiftImageBinding; }
-    void setShiftUboBinding(unsigned int shift)     { shiftUboBinding = shift; }
-    unsigned int getShiftUboBinding()     const { return shiftUboBinding; }
-    void setShiftSsboBinding(unsigned int shift)     { shiftSsboBinding = shift; }
-    unsigned int getShiftSsboBinding()  const { return shiftSsboBinding; }
-    void setShiftUavBinding(unsigned int shift) { shiftUavBinding = shift; }
-    unsigned int getShiftUavBinding()  const { return shiftUavBinding; }
-    void setResourceSetBinding(const std::vector<std::string>& shift) { resourceSetBinding = shift; }
+    void setShiftBinding(TResourceType res, unsigned int shift)
+    {
+        shiftBinding[res] = shift;
+
+        const char* name = getResourceName(res);
+        if (name != nullptr)
+            processes.addIfNonZero(name, shift);
+    }
+
+    unsigned int getShiftBinding(TResourceType res) const { return shiftBinding[res]; }
+
+    void setShiftBindingForSet(TResourceType res, unsigned int shift, unsigned int set)
+    {
+        if (shift == 0) // ignore if there's no shift: it's a no-op.
+            return;
+
+        shiftBindingForSet[res][set] = shift;
+
+        const char* name = getResourceName(res);
+        if (name != nullptr) {
+            processes.addProcess(name);
+            processes.addArgument(shift);
+            processes.addArgument(set);
+        }
+    }
+
+    int getShiftBindingForSet(TResourceType res, unsigned int set) const
+    {
+        const auto shift = shiftBindingForSet[res].find(set);
+        return shift == shiftBindingForSet[res].end() ? -1 : shift->second;
+    }
+    bool hasShiftBindingForSet(TResourceType res) const { return !shiftBindingForSet[res].empty(); }
+
+    void setResourceSetBinding(const std::vector<std::string>& shift)
+    {
+        resourceSetBinding = shift;
+        if (shift.size() > 0) {
+            processes.addProcess("resource-set-binding");
+            for (int s = 0; s < (int)shift.size(); ++s)
+                processes.addArgument(shift[s]);
+        }
+    }
     const std::vector<std::string>& getResourceSetBinding() const { return resourceSetBinding; }
     const std::vector<std::string>& getResourceSetBinding() const { return resourceSetBinding; }
-    void setAutoMapBindings(bool map)           { autoMapBindings = map; }
-    bool getAutoMapBindings()             const { return autoMapBindings; }
-    void setAutoMapLocations(bool map)          { autoMapLocations = map; }
-    bool getAutoMapLocations()            const { return autoMapLocations; }
-    void setFlattenUniformArrays(bool flatten)  { flattenUniformArrays = flatten; }
-    bool getFlattenUniformArrays()        const { return flattenUniformArrays; }
-    void setNoStorageFormat(bool b)             { useUnknownFormat = b; }
-    bool getNoStorageFormat()             const { return useUnknownFormat; }
-    void setHlslOffsets()         { hlslOffsets = true; }
+    void setAutoMapBindings(bool map)
+    {
+        autoMapBindings = map;
+        if (autoMapBindings)
+            processes.addProcess("auto-map-bindings");
+    }
+    bool getAutoMapBindings() const { return autoMapBindings; }
+    void setAutoMapLocations(bool map)
+    {
+        autoMapLocations = map;
+        if (autoMapLocations)
+            processes.addProcess("auto-map-locations");
+    }
+    bool getAutoMapLocations() const { return autoMapLocations; }
+    void setInvertY(bool invert)
+    {
+        invertY = invert;
+        if (invertY)
+            processes.addProcess("invert-y");
+    }
+    bool getInvertY() const { return invertY; }
+
+    void setFlattenUniformArrays(bool flatten)
+    {
+        flattenUniformArrays = flatten;
+        if (flattenUniformArrays)
+            processes.addProcess("flatten-uniform-arrays");
+    }
+    bool getFlattenUniformArrays() const { return flattenUniformArrays; }
+    void setNoStorageFormat(bool b)
+    {
+        useUnknownFormat = b;
+        if (useUnknownFormat)
+            processes.addProcess("no-storage-format");
+    }
+    bool getNoStorageFormat() const { return useUnknownFormat; }
+    void setHlslOffsets()
+    {
+        hlslOffsets = true;
+        if (hlslOffsets)
+            processes.addProcess("hlsl-offsets");
+    }
     bool usingHlslOFfsets() const { return hlslOffsets; }
     bool usingHlslOFfsets() const { return hlslOffsets; }
-    void setUseStorageBuffer() { useStorageBuffer = true; }
+    void setUseStorageBuffer()
+    {
+        useStorageBuffer = true;
+        processes.addProcess("use-storage-buffer");
+    }
     bool usingStorageBuffer() const { return useStorageBuffer; }
     bool usingStorageBuffer() const { return useStorageBuffer; }
-    void setHlslIoMapping(bool b) { hlslIoMapping = b; }
-    bool usingHlslIoMapping()     { return hlslIoMapping; }
+    void setHlslIoMapping(bool b)
+    {
+        hlslIoMapping = b;
+        if (hlslIoMapping)
+            processes.addProcess("hlsl-iomap");
+    }
+    bool usingHlslIoMapping() { return hlslIoMapping; }
+
     void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { textureSamplerTransformMode = mode; }
     void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { textureSamplerTransformMode = mode; }
 
 
     void setVersion(int v) { version = v; }
     void setVersion(int v) { version = v; }
     int getVersion() const { return version; }
     int getVersion() const { return version; }
     void setProfile(EProfile p) { profile = p; }
     void setProfile(EProfile p) { profile = p; }
     EProfile getProfile() const { return profile; }
     EProfile getProfile() const { return profile; }
-    void setSpv(const SpvVersion& s) { spvVersion = s; }
+    void setSpv(const SpvVersion& s)
+    {
+        spvVersion = s;
+
+        // client processes
+        if (spvVersion.vulkan > 0)
+            processes.addProcess("client vulkan100");
+        if (spvVersion.openGl > 0)
+            processes.addProcess("client opengl100");
+
+        // target-environment processes
+        if (spvVersion.vulkan == 100)
+            processes.addProcess("target-env vulkan1.0");
+        else if (spvVersion.vulkan > 0)
+            processes.addProcess("target-env vulkanUnknown");
+        if (spvVersion.openGl > 0)
+            processes.addProcess("target-env opengl");
+    }
     const SpvVersion& getSpv() const { return spvVersion; }
     const SpvVersion& getSpv() const { return spvVersion; }
     EShLanguage getStage() const { return language; }
     EShLanguage getStage() const { return language; }
     void addRequestedExtension(const char* extension) { requestedExtensions.insert(extension); }
     void addRequestedExtension(const char* extension) { requestedExtensions.insert(extension); }
@@ -276,8 +420,8 @@ 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&);
-    TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&);
+    TIntermTyped* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&, TSelectionControl = ESelectionControlNone);
+    TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&, TSelectionControl = ESelectionControlNone);
     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;
@@ -403,6 +547,8 @@ public:
     bool getPixelCenterInteger() const { return pixelCenterInteger; }
     bool getPixelCenterInteger() const { return pixelCenterInteger; }
     void setEarlyFragmentTests() { earlyFragmentTests = true; }
     void setEarlyFragmentTests() { earlyFragmentTests = true; }
     bool getEarlyFragmentTests() const { return earlyFragmentTests; }
     bool getEarlyFragmentTests() const { return earlyFragmentTests; }
+    void setPostDepthCoverage() { postDepthCoverage = true; }
+    bool getPostDepthCoverage() const { return postDepthCoverage; }
     bool setDepth(TLayoutDepth d)
     bool setDepth(TLayoutDepth d)
     {
     {
         if (depthLayout != EldNone)
         if (depthLayout != EldNone)
@@ -437,6 +583,7 @@ public:
         xfbBuffers[buffer].stride = stride;
         xfbBuffers[buffer].stride = stride;
         return true;
         return true;
     }
     }
+    unsigned getXfbStride(int buffer) const { return xfbBuffers[buffer].stride; }
     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);
@@ -460,8 +607,18 @@ public:
     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) {
+        for (int i = 0; i < (int)p.size(); ++i)
+            processes.addProcess(p[i]);
+    }
+    void addProcess(const std::string& process) { processes.addProcess(process); }
+    void addProcessArgument(const std::string& arg) { processes.addArgument(arg); }
+    const std::vector<std::string>& getProcesses() const { return processes.getProcesses(); }
 
 
-    const char* const implicitThisName = "@this";
+    void setNeedsLegalization() { needToLegalize = true; }
+    bool needsLegalization() const { return needToLegalize; }
+
+    const char* const implicitThisName;
 
 
 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&);
@@ -485,6 +642,7 @@ 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);
+    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
@@ -513,6 +671,7 @@ protected:
     int localSize[3];
     int localSize[3];
     int localSizeSpecId[3];
     int localSizeSpecId[3];
     bool earlyFragmentTests;
     bool earlyFragmentTests;
+    bool postDepthCoverage;
     TLayoutDepth depthLayout;
     TLayoutDepth depthLayout;
     bool depthReplacing;
     bool depthReplacing;
     int blendEquations;        // an 'or'ing of masks of shifts of TBlendEquationShift
     int blendEquations;        // an 'or'ing of masks of shifts of TBlendEquationShift
@@ -524,15 +683,16 @@ protected:
     bool geoPassthroughEXT;
     bool geoPassthroughEXT;
 #endif
 #endif
 
 
-    unsigned int shiftSamplerBinding;
-    unsigned int shiftTextureBinding;
-    unsigned int shiftImageBinding;
-    unsigned int shiftUboBinding;
-    unsigned int shiftSsboBinding;
-    unsigned int shiftUavBinding;
+    // Base shift values
+    std::array<unsigned int, EResCount> shiftBinding;
+
+    // Per-descriptor-set shift values
+    std::array<std::map<int, int>, EResCount>  shiftBindingForSet;
+
     std::vector<std::string> resourceSetBinding;
     std::vector<std::string> resourceSetBinding;
     bool autoMapBindings;
     bool autoMapBindings;
     bool autoMapLocations;
     bool autoMapLocations;
+    bool invertY;
     bool flattenUniformArrays;
     bool flattenUniformArrays;
     bool useUnknownFormat;
     bool useUnknownFormat;
     bool hlslOffsets;
     bool hlslOffsets;
@@ -555,6 +715,11 @@ protected:
     std::string sourceFile;
     std::string sourceFile;
     std::string sourceText;
     std::string sourceText;
 
 
+    // for OpModuleProcessed, or equivalent
+    TProcesses processes;
+
+    bool needToLegalize;
+
 private:
 private:
     void operator=(TIntermediate&); // prevent assignments
     void operator=(TIntermediate&); // prevent assignments
 };
 };

+ 33 - 21
src/libraries/glslang/glslang/MachineIndependent/parseConst.cpp

@@ -84,6 +84,7 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <cstdlib>
 #include <cstdlib>
 #include <cstring>
 #include <cstring>
 #include <cctype>
 #include <cctype>
+#include <climits>
 
 
 #include "PpContext.h"
 #include "PpContext.h"
 #include "PpTokens.h"
 #include "PpTokens.h"
@@ -241,15 +242,20 @@ int TPpContext::CPPelse(int matchelse, TPpToken* ppToken)
         int nextAtom = atomStrings.getAtom(ppToken->name);
         int nextAtom = atomStrings.getAtom(ppToken->name);
         if (nextAtom == PpAtomIf || nextAtom == PpAtomIfdef || nextAtom == PpAtomIfndef) {
         if (nextAtom == PpAtomIf || nextAtom == PpAtomIfdef || nextAtom == PpAtomIfndef) {
             depth++;
             depth++;
-            ifdepth++;
-            elsetracker++;
+            if (ifdepth >= maxIfNesting || elsetracker >= maxIfNesting) {
+                parseContext.ppError(ppToken->loc, "maximum nesting depth exceeded", "#if/#ifdef/#ifndef", "");
+                return EndOfInput;
+            } else {
+                ifdepth++;
+                elsetracker++;
+            }
         } else if (nextAtom == PpAtomEndif) {
         } else if (nextAtom == PpAtomEndif) {
             token = extraTokenCheck(nextAtom, ppToken, scanToken(ppToken));
             token = extraTokenCheck(nextAtom, ppToken, scanToken(ppToken));
             elseSeen[elsetracker] = false;
             elseSeen[elsetracker] = false;
             --elsetracker;
             --elsetracker;
             if (depth == 0) {
             if (depth == 0) {
                 // found the #endif we are looking for
                 // found the #endif we are looking for
-                if (ifdepth)
+                if (ifdepth > 0)
                     --ifdepth;
                     --ifdepth;
                 break;
                 break;
             }
             }
@@ -266,7 +272,7 @@ int TPpContext::CPPelse(int matchelse, TPpToken* ppToken)
                     parseContext.ppError(ppToken->loc, "#elif after #else", "#elif", "");
                     parseContext.ppError(ppToken->loc, "#elif after #else", "#elif", "");
                 /* we decrement ifdepth here, because CPPif will increment
                 /* we decrement ifdepth here, because CPPif will increment
                 * it and we really want to leave it alone */
                 * it and we really want to leave it alone */
-                if (ifdepth) {
+                if (ifdepth > 0) {
                     --ifdepth;
                     --ifdepth;
                     elseSeen[elsetracker] = false;
                     elseSeen[elsetracker] = false;
                     --elsetracker;
                     --elsetracker;
@@ -345,8 +351,8 @@ namespace {
     int op_add(int a, int b) { return a + b; }
     int op_add(int a, int b) { return a + b; }
     int op_sub(int a, int b) { return a - b; }
     int op_sub(int a, int b) { return a - b; }
     int op_mul(int a, int b) { return a * b; }
     int op_mul(int a, int b) { return a * b; }
-    int op_div(int a, int b) { return a / b; }
-    int op_mod(int a, int b) { return a % b; }
+    int op_div(int a, int b) { return a == INT_MIN && b == -1 ? 0 : a / b; }
+    int op_mod(int a, int b) { return a == INT_MIN && b == -1 ? 0 : a % b; }
     int op_pos(int a) { return a; }
     int op_pos(int a) { return a; }
     int op_neg(int a) { return -a; }
     int op_neg(int a) { return -a; }
     int op_cmpl(int a) { return ~a; }
     int op_cmpl(int a) { return ~a; }
@@ -536,11 +542,12 @@ int TPpContext::evalToToken(int token, bool shortCircuit, int& res, bool& err, T
 int TPpContext::CPPif(TPpToken* ppToken)
 int TPpContext::CPPif(TPpToken* ppToken)
 {
 {
     int token = scanToken(ppToken);
     int token = scanToken(ppToken);
-    elsetracker++;
-    ifdepth++;
-    if (ifdepth > maxIfNesting) {
+    if (ifdepth >= maxIfNesting || elsetracker >= maxIfNesting) {
         parseContext.ppError(ppToken->loc, "maximum nesting depth exceeded", "#if", "");
         parseContext.ppError(ppToken->loc, "maximum nesting depth exceeded", "#if", "");
-        return 0;
+        return EndOfInput;
+    } else {
+        elsetracker++;
+        ifdepth++;
     }
     }
     int res = 0;
     int res = 0;
     bool err = false;
     bool err = false;
@@ -556,11 +563,14 @@ int TPpContext::CPPif(TPpToken* ppToken)
 int TPpContext::CPPifdef(int defined, TPpToken* ppToken)
 int TPpContext::CPPifdef(int defined, TPpToken* ppToken)
 {
 {
     int token = scanToken(ppToken);
     int token = scanToken(ppToken);
-    if (++ifdepth > maxIfNesting) {
+    if (ifdepth > maxIfNesting || elsetracker > maxIfNesting) {
         parseContext.ppError(ppToken->loc, "maximum nesting depth exceeded", "#ifdef", "");
         parseContext.ppError(ppToken->loc, "maximum nesting depth exceeded", "#ifdef", "");
-        return 0;
+        return EndOfInput;
+    } else {
+        elsetracker++;
+        ifdepth++;
     }
     }
-    elsetracker++;
+
     if (token != PpAtomIdentifier) {
     if (token != PpAtomIdentifier) {
         if (defined)
         if (defined)
             parseContext.ppError(ppToken->loc, "must be followed by macro name", "#ifdef", "");
             parseContext.ppError(ppToken->loc, "must be followed by macro name", "#ifdef", "");
@@ -886,16 +896,16 @@ int TPpContext::readCPPline(TPpToken* ppToken)
             token = CPPdefine(ppToken);
             token = CPPdefine(ppToken);
             break;
             break;
         case PpAtomElse:
         case PpAtomElse:
-            if (elsetracker[elseSeen])
+            if (elseSeen[elsetracker])
                 parseContext.ppError(ppToken->loc, "#else after #else", "#else", "");
                 parseContext.ppError(ppToken->loc, "#else after #else", "#else", "");
-            elsetracker[elseSeen] = true;
-            if (! ifdepth)
+            elseSeen[elsetracker] = true;
+            if (ifdepth == 0)
                 parseContext.ppError(ppToken->loc, "mismatched statements", "#else", "");
                 parseContext.ppError(ppToken->loc, "mismatched statements", "#else", "");
             token = extraTokenCheck(PpAtomElse, ppToken, scanToken(ppToken));
             token = extraTokenCheck(PpAtomElse, ppToken, scanToken(ppToken));
             token = CPPelse(0, ppToken);
             token = CPPelse(0, ppToken);
             break;
             break;
         case PpAtomElif:
         case PpAtomElif:
-            if (! ifdepth)
+            if (ifdepth == 0)
                 parseContext.ppError(ppToken->loc, "mismatched statements", "#elif", "");
                 parseContext.ppError(ppToken->loc, "mismatched statements", "#elif", "");
             if (elseSeen[elsetracker])
             if (elseSeen[elsetracker])
                 parseContext.ppError(ppToken->loc, "#elif after #else", "#elif", "");
                 parseContext.ppError(ppToken->loc, "#elif after #else", "#elif", "");
@@ -906,7 +916,7 @@ int TPpContext::readCPPline(TPpToken* ppToken)
             token = CPPelse(0, ppToken);
             token = CPPelse(0, ppToken);
             break;
             break;
         case PpAtomEndif:
         case PpAtomEndif:
-            if (! ifdepth)
+            if (ifdepth == 0)
                 parseContext.ppError(ppToken->loc, "mismatched statements", "#endif", "");
                 parseContext.ppError(ppToken->loc, "mismatched statements", "#endif", "");
             else {
             else {
                 elseSeen[elsetracker] = false;
                 elseSeen[elsetracker] = false;
@@ -1068,6 +1078,10 @@ int TPpContext::tMacroInput::scan(TPpToken* ppToken)
         pasting = true;
         pasting = true;
     }
     }
 
 
+    // HLSL does expand macros before concatenation
+    if (pasting && pp->parseContext.isReadingHLSL())
+        pasting = false;
+
     // TODO: preprocessor:  properly handle whitespace (or lack of it) between tokens when expanding
     // TODO: preprocessor:  properly handle whitespace (or lack of it) between tokens when expanding
     if (token == PpAtomIdentifier) {
     if (token == PpAtomIdentifier) {
         int i;
         int i;
@@ -1143,7 +1157,6 @@ int TPpContext::MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOka
     }
     }
 
 
     MacroSymbol* macro = macroAtom == 0 ? nullptr : lookupMacroDef(macroAtom);
     MacroSymbol* macro = macroAtom == 0 ? nullptr : lookupMacroDef(macroAtom);
-    int token;
     int depth = 0;
     int depth = 0;
 
 
     // no recursive expansions
     // no recursive expansions
@@ -1165,13 +1178,12 @@ int TPpContext::MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOka
     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) {
     if (macro->args.size() > 0 || macro->emptyArgs) {
-        token = scanToken(ppToken);
+        int token = scanToken(ppToken);
         if (newLineOkay) {
         if (newLineOkay) {
             while (token == '\n')
             while (token == '\n')
                 token = scanToken(ppToken);
                 token = scanToken(ppToken);
         }
         }
         if (token != '(') {
         if (token != '(') {
-            parseContext.ppError(loc, "expected '(' following", "macro expansion", atomStrings.getString(macroAtom));
             UngetToken(token, ppToken);
             UngetToken(token, ppToken);
             delete in;
             delete in;
             return 0;
             return 0;

+ 1 - 1
src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpAtom.cpp

@@ -309,7 +309,7 @@ protected:
     bool endOfReplacementList() { return inputStack.empty() || inputStack.back()->endOfReplacementList(); }
     bool endOfReplacementList() { return inputStack.empty() || inputStack.back()->endOfReplacementList(); }
     bool isMacroInput() { return inputStack.size() > 0 && inputStack.back()->isMacroInput(); }
     bool isMacroInput() { return inputStack.size() > 0 && inputStack.back()->isMacroInput(); }
 
 
-    static const int maxIfNesting = 64;
+    static const int maxIfNesting = 65;
 
 
     int ifdepth;                  // current #if-#else-#endif nesting in the cpp.c file (pre-processor)
     int ifdepth;                  // current #if-#else-#endif nesting in the cpp.c file (pre-processor)
     bool elseSeen[maxIfNesting];  // Keep a track of whether an else has been seen at a particular depth
     bool elseSeen[maxIfNesting];  // Keep a track of whether an else has been seen at a particular depth

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

@@ -128,7 +128,7 @@ int TPpContext::lFloatConst(int len, int ch, TPpToken* ppToken)
         ch = getChar();
         ch = getChar();
 
 
         // 1.#INF or -1.#INF
         // 1.#INF or -1.#INF
-        if (ch == '#') {
+        if (parseContext.intermediate.getSource() == EShSourceHlsl && ch == '#') {
             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] == '+')) ||
@@ -420,7 +420,7 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
 
 
                     ival = 0;
                     ival = 0;
                     do {
                     do {
-                        if (ival <= 0x0fffffffu || (enableInt64 && ival <= 0x0fffffffffffffffull)) {
+                        if (len < MaxTokenLength && (ival <= 0x0fffffffu || (enableInt64 && 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';
@@ -433,7 +433,10 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
                             ival = (ival << 4) | ii;
                             ival = (ival << 4) | ii;
                         } else {
                         } else {
                             if (! AlreadyComplained) {
                             if (! AlreadyComplained) {
-                                pp->parseContext.ppError(ppToken->loc, "hexadecimal literal too big", "", "");
+                                if(len < MaxTokenLength)
+                                    pp->parseContext.ppError(ppToken->loc, "hexadecimal literal too big", "", "");
+                                else
+                                    pp->parseContext.ppError(ppToken->loc, "hexadecimal literal too long", "", "");
                                 AlreadyComplained = 1;
                                 AlreadyComplained = 1;
                             }
                             }
                             ival = 0xffffffffffffffffull;
                             ival = 0xffffffffffffffffull;

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

@@ -131,8 +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.getBaseAlignment(*memberList[m].type, memberSize, dummyStride,
+                                                                type.getQualifier().layoutPacking == ElpStd140,
+                                                                subMatrixLayout != ElmNone
+                                                                    ? subMatrixLayout == ElmRowMajor
+                                                                    : type.getQualifier().layoutMatrix == ElmRowMajor);
             RoundToPow2(offset, memberAlignment);
             RoundToPow2(offset, memberAlignment);
             if (m < index)
             if (m < index)
                 offset += memberSize;
                 offset += memberSize;
@@ -151,7 +154,8 @@ public:
 
 
         int lastMemberSize;
         int lastMemberSize;
         int dummyStride;
         int dummyStride;
-        intermediate.getBaseAlignment(*memberList[lastIndex].type, lastMemberSize, dummyStride, blockType.getQualifier().layoutPacking == ElpStd140,
+        intermediate.getBaseAlignment(*memberList[lastIndex].type, lastMemberSize, dummyStride,
+                                      blockType.getQualifier().layoutPacking == ElpStd140,
                                       blockType.getQualifier().layoutMatrix == ElmRowMajor);
                                       blockType.getQualifier().layoutMatrix == ElmRowMajor);
 
 
         return lastOffset + lastMemberSize;
         return lastOffset + lastMemberSize;
@@ -167,7 +171,7 @@ public:
     void blowUpActiveAggregate(const TType& baseType, const TString& baseName, const TList<TIntermBinary*>& derefs,
     void blowUpActiveAggregate(const TType& baseType, const TString& baseName, const TList<TIntermBinary*>& derefs,
                                TList<TIntermBinary*>::const_iterator deref, int offset, int blockIndex, int arraySize)
                                TList<TIntermBinary*>::const_iterator deref, int offset, int blockIndex, int arraySize)
     {
     {
-        // process the part of the derefence chain that was explicit in the shader
+        // process the part of the dereference chain that was explicit in the shader
         TString name = baseName;
         TString name = baseName;
         const TType* terminalType = &baseType;
         const TType* terminalType = &baseType;
         for (; deref != derefs.end(); ++deref) {
         for (; deref != derefs.end(); ++deref) {
@@ -177,7 +181,7 @@ public:
             switch (visitNode->getOp()) {
             switch (visitNode->getOp()) {
             case EOpIndexIndirect:
             case EOpIndexIndirect:
                 // Visit all the indices of this array, and for each one add on the remaining dereferencing
                 // Visit all the indices of this array, and for each one add on the remaining dereferencing
-                for (int i = 0; i < visitNode->getLeft()->getType().getOuterArraySize(); ++i) {
+                for (int i = 0; i < std::max(visitNode->getLeft()->getType().getOuterArraySize(), 1); ++i) {
                     TString newBaseName = name;
                     TString newBaseName = name;
                     if (baseType.getBasicType() != EbtBlock)
                     if (baseType.getBasicType() != EbtBlock)
                         newBaseName.append(TString("[") + String(i) + "]");
                         newBaseName.append(TString("[") + String(i) + "]");
@@ -212,7 +216,7 @@ public:
             if (terminalType->isArray()) {
             if (terminalType->isArray()) {
                 // Visit all the indices of this array, and for each one,
                 // Visit all the indices of this array, and for each one,
                 // fully explode the remaining aggregate to dereference
                 // fully explode the remaining aggregate to dereference
-                for (int i = 0; i < terminalType->getOuterArraySize(); ++i) {
+                for (int i = 0; i < std::max(terminalType->getOuterArraySize(), 1); ++i) {
                     TString newBaseName = name;
                     TString newBaseName = name;
                     newBaseName.append(TString("[") + String(i) + "]");
                     newBaseName.append(TString("[") + String(i) + "]");
                     TType derefType(*terminalType, 0);
                     TType derefType(*terminalType, 0);
@@ -235,7 +239,7 @@ public:
         }
         }
 
 
         // Finally, add a full string to the reflection database, and update the array size if necessary.
         // Finally, add a full string to the reflection database, and update the array size if necessary.
-        // If the derefenced entity to record is an array, compute the size and update the maximum size.
+        // If the dereferenced entity to record is an array, compute the size and update the maximum size.
 
 
         // there might not be a final array dereference, it could have been copied as an array object
         // there might not be a final array dereference, it could have been copied as an array object
         if (arraySize == 0)
         if (arraySize == 0)
@@ -244,7 +248,8 @@ public:
         TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name);
         TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name);
         if (it == reflection.nameToIndex.end()) {
         if (it == reflection.nameToIndex.end()) {
             reflection.nameToIndex[name] = (int)reflection.indexToUniform.size();
             reflection.nameToIndex[name] = (int)reflection.indexToUniform.size();
-            reflection.indexToUniform.push_back(TObjectReflection(name, *terminalType, offset, mapToGlType(*terminalType),
+            reflection.indexToUniform.push_back(TObjectReflection(name, *terminalType, offset,
+                                                                  mapToGlType(*terminalType),
                                                                   arraySize, blockIndex));
                                                                   arraySize, blockIndex));
         } else if (arraySize > 1) {
         } else if (arraySize > 1) {
             int& reflectedArraySize = reflection.indexToUniform[it->second].size;
             int& reflectedArraySize = reflection.indexToUniform[it->second].size;
@@ -417,7 +422,8 @@ public:
                 case Esd2D:
                 case Esd2D:
                     switch ((int)sampler.ms) {
                     switch ((int)sampler.ms) {
                     case false:  return sampler.arrayed ? GL_INT_SAMPLER_2D_ARRAY : GL_INT_SAMPLER_2D;
                     case false:  return sampler.arrayed ? GL_INT_SAMPLER_2D_ARRAY : GL_INT_SAMPLER_2D;
-                    case true:   return sampler.arrayed ? GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY : GL_INT_SAMPLER_2D_MULTISAMPLE;
+                    case true:   return sampler.arrayed ? GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY
+                                                        : GL_INT_SAMPLER_2D_MULTISAMPLE;
                     }
                     }
                 case Esd3D:
                 case Esd3D:
                     return GL_INT_SAMPLER_3D;
                     return GL_INT_SAMPLER_3D;
@@ -435,7 +441,8 @@ public:
                 case Esd2D:
                 case Esd2D:
                     switch ((int)sampler.ms) {
                     switch ((int)sampler.ms) {
                     case false:  return sampler.arrayed ? GL_UNSIGNED_INT_SAMPLER_2D_ARRAY : GL_UNSIGNED_INT_SAMPLER_2D;
                     case false:  return sampler.arrayed ? GL_UNSIGNED_INT_SAMPLER_2D_ARRAY : GL_UNSIGNED_INT_SAMPLER_2D;
-                    case true:   return sampler.arrayed ? GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY : GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE;
+                    case true:   return sampler.arrayed ? GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY
+                                                        : GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE;
                     }
                     }
                 case Esd3D:
                 case Esd3D:
                     return GL_UNSIGNED_INT_SAMPLER_3D;
                     return GL_UNSIGNED_INT_SAMPLER_3D;
@@ -495,7 +502,8 @@ public:
                 case Esd2D:
                 case Esd2D:
                     switch ((int)sampler.ms) {
                     switch ((int)sampler.ms) {
                     case false:  return sampler.arrayed ? GL_UNSIGNED_INT_IMAGE_2D_ARRAY : GL_UNSIGNED_INT_IMAGE_2D;
                     case false:  return sampler.arrayed ? GL_UNSIGNED_INT_IMAGE_2D_ARRAY : GL_UNSIGNED_INT_IMAGE_2D;
-                    case true:   return sampler.arrayed ? GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY : GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE;
+                    case true:   return sampler.arrayed ? GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY
+                                                        : GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE;
                     }
                     }
                 case Esd3D:
                 case Esd3D:
                     return GL_UNSIGNED_INT_IMAGE_3D;
                     return GL_UNSIGNED_INT_IMAGE_3D;
@@ -725,7 +733,9 @@ void TReflection::buildCounterIndices()
 // Returns false if the input is too malformed to do this.
 // Returns false if the input is too malformed to do this.
 bool TReflection::addStage(EShLanguage stage, const TIntermediate& intermediate)
 bool TReflection::addStage(EShLanguage stage, const TIntermediate& intermediate)
 {
 {
-    if (intermediate.getNumEntryPoints() != 1 || intermediate.isRecursive())
+    if (intermediate.getTreeRoot() == nullptr ||
+        intermediate.getNumEntryPoints() != 1 ||
+        intermediate.isRecursive())
         return false;
         return false;
 
 
     buildAttributeReflection(stage, intermediate);
     buildAttributeReflection(stage, intermediate);

+ 10 - 11
src/libraries/glslang/glslang/MachineIndependent/reflection.h

@@ -59,7 +59,15 @@ public:
         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), type(pType.clone()) { }
 
 
-    void dump() const {
+    const TType* const getType() const { return type; }
+    int getBinding() const
+    {
+        if (type == nullptr || !type->getQualifier().hasBinding())
+            return -1;
+        return type->getQualifier().layoutBinding;
+    }
+    void dump() const
+    {
         printf("%s: offset %d, type %x, size %d, index %d, binding %d",
         printf("%s: offset %d, type %x, size %d, index %d, binding %d",
                name.c_str(), offset, glDefineType, size, index, getBinding() );
                name.c_str(), offset, glDefineType, size, index, getBinding() );
 
 
@@ -68,8 +76,7 @@ public:
 
 
         printf("\n");
         printf("\n");
     }
     }
-
-    const TType* const getType() const { return type; }
+    static TObjectReflection badReflection() { return TObjectReflection(); }
 
 
     TString name;
     TString name;
     int offset;
     int offset;
@@ -78,15 +85,7 @@ public:
     int index;
     int index;
     int counterIndex;
     int counterIndex;
 
 
-    static TObjectReflection badReflection() { return TObjectReflection(); }
-
 protected:
 protected:
-    int getBinding() const {
-        if (type == nullptr || type->getQualifier().layoutBinding == TQualifier::layoutBindingEnd)
-            return -1;
-        return type->getQualifier().layoutBinding;
-    }
-
     TObjectReflection() : offset(-1), glDefineType(-1), size(-1), index(-1), type(nullptr) { }
     TObjectReflection() : offset(-1), glDefineType(-1), size(-1), index(-1), type(nullptr) { }
 
 
     const TType* type;
     const TType* type;

+ 13 - 0
src/libraries/glslang/glslang/OSDependent/Unix/ossource.cpp

@@ -43,6 +43,9 @@
 #include <assert.h>
 #include <assert.h>
 #include <errno.h>
 #include <errno.h>
 #include <stdint.h>
 #include <stdint.h>
+#include <cstdio>
+#include <sys/time.h>
+#include <sys/resource.h>
 
 
 namespace glslang {
 namespace glslang {
 
 
@@ -184,8 +187,18 @@ void ReleaseGlobalLock()
   pthread_mutex_unlock(&gMutex);
   pthread_mutex_unlock(&gMutex);
 }
 }
 
 
+// #define DUMP_COUNTERS
+
 void OS_DumpMemoryCounters()
 void OS_DumpMemoryCounters()
 {
 {
+#ifdef DUMP_COUNTERS
+    struct rusage usage;
+
+    if (getrusage(RUSAGE_SELF, &usage) == 0)
+        printf("Working set size: %ld\n", usage.ru_maxrss * 1024);
+#else
+    printf("Recompile with DUMP_COUNTERS defined to see counters.\n");
+#endif
 }
 }
 
 
 } // end namespace glslang
 } // end namespace glslang

+ 102 - 17
src/libraries/glslang/glslang/OSDependent/Windows/main.cpp

@@ -68,15 +68,14 @@
 #endif
 #endif
 
 
 //
 //
-// Driver must call this first, once, before doing any other
-// compiler/linker operations.
+// Call before doing any other compiler/linker operations.
 //
 //
 // (Call once per process, not once per thread.)
 // (Call once per process, not once per thread.)
 //
 //
 SH_IMPORT_EXPORT int ShInitialize();
 SH_IMPORT_EXPORT int ShInitialize();
 
 
 //
 //
-// Driver should call this at process shutdown.
+// Call this at process shutdown to clean up memory.
 //
 //
 SH_IMPORT_EXPORT int __fastcall ShFinalize();
 SH_IMPORT_EXPORT int __fastcall ShFinalize();
 
 
@@ -110,7 +109,44 @@ typedef enum {
     EShSourceNone,
     EShSourceNone,
     EShSourceGlsl,
     EShSourceGlsl,
     EShSourceHlsl,
     EShSourceHlsl,
-} EShSource;          // if EShLanguage were EShStage, this could be EShLanguage instead
+} EShSource;                  // if EShLanguage were EShStage, this could be EShLanguage instead
+
+typedef enum {
+    EShClientNone,
+    EShClientVulkan,
+    EShClientOpenGL,
+} EShClient;
+
+typedef enum {
+    EShTargetNone,
+    EshTargetSpv,
+} EShTargetLanguage;
+
+struct TInputLanguage {
+    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
+    EShClient dialect;
+    int dialectVersion;       // version of client's language definition, not the client (when not EShClientNone)
+};
+
+struct TClient {
+    EShClient client;
+    int version;              // version of client itself (not the client's input dialect)
+};
+
+struct TTarget {
+    EShTargetLanguage language;
+    unsigned int version;     // the version to target, if SPIR-V, defined by "word 1" of the SPIR-V binary header
+};
+
+// All source/client/target versions and settings.
+// Can override previous methods of setting, when items are set here.
+// Expected to grow, as more are added, rather than growing parameter lists.
+struct TEnvironment {
+    TInputLanguage input;     // definition of the input language
+    TClient client;           // what client is the overall compilation being done for?
+    TTarget target;           // what to generate
+};
 
 
 const char* StageName(EShLanguage);
 const char* StageName(EShLanguage);
 
 
@@ -253,7 +289,7 @@ SH_IMPORT_EXPORT int ShGetUniformLocation(const ShHandle uniformMap, const char*
 // Deferred-Lowering C++ Interface
 // Deferred-Lowering C++ Interface
 // -----------------------------------
 // -----------------------------------
 //
 //
-// Below is a new alternate C++ interface that might potentially replace the above
+// Below is a new alternate C++ interface, which deprecates the above
 // opaque handle-based interface.
 // opaque handle-based interface.
 //
 //
 // The below is further designed to handle multiple compilation units per stage, where
 // The below is further designed to handle multiple compilation units per stage, where
@@ -287,6 +323,17 @@ bool InitializeProcess();
 // Call once per process to tear down everything
 // Call once per process to tear down everything
 void FinalizeProcess();
 void FinalizeProcess();
 
 
+// Resource type for IO resolver
+enum TResourceType {
+    EResSampler,
+    EResTexture,
+    EResImage,
+    EResUbo,
+    EResSsbo,
+    EResUav,
+    EResCount
+};
+
 // Make one TShader per shader that you will link into a program.  Then provide
 // Make one TShader per shader that you will link into a program.  Then provide
 // the shader through setStrings() or setStringsWithLengths(), then call parse(),
 // the shader through setStrings() or setStringsWithLengths(), then call parse(),
 // then query the info logs.
 // then query the info logs.
@@ -309,21 +356,46 @@ public:
     void setPreamble(const char* s) { preamble = s; }
     void setPreamble(const char* s) { preamble = s; }
     void setEntryPoint(const char* entryPoint);
     void setEntryPoint(const char* entryPoint);
     void setSourceEntryPoint(const char* sourceEntryPointName);
     void setSourceEntryPoint(const char* sourceEntryPointName);
-    void setShiftSamplerBinding(unsigned int base);
-    void setShiftTextureBinding(unsigned int base);
-    void setShiftImageBinding(unsigned int base);
-    void setShiftUboBinding(unsigned int base);
-    void setShiftUavBinding(unsigned int base);
-    void setShiftCbufferBinding(unsigned int base); // synonym for setShiftUboBinding
-    void setShiftSsboBinding(unsigned int base);
+    void addProcesses(const std::vector<std::string>&);
+
+    // IO resolver binding data: see comments in ShaderLang.cpp
+    void setShiftBinding(TResourceType res, unsigned int base);
+    void setShiftSamplerBinding(unsigned int base);  // DEPRECATED: use setShiftBinding
+    void setShiftTextureBinding(unsigned int base);  // DEPRECATED: use setShiftBinding
+    void setShiftImageBinding(unsigned int base);    // DEPRECATED: use setShiftBinding
+    void setShiftUboBinding(unsigned int base);      // DEPRECATED: use setShiftBinding
+    void setShiftUavBinding(unsigned int base);      // DEPRECATED: use setShiftBinding
+    void setShiftCbufferBinding(unsigned int base);  // synonym for setShiftUboBinding
+    void setShiftSsboBinding(unsigned int base);     // DEPRECATED: use setShiftBinding
+    void setShiftBindingForSet(TResourceType res, unsigned int base, unsigned int set);
     void setResourceSetBinding(const std::vector<std::string>& base);
     void setResourceSetBinding(const std::vector<std::string>& base);
     void setAutoMapBindings(bool map);
     void setAutoMapBindings(bool map);
     void setAutoMapLocations(bool map);
     void setAutoMapLocations(bool map);
+    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):
+    void setEnvInput(EShSource lang, EShLanguage envStage, EShClient client, int version)
+    {
+        environment.input.languageFamily = lang;
+        environment.input.stage = envStage;
+        environment.input.dialect = client;
+        environment.input.dialectVersion = version;
+    }
+    void setEnvClient(EShClient client, int version)
+    {
+        environment.client.client = client;
+        environment.client.version = version;
+    }
+    void setEnvTarget(EShTargetLanguage lang, unsigned int version)
+    {
+        environment.target.language = lang;
+        environment.target.version = version;
+    }
+
     // Interface to #include handlers.
     // Interface to #include handlers.
     //
     //
     // To support #include, a client of Glslang does the following:
     // To support #include, a client of Glslang does the following:
@@ -436,8 +508,8 @@ public:
 
 
     const char* getInfoLog();
     const char* getInfoLog();
     const char* getInfoDebugLog();
     const char* getInfoDebugLog();
-
     EShLanguage getStage() const { return stage; }
     EShLanguage getStage() const { return stage; }
+    TIntermediate* getIntermediate() const { return intermediate; }
 
 
 protected:
 protected:
     TPoolAllocator* pool;
     TPoolAllocator* pool;
@@ -463,6 +535,8 @@ protected:
     // a function in the source string can be renamed FROM this TO the name given in setEntryPoint.
     // a function in the source string can be renamed FROM this TO the name given in setEntryPoint.
     std::string sourceEntryPointName;
     std::string sourceEntryPointName;
 
 
+    TEnvironment environment;
+
     friend class TProgram;
     friend class TProgram;
 
 
 private:
 private:
@@ -474,9 +548,10 @@ class TIoMapper;
 
 
 // Allows to customize the binding layout after linking.
 // Allows to customize the binding layout after linking.
 // All used uniform variables will invoke at least validateBinding.
 // All used uniform variables will invoke at least validateBinding.
-// If validateBinding returned true then the other resolveBinding
-// and resolveSet are invoked to resolve the binding and descriptor
-// set index respectively.
+// If validateBinding returned true then the other resolveBinding,
+// resolveSet, and resolveLocation are invoked to resolve the binding
+// and descriptor set index respectively.
+//
 // Invocations happen in a particular order:
 // Invocations happen in a particular order:
 // 1) all shader inputs
 // 1) all shader inputs
 // 2) all shader outputs
 // 2) all shader outputs
@@ -508,6 +583,9 @@ public:
   // Should return a value >= 0 if the current set should be overridden.
   // Should return a value >= 0 if the current set should be overridden.
   // Return -1 if the current set (including no set) should be kept.
   // Return -1 if the current set (including no set) should be kept.
   virtual int resolveSet(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
   virtual int resolveSet(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
+  // Should return a value >= 0 if the current location should be overridden.
+  // Return -1 if the current location (including no location) should be kept.
+  virtual int resolveUniformLocation(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
   // Should return true if the resulting/current setup would be okay.
   // Should return true if the resulting/current setup would be okay.
   // Basic idea is to do aliasing checks and reject invalid semantic names.
   // Basic idea is to do aliasing checks and reject invalid semantic names.
   virtual bool validateInOut(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
   virtual bool validateInOut(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
@@ -525,7 +603,13 @@ public:
   // Notification of a in or out variable
   // Notification of a in or out variable
   virtual void notifyInOut(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
   virtual void notifyInOut(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
   // Called by mapIO when it has finished the notify pass
   // Called by mapIO when it has finished the notify pass
-  virtual void endNotifications() = 0;
+  virtual void endNotifications(EShLanguage stage) = 0;
+  // Called by mapIO when it starts its notify pass for the given stage
+  virtual void beginNotifications(EShLanguage stage) = 0;
+  // Called by mipIO when it starts its resolve pass for the given stage
+  virtual void beginResolve(EShLanguage stage) = 0;
+  // Called by mapIO when it has finished the resolve pass
+  virtual void endResolve(EShLanguage stage) = 0;
 };
 };
 
 
 // Make one TProgram per set of shaders that will get linked together.  Add all
 // Make one TProgram per set of shaders that will get linked together.  Add all
@@ -555,6 +639,7 @@ public:
     const char* getUniformBlockName(int blockIndex) const; // can be used for glGetActiveUniformBlockName()
     const char* getUniformBlockName(int blockIndex) const; // can be used for glGetActiveUniformBlockName()
     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 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)

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