1e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------- 2e5c31af7Sopenharmony_ci * Vulkan Conformance Tests 3e5c31af7Sopenharmony_ci * ------------------------ 4e5c31af7Sopenharmony_ci * 5e5c31af7Sopenharmony_ci * Copyright (c) 2017 The Khronos Group Inc. 6e5c31af7Sopenharmony_ci * 7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License. 9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at 10e5c31af7Sopenharmony_ci * 11e5c31af7Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 12e5c31af7Sopenharmony_ci * 13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and 17e5c31af7Sopenharmony_ci * limitations under the License. 18e5c31af7Sopenharmony_ci * 19e5c31af7Sopenharmony_ci *//*! 20e5c31af7Sopenharmony_ci * \file 21e5c31af7Sopenharmony_ci * \brief SPIR-V Loop Control for DependencyLength qualifier tests 22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 23e5c31af7Sopenharmony_ci 24e5c31af7Sopenharmony_ci#include "vkApiVersion.hpp" 25e5c31af7Sopenharmony_ci 26e5c31af7Sopenharmony_ci#include "vktSpvAsmLoopDepLenTests.hpp" 27e5c31af7Sopenharmony_ci#include "vktTestCase.hpp" 28e5c31af7Sopenharmony_ci#include "vktSpvAsmComputeShaderCase.hpp" 29e5c31af7Sopenharmony_ci 30e5c31af7Sopenharmony_ci#include "deRandom.hpp" 31e5c31af7Sopenharmony_ci 32e5c31af7Sopenharmony_cinamespace vkt 33e5c31af7Sopenharmony_ci{ 34e5c31af7Sopenharmony_cinamespace SpirVAssembly 35e5c31af7Sopenharmony_ci{ 36e5c31af7Sopenharmony_ci 37e5c31af7Sopenharmony_ciusing namespace vk; 38e5c31af7Sopenharmony_ciusing std::map; 39e5c31af7Sopenharmony_ciusing std::string; 40e5c31af7Sopenharmony_ciusing std::vector; 41e5c31af7Sopenharmony_ci 42e5c31af7Sopenharmony_ci// Assembly code used for testing loop control with dependencies is based on GLSL source code: 43e5c31af7Sopenharmony_ci// #version 430 44e5c31af7Sopenharmony_ci// 45e5c31af7Sopenharmony_ci// layout(std140, set = 0, binding = 0) readonly buffer Input { 46e5c31af7Sopenharmony_ci// float elements[]; 47e5c31af7Sopenharmony_ci// } input_data; 48e5c31af7Sopenharmony_ci// layout(std140, set = 0, binding = 1) writeonly buffer Output { 49e5c31af7Sopenharmony_ci// float elements[]; 50e5c31af7Sopenharmony_ci// } output_data; 51e5c31af7Sopenharmony_ci// 52e5c31af7Sopenharmony_ci// void main() { 53e5c31af7Sopenharmony_ci// const uint n = 12; 54e5c31af7Sopenharmony_ci// float c[n]; 55e5c31af7Sopenharmony_ci// uint x = gl_GlobalInvocationID.x; 56e5c31af7Sopenharmony_ci// 57e5c31af7Sopenharmony_ci// for (uint i = 0; i < 6; ++i) 58e5c31af7Sopenharmony_ci// c[i] = float(i) * input_data.elements[x]; 59e5c31af7Sopenharmony_ci// 60e5c31af7Sopenharmony_ci// for (uint i = 6; i < n; ++i) 61e5c31af7Sopenharmony_ci// c[i] = c[i - 4] + c[i - 5] + c[i - 6]; 62e5c31af7Sopenharmony_ci// 63e5c31af7Sopenharmony_ci// output_data.elements[x] = c[n - 1]; 64e5c31af7Sopenharmony_ci// } 65e5c31af7Sopenharmony_cistatic void getComputeSourceCode (std::string& computeSourceCode) 66e5c31af7Sopenharmony_ci{ 67e5c31af7Sopenharmony_ci computeSourceCode = 68e5c31af7Sopenharmony_ci string(getComputeAsmShaderPreamble()) + 69e5c31af7Sopenharmony_ci 70e5c31af7Sopenharmony_ci "OpSource GLSL 430\n" 71e5c31af7Sopenharmony_ci "OpName %main \"main\"\n" 72e5c31af7Sopenharmony_ci "OpName %id \"gl_GlobalInvocationID\"\n" 73e5c31af7Sopenharmony_ci 74e5c31af7Sopenharmony_ci "OpDecorate %id BuiltIn GlobalInvocationId\n" 75e5c31af7Sopenharmony_ci 76e5c31af7Sopenharmony_ci + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) + 77e5c31af7Sopenharmony_ci 78e5c31af7Sopenharmony_ci "%u32ptr = OpTypePointer Function %u32\n" 79e5c31af7Sopenharmony_ci 80e5c31af7Sopenharmony_ci "%id = OpVariable %uvec3ptr Input\n" 81e5c31af7Sopenharmony_ci "%zero = OpConstant %i32 0\n" 82e5c31af7Sopenharmony_ci "%uzero = OpConstant %u32 0\n" 83e5c31af7Sopenharmony_ci "%one = OpConstant %i32 1\n" 84e5c31af7Sopenharmony_ci 85e5c31af7Sopenharmony_ci "%four = OpConstant %u32 4\n" 86e5c31af7Sopenharmony_ci "%five = OpConstant %u32 5\n" 87e5c31af7Sopenharmony_ci "%six = OpConstant %u32 6\n" 88e5c31af7Sopenharmony_ci "%elleven = OpConstant %u32 11\n" 89e5c31af7Sopenharmony_ci "%twelve = OpConstant %u32 12\n" 90e5c31af7Sopenharmony_ci 91e5c31af7Sopenharmony_ci "%f32arr12_t = OpTypeArray %f32 %twelve\n" 92e5c31af7Sopenharmony_ci "%f32arr12ptr_t = OpTypePointer Function %f32arr12_t\n" 93e5c31af7Sopenharmony_ci "%f32funcptr = OpTypePointer Function %f32\n" 94e5c31af7Sopenharmony_ci 95e5c31af7Sopenharmony_ci "%main = OpFunction %void None %voidf\n" 96e5c31af7Sopenharmony_ci "%entry = OpLabel\n" 97e5c31af7Sopenharmony_ci 98e5c31af7Sopenharmony_ci "%f32arr12 = OpVariable %f32arr12ptr_t Function\n" 99e5c31af7Sopenharmony_ci 100e5c31af7Sopenharmony_ci "%i1 = OpVariable %u32ptr Function\n" 101e5c31af7Sopenharmony_ci "%i2 = OpVariable %u32ptr Function\n" 102e5c31af7Sopenharmony_ci " OpStore %i1 %uzero\n" 103e5c31af7Sopenharmony_ci " OpStore %i2 %six\n" 104e5c31af7Sopenharmony_ci 105e5c31af7Sopenharmony_ci "%idval = OpLoad %uvec3 %id\n" 106e5c31af7Sopenharmony_ci "%x = OpCompositeExtract %u32 %idval 0\n" 107e5c31af7Sopenharmony_ci "%inloc = OpAccessChain %f32ptr %indata %zero %x\n" 108e5c31af7Sopenharmony_ci "%inval = OpLoad %f32 %inloc\n" 109e5c31af7Sopenharmony_ci 110e5c31af7Sopenharmony_ci // for (uint i = 0; i < 6; ++i) c[i] = float(i) * input_data.elements[x]; 111e5c31af7Sopenharmony_ci " OpBranch %loop1_entry\n" 112e5c31af7Sopenharmony_ci "%loop1_entry = OpLabel\n" 113e5c31af7Sopenharmony_ci "%i1_val = OpLoad %u32 %i1\n" 114e5c31af7Sopenharmony_ci "%cmp1_lt = OpULessThan %bool %i1_val %six\n" 115e5c31af7Sopenharmony_ci " OpLoopMerge %loop1_merge %loop1_body None\n" 116e5c31af7Sopenharmony_ci " OpBranchConditional %cmp1_lt %loop1_body %loop1_merge\n" 117e5c31af7Sopenharmony_ci "%loop1_body = OpLabel\n" 118e5c31af7Sopenharmony_ci "%i1_valf32 = OpConvertUToF %f32 %i1_val\n" 119e5c31af7Sopenharmony_ci "%mulf1 = OpFMul %f32 %i1_valf32 %inval\n" 120e5c31af7Sopenharmony_ci "%outloc1 = OpAccessChain %f32funcptr %f32arr12 %i1_val\n" 121e5c31af7Sopenharmony_ci " OpStore %outloc1 %mulf1\n" 122e5c31af7Sopenharmony_ci "%new1_i = OpIAdd %u32 %i1_val %one\n" 123e5c31af7Sopenharmony_ci " OpStore %i1 %new1_i\n" 124e5c31af7Sopenharmony_ci " OpBranch %loop1_entry\n" 125e5c31af7Sopenharmony_ci "%loop1_merge = OpLabel\n" 126e5c31af7Sopenharmony_ci 127e5c31af7Sopenharmony_ci // for (uint i = 6; i < n; ++i) c[i] = c[i - 4] + c[i - 5] + c[i - 6]; 128e5c31af7Sopenharmony_ci " OpBranch %loop2_entry\n" 129e5c31af7Sopenharmony_ci "%loop2_entry = OpLabel\n" 130e5c31af7Sopenharmony_ci "%i2_val = OpLoad %u32 %i2\n" 131e5c31af7Sopenharmony_ci "%cmp2_lt = OpULessThan %bool %i2_val %twelve\n" 132e5c31af7Sopenharmony_ci " OpLoopMerge %loop2_merge %loop2_body DependencyLength 3\n" 133e5c31af7Sopenharmony_ci " OpBranchConditional %cmp2_lt %loop2_body %loop2_merge\n" 134e5c31af7Sopenharmony_ci "%loop2_body = OpLabel\n" 135e5c31af7Sopenharmony_ci "%i2_m4 = OpISub %u32 %i2_val %four\n" 136e5c31af7Sopenharmony_ci "%arr1_i2m4loc = OpAccessChain %f32funcptr %f32arr12 %i2_m4\n" 137e5c31af7Sopenharmony_ci "%arr1_i2m4val = OpLoad %f32 %arr1_i2m4loc\n" 138e5c31af7Sopenharmony_ci "%i2_m5 = OpISub %u32 %i2_val %five\n" 139e5c31af7Sopenharmony_ci "%arr1_i2m5loc = OpAccessChain %f32funcptr %f32arr12 %i2_m5\n" 140e5c31af7Sopenharmony_ci "%arr1_i2m5val = OpLoad %f32 %arr1_i2m5loc\n" 141e5c31af7Sopenharmony_ci "%f32add1 = OpFAdd %f32 %arr1_i2m4val %arr1_i2m5val\n" 142e5c31af7Sopenharmony_ci "%i2_m6 = OpISub %u32 %i2_val %six\n" 143e5c31af7Sopenharmony_ci "%arr1_i2m6loc = OpAccessChain %f32funcptr %f32arr12 %i2_m6\n" 144e5c31af7Sopenharmony_ci "%arr1_i2m6val = OpLoad %f32 %arr1_i2m6loc\n" 145e5c31af7Sopenharmony_ci "%f32add2 = OpFAdd %f32 %f32add1 %arr1_i2m6val\n" 146e5c31af7Sopenharmony_ci "%outloc2 = OpAccessChain %f32funcptr %f32arr12 %i2_val\n" 147e5c31af7Sopenharmony_ci " OpStore %outloc2 %f32add2\n" 148e5c31af7Sopenharmony_ci "%new_i2 = OpIAdd %u32 %i2_val %one\n" 149e5c31af7Sopenharmony_ci " OpStore %i2 %new_i2\n" 150e5c31af7Sopenharmony_ci " OpBranch %loop2_entry\n" 151e5c31af7Sopenharmony_ci "%loop2_merge = OpLabel\n" 152e5c31af7Sopenharmony_ci 153e5c31af7Sopenharmony_ci // output_data.elements[x] = c[n - 1]; 154e5c31af7Sopenharmony_ci "%arr1locq = OpAccessChain %f32funcptr %f32arr12 %elleven\n" 155e5c31af7Sopenharmony_ci "%arr1valq = OpLoad %f32 %arr1locq\n" 156e5c31af7Sopenharmony_ci "%outlocq = OpAccessChain %f32ptr %outdata %zero %x\n" 157e5c31af7Sopenharmony_ci " OpStore %outlocq %arr1valq\n" 158e5c31af7Sopenharmony_ci " OpReturn\n" 159e5c31af7Sopenharmony_ci " OpFunctionEnd\n"; 160e5c31af7Sopenharmony_ci} 161e5c31af7Sopenharmony_ci 162e5c31af7Sopenharmony_cistatic ComputeShaderSpec getComputeShaderSpec () 163e5c31af7Sopenharmony_ci{ 164e5c31af7Sopenharmony_ci de::Random rnd (0xABC); 165e5c31af7Sopenharmony_ci const int numElements = 100; 166e5c31af7Sopenharmony_ci vector<float> inputFloats (numElements, 0); 167e5c31af7Sopenharmony_ci vector<float> outputFloats (numElements, 0); 168e5c31af7Sopenharmony_ci ComputeShaderSpec spec; 169e5c31af7Sopenharmony_ci 170e5c31af7Sopenharmony_ci for (size_t ndx = 0; ndx < numElements; ++ndx) 171e5c31af7Sopenharmony_ci inputFloats[ndx] = rnd.getFloat(1.0f, 100.0f); 172e5c31af7Sopenharmony_ci 173e5c31af7Sopenharmony_ci for (size_t ndx = 0; ndx < numElements; ++ndx) 174e5c31af7Sopenharmony_ci { 175e5c31af7Sopenharmony_ci const deUint32 n = 12; 176e5c31af7Sopenharmony_ci float c[n]; 177e5c31af7Sopenharmony_ci 178e5c31af7Sopenharmony_ci for (deUint32 i = 0; i < 6; ++i) 179e5c31af7Sopenharmony_ci c[i] = float(i) * inputFloats[ndx]; 180e5c31af7Sopenharmony_ci 181e5c31af7Sopenharmony_ci for (deUint32 i = 6; i < n; ++i) 182e5c31af7Sopenharmony_ci c[i] = c[i - 4] + c[i - 5] + c[i - 6]; 183e5c31af7Sopenharmony_ci 184e5c31af7Sopenharmony_ci outputFloats[ndx] = c[n - 1]; 185e5c31af7Sopenharmony_ci } 186e5c31af7Sopenharmony_ci 187e5c31af7Sopenharmony_ci // Shader source code can be retrieved to complete definition of ComputeShaderSpec, though it is not required at this stage 188e5c31af7Sopenharmony_ci // getComputeSourceCode (spec.assembly); 189e5c31af7Sopenharmony_ci 190e5c31af7Sopenharmony_ci spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats))); 191e5c31af7Sopenharmony_ci spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats))); 192e5c31af7Sopenharmony_ci spec.numWorkGroups = tcu::IVec3(numElements, 1, 1); 193e5c31af7Sopenharmony_ci spec.verifyIO = &verifyOutput; 194e5c31af7Sopenharmony_ci 195e5c31af7Sopenharmony_ci return spec; 196e5c31af7Sopenharmony_ci} 197e5c31af7Sopenharmony_ci 198e5c31af7Sopenharmony_ci 199e5c31af7Sopenharmony_ciclass SpvAsmLoopControlDependencyLengthInstance : public ComputeShaderSpec, public SpvAsmComputeShaderInstance 200e5c31af7Sopenharmony_ci{ 201e5c31af7Sopenharmony_cipublic: 202e5c31af7Sopenharmony_ci SpvAsmLoopControlDependencyLengthInstance (Context& ctx); 203e5c31af7Sopenharmony_ci}; 204e5c31af7Sopenharmony_ci 205e5c31af7Sopenharmony_ciSpvAsmLoopControlDependencyLengthInstance::SpvAsmLoopControlDependencyLengthInstance (Context& ctx) 206e5c31af7Sopenharmony_ci : ComputeShaderSpec(getComputeShaderSpec()) 207e5c31af7Sopenharmony_ci , SpvAsmComputeShaderInstance(ctx, *this) 208e5c31af7Sopenharmony_ci{ 209e5c31af7Sopenharmony_ci} 210e5c31af7Sopenharmony_ci 211e5c31af7Sopenharmony_ciSpvAsmLoopControlDependencyLengthCase::SpvAsmLoopControlDependencyLengthCase (tcu::TestContext& testCtx, const char* name) 212e5c31af7Sopenharmony_ci : TestCase (testCtx, name) 213e5c31af7Sopenharmony_ci{ 214e5c31af7Sopenharmony_ci} 215e5c31af7Sopenharmony_ci 216e5c31af7Sopenharmony_civoid SpvAsmLoopControlDependencyLengthCase::initPrograms (SourceCollections& programCollection) const 217e5c31af7Sopenharmony_ci{ 218e5c31af7Sopenharmony_ci std::string comp; 219e5c31af7Sopenharmony_ci 220e5c31af7Sopenharmony_ci getComputeSourceCode(comp); 221e5c31af7Sopenharmony_ci 222e5c31af7Sopenharmony_ci programCollection.spirvAsmSources.add("compute") << SpirVAsmBuildOptions(programCollection.usedVulkanVersion, SPIRV_VERSION_1_3) << comp; 223e5c31af7Sopenharmony_ci} 224e5c31af7Sopenharmony_ci 225e5c31af7Sopenharmony_ciTestInstance* SpvAsmLoopControlDependencyLengthCase::createInstance (Context& context) const 226e5c31af7Sopenharmony_ci{ 227e5c31af7Sopenharmony_ci if (!context.contextSupports(vk::ApiVersion(0, 1, 1, 0))) 228e5c31af7Sopenharmony_ci TCU_THROW(NotSupportedError, "SPIR-V higher than 1.3 is required for this test to run"); 229e5c31af7Sopenharmony_ci 230e5c31af7Sopenharmony_ci return new SpvAsmLoopControlDependencyLengthInstance(context); 231e5c31af7Sopenharmony_ci} 232e5c31af7Sopenharmony_ci 233e5c31af7Sopenharmony_ci} // SpirVAssembly 234e5c31af7Sopenharmony_ci} // vkt 235