Browse Source

Updated glslang.

Бранимир Караџић 5 years ago
parent
commit
4b57cdc595
34 changed files with 1381 additions and 704 deletions
  1. 2 1
      3rdparty/glslang/SPIRV/CMakeLists.txt
  2. 1 0
      3rdparty/glslang/SPIRV/GLSL.ext.KHR.h
  3. 242 111
      3rdparty/glslang/SPIRV/GlslangToSpv.cpp
  4. 50 0
      3rdparty/glslang/SPIRV/NonSemanticDebugPrintf.h
  5. 29 12
      3rdparty/glslang/SPIRV/SpvBuilder.cpp
  6. 72 34
      3rdparty/glslang/SPIRV/SpvBuilder.h
  7. 5 4
      3rdparty/glslang/SPIRV/SpvTools.cpp
  8. 8 1
      3rdparty/glslang/SPIRV/disassemble.cpp
  9. 2 1
      3rdparty/glslang/StandAlone/CMakeLists.txt
  10. 1 0
      3rdparty/glslang/StandAlone/StandAlone.cpp
  11. 51 0
      3rdparty/glslang/StandAlone/resource_limits_c.cpp
  12. 54 0
      3rdparty/glslang/StandAlone/resource_limits_c.h
  13. 16 8
      3rdparty/glslang/glslang/CInterface/glslang_c_interface.cpp
  14. 1 0
      3rdparty/glslang/glslang/Include/Types.h
  15. 113 0
      3rdparty/glslang/glslang/Include/glslang_c_interface.h
  16. 2 0
      3rdparty/glslang/glslang/Include/intermediate.h
  17. 1 2
      3rdparty/glslang/glslang/MachineIndependent/Constant.cpp
  18. 6 1
      3rdparty/glslang/glslang/MachineIndependent/Initialize.cpp
  19. 1 1
      3rdparty/glslang/glslang/MachineIndependent/Intermediate.cpp
  20. 14 1
      3rdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp
  21. 8 8
      3rdparty/glslang/glslang/MachineIndependent/Scan.cpp
  22. 1 1
      3rdparty/glslang/glslang/MachineIndependent/ShaderLang.cpp
  23. 3 1
      3rdparty/glslang/glslang/MachineIndependent/Versions.cpp
  24. 1 0
      3rdparty/glslang/glslang/MachineIndependent/Versions.h
  25. 5 1
      3rdparty/glslang/glslang/MachineIndependent/glslang.m4
  26. 4 0
      3rdparty/glslang/glslang/MachineIndependent/glslang.y
  27. 489 406
      3rdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp
  28. 99 98
      3rdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp.h
  29. 1 0
      3rdparty/glslang/glslang/MachineIndependent/intermOut.cpp
  30. 19 4
      3rdparty/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp
  31. 2 1
      3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpContext.cpp
  32. 1 0
      3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpContext.h
  33. 76 6
      3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp
  34. 1 1
      3rdparty/glslang/glslang/OSDependent/Web/CMakeLists.txt

+ 2 - 1
3rdparty/glslang/SPIRV/CMakeLists.txt

@@ -27,7 +27,8 @@ set(HEADERS
     SpvTools.h
     disassemble.h
     GLSL.ext.AMD.h
-    GLSL.ext.NV.h)
+    GLSL.ext.NV.h
+    NonSemanticDebugPrintf.h)
 
 set(SPVREMAP_HEADERS
     SPVRemapper.h

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

@@ -44,5 +44,6 @@ static const char* const E_SPV_EXT_physical_storage_buffer      = "SPV_EXT_physi
 static const char* const E_SPV_KHR_physical_storage_buffer      = "SPV_KHR_physical_storage_buffer";
 static const char* const E_SPV_EXT_fragment_shader_interlock    = "SPV_EXT_fragment_shader_interlock";
 static const char* const E_SPV_KHR_shader_clock                 = "SPV_KHR_shader_clock";
+static const char* const E_SPV_KHR_non_semantic_info            = "SPV_KHR_non_semantic_info";
 
 #endif  // #ifndef GLSLextKHR_H

+ 242 - 111
3rdparty/glslang/SPIRV/GlslangToSpv.cpp

@@ -1,6 +1,6 @@
 //
 // Copyright (C) 2014-2016 LunarG, Inc.
-// Copyright (C) 2015-2018 Google, Inc.
+// Copyright (C) 2015-2020 Google, Inc.
 // Copyright (C) 2017 ARM Limited.
 //
 // All rights reserved.
@@ -48,6 +48,7 @@ namespace spv {
     #include "GLSL.ext.EXT.h"
     #include "GLSL.ext.AMD.h"
     #include "GLSL.ext.NV.h"
+    #include "NonSemanticDebugPrintf.h"
 }
 
 // Glslang includes
@@ -187,7 +188,8 @@ protected:
     void makeGlobalInitializers(const glslang::TIntermSequence&);
     void visitFunctions(const glslang::TIntermSequence&);
     void handleFunctionEntry(const glslang::TIntermAggregate* node);
-    void translateArguments(const glslang::TIntermAggregate& node, std::vector<spv::Id>& arguments, spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags);
+    void translateArguments(const glslang::TIntermAggregate& node, std::vector<spv::Id>& arguments,
+        spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags);
     void translateArguments(glslang::TIntermUnary& node, std::vector<spv::Id>& arguments);
     spv::Id createImageTextureFunctionCall(glslang::TIntermOperator* node);
     spv::Id handleUserFunctionCall(const glslang::TIntermAggregate*);
@@ -196,23 +198,31 @@ protected:
                                   glslang::TBasicType typeProxy, bool reduceComparison = true);
     spv::Id createBinaryMatrixOperation(spv::Op, OpDecorations&, spv::Id typeId, spv::Id left, spv::Id right);
     spv::Id createUnaryOperation(glslang::TOperator op, OpDecorations&, spv::Id typeId, spv::Id operand,
-                                 glslang::TBasicType typeProxy, const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags);
+                                 glslang::TBasicType typeProxy,
+                                 const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags);
     spv::Id createUnaryMatrixOperation(spv::Op op, OpDecorations&, spv::Id typeId, spv::Id operand,
                                        glslang::TBasicType typeProxy);
     spv::Id createConversion(glslang::TOperator op, OpDecorations&, spv::Id destTypeId, spv::Id operand,
                              glslang::TBasicType typeProxy);
     spv::Id createIntWidthConversion(glslang::TOperator op, spv::Id operand, int vectorSize);
     spv::Id makeSmearedConstant(spv::Id constant, int vectorSize);
-    spv::Id createAtomicOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy, const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags);
-    spv::Id createInvocationsOperation(glslang::TOperator op, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy);
-    spv::Id CreateInvocationsVectorOperation(spv::Op op, spv::GroupOperation groupOperation, spv::Id typeId, std::vector<spv::Id>& operands);
-    spv::Id createSubgroupOperation(glslang::TOperator op, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy);
-    spv::Id createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy);
+    spv::Id createAtomicOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId,
+        std::vector<spv::Id>& operands, glslang::TBasicType typeProxy,
+        const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags);
+    spv::Id createInvocationsOperation(glslang::TOperator op, spv::Id typeId, std::vector<spv::Id>& operands,
+        glslang::TBasicType typeProxy);
+    spv::Id CreateInvocationsVectorOperation(spv::Op op, spv::GroupOperation groupOperation,
+        spv::Id typeId, std::vector<spv::Id>& operands);
+    spv::Id createSubgroupOperation(glslang::TOperator op, spv::Id typeId, std::vector<spv::Id>& operands,
+        glslang::TBasicType typeProxy);
+    spv::Id createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId,
+        std::vector<spv::Id>& operands, glslang::TBasicType typeProxy);
     spv::Id createNoArgOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId);
     spv::Id getSymbolId(const glslang::TIntermSymbol* node);
     void addMeshNVDecoration(spv::Id id, int member, const glslang::TQualifier & qualifier);
     spv::Id createSpvConstant(const glslang::TIntermTyped&);
-    spv::Id createSpvConstantFromConstUnionArray(const glslang::TType& type, const glslang::TConstUnionArray&, int& nextConst, bool specConstant);
+    spv::Id createSpvConstantFromConstUnionArray(const glslang::TType& type, const glslang::TConstUnionArray&,
+        int& nextConst, bool specConstant);
     bool isTrivialLeaf(const glslang::TIntermTyped* node);
     bool isTrivial(const glslang::TIntermTyped* node);
     spv::Id createShortCircuit(glslang::TOperator, glslang::TIntermTyped& left, glslang::TIntermTyped& right);
@@ -233,15 +243,18 @@ protected:
     spv::Builder builder;
     bool inEntryPoint;
     bool entryPointTerminated;
-    bool linkageOnly;                  // true when visiting the set of objects in the AST present only for establishing interface, whether or not they were statically used
+    bool linkageOnly;                  // true when visiting the set of objects in the AST present only for
+                                       // establishing interface, whether or not they were statically used
     std::set<spv::Id> iOSet;           // all input/output variables from either static use or declaration of interface
     const glslang::TIntermediate* glslangIntermediate;
     bool nanMinMaxClamp;               // true if use NMin/NMax/NClamp instead of FMin/FMax/FClamp
     spv::Id stdBuiltins;
+    spv::Id nonSemanticDebugPrintf;
     std::unordered_map<const char*, spv::Id> extBuiltinMap;
 
     std::unordered_map<int, spv::Id> symbolValues;
-    std::unordered_set<int> rValueParameters;  // set of formal function parameters passed as rValues, rather than a pointer
+    std::unordered_set<int> rValueParameters;  // set of formal function parameters passed as rValues,
+                                               // rather than a pointer
     std::unordered_map<std::string, spv::Function*> functionMap;
     std::unordered_map<const glslang::TTypeList*, spv::Id> structMap[glslang::ElpCount][glslang::ElmCount];
     // for mapping glslang block indices to spv indices (e.g., due to hidden members):
@@ -374,7 +387,8 @@ spv::Decoration TranslateBlockDecoration(const glslang::TType& type, bool useSto
 }
 
 // Translate glslang type to SPIR-V memory decorations.
-void TranslateMemoryDecoration(const glslang::TQualifier& qualifier, std::vector<spv::Decoration>& memory, bool useVulkanMemoryModel)
+void TranslateMemoryDecoration(const glslang::TQualifier& qualifier, std::vector<spv::Decoration>& memory,
+    bool useVulkanMemoryModel)
 {
     if (!useVulkanMemoryModel) {
         if (qualifier.isCoherent())
@@ -640,7 +654,8 @@ spv::Scope TGlslangToSpvTraverser::TranslateMemoryScope(
 // is generated only when using the variable in an executable instruction, but not when
 // just declaring a struct member variable with it.  This is true for PointSize,
 // ClipDistance, and CullDistance.
-spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltInVariable builtIn, bool memberDeclaration)
+spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltInVariable builtIn,
+    bool memberDeclaration)
 {
     switch (builtIn) {
     case glslang::EbvPointSize:
@@ -1106,7 +1121,8 @@ spv::ImageFormat TGlslangToSpvTraverser::TranslateImageFormat(const glslang::TTy
     }
 }
 
-spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSelectionControl(const glslang::TIntermSelection& selectionNode) const
+spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSelectionControl(
+    const glslang::TIntermSelection& selectionNode) const
 {
     if (selectionNode.getFlatten())
         return spv::SelectionControlFlattenMask;
@@ -1115,7 +1131,8 @@ spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSelectionControl(cons
     return spv::SelectionControlMaskNone;
 }
 
-spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSwitchControl(const glslang::TIntermSwitch& switchNode) const
+spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSwitchControl(const glslang::TIntermSwitch& switchNode)
+    const
 {
     if (switchNode.getFlatten())
         return spv::SelectionControlFlattenMask;
@@ -1350,16 +1367,18 @@ bool HasNonLayoutQualifiers(const glslang::TType& type, const glslang::TQualifie
 // Implement the TGlslangToSpvTraverser class.
 //
 
-TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const glslang::TIntermediate* glslangIntermediate,
-                                               spv::SpvBuildLogger* buildLogger, glslang::SpvOptions& options)
-    : TIntermTraverser(true, false, true),
-      options(options),
-      shaderEntry(nullptr), currentFunction(nullptr),
-      sequenceDepth(0), logger(buildLogger),
-      builder(spvVersion, (glslang::GetKhronosToolId() << 16) | glslang::GetSpirvGeneratorVersion(), logger),
-      inEntryPoint(false), entryPointTerminated(false), linkageOnly(false),
-      glslangIntermediate(glslangIntermediate),
-      nanMinMaxClamp(glslangIntermediate->getNanMinMaxClamp())
+TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
+    const glslang::TIntermediate* glslangIntermediate,
+    spv::SpvBuildLogger* buildLogger, glslang::SpvOptions& options) :
+        TIntermTraverser(true, false, true),
+        options(options),
+        shaderEntry(nullptr), currentFunction(nullptr),
+        sequenceDepth(0), logger(buildLogger),
+        builder(spvVersion, (glslang::GetKhronosToolId() << 16) | glslang::GetSpirvGeneratorVersion(), logger),
+        inEntryPoint(false), entryPointTerminated(false), linkageOnly(false),
+        glslangIntermediate(glslangIntermediate),
+        nanMinMaxClamp(glslangIntermediate->getNanMinMaxClamp()),
+        nonSemanticDebugPrintf(0)
 {
     spv::ExecutionModel executionModel = TranslateExecutionModel(glslangIntermediate->getStage());
 
@@ -1402,7 +1421,7 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const gl
         addressingModel = spv::AddressingModelPhysicalStorageBuffer64EXT;
         builder.addIncorporatedExtension(spv::E_SPV_EXT_physical_storage_buffer, spv::Spv_1_5);
         builder.addCapability(spv::CapabilityPhysicalStorageBufferAddressesEXT);
-    };
+    }
     if (glslangIntermediate->usingVulkanMemoryModel()) {
         memoryModel = spv::MemoryModelVulkanKHR;
         builder.addCapability(spv::CapabilityVulkanMemoryModelKHR);
@@ -1520,7 +1539,8 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const gl
         glslang::TLayoutGeometry primitive;
 
         if (glslangIntermediate->getStage() == EShLangTessControl) {
-            builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, glslangIntermediate->getVertices());
+            builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices,
+                glslangIntermediate->getVertices());
             primitive = glslangIntermediate->getOutputPrimitive();
         } else {
             primitive = glslangIntermediate->getInputPrimitive();
@@ -1599,8 +1619,10 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const gl
                                                                            glslangIntermediate->getLocalSize(1),
                                                                            glslangIntermediate->getLocalSize(2));
         if (glslangIntermediate->getStage() == EShLangMeshNV) {
-            builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, glslangIntermediate->getVertices());
-            builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputPrimitivesNV, glslangIntermediate->getPrimitives());
+            builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices,
+                glslangIntermediate->getVertices());
+            builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputPrimitivesNV,
+                glslangIntermediate->getPrimitives());
 
             switch (glslangIntermediate->getOutputPrimitive()) {
             case glslang::ElgPoints:        mode = spv::ExecutionModeOutputPoints;      break;
@@ -1847,7 +1869,8 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
                 int dummySize;
                 builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()),
                                                TranslateCoherent(node->getLeft()->getType()),
-                                               glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(), dummySize));
+                                               glslangIntermediate->getBaseAlignmentScalar(
+                                                   node->getLeft()->getType(), dummySize));
             } else {
 
                 // Load through a block reference is performed with a dot operator that
@@ -1877,7 +1900,9 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
                 }
 
                 // normal case for indexing array or structure or block
-                builder.accessChainPush(builder.makeIntConstant(spvIndex), TranslateCoherent(node->getLeft()->getType()), node->getLeft()->getType().getBufferReferenceAlignment());
+                builder.accessChainPush(builder.makeIntConstant(spvIndex),
+                    TranslateCoherent(node->getLeft()->getType()),
+                        node->getLeft()->getType().getBufferReferenceAlignment());
 
                 // Add capabilities here for accessing PointSize and clip/cull distance.
                 // We have deferred generation of associated capabilities until now.
@@ -1914,9 +1939,11 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
                 int dummySize;
                 builder.accessChainPushComponent(index, convertGlslangToSpvType(node->getLeft()->getType()),
                                                 TranslateCoherent(node->getLeft()->getType()),
-                                                glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(), dummySize));
+                                                glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(),
+                                                dummySize));
             } else
-                builder.accessChainPush(index, TranslateCoherent(node->getLeft()->getType()), node->getLeft()->getType().getBufferReferenceAlignment());
+                builder.accessChainPush(index, TranslateCoherent(node->getLeft()->getType()),
+                    node->getLeft()->getType().getBufferReferenceAlignment());
         }
         return false;
     case glslang::EOpVectorSwizzle:
@@ -1927,7 +1954,8 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
             int dummySize;
             builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()),
                                            TranslateCoherent(node->getLeft()->getType()),
-                                           glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(), dummySize));
+                                           glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(),
+                                               dummySize));
         }
         return false;
     case glslang::EOpMatrixSwizzle:
@@ -1943,7 +1971,8 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
             if (isTrivial(node->getRight()->getAsTyped()))
                 break; // handle below as a normal binary operation
             // otherwise, we need to do dynamic short circuiting on the right operand
-            spv::Id result = createShortCircuit(node->getOp(), *node->getLeft()->getAsTyped(), *node->getRight()->getAsTyped());
+            spv::Id result = createShortCircuit(node->getOp(), *node->getLeft()->getAsTyped(),
+                *node->getRight()->getAsTyped());
             builder.clearAccessChain();
             builder.setAccessChainRValue(result);
         }
@@ -2091,7 +2120,8 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
         } else {
             glslang::TIntermTyped* block = node->getOperand()->getAsBinaryNode()->getLeft();
             block->traverse(this);
-            unsigned int member = node->getOperand()->getAsBinaryNode()->getRight()->getAsConstantUnion()->getConstArray()[0].getUConst();
+            unsigned int member = node->getOperand()->getAsBinaryNode()->getRight()->getAsConstantUnion()
+                ->getConstArray()[0].getUConst();
             length = builder.createArrayLength(builder.accessChainGetLValue(), member);
         }
 
@@ -2117,7 +2147,8 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
     // Does it need a swizzle inversion?  If so, evaluation is inverted;
     // operate first on the swizzle base, then apply the swizzle.
     spv::Id invertedType = spv::NoType;
-    auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ? invertedType : convertGlslangToSpvType(node->getType()); };
+    auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ?
+        invertedType : convertGlslangToSpvType(node->getType()); };
     if (node->getOp() == glslang::EOpInterpolateAtCentroid)
         invertedType = getInvertedSwizzleType(*node->getOperand());
 
@@ -2154,11 +2185,13 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
 
     // it could be a conversion
     if (! result)
-        result = createConversion(node->getOp(), decorations, resultType(), operand, node->getOperand()->getBasicType());
+        result = createConversion(node->getOp(), decorations, resultType(), operand,
+            node->getOperand()->getBasicType());
 
     // if not, then possibly an operation
     if (! result)
-        result = createUnaryOperation(node->getOp(), decorations, resultType(), operand, node->getOperand()->getBasicType(), lvalueCoherentFlags);
+        result = createUnaryOperation(node->getOp(), decorations, resultType(), operand,
+            node->getOperand()->getBasicType(), lvalueCoherentFlags);
 
     if (result) {
         if (invertedType) {
@@ -2251,7 +2284,8 @@ spv::Id TGlslangToSpvTraverser::createCompositeConstruct(spv::Id resultTypeId, s
                 std::vector<spv::Id> rTypeConstituents;
                 int numrTypeConstituents = builder.getNumTypeConstituents(rType);
                 for (int i = 0; i < numrTypeConstituents; ++i) {
-                    rTypeConstituents.push_back(builder.createCompositeExtract(constituent, builder.getContainedTypeId(rType, i), i));
+                    rTypeConstituents.push_back(builder.createCompositeExtract(constituent,
+                        builder.getContainedTypeId(rType, i), i));
                 }
                 constituents[c] = createCompositeConstruct(lType, rTypeConstituents);
             } else {
@@ -2277,8 +2311,14 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
         spec_constant_op_mode_setter.turnOnSpecConstantOpMode();
 
     spv::Id result = spv::NoResult;
-    spv::Id invertedType = spv::NoType;  // to use to override the natural type of the node
-    auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ? invertedType : convertGlslangToSpvType(node->getType()); };
+    spv::Id invertedType = spv::NoType;       // to use to override the natural type of the node
+    spv::Builder::AccessChain complexLvalue;  // for holding swizzling l-values too complex for SPIR-V,
+                                              // for at out parameter
+    spv::Id temporaryLvalue = spv::NoResult;  // temporary to pass, as proxy for complexLValue
+
+    auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ?
+        invertedType :
+        convertGlslangToSpvType(node->getType()); };
 
     // try texturing
     result = createImageTextureFunctionCall(node);
@@ -2382,7 +2422,6 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
         builder.setLine(node->getLoc().line, node->getLoc().getFilename());
         if (node->isUserDefined())
             result = handleUserFunctionCall(node);
-        // assert(result);  // this can happen for bad shaders because the call graph completeness checking is not yet done
         if (result) {
             builder.clearAccessChain();
             builder.setAccessChainRValue(result);
@@ -2651,6 +2690,10 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
         break;
 #endif
 
+    case glslang::EOpDebugPrintf:
+        noReturnValue = true;
+        break;
+
     default:
         break;
     }
@@ -2727,9 +2770,14 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
 
                 // Does it need a swizzle inversion?  If so, evaluation is inverted;
                 // operate first on the swizzle base, then apply the swizzle.
+                // That is, we transform
+                //
+                //    interpolate(v.zy)  ->  interpolate(v).zy
+                //
                 if (glslangOperands[0]->getAsOperator() &&
                     glslangOperands[0]->getAsOperator()->getOp() == glslang::EOpVectorSwizzle)
-                    invertedType = convertGlslangToSpvType(glslangOperands[0]->getAsBinaryNode()->getLeft()->getType());
+                    invertedType = convertGlslangToSpvType(
+                        glslangOperands[0]->getAsBinaryNode()->getLeft()->getType());
             }
             break;
         case glslang::EOpAtomicLoad:
@@ -2789,8 +2837,9 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
                 builder.setAccessChain(save);
 
                 // Point to the first element of the array.
-                builder.accessChainPush(elementId, TranslateCoherent(glslangOperands[arg]->getAsTyped()->getType()),
-                                                   glslangOperands[arg]->getAsTyped()->getType().getBufferReferenceAlignment());
+                builder.accessChainPush(elementId,
+                    TranslateCoherent(glslangOperands[arg]->getAsTyped()->getType()),
+                                      glslangOperands[arg]->getAsTyped()->getType().getBufferReferenceAlignment());
 
                 spv::Builder::AccessChain::CoherentFlags coherentFlags = builder.getAccessChain().coherentFlags;
                 unsigned int alignment = builder.getAccessChain().alignment;
@@ -2800,7 +2849,8 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
                     memoryAccess &= ~spv::MemoryAccessMakePointerAvailableKHRMask;
                 if (node->getOp() == glslang::EOpCooperativeMatrixStore)
                     memoryAccess &= ~spv::MemoryAccessMakePointerVisibleKHRMask;
-                if (builder.getStorageClass(builder.getAccessChain().base) == spv::StorageClassPhysicalStorageBufferEXT) {
+                if (builder.getStorageClass(builder.getAccessChain().base) ==
+                    spv::StorageClassPhysicalStorageBufferEXT) {
                     memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask);
                 }
 
@@ -2810,8 +2860,10 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
                     memoryAccessOperands.push_back(spv::IdImmediate(false, alignment));
                 }
 
-                if (memoryAccess & (spv::MemoryAccessMakePointerAvailableKHRMask | spv::MemoryAccessMakePointerVisibleKHRMask)) {
-                    memoryAccessOperands.push_back(spv::IdImmediate(true, builder.makeUintConstant(TranslateMemoryScope(coherentFlags))));
+                if (memoryAccess &
+                    (spv::MemoryAccessMakePointerAvailableKHRMask | spv::MemoryAccessMakePointerVisibleKHRMask)) {
+                    memoryAccessOperands.push_back(spv::IdImmediate(true,
+                        builder.makeUintConstant(TranslateMemoryScope(coherentFlags))));
                 }
             } else if (arg == 2) {
                 continue;
@@ -2819,8 +2871,20 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
         }
 #endif
 
+        // for l-values, pass the address, for r-values, pass the value
         if (lvalue) {
-            operands.push_back(builder.accessChainGetLValue());
+            if (invertedType == spv::NoType && !builder.isSpvLvalue()) {
+                // SPIR-V cannot represent an l-value containing a swizzle that doesn't
+                // reduce to a simple access chain.  So, we need a temporary vector to
+                // receive the result, and must later swizzle that into the original
+                // l-value.
+                complexLvalue = builder.getAccessChain();
+                temporaryLvalue = builder.createVariable(spv::StorageClassFunction,
+                    builder.accessChainGetInferredType(), "swizzleTemp");
+                operands.push_back(temporaryLvalue);
+            } else {
+                operands.push_back(builder.accessChainGetLValue());
+            }
             lvalueCoherentFlags = builder.getAccessChain().coherentFlags;
             lvalueCoherentFlags |= TranslateCoherent(glslangOperands[arg]->getAsTyped()->getType());
         } else {
@@ -2861,7 +2925,14 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
 #endif
     if (atomic) {
         // Handle all atomics
-        result = createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType(), lvalueCoherentFlags);
+        result = createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType(),
+            lvalueCoherentFlags);
+    } else if (node->getOp() == glslang::EOpDebugPrintf) {
+        if (!nonSemanticDebugPrintf) {
+            nonSemanticDebugPrintf = builder.import("NonSemantic.DebugPrintf");
+        }
+        result = builder.createBuiltinCall(builder.makeVoidType(), nonSemanticDebugPrintf, spv::NonSemanticDebugPrintfDebugPrintf, operands);
+        builder.addExtension(spv::E_SPV_KHR_non_semantic_info);
     } else {
         // Pass through to generic operations.
         switch (glslangOperands.size()) {
@@ -2883,8 +2954,12 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
             result = createMiscOperation(node->getOp(), precision, resultType(), operands, node->getBasicType());
             break;
         }
-        if (invertedType)
+        if (invertedType != spv::NoResult)
             result = createInvertedSwizzle(precision, *glslangOperands[0]->getAsBinaryNode(), result);
+        else if (temporaryLvalue != spv::NoResult) {
+            builder.setAccessChain(complexLvalue);
+            builder.accessChainStore(builder.createLoad(temporaryLvalue));
+        }
     }
 
     if (noReturnValue)
@@ -3091,7 +3166,8 @@ bool TGlslangToSpvTraverser::visitSwitch(glslang::TVisit /* visit */, glslang::T
             defaultSegment = (int)codeSegments.size();
         else if (child->getAsBranchNode() && child->getAsBranchNode()->getFlowOp() == glslang::EOpCase) {
             valueIndexToSegment[caseValues.size()] = (int)codeSegments.size();
-            caseValues.push_back(child->getAsBranchNode()->getExpression()->getAsConstantUnion()->getConstArray()[0].getIConst());
+            caseValues.push_back(child->getAsBranchNode()->getExpression()->getAsConstantUnion()
+                ->getConstArray()[0].getIConst());
         } else
             codeSegments.push_back(child);
     }
@@ -3104,7 +3180,8 @@ bool TGlslangToSpvTraverser::visitSwitch(glslang::TVisit /* visit */, glslang::T
 
     // make the switch statement
     std::vector<spv::Block*> segmentBlocks; // returned, as the blocks allocated in the call
-    builder.makeSwitch(selector, control, (int)codeSegments.size(), caseValues, valueIndexToSegment, defaultSegment, segmentBlocks);
+    builder.makeSwitch(selector, control, (int)codeSegments.size(), caseValues, valueIndexToSegment, defaultSegment,
+        segmentBlocks);
 
     // emit all the code in the segments
     breakForLoop.push(false);
@@ -3361,7 +3438,8 @@ spv::Id TGlslangToSpvTraverser::getInvertedSwizzleType(const glslang::TIntermTyp
 
 // When inverting a swizzle with a parent op, this function
 // will apply the swizzle operation to a completed parent operation.
-spv::Id TGlslangToSpvTraverser::createInvertedSwizzle(spv::Decoration precision, const glslang::TIntermTyped& node, spv::Id parentResult)
+spv::Id TGlslangToSpvTraverser::createInvertedSwizzle(spv::Decoration precision, const glslang::TIntermTyped& node,
+    spv::Id parentResult)
 {
     std::vector<unsigned> swizzle;
     convertSwizzle(*node.getAsBinaryNode()->getRight()->getAsAggregate(), swizzle);
@@ -3501,6 +3579,9 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
             spvType = convertGlslangStructToSpvType(type, glslangMembers, explicitLayout, qualifier);
         }
         break;
+    case glslang::EbtString:
+        // no type used for OpString
+        return 0;
     default:
         assert(0);
         break;
@@ -3626,7 +3707,8 @@ spv::Id TGlslangToSpvTraverser::convertGlslangStructToSpvType(const glslang::TTy
 {
     // Create a vector of struct types for SPIR-V to consume
     std::vector<spv::Id> spvMembers;
-    int memberDelta = 0;  // how much the member's index changes from glslang to SPIR-V, normally 0, except sometimes for blocks
+    int memberDelta = 0;  // how much the member's index changes from glslang to SPIR-V, normally 0,
+                          // except sometimes for blocks
     std::vector<std::pair<glslang::TType*, glslang::TQualifier> > deferredForwardPointers;
     for (int i = 0; i < (int)glslangMembers->size(); i++) {
         glslang::TType& glslangMember = *(*glslangMembers)[i].type;
@@ -3662,10 +3744,12 @@ spv::Id TGlslangToSpvTraverser::convertGlslangStructToSpvType(const glslang::TTy
                     deferredForwardPointers.push_back(std::make_pair(&glslangMember, memberQualifier));
                 }
                 spvMembers.push_back(
-                    convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier, lastBufferBlockMember, true));
+                    convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier, lastBufferBlockMember,
+                        true));
             } else {
                 spvMembers.push_back(
-                    convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier, lastBufferBlockMember, false));
+                    convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier, lastBufferBlockMember,
+                        false));
             }
         }
     }
@@ -3853,11 +3937,11 @@ spv::Id TGlslangToSpvTraverser::accessChainLoad(const glslang::TType& type)
     alignment |= type.getBufferReferenceAlignment();
 
     spv::Id loadedId = builder.accessChainLoad(TranslatePrecisionDecoration(type),
-                                               TranslateNonUniformDecoration(type.getQualifier()),
-                                               nominalTypeId,
-                                               spv::MemoryAccessMask(TranslateMemoryAccess(coherentFlags) & ~spv::MemoryAccessMakePointerAvailableKHRMask),
-                                               TranslateMemoryScope(coherentFlags),
-                                               alignment);
+        TranslateNonUniformDecoration(type.getQualifier()),
+        nominalTypeId,
+        spv::MemoryAccessMask(TranslateMemoryAccess(coherentFlags) & ~spv::MemoryAccessMakePointerAvailableKHRMask),
+        TranslateMemoryScope(coherentFlags),
+        alignment);
 
     // Need to convert to abstract types when necessary
     if (type.getBasicType() == glslang::EbtBool) {
@@ -3871,7 +3955,8 @@ spv::Id TGlslangToSpvTraverser::accessChainLoad(const glslang::TType& type)
             int vecSize = builder.getNumTypeComponents(nominalTypeId);
             spv::Id bvecType = builder.makeVectorType(builder.makeBoolType(), vecSize);
             if (nominalTypeId != bvecType)
-                loadedId = builder.createBinOp(spv::OpINotEqual, bvecType, loadedId, makeSmearedConstant(builder.makeUintConstant(0), vecSize));
+                loadedId = builder.createBinOp(spv::OpINotEqual, bvecType, loadedId,
+                    makeSmearedConstant(builder.makeUintConstant(0), vecSize));
         }
     }
 
@@ -3920,7 +4005,8 @@ void TGlslangToSpvTraverser::accessChainStore(const glslang::TType& type, spv::I
     alignment |= type.getBufferReferenceAlignment();
 
     builder.accessChainStore(rvalue,
-                             spv::MemoryAccessMask(TranslateMemoryAccess(coherentFlags) & ~spv::MemoryAccessMakePointerVisibleKHRMask),
+                             spv::MemoryAccessMask(TranslateMemoryAccess(coherentFlags) &
+                                ~spv::MemoryAccessMakePointerVisibleKHRMask),
                              TranslateMemoryScope(coherentFlags), alignment);
 }
 
@@ -3981,7 +4067,8 @@ void TGlslangToSpvTraverser::multiTypeStore(const glslang::TType& type, spv::Id
             // set up the target storage
             builder.clearAccessChain();
             builder.setAccessChainLValue(lValue);
-            builder.accessChainPush(builder.makeIntConstant(index), TranslateCoherent(type), type.getBufferReferenceAlignment());
+            builder.accessChainPush(builder.makeIntConstant(index), TranslateCoherent(type),
+                type.getBufferReferenceAlignment());
 
             // store the member
             multiTypeStore(glslangElementType, elementRValue);
@@ -4001,7 +4088,8 @@ void TGlslangToSpvTraverser::multiTypeStore(const glslang::TType& type, spv::Id
             // set up the target storage
             builder.clearAccessChain();
             builder.setAccessChainLValue(lValue);
-            builder.accessChainPush(builder.makeIntConstant(m), TranslateCoherent(type), type.getBufferReferenceAlignment());
+            builder.accessChainPush(builder.makeIntConstant(m), TranslateCoherent(type),
+                type.getBufferReferenceAlignment());
 
             // store the member
             multiTypeStore(glslangMemberType, memberRValue);
@@ -4036,18 +4124,21 @@ glslang::TLayoutPacking TGlslangToSpvTraverser::getExplicitLayout(const glslang:
 }
 
 // Given an array type, returns the integer stride required for that array
-int TGlslangToSpvTraverser::getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout)
+int TGlslangToSpvTraverser::getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking explicitLayout,
+    glslang::TLayoutMatrix matrixLayout)
 {
     int size;
     int stride;
-    glslangIntermediate->getMemberAlignment(arrayType, size, stride, explicitLayout, matrixLayout == glslang::ElmRowMajor);
+    glslangIntermediate->getMemberAlignment(arrayType, size, stride, explicitLayout,
+        matrixLayout == glslang::ElmRowMajor);
 
     return stride;
 }
 
 // Given a matrix type, or array (of array) of matrixes type, returns the integer stride required for that matrix
 // when used as a member of an interface block
-int TGlslangToSpvTraverser::getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout)
+int TGlslangToSpvTraverser::getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking explicitLayout,
+    glslang::TLayoutMatrix matrixLayout)
 {
     glslang::TType elementType;
     elementType.shallowCopy(matrixType);
@@ -4055,7 +4146,8 @@ int TGlslangToSpvTraverser::getMatrixStride(const glslang::TType& matrixType, gl
 
     int size;
     int stride;
-    glslangIntermediate->getMemberAlignment(elementType, size, stride, explicitLayout, matrixLayout == glslang::ElmRowMajor);
+    glslangIntermediate->getMemberAlignment(elementType, size, stride, explicitLayout,
+        matrixLayout == glslang::ElmRowMajor);
 
     return stride;
 }
@@ -4066,8 +4158,8 @@ int TGlslangToSpvTraverser::getMatrixStride(const glslang::TType& matrixType, gl
 // 'currentOffset' should be passed in already initialized, ready to modify, and reflecting
 // the migration of data from nextOffset -> currentOffset.  It should be -1 on the first call.
 // -1 means a non-forced member offset (no decoration needed).
-void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& structType, const glslang::TType& memberType, int& currentOffset, int& nextOffset,
-                                                glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout)
+void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& structType, const glslang::TType& memberType,
+    int& currentOffset, int& nextOffset, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout)
 {
     // this will get a positive value when deemed necessary
     nextOffset = -1;
@@ -4097,7 +4189,8 @@ void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& structType
 
     int memberSize;
     int dummyStride;
-    int memberAlignment = glslangIntermediate->getMemberAlignment(memberType, memberSize, dummyStride, explicitLayout, matrixLayout == glslang::ElmRowMajor);
+    int memberAlignment = glslangIntermediate->getMemberAlignment(memberType, memberSize, dummyStride, explicitLayout,
+        matrixLayout == glslang::ElmRowMajor);
 
     // Adjust alignment for HLSL rules
     // TODO: make this consistent in early phases of code:
@@ -4116,7 +4209,8 @@ void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& structType
     glslang::RoundToPow2(currentOffset, memberAlignment);
 
     // Bump up to vec4 if there is a bad straddle
-    if (explicitLayout != glslang::ElpScalar && glslangIntermediate->improperStraddle(memberType, memberSize, currentOffset))
+    if (explicitLayout != glslang::ElpScalar && glslangIntermediate->improperStraddle(memberType, memberSize,
+        currentOffset))
         glslang::RoundToPow2(currentOffset, 16);
 
     nextOffset = currentOffset + memberSize;
@@ -4188,7 +4282,8 @@ bool TGlslangToSpvTraverser::originalParam(glslang::TStorageQualifier qualifier,
 // Make all the functions, skeletally, without actually visiting their bodies.
 void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslFunctions)
 {
-    const auto getParamDecorations = [&](std::vector<spv::Decoration>& decorations, const glslang::TType& type, bool useVulkanMemoryModel) {
+    const auto getParamDecorations = [&](std::vector<spv::Decoration>& decorations, const glslang::TType& type,
+        bool useVulkanMemoryModel) {
         spv::Decoration paramPrecision = TranslatePrecisionDecoration(type);
         if (paramPrecision != spv::NoPrecision)
             decorations.push_back(paramPrecision);
@@ -4286,7 +4381,8 @@ void TGlslangToSpvTraverser::makeGlobalInitializers(const glslang::TIntermSequen
     builder.setBuildPoint(shaderEntry->getLastBlock());
     for (int i = 0; i < (int)initializers.size(); ++i) {
         glslang::TIntermAggregate* initializer = initializers[i]->getAsAggregate();
-        if (initializer && initializer->getOp() != glslang::EOpFunction && initializer->getOp() != glslang::EOpLinkerObjects) {
+        if (initializer && initializer->getOp() != glslang::EOpFunction && initializer->getOp() !=
+            glslang::EOpLinkerObjects) {
 
             // We're on a top-level node that's not a function.  Treat as an initializer, whose
             // code goes into the beginning of the entry point.
@@ -4314,7 +4410,8 @@ void TGlslangToSpvTraverser::handleFunctionEntry(const glslang::TIntermAggregate
     builder.setBuildPoint(functionBlock);
 }
 
-void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate& node, std::vector<spv::Id>& arguments, spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags)
+void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate& node, std::vector<spv::Id>& arguments,
+    spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags)
 {
     const glslang::TIntermSequence& glslangArguments = node.getSequence();
 
@@ -4327,7 +4424,8 @@ void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate&
         sampler = glslangArguments[0]->getAsTyped()->getType().getSampler();
         cubeCompare = sampler.dim == glslang::EsdCube && sampler.arrayed && sampler.shadow;
 #ifndef GLSLANG_WEB
-        f16ShadowCompare = sampler.shadow && glslangArguments[1]->getAsTyped()->getType().getBasicType() == glslang::EbtFloat16;
+        f16ShadowCompare = sampler.shadow &&
+            glslangArguments[1]->getAsTyped()->getType().getBasicType() == glslang::EbtFloat16;
 #endif
     }
 
@@ -4703,7 +4801,8 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
                 operands.push_back(imageOperand);
             }
             if (mask & spv::ImageOperandsMakeTexelVisibleKHRMask) {
-                spv::IdImmediate imageOperand = { true, builder.makeUintConstant(TranslateMemoryScope(TranslateCoherent(imageType))) };
+                spv::IdImmediate imageOperand = { true, builder.makeUintConstant(TranslateMemoryScope(
+                    TranslateCoherent(imageType))) };
                 operands.push_back(imageOperand);
             }
 
@@ -4736,13 +4835,17 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
                 resultTypeId = builder.makePointer(spv::StorageClassImage, resultType());
             }
             spv::Id pointer = builder.createOp(spv::OpImageTexelPointer, resultTypeId, operands);
+            if (imageType.getQualifier().nonUniform) {
+                builder.addDecoration(pointer, spv::DecorationNonUniformEXT);
+            }
 
             std::vector<spv::Id> operands;
             operands.push_back(pointer);
             for (; opIt != arguments.end(); ++opIt)
                 operands.push_back(*opIt);
 
-            return createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType(), lvalueCoherentFlags);
+            return createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType(),
+                lvalueCoherentFlags);
         }
     }
 
@@ -4767,7 +4870,8 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
             std::vector<spv::Id> comps;
             comps.push_back(zero);
             comps.push_back(zero);
-            operands.push_back(builder.makeCompositeConstant(builder.makeVectorType(builder.makeIntType(32), 2), comps));
+            operands.push_back(builder.makeCompositeConstant(
+                builder.makeVectorType(builder.makeIntType(32), 2), comps));
         }
 
         for (; opIt != arguments.end(); ++opIt)
@@ -4856,7 +4960,8 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
         else
             dRefComp = builder.getNumComponents(params.coords) - 1;
         indexes.push_back(dRefComp);
-        params.Dref = builder.createCompositeExtract(params.coords, builder.getScalarTypeId(builder.getTypeId(params.coords)), indexes);
+        params.Dref = builder.createCompositeExtract(params.coords,
+            builder.getScalarTypeId(builder.getTypeId(params.coords)), indexes);
     }
 
     // lod
@@ -4981,7 +5086,8 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
             flags.clear();
 
             builder.accessChainPush(builder.makeIntConstant(i), flags, 0);
-            builder.accessChainStore(builder.createCompositeExtract(res, builder.getContainedTypeId(resType, i+1), i+1));
+            builder.accessChainStore(builder.createCompositeExtract(res, builder.getContainedTypeId(resType, i+1),
+                i+1));
         }
         return builder.createCompositeExtract(res, resultType(), 0);
     }
@@ -5004,10 +5110,9 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
         // copy the projective coordinate if we have to
         if (projTargetComp != projSourceComp) {
             spv::Id projComp = builder.createCompositeExtract(params.coords,
-                                                              builder.getScalarTypeId(builder.getTypeId(params.coords)),
-                                                              projSourceComp);
+                                    builder.getScalarTypeId(builder.getTypeId(params.coords)), projSourceComp);
             params.coords = builder.createCompositeInsert(projComp, params.coords,
-                                                          builder.getTypeId(params.coords), projTargetComp);
+                                    builder.getTypeId(params.coords), projTargetComp);
         }
     }
 
@@ -5087,7 +5192,8 @@ spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAgg
             ++lValueCount;
         } else if (writableParam(qualifiers[a])) {
             // need space to hold the copy
-            arg = builder.createVariable(spv::StorageClassFunction, builder.getContainedTypeId(function->getParamType(a)), "param");
+            arg = builder.createVariable(spv::StorageClassFunction,
+                builder.getContainedTypeId(function->getParamType(a)), "param");
             if (qualifiers[a] == glslang::EvqIn || qualifiers[a] == glslang::EvqInOut) {
                 // need to copy the input into output space
                 builder.setAccessChain(lValues[lValueCount]);
@@ -5502,7 +5608,7 @@ spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, OpDecora
 }
 
 spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, OpDecorations& decorations, spv::Id typeId,
-                                                     spv::Id operand, glslang::TBasicType typeProxy, const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags)
+    spv::Id operand, glslang::TBasicType typeProxy, const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags)
 {
     spv::Op unaryOp = spv::OpNop;
     int extBuiltins = -1;
@@ -6395,7 +6501,9 @@ spv::Id TGlslangToSpvTraverser::makeSmearedConstant(spv::Id constant, int vector
 }
 
 // For glslang ops that map to SPV atomic opCodes
-spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv::Decoration /*precision*/, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy, const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags)
+spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv::Decoration /*precision*/,
+    spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy,
+    const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags)
 {
     spv::Op opCode = spv::OpNop;
 
@@ -6411,12 +6519,14 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv
     case glslang::EOpAtomicMin:
     case glslang::EOpImageAtomicMin:
     case glslang::EOpAtomicCounterMin:
-        opCode = (typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64) ? spv::OpAtomicUMin : spv::OpAtomicSMin;
+        opCode = (typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64) ?
+            spv::OpAtomicUMin : spv::OpAtomicSMin;
         break;
     case glslang::EOpAtomicMax:
     case glslang::EOpImageAtomicMax:
     case glslang::EOpAtomicCounterMax:
-        opCode = (typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64) ? spv::OpAtomicUMax : spv::OpAtomicSMax;
+        opCode = (typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64) ?
+            spv::OpAtomicUMax : spv::OpAtomicSMax;
         break;
     case glslang::EOpAtomicAnd:
     case glslang::EOpImageAtomicAnd:
@@ -6481,7 +6591,8 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv
         scopeId = builder.makeUintConstant(spv::ScopeDevice);
     }
     // semantics default to relaxed 
-    spv::Id semanticsId = builder.makeUintConstant(lvalueCoherentFlags.isVolatile() && glslangIntermediate->usingVulkanMemoryModel() ?
+    spv::Id semanticsId = builder.makeUintConstant(lvalueCoherentFlags.isVolatile() &&
+        glslangIntermediate->usingVulkanMemoryModel() ?
                                                     spv::MemorySemanticsVolatileMask :
                                                     spv::MemorySemanticsMaskNone);
     spv::Id semanticsId2 = semanticsId;
@@ -6494,20 +6605,24 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv
         valueId = operands[2];
         if (operands.size() > 3) {
             scopeId = operands[3];
-            semanticsId = builder.makeUintConstant(builder.getConstantScalar(operands[4]) | builder.getConstantScalar(operands[5]));
-            semanticsId2 = builder.makeUintConstant(builder.getConstantScalar(operands[6]) | builder.getConstantScalar(operands[7]));
+            semanticsId = builder.makeUintConstant(
+                builder.getConstantScalar(operands[4]) | builder.getConstantScalar(operands[5]));
+            semanticsId2 = builder.makeUintConstant(
+                builder.getConstantScalar(operands[6]) | builder.getConstantScalar(operands[7]));
         }
     } else if (opCode == spv::OpAtomicLoad) {
         if (operands.size() > 1) {
             scopeId = operands[1];
-            semanticsId = builder.makeUintConstant(builder.getConstantScalar(operands[2]) | builder.getConstantScalar(operands[3]));
+            semanticsId = builder.makeUintConstant(
+                builder.getConstantScalar(operands[2]) | builder.getConstantScalar(operands[3]));
         }
     } else {
         // atomic store or RMW
         valueId = operands[1];
         if (operands.size() > 2) {
             scopeId = operands[2];
-            semanticsId = builder.makeUintConstant(builder.getConstantScalar(operands[3]) | builder.getConstantScalar(operands[4]));
+            semanticsId = builder.makeUintConstant
+                (builder.getConstantScalar(operands[3]) | builder.getConstantScalar(operands[4]));
         }
     }
 
@@ -6552,7 +6667,8 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv
 }
 
 // Create group invocation operations.
-spv::Id TGlslangToSpvTraverser::createInvocationsOperation(glslang::TOperator op, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy)
+spv::Id TGlslangToSpvTraverser::createInvocationsOperation(glslang::TOperator op, spv::Id typeId,
+    std::vector<spv::Id>& operands, glslang::TBasicType typeProxy)
 {
     bool isUnsigned = isTypeUnsignedInt(typeProxy);
     bool isFloat = isTypeFloat(typeProxy);
@@ -6766,8 +6882,10 @@ spv::Id TGlslangToSpvTraverser::CreateInvocationsVectorOperation(spv::Op op, spv
            op == spv::OpGroupFMax || op == spv::OpGroupUMax || op == spv::OpGroupSMax ||
            op == spv::OpGroupFAdd || op == spv::OpGroupIAdd || op == spv::OpGroupBroadcast ||
            op == spv::OpSubgroupReadInvocationKHR ||
-           op == spv::OpGroupFMinNonUniformAMD || op == spv::OpGroupUMinNonUniformAMD || op == spv::OpGroupSMinNonUniformAMD ||
-           op == spv::OpGroupFMaxNonUniformAMD || op == spv::OpGroupUMaxNonUniformAMD || op == spv::OpGroupSMaxNonUniformAMD ||
+           op == spv::OpGroupFMinNonUniformAMD || op == spv::OpGroupUMinNonUniformAMD ||
+           op == spv::OpGroupSMinNonUniformAMD ||
+           op == spv::OpGroupFMaxNonUniformAMD || op == spv::OpGroupUMaxNonUniformAMD ||
+           op == spv::OpGroupSMaxNonUniformAMD ||
            op == spv::OpGroupFAddNonUniformAMD || op == spv::OpGroupIAddNonUniformAMD);
 
     // Handle group invocation operations scalar by scalar.
@@ -7156,7 +7274,8 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s
     return builder.createOp(opCode, typeId, spvGroupOperands);
 }
 
-spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy)
+spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::Decoration precision,
+    spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy)
 {
     bool isUnsigned = isTypeUnsignedInt(typeProxy);
     bool isFloat = isTypeFloat(typeProxy);
@@ -7258,14 +7377,16 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::
             unsigned int executionScope = builder.getConstantScalar(operands[0]);
             unsigned int memoryScope = builder.getConstantScalar(operands[1]);
             unsigned int semantics = builder.getConstantScalar(operands[2]) | builder.getConstantScalar(operands[3]);
-            builder.createControlBarrier((spv::Scope)executionScope, (spv::Scope)memoryScope, (spv::MemorySemanticsMask)semantics);
+            builder.createControlBarrier((spv::Scope)executionScope, (spv::Scope)memoryScope,
+                (spv::MemorySemanticsMask)semantics);
             if (semantics & (spv::MemorySemanticsMakeAvailableKHRMask |
                              spv::MemorySemanticsMakeVisibleKHRMask |
                              spv::MemorySemanticsOutputMemoryKHRMask |
                              spv::MemorySemanticsVolatileMask)) {
                 builder.addCapability(spv::CapabilityVulkanMemoryModelKHR);
             }
-            if (glslangIntermediate->usingVulkanMemoryModel() && (executionScope == spv::ScopeDevice || memoryScope == spv::ScopeDevice)) {
+            if (glslangIntermediate->usingVulkanMemoryModel() && (executionScope == spv::ScopeDevice ||
+                memoryScope == spv::ScopeDevice)) {
                 builder.addCapability(spv::CapabilityVulkanMemoryModelDeviceScopeKHR);
             }
             return 0;
@@ -7348,7 +7469,8 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::
             if (builder.getNumComponents(operands[0]) == 1)
                 frexpIntType = builder.makeIntegerType(width, true);
             else
-                frexpIntType = builder.makeVectorType(builder.makeIntegerType(width, true), builder.getNumComponents(operands[0]));
+                frexpIntType = builder.makeVectorType(builder.makeIntegerType(width, true),
+                    builder.getNumComponents(operands[0]));
             typeId = builder.makeStructResultType(typeId0, frexpIntType);
             consumedOperands = 1;
         }
@@ -7558,7 +7680,8 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::
 spv::Id TGlslangToSpvTraverser::createNoArgOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId)
 {
     // GLSL memory barriers use queuefamily scope in new model, device scope in old model
-    spv::Scope memoryBarrierScope = glslangIntermediate->usingVulkanMemoryModel() ? spv::ScopeQueueFamilyKHR : spv::ScopeDevice;
+    spv::Scope memoryBarrierScope = glslangIntermediate->usingVulkanMemoryModel() ?
+        spv::ScopeQueueFamilyKHR : spv::ScopeDevice;
 
     switch (op) {
     case glslang::EOpBarrier:
@@ -7787,7 +7910,8 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
 #ifndef GLSLANG_WEB
     if (symbol->getType().isImage()) {
         std::vector<spv::Decoration> memory;
-        TranslateMemoryDecoration(symbol->getType().getQualifier(), memory, glslangIntermediate->usingVulkanMemoryModel());
+        TranslateMemoryDecoration(symbol->getType().getQualifier(), memory,
+            glslangIntermediate->usingVulkanMemoryModel());
         for (unsigned int i = 0; i < memory.size(); ++i)
             builder.addDecoration(id, memory[i]);
     }
@@ -7841,7 +7965,8 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
     }
 
     if (symbol->isReference()) {
-        builder.addDecoration(id, symbol->getType().getQualifier().restrict ? spv::DecorationRestrictPointerEXT : spv::DecorationAliasedPointerEXT);
+        builder.addDecoration(id, symbol->getType().getQualifier().restrict ?
+            spv::DecorationRestrictPointerEXT : spv::DecorationAliasedPointerEXT);
     }
 #endif
 
@@ -7903,8 +8028,9 @@ spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TIntermTyped& n
         // hand off to the non-spec-constant path
         assert(node.getAsConstantUnion() != nullptr || node.getAsSymbolNode() != nullptr);
         int nextConst = 0;
-        return createSpvConstantFromConstUnionArray(node.getType(), node.getAsConstantUnion() ? node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(),
-                                 nextConst, false);
+        return createSpvConstantFromConstUnionArray(node.getType(), node.getAsConstantUnion() ?
+            node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(),
+            nextConst, false);
     }
 
     // We now know we have a specialization constant to build
@@ -7957,7 +8083,8 @@ spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TIntermTyped& n
 // If there are not enough elements present in 'consts', 0 will be substituted;
 // an empty 'consts' can be used to create a fully zeroed SPIR-V constant.
 //
-spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glslang::TType& glslangType, const glslang::TConstUnionArray& consts, int& nextConst, bool specConstant)
+spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glslang::TType& glslangType,
+    const glslang::TConstUnionArray& consts, int& nextConst, bool specConstant)
 {
     // vector of constants for SPIR-V
     std::vector<spv::Id> spvConsts;
@@ -8075,6 +8202,9 @@ spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glsla
             scalar = builder.createUnaryOp(spv::OpBitcast, typeId, scalar);
             break;
 #endif
+        case glslang::EbtString:
+            scalar = builder.getStringId(consts[nextConst].getSConst()->c_str());
+            break;
         default:
             assert(0);
             break;
@@ -8175,7 +8305,8 @@ bool TGlslangToSpvTraverser::isTrivial(const glslang::TIntermTyped* node)
 
 // Emit short-circuiting code, where 'right' is never evaluated unless
 // the left side is true (for &&) or false (for ||).
-spv::Id TGlslangToSpvTraverser::createShortCircuit(glslang::TOperator op, glslang::TIntermTyped& left, glslang::TIntermTyped& right)
+spv::Id TGlslangToSpvTraverser::createShortCircuit(glslang::TOperator op, glslang::TIntermTyped& left,
+    glslang::TIntermTyped& right)
 {
     spv::Id boolTypeId = builder.makeBoolType();
 

+ 50 - 0
3rdparty/glslang/SPIRV/NonSemanticDebugPrintf.h

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

+ 29 - 12
3rdparty/glslang/SPIRV/SpvBuilder.cpp

@@ -496,7 +496,8 @@ Id Builder::makeFunctionType(Id returnType, const std::vector<Id>& paramTypes)
     return type->getResultId();
 }
 
-Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format)
+Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, bool ms, unsigned sampled,
+    ImageFormat format)
 {
     assert(sampled == 1 || sampled == 2);
 
@@ -1270,7 +1271,8 @@ Function* Builder::makeEntryPoint(const char* entryPoint)
 
 // Comments in header
 Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const char* name,
-                                     const std::vector<Id>& paramTypes, const std::vector<std::vector<Decoration>>& decorations, Block **entry)
+                                     const std::vector<Id>& paramTypes,
+                                     const std::vector<std::vector<Decoration>>& decorations, Block **entry)
 {
     // Make the function and initial instructions in it
     Id typeId = makeFunctionType(returnType, paramTypes);
@@ -1373,7 +1375,8 @@ Id Builder::createUndefined(Id type)
 }
 
 // av/vis/nonprivate are unnecessary and illegal for some storage classes.
-spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) const
+spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc)
+    const
 {
     switch (sc) {
     case spv::StorageClassUniform:
@@ -1392,7 +1395,8 @@ spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAc
 }
 
 // Comments in header
-void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
+void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope,
+    unsigned int alignment)
 {
     Instruction* store = new Instruction(OpStore);
     store->addIdOperand(lValue);
@@ -1495,7 +1499,8 @@ Id Builder::createCompositeExtract(Id composite, Id typeId, unsigned index)
     // Generate code for spec constants if in spec constant operation
     // generation mode.
     if (generatingOpCodeForSpecConst) {
-        return createSpecConstantOp(OpCompositeExtract, typeId, std::vector<Id>(1, composite), std::vector<Id>(1, index));
+        return createSpecConstantOp(OpCompositeExtract, typeId, std::vector<Id>(1, composite),
+            std::vector<Id>(1, index));
     }
     Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract);
     extract->addIdOperand(composite);
@@ -1697,7 +1702,8 @@ Id Builder::createOp(Op opCode, Id typeId, const std::vector<IdImmediate>& opera
     return op->getResultId();
 }
 
-Id Builder::createSpecConstantOp(Op opCode, Id typeId, const std::vector<Id>& operands, const std::vector<unsigned>& literals)
+Id Builder::createSpecConstantOp(Op opCode, Id typeId, const std::vector<Id>& operands,
+    const std::vector<unsigned>& literals)
 {
     Instruction* op = new Instruction(getUniqueId(), typeId, OpSpecConstantOp);
     op->addImmediateOperand((unsigned) opCode);
@@ -2187,7 +2193,8 @@ Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, b
         if (constituent == 0)
             resultId = subResultId;
         else
-            resultId = setPrecision(createBinOp(equal ? OpLogicalAnd : OpLogicalOr, boolType, resultId, subResultId), precision);
+            resultId = setPrecision(createBinOp(equal ? OpLogicalAnd : OpLogicalOr, boolType, resultId, subResultId),
+                                    precision);
     }
 
     return resultId;
@@ -2196,7 +2203,8 @@ Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, b
 // OpCompositeConstruct
 Id Builder::createCompositeConstruct(Id typeId, const std::vector<Id>& constituents)
 {
-    assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 && getNumTypeConstituents(typeId) == (int)constituents.size()));
+    assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 &&
+           getNumTypeConstituents(typeId) == (int)constituents.size()));
 
     if (generatingOpCodeForSpecConst) {
         // Sometime, even in spec-constant-op mode, the constant composite to be
@@ -2609,7 +2617,8 @@ void Builder::clearAccessChain()
 }
 
 // Comments in header
-void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment)
+void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType,
+    AccessChain::CoherentFlags coherentFlags, unsigned int alignment)
 {
     accessChain.coherentFlags |= coherentFlags;
     accessChain.alignment |= alignment;
@@ -2663,7 +2672,8 @@ void Builder::accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess, sp
 }
 
 // Comments in header
-Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resultType, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
+Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resultType,
+    spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
 {
     Id id;
 
@@ -2721,7 +2731,13 @@ Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resu
         }
 
         // load through the access chain
-        id = createLoad(collapseAccessChain(), memoryAccess, scope, alignment);
+        id = collapseAccessChain();
+        // Apply nonuniform both to the access chain and the loaded value.
+        // Buffer accesses need the access chain decorated, and this is where
+        // loaded image types get decorated. TODO: This should maybe move to
+        // createImageTextureFunctionCall.
+        addDecoration(id, nonUniform);
+        id = createLoad(id, memoryAccess, scope, alignment);
         setPrecision(id, precision);
         addDecoration(id, nonUniform);
     }
@@ -3075,7 +3091,8 @@ void Builder::dumpSourceInstructions(std::vector<unsigned int>& out) const
         dumpSourceInstructions(iItr->first, *iItr->second, out);
 }
 
-void Builder::dumpInstructions(std::vector<unsigned int>& out, const std::vector<std::unique_ptr<Instruction> >& instructions) const
+void Builder::dumpInstructions(std::vector<unsigned int>& out,
+    const std::vector<std::unique_ptr<Instruction> >& instructions) const
 {
     for (int i = 0; i < (int)instructions.size(); ++i) {
         instructions[i]->dump(out);

+ 72 - 34
3rdparty/glslang/SPIRV/SpvBuilder.h

@@ -1,6 +1,6 @@
 //
 // Copyright (C) 2014-2015 LunarG, Inc.
-// Copyright (C) 2015-2018 Google, Inc.
+// Copyright (C) 2015-2020 Google, Inc.
 // Copyright (C) 2017 ARM Limited.
 //
 // All rights reserved.
@@ -94,6 +94,7 @@ public:
         const char* file_c_str = str.c_str();
         fileString->addStringOperand(file_c_str);
         strings.push_back(std::unique_ptr<Instruction>(fileString));
+        module.mapInstruction(fileString);
         stringIds[file_c_str] = strId;
         return strId;
     }
@@ -196,7 +197,8 @@ public:
     Id getContainedTypeId(Id typeId) const;
     Id getContainedTypeId(Id typeId, int) const;
     StorageClass getTypeStorageClass(Id typeId) const { return module.getStorageClass(typeId); }
-    ImageFormat getImageTypeFormat(Id typeId) const { return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); }
+    ImageFormat getImageTypeFormat(Id typeId) const
+        { return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); }
 
     bool isPointer(Id resultId)      const { return isPointerType(getTypeId(resultId)); }
     bool isScalar(Id resultId)       const { return isScalarType(getTypeId(resultId)); }
@@ -206,12 +208,17 @@ public:
     bool isAggregate(Id resultId)    const { return isAggregateType(getTypeId(resultId)); }
     bool isSampledImage(Id resultId) const { return isSampledImageType(getTypeId(resultId)); }
 
-    bool isBoolType(Id typeId)               { return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); }
-    bool isIntType(Id typeId)          const { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) != 0; }
-    bool isUintType(Id typeId)         const { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; }
+    bool isBoolType(Id typeId)
+        { return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); }
+    bool isIntType(Id typeId)          const
+        { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) != 0; }
+    bool isUintType(Id typeId)         const
+        { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; }
     bool isFloatType(Id typeId)        const { return getTypeClass(typeId) == OpTypeFloat; }
     bool isPointerType(Id typeId)      const { return getTypeClass(typeId) == OpTypePointer; }
-    bool isScalarType(Id typeId)       const { return getTypeClass(typeId) == OpTypeFloat  || getTypeClass(typeId) == OpTypeInt || getTypeClass(typeId) == OpTypeBool; }
+    bool isScalarType(Id typeId)       const
+        { return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt ||
+          getTypeClass(typeId) == OpTypeBool; }
     bool isVectorType(Id typeId)       const { return getTypeClass(typeId) == OpTypeVector; }
     bool isMatrixType(Id typeId)       const { return getTypeClass(typeId) == OpTypeMatrix; }
     bool isStructType(Id typeId)       const { return getTypeClass(typeId) == OpTypeStruct; }
@@ -221,7 +228,8 @@ public:
 #else
     bool isCooperativeMatrixType(Id typeId)const { return getTypeClass(typeId) == OpTypeCooperativeMatrixNV; }
 #endif
-    bool isAggregateType(Id typeId)    const { return isArrayType(typeId) || isStructType(typeId) || isCooperativeMatrixType(typeId); }
+    bool isAggregateType(Id typeId)    const
+        { return isArrayType(typeId) || isStructType(typeId) || isCooperativeMatrixType(typeId); }
     bool isImageType(Id typeId)        const { return getTypeClass(typeId) == OpTypeImage; }
     bool isSamplerType(Id typeId)      const { return getTypeClass(typeId) == OpTypeSampler; }
     bool isSampledImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampledImage; }
@@ -233,7 +241,8 @@ public:
     bool isConstant(Id resultId) const { return isConstantOpCode(getOpCode(resultId)); }
     bool isConstantScalar(Id resultId) const { return getOpCode(resultId) == OpConstant; }
     bool isSpecConstant(Id resultId) const { return isSpecConstantOpCode(getOpCode(resultId)); }
-    unsigned int getConstantScalar(Id resultId) const { return module.getInstruction(resultId)->getImmediateOperand(0); }
+    unsigned int getConstantScalar(Id resultId) const
+        { return module.getInstruction(resultId)->getImmediateOperand(0); }
     StorageClass getStorageClass(Id resultId) const { return getTypeStorageClass(getTypeId(resultId)); }
 
     int getScalarTypeWidth(Id typeId) const
@@ -275,14 +284,22 @@ public:
 
     // For making new constants (will return old constant if the requested one was already made).
     Id makeBoolConstant(bool b, bool specConstant = false);
-    Id makeInt8Constant(int i, bool specConstant = false)        { return makeIntConstant(makeIntType(8),  (unsigned)i, specConstant); }
-    Id makeUint8Constant(unsigned u, bool specConstant = false)  { return makeIntConstant(makeUintType(8),           u, specConstant); }
-    Id makeInt16Constant(int i, bool specConstant = false)       { return makeIntConstant(makeIntType(16),  (unsigned)i, specConstant); }
-    Id makeUint16Constant(unsigned u, bool specConstant = false) { return makeIntConstant(makeUintType(16),           u, specConstant); }
-    Id makeIntConstant(int i, bool specConstant = false)         { return makeIntConstant(makeIntType(32),  (unsigned)i, specConstant); }
-    Id makeUintConstant(unsigned u, bool specConstant = false)   { return makeIntConstant(makeUintType(32),           u, specConstant); }
-    Id makeInt64Constant(long long i, bool specConstant = false)            { return makeInt64Constant(makeIntType(64),  (unsigned long long)i, specConstant); }
-    Id makeUint64Constant(unsigned long long u, bool specConstant = false)  { return makeInt64Constant(makeUintType(64),                     u, specConstant); }
+    Id makeInt8Constant(int i, bool specConstant = false)
+        { return makeIntConstant(makeIntType(8),  (unsigned)i, specConstant); }
+    Id makeUint8Constant(unsigned u, bool specConstant = false)
+        { return makeIntConstant(makeUintType(8),           u, specConstant); }
+    Id makeInt16Constant(int i, bool specConstant = false)
+        { return makeIntConstant(makeIntType(16),  (unsigned)i, specConstant); }
+    Id makeUint16Constant(unsigned u, bool specConstant = false)
+        { return makeIntConstant(makeUintType(16),           u, specConstant); }
+    Id makeIntConstant(int i, bool specConstant = false)
+        { return makeIntConstant(makeIntType(32),  (unsigned)i, specConstant); }
+    Id makeUintConstant(unsigned u, bool specConstant = false)
+        { return makeIntConstant(makeUintType(32),           u, specConstant); }
+    Id makeInt64Constant(long long i, bool specConstant = false)
+        { return makeInt64Constant(makeIntType(64),  (unsigned long long)i, specConstant); }
+    Id makeUint64Constant(unsigned long long u, bool specConstant = false)
+        { return makeInt64Constant(makeUintType(64),                     u, specConstant); }
     Id makeFloatConstant(float f, bool specConstant = false);
     Id makeDoubleConstant(double d, bool specConstant = false);
     Id makeFloat16Constant(float f16, bool specConstant = false);
@@ -313,8 +330,8 @@ public:
     // Make a shader-style function, and create its entry block if entry is non-zero.
     // Return the function, pass back the entry.
     // The returned pointer is only valid for the lifetime of this builder.
-    Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name, const std::vector<Id>& paramTypes,
-                                const std::vector<std::vector<Decoration>>& precisions, Block **entry = 0);
+    Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name,
+        const std::vector<Id>& paramTypes, const std::vector<std::vector<Decoration>>& precisions, Block **entry = 0);
 
     // Create a return. An 'implicit' return is one not appearing in the source
     // code.  In the case of an implicit return, no post-return block is inserted.
@@ -333,10 +350,12 @@ public:
     Id createUndefined(Id type);
 
     // Store into an Id and return the l-value
-    void createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
+    void createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone,
+        spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
 
     // Load from an Id and return it
-    Id createLoad(Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
+    Id createLoad(Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone,
+        spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
 
     // Create an OpAccessChain instruction
     Id createAccessChain(StorageClass, Id base, const std::vector<Id>& offsets);
@@ -495,7 +514,7 @@ public:
     // recursion stack can hold the memory for it.
     //
     void makeSwitch(Id condition, unsigned int control, int numSegments, const std::vector<int>& caseValues,
-                    const std::vector<int>& valueToSegment, int defaultSegment, std::vector<Block*>& segmentBB); // return argument
+                    const std::vector<int>& valueToSegment, int defaultSegment, std::vector<Block*>& segmentBB);
 
     // Add a branch to the innermost switch's merge block.
     void addSwitchBreak();
@@ -569,10 +588,13 @@ public:
         std::vector<Id> indexChain;
         Id instr;                      // cache the instruction that generates this access chain
         std::vector<unsigned> swizzle; // each std::vector element selects the next GLSL component number
-        Id component;                  // a dynamic component index, can coexist with a swizzle, done after the swizzle, NoResult if not present
-        Id preSwizzleBaseType;         // dereferenced type, before swizzle or component is applied; NoType unless a swizzle or component is present
+        Id component;                  // a dynamic component index, can coexist with a swizzle,
+                                       // done after the swizzle, NoResult if not present
+        Id preSwizzleBaseType;         // dereferenced type, before swizzle or component is applied;
+                                       // NoType unless a swizzle or component is present
         bool isRValue;                 // true if 'base' is an r-value, otherwise, base is an l-value
-        unsigned int alignment;        // bitwise OR of alignment values passed in. Accumulates worst alignment. Only tracks base and (optional) component selection alignment.
+        unsigned int alignment;        // bitwise OR of alignment values passed in. Accumulates worst alignment.
+                                       // Only tracks base and (optional) component selection alignment.
 
         // Accumulate whether anything in the chain of structures has coherent decorations.
         struct CoherentFlags {
@@ -655,11 +677,13 @@ public:
     }
 
     // push new swizzle onto the end of any existing swizzle, merging into a single swizzle
-    void accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment);
+    void accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType,
+        AccessChain::CoherentFlags coherentFlags, unsigned int alignment);
 
     // push a dynamic component selection onto the access chain, only applicable with a
     // non-trivial swizzle or no swizzle
-    void accessChainPushComponent(Id component, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment)
+    void accessChainPushComponent(Id component, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags,
+        unsigned int alignment)
     {
         if (accessChain.swizzle.size() != 1) {
             accessChain.component = component;
@@ -671,10 +695,18 @@ public:
     }
 
     // use accessChain and swizzle to store value
-    void accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
+    void accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone,
+        spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
 
     // use accessChain and swizzle to load an r-value
-    Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
+    Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType,
+        spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax,
+            unsigned int alignment = 0);
+
+    // Return whether or not the access chain can be represented in SPIR-V
+    // as an l-value.
+    // E.g., a[3].yx cannot be, while a[3].y and a[3].y[x] can be.
+    bool isSpvLvalue() const { return accessChain.swizzle.size() <= 1; }
 
     // get the direct pointer for an l-value
     Id accessChainGetLValue();
@@ -703,7 +735,8 @@ public:
 
     void createBranch(Block* block);
     void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock);
-    void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control, const std::vector<unsigned int>& operands);
+    void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control,
+        const std::vector<unsigned int>& operands);
 
     // Sets to generate opcode for specialization constants.
     void setToSpecConstCodeGenMode() { generatingOpCodeForSpecConst = true; }
@@ -729,7 +762,8 @@ public:
     void dumpSourceInstructions(const spv::Id fileId, const std::string& text, std::vector<unsigned int>&) const;
     void dumpInstructions(std::vector<unsigned int>&, const std::vector<std::unique_ptr<Instruction> >&) const;
     void dumpModuleProcesses(std::vector<unsigned int>&) const;
-    spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) const;
+    spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc)
+        const;
 
     unsigned int spvVersion;     // the version of SPIR-V to emit in the header
     SourceLanguage source;
@@ -764,10 +798,14 @@ public:
     std::vector<std::unique_ptr<Instruction> > externals;
     std::vector<std::unique_ptr<Function> > functions;
 
-     // not output, internally used for quick & dirty canonical (unique) creation
-    std::unordered_map<unsigned int, std::vector<Instruction*>> groupedConstants;       // map type opcodes to constant inst.
-    std::unordered_map<unsigned int, std::vector<Instruction*>> groupedStructConstants; // map struct-id to constant instructions
-    std::unordered_map<unsigned int, std::vector<Instruction*>> groupedTypes;           // map type opcodes to type instructions
+    // not output, internally used for quick & dirty canonical (unique) creation
+
+    // map type opcodes to constant inst.
+    std::unordered_map<unsigned int, std::vector<Instruction*>> groupedConstants;
+    // map struct-id to constant instructions
+    std::unordered_map<unsigned int, std::vector<Instruction*>> groupedStructConstants;
+    // map type opcodes to type instructions
+    std::unordered_map<unsigned int, std::vector<Instruction*>> groupedTypes;
 
     // stack of switches
     std::stack<Block*> switchMerges;

+ 5 - 4
3rdparty/glslang/SPIRV/SpvTools.cpp

@@ -1,6 +1,6 @@
 //
 // Copyright (C) 2014-2016 LunarG, Inc.
-// Copyright (C) 2018 Google, Inc.
+// Copyright (C) 2018-2020 Google, Inc.
 //
 // All rights reserved.
 //
@@ -130,8 +130,8 @@ void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector<
 
 // Apply the SPIRV-Tools optimizer to generated SPIR-V, for the purpose of
 // legalizing HLSL SPIR-V.
-void SpirvToolsLegalize(const glslang::TIntermediate&, std::vector<unsigned int>& spirv,
-                        spv::SpvBuildLogger*, const SpvOptions* options)
+void SpirvToolsLegalize(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
+                        spv::SpvBuildLogger* logger, const SpvOptions* options)
 {
     spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2;
 
@@ -207,7 +207,8 @@ void SpirvToolsLegalize(const glslang::TIntermediate&, std::vector<unsigned int>
     }
 
     spvtools::OptimizerOptions spvOptOptions;
-    spvOptOptions.set_run_validator(false); // The validator may run as a seperate step later on
+    optimizer.SetTargetEnv(MapToSpirvToolsEnv(intermediate.getSpv(), logger));
+    spvOptOptions.set_run_validator(false); // The validator may run as a separate step later on
     optimizer.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions);
 }
 

+ 8 - 1
3rdparty/glslang/SPIRV/disassemble.cpp

@@ -75,6 +75,7 @@ enum ExtInstSet {
     GLSLextAMDInst,
     GLSLextNVInst,
     OpenCLExtInst,
+    NonSemanticDebugPrintfExtInst,
 };
 
 // Container class for a single instance of a SPIR-V stream, with methods for disassembly.
@@ -480,8 +481,12 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
             if (opCode == OpExtInst) {
                 ExtInstSet extInstSet = GLSL450Inst;
                 const char* name = idDescriptor[stream[word - 2]].c_str();
-                if (0 == memcmp("OpenCL", name, 6)) {
+                if (strcmp("OpenCL.std", name) == 0) {
                     extInstSet = OpenCLExtInst;
+                } else if (strcmp("OpenCL.DebugInfo.100", name) == 0) {
+                    extInstSet = OpenCLExtInst;
+                } else if (strcmp("NonSemantic.DebugPrintf", name) == 0) {
+                    extInstSet = NonSemanticDebugPrintfExtInst;
                 } else if (strcmp(spv::E_SPV_AMD_shader_ballot, name) == 0 ||
                            strcmp(spv::E_SPV_AMD_shader_trinary_minmax, name) == 0 ||
                            strcmp(spv::E_SPV_AMD_shader_explicit_vertex_parameter, name) == 0 ||
@@ -505,6 +510,8 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
                 }
                 else if (extInstSet == GLSLextNVInst) {
                     out << "(" << GLSLextNVGetDebugNames(name, entrypoint) << ")";
+                } else if (extInstSet == NonSemanticDebugPrintfExtInst) {
+                    out << "(DebugPrintf)";
                 }
             }
             break;

+ 2 - 1
3rdparty/glslang/StandAlone/CMakeLists.txt

@@ -1,5 +1,6 @@
 add_library(glslang-default-resource-limits
-            ${CMAKE_CURRENT_SOURCE_DIR}/ResourceLimits.cpp)
+            ${CMAKE_CURRENT_SOURCE_DIR}/ResourceLimits.cpp
+            ${CMAKE_CURRENT_SOURCE_DIR}/resource_limits_c.cpp)
 set_property(TARGET glslang-default-resource-limits PROPERTY FOLDER glslang)
 set_property(TARGET glslang-default-resource-limits PROPERTY POSITION_INDEPENDENT_CODE ON)
 

+ 1 - 0
3rdparty/glslang/StandAlone/StandAlone.cpp

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

+ 51 - 0
3rdparty/glslang/StandAlone/resource_limits_c.cpp

@@ -0,0 +1,51 @@
+/**
+BSD 2-Clause License
+
+Copyright (c) 2020, Travis Fort
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**/
+
+#include "resource_limits_c.h"
+#include "ResourceLimits.h"
+#include <stdlib.h>
+#include <string.h>
+#include <string>
+
+const glslang_resource_t* glslang_default_resource(void)
+{
+    return reinterpret_cast<const glslang_resource_t*>(&glslang::DefaultTBuiltInResource);
+}
+
+const char* glslang_default_resource_string()
+{
+    std::string cpp_str = glslang::GetDefaultTBuiltInResourceString();
+    char* c_str = (char*)malloc(cpp_str.length() + 1);
+    strcpy(c_str, cpp_str.c_str());
+    return c_str;
+}
+
+void glslang_decode_resource_limits(glslang_resource_t* resources, char* config)
+{
+    glslang::DecodeResourceLimits(reinterpret_cast<TBuiltInResource*>(resources), config);
+}

+ 54 - 0
3rdparty/glslang/StandAlone/resource_limits_c.h

@@ -0,0 +1,54 @@
+/**
+BSD 2-Clause License
+
+Copyright (c) 2020, Travis Fort
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**/
+
+#ifndef _STAND_ALONE_RESOURCE_LIMITS_C_INCLUDED_
+#define _STAND_ALONE_RESOURCE_LIMITS_C_INCLUDED_
+
+#include "../glslang/Include/glslang_c_interface.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// These are the default resources for TBuiltInResources, used for both
+//  - parsing this string for the case where the user didn't supply one,
+//  - dumping out a template for user construction of a config file.
+const glslang_resource_t* glslang_default_resource(void);
+
+// Returns the DefaultTBuiltInResource as a human-readable string.
+// NOTE: User is responsible for freeing this string.
+const char* glslang_default_resource_string();
+
+// Decodes the resource limits from |config| to |resources|.
+void glslang_decode_resource_limits(glslang_resource_t* resources, char* config);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _STAND_ALONE_RESOURCE_LIMITS_C_INCLUDED_

+ 16 - 8
3rdparty/glslang/glslang/CInterface/glslang_c_interface.cpp

@@ -54,6 +54,8 @@ static_assert(int(GLSLANG_TEX_SAMP_TRANS_COUNT) == EShTexSampTransCount, "");
 static_assert(int(GLSLANG_MSG_COUNT) == EShMsgCount, "");
 static_assert(int(GLSLANG_REFLECTION_COUNT) == EShReflectionCount, "");
 static_assert(int(GLSLANG_PROFILE_COUNT) == EProfileCount, "");
+static_assert(sizeof(glslang_limits_t) == sizeof(TLimits), "");
+static_assert(sizeof(glslang_resource_t) == sizeof(TBuiltInResource), "");
 
 typedef struct glslang_shader_s {
     glslang::TShader* shader;
@@ -350,15 +352,19 @@ const char* glslang_shader_get_preprocessed_code(glslang_shader_t* shader)
     return shader->preprocessedGLSL.c_str();
 }
 
-int glslang_shader_preprocess(glslang_shader_t* shader, const glslang_input_t* i)
+int glslang_shader_preprocess(glslang_shader_t* shader, const glslang_input_t* input)
 {
     DirStackFileIncluder Includer;
     /* TODO: use custom callbacks if they are available in 'i->callbacks' */
     return shader->shader->preprocess(
-        /* No user-defined resources limit */
-        &glslang::DefaultTBuiltInResource, i->default_version, c_shader_profile(i->default_profile),
-        i->force_default_version_and_profile != 0, i->forward_compatible != 0,
-        (EShMessages)c_shader_messages(i->messages), &shader->preprocessedGLSL, Includer
+        reinterpret_cast<const TBuiltInResource*>(input->resource),
+        input->default_version,
+        c_shader_profile(input->default_profile),
+        input->force_default_version_and_profile != 0,
+        input->forward_compatible != 0,
+        (EShMessages)c_shader_messages(input->messages),
+        &shader->preprocessedGLSL,
+        Includer
     );
 }
 
@@ -368,9 +374,11 @@ int glslang_shader_parse(glslang_shader_t* shader, const glslang_input_t* input)
     shader->shader->setStrings(&preprocessedCStr, 1);
 
     return shader->shader->parse(
-        /* No user-defined resource limits for now */
-        &glslang::DefaultTBuiltInResource, input->default_version, input->forward_compatible != 0,
-        (EShMessages)c_shader_messages(input->messages));
+        reinterpret_cast<const TBuiltInResource*>(input->resource),
+        input->default_version,
+        input->forward_compatible != 0,
+        (EShMessages)c_shader_messages(input->messages)
+    );
 }
 
 const char* glslang_shader_get_info_log(glslang_shader_t* shader) { return shader->shader->getInfoLog(); }

+ 1 - 0
3rdparty/glslang/glslang/Include/Types.h

@@ -553,6 +553,7 @@ public:
     // having a constant_id is not sufficient: expressions have no id, but are still specConstant
     bool specConstant : 1;
     bool nonUniform   : 1;
+    bool explicitOffset   : 1;
 
 #ifdef GLSLANG_WEB
     bool isWriteOnly() const { return false; }

+ 113 - 0
3rdparty/glslang/glslang/Include/glslang_c_interface.h

@@ -33,6 +33,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef GLSLANG_C_IFACE_H_INCLUDED
 #define GLSLANG_C_IFACE_H_INCLUDED
 
+#include <stdbool.h>
 #include <stdlib.h>
 
 #include "glslang_c_shader_types.h"
@@ -40,6 +41,117 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 typedef struct glslang_shader_s glslang_shader_t;
 typedef struct glslang_program_s glslang_program_t;
 
+/* TLimits counterpart */
+typedef struct glslang_limits_s {
+    bool non_inductive_for_loops;
+    bool while_loops;
+    bool do_while_loops;
+    bool general_uniform_indexing;
+    bool general_attribute_matrix_vector_indexing;
+    bool general_varying_indexing;
+    bool general_sampler_indexing;
+    bool general_variable_indexing;
+    bool general_constant_matrix_vector_indexing;
+} glslang_limits_t;
+
+/* TBuiltInResource counterpart */
+typedef struct glslang_resource_s {
+    int max_lights;
+    int max_clip_planes;
+    int max_texture_units;
+    int max_texture_coords;
+    int max_vertex_attribs;
+    int max_vertex_uniform_components;
+    int max_varying_floats;
+    int max_vertex_texture_image_units;
+    int max_combined_texture_image_units;
+    int max_texture_image_units;
+    int max_fragment_uniform_components;
+    int max_draw_buffers;
+    int max_vertex_uniform_vectors;
+    int max_varying_vectors;
+    int max_fragment_uniform_vectors;
+    int max_vertex_output_vectors;
+    int max_fragment_input_vectors;
+    int min_program_texel_offset;
+    int max_program_texel_offset;
+    int max_clip_distances;
+    int max_compute_work_group_count_x;
+    int max_compute_work_group_count_y;
+    int max_compute_work_group_count_z;
+    int max_compute_work_group_size_x;
+    int max_compute_work_group_size_y;
+    int max_compute_work_group_size_z;
+    int max_compute_uniform_components;
+    int max_compute_texture_image_units;
+    int max_compute_image_uniforms;
+    int max_compute_atomic_counters;
+    int max_compute_atomic_counter_buffers;
+    int max_varying_components;
+    int max_vertex_output_components;
+    int max_geometry_input_components;
+    int max_geometry_output_components;
+    int max_fragment_input_components;
+    int max_image_units;
+    int max_combined_image_units_and_fragment_outputs;
+    int max_combined_shader_output_resources;
+    int max_image_samples;
+    int max_vertex_image_uniforms;
+    int max_tess_control_image_uniforms;
+    int max_tess_evaluation_image_uniforms;
+    int max_geometry_image_uniforms;
+    int max_fragment_image_uniforms;
+    int max_combined_image_uniforms;
+    int max_geometry_texture_image_units;
+    int max_geometry_output_vertices;
+    int max_geometry_total_output_components;
+    int max_geometry_uniform_components;
+    int max_geometry_varying_components;
+    int max_tess_control_input_components;
+    int max_tess_control_output_components;
+    int max_tess_control_texture_image_units;
+    int max_tess_control_uniform_components;
+    int max_tess_control_total_output_components;
+    int max_tess_evaluation_input_components;
+    int max_tess_evaluation_output_components;
+    int max_tess_evaluation_texture_image_units;
+    int max_tess_evaluation_uniform_components;
+    int max_tess_patch_components;
+    int max_patch_vertices;
+    int max_tess_gen_level;
+    int max_viewports;
+    int max_vertex_atomic_counters;
+    int max_tess_control_atomic_counters;
+    int max_tess_evaluation_atomic_counters;
+    int max_geometry_atomic_counters;
+    int max_fragment_atomic_counters;
+    int max_combined_atomic_counters;
+    int max_atomic_counter_bindings;
+    int max_vertex_atomic_counter_buffers;
+    int max_tess_control_atomic_counter_buffers;
+    int max_tess_evaluation_atomic_counter_buffers;
+    int max_geometry_atomic_counter_buffers;
+    int max_fragment_atomic_counter_buffers;
+    int max_combined_atomic_counter_buffers;
+    int max_atomic_counter_buffer_size;
+    int max_transform_feedback_buffers;
+    int max_transform_feedback_interleaved_components;
+    int max_cull_distances;
+    int max_combined_clip_and_cull_distances;
+    int max_samples;
+    int max_mesh_output_vertices_nv;
+    int max_mesh_output_primitives_nv;
+    int max_mesh_work_group_size_x_nv;
+    int max_mesh_work_group_size_y_nv;
+    int max_mesh_work_group_size_z_nv;
+    int max_task_work_group_size_x_nv;
+    int max_task_work_group_size_y_nv;
+    int max_task_work_group_size_z_nv;
+    int max_mesh_view_count_nv;
+
+    glslang_limits_t limits;
+} glslang_resource_t;
+
 typedef struct glslang_input_s {
     glslang_source_t language;
     glslang_stage_t stage;
@@ -54,6 +166,7 @@ typedef struct glslang_input_s {
     int force_default_version_and_profile;
     int forward_compatible;
     glslang_messages_t messages;
+    const glslang_resource_t* resource;
 } glslang_input_t;
 
 /* Inclusion result structure allocated by C include_local/include_system callbacks */

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

@@ -621,6 +621,8 @@ enum TOperator {
 
     EOpIsHelperInvocation,
 
+    EOpDebugPrintf,
+
     //
     // Branch
     //

+ 1 - 2
3rdparty/glslang/glslang/MachineIndependent/Constant.cpp

@@ -2,7 +2,7 @@
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2012-2013 LunarG, Inc.
 // Copyright (C) 2017 ARM Limited.
-// Copyright (C) 2018 Google, Inc.
+// Copyright (C) 2018-2020 Google, Inc.
 //
 // All rights reserved.
 //
@@ -1079,7 +1079,6 @@ TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode)
             {
                 double arg0 = childConstUnions[0][arg0comp].getDConst();
                 double arg1 = childConstUnions[1][arg1comp].getDConst();
-                assert(arg1 != 0.0);
                 double result = arg0 - arg1 * floor(arg0 / arg1);
                 newConstArray[comp].setDConst(result);
                 break;

+ 6 - 1
3rdparty/glslang/glslang/MachineIndependent/Initialize.cpp

@@ -1,7 +1,7 @@
 //
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2012-2016 LunarG, Inc.
-// Copyright (C) 2015-2018 Google, Inc.
+// Copyright (C) 2015-2020 Google, Inc.
 // Copyright (C) 2017 ARM Limited.
 //
 // All rights reserved.
@@ -4086,6 +4086,8 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
     commonBuiltins.append("void controlBarrier(int, int, int, int);\n"
                           "void memoryBarrier(int, int, int);\n");
 
+    commonBuiltins.append("void debugPrintfEXT();\n");
+
     if (profile != EEsProfile && version >= 450) {
         // coopMatStoreNV perhaps ought to have "out" on the buf parameter, but
         // adding it introduces undesirable tempArgs on the stack. What we want
@@ -7903,6 +7905,7 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
         }
 
         symbolTable.setFunctionExtensions("controlBarrier",                 1, &E_GL_KHR_memory_scope_semantics);
+        symbolTable.setFunctionExtensions("debugPrintfEXT",                 1, &E_GL_EXT_debug_printf);
 
         // GL_ARB_shader_ballot
         if (profile != EEsProfile) {
@@ -8451,6 +8454,8 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
     symbolTable.relateToOperator("average",            EOpAverage);
     symbolTable.relateToOperator("averageRounded",     EOpAverageRounded);
     symbolTable.relateToOperator("multiply32x16",      EOpMul32x16);
+    symbolTable.relateToOperator("debugPrintfEXT",     EOpDebugPrintf);
+
 
     if (PureOperatorBuiltins) {
         symbolTable.relateToOperator("imageSize",               EOpImageQuerySize);

+ 1 - 1
3rdparty/glslang/glslang/MachineIndependent/Intermediate.cpp

@@ -1,7 +1,7 @@
 //
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2012-2015 LunarG, Inc.
-// Copyright (C) 2015-2018 Google, Inc.
+// Copyright (C) 2015-2020 Google, Inc.
 // Copyright (C) 2017 ARM Limited.
 //
 // All rights reserved.

+ 14 - 1
3rdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp

@@ -1353,6 +1353,9 @@ void TParseContext::computeBuiltinPrecisions(TIntermTyped& node, const TFunction
         case EOpInterpolateAtSample:
             numArgs = 1;
             break;
+        case EOpDebugPrintf:
+            numArgs = 0;
+            break;
         default:
             break;
         }
@@ -3086,7 +3089,7 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
         error(loc, "constructor argument does not have a type", "constructor", "");
         return true;
     }
-    if (op != EOpConstructStruct && typed->getBasicType() == EbtSampler) {
+    if (op != EOpConstructStruct && op != EOpConstructNonuniform && typed->getBasicType() == EbtSampler) {
         error(loc, "cannot convert a sampler", "constructor", "");
         return true;
     }
@@ -5138,6 +5141,7 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
             profileRequires(loc, EEsProfile, 310, nullptr, feature);
         }
         publicType.qualifier.layoutOffset = value;
+        publicType.qualifier.explicitOffset = true;
         if (nonLiteral)
             error(loc, "needs a literal integer", "offset", "");
         return;
@@ -6082,6 +6086,15 @@ const TFunction* TParseContext::findFunction(const TSourceLoc& loc, const TFunct
 #endif
 
     const TFunction* function = nullptr;
+
+    // debugPrintfEXT has var args and is in the symbol table as "debugPrintfEXT()",
+    // mangled to "debugPrintfEXT("
+    if (call.getName() == "debugPrintfEXT") {
+        TSymbol* symbol = symbolTable.find("debugPrintfEXT(", &builtIn);
+        if (symbol)
+            return symbol->getAsFunction();
+    }
+
     bool explicitTypesEnabled = extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
                                 extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int8) ||
                                 extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int16) ||

+ 8 - 8
3rdparty/glslang/glslang/MachineIndependent/Scan.cpp

@@ -2,6 +2,7 @@
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2013 LunarG, Inc.
 // Copyright (C) 2017 ARM Limited.
+// Copyright (C) 2020 Google, Inc.
 //
 // All rights reserved.
 //
@@ -187,17 +188,15 @@ bool TInputScanner::scanVersion(int& version, EProfile& profile, bool& notFirstT
         if (lookingInMiddle) {
             notFirstToken = true;
             // make forward progress by finishing off the current line plus extra new lines
-            if (peek() == '\n' || peek() == '\r') {
-                while (peek() == '\n' || peek() == '\r')
-                    get();
-            } else
+            if (peek() != '\n' && peek() != '\r') {
                 do {
                     c = get();
                 } while (c != EndOfInput && c != '\n' && c != '\r');
-                while (peek() == '\n' || peek() == '\r')
-                    get();
-                if (peek() == EndOfInput)
-                    return true;
+            }
+            while (peek() == '\n' || peek() == '\r')
+                get();
+            if (peek() == EndOfInput)
+                return true;
         }
         lookingInMiddle = true;
 
@@ -843,6 +842,7 @@ int TScanContext::tokenize(TPpContext* pp, TParserToken& token)
             parseContext.error(loc, "not supported", "::", "");
             break;
 
+        case PpAtomConstString:        parserToken->sType.lex.string = NewPoolTString(tokenText);     return STRING_LITERAL;
         case PpAtomConstInt:           parserToken->sType.lex.i    = ppToken.ival;       return INTCONSTANT;
         case PpAtomConstUint:          parserToken->sType.lex.i    = ppToken.ival;       return UINTCONSTANT;
         case PpAtomConstFloat:         parserToken->sType.lex.d    = ppToken.dval;       return FLOATCONSTANT;

+ 1 - 1
3rdparty/glslang/glslang/MachineIndependent/ShaderLang.cpp

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

+ 3 - 1
3rdparty/glslang/glslang/MachineIndependent/Versions.cpp

@@ -2,7 +2,7 @@
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2012-2013 LunarG, Inc.
 // Copyright (C) 2017 ARM Limited.
-// Copyright (C) 2015-2018 Google, Inc.
+// Copyright (C) 2015-2020 Google, Inc.
 //
 // All rights reserved.
 //
@@ -221,6 +221,7 @@ void TParseVersions::initializeExtensionBehavior()
     extensionBehavior[E_GL_EXT_buffer_reference2]                       = EBhDisable;
     extensionBehavior[E_GL_EXT_buffer_reference_uvec2]                  = EBhDisable;
     extensionBehavior[E_GL_EXT_demote_to_helper_invocation]             = EBhDisable;
+    extensionBehavior[E_GL_EXT_debug_printf]                            = EBhDisable;
 
     extensionBehavior[E_GL_EXT_shader_16bit_storage]                    = EBhDisable;
     extensionBehavior[E_GL_EXT_shader_8bit_storage]                     = EBhDisable;
@@ -418,6 +419,7 @@ void TParseVersions::getPreamble(std::string& preamble)
             "#define GL_EXT_buffer_reference2 1\n"
             "#define GL_EXT_buffer_reference_uvec2 1\n"
             "#define GL_EXT_demote_to_helper_invocation 1\n"
+            "#define GL_EXT_debug_printf 1\n"
 
             // GL_KHR_shader_subgroup
             "#define GL_KHR_shader_subgroup_basic 1\n"

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

@@ -185,6 +185,7 @@ const char* const E_GL_EXT_buffer_reference2                = "GL_EXT_buffer_ref
 const char* const E_GL_EXT_buffer_reference_uvec2           = "GL_EXT_buffer_reference_uvec2";
 const char* const E_GL_EXT_demote_to_helper_invocation      = "GL_EXT_demote_to_helper_invocation";
 const char* const E_GL_EXT_shader_realtime_clock            = "GL_EXT_shader_realtime_clock";
+const char* const E_GL_EXT_debug_printf                     = "GL_EXT_debug_printf";
 
 // Arrays of extensions for the above viewportEXTs duplications
 

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

@@ -2,7 +2,7 @@
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2012-2013 LunarG, Inc.
 // Copyright (C) 2017 ARM Limited.
-// Copyright (C) 2015-2018 Google, Inc.
+// Copyright (C) 2015-2019 Google, Inc.
 //
 // All rights reserved.
 //
@@ -263,6 +263,7 @@ GLSLANG_WEB_EXCLUDE_OFF
 %token <lex> AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN
 %token <lex> MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN
 %token <lex> SUB_ASSIGN
+%token <lex> STRING_LITERAL
 
 %token <lex> LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT
 %token <lex> COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT
@@ -377,6 +378,9 @@ primary_expression
         $$ = parseContext.intermediate.addConstantUnion($1.b, $1.loc, true);
     }
 GLSLANG_WEB_EXCLUDE_ON
+    | STRING_LITERAL {
+        $$ = parseContext.intermediate.addConstantUnion($1.string, $1.loc, true);
+    }
     | INT32CONSTANT {
         parseContext.explicitInt32Check($1.loc, "32-bit signed literal");
         $$ = parseContext.intermediate.addConstantUnion($1.i, $1.loc, true);

+ 4 - 0
3rdparty/glslang/glslang/MachineIndependent/glslang.y

@@ -263,6 +263,7 @@ extern int yylex(YYSTYPE*, TParseContext&);
 %token <lex> AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN
 %token <lex> MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN
 %token <lex> SUB_ASSIGN
+%token <lex> STRING_LITERAL
 
 %token <lex> LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT
 %token <lex> COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT
@@ -377,6 +378,9 @@ primary_expression
         $$ = parseContext.intermediate.addConstantUnion($1.b, $1.loc, true);
     }
 
+    | STRING_LITERAL {
+        $$ = parseContext.intermediate.addConstantUnion($1.string, $1.loc, true);
+    }
     | INT32CONSTANT {
         parseContext.explicitInt32Check($1.loc, "32-bit signed literal");
         $$ = parseContext.intermediate.addConstantUnion($1.i, $1.loc, true);

File diff suppressed because it is too large
+ 489 - 406
3rdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp


+ 99 - 98
3rdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp.h

@@ -356,103 +356,104 @@ extern int yydebug;
     XOR_ASSIGN = 566,
     OR_ASSIGN = 567,
     SUB_ASSIGN = 568,
-    LEFT_PAREN = 569,
-    RIGHT_PAREN = 570,
-    LEFT_BRACKET = 571,
-    RIGHT_BRACKET = 572,
-    LEFT_BRACE = 573,
-    RIGHT_BRACE = 574,
-    DOT = 575,
-    COMMA = 576,
-    COLON = 577,
-    EQUAL = 578,
-    SEMICOLON = 579,
-    BANG = 580,
-    DASH = 581,
-    TILDE = 582,
-    PLUS = 583,
-    STAR = 584,
-    SLASH = 585,
-    PERCENT = 586,
-    LEFT_ANGLE = 587,
-    RIGHT_ANGLE = 588,
-    VERTICAL_BAR = 589,
-    CARET = 590,
-    AMPERSAND = 591,
-    QUESTION = 592,
-    INVARIANT = 593,
-    HIGH_PRECISION = 594,
-    MEDIUM_PRECISION = 595,
-    LOW_PRECISION = 596,
-    PRECISION = 597,
-    PACKED = 598,
-    RESOURCE = 599,
-    SUPERP = 600,
-    FLOATCONSTANT = 601,
-    INTCONSTANT = 602,
-    UINTCONSTANT = 603,
-    BOOLCONSTANT = 604,
-    IDENTIFIER = 605,
-    TYPE_NAME = 606,
-    CENTROID = 607,
-    IN = 608,
-    OUT = 609,
-    INOUT = 610,
-    STRUCT = 611,
-    VOID = 612,
-    WHILE = 613,
-    BREAK = 614,
-    CONTINUE = 615,
-    DO = 616,
-    ELSE = 617,
-    FOR = 618,
-    IF = 619,
-    DISCARD = 620,
-    RETURN = 621,
-    SWITCH = 622,
-    CASE = 623,
-    DEFAULT = 624,
-    UNIFORM = 625,
-    SHARED = 626,
-    BUFFER = 627,
-    FLAT = 628,
-    SMOOTH = 629,
-    LAYOUT = 630,
-    DOUBLECONSTANT = 631,
-    INT16CONSTANT = 632,
-    UINT16CONSTANT = 633,
-    FLOAT16CONSTANT = 634,
-    INT32CONSTANT = 635,
-    UINT32CONSTANT = 636,
-    INT64CONSTANT = 637,
-    UINT64CONSTANT = 638,
-    SUBROUTINE = 639,
-    DEMOTE = 640,
-    PAYLOADNV = 641,
-    PAYLOADINNV = 642,
-    HITATTRNV = 643,
-    CALLDATANV = 644,
-    CALLDATAINNV = 645,
-    PATCH = 646,
-    SAMPLE = 647,
-    NONUNIFORM = 648,
-    COHERENT = 649,
-    VOLATILE = 650,
-    RESTRICT = 651,
-    READONLY = 652,
-    WRITEONLY = 653,
-    DEVICECOHERENT = 654,
-    QUEUEFAMILYCOHERENT = 655,
-    WORKGROUPCOHERENT = 656,
-    SUBGROUPCOHERENT = 657,
-    NONPRIVATE = 658,
-    NOPERSPECTIVE = 659,
-    EXPLICITINTERPAMD = 660,
-    PERVERTEXNV = 661,
-    PERPRIMITIVENV = 662,
-    PERVIEWNV = 663,
-    PERTASKNV = 664,
-    PRECISE = 665
+    STRING_LITERAL = 569,
+    LEFT_PAREN = 570,
+    RIGHT_PAREN = 571,
+    LEFT_BRACKET = 572,
+    RIGHT_BRACKET = 573,
+    LEFT_BRACE = 574,
+    RIGHT_BRACE = 575,
+    DOT = 576,
+    COMMA = 577,
+    COLON = 578,
+    EQUAL = 579,
+    SEMICOLON = 580,
+    BANG = 581,
+    DASH = 582,
+    TILDE = 583,
+    PLUS = 584,
+    STAR = 585,
+    SLASH = 586,
+    PERCENT = 587,
+    LEFT_ANGLE = 588,
+    RIGHT_ANGLE = 589,
+    VERTICAL_BAR = 590,
+    CARET = 591,
+    AMPERSAND = 592,
+    QUESTION = 593,
+    INVARIANT = 594,
+    HIGH_PRECISION = 595,
+    MEDIUM_PRECISION = 596,
+    LOW_PRECISION = 597,
+    PRECISION = 598,
+    PACKED = 599,
+    RESOURCE = 600,
+    SUPERP = 601,
+    FLOATCONSTANT = 602,
+    INTCONSTANT = 603,
+    UINTCONSTANT = 604,
+    BOOLCONSTANT = 605,
+    IDENTIFIER = 606,
+    TYPE_NAME = 607,
+    CENTROID = 608,
+    IN = 609,
+    OUT = 610,
+    INOUT = 611,
+    STRUCT = 612,
+    VOID = 613,
+    WHILE = 614,
+    BREAK = 615,
+    CONTINUE = 616,
+    DO = 617,
+    ELSE = 618,
+    FOR = 619,
+    IF = 620,
+    DISCARD = 621,
+    RETURN = 622,
+    SWITCH = 623,
+    CASE = 624,
+    DEFAULT = 625,
+    UNIFORM = 626,
+    SHARED = 627,
+    BUFFER = 628,
+    FLAT = 629,
+    SMOOTH = 630,
+    LAYOUT = 631,
+    DOUBLECONSTANT = 632,
+    INT16CONSTANT = 633,
+    UINT16CONSTANT = 634,
+    FLOAT16CONSTANT = 635,
+    INT32CONSTANT = 636,
+    UINT32CONSTANT = 637,
+    INT64CONSTANT = 638,
+    UINT64CONSTANT = 639,
+    SUBROUTINE = 640,
+    DEMOTE = 641,
+    PAYLOADNV = 642,
+    PAYLOADINNV = 643,
+    HITATTRNV = 644,
+    CALLDATANV = 645,
+    CALLDATAINNV = 646,
+    PATCH = 647,
+    SAMPLE = 648,
+    NONUNIFORM = 649,
+    COHERENT = 650,
+    VOLATILE = 651,
+    RESTRICT = 652,
+    READONLY = 653,
+    WRITEONLY = 654,
+    DEVICECOHERENT = 655,
+    QUEUEFAMILYCOHERENT = 656,
+    WORKGROUPCOHERENT = 657,
+    SUBGROUPCOHERENT = 658,
+    NONPRIVATE = 659,
+    NOPERSPECTIVE = 660,
+    EXPLICITINTERPAMD = 661,
+    PERVERTEXNV = 662,
+    PERPRIMITIVENV = 663,
+    PERVIEWNV = 664,
+    PERTASKNV = 665,
+    PRECISE = 666
   };
 #endif
 
@@ -497,7 +498,7 @@ union YYSTYPE
         glslang::TArraySizes* typeParameters;
     } interm;
 
-#line 501 "MachineIndependent/glslang_tab.cpp.h" /* yacc.c:1909  */
+#line 502 "MachineIndependent/glslang_tab.cpp.h" /* yacc.c:1909  */
 };
 
 typedef union YYSTYPE YYSTYPE;

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

@@ -1090,6 +1090,7 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
     case EOpCooperativeMatrixMulAdd: out.debug << "MulAdd cooperative matrices"; break;
 
     case EOpIsHelperInvocation: out.debug << "IsHelperInvocation"; break;
+    case EOpDebugPrintf:  out.debug << "Debug printf";  break;
 
     default: out.debug.message(EPrefixError, "Bad aggregation op");
     }

+ 19 - 4
3rdparty/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp

@@ -621,14 +621,25 @@ int TPpContext::CPPinclude(TPpToken* ppToken)
 {
     const TSourceLoc directiveLoc = ppToken->loc;
     bool startWithLocalSearch = true; // to additionally include the extra "" paths
-    int token = scanToken(ppToken);
+    int token;
 
-    // handle <header-name>-style #include
-    if (token == '<') {
+    // Find the first non-whitespace char after #include
+    int ch = getChar();
+    while (ch == ' ' || ch == '\t') {
+        ch = getChar();
+    }
+    if (ch == '<') {
+        // <header-name> style
         startWithLocalSearch = false;
         token = scanHeaderName(ppToken, '>');
+    } else if (ch == '"') {
+        // "header-name" style
+        token = scanHeaderName(ppToken, '"');
+    } else {
+        // unexpected, get the full token to generate the error
+        ungetChar();
+        token = scanToken(ppToken);
     }
-    // otherwise ppToken already has the header name and it was "header-name" style
 
     if (token != PpAtomConstString) {
         parseContext.ppError(directiveLoc, "must be followed by a header name", "#include", "");
@@ -711,7 +722,9 @@ int TPpContext::CPPline(TPpToken* ppToken)
     const char* sourceName = nullptr; // Optional source file name.
     bool lineErr = false;
     bool fileErr = false;
+    disableEscapeSequences = true;
     token = eval(token, MIN_PRECEDENCE, false, lineRes, lineErr, ppToken);
+    disableEscapeSequences = false;
     if (! lineErr) {
         lineToken = lineRes;
         if (token == '\n')
@@ -754,7 +767,9 @@ int TPpContext::CPPline(TPpToken* ppToken)
 // Handle #error
 int TPpContext::CPPerror(TPpToken* ppToken)
 {
+    disableEscapeSequences = true;
     int token = scanToken(ppToken);
+    disableEscapeSequences = false;
     std::string message;
     TSourceLoc loc = ppToken->loc;
 

+ 2 - 1
3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpContext.cpp

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

+ 1 - 0
3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpContext.h

@@ -695,6 +695,7 @@ protected:
     std::string currentSourceFile;
 
     std::istringstream strtodStream;
+    bool disableEscapeSequences;
 };
 
 } // end namespace glslang

+ 76 - 6
3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp

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

+ 1 - 1
3rdparty/glslang/glslang/OSDependent/Web/CMakeLists.txt

@@ -17,7 +17,7 @@ if(ENABLE_GLSLANG_JS)
         target_link_options(glslang.js PRIVATE "SHELL: -s FILESYSTEM=0")
 
         if(ENABLE_EMSCRIPTEN_SINGLE_FILE)
-            target_link_options(glslang.js "SHELL: -s SINGLE_FILE=1")
+            target_link_options(glslang.js PRIVATE "SHELL: -s SINGLE_FILE=1")
         endif(ENABLE_EMSCRIPTEN_SINGLE_FILE)
 
         if(ENABLE_EMSCRIPTEN_ENVIRONMENT_NODE)

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