Browse Source

Updated glslang.

Бранимир Караџић 1 year ago
parent
commit
6ce4b76c9a

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

@@ -1,5 +1,6 @@
 /*
 /*
 ** Copyright (c) 2014-2020 The Khronos Group Inc.
 ** Copyright (c) 2014-2020 The Khronos Group Inc.
+** Copyright (C) 2022-2024 Arm Limited.
 ** Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 ** Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 **
 **
 ** Permission is hereby granted, free of charge, to any person obtaining a copy
 ** Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -53,8 +54,11 @@ static const char* const E_SPV_KHR_terminate_invocation         = "SPV_KHR_termi
 static const char* const E_SPV_KHR_workgroup_memory_explicit_layout = "SPV_KHR_workgroup_memory_explicit_layout";
 static const char* const E_SPV_KHR_workgroup_memory_explicit_layout = "SPV_KHR_workgroup_memory_explicit_layout";
 static const char* const E_SPV_KHR_subgroup_uniform_control_flow = "SPV_KHR_subgroup_uniform_control_flow";
 static const char* const E_SPV_KHR_subgroup_uniform_control_flow = "SPV_KHR_subgroup_uniform_control_flow";
 static const char* const E_SPV_KHR_fragment_shader_barycentric = "SPV_KHR_fragment_shader_barycentric";
 static const char* const E_SPV_KHR_fragment_shader_barycentric = "SPV_KHR_fragment_shader_barycentric";
+static const char* const E_SPV_KHR_quad_control                = "SPV_KHR_quad_control";
 static const char* const E_SPV_AMD_shader_early_and_late_fragment_tests = "SPV_AMD_shader_early_and_late_fragment_tests";
 static const char* const E_SPV_AMD_shader_early_and_late_fragment_tests = "SPV_AMD_shader_early_and_late_fragment_tests";
 static const char* const E_SPV_KHR_ray_tracing_position_fetch   = "SPV_KHR_ray_tracing_position_fetch";
 static const char* const E_SPV_KHR_ray_tracing_position_fetch   = "SPV_KHR_ray_tracing_position_fetch";
 static const char* const E_SPV_KHR_cooperative_matrix           = "SPV_KHR_cooperative_matrix";
 static const char* const E_SPV_KHR_cooperative_matrix           = "SPV_KHR_cooperative_matrix";
+static const char* const E_SPV_KHR_maximal_reconvergence        = "SPV_KHR_maximal_reconvergence";
+static const char* const E_SPV_KHR_subgroup_rotate              = "SPV_KHR_subgroup_rotate";
 
 
 #endif  // #ifndef GLSLextKHR_H
 #endif  // #ifndef GLSLextKHR_H

+ 72 - 26
3rdparty/glslang/SPIRV/GlslangToSpv.cpp

@@ -1,7 +1,7 @@
 //
 //
 // Copyright (C) 2014-2016 LunarG, Inc.
 // Copyright (C) 2014-2016 LunarG, Inc.
 // Copyright (C) 2015-2020 Google, Inc.
 // Copyright (C) 2015-2020 Google, Inc.
-// Copyright (C) 2017 ARM Limited.
+// Copyright (C) 2017, 2022-2024 Arm Limited.
 // Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 // Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 //
 // All rights reserved.
 // All rights reserved.
@@ -1558,8 +1558,13 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
             this->options.generateDebugInfo = true;
             this->options.generateDebugInfo = true;
 
 
     if (this->options.generateDebugInfo) {
     if (this->options.generateDebugInfo) {
-        builder.setEmitOpLines();
-        builder.setSourceFile(glslangIntermediate->getSourceFile());
+        if (this->options.emitNonSemanticShaderDebugInfo) {
+            builder.setEmitNonSemanticShaderDebugInfo(this->options.emitNonSemanticShaderDebugSource);
+        }
+        else {
+            builder.setEmitSpirvDebugInfo();
+        }
+        builder.setDebugSourceFile(glslangIntermediate->getSourceFile());
 
 
         // Set the source shader's text. If for SPV version 1.0, include
         // Set the source shader's text. If for SPV version 1.0, include
         // a preamble in comments stating the OpModuleProcessed instructions.
         // a preamble in comments stating the OpModuleProcessed instructions.
@@ -1584,9 +1589,6 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
             builder.addInclude(iItr->first, iItr->second);
             builder.addInclude(iItr->first, iItr->second);
     }
     }
 
 
-    builder.setEmitNonSemanticShaderDebugInfo(this->options.emitNonSemanticShaderDebugInfo);
-    builder.setEmitNonSemanticShaderDebugSource(this->options.emitNonSemanticShaderDebugSource);
-
     stdBuiltins = builder.import("GLSL.std.450");
     stdBuiltins = builder.import("GLSL.std.450");
 
 
     spv::AddressingModel addressingModel = spv::AddressingModelLogical;
     spv::AddressingModel addressingModel = spv::AddressingModelLogical;
@@ -1635,6 +1637,24 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
         builder.addExtension(spv::E_SPV_KHR_subgroup_uniform_control_flow);
         builder.addExtension(spv::E_SPV_KHR_subgroup_uniform_control_flow);
         builder.addExecutionMode(shaderEntry, spv::ExecutionModeSubgroupUniformControlFlowKHR);
         builder.addExecutionMode(shaderEntry, spv::ExecutionModeSubgroupUniformControlFlowKHR);
     }
     }
+    if (glslangIntermediate->getMaximallyReconverges()) {
+        builder.addExtension(spv::E_SPV_KHR_maximal_reconvergence);
+        builder.addExecutionMode(shaderEntry, spv::ExecutionModeMaximallyReconvergesKHR);
+    }
+
+    if (glslangIntermediate->getQuadDerivMode())
+    {
+        builder.addCapability(spv::CapabilityQuadControlKHR);
+        builder.addExtension(spv::E_SPV_KHR_quad_control);
+        builder.addExecutionMode(shaderEntry, spv::ExecutionModeQuadDerivativesKHR);
+    }
+
+    if (glslangIntermediate->getReqFullQuadsMode())
+    {
+        builder.addCapability(spv::CapabilityQuadControlKHR);
+        builder.addExtension(spv::E_SPV_KHR_quad_control);
+        builder.addExecutionMode(shaderEntry, spv::ExecutionModeRequireFullQuadsKHR);
+    }
 
 
     unsigned int mode;
     unsigned int mode;
     switch (glslangIntermediate->getStage()) {
     switch (glslangIntermediate->getStage()) {
@@ -2019,7 +2039,9 @@ void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol)
 {
 {
     // We update the line information even though no code might be generated here
     // We update the line information even though no code might be generated here
     // This is helpful to yield correct lines for control flow instructions
     // This is helpful to yield correct lines for control flow instructions
-    builder.setLine(symbol->getLoc().line, symbol->getLoc().getFilename());
+    if (!linkageOnly) {
+        builder.setDebugSourceLocation(symbol->getLoc().line, symbol->getLoc().getFilename());
+    }
 
 
     SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder);
     SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder);
     if (symbol->getType().isStruct())
     if (symbol->getType().isStruct())
@@ -2128,7 +2150,7 @@ void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol)
 
 
 bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::TIntermBinary* node)
 bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::TIntermBinary* node)
 {
 {
-    builder.setLine(node->getLoc().line, node->getLoc().getFilename());
+    builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename());
     if (node->getLeft()->getAsSymbolNode() != nullptr && node->getLeft()->getType().isStruct()) {
     if (node->getLeft()->getAsSymbolNode() != nullptr && node->getLeft()->getType().isStruct()) {
         glslangTypeToIdMap[node->getLeft()->getType().getStruct()] = node->getLeft()->getAsSymbolNode()->getId();
         glslangTypeToIdMap[node->getLeft()->getType().getStruct()] = node->getLeft()->getAsSymbolNode()->getId();
     }
     }
@@ -2173,7 +2195,7 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
             spv::Id rValue = accessChainLoad(node->getRight()->getType());
             spv::Id rValue = accessChainLoad(node->getRight()->getType());
 
 
             // reset line number for assignment
             // reset line number for assignment
-            builder.setLine(node->getLoc().line, node->getLoc().getFilename());
+            builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename());
 
 
             if (node->getOp() != glslang::EOpAssign) {
             if (node->getOp() != glslang::EOpAssign) {
                 // the left is also an r-value
                 // the left is also an r-value
@@ -2506,7 +2528,7 @@ spv::Id TGlslangToSpvTraverser::translateForcedType(spv::Id object)
 
 
 bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TIntermUnary* node)
 bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TIntermUnary* node)
 {
 {
-    builder.setLine(node->getLoc().line, node->getLoc().getFilename());
+    builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename());
 
 
     SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder);
     SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder);
     if (node->getType().getQualifier().isSpecConstant())
     if (node->getType().getQualifier().isSpecConstant())
@@ -2894,11 +2916,11 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
                 return false;
                 return false;
             } else {
             } else {
                 if (node->getOp() == glslang::EOpScope)
                 if (node->getOp() == glslang::EOpScope)
-                    builder.enterScope(0);
+                    builder.enterLexicalBlock(0);
             }
             }
         } else {
         } else {
             if (sequenceDepth > 1 && node->getOp() == glslang::EOpScope)
             if (sequenceDepth > 1 && node->getOp() == glslang::EOpScope)
-                builder.leaveScope();
+                builder.leaveLexicalBlock();
             --sequenceDepth;
             --sequenceDepth;
         }
         }
 
 
@@ -2925,6 +2947,9 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
     }
     }
     case glslang::EOpFunction:
     case glslang::EOpFunction:
         if (visit == glslang::EvPreVisit) {
         if (visit == glslang::EvPreVisit) {
+            if (options.generateDebugInfo) {
+                builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename());
+            }
             if (isShaderEntryPoint(node)) {
             if (isShaderEntryPoint(node)) {
                 inEntryPoint = true;
                 inEntryPoint = true;
                 builder.setBuildPoint(shaderEntry->getLastBlock());
                 builder.setBuildPoint(shaderEntry->getLastBlock());
@@ -2933,10 +2958,10 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
             } else {
             } else {
                 handleFunctionEntry(node);
                 handleFunctionEntry(node);
             }
             }
-            if (options.generateDebugInfo) {
+            if (options.generateDebugInfo && !options.emitNonSemanticShaderDebugInfo) {
                 const auto& loc = node->getLoc();
                 const auto& loc = node->getLoc();
                 const char* sourceFileName = loc.getFilename();
                 const char* sourceFileName = loc.getFilename();
-                spv::Id sourceFileId = sourceFileName ? builder.getStringId(sourceFileName) : builder.getSourceFile();
+                spv::Id sourceFileId = sourceFileName ? builder.getStringId(sourceFileName) : builder.getMainFileId();
                 currentFunction->setDebugLineInfo(sourceFileId, loc.line, loc.column);
                 currentFunction->setDebugLineInfo(sourceFileId, loc.line, loc.column);
             }
             }
         } else {
         } else {
@@ -2954,7 +2979,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
         return false;
         return false;
     case glslang::EOpFunctionCall:
     case glslang::EOpFunctionCall:
     {
     {
-        builder.setLine(node->getLoc().line, node->getLoc().getFilename());
+        builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename());
         if (node->isUserDefined())
         if (node->isUserDefined())
             result = handleUserFunctionCall(node);
             result = handleUserFunctionCall(node);
         if (result) {
         if (result) {
@@ -3075,7 +3100,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
     case glslang::EOpConstructCooperativeMatrixNV:
     case glslang::EOpConstructCooperativeMatrixNV:
     case glslang::EOpConstructCooperativeMatrixKHR:
     case glslang::EOpConstructCooperativeMatrixKHR:
     {
     {
-        builder.setLine(node->getLoc().line, node->getLoc().getFilename());
+        builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename());
         std::vector<spv::Id> arguments;
         std::vector<spv::Id> arguments;
         translateArguments(*node, arguments, lvalueCoherentFlags);
         translateArguments(*node, arguments, lvalueCoherentFlags);
         spv::Id constructed;
         spv::Id constructed;
@@ -3361,7 +3386,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
         right->traverse(this);
         right->traverse(this);
         spv::Id rightId = accessChainLoad(right->getType());
         spv::Id rightId = accessChainLoad(right->getType());
 
 
-        builder.setLine(node->getLoc().line, node->getLoc().getFilename());
+        builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename());
         OpDecorations decorations = { precision,
         OpDecorations decorations = { precision,
                                       TranslateNoContractionDecoration(node->getType().getQualifier()),
                                       TranslateNoContractionDecoration(node->getType().getQualifier()),
                                       TranslateNonUniformDecoration(node->getType().getQualifier()) };
                                       TranslateNonUniformDecoration(node->getType().getQualifier()) };
@@ -3596,7 +3621,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
             lvalueCoherentFlags = builder.getAccessChain().coherentFlags;
             lvalueCoherentFlags = builder.getAccessChain().coherentFlags;
             lvalueCoherentFlags |= TranslateCoherent(glslangOperands[arg]->getAsTyped()->getType());
             lvalueCoherentFlags |= TranslateCoherent(glslangOperands[arg]->getAsTyped()->getType());
         } else {
         } else {
-            builder.setLine(node->getLoc().line, node->getLoc().getFilename());
+            builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename());
              glslang::TOperator glslangOp = node->getOp();
              glslang::TOperator glslangOp = node->getOp();
              if (arg == 1 &&
              if (arg == 1 &&
                 (glslangOp == glslang::EOpRayQueryGetIntersectionType ||
                 (glslangOp == glslang::EOpRayQueryGetIntersectionType ||
@@ -3648,7 +3673,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
         }
         }
     }
     }
 
 
-    builder.setLine(node->getLoc().line, node->getLoc().getFilename());
+    builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename());
     if (node->getOp() == glslang::EOpCooperativeMatrixLoad ||
     if (node->getOp() == glslang::EOpCooperativeMatrixLoad ||
         node->getOp() == glslang::EOpCooperativeMatrixLoadNV) {
         node->getOp() == glslang::EOpCooperativeMatrixLoadNV) {
         std::vector<spv::IdImmediate> idImmOps;
         std::vector<spv::IdImmediate> idImmOps;
@@ -3888,7 +3913,7 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang
         node->getFalseBlock()->traverse(this);
         node->getFalseBlock()->traverse(this);
         spv::Id falseValue = accessChainLoad(node->getFalseBlock()->getAsTyped()->getType());
         spv::Id falseValue = accessChainLoad(node->getFalseBlock()->getAsTyped()->getType());
 
 
-        builder.setLine(node->getLoc().line, node->getLoc().getFilename());
+        builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename());
 
 
         // done if void
         // done if void
         if (node->getBasicType() == glslang::EbtVoid)
         if (node->getBasicType() == glslang::EbtVoid)
@@ -4096,7 +4121,7 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn
     // instructions in it, since the body/test may have arbitrary instructions,
     // instructions in it, since the body/test may have arbitrary instructions,
     // including merges of its own.
     // including merges of its own.
     builder.setBuildPoint(&blocks.head);
     builder.setBuildPoint(&blocks.head);
-    builder.setLine(node->getLoc().line, node->getLoc().getFilename());
+    builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename());
     builder.createLoopMerge(&blocks.merge, &blocks.continue_target, control, operands);
     builder.createLoopMerge(&blocks.merge, &blocks.continue_target, control, operands);
     if (node->testFirst() && node->getTest()) {
     if (node->testFirst() && node->getTest()) {
         spv::Block& test = builder.makeNewBlock();
         spv::Block& test = builder.makeNewBlock();
@@ -4119,7 +4144,7 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn
             node->getTerminal()->traverse(this);
             node->getTerminal()->traverse(this);
         builder.createBranch(&blocks.head);
         builder.createBranch(&blocks.head);
     } else {
     } else {
-        builder.setLine(node->getLoc().line, node->getLoc().getFilename());
+        builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename());
         builder.createBranch(&blocks.body);
         builder.createBranch(&blocks.body);
 
 
         breakForLoop.push(true);
         breakForLoop.push(true);
@@ -4154,7 +4179,7 @@ bool TGlslangToSpvTraverser::visitBranch(glslang::TVisit /* visit */, glslang::T
     if (node->getExpression())
     if (node->getExpression())
         node->getExpression()->traverse(this);
         node->getExpression()->traverse(this);
 
 
-    builder.setLine(node->getLoc().line, node->getLoc().getFilename());
+    builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename());
 
 
     switch (node->getFlowOp()) {
     switch (node->getFlowOp()) {
     case glslang::EOpKill:
     case glslang::EOpKill:
@@ -5738,7 +5763,7 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
     if (! node->isImage() && ! node->isTexture())
     if (! node->isImage() && ! node->isTexture())
         return spv::NoResult;
         return spv::NoResult;
 
 
-    builder.setLine(node->getLoc().line, node->getLoc().getFilename());
+    builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename());
 
 
     // Process a GLSL texturing op (will be SPV image)
     // Process a GLSL texturing op (will be SPV image)
 
 
@@ -7169,7 +7194,9 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, OpDe
     case glslang::EOpSubgroupExclusiveXor:
     case glslang::EOpSubgroupExclusiveXor:
     case glslang::EOpSubgroupQuadSwapHorizontal:
     case glslang::EOpSubgroupQuadSwapHorizontal:
     case glslang::EOpSubgroupQuadSwapVertical:
     case glslang::EOpSubgroupQuadSwapVertical:
-    case glslang::EOpSubgroupQuadSwapDiagonal: {
+    case glslang::EOpSubgroupQuadSwapDiagonal:
+    case glslang::EOpSubgroupQuadAll:
+    case glslang::EOpSubgroupQuadAny: {
         std::vector<spv::Id> operands;
         std::vector<spv::Id> operands;
         operands.push_back(operand);
         operands.push_back(operand);
         return createSubgroupOperation(op, typeId, operands, typeProxy);
         return createSubgroupOperation(op, typeId, operands, typeProxy);
@@ -8274,6 +8301,11 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s
     case glslang::EOpSubgroupElect:
     case glslang::EOpSubgroupElect:
         builder.addCapability(spv::CapabilityGroupNonUniform);
         builder.addCapability(spv::CapabilityGroupNonUniform);
         break;
         break;
+    case glslang::EOpSubgroupQuadAll:
+    case glslang::EOpSubgroupQuadAny:
+        builder.addExtension(spv::E_SPV_KHR_quad_control);
+        builder.addCapability(spv::CapabilityQuadControlKHR);
+        // pass through
     case glslang::EOpSubgroupAll:
     case glslang::EOpSubgroupAll:
     case glslang::EOpSubgroupAny:
     case glslang::EOpSubgroupAny:
     case glslang::EOpSubgroupAllEqual:
     case glslang::EOpSubgroupAllEqual:
@@ -8293,6 +8325,11 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s
         builder.addCapability(spv::CapabilityGroupNonUniform);
         builder.addCapability(spv::CapabilityGroupNonUniform);
         builder.addCapability(spv::CapabilityGroupNonUniformBallot);
         builder.addCapability(spv::CapabilityGroupNonUniformBallot);
         break;
         break;
+    case glslang::EOpSubgroupRotate:
+    case glslang::EOpSubgroupClusteredRotate:
+        builder.addExtension(spv::E_SPV_KHR_subgroup_rotate);
+        builder.addCapability(spv::CapabilityGroupNonUniformRotateKHR);
+        break;
     case glslang::EOpSubgroupShuffle:
     case glslang::EOpSubgroupShuffle:
     case glslang::EOpSubgroupShuffleXor:
     case glslang::EOpSubgroupShuffleXor:
         builder.addCapability(spv::CapabilityGroupNonUniform);
         builder.addCapability(spv::CapabilityGroupNonUniform);
@@ -8381,7 +8418,9 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s
     // Figure out which opcode to use.
     // Figure out which opcode to use.
     switch (op) {
     switch (op) {
     case glslang::EOpSubgroupElect:                   opCode = spv::OpGroupNonUniformElect; break;
     case glslang::EOpSubgroupElect:                   opCode = spv::OpGroupNonUniformElect; break;
+    case glslang::EOpSubgroupQuadAll:                 opCode = spv::OpGroupNonUniformQuadAllKHR; break;
     case glslang::EOpSubgroupAll:                     opCode = spv::OpGroupNonUniformAll; break;
     case glslang::EOpSubgroupAll:                     opCode = spv::OpGroupNonUniformAll; break;
+    case glslang::EOpSubgroupQuadAny:                 opCode = spv::OpGroupNonUniformQuadAnyKHR; break;
     case glslang::EOpSubgroupAny:                     opCode = spv::OpGroupNonUniformAny; break;
     case glslang::EOpSubgroupAny:                     opCode = spv::OpGroupNonUniformAny; break;
     case glslang::EOpSubgroupAllEqual:                opCode = spv::OpGroupNonUniformAllEqual; break;
     case glslang::EOpSubgroupAllEqual:                opCode = spv::OpGroupNonUniformAllEqual; break;
     case glslang::EOpSubgroupBroadcast:               opCode = spv::OpGroupNonUniformBroadcast; break;
     case glslang::EOpSubgroupBroadcast:               opCode = spv::OpGroupNonUniformBroadcast; break;
@@ -8398,6 +8437,8 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s
     case glslang::EOpSubgroupShuffleXor:              opCode = spv::OpGroupNonUniformShuffleXor; break;
     case glslang::EOpSubgroupShuffleXor:              opCode = spv::OpGroupNonUniformShuffleXor; break;
     case glslang::EOpSubgroupShuffleUp:               opCode = spv::OpGroupNonUniformShuffleUp; break;
     case glslang::EOpSubgroupShuffleUp:               opCode = spv::OpGroupNonUniformShuffleUp; break;
     case glslang::EOpSubgroupShuffleDown:             opCode = spv::OpGroupNonUniformShuffleDown; break;
     case glslang::EOpSubgroupShuffleDown:             opCode = spv::OpGroupNonUniformShuffleDown; break;
+    case glslang::EOpSubgroupRotate:
+    case glslang::EOpSubgroupClusteredRotate:         opCode = spv::OpGroupNonUniformRotateKHR; break;
     case glslang::EOpSubgroupAdd:
     case glslang::EOpSubgroupAdd:
     case glslang::EOpSubgroupInclusiveAdd:
     case glslang::EOpSubgroupInclusiveAdd:
     case glslang::EOpSubgroupExclusiveAdd:
     case glslang::EOpSubgroupExclusiveAdd:
@@ -8578,7 +8619,10 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s
 
 
     // Every operation begins with the Execution Scope operand.
     // Every operation begins with the Execution Scope operand.
     spv::IdImmediate executionScope = { true, builder.makeUintConstant(spv::ScopeSubgroup) };
     spv::IdImmediate executionScope = { true, builder.makeUintConstant(spv::ScopeSubgroup) };
-    spvGroupOperands.push_back(executionScope);
+    // All other ops need the execution scope. Quad Control Ops don't need scope, it's always Quad.
+    if (opCode != spv::OpGroupNonUniformQuadAllKHR && opCode != spv::OpGroupNonUniformQuadAnyKHR) {
+        spvGroupOperands.push_back(executionScope);
+    }
 
 
     // Next, for all operations that use a Group Operation, push that as an operand.
     // Next, for all operations that use a Group Operation, push that as an operand.
     if (groupOperation != spv::GroupOperationMax) {
     if (groupOperation != spv::GroupOperationMax) {
@@ -8821,6 +8865,8 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::
     case glslang::EOpSubgroupShuffleXor:
     case glslang::EOpSubgroupShuffleXor:
     case glslang::EOpSubgroupShuffleUp:
     case glslang::EOpSubgroupShuffleUp:
     case glslang::EOpSubgroupShuffleDown:
     case glslang::EOpSubgroupShuffleDown:
+    case glslang::EOpSubgroupRotate:
+    case glslang::EOpSubgroupClusteredRotate:
     case glslang::EOpSubgroupClusteredAdd:
     case glslang::EOpSubgroupClusteredAdd:
     case glslang::EOpSubgroupClusteredMul:
     case glslang::EOpSubgroupClusteredMul:
     case glslang::EOpSubgroupClusteredMin:
     case glslang::EOpSubgroupClusteredMin:

+ 106 - 139
3rdparty/glslang/SPIRV/SpvBuilder.cpp

@@ -58,13 +58,6 @@ Builder::Builder(unsigned int spvVersion, unsigned int magicNumber, SpvBuildLogg
     spvVersion(spvVersion),
     spvVersion(spvVersion),
     sourceLang(SourceLanguageUnknown),
     sourceLang(SourceLanguageUnknown),
     sourceVersion(0),
     sourceVersion(0),
-    sourceFileStringId(NoResult),
-    currentLine(0),
-    currentFile(nullptr),
-    currentFileId(NoResult),
-    lastDebugScopeId(NoResult),
-    emitOpLines(false),
-    emitNonSemanticShaderDebugInfo(false),
     addressModel(AddressingModelLogical),
     addressModel(AddressingModelLogical),
     memoryModel(MemoryModelGLSL450),
     memoryModel(MemoryModelGLSL450),
     builderNumber(magicNumber),
     builderNumber(magicNumber),
@@ -91,78 +84,6 @@ Id Builder::import(const char* name)
     return import->getResultId();
     return import->getResultId();
 }
 }
 
 
-// Emit instruction for non-filename-based #line directives (ie. no filename
-// seen yet): emit an OpLine if we've been asked to emit OpLines and the line
-// number has changed since the last time, and is a valid line number.
-void Builder::setLine(int lineNum)
-{
-    if (lineNum != 0 && lineNum != currentLine) {
-        currentLine = lineNum;
-        if (emitOpLines) {
-          if (emitNonSemanticShaderDebugInfo)
-              addDebugScopeAndLine(currentFileId, currentLine, 0);
-          else
-              addLine(sourceFileStringId, currentLine, 0);
-        }
-    }
-}
-
-// If no filename, do non-filename-based #line emit. Else do filename-based emit.
-// Emit OpLine if we've been asked to emit OpLines and the line number or filename
-// has changed since the last time, and line number is valid.
-void Builder::setLine(int lineNum, const char* filename)
-{
-    if (filename == nullptr) {
-        setLine(lineNum);
-        return;
-    }
-    if ((lineNum != 0 && lineNum != currentLine) || currentFile == nullptr ||
-            strncmp(filename, currentFile, strlen(currentFile) + 1) != 0) {
-        currentLine = lineNum;
-        currentFile = filename;
-        if (emitOpLines) {
-            spv::Id strId = getStringId(filename);
-            if (emitNonSemanticShaderDebugInfo)
-                addDebugScopeAndLine(strId, currentLine, 0);
-            else
-                addLine(strId, currentLine, 0);
-        }
-    }
-}
-
-void Builder::addLine(Id fileName, int lineNum, int column)
-{
-    Instruction* line = new Instruction(OpLine);
-    line->addIdOperand(fileName);
-    line->addImmediateOperand(lineNum);
-    line->addImmediateOperand(column);
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(line));
-}
-
-void Builder::addDebugScopeAndLine(Id fileName, int lineNum, int column)
-{
-    assert(!currentDebugScopeId.empty());
-    if (currentDebugScopeId.top() != lastDebugScopeId) {
-        spv::Id resultId = getUniqueId();
-        Instruction* scopeInst = new Instruction(resultId, makeVoidType(), OpExtInst);
-        scopeInst->addIdOperand(nonSemanticShaderDebugInfo);
-        scopeInst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugScope);
-        scopeInst->addIdOperand(currentDebugScopeId.top());
-        buildPoint->addInstruction(std::unique_ptr<Instruction>(scopeInst));
-        lastDebugScopeId = currentDebugScopeId.top();
-    }
-    spv::Id resultId = getUniqueId();
-    Instruction* lineInst = new Instruction(resultId, makeVoidType(), OpExtInst);
-    lineInst->addIdOperand(nonSemanticShaderDebugInfo);
-    lineInst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugLine);
-    lineInst->addIdOperand(makeDebugSource(fileName));
-    lineInst->addIdOperand(makeUintConstant(lineNum));
-    lineInst->addIdOperand(makeUintConstant(lineNum));
-    lineInst->addIdOperand(makeUintConstant(column));
-    lineInst->addIdOperand(makeUintConstant(column));
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(lineInst));
-}
-
 // For creating new groupedTypes (will return old type if the requested one was already made).
 // For creating new groupedTypes (will return old type if the requested one was already made).
 Id Builder::makeVoidType()
 Id Builder::makeVoidType()
 {
 {
@@ -1011,7 +932,7 @@ Id Builder::makeMemberDebugType(Id const memberType, DebugTypeLoc const& debugTy
     type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeMember);
     type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeMember);
     type->addIdOperand(getStringId(debugTypeLoc.name)); // name id
     type->addIdOperand(getStringId(debugTypeLoc.name)); // name id
     type->addIdOperand(debugId[memberType]); // type id
     type->addIdOperand(debugId[memberType]); // type id
-    type->addIdOperand(makeDebugSource(sourceFileStringId)); // source id TODO: verify this works across include directives
+    type->addIdOperand(makeDebugSource(currentFileId)); // source id
     type->addIdOperand(makeUintConstant(debugTypeLoc.line)); // line id TODO: currentLine is always zero
     type->addIdOperand(makeUintConstant(debugTypeLoc.line)); // line id TODO: currentLine is always zero
     type->addIdOperand(makeUintConstant(debugTypeLoc.column)); // TODO: column id
     type->addIdOperand(makeUintConstant(debugTypeLoc.column)); // TODO: column id
     type->addIdOperand(makeUintConstant(0)); // TODO: offset id
     type->addIdOperand(makeUintConstant(0)); // TODO: offset id
@@ -1050,7 +971,7 @@ Id Builder::makeCompositeDebugType(std::vector<Id> const& memberTypes, char cons
     type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeComposite);
     type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeComposite);
     type->addIdOperand(getStringId(name)); // name id
     type->addIdOperand(getStringId(name)); // name id
     type->addIdOperand(makeUintConstant(tag)); // tag id
     type->addIdOperand(makeUintConstant(tag)); // tag id
-    type->addIdOperand(makeDebugSource(sourceFileStringId)); // source id TODO: verify this works across include directives
+    type->addIdOperand(makeDebugSource(currentFileId)); // source id
     type->addIdOperand(makeUintConstant(currentLine)); // line id TODO: currentLine always zero?
     type->addIdOperand(makeUintConstant(currentLine)); // line id TODO: currentLine always zero?
     type->addIdOperand(makeUintConstant(0)); // TODO: column id
     type->addIdOperand(makeUintConstant(0)); // TODO: column id
     type->addIdOperand(makeDebugCompilationUnit()); // scope id
     type->addIdOperand(makeDebugCompilationUnit()); // scope id
@@ -1113,14 +1034,19 @@ Id Builder::makeDebugSource(const Id fileName) {
     sourceInst->addIdOperand(fileName);
     sourceInst->addIdOperand(fileName);
     if (emitNonSemanticShaderDebugSource) {
     if (emitNonSemanticShaderDebugSource) {
         spv::Id sourceId = 0;
         spv::Id sourceId = 0;
-        if (fileName == sourceFileStringId) {
+        if (fileName == mainFileId) {
             sourceId = getStringId(sourceText);
             sourceId = getStringId(sourceText);
         } else {
         } else {
             auto incItr = includeFiles.find(fileName);
             auto incItr = includeFiles.find(fileName);
-            assert(incItr != includeFiles.end());
-            sourceId = getStringId(*incItr->second);
+            if (incItr != includeFiles.end()) {
+                sourceId = getStringId(*incItr->second);
+            }
+        }
+
+        // We omit the optional source text item if not available in glslang
+        if (sourceId != 0) {
+            sourceInst->addIdOperand(sourceId);
         }
         }
-        sourceInst->addIdOperand(sourceId);
     }
     }
     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(sourceInst));
     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(sourceInst));
     module.mapInstruction(sourceInst);
     module.mapInstruction(sourceInst);
@@ -1137,7 +1063,7 @@ Id Builder::makeDebugCompilationUnit() {
     sourceInst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugCompilationUnit);
     sourceInst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugCompilationUnit);
     sourceInst->addIdOperand(makeUintConstant(1)); // TODO(greg-lunarg): Get rid of magic number
     sourceInst->addIdOperand(makeUintConstant(1)); // TODO(greg-lunarg): Get rid of magic number
     sourceInst->addIdOperand(makeUintConstant(4)); // TODO(greg-lunarg): Get rid of magic number
     sourceInst->addIdOperand(makeUintConstant(4)); // TODO(greg-lunarg): Get rid of magic number
-    sourceInst->addIdOperand(makeDebugSource(sourceFileStringId));
+    sourceInst->addIdOperand(makeDebugSource(mainFileId));
     sourceInst->addIdOperand(makeUintConstant(sourceLang));
     sourceInst->addIdOperand(makeUintConstant(sourceLang));
     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(sourceInst));
     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(sourceInst));
     module.mapInstruction(sourceInst);
     module.mapInstruction(sourceInst);
@@ -1160,7 +1086,7 @@ Id Builder::createDebugGlobalVariable(Id const type, char const*const name, Id c
     inst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugGlobalVariable);
     inst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugGlobalVariable);
     inst->addIdOperand(getStringId(name)); // name id
     inst->addIdOperand(getStringId(name)); // name id
     inst->addIdOperand(type); // type id
     inst->addIdOperand(type); // type id
-    inst->addIdOperand(makeDebugSource(sourceFileStringId)); // source id
+    inst->addIdOperand(makeDebugSource(currentFileId)); // source id
     inst->addIdOperand(makeUintConstant(currentLine)); // line id TODO: currentLine always zero?
     inst->addIdOperand(makeUintConstant(currentLine)); // line id TODO: currentLine always zero?
     inst->addIdOperand(makeUintConstant(0)); // TODO: column id
     inst->addIdOperand(makeUintConstant(0)); // TODO: column id
     inst->addIdOperand(makeDebugCompilationUnit()); // scope id
     inst->addIdOperand(makeDebugCompilationUnit()); // scope id
@@ -1184,7 +1110,7 @@ Id Builder::createDebugLocalVariable(Id type, char const*const name, size_t cons
     inst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugLocalVariable);
     inst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugLocalVariable);
     inst->addIdOperand(getStringId(name)); // name id
     inst->addIdOperand(getStringId(name)); // name id
     inst->addIdOperand(type); // type id
     inst->addIdOperand(type); // type id
-    inst->addIdOperand(makeDebugSource(sourceFileStringId)); // source id
+    inst->addIdOperand(makeDebugSource(currentFileId)); // source id
     inst->addIdOperand(makeUintConstant(currentLine)); // line id
     inst->addIdOperand(makeUintConstant(currentLine)); // line id
     inst->addIdOperand(makeUintConstant(0)); // TODO: column id
     inst->addIdOperand(makeUintConstant(0)); // TODO: column id
     inst->addIdOperand(currentDebugScopeId.top()); // scope id
     inst->addIdOperand(currentDebugScopeId.top()); // scope id
@@ -1224,7 +1150,7 @@ Id Builder::makeDebugDeclare(Id const debugLocalVariable, Id const pointer)
     inst->addIdOperand(debugLocalVariable); // debug local variable id
     inst->addIdOperand(debugLocalVariable); // debug local variable id
     inst->addIdOperand(pointer); // pointer to local variable id
     inst->addIdOperand(pointer); // pointer to local variable id
     inst->addIdOperand(makeDebugExpression()); // expression id
     inst->addIdOperand(makeDebugExpression()); // expression id
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(inst));
+    addInstruction(std::unique_ptr<Instruction>(inst));
 
 
     return inst->getResultId();
     return inst->getResultId();
 }
 }
@@ -1237,7 +1163,7 @@ Id Builder::makeDebugValue(Id const debugLocalVariable, Id const value)
     inst->addIdOperand(debugLocalVariable); // debug local variable id
     inst->addIdOperand(debugLocalVariable); // debug local variable id
     inst->addIdOperand(value); // value of local variable id
     inst->addIdOperand(value); // value of local variable id
     inst->addIdOperand(makeDebugExpression()); // expression id
     inst->addIdOperand(makeDebugExpression()); // expression id
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(inst));
+    addInstruction(std::unique_ptr<Instruction>(inst));
 
 
     return inst->getResultId();
     return inst->getResultId();
 }
 }
@@ -2103,6 +2029,49 @@ void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decorat
     decorations.push_back(std::unique_ptr<Instruction>(dec));
     decorations.push_back(std::unique_ptr<Instruction>(dec));
 }
 }
 
 
+void Builder::addInstruction(std::unique_ptr<Instruction> inst) {
+    // Optionally insert OpDebugScope
+    if (emitNonSemanticShaderDebugInfo && dirtyScopeTracker) {
+        if (buildPoint->updateDebugScope(currentDebugScopeId.top())) {
+            auto scopeInst = std::make_unique<Instruction>(getUniqueId(), makeVoidType(), OpExtInst);
+            scopeInst->addIdOperand(nonSemanticShaderDebugInfo);
+            scopeInst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugScope);
+            scopeInst->addIdOperand(currentDebugScopeId.top());
+            buildPoint->addInstruction(std::move(scopeInst));
+        }
+
+        dirtyScopeTracker = false;
+    }
+
+    // Insert OpLine/OpDebugLine if the debug source location has changed
+    if (trackDebugInfo && dirtyLineTracker) {
+        if (buildPoint->updateDebugSourceLocation(currentLine, 0, currentFileId)) {
+            if (emitSpirvDebugInfo) {
+                auto lineInst = std::make_unique<Instruction>(OpLine);
+                lineInst->addIdOperand(currentFileId);
+                lineInst->addImmediateOperand(currentLine);
+                lineInst->addImmediateOperand(0);
+                buildPoint->addInstruction(std::move(lineInst));
+            }
+            if (emitNonSemanticShaderDebugInfo) {
+                auto lineInst = std::make_unique<Instruction>(getUniqueId(), makeVoidType(), OpExtInst);
+                lineInst->addIdOperand(nonSemanticShaderDebugInfo);
+                lineInst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugLine);
+                lineInst->addIdOperand(makeDebugSource(currentFileId));
+                lineInst->addIdOperand(makeUintConstant(currentLine));
+                lineInst->addIdOperand(makeUintConstant(currentLine));
+                lineInst->addIdOperand(makeUintConstant(0));
+                lineInst->addIdOperand(makeUintConstant(0));
+                buildPoint->addInstruction(std::move(lineInst));
+            }
+        }
+
+        dirtyLineTracker = false;
+    }
+
+    buildPoint->addInstruction(std::move(inst));
+}
+
 // Comments in header
 // Comments in header
 Function* Builder::makeEntryPoint(const char* entryPoint)
 Function* Builder::makeEntryPoint(const char* entryPoint)
 {
 {
@@ -2146,7 +2115,7 @@ Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const
 
 
     // reset last debug scope
     // reset last debug scope
     if (emitNonSemanticShaderDebugInfo) {
     if (emitNonSemanticShaderDebugInfo) {
-        lastDebugScopeId = NoResult;
+        dirtyScopeTracker = true;
     }
     }
 
 
     // CFG
     // CFG
@@ -2186,8 +2155,6 @@ void Builder::setupDebugFunctionEntry(Function* function, const char* name, int
     // DebugScope and DebugLine for parameter DebugDeclares
     // DebugScope and DebugLine for parameter DebugDeclares
     assert(paramTypes.size() == paramNames.size());
     assert(paramTypes.size() == paramNames.size());
     if ((int)paramTypes.size() > 0) {
     if ((int)paramTypes.size() > 0) {
-        addDebugScopeAndLine(currentFileId, currentLine, 0);
-
         Id firstParamId = function->getParamId(0);
         Id firstParamId = function->getParamId(0);
 
 
         for (size_t p = 0; p < paramTypes.size(); ++p) {
         for (size_t p = 0; p < paramTypes.size(); ++p) {
@@ -2276,29 +2243,29 @@ void Builder::makeReturn(bool implicit, Id retVal)
     if (retVal) {
     if (retVal) {
         Instruction* inst = new Instruction(NoResult, NoType, OpReturnValue);
         Instruction* inst = new Instruction(NoResult, NoType, OpReturnValue);
         inst->addIdOperand(retVal);
         inst->addIdOperand(retVal);
-        buildPoint->addInstruction(std::unique_ptr<Instruction>(inst));
+        addInstruction(std::unique_ptr<Instruction>(inst));
     } else
     } else
-        buildPoint->addInstruction(std::unique_ptr<Instruction>(new Instruction(NoResult, NoType, OpReturn)));
+        addInstruction(std::unique_ptr<Instruction>(new Instruction(NoResult, NoType, OpReturn)));
 
 
     if (! implicit)
     if (! implicit)
         createAndSetNoPredecessorBlock("post-return");
         createAndSetNoPredecessorBlock("post-return");
 }
 }
 
 
 // Comments in header
 // Comments in header
-void Builder::enterScope(uint32_t line)
+void Builder::enterLexicalBlock(uint32_t line)
 {
 {
     // Generate new lexical scope debug instruction
     // Generate new lexical scope debug instruction
     Id lexId = makeDebugLexicalBlock(line);
     Id lexId = makeDebugLexicalBlock(line);
     currentDebugScopeId.push(lexId);
     currentDebugScopeId.push(lexId);
-    lastDebugScopeId = NoResult;
+    dirtyScopeTracker = true;
 }
 }
 
 
 // Comments in header
 // Comments in header
-void Builder::leaveScope()
+void Builder::leaveLexicalBlock()
 {
 {
     // Pop current scope from stack and clear current scope
     // Pop current scope from stack and clear current scope
     currentDebugScopeId.pop();
     currentDebugScopeId.pop();
-    lastDebugScopeId = NoResult;
+    dirtyScopeTracker = true;
 }
 }
 
 
 // Comments in header
 // Comments in header
@@ -2322,7 +2289,7 @@ void Builder::enterFunction(Function const* function)
         defInst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugFunctionDefinition);
         defInst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugFunctionDefinition);
         defInst->addIdOperand(debugId[funcId]);
         defInst->addIdOperand(debugId[funcId]);
         defInst->addIdOperand(funcId);
         defInst->addIdOperand(funcId);
-        buildPoint->addInstruction(std::unique_ptr<Instruction>(defInst));
+        addInstruction(std::unique_ptr<Instruction>(defInst));
     }
     }
 
 
     if (auto linkType = function->getLinkType(); linkType != LinkageTypeMax) {
     if (auto linkType = function->getLinkType(); linkType != LinkageTypeMax) {
@@ -2358,7 +2325,7 @@ void Builder::leaveFunction()
 // Comments in header
 // Comments in header
 void Builder::makeStatementTerminator(spv::Op opcode, const char *name)
 void Builder::makeStatementTerminator(spv::Op opcode, const char *name)
 {
 {
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(new Instruction(opcode)));
+    addInstruction(std::unique_ptr<Instruction>(new Instruction(opcode)));
     createAndSetNoPredecessorBlock(name);
     createAndSetNoPredecessorBlock(name);
 }
 }
 
 
@@ -2420,7 +2387,7 @@ Id Builder::createVariable(Decoration precision, StorageClass storageClass, Id t
 Id Builder::createUndefined(Id type)
 Id Builder::createUndefined(Id type)
 {
 {
   Instruction* inst = new Instruction(getUniqueId(), type, OpUndef);
   Instruction* inst = new Instruction(getUniqueId(), type, OpUndef);
-  buildPoint->addInstruction(std::unique_ptr<Instruction>(inst));
+  addInstruction(std::unique_ptr<Instruction>(inst));
   return inst->getResultId();
   return inst->getResultId();
 }
 }
 
 
@@ -2464,7 +2431,7 @@ void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAcce
         }
         }
     }
     }
 
 
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(store));
+    addInstruction(std::unique_ptr<Instruction>(store));
 }
 }
 
 
 // Comments in header
 // Comments in header
@@ -2486,7 +2453,7 @@ Id Builder::createLoad(Id lValue, spv::Decoration precision, spv::MemoryAccessMa
         }
         }
     }
     }
 
 
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(load));
+    addInstruction(std::unique_ptr<Instruction>(load));
     setPrecision(load->getResultId(), precision);
     setPrecision(load->getResultId(), precision);
 
 
     return load->getResultId();
     return load->getResultId();
@@ -2504,7 +2471,7 @@ Id Builder::createAccessChain(StorageClass storageClass, Id base, const std::vec
     chain->addIdOperand(base);
     chain->addIdOperand(base);
     for (int i = 0; i < (int)offsets.size(); ++i)
     for (int i = 0; i < (int)offsets.size(); ++i)
         chain->addIdOperand(offsets[i]);
         chain->addIdOperand(offsets[i]);
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(chain));
+    addInstruction(std::unique_ptr<Instruction>(chain));
 
 
     return chain->getResultId();
     return chain->getResultId();
 }
 }
@@ -2515,7 +2482,7 @@ Id Builder::createArrayLength(Id base, unsigned int member)
     Instruction* length = new Instruction(getUniqueId(), intType, OpArrayLength);
     Instruction* length = new Instruction(getUniqueId(), intType, OpArrayLength);
     length->addIdOperand(base);
     length->addIdOperand(base);
     length->addImmediateOperand(member);
     length->addImmediateOperand(member);
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(length));
+    addInstruction(std::unique_ptr<Instruction>(length));
 
 
     return length->getResultId();
     return length->getResultId();
 }
 }
@@ -2532,7 +2499,7 @@ Id Builder::createCooperativeMatrixLengthKHR(Id type)
 
 
     Instruction* length = new Instruction(getUniqueId(), intType, OpCooperativeMatrixLengthKHR);
     Instruction* length = new Instruction(getUniqueId(), intType, OpCooperativeMatrixLengthKHR);
     length->addIdOperand(type);
     length->addIdOperand(type);
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(length));
+    addInstruction(std::unique_ptr<Instruction>(length));
 
 
     return length->getResultId();
     return length->getResultId();
 }
 }
@@ -2549,7 +2516,7 @@ Id Builder::createCooperativeMatrixLengthNV(Id type)
 
 
     Instruction* length = new Instruction(getUniqueId(), intType, OpCooperativeMatrixLengthNV);
     Instruction* length = new Instruction(getUniqueId(), intType, OpCooperativeMatrixLengthNV);
     length->addIdOperand(type);
     length->addIdOperand(type);
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(length));
+    addInstruction(std::unique_ptr<Instruction>(length));
 
 
     return length->getResultId();
     return length->getResultId();
 }
 }
@@ -2565,7 +2532,7 @@ Id Builder::createCompositeExtract(Id composite, Id typeId, unsigned index)
     Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract);
     Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract);
     extract->addIdOperand(composite);
     extract->addIdOperand(composite);
     extract->addImmediateOperand(index);
     extract->addImmediateOperand(index);
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(extract));
+    addInstruction(std::unique_ptr<Instruction>(extract));
 
 
     return extract->getResultId();
     return extract->getResultId();
 }
 }
@@ -2581,7 +2548,7 @@ Id Builder::createCompositeExtract(Id composite, Id typeId, const std::vector<un
     extract->addIdOperand(composite);
     extract->addIdOperand(composite);
     for (int i = 0; i < (int)indexes.size(); ++i)
     for (int i = 0; i < (int)indexes.size(); ++i)
         extract->addImmediateOperand(indexes[i]);
         extract->addImmediateOperand(indexes[i]);
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(extract));
+    addInstruction(std::unique_ptr<Instruction>(extract));
 
 
     return extract->getResultId();
     return extract->getResultId();
 }
 }
@@ -2592,7 +2559,7 @@ Id Builder::createCompositeInsert(Id object, Id composite, Id typeId, unsigned i
     insert->addIdOperand(object);
     insert->addIdOperand(object);
     insert->addIdOperand(composite);
     insert->addIdOperand(composite);
     insert->addImmediateOperand(index);
     insert->addImmediateOperand(index);
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(insert));
+    addInstruction(std::unique_ptr<Instruction>(insert));
 
 
     return insert->getResultId();
     return insert->getResultId();
 }
 }
@@ -2604,7 +2571,7 @@ Id Builder::createCompositeInsert(Id object, Id composite, Id typeId, const std:
     insert->addIdOperand(composite);
     insert->addIdOperand(composite);
     for (int i = 0; i < (int)indexes.size(); ++i)
     for (int i = 0; i < (int)indexes.size(); ++i)
         insert->addImmediateOperand(indexes[i]);
         insert->addImmediateOperand(indexes[i]);
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(insert));
+    addInstruction(std::unique_ptr<Instruction>(insert));
 
 
     return insert->getResultId();
     return insert->getResultId();
 }
 }
@@ -2614,7 +2581,7 @@ Id Builder::createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex)
     Instruction* extract = new Instruction(getUniqueId(), typeId, OpVectorExtractDynamic);
     Instruction* extract = new Instruction(getUniqueId(), typeId, OpVectorExtractDynamic);
     extract->addIdOperand(vector);
     extract->addIdOperand(vector);
     extract->addIdOperand(componentIndex);
     extract->addIdOperand(componentIndex);
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(extract));
+    addInstruction(std::unique_ptr<Instruction>(extract));
 
 
     return extract->getResultId();
     return extract->getResultId();
 }
 }
@@ -2625,7 +2592,7 @@ Id Builder::createVectorInsertDynamic(Id vector, Id typeId, Id component, Id com
     insert->addIdOperand(vector);
     insert->addIdOperand(vector);
     insert->addIdOperand(component);
     insert->addIdOperand(component);
     insert->addIdOperand(componentIndex);
     insert->addIdOperand(componentIndex);
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(insert));
+    addInstruction(std::unique_ptr<Instruction>(insert));
 
 
     return insert->getResultId();
     return insert->getResultId();
 }
 }
@@ -2634,7 +2601,7 @@ Id Builder::createVectorInsertDynamic(Id vector, Id typeId, Id component, Id com
 void Builder::createNoResultOp(Op opCode)
 void Builder::createNoResultOp(Op opCode)
 {
 {
     Instruction* op = new Instruction(opCode);
     Instruction* op = new Instruction(opCode);
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
+    addInstruction(std::unique_ptr<Instruction>(op));
 }
 }
 
 
 // An opcode that has one id operand, no result id, and no type
 // An opcode that has one id operand, no result id, and no type
@@ -2642,7 +2609,7 @@ void Builder::createNoResultOp(Op opCode, Id operand)
 {
 {
     Instruction* op = new Instruction(opCode);
     Instruction* op = new Instruction(opCode);
     op->addIdOperand(operand);
     op->addIdOperand(operand);
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
+    addInstruction(std::unique_ptr<Instruction>(op));
 }
 }
 
 
 // An opcode that has one or more operands, no result id, and no type
 // An opcode that has one or more operands, no result id, and no type
@@ -2652,7 +2619,7 @@ void Builder::createNoResultOp(Op opCode, const std::vector<Id>& operands)
     for (auto it = operands.cbegin(); it != operands.cend(); ++it) {
     for (auto it = operands.cbegin(); it != operands.cend(); ++it) {
         op->addIdOperand(*it);
         op->addIdOperand(*it);
     }
     }
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
+    addInstruction(std::unique_ptr<Instruction>(op));
 }
 }
 
 
 // An opcode that has multiple operands, no result id, and no type
 // An opcode that has multiple operands, no result id, and no type
@@ -2665,7 +2632,7 @@ void Builder::createNoResultOp(Op opCode, const std::vector<IdImmediate>& operan
         else
         else
             op->addImmediateOperand(it->word);
             op->addImmediateOperand(it->word);
     }
     }
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
+    addInstruction(std::unique_ptr<Instruction>(op));
 }
 }
 
 
 void Builder::createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask semantics)
 void Builder::createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask semantics)
@@ -2674,7 +2641,7 @@ void Builder::createControlBarrier(Scope execution, Scope memory, MemorySemantic
     op->addIdOperand(makeUintConstant(execution));
     op->addIdOperand(makeUintConstant(execution));
     op->addIdOperand(makeUintConstant(memory));
     op->addIdOperand(makeUintConstant(memory));
     op->addIdOperand(makeUintConstant(semantics));
     op->addIdOperand(makeUintConstant(semantics));
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
+    addInstruction(std::unique_ptr<Instruction>(op));
 }
 }
 
 
 void Builder::createMemoryBarrier(unsigned executionScope, unsigned memorySemantics)
 void Builder::createMemoryBarrier(unsigned executionScope, unsigned memorySemantics)
@@ -2682,7 +2649,7 @@ void Builder::createMemoryBarrier(unsigned executionScope, unsigned memorySemant
     Instruction* op = new Instruction(OpMemoryBarrier);
     Instruction* op = new Instruction(OpMemoryBarrier);
     op->addIdOperand(makeUintConstant(executionScope));
     op->addIdOperand(makeUintConstant(executionScope));
     op->addIdOperand(makeUintConstant(memorySemantics));
     op->addIdOperand(makeUintConstant(memorySemantics));
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
+    addInstruction(std::unique_ptr<Instruction>(op));
 }
 }
 
 
 // An opcode that has one operands, a result id, and a type
 // An opcode that has one operands, a result id, and a type
@@ -2695,7 +2662,7 @@ Id Builder::createUnaryOp(Op opCode, Id typeId, Id operand)
     }
     }
     Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
     Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
     op->addIdOperand(operand);
     op->addIdOperand(operand);
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
+    addInstruction(std::unique_ptr<Instruction>(op));
 
 
     return op->getResultId();
     return op->getResultId();
 }
 }
@@ -2712,7 +2679,7 @@ Id Builder::createBinOp(Op opCode, Id typeId, Id left, Id right)
     Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
     Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
     op->addIdOperand(left);
     op->addIdOperand(left);
     op->addIdOperand(right);
     op->addIdOperand(right);
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
+    addInstruction(std::unique_ptr<Instruction>(op));
 
 
     return op->getResultId();
     return op->getResultId();
 }
 }
@@ -2733,7 +2700,7 @@ Id Builder::createTriOp(Op opCode, Id typeId, Id op1, Id op2, Id op3)
     op->addIdOperand(op1);
     op->addIdOperand(op1);
     op->addIdOperand(op2);
     op->addIdOperand(op2);
     op->addIdOperand(op3);
     op->addIdOperand(op3);
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
+    addInstruction(std::unique_ptr<Instruction>(op));
 
 
     return op->getResultId();
     return op->getResultId();
 }
 }
@@ -2743,7 +2710,7 @@ Id Builder::createOp(Op opCode, Id typeId, const std::vector<Id>& operands)
     Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
     Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
     for (auto it = operands.cbegin(); it != operands.cend(); ++it)
     for (auto it = operands.cbegin(); it != operands.cend(); ++it)
         op->addIdOperand(*it);
         op->addIdOperand(*it);
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
+    addInstruction(std::unique_ptr<Instruction>(op));
 
 
     return op->getResultId();
     return op->getResultId();
 }
 }
@@ -2757,7 +2724,7 @@ Id Builder::createOp(Op opCode, Id typeId, const std::vector<IdImmediate>& opera
         else
         else
             op->addImmediateOperand(it->word);
             op->addImmediateOperand(it->word);
     }
     }
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
+    addInstruction(std::unique_ptr<Instruction>(op));
 
 
     return op->getResultId();
     return op->getResultId();
 }
 }
@@ -2791,7 +2758,7 @@ Id Builder::createFunctionCall(spv::Function* function, const std::vector<spv::I
     op->addIdOperand(function->getId());
     op->addIdOperand(function->getId());
     for (int a = 0; a < (int)args.size(); ++a)
     for (int a = 0; a < (int)args.size(); ++a)
         op->addIdOperand(args[a]);
         op->addIdOperand(args[a]);
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
+    addInstruction(std::unique_ptr<Instruction>(op));
 
 
     return op->getResultId();
     return op->getResultId();
 }
 }
@@ -2813,7 +2780,7 @@ Id Builder::createRvalueSwizzle(Decoration precision, Id typeId, Id source, cons
     swizzle->addIdOperand(source);
     swizzle->addIdOperand(source);
     for (int i = 0; i < (int)channels.size(); ++i)
     for (int i = 0; i < (int)channels.size(); ++i)
         swizzle->addImmediateOperand(channels[i]);
         swizzle->addImmediateOperand(channels[i]);
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(swizzle));
+    addInstruction(std::unique_ptr<Instruction>(swizzle));
 
 
     return setPrecision(swizzle->getResultId(), precision);
     return setPrecision(swizzle->getResultId(), precision);
 }
 }
@@ -2846,7 +2813,7 @@ Id Builder::createLvalueSwizzle(Id typeId, Id target, Id source, const std::vect
     // finish the instruction with these components selectors
     // finish the instruction with these components selectors
     for (int i = 0; i < numTargetComponents; ++i)
     for (int i = 0; i < numTargetComponents; ++i)
         swizzle->addImmediateOperand(components[i]);
         swizzle->addImmediateOperand(components[i]);
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(swizzle));
+    addInstruction(std::unique_ptr<Instruction>(swizzle));
 
 
     return swizzle->getResultId();
     return swizzle->getResultId();
 }
 }
@@ -2891,7 +2858,7 @@ Id Builder::smearScalar(Decoration precision, Id scalar, Id vectorType)
         smear = new Instruction(getUniqueId(), vectorType, OpCompositeConstruct);
         smear = new Instruction(getUniqueId(), vectorType, OpCompositeConstruct);
         for (int c = 0; c < numComponents; ++c)
         for (int c = 0; c < numComponents; ++c)
             smear->addIdOperand(scalar);
             smear->addIdOperand(scalar);
-        buildPoint->addInstruction(std::unique_ptr<Instruction>(smear));
+        addInstruction(std::unique_ptr<Instruction>(smear));
     }
     }
 
 
     return setPrecision(smear->getResultId(), precision);
     return setPrecision(smear->getResultId(), precision);
@@ -2906,7 +2873,7 @@ Id Builder::createBuiltinCall(Id resultType, Id builtins, int entryPoint, const
     for (int arg = 0; arg < (int)args.size(); ++arg)
     for (int arg = 0; arg < (int)args.size(); ++arg)
         inst->addIdOperand(args[arg]);
         inst->addIdOperand(args[arg]);
 
 
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(inst));
+    addInstruction(std::unique_ptr<Instruction>(inst));
 
 
     return inst->getResultId();
     return inst->getResultId();
 }
 }
@@ -3102,7 +3069,7 @@ Id Builder::createTextureCall(Decoration precision, Id resultType, bool sparse,
     for (size_t op = optArgNum + 1; op < texArgs.size(); ++op)
     for (size_t op = optArgNum + 1; op < texArgs.size(); ++op)
         textureInst->addIdOperand(texArgs[op]);
         textureInst->addIdOperand(texArgs[op]);
     setPrecision(textureInst->getResultId(), precision);
     setPrecision(textureInst->getResultId(), precision);
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(textureInst));
+    addInstruction(std::unique_ptr<Instruction>(textureInst));
 
 
     Id resultId = textureInst->getResultId();
     Id resultId = textureInst->getResultId();
 
 
@@ -3182,7 +3149,7 @@ Id Builder::createTextureQueryCall(Op opCode, const TextureParameters& parameter
         query->addIdOperand(parameters.coords);
         query->addIdOperand(parameters.coords);
     if (parameters.lod)
     if (parameters.lod)
         query->addIdOperand(parameters.lod);
         query->addIdOperand(parameters.lod);
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(query));
+    addInstruction(std::unique_ptr<Instruction>(query));
     addCapability(CapabilityImageQuery);
     addCapability(CapabilityImageQuery);
 
 
     return query->getResultId();
     return query->getResultId();
@@ -3281,7 +3248,7 @@ Id Builder::createCompositeConstruct(Id typeId, const std::vector<Id>& constitue
     Instruction* op = new Instruction(getUniqueId(), typeId, OpCompositeConstruct);
     Instruction* op = new Instruction(getUniqueId(), typeId, OpCompositeConstruct);
     for (int c = 0; c < (int)constituents.size(); ++c)
     for (int c = 0; c < (int)constituents.size(); ++c)
         op->addIdOperand(constituents[c]);
         op->addIdOperand(constituents[c]);
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
+    addInstruction(std::unique_ptr<Instruction>(op));
 
 
     return op->getResultId();
     return op->getResultId();
 }
 }
@@ -3577,7 +3544,7 @@ void Builder::makeSwitch(Id selector, unsigned int control, int numSegments, con
         switchInst->addIdOperand(segmentBlocks[valueIndexToSegment[i]]->getId());
         switchInst->addIdOperand(segmentBlocks[valueIndexToSegment[i]]->getId());
         segmentBlocks[valueIndexToSegment[i]]->addPredecessor(buildPoint);
         segmentBlocks[valueIndexToSegment[i]]->addPredecessor(buildPoint);
     }
     }
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(switchInst));
+    addInstruction(std::unique_ptr<Instruction>(switchInst));
 
 
     // push the merge block
     // push the merge block
     switchMerges.push(mergeBlock);
     switchMerges.push(mergeBlock);
@@ -4096,7 +4063,7 @@ void Builder::createBranch(Block* block)
 {
 {
     Instruction* branch = new Instruction(OpBranch);
     Instruction* branch = new Instruction(OpBranch);
     branch->addIdOperand(block->getId());
     branch->addIdOperand(block->getId());
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(branch));
+    addInstruction(std::unique_ptr<Instruction>(branch));
     block->addPredecessor(buildPoint);
     block->addPredecessor(buildPoint);
 }
 }
 
 
@@ -4105,7 +4072,7 @@ void Builder::createSelectionMerge(Block* mergeBlock, unsigned int control)
     Instruction* merge = new Instruction(OpSelectionMerge);
     Instruction* merge = new Instruction(OpSelectionMerge);
     merge->addIdOperand(mergeBlock->getId());
     merge->addIdOperand(mergeBlock->getId());
     merge->addImmediateOperand(control);
     merge->addImmediateOperand(control);
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(merge));
+    addInstruction(std::unique_ptr<Instruction>(merge));
 }
 }
 
 
 void Builder::createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control,
 void Builder::createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control,
@@ -4117,7 +4084,7 @@ void Builder::createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned
     merge->addImmediateOperand(control);
     merge->addImmediateOperand(control);
     for (int op = 0; op < (int)operands.size(); ++op)
     for (int op = 0; op < (int)operands.size(); ++op)
         merge->addImmediateOperand(operands[op]);
         merge->addImmediateOperand(operands[op]);
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(merge));
+    addInstruction(std::unique_ptr<Instruction>(merge));
 }
 }
 
 
 void Builder::createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock)
 void Builder::createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock)
@@ -4126,7 +4093,7 @@ void Builder::createConditionalBranch(Id condition, Block* thenBlock, Block* els
     branch->addIdOperand(condition);
     branch->addIdOperand(condition);
     branch->addIdOperand(thenBlock->getId());
     branch->addIdOperand(thenBlock->getId());
     branch->addIdOperand(elseBlock->getId());
     branch->addIdOperand(elseBlock->getId());
-    buildPoint->addInstruction(std::unique_ptr<Instruction>(branch));
+    addInstruction(std::unique_ptr<Instruction>(branch));
     thenBlock->addPredecessor(buildPoint);
     thenBlock->addPredecessor(buildPoint);
     elseBlock->addPredecessor(buildPoint);
     elseBlock->addPredecessor(buildPoint);
 }
 }
@@ -4178,7 +4145,7 @@ void Builder::dumpSourceInstructions(const spv::Id fileId, const std::string& te
 void Builder::dumpSourceInstructions(std::vector<unsigned int>& out) const
 void Builder::dumpSourceInstructions(std::vector<unsigned int>& out) const
 {
 {
     if (emitNonSemanticShaderDebugInfo) return;
     if (emitNonSemanticShaderDebugInfo) return;
-    dumpSourceInstructions(sourceFileStringId, sourceText, out);
+    dumpSourceInstructions(mainFileId, sourceText, out);
     for (auto iItr = includeFiles.begin(); iItr != includeFiles.end(); ++iItr)
     for (auto iItr = includeFiles.begin(); iItr != includeFiles.end(); ++iItr)
         dumpSourceInstructions(iItr->first, *iItr->second, out);
         dumpSourceInstructions(iItr->first, *iItr->second, out);
 }
 }

+ 71 - 42
3rdparty/glslang/SPIRV/SpvBuilder.h

@@ -103,31 +103,53 @@ public:
         stringIds[file_c_str] = strId;
         stringIds[file_c_str] = strId;
         return strId;
         return strId;
     }
     }
-    spv::Id getSourceFile() const
+
+    spv::Id getMainFileId() const { return mainFileId; }
+
+    // Initialize the main source file name
+    void setDebugSourceFile(const std::string& file)
     {
     {
-        return sourceFileStringId;
+        if (trackDebugInfo) {
+            dirtyLineTracker = true;
+            mainFileId = getStringId(file);
+            currentFileId = mainFileId;
+        }
     }
     }
-    void setSourceFile(const std::string& file)
+
+    // Set the debug source location tracker in the builder.
+    // The upcoming instructions in basic blocks will be associated to this location.
+    void setDebugSourceLocation(int line, const char* filename)
     {
     {
-        sourceFileStringId = getStringId(file);
-        currentFileId = sourceFileStringId;
+        if (trackDebugInfo) {
+            dirtyLineTracker = true;
+            if (line != 0) {
+                // TODO: This is special handling of some AST nodes having (untracked) line 0. 
+                //       But they should have a valid line number.
+                currentLine = line;
+                if (filename) {
+                    currentFileId = getStringId(filename);
+                }
+            }
+        }
     }
     }
+
     void setSourceText(const std::string& text) { sourceText = text; }
     void setSourceText(const std::string& text) { sourceText = text; }
     void addSourceExtension(const char* ext) { sourceExtensions.push_back(ext); }
     void addSourceExtension(const char* ext) { sourceExtensions.push_back(ext); }
     void addModuleProcessed(const std::string& p) { moduleProcesses.push_back(p.c_str()); }
     void addModuleProcessed(const std::string& p) { moduleProcesses.push_back(p.c_str()); }
-    void setEmitOpLines() { emitOpLines = true; }
-    void setEmitNonSemanticShaderDebugInfo(bool const emit)
+    void setEmitSpirvDebugInfo()
     {
     {
-        emitNonSemanticShaderDebugInfo = emit;
-
-        if(emit)
-        {
-            importNonSemanticShaderDebugInfoInstructions();
-        }
+        trackDebugInfo = true;
+        emitSpirvDebugInfo = true;
     }
     }
-    void setEmitNonSemanticShaderDebugSource(bool const src)
+    void setEmitNonSemanticShaderDebugInfo(bool emitSourceText)
     {
     {
-        emitNonSemanticShaderDebugSource = src;
+        trackDebugInfo = true;
+        emitNonSemanticShaderDebugInfo = true;
+        importNonSemanticShaderDebugInfoInstructions();
+
+        if (emitSourceText) {
+            emitNonSemanticShaderDebugSource = emitSourceText;
+        }
     }
     }
     void addExtension(const char* ext) { extensions.insert(ext); }
     void addExtension(const char* ext) { extensions.insert(ext); }
     void removeExtension(const char* ext)
     void removeExtension(const char* ext)
@@ -169,20 +191,6 @@ public:
         return id;
         return id;
     }
     }
 
 
-    // Generate OpLine for non-filename-based #line directives (ie no filename
-    // seen yet): Log the current line, and if different than the last one,
-    // issue a new OpLine using the new line and current source file name.
-    void setLine(int line);
-
-    // If filename null, generate OpLine for non-filename-based line directives,
-    // else do filename-based: Log the current line and file, and if different
-    // than the last one, issue a new OpLine using the new line and file
-    // name.
-    void setLine(int line, const char* filename);
-    // Low-level OpLine. See setLine() for a layered helper.
-    void addLine(Id fileName, int line, int column);
-    void addDebugScopeAndLine(Id fileName, int line, int column);
-
     // For creating new types (will return old type if the requested one was already made).
     // For creating new types (will return old type if the requested one was already made).
     Id makeVoidType();
     Id makeVoidType();
     Id makeBoolType();
     Id makeBoolType();
@@ -409,11 +417,16 @@ public:
     // Also reset current last DebugScope and current source line to unknown
     // Also reset current last DebugScope and current source line to unknown
     void setBuildPoint(Block* bp) {
     void setBuildPoint(Block* bp) {
         buildPoint = bp;
         buildPoint = bp;
-        lastDebugScopeId = NoResult;
-        currentLine = 0;
+        // TODO: Technically, change of build point should set line tracker dirty. But we'll have bad line info for
+        //       branch instructions. Commenting this for now because at least this matches the old behavior.
+        dirtyScopeTracker = true;
     }
     }
     Block* getBuildPoint() const { return buildPoint; }
     Block* getBuildPoint() const { return buildPoint; }
 
 
+    // Append an instruction to the end of the current build point.
+    // Optionally, additional debug info instructions may also be prepended.
+    void addInstruction(std::unique_ptr<Instruction> inst);
+
     // Make the entry-point function. The returned pointer is only valid
     // Make the entry-point function. The returned pointer is only valid
     // for the lifetime of this builder.
     // for the lifetime of this builder.
     Function* makeEntryPoint(const char*);
     Function* makeEntryPoint(const char*);
@@ -430,10 +443,10 @@ public:
     void makeReturn(bool implicit, Id retVal = 0);
     void makeReturn(bool implicit, Id retVal = 0);
 
 
     // Initialize state and generate instructions for new lexical scope
     // Initialize state and generate instructions for new lexical scope
-    void enterScope(uint32_t line);
+    void enterLexicalBlock(uint32_t line);
 
 
     // Set state and generate instructions to exit current lexical scope
     // Set state and generate instructions to exit current lexical scope
-    void leaveScope();
+    void leaveLexicalBlock();
 
 
     // Prepare builder for generation of instructions for a function.
     // Prepare builder for generation of instructions for a function.
     void enterFunction(Function const* function);
     void enterFunction(Function const* function);
@@ -882,21 +895,37 @@ public:
     unsigned int spvVersion;     // the version of SPIR-V to emit in the header
     unsigned int spvVersion;     // the version of SPIR-V to emit in the header
     SourceLanguage sourceLang;
     SourceLanguage sourceLang;
     int sourceVersion;
     int sourceVersion;
-    spv::Id sourceFileStringId;
     spv::Id nonSemanticShaderCompilationUnitId {0};
     spv::Id nonSemanticShaderCompilationUnitId {0};
     spv::Id nonSemanticShaderDebugInfo {0};
     spv::Id nonSemanticShaderDebugInfo {0};
     spv::Id debugInfoNone {0};
     spv::Id debugInfoNone {0};
     spv::Id debugExpression {0}; // Debug expression with zero operations.
     spv::Id debugExpression {0}; // Debug expression with zero operations.
     std::string sourceText;
     std::string sourceText;
-    int currentLine;
-    const char* currentFile;
-    spv::Id currentFileId;
+
+    // True if an new OpLine/OpDebugLine may need to be inserted. Either:
+    // 1. The current debug location changed
+    // 2. The current build point changed
+    bool dirtyLineTracker;
+    int currentLine = 0;
+    // OpString id of the current file name. Always 0 if debug info is off.
+    spv::Id currentFileId = 0;
+    // OpString id of the main file name. Always 0 if debug info is off.
+    spv::Id mainFileId = 0;
+
+    // True if an new OpDebugScope may need to be inserted. Either:
+    // 1. A new lexical block is pushed
+    // 2. The current build point changed
+    bool dirtyScopeTracker;
     std::stack<spv::Id> currentDebugScopeId;
     std::stack<spv::Id> currentDebugScopeId;
-    spv::Id lastDebugScopeId;
-    bool emitOpLines;
-    bool emitNonSemanticShaderDebugInfo;
-    bool restoreNonSemanticShaderDebugInfo;
-    bool emitNonSemanticShaderDebugSource;
+
+    // This flag toggles tracking of debug info while building the SPIR-V.
+    bool trackDebugInfo = false;
+    // This flag toggles emission of SPIR-V debug instructions, like OpLine and OpSource.
+    bool emitSpirvDebugInfo = false;
+    // This flag toggles emission of Non-Semantic Debug extension debug instructions.
+    bool emitNonSemanticShaderDebugInfo = false;
+    bool restoreNonSemanticShaderDebugInfo = false;
+    bool emitNonSemanticShaderDebugSource = false;
+
     std::set<std::string> extensions;
     std::set<std::string> extensions;
     std::vector<const char*> sourceExtensions;
     std::vector<const char*> sourceExtensions;
     std::vector<const char*> moduleProcesses;
     std::vector<const char*> moduleProcesses;

+ 28 - 1
3rdparty/glslang/SPIRV/doc.cpp

@@ -1,5 +1,6 @@
 //
 //
 // Copyright (C) 2014-2015 LunarG, Inc.
 // Copyright (C) 2014-2015 LunarG, Inc.
+// Copyright (C) 2022-2024 Arm Limited.
 // Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 // Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 //
 // All rights reserved.
 // All rights reserved.
@@ -198,6 +199,7 @@ const char* ExecutionModeString(int mode)
     case ExecutionModeStencilRefGreaterBackAMD:      return "StencilRefGreaterBackAMD";
     case ExecutionModeStencilRefGreaterBackAMD:      return "StencilRefGreaterBackAMD";
     case ExecutionModeStencilRefReplacingEXT:        return "StencilRefReplacingEXT";
     case ExecutionModeStencilRefReplacingEXT:        return "StencilRefReplacingEXT";
     case ExecutionModeSubgroupUniformControlFlowKHR: return "SubgroupUniformControlFlow";
     case ExecutionModeSubgroupUniformControlFlowKHR: return "SubgroupUniformControlFlow";
+    case ExecutionModeMaximallyReconvergesKHR:       return "MaximallyReconverges";
 
 
     case ExecutionModeOutputLinesNV:                 return "OutputLinesNV";
     case ExecutionModeOutputLinesNV:                 return "OutputLinesNV";
     case ExecutionModeOutputPrimitivesNV:            return "OutputPrimitivesNV";
     case ExecutionModeOutputPrimitivesNV:            return "OutputPrimitivesNV";
@@ -217,6 +219,9 @@ const char* ExecutionModeString(int mode)
     case ExecutionModeNoGlobalOffsetINTEL:      return "NoGlobalOffsetINTEL";
     case ExecutionModeNoGlobalOffsetINTEL:      return "NoGlobalOffsetINTEL";
     case ExecutionModeNumSIMDWorkitemsINTEL:    return "NumSIMDWorkitemsINTEL";
     case ExecutionModeNumSIMDWorkitemsINTEL:    return "NumSIMDWorkitemsINTEL";
 
 
+    case ExecutionModeRequireFullQuadsKHR:      return "RequireFullQuadsKHR";
+    case ExecutionModeQuadDerivativesKHR:       return "QuadDerivativesKHR";
+
     case ExecutionModeNonCoherentColorAttachmentReadEXT:        return "NonCoherentColorAttachmentReadEXT";
     case ExecutionModeNonCoherentColorAttachmentReadEXT:        return "NonCoherentColorAttachmentReadEXT";
     case ExecutionModeNonCoherentDepthAttachmentReadEXT:        return "NonCoherentDepthAttachmentReadEXT";
     case ExecutionModeNonCoherentDepthAttachmentReadEXT:        return "NonCoherentDepthAttachmentReadEXT";
     case ExecutionModeNonCoherentStencilAttachmentReadEXT:      return "NonCoherentStencilAttachmentReadEXT";
     case ExecutionModeNonCoherentStencilAttachmentReadEXT:      return "NonCoherentStencilAttachmentReadEXT";
@@ -938,6 +943,7 @@ const char* CapabilityString(int info)
     case CapabilitySubgroupBallotKHR: return "SubgroupBallotKHR";
     case CapabilitySubgroupBallotKHR: return "SubgroupBallotKHR";
     case CapabilityDrawParameters:    return "DrawParameters";
     case CapabilityDrawParameters:    return "DrawParameters";
     case CapabilitySubgroupVoteKHR:   return "SubgroupVoteKHR";
     case CapabilitySubgroupVoteKHR:   return "SubgroupVoteKHR";
+    case CapabilityGroupNonUniformRotateKHR: return "CapabilityGroupNonUniformRotateKHR";
 
 
     case CapabilityStorageUniformBufferBlock16: return "StorageUniformBufferBlock16";
     case CapabilityStorageUniformBufferBlock16: return "StorageUniformBufferBlock16";
     case CapabilityStorageUniform16:            return "StorageUniform16";
     case CapabilityStorageUniform16:            return "StorageUniform16";
@@ -1032,6 +1038,7 @@ const char* CapabilityString(int info)
 
 
     case CapabilityDemoteToHelperInvocationEXT:             return "DemoteToHelperInvocationEXT";
     case CapabilityDemoteToHelperInvocationEXT:             return "DemoteToHelperInvocationEXT";
     case CapabilityShaderClockKHR:                          return "ShaderClockKHR";
     case CapabilityShaderClockKHR:                          return "ShaderClockKHR";
+    case CapabilityQuadControlKHR:                          return "QuadControlKHR";
     case CapabilityInt64ImageEXT:                           return "Int64ImageEXT";
     case CapabilityInt64ImageEXT:                           return "Int64ImageEXT";
 
 
     case CapabilityIntegerFunctions2INTEL:              return "CapabilityIntegerFunctions2INTEL";
     case CapabilityIntegerFunctions2INTEL:              return "CapabilityIntegerFunctions2INTEL";
@@ -1432,10 +1439,16 @@ const char* OpcodeString(int op)
     case 4430: return "OpSubgroupAllEqualKHR";
     case 4430: return "OpSubgroupAllEqualKHR";
     case 4432: return "OpSubgroupReadInvocationKHR";
     case 4432: return "OpSubgroupReadInvocationKHR";
 
 
+    case OpGroupNonUniformQuadAllKHR: return "OpGroupNonUniformQuadAllKHR";
+    case OpGroupNonUniformQuadAnyKHR: return "OpGroupNonUniformQuadAnyKHR";
+
     case OpAtomicFAddEXT: return "OpAtomicFAddEXT";
     case OpAtomicFAddEXT: return "OpAtomicFAddEXT";
     case OpAtomicFMinEXT: return "OpAtomicFMinEXT";
     case OpAtomicFMinEXT: return "OpAtomicFMinEXT";
     case OpAtomicFMaxEXT: return "OpAtomicFMaxEXT";
     case OpAtomicFMaxEXT: return "OpAtomicFMaxEXT";
 
 
+    case OpAssumeTrueKHR: return "OpAssumeTrueKHR";
+    case OpExpectKHR: return "OpExpectKHR";
+
     case 5000: return "OpGroupIAddNonUniformAMD";
     case 5000: return "OpGroupIAddNonUniformAMD";
     case 5001: return "OpGroupFAddNonUniformAMD";
     case 5001: return "OpGroupFAddNonUniformAMD";
     case 5002: return "OpGroupFMinNonUniformAMD";
     case 5002: return "OpGroupFMinNonUniformAMD";
@@ -1472,6 +1485,8 @@ const char* OpcodeString(int op)
     case OpEmitMeshTasksEXT:                 return "OpEmitMeshTasksEXT";
     case OpEmitMeshTasksEXT:                 return "OpEmitMeshTasksEXT";
     case OpSetMeshOutputsEXT:                return "OpSetMeshOutputsEXT";
     case OpSetMeshOutputsEXT:                return "OpSetMeshOutputsEXT";
 
 
+    case OpGroupNonUniformRotateKHR:         return "OpGroupNonUniformRotateKHR";
+
     case OpTypeRayQueryKHR:                                                   return "OpTypeRayQueryKHR";
     case OpTypeRayQueryKHR:                                                   return "OpTypeRayQueryKHR";
     case OpRayQueryInitializeKHR:                                             return "OpRayQueryInitializeKHR";
     case OpRayQueryInitializeKHR:                                             return "OpRayQueryInitializeKHR";
     case OpRayQueryTerminateKHR:                                              return "OpRayQueryTerminateKHR";
     case OpRayQueryTerminateKHR:                                              return "OpRayQueryTerminateKHR";
@@ -1678,7 +1693,7 @@ void Parameterize()
         InstructionDesc[OpCooperativeMatrixStoreKHR].setResultAndType(false, false);
         InstructionDesc[OpCooperativeMatrixStoreKHR].setResultAndType(false, false);
         InstructionDesc[OpBeginInvocationInterlockEXT].setResultAndType(false, false);
         InstructionDesc[OpBeginInvocationInterlockEXT].setResultAndType(false, false);
         InstructionDesc[OpEndInvocationInterlockEXT].setResultAndType(false, false);
         InstructionDesc[OpEndInvocationInterlockEXT].setResultAndType(false, false);
-
+        InstructionDesc[OpAssumeTrueKHR].setResultAndType(false, false);
         // Specific additional context-dependent operands
         // Specific additional context-dependent operands
 
 
         ExecutionModeOperands[ExecutionModeInvocations].push(OperandLiteralNumber, "'Number of <<Invocation,invocations>>'");
         ExecutionModeOperands[ExecutionModeInvocations].push(OperandLiteralNumber, "'Number of <<Invocation,invocations>>'");
@@ -2457,6 +2472,11 @@ void Parameterize()
         InstructionDesc[OpAtomicFAddEXT].operands.push(OperandMemorySemantics, "'Semantics'");
         InstructionDesc[OpAtomicFAddEXT].operands.push(OperandMemorySemantics, "'Semantics'");
         InstructionDesc[OpAtomicFAddEXT].operands.push(OperandId, "'Value'");
         InstructionDesc[OpAtomicFAddEXT].operands.push(OperandId, "'Value'");
 
 
+        InstructionDesc[OpAssumeTrueKHR].operands.push(OperandId, "'Condition'");
+
+        InstructionDesc[OpExpectKHR].operands.push(OperandId, "'Value'");
+        InstructionDesc[OpExpectKHR].operands.push(OperandId, "'ExpectedValue'");
+
         InstructionDesc[OpAtomicISub].operands.push(OperandId, "'Pointer'");
         InstructionDesc[OpAtomicISub].operands.push(OperandId, "'Pointer'");
         InstructionDesc[OpAtomicISub].operands.push(OperandScope, "'Scope'");
         InstructionDesc[OpAtomicISub].operands.push(OperandScope, "'Scope'");
         InstructionDesc[OpAtomicISub].operands.push(OperandMemorySemantics, "'Semantics'");
         InstructionDesc[OpAtomicISub].operands.push(OperandMemorySemantics, "'Semantics'");
@@ -2885,6 +2905,11 @@ void Parameterize()
         InstructionDesc[OpSubgroupAllEqualKHR].operands.push(OperandScope, "'Execution'");
         InstructionDesc[OpSubgroupAllEqualKHR].operands.push(OperandScope, "'Execution'");
         InstructionDesc[OpSubgroupAllEqualKHR].operands.push(OperandId, "'Predicate'");
         InstructionDesc[OpSubgroupAllEqualKHR].operands.push(OperandId, "'Predicate'");
 
 
+        InstructionDesc[OpGroupNonUniformRotateKHR].operands.push(OperandScope, "'Execution'");
+        InstructionDesc[OpGroupNonUniformRotateKHR].operands.push(OperandId, "'X'");
+        InstructionDesc[OpGroupNonUniformRotateKHR].operands.push(OperandId, "'Delta'");
+        InstructionDesc[OpGroupNonUniformRotateKHR].operands.push(OperandId, "'ClusterSize'", true);
+
         InstructionDesc[OpSubgroupReadInvocationKHR].operands.push(OperandId, "'Value'");
         InstructionDesc[OpSubgroupReadInvocationKHR].operands.push(OperandId, "'Value'");
         InstructionDesc[OpSubgroupReadInvocationKHR].operands.push(OperandId, "'Index'");
         InstructionDesc[OpSubgroupReadInvocationKHR].operands.push(OperandId, "'Index'");
 
 
@@ -2931,6 +2956,8 @@ void Parameterize()
 
 
         InstructionDesc[OpGroupNonUniformPartitionNV].operands.push(OperandId, "X");
         InstructionDesc[OpGroupNonUniformPartitionNV].operands.push(OperandId, "X");
 
 
+        InstructionDesc[OpGroupNonUniformQuadAllKHR].operands.push(OperandId, "'Predicate'");
+        InstructionDesc[OpGroupNonUniformQuadAnyKHR].operands.push(OperandId, "'Predicate'");
         InstructionDesc[OpTypeAccelerationStructureKHR].setResultAndType(true, false);
         InstructionDesc[OpTypeAccelerationStructureKHR].setResultAndType(true, false);
 
 
         InstructionDesc[OpTraceNV].operands.push(OperandId, "'Acceleration Structure'");
         InstructionDesc[OpTraceNV].operands.push(OperandId, "'Acceleration Structure'");

+ 8 - 0
3rdparty/glslang/SPIRV/spirv.hpp

@@ -174,6 +174,8 @@ enum ExecutionMode {
     ExecutionModeStencilRefUnchangedBackAMD = 5082,
     ExecutionModeStencilRefUnchangedBackAMD = 5082,
     ExecutionModeStencilRefGreaterBackAMD = 5083,
     ExecutionModeStencilRefGreaterBackAMD = 5083,
     ExecutionModeStencilRefLessBackAMD = 5084,
     ExecutionModeStencilRefLessBackAMD = 5084,
+    ExecutionModeQuadDerivativesKHR  = 5088,
+    ExecutionModeRequireFullQuadsKHR = 5089,
     ExecutionModeOutputLinesEXT = 5269,
     ExecutionModeOutputLinesEXT = 5269,
     ExecutionModeOutputLinesNV = 5269,
     ExecutionModeOutputLinesNV = 5269,
     ExecutionModeOutputPrimitivesEXT = 5270,
     ExecutionModeOutputPrimitivesEXT = 5270,
@@ -198,6 +200,7 @@ enum ExecutionMode {
     ExecutionModeNoGlobalOffsetINTEL = 5895,
     ExecutionModeNoGlobalOffsetINTEL = 5895,
     ExecutionModeNumSIMDWorkitemsINTEL = 5896,
     ExecutionModeNumSIMDWorkitemsINTEL = 5896,
     ExecutionModeSchedulerTargetFmaxMhzINTEL = 5903,
     ExecutionModeSchedulerTargetFmaxMhzINTEL = 5903,
+    ExecutionModeMaximallyReconvergesKHR = 6023,
     ExecutionModeStreamingInterfaceINTEL = 6154,
     ExecutionModeStreamingInterfaceINTEL = 6154,
     ExecutionModeNamedBarrierCountINTEL = 6417,
     ExecutionModeNamedBarrierCountINTEL = 6417,
     ExecutionModeMax = 0x7fffffff,
     ExecutionModeMax = 0x7fffffff,
@@ -1039,6 +1042,7 @@ enum Capability {
     CapabilityImageReadWriteLodAMD = 5015,
     CapabilityImageReadWriteLodAMD = 5015,
     CapabilityInt64ImageEXT = 5016,
     CapabilityInt64ImageEXT = 5016,
     CapabilityShaderClockKHR = 5055,
     CapabilityShaderClockKHR = 5055,
+    CapabilityQuadControlKHR = 5087,
     CapabilitySampleMaskOverrideCoverageNV = 5249,
     CapabilitySampleMaskOverrideCoverageNV = 5249,
     CapabilityGeometryShaderPassthroughNV = 5251,
     CapabilityGeometryShaderPassthroughNV = 5251,
     CapabilityShaderViewportIndexLayerEXT = 5254,
     CapabilityShaderViewportIndexLayerEXT = 5254,
@@ -1704,6 +1708,8 @@ enum Op {
     OpFragmentMaskFetchAMD = 5011,
     OpFragmentMaskFetchAMD = 5011,
     OpFragmentFetchAMD = 5012,
     OpFragmentFetchAMD = 5012,
     OpReadClockKHR = 5056,
     OpReadClockKHR = 5056,
+    OpGroupNonUniformQuadAllKHR = 5110,
+    OpGroupNonUniformQuadAnyKHR = 5111,
     OpHitObjectRecordHitMotionNV = 5249,
     OpHitObjectRecordHitMotionNV = 5249,
     OpHitObjectRecordHitWithIndexMotionNV = 5250,
     OpHitObjectRecordHitWithIndexMotionNV = 5250,
     OpHitObjectRecordMissMotionNV = 5251,
     OpHitObjectRecordMissMotionNV = 5251,
@@ -2374,6 +2380,8 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
     case OpGroupNonUniformLogicalXor: *hasResult = true; *hasResultType = true; break;
     case OpGroupNonUniformLogicalXor: *hasResult = true; *hasResultType = true; break;
     case OpGroupNonUniformQuadBroadcast: *hasResult = true; *hasResultType = true; break;
     case OpGroupNonUniformQuadBroadcast: *hasResult = true; *hasResultType = true; break;
     case OpGroupNonUniformQuadSwap: *hasResult = true; *hasResultType = true; break;
     case OpGroupNonUniformQuadSwap: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformQuadAllKHR: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformQuadAnyKHR: *hasResult = true; *hasResultType = true; break;
     case OpCopyLogical: *hasResult = true; *hasResultType = true; break;
     case OpCopyLogical: *hasResult = true; *hasResultType = true; break;
     case OpPtrEqual: *hasResult = true; *hasResultType = true; break;
     case OpPtrEqual: *hasResult = true; *hasResultType = true; break;
     case OpPtrNotEqual: *hasResult = true; *hasResultType = true; break;
     case OpPtrNotEqual: *hasResult = true; *hasResultType = true; break;

+ 35 - 0
3rdparty/glslang/SPIRV/spvIR.h

@@ -56,6 +56,7 @@
 #include <memory>
 #include <memory>
 #include <vector>
 #include <vector>
 #include <set>
 #include <set>
+#include <optional>
 
 
 namespace spv {
 namespace spv {
 
 
@@ -190,6 +191,12 @@ protected:
 // SPIR-V IR block.
 // SPIR-V IR block.
 //
 //
 
 
+struct DebugSourceLocation {
+    int line;
+    int column;
+    spv::Id fileId;
+};
+
 class Block {
 class Block {
 public:
 public:
     Block(Id id, Function& parent);
     Block(Id id, Function& parent);
@@ -200,6 +207,28 @@ public:
     Id getId() { return instructions.front()->getResultId(); }
     Id getId() { return instructions.front()->getResultId(); }
 
 
     Function& getParent() const { return parent; }
     Function& getParent() const { return parent; }
+    // Returns true if the source location is actually updated.
+    // Note we still need the builder to insert the line marker instruction. This is just a tracker.
+    bool updateDebugSourceLocation(int line, int column, spv::Id fileId) {
+        if (currentSourceLoc && currentSourceLoc->line == line && currentSourceLoc->column == column &&
+            currentSourceLoc->fileId == fileId) {
+            return false;
+        }
+
+        currentSourceLoc = DebugSourceLocation{line, column, fileId};
+        return true;
+    }
+    // Returns true if the scope is actually updated.
+    // Note we still need the builder to insert the debug scope instruction. This is just a tracker.
+    bool updateDebugScope(spv::Id scopeId) {
+        assert(scopeId);
+        if (currentDebugScope && *currentDebugScope == scopeId) {
+            return false;
+        }
+
+        currentDebugScope = scopeId;
+        return true;
+    }
     void addInstruction(std::unique_ptr<Instruction> inst);
     void addInstruction(std::unique_ptr<Instruction> inst);
     void addPredecessor(Block* pred) { predecessors.push_back(pred); pred->successors.push_back(this);}
     void addPredecessor(Block* pred) { predecessors.push_back(pred); pred->successors.push_back(this);}
     void addLocalVariable(std::unique_ptr<Instruction> inst) { localVariables.push_back(std::move(inst)); }
     void addLocalVariable(std::unique_ptr<Instruction> inst) { localVariables.push_back(std::move(inst)); }
@@ -292,6 +321,12 @@ protected:
     std::vector<std::unique_ptr<Instruction> > localVariables;
     std::vector<std::unique_ptr<Instruction> > localVariables;
     Function& parent;
     Function& parent;
 
 
+    // Track source location of the last source location marker instruction.
+    std::optional<DebugSourceLocation> currentSourceLoc;
+
+    // Track scope of the last debug scope instruction.
+    std::optional<spv::Id> currentDebugScope;
+
     // track whether this block is known to be uncreachable (not necessarily
     // track whether this block is known to be uncreachable (not necessarily
     // true for all unreachable blocks, but should be set at least
     // true for all unreachable blocks, but should be set at least
     // for the extraneous ones introduced by the builder).
     // for the extraneous ones introduced by the builder).

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

@@ -852,6 +852,8 @@ public:
         // -2048 as the default value indicating layoutSecondaryViewportRelative is not set
         // -2048 as the default value indicating layoutSecondaryViewportRelative is not set
         layoutSecondaryViewportRelativeOffset = -2048;
         layoutSecondaryViewportRelativeOffset = -2048;
         layoutShaderRecord = false;
         layoutShaderRecord = false;
+        layoutFullQuads = false;
+        layoutQuadDeriv = false;
         layoutHitObjectShaderRecordNV = false;
         layoutHitObjectShaderRecordNV = false;
         layoutBindlessSampler = false;
         layoutBindlessSampler = false;
         layoutBindlessImage = false;
         layoutBindlessImage = false;
@@ -948,6 +950,8 @@ public:
     bool layoutViewportRelative;
     bool layoutViewportRelative;
     int layoutSecondaryViewportRelativeOffset;
     int layoutSecondaryViewportRelativeOffset;
     bool layoutShaderRecord;
     bool layoutShaderRecord;
+    bool layoutFullQuads;
+    bool layoutQuadDeriv;
     bool layoutHitObjectShaderRecordNV;
     bool layoutHitObjectShaderRecordNV;
 
 
     // GL_EXT_spirv_intrinsics
     // GL_EXT_spirv_intrinsics
@@ -1055,6 +1059,8 @@ public:
     TLayoutFormat getFormat() const { return layoutFormat; }
     TLayoutFormat getFormat() const { return layoutFormat; }
     bool isPushConstant() const { return layoutPushConstant; }
     bool isPushConstant() const { return layoutPushConstant; }
     bool isShaderRecord() const { return layoutShaderRecord; }
     bool isShaderRecord() const { return layoutShaderRecord; }
+    bool isFullQuads() const { return layoutFullQuads; }
+    bool isQuadDeriv() const { return layoutQuadDeriv; }
     bool hasHitObjectShaderRecordNV() const { return layoutHitObjectShaderRecordNV; }
     bool hasHitObjectShaderRecordNV() const { return layoutHitObjectShaderRecordNV; }
     bool hasBufferReference() const { return layoutBufferReference; }
     bool hasBufferReference() const { return layoutBufferReference; }
     bool hasBufferReferenceAlign() const
     bool hasBufferReferenceAlign() const
@@ -2206,6 +2212,10 @@ public:
               
               
               if (qualifier.layoutShaderRecord)
               if (qualifier.layoutShaderRecord)
                 appendStr(" shaderRecordNV");
                 appendStr(" shaderRecordNV");
+              if (qualifier.layoutFullQuads)
+                appendStr(" full_quads");
+              if (qualifier.layoutQuadDeriv)
+                appendStr(" quad_derivatives");
               if (qualifier.layoutHitObjectShaderRecordNV)
               if (qualifier.layoutHitObjectShaderRecordNV)
                 appendStr(" hitobjectshaderrecordnv");
                 appendStr(" hitobjectshaderrecordnv");
 
 

+ 5 - 1
3rdparty/glslang/glslang/Include/intermediate.h

@@ -1,7 +1,7 @@
 //
 //
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2012-2016 LunarG, Inc.
 // Copyright (C) 2012-2016 LunarG, Inc.
-// Copyright (C) 2017 ARM Limited.
+// Copyright (C) 2017, 2022-2024 Arm Limited.
 // Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 // Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 //
 // All rights reserved.
 // All rights reserved.
@@ -506,6 +506,8 @@ enum TOperator {
     EOpSubgroupShuffleXor,
     EOpSubgroupShuffleXor,
     EOpSubgroupShuffleUp,
     EOpSubgroupShuffleUp,
     EOpSubgroupShuffleDown,
     EOpSubgroupShuffleDown,
+    EOpSubgroupRotate,
+    EOpSubgroupClusteredRotate,
     EOpSubgroupAdd,
     EOpSubgroupAdd,
     EOpSubgroupMul,
     EOpSubgroupMul,
     EOpSubgroupMin,
     EOpSubgroupMin,
@@ -538,6 +540,8 @@ enum TOperator {
     EOpSubgroupQuadSwapHorizontal,
     EOpSubgroupQuadSwapHorizontal,
     EOpSubgroupQuadSwapVertical,
     EOpSubgroupQuadSwapVertical,
     EOpSubgroupQuadSwapDiagonal,
     EOpSubgroupQuadSwapDiagonal,
+    EOpSubgroupQuadAll,
+    EOpSubgroupQuadAny,
 
 
     EOpSubgroupPartition,
     EOpSubgroupPartition,
     EOpSubgroupPartitionedAdd,
     EOpSubgroupPartitionedAdd,

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

@@ -2,7 +2,7 @@
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2012-2016 LunarG, Inc.
 // Copyright (C) 2012-2016 LunarG, Inc.
 // Copyright (C) 2015-2020 Google, Inc.
 // Copyright (C) 2015-2020 Google, Inc.
-// Copyright (C) 2017 ARM Limited.
+// Copyright (C) 2017, 2022-2024 Arm Limited.
 // Modifications Copyright (C) 2020-2021 Advanced Micro Devices, Inc. All rights reserved.
 // Modifications Copyright (C) 2020-2021 Advanced Micro Devices, Inc. All rights reserved.
 //
 //
 // All rights reserved.
 // All rights reserved.
@@ -2099,6 +2099,8 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
             "%s     subgroupShuffleXor(%s, uint);\n",
             "%s     subgroupShuffleXor(%s, uint);\n",
             "%s     subgroupShuffleUp(%s, uint delta);\n",
             "%s     subgroupShuffleUp(%s, uint delta);\n",
             "%s     subgroupShuffleDown(%s, uint delta);\n",
             "%s     subgroupShuffleDown(%s, uint delta);\n",
+            "%s     subgroupRotate(%s, uint);\n",
+            "%s     subgroupClusteredRotate(%s, uint, uint);\n",
             "%s     subgroupAdd(%s);\n",
             "%s     subgroupAdd(%s);\n",
             "%s     subgroupMul(%s);\n",
             "%s     subgroupMul(%s);\n",
             "%s     subgroupMin(%s);\n",
             "%s     subgroupMin(%s);\n",
@@ -2227,6 +2229,15 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
             );
             );
     }
     }
 
 
+    // GL_EXT_shader_quad_control
+    if ((profile == EEsProfile && version >= 310) ||
+        (profile != EEsProfile && version >= 140)) {
+        commonBuiltins.append(
+            "bool subgroupQuadAll(bool);\n"
+            "bool subgroupQuadAny(bool);\n"
+            );
+    }
+
     if (profile != EEsProfile && version >= 460) {
     if (profile != EEsProfile && version >= 460) {
         commonBuiltins.append(
         commonBuiltins.append(
             "bool anyInvocation(bool);"
             "bool anyInvocation(bool);"
@@ -8661,6 +8672,8 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
             symbolTable.setFunctionExtensions("subgroupShuffleXor",              1, &E_GL_KHR_shader_subgroup_shuffle);
             symbolTable.setFunctionExtensions("subgroupShuffleXor",              1, &E_GL_KHR_shader_subgroup_shuffle);
             symbolTable.setFunctionExtensions("subgroupShuffleUp",               1, &E_GL_KHR_shader_subgroup_shuffle_relative);
             symbolTable.setFunctionExtensions("subgroupShuffleUp",               1, &E_GL_KHR_shader_subgroup_shuffle_relative);
             symbolTable.setFunctionExtensions("subgroupShuffleDown",             1, &E_GL_KHR_shader_subgroup_shuffle_relative);
             symbolTable.setFunctionExtensions("subgroupShuffleDown",             1, &E_GL_KHR_shader_subgroup_shuffle_relative);
+            symbolTable.setFunctionExtensions("subgroupRotate",                  1, &E_GL_KHR_shader_subgroup_rotate);
+            symbolTable.setFunctionExtensions("subgroupClusteredRotate",         1, &E_GL_KHR_shader_subgroup_rotate);
             symbolTable.setFunctionExtensions("subgroupAdd",                     1, &E_GL_KHR_shader_subgroup_arithmetic);
             symbolTable.setFunctionExtensions("subgroupAdd",                     1, &E_GL_KHR_shader_subgroup_arithmetic);
             symbolTable.setFunctionExtensions("subgroupMul",                     1, &E_GL_KHR_shader_subgroup_arithmetic);
             symbolTable.setFunctionExtensions("subgroupMul",                     1, &E_GL_KHR_shader_subgroup_arithmetic);
             symbolTable.setFunctionExtensions("subgroupMin",                     1, &E_GL_KHR_shader_subgroup_arithmetic);
             symbolTable.setFunctionExtensions("subgroupMin",                     1, &E_GL_KHR_shader_subgroup_arithmetic);
@@ -8779,6 +8792,13 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
             symbolTable.setVariableExtensions("gl_ShadingRateFlag4HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
             symbolTable.setVariableExtensions("gl_ShadingRateFlag4HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
         }
         }
 
 
+        // GL_EXT_shader_quad_control
+        if ((profile != EEsProfile && version >= 140) ||
+            (profile == EEsProfile && version >= 310)) {
+            symbolTable.setFunctionExtensions("subgroupQuadAll",                     1,  &E_GL_KHR_shader_subgroup_vote);
+            symbolTable.setFunctionExtensions("subgroupQuadAny",                     1,  &E_GL_KHR_shader_subgroup_vote);
+        }
+
         // GL_EXT_shader_tile_image
         // GL_EXT_shader_tile_image
         symbolTable.setFunctionExtensions("stencilAttachmentReadEXT", 1, &E_GL_EXT_shader_tile_image);
         symbolTable.setFunctionExtensions("stencilAttachmentReadEXT", 1, &E_GL_EXT_shader_tile_image);
         symbolTable.setFunctionExtensions("depthAttachmentReadEXT", 1, &E_GL_EXT_shader_tile_image);
         symbolTable.setFunctionExtensions("depthAttachmentReadEXT", 1, &E_GL_EXT_shader_tile_image);
@@ -9915,6 +9935,8 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
             symbolTable.relateToOperator("subgroupShuffleXor",              EOpSubgroupShuffleXor);
             symbolTable.relateToOperator("subgroupShuffleXor",              EOpSubgroupShuffleXor);
             symbolTable.relateToOperator("subgroupShuffleUp",               EOpSubgroupShuffleUp);
             symbolTable.relateToOperator("subgroupShuffleUp",               EOpSubgroupShuffleUp);
             symbolTable.relateToOperator("subgroupShuffleDown",             EOpSubgroupShuffleDown);
             symbolTable.relateToOperator("subgroupShuffleDown",             EOpSubgroupShuffleDown);
+            symbolTable.relateToOperator("subgroupRotate",                  EOpSubgroupRotate);
+            symbolTable.relateToOperator("subgroupClusteredRotate",         EOpSubgroupClusteredRotate);
             symbolTable.relateToOperator("subgroupAdd",                     EOpSubgroupAdd);
             symbolTable.relateToOperator("subgroupAdd",                     EOpSubgroupAdd);
             symbolTable.relateToOperator("subgroupMul",                     EOpSubgroupMul);
             symbolTable.relateToOperator("subgroupMul",                     EOpSubgroupMul);
             symbolTable.relateToOperator("subgroupMin",                     EOpSubgroupMin);
             symbolTable.relateToOperator("subgroupMin",                     EOpSubgroupMin);
@@ -9977,6 +9999,13 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
             symbolTable.relateToOperator("shadow2DProjEXT",          EOpTextureProj);
             symbolTable.relateToOperator("shadow2DProjEXT",          EOpTextureProj);
         }
         }
 
 
+        // GL_EXT_shader_quad_control
+        if ((profile == EEsProfile && version >= 310) ||
+            (profile != EEsProfile && version >= 140)) {
+            symbolTable.relateToOperator("subgroupQuadAll",                     EOpSubgroupQuadAll);
+            symbolTable.relateToOperator("subgroupQuadAny",                     EOpSubgroupQuadAny);
+        }
+
         if ((profile == EEsProfile && version >= 310) ||
         if ((profile == EEsProfile && version >= 310) ||
             (profile != EEsProfile && version >= 140)) {
             (profile != EEsProfile && version >= 140)) {
             symbolTable.relateToOperator("textureWeightedQCOM",      EOpImageSampleWeightedQCOM);
             symbolTable.relateToOperator("textureWeightedQCOM",      EOpImageSampleWeightedQCOM);

+ 39 - 0
3rdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp

@@ -1351,6 +1351,10 @@ TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction
             //  - a user function.
             //  - a user function.
 
 
             // Error check for a function requiring specific extensions present.
             // Error check for a function requiring specific extensions present.
+            if (builtIn &&
+                (fnCandidate->getBuiltInOp() == EOpSubgroupQuadAll || fnCandidate->getBuiltInOp() == EOpSubgroupQuadAny))
+                requireExtensions(loc, 1, &E_GL_EXT_shader_quad_control, fnCandidate->getName().c_str());
+
             if (builtIn && fnCandidate->getNumExtensions())
             if (builtIn && fnCandidate->getNumExtensions())
                 requireExtensions(loc, fnCandidate->getNumExtensions(), fnCandidate->getExtensions(), fnCandidate->getName().c_str());
                 requireExtensions(loc, fnCandidate->getNumExtensions(), fnCandidate->getExtensions(), fnCandidate->getName().c_str());
 
 
@@ -3986,6 +3990,18 @@ void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& q
     // Storage qualifier isn't ready for memberQualifierCheck, we should skip invariantCheck for it.
     // Storage qualifier isn't ready for memberQualifierCheck, we should skip invariantCheck for it.
     if (!isMemberCheck || structNestingLevel > 0)
     if (!isMemberCheck || structNestingLevel > 0)
         invariantCheck(loc, qualifier);
         invariantCheck(loc, qualifier);
+
+    if (qualifier.isFullQuads()) {
+        if (qualifier.storage != EvqVaryingIn)
+            error(loc, "can only apply to input layout", "full_quads ", "");
+        intermediate.setReqFullQuadsMode();
+    }
+
+    if (qualifier.isQuadDeriv()) {
+        if (qualifier.storage != EvqVaryingIn)
+            error(loc, "can only apply to input layout", "quad_derivatives", "");
+        intermediate.setQuadDerivMode();
+    }
 }
 }
 
 
 //
 //
@@ -5859,6 +5875,15 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
             publicType.shaderQualifiers.layoutOverrideCoverage = true;
             publicType.shaderQualifiers.layoutOverrideCoverage = true;
             return;
             return;
         }
         }
+        if (id == "full_quads")
+        {
+            const char* feature = "full_quads qualifier";
+            requireProfile(loc, ECompatibilityProfile | ECoreProfile | EEsProfile, feature);
+            profileRequires(loc, ECoreProfile | ECompatibilityProfile, 140, E_GL_EXT_shader_quad_control, feature);
+            profileRequires(loc, EEsProfile, 310, E_GL_EXT_shader_quad_control, feature);
+            publicType.qualifier.layoutFullQuads = true;
+            return;
+        }
     }
     }
     if (language == EShLangVertex ||
     if (language == EShLangVertex ||
         language == EShLangTessControl ||
         language == EShLangTessControl ||
@@ -5908,6 +5933,16 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
         return;
         return;
     }
     }
 
 
+    if (id == "quad_derivatives")
+    {
+        const char* feature = "quad_derivatives qualifier";
+        requireProfile(loc, ECompatibilityProfile | ECoreProfile | EEsProfile, feature);
+        profileRequires(loc, ECoreProfile | ECompatibilityProfile, 140, E_GL_EXT_shader_quad_control, feature);
+        profileRequires(loc, EEsProfile, 310, E_GL_EXT_shader_quad_control, feature);
+        publicType.qualifier.layoutQuadDeriv = true;
+        return;
+    }
+
     error(loc, "unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4)", id.c_str(), "");
     error(loc, "unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4)", id.c_str(), "");
 }
 }
 
 
@@ -6336,6 +6371,10 @@ void TParseContext::mergeObjectLayoutQualifiers(TQualifier& dst, const TQualifie
             dst.layoutSecondaryViewportRelativeOffset = src.layoutSecondaryViewportRelativeOffset;
             dst.layoutSecondaryViewportRelativeOffset = src.layoutSecondaryViewportRelativeOffset;
         if (src.layoutShaderRecord)
         if (src.layoutShaderRecord)
             dst.layoutShaderRecord = true;
             dst.layoutShaderRecord = true;
+        if (src.layoutFullQuads)
+            dst.layoutFullQuads = true;
+        if (src.layoutQuadDeriv)
+            dst.layoutQuadDeriv = true;
         if (src.layoutBindlessSampler)
         if (src.layoutBindlessSampler)
             dst.layoutBindlessSampler = true;
             dst.layoutBindlessSampler = true;
         if (src.layoutBindlessImage)
         if (src.layoutBindlessImage)

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

@@ -1,7 +1,7 @@
 //
 //
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2012-2013 LunarG, Inc.
 // Copyright (C) 2012-2013 LunarG, Inc.
-// Copyright (C) 2017 ARM Limited.
+// Copyright (C) 2017, 2022-2024 Arm Limited.
 // Copyright (C) 2015-2020 Google, Inc.
 // Copyright (C) 2015-2020 Google, Inc.
 // Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 // Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 //
@@ -235,6 +235,7 @@ void TParseVersions::initializeExtensionBehavior()
     extensionBehavior[E_GL_KHR_shader_subgroup_ballot]           = EBhDisable;
     extensionBehavior[E_GL_KHR_shader_subgroup_ballot]           = EBhDisable;
     extensionBehavior[E_GL_KHR_shader_subgroup_shuffle]          = EBhDisable;
     extensionBehavior[E_GL_KHR_shader_subgroup_shuffle]          = EBhDisable;
     extensionBehavior[E_GL_KHR_shader_subgroup_shuffle_relative] = EBhDisable;
     extensionBehavior[E_GL_KHR_shader_subgroup_shuffle_relative] = EBhDisable;
+    extensionBehavior[E_GL_KHR_shader_subgroup_rotate]           = EBhDisable;
     extensionBehavior[E_GL_KHR_shader_subgroup_clustered]        = EBhDisable;
     extensionBehavior[E_GL_KHR_shader_subgroup_clustered]        = EBhDisable;
     extensionBehavior[E_GL_KHR_shader_subgroup_quad]             = EBhDisable;
     extensionBehavior[E_GL_KHR_shader_subgroup_quad]             = EBhDisable;
     extensionBehavior[E_GL_KHR_memory_scope_semantics]           = EBhDisable;
     extensionBehavior[E_GL_KHR_memory_scope_semantics]           = EBhDisable;
@@ -258,6 +259,7 @@ void TParseVersions::initializeExtensionBehavior()
     extensionBehavior[E_GL_EXT_shader_16bit_storage]                    = EBhDisable;
     extensionBehavior[E_GL_EXT_shader_16bit_storage]                    = EBhDisable;
     extensionBehavior[E_GL_EXT_shader_8bit_storage]                     = EBhDisable;
     extensionBehavior[E_GL_EXT_shader_8bit_storage]                     = EBhDisable;
     extensionBehavior[E_GL_EXT_subgroup_uniform_control_flow]           = EBhDisable;
     extensionBehavior[E_GL_EXT_subgroup_uniform_control_flow]           = EBhDisable;
+    extensionBehavior[E_GL_EXT_maximal_reconvergence]                   = EBhDisable;
 
 
     extensionBehavior[E_GL_EXT_fragment_shader_barycentric]             = EBhDisable;
     extensionBehavior[E_GL_EXT_fragment_shader_barycentric]             = EBhDisable;
 
 
@@ -356,6 +358,7 @@ void TParseVersions::initializeExtensionBehavior()
     extensionBehavior[E_GL_EXT_spirv_intrinsics]            = EBhDisable;
     extensionBehavior[E_GL_EXT_spirv_intrinsics]            = EBhDisable;
     extensionBehavior[E_GL_EXT_mesh_shader]                 = EBhDisable;
     extensionBehavior[E_GL_EXT_mesh_shader]                 = EBhDisable;
     extensionBehavior[E_GL_EXT_opacity_micromap]            = EBhDisable;
     extensionBehavior[E_GL_EXT_opacity_micromap]            = EBhDisable;
+    extensionBehavior[E_GL_EXT_shader_quad_control]         = EBhDisable;
     extensionBehavior[E_GL_EXT_ray_tracing_position_fetch]  = EBhDisable;
     extensionBehavior[E_GL_EXT_ray_tracing_position_fetch]  = EBhDisable;
     extensionBehavior[E_GL_EXT_shader_tile_image]           = EBhDisable;
     extensionBehavior[E_GL_EXT_shader_tile_image]           = EBhDisable;
     extensionBehavior[E_GL_EXT_texture_shadow_lod]          = EBhDisable;
     extensionBehavior[E_GL_EXT_texture_shadow_lod]          = EBhDisable;
@@ -446,6 +449,7 @@ void TParseVersions::getPreamble(std::string& preamble)
             if (version >= 310) {
             if (version >= 310) {
                 preamble += "#define GL_EXT_null_initializer 1\n";
                 preamble += "#define GL_EXT_null_initializer 1\n";
                 preamble += "#define GL_EXT_subgroup_uniform_control_flow 1\n";
                 preamble += "#define GL_EXT_subgroup_uniform_control_flow 1\n";
+                preamble += "#define GL_EXT_maximal_reconvergence 1\n";
             }
             }
 
 
     } else { // !isEsProfile()
     } else { // !isEsProfile()
@@ -582,6 +586,7 @@ void TParseVersions::getPreamble(std::string& preamble)
             "#define GL_EXT_shader_atomic_float2 1\n"
             "#define GL_EXT_shader_atomic_float2 1\n"
 
 
             "#define GL_EXT_fragment_shader_barycentric 1\n"
             "#define GL_EXT_fragment_shader_barycentric 1\n"
+            "#define GL_EXT_shader_quad_control 1\n"
             "#define GL_EXT_texture_array 1\n"
             "#define GL_EXT_texture_array 1\n"
             ;
             ;
 
 
@@ -599,6 +604,7 @@ void TParseVersions::getPreamble(std::string& preamble)
         if (version >= 140) {
         if (version >= 140) {
             preamble += "#define GL_EXT_null_initializer 1\n";
             preamble += "#define GL_EXT_null_initializer 1\n";
             preamble += "#define GL_EXT_subgroup_uniform_control_flow 1\n";
             preamble += "#define GL_EXT_subgroup_uniform_control_flow 1\n";
+            preamble += "#define GL_EXT_maximal_reconvergence 1\n";
         }
         }
         if (version >= 130) {
         if (version >= 130) {
             preamble +="#define GL_FRAGMENT_PRECISION_HIGH 1\n";
             preamble +="#define GL_FRAGMENT_PRECISION_HIGH 1\n";

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

@@ -1,7 +1,7 @@
 //
 //
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2012-2013 LunarG, Inc.
 // Copyright (C) 2012-2013 LunarG, Inc.
-// Copyright (C) 2017 ARM Limited.
+// Copyright (C) 2017, 2022-2024 Arm Limited.
 // Copyright (C) 2015-2018 Google, Inc.
 // Copyright (C) 2015-2018 Google, Inc.
 // Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 // Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 //
@@ -171,6 +171,7 @@ const char* const E_GL_KHR_shader_subgroup_arithmetic       = "GL_KHR_shader_sub
 const char* const E_GL_KHR_shader_subgroup_ballot           = "GL_KHR_shader_subgroup_ballot";
 const char* const E_GL_KHR_shader_subgroup_ballot           = "GL_KHR_shader_subgroup_ballot";
 const char* const E_GL_KHR_shader_subgroup_shuffle          = "GL_KHR_shader_subgroup_shuffle";
 const char* const E_GL_KHR_shader_subgroup_shuffle          = "GL_KHR_shader_subgroup_shuffle";
 const char* const E_GL_KHR_shader_subgroup_shuffle_relative = "GL_KHR_shader_subgroup_shuffle_relative";
 const char* const E_GL_KHR_shader_subgroup_shuffle_relative = "GL_KHR_shader_subgroup_shuffle_relative";
+const char* const E_GL_KHR_shader_subgroup_rotate           = "GL_KHR_shader_subgroup_rotate";
 const char* const E_GL_KHR_shader_subgroup_clustered        = "GL_KHR_shader_subgroup_clustered";
 const char* const E_GL_KHR_shader_subgroup_clustered        = "GL_KHR_shader_subgroup_clustered";
 const char* const E_GL_KHR_shader_subgroup_quad             = "GL_KHR_shader_subgroup_quad";
 const char* const E_GL_KHR_shader_subgroup_quad             = "GL_KHR_shader_subgroup_quad";
 const char* const E_GL_KHR_memory_scope_semantics           = "GL_KHR_memory_scope_semantics";
 const char* const E_GL_KHR_memory_scope_semantics           = "GL_KHR_memory_scope_semantics";
@@ -215,8 +216,10 @@ const char* const E_GL_EXT_spirv_intrinsics                 = "GL_EXT_spirv_intr
 const char* const E_GL_EXT_fragment_shader_barycentric      = "GL_EXT_fragment_shader_barycentric";
 const char* const E_GL_EXT_fragment_shader_barycentric      = "GL_EXT_fragment_shader_barycentric";
 const char* const E_GL_EXT_mesh_shader                      = "GL_EXT_mesh_shader";
 const char* const E_GL_EXT_mesh_shader                      = "GL_EXT_mesh_shader";
 const char* const E_GL_EXT_opacity_micromap                 = "GL_EXT_opacity_micromap";
 const char* const E_GL_EXT_opacity_micromap                 = "GL_EXT_opacity_micromap";
+const char* const E_GL_EXT_shader_quad_control              = "GL_EXT_shader_quad_control";
 const char* const E_GL_EXT_draw_instanced                   = "GL_EXT_draw_instanced";
 const char* const E_GL_EXT_draw_instanced                   = "GL_EXT_draw_instanced";
 const char* const E_GL_EXT_texture_array                    = "GL_EXT_texture_array";
 const char* const E_GL_EXT_texture_array                    = "GL_EXT_texture_array";
+const char* const E_GL_EXT_maximal_reconvergence            = "GL_EXT_maximal_reconvergence";
 
 
 // Arrays of extensions for the above viewportEXTs duplications
 // Arrays of extensions for the above viewportEXTs duplications
 
 

+ 6 - 0
3rdparty/glslang/glslang/MachineIndependent/attribute.cpp

@@ -125,6 +125,8 @@ TAttributeType TParseContext::attributeFromName(const TString& name) const
         return EatSubgroupUniformControlFlow;
         return EatSubgroupUniformControlFlow;
     else if (name == "export")
     else if (name == "export")
         return EatExport;
         return EatExport;
+    else if (name == "maximally_reconverges")
+        return EatMaximallyReconverges;
     else
     else
         return EatNone;
         return EatNone;
 }
 }
@@ -360,6 +362,10 @@ void TParseContext::handleFunctionAttributes(const TSourceLoc& loc, const TAttri
             requireExtensions(loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute");
             requireExtensions(loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute");
             intermediate.setSubgroupUniformControlFlow();
             intermediate.setSubgroupUniformControlFlow();
             break;
             break;
+        case EatMaximallyReconverges:
+            requireExtensions(loc, 1, &E_GL_EXT_maximal_reconvergence, "attribute");
+            intermediate.setMaximallyReconverges();
+            break;
         default:
         default:
             warn(loc, "attribute does not apply to a function", "", "");
             warn(loc, "attribute does not apply to a function", "", "");
             break;
             break;

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

@@ -121,6 +121,7 @@ namespace glslang {
         EatNonReadable,
         EatNonReadable,
         EatSubgroupUniformControlFlow,
         EatSubgroupUniformControlFlow,
         EatExport,
         EatExport,
+        EatMaximallyReconverges,
     };
     };
 
 
     class TIntermAggregate;
     class TIntermAggregate;

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

@@ -964,18 +964,24 @@ function_prototype
         $$.function = $1;
         $$.function = $1;
         if (parseContext.compileOnly) $$.function->setExport();
         if (parseContext.compileOnly) $$.function->setExport();
         $$.loc = $2.loc;
         $$.loc = $2.loc;
+        const char * extensions[2] = { E_GL_EXT_subgroup_uniform_control_flow, E_GL_EXT_maximal_reconvergence };
+        parseContext.requireExtensions($2.loc, 2, extensions, "attribute");
         parseContext.handleFunctionAttributes($2.loc, *$3);
         parseContext.handleFunctionAttributes($2.loc, *$3);
     }
     }
     | attribute function_declarator RIGHT_PAREN {
     | attribute function_declarator RIGHT_PAREN {
         $$.function = $2;
         $$.function = $2;
         if (parseContext.compileOnly) $$.function->setExport();
         if (parseContext.compileOnly) $$.function->setExport();
         $$.loc = $3.loc;
         $$.loc = $3.loc;
+        const char * extensions[2] = { E_GL_EXT_subgroup_uniform_control_flow, E_GL_EXT_maximal_reconvergence };
+        parseContext.requireExtensions($3.loc, 2, extensions, "attribute");
         parseContext.handleFunctionAttributes($3.loc, *$1);
         parseContext.handleFunctionAttributes($3.loc, *$1);
     }
     }
     | attribute function_declarator RIGHT_PAREN attribute {
     | attribute function_declarator RIGHT_PAREN attribute {
         $$.function = $2;
         $$.function = $2;
         if (parseContext.compileOnly) $$.function->setExport();
         if (parseContext.compileOnly) $$.function->setExport();
         $$.loc = $3.loc;
         $$.loc = $3.loc;
+        const char * extensions[2] = { E_GL_EXT_subgroup_uniform_control_flow, E_GL_EXT_maximal_reconvergence };
+        parseContext.requireExtensions($3.loc, 2, extensions, "attribute");
         parseContext.handleFunctionAttributes($3.loc, *$1);
         parseContext.handleFunctionAttributes($3.loc, *$1);
         parseContext.handleFunctionAttributes($3.loc, *$4);
         parseContext.handleFunctionAttributes($3.loc, *$4);
     }
     }

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


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

@@ -1,7 +1,7 @@
 //
 //
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2012-2016 LunarG, Inc.
 // Copyright (C) 2012-2016 LunarG, Inc.
-// Copyright (C) 2017 ARM Limited.
+// Copyright (C) 2017, 2022-2024 Arm Limited.
 // Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 // Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 //
 // All rights reserved.
 // All rights reserved.
@@ -565,6 +565,8 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
     case EOpSubgroupShuffleXor:              out.debug << "subgroupShuffleXor";              break;
     case EOpSubgroupShuffleXor:              out.debug << "subgroupShuffleXor";              break;
     case EOpSubgroupShuffleUp:               out.debug << "subgroupShuffleUp";               break;
     case EOpSubgroupShuffleUp:               out.debug << "subgroupShuffleUp";               break;
     case EOpSubgroupShuffleDown:             out.debug << "subgroupShuffleDown";             break;
     case EOpSubgroupShuffleDown:             out.debug << "subgroupShuffleDown";             break;
+    case EOpSubgroupRotate:                  out.debug << "subgroupRotate";                  break;
+    case EOpSubgroupClusteredRotate:         out.debug << "subgroupClusteredRotate";         break;
     case EOpSubgroupAdd:                     out.debug << "subgroupAdd";                     break;
     case EOpSubgroupAdd:                     out.debug << "subgroupAdd";                     break;
     case EOpSubgroupMul:                     out.debug << "subgroupMul";                     break;
     case EOpSubgroupMul:                     out.debug << "subgroupMul";                     break;
     case EOpSubgroupMin:                     out.debug << "subgroupMin";                     break;
     case EOpSubgroupMin:                     out.debug << "subgroupMin";                     break;
@@ -597,6 +599,8 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
     case EOpSubgroupQuadSwapHorizontal:      out.debug << "subgroupQuadSwapHorizontal";      break;
     case EOpSubgroupQuadSwapHorizontal:      out.debug << "subgroupQuadSwapHorizontal";      break;
     case EOpSubgroupQuadSwapVertical:        out.debug << "subgroupQuadSwapVertical";        break;
     case EOpSubgroupQuadSwapVertical:        out.debug << "subgroupQuadSwapVertical";        break;
     case EOpSubgroupQuadSwapDiagonal:        out.debug << "subgroupQuadSwapDiagonal";        break;
     case EOpSubgroupQuadSwapDiagonal:        out.debug << "subgroupQuadSwapDiagonal";        break;
+    case EOpSubgroupQuadAll:                 out.debug << "subgroupQuadAll";                 break;
+    case EOpSubgroupQuadAny:                 out.debug << "subgroupQuadAny";                 break;
 
 
     case EOpSubgroupPartition:                          out.debug << "subgroupPartitionNV";                          break;
     case EOpSubgroupPartition:                          out.debug << "subgroupPartitionNV";                          break;
     case EOpSubgroupPartitionedAdd:                     out.debug << "subgroupPartitionedAddNV";                     break;
     case EOpSubgroupPartitionedAdd:                     out.debug << "subgroupPartitionedAddNV";                     break;
@@ -1000,6 +1004,8 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
     case EOpSubgroupShuffleXor:              out.debug << "subgroupShuffleXor"; break;
     case EOpSubgroupShuffleXor:              out.debug << "subgroupShuffleXor"; break;
     case EOpSubgroupShuffleUp:               out.debug << "subgroupShuffleUp"; break;
     case EOpSubgroupShuffleUp:               out.debug << "subgroupShuffleUp"; break;
     case EOpSubgroupShuffleDown:             out.debug << "subgroupShuffleDown"; break;
     case EOpSubgroupShuffleDown:             out.debug << "subgroupShuffleDown"; break;
+    case EOpSubgroupRotate:                  out.debug << "subgroupRotate"; break;
+    case EOpSubgroupClusteredRotate:         out.debug << "subgroupClusteredRotate"; break;
     case EOpSubgroupAdd:                     out.debug << "subgroupAdd"; break;
     case EOpSubgroupAdd:                     out.debug << "subgroupAdd"; break;
     case EOpSubgroupMul:                     out.debug << "subgroupMul"; break;
     case EOpSubgroupMul:                     out.debug << "subgroupMul"; break;
     case EOpSubgroupMin:                     out.debug << "subgroupMin"; break;
     case EOpSubgroupMin:                     out.debug << "subgroupMin"; break;
@@ -1032,6 +1038,8 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
     case EOpSubgroupQuadSwapHorizontal:      out.debug << "subgroupQuadSwapHorizontal"; break;
     case EOpSubgroupQuadSwapHorizontal:      out.debug << "subgroupQuadSwapHorizontal"; break;
     case EOpSubgroupQuadSwapVertical:        out.debug << "subgroupQuadSwapVertical"; break;
     case EOpSubgroupQuadSwapVertical:        out.debug << "subgroupQuadSwapVertical"; break;
     case EOpSubgroupQuadSwapDiagonal:        out.debug << "subgroupQuadSwapDiagonal"; break;
     case EOpSubgroupQuadSwapDiagonal:        out.debug << "subgroupQuadSwapDiagonal"; break;
+    case EOpSubgroupQuadAll:                 out.debug << "subgroupQuadAll"; break;
+    case EOpSubgroupQuadAny:                 out.debug << "subgroupQuadAny"; break;
 
 
     case EOpSubgroupPartition:                          out.debug << "subgroupPartitionNV";                          break;
     case EOpSubgroupPartition:                          out.debug << "subgroupPartitionNV";                          break;
     case EOpSubgroupPartitionedAdd:                     out.debug << "subgroupPartitionedAddNV";                     break;
     case EOpSubgroupPartitionedAdd:                     out.debug << "subgroupPartitionedAddNV";                     break;
@@ -1512,6 +1520,9 @@ void TIntermediate::output(TInfoSink& infoSink, bool tree)
     if (getSubgroupUniformControlFlow())
     if (getSubgroupUniformControlFlow())
         infoSink.debug << "subgroup_uniform_control_flow\n";
         infoSink.debug << "subgroup_uniform_control_flow\n";
 
 
+    if (getMaximallyReconverges())
+        infoSink.debug << "maximally_reconverges\n";
+
     switch (language) {
     switch (language) {
     case EShLangVertex:
     case EShLangVertex:
         break;
         break;

+ 13 - 1
3rdparty/glslang/glslang/MachineIndependent/localintermediate.h

@@ -345,10 +345,12 @@ public:
         needToLegalize(false),
         needToLegalize(false),
         binaryDoubleOutput(false),
         binaryDoubleOutput(false),
         subgroupUniformControlFlow(false),
         subgroupUniformControlFlow(false),
+        maximallyReconverges(false),
         usePhysicalStorageBuffer(false),
         usePhysicalStorageBuffer(false),
         spirvRequirement(nullptr),
         spirvRequirement(nullptr),
         spirvExecutionMode(nullptr),
         spirvExecutionMode(nullptr),
-        uniformLocationBase(0)
+        uniformLocationBase(0),
+        quadDerivMode(false), reqFullQuadsMode(false)
     {
     {
         localSize[0] = 1;
         localSize[0] = 1;
         localSize[1] = 1;
         localSize[1] = 1;
@@ -857,6 +859,10 @@ public:
 
 
     void setXfbMode() { xfbMode = true; }
     void setXfbMode() { xfbMode = true; }
     bool getXfbMode() const { return xfbMode; }
     bool getXfbMode() const { return xfbMode; }
+    void setQuadDerivMode(bool mode = true) { quadDerivMode = mode; }
+    bool getQuadDerivMode() const { return quadDerivMode; }
+    void setReqFullQuadsMode(bool mode = true) { reqFullQuadsMode = mode; }
+    bool getReqFullQuadsMode() const { return reqFullQuadsMode; }
     void setMultiStream() { multiStream = true; }
     void setMultiStream() { multiStream = true; }
     bool isMultiStream() const { return multiStream; }
     bool isMultiStream() const { return multiStream; }
     bool setOutputPrimitive(TLayoutGeometry p)
     bool setOutputPrimitive(TLayoutGeometry p)
@@ -963,6 +969,9 @@ public:
     void setSubgroupUniformControlFlow() { subgroupUniformControlFlow = true; }
     void setSubgroupUniformControlFlow() { subgroupUniformControlFlow = true; }
     bool getSubgroupUniformControlFlow() const { return subgroupUniformControlFlow; }
     bool getSubgroupUniformControlFlow() const { return subgroupUniformControlFlow; }
 
 
+    void setMaximallyReconverges() { maximallyReconverges = true; }
+    bool getMaximallyReconverges() const { return maximallyReconverges; }
+
     // GL_EXT_spirv_intrinsics
     // GL_EXT_spirv_intrinsics
     void insertSpirvRequirement(const TSpirvRequirement* spirvReq);
     void insertSpirvRequirement(const TSpirvRequirement* spirvReq);
     bool hasSpirvRequirement() const { return spirvRequirement != nullptr; }
     bool hasSpirvRequirement() const { return spirvRequirement != nullptr; }
@@ -1226,6 +1235,7 @@ protected:
     bool needToLegalize;
     bool needToLegalize;
     bool binaryDoubleOutput;
     bool binaryDoubleOutput;
     bool subgroupUniformControlFlow;
     bool subgroupUniformControlFlow;
+    bool maximallyReconverges;
     bool usePhysicalStorageBuffer;
     bool usePhysicalStorageBuffer;
 
 
     TSpirvRequirement* spirvRequirement;
     TSpirvRequirement* spirvRequirement;
@@ -1234,6 +1244,8 @@ protected:
     std::map<TString, AstRefType> bindlessImageModeCaller;
     std::map<TString, AstRefType> bindlessImageModeCaller;
     std::unordered_map<std::string, int> uniformLocationOverrides;
     std::unordered_map<std::string, int> uniformLocationOverrides;
     int uniformLocationBase;
     int uniformLocationBase;
+    bool quadDerivMode;
+    bool reqFullQuadsMode;
     TNumericFeatures numericFeatures;
     TNumericFeatures numericFeatures;
     std::unordered_map<std::string, TBlockStorageClass> blockBackingOverrides;
     std::unordered_map<std::string, TBlockStorageClass> blockBackingOverrides;
 
 

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