aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgreg-lunarg <greg@lunarg.com>2021-03-15 13:38:49 -0600
committerGitHub <noreply@github.com>2021-03-15 13:38:49 -0600
commitb2e5b5c559e10a882ea72b5e4860d7f698fdf93c (patch)
tree2b0d25e8a0ed5d450c615bfd2f83deb29cc71932
parenta36d91e5acdbcece9c3ea3186fca185199827797 (diff)
parent4e064eef4619b0b1e17aca78c52fcfca83ad937d (diff)
downloadglslang-b2e5b5c559e10a882ea72b5e4860d7f698fdf93c.tar.gz
Merge pull request #2576 from KhronosGroup/revert-2569-revert-2242-GL_EXT_vulkan_glsl_relaxed
Revert "Revert "GL_ext_vulkan_glsl_relaxed extension support, and cross stage aware IO mapper""
-rw-r--r--SPIRV/GlslangToSpv.cpp3
-rw-r--r--StandAlone/StandAlone.cpp174
-rw-r--r--Test/baseResults/iomap.crossStage.2.vert.out787
-rw-r--r--Test/baseResults/iomap.crossStage.vert.out515
-rw-r--r--Test/baseResults/iomap.crossStage.vk.vert.out720
-rw-r--r--Test/baseResults/vk.relaxed.errorcheck.vert.out124
-rw-r--r--Test/baseResults/vk.relaxed.frag.out826
-rw-r--r--Test/baseResults/vk.relaxed.link1.frag.out515
-rw-r--r--Test/baseResults/vk.relaxed.stagelink.vert.out717
-rw-r--r--Test/iomap.crossStage.2.frag42
-rw-r--r--Test/iomap.crossStage.2.geom39
-rw-r--r--Test/iomap.crossStage.2.vert38
-rw-r--r--Test/iomap.crossStage.frag41
-rw-r--r--Test/iomap.crossStage.vert38
-rw-r--r--Test/iomap.crossStage.vk.frag50
-rw-r--r--Test/iomap.crossStage.vk.geom35
-rw-r--r--Test/iomap.crossStage.vk.vert32
-rw-r--r--Test/vk.relaxed.errorcheck.frag16
-rw-r--r--Test/vk.relaxed.errorcheck.vert15
-rw-r--r--Test/vk.relaxed.frag74
-rw-r--r--Test/vk.relaxed.link1.frag28
-rw-r--r--Test/vk.relaxed.link2.frag19
-rw-r--r--Test/vk.relaxed.stagelink.frag28
-rw-r--r--Test/vk.relaxed.stagelink.vert31
-rw-r--r--glslang/Include/Types.h44
-rw-r--r--glslang/Include/intermediate.h3
-rw-r--r--glslang/MachineIndependent/Initialize.cpp86
-rw-r--r--glslang/MachineIndependent/ParseContextBase.cpp63
-rw-r--r--glslang/MachineIndependent/ParseHelper.cpp300
-rw-r--r--glslang/MachineIndependent/ParseHelper.h43
-rw-r--r--glslang/MachineIndependent/ShaderLang.cpp83
-rw-r--r--glslang/MachineIndependent/Versions.cpp2
-rw-r--r--glslang/MachineIndependent/Versions.h3
-rw-r--r--glslang/MachineIndependent/intermOut.cpp1
-rw-r--r--glslang/MachineIndependent/iomapper.cpp184
-rw-r--r--glslang/MachineIndependent/iomapper.h41
-rw-r--r--glslang/MachineIndependent/linkValidate.cpp364
-rw-r--r--glslang/MachineIndependent/localintermediate.h53
-rw-r--r--glslang/Public/ShaderLang.h23
-rw-r--r--gtests/CMakeLists.txt4
-rw-r--r--gtests/GlslMapIO.FromFile.cpp306
-rw-r--r--gtests/Link.FromFile.Vk.cpp12
-rw-r--r--gtests/VkRelaxed.FromFile.cpp296
43 files changed, 6707 insertions, 111 deletions
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index 8eb06b7c..6d9c7cfe 100644
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -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:
@@ -6894,6 +6896,7 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv
builder.addCapability(spv::CapabilityAtomicFloat64AddEXT);
}
break;
+ case glslang::EOpAtomicSubtract:
case glslang::EOpAtomicCounterSubtract:
opCode = spv::OpAtomicISub;
break;
diff --git a/StandAlone/StandAlone.cpp b/StandAlone/StandAlone.cpp
index fdbf0279..923ded30 100644
--- a/StandAlone/StandAlone.cpp
+++ b/StandAlone/StandAlone.cpp
@@ -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
index 00000000..325c1b46
--- /dev/null
+++ b/Test/baseResults/iomap.crossStage.2.vert.out
@@ -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
index 00000000..5338b807
--- /dev/null
+++ b/Test/baseResults/iomap.crossStage.vert.out
@@ -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
index 00000000..e137bdfc
--- /dev/null
+++ b/Test/baseResults/iomap.crossStage.vk.vert.out
@@ -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
index 00000000..f19eae64
--- /dev/null
+++ b/Test/baseResults/vk.relaxed.errorcheck.vert.out
@@ -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
index 00000000..d98910e6
--- /dev/null
+++ b/Test/baseResults/vk.relaxed.frag.out
@@ -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
index 00000000..9dac4c64
--- /dev/null
+++ b/Test/baseResults/vk.relaxed.link1.frag.out
@@ -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
index 00000000..a63f10c3
--- /dev/null
+++ b/Test/baseResults/vk.relaxed.stagelink.vert.out
@@ -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
index 00000000..25756a6d
--- /dev/null
+++ b/Test/iomap.crossStage.2.frag
@@ -0,0 +1,42 @@
+#version 460
+
+
+layout(location = 5) in outBlock {
+ vec4 o3;
+};
+
+
+in vec4 gfo1;
+in vec2 gfo2;
+
+out vec4 outColor;
+
+uniform vec2 u1;
+uniform vec3 u2; // initializer present in vertex stage
+uniform vec4 u3 = vec4(0); // initializer matches initializer in vertex stage
+
+uniform mat2 um2 = mat2(4.0);
+
+layout (location = 0, binding = 0) uniform sampler2D glass;
+
+uniform crossStageBlock1 {
+ uniform vec4 a;
+ vec4 b;
+};
+
+buffer fragOnlyBlock {
+ vec2 fb1;
+};
+
+uniform crossStageBlock2 {
+ uniform vec4 a;
+ vec2 b;
+} blockName2 [2]; // instance name different from vert
+
+
+void main()
+{
+ vec4 color = gfo1 * u1.rgrg * u2.rgbr * u3.rgba; // o1 is statically used
+ outColor = color;
+}
+
diff --git a/Test/iomap.crossStage.2.geom b/Test/iomap.crossStage.2.geom
new file mode 100644
index 00000000..91508ab5
--- /dev/null
+++ b/Test/iomap.crossStage.2.geom
@@ -0,0 +1,39 @@
+#version 460
+
+layout(points) in;
+layout(triangle_strip, max_vertices=3) out;
+
+in vec4 vgo1[];
+in vec2 vgo2[];
+
+layout(location = 5) in outBlock {
+ vec4 o3;
+} inBlock[];
+
+out vec4 gfo1;
+out vec2 gfo2;
+
+layout(location = 5) out outBlock {
+ vec4 o3;
+} gf_out;
+
+uniform vec2 u1;
+uniform vec3 u2 = vec3(0); // initializer not present in fragment stage
+uniform vec4 u3 = vec4(0); // initializer matches initializer in fragment stage
+
+uniform crossStageBlock2 {
+ uniform vec4 a;
+ vec2 b;
+} blockName1 [2]; // instance name different from frag
+
+void main()
+{
+ for (int i = 0; i < 3; i++) {
+ gfo1 = vec4(0);
+ gfo2 = vec2(0);
+ gf_out.o3 = inBlock[i].o3;
+ EmitVertex();
+ }
+ EndPrimitive();
+}
+
diff --git a/Test/iomap.crossStage.2.vert b/Test/iomap.crossStage.2.vert
new file mode 100644
index 00000000..ebb0d9d1
--- /dev/null
+++ b/Test/iomap.crossStage.2.vert
@@ -0,0 +1,38 @@
+#version 460
+
+out vec4 vgo1; // declaration order different than fragment shader
+out vec2 vgo2; // declaration order different than fragment shader
+
+layout(location = 5) out outBlock {
+ vec4 o3;
+};
+
+uniform vec2 u1;
+uniform vec3 u2 = vec3(0); // initializer not present in fragment stage
+uniform vec4 u3 = vec4(0); // initializer matches initializer in fragment stage
+
+uniform mat2 um2 = mat2(4.0);
+
+layout (location = 0, binding = 0) uniform sampler2D glass;
+
+uniform crossStageBlock1 {
+ uniform vec4 a;
+ vec4 b;
+};
+
+buffer vertOnlyBlock {
+ vec2 vb1;
+};
+
+uniform crossStageBlock2 {
+ uniform vec4 a;
+ vec2 b;
+} blockName1 [2]; // instance name different from frag
+
+void main()
+{
+ vgo1 = vec4(0);
+ vgo2 = vec2(0);
+ o3 = vec4(0);
+}
+
diff --git a/Test/iomap.crossStage.frag b/Test/iomap.crossStage.frag
new file mode 100644
index 00000000..16247032
--- /dev/null
+++ b/Test/iomap.crossStage.frag
@@ -0,0 +1,41 @@
+#version 460
+
+
+layout(location = 5) in outBlock {
+ vec4 o3;
+};
+
+in vec2 o2; // declaration order different than vertex shader
+in vec4 o1; // declaration order different than vertex shader
+
+out vec4 outColor;
+
+uniform vec2 u1;
+uniform vec3 u2; // initializer present in vertex stage
+uniform vec4 u3 = vec4(0); // initializer matches initializer in vertex stage
+
+uniform mat2 um2 = mat2(4.0);
+
+layout (location = 0, binding = 0) uniform sampler2D glass;
+
+uniform crossStageBlock1 {
+ uniform vec4 a;
+ vec4 b;
+};
+
+buffer fragOnlyBlock {
+ vec2 fb1;
+};
+
+uniform crossStageBlock2 {
+ uniform vec4 a;
+ vec2 b;
+} blockName2 [2]; // instance name different from vert
+
+
+void main()
+{
+ vec4 color = o1 * u1.rgrg * u2.rgbr * u3.rgba; // o1 is statically used
+ outColor = color;
+}
+
diff --git a/Test/iomap.crossStage.vert b/Test/iomap.crossStage.vert
new file mode 100644
index 00000000..d05874ff
--- /dev/null
+++ b/Test/iomap.crossStage.vert
@@ -0,0 +1,38 @@
+#version 460
+
+out vec4 o1; // declaration order different than fragment shader
+out vec2 o2; // declaration order different than fragment shader
+
+layout(location = 5) out outBlock {
+ vec4 o3;
+};
+
+uniform vec2 u1;
+uniform vec3 u2 = vec3(0); // initializer not present in fragment stage
+uniform vec4 u3 = vec4(0); // initializer matches initializer in fragment stage
+
+uniform mat2 um2 = mat2(4.0);
+
+layout (location = 0, binding = 0) uniform sampler2D glass;
+
+uniform crossStageBlock1 {
+ uniform vec4 a;
+ vec4 b;
+};
+
+buffer vertOnlyBlock {
+ vec2 vb1;
+};
+
+uniform crossStageBlock2 {
+ uniform vec4 a;
+ vec2 b;
+} blockName1 [2]; // instance name different from frag
+
+void main()
+{
+ o1 = vec4(0);
+ o2 = vec2(0);
+ o3 = vec4(0);
+}
+
diff --git a/Test/iomap.crossStage.vk.frag b/Test/iomap.crossStage.vk.frag
new file mode 100644
index 00000000..d09e6874
--- /dev/null
+++ b/Test/iomap.crossStage.vk.frag
@@ -0,0 +1,50 @@
+#version 460
+
+
+layout(location = 5) in outBlock {
+ vec4 o3;
+};
+
+
+in vec4 gfo1;
+in vec2 gfo2;
+
+out vec4 outColor;
+
+layout (binding = 0) uniform sampler2D glass;
+
+uniform crossStageBlock1 {
+ uniform vec4 a;
+ vec4 b;
+};
+
+readonly buffer fragOnlyBlock {
+ vec2 fb1;
+};
+
+uniform crossStageBlock2 {
+ uniform vec4 a;
+ vec2 b;
+} blockName2 [2]; // instance name different from vert
+
+vec2 Bar() {
+ return fb1 +
+ blockName2[0].b +
+ blockName2[1].b;
+}
+
+vec4 Foo() {
+ return a +
+ b +
+ blockName2[0].a +
+ blockName2[1].a +
+ vec4(Bar(), 0.0, 0.0);
+}
+
+void main()
+{
+ vec4 color = gfo1; // o1 is statically used
+ color = color + Foo();
+ outColor = color;
+}
+
diff --git a/Test/iomap.crossStage.vk.geom b/Test/iomap.crossStage.vk.geom
new file mode 100644
index 00000000..b9517373
--- /dev/null
+++ b/Test/iomap.crossStage.vk.geom
@@ -0,0 +1,35 @@
+#version 460
+
+layout(points) in;
+layout(triangle_strip, max_vertices=3) out;
+
+in vec4 vgo1[];
+in vec2 vgo2[];
+
+layout(location = 5) in outBlock {
+ vec4 o3;
+} inBlock[];
+
+out vec4 gfo1;
+out vec2 gfo2;
+
+layout(location = 5) out outBlock {
+ vec4 o3;
+} gf_out;
+
+uniform crossStageBlock2 {
+ uniform vec4 a;
+ vec2 b;
+} blockName1 [2]; // instance name different from frag
+
+void main()
+{
+ for (int i = 0; i < 3; i++) {
+ gfo1 = vec4(0);
+ gfo2 = vec2(0);
+ gf_out.o3 = inBlock[i].o3;
+ EmitVertex();
+ }
+ EndPrimitive();
+}
+
diff --git a/Test/iomap.crossStage.vk.vert b/Test/iomap.crossStage.vk.vert
new file mode 100644
index 00000000..e422131f
--- /dev/null
+++ b/Test/iomap.crossStage.vk.vert
@@ -0,0 +1,32 @@
+#version 460
+
+out vec4 vgo1; // declaration order different than fragment shader
+out vec2 vgo2; // declaration order different than fragment shader
+
+layout(location = 5) out outBlock {
+ vec4 o3;
+};
+
+layout (binding = 0) uniform sampler2D glass;
+
+uniform crossStageBlock1 {
+ uniform vec4 a;
+ vec4 b;
+};
+
+readonly buffer vertOnlyBlock {
+ vec2 vb1;
+};
+
+uniform crossStageBlock2 {
+ uniform vec4 a;
+ vec2 b;
+} blockName1 [2]; // instance name different from frag
+
+void main()
+{
+ vgo1 = vec4(0);
+ vgo2 = vec2(0);
+ o3 = vec4(0);
+}
+
diff --git a/Test/vk.relaxed.errorcheck.frag b/Test/vk.relaxed.errorcheck.frag
new file mode 100644
index 00000000..b75b50b7
--- /dev/null
+++ b/Test/vk.relaxed.errorcheck.frag
@@ -0,0 +1,16 @@
+#version 460
+
+layout (location = 0) in vec4 io;
+
+out vec4 o;
+
+// default uniforms will be gathered into a uniform block
+uniform vec4 a; // declared in both stages with different types
+
+vec4 foo() {
+ return a;
+}
+
+void main() {
+ o = io + foo();
+} \ No newline at end of file
diff --git a/Test/vk.relaxed.errorcheck.vert b/Test/vk.relaxed.errorcheck.vert
new file mode 100644
index 00000000..b1bdbbec
--- /dev/null
+++ b/Test/vk.relaxed.errorcheck.vert
@@ -0,0 +1,15 @@
+#version 460
+
+layout (location = 0) out vec4 io;
+
+// default uniforms will be gathered into a uniform block
+// final global block will merge uniforms from all linked files
+uniform vec2 a; // declared in both stages with different type
+
+vec4 foo() {
+ return a.xyxy;
+}
+
+void main() {
+ io = foo();
+} \ No newline at end of file
diff --git a/Test/vk.relaxed.frag b/Test/vk.relaxed.frag
new file mode 100644
index 00000000..d43416e0
--- /dev/null
+++ b/Test/vk.relaxed.frag
@@ -0,0 +1,74 @@
+#version 460
+
+out vec4 o;
+
+// default uniforms will be gathered into a uniform block
+uniform vec4 a;
+uniform vec2 b = vec2(0, 0); // initializer will be ignored
+layout(location = 0) uniform vec2 c; // location qualifier will be ignored
+uniform vec4 d[10];
+uniform struct e {
+ vec2 x;
+ float y;
+ uint z;
+} structUniform;
+
+// opaque types will not be grouped into uniform block
+uniform sampler2D t1;
+
+// shared and packed layout qualifier are silently ignored
+layout(shared) uniform UniformBlock {
+ float j;
+ vec4 k;
+};
+
+layout(packed) buffer BufferBlock {
+ float j;
+ vec4 k;
+} bufferInstance;
+
+// atomic_uint will be converted to uint and gathered in a buffer block
+layout(binding = 0) uniform atomic_uint counter1; // offset not used
+layout(binding = 0) uniform atomic_uint counter2; // offset not used
+layout(binding = 1) uniform atomic_uint counter3; // offset not used
+
+// atomic counter functions will be converted to equivalent integer atomic operations
+uint bar() {
+ uint j = 0;
+ j = atomicCounterIncrement(counter1);
+ j = atomicCounterDecrement(counter1);
+ j = atomicCounter(counter1);
+
+ j = atomicCounterAdd(counter1, 1);
+ j = atomicCounterAdd(counter1, -1);
+ j = atomicCounterSubtract(counter1, 1);
+
+ j = atomicCounterMin(counter1, j);
+ j = atomicCounterMax(counter1, j);
+ j = atomicCounterAnd(counter1, j);
+
+ j = atomicCounterOr(counter1, j);
+ j = atomicCounterXor(counter1, j);
+
+ j = atomicCounterExchange(counter1, j);
+ j = atomicCounterCompSwap(counter1, 0, j);
+
+ atomicCounterIncrement(counter2);
+ atomicCounterIncrement(counter3);
+
+ memoryBarrierAtomicCounter();
+
+ return j;
+}
+
+vec4 foo() {
+ float f = j + bufferInstance.j + structUniform.y + structUniform.z;
+ vec2 v2 = b + c + structUniform.x;
+ vec4 v4 = a + d[0] + d[1] + d[2] + k + bufferInstance.k + texture(t1, vec2(0, 0));
+ return vec4(f) * vec4(v2, 1, 1) * v4;
+}
+
+void main() {
+ float j = float(bar());
+ o = j * foo();
+} \ No newline at end of file
diff --git a/Test/vk.relaxed.link1.frag b/Test/vk.relaxed.link1.frag
new file mode 100644
index 00000000..95b609f2
--- /dev/null
+++ b/Test/vk.relaxed.link1.frag
@@ -0,0 +1,28 @@
+#version 460
+
+out vec4 o;
+
+// default uniforms will be gathered into a uniform block
+// final global block will merge uniforms from all linked files
+uniform vec4 a; // declared in both stages
+uniform vec2 b1; // declaration order swapped in other stage
+uniform vec2 b2;
+uniform vec4 c1; // not delcared in other file
+uniform vec4 d;
+
+// final global buffer will berge buffers from all linked files
+layout (binding = 0) uniform atomic_uint counter1;
+layout (binding = 0) uniform atomic_uint counter2;
+
+vec4 foo();
+
+vec4 bar() {
+ uint j = atomicCounterIncrement(counter1) + atomicCounterDecrement(counter2);
+ vec4 v = a + vec4(b1.x, b1.y, b2.x, b2.y) + c1 + d;
+
+ return float(j) * v;
+}
+
+void main() {
+ o = foo() + bar();
+} \ No newline at end of file
diff --git a/Test/vk.relaxed.link2.frag b/Test/vk.relaxed.link2.frag
new file mode 100644
index 00000000..a4f468a4
--- /dev/null
+++ b/Test/vk.relaxed.link2.frag
@@ -0,0 +1,19 @@
+#version 460
+
+// default uniforms will be gathered into a uniform block
+// final global block will merge uniforms from all linked files
+uniform vec4 a; // declared in both stages
+uniform vec2 b2; // declaration order swapped in other stage
+uniform vec2 b1;
+uniform vec4 c2; // not delcared in other file
+uniform vec4 d;
+
+layout (binding = 0) uniform atomic_uint counter3;
+layout (binding = 0) uniform atomic_uint counter2;
+
+vec4 foo() {
+ uint j = atomicCounterIncrement(counter2) + atomicCounterDecrement(counter3);
+ vec4 v = a + vec4(b1.x, b1.y, b2.x, b2.y) + c2 + d;
+
+ return float(j) * v;
+} \ No newline at end of file
diff --git a/Test/vk.relaxed.stagelink.frag b/Test/vk.relaxed.stagelink.frag
new file mode 100644
index 00000000..d1eebba0
--- /dev/null
+++ b/Test/vk.relaxed.stagelink.frag
@@ -0,0 +1,28 @@
+#version 460
+
+layout (location = 0) in vec4 io;
+
+out vec4 o;
+
+// default uniforms will be gathered into a uniform block
+// final global block will merge uniforms from all linked files
+uniform vec4 a; // declared in both stages
+uniform vec2 b1; // declaration order swapped in other stage
+uniform vec2 b2;
+uniform vec4 c1; // not delcared in other file
+uniform vec4 d;
+
+// final global buffer will berge buffers from all linked files
+layout (binding = 0) uniform atomic_uint counter1;
+layout (binding = 0) uniform atomic_uint counter2;
+
+vec4 foo() {
+ uint j = atomicCounterIncrement(counter1) + atomicCounterDecrement(counter2);
+ vec4 v = a + vec4(b1.x, b1.y, b2.x, b2.y) + c1 + d;
+
+ return float(j) * v;
+}
+
+void main() {
+ o = io + foo();
+} \ No newline at end of file
diff --git a/Test/vk.relaxed.stagelink.vert b/Test/vk.relaxed.stagelink.vert
new file mode 100644
index 00000000..52396ac5
--- /dev/null
+++ b/Test/vk.relaxed.stagelink.vert
@@ -0,0 +1,31 @@
+#version 460
+
+layout (location = 0) out vec4 io;
+
+// default uniforms will be gathered into a uniform block
+// final global block will merge uniforms from all linked files
+uniform vec4 a; // declared in both stages
+uniform vec2 b2; // declaration order swapped in other stage
+uniform vec2 b1;
+uniform vec4 c2; // not delcared in other file
+uniform vec4 d;
+
+uniform vec4 s[4];
+
+layout (binding = 0) uniform atomic_uint counter3;
+layout (binding = 0) uniform atomic_uint counter2;
+
+vec4 foo() {
+ uint j = atomicCounterIncrement(counter2) + atomicCounterDecrement(counter3);
+ vec4 v = a + vec4(b1.x, b1.y, b2.x, b2.y) + c2 + d;
+
+ return float(j) * v;
+}
+
+void main() {
+
+ vec4 v = foo();
+ v = v + s[gl_VertexID];
+ v.x = v.x - float(gl_InstanceID);
+ io = v;
+} \ No newline at end of file
diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h
index 603203db..bb6d0bd8 100644
--- a/glslang/Include/Types.h
+++ b/glslang/Include/Types.h
@@ -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;
diff --git a/glslang/Include/intermediate.h b/glslang/Include/intermediate.h
index 85edd635..1440c205 100644
--- a/glslang/Include/intermediate.h
+++ b/glslang/Include/intermediate.h
@@ -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(); }
diff --git a/glslang/MachineIndependent/Initialize.cpp b/glslang/MachineIndependent/Initialize.cpp
index c94a8a4b..a9e5af45 100644
--- a/glslang/MachineIndependent/Initialize.cpp
+++ b/glslang/MachineIndependent/Initialize.cpp
@@ -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);
diff --git a/glslang/MachineIndependent/ParseContextBase.cpp b/glslang/MachineIndependent/ParseContextBase.cpp
index 3efa27ac..02cca409 100644
--- a/glslang/MachineIndependent/ParseContextBase.cpp
+++ b/glslang/MachineIndependent/ParseContextBase.cpp
@@ -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()
{
diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp
index 12d68a3e..550fce67 100644
--- a/glslang/MachineIndependent/ParseHelper.cpp
+++ b/glslang/MachineIndependent/ParseHelper.cpp
@@ -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)
diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h
index ad9b8d6a..6f00621a 100644
--- a/glslang/MachineIndependent/ParseHelper.h
+++ b/glslang/MachineIndependent/ParseHelper.h
@@ -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
diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp
index 3f793a74..4b340eaa 100644
--- a/glslang/MachineIndependent/ShaderLang.cpp
+++ b/glslang/MachineIndependent/ShaderLang.cpp
@@ -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();
diff --git a/glslang/MachineIndependent/Versions.cpp b/glslang/MachineIndependent/Versions.cpp
index 488c98c5..7554bfd7 100644
--- a/glslang/MachineIndependent/Versions.cpp
+++ b/glslang/MachineIndependent/Versions.cpp
@@ -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, "");
}
diff --git a/glslang/MachineIndependent/Versions.h b/glslang/MachineIndependent/Versions.h
index f377973a..25feb0b7 100644
--- a/glslang/MachineIndependent/Versions.h
+++ b/glslang/MachineIndependent/Versions.h
@@ -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
};
//
diff --git a/glslang/MachineIndependent/intermOut.cpp b/glslang/MachineIndependent/intermOut.cpp
index 5ce3e472..c718f949 100644
--- a/glslang/MachineIndependent/intermOut.cpp
+++ b/glslang/MachineIndependent/intermOut.cpp
@@ -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;
diff --git a/glslang/MachineIndependent/iomapper.cpp b/glslang/MachineIndependent/iomapper.cpp
index c42e74fa..7e12864f 100644
--- a/glslang/MachineIndependent/iomapper.cpp
+++ b/glslang/MachineIndependent/iomapper.cpp
@@ -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); }
diff --git a/glslang/MachineIndependent/iomapper.h b/glslang/MachineIndependent/iomapper.h
index 1dce8ff5..07357c2e 100644
--- a/glslang/MachineIndependent/iomapper.h
+++ b/glslang/MachineIndependent/iomapper.h
@@ -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;
diff --git a/glslang/MachineIndependent/linkValidate.cpp b/glslang/MachineIndependent/linkValidate.cpp
index 3f3a3127..789dc3c3 100644
--- a/glslang/MachineIndependent/linkValidate.cpp
+++ b/glslang/MachineIndependent/linkValidate.cpp
@@ -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
diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h
index 9fe684a3..9bfa35cc 100644
--- a/glslang/MachineIndependent/localintermediate.h
+++ b/glslang/MachineIndependent/localintermediate.h
@@ -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
diff --git a/glslang/Public/ShaderLang.h b/glslang/Public/ShaderLang.h
index e147b0dc..74b9f3ee 100644
--- a/glslang/Public/ShaderLang.h
+++ b/glslang/Public/ShaderLang.h
@@ -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];
diff --git a/gtests/CMakeLists.txt b/gtests/CMakeLists.txt
index 0617ff85..74c9809a 100644
--- a/gtests/CMakeLists.txt
+++ b/gtests/CMakeLists.txt
@@ -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
index 00000000..574e905f
--- /dev/null
+++ b/gtests/GlslMapIO.FromFile.cpp
@@ -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
diff --git a/gtests/Link.FromFile.Vk.cpp b/gtests/Link.FromFile.Vk.cpp
index 2909a9c1..5e005a46 100644
--- a/gtests/Link.FromFile.Vk.cpp
+++ b/gtests/Link.FromFile.Vk.cpp
@@ -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
index 00000000..d791d6cc
--- /dev/null
+++ b/gtests/VkRelaxed.FromFile.cpp
@@ -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