ソースを参照

Merge branch 'master' of github.com:bkaradzic/bgfx

Branimir Karadžić 8 年 前
コミット
16e97bbdf1
56 ファイル変更1908 行追加1032 行削除
  1. 44 27
      3rdparty/glslang/SPIRV/GlslangToSpv.cpp
  2. 7 5
      3rdparty/glslang/SPIRV/SpvBuilder.cpp
  3. 3 2
      3rdparty/glslang/SPIRV/SpvBuilder.h
  4. 1 0
      3rdparty/glslang/SPIRV/doc.cpp
  5. 34 5
      3rdparty/glslang/SPIRV/spirv.hpp
  6. 2 2
      3rdparty/glslang/StandAlone/StandAlone.cpp
  7. 6 0
      3rdparty/glslang/Test/310AofA.vert
  8. 15 0
      3rdparty/glslang/Test/460.frag
  9. 1 1
      3rdparty/glslang/Test/baseResults/120.frag.out
  10. 1 1
      3rdparty/glslang/Test/baseResults/120.vert.out
  11. 19 0
      3rdparty/glslang/Test/baseResults/310AofA.vert.out
  12. 48 2
      3rdparty/glslang/Test/baseResults/460.frag.out
  13. 2 2
      3rdparty/glslang/Test/baseResults/hlsl.attribute.expression.comp.out
  14. 2 2
      3rdparty/glslang/Test/baseResults/hlsl.attribute.frag.out
  15. 4 4
      3rdparty/glslang/Test/baseResults/hlsl.doLoop.frag.out
  16. 2 2
      3rdparty/glslang/Test/baseResults/hlsl.forLoop.frag.out
  17. 2 2
      3rdparty/glslang/Test/baseResults/hlsl.if.frag.out
  18. 4 4
      3rdparty/glslang/Test/baseResults/hlsl.loopattr.frag.out
  19. 15 15
      3rdparty/glslang/Test/baseResults/hlsl.numthreads.comp.out
  20. 2 2
      3rdparty/glslang/Test/baseResults/hlsl.switch.frag.out
  21. 2 2
      3rdparty/glslang/Test/baseResults/hlsl.whileLoop.frag.out
  22. 238 0
      3rdparty/glslang/Test/baseResults/spv.controlFlowAttributes.frag.out
  23. 2 5
      3rdparty/glslang/Test/hlsl.numthreads.comp
  24. 39 0
      3rdparty/glslang/Test/spv.controlFlowAttributes.frag
  25. 2 0
      3rdparty/glslang/glslang/CMakeLists.txt
  26. 1 1
      3rdparty/glslang/glslang/Include/Common.h
  27. 3 3
      3rdparty/glslang/glslang/Include/ConstantUnion.h
  28. 40 35
      3rdparty/glslang/glslang/Include/intermediate.h
  29. 9 9
      3rdparty/glslang/glslang/MachineIndependent/Intermediate.cpp
  30. 2 2
      3rdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp
  31. 15 2
      3rdparty/glslang/glslang/MachineIndependent/ParseHelper.h
  32. 1 0
      3rdparty/glslang/glslang/MachineIndependent/Scan.cpp
  33. 2 0
      3rdparty/glslang/glslang/MachineIndependent/Versions.cpp
  34. 1 0
      3rdparty/glslang/glslang/MachineIndependent/Versions.h
  35. 257 0
      3rdparty/glslang/glslang/MachineIndependent/attribute.cpp
  36. 102 0
      3rdparty/glslang/glslang/MachineIndependent/attribute.h
  37. 58 5
      3rdparty/glslang/glslang/MachineIndependent/glslang.y
  38. 477 434
      3rdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp
  39. 3 2
      3rdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp.h
  40. 25 3
      3rdparty/glslang/glslang/MachineIndependent/intermOut.cpp
  41. 5 4
      3rdparty/glslang/glslang/MachineIndependent/localintermediate.h
  42. 2 1
      3rdparty/glslang/glslang/Public/ShaderLang.h
  43. 1 1
      3rdparty/glslang/gtests/Hlsl.FromFile.cpp
  44. 1 0
      3rdparty/glslang/gtests/Spv.FromFile.cpp
  45. 29 113
      3rdparty/glslang/hlsl/hlslAttributes.cpp
  46. 4 75
      3rdparty/glslang/hlsl/hlslAttributes.h
  47. 57 34
      3rdparty/glslang/hlsl/hlslGrammar.cpp
  48. 6 7
      3rdparty/glslang/hlsl/hlslGrammar.h
  49. 247 173
      3rdparty/glslang/hlsl/hlslParseHelper.cpp
  50. 11 8
      3rdparty/glslang/hlsl/hlslParseHelper.h
  51. 17 13
      3rdparty/ocornut-imgui/imgui.cpp
  52. 16 14
      3rdparty/ocornut-imgui/imgui.h
  53. 14 5
      3rdparty/ocornut-imgui/imgui_demo.cpp
  54. 2 2
      3rdparty/ocornut-imgui/imgui_draw.cpp
  55. 1 0
      3rdparty/ocornut-imgui/imgui_internal.h
  56. 2 1
      examples/common/imgui/imgui.cpp

+ 44 - 27
3rdparty/glslang/SPIRV/GlslangToSpv.cpp

@@ -107,7 +107,8 @@ private:
 //
 class TGlslangToSpvTraverser : public glslang::TIntermTraverser {
 public:
-    TGlslangToSpvTraverser(const glslang::TIntermediate*, spv::SpvBuildLogger* logger, glslang::SpvOptions& options);
+    TGlslangToSpvTraverser(unsigned int spvVersion, const glslang::TIntermediate*, spv::SpvBuildLogger* logger,
+        glslang::SpvOptions& options);
     virtual ~TGlslangToSpvTraverser() { }
 
     bool visitAggregate(glslang::TVisit, glslang::TIntermAggregate*);
@@ -128,8 +129,9 @@ protected:
     spv::Decoration TranslateAuxiliaryStorageDecoration(const glslang::TQualifier& qualifier);
     spv::BuiltIn TranslateBuiltInDecoration(glslang::TBuiltInVariable, bool memberDeclaration);
     spv::ImageFormat TranslateImageFormat(const glslang::TType& type);
-    spv::SelectionControlMask TranslateSelectionControl(glslang::TSelectionControl) const;
-    spv::LoopControlMask TranslateLoopControl(glslang::TLoopControl) const;
+    spv::SelectionControlMask TranslateSelectionControl(const glslang::TIntermSelection&) const;
+    spv::SelectionControlMask TranslateSwitchControl(const glslang::TIntermSwitch&) const;
+    spv::LoopControlMask TranslateLoopControl(const glslang::TIntermLoop&, unsigned int& dependencyLength) const;
     spv::StorageClass TranslateStorageClass(const glslang::TType&);
     spv::Id createSpvVariable(const glslang::TIntermSymbol*);
     spv::Id getSampledType(const glslang::TSampler&);
@@ -747,26 +749,42 @@ spv::ImageFormat TGlslangToSpvTraverser::TranslateImageFormat(const glslang::TTy
     }
 }
 
-spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSelectionControl(glslang::TSelectionControl selectionControl) const
+spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSelectionControl(const glslang::TIntermSelection& selectionNode) const
 {
-    switch (selectionControl) {
-    case glslang::ESelectionControlNone:        return spv::SelectionControlMaskNone;
-    case glslang::ESelectionControlFlatten:     return spv::SelectionControlFlattenMask;
-    case glslang::ESelectionControlDontFlatten: return spv::SelectionControlDontFlattenMask;
-    default:                                    return spv::SelectionControlMaskNone;
-    }
+    if (selectionNode.getFlatten())
+        return spv::SelectionControlFlattenMask;
+    if (selectionNode.getDontFlatten())
+        return spv::SelectionControlDontFlattenMask;
+    return spv::SelectionControlMaskNone;
+}
+
+spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSwitchControl(const glslang::TIntermSwitch& switchNode) const
+{
+    if (switchNode.getFlatten())
+        return spv::SelectionControlFlattenMask;
+    if (switchNode.getDontFlatten())
+        return spv::SelectionControlDontFlattenMask;
+    return spv::SelectionControlMaskNone;
 }
 
-spv::LoopControlMask TGlslangToSpvTraverser::TranslateLoopControl(glslang::TLoopControl loopControl) const
+// return a non-0 dependency if the dependency argument must be set
+spv::LoopControlMask TGlslangToSpvTraverser::TranslateLoopControl(const glslang::TIntermLoop& loopNode,
+    unsigned int& dependencyLength) const
 {
-    switch (loopControl) {
-    case glslang::ELoopControlNone:       return spv::LoopControlMaskNone;
-    case glslang::ELoopControlUnroll:     return spv::LoopControlUnrollMask;
-    case glslang::ELoopControlDontUnroll: return spv::LoopControlDontUnrollMask;
-    // TODO: DependencyInfinite
-    // TODO: DependencyLength
-    default:                              return spv::LoopControlMaskNone;
+    spv::LoopControlMask control = spv::LoopControlMaskNone;
+
+    if (loopNode.getDontUnroll())
+        control = control | spv::LoopControlDontUnrollMask;
+    if (loopNode.getUnroll())
+        control = control | spv::LoopControlUnrollMask;
+    if (loopNode.getLoopDependency() == glslang::TIntermLoop::dependencyInfinite)
+        control = control | spv::LoopControlDependencyInfiniteMask;
+    else if (loopNode.getLoopDependency() > 0) {
+        control = control | spv::LoopControlDependencyLengthMask;
+        dependencyLength = loopNode.getLoopDependency();
     }
+
+    return control;
 }
 
 // Translate glslang type to SPIR-V storage class.
@@ -880,13 +898,13 @@ bool HasNonLayoutQualifiers(const glslang::TType& type, const glslang::TQualifie
 // Implement the TGlslangToSpvTraverser class.
 //
 
-TGlslangToSpvTraverser::TGlslangToSpvTraverser(const glslang::TIntermediate* glslangIntermediate,
+TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const glslang::TIntermediate* glslangIntermediate,
                                                spv::SpvBuildLogger* buildLogger, glslang::SpvOptions& options)
     : TIntermTraverser(true, false, true),
       options(options),
       shaderEntry(nullptr), currentFunction(nullptr),
       sequenceDepth(0), logger(buildLogger),
-      builder((glslang::GetKhronosToolId() << 16) | glslang::GetSpirvGeneratorVersion(), logger),
+      builder(spvVersion, (glslang::GetKhronosToolId() << 16) | glslang::GetSpirvGeneratorVersion(), logger),
       inEntryPoint(false), entryPointTerminated(false), linkageOnly(false),
       glslangIntermediate(glslangIntermediate)
 {
@@ -2025,7 +2043,7 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang
     node->getCondition()->traverse(this);
 
     // Selection control:
-    const spv::SelectionControlMask control = TranslateSelectionControl(node->getSelectionControl());
+    const spv::SelectionControlMask control = TranslateSelectionControl(*node);
 
     // make an "if" based on the value created by the condition
     spv::Builder::If ifBuilder(accessChainLoad(node->getCondition()->getType()), control, builder);
@@ -2067,7 +2085,7 @@ bool TGlslangToSpvTraverser::visitSwitch(glslang::TVisit /* visit */, glslang::T
     spv::Id selector = accessChainLoad(node->getCondition()->getAsTyped()->getType());
 
     // Selection control:
-    const spv::SelectionControlMask control = TranslateSelectionControl(node->getSelectionControl());
+    const spv::SelectionControlMask control = TranslateSwitchControl(*node);
 
     // browse the children to sort out code segments
     int defaultSegment = -1;
@@ -2127,9 +2145,8 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn
     builder.createBranch(&blocks.head);
 
     // Loop control:
-    const spv::LoopControlMask control = TranslateLoopControl(node->getLoopControl());
-
-    // TODO: dependency length
+    unsigned int dependencyLength = glslang::TIntermLoop::dependencyInfinite;
+    const spv::LoopControlMask control = TranslateLoopControl(*node, dependencyLength);
 
     // Spec requires back edges to target header blocks, and every header block
     // must dominate its merge block.  Make a header block first to ensure these
@@ -2139,7 +2156,7 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn
     // including merges of its own.
     builder.setLine(node->getLoc().line);
     builder.setBuildPoint(&blocks.head);
-    builder.createLoopMerge(&blocks.merge, &blocks.continue_target, control);
+    builder.createLoopMerge(&blocks.merge, &blocks.continue_target, control, dependencyLength);
     if (node->testFirst() && node->getTest()) {
         spv::Block& test = builder.makeNewBlock();
         builder.createBranch(&test);
@@ -6067,7 +6084,7 @@ void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsign
 
     glslang::GetThreadPoolAllocator().push();
 
-    TGlslangToSpvTraverser it(&intermediate, logger, *options);
+    TGlslangToSpvTraverser it(intermediate.getSpv().spv, &intermediate, logger, *options);
     root->traverse(&it);
     it.finishSpv();
     it.dumpSpv(spirv);

+ 7 - 5
3rdparty/glslang/SPIRV/SpvBuilder.cpp

@@ -56,7 +56,8 @@
 
 namespace spv {
 
-Builder::Builder(unsigned int magicNumber, SpvBuildLogger* buildLogger) :
+Builder::Builder(unsigned int spvVersion, unsigned int magicNumber, SpvBuildLogger* buildLogger) :
+    spvVersion(spvVersion),
     source(SourceLanguageUnknown),
     sourceVersion(0),
     sourceFileStringId(NoResult),
@@ -2403,7 +2404,7 @@ void Builder::dump(std::vector<unsigned int>& out) const
 {
     // Header, before first instructions:
     out.push_back(MagicNumber);
-    out.push_back(Version);
+    out.push_back(spvVersion);
     out.push_back(builderNumber);
     out.push_back(uniqueId + 1);
     out.push_back(0);
@@ -2572,12 +2573,15 @@ void Builder::createSelectionMerge(Block* mergeBlock, unsigned int control)
     buildPoint->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,
+                              unsigned int dependencyLength)
 {
     Instruction* merge = new Instruction(OpLoopMerge);
     merge->addIdOperand(mergeBlock->getId());
     merge->addIdOperand(continueBlock->getId());
     merge->addImmediateOperand(control);
+    if ((control & LoopControlDependencyLengthMask) != 0)
+        merge->addImmediateOperand(dependencyLength);
     buildPoint->addInstruction(std::unique_ptr<Instruction>(merge));
 }
 
@@ -2644,8 +2648,6 @@ void Builder::dumpInstructions(std::vector<unsigned int>& out, const std::vector
 void Builder::dumpModuleProcesses(std::vector<unsigned int>& out) const
 {
     for (int i = 0; i < (int)moduleProcesses.size(); ++i) {
-        // TODO: switch this out for the 1.1 headers
-        const spv::Op OpModuleProcessed = (spv::Op)330;
         Instruction moduleProcessed(OpModuleProcessed);
         moduleProcessed.addStringOperand(moduleProcesses[i]);
         moduleProcessed.dump(out);

+ 3 - 2
3rdparty/glslang/SPIRV/SpvBuilder.h

@@ -60,7 +60,7 @@ namespace spv {
 
 class Builder {
 public:
-    Builder(unsigned int userNumber, SpvBuildLogger* logger);
+    Builder(unsigned int spvVersion, unsigned int userNumber, SpvBuildLogger* logger);
     virtual ~Builder();
 
     static const int maxMatrixSize = 4;
@@ -561,7 +561,7 @@ public:
 
     void createBranch(Block* block);
     void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock);
-    void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control);
+    void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control, unsigned int dependencyLength);
 
     // Sets to generate opcode for specialization constants.
     void setToSpecConstCodeGenMode() { generatingOpCodeForSpecConst = true; }
@@ -585,6 +585,7 @@ public:
     void dumpInstructions(std::vector<unsigned int>&, const std::vector<std::unique_ptr<Instruction> >&) const;
     void dumpModuleProcesses(std::vector<unsigned int>&) const;
 
+    unsigned int spvVersion;     // the version of SPIR-V to emit in the header
     SourceLanguage source;
     int sourceVersion;
     spv::Id sourceFileStringId;

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

@@ -2558,6 +2558,7 @@ void Parameterize()
     InstructionDesc[OpLoopMerge].operands.push(OperandId, "'Merge Block'");
     InstructionDesc[OpLoopMerge].operands.push(OperandId, "'Continue Target'");
     InstructionDesc[OpLoopMerge].operands.push(OperandLoop, "");
+    InstructionDesc[OpLoopMerge].operands.push(OperandOptionalLiteral, "");
 
     InstructionDesc[OpSelectionMerge].operands.push(OperandId, "'Merge Block'");
     InstructionDesc[OpSelectionMerge].operands.push(OperandSelect, "");

+ 34 - 5
3rdparty/glslang/SPIRV/spirv.hpp

@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2017 The Khronos Group Inc.
+// Copyright (c) 2014-2018 The Khronos Group Inc.
 // 
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and/or associated documentation files (the "Materials"),
@@ -46,12 +46,12 @@ namespace spv {
 
 typedef unsigned int Id;
 
-#define SPV_VERSION 0x10000
-#define SPV_REVISION 12
+#define SPV_VERSION 0x10200
+#define SPV_REVISION 3
 
 static const unsigned int MagicNumber = 0x07230203;
-static const unsigned int Version = 0x00010000;
-static const unsigned int Revision = 12;
+static const unsigned int Version = 0x00010200;
+static const unsigned int Revision = 3;
 static const unsigned int OpCodeMask = 0xffff;
 static const unsigned int WordCountShift = 16;
 
@@ -122,6 +122,13 @@ enum ExecutionMode {
     ExecutionModeOutputTriangleStrip = 29,
     ExecutionModeVecTypeHint = 30,
     ExecutionModeContractionOff = 31,
+    ExecutionModeInitializer = 33,
+    ExecutionModeFinalizer = 34,
+    ExecutionModeSubgroupSize = 35,
+    ExecutionModeSubgroupsPerWorkgroup = 36,
+    ExecutionModeSubgroupsPerWorkgroupId = 37,
+    ExecutionModeLocalSizeId = 38,
+    ExecutionModeLocalSizeHintId = 39,
     ExecutionModePostDepthCoverage = 4446,
     ExecutionModeStencilRefReplacingEXT = 5027,
     ExecutionModeMax = 0x7fffffff,
@@ -378,6 +385,9 @@ enum Decoration {
     DecorationNoContraction = 42,
     DecorationInputAttachmentIndex = 43,
     DecorationAlignment = 44,
+    DecorationMaxByteOffset = 45,
+    DecorationAlignmentId = 46,
+    DecorationMaxByteOffsetId = 47,
     DecorationExplicitInterpAMD = 4999,
     DecorationOverrideCoverageNV = 5248,
     DecorationPassthroughNV = 5250,
@@ -470,6 +480,8 @@ enum SelectionControlMask {
 enum LoopControlShift {
     LoopControlUnrollShift = 0,
     LoopControlDontUnrollShift = 1,
+    LoopControlDependencyInfiniteShift = 2,
+    LoopControlDependencyLengthShift = 3,
     LoopControlMax = 0x7fffffff,
 };
 
@@ -477,6 +489,8 @@ enum LoopControlMask {
     LoopControlMaskNone = 0,
     LoopControlUnrollMask = 0x00000001,
     LoopControlDontUnrollMask = 0x00000002,
+    LoopControlDependencyInfiniteMask = 0x00000004,
+    LoopControlDependencyLengthMask = 0x00000008,
 };
 
 enum FunctionControlShift {
@@ -627,6 +641,9 @@ enum Capability {
     CapabilityStorageImageReadWithoutFormat = 55,
     CapabilityStorageImageWriteWithoutFormat = 56,
     CapabilityMultiViewport = 57,
+    CapabilitySubgroupDispatch = 58,
+    CapabilityNamedBarrier = 59,
+    CapabilityPipeStorage = 60,
     CapabilitySubgroupBallotKHR = 4423,
     CapabilityDrawParameters = 4427,
     CapabilitySubgroupVoteKHR = 4431,
@@ -955,6 +972,18 @@ enum Op {
     OpAtomicFlagTestAndSet = 318,
     OpAtomicFlagClear = 319,
     OpImageSparseRead = 320,
+    OpSizeOf = 321,
+    OpTypePipeStorage = 322,
+    OpConstantPipeStorage = 323,
+    OpCreatePipeFromPipeStorage = 324,
+    OpGetKernelLocalSizeForSubgroupCount = 325,
+    OpGetKernelMaxNumSubgroups = 326,
+    OpTypeNamedBarrier = 327,
+    OpNamedBarrierInitialize = 328,
+    OpMemoryNamedBarrier = 329,
+    OpModuleProcessed = 330,
+    OpExecutionModeId = 331,
+    OpDecorateId = 332,
     OpSubgroupBallotKHR = 4421,
     OpSubgroupFirstInvocationKHR = 4422,
     OpSubgroupAllKHR = 4428,

+ 2 - 2
3rdparty/glslang/StandAlone/StandAlone.cpp

@@ -159,7 +159,7 @@ std::vector<std::string> IncludeDirectoryList;
 int ClientInputSemanticsVersion = 100;   // maps to, say, #define VULKAN 100
 int VulkanClientVersion = 100;           // would map to, say, Vulkan 1.0
 int OpenGLClientVersion = 450;           // doesn't influence anything yet, but maps to OpenGL 4.50
-unsigned int TargetVersion = 0x00001000; // maps to, say, SPIR-V 1.0
+unsigned int TargetVersion = 0x00010000; // maps to, say, SPIR-V 1.0
 std::vector<std::string> Processes;      // what should be recorded by OpModuleProcessed, or equivalent
 
 // Per descriptor-set binding base data
@@ -855,7 +855,7 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
                                                                 : glslang::EShSourceGlsl,
                                         compUnit.stage, glslang::EShClientVulkan, ClientInputSemanticsVersion);
                 shader->setEnvClient(glslang::EShClientVulkan, VulkanClientVersion);
-                shader->setEnvTarget(glslang::EshTargetSpv, TargetVersion);
+                shader->setEnvTarget(glslang::EShTargetSpv, TargetVersion);
             } else {
                 shader->setEnvInput((Options & EOptionReadHlsl) ? glslang::EShSourceHlsl
                                                                 : glslang::EShSourceGlsl,

+ 6 - 0
3rdparty/glslang/Test/310AofA.vert

@@ -113,3 +113,9 @@ out float outArray[2][3];  // ERROR
 uniform ubaa {
     int a;
 } ubaaname[2][3];  // ERROR
+
+vec3 func(in mat3[2] x[3])
+{
+	mat3 a0 = x[2][1];
+    return a0[2];
+}

+ 15 - 0
3rdparty/glslang/Test/460.frag

@@ -15,3 +15,18 @@ void main()
     b1 = allInvocations(b1);
     b1 = allInvocationsEqual(b1);
 }
+
+void attExtBad()
+{
+    // ERRORs, not enabled
+    [[dependency_length(1+3)]] for (int i = 0; i < 8; ++i) { }
+    [[flatten]]                if (true) { } else { }
+}
+
+#extension GL_EXT_control_flow_attributes : enable
+
+void attExt()
+{
+    [[dependency_length(-3)]] do {  } while(true); // ERROR, not positive
+    [[dependency_length(0)]] do {  } while(true);  // ERROR, not positive
+}

+ 1 - 1
3rdparty/glslang/Test/baseResults/120.frag.out

@@ -19,7 +19,7 @@ ERROR: 0:82: 'xr' : vector swizzle selectors not from the same set
 ERROR: 0:83: 'xyxyx' : vector swizzle too long 
 ERROR: 0:84: 'z' : vector swizzle selection out of range 
 ERROR: 0:85: 'assign' :  l-value required 
-ERROR: 0:91: 'int' : overloaded functions must have the same return type 
+ERROR: 0:91: 'main' : overloaded functions must have the same return type 
 ERROR: 0:91: 'main' : function already has a body 
 ERROR: 0:91: 'int' :  entry point cannot return a value
 ERROR: 0:92: 'main' : function cannot take any parameter(s) 

+ 1 - 1
3rdparty/glslang/Test/baseResults/120.vert.out

@@ -34,7 +34,7 @@ ERROR: 0:51: 'arrays of arrays' : not supported with this profile: none
 ERROR: 0:52: 'arrays of arrays' : not supported with this profile: none
 ERROR: 0:53: 'arrays of arrays' : not supported with this profile: none
 ERROR: 0:56: 'out' : overloaded functions must have the same parameter storage qualifiers for argument 1
-ERROR: 0:57: 'float' : overloaded functions must have the same return type 
+ERROR: 0:57: 'overloadA' : overloaded functions must have the same return type 
 ERROR: 0:87: 'overloadC' : no matching overloaded function found 
 ERROR: 0:90: 'overloadC' : no matching overloaded function found 
 ERROR: 0:95: 'overloadD' : ambiguous function signature match: multiple signatures match under implicit type conversion 

+ 19 - 0
3rdparty/glslang/Test/baseResults/310AofA.vert.out

@@ -317,6 +317,25 @@ ERROR: node is still EOpNull!
 0:99              0 (const int)
 0:99          Constant:
 0:99            1 (const int)
+0:117  Function Definition: func(mf33[3][2]; ( global highp 3-component vector of float)
+0:117    Function Parameters: 
+0:117      'x' ( in 3-element array of 2-element array of highp 3X3 matrix of float)
+0:119    Sequence
+0:119      Sequence
+0:119        move second child to first child ( temp highp 3X3 matrix of float)
+0:119          'a0' ( temp highp 3X3 matrix of float)
+0:119          direct index ( temp highp 3X3 matrix of float)
+0:119            direct index ( temp 2-element array of highp 3X3 matrix of float)
+0:119              'x' ( in 3-element array of 2-element array of highp 3X3 matrix of float)
+0:119              Constant:
+0:119                2 (const int)
+0:119            Constant:
+0:119              1 (const int)
+0:120      Branch: Return with expression
+0:120        direct index ( temp highp 3-component vector of float)
+0:120          'a0' ( temp highp 3X3 matrix of float)
+0:120          Constant:
+0:120            2 (const int)
 0:?   Linker Objects
 0:?     'name' (layout( column_major shared) buffer 3-element array of block{layout( column_major shared) buffer implicitly-sized array of highp float u, layout( column_major shared) buffer implicitly-sized array of highp 4-component vector of float v})
 0:?     'uname' (layout( column_major shared) uniform 3-element array of block{layout( column_major shared) uniform highp float u, layout( column_major shared) uniform implicitly-sized array of highp 4-component vector of float v})

+ 48 - 2
3rdparty/glslang/Test/baseResults/460.frag.out

@@ -1,6 +1,14 @@
 460.frag
+ERROR: 0:22: 'attribute' : required extension not requested: GL_EXT_control_flow_attributes
+ERROR: 0:23: 'attribute' : required extension not requested: GL_EXT_control_flow_attributes
+ERROR: 0:30: 'dependency_length' : must be positive 
+ERROR: 0:31: 'dependency_length' : must be positive 
+ERROR: 4 compilation errors.  No code generated.
+
+
 Shader version: 460
-0:? Sequence
+Requested GL_EXT_control_flow_attributes
+ERROR: node is still EOpNull!
 0:10  Function Definition: main( ( global void)
 0:10    Function Parameters: 
 0:12    Sequence
@@ -21,6 +29,43 @@ Shader version: 460
 0:16        'b1' ( temp bool)
 0:16        allInvocationsEqual ( global bool)
 0:16          'b1' ( temp bool)
+0:19  Function Definition: attExtBad( ( global void)
+0:19    Function Parameters: 
+0:22    Sequence
+0:22      Sequence
+0:22        Sequence
+0:22          move second child to first child ( temp int)
+0:22            'i' ( temp int)
+0:22            Constant:
+0:22              0 (const int)
+0:22        Loop with condition tested first: Dependency 4
+0:22          Loop Condition
+0:22          Compare Less Than ( temp bool)
+0:22            'i' ( temp int)
+0:22            Constant:
+0:22              8 (const int)
+0:22          No loop body
+0:22          Loop Terminal Expression
+0:22          Pre-Increment ( temp int)
+0:22            'i' ( temp int)
+0:23      Test condition and select ( temp void): Flatten
+0:23        Condition
+0:23        Constant:
+0:23          true (const bool)
+0:23        true case is null
+0:28  Function Definition: attExt( ( global void)
+0:28    Function Parameters: 
+0:30    Sequence
+0:30      Loop with condition not tested first: Dependency -3
+0:30        Loop Condition
+0:30        Constant:
+0:30          true (const bool)
+0:30        No loop body
+0:31      Loop with condition not tested first
+0:31        Loop Condition
+0:31        Constant:
+0:31          true (const bool)
+0:31        No loop body
 0:?   Linker Objects
 0:?     's' ( smooth in structure{ global float f,  global 4-component vector of float v})
 
@@ -29,7 +74,8 @@ Linked fragment stage:
 
 
 Shader version: 460
-0:? Sequence
+Requested GL_EXT_control_flow_attributes
+ERROR: node is still EOpNull!
 0:10  Function Definition: main( ( global void)
 0:10    Function Parameters: 
 0:12    Sequence

+ 2 - 2
3rdparty/glslang/Test/baseResults/hlsl.attribute.expression.comp.out

@@ -10,7 +10,7 @@ local_size = (4, 6, 8)
 0:11          'x' ( temp int)
 0:11          Constant:
 0:11            0 (const int)
-0:11        Loop with condition tested first
+0:11        Loop with condition tested first: Unroll
 0:11          Loop Condition
 0:11          Compare Less Than ( temp bool)
 0:11            'x' ( temp int)
@@ -53,7 +53,7 @@ local_size = (4, 6, 8)
 0:11          'x' ( temp int)
 0:11          Constant:
 0:11            0 (const int)
-0:11        Loop with condition tested first
+0:11        Loop with condition tested first: Unroll
 0:11          Loop Condition
 0:11          Compare Less Than ( temp bool)
 0:11            'x' ( temp int)

+ 2 - 2
3rdparty/glslang/Test/baseResults/hlsl.attribute.frag.out

@@ -6,7 +6,7 @@ gl_FragCoord origin is upper left
 0:2    Function Parameters: 
 0:2      'input' ( in 4-component vector of float)
 0:?     Sequence
-0:11      Test condition and select ( temp void)
+0:11      Test condition and select ( temp void): DontFlatten
 0:11        Condition
 0:11        Constant:
 0:11          false (const bool)
@@ -33,7 +33,7 @@ gl_FragCoord origin is upper left
 0:2    Function Parameters: 
 0:2      'input' ( in 4-component vector of float)
 0:?     Sequence
-0:11      Test condition and select ( temp void)
+0:11      Test condition and select ( temp void): DontFlatten
 0:11        Condition
 0:11        Constant:
 0:11          false (const bool)

+ 4 - 4
3rdparty/glslang/Test/baseResults/hlsl.doLoop.frag.out

@@ -6,12 +6,12 @@ gl_FragCoord origin is upper left
 0:2    Function Parameters: 
 0:2      'input' ( in float)
 0:?     Sequence
-0:3      Loop with condition not tested first
+0:3      Loop with condition not tested first: Unroll
 0:3        Loop Condition
 0:3        Constant:
 0:3          false (const bool)
 0:3        No loop body
-0:4      Loop with condition not tested first
+0:4      Loop with condition not tested first: Unroll
 0:4        Loop Condition
 0:4        Constant:
 0:4          false (const bool)
@@ -80,12 +80,12 @@ gl_FragCoord origin is upper left
 0:2    Function Parameters: 
 0:2      'input' ( in float)
 0:?     Sequence
-0:3      Loop with condition not tested first
+0:3      Loop with condition not tested first: Unroll
 0:3        Loop Condition
 0:3        Constant:
 0:3          false (const bool)
 0:3        No loop body
-0:4      Loop with condition not tested first
+0:4      Loop with condition not tested first: Unroll
 0:4        Loop Condition
 0:4        Constant:
 0:4          false (const bool)

+ 2 - 2
3rdparty/glslang/Test/baseResults/hlsl.forLoop.frag.out

@@ -17,7 +17,7 @@ gl_FragCoord origin is upper left
 0:4          No loop condition
 0:4          No loop body
 0:?       Sequence
-0:5        Loop with condition tested first
+0:5        Loop with condition tested first: Unroll
 0:5          Loop Condition
 0:5          any ( temp bool)
 0:5            NotEqual ( temp 4-component vector of bool)
@@ -220,7 +220,7 @@ gl_FragCoord origin is upper left
 0:4          No loop condition
 0:4          No loop body
 0:?       Sequence
-0:5        Loop with condition tested first
+0:5        Loop with condition tested first: Unroll
 0:5          Loop Condition
 0:5          any ( temp bool)
 0:5            NotEqual ( temp 4-component vector of bool)

+ 2 - 2
3rdparty/glslang/Test/baseResults/hlsl.if.frag.out

@@ -42,7 +42,7 @@ gl_FragCoord origin is upper left
 0:14            'input' ( in 4-component vector of float)
 0:14            'input' ( in 4-component vector of float)
 0:14        true case is null
-0:19      Test condition and select ( temp void)
+0:19      Test condition and select ( temp void): Flatten
 0:19        Condition
 0:19        all ( temp bool)
 0:19          Equal ( temp 4-component vector of bool)
@@ -152,7 +152,7 @@ gl_FragCoord origin is upper left
 0:14            'input' ( in 4-component vector of float)
 0:14            'input' ( in 4-component vector of float)
 0:14        true case is null
-0:19      Test condition and select ( temp void)
+0:19      Test condition and select ( temp void): Flatten
 0:19        Condition
 0:19        all ( temp bool)
 0:19          Equal ( temp 4-component vector of bool)

+ 4 - 4
3rdparty/glslang/Test/baseResults/hlsl.loopattr.frag.out

@@ -10,7 +10,7 @@ gl_FragCoord origin is upper left
 0:5          'x' ( temp int)
 0:5          Constant:
 0:5            0 (const int)
-0:5        Loop with condition tested first
+0:5        Loop with condition tested first: Unroll
 0:5          Loop Condition
 0:5          Compare Less Than ( temp bool)
 0:5            'x' ( temp int)
@@ -25,7 +25,7 @@ gl_FragCoord origin is upper left
 0:8          'y' ( temp int)
 0:8          Constant:
 0:8            0 (const int)
-0:8        Loop with condition tested first
+0:8        Loop with condition tested first: DontUnroll
 0:8          Loop Condition
 0:8          Compare Less Than ( temp bool)
 0:8            'y' ( temp int)
@@ -80,7 +80,7 @@ gl_FragCoord origin is upper left
 0:5          'x' ( temp int)
 0:5          Constant:
 0:5            0 (const int)
-0:5        Loop with condition tested first
+0:5        Loop with condition tested first: Unroll
 0:5          Loop Condition
 0:5          Compare Less Than ( temp bool)
 0:5            'x' ( temp int)
@@ -95,7 +95,7 @@ gl_FragCoord origin is upper left
 0:8          'y' ( temp int)
 0:8          Constant:
 0:8            0 (const int)
-0:8        Loop with condition tested first
+0:8        Loop with condition tested first: DontUnroll
 0:8          Loop Condition
 0:8          Compare Less Than ( temp bool)
 0:8            'y' ( temp int)

+ 15 - 15
3rdparty/glslang/Test/baseResults/hlsl.numthreads.comp.out

@@ -1,20 +1,20 @@
 hlsl.numthreads.comp
 Shader version: 500
-local_size = (4, 4, 2)
+local_size = (1, 4, 8)
 0:? Sequence
 0:4  Function Definition: main(vu3; ( temp void)
 0:4    Function Parameters: 
 0:4      'tid' ( in 3-component vector of uint)
-0:9  Function Definition: @main_aux1(vu3; ( temp void)
+0:9  Function Definition: @main_aux2(vu3; ( temp void)
 0:9    Function Parameters: 
 0:9      'tid' ( in 3-component vector of uint)
-0:9  Function Definition: main_aux1( ( temp void)
+0:9  Function Definition: main_aux2( ( temp void)
 0:9    Function Parameters: 
 0:?     Sequence
 0:9      move second child to first child ( temp 3-component vector of uint)
 0:?         'tid' ( temp 3-component vector of uint)
 0:?         'tid' ( in 3-component vector of uint GlobalInvocationID)
-0:9      Function Call: @main_aux1(vu3; ( temp void)
+0:9      Function Call: @main_aux2(vu3; ( temp void)
 0:?         'tid' ( temp 3-component vector of uint)
 0:?   Linker Objects
 0:?     'tid' ( in 3-component vector of uint GlobalInvocationID)
@@ -24,21 +24,21 @@ Linked compute stage:
 
 
 Shader version: 500
-local_size = (4, 4, 2)
+local_size = (1, 4, 8)
 0:? Sequence
 0:4  Function Definition: main(vu3; ( temp void)
 0:4    Function Parameters: 
 0:4      'tid' ( in 3-component vector of uint)
-0:9  Function Definition: @main_aux1(vu3; ( temp void)
+0:9  Function Definition: @main_aux2(vu3; ( temp void)
 0:9    Function Parameters: 
 0:9      'tid' ( in 3-component vector of uint)
-0:9  Function Definition: main_aux1( ( temp void)
+0:9  Function Definition: main_aux2( ( temp void)
 0:9    Function Parameters: 
 0:?     Sequence
 0:9      move second child to first child ( temp 3-component vector of uint)
 0:?         'tid' ( temp 3-component vector of uint)
 0:?         'tid' ( in 3-component vector of uint GlobalInvocationID)
-0:9      Function Call: @main_aux1(vu3; ( temp void)
+0:9      Function Call: @main_aux2(vu3; ( temp void)
 0:?         'tid' ( temp 3-component vector of uint)
 0:?   Linker Objects
 0:?     'tid' ( in 3-component vector of uint GlobalInvocationID)
@@ -50,13 +50,13 @@ local_size = (4, 4, 2)
                               Capability Shader
                1:             ExtInstImport  "GLSL.std.450"
                               MemoryModel Logical GLSL450
-                              EntryPoint GLCompute 4  "main_aux1" 18
-                              ExecutionMode 4 LocalSize 4 4 2
+                              EntryPoint GLCompute 4  "main_aux2" 18
+                              ExecutionMode 4 LocalSize 1 4 8
                               Source HLSL 500
-                              Name 4  "main_aux1"
+                              Name 4  "main_aux2"
                               Name 11  "main(vu3;"
                               Name 10  "tid"
-                              Name 14  "@main_aux1(vu3;"
+                              Name 14  "@main_aux2(vu3;"
                               Name 13  "tid"
                               Name 16  "tid"
                               Name 18  "tid"
@@ -70,7 +70,7 @@ local_size = (4, 4, 2)
                9:             TypeFunction 2 8(ptr)
               17:             TypePointer Input 7(ivec3)
          18(tid):     17(ptr) Variable Input
-    4(main_aux1):           2 Function None 3
+    4(main_aux2):           2 Function None 3
                5:             Label
          16(tid):      8(ptr) Variable Function
        20(param):      8(ptr) Variable Function
@@ -78,7 +78,7 @@ local_size = (4, 4, 2)
                               Store 16(tid) 19
               21:    7(ivec3) Load 16(tid)
                               Store 20(param) 21
-              22:           2 FunctionCall 14(@main_aux1(vu3;) 20(param)
+              22:           2 FunctionCall 14(@main_aux2(vu3;) 20(param)
                               Return
                               FunctionEnd
    11(main(vu3;):           2 Function None 9
@@ -86,7 +86,7 @@ local_size = (4, 4, 2)
               12:             Label
                               Return
                               FunctionEnd
-14(@main_aux1(vu3;):           2 Function None 9
+14(@main_aux2(vu3;):           2 Function None 9
          13(tid):      8(ptr) FunctionParameter
               15:             Label
                               Return

+ 2 - 2
3rdparty/glslang/Test/baseResults/hlsl.switch.frag.out

@@ -36,7 +36,7 @@ gl_FragCoord origin is upper left
 0:17            Pre-Decrement ( temp 4-component vector of float)
 0:17              'input' ( in 4-component vector of float)
 0:18            Branch: Break
-0:21      switch
+0:21      switch: DontFlatten
 0:21      condition
 0:21        'c' ( in int)
 0:21      body
@@ -186,7 +186,7 @@ gl_FragCoord origin is upper left
 0:17            Pre-Decrement ( temp 4-component vector of float)
 0:17              'input' ( in 4-component vector of float)
 0:18            Branch: Break
-0:21      switch
+0:21      switch: DontFlatten
 0:21      condition
 0:21        'c' ( in int)
 0:21      body

+ 2 - 2
3rdparty/glslang/Test/baseResults/hlsl.whileLoop.frag.out

@@ -21,7 +21,7 @@ gl_FragCoord origin is upper left
 0:4        Constant:
 0:4          false (const bool)
 0:4        No loop body
-0:5      Loop with condition tested first
+0:5      Loop with condition tested first: Unroll
 0:5        Loop Condition
 0:5        Constant:
 0:5          false (const bool)
@@ -71,7 +71,7 @@ gl_FragCoord origin is upper left
 0:4        Constant:
 0:4          false (const bool)
 0:4        No loop body
-0:5      Loop with condition tested first
+0:5      Loop with condition tested first: Unroll
 0:5        Loop Condition
 0:5        Constant:
 0:5          false (const bool)

+ 238 - 0
3rdparty/glslang/Test/baseResults/spv.controlFlowAttributes.frag.out

@@ -0,0 +1,238 @@
+spv.controlFlowAttributes.frag
+WARNING: 0:20: '' : attribute with arguments not recognized, skipping 
+WARNING: 0:21: '' : attribute with arguments not recognized, skipping 
+WARNING: 0:22: '' : attribute with arguments not recognized, skipping 
+WARNING: 0:23: 'dependency_length' : expected a single integer argument 
+WARNING: 0:24: '' : attribute with arguments not recognized, skipping 
+WARNING: 0:25: '' : attribute with arguments not recognized, skipping 
+WARNING: 0:26: '' : attribute with arguments not recognized, skipping 
+
+// Module Version 10000
+// Generated by (magic number): 80003
+// Id's are bound by 118
+
+                              Capability Shader
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Fragment 4  "main"
+                              ExecutionMode 4 OriginUpperLeft
+                              Source GLSL 450
+                              SourceExtension  "GL_EXT_control_flow_attributes"
+                              Name 4  "main"
+                              Name 8  "i"
+                              Name 36  "i"
+                              Name 47  "cond"
+                              Name 60  "i"
+                              Name 79  "i"
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeInt 32 1
+               7:             TypePointer Function 6(int)
+               9:      6(int) Constant 0
+              16:      6(int) Constant 8
+              17:             TypeBool
+              20:      6(int) Constant 1
+              31:    17(bool) ConstantTrue
+              46:             TypePointer Private 17(bool)
+        47(cond):     46(ptr) Variable Private
+              54:    17(bool) ConstantFalse
+              55:      6(int) Constant 3
+         4(main):           2 Function None 3
+               5:             Label
+            8(i):      7(ptr) Variable Function
+           36(i):      7(ptr) Variable Function
+           60(i):      7(ptr) Variable Function
+           79(i):      7(ptr) Variable Function
+                              Store 8(i) 9
+                              Branch 10
+              10:             Label
+                              LoopMerge 12 13 Unroll 
+                              Branch 14
+              14:             Label
+              15:      6(int) Load 8(i)
+              18:    17(bool) SLessThan 15 16
+                              BranchConditional 18 11 12
+              11:               Label
+                                Branch 13
+              13:               Label
+              19:      6(int)   Load 8(i)
+              21:      6(int)   IAdd 19 20
+                                Store 8(i) 21
+                                Branch 10
+              12:             Label
+                              Branch 22
+              22:             Label
+                              LoopMerge 24 25 DontUnroll 
+                              Branch 23
+              23:             Label
+                              Branch 25
+              25:             Label
+                              Branch 22
+              24:             Label
+                              Branch 26
+              26:             Label
+                              LoopMerge 28 29 DontUnroll 
+                              Branch 30
+              30:             Label
+                              BranchConditional 31 27 28
+              27:               Label
+                                Branch 29
+              29:               Label
+                                Branch 26
+              28:             Label
+                              Branch 32
+              32:             Label
+                              LoopMerge 34 35 DependencyInfinite 
+                              Branch 33
+              33:             Label
+                              Branch 35
+              35:             Label
+                              BranchConditional 31 32 34
+              34:             Label
+                              Store 36(i) 9
+                              Branch 37
+              37:             Label
+                              LoopMerge 39 40 DependencyLength  4
+                              Branch 41
+              41:             Label
+              42:      6(int) Load 36(i)
+              43:    17(bool) SLessThan 42 16
+                              BranchConditional 43 38 39
+              38:               Label
+                                Branch 40
+              40:               Label
+              44:      6(int)   Load 36(i)
+              45:      6(int)   IAdd 44 20
+                                Store 36(i) 45
+                                Branch 37
+              39:             Label
+              48:    17(bool) Load 47(cond)
+                              SelectionMerge 50 Flatten 
+                              BranchConditional 48 49 50
+              49:               Label
+                                Branch 50
+              50:             Label
+              51:    17(bool) Load 47(cond)
+                              SelectionMerge 53 DontFlatten 
+                              BranchConditional 51 52 53
+              52:               Label
+                                Store 47(cond) 54
+                                Branch 53
+              53:             Label
+                              SelectionMerge 57 DontFlatten 
+                              Switch 55 57 
+                                     case 3: 56
+              56:               Label
+                                Branch 57
+              57:             Label
+                              Store 60(i) 9
+                              Branch 61
+              61:             Label
+                              LoopMerge 63 64 None
+                              Branch 65
+              65:             Label
+              66:      6(int) Load 60(i)
+              67:    17(bool) SLessThan 66 16
+                              BranchConditional 67 62 63
+              62:               Label
+                                Branch 64
+              64:               Label
+              68:      6(int)   Load 60(i)
+              69:      6(int)   IAdd 68 20
+                                Store 60(i) 69
+                                Branch 61
+              63:             Label
+                              Branch 70
+              70:             Label
+                              LoopMerge 72 73 None
+                              Branch 74
+              74:             Label
+                              BranchConditional 31 71 72
+              71:               Label
+                                Branch 73
+              73:               Label
+                                Branch 70
+              72:             Label
+                              Branch 75
+              75:             Label
+                              LoopMerge 77 78 None
+                              Branch 76
+              76:             Label
+                              Branch 78
+              78:             Label
+                              BranchConditional 31 75 77
+              77:             Label
+                              Store 79(i) 9
+                              Branch 80
+              80:             Label
+                              LoopMerge 82 83 None
+                              Branch 84
+              84:             Label
+              85:      6(int) Load 79(i)
+              86:    17(bool) SLessThan 85 16
+                              BranchConditional 86 81 82
+              81:               Label
+                                Branch 83
+              83:               Label
+              87:      6(int)   Load 79(i)
+              88:      6(int)   IAdd 87 20
+                                Store 79(i) 88
+                                Branch 80
+              82:             Label
+              89:    17(bool) Load 47(cond)
+                              SelectionMerge 91 None
+                              BranchConditional 89 90 91
+              90:               Label
+                                Branch 91
+              91:             Label
+              92:    17(bool) Load 47(cond)
+                              SelectionMerge 94 None
+                              BranchConditional 92 93 94
+              93:               Label
+                                Store 47(cond) 54
+                                Branch 94
+              94:             Label
+                              SelectionMerge 96 None
+                              Switch 55 96 
+                                     case 3: 95
+              95:               Label
+                                Branch 96
+              96:             Label
+                              Branch 99
+              99:             Label
+                              LoopMerge 101 102 Unroll DontUnroll DependencyLength  2
+                              Branch 103
+             103:             Label
+             104:    17(bool) Load 47(cond)
+                              BranchConditional 104 100 101
+             100:               Label
+                                Branch 102
+             102:               Label
+                                Branch 99
+             101:             Label
+                              SelectionMerge 106 DontFlatten 
+                              Switch 55 106 
+                                     case 3: 105
+             105:               Label
+                                Branch 106
+             106:             Label
+             109:    17(bool) Load 47(cond)
+                              SelectionMerge 111 Flatten 
+                              BranchConditional 109 110 111
+             110:               Label
+                                Branch 111
+             111:             Label
+                              Branch 112
+             112:             Label
+                              LoopMerge 114 115 DependencyInfinite 
+                              Branch 116
+             116:             Label
+             117:    17(bool) Load 47(cond)
+                              BranchConditional 117 113 114
+             113:               Label
+                                Branch 115
+             115:               Label
+                                Branch 112
+             114:             Label
+                              Return
+                              FunctionEnd

+ 2 - 5
3rdparty/glslang/Test/hlsl.numthreads.comp

@@ -4,11 +4,8 @@ void main(uint3 tid : SV_DispatchThreadID )
 {
 }
 
-[numTHreaDs(4,4,2)]  // case insensitive
-void main_aux1(uint3 tid : SV_DispatchThreadID )
+[numthreads(1,4,8)]
+void main_aux2(uint3 tid : SV_DispatchThreadID )
 {
 }
 
-[numthreads(1,4,8)]
-void main_aux2(uint3 tid : SV_DispatchThreadID );
-

+ 39 - 0
3rdparty/glslang/Test/spv.controlFlowAttributes.frag

@@ -0,0 +1,39 @@
+#version 450
+
+#extension GL_EXT_control_flow_attributes : enable
+
+bool cond;
+
+void main()
+{
+        [[unroll]]                 for (int i = 0; i < 8; ++i) { }
+        [[loop]]                   for (;;) { }
+        [[dont_unroll]]            while(true) {  }
+        [[dependency_infinite]]    do {  } while(true);
+        [[dependency_length(1+3)]] for (int i = 0; i < 8; ++i) { }
+        [[flatten]]                if (cond) { } else { }
+        [[branch]]                 if (cond) cond = false;
+        [[dont_flatten]]           switch(3) {  }                      // dropped
+        [[dont_flatten]]           switch(3) { case 3: break; }
+
+        // warnings on all these
+        [[unroll(2)]]              for (int i = 0; i < 8; ++i) { }
+        [[dont_unroll(-2)]]        while(true) {  }
+        [[dependency_infinite(3)]] do {  } while(true);
+        [[dependency_length]]      for (int i = 0; i < 8; ++i) { }
+        [[flatten(3)]]             if (cond) { } else { }
+        [[branch(5.2)]]            if (cond) cond = false;
+        [[dont_flatten(3 + 7)]]    switch(3) { case 3: break; }
+
+        // other valid uses
+        [[ unroll, dont_unroll, dependency_length(2) ]]  while(cond) {  }
+        [ [ dont_flatten , branch ] ]                    switch(3) { case 3: break; }
+        [
+            // attribute
+            [
+                // here
+                flatten
+            ]
+        ]                       if (cond) { } else { }
+        [[ dependency_length(2), dependency_infinite ]]  while(cond) {  }
+}

+ 2 - 0
3rdparty/glslang/glslang/CMakeLists.txt

@@ -9,6 +9,7 @@ endif(WIN32)
 set(SOURCES
     MachineIndependent/glslang.y
     MachineIndependent/glslang_tab.cpp
+    MachineIndependent/attribute.cpp
     MachineIndependent/Constant.cpp
     MachineIndependent/iomapper.cpp
     MachineIndependent/InfoSink.cpp
@@ -51,6 +52,7 @@ set(HEADERS
     Include/revision.h
     Include/ShHandle.h
     Include/Types.h
+    MachineIndependent/attribute.h
     MachineIndependent/glslang_tab.cpp.h
     MachineIndependent/gl_types.h
     MachineIndependent/Initialize.h

+ 1 - 1
3rdparty/glslang/glslang/Include/Common.h

@@ -155,7 +155,7 @@ inline TString* NewPoolTString(const char* s)
     return new(memory) TString(s);
 }
 
-template<class T> inline T* NewPoolObject(T)
+template<class T> inline T* NewPoolObject(T*)
 {
     return new(GetThreadPoolAllocator().allocate(sizeof(T))) T;
 }

+ 3 - 3
3rdparty/glslang/glslang/Include/ConstantUnion.h

@@ -37,6 +37,9 @@
 #ifndef _CONSTANT_UNION_INCLUDED_
 #define _CONSTANT_UNION_INCLUDED_
 
+#include "../Include/Common.h"
+#include "../Include/BaseTypes.h"
+
 namespace glslang {
 
 class TConstUnion {
@@ -595,9 +598,6 @@ public:
         if (! unionArray || ! rhs.unionArray)
             return false;
 
-        if (! unionArray || ! rhs.unionArray)
-            return false;
-
         return *unionArray == *rhs.unionArray;
     }
     bool operator!=(const TConstUnionArray& rhs) const { return ! operator==(rhs); }

+ 40 - 35
3rdparty/glslang/glslang/Include/intermediate.h

@@ -819,7 +819,7 @@ public:
     virtual       glslang::TIntermMethod*        getAsMethodNode()          { return 0; }
     virtual       glslang::TIntermSymbol*        getAsSymbolNode()          { return 0; }
     virtual       glslang::TIntermBranch*        getAsBranchNode()          { return 0; }
-	virtual       glslang::TIntermLoop*          getAsLoopNode()            { return 0; }
+    virtual       glslang::TIntermLoop*          getAsLoopNode()            { return 0; }
 
     virtual const glslang::TIntermTyped*         getAsTyped()         const { return 0; }
     virtual const glslang::TIntermOperator*      getAsOperator()      const { return 0; }
@@ -832,7 +832,7 @@ public:
     virtual const glslang::TIntermMethod*        getAsMethodNode()    const { return 0; }
     virtual const glslang::TIntermSymbol*        getAsSymbolNode()    const { return 0; }
     virtual const glslang::TIntermBranch*        getAsBranchNode()    const { return 0; }
-	virtual const glslang::TIntermLoop*          getAsLoopNode()      const { return 0; }
+    virtual const glslang::TIntermLoop*          getAsLoopNode()      const { return 0; }
     virtual ~TIntermNode() { }
 
 protected:
@@ -885,24 +885,6 @@ protected:
     TType type;
 };
 
-//
-// Selection control hints
-//
-enum TSelectionControl {
-    ESelectionControlNone,
-    ESelectionControlFlatten,
-    ESelectionControlDontFlatten,
-};
-
-//
-// Loop control hints
-//
-enum TLoopControl {
-    ELoopControlNone,
-    ELoopControlUnroll,
-    ELoopControlDontUnroll,
-};
-
 //
 // Handle for, do-while, and while loops.
 //
@@ -913,26 +895,36 @@ public:
         test(aTest),
         terminal(aTerminal),
         first(testFirst),
-        control(ELoopControlNone)
+        unroll(false),
+        dontUnroll(false),
+        dependency(0)
     { }
 
-	virtual       TIntermLoop* getAsLoopNode() { return this; }
-	virtual const TIntermLoop* getAsLoopNode() const { return this; }
+    virtual       TIntermLoop* getAsLoopNode() { return this; }
+    virtual const TIntermLoop* getAsLoopNode() const { return this; }
     virtual void traverse(TIntermTraverser*);
     TIntermNode*  getBody() const { return body; }
     TIntermTyped* getTest() const { return test; }
     TIntermTyped* getTerminal() const { return terminal; }
     bool testFirst() const { return first; }
 
-    void setLoopControl(TLoopControl c) { control = c; }
-    TLoopControl getLoopControl() const { return control; }
+    void setUnroll()     { unroll = true; }
+    void setDontUnroll() { dontUnroll = true; }
+    bool getUnroll()     const { return unroll; }
+    bool getDontUnroll() const { return dontUnroll; }
+
+    static const unsigned int dependencyInfinite = 0xFFFFFFFF;
+    void setLoopDependency(int d) { dependency = d; }
+    int getLoopDependency() const { return dependency; }
 
 protected:
     TIntermNode* body;       // code to loop over
     TIntermTyped* test;      // exit condition associated with loop, could be 0 for 'for' loops
     TIntermTyped* terminal;  // exists for for-loops
     bool first;              // true for while and for, not for do-while
-    TLoopControl control;    // loop control hint
+    bool unroll;             // true if unroll requested
+    bool dontUnroll;         // true if request to not unroll
+    unsigned int dependency; // loop dependency hint; 0 means not set or unknown
 };
 
 //
@@ -1343,22 +1335,29 @@ protected:
 class TIntermSelection : public TIntermTyped {
 public:
     TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) :
-        TIntermTyped(EbtVoid), condition(cond), trueBlock(trueB), falseBlock(falseB), control(ESelectionControlNone) {}
+        TIntermTyped(EbtVoid), condition(cond), trueBlock(trueB), falseBlock(falseB),
+        flatten(false), dontFlatten(false) {}
     TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) :
-        TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB), control(ESelectionControlNone) {}
+        TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB),
+        flatten(false), dontFlatten(false) {}
     virtual void traverse(TIntermTraverser*);
     virtual TIntermTyped* getCondition() const { return condition; }
     virtual TIntermNode* getTrueBlock() const { return trueBlock; }
     virtual TIntermNode* getFalseBlock() const { return falseBlock; }
     virtual       TIntermSelection* getAsSelectionNode()       { return this; }
     virtual const TIntermSelection* getAsSelectionNode() const { return this; }
-    void setSelectionControl(TSelectionControl c) { control = c; }
-    TSelectionControl getSelectionControl() const { return control; }
+
+    void setFlatten()     { flatten = true; }
+    void setDontFlatten() { dontFlatten = true; }
+    bool getFlatten()     const { return flatten; }
+    bool getDontFlatten() const { return dontFlatten; }
+
 protected:
     TIntermTyped* condition;
     TIntermNode* trueBlock;
     TIntermNode* falseBlock;
-    TSelectionControl control;    // selection control hint
+    bool flatten;     // true if flatten requested
+    bool dontFlatten; // true if requested to not flatten
 };
 
 //
@@ -1369,18 +1368,24 @@ protected:
 //
 class TIntermSwitch : public TIntermNode {
 public:
-    TIntermSwitch(TIntermTyped* cond, TIntermAggregate* b) : condition(cond), body(b), control(ESelectionControlNone) { }
+    TIntermSwitch(TIntermTyped* cond, TIntermAggregate* b) : condition(cond), body(b),
+        flatten(false), dontFlatten(false) {}
     virtual void traverse(TIntermTraverser*);
     virtual TIntermNode* getCondition() const { return condition; }
     virtual TIntermAggregate* getBody() const { return body; }
     virtual       TIntermSwitch* getAsSwitchNode()       { return this; }
     virtual const TIntermSwitch* getAsSwitchNode() const { return this; }
-    void setSelectionControl(TSelectionControl c) { control = c; }
-    TSelectionControl getSelectionControl() const { return control; }
+
+    void setFlatten()     { flatten = true; }
+    void setDontFlatten() { dontFlatten = true; }
+    bool getFlatten()     const { return flatten; }
+    bool getDontFlatten() const { return dontFlatten; }
+
 protected:
     TIntermTyped* condition;
     TIntermAggregate* body;
-    TSelectionControl control;    // selection control hint
+    bool flatten;     // true if flatten requested
+    bool dontFlatten; // true if requested to not flatten
 };
 
 enum TVisit

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

@@ -1614,7 +1614,7 @@ TIntermAggregate* TIntermediate::makeAggregate(const TSourceLoc& loc)
 //
 // Returns the selection node created.
 //
-TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc& loc, TSelectionControl control)
+TIntermSelection* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc& loc)
 {
     //
     // Don't prune the false path for compile-time constants; it's needed
@@ -1623,7 +1623,6 @@ TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair no
 
     TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
     node->setLoc(loc);
-    node->setSelectionControl(control);
 
     return node;
 }
@@ -1666,12 +1665,13 @@ TIntermTyped* TIntermediate::addMethod(TIntermTyped* object, const TType& type,
 //
 // Returns the selection node created, or nullptr if one could not be.
 //
-TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc& loc, TSelectionControl control)
+TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock,
+                                          const TSourceLoc& loc)
 {
     // If it's void, go to the if-then-else selection()
     if (trueBlock->getBasicType() == EbtVoid && falseBlock->getBasicType() == EbtVoid) {
         TIntermNodePair pair = { trueBlock, falseBlock };
-        return addSelection(cond, pair, loc, control);
+        return addSelection(cond, pair, loc);
     }
 
     //
@@ -1909,11 +1909,11 @@ const TIntermTyped* TIntermediate::findLValueBase(const TIntermTyped* node, bool
 //
 // Create while and do-while loop nodes.
 //
-TIntermLoop* TIntermediate::addLoop(TIntermNode* body, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, const TSourceLoc& loc, TLoopControl control)
+TIntermLoop* TIntermediate::addLoop(TIntermNode* body, TIntermTyped* test, TIntermTyped* terminal, bool testFirst,
+    const TSourceLoc& loc)
 {
     TIntermLoop* node = new TIntermLoop(body, test, terminal, testFirst);
     node->setLoc(loc);
-    node->setLoopControl(control);
 
     return node;
 }
@@ -1921,11 +1921,11 @@ TIntermLoop* TIntermediate::addLoop(TIntermNode* body, TIntermTyped* test, TInte
 //
 // Create a for-loop sequence.
 //
-TIntermAggregate* TIntermediate::addForLoop(TIntermNode* body, TIntermNode* initializer, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, const TSourceLoc& loc, TLoopControl control)
+TIntermAggregate* TIntermediate::addForLoop(TIntermNode* body, TIntermNode* initializer, TIntermTyped* test,
+    TIntermTyped* terminal, bool testFirst, const TSourceLoc& loc, TIntermLoop*& node)
 {
-    TIntermLoop* node = new TIntermLoop(body, test, terminal, testFirst);
+    node = new TIntermLoop(body, test, terminal, testFirst);
     node->setLoc(loc);
-    node->setLoopControl(control);
 
     // make a sequence of the initializer and statement, but try to reuse the
     // aggregate already created for whatever is in the initializer, if there is one

+ 2 - 2
3rdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp

@@ -776,7 +776,7 @@ TFunction* TParseContext::handleFunctionDeclarator(const TSourceLoc& loc, TFunct
         if (prevDec->isPrototyped() && prototype)
             profileRequires(loc, EEsProfile, 300, nullptr, "multiple prototypes for same function");
         if (prevDec->getType() != function.getType())
-            error(loc, "overloaded functions must have the same return type", function.getType().getBasicTypeString().c_str(), "");
+            error(loc, "overloaded functions must have the same return type", function.getName().c_str(), "");
         for (int i = 0; i < prevDec->getParamCount(); ++i) {
             if ((*prevDec)[i].type->getQualifier().storage != function[i].type->getQualifier().storage)
                 error(loc, "overloaded functions must have the same parameter storage qualifiers for argument", function[i].type->getStorageQualifierString(), "%d", i+1);
@@ -3103,7 +3103,7 @@ void TParseContext::arrayDimCheck(const TSourceLoc& loc, const TType* type, cons
 //
 void TParseContext::arrayDimMerge(TType& type, const TArraySizes* sizes)
 {
-    if (sizes)
+    if (sizes != nullptr)
         type.addArrayOuterSizes(*sizes);
 }
 

+ 15 - 2
3rdparty/glslang/glslang/MachineIndependent/ParseHelper.h

@@ -44,13 +44,15 @@
 #ifndef _PARSER_HELPER_INCLUDED_
 #define _PARSER_HELPER_INCLUDED_
 
+#include <cstdarg>
+#include <functional>
+
 #include "parseVersions.h"
 #include "../Include/ShHandle.h"
 #include "SymbolTable.h"
 #include "localintermediate.h"
 #include "Scan.h"
-#include <cstdarg>
-#include <functional>
+#include "attribute.h"
 
 namespace glslang {
 
@@ -409,6 +411,17 @@ public:
     TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body);
 
     void updateImplicitArraySize(const TSourceLoc&, TIntermNode*, int index);
+    TAttributeType attributeFromName(const TString& name) const;
+    TAttributes* makeAttributes(const TString& identifier) const;
+    TAttributes* makeAttributes(const TString& identifier, TIntermNode* node) const;
+    TAttributes* mergeAttributes(TAttributes*, TAttributes*) const;
+
+    // Determine selection control from attributes
+    void handleSelectionAttributes(const TAttributes& attributes, TIntermNode*);
+    void handleSwitchAttributes(const TAttributes& attributes, TIntermNode*);
+
+    // Determine loop control from attributes
+    void handleLoopAttributes(const TAttributes& attributes, TIntermNode*);
 
 protected:
     void nonInitConstCheck(const TSourceLoc&, TString& identifier, TType& type);

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

@@ -45,6 +45,7 @@
 #include "../Include/Types.h"
 #include "SymbolTable.h"
 #include "ParseHelper.h"
+#include "attribute.h"
 #include "glslang_tab.cpp.h"
 #include "ScanContext.h"
 #include "Scan.h"

+ 2 - 0
3rdparty/glslang/glslang/MachineIndependent/Versions.cpp

@@ -188,6 +188,7 @@ void TParseVersions::initializeExtensionBehavior()
     extensionBehavior[E_GL_EXT_shader_non_constant_global_initializers] = EBhDisable;
     extensionBehavior[E_GL_EXT_shader_image_load_formatted]             = EBhDisable;
     extensionBehavior[E_GL_EXT_post_depth_coverage]                     = EBhDisable;
+    extensionBehavior[E_GL_EXT_control_flow_attributes]                 = EBhDisable;
 
     // #line and #include
     extensionBehavior[E_GL_GOOGLE_cpp_style_line_directive]          = EBhDisable;
@@ -328,6 +329,7 @@ void TParseVersions::getPreamble(std::string& preamble)
             "#define GL_EXT_shader_non_constant_global_initializers 1\n"
             "#define GL_EXT_shader_image_load_formatted 1\n"
             "#define GL_EXT_post_depth_coverage 1\n"
+            "#define GL_EXT_control_flow_attributes 1\n"
 
 #ifdef AMD_EXTENSIONS
             "#define GL_AMD_shader_ballot 1\n"

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

@@ -146,6 +146,7 @@ const char* const E_GL_EXT_shader_image_load_formatted = "GL_EXT_shader_image_lo
 const char* const E_GL_EXT_device_group                 = "GL_EXT_device_group";
 const char* const E_GL_EXT_multiview                    = "GL_EXT_multiview";
 const char* const E_GL_EXT_post_depth_coverage          = "GL_EXT_post_depth_coverage";
+const char* const E_GL_EXT_control_flow_attributes      = "GL_EXT_control_flow_attributes";
 
 // Arrays of extensions for the above viewportEXTs duplications
 

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

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

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

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

+ 58 - 5
3rdparty/glslang/glslang/MachineIndependent/glslang.y

@@ -58,6 +58,7 @@ Jutta Degener, 1995
 #include "SymbolTable.h"
 #include "ParseHelper.h"
 #include "../Public/ShaderLang.h"
+#include "attribute.h"
 
 using namespace glslang;
 
@@ -86,6 +87,7 @@ using namespace glslang;
             TIntermNode* intermNode;
             glslang::TIntermNodePair nodePair;
             glslang::TIntermTyped* intermTypedNode;
+            glslang::TAttributes* attributes;
         };
         union {
             glslang::TPublicType type;
@@ -218,12 +220,12 @@ extern int yylex(YYSTYPE*, TParseContext&);
 %type <interm.intermNode> translation_unit function_definition
 %type <interm.intermNode> statement simple_statement
 %type <interm.intermNode> statement_list switch_statement_list compound_statement
-%type <interm.intermNode> declaration_statement selection_statement expression_statement
-%type <interm.intermNode> switch_statement case_label
+%type <interm.intermNode> declaration_statement selection_statement selection_statement_nonattributed expression_statement
+%type <interm.intermNode> switch_statement switch_statement_nonattributed case_label
 %type <interm.intermNode> declaration external_declaration
 %type <interm.intermNode> for_init_statement compound_statement_no_new_scope
 %type <interm.nodePair> selection_rest_statement for_rest_statement
-%type <interm.intermNode> iteration_statement jump_statement statement_no_new_scope statement_scoped
+%type <interm.intermNode> iteration_statement iteration_statement_nonattributed jump_statement statement_no_new_scope statement_scoped
 %type <interm> single_declaration init_declarator_list
 
 %type <interm> parameter_declaration parameter_declarator parameter_type_specifier
@@ -246,6 +248,8 @@ extern int yylex(YYSTYPE*, TParseContext&);
 
 %type <interm.identifierList> identifier_list
 
+%type <interm.attributes> attribute attribute_list single_attribute
+
 %start translation_unit
 %%
 
@@ -898,9 +902,9 @@ parameter_declarator
         parseContext.arraySizeRequiredCheck($3.loc, *$3.arraySizes);
         parseContext.reservedErrorCheck($2.loc, *$2.string);
 
-        $1.arraySizes = $3.arraySizes;
-
         TParameter param = { $2.string, new TType($1)};
+        parseContext.arrayDimMerge(*param.type, $3.arraySizes);
+
         $$.loc = $2.loc;
         $$.param = param;
     }
@@ -2673,6 +2677,15 @@ expression_statement
     ;
 
 selection_statement
+    : selection_statement_nonattributed {
+        $$ = $1;
+    }
+    | attribute selection_statement_nonattributed {
+        parseContext.handleSelectionAttributes(*$1, $2);
+        $$ = $2;
+    }
+
+selection_statement_nonattributed
     : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement {
         parseContext.boolCheck($1.loc, $3);
         $$ = parseContext.intermediate.addSelection($3, $5, $1.loc);
@@ -2709,6 +2722,15 @@ condition
     ;
 
 switch_statement
+    : switch_statement_nonattributed {
+        $$ = $1;
+    }
+    | attribute switch_statement_nonattributed {
+        parseContext.handleSwitchAttributes(*$1, $2);
+        $$ = $2;
+    }
+
+switch_statement_nonattributed
     : SWITCH LEFT_PAREN expression RIGHT_PAREN {
         // start new switch sequence on the switch stack
         ++parseContext.controlFlowNestingLevel;
@@ -2762,6 +2784,15 @@ case_label
     ;
 
 iteration_statement
+    : iteration_statement_nonattributed {
+        $$ = $1;
+    }
+    | attribute iteration_statement_nonattributed {
+        parseContext.handleLoopAttributes(*$1, $2);
+        $$ = $2;
+    }
+
+iteration_statement_nonattributed
     : WHILE LEFT_PAREN {
         if (! parseContext.limits.whileLoops)
             parseContext.error($1.loc, "while loops not available", "limitation", "");
@@ -2920,4 +2951,26 @@ function_definition
     }
     ;
 
+attribute
+    : LEFT_BRACKET LEFT_BRACKET attribute_list RIGHT_BRACKET RIGHT_BRACKET {
+        $$ = $3;
+        parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_control_flow_attributes, "attribute");
+    }
+
+attribute_list
+    : single_attribute {
+        $$ = $1;
+    }
+    | attribute_list COMMA single_attribute {
+        $$ = parseContext.mergeAttributes($1, $3);
+    }
+
+single_attribute
+    : IDENTIFIER {
+        $$ = parseContext.makeAttributes(*$1.string);
+    }
+    | IDENTIFIER LEFT_PAREN constant_expression RIGHT_PAREN {
+        $$ = parseContext.makeAttributes(*$1.string, $3);
+    }
+
 %%

ファイルの差分が大きいため隠しています
+ 477 - 434
3rdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp


+ 3 - 2
3rdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp.h

@@ -348,7 +348,7 @@ extern int yydebug;
 typedef union YYSTYPE YYSTYPE;
 union YYSTYPE
 {
-#line 68 "MachineIndependent/glslang.y" /* yacc.c:1909  */
+#line 69 "MachineIndependent/glslang.y" /* yacc.c:1909  */
 
     struct {
         glslang::TSourceLoc loc;
@@ -370,6 +370,7 @@ union YYSTYPE
             TIntermNode* intermNode;
             glslang::TIntermNodePair nodePair;
             glslang::TIntermTyped* intermTypedNode;
+            glslang::TAttributes* attributes;
         };
         union {
             glslang::TPublicType type;
@@ -382,7 +383,7 @@ union YYSTYPE
         };
     } interm;
 
-#line 386 "MachineIndependent/glslang_tab.cpp.h" /* yacc.c:1909  */
+#line 387 "MachineIndependent/glslang_tab.cpp.h" /* yacc.c:1909  */
 };
 # define YYSTYPE_IS_TRIVIAL 1
 # define YYSTYPE_IS_DECLARED 1

+ 25 - 3
3rdparty/glslang/glslang/MachineIndependent/intermOut.cpp

@@ -817,7 +817,13 @@ bool TOutputTraverser::visitSelection(TVisit /* visit */, TIntermSelection* node
     OutputTreeText(out, node, depth);
 
     out.debug << "Test condition and select";
-    out.debug << " (" << node->getCompleteString() << ")\n";
+    out.debug << " (" << node->getCompleteString() << ")";
+
+    if (node->getFlatten())
+        out.debug << ": Flatten";
+    if (node->getDontFlatten())
+        out.debug << ": DontFlatten";
+    out.debug << "\n";
 
     ++depth;
 
@@ -979,7 +985,17 @@ bool TOutputTraverser::visitLoop(TVisit /* visit */, TIntermLoop* node)
     out.debug << "Loop with condition ";
     if (! node->testFirst())
         out.debug << "not ";
-    out.debug << "tested first\n";
+    out.debug << "tested first";
+
+    if (node->getUnroll())
+        out.debug << ": Unroll";
+    if (node->getDontUnroll())
+        out.debug << ": DontUnroll";
+    if (node->getLoopDependency()) {
+        out.debug << ": Dependency ";
+        out.debug << node->getLoopDependency();
+    }
+    out.debug << "\n";
 
     ++depth;
 
@@ -1040,7 +1056,13 @@ bool TOutputTraverser::visitSwitch(TVisit /* visit */, TIntermSwitch* node)
     TInfoSink& out = infoSink;
 
     OutputTreeText(out, node, depth);
-    out.debug << "switch\n";
+    out.debug << "switch";
+
+    if (node->getFlatten())
+        out.debug << ": Flatten";
+    if (node->getDontFlatten())
+        out.debug << ": DontFlatten";
+    out.debug << "\n";
 
     OutputTreeText(out, node, depth);
     out.debug << "condition\n";

+ 5 - 4
3rdparty/glslang/glslang/MachineIndependent/localintermediate.h

@@ -420,8 +420,8 @@ public:
     TIntermAggregate* makeAggregate(const TSourceLoc&);
     TIntermTyped* setAggregateOperator(TIntermNode*, TOperator, const TType& type, TSourceLoc);
     bool areAllChildConst(TIntermAggregate* aggrNode);
-    TIntermTyped* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&, TSelectionControl = ESelectionControlNone);
-    TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&, TSelectionControl = ESelectionControlNone);
+    TIntermSelection* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&);
+    TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&);
     TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
     TIntermTyped* addMethod(TIntermTyped*, const TType&, const TString*, const TSourceLoc&);
     TIntermConstantUnion* addConstantUnion(const TConstUnionArray&, const TType&, const TSourceLoc&, bool literal = false) const;
@@ -439,8 +439,9 @@ public:
     TIntermConstantUnion* addConstantUnion(const TString*, const TSourceLoc&, bool literal = false) const;
     TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) const;
     bool parseConstTree(TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false);
-    TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&, TLoopControl = ELoopControlNone);
-    TIntermAggregate* addForLoop(TIntermNode*, TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&, TLoopControl = ELoopControlNone);
+    TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&);
+    TIntermAggregate* addForLoop(TIntermNode*, TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst,
+        const TSourceLoc&, TIntermLoop*&);
     TIntermBranch* addBranch(TOperator, const TSourceLoc&);
     TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&);
     template<typename selectorType> TIntermTyped* addSwizzle(TSwizzleSelectors<selectorType>&, const TSourceLoc&);

+ 2 - 1
3rdparty/glslang/glslang/Public/ShaderLang.h

@@ -119,7 +119,8 @@ typedef enum {
 
 typedef enum {
     EShTargetNone,
-    EshTargetSpv,
+    EShTargetSpv,                 // preferred spelling
+    EshTargetSpv = EShTargetSpv,  // legacy spelling
 } EShTargetLanguage;
 
 struct TInputLanguage {

+ 1 - 1
3rdparty/glslang/gtests/Hlsl.FromFile.cpp

@@ -247,7 +247,7 @@ INSTANTIATE_TEST_CASE_P(
         {"hlsl.matrixindex.frag", "main"},
         {"hlsl.nonstaticMemberFunction.frag", "main"},
         {"hlsl.numericsuffixes.frag", "main"},
-        {"hlsl.numthreads.comp", "main_aux1"},
+        {"hlsl.numthreads.comp", "main_aux2"},
         {"hlsl.overload.frag", "PixelShaderFunction"},
         {"hlsl.opaque-type-bug.frag", "main"},
         {"hlsl.params.default.frag", "main"},

+ 1 - 0
3rdparty/glslang/gtests/Spv.FromFile.cpp

@@ -235,6 +235,7 @@ INSTANTIATE_TEST_CASE_P(
         "spv.branch-return.vert",
         "spv.builtInXFB.vert",
         "spv.conditionalDiscard.frag",
+        "spv.controlFlowAttributes.frag",
         "spv.conversion.frag",
         "spv.dataOut.frag",
         "spv.dataOutIndirect.frag",

+ 29 - 113
3rdparty/glslang/hlsl/hlslAttributes.cpp

@@ -34,157 +34,73 @@
 //
 
 #include "hlslAttributes.h"
-#include <cstdlib>
-#include <cctype>
-#include <algorithm>
+#include "hlslParseHelper.h"
 
 namespace glslang {
     // Map the given string to an attribute enum from TAttributeType,
     // or EatNone if invalid.
-    TAttributeType TAttributeMap::attributeFromName(const TString& nameSpace, const TString& name)
+    TAttributeType HlslParseContext::attributeFromName(const TString& nameSpace, const TString& name) const
     {
-        // These are case insensitive.
-        TString lowername(name);
-        std::transform(lowername.begin(), lowername.end(), lowername.begin(), ::tolower);
-        TString lowernameSpace(nameSpace);
-        std::transform(lowernameSpace.begin(), lowernameSpace.end(), lowernameSpace.begin(), ::tolower);
-
         // handle names within a namespace
 
-        if (lowernameSpace == "vk") {
-            if (lowername == "input_attachment_index")
+        if (nameSpace == "vk") {
+            if (name == "input_attachment_index")
                 return EatInputAttachment;
-            else if (lowername == "location")
+            else if (name == "location")
                 return EatLocation;
-            else if (lowername == "binding")
+            else if (name == "binding")
                 return EatBinding;
-            else if (lowername == "global_cbuffer_binding")
+            else if (name == "global_cbuffer_binding")
                 return EatGlobalBinding;
-            else if (lowername == "builtin")
+            else if (name == "builtin")
                 return EatBuiltIn;
-            else if (lowername == "constant_id")
+            else if (name == "constant_id")
                 return EatConstantId;
-            else if (lowername == "push_constant")
+            else if (name == "push_constant")
                 return EatPushConstant;
-        } else if (lowernameSpace.size() > 0)
+        } else if (nameSpace.size() > 0)
             return EatNone;
 
         // handle names with no namespace
 
-        if (lowername == "allow_uav_condition")
+        if (name == "allow_uav_condition")
             return EatAllow_uav_condition;
-        else if (lowername == "branch")
+        else if (name == "branch")
             return EatBranch;
-        else if (lowername == "call")
+        else if (name == "call")
             return EatCall;
-        else if (lowername == "domain")
+        else if (name == "domain")
             return EatDomain;
-        else if (lowername == "earlydepthstencil")
+        else if (name == "earlydepthstencil")
             return EatEarlyDepthStencil;
-        else if (lowername == "fastopt")
+        else if (name == "fastopt")
             return EatFastOpt;
-        else if (lowername == "flatten")
+        else if (name == "flatten")
             return EatFlatten;
-        else if (lowername == "forcecase")
+        else if (name == "forcecase")
             return EatForceCase;
-        else if (lowername == "instance")
+        else if (name == "instance")
             return EatInstance;
-        else if (lowername == "maxtessfactor")
+        else if (name == "maxtessfactor")
             return EatMaxTessFactor;
-        else if (lowername == "maxvertexcount")
+        else if (name == "maxvertexcount")
             return EatMaxVertexCount;
-        else if (lowername == "numthreads")
+        else if (name == "numthreads")
             return EatNumThreads;
-        else if (lowername == "outputcontrolpoints")
+        else if (name == "outputcontrolpoints")
             return EatOutputControlPoints;
-        else if (lowername == "outputtopology")
+        else if (name == "outputtopology")
             return EatOutputTopology;
-        else if (lowername == "partitioning")
+        else if (name == "partitioning")
             return EatPartitioning;
-        else if (lowername == "patchconstantfunc")
+        else if (name == "patchconstantfunc")
             return EatPatchConstantFunc;
-        else if (lowername == "unroll")
+        else if (name == "unroll")
             return EatUnroll;
-        else if (lowername == "loop")
+        else if (name == "loop")
             return EatLoop;
         else
             return EatNone;
     }
 
-    // Look up entry, inserting if it's not there, and if name is a valid attribute name
-    // as known by attributeFromName.
-    TAttributeType TAttributeMap::setAttribute(const TString& nameSpace, const TString* name, TIntermAggregate* value)
-    {
-        if (name == nullptr)
-            return EatNone;
-
-        const TAttributeType attr = attributeFromName(nameSpace, *name);
-
-        if (attr != EatNone)
-            attributes[attr] = value;
-
-        return attr;
-    }
-
-    // Look up entry (const version), and return aggregate node.  This cannot change the map.
-    const TIntermAggregate* TAttributeMap::operator[](TAttributeType attr) const
-    {
-        const auto entry = attributes.find(attr);
-
-        return (entry == attributes.end()) ? nullptr : entry->second;
-    }
-
-    // True if entry exists in map (even if value is nullptr)
-    bool TAttributeMap::contains(TAttributeType attr) const
-    {
-        return attributes.find(attr) != attributes.end();
-    }
-
-    // extract integers out of attribute arguments stored in attribute aggregate
-    bool TAttributeMap::getInt(TAttributeType attr, int& value, int argNum) const 
-    {
-        const TConstUnion* intConst = getConstUnion(attr, EbtInt, argNum);
-
-        if (intConst == nullptr)
-            return false;
-
-        value = intConst->getIConst();
-        return true;
-    };
-
-    // extract strings out of attribute arguments stored in attribute aggregate.
-    // convert to lower case if converToLower is true (for case-insensitive compare convenience)
-    bool TAttributeMap::getString(TAttributeType attr, TString& value, int argNum, bool convertToLower) const 
-    {
-        const TConstUnion* stringConst = getConstUnion(attr, EbtString, argNum);
-
-        if (stringConst == nullptr)
-            return false;
-
-        value = *stringConst->getSConst();
-
-        // Convenience.
-        if (convertToLower)
-            std::transform(value.begin(), value.end(), value.begin(), ::tolower);
-
-        return true;
-    };
-
-    // Helper to get attribute const union.  Returns nullptr on failure.
-    const TConstUnion* TAttributeMap::getConstUnion(TAttributeType attr, TBasicType basicType, int argNum) const
-    {
-        const TIntermAggregate* attrAgg = (*this)[attr];
-        if (attrAgg == nullptr)
-            return nullptr;
-
-        if (argNum >= int(attrAgg->getSequence().size()))
-            return nullptr;
-
-        const TConstUnion* constVal = &attrAgg->getSequence()[argNum]->getAsConstantUnion()->getConstArray()[0];
-        if (constVal == nullptr || constVal->getType() != basicType)
-            return nullptr;
-
-        return constVal;
-    }
-
 } // end namespace glslang

+ 4 - 75
3rdparty/glslang/hlsl/hlslAttributes.h

@@ -38,93 +38,22 @@
 
 #include <unordered_map>
 #include <functional>
-#include "hlslScanContext.h"
-#include "../glslang/Include/Common.h"
 
-namespace glslang {
-    enum TAttributeType {
-        EatNone,
-        EatAllow_uav_condition,
-        EatBranch,
-        EatCall,
-        EatDomain,
-        EatEarlyDepthStencil,
-        EatFastOpt,
-        EatFlatten,
-        EatForceCase,
-        EatInstance,
-        EatMaxTessFactor,
-        EatNumThreads,
-        EatMaxVertexCount,
-        EatOutputControlPoints,
-        EatOutputTopology,
-        EatPartitioning,
-        EatPatchConstantFunc,
-        EatPatchSize,
-        EatUnroll,
-        EatLoop,
-        EatBinding,
-        EatGlobalBinding,
-        EatLocation,
-        EatInputAttachment,
-        EatBuiltIn,
-        EatPushConstant,
-        EatConstantId
-    };
-}
-
-namespace std {
-    // Allow use of TAttributeType enum in hash_map without calling code having to cast.
-    template <> struct hash<glslang::TAttributeType> {
-        std::size_t operator()(glslang::TAttributeType attr) const {
-            return std::hash<int>()(int(attr));
-        }
-    };
-} // end namespace std
+#include "../glslang/MachineIndependent/attribute.h"
+#include "../glslang/MachineIndependent/SymbolTable.h"
+#include "hlslScanContext.h"
 
 namespace glslang {
-    class TIntermAggregate;
-
-    class TAttributeMap {
-    public:
-        int size() const { return (int)attributes.size(); }
-
-        // Search for and potentially add the attribute into the map.  Return the
-        // attribute type enum for it, if found, else EatNone.
-        TAttributeType setAttribute(const TString& nameSpace, const TString* name, TIntermAggregate* value);
-
-        // Const lookup: search for (but do not modify) the attribute in the map.
-        const TIntermAggregate* operator[](TAttributeType) const;
-
-        // True if entry exists in map (even if value is nullptr)
-        bool contains(TAttributeType) const;
-
-        // Obtain attribute as integer
-        bool getInt(TAttributeType attr, int& value, int argNum = 0) const;
-
-        // Obtain attribute as string, with optional to-lower transform
-        bool getString(TAttributeType attr, TString& value, int argNum = 0, bool convertToLower = true) const;
-
-    protected:
-        // Helper to get attribute const union
-        const TConstUnion* getConstUnion(TAttributeType attr, TBasicType, int argNum) const;
-
-        // Find an attribute enum given its name.
-        static TAttributeType attributeFromName(const TString& nameSpace, const TString& name);
-
-        std::unordered_map<TAttributeType, TIntermAggregate*> attributes;
-    };
 
     class TFunctionDeclarator {
     public:
         TFunctionDeclarator() : function(nullptr), body(nullptr) { }
         TSourceLoc loc;
         TFunction* function;
-        TAttributeMap attributes;
+        TAttributes attributes;
         TVector<HlslToken>* body;
     };
 
 } // end namespace glslang
 
-
 #endif // HLSLATTRIBUTES_H_

+ 57 - 34
3rdparty/glslang/hlsl/hlslGrammar.cpp

@@ -396,6 +396,9 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& nodeList)
         if (peekTokenClass(EHTokLeftParen)) {
             // looks like function parameters
 
+            // merge in the attributes into the return type
+            parseContext.transferTypeAttributes(token.loc, declarator.attributes, declaredType, true);
+
             // Potentially rename shader entry point function.  No-op most of the time.
             parseContext.renameShaderFunction(fullName);
 
@@ -423,7 +426,13 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& nodeList)
                 parseContext.handleFunctionDeclarator(declarator.loc, *declarator.function, true);
             }
         } else {
-            // A variable declaration. Fix the storage qualifier if it's a global.
+            // A variable declaration.
+
+            // merge in the attributes, the first time around, into the shared type
+            if (! declarator_list)
+                parseContext.transferTypeAttributes(token.loc, declarator.attributes, declaredType);
+
+            // Fix the storage qualifier if it's a global.
             if (declaredType.getQualifier().storage == EvqTemporary && parseContext.symbolTable.atGlobalLevel())
                 declaredType.getQualifier().storage = EvqUniform;
 
@@ -536,13 +545,16 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& nodeList)
 bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node)
 {
     node = nullptr;
-    TAttributeMap attributes;
+    TAttributes attributes;
 
     // fully_specified_type
     TType type;
     if (! acceptFullySpecifiedType(type, attributes))
         return false;
 
+    if (attributes.size() > 0)
+        parseContext.warn(token.loc, "attributes don't apply to control declaration", "", "");
+
     // filter out type casts
     if (peekTokenClass(EHTokLeftParen)) {
         recedeToken();
@@ -578,12 +590,12 @@ bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node)
 //      : type_specifier
 //      | type_qualifier type_specifier
 //
-bool HlslGrammar::acceptFullySpecifiedType(TType& type, const TAttributeMap& attributes)
+bool HlslGrammar::acceptFullySpecifiedType(TType& type, const TAttributes& attributes)
 {
     TIntermNode* nodeList = nullptr;
     return acceptFullySpecifiedType(type, nodeList, attributes);
 }
-bool HlslGrammar::acceptFullySpecifiedType(TType& type, TIntermNode*& nodeList, const TAttributeMap& attributes, bool forbidDeclarators)
+bool HlslGrammar::acceptFullySpecifiedType(TType& type, TIntermNode*& nodeList, const TAttributes& attributes, bool forbidDeclarators)
 {
     // type_qualifier
     TQualifier qualifier;
@@ -608,7 +620,7 @@ bool HlslGrammar::acceptFullySpecifiedType(TType& type, TIntermNode*& nodeList,
         parseContext.mergeQualifiers(type.getQualifier(), qualifier);
     
         // merge in the attributes
-        parseContext.transferTypeAttributes(attributes, type);
+        parseContext.transferTypeAttributes(token.loc, attributes, type);
 
         // further, it can create an anonymous instance of the block
         // (cbuffer and tbuffer don't consume the next identifier, and
@@ -633,9 +645,6 @@ bool HlslGrammar::acceptFullySpecifiedType(TType& type, TIntermNode*& nodeList,
             qualifier.builtIn = type.getQualifier().builtIn;
 
         type.getQualifier() = qualifier;
-
-        // merge in the attributes
-        parseContext.transferTypeAttributes(attributes, type);
     }
 
     return true;
@@ -2335,7 +2344,7 @@ bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList, TIntermNode*
         // struct_declaration
 
         // attributes
-        TAttributeMap attributes;
+        TAttributes attributes;
         acceptAttributes(attributes);
 
         bool declarator_list = false;
@@ -2346,6 +2355,9 @@ bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList, TIntermNode*
             expected("member type");
             return false;
         }
+        
+        // merge in the attributes
+        parseContext.transferTypeAttributes(token.loc, attributes, memberType);
 
         // struct_declarator COMMA struct_declarator ...
         bool functionDefinitionAccepted = false;
@@ -2542,7 +2554,7 @@ bool HlslGrammar::acceptDefaultParameterDeclaration(const TType& type, TIntermTy
 bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
 {
     // attributes
-    TAttributeMap attributes;
+    TAttributes attributes;
     acceptAttributes(attributes);
 
     // fully_specified_type
@@ -2550,6 +2562,9 @@ bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
     if (! acceptFullySpecifiedType(*type, attributes))
         return false;
 
+    // merge in the attributes
+    parseContext.transferTypeAttributes(token.loc, attributes, *type);
+
     // identifier
     HlslToken idToken;
     acceptIdentifier(idToken);
@@ -3386,7 +3401,7 @@ bool HlslGrammar::acceptStatement(TIntermNode*& statement)
     statement = nullptr;
 
     // attributes
-    TAttributeMap attributes;
+    TAttributes attributes;
     acceptAttributes(attributes);
 
     // attributed_statement
@@ -3458,7 +3473,7 @@ bool HlslGrammar::acceptStatement(TIntermNode*& statement)
 //      | PATCHCONSTANTFUNC
 //      | NUMTHREADS LEFT_PAREN x_size, y_size,z z_size RIGHT_PAREN
 //
-void HlslGrammar::acceptAttributes(TAttributeMap& attributes)
+void HlslGrammar::acceptAttributes(TAttributes& attributes)
 {
     // For now, accept the [ XXX(X) ] syntax, but drop all but
     // numthreads, which is used to set the CS local size.
@@ -3529,9 +3544,16 @@ void HlslGrammar::acceptAttributes(TAttributeMap& attributes)
             return;
         }
 
-        // Add any values we found into the attribute map.  This accepts
-        // (and ignores) values not mapping to a known TAttributeType;
-        attributes.setAttribute(nameSpace, attributeToken.string, expressions);
+        // Add any values we found into the attribute map.
+        if (attributeToken.string != nullptr) {
+            TAttributeType attributeType = parseContext.attributeFromName(nameSpace, *attributeToken.string);
+            if (attributeType == EatNone)
+                parseContext.warn(attributeToken.loc, "unrecognized attribute", attributeToken.string->c_str(), "");
+            else {
+                TAttributeArgs attributeArgs = { attributeType, expressions };
+                attributes.push_back(attributeArgs);
+            }
+        }
     } while (true);
 }
 
@@ -3539,12 +3561,10 @@ void HlslGrammar::acceptAttributes(TAttributeMap& attributes)
 //      : IF LEFT_PAREN expression RIGHT_PAREN statement
 //      : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
 //
-bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement, const TAttributeMap& attributes)
+bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement, const TAttributes& attributes)
 {
     TSourceLoc loc = token.loc;
 
-    const TSelectionControl control = parseContext.handleSelectionControl(attributes);
-
     // IF
     if (! acceptTokenClass(EHTokIf))
         return false;
@@ -3582,7 +3602,9 @@ bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement, const TAttri
     }
 
     // Put the pieces together
-    statement = intermediate.addSelection(condition, thenElse, loc, control);
+    statement = intermediate.addSelection(condition, thenElse, loc);
+    parseContext.handleSelectionAttributes(loc, statement->getAsSelectionNode(), attributes);
+
     parseContext.popScope();
     --parseContext.controlFlowNestingLevel;
 
@@ -3592,13 +3614,11 @@ bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement, const TAttri
 // switch_statement
 //      : SWITCH LEFT_PAREN expression RIGHT_PAREN compound_statement
 //
-bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement, const TAttributeMap& attributes)
+bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement, const TAttributes& attributes)
 {
     // SWITCH
     TSourceLoc loc = token.loc;
 
-    const TSelectionControl control = parseContext.handleSelectionControl(attributes);
-
     if (! acceptTokenClass(EHTokSwitch))
         return false;
 
@@ -3618,7 +3638,8 @@ bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement, const TAttribut
     --parseContext.controlFlowNestingLevel;
 
     if (statementOkay)
-        statement = parseContext.addSwitch(loc, switchExpression, statement ? statement->getAsAggregate() : nullptr, control);
+        statement = parseContext.addSwitch(loc, switchExpression, statement ? statement->getAsAggregate() : nullptr,
+                                           attributes);
 
     parseContext.popSwitchSequence();
     parseContext.popScope();
@@ -3632,7 +3653,7 @@ bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement, const TAttribut
 //      | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
 //
 // Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
-bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement, const TAttributeMap& attributes)
+bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement, const TAttributes& attributes)
 {
     TSourceLoc loc = token.loc;
     TIntermTyped* condition = nullptr;
@@ -3642,9 +3663,8 @@ bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement, const TAttri
 
     //  WHILE or DO or FOR
     advanceToken();
-    
-    const TLoopControl control = parseContext.handleLoopControl(attributes);
 
+    TIntermLoop* loopNode = nullptr;
     switch (loop) {
     case EHTokWhile:
         // so that something declared in the condition is scoped to the lifetime
@@ -3670,9 +3690,9 @@ bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement, const TAttri
         parseContext.popScope();
         --parseContext.controlFlowNestingLevel;
 
-        statement = intermediate.addLoop(statement, condition, nullptr, true, loc, control);
-
-        return true;
+        loopNode = intermediate.addLoop(statement, condition, nullptr, true, loc);
+        statement = loopNode;
+        break;
 
     case EHTokDo:
         parseContext.nestLooping();  // this only needs to work right if no errors
@@ -3703,9 +3723,9 @@ bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement, const TAttri
         parseContext.unnestLooping();
         --parseContext.controlFlowNestingLevel;
 
-        statement = intermediate.addLoop(statement, condition, 0, false, loc, control);
-
-        return true;
+        loopNode = intermediate.addLoop(statement, condition, 0, false, loc);
+        statement = loopNode;
+        break;
 
     case EHTokFor:
     {
@@ -3747,18 +3767,21 @@ bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement, const TAttri
             return false;
         }
 
-        statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc, control);
+        statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc, loopNode);
 
         parseContext.popScope();
         parseContext.unnestLooping();
         --parseContext.controlFlowNestingLevel;
 
-        return true;
+        break;
     }
 
     default:
         return false;
     }
+
+    parseContext.handleLoopAttributes(loc, loopNode, attributes);
+    return true;
 }
 
 // jump_statement

+ 6 - 7
3rdparty/glslang/hlsl/hlslGrammar.h

@@ -43,7 +43,6 @@
 
 namespace glslang {
 
-    class TAttributeMap;
     class TFunctionDeclarator;
 
     // Should just be the grammar aspect of HLSL.
@@ -71,8 +70,8 @@ namespace glslang {
         bool acceptControlDeclaration(TIntermNode*& node);
         bool acceptSamplerDeclarationDX9(TType&);
         bool acceptSamplerState();
-        bool acceptFullySpecifiedType(TType&, const TAttributeMap&);
-        bool acceptFullySpecifiedType(TType&, TIntermNode*& nodeList, const TAttributeMap&, bool forbidDeclarators = false);
+        bool acceptFullySpecifiedType(TType&, const TAttributes&);
+        bool acceptFullySpecifiedType(TType&, TIntermNode*& nodeList, const TAttributes&, bool forbidDeclarators = false);
         bool acceptQualifier(TQualifier&);
         bool acceptLayoutQualifierList(TQualifier&);
         bool acceptType(TType&);
@@ -117,10 +116,10 @@ namespace glslang {
         bool acceptScopedCompoundStatement(TIntermNode*&);
         bool acceptStatement(TIntermNode*&);
         bool acceptNestedStatement(TIntermNode*&);
-        void acceptAttributes(TAttributeMap&);
-        bool acceptSelectionStatement(TIntermNode*&, const TAttributeMap&);
-        bool acceptSwitchStatement(TIntermNode*&, const TAttributeMap&);
-        bool acceptIterationStatement(TIntermNode*&, const TAttributeMap&);
+        void acceptAttributes(TAttributes&);
+        bool acceptSelectionStatement(TIntermNode*&, const TAttributes&);
+        bool acceptSwitchStatement(TIntermNode*&, const TAttributes&);
+        bool acceptIterationStatement(TIntermNode*&, const TAttributes&);
         bool acceptJumpStatement(TIntermNode*&);
         bool acceptCaseLabel(TIntermNode*&);
         bool acceptDefaultLabel(TIntermNode*&);

+ 247 - 173
3rdparty/glslang/hlsl/hlslParseHelper.cpp

@@ -1620,7 +1620,7 @@ void HlslParseContext::addStructBufferHiddenCounterParam(const TSourceLoc& loc,
 // Returns an aggregate of parameter-symbol nodes.
 //
 TIntermAggregate* HlslParseContext::handleFunctionDefinition(const TSourceLoc& loc, TFunction& function,
-                                                             const TAttributeMap& attributes,
+                                                             const TAttributes& attributes,
                                                              TIntermNode*& entryPointTree)
 {
     currentCaller = function.getMangledName();
@@ -1717,189 +1717,217 @@ TIntermAggregate* HlslParseContext::handleFunctionDefinition(const TSourceLoc& l
 }
 
 // Handle all [attrib] attribute for the shader entry point
-void HlslParseContext::handleEntryPointAttributes(const TSourceLoc& loc, const TAttributeMap& attributes)
+void HlslParseContext::handleEntryPointAttributes(const TSourceLoc& loc, const TAttributes& attributes)
 {
-    // Handle entry-point function attributes
-    const TIntermAggregate* numThreads = attributes[EatNumThreads];
-    if (numThreads != nullptr) {
-        const TIntermSequence& sequence = numThreads->getSequence();
-
-        for (int lid = 0; lid < int(sequence.size()); ++lid)
-            intermediate.setLocalSize(lid, sequence[lid]->getAsConstantUnion()->getConstArray()[0].getIConst());
-    }
-
-    // MaxVertexCount
-    if (attributes.contains(EatMaxVertexCount)) {
-        int maxVertexCount;
-
-        if (! attributes.getInt(EatMaxVertexCount, maxVertexCount)) {
-            error(loc, "invalid maxvertexcount", "", "");
-        } else {
-            if (! intermediate.setVertices(maxVertexCount))
-                error(loc, "cannot change previously set maxvertexcount attribute", "", "");
-        }
-    }
-
-    // Handle [patchconstantfunction("...")]
-    if (attributes.contains(EatPatchConstantFunc)) {
-        TString pcfName;
-        if (! attributes.getString(EatPatchConstantFunc, pcfName, 0, false)) {
-            error(loc, "invalid patch constant function", "", "");
-        } else {
-            patchConstantFunctionName = pcfName;
+    for (auto it = attributes.begin(); it != attributes.end(); ++it) {
+        switch (it->name) {
+        case EatNumThreads:
+        {
+            const TIntermSequence& sequence = it->args->getSequence();
+            for (int lid = 0; lid < int(sequence.size()); ++lid)
+                intermediate.setLocalSize(lid, sequence[lid]->getAsConstantUnion()->getConstArray()[0].getIConst());
+            break;
         }
-    }
+        case EatMaxVertexCount:
+        {
+            int maxVertexCount;
 
-    // Handle [domain("...")]
-    if (attributes.contains(EatDomain)) {
-        TString domainStr;
-        if (! attributes.getString(EatDomain, domainStr)) {
-            error(loc, "invalid domain", "", "");
-        } else {
-            TLayoutGeometry domain = ElgNone;
-
-            if (domainStr == "tri") {
-                domain = ElgTriangles;
-            } else if (domainStr == "quad") {
-                domain = ElgQuads;
-            } else if (domainStr == "isoline") {
-                domain = ElgIsolines;
+            if (! it->getInt(maxVertexCount)) {
+                error(loc, "invalid maxvertexcount", "", "");
             } else {
-                error(loc, "unsupported domain type", domainStr.c_str(), "");
+                if (! intermediate.setVertices(maxVertexCount))
+                    error(loc, "cannot change previously set maxvertexcount attribute", "", "");
             }
-
-            if (language == EShLangTessEvaluation) {
-                if (! intermediate.setInputPrimitive(domain))
-                    error(loc, "cannot change previously set domain", TQualifier::getGeometryString(domain), "");
+            break;
+        }
+        case EatPatchConstantFunc:
+        {
+            TString pcfName;
+            if (! it->getString(pcfName, 0, false)) {
+                error(loc, "invalid patch constant function", "", "");
             } else {
-                if (! intermediate.setOutputPrimitive(domain))
-                    error(loc, "cannot change previously set domain", TQualifier::getGeometryString(domain), "");
+                patchConstantFunctionName = pcfName;
             }
+            break;
         }
-    }
-
-    // Handle [outputtopology("...")]
-    if (attributes.contains(EatOutputTopology)) {
-        TString topologyStr;
-        if (! attributes.getString(EatOutputTopology, topologyStr)) {
-            error(loc, "invalid outputtopology", "", "");
-        } else {
-            TVertexOrder vertexOrder = EvoNone;
-            TLayoutGeometry primitive = ElgNone;
-
-            if (topologyStr == "point") {
-                intermediate.setPointMode();
-            } else if (topologyStr == "line") {
-                primitive = ElgIsolines;
-            } else if (topologyStr == "triangle_cw") {
-                vertexOrder = EvoCw;
-                primitive = ElgTriangles;
-            } else if (topologyStr == "triangle_ccw") {
-                vertexOrder = EvoCcw;
-                primitive = ElgTriangles;
+        case EatDomain:
+        {
+            // Handle [domain("...")]
+            TString domainStr;
+            if (! it->getString(domainStr)) {
+                error(loc, "invalid domain", "", "");
             } else {
-                error(loc, "unsupported outputtopology type", topologyStr.c_str(), "");
-            }
+                TLayoutGeometry domain = ElgNone;
+
+                if (domainStr == "tri") {
+                    domain = ElgTriangles;
+                } else if (domainStr == "quad") {
+                    domain = ElgQuads;
+                } else if (domainStr == "isoline") {
+                    domain = ElgIsolines;
+                } else {
+                    error(loc, "unsupported domain type", domainStr.c_str(), "");
+                }
 
-            if (vertexOrder != EvoNone) {
-                if (! intermediate.setVertexOrder(vertexOrder)) {
-                    error(loc, "cannot change previously set outputtopology",
-                          TQualifier::getVertexOrderString(vertexOrder), "");
+                if (language == EShLangTessEvaluation) {
+                    if (! intermediate.setInputPrimitive(domain))
+                        error(loc, "cannot change previously set domain", TQualifier::getGeometryString(domain), "");
+                } else {
+                    if (! intermediate.setOutputPrimitive(domain))
+                        error(loc, "cannot change previously set domain", TQualifier::getGeometryString(domain), "");
                 }
             }
-            if (primitive != ElgNone)
-                intermediate.setOutputPrimitive(primitive);
+            break;
         }
-    }
-
-    // Handle [partitioning("...")]
-    if (attributes.contains(EatPartitioning)) {
-        TString partitionStr;
-        if (! attributes.getString(EatPartitioning, partitionStr)) {
-            error(loc, "invalid partitioning", "", "");
-        } else {
-            TVertexSpacing partitioning = EvsNone;
-                
-            if (partitionStr == "integer") {
-                partitioning = EvsEqual;
-            } else if (partitionStr == "fractional_even") {
-                partitioning = EvsFractionalEven;
-            } else if (partitionStr == "fractional_odd") {
-                partitioning = EvsFractionalOdd;
-                //} else if (partition == "pow2") { // TODO: currently nothing to map this to.
+        case EatOutputTopology:
+        {
+            // Handle [outputtopology("...")]
+            TString topologyStr;
+            if (! it->getString(topologyStr)) {
+                error(loc, "invalid outputtopology", "", "");
             } else {
-                error(loc, "unsupported partitioning type", partitionStr.c_str(), "");
-            }
+                TVertexOrder vertexOrder = EvoNone;
+                TLayoutGeometry primitive = ElgNone;
+
+                if (topologyStr == "point") {
+                    intermediate.setPointMode();
+                } else if (topologyStr == "line") {
+                    primitive = ElgIsolines;
+                } else if (topologyStr == "triangle_cw") {
+                    vertexOrder = EvoCw;
+                    primitive = ElgTriangles;
+                } else if (topologyStr == "triangle_ccw") {
+                    vertexOrder = EvoCcw;
+                    primitive = ElgTriangles;
+                } else {
+                    error(loc, "unsupported outputtopology type", topologyStr.c_str(), "");
+                }
 
-            if (! intermediate.setVertexSpacing(partitioning))
-                error(loc, "cannot change previously set partitioning",
-                      TQualifier::getVertexSpacingString(partitioning), "");
+                if (vertexOrder != EvoNone) {
+                    if (! intermediate.setVertexOrder(vertexOrder)) {
+                        error(loc, "cannot change previously set outputtopology",
+                              TQualifier::getVertexOrderString(vertexOrder), "");
+                    }
+                }
+                if (primitive != ElgNone)
+                    intermediate.setOutputPrimitive(primitive);
+            }
+            break;
         }
-    }
+        case EatPartitioning:
+        {
+            // Handle [partitioning("...")]
+            TString partitionStr;
+            if (! it->getString(partitionStr)) {
+                error(loc, "invalid partitioning", "", "");
+            } else {
+                TVertexSpacing partitioning = EvsNone;
+                
+                if (partitionStr == "integer") {
+                    partitioning = EvsEqual;
+                } else if (partitionStr == "fractional_even") {
+                    partitioning = EvsFractionalEven;
+                } else if (partitionStr == "fractional_odd") {
+                    partitioning = EvsFractionalOdd;
+                    //} else if (partition == "pow2") { // TODO: currently nothing to map this to.
+                } else {
+                    error(loc, "unsupported partitioning type", partitionStr.c_str(), "");
+                }
 
-    // Handle [outputcontrolpoints("...")]
-    if (attributes.contains(EatOutputControlPoints)) {
-        int ctrlPoints;
-        if (! attributes.getInt(EatOutputControlPoints, ctrlPoints)) {
-            error(loc, "invalid outputcontrolpoints", "", "");
-        } else {
-            if (! intermediate.setVertices(ctrlPoints)) {
-                error(loc, "cannot change previously set outputcontrolpoints attribute", "", "");
+                if (! intermediate.setVertexSpacing(partitioning))
+                    error(loc, "cannot change previously set partitioning",
+                          TQualifier::getVertexSpacingString(partitioning), "");
+            }
+            break;
+        }
+        case EatOutputControlPoints:
+        {
+            // Handle [outputcontrolpoints("...")]
+            int ctrlPoints;
+            if (! it->getInt(ctrlPoints)) {
+                error(loc, "invalid outputcontrolpoints", "", "");
+            } else {
+                if (! intermediate.setVertices(ctrlPoints)) {
+                    error(loc, "cannot change previously set outputcontrolpoints attribute", "", "");
+                }
             }
+            break;
+        }
+        case EatBuiltIn:
+        case EatLocation:
+            // tolerate these because of dual use of entrypoint and type attributes
+            break;
+        default:
+            warn(loc, "attribute does not apply to entry point", "", "");
+            break;
         }
     }
 }
 
 // Update the given type with any type-like attribute information in the
 // attributes.
-void HlslParseContext::transferTypeAttributes(const TAttributeMap& attributes, TType& type)
+void HlslParseContext::transferTypeAttributes(const TSourceLoc& loc, const TAttributes& attributes, TType& type,
+    bool allowEntry)
 {
     if (attributes.size() == 0)
         return;
 
-    // location
     int value;
-    if (attributes.getInt(EatLocation, value))
-        type.getQualifier().layoutLocation = value;
-
-    // binding
-    if (attributes.getInt(EatBinding, value)) {
-        type.getQualifier().layoutBinding = value;
-        type.getQualifier().layoutSet = 0;
-    }
-
-    // set
-    if (attributes.getInt(EatBinding, value, 1))
-        type.getQualifier().layoutSet = value;
-
-    // global cbuffer binding
-    if (attributes.getInt(EatGlobalBinding, value))
-        globalUniformBinding = value;
-
-    // global cbuffer binding
-    if (attributes.getInt(EatGlobalBinding, value, 1))
-        globalUniformSet = value;
-
-    // input attachment
-    if (attributes.getInt(EatInputAttachment, value))
-        type.getQualifier().layoutAttachment = value;
-
-    // PointSize built-in
     TString builtInString;
-    if (attributes.getString(EatBuiltIn, builtInString, 0, false)) {
-        if (builtInString == "PointSize")
-            type.getQualifier().builtIn = EbvPointSize;
-    }
-
-    // push_constant
-    if (attributes.contains(EatPushConstant))
-        type.getQualifier().layoutPushConstant = true;
-
-    // specialization constant
-    if (attributes.getInt(EatConstantId, value)) {
-        TSourceLoc loc;
-        loc.init();
-        setSpecConstantId(loc, type.getQualifier(), value);
+    for (auto it = attributes.begin(); it != attributes.end(); ++it) {
+        switch (it->name) {
+        case EatLocation:
+            // location
+            if (it->getInt(value))
+                type.getQualifier().layoutLocation = value;
+            break;
+        case EatBinding:
+            // binding
+            if (it->getInt(value)) {
+                type.getQualifier().layoutBinding = value;
+                type.getQualifier().layoutSet = 0;
+            }
+            // set
+            if (it->getInt(value, 1))
+                type.getQualifier().layoutSet = value;
+            break;
+        case EatGlobalBinding:
+            // global cbuffer binding
+            if (it->getInt(value))
+                globalUniformBinding = value;
+            // global cbuffer binding
+            if (it->getInt(value, 1))
+                globalUniformSet = value;
+            break;
+        case EatInputAttachment:
+            // input attachment
+            if (it->getInt(value))
+                type.getQualifier().layoutAttachment = value;
+            break;
+        case EatBuiltIn:
+            // PointSize built-in
+            if (it->getString(builtInString, 0, false)) {
+                if (builtInString == "PointSize")
+                    type.getQualifier().builtIn = EbvPointSize;
+            }
+            break;
+        case EatPushConstant:
+            // push_constant
+            type.getQualifier().layoutPushConstant = true;
+            break;
+        case EatConstantId:
+            // specialization constant
+            if (it->getInt(value)) {
+                TSourceLoc loc;
+                loc.init();
+                setSpecConstantId(loc, type.getQualifier(), value);
+            }
+            break;
+        default:
+            if (! allowEntry)
+                warn(loc, "attribute does not apply to a type", "", "");
+            break;
+        }
     }
 }
 
@@ -1936,7 +1964,7 @@ void HlslParseContext::transferTypeAttributes(const TAttributeMap& attributes, T
 // a subtree that creates the entry point.
 //
 TIntermNode* HlslParseContext::transformEntryPoint(const TSourceLoc& loc, TFunction& userFunction,
-                                                   const TAttributeMap& attributes)
+                                                   const TAttributes& attributes)
 {
     // Return true if this is a tessellation patch constant function input to a domain shader.
     const auto isDsPcfInput = [this](const TType& type) {
@@ -8792,29 +8820,75 @@ bool HlslParseContext::handleOutputGeometry(const TSourceLoc& loc, const TLayout
 }
 
 //
-// Selection hints
+// Selection attributes
 //
-TSelectionControl HlslParseContext::handleSelectionControl(const TAttributeMap& attributes) const
+void HlslParseContext::handleSelectionAttributes(const TSourceLoc& loc, TIntermSelection* selection,
+    const TAttributes& attributes)
 {
-    if (attributes.contains(EatFlatten))
-        return ESelectionControlFlatten;
-    else if (attributes.contains(EatBranch))
-        return ESelectionControlDontFlatten;
-    else
-        return ESelectionControlNone;
+    if (selection == nullptr)
+        return;
+
+    for (auto it = attributes.begin(); it != attributes.end(); ++it) {
+        switch (it->name) {
+        case EatFlatten:
+            selection->setFlatten();
+            break;
+        case EatBranch:
+            selection->setDontFlatten();
+            break;
+        default:
+            warn(loc, "attribute does not apply to a selection", "", "");
+            break;
+        }
+    }
 }
 
 //
-// Loop hints
+// Switch attributes
 //
-TLoopControl HlslParseContext::handleLoopControl(const TAttributeMap& attributes) const
+void HlslParseContext::handleSwitchAttributes(const TSourceLoc& loc, TIntermSwitch* selection,
+    const TAttributes& attributes)
 {
-    if (attributes.contains(EatUnroll))
-        return ELoopControlUnroll;
-    else if (attributes.contains(EatLoop))
-        return ELoopControlDontUnroll;
-    else
-        return ELoopControlNone;
+    if (selection == nullptr)
+        return;
+
+    for (auto it = attributes.begin(); it != attributes.end(); ++it) {
+        switch (it->name) {
+        case EatFlatten:
+            selection->setFlatten();
+            break;
+        case EatBranch:
+            selection->setDontFlatten();
+            break;
+        default:
+            warn(loc, "attribute does not apply to a switch", "", "");
+            break;
+        }
+    }
+}
+
+//
+// Loop attributes
+//
+void HlslParseContext::handleLoopAttributes(const TSourceLoc& loc, TIntermLoop* loop,
+    const TAttributes& attributes)
+{
+    if (loop == nullptr)
+        return;
+
+    for (auto it = attributes.begin(); it != attributes.end(); ++it) {
+        switch (it->name) {
+        case EatUnroll:
+            loop->setUnroll();
+            break;
+        case EatLoop:
+            loop->setDontUnroll();
+            break;
+        default:
+            warn(loc, "attribute does not apply to a loop", "", "");
+            break;
+        }
+    }
 }
 
 //
@@ -8959,7 +9033,7 @@ void HlslParseContext::wrapupSwitchSubsequence(TIntermAggregate* statements, TIn
 // into a switch node.
 //
 TIntermNode* HlslParseContext::addSwitch(const TSourceLoc& loc, TIntermTyped* expression,
-                                         TIntermAggregate* lastStatements, TSelectionControl control)
+                                         TIntermAggregate* lastStatements, const TAttributes& attributes)
 {
     wrapupSwitchSubsequence(lastStatements, nullptr);
 
@@ -8986,7 +9060,7 @@ TIntermNode* HlslParseContext::addSwitch(const TSourceLoc& loc, TIntermTyped* ex
 
     TIntermSwitch* switchNode = new TIntermSwitch(expression, body);
     switchNode->setLoc(loc);
-    switchNode->setSelectionControl(control);
+    handleSwitchAttributes(loc, switchNode, attributes);
 
     return switchNode;
 }

+ 11 - 8
3rdparty/glslang/hlsl/hlslParseHelper.h

@@ -38,12 +38,12 @@
 
 #include "../glslang/MachineIndependent/parseVersions.h"
 #include "../glslang/MachineIndependent/ParseHelper.h"
+#include "../glslang/MachineIndependent/attribute.h"
 
 #include <array>
 
 namespace glslang {
 
-class TAttributeMap; // forward declare
 class TFunctionDeclarator;
 
 class HlslParseContext : public TParseContextBase {
@@ -80,10 +80,10 @@ public:
     bool isBuiltInMethod(const TSourceLoc&, TIntermTyped* base, const TString& field);
     void assignToInterface(TVariable& variable);
     void handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype);
-    TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&, const TAttributeMap&, TIntermNode*& entryPointTree);
-    TIntermNode* transformEntryPoint(const TSourceLoc&, TFunction&, const TAttributeMap&);
-    void handleEntryPointAttributes(const TSourceLoc&, const TAttributeMap&);
-    void transferTypeAttributes(const TAttributeMap&, TType&);
+    TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&, const TAttributes&, TIntermNode*& entryPointTree);
+    TIntermNode* transformEntryPoint(const TSourceLoc&, TFunction&, const TAttributes&);
+    void handleEntryPointAttributes(const TSourceLoc&, const TAttributes&);
+    void transferTypeAttributes(const TSourceLoc&, const TAttributes&, TType&, bool allowEntry = false);
     void handleFunctionBody(const TSourceLoc&, TFunction&, TIntermNode* functionBody, TIntermNode*& node);
     void remapEntryPointIO(TFunction& function, TVariable*& returnValue, TVector<TVariable*>& inputs, TVector<TVariable*>& outputs);
     void remapNonEntryPointIO(TFunction& function);
@@ -163,7 +163,7 @@ public:
     void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&);
     void updateStandaloneQualifierDefaults(const TSourceLoc&, const TPublicType&);
     void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode);
-    TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body, TSelectionControl control);
+    TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body, const TAttributes&);
 
     void updateImplicitArraySize(const TSourceLoc&, TIntermNode*, int index);
 
@@ -203,10 +203,11 @@ public:
     bool handleInputGeometry(const TSourceLoc&, const TLayoutGeometry& geometry);
 
     // Determine selection control from attributes
-    TSelectionControl handleSelectionControl(const TAttributeMap& attributes) const;
+    void handleSelectionAttributes(const TSourceLoc& loc, TIntermSelection*, const TAttributes& attributes);
+    void handleSwitchAttributes(const TSourceLoc& loc, TIntermSwitch*, const TAttributes& attributes);
 
     // Determine loop control from attributes
-    TLoopControl handleLoopControl(const TAttributeMap& attributes) const;
+    void handleLoopAttributes(const TSourceLoc& loc, TIntermLoop*, const TAttributes& attributes);
 
     // Share struct buffer deep types
     void shareStructBufferType(TType&);
@@ -217,6 +218,8 @@ public:
     // Obtain the sampler return type of the given sampler in retType.
     void getTextureReturnType(const TSampler& sampler, TType& retType) const;
 
+    TAttributeType attributeFromName(const TString& nameSpace, const TString& name) const;
+
 protected:
     struct TFlattenData {
         TFlattenData() : nextBinding(TQualifier::layoutBindingEnd),

+ 17 - 13
3rdparty/ocornut-imgui/imgui.cpp

@@ -510,11 +510,11 @@
 
  Q: How can I easily use icons in my application?
  A: The most convenient and practical way is to merge an icon font such as FontAwesome inside you main font. Then you can refer to icons within your 
-    strings. Read 'How can I load multiple fonts?' and the file 'extra_fonts/README.txt' for instructions and useful header files.
+    strings. Read 'How can I load multiple fonts?' and the file 'misc/fonts/README.txt' for instructions and useful header files.
 
  Q: How can I load multiple fonts?
  A: Use the font atlas to pack them into a single texture:
-    (Read extra_fonts/README.txt and the code in ImFontAtlas for more details.)
+    (Read misc/fonts/README.txt and the code in ImFontAtlas for more details.)
 
       ImGuiIO& io = ImGui::GetIO();
       ImFont* font0 = io.Fonts->AddFontDefault();
@@ -672,7 +672,6 @@ static void             MarkIniSettingsDirty(ImGuiWindow* window);
 
 static ImRect           GetViewportRect();
 
-static void             CloseInactivePopups(ImGuiWindow* ref_window);
 static void             ClosePopupToLevel(int remaining);
 static ImGuiWindow*     GetFrontMostModalRootWindow();
 
@@ -2552,7 +2551,7 @@ void ImGui::NewFrame()
     // But in order to allow the user to call NewFrame() multiple times without calling Render(), we are doing an explicit clear.
     g.CurrentWindowStack.resize(0);
     g.CurrentPopupStack.resize(0);
-    CloseInactivePopups(g.NavWindow);
+    ClosePopupsOverWindow(g.NavWindow);
 
     // Create implicit window - we will only render it if the user has added something to it.
     // We don't use "Debug" to avoid colliding with user trying to create a "Debug" window with custom flags.
@@ -3003,7 +3002,7 @@ void ImGui::EndFrame()
             }
 
             // With right mouse button we close popups without changing focus
-            // (The left mouse button path calls FocusWindow which will lead NewFrame->CloseInactivePopups to trigger)
+            // (The left mouse button path calls FocusWindow which will lead NewFrame->ClosePopupsOverWindow to trigger)
             if (g.IO.MouseClicked[1])
             {
                 // Find the top-most window between HoveredWindow and the front most Modal Window.
@@ -3020,7 +3019,7 @@ void ImGui::EndFrame()
                     if (window == g.HoveredWindow)
                         hovered_window_above_modal = true;
                 }
-                CloseInactivePopups(hovered_window_above_modal ? g.HoveredWindow : modal);
+                ClosePopupsOverWindow(hovered_window_above_modal ? g.HoveredWindow : modal);
             }
         }
     }
@@ -3775,7 +3774,7 @@ void ImGui::OpenPopupEx(ImGuiID id)
         else
             g.OpenPopupStack[current_stack_size] = popup_ref;
 
-        // When reopening a popup we first refocus its parent, otherwise if its parent is itself a popup it would get closed by CloseInactivePopups().
+        // When reopening a popup we first refocus its parent, otherwise if its parent is itself a popup it would get closed by ClosePopupsOverWindow().
         // This is equivalent to what ClosePopupToLevel() does.
         //if (g.OpenPopupStack[current_stack_size].PopupId == id)
         //    FocusWindow(parent_window);
@@ -3788,7 +3787,7 @@ void ImGui::OpenPopup(const char* str_id)
     OpenPopupEx(g.CurrentWindow->GetID(str_id));
 }
 
-static void CloseInactivePopups(ImGuiWindow* ref_window)
+void ImGui::ClosePopupsOverWindow(ImGuiWindow* ref_window)
 {
     ImGuiContext& g = *GImGui;
     if (g.OpenPopupStack.empty())
@@ -5164,7 +5163,8 @@ void ImGui::Scrollbar(ImGuiLayoutType direction)
 void ImGui::BringWindowToFront(ImGuiWindow* window)
 {
     ImGuiContext& g = *GImGui;
-    if (g.Windows.back() == window)
+    ImGuiWindow* current_front_window = g.Windows.back();
+    if (current_front_window == window || current_front_window->RootWindow == window)
         return;
     for (int i = g.Windows.Size - 2; i >= 0; i--) // We can ignore the front most window
         if (g.Windows[i] == window)
@@ -6462,12 +6462,13 @@ bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos, float radius)
 
     // Render
     const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_CloseButtonActive : hovered ? ImGuiCol_CloseButtonHovered : ImGuiCol_CloseButton);
-    const ImVec2 center = bb.GetCenter();
+    ImVec2 center = bb.GetCenter();
     window->DrawList->AddCircleFilled(center, ImMax(2.0f, radius), col, 12);
 
     const float cross_extent = (radius * 0.7071f) - 1.0f;
     if (hovered)
     {
+        center -= ImVec2(0.5f, 0.5f);
         window->DrawList->AddLine(center + ImVec2(+cross_extent,+cross_extent), center + ImVec2(-cross_extent,-cross_extent), GetColorU32(ImGuiCol_Text));
         window->DrawList->AddLine(center + ImVec2(+cross_extent,-cross_extent), center + ImVec2(-cross_extent,+cross_extent), GetColorU32(ImGuiCol_Text));
     }
@@ -6574,8 +6575,9 @@ void ImGui::LogToTTY(int max_depth)
         return;
     ImGuiWindow* window = g.CurrentWindow;
 
-    g.LogEnabled = true;
+    IM_ASSERT(g.LogFile == NULL);
     g.LogFile = stdout;
+    g.LogEnabled = true;
     g.LogStartDepth = window->DC.TreeDepth;
     if (max_depth >= 0)
         g.LogAutoExpandMaxDepth = max_depth;
@@ -6596,6 +6598,7 @@ void ImGui::LogToFile(int max_depth, const char* filename)
             return;
     }
 
+    IM_ASSERT(g.LogFile == NULL);
     g.LogFile = ImFileOpen(filename, "ab");
     if (!g.LogFile)
     {
@@ -6616,8 +6619,9 @@ void ImGui::LogToClipboard(int max_depth)
         return;
     ImGuiWindow* window = g.CurrentWindow;
 
-    g.LogEnabled = true;
+    IM_ASSERT(g.LogFile == NULL);
     g.LogFile = NULL;
+    g.LogEnabled = true;
     g.LogStartDepth = window->DC.TreeDepth;
     if (max_depth >= 0)
         g.LogAutoExpandMaxDepth = max_depth;
@@ -6630,7 +6634,6 @@ void ImGui::LogFinish()
         return;
 
     LogText(IM_NEWLINE);
-    g.LogEnabled = false;
     if (g.LogFile != NULL)
     {
         if (g.LogFile == stdout)
@@ -6644,6 +6647,7 @@ void ImGui::LogFinish()
         SetClipboardText(g.LogClipboard->begin());
         g.LogClipboard->clear();
     }
+    g.LogEnabled = false;
 }
 
 // Helper to display logging buttons

+ 16 - 14
3rdparty/ocornut-imgui/imgui.h

@@ -841,28 +841,30 @@ enum ImGuiCond_
 #endif
 };
 
+// You may modify the ImGui::GetStyle() main instance during initialization and before NewFrame().
+// During the frame, prefer using ImGui::PushStyleVar(ImGuiStyleVar_XXXX)/PopStyleVar() to alter the main style values, and ImGui::PushStyleColor(ImGuiCol_XXX)/PopStyleColor() for colors.
 struct ImGuiStyle
 {
-    float       Alpha;                      // Global alpha applies to everything in ImGui
-    ImVec2      WindowPadding;              // Padding within a window
-    float       WindowRounding;             // Radius of window corners rounding. Set to 0.0f to have rectangular windows
-    float       WindowBorderSize;           // Thickness of border around windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly)
-    ImVec2      WindowMinSize;              // Minimum window size
+    float       Alpha;                      // Global alpha applies to everything in ImGui.
+    ImVec2      WindowPadding;              // Padding within a window.
+    float       WindowRounding;             // Radius of window corners rounding. Set to 0.0f to have rectangular windows.
+    float       WindowBorderSize;           // Thickness of border around windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly).
+    ImVec2      WindowMinSize;              // Minimum window size. This is a global setting. If you want to constraint individual windows, use SetNextWindowSizeConstraints().
     ImVec2      WindowTitleAlign;           // Alignment for title bar text. Defaults to (0.0f,0.5f) for left-aligned,vertically centered.
     float       ChildRounding;              // Radius of child window corners rounding. Set to 0.0f to have rectangular windows.
-    float       ChildBorderSize;            // Thickness of border around child windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly)
+    float       ChildBorderSize;            // Thickness of border around child windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly).
     float       PopupRounding;              // Radius of popup window corners rounding.
-    float       PopupBorderSize;            // Thickness of border around popup windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly)
-    ImVec2      FramePadding;               // Padding within a framed rectangle (used by most widgets)
+    float       PopupBorderSize;            // Thickness of border around popup windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly).
+    ImVec2      FramePadding;               // Padding within a framed rectangle (used by most widgets).
     float       FrameRounding;              // Radius of frame corners rounding. Set to 0.0f to have rectangular frame (used by most widgets).
-    float       FrameBorderSize;            // Thickness of border around frames. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly)
-    ImVec2      ItemSpacing;                // Horizontal and vertical spacing between widgets/lines
-    ImVec2      ItemInnerSpacing;           // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label)
+    float       FrameBorderSize;            // Thickness of border around frames. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly).
+    ImVec2      ItemSpacing;                // Horizontal and vertical spacing between widgets/lines.
+    ImVec2      ItemInnerSpacing;           // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label).
     ImVec2      TouchExtraPadding;          // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much!
     float       IndentSpacing;              // Horizontal indentation when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2).
-    float       ColumnsMinSpacing;          // Minimum horizontal spacing between two columns
-    float       ScrollbarSize;              // Width of the vertical scrollbar, Height of the horizontal scrollbar
-    float       ScrollbarRounding;          // Radius of grab corners for scrollbar
+    float       ColumnsMinSpacing;          // Minimum horizontal spacing between two columns.
+    float       ScrollbarSize;              // Width of the vertical scrollbar, Height of the horizontal scrollbar.
+    float       ScrollbarRounding;          // Radius of grab corners for scrollbar.
     float       GrabMinSize;                // Minimum width/height of a grab box for slider/scrollbar.
     float       ViewId;
     float       GrabRounding;               // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs.

+ 14 - 5
3rdparty/ocornut-imgui/imgui_demo.cpp

@@ -1051,9 +1051,10 @@ void ImGui::ShowDemoWindow(bool* p_open)
         if (ImGui::TreeNode("Child regions"))
         {
             static bool disable_mouse_wheel = false;
+            static bool disable_menu = false;
             ImGui::Checkbox("Disable Mouse Wheel", &disable_mouse_wheel);
+            ImGui::Checkbox("Disable Menu", &disable_menu);
 
-            ImGui::Text("Without border");
             static int line = 50;
             bool goto_line = ImGui::Button("Goto");
             ImGui::SameLine();
@@ -1080,8 +1081,16 @@ void ImGui::ShowDemoWindow(bool* p_open)
             // Child 2: rounded border
             {
                 ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0f);
-                ImGui::BeginChild("Child2", ImVec2(0,300), true, (disable_mouse_wheel ? ImGuiWindowFlags_NoScrollWithMouse : 0));
-                ImGui::Text("With border");
+                ImGui::BeginChild("Child2", ImVec2(0,300), true, (disable_mouse_wheel ? ImGuiWindowFlags_NoScrollWithMouse : 0) | (disable_menu ? 0 : ImGuiWindowFlags_MenuBar));
+                if (!disable_menu && ImGui::BeginMenuBar())
+                {
+                    if (ImGui::BeginMenu("Menu"))
+                    {
+                        ShowExampleMenuFile();
+                        ImGui::EndMenu();
+                    }
+                    ImGui::EndMenuBar();
+                }
                 ImGui::Columns(2);
                 for (int i = 0; i < 100; i++)
                 {
@@ -2010,7 +2019,7 @@ void ImGui::ShowFontSelector(const char* label)
     ShowHelpMarker(
         "- Load additional fonts with io.Fonts->AddFontFromFileTTF().\n"
         "- The font atlas is built when calling io.Fonts->GetTexDataAsXXXX() or io.Fonts->Build().\n"
-        "- Read FAQ and documentation in extra_fonts/ for more details.\n"
+        "- Read FAQ and documentation in misc/fonts/ for more details.\n"
         "- If you need to add/remove fonts at runtime (e.g. for DPI change), do it before calling NewFrame().");
 }
 
@@ -2137,7 +2146,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
             if (memcmp(&style.Colors[i], &ref->Colors[i], sizeof(ImVec4)) != 0)
             {
                 // Tips: in a real user application, you may want to merge and use an icon font into the main font, so instead of "Save"/"Revert" you'd use icons.
-                // Read the FAQ and extra_fonts/README.txt about using icon fonts. It's really easy and super convenient!
+                // Read the FAQ and misc/fonts/README.txt about using icon fonts. It's really easy and super convenient!
                 ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Save")) ref->Colors[i] = style.Colors[i];
                 ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Revert")) style.Colors[i] = ref->Colors[i];
             }

+ 2 - 2
3rdparty/ocornut-imgui/imgui_draw.cpp

@@ -1486,7 +1486,7 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg)
     return new_font_cfg.DstFont;
 }
 
-// Default font TTF is compressed with stb_compress then base85 encoded (see extra_fonts/binary_to_compressed_c.cpp for encoder)
+// Default font TTF is compressed with stb_compress then base85 encoded (see misc/fonts/binary_to_compressed_c.cpp for encoder)
 static unsigned int stb_decompress_length(unsigned char *input);
 static unsigned int stb_decompress(unsigned char *output, unsigned char *i, unsigned int length);
 static const char*  GetDefaultCompressedFontDataTTFBase85();
@@ -2700,7 +2700,7 @@ void ImGui::RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, Im
 // DEFAULT FONT DATA
 //-----------------------------------------------------------------------------
 // Compressed with stb_compress() then converted to a C array.
-// Use the program in extra_fonts/binary_to_compressed_c.cpp to create the array from a TTF file.
+// Use the program in misc/fonts/binary_to_compressed_c.cpp to create the array from a TTF file.
 // Decompression from stb.h (public domain) by Sean Barrett https://github.com/nothings/stb/blob/master/stb.h
 //-----------------------------------------------------------------------------
 

+ 1 - 0
3rdparty/ocornut-imgui/imgui_internal.h

@@ -894,6 +894,7 @@ namespace ImGui
 
     IMGUI_API void          OpenPopupEx(ImGuiID id);
     IMGUI_API void          ClosePopup(ImGuiID id);
+    IMGUI_API void          ClosePopupsOverWindow(ImGuiWindow* ref_window);
     IMGUI_API bool          IsPopupOpen(ImGuiID id);
     IMGUI_API bool          BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags);
     IMGUI_API void          BeginTooltipEx(ImGuiWindowFlags extra_flags, bool override_previous_tooltip = true);

+ 2 - 1
examples/common/imgui/imgui.cpp

@@ -332,7 +332,8 @@ struct OcornutImguiContext
 			ImGui::StyleColorsLight(&style);
 		}
 
-		style.FrameRounding = 4.0f;
+		style.FrameRounding    = 4.0f;
+		style.WindowBorderSize = 0.0f;
 	}
 
 	void beginFrame(

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません