1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2017 The Khronos Group Inc.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
21 * \brief SPIR-V Loop Control for DependencyInfinite qualifier tests
22 *//*--------------------------------------------------------------------*/
24 #include "vkApiVersion.hpp"
26 #include "vktSpvAsmLoopDepInfTests.hpp"
27 #include "vktTestCase.hpp"
28 #include "vktSpvAsmComputeShaderCase.hpp"
30 #include "deRandom.hpp"
34 namespace SpirVAssembly
42 // Assembly code used for testing loop control with dependencies is based on GLSL source code:
45 // layout(std140, set = 0, binding = 0) readonly buffer Input {
48 // layout(std140, set = 0, binding = 1) writeonly buffer Output {
55 // uint x = gl_GlobalInvocationID.x;
57 // for (uint i = 0; i < n; ++i)
58 // c[i] = float(i) * input_data.elements[x];
60 // output_data.elements[x] = 0.0f;
61 // for (uint i = 0; i < n; ++i)
62 // output_data.elements[x] += c[i];
64 static void getComputeSourceCode (std::string& computeSourceCode)
67 string(getComputeAsmShaderPreamble()) +
70 "OpName %main \"main\"\n"
71 "OpName %id \"gl_GlobalInvocationID\"\n"
73 "OpDecorate %id BuiltIn GlobalInvocationId\n"
75 + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) +
77 "%u32ptr = OpTypePointer Function %u32\n"
79 "%id = OpVariable %uvec3ptr Input\n"
80 "%zero = OpConstant %i32 0\n"
81 "%uzero = OpConstant %u32 0\n"
82 "%fzero = OpConstant %f32 0\n"
83 "%one = OpConstant %i32 1\n"
84 "%twelve = OpConstant %u32 12\n"
85 "%f32arr12_t = OpTypeArray %f32 %twelve\n"
86 "%f32arr12ptr_t = OpTypePointer Function %f32arr12_t\n"
87 "%f32funcptr = OpTypePointer Function %f32\n"
88 "%main = OpFunction %void None %voidf\n"
91 "%f32arr12 = OpVariable %f32arr12ptr_t Function\n"
93 "%i1 = OpVariable %u32ptr Function\n"
94 " OpStore %i1 %uzero\n"
95 "%i2 = OpVariable %u32ptr Function\n"
96 " OpStore %i2 %uzero\n"
98 "%idval = OpLoad %uvec3 %id\n"
99 "%x = OpCompositeExtract %u32 %idval 0\n"
100 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
101 "%inval = OpLoad %f32 %inloc\n"
103 // for (uint i = 0; i < 12; ++i) c[i] = float(i) * input_data.elements[x];
104 " OpBranch %loop1_entry\n"
105 "%loop1_entry = OpLabel\n"
106 "%i1_val = OpLoad %u32 %i1\n"
107 "%cmp1_lt = OpULessThan %bool %i1_val %twelve\n"
108 " OpLoopMerge %loop1_merge %loop1_body DependencyInfinite\n"
109 " OpBranchConditional %cmp1_lt %loop1_body %loop1_merge\n"
110 "%loop1_body = OpLabel\n"
111 "%i1_valf32 = OpConvertUToF %f32 %i1_val\n"
112 "%mulf1 = OpFMul %f32 %i1_valf32 %inval\n"
113 "%outloc1 = OpAccessChain %f32funcptr %f32arr12 %i1_val\n"
114 " OpStore %outloc1 %mulf1\n"
115 "%new1_i = OpIAdd %u32 %i1_val %one\n"
116 " OpStore %i1 %new1_i\n"
117 " OpBranch %loop1_entry\n"
118 "%loop1_merge = OpLabel\n"
120 // output_data.elements[x] = 0.0f;
121 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
122 " OpStore %outloc %fzero\n"
123 " OpBranch %loop2_entry\n"
125 // for (uint i = 0; i < n; ++i) output_data.elements[x] += c[i];
126 "%loop2_entry = OpLabel\n"
127 "%i2_val = OpLoad %u32 %i2\n"
128 "%cmp2_lt = OpULessThan %bool %i2_val %twelve\n"
129 " OpLoopMerge %loop2_merge %loop2_body None\n"
130 " OpBranchConditional %cmp2_lt %loop2_body %loop2_merge\n"
131 "%loop2_body = OpLabel\n"
132 "%arr1_i2loc = OpAccessChain %f32funcptr %f32arr12 %i2_val\n"
133 "%arr1_i2val = OpLoad %f32 %arr1_i2loc\n"
134 "%outval = OpLoad %f32 %outloc\n"
135 "%addf1 = OpFAdd %f32 %outval %arr1_i2val\n"
136 " OpStore %outloc %addf1\n"
137 "%new_i2 = OpIAdd %u32 %i2_val %one\n"
138 " OpStore %i2 %new_i2\n"
139 " OpBranch %loop2_entry\n"
140 "%loop2_merge = OpLabel\n"
146 static ComputeShaderSpec getComputeShaderSpec ()
148 de::Random rnd (0xABC);
149 const int numElements = 100;
150 vector<float> inputFloats (numElements, 0);
151 vector<float> outputFloats (numElements, 0);
152 ComputeShaderSpec spec;
154 for (size_t ndx = 0; ndx < numElements; ++ndx)
155 inputFloats[ndx] = rnd.getFloat(1.0f, 100.0f);
157 for (size_t ndx = 0; ndx < numElements; ++ndx)
159 const deUint32 n = 12;
163 for (deUint32 i = 0; i < n; ++i)
164 c[i] = float(i) * inputFloats[ndx];
166 for (deUint32 i = 0; i < n; ++i)
169 outputFloats[ndx] = result;
172 // Shader source code can be retrieved to complete definition of ComputeShaderSpec, though it is not required at this stage
173 // getComputeSourceCode (spec.assembly);
175 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
176 spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
177 spec.numWorkGroups = tcu::IVec3(numElements, 1, 1);
183 class SpvAsmLoopControlDependencyInfiniteInstance : public ComputeShaderSpec, public SpvAsmComputeShaderInstance
186 SpvAsmLoopControlDependencyInfiniteInstance (Context& ctx);
189 SpvAsmLoopControlDependencyInfiniteInstance::SpvAsmLoopControlDependencyInfiniteInstance (Context& ctx)
190 : ComputeShaderSpec(getComputeShaderSpec())
191 , SpvAsmComputeShaderInstance(ctx, *this, COMPUTE_TEST_USES_NONE)
195 SpvAsmLoopControlDependencyInfiniteCase::SpvAsmLoopControlDependencyInfiniteCase (tcu::TestContext& testCtx, const char* name, const char* description)
196 : TestCase (testCtx, name, description)
200 void SpvAsmLoopControlDependencyInfiniteCase::initPrograms (SourceCollections& programCollection) const
204 getComputeSourceCode(comp);
206 programCollection.spirvAsmSources.add("compute") << SpirVAsmBuildOptions(SPIRV_VERSION_1_3) << comp;
209 TestInstance* SpvAsmLoopControlDependencyInfiniteCase::createInstance (Context& context) const
211 if (context.getUsedApiVersion() < VK_API_VERSION_1_1)
212 TCU_THROW(NotSupportedError, "SPIR-V higher than 1.3 is required for this test to run");
214 return new SpvAsmLoopControlDependencyInfiniteInstance(context);