Test additional atomic image SPIR-V operations
This commit adds tests to check OpAtomicIIncrement, OpAtomicIDecrement
and OpAtomicISub with images.
New tests:
dEQP-VK.image.atomic_operations.sub.*
dEQP-VK.image.atomic_operations.inc.*
dEQP-VK.image.atomic_operations.dec.*
Components: Framework, Vulkan
VK-GL-CTS issue: 2186
Change-Id: Ib2c5d5075555ad0be025b0498960b646852fdcd4
diff --git a/AndroidGen.mk b/AndroidGen.mk
index 94b62d9..816e5d6 100644
--- a/AndroidGen.mk
+++ b/AndroidGen.mk
@@ -159,6 +159,7 @@
external/vulkancts/modules/vulkan/geometry/vktGeometryVaryingGeometryShaderTests.cpp \
external/vulkancts/modules/vulkan/image/vktImageAstcDecodeModeTests.cpp \
external/vulkancts/modules/vulkan/image/vktImageAtomicOperationTests.cpp \
+ external/vulkancts/modules/vulkan/image/vktImageAtomicSpirvShaders.cpp \
external/vulkancts/modules/vulkan/image/vktImageCompressionTranscodingSupport.cpp \
external/vulkancts/modules/vulkan/image/vktImageLoadStoreTests.cpp \
external/vulkancts/modules/vulkan/image/vktImageLoadStoreUtil.cpp \
diff --git a/android/cts/master/vk-master.txt b/android/cts/master/vk-master.txt
index df49b59..93b763b 100644
--- a/android/cts/master/vk-master.txt
+++ b/android/cts/master/vk-master.txt
Binary files differ
diff --git a/external/vulkancts/modules/vulkan/image/CMakeLists.txt b/external/vulkancts/modules/vulkan/image/CMakeLists.txt
index 19ba98c..b8d3c45 100644
--- a/external/vulkancts/modules/vulkan/image/CMakeLists.txt
+++ b/external/vulkancts/modules/vulkan/image/CMakeLists.txt
@@ -9,6 +9,8 @@
vktImageAstcDecodeModeTests.hpp
vktImageAtomicOperationTests.cpp
vktImageAtomicOperationTests.hpp
+ vktImageAtomicSpirvShaders.cpp
+ vktImageAtomicSpirvShaders.hpp
vktImageLoadStoreTests.cpp
vktImageLoadStoreTests.hpp
vktImageMutableTests.cpp
diff --git a/external/vulkancts/modules/vulkan/image/vktImageAtomicOperationTests.cpp b/external/vulkancts/modules/vulkan/image/vktImageAtomicOperationTests.cpp
index 66d9265..a6e624b 100644
--- a/external/vulkancts/modules/vulkan/image/vktImageAtomicOperationTests.cpp
+++ b/external/vulkancts/modules/vulkan/image/vktImageAtomicOperationTests.cpp
@@ -22,6 +22,7 @@
*//*--------------------------------------------------------------------*/
#include "vktImageAtomicOperationTests.hpp"
+#include "vktImageAtomicSpirvShaders.hpp"
#include "deUniquePtr.hpp"
#include "deStringUtil.hpp"
@@ -41,6 +42,7 @@
#include "tcuTextureUtil.hpp"
#include "tcuTexture.hpp"
#include "tcuVectorType.hpp"
+#include "tcuStringTemplate.hpp"
namespace vkt
{
@@ -79,6 +81,9 @@
enum AtomicOperation
{
ATOMIC_OPERATION_ADD = 0,
+ ATOMIC_OPERATION_SUB,
+ ATOMIC_OPERATION_INC,
+ ATOMIC_OPERATION_DEC,
ATOMIC_OPERATION_MIN,
ATOMIC_OPERATION_MAX,
ATOMIC_OPERATION_AND,
@@ -146,6 +151,9 @@
switch (op)
{
case ATOMIC_OPERATION_ADD: return string("add");
+ case ATOMIC_OPERATION_SUB: return string("sub");
+ case ATOMIC_OPERATION_INC: return string("inc");
+ case ATOMIC_OPERATION_DEC: return string("dec");
case ATOMIC_OPERATION_MIN: return string("min");
case ATOMIC_OPERATION_MAX: return string("max");
case ATOMIC_OPERATION_AND: return string("and");
@@ -183,6 +191,9 @@
{
// \note 18 is just an arbitrary small nonzero value.
case ATOMIC_OPERATION_ADD: return 18;
+ case ATOMIC_OPERATION_INC: return 18;
+ case ATOMIC_OPERATION_SUB: return (1 << 24) - 1;
+ case ATOMIC_OPERATION_DEC: return (1 << 24) - 1;
case ATOMIC_OPERATION_MIN: return (1 << 15) - 1;
case ATOMIC_OPERATION_MAX: return 18;
case ATOMIC_OPERATION_AND: return (1 << 15) - 1;
@@ -209,10 +220,14 @@
{
// \note Fall-throughs.
case ATOMIC_OPERATION_ADD:
+ case ATOMIC_OPERATION_SUB:
case ATOMIC_OPERATION_AND:
case ATOMIC_OPERATION_OR:
case ATOMIC_OPERATION_XOR:
return x*x + y*y + z*z;
+ case ATOMIC_OPERATION_INC:
+ case ATOMIC_OPERATION_DEC:
+ return 1;
case ATOMIC_OPERATION_MIN:
case ATOMIC_OPERATION_MAX:
// multiply half of the data by -1
@@ -230,6 +245,9 @@
static bool isOrderIndependentAtomicOperation (const AtomicOperation op)
{
return op == ATOMIC_OPERATION_ADD ||
+ op == ATOMIC_OPERATION_SUB ||
+ op == ATOMIC_OPERATION_INC ||
+ op == ATOMIC_OPERATION_DEC ||
op == ATOMIC_OPERATION_MIN ||
op == ATOMIC_OPERATION_MAX ||
op == ATOMIC_OPERATION_AND ||
@@ -237,13 +255,54 @@
op == ATOMIC_OPERATION_XOR;
}
+//! Checks if the operation needs an SPIR-V shader.
+static bool isSpirvAtomicOperation (const AtomicOperation op)
+{
+ return op == ATOMIC_OPERATION_SUB ||
+ op == ATOMIC_OPERATION_INC ||
+ op == ATOMIC_OPERATION_DEC;
+}
+
+//! Returns the SPIR-V assembler name of the given operation.
+static std::string getSpirvAtomicOpName (const AtomicOperation op)
+{
+ switch (op)
+ {
+ case ATOMIC_OPERATION_SUB: return "OpAtomicISub";
+ case ATOMIC_OPERATION_INC: return "OpAtomicIIncrement";
+ case ATOMIC_OPERATION_DEC: return "OpAtomicIDecrement";
+ default: break;
+ }
+
+ DE_ASSERT(false);
+ return "";
+}
+
+//! Returns true if the given SPIR-V operation does not need the last argument, compared to OpAtomicIAdd.
+static bool isSpirvAtomicNoLastArgOp (const AtomicOperation op)
+{
+ switch (op)
+ {
+ case ATOMIC_OPERATION_SUB: return false;
+ case ATOMIC_OPERATION_INC: // fallthrough
+ case ATOMIC_OPERATION_DEC: return true;
+ default: break;
+ }
+
+ DE_ASSERT(false);
+ return false;
+}
+
//! Computes the result of an atomic operation where "a" is the data operated on and "b" is the parameter to the atomic function.
template <typename T>
static T computeBinaryAtomicOperationResult (const AtomicOperation op, const T a, const T b)
{
switch (op)
{
+ case ATOMIC_OPERATION_INC: // fallthrough.
case ATOMIC_OPERATION_ADD: return a + b;
+ case ATOMIC_OPERATION_DEC: // fallthrough.
+ case ATOMIC_OPERATION_SUB: return a - b;
case ATOMIC_OPERATION_MIN: return de::min(a, b);
case ATOMIC_OPERATION_MAX: return de::max(a, b);
case ATOMIC_OPERATION_AND: return a & b;
@@ -306,36 +365,51 @@
void BinaryAtomicEndResultCase::initPrograms (SourceCollections& sourceCollections) const
{
- const string versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
+ if (isSpirvAtomicOperation(m_operation))
+ {
+ const CaseVariant caseVariant{m_imageType, m_format.order, m_format.type, CaseVariant::CHECK_TYPE_END_RESULTS};
+ const tcu::StringTemplate shaderTemplate{getSpirvAtomicOpShader(caseVariant)};
+ std::map<std::string, std::string> specializations;
- const bool uintFormat = isUintFormat(mapTextureFormat(m_format));
- const bool intFormat = isIntFormat(mapTextureFormat(m_format));
- const UVec3 gridSize = getShaderGridSize(m_imageType, m_imageSize);
- const string atomicCoord = getCoordStr(m_imageType, "gx % " + toString(gridSize.x()), "gy", "gz");
+ specializations["OPNAME"] = getSpirvAtomicOpName(m_operation);
+ if (isSpirvAtomicNoLastArgOp(m_operation))
+ specializations["LASTARG"] = "";
- const string atomicArgExpr = (uintFormat ? "uint" : intFormat ? "int" : "float")
- + getAtomicFuncArgumentShaderStr(m_operation, "gx", "gy", "gz", IVec3(NUM_INVOCATIONS_PER_PIXEL*gridSize.x(), gridSize.y(), gridSize.z()));
+ sourceCollections.spirvAsmSources.add(m_name) << shaderTemplate.specialize(specializations);
+ }
+ else
+ {
+ const string versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
- const string compareExchangeStr = (m_operation == ATOMIC_OPERATION_COMPARE_EXCHANGE) ? ", 18" + string(uintFormat ? "u" : "") : "";
- const string atomicInvocation = getAtomicOperationShaderFuncName(m_operation) + "(u_resultImage, " + atomicCoord + compareExchangeStr + ", " + atomicArgExpr + ")";
- const string shaderImageFormatStr = getShaderImageFormatQualifier(m_format);
- const string shaderImageTypeStr = getShaderImageType(m_format, m_imageType);
+ const bool uintFormat = isUintFormat(mapTextureFormat(m_format));
+ const bool intFormat = isIntFormat(mapTextureFormat(m_format));
+ const UVec3 gridSize = getShaderGridSize(m_imageType, m_imageSize);
+ const string atomicCoord = getCoordStr(m_imageType, "gx % " + toString(gridSize.x()), "gy", "gz");
- string source = versionDecl + "\n"
- "precision highp " + shaderImageTypeStr + ";\n"
- "\n"
- "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
- "layout (" + shaderImageFormatStr + ", binding=0) coherent uniform " + shaderImageTypeStr + " u_resultImage;\n"
- "\n"
- "void main (void)\n"
- "{\n"
- " int gx = int(gl_GlobalInvocationID.x);\n"
- " int gy = int(gl_GlobalInvocationID.y);\n"
- " int gz = int(gl_GlobalInvocationID.z);\n"
- " " + atomicInvocation + ";\n"
- "}\n";
+ const string atomicArgExpr = (uintFormat ? "uint" : intFormat ? "int" : "float")
+ + getAtomicFuncArgumentShaderStr(m_operation, "gx", "gy", "gz", IVec3(NUM_INVOCATIONS_PER_PIXEL*gridSize.x(), gridSize.y(), gridSize.z()));
- sourceCollections.glslSources.add(m_name) << glu::ComputeSource(source.c_str());
+ const string compareExchangeStr = (m_operation == ATOMIC_OPERATION_COMPARE_EXCHANGE) ? ", 18" + string(uintFormat ? "u" : "") : "";
+ const string atomicInvocation = getAtomicOperationShaderFuncName(m_operation) + "(u_resultImage, " + atomicCoord + compareExchangeStr + ", " + atomicArgExpr + ")";
+ const string shaderImageFormatStr = getShaderImageFormatQualifier(m_format);
+ const string shaderImageTypeStr = getShaderImageType(m_format, m_imageType);
+
+ string source = versionDecl + "\n"
+ "precision highp " + shaderImageTypeStr + ";\n"
+ "\n"
+ "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
+ "layout (" + shaderImageFormatStr + ", binding=0) coherent uniform " + shaderImageTypeStr + " u_resultImage;\n"
+ "\n"
+ "void main (void)\n"
+ "{\n"
+ " int gx = int(gl_GlobalInvocationID.x);\n"
+ " int gy = int(gl_GlobalInvocationID.y);\n"
+ " int gz = int(gl_GlobalInvocationID.z);\n"
+ " " + atomicInvocation + ";\n"
+ "}\n";
+
+ sourceCollections.glslSources.add(m_name) << glu::ComputeSource(source.c_str());
+ }
}
class BinaryAtomicIntermValuesCase : public vkt::TestCase
@@ -387,38 +461,53 @@
void BinaryAtomicIntermValuesCase::initPrograms (SourceCollections& sourceCollections) const
{
- const string versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
+ if (isSpirvAtomicOperation(m_operation))
+ {
+ const CaseVariant caseVariant{m_imageType, m_format.order, m_format.type, CaseVariant::CHECK_TYPE_INTERMEDIATE_RESULTS};
+ const tcu::StringTemplate shaderTemplate{getSpirvAtomicOpShader(caseVariant)};
+ std::map<std::string, std::string> specializations;
- const bool uintFormat = isUintFormat(mapTextureFormat(m_format));
- const bool intFormat = isIntFormat(mapTextureFormat(m_format));
- const string colorVecTypeName = string(uintFormat ? "u" : intFormat ? "i" : "") + "vec4";
- const UVec3 gridSize = getShaderGridSize(m_imageType, m_imageSize);
- const string atomicCoord = getCoordStr(m_imageType, "gx % " + toString(gridSize.x()), "gy", "gz");
- const string invocationCoord = getCoordStr(m_imageType, "gx", "gy", "gz");
- const string atomicArgExpr = (uintFormat ? "uint" : intFormat ? "int" : "float")
- + getAtomicFuncArgumentShaderStr(m_operation, "gx", "gy", "gz", IVec3(NUM_INVOCATIONS_PER_PIXEL*gridSize.x(), gridSize.y(), gridSize.z()));
+ specializations["OPNAME"] = getSpirvAtomicOpName(m_operation);
+ if (isSpirvAtomicNoLastArgOp(m_operation))
+ specializations["LASTARG"] = "";
- const string compareExchangeStr = (m_operation == ATOMIC_OPERATION_COMPARE_EXCHANGE) ? ", 18" + string(uintFormat ? "u" : "") : "";
- const string atomicInvocation = getAtomicOperationShaderFuncName(m_operation) + "(u_resultImage, " + atomicCoord + compareExchangeStr + ", " + atomicArgExpr + ")";
- const string shaderImageFormatStr = getShaderImageFormatQualifier(m_format);
- const string shaderImageTypeStr = getShaderImageType(m_format, m_imageType);
+ sourceCollections.spirvAsmSources.add(m_name) << shaderTemplate.specialize(specializations);
+ }
+ else
+ {
+ const string versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
- string source = versionDecl + "\n"
- "precision highp " + shaderImageTypeStr + ";\n"
- "\n"
- "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
- "layout (" + shaderImageFormatStr + ", binding=0) coherent uniform " + shaderImageTypeStr + " u_resultImage;\n"
- "layout (" + shaderImageFormatStr + ", binding=1) writeonly uniform " + shaderImageTypeStr + " u_intermValuesImage;\n"
- "\n"
- "void main (void)\n"
- "{\n"
- " int gx = int(gl_GlobalInvocationID.x);\n"
- " int gy = int(gl_GlobalInvocationID.y);\n"
- " int gz = int(gl_GlobalInvocationID.z);\n"
- " imageStore(u_intermValuesImage, " + invocationCoord + ", " + colorVecTypeName + "(" + atomicInvocation + "));\n"
- "}\n";
+ const bool uintFormat = isUintFormat(mapTextureFormat(m_format));
+ const bool intFormat = isIntFormat(mapTextureFormat(m_format));
+ const string colorVecTypeName = string(uintFormat ? "u" : intFormat ? "i" : "") + "vec4";
+ const UVec3 gridSize = getShaderGridSize(m_imageType, m_imageSize);
+ const string atomicCoord = getCoordStr(m_imageType, "gx % " + toString(gridSize.x()), "gy", "gz");
+ const string invocationCoord = getCoordStr(m_imageType, "gx", "gy", "gz");
+ const string atomicArgExpr = (uintFormat ? "uint" : intFormat ? "int" : "float")
+ + getAtomicFuncArgumentShaderStr(m_operation, "gx", "gy", "gz", IVec3(NUM_INVOCATIONS_PER_PIXEL*gridSize.x(), gridSize.y(), gridSize.z()));
- sourceCollections.glslSources.add(m_name) << glu::ComputeSource(source.c_str());
+ const string compareExchangeStr = (m_operation == ATOMIC_OPERATION_COMPARE_EXCHANGE) ? ", 18" + string(uintFormat ? "u" : "") : "";
+ const string atomicInvocation = getAtomicOperationShaderFuncName(m_operation) + "(u_resultImage, " + atomicCoord + compareExchangeStr + ", " + atomicArgExpr + ")";
+ const string shaderImageFormatStr = getShaderImageFormatQualifier(m_format);
+ const string shaderImageTypeStr = getShaderImageType(m_format, m_imageType);
+
+ string source = versionDecl + "\n"
+ "precision highp " + shaderImageTypeStr + ";\n"
+ "\n"
+ "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
+ "layout (" + shaderImageFormatStr + ", binding=0) coherent uniform " + shaderImageTypeStr + " u_resultImage;\n"
+ "layout (" + shaderImageFormatStr + ", binding=1) writeonly uniform " + shaderImageTypeStr + " u_intermValuesImage;\n"
+ "\n"
+ "void main (void)\n"
+ "{\n"
+ " int gx = int(gl_GlobalInvocationID.x);\n"
+ " int gy = int(gl_GlobalInvocationID.y);\n"
+ " int gz = int(gl_GlobalInvocationID.z);\n"
+ " imageStore(u_intermValuesImage, " + invocationCoord + ", " + colorVecTypeName + "(" + atomicInvocation + "));\n"
+ "}\n";
+
+ sourceCollections.glslSources.add(m_name) << glu::ComputeSource(source.c_str());
+ }
}
class BinaryAtomicInstanceBase : public vkt::TestInstance
diff --git a/external/vulkancts/modules/vulkan/image/vktImageAtomicSpirvShaders.cpp b/external/vulkancts/modules/vulkan/image/vktImageAtomicSpirvShaders.cpp
new file mode 100644
index 0000000..59da84e
--- /dev/null
+++ b/external/vulkancts/modules/vulkan/image/vktImageAtomicSpirvShaders.cpp
@@ -0,0 +1,2903 @@
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2020 Valve Corporation.
+ * Copyright (c) 2020 The Khronos Group Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Helper SPIR-V shaders for some image atomic operations.
+ *//*--------------------------------------------------------------------*/
+
+#include "vktImageAtomicSpirvShaders.hpp"
+
+#include <array>
+#include <map>
+
+namespace vkt
+{
+namespace image
+{
+
+namespace
+{
+
+const std::string kShader_1d_r32ui_end_result = R"(
+; The SPIR-V shader below is based on the following GLSL shader, but OpAtomicIAdd has been
+; replaced with a template parameter and the last argument for it has been made optional.
+;
+; #version 440
+; precision highp uimage1D;
+;
+; layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+; layout (r32ui, binding=0) coherent uniform uimage1D u_resultImage;
+;
+; void main (void)
+; {
+; int gx = int(gl_GlobalInvocationID.x);
+; int gy = int(gl_GlobalInvocationID.y);
+; int gz = int(gl_GlobalInvocationID.z);
+; imageAtomicAdd(u_resultImage, gx % 64, uint(gx*gx + gy*gy + gz*gz));
+; }
+;
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 50
+; Schema: 0
+OpCapability Shader
+OpCapability Image1D
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %4 "main" %12
+OpExecutionMode %4 LocalSize 1 1 1
+OpDecorate %12 BuiltIn GlobalInvocationId
+OpDecorate %30 DescriptorSet 0
+OpDecorate %30 Binding 0
+OpDecorate %30 Coherent
+OpDecorate %49 BuiltIn WorkgroupSize
+%2 = OpTypeVoid
+%3 = OpTypeFunction %2
+%6 = OpTypeInt 32 1
+%7 = OpTypePointer Function %6
+%9 = OpTypeInt 32 0
+%10 = OpTypeVector %9 3
+%11 = OpTypePointer Input %10
+%12 = OpVariable %11 Input
+%13 = OpConstant %9 0
+%14 = OpTypePointer Input %9
+%19 = OpConstant %9 1
+%24 = OpConstant %9 2
+%28 = OpTypeImage %9 1D 0 0 0 2 R32ui
+%29 = OpTypePointer UniformConstant %28
+%30 = OpVariable %29 UniformConstant
+%32 = OpConstant %6 64
+%46 = OpTypePointer Image %9
+%49 = OpConstantComposite %10 %19 %19 %19
+%4 = OpFunction %2 None %3
+%5 = OpLabel
+%8 = OpVariable %7 Function
+%18 = OpVariable %7 Function
+%23 = OpVariable %7 Function
+%15 = OpAccessChain %14 %12 %13
+%16 = OpLoad %9 %15
+%17 = OpBitcast %6 %16
+OpStore %8 %17
+%20 = OpAccessChain %14 %12 %19
+%21 = OpLoad %9 %20
+%22 = OpBitcast %6 %21
+OpStore %18 %22
+%25 = OpAccessChain %14 %12 %24
+%26 = OpLoad %9 %25
+%27 = OpBitcast %6 %26
+OpStore %23 %27
+%31 = OpLoad %6 %8
+%33 = OpSMod %6 %31 %32
+%34 = OpLoad %6 %8
+%35 = OpLoad %6 %8
+%36 = OpIMul %6 %34 %35
+%37 = OpLoad %6 %18
+%38 = OpLoad %6 %18
+%39 = OpIMul %6 %37 %38
+%40 = OpIAdd %6 %36 %39
+%41 = OpLoad %6 %23
+%42 = OpLoad %6 %23
+%43 = OpIMul %6 %41 %42
+%44 = OpIAdd %6 %40 %43
+%45 = OpBitcast %9 %44
+%47 = OpImageTexelPointer %46 %30 %33 %13
+%48 = ${OPNAME} %9 %47 %19 %13 ${LASTARG:default=%45}
+OpReturn
+OpFunctionEnd
+)";
+
+const std::string kShader_1d_r32ui_intermediate_values = R"(
+; The SPIR-V shader below is based on the following GLSL shader, but OpAtomicIAdd has been
+; replaced with a template parameter and the last argument for it has been made optional.
+;
+; #version 440
+; precision highp uimage1D;
+;
+; layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+; layout (r32ui, binding=0) coherent uniform uimage1D u_resultImage;
+; layout (r32ui, binding=1) writeonly uniform uimage1D u_intermValuesImage;
+;
+; void main (void)
+; {
+; int gx = int(gl_GlobalInvocationID.x);
+; int gy = int(gl_GlobalInvocationID.y);
+; int gz = int(gl_GlobalInvocationID.z);
+; imageStore(u_intermValuesImage, gx, uvec4(imageAtomicAdd(u_resultImage, gx % 64, uint(gx*gx + gy*gy + gz*gz))));
+; }
+;
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 55
+; Schema: 0
+OpCapability Shader
+OpCapability Image1D
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %4 "main" %12
+OpExecutionMode %4 LocalSize 1 1 1
+OpDecorate %12 BuiltIn GlobalInvocationId
+OpDecorate %30 DescriptorSet 0
+OpDecorate %30 Binding 1
+OpDecorate %30 NonReadable
+OpDecorate %33 DescriptorSet 0
+OpDecorate %33 Binding 0
+OpDecorate %33 Coherent
+OpDecorate %54 BuiltIn WorkgroupSize
+%2 = OpTypeVoid
+%3 = OpTypeFunction %2
+%6 = OpTypeInt 32 1
+%7 = OpTypePointer Function %6
+%9 = OpTypeInt 32 0
+%10 = OpTypeVector %9 3
+%11 = OpTypePointer Input %10
+%12 = OpVariable %11 Input
+%13 = OpConstant %9 0
+%14 = OpTypePointer Input %9
+%19 = OpConstant %9 1
+%24 = OpConstant %9 2
+%28 = OpTypeImage %9 1D 0 0 0 2 R32ui
+%29 = OpTypePointer UniformConstant %28
+%30 = OpVariable %29 UniformConstant
+%33 = OpVariable %29 UniformConstant
+%35 = OpConstant %6 64
+%49 = OpTypePointer Image %9
+%52 = OpTypeVector %9 4
+%54 = OpConstantComposite %10 %19 %19 %19
+%4 = OpFunction %2 None %3
+%5 = OpLabel
+%8 = OpVariable %7 Function
+%18 = OpVariable %7 Function
+%23 = OpVariable %7 Function
+%15 = OpAccessChain %14 %12 %13
+%16 = OpLoad %9 %15
+%17 = OpBitcast %6 %16
+OpStore %8 %17
+%20 = OpAccessChain %14 %12 %19
+%21 = OpLoad %9 %20
+%22 = OpBitcast %6 %21
+OpStore %18 %22
+%25 = OpAccessChain %14 %12 %24
+%26 = OpLoad %9 %25
+%27 = OpBitcast %6 %26
+OpStore %23 %27
+%31 = OpLoad %28 %30
+%32 = OpLoad %6 %8
+%34 = OpLoad %6 %8
+%36 = OpSMod %6 %34 %35
+%37 = OpLoad %6 %8
+%38 = OpLoad %6 %8
+%39 = OpIMul %6 %37 %38
+%40 = OpLoad %6 %18
+%41 = OpLoad %6 %18
+%42 = OpIMul %6 %40 %41
+%43 = OpIAdd %6 %39 %42
+%44 = OpLoad %6 %23
+%45 = OpLoad %6 %23
+%46 = OpIMul %6 %44 %45
+%47 = OpIAdd %6 %43 %46
+%48 = OpBitcast %9 %47
+%50 = OpImageTexelPointer %49 %33 %36 %13
+%51 = ${OPNAME} %9 %50 %19 %13 ${LASTARG:default=%48}
+%53 = OpCompositeConstruct %52 %51 %51 %51 %51
+OpImageWrite %31 %32 %53
+OpReturn
+OpFunctionEnd
+)";
+
+const std::string kShader_1d_r32i_end_result = R"(
+; The SPIR-V shader below is based on the following GLSL shader, but OpAtomicIAdd has been
+; replaced with a template parameter and the last argument for it has been made optional.
+;
+; #version 440
+; precision highp iimage1D;
+;
+; layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+; layout (r32i, binding=0) coherent uniform iimage1D u_resultImage;
+;
+; void main (void)
+; {
+; int gx = int(gl_GlobalInvocationID.x);
+; int gy = int(gl_GlobalInvocationID.y);
+; int gz = int(gl_GlobalInvocationID.z);
+; imageAtomicAdd(u_resultImage, gx % 64, int(gx*gx + gy*gy + gz*gz));
+; }
+;
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 49
+; Schema: 0
+OpCapability Shader
+OpCapability Image1D
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %4 "main" %12
+OpExecutionMode %4 LocalSize 1 1 1
+OpDecorate %12 BuiltIn GlobalInvocationId
+OpDecorate %30 DescriptorSet 0
+OpDecorate %30 Binding 0
+OpDecorate %30 Coherent
+OpDecorate %48 BuiltIn WorkgroupSize
+%2 = OpTypeVoid
+%3 = OpTypeFunction %2
+%6 = OpTypeInt 32 1
+%7 = OpTypePointer Function %6
+%9 = OpTypeInt 32 0
+%10 = OpTypeVector %9 3
+%11 = OpTypePointer Input %10
+%12 = OpVariable %11 Input
+%13 = OpConstant %9 0
+%14 = OpTypePointer Input %9
+%19 = OpConstant %9 1
+%24 = OpConstant %9 2
+%28 = OpTypeImage %6 1D 0 0 0 2 R32i
+%29 = OpTypePointer UniformConstant %28
+%30 = OpVariable %29 UniformConstant
+%32 = OpConstant %6 64
+%45 = OpTypePointer Image %6
+%48 = OpConstantComposite %10 %19 %19 %19
+%4 = OpFunction %2 None %3
+%5 = OpLabel
+%8 = OpVariable %7 Function
+%18 = OpVariable %7 Function
+%23 = OpVariable %7 Function
+%15 = OpAccessChain %14 %12 %13
+%16 = OpLoad %9 %15
+%17 = OpBitcast %6 %16
+OpStore %8 %17
+%20 = OpAccessChain %14 %12 %19
+%21 = OpLoad %9 %20
+%22 = OpBitcast %6 %21
+OpStore %18 %22
+%25 = OpAccessChain %14 %12 %24
+%26 = OpLoad %9 %25
+%27 = OpBitcast %6 %26
+OpStore %23 %27
+%31 = OpLoad %6 %8
+%33 = OpSMod %6 %31 %32
+%34 = OpLoad %6 %8
+%35 = OpLoad %6 %8
+%36 = OpIMul %6 %34 %35
+%37 = OpLoad %6 %18
+%38 = OpLoad %6 %18
+%39 = OpIMul %6 %37 %38
+%40 = OpIAdd %6 %36 %39
+%41 = OpLoad %6 %23
+%42 = OpLoad %6 %23
+%43 = OpIMul %6 %41 %42
+%44 = OpIAdd %6 %40 %43
+%46 = OpImageTexelPointer %45 %30 %33 %13
+%47 = ${OPNAME} %6 %46 %19 %13 ${LASTARG:default=%44}
+OpReturn
+OpFunctionEnd
+)";
+
+const std::string kShader_1d_r32i_intermediate_values = R"(
+; The SPIR-V shader below is based on the following GLSL shader, but OpAtomicIAdd has been
+; replaced with a template parameter and the last argument for it has been made optional.
+;
+; #version 440
+; precision highp iimage1D;
+;
+; layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+; layout (r32i, binding=0) coherent uniform iimage1D u_resultImage;
+; layout (r32i, binding=1) writeonly uniform iimage1D u_intermValuesImage;
+;
+; void main (void)
+; {
+; int gx = int(gl_GlobalInvocationID.x);
+; int gy = int(gl_GlobalInvocationID.y);
+; int gz = int(gl_GlobalInvocationID.z);
+; imageStore(u_intermValuesImage, gx, ivec4(imageAtomicAdd(u_resultImage, gx % 64, int(gx*gx + gy*gy + gz*gz))));
+; }
+;
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 54
+; Schema: 0
+OpCapability Shader
+OpCapability Image1D
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %4 "main" %12
+OpExecutionMode %4 LocalSize 1 1 1
+OpDecorate %12 BuiltIn GlobalInvocationId
+OpDecorate %30 DescriptorSet 0
+OpDecorate %30 Binding 1
+OpDecorate %30 NonReadable
+OpDecorate %33 DescriptorSet 0
+OpDecorate %33 Binding 0
+OpDecorate %33 Coherent
+OpDecorate %53 BuiltIn WorkgroupSize
+%2 = OpTypeVoid
+%3 = OpTypeFunction %2
+%6 = OpTypeInt 32 1
+%7 = OpTypePointer Function %6
+%9 = OpTypeInt 32 0
+%10 = OpTypeVector %9 3
+%11 = OpTypePointer Input %10
+%12 = OpVariable %11 Input
+%13 = OpConstant %9 0
+%14 = OpTypePointer Input %9
+%19 = OpConstant %9 1
+%24 = OpConstant %9 2
+%28 = OpTypeImage %6 1D 0 0 0 2 R32i
+%29 = OpTypePointer UniformConstant %28
+%30 = OpVariable %29 UniformConstant
+%33 = OpVariable %29 UniformConstant
+%35 = OpConstant %6 64
+%48 = OpTypePointer Image %6
+%51 = OpTypeVector %6 4
+%53 = OpConstantComposite %10 %19 %19 %19
+%4 = OpFunction %2 None %3
+%5 = OpLabel
+%8 = OpVariable %7 Function
+%18 = OpVariable %7 Function
+%23 = OpVariable %7 Function
+%15 = OpAccessChain %14 %12 %13
+%16 = OpLoad %9 %15
+%17 = OpBitcast %6 %16
+OpStore %8 %17
+%20 = OpAccessChain %14 %12 %19
+%21 = OpLoad %9 %20
+%22 = OpBitcast %6 %21
+OpStore %18 %22
+%25 = OpAccessChain %14 %12 %24
+%26 = OpLoad %9 %25
+%27 = OpBitcast %6 %26
+OpStore %23 %27
+%31 = OpLoad %28 %30
+%32 = OpLoad %6 %8
+%34 = OpLoad %6 %8
+%36 = OpSMod %6 %34 %35
+%37 = OpLoad %6 %8
+%38 = OpLoad %6 %8
+%39 = OpIMul %6 %37 %38
+%40 = OpLoad %6 %18
+%41 = OpLoad %6 %18
+%42 = OpIMul %6 %40 %41
+%43 = OpIAdd %6 %39 %42
+%44 = OpLoad %6 %23
+%45 = OpLoad %6 %23
+%46 = OpIMul %6 %44 %45
+%47 = OpIAdd %6 %43 %46
+%49 = OpImageTexelPointer %48 %33 %36 %13
+%50 = ${OPNAME} %6 %49 %19 %13 ${LASTARG:default=%47}
+%52 = OpCompositeConstruct %51 %50 %50 %50 %50
+OpImageWrite %31 %32 %52
+OpReturn
+OpFunctionEnd
+)";
+
+const std::string kShader_1d_array_r32ui_end_result = R"(
+; The SPIR-V shader below is based on the following GLSL shader, but OpAtomicIAdd has been
+; replaced with a template parameter and the last argument for it has been made optional.
+;
+; #version 440
+; precision highp uimage1DArray;
+;
+; layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+; layout (r32ui, binding=0) coherent uniform uimage1DArray u_resultImage;
+;
+; void main (void)
+; {
+; int gx = int(gl_GlobalInvocationID.x);
+; int gy = int(gl_GlobalInvocationID.y);
+; int gz = int(gl_GlobalInvocationID.z);
+; imageAtomicAdd(u_resultImage, ivec2(gx % 64,gy), uint(gx*gx + gy*gy + gz*gz));
+; }
+;
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 53
+; Schema: 0
+OpCapability Shader
+OpCapability Image1D
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %4 "main" %12
+OpExecutionMode %4 LocalSize 1 1 1
+OpDecorate %12 BuiltIn GlobalInvocationId
+OpDecorate %30 DescriptorSet 0
+OpDecorate %30 Binding 0
+OpDecorate %30 Coherent
+OpDecorate %52 BuiltIn WorkgroupSize
+%2 = OpTypeVoid
+%3 = OpTypeFunction %2
+%6 = OpTypeInt 32 1
+%7 = OpTypePointer Function %6
+%9 = OpTypeInt 32 0
+%10 = OpTypeVector %9 3
+%11 = OpTypePointer Input %10
+%12 = OpVariable %11 Input
+%13 = OpConstant %9 0
+%14 = OpTypePointer Input %9
+%19 = OpConstant %9 1
+%24 = OpConstant %9 2
+%28 = OpTypeImage %9 1D 0 1 0 2 R32ui
+%29 = OpTypePointer UniformConstant %28
+%30 = OpVariable %29 UniformConstant
+%32 = OpConstant %6 64
+%35 = OpTypeVector %6 2
+%49 = OpTypePointer Image %9
+%52 = OpConstantComposite %10 %19 %19 %19
+%4 = OpFunction %2 None %3
+%5 = OpLabel
+%8 = OpVariable %7 Function
+%18 = OpVariable %7 Function
+%23 = OpVariable %7 Function
+%15 = OpAccessChain %14 %12 %13
+%16 = OpLoad %9 %15
+%17 = OpBitcast %6 %16
+OpStore %8 %17
+%20 = OpAccessChain %14 %12 %19
+%21 = OpLoad %9 %20
+%22 = OpBitcast %6 %21
+OpStore %18 %22
+%25 = OpAccessChain %14 %12 %24
+%26 = OpLoad %9 %25
+%27 = OpBitcast %6 %26
+OpStore %23 %27
+%31 = OpLoad %6 %8
+%33 = OpSMod %6 %31 %32
+%34 = OpLoad %6 %18
+%36 = OpCompositeConstruct %35 %33 %34
+%37 = OpLoad %6 %8
+%38 = OpLoad %6 %8
+%39 = OpIMul %6 %37 %38
+%40 = OpLoad %6 %18
+%41 = OpLoad %6 %18
+%42 = OpIMul %6 %40 %41
+%43 = OpIAdd %6 %39 %42
+%44 = OpLoad %6 %23
+%45 = OpLoad %6 %23
+%46 = OpIMul %6 %44 %45
+%47 = OpIAdd %6 %43 %46
+%48 = OpBitcast %9 %47
+%50 = OpImageTexelPointer %49 %30 %36 %13
+%51 = ${OPNAME} %9 %50 %19 %13 ${LASTARG:default=%48}
+OpReturn
+OpFunctionEnd
+)";
+
+const std::string kShader_1d_array_r32ui_intermediate_values = R"(
+; The SPIR-V shader below is based on the following GLSL shader, but OpAtomicIAdd has been
+; replaced with a template parameter and the last argument for it has been made optional.
+;
+; #version 440
+; precision highp uimage1DArray;
+;
+; layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+; layout (r32ui, binding=0) coherent uniform uimage1DArray u_resultImage;
+; layout (r32ui, binding=1) writeonly uniform uimage1DArray u_intermValuesImage;
+;
+; void main (void)
+; {
+; int gx = int(gl_GlobalInvocationID.x);
+; int gy = int(gl_GlobalInvocationID.y);
+; int gz = int(gl_GlobalInvocationID.z);
+; imageStore(u_intermValuesImage, ivec2(gx,gy), uvec4(imageAtomicAdd(u_resultImage, ivec2(gx % 64,gy), uint(gx*gx + gy*gy + gz*gz))));
+; }
+;
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 60
+; Schema: 0
+OpCapability Shader
+OpCapability Image1D
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %4 "main" %12
+OpExecutionMode %4 LocalSize 1 1 1
+OpDecorate %12 BuiltIn GlobalInvocationId
+OpDecorate %30 DescriptorSet 0
+OpDecorate %30 Binding 1
+OpDecorate %30 NonReadable
+OpDecorate %36 DescriptorSet 0
+OpDecorate %36 Binding 0
+OpDecorate %36 Coherent
+OpDecorate %59 BuiltIn WorkgroupSize
+%2 = OpTypeVoid
+%3 = OpTypeFunction %2
+%6 = OpTypeInt 32 1
+%7 = OpTypePointer Function %6
+%9 = OpTypeInt 32 0
+%10 = OpTypeVector %9 3
+%11 = OpTypePointer Input %10
+%12 = OpVariable %11 Input
+%13 = OpConstant %9 0
+%14 = OpTypePointer Input %9
+%19 = OpConstant %9 1
+%24 = OpConstant %9 2
+%28 = OpTypeImage %9 1D 0 1 0 2 R32ui
+%29 = OpTypePointer UniformConstant %28
+%30 = OpVariable %29 UniformConstant
+%34 = OpTypeVector %6 2
+%36 = OpVariable %29 UniformConstant
+%38 = OpConstant %6 64
+%54 = OpTypePointer Image %9
+%57 = OpTypeVector %9 4
+%59 = OpConstantComposite %10 %19 %19 %19
+%4 = OpFunction %2 None %3
+%5 = OpLabel
+%8 = OpVariable %7 Function
+%18 = OpVariable %7 Function
+%23 = OpVariable %7 Function
+%15 = OpAccessChain %14 %12 %13
+%16 = OpLoad %9 %15
+%17 = OpBitcast %6 %16
+OpStore %8 %17
+%20 = OpAccessChain %14 %12 %19
+%21 = OpLoad %9 %20
+%22 = OpBitcast %6 %21
+OpStore %18 %22
+%25 = OpAccessChain %14 %12 %24
+%26 = OpLoad %9 %25
+%27 = OpBitcast %6 %26
+OpStore %23 %27
+%31 = OpLoad %28 %30
+%32 = OpLoad %6 %8
+%33 = OpLoad %6 %18
+%35 = OpCompositeConstruct %34 %32 %33
+%37 = OpLoad %6 %8
+%39 = OpSMod %6 %37 %38
+%40 = OpLoad %6 %18
+%41 = OpCompositeConstruct %34 %39 %40
+%42 = OpLoad %6 %8
+%43 = OpLoad %6 %8
+%44 = OpIMul %6 %42 %43
+%45 = OpLoad %6 %18
+%46 = OpLoad %6 %18
+%47 = OpIMul %6 %45 %46
+%48 = OpIAdd %6 %44 %47
+%49 = OpLoad %6 %23
+%50 = OpLoad %6 %23
+%51 = OpIMul %6 %49 %50
+%52 = OpIAdd %6 %48 %51
+%53 = OpBitcast %9 %52
+%55 = OpImageTexelPointer %54 %36 %41 %13
+%56 = ${OPNAME} %9 %55 %19 %13 ${LASTARG:default=%53}
+%58 = OpCompositeConstruct %57 %56 %56 %56 %56
+OpImageWrite %31 %35 %58
+OpReturn
+OpFunctionEnd
+)";
+
+const std::string kShader_1d_array_r32i_end_result = R"(
+; The SPIR-V shader below is based on the following GLSL shader, but OpAtomicIAdd has been
+; replaced with a template parameter and the last argument for it has been made optional.
+;
+; #version 440
+; precision highp iimage1DArray;
+;
+; layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+; layout (r32i, binding=0) coherent uniform iimage1DArray u_resultImage;
+;
+; void main (void)
+; {
+; int gx = int(gl_GlobalInvocationID.x);
+; int gy = int(gl_GlobalInvocationID.y);
+; int gz = int(gl_GlobalInvocationID.z);
+; imageAtomicAdd(u_resultImage, ivec2(gx % 64,gy), int(gx*gx + gy*gy + gz*gz));
+; }
+;
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 52
+; Schema: 0
+OpCapability Shader
+OpCapability Image1D
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %4 "main" %12
+OpExecutionMode %4 LocalSize 1 1 1
+OpDecorate %12 BuiltIn GlobalInvocationId
+OpDecorate %30 DescriptorSet 0
+OpDecorate %30 Binding 0
+OpDecorate %30 Coherent
+OpDecorate %51 BuiltIn WorkgroupSize
+%2 = OpTypeVoid
+%3 = OpTypeFunction %2
+%6 = OpTypeInt 32 1
+%7 = OpTypePointer Function %6
+%9 = OpTypeInt 32 0
+%10 = OpTypeVector %9 3
+%11 = OpTypePointer Input %10
+%12 = OpVariable %11 Input
+%13 = OpConstant %9 0
+%14 = OpTypePointer Input %9
+%19 = OpConstant %9 1
+%24 = OpConstant %9 2
+%28 = OpTypeImage %6 1D 0 1 0 2 R32i
+%29 = OpTypePointer UniformConstant %28
+%30 = OpVariable %29 UniformConstant
+%32 = OpConstant %6 64
+%35 = OpTypeVector %6 2
+%48 = OpTypePointer Image %6
+%51 = OpConstantComposite %10 %19 %19 %19
+%4 = OpFunction %2 None %3
+%5 = OpLabel
+%8 = OpVariable %7 Function
+%18 = OpVariable %7 Function
+%23 = OpVariable %7 Function
+%15 = OpAccessChain %14 %12 %13
+%16 = OpLoad %9 %15
+%17 = OpBitcast %6 %16
+OpStore %8 %17
+%20 = OpAccessChain %14 %12 %19
+%21 = OpLoad %9 %20
+%22 = OpBitcast %6 %21
+OpStore %18 %22
+%25 = OpAccessChain %14 %12 %24
+%26 = OpLoad %9 %25
+%27 = OpBitcast %6 %26
+OpStore %23 %27
+%31 = OpLoad %6 %8
+%33 = OpSMod %6 %31 %32
+%34 = OpLoad %6 %18
+%36 = OpCompositeConstruct %35 %33 %34
+%37 = OpLoad %6 %8
+%38 = OpLoad %6 %8
+%39 = OpIMul %6 %37 %38
+%40 = OpLoad %6 %18
+%41 = OpLoad %6 %18
+%42 = OpIMul %6 %40 %41
+%43 = OpIAdd %6 %39 %42
+%44 = OpLoad %6 %23
+%45 = OpLoad %6 %23
+%46 = OpIMul %6 %44 %45
+%47 = OpIAdd %6 %43 %46
+%49 = OpImageTexelPointer %48 %30 %36 %13
+%50 = ${OPNAME} %6 %49 %19 %13 ${LASTARG:default=%47}
+OpReturn
+OpFunctionEnd
+)";
+
+const std::string kShader_1d_array_r32i_intermediate_values = R"(
+; The SPIR-V shader below is based on the following GLSL shader, but OpAtomicIAdd has been
+; replaced with a template parameter and the last argument for it has been made optional.
+;
+; #version 440
+; precision highp iimage1DArray;
+;
+; layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+; layout (r32i, binding=0) coherent uniform iimage1DArray u_resultImage;
+; layout (r32i, binding=1) writeonly uniform iimage1DArray u_intermValuesImage;
+;
+; void main (void)
+; {
+; int gx = int(gl_GlobalInvocationID.x);
+; int gy = int(gl_GlobalInvocationID.y);
+; int gz = int(gl_GlobalInvocationID.z);
+; imageStore(u_intermValuesImage, ivec2(gx,gy), ivec4(imageAtomicAdd(u_resultImage, ivec2(gx % 64,gy), int(gx*gx + gy*gy + gz*gz))));
+; }
+;
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 59
+; Schema: 0
+OpCapability Shader
+OpCapability Image1D
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %4 "main" %12
+OpExecutionMode %4 LocalSize 1 1 1
+OpDecorate %12 BuiltIn GlobalInvocationId
+OpDecorate %30 DescriptorSet 0
+OpDecorate %30 Binding 1
+OpDecorate %30 NonReadable
+OpDecorate %36 DescriptorSet 0
+OpDecorate %36 Binding 0
+OpDecorate %36 Coherent
+OpDecorate %58 BuiltIn WorkgroupSize
+%2 = OpTypeVoid
+%3 = OpTypeFunction %2
+%6 = OpTypeInt 32 1
+%7 = OpTypePointer Function %6
+%9 = OpTypeInt 32 0
+%10 = OpTypeVector %9 3
+%11 = OpTypePointer Input %10
+%12 = OpVariable %11 Input
+%13 = OpConstant %9 0
+%14 = OpTypePointer Input %9
+%19 = OpConstant %9 1
+%24 = OpConstant %9 2
+%28 = OpTypeImage %6 1D 0 1 0 2 R32i
+%29 = OpTypePointer UniformConstant %28
+%30 = OpVariable %29 UniformConstant
+%34 = OpTypeVector %6 2
+%36 = OpVariable %29 UniformConstant
+%38 = OpConstant %6 64
+%53 = OpTypePointer Image %6
+%56 = OpTypeVector %6 4
+%58 = OpConstantComposite %10 %19 %19 %19
+%4 = OpFunction %2 None %3
+%5 = OpLabel
+%8 = OpVariable %7 Function
+%18 = OpVariable %7 Function
+%23 = OpVariable %7 Function
+%15 = OpAccessChain %14 %12 %13
+%16 = OpLoad %9 %15
+%17 = OpBitcast %6 %16
+OpStore %8 %17
+%20 = OpAccessChain %14 %12 %19
+%21 = OpLoad %9 %20
+%22 = OpBitcast %6 %21
+OpStore %18 %22
+%25 = OpAccessChain %14 %12 %24
+%26 = OpLoad %9 %25
+%27 = OpBitcast %6 %26
+OpStore %23 %27
+%31 = OpLoad %28 %30
+%32 = OpLoad %6 %8
+%33 = OpLoad %6 %18
+%35 = OpCompositeConstruct %34 %32 %33
+%37 = OpLoad %6 %8
+%39 = OpSMod %6 %37 %38
+%40 = OpLoad %6 %18
+%41 = OpCompositeConstruct %34 %39 %40
+%42 = OpLoad %6 %8
+%43 = OpLoad %6 %8
+%44 = OpIMul %6 %42 %43
+%45 = OpLoad %6 %18
+%46 = OpLoad %6 %18
+%47 = OpIMul %6 %45 %46
+%48 = OpIAdd %6 %44 %47
+%49 = OpLoad %6 %23
+%50 = OpLoad %6 %23
+%51 = OpIMul %6 %49 %50
+%52 = OpIAdd %6 %48 %51
+%54 = OpImageTexelPointer %53 %36 %41 %13
+%55 = ${OPNAME} %6 %54 %19 %13 ${LASTARG:default=%52}
+%57 = OpCompositeConstruct %56 %55 %55 %55 %55
+OpImageWrite %31 %35 %57
+OpReturn
+OpFunctionEnd
+)";
+
+const std::string kShader_2d_r32ui_end_result = R"(
+; The SPIR-V shader below is based on the following GLSL shader, but OpAtomicIAdd has been
+; replaced with a template parameter and the last argument for it has been made optional.
+;
+; #version 440
+; precision highp uimage2D;
+;
+; layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+; layout (r32ui, binding=0) coherent uniform uimage2D u_resultImage;
+;
+; void main (void)
+; {
+; int gx = int(gl_GlobalInvocationID.x);
+; int gy = int(gl_GlobalInvocationID.y);
+; int gz = int(gl_GlobalInvocationID.z);
+; imageAtomicAdd(u_resultImage, ivec2(gx % 64,gy), uint(gx*gx + gy*gy + gz*gz));
+; }
+;
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 53
+; Schema: 0
+OpCapability Shader
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %4 "main" %12
+OpExecutionMode %4 LocalSize 1 1 1
+OpDecorate %12 BuiltIn GlobalInvocationId
+OpDecorate %30 DescriptorSet 0
+OpDecorate %30 Binding 0
+OpDecorate %30 Coherent
+OpDecorate %52 BuiltIn WorkgroupSize
+%2 = OpTypeVoid
+%3 = OpTypeFunction %2
+%6 = OpTypeInt 32 1
+%7 = OpTypePointer Function %6
+%9 = OpTypeInt 32 0
+%10 = OpTypeVector %9 3
+%11 = OpTypePointer Input %10
+%12 = OpVariable %11 Input
+%13 = OpConstant %9 0
+%14 = OpTypePointer Input %9
+%19 = OpConstant %9 1
+%24 = OpConstant %9 2
+%28 = OpTypeImage %9 2D 0 0 0 2 R32ui
+%29 = OpTypePointer UniformConstant %28
+%30 = OpVariable %29 UniformConstant
+%32 = OpConstant %6 64
+%35 = OpTypeVector %6 2
+%49 = OpTypePointer Image %9
+%52 = OpConstantComposite %10 %19 %19 %19
+%4 = OpFunction %2 None %3
+%5 = OpLabel
+%8 = OpVariable %7 Function
+%18 = OpVariable %7 Function
+%23 = OpVariable %7 Function
+%15 = OpAccessChain %14 %12 %13
+%16 = OpLoad %9 %15
+%17 = OpBitcast %6 %16
+OpStore %8 %17
+%20 = OpAccessChain %14 %12 %19
+%21 = OpLoad %9 %20
+%22 = OpBitcast %6 %21
+OpStore %18 %22
+%25 = OpAccessChain %14 %12 %24
+%26 = OpLoad %9 %25
+%27 = OpBitcast %6 %26
+OpStore %23 %27
+%31 = OpLoad %6 %8
+%33 = OpSMod %6 %31 %32
+%34 = OpLoad %6 %18
+%36 = OpCompositeConstruct %35 %33 %34
+%37 = OpLoad %6 %8
+%38 = OpLoad %6 %8
+%39 = OpIMul %6 %37 %38
+%40 = OpLoad %6 %18
+%41 = OpLoad %6 %18
+%42 = OpIMul %6 %40 %41
+%43 = OpIAdd %6 %39 %42
+%44 = OpLoad %6 %23
+%45 = OpLoad %6 %23
+%46 = OpIMul %6 %44 %45
+%47 = OpIAdd %6 %43 %46
+%48 = OpBitcast %9 %47
+%50 = OpImageTexelPointer %49 %30 %36 %13
+%51 = ${OPNAME} %9 %50 %19 %13 ${LASTARG:default=%48}
+OpReturn
+OpFunctionEnd
+)";
+
+const std::string kShader_2d_r32ui_intermediate_values = R"(
+; The SPIR-V shader below is based on the following GLSL shader, but OpAtomicIAdd has been
+; replaced with a template parameter and the last argument for it has been made optional.
+;
+; #version 440
+; precision highp uimage2D;
+;
+; layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+; layout (r32ui, binding=0) coherent uniform uimage2D u_resultImage;
+; layout (r32ui, binding=1) writeonly uniform uimage2D u_intermValuesImage;
+;
+; void main (void)
+; {
+; int gx = int(gl_GlobalInvocationID.x);
+; int gy = int(gl_GlobalInvocationID.y);
+; int gz = int(gl_GlobalInvocationID.z);
+; imageStore(u_intermValuesImage, ivec2(gx,gy), uvec4(imageAtomicAdd(u_resultImage, ivec2(gx % 64,gy), uint(gx*gx + gy*gy + gz*gz))));
+; }
+;
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 60
+; Schema: 0
+OpCapability Shader
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %4 "main" %12
+OpExecutionMode %4 LocalSize 1 1 1
+OpDecorate %12 BuiltIn GlobalInvocationId
+OpDecorate %30 DescriptorSet 0
+OpDecorate %30 Binding 1
+OpDecorate %30 NonReadable
+OpDecorate %36 DescriptorSet 0
+OpDecorate %36 Binding 0
+OpDecorate %36 Coherent
+OpDecorate %59 BuiltIn WorkgroupSize
+%2 = OpTypeVoid
+%3 = OpTypeFunction %2
+%6 = OpTypeInt 32 1
+%7 = OpTypePointer Function %6
+%9 = OpTypeInt 32 0
+%10 = OpTypeVector %9 3
+%11 = OpTypePointer Input %10
+%12 = OpVariable %11 Input
+%13 = OpConstant %9 0
+%14 = OpTypePointer Input %9
+%19 = OpConstant %9 1
+%24 = OpConstant %9 2
+%28 = OpTypeImage %9 2D 0 0 0 2 R32ui
+%29 = OpTypePointer UniformConstant %28
+%30 = OpVariable %29 UniformConstant
+%34 = OpTypeVector %6 2
+%36 = OpVariable %29 UniformConstant
+%38 = OpConstant %6 64
+%54 = OpTypePointer Image %9
+%57 = OpTypeVector %9 4
+%59 = OpConstantComposite %10 %19 %19 %19
+%4 = OpFunction %2 None %3
+%5 = OpLabel
+%8 = OpVariable %7 Function
+%18 = OpVariable %7 Function
+%23 = OpVariable %7 Function
+%15 = OpAccessChain %14 %12 %13
+%16 = OpLoad %9 %15
+%17 = OpBitcast %6 %16
+OpStore %8 %17
+%20 = OpAccessChain %14 %12 %19
+%21 = OpLoad %9 %20
+%22 = OpBitcast %6 %21
+OpStore %18 %22
+%25 = OpAccessChain %14 %12 %24
+%26 = OpLoad %9 %25
+%27 = OpBitcast %6 %26
+OpStore %23 %27
+%31 = OpLoad %28 %30
+%32 = OpLoad %6 %8
+%33 = OpLoad %6 %18
+%35 = OpCompositeConstruct %34 %32 %33
+%37 = OpLoad %6 %8
+%39 = OpSMod %6 %37 %38
+%40 = OpLoad %6 %18
+%41 = OpCompositeConstruct %34 %39 %40
+%42 = OpLoad %6 %8
+%43 = OpLoad %6 %8
+%44 = OpIMul %6 %42 %43
+%45 = OpLoad %6 %18
+%46 = OpLoad %6 %18
+%47 = OpIMul %6 %45 %46
+%48 = OpIAdd %6 %44 %47
+%49 = OpLoad %6 %23
+%50 = OpLoad %6 %23
+%51 = OpIMul %6 %49 %50
+%52 = OpIAdd %6 %48 %51
+%53 = OpBitcast %9 %52
+%55 = OpImageTexelPointer %54 %36 %41 %13
+%56 = ${OPNAME} %9 %55 %19 %13 ${LASTARG:default=%53}
+%58 = OpCompositeConstruct %57 %56 %56 %56 %56
+OpImageWrite %31 %35 %58
+OpReturn
+OpFunctionEnd
+)";
+
+const std::string kShader_2d_r32i_end_result = R"(
+; The SPIR-V shader below is based on the following GLSL shader, but OpAtomicIAdd has been
+; replaced with a template parameter and the last argument for it has been made optional.
+;
+; #version 440
+; precision highp iimage2D;
+;
+; layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+; layout (r32i, binding=0) coherent uniform iimage2D u_resultImage;
+;
+; void main (void)
+; {
+; int gx = int(gl_GlobalInvocationID.x);
+; int gy = int(gl_GlobalInvocationID.y);
+; int gz = int(gl_GlobalInvocationID.z);
+; imageAtomicAdd(u_resultImage, ivec2(gx % 64,gy), int(gx*gx + gy*gy + gz*gz));
+; }
+;
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 52
+; Schema: 0
+OpCapability Shader
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %4 "main" %12
+OpExecutionMode %4 LocalSize 1 1 1
+OpDecorate %12 BuiltIn GlobalInvocationId
+OpDecorate %30 DescriptorSet 0
+OpDecorate %30 Binding 0
+OpDecorate %30 Coherent
+OpDecorate %51 BuiltIn WorkgroupSize
+%2 = OpTypeVoid
+%3 = OpTypeFunction %2
+%6 = OpTypeInt 32 1
+%7 = OpTypePointer Function %6
+%9 = OpTypeInt 32 0
+%10 = OpTypeVector %9 3
+%11 = OpTypePointer Input %10
+%12 = OpVariable %11 Input
+%13 = OpConstant %9 0
+%14 = OpTypePointer Input %9
+%19 = OpConstant %9 1
+%24 = OpConstant %9 2
+%28 = OpTypeImage %6 2D 0 0 0 2 R32i
+%29 = OpTypePointer UniformConstant %28
+%30 = OpVariable %29 UniformConstant
+%32 = OpConstant %6 64
+%35 = OpTypeVector %6 2
+%48 = OpTypePointer Image %6
+%51 = OpConstantComposite %10 %19 %19 %19
+%4 = OpFunction %2 None %3
+%5 = OpLabel
+%8 = OpVariable %7 Function
+%18 = OpVariable %7 Function
+%23 = OpVariable %7 Function
+%15 = OpAccessChain %14 %12 %13
+%16 = OpLoad %9 %15
+%17 = OpBitcast %6 %16
+OpStore %8 %17
+%20 = OpAccessChain %14 %12 %19
+%21 = OpLoad %9 %20
+%22 = OpBitcast %6 %21
+OpStore %18 %22
+%25 = OpAccessChain %14 %12 %24
+%26 = OpLoad %9 %25
+%27 = OpBitcast %6 %26
+OpStore %23 %27
+%31 = OpLoad %6 %8
+%33 = OpSMod %6 %31 %32
+%34 = OpLoad %6 %18
+%36 = OpCompositeConstruct %35 %33 %34
+%37 = OpLoad %6 %8
+%38 = OpLoad %6 %8
+%39 = OpIMul %6 %37 %38
+%40 = OpLoad %6 %18
+%41 = OpLoad %6 %18
+%42 = OpIMul %6 %40 %41
+%43 = OpIAdd %6 %39 %42
+%44 = OpLoad %6 %23
+%45 = OpLoad %6 %23
+%46 = OpIMul %6 %44 %45
+%47 = OpIAdd %6 %43 %46
+%49 = OpImageTexelPointer %48 %30 %36 %13
+%50 = ${OPNAME} %6 %49 %19 %13 ${LASTARG:default=%47}
+OpReturn
+OpFunctionEnd
+)";
+
+const std::string kShader_2d_r32i_intermediate_values = R"(
+; The SPIR-V shader below is based on the following GLSL shader, but OpAtomicIAdd has been
+; replaced with a template parameter and the last argument for it has been made optional.
+;
+; #version 440
+; precision highp iimage2D;
+;
+; layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+; layout (r32i, binding=0) coherent uniform iimage2D u_resultImage;
+; layout (r32i, binding=1) writeonly uniform iimage2D u_intermValuesImage;
+;
+; void main (void)
+; {
+; int gx = int(gl_GlobalInvocationID.x);
+; int gy = int(gl_GlobalInvocationID.y);
+; int gz = int(gl_GlobalInvocationID.z);
+; imageStore(u_intermValuesImage, ivec2(gx,gy), ivec4(imageAtomicAdd(u_resultImage, ivec2(gx % 64,gy), int(gx*gx + gy*gy + gz*gz))));
+; }
+;
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 59
+; Schema: 0
+OpCapability Shader
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %4 "main" %12
+OpExecutionMode %4 LocalSize 1 1 1
+OpDecorate %12 BuiltIn GlobalInvocationId
+OpDecorate %30 DescriptorSet 0
+OpDecorate %30 Binding 1
+OpDecorate %30 NonReadable
+OpDecorate %36 DescriptorSet 0
+OpDecorate %36 Binding 0
+OpDecorate %36 Coherent
+OpDecorate %58 BuiltIn WorkgroupSize
+%2 = OpTypeVoid
+%3 = OpTypeFunction %2
+%6 = OpTypeInt 32 1
+%7 = OpTypePointer Function %6
+%9 = OpTypeInt 32 0
+%10 = OpTypeVector %9 3
+%11 = OpTypePointer Input %10
+%12 = OpVariable %11 Input
+%13 = OpConstant %9 0
+%14 = OpTypePointer Input %9
+%19 = OpConstant %9 1
+%24 = OpConstant %9 2
+%28 = OpTypeImage %6 2D 0 0 0 2 R32i
+%29 = OpTypePointer UniformConstant %28
+%30 = OpVariable %29 UniformConstant
+%34 = OpTypeVector %6 2
+%36 = OpVariable %29 UniformConstant
+%38 = OpConstant %6 64
+%53 = OpTypePointer Image %6
+%56 = OpTypeVector %6 4
+%58 = OpConstantComposite %10 %19 %19 %19
+%4 = OpFunction %2 None %3
+%5 = OpLabel
+%8 = OpVariable %7 Function
+%18 = OpVariable %7 Function
+%23 = OpVariable %7 Function
+%15 = OpAccessChain %14 %12 %13
+%16 = OpLoad %9 %15
+%17 = OpBitcast %6 %16
+OpStore %8 %17
+%20 = OpAccessChain %14 %12 %19
+%21 = OpLoad %9 %20
+%22 = OpBitcast %6 %21
+OpStore %18 %22
+%25 = OpAccessChain %14 %12 %24
+%26 = OpLoad %9 %25
+%27 = OpBitcast %6 %26
+OpStore %23 %27
+%31 = OpLoad %28 %30
+%32 = OpLoad %6 %8
+%33 = OpLoad %6 %18
+%35 = OpCompositeConstruct %34 %32 %33
+%37 = OpLoad %6 %8
+%39 = OpSMod %6 %37 %38
+%40 = OpLoad %6 %18
+%41 = OpCompositeConstruct %34 %39 %40
+%42 = OpLoad %6 %8
+%43 = OpLoad %6 %8
+%44 = OpIMul %6 %42 %43
+%45 = OpLoad %6 %18
+%46 = OpLoad %6 %18
+%47 = OpIMul %6 %45 %46
+%48 = OpIAdd %6 %44 %47
+%49 = OpLoad %6 %23
+%50 = OpLoad %6 %23
+%51 = OpIMul %6 %49 %50
+%52 = OpIAdd %6 %48 %51
+%54 = OpImageTexelPointer %53 %36 %41 %13
+%55 = ${OPNAME} %6 %54 %19 %13 ${LASTARG:default=%52}
+%57 = OpCompositeConstruct %56 %55 %55 %55 %55
+OpImageWrite %31 %35 %57
+OpReturn
+OpFunctionEnd
+)";
+
+const std::string kShader_2d_array_r32ui_end_result = R"(
+; The SPIR-V shader below is based on the following GLSL shader, but OpAtomicIAdd has been
+; replaced with a template parameter and the last argument for it has been made optional.
+;
+; #version 440
+; precision highp uimage2DArray;
+;
+; layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+; layout (r32ui, binding=0) coherent uniform uimage2DArray u_resultImage;
+;
+; void main (void)
+; {
+; int gx = int(gl_GlobalInvocationID.x);
+; int gy = int(gl_GlobalInvocationID.y);
+; int gz = int(gl_GlobalInvocationID.z);
+; imageAtomicAdd(u_resultImage, ivec3(gx % 64,gy,gz), uint(gx*gx + gy*gy + gz*gz));
+; }
+;
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 54
+; Schema: 0
+OpCapability Shader
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %4 "main" %12
+OpExecutionMode %4 LocalSize 1 1 1
+OpDecorate %12 BuiltIn GlobalInvocationId
+OpDecorate %30 DescriptorSet 0
+OpDecorate %30 Binding 0
+OpDecorate %30 Coherent
+OpDecorate %53 BuiltIn WorkgroupSize
+%2 = OpTypeVoid
+%3 = OpTypeFunction %2
+%6 = OpTypeInt 32 1
+%7 = OpTypePointer Function %6
+%9 = OpTypeInt 32 0
+%10 = OpTypeVector %9 3
+%11 = OpTypePointer Input %10
+%12 = OpVariable %11 Input
+%13 = OpConstant %9 0
+%14 = OpTypePointer Input %9
+%19 = OpConstant %9 1
+%24 = OpConstant %9 2
+%28 = OpTypeImage %9 2D 0 1 0 2 R32ui
+%29 = OpTypePointer UniformConstant %28
+%30 = OpVariable %29 UniformConstant
+%32 = OpConstant %6 64
+%36 = OpTypeVector %6 3
+%50 = OpTypePointer Image %9
+%53 = OpConstantComposite %10 %19 %19 %19
+%4 = OpFunction %2 None %3
+%5 = OpLabel
+%8 = OpVariable %7 Function
+%18 = OpVariable %7 Function
+%23 = OpVariable %7 Function
+%15 = OpAccessChain %14 %12 %13
+%16 = OpLoad %9 %15
+%17 = OpBitcast %6 %16
+OpStore %8 %17
+%20 = OpAccessChain %14 %12 %19
+%21 = OpLoad %9 %20
+%22 = OpBitcast %6 %21
+OpStore %18 %22
+%25 = OpAccessChain %14 %12 %24
+%26 = OpLoad %9 %25
+%27 = OpBitcast %6 %26
+OpStore %23 %27
+%31 = OpLoad %6 %8
+%33 = OpSMod %6 %31 %32
+%34 = OpLoad %6 %18
+%35 = OpLoad %6 %23
+%37 = OpCompositeConstruct %36 %33 %34 %35
+%38 = OpLoad %6 %8
+%39 = OpLoad %6 %8
+%40 = OpIMul %6 %38 %39
+%41 = OpLoad %6 %18
+%42 = OpLoad %6 %18
+%43 = OpIMul %6 %41 %42
+%44 = OpIAdd %6 %40 %43
+%45 = OpLoad %6 %23
+%46 = OpLoad %6 %23
+%47 = OpIMul %6 %45 %46
+%48 = OpIAdd %6 %44 %47
+%49 = OpBitcast %9 %48
+%51 = OpImageTexelPointer %50 %30 %37 %13
+%52 = ${OPNAME} %9 %51 %19 %13 ${LASTARG:default=%49}
+OpReturn
+OpFunctionEnd
+)";
+
+const std::string kShader_2d_array_r32ui_intermediate_values = R"(
+; The SPIR-V shader below is based on the following GLSL shader, but OpAtomicIAdd has been
+; replaced with a template parameter and the last argument for it has been made optional.
+;
+; #version 440
+; precision highp uimage2DArray;
+;
+; layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+; layout (r32ui, binding=0) coherent uniform uimage2DArray u_resultImage;
+; layout (r32ui, binding=1) writeonly uniform uimage2DArray u_intermValuesImage;
+;
+; void main (void)
+; {
+; int gx = int(gl_GlobalInvocationID.x);
+; int gy = int(gl_GlobalInvocationID.y);
+; int gz = int(gl_GlobalInvocationID.z);
+; imageStore(u_intermValuesImage, ivec3(gx,gy,gz), uvec4(imageAtomicAdd(u_resultImage, ivec3(gx % 64,gy,gz), uint(gx*gx + gy*gy + gz*gz))));
+; }
+;
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 62
+; Schema: 0
+OpCapability Shader
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %4 "main" %12
+OpExecutionMode %4 LocalSize 1 1 1
+OpDecorate %12 BuiltIn GlobalInvocationId
+OpDecorate %30 DescriptorSet 0
+OpDecorate %30 Binding 1
+OpDecorate %30 NonReadable
+OpDecorate %37 DescriptorSet 0
+OpDecorate %37 Binding 0
+OpDecorate %37 Coherent
+OpDecorate %61 BuiltIn WorkgroupSize
+%2 = OpTypeVoid
+%3 = OpTypeFunction %2
+%6 = OpTypeInt 32 1
+%7 = OpTypePointer Function %6
+%9 = OpTypeInt 32 0
+%10 = OpTypeVector %9 3
+%11 = OpTypePointer Input %10
+%12 = OpVariable %11 Input
+%13 = OpConstant %9 0
+%14 = OpTypePointer Input %9
+%19 = OpConstant %9 1
+%24 = OpConstant %9 2
+%28 = OpTypeImage %9 2D 0 1 0 2 R32ui
+%29 = OpTypePointer UniformConstant %28
+%30 = OpVariable %29 UniformConstant
+%35 = OpTypeVector %6 3
+%37 = OpVariable %29 UniformConstant
+%39 = OpConstant %6 64
+%56 = OpTypePointer Image %9
+%59 = OpTypeVector %9 4
+%61 = OpConstantComposite %10 %19 %19 %19
+%4 = OpFunction %2 None %3
+%5 = OpLabel
+%8 = OpVariable %7 Function
+%18 = OpVariable %7 Function
+%23 = OpVariable %7 Function
+%15 = OpAccessChain %14 %12 %13
+%16 = OpLoad %9 %15
+%17 = OpBitcast %6 %16
+OpStore %8 %17
+%20 = OpAccessChain %14 %12 %19
+%21 = OpLoad %9 %20
+%22 = OpBitcast %6 %21
+OpStore %18 %22
+%25 = OpAccessChain %14 %12 %24
+%26 = OpLoad %9 %25
+%27 = OpBitcast %6 %26
+OpStore %23 %27
+%31 = OpLoad %28 %30
+%32 = OpLoad %6 %8
+%33 = OpLoad %6 %18
+%34 = OpLoad %6 %23
+%36 = OpCompositeConstruct %35 %32 %33 %34
+%38 = OpLoad %6 %8
+%40 = OpSMod %6 %38 %39
+%41 = OpLoad %6 %18
+%42 = OpLoad %6 %23
+%43 = OpCompositeConstruct %35 %40 %41 %42
+%44 = OpLoad %6 %8
+%45 = OpLoad %6 %8
+%46 = OpIMul %6 %44 %45
+%47 = OpLoad %6 %18
+%48 = OpLoad %6 %18
+%49 = OpIMul %6 %47 %48
+%50 = OpIAdd %6 %46 %49
+%51 = OpLoad %6 %23
+%52 = OpLoad %6 %23
+%53 = OpIMul %6 %51 %52
+%54 = OpIAdd %6 %50 %53
+%55 = OpBitcast %9 %54
+%57 = OpImageTexelPointer %56 %37 %43 %13
+%58 = ${OPNAME} %9 %57 %19 %13 ${LASTARG:default=%55}
+%60 = OpCompositeConstruct %59 %58 %58 %58 %58
+OpImageWrite %31 %36 %60
+OpReturn
+OpFunctionEnd
+)";
+
+const std::string kShader_2d_array_r32i_end_result = R"(
+; The SPIR-V shader below is based on the following GLSL shader, but OpAtomicIAdd has been
+; replaced with a template parameter and the last argument for it has been made optional.
+;
+; #version 440
+; precision highp iimage2DArray;
+;
+; layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+; layout (r32i, binding=0) coherent uniform iimage2DArray u_resultImage;
+;
+; void main (void)
+; {
+; int gx = int(gl_GlobalInvocationID.x);
+; int gy = int(gl_GlobalInvocationID.y);
+; int gz = int(gl_GlobalInvocationID.z);
+; imageAtomicAdd(u_resultImage, ivec3(gx % 64,gy,gz), int(gx*gx + gy*gy + gz*gz));
+; }
+;
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 53
+; Schema: 0
+OpCapability Shader
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %4 "main" %12
+OpExecutionMode %4 LocalSize 1 1 1
+OpDecorate %12 BuiltIn GlobalInvocationId
+OpDecorate %30 DescriptorSet 0
+OpDecorate %30 Binding 0
+OpDecorate %30 Coherent
+OpDecorate %52 BuiltIn WorkgroupSize
+%2 = OpTypeVoid
+%3 = OpTypeFunction %2
+%6 = OpTypeInt 32 1
+%7 = OpTypePointer Function %6
+%9 = OpTypeInt 32 0
+%10 = OpTypeVector %9 3
+%11 = OpTypePointer Input %10
+%12 = OpVariable %11 Input
+%13 = OpConstant %9 0
+%14 = OpTypePointer Input %9
+%19 = OpConstant %9 1
+%24 = OpConstant %9 2
+%28 = OpTypeImage %6 2D 0 1 0 2 R32i
+%29 = OpTypePointer UniformConstant %28
+%30 = OpVariable %29 UniformConstant
+%32 = OpConstant %6 64
+%36 = OpTypeVector %6 3
+%49 = OpTypePointer Image %6
+%52 = OpConstantComposite %10 %19 %19 %19
+%4 = OpFunction %2 None %3
+%5 = OpLabel
+%8 = OpVariable %7 Function
+%18 = OpVariable %7 Function
+%23 = OpVariable %7 Function
+%15 = OpAccessChain %14 %12 %13
+%16 = OpLoad %9 %15
+%17 = OpBitcast %6 %16
+OpStore %8 %17
+%20 = OpAccessChain %14 %12 %19
+%21 = OpLoad %9 %20
+%22 = OpBitcast %6 %21
+OpStore %18 %22
+%25 = OpAccessChain %14 %12 %24
+%26 = OpLoad %9 %25
+%27 = OpBitcast %6 %26
+OpStore %23 %27
+%31 = OpLoad %6 %8
+%33 = OpSMod %6 %31 %32
+%34 = OpLoad %6 %18
+%35 = OpLoad %6 %23
+%37 = OpCompositeConstruct %36 %33 %34 %35
+%38 = OpLoad %6 %8
+%39 = OpLoad %6 %8
+%40 = OpIMul %6 %38 %39
+%41 = OpLoad %6 %18
+%42 = OpLoad %6 %18
+%43 = OpIMul %6 %41 %42
+%44 = OpIAdd %6 %40 %43
+%45 = OpLoad %6 %23
+%46 = OpLoad %6 %23
+%47 = OpIMul %6 %45 %46
+%48 = OpIAdd %6 %44 %47
+%50 = OpImageTexelPointer %49 %30 %37 %13
+%51 = ${OPNAME} %6 %50 %19 %13 ${LASTARG:default=%48}
+OpReturn
+OpFunctionEnd
+)";
+
+const std::string kShader_2d_array_r32i_intermediate_values = R"(
+; The SPIR-V shader below is based on the following GLSL shader, but OpAtomicIAdd has been
+; replaced with a template parameter and the last argument for it has been made optional.
+;
+; #version 440
+; precision highp iimage2DArray;
+;
+; layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+; layout (r32i, binding=0) coherent uniform iimage2DArray u_resultImage;
+; layout (r32i, binding=1) writeonly uniform iimage2DArray u_intermValuesImage;
+;
+; void main (void)
+; {
+; int gx = int(gl_GlobalInvocationID.x);
+; int gy = int(gl_GlobalInvocationID.y);
+; int gz = int(gl_GlobalInvocationID.z);
+; imageStore(u_intermValuesImage, ivec3(gx,gy,gz), ivec4(imageAtomicAdd(u_resultImage, ivec3(gx % 64,gy,gz), int(gx*gx + gy*gy + gz*gz))));
+; }
+;
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 61
+; Schema: 0
+OpCapability Shader
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %4 "main" %12
+OpExecutionMode %4 LocalSize 1 1 1
+OpDecorate %12 BuiltIn GlobalInvocationId
+OpDecorate %30 DescriptorSet 0
+OpDecorate %30 Binding 1
+OpDecorate %30 NonReadable
+OpDecorate %37 DescriptorSet 0
+OpDecorate %37 Binding 0
+OpDecorate %37 Coherent
+OpDecorate %60 BuiltIn WorkgroupSize
+%2 = OpTypeVoid
+%3 = OpTypeFunction %2
+%6 = OpTypeInt 32 1
+%7 = OpTypePointer Function %6
+%9 = OpTypeInt 32 0
+%10 = OpTypeVector %9 3
+%11 = OpTypePointer Input %10
+%12 = OpVariable %11 Input
+%13 = OpConstant %9 0
+%14 = OpTypePointer Input %9
+%19 = OpConstant %9 1
+%24 = OpConstant %9 2
+%28 = OpTypeImage %6 2D 0 1 0 2 R32i
+%29 = OpTypePointer UniformConstant %28
+%30 = OpVariable %29 UniformConstant
+%35 = OpTypeVector %6 3
+%37 = OpVariable %29 UniformConstant
+%39 = OpConstant %6 64
+%55 = OpTypePointer Image %6
+%58 = OpTypeVector %6 4
+%60 = OpConstantComposite %10 %19 %19 %19
+%4 = OpFunction %2 None %3
+%5 = OpLabel
+%8 = OpVariable %7 Function
+%18 = OpVariable %7 Function
+%23 = OpVariable %7 Function
+%15 = OpAccessChain %14 %12 %13
+%16 = OpLoad %9 %15
+%17 = OpBitcast %6 %16
+OpStore %8 %17
+%20 = OpAccessChain %14 %12 %19
+%21 = OpLoad %9 %20
+%22 = OpBitcast %6 %21
+OpStore %18 %22
+%25 = OpAccessChain %14 %12 %24
+%26 = OpLoad %9 %25
+%27 = OpBitcast %6 %26
+OpStore %23 %27
+%31 = OpLoad %28 %30
+%32 = OpLoad %6 %8
+%33 = OpLoad %6 %18
+%34 = OpLoad %6 %23
+%36 = OpCompositeConstruct %35 %32 %33 %34
+%38 = OpLoad %6 %8
+%40 = OpSMod %6 %38 %39
+%41 = OpLoad %6 %18
+%42 = OpLoad %6 %23
+%43 = OpCompositeConstruct %35 %40 %41 %42
+%44 = OpLoad %6 %8
+%45 = OpLoad %6 %8
+%46 = OpIMul %6 %44 %45
+%47 = OpLoad %6 %18
+%48 = OpLoad %6 %18
+%49 = OpIMul %6 %47 %48
+%50 = OpIAdd %6 %46 %49
+%51 = OpLoad %6 %23
+%52 = OpLoad %6 %23
+%53 = OpIMul %6 %51 %52
+%54 = OpIAdd %6 %50 %53
+%56 = OpImageTexelPointer %55 %37 %43 %13
+%57 = ${OPNAME} %6 %56 %19 %13 ${LASTARG:default=%54}
+%59 = OpCompositeConstruct %58 %57 %57 %57 %57
+OpImageWrite %31 %36 %59
+OpReturn
+OpFunctionEnd
+)";
+
+const std::string kShader_3d_r32ui_end_result = R"(
+; The SPIR-V shader below is based on the following GLSL shader, but OpAtomicIAdd has been
+; replaced with a template parameter and the last argument for it has been made optional.
+;
+; #version 440
+; precision highp uimage3D;
+;
+; layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+; layout (r32ui, binding=0) coherent uniform uimage3D u_resultImage;
+;
+; void main (void)
+; {
+; int gx = int(gl_GlobalInvocationID.x);
+; int gy = int(gl_GlobalInvocationID.y);
+; int gz = int(gl_GlobalInvocationID.z);
+; imageAtomicAdd(u_resultImage, ivec3(gx % 64,gy,gz), uint(gx*gx + gy*gy + gz*gz));
+; }
+;
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 54
+; Schema: 0
+OpCapability Shader
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %4 "main" %12
+OpExecutionMode %4 LocalSize 1 1 1
+OpDecorate %12 BuiltIn GlobalInvocationId
+OpDecorate %30 DescriptorSet 0
+OpDecorate %30 Binding 0
+OpDecorate %30 Coherent
+OpDecorate %53 BuiltIn WorkgroupSize
+%2 = OpTypeVoid
+%3 = OpTypeFunction %2
+%6 = OpTypeInt 32 1
+%7 = OpTypePointer Function %6
+%9 = OpTypeInt 32 0
+%10 = OpTypeVector %9 3
+%11 = OpTypePointer Input %10
+%12 = OpVariable %11 Input
+%13 = OpConstant %9 0
+%14 = OpTypePointer Input %9
+%19 = OpConstant %9 1
+%24 = OpConstant %9 2
+%28 = OpTypeImage %9 3D 0 0 0 2 R32ui
+%29 = OpTypePointer UniformConstant %28
+%30 = OpVariable %29 UniformConstant
+%32 = OpConstant %6 64
+%36 = OpTypeVector %6 3
+%50 = OpTypePointer Image %9
+%53 = OpConstantComposite %10 %19 %19 %19
+%4 = OpFunction %2 None %3
+%5 = OpLabel
+%8 = OpVariable %7 Function
+%18 = OpVariable %7 Function
+%23 = OpVariable %7 Function
+%15 = OpAccessChain %14 %12 %13
+%16 = OpLoad %9 %15
+%17 = OpBitcast %6 %16
+OpStore %8 %17
+%20 = OpAccessChain %14 %12 %19
+%21 = OpLoad %9 %20
+%22 = OpBitcast %6 %21
+OpStore %18 %22
+%25 = OpAccessChain %14 %12 %24
+%26 = OpLoad %9 %25
+%27 = OpBitcast %6 %26
+OpStore %23 %27
+%31 = OpLoad %6 %8
+%33 = OpSMod %6 %31 %32
+%34 = OpLoad %6 %18
+%35 = OpLoad %6 %23
+%37 = OpCompositeConstruct %36 %33 %34 %35
+%38 = OpLoad %6 %8
+%39 = OpLoad %6 %8
+%40 = OpIMul %6 %38 %39
+%41 = OpLoad %6 %18
+%42 = OpLoad %6 %18
+%43 = OpIMul %6 %41 %42
+%44 = OpIAdd %6 %40 %43
+%45 = OpLoad %6 %23
+%46 = OpLoad %6 %23
+%47 = OpIMul %6 %45 %46
+%48 = OpIAdd %6 %44 %47
+%49 = OpBitcast %9 %48
+%51 = OpImageTexelPointer %50 %30 %37 %13
+%52 = ${OPNAME} %9 %51 %19 %13 ${LASTARG:default=%49}
+OpReturn
+OpFunctionEnd
+)";
+
+const std::string kShader_3d_r32ui_intermediate_values = R"(
+; The SPIR-V shader below is based on the following GLSL shader, but OpAtomicIAdd has been
+; replaced with a template parameter and the last argument for it has been made optional.
+;
+; #version 440
+; precision highp uimage3D;
+;
+; layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+; layout (r32ui, binding=0) coherent uniform uimage3D u_resultImage;
+; layout (r32ui, binding=1) writeonly uniform uimage3D u_intermValuesImage;
+;
+; void main (void)
+; {
+; int gx = int(gl_GlobalInvocationID.x);
+; int gy = int(gl_GlobalInvocationID.y);
+; int gz = int(gl_GlobalInvocationID.z);
+; imageStore(u_intermValuesImage, ivec3(gx,gy,gz), uvec4(imageAtomicAdd(u_resultImage, ivec3(gx % 64,gy,gz), uint(gx*gx + gy*gy + gz*gz))));
+; }
+;
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 62
+; Schema: 0
+OpCapability Shader
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %4 "main" %12
+OpExecutionMode %4 LocalSize 1 1 1
+OpDecorate %12 BuiltIn GlobalInvocationId
+OpDecorate %30 DescriptorSet 0
+OpDecorate %30 Binding 1
+OpDecorate %30 NonReadable
+OpDecorate %37 DescriptorSet 0
+OpDecorate %37 Binding 0
+OpDecorate %37 Coherent
+OpDecorate %61 BuiltIn WorkgroupSize
+%2 = OpTypeVoid
+%3 = OpTypeFunction %2
+%6 = OpTypeInt 32 1
+%7 = OpTypePointer Function %6
+%9 = OpTypeInt 32 0
+%10 = OpTypeVector %9 3
+%11 = OpTypePointer Input %10
+%12 = OpVariable %11 Input
+%13 = OpConstant %9 0
+%14 = OpTypePointer Input %9
+%19 = OpConstant %9 1
+%24 = OpConstant %9 2
+%28 = OpTypeImage %9 3D 0 0 0 2 R32ui
+%29 = OpTypePointer UniformConstant %28
+%30 = OpVariable %29 UniformConstant
+%35 = OpTypeVector %6 3
+%37 = OpVariable %29 UniformConstant
+%39 = OpConstant %6 64
+%56 = OpTypePointer Image %9
+%59 = OpTypeVector %9 4
+%61 = OpConstantComposite %10 %19 %19 %19
+%4 = OpFunction %2 None %3
+%5 = OpLabel
+%8 = OpVariable %7 Function
+%18 = OpVariable %7 Function
+%23 = OpVariable %7 Function
+%15 = OpAccessChain %14 %12 %13
+%16 = OpLoad %9 %15
+%17 = OpBitcast %6 %16
+OpStore %8 %17
+%20 = OpAccessChain %14 %12 %19
+%21 = OpLoad %9 %20
+%22 = OpBitcast %6 %21
+OpStore %18 %22
+%25 = OpAccessChain %14 %12 %24
+%26 = OpLoad %9 %25
+%27 = OpBitcast %6 %26
+OpStore %23 %27
+%31 = OpLoad %28 %30
+%32 = OpLoad %6 %8
+%33 = OpLoad %6 %18
+%34 = OpLoad %6 %23
+%36 = OpCompositeConstruct %35 %32 %33 %34
+%38 = OpLoad %6 %8
+%40 = OpSMod %6 %38 %39
+%41 = OpLoad %6 %18
+%42 = OpLoad %6 %23
+%43 = OpCompositeConstruct %35 %40 %41 %42
+%44 = OpLoad %6 %8
+%45 = OpLoad %6 %8
+%46 = OpIMul %6 %44 %45
+%47 = OpLoad %6 %18
+%48 = OpLoad %6 %18
+%49 = OpIMul %6 %47 %48
+%50 = OpIAdd %6 %46 %49
+%51 = OpLoad %6 %23
+%52 = OpLoad %6 %23
+%53 = OpIMul %6 %51 %52
+%54 = OpIAdd %6 %50 %53
+%55 = OpBitcast %9 %54
+%57 = OpImageTexelPointer %56 %37 %43 %13
+%58 = ${OPNAME} %9 %57 %19 %13 ${LASTARG:default=%55}
+%60 = OpCompositeConstruct %59 %58 %58 %58 %58
+OpImageWrite %31 %36 %60
+OpReturn
+OpFunctionEnd
+)";
+
+const std::string kShader_3d_r32i_end_result = R"(
+; The SPIR-V shader below is based on the following GLSL shader, but OpAtomicIAdd has been
+; replaced with a template parameter and the last argument for it has been made optional.
+;
+; #version 440
+; precision highp iimage3D;
+;
+; layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+; layout (r32i, binding=0) coherent uniform iimage3D u_resultImage;
+;
+; void main (void)
+; {
+; int gx = int(gl_GlobalInvocationID.x);
+; int gy = int(gl_GlobalInvocationID.y);
+; int gz = int(gl_GlobalInvocationID.z);
+; imageAtomicAdd(u_resultImage, ivec3(gx % 64,gy,gz), int(gx*gx + gy*gy + gz*gz));
+; }
+;
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 53
+; Schema: 0
+OpCapability Shader
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %4 "main" %12
+OpExecutionMode %4 LocalSize 1 1 1
+OpDecorate %12 BuiltIn GlobalInvocationId
+OpDecorate %30 DescriptorSet 0
+OpDecorate %30 Binding 0
+OpDecorate %30 Coherent
+OpDecorate %52 BuiltIn WorkgroupSize
+%2 = OpTypeVoid
+%3 = OpTypeFunction %2
+%6 = OpTypeInt 32 1
+%7 = OpTypePointer Function %6
+%9 = OpTypeInt 32 0
+%10 = OpTypeVector %9 3
+%11 = OpTypePointer Input %10
+%12 = OpVariable %11 Input
+%13 = OpConstant %9 0
+%14 = OpTypePointer Input %9
+%19 = OpConstant %9 1
+%24 = OpConstant %9 2
+%28 = OpTypeImage %6 3D 0 0 0 2 R32i
+%29 = OpTypePointer UniformConstant %28
+%30 = OpVariable %29 UniformConstant
+%32 = OpConstant %6 64
+%36 = OpTypeVector %6 3
+%49 = OpTypePointer Image %6
+%52 = OpConstantComposite %10 %19 %19 %19
+%4 = OpFunction %2 None %3
+%5 = OpLabel
+%8 = OpVariable %7 Function
+%18 = OpVariable %7 Function
+%23 = OpVariable %7 Function
+%15 = OpAccessChain %14 %12 %13
+%16 = OpLoad %9 %15
+%17 = OpBitcast %6 %16
+OpStore %8 %17
+%20 = OpAccessChain %14 %12 %19
+%21 = OpLoad %9 %20
+%22 = OpBitcast %6 %21
+OpStore %18 %22
+%25 = OpAccessChain %14 %12 %24
+%26 = OpLoad %9 %25
+%27 = OpBitcast %6 %26
+OpStore %23 %27
+%31 = OpLoad %6 %8
+%33 = OpSMod %6 %31 %32
+%34 = OpLoad %6 %18
+%35 = OpLoad %6 %23
+%37 = OpCompositeConstruct %36 %33 %34 %35
+%38 = OpLoad %6 %8
+%39 = OpLoad %6 %8
+%40 = OpIMul %6 %38 %39
+%41 = OpLoad %6 %18
+%42 = OpLoad %6 %18
+%43 = OpIMul %6 %41 %42
+%44 = OpIAdd %6 %40 %43
+%45 = OpLoad %6 %23
+%46 = OpLoad %6 %23
+%47 = OpIMul %6 %45 %46
+%48 = OpIAdd %6 %44 %47
+%50 = OpImageTexelPointer %49 %30 %37 %13
+%51 = ${OPNAME} %6 %50 %19 %13 ${LASTARG:default=%48}
+OpReturn
+OpFunctionEnd
+)";
+
+const std::string kShader_3d_r32i_intermediate_values = R"(
+; The SPIR-V shader below is based on the following GLSL shader, but OpAtomicIAdd has been
+; replaced with a template parameter and the last argument for it has been made optional.
+;
+; #version 440
+; precision highp iimage3D;
+;
+; layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+; layout (r32i, binding=0) coherent uniform iimage3D u_resultImage;
+; layout (r32i, binding=1) writeonly uniform iimage3D u_intermValuesImage;
+;
+; void main (void)
+; {
+; int gx = int(gl_GlobalInvocationID.x);
+; int gy = int(gl_GlobalInvocationID.y);
+; int gz = int(gl_GlobalInvocationID.z);
+; imageStore(u_intermValuesImage, ivec3(gx,gy,gz), ivec4(imageAtomicAdd(u_resultImage, ivec3(gx % 64,gy,gz), int(gx*gx + gy*gy + gz*gz))));
+; }
+;
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 61
+; Schema: 0
+OpCapability Shader
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %4 "main" %12
+OpExecutionMode %4 LocalSize 1 1 1
+OpDecorate %12 BuiltIn GlobalInvocationId
+OpDecorate %30 DescriptorSet 0
+OpDecorate %30 Binding 1
+OpDecorate %30 NonReadable
+OpDecorate %37 DescriptorSet 0
+OpDecorate %37 Binding 0
+OpDecorate %37 Coherent
+OpDecorate %60 BuiltIn WorkgroupSize
+%2 = OpTypeVoid
+%3 = OpTypeFunction %2
+%6 = OpTypeInt 32 1
+%7 = OpTypePointer Function %6
+%9 = OpTypeInt 32 0
+%10 = OpTypeVector %9 3
+%11 = OpTypePointer Input %10
+%12 = OpVariable %11 Input
+%13 = OpConstant %9 0
+%14 = OpTypePointer Input %9
+%19 = OpConstant %9 1
+%24 = OpConstant %9 2
+%28 = OpTypeImage %6 3D 0 0 0 2 R32i
+%29 = OpTypePointer UniformConstant %28
+%30 = OpVariable %29 UniformConstant
+%35 = OpTypeVector %6 3
+%37 = OpVariable %29 UniformConstant
+%39 = OpConstant %6 64
+%55 = OpTypePointer Image %6
+%58 = OpTypeVector %6 4
+%60 = OpConstantComposite %10 %19 %19 %19
+%4 = OpFunction %2 None %3
+%5 = OpLabel
+%8 = OpVariable %7 Function
+%18 = OpVariable %7 Function
+%23 = OpVariable %7 Function
+%15 = OpAccessChain %14 %12 %13
+%16 = OpLoad %9 %15
+%17 = OpBitcast %6 %16
+OpStore %8 %17
+%20 = OpAccessChain %14 %12 %19
+%21 = OpLoad %9 %20
+%22 = OpBitcast %6 %21
+OpStore %18 %22
+%25 = OpAccessChain %14 %12 %24
+%26 = OpLoad %9 %25
+%27 = OpBitcast %6 %26
+OpStore %23 %27
+%31 = OpLoad %28 %30
+%32 = OpLoad %6 %8
+%33 = OpLoad %6 %18
+%34 = OpLoad %6 %23
+%36 = OpCompositeConstruct %35 %32 %33 %34
+%38 = OpLoad %6 %8
+%40 = OpSMod %6 %38 %39
+%41 = OpLoad %6 %18
+%42 = OpLoad %6 %23
+%43 = OpCompositeConstruct %35 %40 %41 %42
+%44 = OpLoad %6 %8
+%45 = OpLoad %6 %8
+%46 = OpIMul %6 %44 %45
+%47 = OpLoad %6 %18
+%48 = OpLoad %6 %18
+%49 = OpIMul %6 %47 %48
+%50 = OpIAdd %6 %46 %49
+%51 = OpLoad %6 %23
+%52 = OpLoad %6 %23
+%53 = OpIMul %6 %51 %52
+%54 = OpIAdd %6 %50 %53
+%56 = OpImageTexelPointer %55 %37 %43 %13
+%57 = ${OPNAME} %6 %56 %19 %13 ${LASTARG:default=%54}
+%59 = OpCompositeConstruct %58 %57 %57 %57 %57
+OpImageWrite %31 %36 %59
+OpReturn
+OpFunctionEnd
+)";
+
+const std::string kShader_cube_r32ui_end_result = R"(
+; The SPIR-V shader below is based on the following GLSL shader, but OpAtomicIAdd has been
+; replaced with a template parameter and the last argument for it has been made optional.
+;
+; #version 440
+; precision highp uimageCube;
+;
+; layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+; layout (r32ui, binding=0) coherent uniform uimageCube u_resultImage;
+;
+; void main (void)
+; {
+; int gx = int(gl_GlobalInvocationID.x);
+; int gy = int(gl_GlobalInvocationID.y);
+; int gz = int(gl_GlobalInvocationID.z);
+; imageAtomicAdd(u_resultImage, ivec3(gx % 64,gy,gz), uint(gx*gx + gy*gy + gz*gz));
+; }
+;
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 54
+; Schema: 0
+OpCapability Shader
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %4 "main" %12
+OpExecutionMode %4 LocalSize 1 1 1
+OpDecorate %12 BuiltIn GlobalInvocationId
+OpDecorate %30 DescriptorSet 0
+OpDecorate %30 Binding 0
+OpDecorate %30 Coherent
+OpDecorate %53 BuiltIn WorkgroupSize
+%2 = OpTypeVoid
+%3 = OpTypeFunction %2
+%6 = OpTypeInt 32 1
+%7 = OpTypePointer Function %6
+%9 = OpTypeInt 32 0
+%10 = OpTypeVector %9 3
+%11 = OpTypePointer Input %10
+%12 = OpVariable %11 Input
+%13 = OpConstant %9 0
+%14 = OpTypePointer Input %9
+%19 = OpConstant %9 1
+%24 = OpConstant %9 2
+%28 = OpTypeImage %9 Cube 0 0 0 2 R32ui
+%29 = OpTypePointer UniformConstant %28
+%30 = OpVariable %29 UniformConstant
+%32 = OpConstant %6 64
+%36 = OpTypeVector %6 3
+%50 = OpTypePointer Image %9
+%53 = OpConstantComposite %10 %19 %19 %19
+%4 = OpFunction %2 None %3
+%5 = OpLabel
+%8 = OpVariable %7 Function
+%18 = OpVariable %7 Function
+%23 = OpVariable %7 Function
+%15 = OpAccessChain %14 %12 %13
+%16 = OpLoad %9 %15
+%17 = OpBitcast %6 %16
+OpStore %8 %17
+%20 = OpAccessChain %14 %12 %19
+%21 = OpLoad %9 %20
+%22 = OpBitcast %6 %21
+OpStore %18 %22
+%25 = OpAccessChain %14 %12 %24
+%26 = OpLoad %9 %25
+%27 = OpBitcast %6 %26
+OpStore %23 %27
+%31 = OpLoad %6 %8
+%33 = OpSMod %6 %31 %32
+%34 = OpLoad %6 %18
+%35 = OpLoad %6 %23
+%37 = OpCompositeConstruct %36 %33 %34 %35
+%38 = OpLoad %6 %8
+%39 = OpLoad %6 %8
+%40 = OpIMul %6 %38 %39
+%41 = OpLoad %6 %18
+%42 = OpLoad %6 %18
+%43 = OpIMul %6 %41 %42
+%44 = OpIAdd %6 %40 %43
+%45 = OpLoad %6 %23
+%46 = OpLoad %6 %23
+%47 = OpIMul %6 %45 %46
+%48 = OpIAdd %6 %44 %47
+%49 = OpBitcast %9 %48
+%51 = OpImageTexelPointer %50 %30 %37 %13
+%52 = ${OPNAME} %9 %51 %19 %13 ${LASTARG:default=%49}
+OpReturn
+OpFunctionEnd
+)";
+
+const std::string kShader_cube_r32ui_intermediate_values = R"(
+; The SPIR-V shader below is based on the following GLSL shader, but OpAtomicIAdd has been
+; replaced with a template parameter and the last argument for it has been made optional.
+;
+; #version 440
+; precision highp uimageCube;
+;
+; layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+; layout (r32ui, binding=0) coherent uniform uimageCube u_resultImage;
+; layout (r32ui, binding=1) writeonly uniform uimageCube u_intermValuesImage;
+;
+; void main (void)
+; {
+; int gx = int(gl_GlobalInvocationID.x);
+; int gy = int(gl_GlobalInvocationID.y);
+; int gz = int(gl_GlobalInvocationID.z);
+; imageStore(u_intermValuesImage, ivec3(gx,gy,gz), uvec4(imageAtomicAdd(u_resultImage, ivec3(gx % 64,gy,gz), uint(gx*gx + gy*gy + gz*gz))));
+; }
+;
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 62
+; Schema: 0
+OpCapability Shader
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %4 "main" %12
+OpExecutionMode %4 LocalSize 1 1 1
+OpDecorate %12 BuiltIn GlobalInvocationId
+OpDecorate %30 DescriptorSet 0
+OpDecorate %30 Binding 1
+OpDecorate %30 NonReadable
+OpDecorate %37 DescriptorSet 0
+OpDecorate %37 Binding 0
+OpDecorate %37 Coherent
+OpDecorate %61 BuiltIn WorkgroupSize
+%2 = OpTypeVoid
+%3 = OpTypeFunction %2
+%6 = OpTypeInt 32 1
+%7 = OpTypePointer Function %6
+%9 = OpTypeInt 32 0
+%10 = OpTypeVector %9 3
+%11 = OpTypePointer Input %10
+%12 = OpVariable %11 Input
+%13 = OpConstant %9 0
+%14 = OpTypePointer Input %9
+%19 = OpConstant %9 1
+%24 = OpConstant %9 2
+%28 = OpTypeImage %9 Cube 0 0 0 2 R32ui
+%29 = OpTypePointer UniformConstant %28
+%30 = OpVariable %29 UniformConstant
+%35 = OpTypeVector %6 3
+%37 = OpVariable %29 UniformConstant
+%39 = OpConstant %6 64
+%56 = OpTypePointer Image %9
+%59 = OpTypeVector %9 4
+%61 = OpConstantComposite %10 %19 %19 %19
+%4 = OpFunction %2 None %3
+%5 = OpLabel
+%8 = OpVariable %7 Function
+%18 = OpVariable %7 Function
+%23 = OpVariable %7 Function
+%15 = OpAccessChain %14 %12 %13
+%16 = OpLoad %9 %15
+%17 = OpBitcast %6 %16
+OpStore %8 %17
+%20 = OpAccessChain %14 %12 %19
+%21 = OpLoad %9 %20
+%22 = OpBitcast %6 %21
+OpStore %18 %22
+%25 = OpAccessChain %14 %12 %24
+%26 = OpLoad %9 %25
+%27 = OpBitcast %6 %26
+OpStore %23 %27
+%31 = OpLoad %28 %30
+%32 = OpLoad %6 %8
+%33 = OpLoad %6 %18
+%34 = OpLoad %6 %23
+%36 = OpCompositeConstruct %35 %32 %33 %34
+%38 = OpLoad %6 %8
+%40 = OpSMod %6 %38 %39
+%41 = OpLoad %6 %18
+%42 = OpLoad %6 %23
+%43 = OpCompositeConstruct %35 %40 %41 %42
+%44 = OpLoad %6 %8
+%45 = OpLoad %6 %8
+%46 = OpIMul %6 %44 %45
+%47 = OpLoad %6 %18
+%48 = OpLoad %6 %18
+%49 = OpIMul %6 %47 %48
+%50 = OpIAdd %6 %46 %49
+%51 = OpLoad %6 %23
+%52 = OpLoad %6 %23
+%53 = OpIMul %6 %51 %52
+%54 = OpIAdd %6 %50 %53
+%55 = OpBitcast %9 %54
+%57 = OpImageTexelPointer %56 %37 %43 %13
+%58 = ${OPNAME} %9 %57 %19 %13 ${LASTARG:default=%55}
+%60 = OpCompositeConstruct %59 %58 %58 %58 %58
+OpImageWrite %31 %36 %60
+OpReturn
+OpFunctionEnd
+)";
+
+const std::string kShader_cube_r32i_end_result = R"(
+; The SPIR-V shader below is based on the following GLSL shader, but OpAtomicIAdd has been
+; replaced with a template parameter and the last argument for it has been made optional.
+;
+; #version 440
+; precision highp iimageCube;
+;
+; layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+; layout (r32i, binding=0) coherent uniform iimageCube u_resultImage;
+;
+; void main (void)
+; {
+; int gx = int(gl_GlobalInvocationID.x);
+; int gy = int(gl_GlobalInvocationID.y);
+; int gz = int(gl_GlobalInvocationID.z);
+; imageAtomicAdd(u_resultImage, ivec3(gx % 64,gy,gz), int(gx*gx + gy*gy + gz*gz));
+; }
+;
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 53
+; Schema: 0
+OpCapability Shader
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %4 "main" %12
+OpExecutionMode %4 LocalSize 1 1 1
+OpDecorate %12 BuiltIn GlobalInvocationId
+OpDecorate %30 DescriptorSet 0
+OpDecorate %30 Binding 0
+OpDecorate %30 Coherent
+OpDecorate %52 BuiltIn WorkgroupSize
+%2 = OpTypeVoid
+%3 = OpTypeFunction %2
+%6 = OpTypeInt 32 1
+%7 = OpTypePointer Function %6
+%9 = OpTypeInt 32 0
+%10 = OpTypeVector %9 3
+%11 = OpTypePointer Input %10
+%12 = OpVariable %11 Input
+%13 = OpConstant %9 0
+%14 = OpTypePointer Input %9
+%19 = OpConstant %9 1
+%24 = OpConstant %9 2
+%28 = OpTypeImage %6 Cube 0 0 0 2 R32i
+%29 = OpTypePointer UniformConstant %28
+%30 = OpVariable %29 UniformConstant
+%32 = OpConstant %6 64
+%36 = OpTypeVector %6 3
+%49 = OpTypePointer Image %6
+%52 = OpConstantComposite %10 %19 %19 %19
+%4 = OpFunction %2 None %3
+%5 = OpLabel
+%8 = OpVariable %7 Function
+%18 = OpVariable %7 Function
+%23 = OpVariable %7 Function
+%15 = OpAccessChain %14 %12 %13
+%16 = OpLoad %9 %15
+%17 = OpBitcast %6 %16
+OpStore %8 %17
+%20 = OpAccessChain %14 %12 %19
+%21 = OpLoad %9 %20
+%22 = OpBitcast %6 %21
+OpStore %18 %22
+%25 = OpAccessChain %14 %12 %24
+%26 = OpLoad %9 %25
+%27 = OpBitcast %6 %26
+OpStore %23 %27
+%31 = OpLoad %6 %8
+%33 = OpSMod %6 %31 %32
+%34 = OpLoad %6 %18
+%35 = OpLoad %6 %23
+%37 = OpCompositeConstruct %36 %33 %34 %35
+%38 = OpLoad %6 %8
+%39 = OpLoad %6 %8
+%40 = OpIMul %6 %38 %39
+%41 = OpLoad %6 %18
+%42 = OpLoad %6 %18
+%43 = OpIMul %6 %41 %42
+%44 = OpIAdd %6 %40 %43
+%45 = OpLoad %6 %23
+%46 = OpLoad %6 %23
+%47 = OpIMul %6 %45 %46
+%48 = OpIAdd %6 %44 %47
+%50 = OpImageTexelPointer %49 %30 %37 %13
+%51 = ${OPNAME} %6 %50 %19 %13 ${LASTARG:default=%48}
+OpReturn
+OpFunctionEnd
+)";
+
+const std::string kShader_cube_r32i_intermediate_values = R"(
+; The SPIR-V shader below is based on the following GLSL shader, but OpAtomicIAdd has been
+; replaced with a template parameter and the last argument for it has been made optional.
+;
+; #version 440
+; precision highp iimageCube;
+;
+; layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+; layout (r32i, binding=0) coherent uniform iimageCube u_resultImage;
+; layout (r32i, binding=1) writeonly uniform iimageCube u_intermValuesImage;
+;
+; void main (void)
+; {
+; int gx = int(gl_GlobalInvocationID.x);
+; int gy = int(gl_GlobalInvocationID.y);
+; int gz = int(gl_GlobalInvocationID.z);
+; imageStore(u_intermValuesImage, ivec3(gx,gy,gz), ivec4(imageAtomicAdd(u_resultImage, ivec3(gx % 64,gy,gz), int(gx*gx + gy*gy + gz*gz))));
+; }
+;
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 61
+; Schema: 0
+OpCapability Shader
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %4 "main" %12
+OpExecutionMode %4 LocalSize 1 1 1
+OpDecorate %12 BuiltIn GlobalInvocationId
+OpDecorate %30 DescriptorSet 0
+OpDecorate %30 Binding 1
+OpDecorate %30 NonReadable
+OpDecorate %37 DescriptorSet 0
+OpDecorate %37 Binding 0
+OpDecorate %37 Coherent
+OpDecorate %60 BuiltIn WorkgroupSize
+%2 = OpTypeVoid
+%3 = OpTypeFunction %2
+%6 = OpTypeInt 32 1
+%7 = OpTypePointer Function %6
+%9 = OpTypeInt 32 0
+%10 = OpTypeVector %9 3
+%11 = OpTypePointer Input %10
+%12 = OpVariable %11 Input
+%13 = OpConstant %9 0
+%14 = OpTypePointer Input %9
+%19 = OpConstant %9 1
+%24 = OpConstant %9 2
+%28 = OpTypeImage %6 Cube 0 0 0 2 R32i
+%29 = OpTypePointer UniformConstant %28
+%30 = OpVariable %29 UniformConstant
+%35 = OpTypeVector %6 3
+%37 = OpVariable %29 UniformConstant
+%39 = OpConstant %6 64
+%55 = OpTypePointer Image %6
+%58 = OpTypeVector %6 4
+%60 = OpConstantComposite %10 %19 %19 %19
+%4 = OpFunction %2 None %3
+%5 = OpLabel
+%8 = OpVariable %7 Function
+%18 = OpVariable %7 Function
+%23 = OpVariable %7 Function
+%15 = OpAccessChain %14 %12 %13
+%16 = OpLoad %9 %15
+%17 = OpBitcast %6 %16
+OpStore %8 %17
+%20 = OpAccessChain %14 %12 %19
+%21 = OpLoad %9 %20
+%22 = OpBitcast %6 %21
+OpStore %18 %22
+%25 = OpAccessChain %14 %12 %24
+%26 = OpLoad %9 %25
+%27 = OpBitcast %6 %26
+OpStore %23 %27
+%31 = OpLoad %28 %30
+%32 = OpLoad %6 %8
+%33 = OpLoad %6 %18
+%34 = OpLoad %6 %23
+%36 = OpCompositeConstruct %35 %32 %33 %34
+%38 = OpLoad %6 %8
+%40 = OpSMod %6 %38 %39
+%41 = OpLoad %6 %18
+%42 = OpLoad %6 %23
+%43 = OpCompositeConstruct %35 %40 %41 %42
+%44 = OpLoad %6 %8
+%45 = OpLoad %6 %8
+%46 = OpIMul %6 %44 %45
+%47 = OpLoad %6 %18
+%48 = OpLoad %6 %18
+%49 = OpIMul %6 %47 %48
+%50 = OpIAdd %6 %46 %49
+%51 = OpLoad %6 %23
+%52 = OpLoad %6 %23
+%53 = OpIMul %6 %51 %52
+%54 = OpIAdd %6 %50 %53
+%56 = OpImageTexelPointer %55 %37 %43 %13
+%57 = ${OPNAME} %6 %56 %19 %13 ${LASTARG:default=%54}
+%59 = OpCompositeConstruct %58 %57 %57 %57 %57
+OpImageWrite %31 %36 %59
+OpReturn
+OpFunctionEnd
+)";
+
+const std::string kShader_cube_array_r32ui_end_result = R"(
+; The SPIR-V shader below is based on the following GLSL shader, but OpAtomicIAdd has been
+; replaced with a template parameter and the last argument for it has been made optional.
+;
+; #version 440
+; precision highp uimageCubeArray;
+;
+; layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+; layout (r32ui, binding=0) coherent uniform uimageCubeArray u_resultImage;
+;
+; void main (void)
+; {
+; int gx = int(gl_GlobalInvocationID.x);
+; int gy = int(gl_GlobalInvocationID.y);
+; int gz = int(gl_GlobalInvocationID.z);
+; imageAtomicAdd(u_resultImage, ivec3(gx % 64,gy,gz), uint(gx*gx + gy*gy + gz*gz));
+; }
+;
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 54
+; Schema: 0
+OpCapability Shader
+OpCapability ImageCubeArray
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %4 "main" %12
+OpExecutionMode %4 LocalSize 1 1 1
+OpDecorate %12 BuiltIn GlobalInvocationId
+OpDecorate %30 DescriptorSet 0
+OpDecorate %30 Binding 0
+OpDecorate %30 Coherent
+OpDecorate %53 BuiltIn WorkgroupSize
+%2 = OpTypeVoid
+%3 = OpTypeFunction %2
+%6 = OpTypeInt 32 1
+%7 = OpTypePointer Function %6
+%9 = OpTypeInt 32 0
+%10 = OpTypeVector %9 3
+%11 = OpTypePointer Input %10
+%12 = OpVariable %11 Input
+%13 = OpConstant %9 0
+%14 = OpTypePointer Input %9
+%19 = OpConstant %9 1
+%24 = OpConstant %9 2
+%28 = OpTypeImage %9 Cube 0 1 0 2 R32ui
+%29 = OpTypePointer UniformConstant %28
+%30 = OpVariable %29 UniformConstant
+%32 = OpConstant %6 64
+%36 = OpTypeVector %6 3
+%50 = OpTypePointer Image %9
+%53 = OpConstantComposite %10 %19 %19 %19
+%4 = OpFunction %2 None %3
+%5 = OpLabel
+%8 = OpVariable %7 Function
+%18 = OpVariable %7 Function
+%23 = OpVariable %7 Function
+%15 = OpAccessChain %14 %12 %13
+%16 = OpLoad %9 %15
+%17 = OpBitcast %6 %16
+OpStore %8 %17
+%20 = OpAccessChain %14 %12 %19
+%21 = OpLoad %9 %20
+%22 = OpBitcast %6 %21
+OpStore %18 %22
+%25 = OpAccessChain %14 %12 %24
+%26 = OpLoad %9 %25
+%27 = OpBitcast %6 %26
+OpStore %23 %27
+%31 = OpLoad %6 %8
+%33 = OpSMod %6 %31 %32
+%34 = OpLoad %6 %18
+%35 = OpLoad %6 %23
+%37 = OpCompositeConstruct %36 %33 %34 %35
+%38 = OpLoad %6 %8
+%39 = OpLoad %6 %8
+%40 = OpIMul %6 %38 %39
+%41 = OpLoad %6 %18
+%42 = OpLoad %6 %18
+%43 = OpIMul %6 %41 %42
+%44 = OpIAdd %6 %40 %43
+%45 = OpLoad %6 %23
+%46 = OpLoad %6 %23
+%47 = OpIMul %6 %45 %46
+%48 = OpIAdd %6 %44 %47
+%49 = OpBitcast %9 %48
+%51 = OpImageTexelPointer %50 %30 %37 %13
+%52 = ${OPNAME} %9 %51 %19 %13 ${LASTARG:default=%49}
+OpReturn
+OpFunctionEnd
+)";
+
+const std::string kShader_cube_array_r32ui_intermediate_values = R"(
+; The SPIR-V shader below is based on the following GLSL shader, but OpAtomicIAdd has been
+; replaced with a template parameter and the last argument for it has been made optional.
+;
+; #version 440
+; precision highp uimageCubeArray;
+;
+; layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+; layout (r32ui, binding=0) coherent uniform uimageCubeArray u_resultImage;
+; layout (r32ui, binding=1) writeonly uniform uimageCubeArray u_intermValuesImage;
+;
+; void main (void)
+; {
+; int gx = int(gl_GlobalInvocationID.x);
+; int gy = int(gl_GlobalInvocationID.y);
+; int gz = int(gl_GlobalInvocationID.z);
+; imageStore(u_intermValuesImage, ivec3(gx,gy,gz), uvec4(imageAtomicAdd(u_resultImage, ivec3(gx % 64,gy,gz), uint(gx*gx + gy*gy + gz*gz))));
+; }
+;
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 62
+; Schema: 0
+OpCapability Shader
+OpCapability ImageCubeArray
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %4 "main" %12
+OpExecutionMode %4 LocalSize 1 1 1
+OpDecorate %12 BuiltIn GlobalInvocationId
+OpDecorate %30 DescriptorSet 0
+OpDecorate %30 Binding 1
+OpDecorate %30 NonReadable
+OpDecorate %37 DescriptorSet 0
+OpDecorate %37 Binding 0
+OpDecorate %37 Coherent
+OpDecorate %61 BuiltIn WorkgroupSize
+%2 = OpTypeVoid
+%3 = OpTypeFunction %2
+%6 = OpTypeInt 32 1
+%7 = OpTypePointer Function %6
+%9 = OpTypeInt 32 0
+%10 = OpTypeVector %9 3
+%11 = OpTypePointer Input %10
+%12 = OpVariable %11 Input
+%13 = OpConstant %9 0
+%14 = OpTypePointer Input %9
+%19 = OpConstant %9 1
+%24 = OpConstant %9 2
+%28 = OpTypeImage %9 Cube 0 1 0 2 R32ui
+%29 = OpTypePointer UniformConstant %28
+%30 = OpVariable %29 UniformConstant
+%35 = OpTypeVector %6 3
+%37 = OpVariable %29 UniformConstant
+%39 = OpConstant %6 64
+%56 = OpTypePointer Image %9
+%59 = OpTypeVector %9 4
+%61 = OpConstantComposite %10 %19 %19 %19
+%4 = OpFunction %2 None %3
+%5 = OpLabel
+%8 = OpVariable %7 Function
+%18 = OpVariable %7 Function
+%23 = OpVariable %7 Function
+%15 = OpAccessChain %14 %12 %13
+%16 = OpLoad %9 %15
+%17 = OpBitcast %6 %16
+OpStore %8 %17
+%20 = OpAccessChain %14 %12 %19
+%21 = OpLoad %9 %20
+%22 = OpBitcast %6 %21
+OpStore %18 %22
+%25 = OpAccessChain %14 %12 %24
+%26 = OpLoad %9 %25
+%27 = OpBitcast %6 %26
+OpStore %23 %27
+%31 = OpLoad %28 %30
+%32 = OpLoad %6 %8
+%33 = OpLoad %6 %18
+%34 = OpLoad %6 %23
+%36 = OpCompositeConstruct %35 %32 %33 %34
+%38 = OpLoad %6 %8
+%40 = OpSMod %6 %38 %39
+%41 = OpLoad %6 %18
+%42 = OpLoad %6 %23
+%43 = OpCompositeConstruct %35 %40 %41 %42
+%44 = OpLoad %6 %8
+%45 = OpLoad %6 %8
+%46 = OpIMul %6 %44 %45
+%47 = OpLoad %6 %18
+%48 = OpLoad %6 %18
+%49 = OpIMul %6 %47 %48
+%50 = OpIAdd %6 %46 %49
+%51 = OpLoad %6 %23
+%52 = OpLoad %6 %23
+%53 = OpIMul %6 %51 %52
+%54 = OpIAdd %6 %50 %53
+%55 = OpBitcast %9 %54
+%57 = OpImageTexelPointer %56 %37 %43 %13
+%58 = ${OPNAME} %9 %57 %19 %13 ${LASTARG:default=%55}
+%60 = OpCompositeConstruct %59 %58 %58 %58 %58
+OpImageWrite %31 %36 %60
+OpReturn
+OpFunctionEnd
+)";
+
+const std::string kShader_cube_array_r32i_end_result = R"(
+; The SPIR-V shader below is based on the following GLSL shader, but OpAtomicIAdd has been
+; replaced with a template parameter and the last argument for it has been made optional.
+;
+; #version 440
+; precision highp iimageCubeArray;
+;
+; layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+; layout (r32i, binding=0) coherent uniform iimageCubeArray u_resultImage;
+;
+; void main (void)
+; {
+; int gx = int(gl_GlobalInvocationID.x);
+; int gy = int(gl_GlobalInvocationID.y);
+; int gz = int(gl_GlobalInvocationID.z);
+; imageAtomicAdd(u_resultImage, ivec3(gx % 64,gy,gz), int(gx*gx + gy*gy + gz*gz));
+; }
+;
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 53
+; Schema: 0
+OpCapability Shader
+OpCapability ImageCubeArray
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %4 "main" %12
+OpExecutionMode %4 LocalSize 1 1 1
+OpDecorate %12 BuiltIn GlobalInvocationId
+OpDecorate %30 DescriptorSet 0
+OpDecorate %30 Binding 0
+OpDecorate %30 Coherent
+OpDecorate %52 BuiltIn WorkgroupSize
+%2 = OpTypeVoid
+%3 = OpTypeFunction %2
+%6 = OpTypeInt 32 1
+%7 = OpTypePointer Function %6
+%9 = OpTypeInt 32 0
+%10 = OpTypeVector %9 3
+%11 = OpTypePointer Input %10
+%12 = OpVariable %11 Input
+%13 = OpConstant %9 0
+%14 = OpTypePointer Input %9
+%19 = OpConstant %9 1
+%24 = OpConstant %9 2
+%28 = OpTypeImage %6 Cube 0 1 0 2 R32i
+%29 = OpTypePointer UniformConstant %28
+%30 = OpVariable %29 UniformConstant
+%32 = OpConstant %6 64
+%36 = OpTypeVector %6 3
+%49 = OpTypePointer Image %6
+%52 = OpConstantComposite %10 %19 %19 %19
+%4 = OpFunction %2 None %3
+%5 = OpLabel
+%8 = OpVariable %7 Function
+%18 = OpVariable %7 Function
+%23 = OpVariable %7 Function
+%15 = OpAccessChain %14 %12 %13
+%16 = OpLoad %9 %15
+%17 = OpBitcast %6 %16
+OpStore %8 %17
+%20 = OpAccessChain %14 %12 %19
+%21 = OpLoad %9 %20
+%22 = OpBitcast %6 %21
+OpStore %18 %22
+%25 = OpAccessChain %14 %12 %24
+%26 = OpLoad %9 %25
+%27 = OpBitcast %6 %26
+OpStore %23 %27
+%31 = OpLoad %6 %8
+%33 = OpSMod %6 %31 %32
+%34 = OpLoad %6 %18
+%35 = OpLoad %6 %23
+%37 = OpCompositeConstruct %36 %33 %34 %35
+%38 = OpLoad %6 %8
+%39 = OpLoad %6 %8
+%40 = OpIMul %6 %38 %39
+%41 = OpLoad %6 %18
+%42 = OpLoad %6 %18
+%43 = OpIMul %6 %41 %42
+%44 = OpIAdd %6 %40 %43
+%45 = OpLoad %6 %23
+%46 = OpLoad %6 %23
+%47 = OpIMul %6 %45 %46
+%48 = OpIAdd %6 %44 %47
+%50 = OpImageTexelPointer %49 %30 %37 %13
+%51 = ${OPNAME} %6 %50 %19 %13 ${LASTARG:default=%48}
+OpReturn
+OpFunctionEnd
+)";
+
+const std::string kShader_cube_array_r32i_intermediate_values = R"(
+; The SPIR-V shader below is based on the following GLSL shader, but OpAtomicIAdd has been
+; replaced with a template parameter and the last argument for it has been made optional.
+;
+; #version 440
+; precision highp iimageCubeArray;
+;
+; layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+; layout (r32i, binding=0) coherent uniform iimageCubeArray u_resultImage;
+; layout (r32i, binding=1) writeonly uniform iimageCubeArray u_intermValuesImage;
+;
+; void main (void)
+; {
+; int gx = int(gl_GlobalInvocationID.x);
+; int gy = int(gl_GlobalInvocationID.y);
+; int gz = int(gl_GlobalInvocationID.z);
+; imageStore(u_intermValuesImage, ivec3(gx,gy,gz), ivec4(imageAtomicAdd(u_resultImage, ivec3(gx % 64,gy,gz), int(gx*gx + gy*gy + gz*gz))));
+; }
+;
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 61
+; Schema: 0
+OpCapability Shader
+OpCapability ImageCubeArray
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %4 "main" %12
+OpExecutionMode %4 LocalSize 1 1 1
+OpDecorate %12 BuiltIn GlobalInvocationId
+OpDecorate %30 DescriptorSet 0
+OpDecorate %30 Binding 1
+OpDecorate %30 NonReadable
+OpDecorate %37 DescriptorSet 0
+OpDecorate %37 Binding 0
+OpDecorate %37 Coherent
+OpDecorate %60 BuiltIn WorkgroupSize
+%2 = OpTypeVoid
+%3 = OpTypeFunction %2
+%6 = OpTypeInt 32 1
+%7 = OpTypePointer Function %6
+%9 = OpTypeInt 32 0
+%10 = OpTypeVector %9 3
+%11 = OpTypePointer Input %10
+%12 = OpVariable %11 Input
+%13 = OpConstant %9 0
+%14 = OpTypePointer Input %9
+%19 = OpConstant %9 1
+%24 = OpConstant %9 2
+%28 = OpTypeImage %6 Cube 0 1 0 2 R32i
+%29 = OpTypePointer UniformConstant %28
+%30 = OpVariable %29 UniformConstant
+%35 = OpTypeVector %6 3
+%37 = OpVariable %29 UniformConstant
+%39 = OpConstant %6 64
+%55 = OpTypePointer Image %6
+%58 = OpTypeVector %6 4
+%60 = OpConstantComposite %10 %19 %19 %19
+%4 = OpFunction %2 None %3
+%5 = OpLabel
+%8 = OpVariable %7 Function
+%18 = OpVariable %7 Function
+%23 = OpVariable %7 Function
+%15 = OpAccessChain %14 %12 %13
+%16 = OpLoad %9 %15
+%17 = OpBitcast %6 %16
+OpStore %8 %17
+%20 = OpAccessChain %14 %12 %19
+%21 = OpLoad %9 %20
+%22 = OpBitcast %6 %21
+OpStore %18 %22
+%25 = OpAccessChain %14 %12 %24
+%26 = OpLoad %9 %25
+%27 = OpBitcast %6 %26
+OpStore %23 %27
+%31 = OpLoad %28 %30
+%32 = OpLoad %6 %8
+%33 = OpLoad %6 %18
+%34 = OpLoad %6 %23
+%36 = OpCompositeConstruct %35 %32 %33 %34
+%38 = OpLoad %6 %8
+%40 = OpSMod %6 %38 %39
+%41 = OpLoad %6 %18
+%42 = OpLoad %6 %23
+%43 = OpCompositeConstruct %35 %40 %41 %42
+%44 = OpLoad %6 %8
+%45 = OpLoad %6 %8
+%46 = OpIMul %6 %44 %45
+%47 = OpLoad %6 %18
+%48 = OpLoad %6 %18
+%49 = OpIMul %6 %47 %48
+%50 = OpIAdd %6 %46 %49
+%51 = OpLoad %6 %23
+%52 = OpLoad %6 %23
+%53 = OpIMul %6 %51 %52
+%54 = OpIAdd %6 %50 %53
+%56 = OpImageTexelPointer %55 %37 %43 %13
+%57 = ${OPNAME} %6 %56 %19 %13 ${LASTARG:default=%54}
+%59 = OpCompositeConstruct %58 %57 %57 %57 %57
+OpImageWrite %31 %36 %59
+OpReturn
+OpFunctionEnd
+)";
+
+} // anonymous namespace
+
+bool CaseVariant::operator< (const CaseVariant& other) const
+{
+ // Simple lexicographical comparison using the struct members.
+ const std::array<int, 4> thisMembers =
+ {{
+ static_cast<int>(imageType),
+ static_cast<int>(textureFormat.order),
+ static_cast<int>(textureFormat.type),
+ static_cast<int>(checkType),
+ }};
+
+ const std::array<int, 4> otherMembers =
+ {{
+ static_cast<int>(other.imageType),
+ static_cast<int>(other.textureFormat.order),
+ static_cast<int>(other.textureFormat.type),
+ static_cast<int>(other.checkType),
+ }};
+
+ return thisMembers < otherMembers;
+}
+
+CaseVariant::CaseVariant (ImageType imgtype, tcu::TextureFormat::ChannelOrder order, tcu::TextureFormat::ChannelType chtype, CheckType cktype)
+ : imageType{imgtype}, textureFormat{order, chtype}, checkType{cktype}
+{}
+
+std::string getSpirvAtomicOpShader (const CaseVariant& caseVariant)
+{
+ using ShadersMapT = std::map<CaseVariant, const std::string*>;
+ using ValueType = ShadersMapT::value_type;
+
+ static const ShadersMapT kShadersMap =
+ {
+ ValueType{CaseVariant{IMAGE_TYPE_1D, tcu::TextureFormat::R, tcu::TextureFormat::UNSIGNED_INT32, CaseVariant::CHECK_TYPE_END_RESULTS}, &kShader_1d_r32ui_end_result},
+ ValueType{CaseVariant{IMAGE_TYPE_1D, tcu::TextureFormat::R, tcu::TextureFormat::UNSIGNED_INT32, CaseVariant::CHECK_TYPE_INTERMEDIATE_RESULTS}, &kShader_1d_r32ui_intermediate_values},
+ ValueType{CaseVariant{IMAGE_TYPE_1D, tcu::TextureFormat::R, tcu::TextureFormat::SIGNED_INT32, CaseVariant::CHECK_TYPE_END_RESULTS}, &kShader_1d_r32i_end_result},
+ ValueType{CaseVariant{IMAGE_TYPE_1D, tcu::TextureFormat::R, tcu::TextureFormat::SIGNED_INT32, CaseVariant::CHECK_TYPE_INTERMEDIATE_RESULTS}, &kShader_1d_r32i_intermediate_values},
+ ValueType{CaseVariant{IMAGE_TYPE_1D_ARRAY, tcu::TextureFormat::R, tcu::TextureFormat::UNSIGNED_INT32, CaseVariant::CHECK_TYPE_END_RESULTS}, &kShader_1d_array_r32ui_end_result},
+ ValueType{CaseVariant{IMAGE_TYPE_1D_ARRAY, tcu::TextureFormat::R, tcu::TextureFormat::UNSIGNED_INT32, CaseVariant::CHECK_TYPE_INTERMEDIATE_RESULTS}, &kShader_1d_array_r32ui_intermediate_values},
+ ValueType{CaseVariant{IMAGE_TYPE_1D_ARRAY, tcu::TextureFormat::R, tcu::TextureFormat::SIGNED_INT32, CaseVariant::CHECK_TYPE_END_RESULTS}, &kShader_1d_array_r32i_end_result},
+ ValueType{CaseVariant{IMAGE_TYPE_1D_ARRAY, tcu::TextureFormat::R, tcu::TextureFormat::SIGNED_INT32, CaseVariant::CHECK_TYPE_INTERMEDIATE_RESULTS}, &kShader_1d_array_r32i_intermediate_values},
+ ValueType{CaseVariant{IMAGE_TYPE_2D, tcu::TextureFormat::R, tcu::TextureFormat::UNSIGNED_INT32, CaseVariant::CHECK_TYPE_END_RESULTS}, &kShader_2d_r32ui_end_result},
+ ValueType{CaseVariant{IMAGE_TYPE_2D, tcu::TextureFormat::R, tcu::TextureFormat::UNSIGNED_INT32, CaseVariant::CHECK_TYPE_INTERMEDIATE_RESULTS}, &kShader_2d_r32ui_intermediate_values},
+ ValueType{CaseVariant{IMAGE_TYPE_2D, tcu::TextureFormat::R, tcu::TextureFormat::SIGNED_INT32, CaseVariant::CHECK_TYPE_END_RESULTS}, &kShader_2d_r32i_end_result},
+ ValueType{CaseVariant{IMAGE_TYPE_2D, tcu::TextureFormat::R, tcu::TextureFormat::SIGNED_INT32, CaseVariant::CHECK_TYPE_INTERMEDIATE_RESULTS}, &kShader_2d_r32i_intermediate_values},
+ ValueType{CaseVariant{IMAGE_TYPE_2D_ARRAY, tcu::TextureFormat::R, tcu::TextureFormat::UNSIGNED_INT32, CaseVariant::CHECK_TYPE_END_RESULTS}, &kShader_2d_array_r32ui_end_result},
+ ValueType{CaseVariant{IMAGE_TYPE_2D_ARRAY, tcu::TextureFormat::R, tcu::TextureFormat::UNSIGNED_INT32, CaseVariant::CHECK_TYPE_INTERMEDIATE_RESULTS}, &kShader_2d_array_r32ui_intermediate_values},
+ ValueType{CaseVariant{IMAGE_TYPE_2D_ARRAY, tcu::TextureFormat::R, tcu::TextureFormat::SIGNED_INT32, CaseVariant::CHECK_TYPE_END_RESULTS}, &kShader_2d_array_r32i_end_result},
+ ValueType{CaseVariant{IMAGE_TYPE_2D_ARRAY, tcu::TextureFormat::R, tcu::TextureFormat::SIGNED_INT32, CaseVariant::CHECK_TYPE_INTERMEDIATE_RESULTS}, &kShader_2d_array_r32i_intermediate_values},
+ ValueType{CaseVariant{IMAGE_TYPE_3D, tcu::TextureFormat::R, tcu::TextureFormat::UNSIGNED_INT32, CaseVariant::CHECK_TYPE_END_RESULTS}, &kShader_3d_r32ui_end_result},
+ ValueType{CaseVariant{IMAGE_TYPE_3D, tcu::TextureFormat::R, tcu::TextureFormat::UNSIGNED_INT32, CaseVariant::CHECK_TYPE_INTERMEDIATE_RESULTS}, &kShader_3d_r32ui_intermediate_values},
+ ValueType{CaseVariant{IMAGE_TYPE_3D, tcu::TextureFormat::R, tcu::TextureFormat::SIGNED_INT32, CaseVariant::CHECK_TYPE_END_RESULTS}, &kShader_3d_r32i_end_result},
+ ValueType{CaseVariant{IMAGE_TYPE_3D, tcu::TextureFormat::R, tcu::TextureFormat::SIGNED_INT32, CaseVariant::CHECK_TYPE_INTERMEDIATE_RESULTS}, &kShader_3d_r32i_intermediate_values},
+ ValueType{CaseVariant{IMAGE_TYPE_CUBE, tcu::TextureFormat::R, tcu::TextureFormat::UNSIGNED_INT32, CaseVariant::CHECK_TYPE_END_RESULTS}, &kShader_cube_r32ui_end_result},
+ ValueType{CaseVariant{IMAGE_TYPE_CUBE, tcu::TextureFormat::R, tcu::TextureFormat::UNSIGNED_INT32, CaseVariant::CHECK_TYPE_INTERMEDIATE_RESULTS}, &kShader_cube_r32ui_intermediate_values},
+ ValueType{CaseVariant{IMAGE_TYPE_CUBE, tcu::TextureFormat::R, tcu::TextureFormat::SIGNED_INT32, CaseVariant::CHECK_TYPE_END_RESULTS}, &kShader_cube_r32i_end_result},
+ ValueType{CaseVariant{IMAGE_TYPE_CUBE, tcu::TextureFormat::R, tcu::TextureFormat::SIGNED_INT32, CaseVariant::CHECK_TYPE_INTERMEDIATE_RESULTS}, &kShader_cube_r32i_intermediate_values},
+ ValueType{CaseVariant{IMAGE_TYPE_CUBE_ARRAY, tcu::TextureFormat::R, tcu::TextureFormat::UNSIGNED_INT32, CaseVariant::CHECK_TYPE_END_RESULTS}, &kShader_cube_array_r32ui_end_result},
+ ValueType{CaseVariant{IMAGE_TYPE_CUBE_ARRAY, tcu::TextureFormat::R, tcu::TextureFormat::UNSIGNED_INT32, CaseVariant::CHECK_TYPE_INTERMEDIATE_RESULTS}, &kShader_cube_array_r32ui_intermediate_values},
+ ValueType{CaseVariant{IMAGE_TYPE_CUBE_ARRAY, tcu::TextureFormat::R, tcu::TextureFormat::SIGNED_INT32, CaseVariant::CHECK_TYPE_END_RESULTS}, &kShader_cube_array_r32i_end_result},
+ ValueType{CaseVariant{IMAGE_TYPE_CUBE_ARRAY, tcu::TextureFormat::R, tcu::TextureFormat::SIGNED_INT32, CaseVariant::CHECK_TYPE_INTERMEDIATE_RESULTS}, &kShader_cube_array_r32i_intermediate_values},
+ };
+
+ const auto iter = kShadersMap.find(caseVariant);
+ DE_ASSERT(iter != kShadersMap.end());
+ return *(iter->second);
+}
+
+} // namespace image
+} // namespace vkt
+
+// Note: the SPIR-V shaders above were created using the atomic addition shaders as a base, replacing OpAtomicIAdd with a string
+// template and making the last operation argument optional. Because the atomic addition shaders are generated, the final version of
+// each shader was obtained from TestResults.qpa after running the whole atomic addition group, using the Python script documented
+// below.
+#if 0
+import html
+import re
+import sys
+
+STATE_OUT = 0
+STATE_GLSL = 1
+STATE_SPIRV = 2
+
+state = STATE_OUT
+test_name = None
+glsl_lines = []
+spirv_lines = []
+header_printed = False
+
+for line in sys.stdin:
+ if line.startswith("#beginTestCaseResult"):
+ test_name = line.strip().split()[1]
+ test_name = "_".join(test_name.split(".")[-2:])
+
+ if "<ShaderSource>" in line:
+ line = re.sub(r".*<ShaderSource>", "", line)
+ state = STATE_GLSL
+
+ if "</ShaderSource>" in line:
+ state = STATE_OUT
+
+ if "<SpirVAssemblySource>" in line:
+ line = re.sub(r".*<SpirVAssemblySource>", "", line)
+ state = STATE_SPIRV
+
+ if "</SpirVAssemblySource>" in line:
+ state = STATE_OUT
+ if not header_printed:
+ print("#include <string>")
+ print()
+ header_printed = True
+ print("const std::string kShader_%s = R\"(" % (test_name,))
+ print("; The SPIR-V shader below is based on the following GLSL shader, but OpAtomicIAdd has been")
+ print("; replaced with a template parameter and the last argument for it has been made optional.")
+ print(";")
+ for glsl_line in glsl_lines:
+ glsl_line = html.unescape(glsl_line)
+ print("; %s" % (glsl_line,), end="")
+ print(";")
+ for spirv_line in spirv_lines:
+ spirv_line = html.unescape(spirv_line)
+ if "OpAtomicIAdd" in spirv_line:
+ words = spirv_line.strip().split()
+ for i in range(len(words)):
+ if words[i] == "OpAtomicIAdd":
+ words[i] = r"${OPNAME}"
+ words[-1] = r"${LASTARG:default=%s}" % (words[-1], )
+ spirv_line = " ".join(words) + "\n"
+ print("%s" % (spirv_line, ), end="")
+ print(")\";")
+ print()
+
+ test_name = None
+ glsl_lines = []
+ spirv_lines = []
+
+ if state == STATE_GLSL:
+ glsl_lines.append(line)
+ elif state == STATE_SPIRV:
+ spirv_lines.append(line)
+#endif
diff --git a/external/vulkancts/modules/vulkan/image/vktImageAtomicSpirvShaders.hpp b/external/vulkancts/modules/vulkan/image/vktImageAtomicSpirvShaders.hpp
new file mode 100644
index 0000000..e4e284c
--- /dev/null
+++ b/external/vulkancts/modules/vulkan/image/vktImageAtomicSpirvShaders.hpp
@@ -0,0 +1,61 @@
+#ifndef _VKTIMAGEATOMICSPIRVSHADERS_HPP
+#define _VKTIMAGEATOMICSPIRVSHADERS_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2020 Valve Corporation.
+ * Copyright (c) 2020 The Khronos Group Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Helper SPIR-V shaders for some image atomic operations.
+ *//*--------------------------------------------------------------------*/
+#include "vktImageTestsUtil.hpp"
+
+#include <string>
+
+namespace vkt
+{
+namespace image
+{
+
+// Test case variant, used when deciding which SPIR-V shader to get.
+struct CaseVariant
+{
+ enum CheckType
+ {
+ CHECK_TYPE_INTERMEDIATE_RESULTS = 0,
+ CHECK_TYPE_END_RESULTS,
+ };
+
+ ImageType imageType;
+ tcu::TextureFormat textureFormat;
+ CheckType checkType;
+
+ // Allows this struct to be used as key in maps.
+ bool operator< (const CaseVariant& other) const;
+
+ // Constructor.
+ CaseVariant (ImageType imgtype, tcu::TextureFormat::ChannelOrder order, tcu::TextureFormat::ChannelType chtype, CheckType cktype);
+};
+
+// Gets the shader template for the appropriate case variant.
+std::string getSpirvAtomicOpShader (const CaseVariant& caseVariant);
+
+} // namespace image
+} // namespace vkt
+
+#endif // _VKTIMAGEATOMICSPIRVSHADERS_HPP
diff --git a/external/vulkancts/mustpass/master/vk-default-no-waivers.txt b/external/vulkancts/mustpass/master/vk-default-no-waivers.txt
index b9ac5d0..bbada76 100644
--- a/external/vulkancts/mustpass/master/vk-default-no-waivers.txt
+++ b/external/vulkancts/mustpass/master/vk-default-no-waivers.txt
Binary files differ
diff --git a/external/vulkancts/mustpass/master/vk-default.txt b/external/vulkancts/mustpass/master/vk-default.txt
index 2edc568..d4c9e20 100644
--- a/external/vulkancts/mustpass/master/vk-default.txt
+++ b/external/vulkancts/mustpass/master/vk-default.txt
Binary files differ
diff --git a/framework/common/tcuStringTemplate.cpp b/framework/common/tcuStringTemplate.cpp
index d9ddedc..702f949 100644
--- a/framework/common/tcuStringTemplate.cpp
+++ b/framework/common/tcuStringTemplate.cpp
@@ -24,6 +24,8 @@
#include "tcuStringTemplate.hpp"
#include "tcuDefs.hpp"
+#include "deStringUtil.hpp"
+
#include <sstream>
using std::string;
@@ -51,6 +53,10 @@
m_template = str;
}
+const string kSingleLineFlag = "single-line";
+const string kOptFlag = "opt";
+const string kDefaultFlag = "default=";
+
string StringTemplate::specialize (const map<string, string>& params) const
{
ostringstream res;
@@ -73,20 +79,27 @@
string paramStr = m_template.substr(paramNdx+2, paramEndNdx-2-paramNdx);
bool paramSingleLine = false;
bool paramOptional = false;
+ bool paramDefault = false;
string paramName;
+ string defaultValue;
size_t colonNdx = paramStr.find(":");
if (colonNdx != string::npos)
{
paramName = paramStr.substr(0, colonNdx);
string flagsStr = paramStr.substr(colonNdx+1);
- if (flagsStr == "single-line")
+ if (flagsStr == kSingleLineFlag)
{
paramSingleLine = true;
}
- else if (flagsStr == "opt")
+ else if (flagsStr == kOptFlag)
{
paramOptional = true;
}
+ else if (de::beginsWith(flagsStr, kDefaultFlag))
+ {
+ paramDefault = true;
+ defaultValue = flagsStr.substr(kDefaultFlag.size());
+ }
else
{
TCU_THROW(InternalError, (string("Unrecognized flag") + paramStr).c_str());
@@ -109,6 +122,8 @@
else
res << val;
}
+ else if (paramDefault)
+ res << defaultValue;
else if (!paramOptional)
TCU_THROW(InternalError, (string("Value for parameter '") + paramName + "' not found in map").c_str());