Implement GL_EXT_vulkan_glsl_relaxed option
authorwill brown <will.brown039@gmail.com>
Wed, 10 Jun 2020 00:43:48 +0000 (20:43 -0400)
committerMalcolm Bechard <malcolm@derivative.ca>
Mon, 8 Mar 2021 18:31:39 +0000 (13:31 -0500)
43 files changed:
SPIRV/GlslangToSpv.cpp
StandAlone/StandAlone.cpp
Test/baseResults/iomap.crossStage.2.vert.out [new file with mode: 0644]
Test/baseResults/iomap.crossStage.vert.out [new file with mode: 0644]
Test/baseResults/iomap.crossStage.vk.vert.out [new file with mode: 0644]
Test/baseResults/vk.relaxed.errorcheck.vert.out [new file with mode: 0644]
Test/baseResults/vk.relaxed.frag.out [new file with mode: 0644]
Test/baseResults/vk.relaxed.link1.frag.out [new file with mode: 0644]
Test/baseResults/vk.relaxed.stagelink.vert.out [new file with mode: 0644]
Test/iomap.crossStage.2.frag [new file with mode: 0644]
Test/iomap.crossStage.2.geom [new file with mode: 0644]
Test/iomap.crossStage.2.vert [new file with mode: 0644]
Test/iomap.crossStage.frag [new file with mode: 0644]
Test/iomap.crossStage.vert [new file with mode: 0644]
Test/iomap.crossStage.vk.frag [new file with mode: 0644]
Test/iomap.crossStage.vk.geom [new file with mode: 0644]
Test/iomap.crossStage.vk.vert [new file with mode: 0644]
Test/vk.relaxed.errorcheck.frag [new file with mode: 0644]
Test/vk.relaxed.errorcheck.vert [new file with mode: 0644]
Test/vk.relaxed.frag [new file with mode: 0644]
Test/vk.relaxed.link1.frag [new file with mode: 0644]
Test/vk.relaxed.link2.frag [new file with mode: 0644]
Test/vk.relaxed.stagelink.frag [new file with mode: 0644]
Test/vk.relaxed.stagelink.vert [new file with mode: 0644]
glslang/Include/Types.h
glslang/Include/intermediate.h
glslang/MachineIndependent/Initialize.cpp
glslang/MachineIndependent/ParseContextBase.cpp
glslang/MachineIndependent/ParseHelper.cpp
glslang/MachineIndependent/ParseHelper.h
glslang/MachineIndependent/ShaderLang.cpp
glslang/MachineIndependent/Versions.cpp
glslang/MachineIndependent/Versions.h
glslang/MachineIndependent/intermOut.cpp
glslang/MachineIndependent/iomapper.cpp
glslang/MachineIndependent/iomapper.h
glslang/MachineIndependent/linkValidate.cpp
glslang/MachineIndependent/localintermediate.h
glslang/Public/ShaderLang.h
gtests/CMakeLists.txt
gtests/GlslMapIO.FromFile.cpp [new file with mode: 0644]
gtests/Link.FromFile.Vk.cpp
gtests/VkRelaxed.FromFile.cpp [new file with mode: 0644]

index 8a1b30d..28a1ffe 100644 (file)
@@ -2784,6 +2784,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
         break;
 
     case glslang::EOpAtomicAdd:
+    case glslang::EOpAtomicSubtract:
     case glslang::EOpAtomicMin:
     case glslang::EOpAtomicMax:
     case glslang::EOpAtomicAnd:
@@ -2955,6 +2956,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
             break;
 
         case glslang::EOpAtomicAdd:
+        case glslang::EOpAtomicSubtract:
         case glslang::EOpAtomicMin:
         case glslang::EOpAtomicMax:
         case glslang::EOpAtomicAnd:
@@ -6892,6 +6894,7 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv
                 builder.addCapability(spv::CapabilityAtomicFloat64AddEXT);
         }
         break;
+    case glslang::EOpAtomicSubtract:
     case glslang::EOpAtomicCounterSubtract:
         opCode = spv::OpAtomicISub;
         break;
index fdbf027..923ded3 100644 (file)
@@ -110,6 +110,7 @@ bool SpvToolsValidate = false;
 bool NaNClamp = false;
 bool stripDebugInfo = false;
 bool beQuiet = false;
+bool VulkanRulesRelaxed = false;
 
 //
 // Return codes from main/exit().
@@ -195,6 +196,17 @@ std::array<std::array<unsigned int, EShLangCount>, glslang::EResCount> baseBindi
 std::array<std::array<TPerSetBaseBinding, EShLangCount>, glslang::EResCount> baseBindingForSet;
 std::array<std::vector<std::string>, EShLangCount> baseResourceSetBinding;
 
+std::vector<std::pair<std::string, glslang::TBlockStorageClass>> blockStorageOverrides;
+
+bool setGlobalUniformBlock = false;
+std::string globalUniformName;
+unsigned int globalUniformBinding;
+unsigned int globalUniformSet;
+
+bool setGlobalBufferBlock = false;
+std::string atomicCounterBlockName;
+unsigned int atomicCounterBlockSet;
+
 // Add things like "#define ..." to a preamble to use in the beginning of the shader.
 class TPreamble {
 public:
@@ -397,6 +409,115 @@ void ProcessResourceSetBindingBase(int& argc, char**& argv, std::array<std::vect
 }
 
 //
+// Process an optional binding base of one the forms:
+//   --argname name {uniform|buffer|push_constant}
+void ProcessBlockStorage(int& argc, char**& argv, std::vector<std::pair<std::string, glslang::TBlockStorageClass>>& storage)
+{
+    if (argc < 3)
+        usage();
+
+    glslang::TBlockStorageClass blockStorage = glslang::EbsNone;
+
+    std::string strBacking(argv[2]);
+    if (strBacking == "uniform")
+        blockStorage = glslang::EbsUniform;
+    else if (strBacking == "buffer")
+        blockStorage = glslang::EbsStorageBuffer;
+    else if (strBacking == "push_constant")
+        blockStorage = glslang::EbsPushConstant;
+    else {
+        printf("%s: invalid block storage\n", strBacking.c_str());
+        usage();
+    }
+
+    storage.push_back(std::make_pair(std::string(argv[1]), blockStorage));
+
+    argc -= 2;
+    argv += 2;
+}
+
+inline bool isNonDigit(char c) {
+    // a non-digit character valid in a glsl identifier
+    return (c == '_') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
+}
+
+// whether string isa  valid identifier to be used in glsl
+bool isValidIdentifier(const char* str) {
+    std::string idn(str);
+
+    if (idn.length() == 0) {
+        return false;
+    }
+
+    if (idn.length() >= 3 && idn.substr(0, 3) == "gl_") {
+        // identifiers startin with "gl_" are reserved
+        return false;
+    }
+
+    if (!isNonDigit(idn[0])) {
+        return false;
+    }
+
+    for (unsigned int i = 1; i < idn.length(); ++i) {
+        if (!(isdigit(idn[i]) || isNonDigit(idn[i]))) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+// Process settings for either the global buffer block or global unfirom block
+// of the form:
+//      --argname name set binding
+void ProcessGlobalBlockSettings(int& argc, char**& argv, std::string* name, unsigned int* set, unsigned int* binding)
+{
+    if (argc < 4)
+        usage();
+
+    unsigned int curArg = 1;
+
+    assert(name || set || binding);
+
+    if (name) {
+        if (!isValidIdentifier(argv[curArg])) {
+            printf("%s: invalid identifier\n", argv[curArg]);
+            usage();
+        }
+        *name = argv[curArg];
+
+        curArg++;
+    }
+
+    if (set) {
+        errno = 0;
+        int setVal = ::strtol(argv[curArg], NULL, 10);
+        if (errno || setVal < 0) {
+            printf("%s: invalid set\n", argv[curArg]);
+            usage();
+        }
+        *set = setVal;
+
+        curArg++;
+    }
+
+    if (binding) {
+        errno = 0;
+        int bindingVal = ::strtol(argv[curArg], NULL, 10);
+        if (errno || bindingVal < 0) {
+            printf("%s: invalid binding\n", argv[curArg]);
+            usage();
+        }
+        *binding = bindingVal;
+
+        curArg++;
+    }
+
+    argc -= (curArg - 1);
+    argv += (curArg - 1);
+}
+
+//
 // Do all command-line argument parsing.  This includes building up the work-items
 // to be processed later, and saving all the command-line options.
 //
@@ -569,6 +690,17 @@ void ProcessArguments(std::vector<std::unique_ptr<glslang::TWorkItem>>& workItem
                                lowerword == "resource-set-binding"  ||
                                lowerword == "rsb") {
                         ProcessResourceSetBindingBase(argc, argv, baseResourceSetBinding);
+                    } else if (lowerword == "set-block-storage" ||
+                               lowerword == "sbs") {
+                        ProcessBlockStorage(argc, argv, blockStorageOverrides);
+                    } else if (lowerword == "set-atomic-counter-block" ||
+                               lowerword == "sacb") {
+                        ProcessGlobalBlockSettings(argc, argv, &atomicCounterBlockName, &atomicCounterBlockSet, nullptr);
+                        setGlobalBufferBlock = true;
+                    } else if (lowerword == "set-default-uniform-block" ||
+                               lowerword == "sdub") {
+                        ProcessGlobalBlockSettings(argc, argv, &globalUniformName, &globalUniformSet, &globalUniformBinding);
+                        setGlobalUniformBlock = true;
                     } else if (lowerword == "shift-image-bindings" ||  // synonyms
                                lowerword == "shift-image-binding"  ||
                                lowerword == "sib") {
@@ -721,6 +853,9 @@ void ProcessArguments(std::vector<std::unique_ptr<glslang::TWorkItem>>& workItem
                 else
                     Error("unknown -O option");
                 break;
+            case 'R':
+                VulkanRulesRelaxed = true;
+                break;
             case 'S':
                 if (argc <= 1)
                     Error("no <stage> specified for -S");
@@ -1068,6 +1203,24 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
         shader->setUniformLocationBase(uniformBase);
 #endif
 
+        if (VulkanRulesRelaxed) {
+            for (auto& storageOverride : blockStorageOverrides) {
+                shader->addBlockStorageOverride(storageOverride.first.c_str(),
+                    storageOverride.second);
+            }
+
+            if (setGlobalBufferBlock) {
+                shader->setAtomicCounterBlockName(atomicCounterBlockName.c_str());
+                shader->setAtomicCounterBlockSet(atomicCounterBlockSet);
+            }
+
+            if (setGlobalUniformBlock) {
+                shader->setGlobalUniformBlockName(globalUniformName.c_str());
+                shader->setGlobalUniformSet(globalUniformSet);
+                shader->setGlobalUniformBinding(globalUniformBinding);
+            }
+        }
+
         shader->setNanMinMaxClamp(NaNClamp);
 
 #ifdef ENABLE_HLSL
@@ -1091,6 +1244,8 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
             if (targetHlslFunctionality1)
                 shader->setEnvTargetHlslFunctionality1();
 #endif
+            if (VulkanRulesRelaxed)
+                shader->setEnvInputVulkanRulesRelaxed();
         }
 
         shaders.push_back(shader);
@@ -1572,6 +1727,9 @@ void usage()
            "              is searched first, followed by left-to-right order of -I\n"
            "  -Od         disables optimization; may cause illegal SPIR-V for HLSL\n"
            "  -Os         optimizes SPIR-V to minimize size\n"
+           "  -R          use relaxed verification rules for generating Vulkan SPIR-V,\n"
+           "              allowing the use of default uniforms, atomic_uints, and\n"
+           "              gl_VertexID and gl_InstanceID keywords.\n"
            "  -S <stage>  uses specified stage rather than parsing the file extension\n"
            "              choices for <stage> are vert, tesc, tese, geom, frag, or comp\n"
            "  -U<name> | --undef-macro <name> | --U <name>\n"
@@ -1649,6 +1807,22 @@ void usage()
            "  --resource-set-binding [stage] set\n"
            "                                    set descriptor set for all resources\n"
            "  --rsb                             synonym for --resource-set-binding\n"
+           "  --set-block-backing name {uniform|buffer|push_constant}\n"
+           "                                    changes the backing type of a uniform, buffer,\n"
+           "                                    or push_constant block declared in\n"
+           "                                    in the program, when using -R option.\n"
+           "                                    This can be used to change the backing\n"
+           "                                    for existing blocks as well as implicit ones\n"
+           "                                    such as 'gl_DefaultUniformBlock'.\n"
+           "  --sbs                             synonym for set-block-storage\n"
+           "  --set-atomic-counter-block name set\n"
+           "                                    set name, and descriptor set for\n"
+           "                                    atomic counter blocks, with -R opt\n"
+           "  --sacb                            synonym for set-atomic-counter-block\n"
+           "  --set-default-uniform-block name set binding\n"
+           "                                    set name, descriptor set, and binding for\n"
+           "                                    global default-uniform-block, with -R opt\n"
+           "  --sdub                            synonym for set-default-uniform-block\n"
            "  --shift-image-binding [stage] num\n"
            "                                    base binding number for images (uav)\n"
            "  --shift-image-binding [stage] [num set]...\n"
diff --git a/Test/baseResults/iomap.crossStage.2.vert.out b/Test/baseResults/iomap.crossStage.2.vert.out
new file mode 100644 (file)
index 0000000..325c1b4
--- /dev/null
@@ -0,0 +1,787 @@
+iomap.crossStage.2.vert
+Shader version: 460
+0:? Sequence
+0:32  Function Definition: main( ( global void)
+0:32    Function Parameters: 
+0:34    Sequence
+0:34      move second child to first child ( temp 4-component vector of float)
+0:34        'vgo1' ( smooth out 4-component vector of float)
+0:34        Constant:
+0:34          0.000000
+0:34          0.000000
+0:34          0.000000
+0:34          0.000000
+0:35      move second child to first child ( temp 2-component vector of float)
+0:35        'vgo2' ( smooth out 2-component vector of float)
+0:35        Constant:
+0:35          0.000000
+0:35          0.000000
+0:36      move second child to first child ( temp 4-component vector of float)
+0:36        o3: direct index for structure ( out 4-component vector of float)
+0:36          'anon@0' (layout( location=5) out block{ out 4-component vector of float o3})
+0:36          Constant:
+0:36            0 (const uint)
+0:36        Constant:
+0:36          0.000000
+0:36          0.000000
+0:36          0.000000
+0:36          0.000000
+0:?   Linker Objects
+0:?     'vgo1' ( smooth out 4-component vector of float)
+0:?     'vgo2' ( smooth out 2-component vector of float)
+0:?     'anon@0' (layout( location=5) out block{ out 4-component vector of float o3})
+0:?     'u1' ( uniform 2-component vector of float)
+0:?     'u2' ( uniform 3-component vector of float)
+0:?       0.000000
+0:?       0.000000
+0:?       0.000000
+0:?     'u3' ( uniform 4-component vector of float)
+0:?       0.000000
+0:?       0.000000
+0:?       0.000000
+0:?       0.000000
+0:?     'um2' ( uniform 2X2 matrix of float)
+0:?       4.000000
+0:?       0.000000
+0:?       0.000000
+0:?       4.000000
+0:?     'glass' (layout( location=0 binding=0) uniform sampler2D)
+0:?     'anon@1' (layout( column_major std140) uniform block{layout( column_major std140) uniform 4-component vector of float a, layout( column_major std140) uniform 4-component vector of float b})
+0:?     'anon@2' (layout( column_major std430) buffer block{layout( column_major std430) buffer 2-component vector of float vb1})
+0:?     'blockName1' (layout( column_major std140) uniform 2-element array of block{layout( column_major std140) uniform 4-component vector of float a, layout( column_major std140) uniform 2-component vector of float b})
+0:?     'gl_VertexID' ( gl_VertexId int VertexId)
+0:?     'gl_InstanceID' ( gl_InstanceId int InstanceId)
+
+iomap.crossStage.2.geom
+Shader version: 460
+invocations = -1
+max_vertices = 3
+input primitive = points
+output primitive = triangle_strip
+0:? Sequence
+0:29  Function Definition: main( ( global void)
+0:29    Function Parameters: 
+0:31    Sequence
+0:31      Sequence
+0:31        Sequence
+0:31          move second child to first child ( temp int)
+0:31            'i' ( temp int)
+0:31            Constant:
+0:31              0 (const int)
+0:31        Loop with condition tested first
+0:31          Loop Condition
+0:31          Compare Less Than ( temp bool)
+0:31            'i' ( temp int)
+0:31            Constant:
+0:31              3 (const int)
+0:31          Loop Body
+0:32          Sequence
+0:32            move second child to first child ( temp 4-component vector of float)
+0:32              'gfo1' (layout( stream=0) out 4-component vector of float)
+0:32              Constant:
+0:32                0.000000
+0:32                0.000000
+0:32                0.000000
+0:32                0.000000
+0:33            move second child to first child ( temp 2-component vector of float)
+0:33              'gfo2' (layout( stream=0) out 2-component vector of float)
+0:33              Constant:
+0:33                0.000000
+0:33                0.000000
+0:34            move second child to first child ( temp 4-component vector of float)
+0:34              o3: direct index for structure (layout( stream=0) out 4-component vector of float)
+0:34                'gf_out' (layout( location=5 stream=0) out block{layout( stream=0) out 4-component vector of float o3})
+0:34                Constant:
+0:34                  0 (const int)
+0:34              o3: direct index for structure ( in 4-component vector of float)
+0:34                indirect index (layout( location=5) temp block{ in 4-component vector of float o3})
+0:34                  'inBlock' (layout( location=5) in 1-element array of block{ in 4-component vector of float o3})
+0:34                  'i' ( temp int)
+0:34                Constant:
+0:34                  0 (const int)
+0:35            EmitVertex ( global void)
+0:31          Loop Terminal Expression
+0:31          Post-Increment ( temp int)
+0:31            'i' ( temp int)
+0:37      EndPrimitive ( global void)
+0:?   Linker Objects
+0:?     'vgo1' ( in 1-element array of 4-component vector of float)
+0:?     'vgo2' ( in 1-element array of 2-component vector of float)
+0:?     'inBlock' (layout( location=5) in 1-element array of block{ in 4-component vector of float o3})
+0:?     'gfo1' (layout( stream=0) out 4-component vector of float)
+0:?     'gfo2' (layout( stream=0) out 2-component vector of float)
+0:?     'gf_out' (layout( location=5 stream=0) out block{layout( stream=0) out 4-component vector of float o3})
+0:?     'u1' ( uniform 2-component vector of float)
+0:?     'u2' ( uniform 3-component vector of float)
+0:?       0.000000
+0:?       0.000000
+0:?       0.000000
+0:?     'u3' ( uniform 4-component vector of float)
+0:?       0.000000
+0:?       0.000000
+0:?       0.000000
+0:?       0.000000
+0:?     'blockName1' (layout( column_major std140) uniform 2-element array of block{layout( column_major std140) uniform 4-component vector of float a, layout( column_major std140) uniform 2-component vector of float b})
+
+iomap.crossStage.2.frag
+Shader version: 460
+0:? Sequence
+0:37  Function Definition: main( ( global void)
+0:37    Function Parameters: 
+0:39    Sequence
+0:39      Sequence
+0:39        move second child to first child ( temp 4-component vector of float)
+0:39          'color' ( temp 4-component vector of float)
+0:39          component-wise multiply ( temp 4-component vector of float)
+0:39            component-wise multiply ( temp 4-component vector of float)
+0:39              component-wise multiply ( temp 4-component vector of float)
+0:39                'gfo1' ( smooth in 4-component vector of float)
+0:39                vector swizzle ( temp 4-component vector of float)
+0:39                  'u1' ( uniform 2-component vector of float)
+0:39                  Sequence
+0:39                    Constant:
+0:39                      0 (const int)
+0:39                    Constant:
+0:39                      1 (const int)
+0:39                    Constant:
+0:39                      0 (const int)
+0:39                    Constant:
+0:39                      1 (const int)
+0:39              vector swizzle ( temp 4-component vector of float)
+0:39                'u2' ( uniform 3-component vector of float)
+0:39                Sequence
+0:39                  Constant:
+0:39                    0 (const int)
+0:39                  Constant:
+0:39                    1 (const int)
+0:39                  Constant:
+0:39                    2 (const int)
+0:39                  Constant:
+0:39                    0 (const int)
+0:39            vector swizzle ( temp 4-component vector of float)
+0:39              'u3' ( uniform 4-component vector of float)
+0:39                0.000000
+0:39                0.000000
+0:39                0.000000
+0:39                0.000000
+0:39              Sequence
+0:39                Constant:
+0:39                  0 (const int)
+0:39                Constant:
+0:39                  1 (const int)
+0:39                Constant:
+0:39                  2 (const int)
+0:39                Constant:
+0:39                  3 (const int)
+0:40      move second child to first child ( temp 4-component vector of float)
+0:40        'outColor' ( out 4-component vector of float)
+0:40        'color' ( temp 4-component vector of float)
+0:?   Linker Objects
+0:?     'anon@0' (layout( location=5) in block{ in 4-component vector of float o3})
+0:?     'gfo1' ( smooth in 4-component vector of float)
+0:?     'gfo2' ( smooth in 2-component vector of float)
+0:?     'outColor' ( out 4-component vector of float)
+0:?     'u1' ( uniform 2-component vector of float)
+0:?     'u2' ( uniform 3-component vector of float)
+0:?     'u3' ( uniform 4-component vector of float)
+0:?       0.000000
+0:?       0.000000
+0:?       0.000000
+0:?       0.000000
+0:?     'um2' ( uniform 2X2 matrix of float)
+0:?       4.000000
+0:?       0.000000
+0:?       0.000000
+0:?       4.000000
+0:?     'glass' (layout( location=0 binding=0) uniform sampler2D)
+0:?     'anon@1' (layout( column_major std140) uniform block{layout( column_major std140) uniform 4-component vector of float a, layout( column_major std140) uniform 4-component vector of float b})
+0:?     'anon@2' (layout( column_major std430) buffer block{layout( column_major std430) buffer 2-component vector of float fb1})
+0:?     'blockName2' (layout( column_major std140) uniform 2-element array of block{layout( column_major std140) uniform 4-component vector of float a, layout( column_major std140) uniform 2-component vector of float b})
+
+
+Linked vertex stage:
+
+
+Linked geometry stage:
+
+
+Linked fragment stage:
+
+WARNING: Linking unknown stage stage: Matched shader interfaces are using different instance names.
+    blockName1: "layout( column_major std140) uniform 2-element array of block{layout( column_major std140) uniform 4-component vector of float a, layout( column_major std140) uniform 2-component vector of float b}" versus blockName2: "layout( column_major std140) uniform 2-element array of block{layout( column_major std140) uniform 4-component vector of float a, layout( column_major std140) uniform 2-component vector of float b}"
+
+Shader version: 460
+0:? Sequence
+0:32  Function Definition: main( ( global void)
+0:32    Function Parameters: 
+0:34    Sequence
+0:34      move second child to first child ( temp 4-component vector of float)
+0:34        'vgo1' ( smooth out 4-component vector of float)
+0:34        Constant:
+0:34          0.000000
+0:34          0.000000
+0:34          0.000000
+0:34          0.000000
+0:35      move second child to first child ( temp 2-component vector of float)
+0:35        'vgo2' ( smooth out 2-component vector of float)
+0:35        Constant:
+0:35          0.000000
+0:35          0.000000
+0:36      move second child to first child ( temp 4-component vector of float)
+0:36        o3: direct index for structure ( out 4-component vector of float)
+0:36          'anon@0' (layout( location=5) out block{ out 4-component vector of float o3})
+0:36          Constant:
+0:36            0 (const uint)
+0:36        Constant:
+0:36          0.000000
+0:36          0.000000
+0:36          0.000000
+0:36          0.000000
+0:?   Linker Objects
+0:?     'vgo1' ( smooth out 4-component vector of float)
+0:?     'vgo2' ( smooth out 2-component vector of float)
+0:?     'anon@0' (layout( location=5) out block{ out 4-component vector of float o3})
+0:?     'u1' ( uniform 2-component vector of float)
+0:?     'u2' ( uniform 3-component vector of float)
+0:?       0.000000
+0:?       0.000000
+0:?       0.000000
+0:?     'u3' ( uniform 4-component vector of float)
+0:?       0.000000
+0:?       0.000000
+0:?       0.000000
+0:?       0.000000
+0:?     'um2' ( uniform 2X2 matrix of float)
+0:?       4.000000
+0:?       0.000000
+0:?       0.000000
+0:?       4.000000
+0:?     'glass' (layout( location=0 binding=0) uniform sampler2D)
+0:?     'anon@1' (layout( column_major std140) uniform block{layout( column_major std140) uniform 4-component vector of float a, layout( column_major std140) uniform 4-component vector of float b})
+0:?     'anon@2' (layout( column_major std430) buffer block{layout( column_major std430) buffer 2-component vector of float vb1})
+0:?     'blockName1' (layout( column_major std140) uniform 2-element array of block{layout( column_major std140) uniform 4-component vector of float a, layout( column_major std140) uniform 2-component vector of float b})
+0:?     'gl_VertexID' ( gl_VertexId int VertexId)
+0:?     'gl_InstanceID' ( gl_InstanceId int InstanceId)
+Shader version: 460
+invocations = 1
+max_vertices = 3
+input primitive = points
+output primitive = triangle_strip
+0:? Sequence
+0:29  Function Definition: main( ( global void)
+0:29    Function Parameters: 
+0:31    Sequence
+0:31      Sequence
+0:31        Sequence
+0:31          move second child to first child ( temp int)
+0:31            'i' ( temp int)
+0:31            Constant:
+0:31              0 (const int)
+0:31        Loop with condition tested first
+0:31          Loop Condition
+0:31          Compare Less Than ( temp bool)
+0:31            'i' ( temp int)
+0:31            Constant:
+0:31              3 (const int)
+0:31          Loop Body
+0:32          Sequence
+0:32            move second child to first child ( temp 4-component vector of float)
+0:32              'gfo1' (layout( stream=0) out 4-component vector of float)
+0:32              Constant:
+0:32                0.000000
+0:32                0.000000
+0:32                0.000000
+0:32                0.000000
+0:33            move second child to first child ( temp 2-component vector of float)
+0:33              'gfo2' (layout( stream=0) out 2-component vector of float)
+0:33              Constant:
+0:33                0.000000
+0:33                0.000000
+0:34            move second child to first child ( temp 4-component vector of float)
+0:34              o3: direct index for structure (layout( stream=0) out 4-component vector of float)
+0:34                'gf_out' (layout( location=5 stream=0) out block{layout( stream=0) out 4-component vector of float o3})
+0:34                Constant:
+0:34                  0 (const int)
+0:34              o3: direct index for structure ( in 4-component vector of float)
+0:34                indirect index (layout( location=5) temp block{ in 4-component vector of float o3})
+0:34                  'inBlock' (layout( location=5) in 1-element array of block{ in 4-component vector of float o3})
+0:34                  'i' ( temp int)
+0:34                Constant:
+0:34                  0 (const int)
+0:35            EmitVertex ( global void)
+0:31          Loop Terminal Expression
+0:31          Post-Increment ( temp int)
+0:31            'i' ( temp int)
+0:37      EndPrimitive ( global void)
+0:?   Linker Objects
+0:?     'vgo1' ( in 1-element array of 4-component vector of float)
+0:?     'vgo2' ( in 1-element array of 2-component vector of float)
+0:?     'inBlock' (layout( location=5) in 1-element array of block{ in 4-component vector of float o3})
+0:?     'gfo1' (layout( stream=0) out 4-component vector of float)
+0:?     'gfo2' (layout( stream=0) out 2-component vector of float)
+0:?     'gf_out' (layout( location=5 stream=0) out block{layout( stream=0) out 4-component vector of float o3})
+0:?     'u1' ( uniform 2-component vector of float)
+0:?     'u2' ( uniform 3-component vector of float)
+0:?       0.000000
+0:?       0.000000
+0:?       0.000000
+0:?     'u3' ( uniform 4-component vector of float)
+0:?       0.000000
+0:?       0.000000
+0:?       0.000000
+0:?       0.000000
+0:?     'blockName1' (layout( column_major std140) uniform 2-element array of block{layout( column_major std140) uniform 4-component vector of float a, layout( column_major std140) uniform 2-component vector of float b})
+Shader version: 460
+0:? Sequence
+0:37  Function Definition: main( ( global void)
+0:37    Function Parameters: 
+0:39    Sequence
+0:39      Sequence
+0:39        move second child to first child ( temp 4-component vector of float)
+0:39          'color' ( temp 4-component vector of float)
+0:39          component-wise multiply ( temp 4-component vector of float)
+0:39            component-wise multiply ( temp 4-component vector of float)
+0:39              component-wise multiply ( temp 4-component vector of float)
+0:39                'gfo1' ( smooth in 4-component vector of float)
+0:39                vector swizzle ( temp 4-component vector of float)
+0:39                  'u1' ( uniform 2-component vector of float)
+0:39                  Sequence
+0:39                    Constant:
+0:39                      0 (const int)
+0:39                    Constant:
+0:39                      1 (const int)
+0:39                    Constant:
+0:39                      0 (const int)
+0:39                    Constant:
+0:39                      1 (const int)
+0:39              vector swizzle ( temp 4-component vector of float)
+0:39                'u2' ( uniform 3-component vector of float)
+0:39                Sequence
+0:39                  Constant:
+0:39                    0 (const int)
+0:39                  Constant:
+0:39                    1 (const int)
+0:39                  Constant:
+0:39                    2 (const int)
+0:39                  Constant:
+0:39                    0 (const int)
+0:39            vector swizzle ( temp 4-component vector of float)
+0:39              'u3' ( uniform 4-component vector of float)
+0:39                0.000000
+0:39                0.000000
+0:39                0.000000
+0:39                0.000000
+0:39              Sequence
+0:39                Constant:
+0:39                  0 (const int)
+0:39                Constant:
+0:39                  1 (const int)
+0:39                Constant:
+0:39                  2 (const int)
+0:39                Constant:
+0:39                  3 (const int)
+0:40      move second child to first child ( temp 4-component vector of float)
+0:40        'outColor' ( out 4-component vector of float)
+0:40        'color' ( temp 4-component vector of float)
+0:?   Linker Objects
+0:?     'anon@0' (layout( location=5) in block{ in 4-component vector of float o3})
+0:?     'gfo1' ( smooth in 4-component vector of float)
+0:?     'gfo2' ( smooth in 2-component vector of float)
+0:?     'outColor' ( out 4-component vector of float)
+0:?     'u1' ( uniform 2-component vector of float)
+0:?     'u2' ( uniform 3-component vector of float)
+0:?     'u3' ( uniform 4-component vector of float)
+0:?       0.000000
+0:?       0.000000
+0:?       0.000000
+0:?       0.000000
+0:?     'um2' ( uniform 2X2 matrix of float)
+0:?       4.000000
+0:?       0.000000
+0:?       0.000000
+0:?       4.000000
+0:?     'glass' (layout( location=0 binding=0) uniform sampler2D)
+0:?     'anon@1' (layout( column_major std140) uniform block{layout( column_major std140) uniform 4-component vector of float a, layout( column_major std140) uniform 4-component vector of float b})
+0:?     'anon@2' (layout( column_major std430) buffer block{layout( column_major std430) buffer 2-component vector of float fb1})
+0:?     'blockName2' (layout( column_major std140) uniform 2-element array of block{layout( column_major std140) uniform 4-component vector of float a, layout( column_major std140) uniform 2-component vector of float b})
+
+// Module Version 10000
+// Generated by (magic number): 8000a
+// Id's are bound by 56
+
+                              Capability Shader
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Vertex 4  "main" 9 14 18 54 55
+                              Source GLSL 460
+                              Name 4  "main"
+                              Name 9  "vgo1"
+                              Name 14  "vgo2"
+                              Name 16  "outBlock"
+                              MemberName 16(outBlock) 0  "o3"
+                              Name 18  ""
+                              Name 23  "u1"
+                              Name 27  "u2"
+                              Name 29  "u3"
+                              Name 36  "um2"
+                              Name 40  "glass"
+                              Name 41  "crossStageBlock1"
+                              MemberName 41(crossStageBlock1) 0  "a"
+                              MemberName 41(crossStageBlock1) 1  "b"
+                              Name 43  ""
+                              Name 44  "vertOnlyBlock"
+                              MemberName 44(vertOnlyBlock) 0  "vb1"
+                              Name 46  ""
+                              Name 47  "crossStageBlock2"
+                              MemberName 47(crossStageBlock2) 0  "a"
+                              MemberName 47(crossStageBlock2) 1  "b"
+                              Name 52  "blockName1"
+                              Name 54  "gl_VertexID"
+                              Name 55  "gl_InstanceID"
+                              Decorate 9(vgo1) Location 0
+                              Decorate 14(vgo2) Location 1
+                              Decorate 16(outBlock) Block
+                              Decorate 18 Location 5
+                              Decorate 23(u1) Location 1
+                              Decorate 23(u1) DescriptorSet 0
+                              Decorate 27(u2) Location 2
+                              Decorate 27(u2) DescriptorSet 0
+                              Decorate 29(u3) Location 3
+                              Decorate 29(u3) DescriptorSet 0
+                              Decorate 36(um2) Location 4
+                              Decorate 36(um2) DescriptorSet 0
+                              Decorate 40(glass) Location 0
+                              Decorate 40(glass) DescriptorSet 0
+                              Decorate 40(glass) Binding 0
+                              MemberDecorate 41(crossStageBlock1) 0 Offset 0
+                              MemberDecorate 41(crossStageBlock1) 1 Offset 16
+                              Decorate 41(crossStageBlock1) Block
+                              Decorate 43 DescriptorSet 0
+                              Decorate 43 Binding 0
+                              MemberDecorate 44(vertOnlyBlock) 0 Offset 0
+                              Decorate 44(vertOnlyBlock) BufferBlock
+                              Decorate 46 DescriptorSet 0
+                              Decorate 46 Binding 0
+                              MemberDecorate 47(crossStageBlock2) 0 Offset 0
+                              MemberDecorate 47(crossStageBlock2) 1 Offset 16
+                              Decorate 47(crossStageBlock2) Block
+                              Decorate 52(blockName1) DescriptorSet 0
+                              Decorate 52(blockName1) Binding 0
+                              Decorate 54(gl_VertexID) BuiltIn VertexId
+                              Decorate 55(gl_InstanceID) BuiltIn InstanceId
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypeVector 6(float) 4
+               8:             TypePointer Output 7(fvec4)
+         9(vgo1):      8(ptr) Variable Output
+              10:    6(float) Constant 0
+              11:    7(fvec4) ConstantComposite 10 10 10 10
+              12:             TypeVector 6(float) 2
+              13:             TypePointer Output 12(fvec2)
+        14(vgo2):     13(ptr) Variable Output
+              15:   12(fvec2) ConstantComposite 10 10
+    16(outBlock):             TypeStruct 7(fvec4)
+              17:             TypePointer Output 16(outBlock)
+              18:     17(ptr) Variable Output
+              19:             TypeInt 32 1
+              20:     19(int) Constant 0
+              22:             TypePointer UniformConstant 12(fvec2)
+          23(u1):     22(ptr) Variable UniformConstant
+              24:             TypeVector 6(float) 3
+              25:   24(fvec3) ConstantComposite 10 10 10
+              26:             TypePointer UniformConstant 24(fvec3)
+          27(u2):     26(ptr) Variable UniformConstant 25
+              28:             TypePointer UniformConstant 7(fvec4)
+          29(u3):     28(ptr) Variable UniformConstant 11
+              30:             TypeMatrix 12(fvec2) 2
+              31:    6(float) Constant 1082130432
+              32:   12(fvec2) ConstantComposite 31 10
+              33:   12(fvec2) ConstantComposite 10 31
+              34:          30 ConstantComposite 32 33
+              35:             TypePointer UniformConstant 30
+         36(um2):     35(ptr) Variable UniformConstant 34
+              37:             TypeImage 6(float) 2D sampled format:Unknown
+              38:             TypeSampledImage 37
+              39:             TypePointer UniformConstant 38
+       40(glass):     39(ptr) Variable UniformConstant
+41(crossStageBlock1):             TypeStruct 7(fvec4) 7(fvec4)
+              42:             TypePointer Uniform 41(crossStageBlock1)
+              43:     42(ptr) Variable Uniform
+44(vertOnlyBlock):             TypeStruct 12(fvec2)
+              45:             TypePointer Uniform 44(vertOnlyBlock)
+              46:     45(ptr) Variable Uniform
+47(crossStageBlock2):             TypeStruct 7(fvec4) 12(fvec2)
+              48:             TypeInt 32 0
+              49:     48(int) Constant 2
+              50:             TypeArray 47(crossStageBlock2) 49
+              51:             TypePointer Uniform 50
+  52(blockName1):     51(ptr) Variable Uniform
+              53:             TypePointer Input 19(int)
+ 54(gl_VertexID):     53(ptr) Variable Input
+55(gl_InstanceID):     53(ptr) Variable Input
+         4(main):           2 Function None 3
+               5:             Label
+                              Store 9(vgo1) 11
+                              Store 14(vgo2) 15
+              21:      8(ptr) AccessChain 18 20
+                              Store 21 11
+                              Return
+                              FunctionEnd
+// Module Version 10000
+// Generated by (magic number): 8000a
+// Id's are bound by 65
+
+                              Capability Geometry
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Geometry 4  "main" 22 27 31 37 48 51
+                              ExecutionMode 4 InputPoints
+                              ExecutionMode 4 Invocations 1
+                              ExecutionMode 4 OutputTriangleStrip
+                              ExecutionMode 4 OutputVertices 3
+                              Source GLSL 460
+                              Name 4  "main"
+                              Name 8  "i"
+                              Name 22  "gfo1"
+                              Name 27  "gfo2"
+                              Name 29  "outBlock"
+                              MemberName 29(outBlock) 0  "o3"
+                              Name 31  "gf_out"
+                              Name 32  "outBlock"
+                              MemberName 32(outBlock) 0  "o3"
+                              Name 37  "inBlock"
+                              Name 48  "vgo1"
+                              Name 51  "vgo2"
+                              Name 53  "u1"
+                              Name 57  "u2"
+                              Name 59  "u3"
+                              Name 60  "crossStageBlock2"
+                              MemberName 60(crossStageBlock2) 0  "a"
+                              MemberName 60(crossStageBlock2) 1  "b"
+                              Name 64  "blockName1"
+                              Decorate 22(gfo1) Location 0
+                              Decorate 27(gfo2) Location 1
+                              Decorate 29(outBlock) Block
+                              Decorate 31(gf_out) Location 5
+                              Decorate 32(outBlock) Block
+                              Decorate 37(inBlock) Location 5
+                              Decorate 48(vgo1) Location 0
+                              Decorate 51(vgo2) Location 1
+                              Decorate 53(u1) Location 1
+                              Decorate 53(u1) DescriptorSet 0
+                              Decorate 57(u2) Location 2
+                              Decorate 57(u2) DescriptorSet 0
+                              Decorate 59(u3) Location 3
+                              Decorate 59(u3) DescriptorSet 0
+                              MemberDecorate 60(crossStageBlock2) 0 Offset 0
+                              MemberDecorate 60(crossStageBlock2) 1 Offset 16
+                              Decorate 60(crossStageBlock2) Block
+                              Decorate 64(blockName1) DescriptorSet 0
+                              Decorate 64(blockName1) Binding 0
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeInt 32 1
+               7:             TypePointer Function 6(int)
+               9:      6(int) Constant 0
+              16:      6(int) Constant 3
+              17:             TypeBool
+              19:             TypeFloat 32
+              20:             TypeVector 19(float) 4
+              21:             TypePointer Output 20(fvec4)
+        22(gfo1):     21(ptr) Variable Output
+              23:   19(float) Constant 0
+              24:   20(fvec4) ConstantComposite 23 23 23 23
+              25:             TypeVector 19(float) 2
+              26:             TypePointer Output 25(fvec2)
+        27(gfo2):     26(ptr) Variable Output
+              28:   25(fvec2) ConstantComposite 23 23
+    29(outBlock):             TypeStruct 20(fvec4)
+              30:             TypePointer Output 29(outBlock)
+      31(gf_out):     30(ptr) Variable Output
+    32(outBlock):             TypeStruct 20(fvec4)
+              33:             TypeInt 32 0
+              34:     33(int) Constant 1
+              35:             TypeArray 32(outBlock) 34
+              36:             TypePointer Input 35
+     37(inBlock):     36(ptr) Variable Input
+              39:             TypePointer Input 20(fvec4)
+              44:      6(int) Constant 1
+              46:             TypeArray 20(fvec4) 34
+              47:             TypePointer Input 46
+        48(vgo1):     47(ptr) Variable Input
+              49:             TypeArray 25(fvec2) 34
+              50:             TypePointer Input 49
+        51(vgo2):     50(ptr) Variable Input
+              52:             TypePointer UniformConstant 25(fvec2)
+          53(u1):     52(ptr) Variable UniformConstant
+              54:             TypeVector 19(float) 3
+              55:   54(fvec3) ConstantComposite 23 23 23
+              56:             TypePointer UniformConstant 54(fvec3)
+          57(u2):     56(ptr) Variable UniformConstant 55
+              58:             TypePointer UniformConstant 20(fvec4)
+          59(u3):     58(ptr) Variable UniformConstant 24
+60(crossStageBlock2):             TypeStruct 20(fvec4) 25(fvec2)
+              61:     33(int) Constant 2
+              62:             TypeArray 60(crossStageBlock2) 61
+              63:             TypePointer Uniform 62
+  64(blockName1):     63(ptr) Variable Uniform
+         4(main):           2 Function None 3
+               5:             Label
+            8(i):      7(ptr) Variable Function
+                              Store 8(i) 9
+                              Branch 10
+              10:             Label
+                              LoopMerge 12 13 None
+                              Branch 14
+              14:             Label
+              15:      6(int) Load 8(i)
+              18:    17(bool) SLessThan 15 16
+                              BranchConditional 18 11 12
+              11:               Label
+                                Store 22(gfo1) 24
+                                Store 27(gfo2) 28
+              38:      6(int)   Load 8(i)
+              40:     39(ptr)   AccessChain 37(inBlock) 38 9
+              41:   20(fvec4)   Load 40
+              42:     21(ptr)   AccessChain 31(gf_out) 9
+                                Store 42 41
+                                EmitVertex
+                                Branch 13
+              13:               Label
+              43:      6(int)   Load 8(i)
+              45:      6(int)   IAdd 43 44
+                                Store 8(i) 45
+                                Branch 10
+              12:             Label
+                              EndPrimitive
+                              Return
+                              FunctionEnd
+// Module Version 10000
+// Generated by (magic number): 8000a
+// Id's are bound by 62
+
+                              Capability Shader
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Fragment 4  "main" 11 32 36 38
+                              ExecutionMode 4 OriginLowerLeft
+                              Source GLSL 460
+                              Name 4  "main"
+                              Name 9  "color"
+                              Name 11  "gfo1"
+                              Name 15  "u1"
+                              Name 21  "u2"
+                              Name 28  "u3"
+                              Name 32  "outColor"
+                              Name 34  "outBlock"
+                              MemberName 34(outBlock) 0  "o3"
+                              Name 36  ""
+                              Name 38  "gfo2"
+                              Name 45  "um2"
+                              Name 49  "glass"
+                              Name 50  "crossStageBlock1"
+                              MemberName 50(crossStageBlock1) 0  "a"
+                              MemberName 50(crossStageBlock1) 1  "b"
+                              Name 52  ""
+                              Name 53  "fragOnlyBlock"
+                              MemberName 53(fragOnlyBlock) 0  "fb1"
+                              Name 55  ""
+                              Name 56  "crossStageBlock2"
+                              MemberName 56(crossStageBlock2) 0  "a"
+                              MemberName 56(crossStageBlock2) 1  "b"
+                              Name 61  "blockName2"
+                              Decorate 11(gfo1) Location 0
+                              Decorate 15(u1) Location 1
+                              Decorate 15(u1) DescriptorSet 0
+                              Decorate 21(u2) Location 2
+                              Decorate 21(u2) DescriptorSet 0
+                              Decorate 28(u3) Location 3
+                              Decorate 28(u3) DescriptorSet 0
+                              Decorate 32(outColor) Location 0
+                              Decorate 34(outBlock) Block
+                              Decorate 36 Location 5
+                              Decorate 38(gfo2) Location 1
+                              Decorate 45(um2) Location 4
+                              Decorate 45(um2) DescriptorSet 0
+                              Decorate 49(glass) Location 0
+                              Decorate 49(glass) DescriptorSet 0
+                              Decorate 49(glass) Binding 0
+                              MemberDecorate 50(crossStageBlock1) 0 Offset 0
+                              MemberDecorate 50(crossStageBlock1) 1 Offset 16
+                              Decorate 50(crossStageBlock1) Block
+                              Decorate 52 DescriptorSet 0
+                              Decorate 52 Binding 0
+                              MemberDecorate 53(fragOnlyBlock) 0 Offset 0
+                              Decorate 53(fragOnlyBlock) BufferBlock
+                              Decorate 55 DescriptorSet 0
+                              Decorate 55 Binding 0
+                              MemberDecorate 56(crossStageBlock2) 0 Offset 0
+                              MemberDecorate 56(crossStageBlock2) 1 Offset 16
+                              Decorate 56(crossStageBlock2) Block
+                              Decorate 61(blockName2) DescriptorSet 0
+                              Decorate 61(blockName2) Binding 0
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypeVector 6(float) 4
+               8:             TypePointer Function 7(fvec4)
+              10:             TypePointer Input 7(fvec4)
+        11(gfo1):     10(ptr) Variable Input
+              13:             TypeVector 6(float) 2
+              14:             TypePointer UniformConstant 13(fvec2)
+          15(u1):     14(ptr) Variable UniformConstant
+              19:             TypeVector 6(float) 3
+              20:             TypePointer UniformConstant 19(fvec3)
+          21(u2):     20(ptr) Variable UniformConstant
+              25:    6(float) Constant 0
+              26:    7(fvec4) ConstantComposite 25 25 25 25
+              27:             TypePointer UniformConstant 7(fvec4)
+          28(u3):     27(ptr) Variable UniformConstant 26
+              31:             TypePointer Output 7(fvec4)
+    32(outColor):     31(ptr) Variable Output
+    34(outBlock):             TypeStruct 7(fvec4)
+              35:             TypePointer Input 34(outBlock)
+              36:     35(ptr) Variable Input
+              37:             TypePointer Input 13(fvec2)
+        38(gfo2):     37(ptr) Variable Input
+              39:             TypeMatrix 13(fvec2) 2
+              40:    6(float) Constant 1082130432
+              41:   13(fvec2) ConstantComposite 40 25
+              42:   13(fvec2) ConstantComposite 25 40
+              43:          39 ConstantComposite 41 42
+              44:             TypePointer UniformConstant 39
+         45(um2):     44(ptr) Variable UniformConstant 43
+              46:             TypeImage 6(float) 2D sampled format:Unknown
+              47:             TypeSampledImage 46
+              48:             TypePointer UniformConstant 47
+       49(glass):     48(ptr) Variable UniformConstant
+50(crossStageBlock1):             TypeStruct 7(fvec4) 7(fvec4)
+              51:             TypePointer Uniform 50(crossStageBlock1)
+              52:     51(ptr) Variable Uniform
+53(fragOnlyBlock):             TypeStruct 13(fvec2)
+              54:             TypePointer Uniform 53(fragOnlyBlock)
+              55:     54(ptr) Variable Uniform
+56(crossStageBlock2):             TypeStruct 7(fvec4) 13(fvec2)
+              57:             TypeInt 32 0
+              58:     57(int) Constant 2
+              59:             TypeArray 56(crossStageBlock2) 58
+              60:             TypePointer Uniform 59
+  61(blockName2):     60(ptr) Variable Uniform
+         4(main):           2 Function None 3
+               5:             Label
+        9(color):      8(ptr) Variable Function
+              12:    7(fvec4) Load 11(gfo1)
+              16:   13(fvec2) Load 15(u1)
+              17:    7(fvec4) VectorShuffle 16 16 0 1 0 1
+              18:    7(fvec4) FMul 12 17
+              22:   19(fvec3) Load 21(u2)
+              23:    7(fvec4) VectorShuffle 22 22 0 1 2 0
+              24:    7(fvec4) FMul 18 23
+              29:    7(fvec4) Load 28(u3)
+              30:    7(fvec4) FMul 24 29
+                              Store 9(color) 30
+              33:    7(fvec4) Load 9(color)
+                              Store 32(outColor) 33
+                              Return
+                              FunctionEnd
diff --git a/Test/baseResults/iomap.crossStage.vert.out b/Test/baseResults/iomap.crossStage.vert.out
new file mode 100644 (file)
index 0000000..5338b80
--- /dev/null
@@ -0,0 +1,515 @@
+iomap.crossStage.vert
+Shader version: 460
+0:? Sequence
+0:32  Function Definition: main( ( global void)
+0:32    Function Parameters: 
+0:34    Sequence
+0:34      move second child to first child ( temp 4-component vector of float)
+0:34        'o1' ( smooth out 4-component vector of float)
+0:34        Constant:
+0:34          0.000000
+0:34          0.000000
+0:34          0.000000
+0:34          0.000000
+0:35      move second child to first child ( temp 2-component vector of float)
+0:35        'o2' ( smooth out 2-component vector of float)
+0:35        Constant:
+0:35          0.000000
+0:35          0.000000
+0:36      move second child to first child ( temp 4-component vector of float)
+0:36        o3: direct index for structure ( out 4-component vector of float)
+0:36          'anon@0' (layout( location=5) out block{ out 4-component vector of float o3})
+0:36          Constant:
+0:36            0 (const uint)
+0:36        Constant:
+0:36          0.000000
+0:36          0.000000
+0:36          0.000000
+0:36          0.000000
+0:?   Linker Objects
+0:?     'o1' ( smooth out 4-component vector of float)
+0:?     'o2' ( smooth out 2-component vector of float)
+0:?     'anon@0' (layout( location=5) out block{ out 4-component vector of float o3})
+0:?     'u1' ( uniform 2-component vector of float)
+0:?     'u2' ( uniform 3-component vector of float)
+0:?       0.000000
+0:?       0.000000
+0:?       0.000000
+0:?     'u3' ( uniform 4-component vector of float)
+0:?       0.000000
+0:?       0.000000
+0:?       0.000000
+0:?       0.000000
+0:?     'um2' ( uniform 2X2 matrix of float)
+0:?       4.000000
+0:?       0.000000
+0:?       0.000000
+0:?       4.000000
+0:?     'glass' (layout( location=0 binding=0) uniform sampler2D)
+0:?     'anon@1' (layout( column_major std140) uniform block{layout( column_major std140) uniform 4-component vector of float a, layout( column_major std140) uniform 4-component vector of float b})
+0:?     'anon@2' (layout( column_major std430) buffer block{layout( column_major std430) buffer 2-component vector of float vb1})
+0:?     'blockName1' (layout( column_major std140) uniform 2-element array of block{layout( column_major std140) uniform 4-component vector of float a, layout( column_major std140) uniform 2-component vector of float b})
+0:?     'gl_VertexID' ( gl_VertexId int VertexId)
+0:?     'gl_InstanceID' ( gl_InstanceId int InstanceId)
+
+iomap.crossStage.frag
+Shader version: 460
+0:? Sequence
+0:36  Function Definition: main( ( global void)
+0:36    Function Parameters: 
+0:38    Sequence
+0:38      Sequence
+0:38        move second child to first child ( temp 4-component vector of float)
+0:38          'color' ( temp 4-component vector of float)
+0:38          component-wise multiply ( temp 4-component vector of float)
+0:38            component-wise multiply ( temp 4-component vector of float)
+0:38              component-wise multiply ( temp 4-component vector of float)
+0:38                'o1' ( smooth in 4-component vector of float)
+0:38                vector swizzle ( temp 4-component vector of float)
+0:38                  'u1' ( uniform 2-component vector of float)
+0:38                  Sequence
+0:38                    Constant:
+0:38                      0 (const int)
+0:38                    Constant:
+0:38                      1 (const int)
+0:38                    Constant:
+0:38                      0 (const int)
+0:38                    Constant:
+0:38                      1 (const int)
+0:38              vector swizzle ( temp 4-component vector of float)
+0:38                'u2' ( uniform 3-component vector of float)
+0:38                Sequence
+0:38                  Constant:
+0:38                    0 (const int)
+0:38                  Constant:
+0:38                    1 (const int)
+0:38                  Constant:
+0:38                    2 (const int)
+0:38                  Constant:
+0:38                    0 (const int)
+0:38            vector swizzle ( temp 4-component vector of float)
+0:38              'u3' ( uniform 4-component vector of float)
+0:38                0.000000
+0:38                0.000000
+0:38                0.000000
+0:38                0.000000
+0:38              Sequence
+0:38                Constant:
+0:38                  0 (const int)
+0:38                Constant:
+0:38                  1 (const int)
+0:38                Constant:
+0:38                  2 (const int)
+0:38                Constant:
+0:38                  3 (const int)
+0:39      move second child to first child ( temp 4-component vector of float)
+0:39        'outColor' ( out 4-component vector of float)
+0:39        'color' ( temp 4-component vector of float)
+0:?   Linker Objects
+0:?     'anon@0' (layout( location=5) in block{ in 4-component vector of float o3})
+0:?     'o2' ( smooth in 2-component vector of float)
+0:?     'o1' ( smooth in 4-component vector of float)
+0:?     'outColor' ( out 4-component vector of float)
+0:?     'u1' ( uniform 2-component vector of float)
+0:?     'u2' ( uniform 3-component vector of float)
+0:?     'u3' ( uniform 4-component vector of float)
+0:?       0.000000
+0:?       0.000000
+0:?       0.000000
+0:?       0.000000
+0:?     'um2' ( uniform 2X2 matrix of float)
+0:?       4.000000
+0:?       0.000000
+0:?       0.000000
+0:?       4.000000
+0:?     'glass' (layout( location=0 binding=0) uniform sampler2D)
+0:?     'anon@1' (layout( column_major std140) uniform block{layout( column_major std140) uniform 4-component vector of float a, layout( column_major std140) uniform 4-component vector of float b})
+0:?     'anon@2' (layout( column_major std430) buffer block{layout( column_major std430) buffer 2-component vector of float fb1})
+0:?     'blockName2' (layout( column_major std140) uniform 2-element array of block{layout( column_major std140) uniform 4-component vector of float a, layout( column_major std140) uniform 2-component vector of float b})
+
+
+Linked vertex stage:
+
+
+Linked fragment stage:
+
+WARNING: Linking unknown stage stage: Matched shader interfaces are using different instance names.
+    blockName1: "layout( column_major std140) uniform 2-element array of block{layout( column_major std140) uniform 4-component vector of float a, layout( column_major std140) uniform 2-component vector of float b}" versus blockName2: "layout( column_major std140) uniform 2-element array of block{layout( column_major std140) uniform 4-component vector of float a, layout( column_major std140) uniform 2-component vector of float b}"
+
+Shader version: 460
+0:? Sequence
+0:32  Function Definition: main( ( global void)
+0:32    Function Parameters: 
+0:34    Sequence
+0:34      move second child to first child ( temp 4-component vector of float)
+0:34        'o1' ( smooth out 4-component vector of float)
+0:34        Constant:
+0:34          0.000000
+0:34          0.000000
+0:34          0.000000
+0:34          0.000000
+0:35      move second child to first child ( temp 2-component vector of float)
+0:35        'o2' ( smooth out 2-component vector of float)
+0:35        Constant:
+0:35          0.000000
+0:35          0.000000
+0:36      move second child to first child ( temp 4-component vector of float)
+0:36        o3: direct index for structure ( out 4-component vector of float)
+0:36          'anon@0' (layout( location=5) out block{ out 4-component vector of float o3})
+0:36          Constant:
+0:36            0 (const uint)
+0:36        Constant:
+0:36          0.000000
+0:36          0.000000
+0:36          0.000000
+0:36          0.000000
+0:?   Linker Objects
+0:?     'o1' ( smooth out 4-component vector of float)
+0:?     'o2' ( smooth out 2-component vector of float)
+0:?     'anon@0' (layout( location=5) out block{ out 4-component vector of float o3})
+0:?     'u1' ( uniform 2-component vector of float)
+0:?     'u2' ( uniform 3-component vector of float)
+0:?       0.000000
+0:?       0.000000
+0:?       0.000000
+0:?     'u3' ( uniform 4-component vector of float)
+0:?       0.000000
+0:?       0.000000
+0:?       0.000000
+0:?       0.000000
+0:?     'um2' ( uniform 2X2 matrix of float)
+0:?       4.000000
+0:?       0.000000
+0:?       0.000000
+0:?       4.000000
+0:?     'glass' (layout( location=0 binding=0) uniform sampler2D)
+0:?     'anon@1' (layout( column_major std140) uniform block{layout( column_major std140) uniform 4-component vector of float a, layout( column_major std140) uniform 4-component vector of float b})
+0:?     'anon@2' (layout( column_major std430) buffer block{layout( column_major std430) buffer 2-component vector of float vb1})
+0:?     'blockName1' (layout( column_major std140) uniform 2-element array of block{layout( column_major std140) uniform 4-component vector of float a, layout( column_major std140) uniform 2-component vector of float b})
+0:?     'gl_VertexID' ( gl_VertexId int VertexId)
+0:?     'gl_InstanceID' ( gl_InstanceId int InstanceId)
+Shader version: 460
+0:? Sequence
+0:36  Function Definition: main( ( global void)
+0:36    Function Parameters: 
+0:38    Sequence
+0:38      Sequence
+0:38        move second child to first child ( temp 4-component vector of float)
+0:38          'color' ( temp 4-component vector of float)
+0:38          component-wise multiply ( temp 4-component vector of float)
+0:38            component-wise multiply ( temp 4-component vector of float)
+0:38              component-wise multiply ( temp 4-component vector of float)
+0:38                'o1' ( smooth in 4-component vector of float)
+0:38                vector swizzle ( temp 4-component vector of float)
+0:38                  'u1' ( uniform 2-component vector of float)
+0:38                  Sequence
+0:38                    Constant:
+0:38                      0 (const int)
+0:38                    Constant:
+0:38                      1 (const int)
+0:38                    Constant:
+0:38                      0 (const int)
+0:38                    Constant:
+0:38                      1 (const int)
+0:38              vector swizzle ( temp 4-component vector of float)
+0:38                'u2' ( uniform 3-component vector of float)
+0:38                Sequence
+0:38                  Constant:
+0:38                    0 (const int)
+0:38                  Constant:
+0:38                    1 (const int)
+0:38                  Constant:
+0:38                    2 (const int)
+0:38                  Constant:
+0:38                    0 (const int)
+0:38            vector swizzle ( temp 4-component vector of float)
+0:38              'u3' ( uniform 4-component vector of float)
+0:38                0.000000
+0:38                0.000000
+0:38                0.000000
+0:38                0.000000
+0:38              Sequence
+0:38                Constant:
+0:38                  0 (const int)
+0:38                Constant:
+0:38                  1 (const int)
+0:38                Constant:
+0:38                  2 (const int)
+0:38                Constant:
+0:38                  3 (const int)
+0:39      move second child to first child ( temp 4-component vector of float)
+0:39        'outColor' ( out 4-component vector of float)
+0:39        'color' ( temp 4-component vector of float)
+0:?   Linker Objects
+0:?     'anon@0' (layout( location=5) in block{ in 4-component vector of float o3})
+0:?     'o2' ( smooth in 2-component vector of float)
+0:?     'o1' ( smooth in 4-component vector of float)
+0:?     'outColor' ( out 4-component vector of float)
+0:?     'u1' ( uniform 2-component vector of float)
+0:?     'u2' ( uniform 3-component vector of float)
+0:?     'u3' ( uniform 4-component vector of float)
+0:?       0.000000
+0:?       0.000000
+0:?       0.000000
+0:?       0.000000
+0:?     'um2' ( uniform 2X2 matrix of float)
+0:?       4.000000
+0:?       0.000000
+0:?       0.000000
+0:?       4.000000
+0:?     'glass' (layout( location=0 binding=0) uniform sampler2D)
+0:?     'anon@1' (layout( column_major std140) uniform block{layout( column_major std140) uniform 4-component vector of float a, layout( column_major std140) uniform 4-component vector of float b})
+0:?     'anon@2' (layout( column_major std430) buffer block{layout( column_major std430) buffer 2-component vector of float fb1})
+0:?     'blockName2' (layout( column_major std140) uniform 2-element array of block{layout( column_major std140) uniform 4-component vector of float a, layout( column_major std140) uniform 2-component vector of float b})
+
+// Module Version 10000
+// Generated by (magic number): 8000a
+// Id's are bound by 56
+
+                              Capability Shader
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Vertex 4  "main" 9 14 18 54 55
+                              Source GLSL 460
+                              Name 4  "main"
+                              Name 9  "o1"
+                              Name 14  "o2"
+                              Name 16  "outBlock"
+                              MemberName 16(outBlock) 0  "o3"
+                              Name 18  ""
+                              Name 23  "u1"
+                              Name 27  "u2"
+                              Name 29  "u3"
+                              Name 36  "um2"
+                              Name 40  "glass"
+                              Name 41  "crossStageBlock1"
+                              MemberName 41(crossStageBlock1) 0  "a"
+                              MemberName 41(crossStageBlock1) 1  "b"
+                              Name 43  ""
+                              Name 44  "vertOnlyBlock"
+                              MemberName 44(vertOnlyBlock) 0  "vb1"
+                              Name 46  ""
+                              Name 47  "crossStageBlock2"
+                              MemberName 47(crossStageBlock2) 0  "a"
+                              MemberName 47(crossStageBlock2) 1  "b"
+                              Name 52  "blockName1"
+                              Name 54  "gl_VertexID"
+                              Name 55  "gl_InstanceID"
+                              Decorate 9(o1) Location 0
+                              Decorate 14(o2) Location 1
+                              Decorate 16(outBlock) Block
+                              Decorate 18 Location 5
+                              Decorate 23(u1) Location 1
+                              Decorate 23(u1) DescriptorSet 0
+                              Decorate 27(u2) Location 2
+                              Decorate 27(u2) DescriptorSet 0
+                              Decorate 29(u3) Location 3
+                              Decorate 29(u3) DescriptorSet 0
+                              Decorate 36(um2) Location 4
+                              Decorate 36(um2) DescriptorSet 0
+                              Decorate 40(glass) Location 0
+                              Decorate 40(glass) DescriptorSet 0
+                              Decorate 40(glass) Binding 0
+                              MemberDecorate 41(crossStageBlock1) 0 Offset 0
+                              MemberDecorate 41(crossStageBlock1) 1 Offset 16
+                              Decorate 41(crossStageBlock1) Block
+                              Decorate 43 DescriptorSet 0
+                              Decorate 43 Binding 0
+                              MemberDecorate 44(vertOnlyBlock) 0 Offset 0
+                              Decorate 44(vertOnlyBlock) BufferBlock
+                              Decorate 46 DescriptorSet 0
+                              Decorate 46 Binding 0
+                              MemberDecorate 47(crossStageBlock2) 0 Offset 0
+                              MemberDecorate 47(crossStageBlock2) 1 Offset 16
+                              Decorate 47(crossStageBlock2) Block
+                              Decorate 52(blockName1) DescriptorSet 0
+                              Decorate 52(blockName1) Binding 0
+                              Decorate 54(gl_VertexID) BuiltIn VertexId
+                              Decorate 55(gl_InstanceID) BuiltIn InstanceId
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypeVector 6(float) 4
+               8:             TypePointer Output 7(fvec4)
+           9(o1):      8(ptr) Variable Output
+              10:    6(float) Constant 0
+              11:    7(fvec4) ConstantComposite 10 10 10 10
+              12:             TypeVector 6(float) 2
+              13:             TypePointer Output 12(fvec2)
+          14(o2):     13(ptr) Variable Output
+              15:   12(fvec2) ConstantComposite 10 10
+    16(outBlock):             TypeStruct 7(fvec4)
+              17:             TypePointer Output 16(outBlock)
+              18:     17(ptr) Variable Output
+              19:             TypeInt 32 1
+              20:     19(int) Constant 0
+              22:             TypePointer UniformConstant 12(fvec2)
+          23(u1):     22(ptr) Variable UniformConstant
+              24:             TypeVector 6(float) 3
+              25:   24(fvec3) ConstantComposite 10 10 10
+              26:             TypePointer UniformConstant 24(fvec3)
+          27(u2):     26(ptr) Variable UniformConstant 25
+              28:             TypePointer UniformConstant 7(fvec4)
+          29(u3):     28(ptr) Variable UniformConstant 11
+              30:             TypeMatrix 12(fvec2) 2
+              31:    6(float) Constant 1082130432
+              32:   12(fvec2) ConstantComposite 31 10
+              33:   12(fvec2) ConstantComposite 10 31
+              34:          30 ConstantComposite 32 33
+              35:             TypePointer UniformConstant 30
+         36(um2):     35(ptr) Variable UniformConstant 34
+              37:             TypeImage 6(float) 2D sampled format:Unknown
+              38:             TypeSampledImage 37
+              39:             TypePointer UniformConstant 38
+       40(glass):     39(ptr) Variable UniformConstant
+41(crossStageBlock1):             TypeStruct 7(fvec4) 7(fvec4)
+              42:             TypePointer Uniform 41(crossStageBlock1)
+              43:     42(ptr) Variable Uniform
+44(vertOnlyBlock):             TypeStruct 12(fvec2)
+              45:             TypePointer Uniform 44(vertOnlyBlock)
+              46:     45(ptr) Variable Uniform
+47(crossStageBlock2):             TypeStruct 7(fvec4) 12(fvec2)
+              48:             TypeInt 32 0
+              49:     48(int) Constant 2
+              50:             TypeArray 47(crossStageBlock2) 49
+              51:             TypePointer Uniform 50
+  52(blockName1):     51(ptr) Variable Uniform
+              53:             TypePointer Input 19(int)
+ 54(gl_VertexID):     53(ptr) Variable Input
+55(gl_InstanceID):     53(ptr) Variable Input
+         4(main):           2 Function None 3
+               5:             Label
+                              Store 9(o1) 11
+                              Store 14(o2) 15
+              21:      8(ptr) AccessChain 18 20
+                              Store 21 11
+                              Return
+                              FunctionEnd
+// Module Version 10000
+// Generated by (magic number): 8000a
+// Id's are bound by 62
+
+                              Capability Shader
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Fragment 4  "main" 11 32 36 38
+                              ExecutionMode 4 OriginLowerLeft
+                              Source GLSL 460
+                              Name 4  "main"
+                              Name 9  "color"
+                              Name 11  "o1"
+                              Name 15  "u1"
+                              Name 21  "u2"
+                              Name 28  "u3"
+                              Name 32  "outColor"
+                              Name 34  "outBlock"
+                              MemberName 34(outBlock) 0  "o3"
+                              Name 36  ""
+                              Name 38  "o2"
+                              Name 45  "um2"
+                              Name 49  "glass"
+                              Name 50  "crossStageBlock1"
+                              MemberName 50(crossStageBlock1) 0  "a"
+                              MemberName 50(crossStageBlock1) 1  "b"
+                              Name 52  ""
+                              Name 53  "fragOnlyBlock"
+                              MemberName 53(fragOnlyBlock) 0  "fb1"
+                              Name 55  ""
+                              Name 56  "crossStageBlock2"
+                              MemberName 56(crossStageBlock2) 0  "a"
+                              MemberName 56(crossStageBlock2) 1  "b"
+                              Name 61  "blockName2"
+                              Decorate 11(o1) Location 0
+                              Decorate 15(u1) Location 1
+                              Decorate 15(u1) DescriptorSet 0
+                              Decorate 21(u2) Location 2
+                              Decorate 21(u2) DescriptorSet 0
+                              Decorate 28(u3) Location 3
+                              Decorate 28(u3) DescriptorSet 0
+                              Decorate 32(outColor) Location 0
+                              Decorate 34(outBlock) Block
+                              Decorate 36 Location 5
+                              Decorate 38(o2) Location 1
+                              Decorate 45(um2) Location 4
+                              Decorate 45(um2) DescriptorSet 0
+                              Decorate 49(glass) Location 0
+                              Decorate 49(glass) DescriptorSet 0
+                              Decorate 49(glass) Binding 0
+                              MemberDecorate 50(crossStageBlock1) 0 Offset 0
+                              MemberDecorate 50(crossStageBlock1) 1 Offset 16
+                              Decorate 50(crossStageBlock1) Block
+                              Decorate 52 DescriptorSet 0
+                              Decorate 52 Binding 0
+                              MemberDecorate 53(fragOnlyBlock) 0 Offset 0
+                              Decorate 53(fragOnlyBlock) BufferBlock
+                              Decorate 55 DescriptorSet 0
+                              Decorate 55 Binding 0
+                              MemberDecorate 56(crossStageBlock2) 0 Offset 0
+                              MemberDecorate 56(crossStageBlock2) 1 Offset 16
+                              Decorate 56(crossStageBlock2) Block
+                              Decorate 61(blockName2) DescriptorSet 0
+                              Decorate 61(blockName2) Binding 0
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypeVector 6(float) 4
+               8:             TypePointer Function 7(fvec4)
+              10:             TypePointer Input 7(fvec4)
+          11(o1):     10(ptr) Variable Input
+              13:             TypeVector 6(float) 2
+              14:             TypePointer UniformConstant 13(fvec2)
+          15(u1):     14(ptr) Variable UniformConstant
+              19:             TypeVector 6(float) 3
+              20:             TypePointer UniformConstant 19(fvec3)
+          21(u2):     20(ptr) Variable UniformConstant
+              25:    6(float) Constant 0
+              26:    7(fvec4) ConstantComposite 25 25 25 25
+              27:             TypePointer UniformConstant 7(fvec4)
+          28(u3):     27(ptr) Variable UniformConstant 26
+              31:             TypePointer Output 7(fvec4)
+    32(outColor):     31(ptr) Variable Output
+    34(outBlock):             TypeStruct 7(fvec4)
+              35:             TypePointer Input 34(outBlock)
+              36:     35(ptr) Variable Input
+              37:             TypePointer Input 13(fvec2)
+          38(o2):     37(ptr) Variable Input
+              39:             TypeMatrix 13(fvec2) 2
+              40:    6(float) Constant 1082130432
+              41:   13(fvec2) ConstantComposite 40 25
+              42:   13(fvec2) ConstantComposite 25 40
+              43:          39 ConstantComposite 41 42
+              44:             TypePointer UniformConstant 39
+         45(um2):     44(ptr) Variable UniformConstant 43
+              46:             TypeImage 6(float) 2D sampled format:Unknown
+              47:             TypeSampledImage 46
+              48:             TypePointer UniformConstant 47
+       49(glass):     48(ptr) Variable UniformConstant
+50(crossStageBlock1):             TypeStruct 7(fvec4) 7(fvec4)
+              51:             TypePointer Uniform 50(crossStageBlock1)
+              52:     51(ptr) Variable Uniform
+53(fragOnlyBlock):             TypeStruct 13(fvec2)
+              54:             TypePointer Uniform 53(fragOnlyBlock)
+              55:     54(ptr) Variable Uniform
+56(crossStageBlock2):             TypeStruct 7(fvec4) 13(fvec2)
+              57:             TypeInt 32 0
+              58:     57(int) Constant 2
+              59:             TypeArray 56(crossStageBlock2) 58
+              60:             TypePointer Uniform 59
+  61(blockName2):     60(ptr) Variable Uniform
+         4(main):           2 Function None 3
+               5:             Label
+        9(color):      8(ptr) Variable Function
+              12:    7(fvec4) Load 11(o1)
+              16:   13(fvec2) Load 15(u1)
+              17:    7(fvec4) VectorShuffle 16 16 0 1 0 1
+              18:    7(fvec4) FMul 12 17
+              22:   19(fvec3) Load 21(u2)
+              23:    7(fvec4) VectorShuffle 22 22 0 1 2 0
+              24:    7(fvec4) FMul 18 23
+              29:    7(fvec4) Load 28(u3)
+              30:    7(fvec4) FMul 24 29
+                              Store 9(color) 30
+              33:    7(fvec4) Load 9(color)
+                              Store 32(outColor) 33
+                              Return
+                              FunctionEnd
diff --git a/Test/baseResults/iomap.crossStage.vk.vert.out b/Test/baseResults/iomap.crossStage.vk.vert.out
new file mode 100644 (file)
index 0000000..e137bdf
--- /dev/null
@@ -0,0 +1,720 @@
+iomap.crossStage.vk.vert
+Shader version: 460
+0:? Sequence
+0:26  Function Definition: main( ( global void)
+0:26    Function Parameters: 
+0:28    Sequence
+0:28      move second child to first child ( temp highp 4-component vector of float)
+0:28        'vgo1' ( smooth out highp 4-component vector of float)
+0:28        Constant:
+0:28          0.000000
+0:28          0.000000
+0:28          0.000000
+0:28          0.000000
+0:29      move second child to first child ( temp highp 2-component vector of float)
+0:29        'vgo2' ( smooth out highp 2-component vector of float)
+0:29        Constant:
+0:29          0.000000
+0:29          0.000000
+0:30      move second child to first child ( temp highp 4-component vector of float)
+0:30        o3: direct index for structure ( out highp 4-component vector of float)
+0:30          'anon@0' (layout( location=5) out block{ out highp 4-component vector of float o3})
+0:30          Constant:
+0:30            0 (const uint)
+0:30        Constant:
+0:30          0.000000
+0:30          0.000000
+0:30          0.000000
+0:30          0.000000
+0:?   Linker Objects
+0:?     'vgo1' ( smooth out highp 4-component vector of float)
+0:?     'vgo2' ( smooth out highp 2-component vector of float)
+0:?     'anon@0' (layout( location=5) out block{ out highp 4-component vector of float o3})
+0:?     'glass' (layout( binding=0) uniform highp sampler2D)
+0:?     'anon@1' (layout( column_major std140) uniform block{layout( column_major std140) uniform highp 4-component vector of float a, layout( column_major std140) uniform highp 4-component vector of float b})
+0:?     'anon@2' (layout( column_major std430) readonly buffer block{layout( column_major std430) readonly buffer highp 2-component vector of float vb1})
+0:?     'blockName1' (layout( column_major std140) uniform 2-element array of block{layout( column_major std140) uniform highp 4-component vector of float a, layout( column_major std140) uniform highp 2-component vector of float b})
+
+iomap.crossStage.vk.geom
+Shader version: 460
+invocations = -1
+max_vertices = 3
+input primitive = points
+output primitive = triangle_strip
+0:? Sequence
+0:25  Function Definition: main( ( global void)
+0:25    Function Parameters: 
+0:27    Sequence
+0:27      Sequence
+0:27        Sequence
+0:27          move second child to first child ( temp highp int)
+0:27            'i' ( temp highp int)
+0:27            Constant:
+0:27              0 (const int)
+0:27        Loop with condition tested first
+0:27          Loop Condition
+0:27          Compare Less Than ( temp bool)
+0:27            'i' ( temp highp int)
+0:27            Constant:
+0:27              3 (const int)
+0:27          Loop Body
+0:28          Sequence
+0:28            move second child to first child ( temp highp 4-component vector of float)
+0:28              'gfo1' (layout( stream=0) out highp 4-component vector of float)
+0:28              Constant:
+0:28                0.000000
+0:28                0.000000
+0:28                0.000000
+0:28                0.000000
+0:29            move second child to first child ( temp highp 2-component vector of float)
+0:29              'gfo2' (layout( stream=0) out highp 2-component vector of float)
+0:29              Constant:
+0:29                0.000000
+0:29                0.000000
+0:30            move second child to first child ( temp highp 4-component vector of float)
+0:30              o3: direct index for structure (layout( stream=0) out highp 4-component vector of float)
+0:30                'gf_out' (layout( location=5 stream=0) out block{layout( stream=0) out highp 4-component vector of float o3})
+0:30                Constant:
+0:30                  0 (const int)
+0:30              o3: direct index for structure ( in highp 4-component vector of float)
+0:30                indirect index (layout( location=5) temp block{ in highp 4-component vector of float o3})
+0:30                  'inBlock' (layout( location=5) in 1-element array of block{ in highp 4-component vector of float o3})
+0:30                  'i' ( temp highp int)
+0:30                Constant:
+0:30                  0 (const int)
+0:31            EmitVertex ( global void)
+0:27          Loop Terminal Expression
+0:27          Post-Increment ( temp highp int)
+0:27            'i' ( temp highp int)
+0:33      EndPrimitive ( global void)
+0:?   Linker Objects
+0:?     'vgo1' ( in 1-element array of highp 4-component vector of float)
+0:?     'vgo2' ( in 1-element array of highp 2-component vector of float)
+0:?     'inBlock' (layout( location=5) in 1-element array of block{ in highp 4-component vector of float o3})
+0:?     'gfo1' (layout( stream=0) out highp 4-component vector of float)
+0:?     'gfo2' (layout( stream=0) out highp 2-component vector of float)
+0:?     'gf_out' (layout( location=5 stream=0) out block{layout( stream=0) out highp 4-component vector of float o3})
+0:?     'blockName1' (layout( column_major std140) uniform 2-element array of block{layout( column_major std140) uniform highp 4-component vector of float a, layout( column_major std140) uniform highp 2-component vector of float b})
+
+iomap.crossStage.vk.frag
+Shader version: 460
+gl_FragCoord origin is upper left
+0:? Sequence
+0:30  Function Definition: Bar( ( global highp 2-component vector of float)
+0:30    Function Parameters: 
+0:31    Sequence
+0:31      Branch: Return with expression
+0:32        add ( temp highp 2-component vector of float)
+0:31          add ( temp highp 2-component vector of float)
+0:31            fb1: direct index for structure (layout( column_major std430) readonly buffer highp 2-component vector of float)
+0:31              'anon@2' (layout( column_major std430) readonly buffer block{layout( column_major std430) readonly buffer highp 2-component vector of float fb1})
+0:31              Constant:
+0:31                0 (const uint)
+0:32            b: direct index for structure (layout( column_major std140) uniform highp 2-component vector of float)
+0:32              direct index (layout( column_major std140) temp block{layout( column_major std140) uniform highp 4-component vector of float a, layout( column_major std140) uniform highp 2-component vector of float b})
+0:32                'blockName2' (layout( column_major std140) uniform 2-element array of block{layout( column_major std140) uniform highp 4-component vector of float a, layout( column_major std140) uniform highp 2-component vector of float b})
+0:32                Constant:
+0:32                  0 (const int)
+0:32              Constant:
+0:32                1 (const int)
+0:33          b: direct index for structure (layout( column_major std140) uniform highp 2-component vector of float)
+0:33            direct index (layout( column_major std140) temp block{layout( column_major std140) uniform highp 4-component vector of float a, layout( column_major std140) uniform highp 2-component vector of float b})
+0:33              'blockName2' (layout( column_major std140) uniform 2-element array of block{layout( column_major std140) uniform highp 4-component vector of float a, layout( column_major std140) uniform highp 2-component vector of float b})
+0:33              Constant:
+0:33                1 (const int)
+0:33            Constant:
+0:33              1 (const int)
+0:36  Function Definition: Foo( ( global highp 4-component vector of float)
+0:36    Function Parameters: 
+0:37    Sequence
+0:37      Branch: Return with expression
+0:40        add ( temp highp 4-component vector of float)
+0:39          add ( temp highp 4-component vector of float)
+0:38            add ( temp highp 4-component vector of float)
+0:37              add ( temp highp 4-component vector of float)
+0:37                a: direct index for structure (layout( column_major std140) uniform highp 4-component vector of float)
+0:37                  'anon@1' (layout( column_major std140) uniform block{layout( column_major std140) uniform highp 4-component vector of float a, layout( column_major std140) uniform highp 4-component vector of float b})
+0:37                  Constant:
+0:37                    0 (const uint)
+0:38                b: direct index for structure (layout( column_major std140) uniform highp 4-component vector of float)
+0:38                  'anon@1' (layout( column_major std140) uniform block{layout( column_major std140) uniform highp 4-component vector of float a, layout( column_major std140) uniform highp 4-component vector of float b})
+0:38                  Constant:
+0:38                    1 (const uint)
+0:39              a: direct index for structure (layout( column_major std140) uniform highp 4-component vector of float)
+0:39                direct index (layout( column_major std140) temp block{layout( column_major std140) uniform highp 4-component vector of float a, layout( column_major std140) uniform highp 2-component vector of float b})
+0:39                  'blockName2' (layout( column_major std140) uniform 2-element array of block{layout( column_major std140) uniform highp 4-component vector of float a, layout( column_major std140) uniform highp 2-component vector of float b})
+0:39                  Constant:
+0:39                    0 (const int)
+0:39                Constant:
+0:39                  0 (const int)
+0:40            a: direct index for structure (layout( column_major std140) uniform highp 4-component vector of float)
+0:40              direct index (layout( column_major std140) temp block{layout( column_major std140) uniform highp 4-component vector of float a, layout( column_major std140) uniform highp 2-component vector of float b})
+0:40                'blockName2' (layout( column_major std140) uniform 2-element array of block{layout( column_major std140) uniform highp 4-component vector of float a, layout( column_major std140) uniform highp 2-component vector of float b})
+0:40                Constant:
+0:40                  1 (const int)
+0:40              Constant:
+0:40                0 (const int)
+0:41          Construct vec4 ( temp highp 4-component vector of float)
+0:41            Function Call: Bar( ( global highp 2-component vector of float)
+0:41            Constant:
+0:41              0.000000
+0:41            Constant:
+0:41              0.000000
+0:44  Function Definition: main( ( global void)
+0:44    Function Parameters: 
+0:46    Sequence
+0:46      Sequence
+0:46        move second child to first child ( temp highp 4-component vector of float)
+0:46          'color' ( temp highp 4-component vector of float)
+0:46          'gfo1' ( smooth in highp 4-component vector of float)
+0:47      move second child to first child ( temp highp 4-component vector of float)
+0:47        'color' ( temp highp 4-component vector of float)
+0:47        add ( temp highp 4-component vector of float)
+0:47          'color' ( temp highp 4-component vector of float)
+0:47          Function Call: Foo( ( global highp 4-component vector of float)
+0:48      move second child to first child ( temp highp 4-component vector of float)
+0:48        'outColor' ( out highp 4-component vector of float)
+0:48        'color' ( temp highp 4-component vector of float)
+0:?   Linker Objects
+0:?     'anon@0' (layout( location=5) in block{ in highp 4-component vector of float o3})
+0:?     'gfo1' ( smooth in highp 4-component vector of float)
+0:?     'gfo2' ( smooth in highp 2-component vector of float)
+0:?     'outColor' ( out highp 4-component vector of float)
+0:?     'glass' (layout( binding=0) uniform highp sampler2D)
+0:?     'anon@1' (layout( column_major std140) uniform block{layout( column_major std140) uniform highp 4-component vector of float a, layout( column_major std140) uniform highp 4-component vector of float b})
+0:?     'anon@2' (layout( column_major std430) readonly buffer block{layout( column_major std430) readonly buffer highp 2-component vector of float fb1})
+0:?     'blockName2' (layout( column_major std140) uniform 2-element array of block{layout( column_major std140) uniform highp 4-component vector of float a, layout( column_major std140) uniform highp 2-component vector of float b})
+
+
+Linked vertex stage:
+
+
+Linked geometry stage:
+
+
+Linked fragment stage:
+
+WARNING: Linking unknown stage stage: Matched shader interfaces are using different instance names.
+    blockName1: "layout( column_major std140) uniform 2-element array of block{layout( column_major std140) uniform highp 4-component vector of float a, layout( column_major std140) uniform highp 2-component vector of float b}" versus blockName2: "layout( column_major std140) uniform 2-element array of block{layout( column_major std140) uniform highp 4-component vector of float a, layout( column_major std140) uniform highp 2-component vector of float b}"
+
+Shader version: 460
+0:? Sequence
+0:26  Function Definition: main( ( global void)
+0:26    Function Parameters: 
+0:28    Sequence
+0:28      move second child to first child ( temp highp 4-component vector of float)
+0:28        'vgo1' ( smooth out highp 4-component vector of float)
+0:28        Constant:
+0:28          0.000000
+0:28          0.000000
+0:28          0.000000
+0:28          0.000000
+0:29      move second child to first child ( temp highp 2-component vector of float)
+0:29        'vgo2' ( smooth out highp 2-component vector of float)
+0:29        Constant:
+0:29          0.000000
+0:29          0.000000
+0:30      move second child to first child ( temp highp 4-component vector of float)
+0:30        o3: direct index for structure ( out highp 4-component vector of float)
+0:30          'anon@0' (layout( location=5) out block{ out highp 4-component vector of float o3})
+0:30          Constant:
+0:30            0 (const uint)
+0:30        Constant:
+0:30          0.000000
+0:30          0.000000
+0:30          0.000000
+0:30          0.000000
+0:?   Linker Objects
+0:?     'vgo1' ( smooth out highp 4-component vector of float)
+0:?     'vgo2' ( smooth out highp 2-component vector of float)
+0:?     'anon@0' (layout( location=5) out block{ out highp 4-component vector of float o3})
+0:?     'glass' (layout( binding=0) uniform highp sampler2D)
+0:?     'anon@1' (layout( column_major std140) uniform block{layout( column_major std140) uniform highp 4-component vector of float a, layout( column_major std140) uniform highp 4-component vector of float b})
+0:?     'anon@2' (layout( column_major std430) readonly buffer block{layout( column_major std430) readonly buffer highp 2-component vector of float vb1})
+0:?     'blockName1' (layout( column_major std140) uniform 2-element array of block{layout( column_major std140) uniform highp 4-component vector of float a, layout( column_major std140) uniform highp 2-component vector of float b})
+Shader version: 460
+invocations = 1
+max_vertices = 3
+input primitive = points
+output primitive = triangle_strip
+0:? Sequence
+0:25  Function Definition: main( ( global void)
+0:25    Function Parameters: 
+0:27    Sequence
+0:27      Sequence
+0:27        Sequence
+0:27          move second child to first child ( temp highp int)
+0:27            'i' ( temp highp int)
+0:27            Constant:
+0:27              0 (const int)
+0:27        Loop with condition tested first
+0:27          Loop Condition
+0:27          Compare Less Than ( temp bool)
+0:27            'i' ( temp highp int)
+0:27            Constant:
+0:27              3 (const int)
+0:27          Loop Body
+0:28          Sequence
+0:28            move second child to first child ( temp highp 4-component vector of float)
+0:28              'gfo1' (layout( stream=0) out highp 4-component vector of float)
+0:28              Constant:
+0:28                0.000000
+0:28                0.000000
+0:28                0.000000
+0:28                0.000000
+0:29            move second child to first child ( temp highp 2-component vector of float)
+0:29              'gfo2' (layout( stream=0) out highp 2-component vector of float)
+0:29              Constant:
+0:29                0.000000
+0:29                0.000000
+0:30            move second child to first child ( temp highp 4-component vector of float)
+0:30              o3: direct index for structure (layout( stream=0) out highp 4-component vector of float)
+0:30                'gf_out' (layout( location=5 stream=0) out block{layout( stream=0) out highp 4-component vector of float o3})
+0:30                Constant:
+0:30                  0 (const int)
+0:30              o3: direct index for structure ( in highp 4-component vector of float)
+0:30                indirect index (layout( location=5) temp block{ in highp 4-component vector of float o3})
+0:30                  'inBlock' (layout( location=5) in 1-element array of block{ in highp 4-component vector of float o3})
+0:30                  'i' ( temp highp int)
+0:30                Constant:
+0:30                  0 (const int)
+0:31            EmitVertex ( global void)
+0:27          Loop Terminal Expression
+0:27          Post-Increment ( temp highp int)
+0:27            'i' ( temp highp int)
+0:33      EndPrimitive ( global void)
+0:?   Linker Objects
+0:?     'vgo1' ( in 1-element array of highp 4-component vector of float)
+0:?     'vgo2' ( in 1-element array of highp 2-component vector of float)
+0:?     'inBlock' (layout( location=5) in 1-element array of block{ in highp 4-component vector of float o3})
+0:?     'gfo1' (layout( stream=0) out highp 4-component vector of float)
+0:?     'gfo2' (layout( stream=0) out highp 2-component vector of float)
+0:?     'gf_out' (layout( location=5 stream=0) out block{layout( stream=0) out highp 4-component vector of float o3})
+0:?     'blockName1' (layout( column_major std140) uniform 2-element array of block{layout( column_major std140) uniform highp 4-component vector of float a, layout( column_major std140) uniform highp 2-component vector of float b})
+Shader version: 460
+gl_FragCoord origin is upper left
+0:? Sequence
+0:30  Function Definition: Bar( ( global highp 2-component vector of float)
+0:30    Function Parameters: 
+0:31    Sequence
+0:31      Branch: Return with expression
+0:32        add ( temp highp 2-component vector of float)
+0:31          add ( temp highp 2-component vector of float)
+0:31            fb1: direct index for structure (layout( column_major std430) readonly buffer highp 2-component vector of float)
+0:31              'anon@2' (layout( column_major std430) readonly buffer block{layout( column_major std430) readonly buffer highp 2-component vector of float fb1})
+0:31              Constant:
+0:31                0 (const uint)
+0:32            b: direct index for structure (layout( column_major std140) uniform highp 2-component vector of float)
+0:32              direct index (layout( column_major std140) temp block{layout( column_major std140) uniform highp 4-component vector of float a, layout( column_major std140) uniform highp 2-component vector of float b})
+0:32                'blockName2' (layout( column_major std140) uniform 2-element array of block{layout( column_major std140) uniform highp 4-component vector of float a, layout( column_major std140) uniform highp 2-component vector of float b})
+0:32                Constant:
+0:32                  0 (const int)
+0:32              Constant:
+0:32                1 (const int)
+0:33          b: direct index for structure (layout( column_major std140) uniform highp 2-component vector of float)
+0:33            direct index (layout( column_major std140) temp block{layout( column_major std140) uniform highp 4-component vector of float a, layout( column_major std140) uniform highp 2-component vector of float b})
+0:33              'blockName2' (layout( column_major std140) uniform 2-element array of block{layout( column_major std140) uniform highp 4-component vector of float a, layout( column_major std140) uniform highp 2-component vector of float b})
+0:33              Constant:
+0:33                1 (const int)
+0:33            Constant:
+0:33              1 (const int)
+0:36  Function Definition: Foo( ( global highp 4-component vector of float)
+0:36    Function Parameters: 
+0:37    Sequence
+0:37      Branch: Return with expression
+0:40        add ( temp highp 4-component vector of float)
+0:39          add ( temp highp 4-component vector of float)
+0:38            add ( temp highp 4-component vector of float)
+0:37              add ( temp highp 4-component vector of float)
+0:37                a: direct index for structure (layout( column_major std140) uniform highp 4-component vector of float)
+0:37                  'anon@1' (layout( column_major std140) uniform block{layout( column_major std140) uniform highp 4-component vector of float a, layout( column_major std140) uniform highp 4-component vector of float b})
+0:37                  Constant:
+0:37                    0 (const uint)
+0:38                b: direct index for structure (layout( column_major std140) uniform highp 4-component vector of float)
+0:38                  'anon@1' (layout( column_major std140) uniform block{layout( column_major std140) uniform highp 4-component vector of float a, layout( column_major std140) uniform highp 4-component vector of float b})
+0:38                  Constant:
+0:38                    1 (const uint)
+0:39              a: direct index for structure (layout( column_major std140) uniform highp 4-component vector of float)
+0:39                direct index (layout( column_major std140) temp block{layout( column_major std140) uniform highp 4-component vector of float a, layout( column_major std140) uniform highp 2-component vector of float b})
+0:39                  'blockName2' (layout( column_major std140) uniform 2-element array of block{layout( column_major std140) uniform highp 4-component vector of float a, layout( column_major std140) uniform highp 2-component vector of float b})
+0:39                  Constant:
+0:39                    0 (const int)
+0:39                Constant:
+0:39                  0 (const int)
+0:40            a: direct index for structure (layout( column_major std140) uniform highp 4-component vector of float)
+0:40              direct index (layout( column_major std140) temp block{layout( column_major std140) uniform highp 4-component vector of float a, layout( column_major std140) uniform highp 2-component vector of float b})
+0:40                'blockName2' (layout( column_major std140) uniform 2-element array of block{layout( column_major std140) uniform highp 4-component vector of float a, layout( column_major std140) uniform highp 2-component vector of float b})
+0:40                Constant:
+0:40                  1 (const int)
+0:40              Constant:
+0:40                0 (const int)
+0:41          Construct vec4 ( temp highp 4-component vector of float)
+0:41            Function Call: Bar( ( global highp 2-component vector of float)
+0:41            Constant:
+0:41              0.000000
+0:41            Constant:
+0:41              0.000000
+0:44  Function Definition: main( ( global void)
+0:44    Function Parameters: 
+0:46    Sequence
+0:46      Sequence
+0:46        move second child to first child ( temp highp 4-component vector of float)
+0:46          'color' ( temp highp 4-component vector of float)
+0:46          'gfo1' ( smooth in highp 4-component vector of float)
+0:47      move second child to first child ( temp highp 4-component vector of float)
+0:47        'color' ( temp highp 4-component vector of float)
+0:47        add ( temp highp 4-component vector of float)
+0:47          'color' ( temp highp 4-component vector of float)
+0:47          Function Call: Foo( ( global highp 4-component vector of float)
+0:48      move second child to first child ( temp highp 4-component vector of float)
+0:48        'outColor' ( out highp 4-component vector of float)
+0:48        'color' ( temp highp 4-component vector of float)
+0:?   Linker Objects
+0:?     'anon@0' (layout( location=5) in block{ in highp 4-component vector of float o3})
+0:?     'gfo1' ( smooth in highp 4-component vector of float)
+0:?     'gfo2' ( smooth in highp 2-component vector of float)
+0:?     'outColor' ( out highp 4-component vector of float)
+0:?     'glass' (layout( binding=0) uniform highp sampler2D)
+0:?     'anon@1' (layout( column_major std140) uniform block{layout( column_major std140) uniform highp 4-component vector of float a, layout( column_major std140) uniform highp 4-component vector of float b})
+0:?     'anon@2' (layout( column_major std430) readonly buffer block{layout( column_major std430) readonly buffer highp 2-component vector of float fb1})
+0:?     'blockName2' (layout( column_major std140) uniform 2-element array of block{layout( column_major std140) uniform highp 4-component vector of float a, layout( column_major std140) uniform highp 2-component vector of float b})
+
+// Module Version 10000
+// Generated by (magic number): 8000a
+// Id's are bound by 38
+
+                              Capability Shader
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Vertex 4  "main" 9 14 18
+                              Source GLSL 460
+                              Name 4  "main"
+                              Name 9  "vgo1"
+                              Name 14  "vgo2"
+                              Name 16  "outBlock"
+                              MemberName 16(outBlock) 0  "o3"
+                              Name 18  ""
+                              Name 25  "glass"
+                              Name 26  "crossStageBlock1"
+                              MemberName 26(crossStageBlock1) 0  "a"
+                              MemberName 26(crossStageBlock1) 1  "b"
+                              Name 28  ""
+                              Name 29  "vertOnlyBlock"
+                              MemberName 29(vertOnlyBlock) 0  "vb1"
+                              Name 31  ""
+                              Name 32  "crossStageBlock2"
+                              MemberName 32(crossStageBlock2) 0  "a"
+                              MemberName 32(crossStageBlock2) 1  "b"
+                              Name 37  "blockName1"
+                              Decorate 9(vgo1) Location 0
+                              Decorate 14(vgo2) Location 1
+                              Decorate 16(outBlock) Block
+                              Decorate 18 Location 5
+                              Decorate 25(glass) DescriptorSet 0
+                              Decorate 25(glass) Binding 0
+                              MemberDecorate 26(crossStageBlock1) 0 Offset 0
+                              MemberDecorate 26(crossStageBlock1) 1 Offset 16
+                              Decorate 26(crossStageBlock1) Block
+                              Decorate 28 DescriptorSet 0
+                              Decorate 28 Binding 1
+                              MemberDecorate 29(vertOnlyBlock) 0 NonWritable
+                              MemberDecorate 29(vertOnlyBlock) 0 Offset 0
+                              Decorate 29(vertOnlyBlock) BufferBlock
+                              Decorate 31 DescriptorSet 0
+                              Decorate 31 Binding 0
+                              MemberDecorate 32(crossStageBlock2) 0 Offset 0
+                              MemberDecorate 32(crossStageBlock2) 1 Offset 16
+                              Decorate 32(crossStageBlock2) Block
+                              Decorate 37(blockName1) DescriptorSet 0
+                              Decorate 37(blockName1) Binding 3
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypeVector 6(float) 4
+               8:             TypePointer Output 7(fvec4)
+         9(vgo1):      8(ptr) Variable Output
+              10:    6(float) Constant 0
+              11:    7(fvec4) ConstantComposite 10 10 10 10
+              12:             TypeVector 6(float) 2
+              13:             TypePointer Output 12(fvec2)
+        14(vgo2):     13(ptr) Variable Output
+              15:   12(fvec2) ConstantComposite 10 10
+    16(outBlock):             TypeStruct 7(fvec4)
+              17:             TypePointer Output 16(outBlock)
+              18:     17(ptr) Variable Output
+              19:             TypeInt 32 1
+              20:     19(int) Constant 0
+              22:             TypeImage 6(float) 2D sampled format:Unknown
+              23:             TypeSampledImage 22
+              24:             TypePointer UniformConstant 23
+       25(glass):     24(ptr) Variable UniformConstant
+26(crossStageBlock1):             TypeStruct 7(fvec4) 7(fvec4)
+              27:             TypePointer Uniform 26(crossStageBlock1)
+              28:     27(ptr) Variable Uniform
+29(vertOnlyBlock):             TypeStruct 12(fvec2)
+              30:             TypePointer Uniform 29(vertOnlyBlock)
+              31:     30(ptr) Variable Uniform
+32(crossStageBlock2):             TypeStruct 7(fvec4) 12(fvec2)
+              33:             TypeInt 32 0
+              34:     33(int) Constant 2
+              35:             TypeArray 32(crossStageBlock2) 34
+              36:             TypePointer Uniform 35
+  37(blockName1):     36(ptr) Variable Uniform
+         4(main):           2 Function None 3
+               5:             Label
+                              Store 9(vgo1) 11
+                              Store 14(vgo2) 15
+              21:      8(ptr) AccessChain 18 20
+                              Store 21 11
+                              Return
+                              FunctionEnd
+// Module Version 10000
+// Generated by (magic number): 8000a
+// Id's are bound by 57
+
+                              Capability Geometry
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Geometry 4  "main" 22 27 31 37 48 51
+                              ExecutionMode 4 InputPoints
+                              ExecutionMode 4 Invocations 1
+                              ExecutionMode 4 OutputTriangleStrip
+                              ExecutionMode 4 OutputVertices 3
+                              Source GLSL 460
+                              Name 4  "main"
+                              Name 8  "i"
+                              Name 22  "gfo1"
+                              Name 27  "gfo2"
+                              Name 29  "outBlock"
+                              MemberName 29(outBlock) 0  "o3"
+                              Name 31  "gf_out"
+                              Name 32  "outBlock"
+                              MemberName 32(outBlock) 0  "o3"
+                              Name 37  "inBlock"
+                              Name 48  "vgo1"
+                              Name 51  "vgo2"
+                              Name 52  "crossStageBlock2"
+                              MemberName 52(crossStageBlock2) 0  "a"
+                              MemberName 52(crossStageBlock2) 1  "b"
+                              Name 56  "blockName1"
+                              Decorate 22(gfo1) Location 0
+                              Decorate 27(gfo2) Location 1
+                              Decorate 29(outBlock) Block
+                              Decorate 31(gf_out) Location 5
+                              Decorate 32(outBlock) Block
+                              Decorate 37(inBlock) Location 5
+                              Decorate 48(vgo1) Location 0
+                              Decorate 51(vgo2) Location 1
+                              MemberDecorate 52(crossStageBlock2) 0 Offset 0
+                              MemberDecorate 52(crossStageBlock2) 1 Offset 16
+                              Decorate 52(crossStageBlock2) Block
+                              Decorate 56(blockName1) DescriptorSet 0
+                              Decorate 56(blockName1) Binding 3
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeInt 32 1
+               7:             TypePointer Function 6(int)
+               9:      6(int) Constant 0
+              16:      6(int) Constant 3
+              17:             TypeBool
+              19:             TypeFloat 32
+              20:             TypeVector 19(float) 4
+              21:             TypePointer Output 20(fvec4)
+        22(gfo1):     21(ptr) Variable Output
+              23:   19(float) Constant 0
+              24:   20(fvec4) ConstantComposite 23 23 23 23
+              25:             TypeVector 19(float) 2
+              26:             TypePointer Output 25(fvec2)
+        27(gfo2):     26(ptr) Variable Output
+              28:   25(fvec2) ConstantComposite 23 23
+    29(outBlock):             TypeStruct 20(fvec4)
+              30:             TypePointer Output 29(outBlock)
+      31(gf_out):     30(ptr) Variable Output
+    32(outBlock):             TypeStruct 20(fvec4)
+              33:             TypeInt 32 0
+              34:     33(int) Constant 1
+              35:             TypeArray 32(outBlock) 34
+              36:             TypePointer Input 35
+     37(inBlock):     36(ptr) Variable Input
+              39:             TypePointer Input 20(fvec4)
+              44:      6(int) Constant 1
+              46:             TypeArray 20(fvec4) 34
+              47:             TypePointer Input 46
+        48(vgo1):     47(ptr) Variable Input
+              49:             TypeArray 25(fvec2) 34
+              50:             TypePointer Input 49
+        51(vgo2):     50(ptr) Variable Input
+52(crossStageBlock2):             TypeStruct 20(fvec4) 25(fvec2)
+              53:     33(int) Constant 2
+              54:             TypeArray 52(crossStageBlock2) 53
+              55:             TypePointer Uniform 54
+  56(blockName1):     55(ptr) Variable Uniform
+         4(main):           2 Function None 3
+               5:             Label
+            8(i):      7(ptr) Variable Function
+                              Store 8(i) 9
+                              Branch 10
+              10:             Label
+                              LoopMerge 12 13 None
+                              Branch 14
+              14:             Label
+              15:      6(int) Load 8(i)
+              18:    17(bool) SLessThan 15 16
+                              BranchConditional 18 11 12
+              11:               Label
+                                Store 22(gfo1) 24
+                                Store 27(gfo2) 28
+              38:      6(int)   Load 8(i)
+              40:     39(ptr)   AccessChain 37(inBlock) 38 9
+              41:   20(fvec4)   Load 40
+              42:     21(ptr)   AccessChain 31(gf_out) 9
+                                Store 42 41
+                                EmitVertex
+                                Branch 13
+              13:               Label
+              43:      6(int)   Load 8(i)
+              45:      6(int)   IAdd 43 44
+                                Store 8(i) 45
+                                Branch 10
+              12:             Label
+                              EndPrimitive
+                              Return
+                              FunctionEnd
+// Module Version 10000
+// Generated by (magic number): 8000a
+// Id's are bound by 81
+
+                              Capability Shader
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Fragment 4  "main" 64 70 74 76
+                              ExecutionMode 4 OriginUpperLeft
+                              Source GLSL 460
+                              Name 4  "main"
+                              Name 9  "Bar("
+                              Name 13  "Foo("
+                              Name 15  "fragOnlyBlock"
+                              MemberName 15(fragOnlyBlock) 0  "fb1"
+                              Name 17  ""
+                              Name 23  "crossStageBlock2"
+                              MemberName 23(crossStageBlock2) 0  "a"
+                              MemberName 23(crossStageBlock2) 1  "b"
+                              Name 28  "blockName2"
+                              Name 38  "crossStageBlock1"
+                              MemberName 38(crossStageBlock1) 0  "a"
+                              MemberName 38(crossStageBlock1) 1  "b"
+                              Name 40  ""
+                              Name 62  "color"
+                              Name 64  "gfo1"
+                              Name 70  "outColor"
+                              Name 72  "outBlock"
+                              MemberName 72(outBlock) 0  "o3"
+                              Name 74  ""
+                              Name 76  "gfo2"
+                              Name 80  "glass"
+                              MemberDecorate 15(fragOnlyBlock) 0 NonWritable
+                              MemberDecorate 15(fragOnlyBlock) 0 Offset 0
+                              Decorate 15(fragOnlyBlock) BufferBlock
+                              Decorate 17 DescriptorSet 0
+                              Decorate 17 Binding 2
+                              MemberDecorate 23(crossStageBlock2) 0 Offset 0
+                              MemberDecorate 23(crossStageBlock2) 1 Offset 16
+                              Decorate 23(crossStageBlock2) Block
+                              Decorate 28(blockName2) DescriptorSet 0
+                              Decorate 28(blockName2) Binding 3
+                              MemberDecorate 38(crossStageBlock1) 0 Offset 0
+                              MemberDecorate 38(crossStageBlock1) 1 Offset 16
+                              Decorate 38(crossStageBlock1) Block
+                              Decorate 40 DescriptorSet 0
+                              Decorate 40 Binding 1
+                              Decorate 64(gfo1) Location 0
+                              Decorate 70(outColor) Location 0
+                              Decorate 72(outBlock) Block
+                              Decorate 74 Location 5
+                              Decorate 76(gfo2) Location 1
+                              Decorate 80(glass) DescriptorSet 0
+                              Decorate 80(glass) Binding 0
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypeVector 6(float) 2
+               8:             TypeFunction 7(fvec2)
+              11:             TypeVector 6(float) 4
+              12:             TypeFunction 11(fvec4)
+15(fragOnlyBlock):             TypeStruct 7(fvec2)
+              16:             TypePointer Uniform 15(fragOnlyBlock)
+              17:     16(ptr) Variable Uniform
+              18:             TypeInt 32 1
+              19:     18(int) Constant 0
+              20:             TypePointer Uniform 7(fvec2)
+23(crossStageBlock2):             TypeStruct 11(fvec4) 7(fvec2)
+              24:             TypeInt 32 0
+              25:     24(int) Constant 2
+              26:             TypeArray 23(crossStageBlock2) 25
+              27:             TypePointer Uniform 26
+  28(blockName2):     27(ptr) Variable Uniform
+              29:     18(int) Constant 1
+38(crossStageBlock1):             TypeStruct 11(fvec4) 11(fvec4)
+              39:             TypePointer Uniform 38(crossStageBlock1)
+              40:     39(ptr) Variable Uniform
+              41:             TypePointer Uniform 11(fvec4)
+              54:    6(float) Constant 0
+              61:             TypePointer Function 11(fvec4)
+              63:             TypePointer Input 11(fvec4)
+        64(gfo1):     63(ptr) Variable Input
+              69:             TypePointer Output 11(fvec4)
+    70(outColor):     69(ptr) Variable Output
+    72(outBlock):             TypeStruct 11(fvec4)
+              73:             TypePointer Input 72(outBlock)
+              74:     73(ptr) Variable Input
+              75:             TypePointer Input 7(fvec2)
+        76(gfo2):     75(ptr) Variable Input
+              77:             TypeImage 6(float) 2D sampled format:Unknown
+              78:             TypeSampledImage 77
+              79:             TypePointer UniformConstant 78
+       80(glass):     79(ptr) Variable UniformConstant
+         4(main):           2 Function None 3
+               5:             Label
+       62(color):     61(ptr) Variable Function
+              65:   11(fvec4) Load 64(gfo1)
+                              Store 62(color) 65
+              66:   11(fvec4) Load 62(color)
+              67:   11(fvec4) FunctionCall 13(Foo()
+              68:   11(fvec4) FAdd 66 67
+                              Store 62(color) 68
+              71:   11(fvec4) Load 62(color)
+                              Store 70(outColor) 71
+                              Return
+                              FunctionEnd
+         9(Bar():    7(fvec2) Function None 8
+              10:             Label
+              21:     20(ptr) AccessChain 17 19
+              22:    7(fvec2) Load 21
+              30:     20(ptr) AccessChain 28(blockName2) 19 29
+              31:    7(fvec2) Load 30
+              32:    7(fvec2) FAdd 22 31
+              33:     20(ptr) AccessChain 28(blockName2) 29 29
+              34:    7(fvec2) Load 33
+              35:    7(fvec2) FAdd 32 34
+                              ReturnValue 35
+                              FunctionEnd
+        13(Foo():   11(fvec4) Function None 12
+              14:             Label
+              42:     41(ptr) AccessChain 40 19
+              43:   11(fvec4) Load 42
+              44:     41(ptr) AccessChain 40 29
+              45:   11(fvec4) Load 44
+              46:   11(fvec4) FAdd 43 45
+              47:     41(ptr) AccessChain 28(blockName2) 19 19
+              48:   11(fvec4) Load 47
+              49:   11(fvec4) FAdd 46 48
+              50:     41(ptr) AccessChain 28(blockName2) 29 19
+              51:   11(fvec4) Load 50
+              52:   11(fvec4) FAdd 49 51
+              53:    7(fvec2) FunctionCall 9(Bar()
+              55:    6(float) CompositeExtract 53 0
+              56:    6(float) CompositeExtract 53 1
+              57:   11(fvec4) CompositeConstruct 55 56 54 54
+              58:   11(fvec4) FAdd 52 57
+                              ReturnValue 58
+                              FunctionEnd
diff --git a/Test/baseResults/vk.relaxed.errorcheck.vert.out b/Test/baseResults/vk.relaxed.errorcheck.vert.out
new file mode 100644 (file)
index 0000000..f19eae6
--- /dev/null
@@ -0,0 +1,124 @@
+vk.relaxed.errorcheck.vert
+Shader version: 460
+0:? Sequence
+0:9  Function Definition: foo( ( global highp 4-component vector of float)
+0:9    Function Parameters: 
+0:10    Sequence
+0:10      Branch: Return with expression
+0:10        vector swizzle ( temp highp 4-component vector of float)
+0:10          a: direct index for structure ( uniform highp 2-component vector of float)
+0:10            'anon@0' (layout( column_major std140) uniform block{ uniform highp 2-component vector of float a})
+0:10            Constant:
+0:10              0 (const uint)
+0:10          Sequence
+0:10            Constant:
+0:10              0 (const int)
+0:10            Constant:
+0:10              1 (const int)
+0:10            Constant:
+0:10              0 (const int)
+0:10            Constant:
+0:10              1 (const int)
+0:13  Function Definition: main( ( global void)
+0:13    Function Parameters: 
+0:14    Sequence
+0:14      move second child to first child ( temp highp 4-component vector of float)
+0:14        'io' (layout( location=0) smooth out highp 4-component vector of float)
+0:14        Function Call: foo( ( global highp 4-component vector of float)
+0:?   Linker Objects
+0:?     'io' (layout( location=0) smooth out highp 4-component vector of float)
+0:?     'anon@0' (layout( column_major std140) uniform block{ uniform highp 2-component vector of float a})
+0:?     'gl_VertexID' ( in int VertexIndex)
+0:?     'gl_InstanceID' ( in int InstanceIndex)
+
+vk.relaxed.errorcheck.frag
+Shader version: 460
+gl_FragCoord origin is upper left
+0:? Sequence
+0:10  Function Definition: foo( ( global highp 4-component vector of float)
+0:10    Function Parameters: 
+0:11    Sequence
+0:11      Branch: Return with expression
+0:11        a: direct index for structure ( uniform highp 4-component vector of float)
+0:11          'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a})
+0:11          Constant:
+0:11            0 (const uint)
+0:14  Function Definition: main( ( global void)
+0:14    Function Parameters: 
+0:15    Sequence
+0:15      move second child to first child ( temp highp 4-component vector of float)
+0:15        'o' ( out highp 4-component vector of float)
+0:15        add ( temp highp 4-component vector of float)
+0:15          'io' (layout( location=0) smooth in highp 4-component vector of float)
+0:15          Function Call: foo( ( global highp 4-component vector of float)
+0:?   Linker Objects
+0:?     'io' (layout( location=0) smooth in highp 4-component vector of float)
+0:?     'o' ( out highp 4-component vector of float)
+0:?     'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a})
+
+
+Linked vertex stage:
+
+
+Linked fragment stage:
+
+ERROR: Linking unknown stage stage: Types must match:
+    a: " uniform highp 2-component vector of float" versus " uniform highp 4-component vector of float"
+
+Shader version: 460
+0:? Sequence
+0:9  Function Definition: foo( ( global highp 4-component vector of float)
+0:9    Function Parameters: 
+0:10    Sequence
+0:10      Branch: Return with expression
+0:10        vector swizzle ( temp highp 4-component vector of float)
+0:10          a: direct index for structure ( uniform highp 2-component vector of float)
+0:10            'anon@0' (layout( column_major std140) uniform block{ uniform highp 2-component vector of float a})
+0:10            Constant:
+0:10              0 (const uint)
+0:10          Sequence
+0:10            Constant:
+0:10              0 (const int)
+0:10            Constant:
+0:10              1 (const int)
+0:10            Constant:
+0:10              0 (const int)
+0:10            Constant:
+0:10              1 (const int)
+0:13  Function Definition: main( ( global void)
+0:13    Function Parameters: 
+0:14    Sequence
+0:14      move second child to first child ( temp highp 4-component vector of float)
+0:14        'io' (layout( location=0) smooth out highp 4-component vector of float)
+0:14        Function Call: foo( ( global highp 4-component vector of float)
+0:?   Linker Objects
+0:?     'io' (layout( location=0) smooth out highp 4-component vector of float)
+0:?     'anon@0' (layout( column_major std140) uniform block{ uniform highp 2-component vector of float a})
+0:?     'gl_VertexID' ( in int VertexIndex)
+0:?     'gl_InstanceID' ( in int InstanceIndex)
+Shader version: 460
+gl_FragCoord origin is upper left
+0:? Sequence
+0:10  Function Definition: foo( ( global highp 4-component vector of float)
+0:10    Function Parameters: 
+0:11    Sequence
+0:11      Branch: Return with expression
+0:11        a: direct index for structure ( uniform highp 4-component vector of float)
+0:11          'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a})
+0:11          Constant:
+0:11            0 (const uint)
+0:14  Function Definition: main( ( global void)
+0:14    Function Parameters: 
+0:15    Sequence
+0:15      move second child to first child ( temp highp 4-component vector of float)
+0:15        'o' ( out highp 4-component vector of float)
+0:15        add ( temp highp 4-component vector of float)
+0:15          'io' (layout( location=0) smooth in highp 4-component vector of float)
+0:15          Function Call: foo( ( global highp 4-component vector of float)
+0:?   Linker Objects
+0:?     'io' (layout( location=0) smooth in highp 4-component vector of float)
+0:?     'o' ( out highp 4-component vector of float)
+0:?     'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a})
+
+Validation failed
+SPIR-V is not generated for failed compile or link
diff --git a/Test/baseResults/vk.relaxed.frag.out b/Test/baseResults/vk.relaxed.frag.out
new file mode 100644 (file)
index 0000000..d98910e
--- /dev/null
@@ -0,0 +1,826 @@
+vk.relaxed.frag
+WARNING: 0:7: 'b' : Ignoring initializer for uniform 
+WARNING: 0:8: 'c' : ignoring layout qualifier for uniform location
+
+Shader version: 460
+gl_FragCoord origin is upper left
+0:? Sequence
+0:36  Function Definition: bar( ( global highp uint)
+0:36    Function Parameters: 
+0:37    Sequence
+0:37      Sequence
+0:37        move second child to first child ( temp highp uint)
+0:37          'j' ( temp highp uint)
+0:37          Constant:
+0:37            0 (const uint)
+0:38      move second child to first child ( temp highp uint)
+0:38        'j' ( temp highp uint)
+0:38        AtomicAdd ( global highp uint)
+0:38          counter1: direct index for structure ( coherent volatile buffer highp uint)
+0:38            'anon@2' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:38            Constant:
+0:38              0 (const uint)
+0:38          Constant:
+0:38            1 (const uint)
+0:39      move second child to first child ( temp highp uint)
+0:39        'j' ( temp highp uint)
+0:39        subtract ( temp highp uint)
+0:39          AtomicAdd ( global highp uint)
+0:39            counter1: direct index for structure ( coherent volatile buffer highp uint)
+0:39              'anon@2' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:39              Constant:
+0:39                0 (const uint)
+0:39            Constant:
+0:39              4294967295 (const uint)
+0:39          Constant:
+0:39            1 (const uint)
+0:40      move second child to first child ( temp highp uint)
+0:40        'j' ( temp highp uint)
+0:40        counter1: direct index for structure ( coherent volatile buffer highp uint)
+0:40          'anon@2' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:40          Constant:
+0:40            0 (const uint)
+0:42      move second child to first child ( temp highp uint)
+0:42        'j' ( temp highp uint)
+0:42        AtomicAdd ( global highp uint)
+0:42          counter1: direct index for structure ( coherent volatile buffer highp uint)
+0:42            'anon@2' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:42            Constant:
+0:42              0 (const uint)
+0:42          Constant:
+0:42            1 (const uint)
+0:43      move second child to first child ( temp highp uint)
+0:43        'j' ( temp highp uint)
+0:43        AtomicAdd ( global highp uint)
+0:43          counter1: direct index for structure ( coherent volatile buffer highp uint)
+0:43            'anon@2' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:43            Constant:
+0:43              0 (const uint)
+0:43          Constant:
+0:43            4294967295 (const uint)
+0:44      move second child to first child ( temp highp uint)
+0:44        'j' ( temp highp uint)
+0:44        AtomicSubtract ( global highp uint)
+0:44          counter1: direct index for structure ( coherent volatile buffer highp uint)
+0:44            'anon@2' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:44            Constant:
+0:44              0 (const uint)
+0:44          Constant:
+0:44            1 (const uint)
+0:46      move second child to first child ( temp highp uint)
+0:46        'j' ( temp highp uint)
+0:46        AtomicMin ( global highp uint)
+0:46          counter1: direct index for structure ( coherent volatile buffer highp uint)
+0:46            'anon@2' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:46            Constant:
+0:46              0 (const uint)
+0:46          'j' ( temp highp uint)
+0:47      move second child to first child ( temp highp uint)
+0:47        'j' ( temp highp uint)
+0:47        AtomicMax ( global highp uint)
+0:47          counter1: direct index for structure ( coherent volatile buffer highp uint)
+0:47            'anon@2' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:47            Constant:
+0:47              0 (const uint)
+0:47          'j' ( temp highp uint)
+0:48      move second child to first child ( temp highp uint)
+0:48        'j' ( temp highp uint)
+0:48        AtomicAnd ( global highp uint)
+0:48          counter1: direct index for structure ( coherent volatile buffer highp uint)
+0:48            'anon@2' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:48            Constant:
+0:48              0 (const uint)
+0:48          'j' ( temp highp uint)
+0:50      move second child to first child ( temp highp uint)
+0:50        'j' ( temp highp uint)
+0:50        AtomicOr ( global highp uint)
+0:50          counter1: direct index for structure ( coherent volatile buffer highp uint)
+0:50            'anon@2' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:50            Constant:
+0:50              0 (const uint)
+0:50          'j' ( temp highp uint)
+0:51      move second child to first child ( temp highp uint)
+0:51        'j' ( temp highp uint)
+0:51        AtomicXor ( global highp uint)
+0:51          counter1: direct index for structure ( coherent volatile buffer highp uint)
+0:51            'anon@2' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:51            Constant:
+0:51              0 (const uint)
+0:51          'j' ( temp highp uint)
+0:53      move second child to first child ( temp highp uint)
+0:53        'j' ( temp highp uint)
+0:53        AtomicExchange ( global highp uint)
+0:53          counter1: direct index for structure ( coherent volatile buffer highp uint)
+0:53            'anon@2' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:53            Constant:
+0:53              0 (const uint)
+0:53          'j' ( temp highp uint)
+0:54      move second child to first child ( temp highp uint)
+0:54        'j' ( temp highp uint)
+0:54        AtomicCompSwap ( global highp uint)
+0:54          counter1: direct index for structure ( coherent volatile buffer highp uint)
+0:54            'anon@2' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:54            Constant:
+0:54              0 (const uint)
+0:54          Constant:
+0:54            0 (const uint)
+0:54          'j' ( temp highp uint)
+0:56      AtomicAdd ( global highp uint)
+0:56        counter2: direct index for structure ( coherent volatile buffer highp uint)
+0:56          'anon@2' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:56          Constant:
+0:56            1 (const uint)
+0:56        Constant:
+0:56          1 (const uint)
+0:57      AtomicAdd ( global highp uint)
+0:57        counter3: direct index for structure ( coherent volatile buffer highp uint)
+0:57          'anon@3' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter3})
+0:57          Constant:
+0:57            0 (const uint)
+0:57        Constant:
+0:57          1 (const uint)
+0:59      MemoryBarrierBuffer ( global void)
+0:61      Branch: Return with expression
+0:61        'j' ( temp highp uint)
+0:64  Function Definition: foo( ( global highp 4-component vector of float)
+0:64    Function Parameters: 
+0:65    Sequence
+0:65      Sequence
+0:65        move second child to first child ( temp highp float)
+0:65          'f' ( temp highp float)
+0:65          add ( temp highp float)
+0:65            add ( temp highp float)
+0:65              add ( temp highp float)
+0:65                j: direct index for structure (layout( column_major std140) uniform highp float)
+0:65                  'anon@1' (layout( column_major std140) uniform block{layout( column_major std140) uniform highp float j, layout( column_major std140) uniform highp 4-component vector of float k})
+0:65                  Constant:
+0:65                    0 (const uint)
+0:65                j: direct index for structure (layout( column_major std430) buffer highp float)
+0:65                  'bufferInstance' (layout( column_major std430) buffer block{layout( column_major std430) buffer highp float j, layout( column_major std430) buffer highp 4-component vector of float k})
+0:65                  Constant:
+0:65                    0 (const int)
+0:65              y: direct index for structure ( global highp float)
+0:65                structUniform: direct index for structure ( uniform structure{ global highp 2-component vector of float x,  global highp float y,  global highp uint z})
+0:65                  'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b,  uniform highp 2-component vector of float c,  uniform 10-element array of highp 4-component vector of float d,  uniform structure{ global highp 2-component vector of float x,  global highp float y,  global highp uint z} structUniform})
+0:65                  Constant:
+0:65                    4 (const uint)
+0:65                Constant:
+0:65                  1 (const int)
+0:65            Convert uint to float ( temp highp float)
+0:65              z: direct index for structure ( global highp uint)
+0:65                structUniform: direct index for structure ( uniform structure{ global highp 2-component vector of float x,  global highp float y,  global highp uint z})
+0:65                  'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b,  uniform highp 2-component vector of float c,  uniform 10-element array of highp 4-component vector of float d,  uniform structure{ global highp 2-component vector of float x,  global highp float y,  global highp uint z} structUniform})
+0:65                  Constant:
+0:65                    4 (const uint)
+0:65                Constant:
+0:65                  2 (const int)
+0:66      Sequence
+0:66        move second child to first child ( temp highp 2-component vector of float)
+0:66          'v2' ( temp highp 2-component vector of float)
+0:66          add ( temp highp 2-component vector of float)
+0:66            add ( temp highp 2-component vector of float)
+0:66              b: direct index for structure ( uniform highp 2-component vector of float)
+0:66                'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b,  uniform highp 2-component vector of float c,  uniform 10-element array of highp 4-component vector of float d,  uniform structure{ global highp 2-component vector of float x,  global highp float y,  global highp uint z} structUniform})
+0:66                Constant:
+0:66                  1 (const uint)
+0:66              c: direct index for structure ( uniform highp 2-component vector of float)
+0:66                'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b,  uniform highp 2-component vector of float c,  uniform 10-element array of highp 4-component vector of float d,  uniform structure{ global highp 2-component vector of float x,  global highp float y,  global highp uint z} structUniform})
+0:66                Constant:
+0:66                  2 (const uint)
+0:66            x: direct index for structure ( global highp 2-component vector of float)
+0:66              structUniform: direct index for structure ( uniform structure{ global highp 2-component vector of float x,  global highp float y,  global highp uint z})
+0:66                'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b,  uniform highp 2-component vector of float c,  uniform 10-element array of highp 4-component vector of float d,  uniform structure{ global highp 2-component vector of float x,  global highp float y,  global highp uint z} structUniform})
+0:66                Constant:
+0:66                  4 (const uint)
+0:66              Constant:
+0:66                0 (const int)
+0:67      Sequence
+0:67        move second child to first child ( temp highp 4-component vector of float)
+0:67          'v4' ( temp highp 4-component vector of float)
+0:67          add ( temp highp 4-component vector of float)
+0:67            add ( temp highp 4-component vector of float)
+0:67              add ( temp highp 4-component vector of float)
+0:67                add ( temp highp 4-component vector of float)
+0:67                  add ( temp highp 4-component vector of float)
+0:67                    add ( temp highp 4-component vector of float)
+0:67                      a: direct index for structure ( uniform highp 4-component vector of float)
+0:67                        'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b,  uniform highp 2-component vector of float c,  uniform 10-element array of highp 4-component vector of float d,  uniform structure{ global highp 2-component vector of float x,  global highp float y,  global highp uint z} structUniform})
+0:67                        Constant:
+0:67                          0 (const uint)
+0:67                      direct index ( temp highp 4-component vector of float)
+0:67                        d: direct index for structure ( uniform 10-element array of highp 4-component vector of float)
+0:67                          'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b,  uniform highp 2-component vector of float c,  uniform 10-element array of highp 4-component vector of float d,  uniform structure{ global highp 2-component vector of float x,  global highp float y,  global highp uint z} structUniform})
+0:67                          Constant:
+0:67                            3 (const uint)
+0:67                        Constant:
+0:67                          0 (const int)
+0:67                    direct index ( temp highp 4-component vector of float)
+0:67                      d: direct index for structure ( uniform 10-element array of highp 4-component vector of float)
+0:67                        'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b,  uniform highp 2-component vector of float c,  uniform 10-element array of highp 4-component vector of float d,  uniform structure{ global highp 2-component vector of float x,  global highp float y,  global highp uint z} structUniform})
+0:67                        Constant:
+0:67                          3 (const uint)
+0:67                      Constant:
+0:67                        1 (const int)
+0:67                  direct index ( temp highp 4-component vector of float)
+0:67                    d: direct index for structure ( uniform 10-element array of highp 4-component vector of float)
+0:67                      'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b,  uniform highp 2-component vector of float c,  uniform 10-element array of highp 4-component vector of float d,  uniform structure{ global highp 2-component vector of float x,  global highp float y,  global highp uint z} structUniform})
+0:67                      Constant:
+0:67                        3 (const uint)
+0:67                    Constant:
+0:67                      2 (const int)
+0:67                k: direct index for structure (layout( column_major std140) uniform highp 4-component vector of float)
+0:67                  'anon@1' (layout( column_major std140) uniform block{layout( column_major std140) uniform highp float j, layout( column_major std140) uniform highp 4-component vector of float k})
+0:67                  Constant:
+0:67                    1 (const uint)
+0:67              k: direct index for structure (layout( column_major std430) buffer highp 4-component vector of float)
+0:67                'bufferInstance' (layout( column_major std430) buffer block{layout( column_major std430) buffer highp float j, layout( column_major std430) buffer highp 4-component vector of float k})
+0:67                Constant:
+0:67                  1 (const int)
+0:67            texture ( global highp 4-component vector of float)
+0:67              't1' ( uniform highp sampler2D)
+0:67              Constant:
+0:67                0.000000
+0:67                0.000000
+0:68      Branch: Return with expression
+0:68        component-wise multiply ( temp highp 4-component vector of float)
+0:68          component-wise multiply ( temp highp 4-component vector of float)
+0:68            Construct vec4 ( temp highp 4-component vector of float)
+0:68              'f' ( temp highp float)
+0:68            Construct vec4 ( temp highp 4-component vector of float)
+0:68              'v2' ( temp highp 2-component vector of float)
+0:68              Constant:
+0:68                1.000000
+0:68              Constant:
+0:68                1.000000
+0:68          'v4' ( temp highp 4-component vector of float)
+0:71  Function Definition: main( ( global void)
+0:71    Function Parameters: 
+0:72    Sequence
+0:72      Sequence
+0:72        move second child to first child ( temp highp float)
+0:72          'j' ( temp highp float)
+0:72          Convert uint to float ( temp highp float)
+0:72            Function Call: bar( ( global highp uint)
+0:73      move second child to first child ( temp highp 4-component vector of float)
+0:73        'o' ( out highp 4-component vector of float)
+0:73        vector-scale ( temp highp 4-component vector of float)
+0:73          'j' ( temp highp float)
+0:73          Function Call: foo( ( global highp 4-component vector of float)
+0:?   Linker Objects
+0:?     'o' ( out highp 4-component vector of float)
+0:?     'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b,  uniform highp 2-component vector of float c,  uniform 10-element array of highp 4-component vector of float d,  uniform structure{ global highp 2-component vector of float x,  global highp float y,  global highp uint z} structUniform})
+0:?     't1' ( uniform highp sampler2D)
+0:?     'anon@1' (layout( column_major std140) uniform block{layout( column_major std140) uniform highp float j, layout( column_major std140) uniform highp 4-component vector of float k})
+0:?     'bufferInstance' (layout( column_major std430) buffer block{layout( column_major std430) buffer highp float j, layout( column_major std430) buffer highp 4-component vector of float k})
+0:?     'anon@2' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:?     'anon@3' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter3})
+
+
+Linked fragment stage:
+
+
+Shader version: 460
+gl_FragCoord origin is upper left
+0:? Sequence
+0:36  Function Definition: bar( ( global highp uint)
+0:36    Function Parameters: 
+0:37    Sequence
+0:37      Sequence
+0:37        move second child to first child ( temp highp uint)
+0:37          'j' ( temp highp uint)
+0:37          Constant:
+0:37            0 (const uint)
+0:38      move second child to first child ( temp highp uint)
+0:38        'j' ( temp highp uint)
+0:38        AtomicAdd ( global highp uint)
+0:38          counter1: direct index for structure ( coherent volatile buffer highp uint)
+0:38            'anon@2' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:38            Constant:
+0:38              0 (const uint)
+0:38          Constant:
+0:38            1 (const uint)
+0:39      move second child to first child ( temp highp uint)
+0:39        'j' ( temp highp uint)
+0:39        subtract ( temp highp uint)
+0:39          AtomicAdd ( global highp uint)
+0:39            counter1: direct index for structure ( coherent volatile buffer highp uint)
+0:39              'anon@2' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:39              Constant:
+0:39                0 (const uint)
+0:39            Constant:
+0:39              4294967295 (const uint)
+0:39          Constant:
+0:39            1 (const uint)
+0:40      move second child to first child ( temp highp uint)
+0:40        'j' ( temp highp uint)
+0:40        counter1: direct index for structure ( coherent volatile buffer highp uint)
+0:40          'anon@2' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:40          Constant:
+0:40            0 (const uint)
+0:42      move second child to first child ( temp highp uint)
+0:42        'j' ( temp highp uint)
+0:42        AtomicAdd ( global highp uint)
+0:42          counter1: direct index for structure ( coherent volatile buffer highp uint)
+0:42            'anon@2' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:42            Constant:
+0:42              0 (const uint)
+0:42          Constant:
+0:42            1 (const uint)
+0:43      move second child to first child ( temp highp uint)
+0:43        'j' ( temp highp uint)
+0:43        AtomicAdd ( global highp uint)
+0:43          counter1: direct index for structure ( coherent volatile buffer highp uint)
+0:43            'anon@2' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:43            Constant:
+0:43              0 (const uint)
+0:43          Constant:
+0:43            4294967295 (const uint)
+0:44      move second child to first child ( temp highp uint)
+0:44        'j' ( temp highp uint)
+0:44        AtomicSubtract ( global highp uint)
+0:44          counter1: direct index for structure ( coherent volatile buffer highp uint)
+0:44            'anon@2' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:44            Constant:
+0:44              0 (const uint)
+0:44          Constant:
+0:44            1 (const uint)
+0:46      move second child to first child ( temp highp uint)
+0:46        'j' ( temp highp uint)
+0:46        AtomicMin ( global highp uint)
+0:46          counter1: direct index for structure ( coherent volatile buffer highp uint)
+0:46            'anon@2' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:46            Constant:
+0:46              0 (const uint)
+0:46          'j' ( temp highp uint)
+0:47      move second child to first child ( temp highp uint)
+0:47        'j' ( temp highp uint)
+0:47        AtomicMax ( global highp uint)
+0:47          counter1: direct index for structure ( coherent volatile buffer highp uint)
+0:47            'anon@2' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:47            Constant:
+0:47              0 (const uint)
+0:47          'j' ( temp highp uint)
+0:48      move second child to first child ( temp highp uint)
+0:48        'j' ( temp highp uint)
+0:48        AtomicAnd ( global highp uint)
+0:48          counter1: direct index for structure ( coherent volatile buffer highp uint)
+0:48            'anon@2' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:48            Constant:
+0:48              0 (const uint)
+0:48          'j' ( temp highp uint)
+0:50      move second child to first child ( temp highp uint)
+0:50        'j' ( temp highp uint)
+0:50        AtomicOr ( global highp uint)
+0:50          counter1: direct index for structure ( coherent volatile buffer highp uint)
+0:50            'anon@2' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:50            Constant:
+0:50              0 (const uint)
+0:50          'j' ( temp highp uint)
+0:51      move second child to first child ( temp highp uint)
+0:51        'j' ( temp highp uint)
+0:51        AtomicXor ( global highp uint)
+0:51          counter1: direct index for structure ( coherent volatile buffer highp uint)
+0:51            'anon@2' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:51            Constant:
+0:51              0 (const uint)
+0:51          'j' ( temp highp uint)
+0:53      move second child to first child ( temp highp uint)
+0:53        'j' ( temp highp uint)
+0:53        AtomicExchange ( global highp uint)
+0:53          counter1: direct index for structure ( coherent volatile buffer highp uint)
+0:53            'anon@2' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:53            Constant:
+0:53              0 (const uint)
+0:53          'j' ( temp highp uint)
+0:54      move second child to first child ( temp highp uint)
+0:54        'j' ( temp highp uint)
+0:54        AtomicCompSwap ( global highp uint)
+0:54          counter1: direct index for structure ( coherent volatile buffer highp uint)
+0:54            'anon@2' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:54            Constant:
+0:54              0 (const uint)
+0:54          Constant:
+0:54            0 (const uint)
+0:54          'j' ( temp highp uint)
+0:56      AtomicAdd ( global highp uint)
+0:56        counter2: direct index for structure ( coherent volatile buffer highp uint)
+0:56          'anon@2' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:56          Constant:
+0:56            1 (const uint)
+0:56        Constant:
+0:56          1 (const uint)
+0:57      AtomicAdd ( global highp uint)
+0:57        counter3: direct index for structure ( coherent volatile buffer highp uint)
+0:57          'anon@3' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter3})
+0:57          Constant:
+0:57            0 (const uint)
+0:57        Constant:
+0:57          1 (const uint)
+0:59      MemoryBarrierBuffer ( global void)
+0:61      Branch: Return with expression
+0:61        'j' ( temp highp uint)
+0:64  Function Definition: foo( ( global highp 4-component vector of float)
+0:64    Function Parameters: 
+0:65    Sequence
+0:65      Sequence
+0:65        move second child to first child ( temp highp float)
+0:65          'f' ( temp highp float)
+0:65          add ( temp highp float)
+0:65            add ( temp highp float)
+0:65              add ( temp highp float)
+0:65                j: direct index for structure (layout( column_major std140) uniform highp float)
+0:65                  'anon@1' (layout( column_major std140) uniform block{layout( column_major std140) uniform highp float j, layout( column_major std140) uniform highp 4-component vector of float k})
+0:65                  Constant:
+0:65                    0 (const uint)
+0:65                j: direct index for structure (layout( column_major std430) buffer highp float)
+0:65                  'bufferInstance' (layout( column_major std430) buffer block{layout( column_major std430) buffer highp float j, layout( column_major std430) buffer highp 4-component vector of float k})
+0:65                  Constant:
+0:65                    0 (const int)
+0:65              y: direct index for structure ( global highp float)
+0:65                structUniform: direct index for structure ( uniform structure{ global highp 2-component vector of float x,  global highp float y,  global highp uint z})
+0:65                  'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b,  uniform highp 2-component vector of float c,  uniform 10-element array of highp 4-component vector of float d,  uniform structure{ global highp 2-component vector of float x,  global highp float y,  global highp uint z} structUniform})
+0:65                  Constant:
+0:65                    4 (const uint)
+0:65                Constant:
+0:65                  1 (const int)
+0:65            Convert uint to float ( temp highp float)
+0:65              z: direct index for structure ( global highp uint)
+0:65                structUniform: direct index for structure ( uniform structure{ global highp 2-component vector of float x,  global highp float y,  global highp uint z})
+0:65                  'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b,  uniform highp 2-component vector of float c,  uniform 10-element array of highp 4-component vector of float d,  uniform structure{ global highp 2-component vector of float x,  global highp float y,  global highp uint z} structUniform})
+0:65                  Constant:
+0:65                    4 (const uint)
+0:65                Constant:
+0:65                  2 (const int)
+0:66      Sequence
+0:66        move second child to first child ( temp highp 2-component vector of float)
+0:66          'v2' ( temp highp 2-component vector of float)
+0:66          add ( temp highp 2-component vector of float)
+0:66            add ( temp highp 2-component vector of float)
+0:66              b: direct index for structure ( uniform highp 2-component vector of float)
+0:66                'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b,  uniform highp 2-component vector of float c,  uniform 10-element array of highp 4-component vector of float d,  uniform structure{ global highp 2-component vector of float x,  global highp float y,  global highp uint z} structUniform})
+0:66                Constant:
+0:66                  1 (const uint)
+0:66              c: direct index for structure ( uniform highp 2-component vector of float)
+0:66                'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b,  uniform highp 2-component vector of float c,  uniform 10-element array of highp 4-component vector of float d,  uniform structure{ global highp 2-component vector of float x,  global highp float y,  global highp uint z} structUniform})
+0:66                Constant:
+0:66                  2 (const uint)
+0:66            x: direct index for structure ( global highp 2-component vector of float)
+0:66              structUniform: direct index for structure ( uniform structure{ global highp 2-component vector of float x,  global highp float y,  global highp uint z})
+0:66                'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b,  uniform highp 2-component vector of float c,  uniform 10-element array of highp 4-component vector of float d,  uniform structure{ global highp 2-component vector of float x,  global highp float y,  global highp uint z} structUniform})
+0:66                Constant:
+0:66                  4 (const uint)
+0:66              Constant:
+0:66                0 (const int)
+0:67      Sequence
+0:67        move second child to first child ( temp highp 4-component vector of float)
+0:67          'v4' ( temp highp 4-component vector of float)
+0:67          add ( temp highp 4-component vector of float)
+0:67            add ( temp highp 4-component vector of float)
+0:67              add ( temp highp 4-component vector of float)
+0:67                add ( temp highp 4-component vector of float)
+0:67                  add ( temp highp 4-component vector of float)
+0:67                    add ( temp highp 4-component vector of float)
+0:67                      a: direct index for structure ( uniform highp 4-component vector of float)
+0:67                        'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b,  uniform highp 2-component vector of float c,  uniform 10-element array of highp 4-component vector of float d,  uniform structure{ global highp 2-component vector of float x,  global highp float y,  global highp uint z} structUniform})
+0:67                        Constant:
+0:67                          0 (const uint)
+0:67                      direct index ( temp highp 4-component vector of float)
+0:67                        d: direct index for structure ( uniform 10-element array of highp 4-component vector of float)
+0:67                          'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b,  uniform highp 2-component vector of float c,  uniform 10-element array of highp 4-component vector of float d,  uniform structure{ global highp 2-component vector of float x,  global highp float y,  global highp uint z} structUniform})
+0:67                          Constant:
+0:67                            3 (const uint)
+0:67                        Constant:
+0:67                          0 (const int)
+0:67                    direct index ( temp highp 4-component vector of float)
+0:67                      d: direct index for structure ( uniform 10-element array of highp 4-component vector of float)
+0:67                        'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b,  uniform highp 2-component vector of float c,  uniform 10-element array of highp 4-component vector of float d,  uniform structure{ global highp 2-component vector of float x,  global highp float y,  global highp uint z} structUniform})
+0:67                        Constant:
+0:67                          3 (const uint)
+0:67                      Constant:
+0:67                        1 (const int)
+0:67                  direct index ( temp highp 4-component vector of float)
+0:67                    d: direct index for structure ( uniform 10-element array of highp 4-component vector of float)
+0:67                      'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b,  uniform highp 2-component vector of float c,  uniform 10-element array of highp 4-component vector of float d,  uniform structure{ global highp 2-component vector of float x,  global highp float y,  global highp uint z} structUniform})
+0:67                      Constant:
+0:67                        3 (const uint)
+0:67                    Constant:
+0:67                      2 (const int)
+0:67                k: direct index for structure (layout( column_major std140) uniform highp 4-component vector of float)
+0:67                  'anon@1' (layout( column_major std140) uniform block{layout( column_major std140) uniform highp float j, layout( column_major std140) uniform highp 4-component vector of float k})
+0:67                  Constant:
+0:67                    1 (const uint)
+0:67              k: direct index for structure (layout( column_major std430) buffer highp 4-component vector of float)
+0:67                'bufferInstance' (layout( column_major std430) buffer block{layout( column_major std430) buffer highp float j, layout( column_major std430) buffer highp 4-component vector of float k})
+0:67                Constant:
+0:67                  1 (const int)
+0:67            texture ( global highp 4-component vector of float)
+0:67              't1' ( uniform highp sampler2D)
+0:67              Constant:
+0:67                0.000000
+0:67                0.000000
+0:68      Branch: Return with expression
+0:68        component-wise multiply ( temp highp 4-component vector of float)
+0:68          component-wise multiply ( temp highp 4-component vector of float)
+0:68            Construct vec4 ( temp highp 4-component vector of float)
+0:68              'f' ( temp highp float)
+0:68            Construct vec4 ( temp highp 4-component vector of float)
+0:68              'v2' ( temp highp 2-component vector of float)
+0:68              Constant:
+0:68                1.000000
+0:68              Constant:
+0:68                1.000000
+0:68          'v4' ( temp highp 4-component vector of float)
+0:71  Function Definition: main( ( global void)
+0:71    Function Parameters: 
+0:72    Sequence
+0:72      Sequence
+0:72        move second child to first child ( temp highp float)
+0:72          'j' ( temp highp float)
+0:72          Convert uint to float ( temp highp float)
+0:72            Function Call: bar( ( global highp uint)
+0:73      move second child to first child ( temp highp 4-component vector of float)
+0:73        'o' ( out highp 4-component vector of float)
+0:73        vector-scale ( temp highp 4-component vector of float)
+0:73          'j' ( temp highp float)
+0:73          Function Call: foo( ( global highp 4-component vector of float)
+0:?   Linker Objects
+0:?     'o' ( out highp 4-component vector of float)
+0:?     'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b,  uniform highp 2-component vector of float c,  uniform 10-element array of highp 4-component vector of float d,  uniform structure{ global highp 2-component vector of float x,  global highp float y,  global highp uint z} structUniform})
+0:?     't1' ( uniform highp sampler2D)
+0:?     'anon@1' (layout( column_major std140) uniform block{layout( column_major std140) uniform highp float j, layout( column_major std140) uniform highp 4-component vector of float k})
+0:?     'bufferInstance' (layout( column_major std430) buffer block{layout( column_major std430) buffer highp float j, layout( column_major std430) buffer highp 4-component vector of float k})
+0:?     'anon@2' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:?     'anon@3' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter3})
+
+// Module Version 10000
+// Generated by (magic number): 8000a
+// Id's are bound by 163
+
+                              Capability Shader
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Fragment 4  "main" 159
+                              ExecutionMode 4 OriginUpperLeft
+                              Source GLSL 460
+                              Name 4  "main"
+                              Name 8  "bar("
+                              Name 13  "foo("
+                              Name 16  "j"
+                              Name 18  "gl_AtomicCounterBlock_0"
+                              MemberName 18(gl_AtomicCounterBlock_0) 0  "counter1"
+                              MemberName 18(gl_AtomicCounterBlock_0) 1  "counter2"
+                              Name 20  ""
+                              Name 63  "gl_AtomicCounterBlock_1"
+                              MemberName 63(gl_AtomicCounterBlock_1) 0  "counter3"
+                              Name 65  ""
+                              Name 73  "f"
+                              Name 74  "UniformBlock"
+                              MemberName 74(UniformBlock) 0  "j"
+                              MemberName 74(UniformBlock) 1  "k"
+                              Name 76  ""
+                              Name 80  "BufferBlock"
+                              MemberName 80(BufferBlock) 0  "j"
+                              MemberName 80(BufferBlock) 1  "k"
+                              Name 82  "bufferInstance"
+                              Name 89  "e"
+                              MemberName 89(e) 0  "x"
+                              MemberName 89(e) 1  "y"
+                              MemberName 89(e) 2  "z"
+                              Name 90  "gl_DefaultUniformBlock"
+                              MemberName 90(gl_DefaultUniformBlock) 0  "a"
+                              MemberName 90(gl_DefaultUniformBlock) 1  "b"
+                              MemberName 90(gl_DefaultUniformBlock) 2  "c"
+                              MemberName 90(gl_DefaultUniformBlock) 3  "d"
+                              MemberName 90(gl_DefaultUniformBlock) 4  "structUniform"
+                              Name 92  ""
+                              Name 103  "v2"
+                              Name 114  "v4"
+                              Name 137  "t1"
+                              Name 155  "j"
+                              Name 159  "o"
+                              MemberDecorate 18(gl_AtomicCounterBlock_0) 0 Coherent
+                              MemberDecorate 18(gl_AtomicCounterBlock_0) 0 Volatile
+                              MemberDecorate 18(gl_AtomicCounterBlock_0) 0 Coherent
+                              MemberDecorate 18(gl_AtomicCounterBlock_0) 0 Offset 0
+                              MemberDecorate 18(gl_AtomicCounterBlock_0) 1 Coherent
+                              MemberDecorate 18(gl_AtomicCounterBlock_0) 1 Volatile
+                              MemberDecorate 18(gl_AtomicCounterBlock_0) 1 Coherent
+                              MemberDecorate 18(gl_AtomicCounterBlock_0) 1 Offset 4
+                              Decorate 18(gl_AtomicCounterBlock_0) BufferBlock
+                              Decorate 20 DescriptorSet 0
+                              Decorate 20 Binding 4
+                              MemberDecorate 63(gl_AtomicCounterBlock_1) 0 Coherent
+                              MemberDecorate 63(gl_AtomicCounterBlock_1) 0 Volatile
+                              MemberDecorate 63(gl_AtomicCounterBlock_1) 0 Coherent
+                              MemberDecorate 63(gl_AtomicCounterBlock_1) 0 Offset 0
+                              Decorate 63(gl_AtomicCounterBlock_1) BufferBlock
+                              Decorate 65 DescriptorSet 0
+                              Decorate 65 Binding 5
+                              MemberDecorate 74(UniformBlock) 0 Offset 0
+                              MemberDecorate 74(UniformBlock) 1 Offset 16
+                              Decorate 74(UniformBlock) Block
+                              Decorate 76 DescriptorSet 0
+                              Decorate 76 Binding 2
+                              MemberDecorate 80(BufferBlock) 0 Offset 0
+                              MemberDecorate 80(BufferBlock) 1 Offset 16
+                              Decorate 80(BufferBlock) BufferBlock
+                              Decorate 82(bufferInstance) DescriptorSet 0
+                              Decorate 82(bufferInstance) Binding 3
+                              Decorate 88 ArrayStride 16
+                              MemberDecorate 89(e) 0 Offset 0
+                              MemberDecorate 89(e) 1 Offset 8
+                              MemberDecorate 89(e) 2 Offset 12
+                              MemberDecorate 90(gl_DefaultUniformBlock) 0 Offset 0
+                              MemberDecorate 90(gl_DefaultUniformBlock) 1 Offset 16
+                              MemberDecorate 90(gl_DefaultUniformBlock) 2 Offset 24
+                              MemberDecorate 90(gl_DefaultUniformBlock) 3 Offset 32
+                              MemberDecorate 90(gl_DefaultUniformBlock) 4 Offset 192
+                              Decorate 90(gl_DefaultUniformBlock) Block
+                              Decorate 92 DescriptorSet 0
+                              Decorate 92 Binding 0
+                              Decorate 137(t1) DescriptorSet 0
+                              Decorate 137(t1) Binding 1
+                              Decorate 159(o) Location 0
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeInt 32 0
+               7:             TypeFunction 6(int)
+              10:             TypeFloat 32
+              11:             TypeVector 10(float) 4
+              12:             TypeFunction 11(fvec4)
+              15:             TypePointer Function 6(int)
+              17:      6(int) Constant 0
+18(gl_AtomicCounterBlock_0):             TypeStruct 6(int) 6(int)
+              19:             TypePointer Uniform 18(gl_AtomicCounterBlock_0)
+              20:     19(ptr) Variable Uniform
+              21:             TypeInt 32 1
+              22:     21(int) Constant 0
+              23:             TypePointer Uniform 6(int)
+              25:      6(int) Constant 1
+              28:      6(int) Constant 4294967295
+              60:     21(int) Constant 1
+63(gl_AtomicCounterBlock_1):             TypeStruct 6(int)
+              64:             TypePointer Uniform 63(gl_AtomicCounterBlock_1)
+              65:     64(ptr) Variable Uniform
+              68:      6(int) Constant 72
+              72:             TypePointer Function 10(float)
+74(UniformBlock):             TypeStruct 10(float) 11(fvec4)
+              75:             TypePointer Uniform 74(UniformBlock)
+              76:     75(ptr) Variable Uniform
+              77:             TypePointer Uniform 10(float)
+ 80(BufferBlock):             TypeStruct 10(float) 11(fvec4)
+              81:             TypePointer Uniform 80(BufferBlock)
+82(bufferInstance):     81(ptr) Variable Uniform
+              86:             TypeVector 10(float) 2
+              87:      6(int) Constant 10
+              88:             TypeArray 11(fvec4) 87
+           89(e):             TypeStruct 86(fvec2) 10(float) 6(int)
+90(gl_DefaultUniformBlock):             TypeStruct 11(fvec4) 86(fvec2) 86(fvec2) 88 89(e)
+              91:             TypePointer Uniform 90(gl_DefaultUniformBlock)
+              92:     91(ptr) Variable Uniform
+              93:     21(int) Constant 4
+              97:     21(int) Constant 2
+             102:             TypePointer Function 86(fvec2)
+             104:             TypePointer Uniform 86(fvec2)
+             113:             TypePointer Function 11(fvec4)
+             115:             TypePointer Uniform 11(fvec4)
+             118:     21(int) Constant 3
+             134:             TypeImage 10(float) 2D sampled format:Unknown
+             135:             TypeSampledImage 134
+             136:             TypePointer UniformConstant 135
+         137(t1):    136(ptr) Variable UniformConstant
+             139:   10(float) Constant 0
+             140:   86(fvec2) ConstantComposite 139 139
+             146:   10(float) Constant 1065353216
+             158:             TypePointer Output 11(fvec4)
+          159(o):    158(ptr) Variable Output
+         4(main):           2 Function None 3
+               5:             Label
+          155(j):     72(ptr) Variable Function
+             156:      6(int) FunctionCall 8(bar()
+             157:   10(float) ConvertUToF 156
+                              Store 155(j) 157
+             160:   10(float) Load 155(j)
+             161:   11(fvec4) FunctionCall 13(foo()
+             162:   11(fvec4) VectorTimesScalar 161 160
+                              Store 159(o) 162
+                              Return
+                              FunctionEnd
+         8(bar():      6(int) Function None 7
+               9:             Label
+           16(j):     15(ptr) Variable Function
+                              Store 16(j) 17
+              24:     23(ptr) AccessChain 20 22
+              26:      6(int) AtomicIAdd 24 25 17 25
+                              Store 16(j) 26
+              27:     23(ptr) AccessChain 20 22
+              29:      6(int) AtomicIAdd 27 25 17 28
+              30:      6(int) ISub 29 25
+                              Store 16(j) 30
+              31:     23(ptr) AccessChain 20 22
+              32:      6(int) Load 31
+                              Store 16(j) 32
+              33:     23(ptr) AccessChain 20 22
+              34:      6(int) AtomicIAdd 33 25 17 25
+                              Store 16(j) 34
+              35:     23(ptr) AccessChain 20 22
+              36:      6(int) AtomicIAdd 35 25 17 28
+                              Store 16(j) 36
+              37:     23(ptr) AccessChain 20 22
+              38:      6(int) AtomicISub 37 25 17 25
+                              Store 16(j) 38
+              39:     23(ptr) AccessChain 20 22
+              40:      6(int) Load 16(j)
+              41:      6(int) AtomicUMin 39 25 17 40
+                              Store 16(j) 41
+              42:     23(ptr) AccessChain 20 22
+              43:      6(int) Load 16(j)
+              44:      6(int) AtomicUMax 42 25 17 43
+                              Store 16(j) 44
+              45:     23(ptr) AccessChain 20 22
+              46:      6(int) Load 16(j)
+              47:      6(int) AtomicAnd 45 25 17 46
+                              Store 16(j) 47
+              48:     23(ptr) AccessChain 20 22
+              49:      6(int) Load 16(j)
+              50:      6(int) AtomicOr 48 25 17 49
+                              Store 16(j) 50
+              51:     23(ptr) AccessChain 20 22
+              52:      6(int) Load 16(j)
+              53:      6(int) AtomicXor 51 25 17 52
+                              Store 16(j) 53
+              54:     23(ptr) AccessChain 20 22
+              55:      6(int) Load 16(j)
+              56:      6(int) AtomicExchange 54 25 17 55
+                              Store 16(j) 56
+              57:     23(ptr) AccessChain 20 22
+              58:      6(int) Load 16(j)
+              59:      6(int) AtomicCompareExchange 57 25 17 17 58 17
+                              Store 16(j) 59
+              61:     23(ptr) AccessChain 20 60
+              62:      6(int) AtomicIAdd 61 25 17 25
+              66:     23(ptr) AccessChain 65 22
+              67:      6(int) AtomicIAdd 66 25 17 25
+                              MemoryBarrier 25 68
+              69:      6(int) Load 16(j)
+                              ReturnValue 69
+                              FunctionEnd
+        13(foo():   11(fvec4) Function None 12
+              14:             Label
+           73(f):     72(ptr) Variable Function
+         103(v2):    102(ptr) Variable Function
+         114(v4):    113(ptr) Variable Function
+              78:     77(ptr) AccessChain 76 22
+              79:   10(float) Load 78
+              83:     77(ptr) AccessChain 82(bufferInstance) 22
+              84:   10(float) Load 83
+              85:   10(float) FAdd 79 84
+              94:     77(ptr) AccessChain 92 93 60
+              95:   10(float) Load 94
+              96:   10(float) FAdd 85 95
+              98:     23(ptr) AccessChain 92 93 97
+              99:      6(int) Load 98
+             100:   10(float) ConvertUToF 99
+             101:   10(float) FAdd 96 100
+                              Store 73(f) 101
+             105:    104(ptr) AccessChain 92 60
+             106:   86(fvec2) Load 105
+             107:    104(ptr) AccessChain 92 97
+             108:   86(fvec2) Load 107
+             109:   86(fvec2) FAdd 106 108
+             110:    104(ptr) AccessChain 92 93 22
+             111:   86(fvec2) Load 110
+             112:   86(fvec2) FAdd 109 111
+                              Store 103(v2) 112
+             116:    115(ptr) AccessChain 92 22
+             117:   11(fvec4) Load 116
+             119:    115(ptr) AccessChain 92 118 22
+             120:   11(fvec4) Load 119
+             121:   11(fvec4) FAdd 117 120
+             122:    115(ptr) AccessChain 92 118 60
+             123:   11(fvec4) Load 122
+             124:   11(fvec4) FAdd 121 123
+             125:    115(ptr) AccessChain 92 118 97
+             126:   11(fvec4) Load 125
+             127:   11(fvec4) FAdd 124 126
+             128:    115(ptr) AccessChain 76 60
+             129:   11(fvec4) Load 128
+             130:   11(fvec4) FAdd 127 129
+             131:    115(ptr) AccessChain 82(bufferInstance) 60
+             132:   11(fvec4) Load 131
+             133:   11(fvec4) FAdd 130 132
+             138:         135 Load 137(t1)
+             141:   11(fvec4) ImageSampleImplicitLod 138 140
+             142:   11(fvec4) FAdd 133 141
+                              Store 114(v4) 142
+             143:   10(float) Load 73(f)
+             144:   11(fvec4) CompositeConstruct 143 143 143 143
+             145:   86(fvec2) Load 103(v2)
+             147:   10(float) CompositeExtract 145 0
+             148:   10(float) CompositeExtract 145 1
+             149:   11(fvec4) CompositeConstruct 147 148 146 146
+             150:   11(fvec4) FMul 144 149
+             151:   11(fvec4) Load 114(v4)
+             152:   11(fvec4) FMul 150 151
+                              ReturnValue 152
+                              FunctionEnd
diff --git a/Test/baseResults/vk.relaxed.link1.frag.out b/Test/baseResults/vk.relaxed.link1.frag.out
new file mode 100644 (file)
index 0000000..9dac4c6
--- /dev/null
@@ -0,0 +1,515 @@
+vk.relaxed.link1.frag
+Shader version: 460
+gl_FragCoord origin is upper left
+0:? Sequence
+0:19  Function Definition: bar( ( global highp 4-component vector of float)
+0:19    Function Parameters: 
+0:20    Sequence
+0:20      Sequence
+0:20        move second child to first child ( temp highp uint)
+0:20          'j' ( temp highp uint)
+0:20          add ( temp highp uint)
+0:20            AtomicAdd ( global highp uint)
+0:20              counter1: direct index for structure ( coherent volatile buffer highp uint)
+0:20                'anon@1' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:20                Constant:
+0:20                  0 (const uint)
+0:20              Constant:
+0:20                1 (const uint)
+0:20            subtract ( temp highp uint)
+0:20              AtomicAdd ( global highp uint)
+0:20                counter2: direct index for structure ( coherent volatile buffer highp uint)
+0:20                  'anon@1' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:20                  Constant:
+0:20                    1 (const uint)
+0:20                Constant:
+0:20                  4294967295 (const uint)
+0:20              Constant:
+0:20                1 (const uint)
+0:21      Sequence
+0:21        move second child to first child ( temp highp 4-component vector of float)
+0:21          'v' ( temp highp 4-component vector of float)
+0:21          add ( temp highp 4-component vector of float)
+0:21            add ( temp highp 4-component vector of float)
+0:21              add ( temp highp 4-component vector of float)
+0:21                a: direct index for structure ( uniform highp 4-component vector of float)
+0:21                  'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d})
+0:21                  Constant:
+0:21                    0 (const uint)
+0:21                Construct vec4 ( temp highp 4-component vector of float)
+0:21                  direct index ( temp highp float)
+0:21                    b1: direct index for structure ( uniform highp 2-component vector of float)
+0:21                      'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d})
+0:21                      Constant:
+0:21                        1 (const uint)
+0:21                    Constant:
+0:21                      0 (const int)
+0:21                  direct index ( temp highp float)
+0:21                    b1: direct index for structure ( uniform highp 2-component vector of float)
+0:21                      'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d})
+0:21                      Constant:
+0:21                        1 (const uint)
+0:21                    Constant:
+0:21                      1 (const int)
+0:21                  direct index ( temp highp float)
+0:21                    b2: direct index for structure ( uniform highp 2-component vector of float)
+0:21                      'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d})
+0:21                      Constant:
+0:21                        2 (const uint)
+0:21                    Constant:
+0:21                      0 (const int)
+0:21                  direct index ( temp highp float)
+0:21                    b2: direct index for structure ( uniform highp 2-component vector of float)
+0:21                      'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d})
+0:21                      Constant:
+0:21                        2 (const uint)
+0:21                    Constant:
+0:21                      1 (const int)
+0:21              c1: direct index for structure ( uniform highp 4-component vector of float)
+0:21                'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d})
+0:21                Constant:
+0:21                  3 (const uint)
+0:21            d: direct index for structure ( uniform highp 4-component vector of float)
+0:21              'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d})
+0:21              Constant:
+0:21                4 (const uint)
+0:23      Branch: Return with expression
+0:23        vector-scale ( temp highp 4-component vector of float)
+0:23          Convert uint to float ( temp highp float)
+0:23            'j' ( temp highp uint)
+0:23          'v' ( temp highp 4-component vector of float)
+0:26  Function Definition: main( ( global void)
+0:26    Function Parameters: 
+0:27    Sequence
+0:27      move second child to first child ( temp highp 4-component vector of float)
+0:27        'o' ( out highp 4-component vector of float)
+0:27        add ( temp highp 4-component vector of float)
+0:27          Function Call: foo( ( global highp 4-component vector of float)
+0:27          Function Call: bar( ( global highp 4-component vector of float)
+0:?   Linker Objects
+0:?     'o' ( out highp 4-component vector of float)
+0:?     'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d})
+0:?     'anon@1' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+
+vk.relaxed.link2.frag
+Shader version: 460
+gl_FragCoord origin is upper left
+0:? Sequence
+0:14  Function Definition: foo( ( global highp 4-component vector of float)
+0:14    Function Parameters: 
+0:15    Sequence
+0:15      Sequence
+0:15        move second child to first child ( temp highp uint)
+0:15          'j' ( temp highp uint)
+0:15          add ( temp highp uint)
+0:15            AtomicAdd ( global highp uint)
+0:15              counter2: direct index for structure ( coherent volatile buffer highp uint)
+0:15                'anon@1' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter3,  coherent volatile buffer highp uint counter2})
+0:15                Constant:
+0:15                  1 (const uint)
+0:15              Constant:
+0:15                1 (const uint)
+0:15            subtract ( temp highp uint)
+0:15              AtomicAdd ( global highp uint)
+0:15                counter3: direct index for structure ( coherent volatile buffer highp uint)
+0:15                  'anon@1' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter3,  coherent volatile buffer highp uint counter2})
+0:15                  Constant:
+0:15                    0 (const uint)
+0:15                Constant:
+0:15                  4294967295 (const uint)
+0:15              Constant:
+0:15                1 (const uint)
+0:16      Sequence
+0:16        move second child to first child ( temp highp 4-component vector of float)
+0:16          'v' ( temp highp 4-component vector of float)
+0:16          add ( temp highp 4-component vector of float)
+0:16            add ( temp highp 4-component vector of float)
+0:16              add ( temp highp 4-component vector of float)
+0:16                a: direct index for structure ( uniform highp 4-component vector of float)
+0:16                  'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b2,  uniform highp 2-component vector of float b1,  uniform highp 4-component vector of float c2,  uniform highp 4-component vector of float d})
+0:16                  Constant:
+0:16                    0 (const uint)
+0:16                Construct vec4 ( temp highp 4-component vector of float)
+0:16                  direct index ( temp highp float)
+0:16                    b1: direct index for structure ( uniform highp 2-component vector of float)
+0:16                      'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b2,  uniform highp 2-component vector of float b1,  uniform highp 4-component vector of float c2,  uniform highp 4-component vector of float d})
+0:16                      Constant:
+0:16                        2 (const uint)
+0:16                    Constant:
+0:16                      0 (const int)
+0:16                  direct index ( temp highp float)
+0:16                    b1: direct index for structure ( uniform highp 2-component vector of float)
+0:16                      'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b2,  uniform highp 2-component vector of float b1,  uniform highp 4-component vector of float c2,  uniform highp 4-component vector of float d})
+0:16                      Constant:
+0:16                        2 (const uint)
+0:16                    Constant:
+0:16                      1 (const int)
+0:16                  direct index ( temp highp float)
+0:16                    b2: direct index for structure ( uniform highp 2-component vector of float)
+0:16                      'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b2,  uniform highp 2-component vector of float b1,  uniform highp 4-component vector of float c2,  uniform highp 4-component vector of float d})
+0:16                      Constant:
+0:16                        1 (const uint)
+0:16                    Constant:
+0:16                      0 (const int)
+0:16                  direct index ( temp highp float)
+0:16                    b2: direct index for structure ( uniform highp 2-component vector of float)
+0:16                      'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b2,  uniform highp 2-component vector of float b1,  uniform highp 4-component vector of float c2,  uniform highp 4-component vector of float d})
+0:16                      Constant:
+0:16                        1 (const uint)
+0:16                    Constant:
+0:16                      1 (const int)
+0:16              c2: direct index for structure ( uniform highp 4-component vector of float)
+0:16                'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b2,  uniform highp 2-component vector of float b1,  uniform highp 4-component vector of float c2,  uniform highp 4-component vector of float d})
+0:16                Constant:
+0:16                  3 (const uint)
+0:16            d: direct index for structure ( uniform highp 4-component vector of float)
+0:16              'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b2,  uniform highp 2-component vector of float b1,  uniform highp 4-component vector of float c2,  uniform highp 4-component vector of float d})
+0:16              Constant:
+0:16                4 (const uint)
+0:18      Branch: Return with expression
+0:18        vector-scale ( temp highp 4-component vector of float)
+0:18          Convert uint to float ( temp highp float)
+0:18            'j' ( temp highp uint)
+0:18          'v' ( temp highp 4-component vector of float)
+0:?   Linker Objects
+0:?     'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b2,  uniform highp 2-component vector of float b1,  uniform highp 4-component vector of float c2,  uniform highp 4-component vector of float d})
+0:?     'anon@1' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter3,  coherent volatile buffer highp uint counter2})
+
+
+Linked fragment stage:
+
+
+Shader version: 460
+gl_FragCoord origin is upper left
+0:? Sequence
+0:19  Function Definition: bar( ( global highp 4-component vector of float)
+0:19    Function Parameters: 
+0:20    Sequence
+0:20      Sequence
+0:20        move second child to first child ( temp highp uint)
+0:20          'j' ( temp highp uint)
+0:20          add ( temp highp uint)
+0:20            AtomicAdd ( global highp uint)
+0:20              counter1: direct index for structure ( coherent volatile buffer highp uint)
+0:20                'anon@1' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2,  coherent volatile buffer highp uint counter3})
+0:20                Constant:
+0:20                  0 (const uint)
+0:20              Constant:
+0:20                1 (const uint)
+0:20            subtract ( temp highp uint)
+0:20              AtomicAdd ( global highp uint)
+0:20                counter2: direct index for structure ( coherent volatile buffer highp uint)
+0:20                  'anon@1' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2,  coherent volatile buffer highp uint counter3})
+0:20                  Constant:
+0:20                    1 (const uint)
+0:20                Constant:
+0:20                  4294967295 (const uint)
+0:20              Constant:
+0:20                1 (const uint)
+0:21      Sequence
+0:21        move second child to first child ( temp highp 4-component vector of float)
+0:21          'v' ( temp highp 4-component vector of float)
+0:21          add ( temp highp 4-component vector of float)
+0:21            add ( temp highp 4-component vector of float)
+0:21              add ( temp highp 4-component vector of float)
+0:21                a: direct index for structure ( uniform highp 4-component vector of float)
+0:21                  'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d,  uniform highp 4-component vector of float c2})
+0:21                  Constant:
+0:21                    0 (const uint)
+0:21                Construct vec4 ( temp highp 4-component vector of float)
+0:21                  direct index ( temp highp float)
+0:21                    b1: direct index for structure ( uniform highp 2-component vector of float)
+0:21                      'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d,  uniform highp 4-component vector of float c2})
+0:21                      Constant:
+0:21                        1 (const uint)
+0:21                    Constant:
+0:21                      0 (const int)
+0:21                  direct index ( temp highp float)
+0:21                    b1: direct index for structure ( uniform highp 2-component vector of float)
+0:21                      'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d,  uniform highp 4-component vector of float c2})
+0:21                      Constant:
+0:21                        1 (const uint)
+0:21                    Constant:
+0:21                      1 (const int)
+0:21                  direct index ( temp highp float)
+0:21                    b2: direct index for structure ( uniform highp 2-component vector of float)
+0:21                      'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d,  uniform highp 4-component vector of float c2})
+0:21                      Constant:
+0:21                        2 (const uint)
+0:21                    Constant:
+0:21                      0 (const int)
+0:21                  direct index ( temp highp float)
+0:21                    b2: direct index for structure ( uniform highp 2-component vector of float)
+0:21                      'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d,  uniform highp 4-component vector of float c2})
+0:21                      Constant:
+0:21                        2 (const uint)
+0:21                    Constant:
+0:21                      1 (const int)
+0:21              c1: direct index for structure ( uniform highp 4-component vector of float)
+0:21                'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d,  uniform highp 4-component vector of float c2})
+0:21                Constant:
+0:21                  3 (const uint)
+0:21            d: direct index for structure ( uniform highp 4-component vector of float)
+0:21              'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d,  uniform highp 4-component vector of float c2})
+0:21              Constant:
+0:21                4 (const uint)
+0:23      Branch: Return with expression
+0:23        vector-scale ( temp highp 4-component vector of float)
+0:23          Convert uint to float ( temp highp float)
+0:23            'j' ( temp highp uint)
+0:23          'v' ( temp highp 4-component vector of float)
+0:26  Function Definition: main( ( global void)
+0:26    Function Parameters: 
+0:27    Sequence
+0:27      move second child to first child ( temp highp 4-component vector of float)
+0:27        'o' ( out highp 4-component vector of float)
+0:27        add ( temp highp 4-component vector of float)
+0:27          Function Call: foo( ( global highp 4-component vector of float)
+0:27          Function Call: bar( ( global highp 4-component vector of float)
+0:14  Function Definition: foo( ( global highp 4-component vector of float)
+0:14    Function Parameters: 
+0:15    Sequence
+0:15      Sequence
+0:15        move second child to first child ( temp highp uint)
+0:15          'j' ( temp highp uint)
+0:15          add ( temp highp uint)
+0:15            AtomicAdd ( global highp uint)
+0:15              counter2: direct index for structure ( coherent volatile buffer highp uint)
+0:15                'anon@1' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2,  coherent volatile buffer highp uint counter3})
+0:15                Constant:
+0:15                  1 (const uint)
+0:15              Constant:
+0:15                1 (const uint)
+0:15            subtract ( temp highp uint)
+0:15              AtomicAdd ( global highp uint)
+0:15                counter3: direct index for structure ( coherent volatile buffer highp uint)
+0:15                  'anon@1' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2,  coherent volatile buffer highp uint counter3})
+0:15                  Constant:
+0:15                    2 (const uint)
+0:15                Constant:
+0:15                  4294967295 (const uint)
+0:15              Constant:
+0:15                1 (const uint)
+0:16      Sequence
+0:16        move second child to first child ( temp highp 4-component vector of float)
+0:16          'v' ( temp highp 4-component vector of float)
+0:16          add ( temp highp 4-component vector of float)
+0:16            add ( temp highp 4-component vector of float)
+0:16              add ( temp highp 4-component vector of float)
+0:16                a: direct index for structure ( uniform highp 4-component vector of float)
+0:16                  'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d,  uniform highp 4-component vector of float c2})
+0:16                  Constant:
+0:16                    0 (const uint)
+0:16                Construct vec4 ( temp highp 4-component vector of float)
+0:16                  direct index ( temp highp float)
+0:16                    b1: direct index for structure ( uniform highp 2-component vector of float)
+0:16                      'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d,  uniform highp 4-component vector of float c2})
+0:16                      Constant:
+0:16                        1 (const uint)
+0:16                    Constant:
+0:16                      0 (const int)
+0:16                  direct index ( temp highp float)
+0:16                    b1: direct index for structure ( uniform highp 2-component vector of float)
+0:16                      'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d,  uniform highp 4-component vector of float c2})
+0:16                      Constant:
+0:16                        1 (const uint)
+0:16                    Constant:
+0:16                      1 (const int)
+0:16                  direct index ( temp highp float)
+0:16                    b2: direct index for structure ( uniform highp 2-component vector of float)
+0:16                      'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d,  uniform highp 4-component vector of float c2})
+0:16                      Constant:
+0:16                        2 (const uint)
+0:16                    Constant:
+0:16                      0 (const int)
+0:16                  direct index ( temp highp float)
+0:16                    b2: direct index for structure ( uniform highp 2-component vector of float)
+0:16                      'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d,  uniform highp 4-component vector of float c2})
+0:16                      Constant:
+0:16                        2 (const uint)
+0:16                    Constant:
+0:16                      1 (const int)
+0:16              c2: direct index for structure ( uniform highp 4-component vector of float)
+0:16                'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d,  uniform highp 4-component vector of float c2})
+0:16                Constant:
+0:16                  5 (const uint)
+0:16            d: direct index for structure ( uniform highp 4-component vector of float)
+0:16              'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d,  uniform highp 4-component vector of float c2})
+0:16              Constant:
+0:16                4 (const uint)
+0:18      Branch: Return with expression
+0:18        vector-scale ( temp highp 4-component vector of float)
+0:18          Convert uint to float ( temp highp float)
+0:18            'j' ( temp highp uint)
+0:18          'v' ( temp highp 4-component vector of float)
+0:?   Linker Objects
+0:?     'o' ( out highp 4-component vector of float)
+0:?     'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d,  uniform highp 4-component vector of float c2})
+0:?     'anon@1' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2,  coherent volatile buffer highp uint counter3})
+
+// Module Version 10000
+// Generated by (magic number): 8000a
+// Id's are bound by 105
+
+                              Capability Shader
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Fragment 4  "main" 68
+                              ExecutionMode 4 OriginUpperLeft
+                              Source GLSL 460
+                              Name 4  "main"
+                              Name 9  "bar("
+                              Name 11  "foo("
+                              Name 15  "j"
+                              Name 16  "gl_AtomicCounterBlock_0"
+                              MemberName 16(gl_AtomicCounterBlock_0) 0  "counter1"
+                              MemberName 16(gl_AtomicCounterBlock_0) 1  "counter2"
+                              MemberName 16(gl_AtomicCounterBlock_0) 2  "counter3"
+                              Name 18  ""
+                              Name 33  "v"
+                              Name 35  "gl_DefaultUniformBlock"
+                              MemberName 35(gl_DefaultUniformBlock) 0  "a"
+                              MemberName 35(gl_DefaultUniformBlock) 1  "b1"
+                              MemberName 35(gl_DefaultUniformBlock) 2  "b2"
+                              MemberName 35(gl_DefaultUniformBlock) 3  "c1"
+                              MemberName 35(gl_DefaultUniformBlock) 4  "d"
+                              MemberName 35(gl_DefaultUniformBlock) 5  "c2"
+                              Name 37  ""
+                              Name 68  "o"
+                              Name 72  "j"
+                              Name 79  "v"
+                              MemberDecorate 16(gl_AtomicCounterBlock_0) 0 Coherent
+                              MemberDecorate 16(gl_AtomicCounterBlock_0) 0 Volatile
+                              MemberDecorate 16(gl_AtomicCounterBlock_0) 0 Coherent
+                              MemberDecorate 16(gl_AtomicCounterBlock_0) 0 Offset 0
+                              MemberDecorate 16(gl_AtomicCounterBlock_0) 1 Coherent
+                              MemberDecorate 16(gl_AtomicCounterBlock_0) 1 Volatile
+                              MemberDecorate 16(gl_AtomicCounterBlock_0) 1 Coherent
+                              MemberDecorate 16(gl_AtomicCounterBlock_0) 1 Offset 4
+                              MemberDecorate 16(gl_AtomicCounterBlock_0) 2 Coherent
+                              MemberDecorate 16(gl_AtomicCounterBlock_0) 2 Volatile
+                              MemberDecorate 16(gl_AtomicCounterBlock_0) 2 Coherent
+                              MemberDecorate 16(gl_AtomicCounterBlock_0) 2 Offset 8
+                              Decorate 16(gl_AtomicCounterBlock_0) BufferBlock
+                              Decorate 18 DescriptorSet 0
+                              Decorate 18 Binding 1
+                              MemberDecorate 35(gl_DefaultUniformBlock) 0 Offset 0
+                              MemberDecorate 35(gl_DefaultUniformBlock) 1 Offset 16
+                              MemberDecorate 35(gl_DefaultUniformBlock) 2 Offset 24
+                              MemberDecorate 35(gl_DefaultUniformBlock) 3 Offset 32
+                              MemberDecorate 35(gl_DefaultUniformBlock) 4 Offset 48
+                              MemberDecorate 35(gl_DefaultUniformBlock) 5 Offset 64
+                              Decorate 35(gl_DefaultUniformBlock) Block
+                              Decorate 37 DescriptorSet 0
+                              Decorate 37 Binding 0
+                              Decorate 68(o) Location 0
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypeVector 6(float) 4
+               8:             TypeFunction 7(fvec4)
+              13:             TypeInt 32 0
+              14:             TypePointer Function 13(int)
+16(gl_AtomicCounterBlock_0):             TypeStruct 13(int) 13(int) 13(int)
+              17:             TypePointer Uniform 16(gl_AtomicCounterBlock_0)
+              18:     17(ptr) Variable Uniform
+              19:             TypeInt 32 1
+              20:     19(int) Constant 0
+              21:             TypePointer Uniform 13(int)
+              23:     13(int) Constant 1
+              24:     13(int) Constant 0
+              26:     19(int) Constant 1
+              28:     13(int) Constant 4294967295
+              32:             TypePointer Function 7(fvec4)
+              34:             TypeVector 6(float) 2
+35(gl_DefaultUniformBlock):             TypeStruct 7(fvec4) 34(fvec2) 34(fvec2) 7(fvec4) 7(fvec4) 7(fvec4)
+              36:             TypePointer Uniform 35(gl_DefaultUniformBlock)
+              37:     36(ptr) Variable Uniform
+              38:             TypePointer Uniform 7(fvec4)
+              41:             TypePointer Uniform 6(float)
+              46:     19(int) Constant 2
+              53:     19(int) Constant 3
+              57:     19(int) Constant 4
+              67:             TypePointer Output 7(fvec4)
+           68(o):     67(ptr) Variable Output
+              92:     19(int) Constant 5
+         4(main):           2 Function None 3
+               5:             Label
+              69:    7(fvec4) FunctionCall 11(foo()
+              70:    7(fvec4) FunctionCall 9(bar()
+              71:    7(fvec4) FAdd 69 70
+                              Store 68(o) 71
+                              Return
+                              FunctionEnd
+         9(bar():    7(fvec4) Function None 8
+              10:             Label
+           15(j):     14(ptr) Variable Function
+           33(v):     32(ptr) Variable Function
+              22:     21(ptr) AccessChain 18 20
+              25:     13(int) AtomicIAdd 22 23 24 23
+              27:     21(ptr) AccessChain 18 26
+              29:     13(int) AtomicIAdd 27 23 24 28
+              30:     13(int) ISub 29 23
+              31:     13(int) IAdd 25 30
+                              Store 15(j) 31
+              39:     38(ptr) AccessChain 37 20
+              40:    7(fvec4) Load 39
+              42:     41(ptr) AccessChain 37 26 24
+              43:    6(float) Load 42
+              44:     41(ptr) AccessChain 37 26 23
+              45:    6(float) Load 44
+              47:     41(ptr) AccessChain 37 46 24
+              48:    6(float) Load 47
+              49:     41(ptr) AccessChain 37 46 23
+              50:    6(float) Load 49
+              51:    7(fvec4) CompositeConstruct 43 45 48 50
+              52:    7(fvec4) FAdd 40 51
+              54:     38(ptr) AccessChain 37 53
+              55:    7(fvec4) Load 54
+              56:    7(fvec4) FAdd 52 55
+              58:     38(ptr) AccessChain 37 57
+              59:    7(fvec4) Load 58
+              60:    7(fvec4) FAdd 56 59
+                              Store 33(v) 60
+              61:     13(int) Load 15(j)
+              62:    6(float) ConvertUToF 61
+              63:    7(fvec4) Load 33(v)
+              64:    7(fvec4) VectorTimesScalar 63 62
+                              ReturnValue 64
+                              FunctionEnd
+        11(foo():    7(fvec4) Function None 8
+              12:             Label
+           72(j):     14(ptr) Variable Function
+           79(v):     32(ptr) Variable Function
+              73:     21(ptr) AccessChain 18 26
+              74:     13(int) AtomicIAdd 73 23 24 23
+              75:     21(ptr) AccessChain 18 46
+              76:     13(int) AtomicIAdd 75 23 24 28
+              77:     13(int) ISub 76 23
+              78:     13(int) IAdd 74 77
+                              Store 72(j) 78
+              80:     38(ptr) AccessChain 37 20
+              81:    7(fvec4) Load 80
+              82:     41(ptr) AccessChain 37 26 24
+              83:    6(float) Load 82
+              84:     41(ptr) AccessChain 37 26 23
+              85:    6(float) Load 84
+              86:     41(ptr) AccessChain 37 46 24
+              87:    6(float) Load 86
+              88:     41(ptr) AccessChain 37 46 23
+              89:    6(float) Load 88
+              90:    7(fvec4) CompositeConstruct 83 85 87 89
+              91:    7(fvec4) FAdd 81 90
+              93:     38(ptr) AccessChain 37 92
+              94:    7(fvec4) Load 93
+              95:    7(fvec4) FAdd 91 94
+              96:     38(ptr) AccessChain 37 57
+              97:    7(fvec4) Load 96
+              98:    7(fvec4) FAdd 95 97
+                              Store 79(v) 98
+              99:     13(int) Load 72(j)
+             100:    6(float) ConvertUToF 99
+             101:    7(fvec4) Load 79(v)
+             102:    7(fvec4) VectorTimesScalar 101 100
+                              ReturnValue 102
+                              FunctionEnd
diff --git a/Test/baseResults/vk.relaxed.stagelink.vert.out b/Test/baseResults/vk.relaxed.stagelink.vert.out
new file mode 100644 (file)
index 0000000..a63f10c
--- /dev/null
@@ -0,0 +1,717 @@
+vk.relaxed.stagelink.vert
+Shader version: 460
+0:? Sequence
+0:18  Function Definition: foo( ( global highp 4-component vector of float)
+0:18    Function Parameters: 
+0:19    Sequence
+0:19      Sequence
+0:19        move second child to first child ( temp highp uint)
+0:19          'j' ( temp highp uint)
+0:19          add ( temp highp uint)
+0:19            AtomicAdd ( global highp uint)
+0:19              counter2: direct index for structure ( coherent volatile buffer highp uint)
+0:19                'anon@1' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter3,  coherent volatile buffer highp uint counter2})
+0:19                Constant:
+0:19                  1 (const uint)
+0:19              Constant:
+0:19                1 (const uint)
+0:19            subtract ( temp highp uint)
+0:19              AtomicAdd ( global highp uint)
+0:19                counter3: direct index for structure ( coherent volatile buffer highp uint)
+0:19                  'anon@1' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter3,  coherent volatile buffer highp uint counter2})
+0:19                  Constant:
+0:19                    0 (const uint)
+0:19                Constant:
+0:19                  4294967295 (const uint)
+0:19              Constant:
+0:19                1 (const uint)
+0:20      Sequence
+0:20        move second child to first child ( temp highp 4-component vector of float)
+0:20          'v' ( temp highp 4-component vector of float)
+0:20          add ( temp highp 4-component vector of float)
+0:20            add ( temp highp 4-component vector of float)
+0:20              add ( temp highp 4-component vector of float)
+0:20                a: direct index for structure ( uniform highp 4-component vector of float)
+0:20                  'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b2,  uniform highp 2-component vector of float b1,  uniform highp 4-component vector of float c2,  uniform highp 4-component vector of float d,  uniform 4-element array of highp 4-component vector of float s})
+0:20                  Constant:
+0:20                    0 (const uint)
+0:20                Construct vec4 ( temp highp 4-component vector of float)
+0:20                  direct index ( temp highp float)
+0:20                    b1: direct index for structure ( uniform highp 2-component vector of float)
+0:20                      'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b2,  uniform highp 2-component vector of float b1,  uniform highp 4-component vector of float c2,  uniform highp 4-component vector of float d,  uniform 4-element array of highp 4-component vector of float s})
+0:20                      Constant:
+0:20                        2 (const uint)
+0:20                    Constant:
+0:20                      0 (const int)
+0:20                  direct index ( temp highp float)
+0:20                    b1: direct index for structure ( uniform highp 2-component vector of float)
+0:20                      'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b2,  uniform highp 2-component vector of float b1,  uniform highp 4-component vector of float c2,  uniform highp 4-component vector of float d,  uniform 4-element array of highp 4-component vector of float s})
+0:20                      Constant:
+0:20                        2 (const uint)
+0:20                    Constant:
+0:20                      1 (const int)
+0:20                  direct index ( temp highp float)
+0:20                    b2: direct index for structure ( uniform highp 2-component vector of float)
+0:20                      'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b2,  uniform highp 2-component vector of float b1,  uniform highp 4-component vector of float c2,  uniform highp 4-component vector of float d,  uniform 4-element array of highp 4-component vector of float s})
+0:20                      Constant:
+0:20                        1 (const uint)
+0:20                    Constant:
+0:20                      0 (const int)
+0:20                  direct index ( temp highp float)
+0:20                    b2: direct index for structure ( uniform highp 2-component vector of float)
+0:20                      'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b2,  uniform highp 2-component vector of float b1,  uniform highp 4-component vector of float c2,  uniform highp 4-component vector of float d,  uniform 4-element array of highp 4-component vector of float s})
+0:20                      Constant:
+0:20                        1 (const uint)
+0:20                    Constant:
+0:20                      1 (const int)
+0:20              c2: direct index for structure ( uniform highp 4-component vector of float)
+0:20                'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b2,  uniform highp 2-component vector of float b1,  uniform highp 4-component vector of float c2,  uniform highp 4-component vector of float d,  uniform 4-element array of highp 4-component vector of float s})
+0:20                Constant:
+0:20                  3 (const uint)
+0:20            d: direct index for structure ( uniform highp 4-component vector of float)
+0:20              'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b2,  uniform highp 2-component vector of float b1,  uniform highp 4-component vector of float c2,  uniform highp 4-component vector of float d,  uniform 4-element array of highp 4-component vector of float s})
+0:20              Constant:
+0:20                4 (const uint)
+0:22      Branch: Return with expression
+0:22        vector-scale ( temp highp 4-component vector of float)
+0:22          Convert uint to float ( temp highp float)
+0:22            'j' ( temp highp uint)
+0:22          'v' ( temp highp 4-component vector of float)
+0:25  Function Definition: main( ( global void)
+0:25    Function Parameters: 
+0:27    Sequence
+0:27      Sequence
+0:27        move second child to first child ( temp highp 4-component vector of float)
+0:27          'v' ( temp highp 4-component vector of float)
+0:27          Function Call: foo( ( global highp 4-component vector of float)
+0:28      move second child to first child ( temp highp 4-component vector of float)
+0:28        'v' ( temp highp 4-component vector of float)
+0:28        add ( temp highp 4-component vector of float)
+0:28          'v' ( temp highp 4-component vector of float)
+0:28          indirect index ( temp highp 4-component vector of float)
+0:28            s: direct index for structure ( uniform 4-element array of highp 4-component vector of float)
+0:28              'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b2,  uniform highp 2-component vector of float b1,  uniform highp 4-component vector of float c2,  uniform highp 4-component vector of float d,  uniform 4-element array of highp 4-component vector of float s})
+0:28              Constant:
+0:28                5 (const uint)
+0:28            'gl_VertexID' ( in int VertexIndex)
+0:29      move second child to first child ( temp highp float)
+0:29        direct index ( temp highp float)
+0:29          'v' ( temp highp 4-component vector of float)
+0:29          Constant:
+0:29            0 (const int)
+0:29        subtract ( temp highp float)
+0:29          direct index ( temp highp float)
+0:29            'v' ( temp highp 4-component vector of float)
+0:29            Constant:
+0:29              0 (const int)
+0:29          Convert int to float ( temp highp float)
+0:29            'gl_InstanceID' ( in highp int InstanceIndex)
+0:30      move second child to first child ( temp highp 4-component vector of float)
+0:30        'io' (layout( location=0) smooth out highp 4-component vector of float)
+0:30        'v' ( temp highp 4-component vector of float)
+0:?   Linker Objects
+0:?     'io' (layout( location=0) smooth out highp 4-component vector of float)
+0:?     'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b2,  uniform highp 2-component vector of float b1,  uniform highp 4-component vector of float c2,  uniform highp 4-component vector of float d,  uniform 4-element array of highp 4-component vector of float s})
+0:?     'anon@1' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter3,  coherent volatile buffer highp uint counter2})
+0:?     'gl_VertexID' ( in int VertexIndex)
+0:?     'gl_InstanceID' ( in int InstanceIndex)
+
+vk.relaxed.stagelink.frag
+Shader version: 460
+gl_FragCoord origin is upper left
+0:? Sequence
+0:19  Function Definition: foo( ( global highp 4-component vector of float)
+0:19    Function Parameters: 
+0:20    Sequence
+0:20      Sequence
+0:20        move second child to first child ( temp highp uint)
+0:20          'j' ( temp highp uint)
+0:20          add ( temp highp uint)
+0:20            AtomicAdd ( global highp uint)
+0:20              counter1: direct index for structure ( coherent volatile buffer highp uint)
+0:20                'anon@1' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:20                Constant:
+0:20                  0 (const uint)
+0:20              Constant:
+0:20                1 (const uint)
+0:20            subtract ( temp highp uint)
+0:20              AtomicAdd ( global highp uint)
+0:20                counter2: direct index for structure ( coherent volatile buffer highp uint)
+0:20                  'anon@1' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:20                  Constant:
+0:20                    1 (const uint)
+0:20                Constant:
+0:20                  4294967295 (const uint)
+0:20              Constant:
+0:20                1 (const uint)
+0:21      Sequence
+0:21        move second child to first child ( temp highp 4-component vector of float)
+0:21          'v' ( temp highp 4-component vector of float)
+0:21          add ( temp highp 4-component vector of float)
+0:21            add ( temp highp 4-component vector of float)
+0:21              add ( temp highp 4-component vector of float)
+0:21                a: direct index for structure ( uniform highp 4-component vector of float)
+0:21                  'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d})
+0:21                  Constant:
+0:21                    0 (const uint)
+0:21                Construct vec4 ( temp highp 4-component vector of float)
+0:21                  direct index ( temp highp float)
+0:21                    b1: direct index for structure ( uniform highp 2-component vector of float)
+0:21                      'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d})
+0:21                      Constant:
+0:21                        1 (const uint)
+0:21                    Constant:
+0:21                      0 (const int)
+0:21                  direct index ( temp highp float)
+0:21                    b1: direct index for structure ( uniform highp 2-component vector of float)
+0:21                      'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d})
+0:21                      Constant:
+0:21                        1 (const uint)
+0:21                    Constant:
+0:21                      1 (const int)
+0:21                  direct index ( temp highp float)
+0:21                    b2: direct index for structure ( uniform highp 2-component vector of float)
+0:21                      'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d})
+0:21                      Constant:
+0:21                        2 (const uint)
+0:21                    Constant:
+0:21                      0 (const int)
+0:21                  direct index ( temp highp float)
+0:21                    b2: direct index for structure ( uniform highp 2-component vector of float)
+0:21                      'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d})
+0:21                      Constant:
+0:21                        2 (const uint)
+0:21                    Constant:
+0:21                      1 (const int)
+0:21              c1: direct index for structure ( uniform highp 4-component vector of float)
+0:21                'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d})
+0:21                Constant:
+0:21                  3 (const uint)
+0:21            d: direct index for structure ( uniform highp 4-component vector of float)
+0:21              'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d})
+0:21              Constant:
+0:21                4 (const uint)
+0:23      Branch: Return with expression
+0:23        vector-scale ( temp highp 4-component vector of float)
+0:23          Convert uint to float ( temp highp float)
+0:23            'j' ( temp highp uint)
+0:23          'v' ( temp highp 4-component vector of float)
+0:26  Function Definition: main( ( global void)
+0:26    Function Parameters: 
+0:27    Sequence
+0:27      move second child to first child ( temp highp 4-component vector of float)
+0:27        'o' ( out highp 4-component vector of float)
+0:27        add ( temp highp 4-component vector of float)
+0:27          'io' (layout( location=0) smooth in highp 4-component vector of float)
+0:27          Function Call: foo( ( global highp 4-component vector of float)
+0:?   Linker Objects
+0:?     'io' (layout( location=0) smooth in highp 4-component vector of float)
+0:?     'o' ( out highp 4-component vector of float)
+0:?     'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d})
+0:?     'anon@1' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+
+
+Linked vertex stage:
+
+
+Linked fragment stage:
+
+
+Shader version: 460
+0:? Sequence
+0:18  Function Definition: foo( ( global highp 4-component vector of float)
+0:18    Function Parameters: 
+0:19    Sequence
+0:19      Sequence
+0:19        move second child to first child ( temp highp uint)
+0:19          'j' ( temp highp uint)
+0:19          add ( temp highp uint)
+0:19            AtomicAdd ( global highp uint)
+0:19              counter2: direct index for structure ( coherent volatile buffer highp uint)
+0:19                'anon@1' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter3,  coherent volatile buffer highp uint counter2})
+0:19                Constant:
+0:19                  1 (const uint)
+0:19              Constant:
+0:19                1 (const uint)
+0:19            subtract ( temp highp uint)
+0:19              AtomicAdd ( global highp uint)
+0:19                counter3: direct index for structure ( coherent volatile buffer highp uint)
+0:19                  'anon@1' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter3,  coherent volatile buffer highp uint counter2})
+0:19                  Constant:
+0:19                    0 (const uint)
+0:19                Constant:
+0:19                  4294967295 (const uint)
+0:19              Constant:
+0:19                1 (const uint)
+0:20      Sequence
+0:20        move second child to first child ( temp highp 4-component vector of float)
+0:20          'v' ( temp highp 4-component vector of float)
+0:20          add ( temp highp 4-component vector of float)
+0:20            add ( temp highp 4-component vector of float)
+0:20              add ( temp highp 4-component vector of float)
+0:20                a: direct index for structure ( uniform highp 4-component vector of float)
+0:20                  'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b2,  uniform highp 2-component vector of float b1,  uniform highp 4-component vector of float c2,  uniform highp 4-component vector of float d,  uniform 4-element array of highp 4-component vector of float s})
+0:20                  Constant:
+0:20                    0 (const uint)
+0:20                Construct vec4 ( temp highp 4-component vector of float)
+0:20                  direct index ( temp highp float)
+0:20                    b1: direct index for structure ( uniform highp 2-component vector of float)
+0:20                      'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b2,  uniform highp 2-component vector of float b1,  uniform highp 4-component vector of float c2,  uniform highp 4-component vector of float d,  uniform 4-element array of highp 4-component vector of float s})
+0:20                      Constant:
+0:20                        2 (const uint)
+0:20                    Constant:
+0:20                      0 (const int)
+0:20                  direct index ( temp highp float)
+0:20                    b1: direct index for structure ( uniform highp 2-component vector of float)
+0:20                      'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b2,  uniform highp 2-component vector of float b1,  uniform highp 4-component vector of float c2,  uniform highp 4-component vector of float d,  uniform 4-element array of highp 4-component vector of float s})
+0:20                      Constant:
+0:20                        2 (const uint)
+0:20                    Constant:
+0:20                      1 (const int)
+0:20                  direct index ( temp highp float)
+0:20                    b2: direct index for structure ( uniform highp 2-component vector of float)
+0:20                      'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b2,  uniform highp 2-component vector of float b1,  uniform highp 4-component vector of float c2,  uniform highp 4-component vector of float d,  uniform 4-element array of highp 4-component vector of float s})
+0:20                      Constant:
+0:20                        1 (const uint)
+0:20                    Constant:
+0:20                      0 (const int)
+0:20                  direct index ( temp highp float)
+0:20                    b2: direct index for structure ( uniform highp 2-component vector of float)
+0:20                      'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b2,  uniform highp 2-component vector of float b1,  uniform highp 4-component vector of float c2,  uniform highp 4-component vector of float d,  uniform 4-element array of highp 4-component vector of float s})
+0:20                      Constant:
+0:20                        1 (const uint)
+0:20                    Constant:
+0:20                      1 (const int)
+0:20              c2: direct index for structure ( uniform highp 4-component vector of float)
+0:20                'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b2,  uniform highp 2-component vector of float b1,  uniform highp 4-component vector of float c2,  uniform highp 4-component vector of float d,  uniform 4-element array of highp 4-component vector of float s})
+0:20                Constant:
+0:20                  3 (const uint)
+0:20            d: direct index for structure ( uniform highp 4-component vector of float)
+0:20              'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b2,  uniform highp 2-component vector of float b1,  uniform highp 4-component vector of float c2,  uniform highp 4-component vector of float d,  uniform 4-element array of highp 4-component vector of float s})
+0:20              Constant:
+0:20                4 (const uint)
+0:22      Branch: Return with expression
+0:22        vector-scale ( temp highp 4-component vector of float)
+0:22          Convert uint to float ( temp highp float)
+0:22            'j' ( temp highp uint)
+0:22          'v' ( temp highp 4-component vector of float)
+0:25  Function Definition: main( ( global void)
+0:25    Function Parameters: 
+0:27    Sequence
+0:27      Sequence
+0:27        move second child to first child ( temp highp 4-component vector of float)
+0:27          'v' ( temp highp 4-component vector of float)
+0:27          Function Call: foo( ( global highp 4-component vector of float)
+0:28      move second child to first child ( temp highp 4-component vector of float)
+0:28        'v' ( temp highp 4-component vector of float)
+0:28        add ( temp highp 4-component vector of float)
+0:28          'v' ( temp highp 4-component vector of float)
+0:28          indirect index ( temp highp 4-component vector of float)
+0:28            s: direct index for structure ( uniform 4-element array of highp 4-component vector of float)
+0:28              'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b2,  uniform highp 2-component vector of float b1,  uniform highp 4-component vector of float c2,  uniform highp 4-component vector of float d,  uniform 4-element array of highp 4-component vector of float s})
+0:28              Constant:
+0:28                5 (const uint)
+0:28            'gl_VertexID' ( in int VertexIndex)
+0:29      move second child to first child ( temp highp float)
+0:29        direct index ( temp highp float)
+0:29          'v' ( temp highp 4-component vector of float)
+0:29          Constant:
+0:29            0 (const int)
+0:29        subtract ( temp highp float)
+0:29          direct index ( temp highp float)
+0:29            'v' ( temp highp 4-component vector of float)
+0:29            Constant:
+0:29              0 (const int)
+0:29          Convert int to float ( temp highp float)
+0:29            'gl_InstanceID' ( in highp int InstanceIndex)
+0:30      move second child to first child ( temp highp 4-component vector of float)
+0:30        'io' (layout( location=0) smooth out highp 4-component vector of float)
+0:30        'v' ( temp highp 4-component vector of float)
+0:?   Linker Objects
+0:?     'io' (layout( location=0) smooth out highp 4-component vector of float)
+0:?     'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b2,  uniform highp 2-component vector of float b1,  uniform highp 4-component vector of float c2,  uniform highp 4-component vector of float d,  uniform 4-element array of highp 4-component vector of float s})
+0:?     'anon@1' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter3,  coherent volatile buffer highp uint counter2})
+0:?     'gl_VertexID' ( in int VertexIndex)
+0:?     'gl_InstanceID' ( in int InstanceIndex)
+Shader version: 460
+gl_FragCoord origin is upper left
+0:? Sequence
+0:19  Function Definition: foo( ( global highp 4-component vector of float)
+0:19    Function Parameters: 
+0:20    Sequence
+0:20      Sequence
+0:20        move second child to first child ( temp highp uint)
+0:20          'j' ( temp highp uint)
+0:20          add ( temp highp uint)
+0:20            AtomicAdd ( global highp uint)
+0:20              counter1: direct index for structure ( coherent volatile buffer highp uint)
+0:20                'anon@1' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:20                Constant:
+0:20                  0 (const uint)
+0:20              Constant:
+0:20                1 (const uint)
+0:20            subtract ( temp highp uint)
+0:20              AtomicAdd ( global highp uint)
+0:20                counter2: direct index for structure ( coherent volatile buffer highp uint)
+0:20                  'anon@1' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+0:20                  Constant:
+0:20                    1 (const uint)
+0:20                Constant:
+0:20                  4294967295 (const uint)
+0:20              Constant:
+0:20                1 (const uint)
+0:21      Sequence
+0:21        move second child to first child ( temp highp 4-component vector of float)
+0:21          'v' ( temp highp 4-component vector of float)
+0:21          add ( temp highp 4-component vector of float)
+0:21            add ( temp highp 4-component vector of float)
+0:21              add ( temp highp 4-component vector of float)
+0:21                a: direct index for structure ( uniform highp 4-component vector of float)
+0:21                  'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d})
+0:21                  Constant:
+0:21                    0 (const uint)
+0:21                Construct vec4 ( temp highp 4-component vector of float)
+0:21                  direct index ( temp highp float)
+0:21                    b1: direct index for structure ( uniform highp 2-component vector of float)
+0:21                      'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d})
+0:21                      Constant:
+0:21                        1 (const uint)
+0:21                    Constant:
+0:21                      0 (const int)
+0:21                  direct index ( temp highp float)
+0:21                    b1: direct index for structure ( uniform highp 2-component vector of float)
+0:21                      'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d})
+0:21                      Constant:
+0:21                        1 (const uint)
+0:21                    Constant:
+0:21                      1 (const int)
+0:21                  direct index ( temp highp float)
+0:21                    b2: direct index for structure ( uniform highp 2-component vector of float)
+0:21                      'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d})
+0:21                      Constant:
+0:21                        2 (const uint)
+0:21                    Constant:
+0:21                      0 (const int)
+0:21                  direct index ( temp highp float)
+0:21                    b2: direct index for structure ( uniform highp 2-component vector of float)
+0:21                      'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d})
+0:21                      Constant:
+0:21                        2 (const uint)
+0:21                    Constant:
+0:21                      1 (const int)
+0:21              c1: direct index for structure ( uniform highp 4-component vector of float)
+0:21                'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d})
+0:21                Constant:
+0:21                  3 (const uint)
+0:21            d: direct index for structure ( uniform highp 4-component vector of float)
+0:21              'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d})
+0:21              Constant:
+0:21                4 (const uint)
+0:23      Branch: Return with expression
+0:23        vector-scale ( temp highp 4-component vector of float)
+0:23          Convert uint to float ( temp highp float)
+0:23            'j' ( temp highp uint)
+0:23          'v' ( temp highp 4-component vector of float)
+0:26  Function Definition: main( ( global void)
+0:26    Function Parameters: 
+0:27    Sequence
+0:27      move second child to first child ( temp highp 4-component vector of float)
+0:27        'o' ( out highp 4-component vector of float)
+0:27        add ( temp highp 4-component vector of float)
+0:27          'io' (layout( location=0) smooth in highp 4-component vector of float)
+0:27          Function Call: foo( ( global highp 4-component vector of float)
+0:?   Linker Objects
+0:?     'io' (layout( location=0) smooth in highp 4-component vector of float)
+0:?     'o' ( out highp 4-component vector of float)
+0:?     'anon@0' (layout( column_major std140) uniform block{ uniform highp 4-component vector of float a,  uniform highp 2-component vector of float b1,  uniform highp 2-component vector of float b2,  uniform highp 4-component vector of float c1,  uniform highp 4-component vector of float d})
+0:?     'anon@1' (layout( column_major std430) buffer block{ coherent volatile buffer highp uint counter1,  coherent volatile buffer highp uint counter2})
+
+// Module Version 10000
+// Generated by (magic number): 8000a
+// Id's are bound by 88
+
+                              Capability Shader
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Vertex 4  "main" 72 80 86
+                              Source GLSL 460
+                              Name 4  "main"
+                              Name 9  "foo("
+                              Name 13  "j"
+                              Name 14  "gl_AtomicCounterBlock_0"
+                              MemberName 14(gl_AtomicCounterBlock_0) 0  "counter3"
+                              MemberName 14(gl_AtomicCounterBlock_0) 1  "counter2"
+                              MemberName 14(gl_AtomicCounterBlock_0) 2  "counter1"
+                              Name 16  ""
+                              Name 31  "v"
+                              Name 35  "gl_DefaultUniformBlock"
+                              MemberName 35(gl_DefaultUniformBlock) 0  "a"
+                              MemberName 35(gl_DefaultUniformBlock) 1  "b2"
+                              MemberName 35(gl_DefaultUniformBlock) 2  "b1"
+                              MemberName 35(gl_DefaultUniformBlock) 3  "c2"
+                              MemberName 35(gl_DefaultUniformBlock) 4  "d"
+                              MemberName 35(gl_DefaultUniformBlock) 5  "s"
+                              MemberName 35(gl_DefaultUniformBlock) 6  "c1"
+                              Name 37  ""
+                              Name 67  "v"
+                              Name 72  "gl_VertexID"
+                              Name 80  "gl_InstanceID"
+                              Name 86  "io"
+                              MemberDecorate 14(gl_AtomicCounterBlock_0) 0 Coherent
+                              MemberDecorate 14(gl_AtomicCounterBlock_0) 0 Volatile
+                              MemberDecorate 14(gl_AtomicCounterBlock_0) 0 Coherent
+                              MemberDecorate 14(gl_AtomicCounterBlock_0) 0 Offset 0
+                              MemberDecorate 14(gl_AtomicCounterBlock_0) 1 Coherent
+                              MemberDecorate 14(gl_AtomicCounterBlock_0) 1 Volatile
+                              MemberDecorate 14(gl_AtomicCounterBlock_0) 1 Coherent
+                              MemberDecorate 14(gl_AtomicCounterBlock_0) 1 Offset 4
+                              MemberDecorate 14(gl_AtomicCounterBlock_0) 2 Coherent
+                              MemberDecorate 14(gl_AtomicCounterBlock_0) 2 Volatile
+                              MemberDecorate 14(gl_AtomicCounterBlock_0) 2 Coherent
+                              MemberDecorate 14(gl_AtomicCounterBlock_0) 2 Offset 8
+                              Decorate 14(gl_AtomicCounterBlock_0) BufferBlock
+                              Decorate 16 DescriptorSet 0
+                              Decorate 16 Binding 1
+                              Decorate 34 ArrayStride 16
+                              MemberDecorate 35(gl_DefaultUniformBlock) 0 Offset 0
+                              MemberDecorate 35(gl_DefaultUniformBlock) 1 Offset 16
+                              MemberDecorate 35(gl_DefaultUniformBlock) 2 Offset 24
+                              MemberDecorate 35(gl_DefaultUniformBlock) 3 Offset 32
+                              MemberDecorate 35(gl_DefaultUniformBlock) 4 Offset 48
+                              MemberDecorate 35(gl_DefaultUniformBlock) 5 Offset 64
+                              MemberDecorate 35(gl_DefaultUniformBlock) 6 Offset 128
+                              Decorate 35(gl_DefaultUniformBlock) Block
+                              Decorate 37 DescriptorSet 0
+                              Decorate 37 Binding 0
+                              Decorate 72(gl_VertexID) BuiltIn VertexIndex
+                              Decorate 80(gl_InstanceID) BuiltIn InstanceIndex
+                              Decorate 86(io) Location 0
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypeVector 6(float) 4
+               8:             TypeFunction 7(fvec4)
+              11:             TypeInt 32 0
+              12:             TypePointer Function 11(int)
+14(gl_AtomicCounterBlock_0):             TypeStruct 11(int) 11(int) 11(int)
+              15:             TypePointer Uniform 14(gl_AtomicCounterBlock_0)
+              16:     15(ptr) Variable Uniform
+              17:             TypeInt 32 1
+              18:     17(int) Constant 1
+              19:             TypePointer Uniform 11(int)
+              21:     11(int) Constant 1
+              22:     11(int) Constant 0
+              24:     17(int) Constant 0
+              26:     11(int) Constant 4294967295
+              30:             TypePointer Function 7(fvec4)
+              32:             TypeVector 6(float) 2
+              33:     11(int) Constant 4
+              34:             TypeArray 7(fvec4) 33
+35(gl_DefaultUniformBlock):             TypeStruct 7(fvec4) 32(fvec2) 32(fvec2) 7(fvec4) 7(fvec4) 34 7(fvec4)
+              36:             TypePointer Uniform 35(gl_DefaultUniformBlock)
+              37:     36(ptr) Variable Uniform
+              38:             TypePointer Uniform 7(fvec4)
+              41:     17(int) Constant 2
+              42:             TypePointer Uniform 6(float)
+              53:     17(int) Constant 3
+              57:     17(int) Constant 4
+              70:     17(int) Constant 5
+              71:             TypePointer Input 17(int)
+ 72(gl_VertexID):     71(ptr) Variable Input
+              77:             TypePointer Function 6(float)
+80(gl_InstanceID):     71(ptr) Variable Input
+              85:             TypePointer Output 7(fvec4)
+          86(io):     85(ptr) Variable Output
+         4(main):           2 Function None 3
+               5:             Label
+           67(v):     30(ptr) Variable Function
+              68:    7(fvec4) FunctionCall 9(foo()
+                              Store 67(v) 68
+              69:    7(fvec4) Load 67(v)
+              73:     17(int) Load 72(gl_VertexID)
+              74:     38(ptr) AccessChain 37 70 73
+              75:    7(fvec4) Load 74
+              76:    7(fvec4) FAdd 69 75
+                              Store 67(v) 76
+              78:     77(ptr) AccessChain 67(v) 22
+              79:    6(float) Load 78
+              81:     17(int) Load 80(gl_InstanceID)
+              82:    6(float) ConvertSToF 81
+              83:    6(float) FSub 79 82
+              84:     77(ptr) AccessChain 67(v) 22
+                              Store 84 83
+              87:    7(fvec4) Load 67(v)
+                              Store 86(io) 87
+                              Return
+                              FunctionEnd
+         9(foo():    7(fvec4) Function None 8
+              10:             Label
+           13(j):     12(ptr) Variable Function
+           31(v):     30(ptr) Variable Function
+              20:     19(ptr) AccessChain 16 18
+              23:     11(int) AtomicIAdd 20 21 22 21
+              25:     19(ptr) AccessChain 16 24
+              27:     11(int) AtomicIAdd 25 21 22 26
+              28:     11(int) ISub 27 21
+              29:     11(int) IAdd 23 28
+                              Store 13(j) 29
+              39:     38(ptr) AccessChain 37 24
+              40:    7(fvec4) Load 39
+              43:     42(ptr) AccessChain 37 41 22
+              44:    6(float) Load 43
+              45:     42(ptr) AccessChain 37 41 21
+              46:    6(float) Load 45
+              47:     42(ptr) AccessChain 37 18 22
+              48:    6(float) Load 47
+              49:     42(ptr) AccessChain 37 18 21
+              50:    6(float) Load 49
+              51:    7(fvec4) CompositeConstruct 44 46 48 50
+              52:    7(fvec4) FAdd 40 51
+              54:     38(ptr) AccessChain 37 53
+              55:    7(fvec4) Load 54
+              56:    7(fvec4) FAdd 52 55
+              58:     38(ptr) AccessChain 37 57
+              59:    7(fvec4) Load 58
+              60:    7(fvec4) FAdd 56 59
+                              Store 31(v) 60
+              61:     11(int) Load 13(j)
+              62:    6(float) ConvertUToF 61
+              63:    7(fvec4) Load 31(v)
+              64:    7(fvec4) VectorTimesScalar 63 62
+                              ReturnValue 64
+                              FunctionEnd
+// Module Version 10000
+// Generated by (magic number): 8000a
+// Id's are bound by 74
+
+                              Capability Shader
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Fragment 4  "main" 68 70
+                              ExecutionMode 4 OriginUpperLeft
+                              Source GLSL 460
+                              Name 4  "main"
+                              Name 9  "foo("
+                              Name 13  "j"
+                              Name 14  "gl_AtomicCounterBlock_0"
+                              MemberName 14(gl_AtomicCounterBlock_0) 0  "counter3"
+                              MemberName 14(gl_AtomicCounterBlock_0) 1  "counter2"
+                              MemberName 14(gl_AtomicCounterBlock_0) 2  "counter1"
+                              Name 16  ""
+                              Name 31  "v"
+                              Name 35  "gl_DefaultUniformBlock"
+                              MemberName 35(gl_DefaultUniformBlock) 0  "a"
+                              MemberName 35(gl_DefaultUniformBlock) 1  "b2"
+                              MemberName 35(gl_DefaultUniformBlock) 2  "b1"
+                              MemberName 35(gl_DefaultUniformBlock) 3  "c2"
+                              MemberName 35(gl_DefaultUniformBlock) 4  "d"
+                              MemberName 35(gl_DefaultUniformBlock) 5  "s"
+                              MemberName 35(gl_DefaultUniformBlock) 6  "c1"
+                              Name 37  ""
+                              Name 68  "o"
+                              Name 70  "io"
+                              MemberDecorate 14(gl_AtomicCounterBlock_0) 0 Coherent
+                              MemberDecorate 14(gl_AtomicCounterBlock_0) 0 Volatile
+                              MemberDecorate 14(gl_AtomicCounterBlock_0) 0 Coherent
+                              MemberDecorate 14(gl_AtomicCounterBlock_0) 0 Offset 0
+                              MemberDecorate 14(gl_AtomicCounterBlock_0) 1 Coherent
+                              MemberDecorate 14(gl_AtomicCounterBlock_0) 1 Volatile
+                              MemberDecorate 14(gl_AtomicCounterBlock_0) 1 Coherent
+                              MemberDecorate 14(gl_AtomicCounterBlock_0) 1 Offset 4
+                              MemberDecorate 14(gl_AtomicCounterBlock_0) 2 Coherent
+                              MemberDecorate 14(gl_AtomicCounterBlock_0) 2 Volatile
+                              MemberDecorate 14(gl_AtomicCounterBlock_0) 2 Coherent
+                              MemberDecorate 14(gl_AtomicCounterBlock_0) 2 Offset 8
+                              Decorate 14(gl_AtomicCounterBlock_0) BufferBlock
+                              Decorate 16 DescriptorSet 0
+                              Decorate 16 Binding 1
+                              Decorate 34 ArrayStride 16
+                              MemberDecorate 35(gl_DefaultUniformBlock) 0 Offset 0
+                              MemberDecorate 35(gl_DefaultUniformBlock) 1 Offset 16
+                              MemberDecorate 35(gl_DefaultUniformBlock) 2 Offset 24
+                              MemberDecorate 35(gl_DefaultUniformBlock) 3 Offset 32
+                              MemberDecorate 35(gl_DefaultUniformBlock) 4 Offset 48
+                              MemberDecorate 35(gl_DefaultUniformBlock) 5 Offset 64
+                              MemberDecorate 35(gl_DefaultUniformBlock) 6 Offset 128
+                              Decorate 35(gl_DefaultUniformBlock) Block
+                              Decorate 37 DescriptorSet 0
+                              Decorate 37 Binding 0
+                              Decorate 68(o) Location 0
+                              Decorate 70(io) Location 0
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypeVector 6(float) 4
+               8:             TypeFunction 7(fvec4)
+              11:             TypeInt 32 0
+              12:             TypePointer Function 11(int)
+14(gl_AtomicCounterBlock_0):             TypeStruct 11(int) 11(int) 11(int)
+              15:             TypePointer Uniform 14(gl_AtomicCounterBlock_0)
+              16:     15(ptr) Variable Uniform
+              17:             TypeInt 32 1
+              18:     17(int) Constant 2
+              19:             TypePointer Uniform 11(int)
+              21:     11(int) Constant 1
+              22:     11(int) Constant 0
+              24:     17(int) Constant 1
+              26:     11(int) Constant 4294967295
+              30:             TypePointer Function 7(fvec4)
+              32:             TypeVector 6(float) 2
+              33:     11(int) Constant 4
+              34:             TypeArray 7(fvec4) 33
+35(gl_DefaultUniformBlock):             TypeStruct 7(fvec4) 32(fvec2) 32(fvec2) 7(fvec4) 7(fvec4) 34 7(fvec4)
+              36:             TypePointer Uniform 35(gl_DefaultUniformBlock)
+              37:     36(ptr) Variable Uniform
+              38:     17(int) Constant 0
+              39:             TypePointer Uniform 7(fvec4)
+              42:             TypePointer Uniform 6(float)
+              53:     17(int) Constant 6
+              57:     17(int) Constant 4
+              67:             TypePointer Output 7(fvec4)
+           68(o):     67(ptr) Variable Output
+              69:             TypePointer Input 7(fvec4)
+          70(io):     69(ptr) Variable Input
+         4(main):           2 Function None 3
+               5:             Label
+              71:    7(fvec4) Load 70(io)
+              72:    7(fvec4) FunctionCall 9(foo()
+              73:    7(fvec4) FAdd 71 72
+                              Store 68(o) 73
+                              Return
+                              FunctionEnd
+         9(foo():    7(fvec4) Function None 8
+              10:             Label
+           13(j):     12(ptr) Variable Function
+           31(v):     30(ptr) Variable Function
+              20:     19(ptr) AccessChain 16 18
+              23:     11(int) AtomicIAdd 20 21 22 21
+              25:     19(ptr) AccessChain 16 24
+              27:     11(int) AtomicIAdd 25 21 22 26
+              28:     11(int) ISub 27 21
+              29:     11(int) IAdd 23 28
+                              Store 13(j) 29
+              40:     39(ptr) AccessChain 37 38
+              41:    7(fvec4) Load 40
+              43:     42(ptr) AccessChain 37 18 22
+              44:    6(float) Load 43
+              45:     42(ptr) AccessChain 37 18 21
+              46:    6(float) Load 45
+              47:     42(ptr) AccessChain 37 24 22
+              48:    6(float) Load 47
+              49:     42(ptr) AccessChain 37 24 21
+              50:    6(float) Load 49
+              51:    7(fvec4) CompositeConstruct 44 46 48 50
+              52:    7(fvec4) FAdd 41 51
+              54:     39(ptr) AccessChain 37 53
+              55:    7(fvec4) Load 54
+              56:    7(fvec4) FAdd 52 55
+              58:     39(ptr) AccessChain 37 57
+              59:    7(fvec4) Load 58
+              60:    7(fvec4) FAdd 56 59
+                              Store 31(v) 60
+              61:     11(int) Load 13(j)
+              62:    6(float) ConvertUToF 61
+              63:    7(fvec4) Load 31(v)
+              64:    7(fvec4) VectorTimesScalar 63 62
+                              ReturnValue 64
+                              FunctionEnd
diff --git a/Test/iomap.crossStage.2.frag b/Test/iomap.crossStage.2.frag
new file mode 100644 (file)
index 0000000..25756a6
--- /dev/null
@@ -0,0 +1,42 @@
+#version 460\r
+\r
+\r
+layout(location = 5) in outBlock {\r
+    vec4 o3;\r
+};\r
+\r
+\r
+in vec4 gfo1;\r
+in vec2 gfo2;\r
+\r
+out vec4 outColor;\r
+\r
+uniform vec2 u1;\r
+uniform vec3 u2;           // initializer present in vertex stage\r
+uniform vec4 u3 = vec4(0); // initializer matches initializer in vertex stage\r
+\r
+uniform mat2 um2 = mat2(4.0);\r
+\r
+layout (location = 0, binding = 0) uniform sampler2D glass;\r
+\r
+uniform crossStageBlock1 {\r
+    uniform vec4 a;\r
+    vec4 b;\r
+};\r
+\r
+buffer fragOnlyBlock {\r
+    vec2 fb1;\r
+};\r
+\r
+uniform crossStageBlock2 {\r
+    uniform vec4 a;\r
+    vec2 b;\r
+} blockName2 [2]; // instance name different from vert\r
+\r
+\r
+void main()\r
+{\r
+    vec4 color = gfo1 * u1.rgrg * u2.rgbr * u3.rgba;        // o1 is statically used\r
+    outColor = color;\r
+}\r
+\r
diff --git a/Test/iomap.crossStage.2.geom b/Test/iomap.crossStage.2.geom
new file mode 100644 (file)
index 0000000..91508ab
--- /dev/null
@@ -0,0 +1,39 @@
+#version 460\r
+\r
+layout(points) in;\r
+layout(triangle_strip, max_vertices=3) out;\r
+\r
+in vec4 vgo1[];\r
+in vec2 vgo2[];\r
+\r
+layout(location = 5) in outBlock {\r
+    vec4 o3;\r
+} inBlock[];\r
+\r
+out vec4 gfo1;\r
+out vec2 gfo2;\r
+\r
+layout(location = 5) out outBlock {\r
+    vec4 o3;\r
+} gf_out;\r
+\r
+uniform vec2 u1;\r
+uniform vec3 u2 = vec3(0); // initializer not present in fragment stage\r
+uniform vec4 u3 = vec4(0); // initializer matches initializer in fragment stage\r
+\r
+uniform crossStageBlock2 {\r
+    uniform vec4 a;\r
+    vec2 b;\r
+} blockName1 [2]; // instance name different from frag\r
+\r
+void main()\r
+{\r
+    for (int i = 0; i < 3; i++) {\r
+        gfo1 = vec4(0);\r
+        gfo2 = vec2(0);\r
+        gf_out.o3 = inBlock[i].o3;\r
+        EmitVertex();\r
+    }\r
+    EndPrimitive();\r
+}\r
+\r
diff --git a/Test/iomap.crossStage.2.vert b/Test/iomap.crossStage.2.vert
new file mode 100644 (file)
index 0000000..ebb0d9d
--- /dev/null
@@ -0,0 +1,38 @@
+#version 460\r
+\r
+out vec4 vgo1; // declaration order different than fragment shader\r
+out vec2 vgo2; // declaration order different than fragment shader\r
+\r
+layout(location = 5) out outBlock {\r
+    vec4 o3;\r
+};\r
+\r
+uniform vec2 u1;\r
+uniform vec3 u2 = vec3(0); // initializer not present in fragment stage\r
+uniform vec4 u3 = vec4(0); // initializer matches initializer in fragment stage\r
+\r
+uniform mat2 um2 = mat2(4.0);\r
+\r
+layout (location = 0, binding = 0) uniform sampler2D glass;\r
+\r
+uniform crossStageBlock1 {\r
+    uniform vec4 a;\r
+    vec4 b;\r
+};\r
+\r
+buffer vertOnlyBlock {\r
+    vec2 vb1;\r
+};\r
+\r
+uniform crossStageBlock2 {\r
+    uniform vec4 a;\r
+    vec2 b;\r
+} blockName1 [2]; // instance name different from frag\r
+\r
+void main()\r
+{\r
+    vgo1 = vec4(0);\r
+    vgo2 = vec2(0);\r
+    o3 = vec4(0);\r
+}\r
+\r
diff --git a/Test/iomap.crossStage.frag b/Test/iomap.crossStage.frag
new file mode 100644 (file)
index 0000000..1624703
--- /dev/null
@@ -0,0 +1,41 @@
+#version 460\r
+\r
+\r
+layout(location = 5) in outBlock {\r
+    vec4 o3;\r
+};\r
+\r
+in vec2 o2; // declaration order different than vertex shader\r
+in vec4 o1; // declaration order different than vertex shader\r
+\r
+out vec4 outColor;\r
+\r
+uniform vec2 u1;\r
+uniform vec3 u2;    // initializer present in vertex stage\r
+uniform vec4 u3 = vec4(0); // initializer matches initializer in vertex stage\r
+\r
+uniform mat2 um2 = mat2(4.0);\r
+\r
+layout (location = 0, binding = 0) uniform sampler2D glass;\r
+\r
+uniform crossStageBlock1 {\r
+    uniform vec4 a;\r
+    vec4 b;\r
+};\r
+\r
+buffer fragOnlyBlock {\r
+    vec2 fb1;\r
+};\r
+\r
+uniform crossStageBlock2 {\r
+    uniform vec4 a;\r
+    vec2 b;\r
+} blockName2 [2]; // instance name different from vert\r
+\r
+\r
+void main()\r
+{\r
+    vec4 color = o1 * u1.rgrg * u2.rgbr * u3.rgba;        // o1 is statically used\r
+    outColor = color;\r
+}\r
+\r
diff --git a/Test/iomap.crossStage.vert b/Test/iomap.crossStage.vert
new file mode 100644 (file)
index 0000000..d05874f
--- /dev/null
@@ -0,0 +1,38 @@
+#version 460\r
+\r
+out vec4 o1; // declaration order different than fragment shader\r
+out vec2 o2; // declaration order different than fragment shader\r
+\r
+layout(location = 5) out outBlock {\r
+    vec4 o3;\r
+};\r
+\r
+uniform vec2 u1;\r
+uniform vec3 u2 = vec3(0); // initializer not present in fragment stage\r
+uniform vec4 u3 = vec4(0); // initializer matches initializer in fragment stage\r
+\r
+uniform mat2 um2 = mat2(4.0);\r
+\r
+layout (location = 0, binding = 0) uniform sampler2D glass;\r
+\r
+uniform crossStageBlock1 {\r
+    uniform vec4 a;\r
+    vec4 b;\r
+};\r
+\r
+buffer vertOnlyBlock {\r
+    vec2 vb1;\r
+};\r
+\r
+uniform crossStageBlock2 {\r
+    uniform vec4 a;\r
+    vec2 b;\r
+} blockName1 [2]; // instance name different from frag\r
+\r
+void main()\r
+{\r
+    o1 = vec4(0);\r
+    o2 = vec2(0);\r
+    o3 = vec4(0);\r
+}\r
+\r
diff --git a/Test/iomap.crossStage.vk.frag b/Test/iomap.crossStage.vk.frag
new file mode 100644 (file)
index 0000000..d09e687
--- /dev/null
@@ -0,0 +1,50 @@
+#version 460\r
+\r
+\r
+layout(location = 5) in outBlock {\r
+    vec4 o3;\r
+};\r
+\r
+\r
+in vec4 gfo1;\r
+in vec2 gfo2;\r
+\r
+out vec4 outColor;\r
+\r
+layout (binding = 0) uniform sampler2D glass;\r
+\r
+uniform crossStageBlock1 {\r
+    uniform vec4 a;\r
+    vec4 b;\r
+};\r
+\r
+readonly buffer fragOnlyBlock {\r
+    vec2 fb1;\r
+};\r
+\r
+uniform crossStageBlock2 {\r
+    uniform vec4 a;\r
+    vec2 b;\r
+} blockName2 [2]; // instance name different from vert\r
+\r
+vec2 Bar() {\r
+    return  fb1 + \r
+            blockName2[0].b +\r
+            blockName2[1].b;\r
+}\r
+\r
+vec4 Foo() {\r
+    return  a + \r
+            b + \r
+            blockName2[0].a +\r
+            blockName2[1].a +\r
+            vec4(Bar(), 0.0, 0.0);\r
+}\r
+\r
+void main()\r
+{\r
+    vec4 color = gfo1; // o1 is statically used\r
+    color = color + Foo();\r
+    outColor = color;\r
+}\r
+\r
diff --git a/Test/iomap.crossStage.vk.geom b/Test/iomap.crossStage.vk.geom
new file mode 100644 (file)
index 0000000..b951737
--- /dev/null
@@ -0,0 +1,35 @@
+#version 460\r
+\r
+layout(points) in;\r
+layout(triangle_strip, max_vertices=3) out;\r
+\r
+in vec4 vgo1[];\r
+in vec2 vgo2[];\r
+\r
+layout(location = 5) in outBlock {\r
+    vec4 o3;\r
+} inBlock[];\r
+\r
+out vec4 gfo1;\r
+out vec2 gfo2;\r
+\r
+layout(location = 5) out outBlock {\r
+    vec4 o3;\r
+} gf_out;\r
+\r
+uniform crossStageBlock2 {\r
+    uniform vec4 a;\r
+    vec2 b;\r
+} blockName1 [2]; // instance name different from frag\r
+\r
+void main()\r
+{\r
+    for (int i = 0; i < 3; i++) {\r
+        gfo1 = vec4(0);\r
+        gfo2 = vec2(0);\r
+        gf_out.o3 = inBlock[i].o3;\r
+        EmitVertex();\r
+    }\r
+    EndPrimitive();\r
+}\r
+\r
diff --git a/Test/iomap.crossStage.vk.vert b/Test/iomap.crossStage.vk.vert
new file mode 100644 (file)
index 0000000..e422131
--- /dev/null
@@ -0,0 +1,32 @@
+#version 460\r
+\r
+out vec4 vgo1; // declaration order different than fragment shader\r
+out vec2 vgo2; // declaration order different than fragment shader\r
+\r
+layout(location = 5) out outBlock {\r
+    vec4 o3;\r
+};\r
+\r
+layout (binding = 0) uniform sampler2D glass;\r
+\r
+uniform crossStageBlock1 {\r
+    uniform vec4 a;\r
+    vec4 b;\r
+};\r
+\r
+readonly buffer vertOnlyBlock {\r
+    vec2 vb1;\r
+};\r
+\r
+uniform crossStageBlock2 {\r
+    uniform vec4 a;\r
+    vec2 b;\r
+} blockName1 [2]; // instance name different from frag\r
+\r
+void main()\r
+{\r
+    vgo1 = vec4(0);\r
+    vgo2 = vec2(0);\r
+    o3 = vec4(0);\r
+}\r
+\r
diff --git a/Test/vk.relaxed.errorcheck.frag b/Test/vk.relaxed.errorcheck.frag
new file mode 100644 (file)
index 0000000..b75b50b
--- /dev/null
@@ -0,0 +1,16 @@
+#version 460\r
+\r
+layout (location = 0) in vec4 io;\r
+\r
+out vec4 o;\r
+\r
+// default uniforms will be gathered into a uniform block\r
+uniform vec4 a;     // declared in both stages with different types\r
+\r
+vec4 foo() {\r
+    return a;\r
+}\r
+\r
+void main() {\r
+    o = io + foo();\r
+}
\ No newline at end of file
diff --git a/Test/vk.relaxed.errorcheck.vert b/Test/vk.relaxed.errorcheck.vert
new file mode 100644 (file)
index 0000000..b1bdbbe
--- /dev/null
@@ -0,0 +1,15 @@
+#version 460\r
+\r
+layout (location = 0) out vec4 io;\r
+\r
+// default uniforms will be gathered into a uniform block\r
+// final global block will merge uniforms from all linked files\r
+uniform vec2 a;     // declared in both stages with different type\r
+\r
+vec4 foo() {\r
+    return a.xyxy;\r
+}\r
+\r
+void main() {\r
+    io = foo();\r
+}
\ No newline at end of file
diff --git a/Test/vk.relaxed.frag b/Test/vk.relaxed.frag
new file mode 100644 (file)
index 0000000..d43416e
--- /dev/null
@@ -0,0 +1,74 @@
+#version 460\r
+\r
+out vec4 o;\r
+\r
+// default uniforms will be gathered into a uniform block\r
+uniform vec4 a;\r
+uniform vec2 b = vec2(0, 0);            // initializer will be ignored\r
+layout(location = 0) uniform vec2 c;    // location qualifier will be ignored\r
+uniform vec4 d[10];\r
+uniform struct e {                      \r
+    vec2 x;\r
+    float y;\r
+    uint z;\r
+} structUniform; \r
+\r
+// opaque types will not be grouped into uniform block\r
+uniform sampler2D t1;\r
+\r
+// shared and packed layout qualifier are silently ignored\r
+layout(shared) uniform UniformBlock {\r
+    float j;\r
+    vec4 k;\r
+};\r
+\r
+layout(packed) buffer BufferBlock {\r
+    float j;\r
+    vec4 k;\r
+} bufferInstance;\r
+\r
+// atomic_uint will be converted to uint and gathered in a buffer block\r
+layout(binding = 0) uniform atomic_uint counter1; // offset not used\r
+layout(binding = 0) uniform atomic_uint counter2; // offset not used\r
+layout(binding = 1) uniform atomic_uint counter3; // offset not used\r
+\r
+// atomic counter functions will be converted to equivalent integer atomic operations\r
+uint bar() {\r
+    uint j = 0;\r
+    j = atomicCounterIncrement(counter1);\r
+    j = atomicCounterDecrement(counter1);\r
+    j = atomicCounter(counter1);\r
+\r
+    j = atomicCounterAdd(counter1, 1);\r
+    j = atomicCounterAdd(counter1, -1);\r
+    j = atomicCounterSubtract(counter1, 1);\r
+\r
+    j = atomicCounterMin(counter1, j);\r
+    j = atomicCounterMax(counter1, j);\r
+    j = atomicCounterAnd(counter1, j);\r
+\r
+    j = atomicCounterOr(counter1, j);\r
+    j = atomicCounterXor(counter1, j);\r
+    \r
+    j = atomicCounterExchange(counter1, j);\r
+    j = atomicCounterCompSwap(counter1, 0, j);\r
+\r
+    atomicCounterIncrement(counter2);\r
+    atomicCounterIncrement(counter3);\r
+\r
+    memoryBarrierAtomicCounter();\r
+    \r
+    return j;\r
+}\r
+\r
+vec4 foo() {\r
+    float f = j + bufferInstance.j + structUniform.y + structUniform.z;\r
+    vec2 v2 = b + c + structUniform.x;\r
+    vec4 v4 = a + d[0] + d[1] + d[2] + k + bufferInstance.k + texture(t1, vec2(0, 0));\r
+    return vec4(f) * vec4(v2, 1, 1) * v4;\r
+}\r
+\r
+void main() {\r
+    float j = float(bar());\r
+    o = j * foo();\r
+}
\ No newline at end of file
diff --git a/Test/vk.relaxed.link1.frag b/Test/vk.relaxed.link1.frag
new file mode 100644 (file)
index 0000000..95b609f
--- /dev/null
@@ -0,0 +1,28 @@
+#version 460\r
+\r
+out vec4 o;\r
+\r
+// default uniforms will be gathered into a uniform block\r
+// final global block will merge uniforms from all linked files\r
+uniform vec4 a;     // declared in both stages\r
+uniform vec2 b1;    // declaration order swapped in other stage\r
+uniform vec2 b2;\r
+uniform vec4 c1;    // not delcared in other file\r
+uniform vec4 d;\r
+\r
+// final global buffer will berge buffers from all linked files\r
+layout (binding = 0) uniform atomic_uint counter1;\r
+layout (binding = 0) uniform atomic_uint counter2;\r
+\r
+vec4 foo();\r
+\r
+vec4 bar() {\r
+    uint j = atomicCounterIncrement(counter1) + atomicCounterDecrement(counter2);\r
+    vec4 v = a + vec4(b1.x, b1.y, b2.x, b2.y) + c1 + d;\r
+\r
+    return float(j) * v;\r
+}\r
+\r
+void main() {\r
+    o = foo() + bar();\r
+}
\ No newline at end of file
diff --git a/Test/vk.relaxed.link2.frag b/Test/vk.relaxed.link2.frag
new file mode 100644 (file)
index 0000000..a4f468a
--- /dev/null
@@ -0,0 +1,19 @@
+#version 460\r
+\r
+// default uniforms will be gathered into a uniform block\r
+// final global block will merge uniforms from all linked files\r
+uniform vec4 a;     // declared in both stages\r
+uniform vec2 b2;    // declaration order swapped in other stage\r
+uniform vec2 b1;\r
+uniform vec4 c2;    // not delcared in other file\r
+uniform vec4 d;\r
+\r
+layout (binding = 0) uniform atomic_uint counter3;\r
+layout (binding = 0) uniform atomic_uint counter2;\r
+\r
+vec4 foo() {\r
+    uint j = atomicCounterIncrement(counter2) + atomicCounterDecrement(counter3);\r
+    vec4 v = a + vec4(b1.x, b1.y, b2.x, b2.y) + c2 + d;\r
+\r
+    return float(j) * v;\r
+}
\ No newline at end of file
diff --git a/Test/vk.relaxed.stagelink.frag b/Test/vk.relaxed.stagelink.frag
new file mode 100644 (file)
index 0000000..d1eebba
--- /dev/null
@@ -0,0 +1,28 @@
+#version 460\r
+\r
+layout (location = 0) in vec4 io;\r
+\r
+out vec4 o;\r
+\r
+// default uniforms will be gathered into a uniform block\r
+// final global block will merge uniforms from all linked files\r
+uniform vec4 a;     // declared in both stages\r
+uniform vec2 b1;    // declaration order swapped in other stage\r
+uniform vec2 b2;\r
+uniform vec4 c1;    // not delcared in other file\r
+uniform vec4 d;\r
+\r
+// final global buffer will berge buffers from all linked files\r
+layout (binding = 0) uniform atomic_uint counter1;\r
+layout (binding = 0) uniform atomic_uint counter2;\r
+\r
+vec4 foo() {\r
+    uint j = atomicCounterIncrement(counter1) + atomicCounterDecrement(counter2);\r
+    vec4 v = a + vec4(b1.x, b1.y, b2.x, b2.y) + c1 + d;\r
+\r
+    return float(j) * v;\r
+}\r
+\r
+void main() {\r
+    o = io + foo();\r
+}
\ No newline at end of file
diff --git a/Test/vk.relaxed.stagelink.vert b/Test/vk.relaxed.stagelink.vert
new file mode 100644 (file)
index 0000000..52396ac
--- /dev/null
@@ -0,0 +1,31 @@
+#version 460\r
+\r
+layout (location = 0) out vec4 io;\r
+\r
+// default uniforms will be gathered into a uniform block\r
+// final global block will merge uniforms from all linked files\r
+uniform vec4 a;     // declared in both stages\r
+uniform vec2 b2;    // declaration order swapped in other stage\r
+uniform vec2 b1;\r
+uniform vec4 c2;    // not delcared in other file\r
+uniform vec4 d;\r
+\r
+uniform vec4 s[4];\r
+\r
+layout (binding = 0) uniform atomic_uint counter3;\r
+layout (binding = 0) uniform atomic_uint counter2;\r
+\r
+vec4 foo() {\r
+    uint j = atomicCounterIncrement(counter2) + atomicCounterDecrement(counter3);\r
+    vec4 v = a + vec4(b1.x, b1.y, b2.x, b2.y) + c2 + d;\r
+\r
+    return float(j) * v;\r
+}\r
+\r
+void main() {\r
+\r
+    vec4 v = foo();\r
+    v = v + s[gl_VertexID];\r
+    v.x = v.x - float(gl_InstanceID);\r
+    io = v;\r
+}
\ No newline at end of file
index 603203d..bb6d0bd 100644 (file)
@@ -501,6 +501,7 @@ public:
         noContraction = false;
         nullInit = false;
 #endif
+        defaultBlock = false;
     }
 
     // drop qualifiers that don't belong in a temporary variable
@@ -514,6 +515,7 @@ public:
         specConstant = false;
         nonUniform = false;
         nullInit = false;
+        defaultBlock = false;
         clearLayout();
     }
 
@@ -572,6 +574,7 @@ public:
     bool specConstant : 1;
     bool nonUniform   : 1;
     bool explicitOffset   : 1;
+    bool defaultBlock : 1; // default blocks with matching names have structures merged when linking
 
 #ifdef GLSLANG_WEB
     bool isWriteOnly() const { return false; }
@@ -756,6 +759,46 @@ public:
         }
     }
 
+    TBlockStorageClass getBlockStorage() const {
+        if (storage == EvqUniform && !isPushConstant()) {
+            return EbsUniform;
+        }
+        else if (storage == EvqUniform) {
+            return EbsPushConstant;
+        }
+        else if (storage == EvqBuffer) {
+            return EbsStorageBuffer;
+        }
+        return EbsNone;
+    }
+
+    void setBlockStorage(TBlockStorageClass newBacking) {
+#ifndef GLSLANG_WEB
+        layoutPushConstant = (newBacking == EbsPushConstant);
+#endif
+        switch (newBacking) {
+        case EbsUniform :
+            if (layoutPacking == ElpStd430) {
+                // std430 would not be valid
+                layoutPacking = ElpStd140;
+            }
+            storage = EvqUniform;
+            break;
+        case EbsStorageBuffer : 
+            storage = EvqBuffer;
+            break;
+#ifndef GLSLANG_WEB
+        case EbsPushConstant :
+            storage = EvqUniform;
+            layoutSet = TQualifier::layoutSetEnd;
+            layoutBinding = TQualifier::layoutBindingEnd;
+            break;
+#endif
+        default:
+            break;
+        }
+    }
+
 #ifdef GLSLANG_WEB
     bool isPerView() const { return false; }
     bool isTaskMemory() const { return false; }
@@ -852,6 +895,7 @@ public:
         return hasNonXfbLayout() ||
                hasXfb();
     }
+
     TLayoutMatrix  layoutMatrix  : 3;
     TLayoutPacking layoutPacking : 4;
     int layoutOffset;
index 85edd63..1440c20 100644 (file)
@@ -593,6 +593,7 @@ enum TOperator {
     EOpTime,
 
     EOpAtomicAdd,
+    EOpAtomicSubtract,
     EOpAtomicMin,
     EOpAtomicMax,
     EOpAtomicAnd,
@@ -1135,6 +1136,8 @@ public:
     virtual TBasicType getBasicType() const { return type.getBasicType(); }
     virtual TQualifier& getQualifier() { return type.getQualifier(); }
     virtual const TQualifier& getQualifier() const { return type.getQualifier(); }
+    virtual TArraySizes* getArraySizes() { return type.getArraySizes(); }
+    virtual const TArraySizes* getArraySizes() const { return type.getArraySizes(); }
     virtual void propagatePrecision(TPrecisionQualifier);
     virtual int getVectorSize() const { return type.getVectorSize(); }
     virtual int getMatrixCols() const { return type.getMatrixCols(); }
index c94a8a4..a9e5af4 100644 (file)
@@ -1630,6 +1630,36 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
                 "\n");
         }
     }
+    else if (spvVersion.vulkanRelaxed) {
+        //
+        // Atomic counter functions act as aliases to normal atomic functions.
+        // replace definitions to take 'volatile coherent uint' instead of 'atomic_uint'
+        // and map to equivalent non-counter atomic op
+        //
+        if ((profile != EEsProfile && version >= 300) ||
+            (profile == EEsProfile && version >= 310)) {
+            commonBuiltins.append(
+                "uint atomicCounterIncrement(volatile coherent uint);"
+                "uint atomicCounterDecrement(volatile coherent uint);"
+                "uint atomicCounter(volatile coherent uint);"
+
+                "\n");
+        }
+        if (profile != EEsProfile && version >= 460) {
+            commonBuiltins.append(
+                "uint atomicCounterAdd(volatile coherent uint, uint);"
+                "uint atomicCounterSubtract(volatile coherent uint, uint);"
+                "uint atomicCounterMin(volatile coherent uint, uint);"
+                "uint atomicCounterMax(volatile coherent uint, uint);"
+                "uint atomicCounterAnd(volatile coherent uint, uint);"
+                "uint atomicCounterOr(volatile coherent uint, uint);"
+                "uint atomicCounterXor(volatile coherent uint, uint);"
+                "uint atomicCounterExchange(volatile coherent uint, uint);"
+                "uint atomicCounterCompSwap(volatile coherent uint, uint, uint);"
+
+                "\n");
+        }
+    }
 #endif // !GLSLANG_ANGLE
 
     // Bitfield
@@ -4124,7 +4154,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
     }
 #ifndef GLSLANG_WEB
     if ((profile != EEsProfile && version >= 420) || esBarrier) {
-        if (spvVersion.vulkan == 0) {
+        if (spvVersion.vulkan == 0 || spvVersion.vulkanRelaxed) {
             commonBuiltins.append("void memoryBarrierAtomicCounter();");
         }
         commonBuiltins.append("void memoryBarrierImage();");
@@ -4848,6 +4878,13 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
                 "in int gl_VertexIndex;"
                 "in int gl_InstanceIndex;"
                 );
+
+        if (spvVersion.vulkan > 0 && version >= 140 && spvVersion.vulkanRelaxed)
+            stageBuiltins[EShLangVertex].append(
+                "in int gl_VertexID;"         // declare with 'in' qualifier
+                "in int gl_InstanceID;"
+                );
+
         if (version >= 440) {
             stageBuiltins[EShLangVertex].append(
                 "in int gl_BaseVertexARB;"
@@ -4885,7 +4922,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
                 "mediump float gl_PointSize;" // needs qualifier fixed later
                 );
         } else {
-            if (spvVersion.vulkan == 0)
+            if (spvVersion.vulkan == 0 || spvVersion.vulkanRelaxed)
                 stageBuiltins[EShLangVertex].append(
                     "in highp int gl_VertexID;"      // needs qualifier fixed later
                     "in highp int gl_InstanceID;"    // needs qualifier fixed later
@@ -7436,6 +7473,12 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
             SpecialQualifier("gl_InstanceID", EvqInstanceId, EbvInstanceId, symbolTable);
         }
 
+        if (spvVersion.vulkan > 0 && spvVersion.vulkanRelaxed) {
+            // treat these built-ins as aliases of VertexIndex and InstanceIndex
+            BuiltInVariable("gl_VertexID", EbvVertexIndex, symbolTable);
+            BuiltInVariable("gl_InstanceID", EbvInstanceIndex, symbolTable);
+        }
+
         if (profile != EEsProfile) {
             if (version >= 440) {
                 symbolTable.setVariableExtensions("gl_BaseVertexARB",   1, &E_GL_ARB_shader_draw_parameters);
@@ -8912,6 +8955,14 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
     symbolTable.relateToOperator("memoryBarrierAtomicCounter", EOpMemoryBarrierAtomicCounter);
     symbolTable.relateToOperator("memoryBarrierImage",         EOpMemoryBarrierImage);
 
+    if (spvVersion.vulkanRelaxed) {
+        //
+        // functions signature have been replaced to take uint operations on buffer variables
+        // remap atomic counter functions to atomic operations
+        //
+        symbolTable.relateToOperator("memoryBarrierAtomicCounter", EOpMemoryBarrierBuffer);
+    }
+
     symbolTable.relateToOperator("atomicLoad",     EOpAtomicLoad);
     symbolTable.relateToOperator("atomicStore",    EOpAtomicStore);
 
@@ -8919,6 +8970,20 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
     symbolTable.relateToOperator("atomicCounterDecrement", EOpAtomicCounterDecrement);
     symbolTable.relateToOperator("atomicCounter",          EOpAtomicCounter);
 
+    if (spvVersion.vulkanRelaxed) {
+        //
+        // functions signature have been replaced to take uint operations
+        // remap atomic counter functions to atomic operations
+        //
+        // these atomic counter functions do not match signatures of glsl
+        // atomic functions, so they will be remapped to semantically
+        // equivalent functions in the parser
+        //
+        symbolTable.relateToOperator("atomicCounterIncrement", EOpNull);
+        symbolTable.relateToOperator("atomicCounterDecrement", EOpNull);
+        symbolTable.relateToOperator("atomicCounter", EOpNull);
+    }
+
     symbolTable.relateToOperator("clockARB",     EOpReadClockSubgroupKHR);
     symbolTable.relateToOperator("clock2x32ARB", EOpReadClockSubgroupKHR);
 
@@ -8937,6 +9002,23 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
         symbolTable.relateToOperator("atomicCounterCompSwap", EOpAtomicCounterCompSwap);
     }
 
+    if (spvVersion.vulkanRelaxed) {
+        //
+        // functions signature have been replaced to take 'uint' instead of 'atomic_uint'
+        // remap atomic counter functions to non-counter atomic ops so
+        // functions act as aliases to non-counter atomic ops
+        //
+        symbolTable.relateToOperator("atomicCounterAdd", EOpAtomicAdd);
+        symbolTable.relateToOperator("atomicCounterSubtract", EOpAtomicSubtract);
+        symbolTable.relateToOperator("atomicCounterMin", EOpAtomicMin);
+        symbolTable.relateToOperator("atomicCounterMax", EOpAtomicMax);
+        symbolTable.relateToOperator("atomicCounterAnd", EOpAtomicAnd);
+        symbolTable.relateToOperator("atomicCounterOr", EOpAtomicOr);
+        symbolTable.relateToOperator("atomicCounterXor", EOpAtomicXor);
+        symbolTable.relateToOperator("atomicCounterExchange", EOpAtomicExchange);
+        symbolTable.relateToOperator("atomicCounterCompSwap", EOpAtomicCompSwap);
+    }
+
     symbolTable.relateToOperator("fma",               EOpFma);
     symbolTable.relateToOperator("frexp",             EOpFrexp);
     symbolTable.relateToOperator("ldexp",             EOpLdexp);
index 3efa27a..02cca40 100644 (file)
@@ -601,7 +601,6 @@ void TParseContextBase::parseSwizzleSelector(const TSourceLoc& loc, const TStrin
         selector.push_back(0);
 }
 
-#ifdef ENABLE_HLSL
 //
 // Make the passed-in variable information become a member of the
 // global uniform block.  If this doesn't exist yet, make it.
@@ -646,7 +645,67 @@ void TParseContextBase::growGlobalUniformBlock(const TSourceLoc& loc, TType& mem
 
     ++firstNewMember;
 }
-#endif
+
+void TParseContextBase::growAtomicCounterBlock(int binding, const TSourceLoc& loc, TType& memberType, const TString& memberName, TTypeList* typeList) {
+    // Make the atomic counter block, if not yet made.
+    const auto &at  = atomicCounterBuffers.find(binding);
+    if (at == atomicCounterBuffers.end()) {
+        atomicCounterBuffers.insert({binding, (TVariable*)nullptr });
+        atomicCounterBlockFirstNewMember.insert({binding, 0});
+    }
+
+    TVariable*& atomicCounterBuffer = atomicCounterBuffers[binding];
+    int& bufferNewMember = atomicCounterBlockFirstNewMember[binding];
+
+    if (atomicCounterBuffer == nullptr) {
+        TQualifier blockQualifier;
+        blockQualifier.clear();
+        blockQualifier.storage = EvqBuffer;
+        
+        char charBuffer[512];
+        if (binding != TQualifier::layoutBindingEnd) {
+            snprintf(charBuffer, 512, "%s_%d", getAtomicCounterBlockName(), binding);
+        } else {
+            snprintf(charBuffer, 512, "%s_0", getAtomicCounterBlockName());
+        }
+        
+        TType blockType(new TTypeList, *NewPoolTString(charBuffer), blockQualifier);
+        setUniformBlockDefaults(blockType);
+        blockType.getQualifier().layoutPacking = ElpStd430;
+        atomicCounterBuffer = new TVariable(NewPoolTString(""), blockType, true);
+        // If we arn't auto mapping bindings then set the block to use the same
+        // binding as what the atomic was set to use
+        if (!intermediate.getAutoMapBindings()) {
+            atomicCounterBuffer->getWritableType().getQualifier().layoutBinding = binding;
+        }
+        bufferNewMember = 0;
+
+        atomicCounterBuffer->getWritableType().getQualifier().layoutSet = atomicCounterBlockSet;
+    }
+
+    // Add the requested member as a member to the global block.
+    TType* type = new TType;
+    type->shallowCopy(memberType);
+    type->setFieldName(memberName);
+    if (typeList)
+        type->setStruct(typeList);
+    TTypeLoc typeLoc = {type, loc};
+    atomicCounterBuffer->getType().getWritableStruct()->push_back(typeLoc);
+
+    // Insert into the symbol table.
+    if (bufferNewMember == 0) {
+        // This is the first request; we need a normal symbol table insert
+        if (symbolTable.insert(*atomicCounterBuffer))
+            trackLinkage(*atomicCounterBuffer);
+        else
+            error(loc, "failed to insert the global constant buffer", "buffer", "");
+    } else {
+        // This is a follow-on request; we need to amend the first insert
+        symbolTable.amend(*atomicCounterBuffer, bufferNewMember);
+    }
+
+    ++bufferNewMember;
+}
 
 void TParseContextBase::finish()
 {
index 12d68a3..550fce6 100644 (file)
@@ -225,6 +225,108 @@ void TParseContext::parserError(const char* s)
         error(getCurrentLoc(), "compilation terminated", "", "");
 }
 
+void TParseContext::growGlobalUniformBlock(const TSourceLoc& loc, TType& memberType, const TString& memberName, TTypeList* typeList)
+{
+    bool createBlock = globalUniformBlock == nullptr;
+
+    if (createBlock) {
+        globalUniformBinding = intermediate.getGlobalUniformBinding();
+        globalUniformSet = intermediate.getGlobalUniformSet();
+    }
+
+    // use base class function to create/expand block
+    TParseContextBase::growGlobalUniformBlock(loc, memberType, memberName, typeList);
+
+    if (spvVersion.vulkan > 0 && spvVersion.vulkanRelaxed) {
+        // check for a block storage override
+        TBlockStorageClass storageOverride = intermediate.getBlockStorageOverride(getGlobalUniformBlockName());
+        TQualifier& qualifier = globalUniformBlock->getWritableType().getQualifier();
+        qualifier.defaultBlock = true;
+
+        if (storageOverride != EbsNone) {
+            if (createBlock) {
+                // Remap block storage
+                qualifier.setBlockStorage(storageOverride);
+
+                // check that the change didn't create errors
+                blockQualifierCheck(loc, qualifier, false);
+            }
+
+            // remap meber storage as well
+            memberType.getQualifier().setBlockStorage(storageOverride);
+        }
+    }
+}
+
+void TParseContext::growAtomicCounterBlock(int binding, const TSourceLoc& loc, TType& memberType, const TString& memberName, TTypeList* typeList)
+{
+    bool createBlock = atomicCounterBuffers.find(binding) == atomicCounterBuffers.end();
+
+    if (createBlock) {
+        atomicCounterBlockSet = intermediate.getAtomicCounterBlockSet();
+    }
+
+    // use base class function to create/expand block
+    TParseContextBase::growAtomicCounterBlock(binding, loc, memberType, memberName, typeList);
+    TQualifier& qualifier = atomicCounterBuffers[binding]->getWritableType().getQualifier();
+    qualifier.defaultBlock = true;
+
+    if (spvVersion.vulkan > 0 && spvVersion.vulkanRelaxed) {
+        // check for a Block storage override
+        TBlockStorageClass storageOverride = intermediate.getBlockStorageOverride(getAtomicCounterBlockName());
+
+        if (storageOverride != EbsNone) {
+            if (createBlock) {
+                // Remap block storage
+
+                qualifier.setBlockStorage(storageOverride);
+
+                // check that the change didn't create errors
+                blockQualifierCheck(loc, qualifier, false);
+            }
+
+            // remap meber storage as well
+            memberType.getQualifier().setBlockStorage(storageOverride);
+        }
+    }
+}
+
+const char* TParseContext::getGlobalUniformBlockName() const
+{
+    const char* name = intermediate.getGlobalUniformBlockName();
+    if (std::string(name) == "")
+        return "gl_DefaultUniformBlock";
+    else
+        return name;
+}
+void TParseContext::finalizeGlobalUniformBlockLayout(TVariable&)
+{
+}
+void TParseContext::setUniformBlockDefaults(TType& block) const
+{
+    block.getQualifier().layoutPacking = ElpStd140;
+    block.getQualifier().layoutMatrix = ElmColumnMajor;
+}
+
+
+const char* TParseContext::getAtomicCounterBlockName() const
+{
+    const char* name = intermediate.getAtomicCounterBlockName();
+    if (std::string(name) == "")
+        return "gl_AtomicCounterBlock";
+    else
+        return name;
+}
+void TParseContext::finalizeAtomicCounterBlockLayout(TVariable&)
+{
+}
+
+void TParseContext::setAtomicCounterBlockDefaults(TType& block) const
+{
+    block.getQualifier().layoutPacking = ElpStd430;
+    block.getQualifier().layoutMatrix = ElmRowMajor;
+}
+
 void TParseContext::handlePragma(const TSourceLoc& loc, const TVector<TString>& tokens)
 {
 #ifndef GLSLANG_WEB
@@ -1135,6 +1237,14 @@ TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction
 {
     TIntermTyped* result = nullptr;
 
+    if (spvVersion.vulkan != 0 && spvVersion.vulkanRelaxed) {
+        // allow calls that are invalid in Vulkan Semantics to be invisibily
+        // remapped to equivalent valid functions
+        result = vkRelaxedRemapFunctionCall(loc, function, arguments);
+        if (result)
+            return result;
+    }
+
     if (function->getBuiltInOp() == EOpArrayLength)
         result = handleLengthMethod(loc, function, arguments);
     else if (function->getBuiltInOp() != EOpNull) {
@@ -1727,6 +1837,7 @@ void TParseContext::memorySemanticsCheck(const TSourceLoc& loc, const TFunction&
     // Grab the semantics and storage class semantics from the operands, based on opcode
     switch (callNode.getOp()) {
     case EOpAtomicAdd:
+    case EOpAtomicSubtract:
     case EOpAtomicMin:
     case EOpAtomicMax:
     case EOpAtomicAnd:
@@ -2176,6 +2287,7 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
     }
 
     case EOpAtomicAdd:
+    case EOpAtomicSubtract:
     case EOpAtomicMin:
     case EOpAtomicMax:
     case EOpAtomicAnd:
@@ -3388,7 +3500,7 @@ void TParseContext::transparentOpaqueCheck(const TSourceLoc& loc, const TType& t
 
     if (type.containsNonOpaque()) {
         // Vulkan doesn't allow transparent uniforms outside of blocks
-        if (spvVersion.vulkan > 0)
+        if (spvVersion.vulkan > 0 && !spvVersion.vulkanRelaxed)
             vulkanRemoved(loc, "non-opaque uniforms outside a block");
         // OpenGL wants locations on these (unless they are getting automapped)
         if (spvVersion.openGl > 0 && !type.getQualifier().hasLocation() && !intermediate.getAutoMapLocations())
@@ -5019,14 +5131,22 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
         return;
     }
     if (id == TQualifier::getLayoutPackingString(ElpPacked)) {
-        if (spvVersion.spv != 0)
-            spvRemoved(loc, "packed");
+        if (spvVersion.spv != 0) {
+            if (spvVersion.vulkanRelaxed)
+                return; // silently ignore qualifier
+            else
+                spvRemoved(loc, "packed");
+        }
         publicType.qualifier.layoutPacking = ElpPacked;
         return;
     }
     if (id == TQualifier::getLayoutPackingString(ElpShared)) {
-        if (spvVersion.spv != 0)
-            spvRemoved(loc, "shared");
+        if (spvVersion.spv != 0) {
+            if (spvVersion.vulkanRelaxed)
+                return; // silently ignore qualifier
+            else
+                spvRemoved(loc, "shared");
+        }
         publicType.qualifier.layoutPacking = ElpShared;
         return;
     }
@@ -5928,7 +6048,7 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
                 error(loc, "sampler binding not less than gl_MaxCombinedTextureImageUnits", "binding", type.isArray() ? "(using array)" : "");
 #endif
         }
-        if (type.isAtomic()) {
+        if (type.isAtomic() && !spvVersion.vulkanRelaxed) {
             if (qualifier.layoutBinding >= (unsigned int)resources.maxAtomicCounterBindings) {
                 error(loc, "atomic_uint binding is too large; see gl_MaxAtomicCounterBindings", "binding", "");
                 return;
@@ -6598,6 +6718,68 @@ const TFunction* TParseContext::findFunctionExplicitTypes(const TSourceLoc& loc,
     return bestMatch;
 }
 
+//
+// Adjust function calls that aren't declared in Vulkan to a
+// calls with equivalent effects
+//
+TIntermTyped* TParseContext::vkRelaxedRemapFunctionCall(const TSourceLoc& loc, TFunction* function, TIntermNode* arguments)
+{
+    TIntermTyped* result = nullptr;
+
+#ifndef GLSLANG_WEB
+    if (function->getBuiltInOp() != EOpNull) {
+        return nullptr;
+    }
+
+    if (function->getName() == "atomicCounterIncrement") {
+        // change atomicCounterIncrement into an atomicAdd of 1
+        TString name("atomicAdd");
+        TType uintType(EbtUint);
+
+        TFunction realFunc(&name, function->getType());
+
+        for (int i = 0; i < function->getParamCount(); ++i) {
+            realFunc.addParameter((*function)[i]);
+        }
+
+        TParameter tmpP = { 0, &uintType };
+        realFunc.addParameter(tmpP);
+        arguments = intermediate.growAggregate(arguments, intermediate.addConstantUnion(1, loc, true));
+
+        result = handleFunctionCall(loc, &realFunc, arguments);
+    } else if (function->getName() == "atomicCounterDecrement") {
+        // change atomicCounterDecrement into an atomicAdd with -1
+        // and subtract 1 from result, to return post-decrement value
+        TString name("atomicAdd");
+        TType uintType(EbtUint);
+
+        TFunction realFunc(&name, function->getType());
+
+        for (int i = 0; i < function->getParamCount(); ++i) {
+            realFunc.addParameter((*function)[i]);
+        }
+
+        TParameter tmpP = { 0, &uintType };
+        realFunc.addParameter(tmpP);
+        arguments = intermediate.growAggregate(arguments, intermediate.addConstantUnion(-1, loc, true));
+
+        result = handleFunctionCall(loc, &realFunc, arguments);
+
+        // post decrement, so that it matches AtomicCounterDecrement semantics
+        if (result) {
+            result = handleBinaryMath(loc, "-", EOpSub, result, intermediate.addConstantUnion(1, loc, true));
+        }
+    } else if (function->getName() == "atomicCounter") {
+        // change atomicCounter into a direct read of the variable
+        if (arguments->getAsTyped()) {
+            result = arguments->getAsTyped();
+        }
+    }
+#endif
+
+    return result;
+}
+
 // When a declaration includes a type, but not a variable name, it can be used
 // to establish defaults.
 void TParseContext::declareTypeDefaults(const TSourceLoc& loc, const TPublicType& publicType)
@@ -6622,6 +6804,91 @@ void TParseContext::declareTypeDefaults(const TSourceLoc& loc, const TPublicType
 #endif
 }
 
+bool TParseContext::vkRelaxedRemapUniformVariable(const TSourceLoc& loc, TString& identifier, const TPublicType&,
+    TArraySizes*, TIntermTyped* initializer, TType& type)
+{
+    if (parsingBuiltins || symbolTable.atBuiltInLevel() || !symbolTable.atGlobalLevel() ||
+        type.getQualifier().storage != EvqUniform ||
+        !(type.containsNonOpaque()
+#ifndef GLSLANG_WEB
+            || type.getBasicType() == EbtAtomicUint
+#endif
+        )) {
+        return false;
+    }
+
+    if (type.getQualifier().hasLocation()) {
+        warn(loc, "ignoring layout qualifier for uniform", identifier.c_str(), "location");
+        type.getQualifier().layoutLocation = TQualifier::layoutLocationEnd;
+    }
+
+    if (initializer) {
+        warn(loc, "Ignoring initializer for uniform", identifier.c_str(), "");
+        initializer = nullptr;
+    }
+
+    if (type.isArray()) {
+        // do array size checks here
+        arraySizesCheck(loc, type.getQualifier(), type.getArraySizes(), initializer, false);
+
+        if (arrayQualifierError(loc, type.getQualifier()) || arrayError(loc, type)) {
+            error(loc, "array param error", identifier.c_str(), "");
+        }
+    }
+
+    // do some checking on the type as it was declared
+    layoutTypeCheck(loc, type);
+
+    int bufferBinding = TQualifier::layoutBindingEnd;
+    TVariable* updatedBlock = nullptr;
+
+#ifndef GLSLANG_WEB
+    // Convert atomic_uint into members of a buffer block
+    if (type.isAtomic()) {
+        type.setBasicType(EbtUint);
+        type.getQualifier().storage = EvqBuffer;
+
+        type.getQualifier().volatil = true;
+        type.getQualifier().coherent = true;
+
+        // xxTODO: use logic from fixOffset() to apply explicit member offset
+        bufferBinding = type.getQualifier().layoutBinding;
+        type.getQualifier().layoutBinding = TQualifier::layoutBindingEnd;
+        type.getQualifier().explicitOffset = false;
+        growAtomicCounterBlock(bufferBinding, loc, type, identifier, nullptr);
+        updatedBlock = atomicCounterBuffers[bufferBinding];
+    }
+#endif
+
+    if (!updatedBlock) {
+        growGlobalUniformBlock(loc, type, identifier, nullptr);
+        updatedBlock = globalUniformBlock;
+    }
+
+    //
+    //      don't assign explicit member offsets here
+    //      if any are assigned, need to be updated here and in the merge/link step
+    // fixBlockUniformOffsets(updatedBlock->getWritableType().getQualifier(), *updatedBlock->getWritableType().getWritableStruct());
+
+    // checks on update buffer object
+    layoutObjectCheck(loc, *updatedBlock);
+
+    TSymbol* symbol = symbolTable.find(identifier);
+
+    if (!symbol) {
+        if (updatedBlock == globalUniformBlock)
+            error(loc, "error adding uniform to default uniform block", identifier.c_str(), "");
+        else
+            error(loc, "error adding atomic counter to atomic counter block", identifier.c_str(), "");
+        return false;
+    }
+
+    // merge qualifiers
+    mergeObjectLayoutQualifiers(updatedBlock->getWritableType().getQualifier(), type.getQualifier(), true);
+
+    return true;
+}
+
 //
 // Do everything necessary to handle a variable (non-block) declaration.
 // Either redeclaring a variable, or making a new one, updating the symbol
@@ -6733,6 +7000,14 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden
     if (symbol == nullptr)
         reservedErrorCheck(loc, identifier);
 
+    if (symbol == nullptr && spvVersion.vulkan > 0 && spvVersion.vulkanRelaxed) {
+        bool remapped = vkRelaxedRemapUniformVariable(loc, identifier, publicType, arraySizes, initializer, type);
+
+        if (remapped) {
+            return nullptr;
+        }
+    }
+
     inheritGlobalDefaults(type.getQualifier());
 
     // Declare the variable
@@ -7625,6 +7900,8 @@ void TParseContext::inheritMemoryQualifiers(const TQualifier& from, TQualifier&
 void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, const TString* instanceName,
     TArraySizes* arraySizes)
 {
+    if (spvVersion.vulkan > 0 && spvVersion.vulkanRelaxed)
+        blockStorageRemap(loc, blockName, currentBlockQualifier);
     blockStageIoCheck(loc, currentBlockQualifier);
     blockQualifierCheck(loc, currentBlockQualifier, instanceName != nullptr);
     if (arraySizes != nullptr) {
@@ -7914,6 +8191,17 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
     trackLinkage(variable);
 }
 
+//
+// allow storage type of block to be remapped at compile time
+//
+void TParseContext::blockStorageRemap(const TSourceLoc&, const TString* instanceName, TQualifier& qualifier)
+{
+    TBlockStorageClass type = intermediate.getBlockStorageOverride(instanceName->c_str());
+    if (type != EbsNone) {
+        qualifier.setBlockStorage(type);
+    }
+}
+
 // Do all block-declaration checking regarding the combination of in/out/uniform/buffer
 // with a particular stage.
 void TParseContext::blockStageIoCheck(const TSourceLoc& loc, const TQualifier& qualifier)
index ad9b8d6..6f00621 100644 (file)
@@ -92,7 +92,8 @@ public:
             limits(resources.limits),
             globalUniformBlock(nullptr),
             globalUniformBinding(TQualifier::layoutBindingEnd),
-            globalUniformSet(TQualifier::layoutSetEnd)
+            globalUniformSet(TQualifier::layoutSetEnd),
+            atomicCounterBlockSet(TQualifier::layoutSetEnd)
     {
         if (entryPoint != nullptr)
             sourceEntryPointName = *entryPoint;
@@ -154,10 +155,11 @@ public:
             extensionCallback(line, extension, behavior);
     }
 
-#ifdef ENABLE_HLSL
     // Manage the global uniform block (default uniforms in GLSL, $Global in HLSL)
     virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr);
-#endif
+
+    // Manage global buffer (used for backing atomic counters in GLSL when using relaxed Vulkan semantics)
+    virtual void growAtomicCounterBlock(int binding, const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr);
 
     // Potentially rename shader entry point function
     void renameShaderFunction(TString*& name) const
@@ -230,7 +232,24 @@ protected:
     // override this to set the language-specific name
     virtual const char* getGlobalUniformBlockName() const { return ""; }
     virtual void setUniformBlockDefaults(TType&) const { }
-    virtual void finalizeGlobalUniformBlockLayout(TVariable&) { }
+    virtual void finalizeGlobalUniformBlockLayout(TVariable&) {}
+
+    // Manage the atomic counter block (used for atomic_uints with Vulkan-Relaxed)
+    TMap<int, TVariable*> atomicCounterBuffers;
+    unsigned int atomicCounterBlockSet;
+    TMap<int, int> atomicCounterBlockFirstNewMember;
+    // override this to set the language-specific name
+    virtual const char* getAtomicCounterBlockName() const { return ""; }
+    virtual void setAtomicCounterBlockDefaults(TType&) const {}
+    virtual void finalizeAtomicCounterBlockLayout(TVariable&) {}
+    bool isAtomicCounterBlock(const TSymbol& symbol) {
+        const TVariable* var = symbol.getAsVariable();
+        if (!var)
+            return false;
+        const auto& at = atomicCounterBuffers.find(var->getType().getQualifier().layoutBinding);
+        return (at != atomicCounterBuffers.end() && (*at).second->getType() == var->getType());
+    }
+
     virtual void outputMessage(const TSourceLoc&, const char* szReason, const char* szToken,
                                const char* szExtraInfoFormat, TPrefixType prefix,
                                va_list args);
@@ -293,6 +312,9 @@ public:
     bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) override;
     void parserError(const char* s);     // for bison's yyerror
 
+    virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr) override;
+    virtual void growAtomicCounterBlock(int binding, const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr) override;
+
     void reservedErrorCheck(const TSourceLoc&, const TString&);
     void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) override;
     bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) override;
@@ -340,6 +362,10 @@ public:
     void checkPrecisionQualifier(const TSourceLoc&, TPrecisionQualifier);
     void memorySemanticsCheck(const TSourceLoc&, const TFunction&, const TIntermOperator& callNode);
 
+    TIntermTyped* vkRelaxedRemapFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*);
+    // returns true if the variable was remapped to something else
+    bool vkRelaxedRemapUniformVariable(const TSourceLoc&, TString&, const TPublicType&, TArraySizes*, TIntermTyped*, TType&);
+
     void assignError(const TSourceLoc&, const char* op, TString left, TString right);
     void unaryOpError(const TSourceLoc&, const char* op, TString operand);
     void binaryOpError(const TSourceLoc&, const char* op, TString left, TString right);
@@ -417,6 +443,7 @@ public:
     TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset);
     void inheritMemoryQualifiers(const TQualifier& from, TQualifier& to);
     void declareBlock(const TSourceLoc&, TTypeList& typeList, const TString* instanceName = 0, TArraySizes* arraySizes = 0);
+    void blockStorageRemap(const TSourceLoc&, const TString*, TQualifier&);
     void blockStageIoCheck(const TSourceLoc&, const TQualifier&);
     void blockQualifierCheck(const TSourceLoc&, const TQualifier&, bool instanceName);
     void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation);
@@ -461,6 +488,14 @@ protected:
     void finish() override;
 #endif
 
+    virtual const char* getGlobalUniformBlockName() const override;
+    virtual void finalizeGlobalUniformBlockLayout(TVariable&) override;
+    virtual void setUniformBlockDefaults(TType& block) const override;
+
+    virtual const char* getAtomicCounterBlockName() const override;
+    virtual void finalizeAtomicCounterBlockLayout(TVariable&) override;
+    virtual void setAtomicCounterBlockDefaults(TType& block) const override;
+
 public:
     //
     // Generally, bison productions, the scanner, and the PP need read/write access to these; just give them direct access
index 3f793a7..4b340ea 100644 (file)
@@ -159,7 +159,7 @@ int MapVersionToIndex(int version)
     return index;
 }
 
-const int SpvVersionCount = 3;  // index range in MapSpvVersionToIndex
+const int SpvVersionCount = 4;  // index range in MapSpvVersionToIndex
 
 int MapSpvVersionToIndex(const SpvVersion& spvVersion)
 {
@@ -167,8 +167,12 @@ int MapSpvVersionToIndex(const SpvVersion& spvVersion)
 
     if (spvVersion.openGl > 0)
         index = 1;
-    else if (spvVersion.vulkan > 0)
-        index = 2;
+    else if (spvVersion.vulkan > 0) {
+        if (!spvVersion.vulkanRelaxed)
+            index = 2;
+        else
+            index = 3;
+    }
 
     assert(index < SpvVersionCount);
 
@@ -723,6 +727,7 @@ void TranslateEnvironment(const TEnvironment* environment, EShMessages& messages
                 break;
             case EShClientVulkan:
                 spvVersion.vulkanGlsl = environment->input.dialectVersion;
+                spvVersion.vulkanRelaxed = environment->input.VulkanRulesRelaxed;
                 break;
             case EShClientOpenGL:
                 spvVersion.openGl = environment->input.dialectVersion;
@@ -1868,6 +1873,15 @@ void TShader::setResourceSetBinding(const std::vector<std::string>& base)   { in
 void TShader::setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { intermediate->setTextureSamplerTransformMode(mode); }
 #endif
 
+void TShader::addBlockStorageOverride(const char* nameStr, TBlockStorageClass backing) { intermediate->addBlockStorageOverride(nameStr, backing); }
+
+void TShader::setGlobalUniformBlockName(const char* name) { intermediate->setGlobalUniformBlockName(name); }
+void TShader::setGlobalUniformSet(unsigned int set) { intermediate->setGlobalUniformSet(set); }
+void TShader::setGlobalUniformBinding(unsigned int binding) { intermediate->setGlobalUniformBinding(binding); }
+
+void TShader::setAtomicCounterBlockName(const char* name) { intermediate->setAtomicCounterBlockName(name); }
+void TShader::setAtomicCounterBlockSet(unsigned int set) { intermediate->setAtomicCounterBlockSet(set); }
+
 #ifdef ENABLE_HLSL
 // See comment above TDefaultHlslIoMapper in iomapper.cpp:
 void TShader::setHlslIoMapping(bool hlslIoMap)          { intermediate->setHlslIoMapping(hlslIoMap); }
@@ -1983,7 +1997,10 @@ bool TProgram::link(EShMessages messages)
             error = true;
     }
 
-    // TODO: Link: cross-stage error checking
+    if (!error) {
+        if (! crossStageCheck(messages))
+            error = true;
+    }
 
     return ! error;
 }
@@ -2060,6 +2077,64 @@ bool TProgram::linkStage(EShLanguage stage, EShMessages messages)
     return intermediate[stage]->getNumErrors() == 0;
 }
 
+//
+// Check that there are no errors in linker objects accross stages
+//
+// Return true if no errors.
+//
+bool TProgram::crossStageCheck(EShMessages) {
+
+    // make temporary intermediates to hold the linkage symbols for each linking interface
+    // while we do the checks
+    // Independent interfaces are:
+    //                  all uniform variables and blocks
+    //                  all buffer blocks
+    //                  all in/out on a stage boundary
+
+    TVector<TIntermediate*> activeStages;
+    for (int s = 0; s < EShLangCount; ++s) {
+        if (intermediate[s])
+            activeStages.push_back(intermediate[s]);
+    }
+
+    // no extra linking if there is only one stage
+    if (! (activeStages.size() > 1))
+        return true;
+
+    // setup temporary tree to hold unfirom objects from different stages
+    TIntermediate* firstIntermediate = activeStages.front();
+    TIntermediate uniforms(EShLangCount,
+                           firstIntermediate->getVersion(),
+                           firstIntermediate->getProfile());
+    uniforms.setSpv(firstIntermediate->getSpv());
+
+    TIntermAggregate uniformObjects(EOpLinkerObjects);
+    TIntermAggregate root(EOpSequence);
+    root.getSequence().push_back(&uniformObjects);
+    uniforms.setTreeRoot(&root);
+
+    bool error = false;
+
+    // merge uniforms from all stages into a single intermediate
+    for (unsigned int i = 0; i < activeStages.size(); ++i) {
+        uniforms.mergeUniformObjects(*infoSink, *activeStages[i]);
+    }
+    error |= uniforms.getNumErrors() != 0;
+
+    // copy final definition of global block back into each stage
+    for (unsigned int i = 0; i < activeStages.size(); ++i) {
+        activeStages[i]->mergeGlobalUniformBlocks(*infoSink, uniforms);
+    }
+
+    // compare cross stage symbols for each stage boundary
+    for (unsigned int i = 1; i < activeStages.size(); ++i) {
+        activeStages[i - 1]->checkStageIO(*infoSink, *activeStages[i]);
+        error |= (activeStages[i - 1]->getNumErrors() != 0);
+    }
+
+    return !error;
+}
+
 const char* TProgram::getInfoLog()
 {
     return infoSink->info.c_str();
index 488c98c..7554bfd 100644 (file)
@@ -1273,7 +1273,7 @@ void TParseVersions::spvRemoved(const TSourceLoc& loc, const char* op)
 // Call for any operation removed because Vulkan SPIR-V is being generated.
 void TParseVersions::vulkanRemoved(const TSourceLoc& loc, const char* op)
 {
-    if (spvVersion.vulkan > 0)
+    if (spvVersion.vulkan > 0 && !spvVersion.vulkanRelaxed)
         error(loc, "not allowed when using GLSL for Vulkan", op, "");
 }
 
index f377973..25feb0b 100644 (file)
@@ -87,11 +87,12 @@ inline const char* ProfileName(EProfile profile)
 // The union of all requested rule sets will be applied.
 //
 struct SpvVersion {
-    SpvVersion() : spv(0), vulkanGlsl(0), vulkan(0), openGl(0) {}
+    SpvVersion() : spv(0), vulkanGlsl(0), vulkan(0), openGl(0), vulkanRelaxed(false) {}
     unsigned int spv; // the version of SPIR-V to target, as defined by "word 1" of the SPIR-V binary header
     int vulkanGlsl;   // the version of GLSL semantics for Vulkan, from GL_KHR_vulkan_glsl, for "#define VULKAN XXX"
     int vulkan;       // the version of Vulkan, for which SPIR-V execution environment rules to use
     int openGl;       // the version of GLSL semantics for OpenGL, from GL_ARB_gl_spirv, for "#define GL_SPIRV XXX"
+    bool vulkanRelaxed; // relax changes to GLSL for Vulkan, allowing some GL-specific to be compiled to Vulkan SPIR-V target
 };
 
 //
index 5ce3e47..c718f94 100644 (file)
@@ -886,6 +886,7 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
     case EOpTime:                       out.debug << "time";                  break;
 
     case EOpAtomicAdd:                  out.debug << "AtomicAdd";             break;
+    case EOpAtomicSubtract:             out.debug << "AtomicSubtract";        break;
     case EOpAtomicMin:                  out.debug << "AtomicMin";             break;
     case EOpAtomicMax:                  out.debug << "AtomicMax";             break;
     case EOpAtomicAnd:                  out.debug << "AtomicAnd";             break;
index c42e74f..7e12864 100644 (file)
@@ -210,8 +210,8 @@ struct TResolverUniformAdaptor {
         ent.newIndex = -1;
         const bool isValid = resolver.validateBinding(stage, ent);
         if (isValid) {
-            resolver.resolveBinding(ent.stage, ent);
             resolver.resolveSet(ent.stage, ent);
+            resolver.resolveBinding(ent.stage, ent);
             resolver.resolveUniformLocation(ent.stage, ent);
 
             if (ent.newBinding != -1) {
@@ -317,15 +317,13 @@ private:
 };
 
 // The class is used for reserving explicit uniform locations and ubo/ssbo/opaque bindings
+// xxTODO: maybe this logic should be moved into the resolver's "validateInOut" and "validateUniform"
 
 struct TSymbolValidater
 {
     TSymbolValidater(TIoMapResolver& r, TInfoSink& i, TVarLiveMap* in[EShLangCount], TVarLiveMap* out[EShLangCount],
                      TVarLiveMap* uniform[EShLangCount], bool& hadError, EProfile profile, int version)
-        : preStage(EShLangCount)
-        , currentStage(EShLangCount)
-        , nextStage(EShLangCount)
-        , resolver(r)
+        : resolver(r)
         , infoSink(i)
         , hadError(hadError)
         , profile(profile)
@@ -438,17 +436,23 @@ struct TSymbolValidater
         TIntermSymbol* base = ent1.symbol;
         const TType& type = ent1.symbol->getType();
         const TString& name = entKey.first;
-        EShLanguage stage = ent1.stage;
         TString mangleName1, mangleName2;
-        if (currentStage != stage) {
-            preStage = currentStage;
-            currentStage = stage;
-            nextStage = EShLangCount;
-            for (int i = currentStage + 1; i < EShLangCount; i++) {
-                if (inVarMaps[i] != nullptr) {
-                    nextStage = static_cast<EShLanguage>(i);
-                    break;
-                }
+        EShLanguage stage = ent1.stage;
+        EShLanguage preStage, currentStage, nextStage;
+
+        preStage = EShLangCount;
+        for (int i = stage - 1; i >= 0; i--) {
+            if (inVarMaps[i] != nullptr) {
+                preStage = static_cast<EShLanguage>(i);
+                break;
+            }
+        }
+        currentStage = stage;
+        nextStage = EShLangCount;
+        for (int i = stage + 1; i < EShLangCount; i++) {
+            if (inVarMaps[i] != nullptr) {
+                nextStage = static_cast<EShLanguage>(i);
+                break;
             }
         }
 
@@ -459,6 +463,9 @@ struct TSymbolValidater
             type.appendMangledName(mangleName1);
         }
 
+
+        // basic checking that symbols match
+        // more extensive checking in the link stage
         if (base->getQualifier().storage == EvqVaryingIn) {
             // validate stage in;
             if (preStage == EShLangCount)
@@ -484,8 +491,7 @@ struct TSymbolValidater
                     if (ent2->second.symbol->getType().getQualifier().isArrayedIo(preStage)) {
                         TType subType(ent2->second.symbol->getType(), 0);
                         subType.appendMangledName(mangleName2);
-                    }
-                    else {
+                    } else {
                         ent2->second.symbol->getType().appendMangledName(mangleName2);
                     }
 
@@ -536,8 +542,7 @@ struct TSymbolValidater
                     if (ent2->second.symbol->getType().getQualifier().isArrayedIo(nextStage)) {
                         TType subType(ent2->second.symbol->getType(), 0);
                         subType.appendMangledName(mangleName2);
-                    }
-                    else {
+                    } else {
                         ent2->second.symbol->getType().appendMangledName(mangleName2);
                     }
                     if (mangleName1 == mangleName2)
@@ -550,7 +555,7 @@ struct TSymbolValidater
                 }
                 return;
             }
-        } else if (base->getQualifier().isUniformOrBuffer() && ! base->getQualifier().isPushConstant()) {
+        } else if (base->getQualifier().isUniformOrBuffer() && !base->getQualifier().isPushConstant()) {
             // validate uniform type;
             for (int i = 0; i < EShLangCount; i++) {
                 if (i != currentStage && outVarMaps[i] != nullptr) {
@@ -558,6 +563,7 @@ struct TSymbolValidater
                     if (ent2 != uniformVarMap[i]->end()) {
                         ent2->second.symbol->getType().appendMangledName(mangleName2);
                         if (mangleName1 != mangleName2) {
+                            ent2->second.symbol->getType().sameElementType(type);
                             TString err = "Invalid Uniform variable type : " + entKey.first;
                             infoSink.info.message(EPrefixInternalError, err.c_str());
                             hadError = true;
@@ -608,8 +614,7 @@ struct TSymbolValidater
     }
 
     TVarLiveMap *inVarMaps[EShLangCount], *outVarMaps[EShLangCount], *uniformVarMap[EShLangCount];
-    // Use for mark pre stage, to get more interface symbol information.
-    EShLanguage preStage, currentStage, nextStage;
+
     // Use for mark current shader stage for resolver
     TIoMapResolver& resolver;
     TInfoSink& infoSink;
@@ -749,14 +754,18 @@ TDefaultIoResolverBase::TDefaultIoResolverBase(const TIntermediate& intermediate
     , nextOutputLocation(0)
 {
     memset(stageMask, false, sizeof(bool) * (EShLangCount + 1));
+    memset(stageIntermediates, 0, sizeof(TIntermediate*) * (EShLangCount));
+    stageIntermediates[intermediate.getStage()] = &intermediate;
 }
 
-int TDefaultIoResolverBase::getBaseBinding(TResourceType res, unsigned int set) const {
-    return selectBaseBinding(intermediate.getShiftBinding(res), intermediate.getShiftBindingForSet(res, set));
+int TDefaultIoResolverBase::getBaseBinding(EShLanguage stage, TResourceType res, unsigned int set) const {
+    return stageIntermediates[stage] ? selectBaseBinding(stageIntermediates[stage]->getShiftBinding(res), stageIntermediates[stage]->getShiftBindingForSet(res, set))
+                                     : selectBaseBinding(intermediate.getShiftBinding(res), intermediate.getShiftBindingForSet(res, set));
 }
 
-const std::vector<std::string>& TDefaultIoResolverBase::getResourceSetBinding() const {
-    return intermediate.getResourceSetBinding();
+const std::vector<std::string>& TDefaultIoResolverBase::getResourceSetBinding(EShLanguage stage) const {
+    return stageIntermediates[stage] ? stageIntermediates[stage]->getResourceSetBinding()
+                                     : intermediate.getResourceSetBinding();
 }
 
 bool TDefaultIoResolverBase::doAutoBindingMapping() const { return intermediate.getAutoMapBindings(); }
@@ -797,14 +806,14 @@ int TDefaultIoResolverBase::getFreeSlot(int set, int base, int size) {
     return reserveSlot(set, base, size);
 }
 
-int TDefaultIoResolverBase::resolveSet(EShLanguage /*stage*/, TVarEntryInfo& ent) {
+int TDefaultIoResolverBase::resolveSet(EShLanguage stage, TVarEntryInfo& ent) {
     const TType& type = ent.symbol->getType();
     if (type.getQualifier().hasSet()) {
         return ent.newSet = type.getQualifier().layoutSet;
     }
     // If a command line or API option requested a single descriptor set, use that (if not overrided by spaceN)
-    if (getResourceSetBinding().size() == 1) {
-        return ent.newSet = atoi(getResourceSetBinding()[0].c_str());
+    if (getResourceSetBinding(stage).size() == 1) {
+        return ent.newSet = atoi(getResourceSetBinding(stage)[0].c_str());
     }
     return ent.newSet = 0;
 }
@@ -925,7 +934,7 @@ int TDefaultGlslIoResolver::resolveInOutLocation(EShLanguage stage, TVarEntryInf
         preStage = currentStage;
         currentStage = stage;
     }
-    // kick out of not doing this
+    // kick out if not doing this
     if (! doAutoLocationMapping()) {
         return ent.newLocation = -1;
     }
@@ -1073,7 +1082,7 @@ int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEn
     return ent.newLocation = location;
 }
 
-int TDefaultGlslIoResolver::resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& ent) {
+int TDefaultGlslIoResolver::resolveBinding(EShLanguage stage, TVarEntryInfo& ent) {
     const TType& type = ent.symbol->getType();
     const TString& name = ent.symbol->getAccessName();
     // On OpenGL arrays of opaque types take a separate binding for each element
@@ -1086,30 +1095,32 @@ int TDefaultGlslIoResolver::resolveBinding(EShLanguage /*stage*/, TVarEntryInfo&
     // There is no 'set' qualifier in OpenGL shading language, each resource has its own
     // binding name space, so remap the 'set' to resource type which make each resource
     // binding is valid from 0 to MAX_XXRESOURCE_BINDINGS
-    int set = resource;
+    int set = intermediate.getSpv().openGl != 0 ? resource : ent.newSet;
+    int resourceKey = set;
     if (resource < EResCount) {
         if (type.getQualifier().hasBinding()) {
-            ent.newBinding = reserveSlot(set, getBaseBinding(resource, set) + type.getQualifier().layoutBinding, numBindings);
-            return ent.newBinding;
-        } else if (ent.live && doAutoBindingMapping()) {
+            int newBinding = reserveSlot(resourceKey, getBaseBinding(stage, resource, set) + type.getQualifier().layoutBinding, numBindings);
+            return ent.newBinding = newBinding;
+
+        } else {
             // The resource in current stage is not declared with binding, but it is possible declared
             // with explicit binding in other stages, find the resourceSlotMap firstly to check whether
             // the resource has binding, don't need to allocate if it already has a binding
             bool hasBinding = false;
-            if (! resourceSlotMap[resource].empty()) {
-                TVarSlotMap::iterator iter = resourceSlotMap[resource].find(name);
-                if (iter != resourceSlotMap[resource].end()) {
+            ent.newBinding = -1; // leave as -1 if it isn't set below
+
+            if (! resourceSlotMap[resourceKey].empty()) {
+                TVarSlotMap::iterator iter = resourceSlotMap[resourceKey].find(name);
+                if (iter != resourceSlotMap[resourceKey].end()) {
                     hasBinding = true;
                     ent.newBinding = iter->second;
                 }
             }
-            if (! hasBinding) {
-                TVarSlotMap varSlotMap;
+            if (!hasBinding && (ent.live && doAutoBindingMapping())) {
                 // find free slot, the caller did make sure it passes all vars with binding
                 // first and now all are passed that do not have a binding and needs one
-                int binding = getFreeSlot(resource, getBaseBinding(resource, set), numBindings);
-                varSlotMap[name] = binding;
-                resourceSlotMap[resource] = varSlotMap;
+                int binding = getFreeSlot(resourceKey, getBaseBinding(stage, resource, set), numBindings);
+                resourceSlotMap[resourceKey][name] = binding;
                 ent.newBinding = binding;
             }
             return ent.newBinding;
@@ -1211,16 +1222,20 @@ void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink&
 void TDefaultGlslIoResolver::reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) {
     const TType& type = ent.symbol->getType();
     const TString& name = ent.symbol->getAccessName();
-    int resource = getResourceType(type);
+    TResourceType resource = getResourceType(type);
+    int set = intermediate.getSpv().openGl != 0 ? resource : resolveSet(ent.stage, ent);
+    int resourceKey = set;
+
     if (type.getQualifier().hasBinding()) {
-        TVarSlotMap& varSlotMap = resourceSlotMap[resource];
+        TVarSlotMap& varSlotMap = resourceSlotMap[resourceKey];
         TVarSlotMap::iterator iter = varSlotMap.find(name);
-        int binding = type.getQualifier().layoutBinding;
+        int binding = type.getQualifier().layoutBinding + getBaseBinding(ent.stage, resource, set);
+
         if (iter == varSlotMap.end()) {
             // Reserve the slots for the ubo, ssbo and opaques who has explicit binding
-            int numBindings = type.isSizedArray() ? type.getCumulativeArraySize() : 1;
+            int numBindings = intermediate.getSpv().openGl != 0 && type.isSizedArray() ? type.getCumulativeArraySize() : 1;
             varSlotMap[name] = binding;
-            reserveSlot(resource, binding, numBindings);
+            reserveSlot(resourceKey, binding, numBindings);
         } else {
             // Allocate binding by name for OpenGL driver, so the resource in different
             // stages should be declared with the same binding
@@ -1269,7 +1284,7 @@ struct TDefaultIoResolver : public TDefaultIoResolverBase {
         return EResCount;
     }
 
-    int resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& ent) override {
+    int resolveBinding(EShLanguage stage, TVarEntryInfo& ent) override {
         const TType& type = ent.symbol->getType();
         const int set = getLayoutSet(type);
         // On OpenGL arrays of opaque types take a seperate binding for each element
@@ -1278,11 +1293,11 @@ struct TDefaultIoResolver : public TDefaultIoResolverBase {
         if (resource < EResCount) {
             if (type.getQualifier().hasBinding()) {
                 return ent.newBinding = reserveSlot(
-                           set, getBaseBinding(resource, set) + type.getQualifier().layoutBinding, numBindings);
+                           set, getBaseBinding(stage, resource, set) + type.getQualifier().layoutBinding, numBindings);
             } else if (ent.live && doAutoBindingMapping()) {
                 // find free slot, the caller did make sure it passes all vars with binding
                 // first and now all are passed that do not have a binding and needs one
-                return ent.newBinding = getFreeSlot(set, getBaseBinding(resource, set), numBindings);
+                return ent.newBinding = getFreeSlot(set, getBaseBinding(stage, resource, set), numBindings);
             }
         }
         return ent.newBinding = -1;
@@ -1354,17 +1369,17 @@ struct TDefaultHlslIoResolver : public TDefaultIoResolverBase {
         return EResCount;
     }
 
-    int resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& ent) override {
+    int resolveBinding(EShLanguage stage, TVarEntryInfo& ent) override {
         const TType& type = ent.symbol->getType();
         const int set = getLayoutSet(type);
         TResourceType resource = getResourceType(type);
         if (resource < EResCount) {
             if (type.getQualifier().hasBinding()) {
-                return ent.newBinding = reserveSlot(set, getBaseBinding(resource, set) + type.getQualifier().layoutBinding);
+                return ent.newBinding = reserveSlot(set, getBaseBinding(stage, resource, set) + type.getQualifier().layoutBinding);
             } else if (ent.live && doAutoBindingMapping()) {
                 // find free slot, the caller did make sure it passes all vars with binding
                 // first and now all are passed that do not have a binding and needs one
-                return ent.newBinding = getFreeSlot(set, getBaseBinding(resource, set));
+                return ent.newBinding = getFreeSlot(set, getBaseBinding(stage, resource, set));
             }
         }
         return ent.newBinding = -1;
@@ -1403,10 +1418,10 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TInfoSi
         else
             resolver = &defaultResolver;
     }
-    resolver->addStage(stage);
 #else
     resolver = &defaultResolver;
 #endif
+    resolver->addStage(stage, intermediate);
 
     TVarLiveMap inVarMap, outVarMap, uniformVarMap;
     TVarLiveVector inVector, outVector, uniformVector;
@@ -1502,10 +1517,21 @@ bool TGlslIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TIn
     }
     // if no resolver is provided, use the default resolver with the given shifts and auto map settings
     TDefaultGlslIoResolver defaultResolver(intermediate);
+#ifdef ENABLE_HLSL
+    TDefaultHlslIoResolver defaultHlslResolver(intermediate);
+    if (resolver == nullptr) {
+        // TODO: use a passed in IO mapper for this
+        if (intermediate.usingHlslIoMapping())
+            resolver = &defaultHlslResolver;
+        else
+            resolver = &defaultResolver;
+    }
+#else
     if (resolver == nullptr) {
         resolver = &defaultResolver;
     }
-    resolver->addStage(stage);
+#endif
+    resolver->addStage(stage, intermediate);
     inVarMaps[stage] = new TVarLiveMap(); outVarMaps[stage] = new TVarLiveMap(); uniformVarMap[stage] = new TVarLiveMap();
     TVarGatherTraverser iter_binding_all(intermediate, true, *inVarMaps[stage], *outVarMaps[stage],
                                          *uniformVarMap[stage]);
@@ -1547,15 +1573,51 @@ bool TGlslIoMapper::doMap(TIoMapResolver* resolver, TInfoSink& infoSink) {
         TResolverInOutAdaptor inOutResolve(EShLangCount, *resolver, infoSink, hadError);
         TSymbolValidater symbolValidater(*resolver, infoSink, inVarMaps,
                                          outVarMaps, uniformVarMap, hadError, profile, version);
+
+        TVarLiveVector inVectors[EShLangCount];
+        TVarLiveVector outVectors[EShLangCount];
         TVarLiveVector uniformVector;
+
         resolver->beginResolve(EShLangCount);
         for (int stage = EShLangVertex; stage < EShLangCount; stage++) {
             if (inVarMaps[stage] != nullptr) {
                 inOutResolve.setStage(EShLanguage(stage));
-                for (auto& var : *(inVarMaps[stage])) { symbolValidater(var); }
-                for (auto& var : *(inVarMaps[stage])) { inOutResolve(var); }
-                for (auto& var : *(outVarMaps[stage])) { symbolValidater(var); }
-                for (auto& var : *(outVarMaps[stage])) { inOutResolve(var); }
+
+                // copy vars into a sorted list
+                std::for_each(inVarMaps[stage]->begin(), inVarMaps[stage]->end(),
+                        [&inVectors, stage](TVarLivePair p) { inVectors[stage].push_back(p); });
+                std::sort(inVectors[stage].begin(), inVectors[stage].end(),
+                        [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
+                            return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
+                });
+
+                std::for_each(outVarMaps[stage]->begin(), outVarMaps[stage]->end(),
+                        [&outVectors, stage](TVarLivePair p) { outVectors[stage].push_back(p); });
+                std::sort(outVectors[stage].begin(), outVectors[stage].end(),
+                        [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
+                            return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
+                });
+
+                for (auto& var : inVectors[stage]) { symbolValidater(var); }
+                for (auto& var : inVectors[stage]) { inOutResolve(var); }
+                for (auto& var : outVectors[stage]) { symbolValidater(var); }
+                for (auto& var : outVectors[stage]) { inOutResolve(var); }
+
+                // copy results back into maps
+                std::for_each(inVectors[stage].begin(), inVectors[stage].end(),
+                    [this, stage](TVarLivePair p) {
+                        auto at = inVarMaps[stage]->find(p.first);
+                        if (at != inVarMaps[stage]->end())
+                            at->second = p.second;
+                });
+
+                std::for_each(outVectors[stage].begin(), outVectors[stage].end(),
+                    [this, stage](TVarLivePair p) {
+                        auto at = outVarMaps[stage]->find(p.first);
+                        if (at != outVarMaps[stage]->end())
+                            at->second = p.second;
+                });
+
             }
             if (uniformVarMap[stage] != nullptr) {
                 uniformResolve.setStage(EShLanguage(stage));
@@ -1563,7 +1625,7 @@ bool TGlslIoMapper::doMap(TIoMapResolver* resolver, TInfoSink& infoSink) {
             }
         }
         std::sort(uniformVector.begin(), uniformVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
-            return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
+            return TVarEntryInfo::TOrderByPriorityAndLive()(p1.second, p2.second);
         });
         for (auto& var : uniformVector) { symbolValidater(var); }
         for (auto& var : uniformVector) { uniformResolve(var); }
index 1dce8ff..07357c2 100644 (file)
@@ -87,6 +87,35 @@ struct TVarEntryInfo {
             return lPoints > rPoints;
         }
     };
+
+    struct TOrderByPriorityAndLive {
+        // ordering:
+        // 1) do live variables first
+        // 2) has both binding and set
+        // 3) has binding but no set
+        // 4) has no binding but set
+        // 5) has no binding and no set
+        inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) {
+
+            const TQualifier& lq = l.symbol->getQualifier();
+            const TQualifier& rq = r.symbol->getQualifier();
+
+            // simple rules:
+            // has binding gives 2 points
+            // has set gives 1 point
+            // who has the most points is more important.
+            int lPoints = (lq.hasBinding() ? 2 : 0) + (lq.hasSet() ? 1 : 0);
+            int rPoints = (rq.hasBinding() ? 2 : 0) + (rq.hasSet() ? 1 : 0);
+
+            if (l.live != r.live)
+                return l.live > r.live;
+
+            if (lPoints != rPoints)
+                return lPoints > rPoints;
+
+            return l.id < r.id;
+        }
+    };
 };
 
 // Base class for shared TIoMapResolver services, used by several derivations.
@@ -107,8 +136,8 @@ public:
     void endCollect(EShLanguage) override {}
     void reserverResourceSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {}
     void reserverStorageSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {}
-    int getBaseBinding(TResourceType res, unsigned int set) const;
-    const std::vector<std::string>& getResourceSetBinding() const;
+    int getBaseBinding(EShLanguage stage, TResourceType res, unsigned int set) const;
+    const std::vector<std::string>& getResourceSetBinding(EShLanguage stage) const;
     virtual TResourceType getResourceType(const glslang::TType& type) = 0;
     bool doAutoBindingMapping() const;
     bool doAutoLocationMapping() const;
@@ -122,9 +151,11 @@ public:
     int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) override;
     int resolveInOutComponent(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
     int resolveInOutIndex(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
-    void addStage(EShLanguage stage) override {
-        if (stage < EShLangCount)
+    void addStage(EShLanguage stage, TIntermediate& stageIntermediate) override {
+        if (stage < EShLangCount) {
             stageMask[stage] = true;
+            stageIntermediates[stage] = &stageIntermediate;
+        }
     }
     uint32_t computeTypeLocationSize(const TType& type, EShLanguage stage);
 
@@ -139,6 +170,8 @@ protected:
     int nextInputLocation;
     int nextOutputLocation;
     bool stageMask[EShLangCount + 1];
+    const TIntermediate* stageIntermediates[EShLangCount];
+
     // Return descriptor set specific base if there is one, and the generic base otherwise.
     int selectBaseBinding(int base, int descriptorSetBase) const {
         return descriptorSetBase != -1 ? descriptorSetBase : base;
index 3f3a312..789dc3c 100644 (file)
@@ -90,6 +90,55 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
 #endif
 }
 
+//
+// check that link objects between stages
+//
+void TIntermediate::mergeUniformObjects(TInfoSink& infoSink, TIntermediate& unit) {
+    if (unit.treeRoot == nullptr || treeRoot == nullptr)
+        return;
+
+    // Get the linker-object lists
+    TIntermSequence& linkerObjects = findLinkerObjects()->getSequence();
+    TIntermSequence unitLinkerObjects = unit.findLinkerObjects()->getSequence();
+
+    // filter unitLinkerObjects to only contain uniforms
+    auto end = std::remove_if(unitLinkerObjects.begin(), unitLinkerObjects.end(),
+        [](TIntermNode* node) {return node->getAsSymbolNode()->getQualifier().storage != EvqUniform &&
+                                      node->getAsSymbolNode()->getQualifier().storage != EvqBuffer; });
+    unitLinkerObjects.resize(end - unitLinkerObjects.begin());
+
+    // merge uniforms and do error checking
+    mergeGlobalUniformBlocks(infoSink, unit);
+    mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects, unit.getStage());
+}
+
+//
+// do error checking on the shader boundary in / out vars 
+//
+void TIntermediate::checkStageIO(TInfoSink& infoSink, TIntermediate& unit) {
+    if (unit.treeRoot == nullptr || treeRoot == nullptr)
+        return;
+
+    // Get copies of the linker-object lists
+    TIntermSequence linkerObjects = findLinkerObjects()->getSequence();
+    TIntermSequence unitLinkerObjects = unit.findLinkerObjects()->getSequence();
+
+    // filter linkerObjects to only contain out variables
+    auto end = std::remove_if(linkerObjects.begin(), linkerObjects.end(),
+        [](TIntermNode* node) {return node->getAsSymbolNode()->getQualifier().storage != EvqVaryingOut; });
+    linkerObjects.resize(end - linkerObjects.begin());
+
+    // filter unitLinkerObjects to only contain in variables
+    auto unitEnd = std::remove_if(unitLinkerObjects.begin(), unitLinkerObjects.end(),
+        [](TIntermNode* node) {return node->getAsSymbolNode()->getQualifier().storage != EvqVaryingIn; });
+    unitLinkerObjects.resize(unitEnd - unitLinkerObjects.begin());
+
+    // do matching and error checking
+    mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects, unit.getStage());
+
+    // TODO: final check; make sure that any statically used `in` have matching `out` written to
+}
+
 void TIntermediate::mergeCallGraphs(TInfoSink& infoSink, TIntermediate& unit)
 {
     if (unit.getNumEntryPoints() > 0) {
@@ -137,6 +186,7 @@ void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit)
     MERGE_MAX(spvVersion.vulkanGlsl);
     MERGE_MAX(spvVersion.vulkan);
     MERGE_MAX(spvVersion.openGl);
+    MERGE_TRUE(spvVersion.vulkanRelaxed);
 
     numErrors += unit.getNumErrors();
     // Only one push_constant is allowed, mergeLinkerObjects() will ensure the push_constant
@@ -312,7 +362,8 @@ void TIntermediate::mergeTrees(TInfoSink& infoSink, TIntermediate& unit)
     remapIds(idMaps, idShift + 1, unit);
 
     mergeBodies(infoSink, globals, unitGlobals);
-    mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects);
+    mergeGlobalUniformBlocks(infoSink, unit);
+    mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects, unit.getStage());
     ioAccessed.insert(unit.ioAccessed.begin(), unit.ioAccessed.end());
 }
 
@@ -456,11 +507,193 @@ void TIntermediate::mergeBodies(TInfoSink& infoSink, TIntermSequence& globals, c
     globals.insert(globals.end() - 1, unitGlobals.begin(), unitGlobals.end() - 1);
 }
 
+static inline bool isSameInterface(TIntermSymbol* symbol, EShLanguage stage, TIntermSymbol* unitSymbol, EShLanguage unitStage) {
+    return // 1) same stage and same shader interface
+        (stage == unitStage && symbol->getType().getShaderInterface() == unitSymbol->getType().getShaderInterface()) ||
+        // 2) accross stages and both are uniform or buffer
+        (symbol->getQualifier().storage == EvqUniform  && unitSymbol->getQualifier().storage == EvqUniform) ||
+        (symbol->getQualifier().storage == EvqBuffer   && unitSymbol->getQualifier().storage == EvqBuffer) ||
+        // 3) in/out matched across stage boundary
+        (stage < unitStage && symbol->getQualifier().storage == EvqVaryingOut  && unitSymbol->getQualifier().storage == EvqVaryingIn) ||
+        (unitStage < stage && symbol->getQualifier().storage == EvqVaryingIn && unitSymbol->getQualifier().storage == EvqVaryingOut);
+}
+
+//
+// Global Unfiform block stores any default uniforms (i.e. uniforms without a block)
+// If two linked stages declare the same member, they are meant to be the same uniform
+// and need to be in the same block
+// merge the members of different stages to allow them to be linked properly
+// as a single block
+//
+void TIntermediate::mergeGlobalUniformBlocks(TInfoSink& infoSink, TIntermediate& unit)
+{
+    TIntermSequence& linkerObjects = findLinkerObjects()->getSequence();
+    TIntermSequence& unitLinkerObjects = unit.findLinkerObjects()->getSequence();
+
+    // build lists of default blocks from the intermediates
+    TIntermSequence defaultBlocks;
+    TIntermSequence unitDefaultBlocks;
+
+    auto filter = [](TIntermSequence& list, TIntermNode* node) {
+        if (node->getAsSymbolNode()->getQualifier().defaultBlock) {
+            list.push_back(node);
+        }
+    };
+
+    std::for_each(linkerObjects.begin(), linkerObjects.end(),
+        [&defaultBlocks, &filter](TIntermNode* node) {
+            filter(defaultBlocks, node);
+        });
+    std::for_each(unitLinkerObjects.begin(), unitLinkerObjects.end(),
+        [&unitDefaultBlocks, &filter](TIntermNode* node) {
+            filter(unitDefaultBlocks, node);
+    });
+
+    auto itUnitBlock = unitDefaultBlocks.begin();
+    for (; itUnitBlock != unitDefaultBlocks.end(); itUnitBlock++) {
+
+        bool add = true;
+        auto itBlock = defaultBlocks.begin();
+
+        for (; itBlock != defaultBlocks.end(); itBlock++) {
+            TIntermSymbol* block = (*itBlock)->getAsSymbolNode();
+            TIntermSymbol* unitBlock = (*itUnitBlock)->getAsSymbolNode();
+
+            assert(block && unitBlock);
+
+            // if the two default blocks match, then merge their definitions
+            if (block->getType().getTypeName() == unitBlock->getType().getTypeName() &&
+                block->getQualifier().storage == unitBlock->getQualifier().storage) {
+                add = false;
+                mergeBlockDefinitions(infoSink, block, unitBlock, &unit);
+            }
+        }
+        if (add) {
+            // push back on original list; won't change the size of the list we're iterating over
+            linkerObjects.push_back(*itUnitBlock);
+        }
+    }
+}
+
+void TIntermediate::mergeBlockDefinitions(TInfoSink& infoSink, TIntermSymbol* block, TIntermSymbol* unitBlock, TIntermediate* unit) {
+    if (block->getType() == unitBlock->getType()) {
+        return;
+    }
+
+    if (block->getType().getTypeName() != unitBlock->getType().getTypeName() ||
+        block->getType().getBasicType() != unitBlock->getType().getBasicType() ||
+        block->getQualifier().storage != unitBlock->getQualifier().storage ||
+        block->getQualifier().layoutSet != unitBlock->getQualifier().layoutSet) {
+        // different block names likely means different blocks
+        return;
+    }
+
+    // merge the struct
+    // order of declarations doesn't matter and they matched based on member name
+    TTypeList* memberList = block->getType().getWritableStruct();
+    TTypeList* unitMemberList = unitBlock->getType().getWritableStruct();
+
+    // keep track of which members have changed position
+    // so we don't have to search the array again
+    std::map<unsigned int, unsigned int> memberIndexUpdates;
+
+    size_t memberListStartSize = memberList->size();
+    for (unsigned int i = 0; i < unitMemberList->size(); ++i) {
+        bool merge = true;
+        for (unsigned int j = 0; j < memberListStartSize; ++j) {
+            if ((*memberList)[j].type->getFieldName() == (*unitMemberList)[i].type->getFieldName()) {
+                merge = false;
+                const TType* memberType = (*memberList)[j].type;
+                const TType* unitMemberType = (*unitMemberList)[i].type;
+
+                // compare types
+                // don't need as many checks as when merging symbols, since
+                // initializers and most qualifiers are stripped when the member is moved into the block
+                if ((*memberType) != (*unitMemberType)) {
+                    error(infoSink, "Types must match:");
+                    infoSink.info << "    " << memberType->getFieldName() << ": ";
+                    infoSink.info << "\"" << memberType->getCompleteString() << "\" versus ";
+                    infoSink.info << "\"" << unitMemberType->getCompleteString() << "\"\n";
+                }
+
+                memberIndexUpdates[i] = j;
+            }
+        }
+        if (merge) {
+            memberList->push_back((*unitMemberList)[i]);
+            memberIndexUpdates[i] = (unsigned int)memberList->size() - 1;
+        }
+    }
+
+    TType unitType;
+    unitType.shallowCopy(unitBlock->getType());
+
+    // update symbol node in unit tree,
+    // and other nodes that may reference it
+    class TMergeBlockTraverser : public TIntermTraverser {
+    public:
+        TMergeBlockTraverser(const glslang::TType &type, const glslang::TType& unitType,
+                             glslang::TIntermediate& unit,
+                             const std::map<unsigned int, unsigned int>& memberIdxUpdates) :
+            newType(type), unitType(unitType), unit(unit), memberIndexUpdates(memberIdxUpdates)
+        { }
+        virtual ~TMergeBlockTraverser() { }
+
+        const glslang::TType& newType;          // type with modifications
+        const glslang::TType& unitType;         // copy of original type
+        glslang::TIntermediate& unit;           // intermediate that is being updated
+        const std::map<unsigned int, unsigned int>& memberIndexUpdates;
+
+        virtual void visitSymbol(TIntermSymbol* symbol)
+        {
+            glslang::TType& symType = symbol->getWritableType();
+
+            if (symType == unitType) {
+                // each symbol node has a local copy of the unitType
+                //  if merging involves changing properties that aren't shared objects
+                //  they should be updated in all instances
+
+                // e.g. the struct list is a ptr to an object, so it can be updated
+                // once, outside the traverser
+                //*symType.getWritableStruct() = *newType.getStruct();
+            }
+
+        }
+
+        virtual bool visitBinary(TVisit, glslang::TIntermBinary* node)
+        {
+            if (node->getOp() == EOpIndexDirectStruct && node->getLeft()->getType() == unitType) {
+                // this is a dereference to a member of the block since the
+                // member list changed, need to update this to point to the
+                // right index
+                assert(node->getRight()->getAsConstantUnion());
+
+                glslang::TIntermConstantUnion* constNode = node->getRight()->getAsConstantUnion();
+                unsigned int memberIdx = constNode->getConstArray()[0].getUConst();
+                unsigned int newIdx = memberIndexUpdates.at(memberIdx);
+                TIntermTyped* newConstNode = unit.addConstantUnion(newIdx, node->getRight()->getLoc());
+
+                node->setRight(newConstNode);
+                delete constNode;
+
+                return true;
+            }
+            return true;
+        }
+    } finalLinkTraverser(block->getType(), unitType, *unit, memberIndexUpdates);
+
+    // update the tree to use the new type
+    unit->getTreeRoot()->traverse(&finalLinkTraverser);
+
+    // update the member list
+    (*unitMemberList) = (*memberList);
+}
+
 //
 // Merge the linker objects from unitLinkerObjects into linkerObjects.
 // Duplication is expected and filtered out, but contradictions are an error.
 //
-void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects)
+void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects, EShLanguage unitStage)
 {
     // Error check and merge the linker objects (duplicates should not be created)
     std::size_t initialNumLinkerObjects = linkerObjects.size();
@@ -475,7 +708,7 @@ void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& lin
             // If they are both blocks in the same shader interface,
             // match by the block-name, not the identifier name.
             if (symbol->getType().getBasicType() == EbtBlock && unitSymbol->getType().getBasicType() == EbtBlock) {
-                if (symbol->getType().getShaderInterface() == unitSymbol->getType().getShaderInterface()) {
+                if (isSameInterface(symbol, getStage(), unitSymbol, unitStage)) {
                     isSameSymbol = symbol->getType().getTypeName() == unitSymbol->getType().getTypeName();
                 }
             }
@@ -495,18 +728,54 @@ void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& lin
                 if (! symbol->getQualifier().hasBinding() && unitSymbol->getQualifier().hasBinding())
                     symbol->getQualifier().layoutBinding = unitSymbol->getQualifier().layoutBinding;
 
+                // Similarly for location
+                if (!symbol->getQualifier().hasLocation() && unitSymbol->getQualifier().hasLocation()) {
+                    symbol->getQualifier().layoutLocation = unitSymbol->getQualifier().layoutLocation;
+                }
+
                 // Update implicit array sizes
                 mergeImplicitArraySizes(symbol->getWritableType(), unitSymbol->getType());
 
                 // Check for consistent types/qualification/initializers etc.
-                mergeErrorCheck(infoSink, *symbol, *unitSymbol, false);
+                mergeErrorCheck(infoSink, *symbol, *unitSymbol, unitStage);
             }
             // If different symbols, verify they arn't push_constant since there can only be one per stage
-            else if (symbol->getQualifier().isPushConstant() && unitSymbol->getQualifier().isPushConstant())
+            else if (symbol->getQualifier().isPushConstant() && unitSymbol->getQualifier().isPushConstant() && getStage() == unitStage)
                 error(infoSink, "Only one push_constant block is allowed per stage");
         }
-        if (merge)
+        if (merge) {
             linkerObjects.push_back(unitLinkerObjects[unitLinkObj]);
+
+            // for anonymous blocks, check that their members don't conflict with other names
+            if (unitLinkerObjects[unitLinkObj]->getAsSymbolNode()->getBasicType() == EbtBlock &&
+                IsAnonymous(unitLinkerObjects[unitLinkObj]->getAsSymbolNode()->getName())) {
+                for (std::size_t linkObj = 0; linkObj < initialNumLinkerObjects; ++linkObj) {
+                    TIntermSymbol* symbol = linkerObjects[linkObj]->getAsSymbolNode();
+                    TIntermSymbol* unitSymbol = unitLinkerObjects[unitLinkObj]->getAsSymbolNode();
+                    assert(symbol && unitSymbol);
+
+                    auto checkName = [this, unitSymbol, &infoSink](const TString& name) {
+                        for (unsigned int i = 0; i < unitSymbol->getType().getStruct()->size(); ++i) {
+                            if (name == (*unitSymbol->getType().getStruct())[i].type->getFieldName()) {
+                                error(infoSink, "Anonymous member name used for global variable or other anonymous member: ");
+                                infoSink.info << (*unitSymbol->getType().getStruct())[i].type->getCompleteString() << "\n";
+                            }
+                        }
+                    };
+
+                    if (isSameInterface(symbol, getStage(), unitSymbol, unitStage)) {
+                        checkName(symbol->getName());
+
+                        // check members of other anonymous blocks
+                        if (symbol->getBasicType() == EbtBlock && IsAnonymous(symbol->getName())) {
+                            for (unsigned int i = 0; i < symbol->getType().getStruct()->size(); ++i) {
+                                checkName((*symbol->getType().getStruct())[i].type->getFieldName());
+                            }
+                        }
+                    }
+                }
+            }
+        }
     }
 }
 
@@ -538,26 +807,74 @@ void TIntermediate::mergeImplicitArraySizes(TType& type, const TType& unitType)
 //
 // This function only does one of intra- or cross-stage matching per call.
 //
-void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& symbol, const TIntermSymbol& unitSymbol, bool crossStage)
+void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& symbol, const TIntermSymbol& unitSymbol, EShLanguage unitStage)
 {
 #if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
+    bool crossStage = getStage() != unitStage;
     bool writeTypeComparison = false;
 
     // Types have to match
-    if (symbol.getType() != unitSymbol.getType()) {
+    {
         // but, we make an exception if one is an implicit array and the other is sized
-        if (! (symbol.getType().isArray() && unitSymbol.getType().isArray() &&
-                symbol.getType().sameElementType(unitSymbol.getType()) &&
-                (symbol.getType().isUnsizedArray() || unitSymbol.getType().isUnsizedArray()))) {
-            error(infoSink, "Types must match:");
+        // or if the array sizes differ because of the extra array dimension on some in/out boundaries
+        bool arraysMatch = false;
+        if (isIoResizeArray(symbol.getType(), getStage()) || isIoResizeArray(unitSymbol.getType(), unitStage)) {
+            // if the arrays have an extra dimension because of the stage.
+            // compare dimensions while ignoring the outer dimension
+            unsigned int firstDim = isIoResizeArray(symbol.getType(), getStage()) ? 1 : 0;
+            unsigned int numDim = symbol.getArraySizes()
+                ? symbol.getArraySizes()->getNumDims() : 0;
+            unsigned int unitFirstDim = isIoResizeArray(unitSymbol.getType(), unitStage) ? 1 : 0;
+            unsigned int unitNumDim = unitSymbol.getArraySizes()
+                ? unitSymbol.getArraySizes()->getNumDims() : 0;
+            arraysMatch = (numDim - firstDim) == (unitNumDim - unitFirstDim);
+            // check that array sizes match as well
+            for (unsigned int i = 0; i < (numDim - firstDim) && arraysMatch; i++) {
+                if (symbol.getArraySizes()->getDimSize(firstDim + i) !=
+                    unitSymbol.getArraySizes()->getDimSize(unitFirstDim + i)) {
+                    arraysMatch = false;
+                    break;
+                }
+            }
+        }
+        else {
+            arraysMatch = symbol.getType().sameArrayness(unitSymbol.getType()) ||
+                (symbol.getType().isArray() && unitSymbol.getType().isArray() &&
+                (symbol.getType().isUnsizedArray() || unitSymbol.getType().isUnsizedArray()));
+        }
+
+        if (!symbol.getType().sameElementType(unitSymbol.getType()) ||
+            !symbol.getType().sameTypeParameters(unitSymbol.getType()) ||
+            !arraysMatch ) {
             writeTypeComparison = true;
+            error(infoSink, "Types must match:");
+        }
+    }
+
+    // Interface block  member-wise layout qualifiers have to match
+    if (symbol.getType().getBasicType() == EbtBlock && unitSymbol.getType().getBasicType() == EbtBlock &&
+        symbol.getType().getStruct() && unitSymbol.getType().getStruct() &&
+        symbol.getType().sameStructType(unitSymbol.getType())) {
+        for (unsigned int i = 0; i < symbol.getType().getStruct()->size(); ++i) {
+            const TQualifier& qualifier = (*symbol.getType().getStruct())[i].type->getQualifier();
+            const TQualifier& unitQualifier = (*unitSymbol.getType().getStruct())[i].type->getQualifier();
+            if (qualifier.layoutMatrix     != unitQualifier.layoutMatrix ||
+                qualifier.layoutOffset     != unitQualifier.layoutOffset ||
+                qualifier.layoutAlign      != unitQualifier.layoutAlign ||
+                qualifier.layoutLocation   != unitQualifier.layoutLocation ||
+                qualifier.layoutComponent  != unitQualifier.layoutComponent) {
+                error(infoSink, "Interface block member layout qualifiers must match:");
+                writeTypeComparison = true;
+            }
         }
     }
 
     // Qualifiers have to (almost) match
 
     // Storage...
-    if (symbol.getQualifier().storage != unitSymbol.getQualifier().storage) {
+    if (symbol.getQualifier().storage != unitSymbol.getQualifier().storage &&
+        !((crossStage && symbol.getQualifier().storage == EvqVaryingIn && unitSymbol.getQualifier().storage == EvqVaryingOut) ||
+          (crossStage && symbol.getQualifier().storage == EvqVaryingOut && unitSymbol.getQualifier().storage == EvqVaryingIn))) {
         error(infoSink, "Storage qualifiers must match:");
         writeTypeComparison = true;
     }
@@ -597,12 +914,16 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
     }
 
     // Auxiliary and interpolation...
-    if (symbol.getQualifier().centroid  != unitSymbol.getQualifier().centroid ||
+    // "interpolation qualification (e.g., flat) and auxiliary qualification (e.g. centroid) may differ.  
+    //  These mismatches are allowed between any pair of stages ...
+    //  those provided in the fragment shader supersede those provided in previous stages."
+    if (!crossStage &&
+        (symbol.getQualifier().centroid  != unitSymbol.getQualifier().centroid ||
         symbol.getQualifier().smooth    != unitSymbol.getQualifier().smooth ||
         symbol.getQualifier().flat      != unitSymbol.getQualifier().flat ||
         symbol.getQualifier().isSample()!= unitSymbol.getQualifier().isSample() ||
         symbol.getQualifier().isPatch() != unitSymbol.getQualifier().isPatch() ||
-        symbol.getQualifier().isNonPerspective() != unitSymbol.getQualifier().isNonPerspective()) {
+        symbol.getQualifier().isNonPerspective() != unitSymbol.getQualifier().isNonPerspective())) {
         error(infoSink, "Interpolation and auxiliary storage qualifiers must match:");
         writeTypeComparison = true;
     }
@@ -1830,4 +2151,17 @@ int TIntermediate::computeBufferReferenceTypeSize(const TType& type)
     return size;
 }
 
+#ifndef GLSLANG_WEB
+bool TIntermediate::isIoResizeArray(const TType& type, EShLanguage language) {
+    return type.isArray() &&
+            ((language == EShLangGeometry    && type.getQualifier().storage == EvqVaryingIn) ||
+            (language == EShLangTessControl && type.getQualifier().storage == EvqVaryingOut &&
+                ! type.getQualifier().patch) ||
+            (language == EShLangFragment && type.getQualifier().storage == EvqVaryingIn &&
+                type.getQualifier().pervertexNV) ||
+            (language == EShLangMeshNV && type.getQualifier().storage == EvqVaryingOut &&
+                !type.getQualifier().perTaskNV));
+}
+#endif // not GLSLANG_WEB
+
 } // end namespace glslang
index 9fe684a..9bfa35c 100644 (file)
@@ -293,7 +293,12 @@ public:
         useStorageBuffer(false),
         nanMinMaxClamp(false),
         depthReplacing(false),
-        uniqueId(0)
+        uniqueId(0),
+        globalUniformBlockName(""),
+        atomicCounterBlockName(""),
+        globalUniformBlockSet(TQualifier::layoutSetEnd),
+        globalUniformBlockBinding(TQualifier::layoutBindingEnd),
+        atomicCounterBlockSet(TQualifier::layoutSetEnd)
 #ifndef GLSLANG_WEB
         ,
         implicitThisName("@this"), implicitCounterName("@count"),
@@ -537,6 +542,19 @@ public:
     void addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymbol&);
     TIntermAggregate* findLinkerObjects() const;
 
+    void setGlobalUniformBlockName(const char* name) { globalUniformBlockName = std::string(name); }
+    const char* getGlobalUniformBlockName() const { return globalUniformBlockName.c_str(); }
+    void setGlobalUniformSet(unsigned int set) { globalUniformBlockSet = set; }
+    unsigned int getGlobalUniformSet() const { return globalUniformBlockSet; }
+    void setGlobalUniformBinding(unsigned int binding) { globalUniformBlockBinding = binding; }
+    unsigned int getGlobalUniformBinding() const { return globalUniformBlockBinding; }
+
+    void setAtomicCounterBlockName(const char* name) { atomicCounterBlockName = std::string(name); }
+    const char* getAtomicCounterBlockName() const { return atomicCounterBlockName.c_str(); }
+    void setAtomicCounterBlockSet(unsigned int set) { atomicCounterBlockSet = set; }
+    unsigned int getAtomicCounterBlockSet() const { return atomicCounterBlockSet; }
+
+
     void setUseStorageBuffer() { useStorageBuffer = true; }
     bool usingStorageBuffer() const { return useStorageBuffer; }
     void setDepthReplacing() { depthReplacing = true; }
@@ -848,6 +866,20 @@ public:
     bool getBinaryDoubleOutput() { return binaryDoubleOutput; }
 #endif // GLSLANG_WEB
 
+    void addBlockStorageOverride(const char* nameStr, TBlockStorageClass backing)
+    {
+        std::string name(nameStr);
+        blockBackingOverrides[name] = backing;
+    }
+    TBlockStorageClass getBlockStorageOverride(const char* nameStr) const
+    {
+        std::string name = nameStr;
+        auto pos = blockBackingOverrides.find(name);
+        if (pos == blockBackingOverrides.end())
+            return EbsNone;
+        else
+            return pos->second;
+    }
 #ifdef ENABLE_HLSL
     void setHlslFunctionality1() { hlslFunctionality1 = true; }
     bool getHlslFunctionality1() const { return hlslFunctionality1; }
@@ -883,6 +915,10 @@ public:
     void merge(TInfoSink&, TIntermediate&);
     void finalCheck(TInfoSink&, bool keepUncalled);
 
+    void mergeGlobalUniformBlocks(TInfoSink& infoSink, TIntermediate& unit);
+    void mergeUniformObjects(TInfoSink& infoSink, TIntermediate& unit);
+    void checkStageIO(TInfoSink&, TIntermediate&);
+
     bool buildConvertOp(TBasicType dst, TBasicType src, TOperator& convertOp) const;
     TIntermTyped* createConversion(TBasicType convertTo, TIntermTyped* node) const;
 
@@ -906,6 +942,8 @@ public:
     static int getOffset(const TType& type, int index);
     static int getBlockSize(const TType& blockType);
     static int computeBufferReferenceTypeSize(const TType&);
+    static bool isIoResizeArray(const TType& type, EShLanguage language);
+
     bool promote(TIntermOperator*);
     void setNanMinMaxClamp(bool setting) { nanMinMaxClamp = setting; }
     bool getNanMinMaxClamp() const { return nanMinMaxClamp; }
@@ -963,9 +1001,10 @@ protected:
     void seedIdMap(TIdMaps& idMaps, long long& IdShift);
     void remapIds(const TIdMaps& idMaps, long long idShift, TIntermediate&);
     void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals);
-    void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects);
+    void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects, EShLanguage);
+    void mergeBlockDefinitions(TInfoSink&, TIntermSymbol* block, TIntermSymbol* unitBlock, TIntermediate* unitRoot);
     void mergeImplicitArraySizes(TType&, const TType&);
-    void mergeErrorCheck(TInfoSink&, const TIntermSymbol&, const TIntermSymbol&, bool crossStage);
+    void mergeErrorCheck(TInfoSink&, const TIntermSymbol&, const TIntermSymbol&, EShLanguage);
     void checkCallGraphCycles(TInfoSink&);
     void checkCallGraphBodies(TInfoSink&, bool keepUncalled);
     void inOutLocationCheck(TInfoSink&);
@@ -1015,6 +1054,13 @@ protected:
     bool localSizeNotDefault[3];
     int localSizeSpecId[3];
     unsigned long long uniqueId;
+
+    std::string globalUniformBlockName;
+    std::string atomicCounterBlockName;
+    unsigned int globalUniformBlockSet;
+    unsigned int globalUniformBlockBinding;
+    unsigned int atomicCounterBlockSet;
+
 #ifndef GLSLANG_WEB
 public:
     const char* const implicitThisName;
@@ -1075,6 +1121,7 @@ protected:
     int uniformLocationBase;
     TNumericFeatures numericFeatures;
 #endif
+    std::unordered_map<std::string, TBlockStorageClass> blockBackingOverrides;
 
     std::unordered_set<int> usedConstantId; // specialization constant ids used
     std::vector<TOffsetRange> usedAtomics;  // sets of bindings used by atomic counters
index e147b0d..74b9f3e 100644 (file)
@@ -187,6 +187,7 @@ struct TInputLanguage {
     EShLanguage stage;        // redundant information with other input, this one overrides when not EShSourceNone
     EShClient dialect;
     int dialectVersion;       // version of client's language definition, not the client (when not EShClientNone)
+    bool VulkanRulesRelaxed = false;
 };
 
 struct TClient {
@@ -427,6 +428,14 @@ enum TResourceType {
     EResCount
 };
 
+enum TBlockStorageClass
+{
+    EbsUniform = 0,
+    EbsStorageBuffer,
+    EbsPushConstant,
+    EbsNone,    // not a uniform or buffer variable
+    EbsCount,
+};
 
 // Make one TShader per shader that you will link into a program. Then
 //  - provide the shader through setStrings() or setStringsWithLengths()
@@ -483,6 +492,14 @@ public:
     GLSLANG_EXPORT void setNoStorageFormat(bool useUnknownFormat);
     GLSLANG_EXPORT void setNanMinMaxClamp(bool nanMinMaxClamp);
     GLSLANG_EXPORT void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode);
+    GLSLANG_EXPORT void addBlockStorageOverride(const char* nameStr, glslang::TBlockStorageClass backing);
+
+    GLSLANG_EXPORT void setGlobalUniformBlockName(const char* name);
+    GLSLANG_EXPORT void setAtomicCounterBlockName(const char* name);
+    GLSLANG_EXPORT void setGlobalUniformSet(unsigned int set);
+    GLSLANG_EXPORT void setGlobalUniformBinding(unsigned int binding);
+    GLSLANG_EXPORT void setAtomicCounterBlockSet(unsigned int set);
+    GLSLANG_EXPORT void setAtomicCounterBlockBinding(unsigned int binding);
 
     // For setting up the environment (cleared to nothingness in the constructor).
     // These must be called so that parsing is done for the right source language and
@@ -539,6 +556,9 @@ public:
     bool getEnvTargetHlslFunctionality1() const { return false; }
 #endif
 
+    void setEnvInputVulkanRulesRelaxed() { environment.input.VulkanRulesRelaxed = true; }
+    bool getEnvInputVulkanRulesRelaxed() const { return environment.input.VulkanRulesRelaxed; }
+
     // Interface to #include handlers.
     //
     // To support #include, a client of Glslang does the following:
@@ -806,7 +826,7 @@ public:
     // Called by TSlotCollector to resolve resource locations or bindings
     virtual void reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) = 0;
     // Called by mapIO.addStage to set shader stage mask to mark a stage be added to this pipeline
-    virtual void addStage(EShLanguage stage) = 0;
+    virtual void addStage(EShLanguage stage, TIntermediate& stageIntermediate) = 0;
 };
 
 #endif // !GLSLANG_WEB && !GLSLANG_ANGLE
@@ -928,6 +948,7 @@ public:
 
 protected:
     GLSLANG_EXPORT bool linkStage(EShLanguage, EShMessages);
+    GLSLANG_EXPORT bool crossStageCheck(EShMessages);
 
     TPoolAllocator* pool;
     std::list<TShader*> stages[EShLangCount];
index 0617ff8..74c9809 100644 (file)
@@ -53,7 +53,9 @@ if(BUILD_TESTING)
             ${CMAKE_CURRENT_SOURCE_DIR}/Link.FromFile.cpp
             ${CMAKE_CURRENT_SOURCE_DIR}/Link.FromFile.Vk.cpp
             ${CMAKE_CURRENT_SOURCE_DIR}/Pp.FromFile.cpp
-            ${CMAKE_CURRENT_SOURCE_DIR}/Spv.FromFile.cpp)
+            ${CMAKE_CURRENT_SOURCE_DIR}/Spv.FromFile.cpp
+            ${CMAKE_CURRENT_SOURCE_DIR}/VkRelaxed.FromFile.cpp
+            ${CMAKE_CURRENT_SOURCE_DIR}/GlslMapIO.FromFile.cpp)
 
         if(ENABLE_SPVREMAPPER)
             set(TEST_SOURCES ${TEST_SOURCES}
diff --git a/gtests/GlslMapIO.FromFile.cpp b/gtests/GlslMapIO.FromFile.cpp
new file mode 100644 (file)
index 0000000..574e905
--- /dev/null
@@ -0,0 +1,306 @@
+//
+// Copyright (C) 2016-2017 Google, Inc.
+// Copyright (C) 2020 The Khronos Group Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+//    Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+//
+//    Redistributions in binary form must reproduce the above
+//    copyright notice, this list of conditions and the following
+//    disclaimer in the documentation and/or other materials provided
+//    with the distribution.
+//
+//    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+//    contributors may be used to endorse or promote products derived
+//    from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+#include <algorithm>
+
+#include <gtest/gtest.h>
+
+#include "TestFixture.h"
+
+#include "glslang/MachineIndependent/iomapper.h"
+#include "glslang/MachineIndependent/reflection.h"
+
+#ifndef GLSLANG_WEB
+namespace glslangtest {
+namespace {
+
+struct IoMapData {
+    std::vector<std::string> fileNames;
+    Semantics semantics;
+};
+
+using GlslMapIOTest = GlslangTest <::testing::TestWithParam<IoMapData>>;
+
+template<class T>
+std::string interfaceName(T symbol) {
+    return symbol.getType()->getBasicType() == glslang::EbtBlock ? std::string(symbol.getType()->getTypeName().c_str()) : symbol.name;
+}
+
+bool verifyIOMapping(std::string& linkingError, glslang::TProgram& program) {
+    bool success = true;
+
+    // Verify IO Mapping by generating reflection for each stage individually
+    // and comparing layout qualifiers on the results
+
+
+    int reflectionOptions = EShReflectionDefault;
+    //reflectionOptions |= EShReflectionStrictArraySuffix;
+    //reflectionOptions |= EShReflectionBasicArraySuffix;
+    reflectionOptions |= EShReflectionIntermediateIO;
+    reflectionOptions |= EShReflectionSeparateBuffers;
+    reflectionOptions |= EShReflectionAllBlockVariables;
+    //reflectionOptions |= EShReflectionUnwrapIOBlocks;
+
+    success &= program.buildReflection(reflectionOptions);
+
+    // check that the reflection output from the individual stages all makes sense..
+    std::vector<glslang::TReflection> stageReflections;
+    for (int s = 0; s < EShLangCount; ++s) {
+        if (program.getIntermediate((EShLanguage)s)) {
+            stageReflections.emplace_back((EShReflectionOptions)reflectionOptions, (EShLanguage)s, (EShLanguage)s);
+            success &= stageReflections.back().addStage((EShLanguage)s, *program.getIntermediate((EShLanguage)s));
+        }
+    }
+
+    // check that input/output locations match between stages
+    auto it = stageReflections.begin();
+    auto nextIt = it + 1;
+    for (; nextIt != stageReflections.end(); it++, nextIt++) {
+        int numOut = it->getNumPipeOutputs();
+        std::map<std::string, const glslang::TObjectReflection*> pipeOut;
+
+        for (int i = 0; i < numOut; i++) {
+            const glslang::TObjectReflection& out = it->getPipeOutput(i);
+            std::string name = interfaceName(out);
+            pipeOut[name] = &out;
+        }
+
+        int numIn = nextIt->getNumPipeInputs();
+        for (int i = 0; i < numIn; i++) {
+            auto in = nextIt->getPipeInput(i);
+            std::string name = interfaceName(in);
+            auto out = pipeOut.find(name);
+
+            if (out != pipeOut.end()) {
+                auto inQualifier = in.getType()->getQualifier();
+                auto outQualifier = out->second->getType()->getQualifier();
+                success &= outQualifier.layoutLocation == inQualifier.layoutLocation;
+            }
+            else {
+                success &= false;
+            }
+        }
+    }
+
+    // compare uniforms in each stage to the program
+    {
+        int totalUniforms = program.getNumUniformVariables();
+        std::map<std::string, const glslang::TObjectReflection*> programUniforms;
+        for (int i = 0; i < totalUniforms; i++) {
+            const glslang::TObjectReflection& uniform = program.getUniform(i);
+            std::string name = interfaceName(uniform);
+            programUniforms[name] = &uniform;
+        }
+        it = stageReflections.begin();
+        for (; it != stageReflections.end(); it++) {
+            int numUniform = it->getNumUniforms();
+            std::map<std::string, glslang::TObjectReflection> uniforms;
+
+            for (int i = 0; i < numUniform; i++) {
+                glslang::TObjectReflection uniform = it->getUniform(i);
+                std::string name = interfaceName(uniform);
+                auto programUniform = programUniforms.find(name);
+
+                if (programUniform != programUniforms.end()) {
+                    auto stageQualifier = uniform.getType()->getQualifier();
+                    auto programQualifier = programUniform->second->getType()->getQualifier();
+
+                    success &= stageQualifier.layoutLocation == programQualifier.layoutLocation;
+                    success &= stageQualifier.layoutBinding == programQualifier.layoutBinding;
+                    success &= stageQualifier.layoutSet == programQualifier.layoutSet;
+                }
+                else {
+                    success &= false;
+                }
+            }
+        }
+    }
+
+    // compare uniform blocks in each stage to the program table
+    {
+        int totalUniforms = program.getNumUniformBlocks();
+        std::map<std::string, const glslang::TObjectReflection*> programUniforms;
+        for (int i = 0; i < totalUniforms; i++) {
+            const glslang::TObjectReflection& uniform = program.getUniformBlock(i);
+            std::string name = interfaceName(uniform);
+            programUniforms[name] = &uniform;
+        }
+        it = stageReflections.begin();
+        for (; it != stageReflections.end(); it++) {
+            int numUniform = it->getNumUniformBlocks();
+            std::map<std::string, glslang::TObjectReflection> uniforms;
+
+            for (int i = 0; i < numUniform; i++) {
+                glslang::TObjectReflection uniform = it->getUniformBlock(i);
+                std::string name = interfaceName(uniform);
+                auto programUniform = programUniforms.find(name);
+
+                if (programUniform != programUniforms.end()) {
+                    auto stageQualifier = uniform.getType()->getQualifier();
+                    auto programQualifier = programUniform->second->getType()->getQualifier();
+
+                    success &= stageQualifier.layoutLocation == programQualifier.layoutLocation;
+                    success &= stageQualifier.layoutBinding == programQualifier.layoutBinding;
+                    success &= stageQualifier.layoutSet == programQualifier.layoutSet;
+                }
+                else {
+                    success &= false;
+                }
+            }
+        }
+    }
+
+    if (!success) {
+        linkingError += "Mismatched cross-stage IO\n";
+    }
+
+    return success;
+}
+
+TEST_P(GlslMapIOTest, FromFile)
+{
+    const auto& fileNames = GetParam().fileNames;
+    Semantics semantics = GetParam().semantics;
+    const size_t fileCount = fileNames.size();
+    const EShMessages controls = DeriveOptions(Source::GLSL, semantics, Target::BothASTAndSpv);
+    GlslangResult result;
+
+    // Compile each input shader file.
+    bool success = true;
+    std::vector<std::unique_ptr<glslang::TShader>> shaders;
+    for (size_t i = 0; i < fileCount; ++i) {
+        std::string contents;
+        tryLoadFile(GlobalTestSettings.testRoot + "/" + fileNames[i],
+            "input", &contents);
+        shaders.emplace_back(
+            new glslang::TShader(GetShaderStage(GetSuffix(fileNames[i]))));
+        auto* shader = shaders.back().get();
+        
+        shader->setAutoMapLocations(true);
+        shader->setAutoMapBindings(true);
+        
+        if (controls & EShMsgSpvRules) {
+            if (controls & EShMsgVulkanRules) {
+                shader->setEnvInput((controls & EShMsgReadHlsl) ? glslang::EShSourceHlsl
+                                                               : glslang::EShSourceGlsl,
+                                    shader->getStage(), glslang::EShClientVulkan, 100);
+                shader->setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_1);
+                shader->setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_0);
+            } else {
+                shader->setEnvInput((controls & EShMsgReadHlsl) ? glslang::EShSourceHlsl
+                                                               : glslang::EShSourceGlsl,
+                                    shader->getStage(), glslang::EShClientOpenGL, 100);
+                shader->setEnvClient(glslang::EShClientOpenGL, glslang::EShTargetOpenGL_450);
+                shader->setEnvTarget(glslang::EshTargetSpv, glslang::EShTargetSpv_1_0);
+            }
+        }
+
+        success &= compile(shader, contents, "", controls);
+        
+        result.shaderResults.push_back(
+            { fileNames[i], shader->getInfoLog(), shader->getInfoDebugLog() });
+    }
+
+    // Link all of them.
+    glslang::TProgram program;
+    for (const auto& shader : shaders) program.addShader(shader.get());
+    success &= program.link(controls);
+    result.linkingOutput = program.getInfoLog();
+    result.linkingError = program.getInfoDebugLog();
+
+    unsigned int stage = 0;
+    glslang::TIntermediate* firstIntermediate = nullptr;
+    while (!program.getIntermediate((EShLanguage)stage) && stage < EShLangCount) { stage++; }
+    firstIntermediate = program.getIntermediate((EShLanguage)stage);
+
+    glslang::TDefaultGlslIoResolver resolver(*firstIntermediate);
+    glslang::TGlslIoMapper ioMapper;
+
+    if (success) {
+        success &= program.mapIO(&resolver, &ioMapper);
+        result.linkingOutput = program.getInfoLog();
+        result.linkingError = program.getInfoDebugLog();
+    }
+
+    success &= verifyIOMapping(result.linkingError, program);
+    result.validationResult = success;
+
+    if (success && (controls & EShMsgSpvRules)) {
+        for (int stage = 0; stage < EShLangCount; ++stage) {
+            if (program.getIntermediate((EShLanguage)stage)) {
+                spv::SpvBuildLogger logger;
+                std::vector<uint32_t> spirv_binary;
+                options().disableOptimizer = false;
+                glslang::GlslangToSpv(*program.getIntermediate((EShLanguage)stage),
+                    spirv_binary, &logger, &options());
+
+                std::ostringstream disassembly_stream;
+                spv::Parameterize();
+                spv::Disassemble(disassembly_stream, spirv_binary);
+                result.spirvWarningsErrors += logger.getAllMessages();
+                result.spirv += disassembly_stream.str();
+                result.validationResult &= !options().validate || logger.getAllMessages().empty();
+            }
+        }
+    }
+
+    std::ostringstream stream;
+    outputResultToStream(&stream, result, controls);
+
+    // Check with expected results.
+    const std::string expectedOutputFname =
+        GlobalTestSettings.testRoot + "/baseResults/" + fileNames.front() + ".out";
+    std::string expectedOutput;
+    tryLoadFile(expectedOutputFname, "expected output", &expectedOutput);
+
+    checkEqAndUpdateIfRequested(expectedOutput, stream.str(), expectedOutputFname,
+        result.spirvWarningsErrors);
+}
+
+// clang-format off
+INSTANTIATE_TEST_SUITE_P(
+    Glsl, GlslMapIOTest,
+    ::testing::ValuesIn(std::vector<IoMapData>({
+        {{"iomap.crossStage.vert", "iomap.crossStage.frag" }, Semantics::OpenGL},
+        {{"iomap.crossStage.2.vert", "iomap.crossStage.2.geom", "iomap.crossStage.2.frag" }, Semantics::OpenGL},
+        // vulkan semantics
+        {{"iomap.crossStage.vk.vert", "iomap.crossStage.vk.geom", "iomap.crossStage.vk.frag" }, Semantics::Vulkan},
+    }))
+);
+// clang-format on
+
+}  // anonymous namespace
+}  // namespace glslangtest
+#endif 
\ No newline at end of file
index 2909a9c..5e005a4 100644 (file)
@@ -114,12 +114,12 @@ INSTANTIATE_TEST_SUITE_P(
     ::testing::ValuesIn(std::vector<std::vector<std::string>>({
         {"link1.vk.frag", "link2.vk.frag"},
         {"spv.unit1.frag", "spv.unit2.frag", "spv.unit3.frag"},
-               {"link.vk.matchingPC.0.0.frag", "link.vk.matchingPC.0.1.frag",
-                       "link.vk.matchingPC.0.2.frag"},
-               {"link.vk.differentPC.0.0.frag", "link.vk.differentPC.0.1.frag",
-                       "link.vk.differentPC.0.2.frag"},
-               {"link.vk.differentPC.1.0.frag", "link.vk.differentPC.1.1.frag",
-                       "link.vk.differentPC.1.2.frag"},
+        {"link.vk.matchingPC.0.0.frag", "link.vk.matchingPC.0.1.frag",
+            "link.vk.matchingPC.0.2.frag"},
+           {"link.vk.differentPC.0.0.frag", "link.vk.differentPC.0.1.frag",
+            "link.vk.differentPC.0.2.frag"},
+        {"link.vk.differentPC.1.0.frag", "link.vk.differentPC.1.1.frag",
+            "link.vk.differentPC.1.2.frag"},
         {"link.vk.pcNamingValid.0.0.vert", "link.vk.pcNamingValid.0.1.vert"},
         {"link.vk.pcNamingInvalid.0.0.vert", "link.vk.pcNamingInvalid.0.1.vert"},
         {"link.vk.multiBlocksValid.0.0.vert", "link.vk.multiBlocksValid.0.1.vert"},
diff --git a/gtests/VkRelaxed.FromFile.cpp b/gtests/VkRelaxed.FromFile.cpp
new file mode 100644 (file)
index 0000000..d791d6c
--- /dev/null
@@ -0,0 +1,296 @@
+//
+// Copyright (C) 2016-2017 Google, Inc.
+// Copyright (C) 2020 The Khronos Group Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+//    Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+//
+//    Redistributions in binary form must reproduce the above
+//    copyright notice, this list of conditions and the following
+//    disclaimer in the documentation and/or other materials provided
+//    with the distribution.
+//
+//    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+//    contributors may be used to endorse or promote products derived
+//    from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+#include <algorithm>
+
+#include <gtest/gtest.h>
+
+#include "TestFixture.h"
+
+#include "glslang/MachineIndependent/iomapper.h"
+#include "glslang/MachineIndependent/reflection.h"
+
+#ifndef GLSLANG_WEB
+namespace glslangtest {
+namespace {
+
+struct vkRelaxedData {
+    std::vector<std::string> fileNames;
+};
+
+using VulkanRelaxedTest = GlslangTest <::testing::TestWithParam<vkRelaxedData>>;
+
+template<class T>
+std::string interfaceName(T symbol) {
+    return symbol.getType()->getBasicType() == glslang::EbtBlock ? std::string(symbol.getType()->getTypeName().c_str()) : symbol.name;
+}
+
+bool verifyIOMapping(std::string& linkingError, glslang::TProgram& program) {
+    bool success = true;
+
+    // Verify IO Mapping by generating reflection for each stage individually
+    // and comparing layout qualifiers on the results
+
+
+    int reflectionOptions = EShReflectionDefault;
+    //reflectionOptions |= EShReflectionStrictArraySuffix;
+    //reflectionOptions |= EShReflectionBasicArraySuffix;
+    reflectionOptions |= EShReflectionIntermediateIO;
+    reflectionOptions |= EShReflectionSeparateBuffers;
+    reflectionOptions |= EShReflectionAllBlockVariables;
+    //reflectionOptions |= EShReflectionUnwrapIOBlocks;
+
+    success &= program.buildReflection(reflectionOptions);
+
+    // check that the reflection output from the individual stages all makes sense..
+    std::vector<glslang::TReflection> stageReflections;
+    for (int s = 0; s < EShLangCount; ++s) {
+        if (program.getIntermediate((EShLanguage)s)) {
+            stageReflections.emplace_back((EShReflectionOptions)reflectionOptions, (EShLanguage)s, (EShLanguage)s);
+            success &= stageReflections.back().addStage((EShLanguage)s, *program.getIntermediate((EShLanguage)s));
+        }
+    }
+
+    // check that input/output locations match between stages
+    auto it = stageReflections.begin();
+    auto nextIt = it + 1;
+    for (; nextIt != stageReflections.end(); it++, nextIt++) {
+        int numOut = it->getNumPipeOutputs();
+        std::map<std::string, const glslang::TObjectReflection*> pipeOut;
+
+        for (int i = 0; i < numOut; i++) {
+            const glslang::TObjectReflection& out = it->getPipeOutput(i);
+            std::string name = interfaceName(out);
+            pipeOut[name] = &out;
+        }
+
+        int numIn = nextIt->getNumPipeInputs();
+        for (int i = 0; i < numIn; i++) {
+            auto in = nextIt->getPipeInput(i);
+            std::string name = interfaceName(in);
+            auto out = pipeOut.find(name);
+
+            if (out != pipeOut.end()) {
+                auto inQualifier = in.getType()->getQualifier();
+                auto outQualifier = out->second->getType()->getQualifier();
+                success &= outQualifier.layoutLocation == inQualifier.layoutLocation;
+            }
+            else {
+                success &= false;
+            }
+        }
+    }
+
+    // compare uniforms in each stage to the program
+    {
+        int totalUniforms = program.getNumUniformVariables();
+        std::map<std::string, const glslang::TObjectReflection*> programUniforms;
+        for (int i = 0; i < totalUniforms; i++) {
+            const glslang::TObjectReflection& uniform = program.getUniform(i);
+            std::string name = interfaceName(uniform);
+            programUniforms[name] = &uniform;
+        }
+        it = stageReflections.begin();
+        for (; it != stageReflections.end(); it++) {
+            int numUniform = it->getNumUniforms();
+            std::map<std::string, glslang::TObjectReflection> uniforms;
+
+            for (int i = 0; i < numUniform; i++) {
+                glslang::TObjectReflection uniform = it->getUniform(i);
+                std::string name = interfaceName(uniform);
+                auto programUniform = programUniforms.find(name);
+
+                if (programUniform != programUniforms.end()) {
+                    auto stageQualifier = uniform.getType()->getQualifier();
+                    auto programQualifier = programUniform->second->getType()->getQualifier();
+
+                    success &= stageQualifier.layoutLocation == programQualifier.layoutLocation;
+                    success &= stageQualifier.layoutBinding == programQualifier.layoutBinding;
+                    success &= stageQualifier.layoutSet == programQualifier.layoutSet;
+                }
+                else {
+                    success &= false;
+                }
+            }
+        }
+    }
+
+    // compare uniform blocks in each stage to the program table
+    {
+        int totalUniforms = program.getNumUniformBlocks();
+        std::map<std::string, const glslang::TObjectReflection*> programUniforms;
+        for (int i = 0; i < totalUniforms; i++) {
+            const glslang::TObjectReflection& uniform = program.getUniformBlock(i);
+            std::string name = interfaceName(uniform);
+            programUniforms[name] = &uniform;
+        }
+        it = stageReflections.begin();
+        for (; it != stageReflections.end(); it++) {
+            int numUniform = it->getNumUniformBlocks();
+            std::map<std::string, glslang::TObjectReflection> uniforms;
+
+            for (int i = 0; i < numUniform; i++) {
+                glslang::TObjectReflection uniform = it->getUniformBlock(i);
+                std::string name = interfaceName(uniform);
+                auto programUniform = programUniforms.find(name);
+
+                if (programUniform != programUniforms.end()) {
+                    auto stageQualifier = uniform.getType()->getQualifier();
+                    auto programQualifier = programUniform->second->getType()->getQualifier();
+
+                    success &= stageQualifier.layoutLocation == programQualifier.layoutLocation;
+                    success &= stageQualifier.layoutBinding == programQualifier.layoutBinding;
+                    success &= stageQualifier.layoutSet == programQualifier.layoutSet;
+                }
+                else {
+                    success &= false;
+                }
+            }
+        }
+    }
+
+    if (!success) {
+        linkingError += "Mismatched cross-stage IO\n";
+    }
+
+    return success;
+}
+
+TEST_P(VulkanRelaxedTest, FromFile)
+{
+    const auto& fileNames = GetParam().fileNames;
+    Semantics semantics = Semantics::Vulkan;
+    const size_t fileCount = fileNames.size();
+    const EShMessages controls = DeriveOptions(Source::GLSL, semantics, Target::BothASTAndSpv);
+    GlslangResult result;
+
+    // Compile each input shader file.
+    bool success = true;
+    std::vector<std::unique_ptr<glslang::TShader>> shaders;
+    for (size_t i = 0; i < fileCount; ++i) {
+        std::string contents;
+        tryLoadFile(GlobalTestSettings.testRoot + "/" + fileNames[i],
+            "input", &contents);
+        shaders.emplace_back(
+            new glslang::TShader(GetShaderStage(GetSuffix(fileNames[i]))));
+        auto* shader = shaders.back().get();
+        
+        shader->setAutoMapLocations(true);
+        shader->setAutoMapBindings(true);
+
+        shader->setEnvInput(glslang::EShSourceGlsl, shader->getStage(), glslang::EShClientVulkan, 100);
+        shader->setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_1);
+        shader->setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_0);
+
+        // Use vulkan relaxed option
+        shader->setEnvInputVulkanRulesRelaxed();
+
+        success &= compile(shader, contents, "", controls);
+        
+        result.shaderResults.push_back(
+            { fileNames[i], shader->getInfoLog(), shader->getInfoDebugLog() });
+    }
+
+    // Link all of them.
+    glslang::TProgram program;
+    for (const auto& shader : shaders) program.addShader(shader.get());
+    success &= program.link(controls);
+    result.linkingOutput = program.getInfoLog();
+    result.linkingError = program.getInfoDebugLog();
+
+    unsigned int stage = 0;
+    glslang::TIntermediate* firstIntermediate = nullptr;
+    while (!program.getIntermediate((EShLanguage)stage) && stage < EShLangCount) { stage++; }
+    firstIntermediate = program.getIntermediate((EShLanguage)stage);
+
+    glslang::TDefaultGlslIoResolver resolver(*firstIntermediate);
+    glslang::TGlslIoMapper ioMapper;
+
+    if (success) {
+        success &= program.mapIO(&resolver, &ioMapper);
+        result.linkingOutput = program.getInfoLog();
+        result.linkingError = program.getInfoDebugLog();
+    }
+
+    success &= verifyIOMapping(result.linkingError, program);
+    result.validationResult = success;
+
+    if (success && (controls & EShMsgSpvRules)) {
+        for (int stage = 0; stage < EShLangCount; ++stage) {
+            if (program.getIntermediate((EShLanguage)stage)) {
+                spv::SpvBuildLogger logger;
+                std::vector<uint32_t> spirv_binary;
+                options().disableOptimizer = false;
+                glslang::GlslangToSpv(*program.getIntermediate((EShLanguage)stage),
+                    spirv_binary, &logger, &options());
+
+                std::ostringstream disassembly_stream;
+                spv::Parameterize();
+                spv::Disassemble(disassembly_stream, spirv_binary);
+                result.spirvWarningsErrors += logger.getAllMessages();
+                result.spirv += disassembly_stream.str();
+                result.validationResult &= !options().validate || logger.getAllMessages().empty();
+            }
+        }
+    }
+
+    std::ostringstream stream;
+    outputResultToStream(&stream, result, controls);
+
+    // Check with expected results.
+    const std::string expectedOutputFname =
+        GlobalTestSettings.testRoot + "/baseResults/" + fileNames.front() + ".out";
+    std::string expectedOutput;
+    tryLoadFile(expectedOutputFname, "expected output", &expectedOutput);
+
+    checkEqAndUpdateIfRequested(expectedOutput, stream.str(), expectedOutputFname,
+        result.spirvWarningsErrors);
+}
+
+// clang-format off
+INSTANTIATE_TEST_SUITE_P(
+    Glsl, VulkanRelaxedTest,
+    ::testing::ValuesIn(std::vector<vkRelaxedData>({
+        {{"vk.relaxed.frag"}},
+        {{"vk.relaxed.link1.frag", "vk.relaxed.link2.frag"}},
+        {{"vk.relaxed.stagelink.vert", "vk.relaxed.stagelink.frag"}},
+        {{"vk.relaxed.errorcheck.vert", "vk.relaxed.errorcheck.frag"}},
+    }))
+);
+// clang-format on
+
+}  // anonymous namespace
+}  // namespace glslangtest
+#endif 
\ No newline at end of file