1 /*------------------------------------------------------------------------- 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2017 Google Inc. 6 * 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 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 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. 18 * 19 *//*! 20 * \file 21 * \brief SPIR-V Assembly Tests for indexing with different bit sizes. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "vktSpvAsmIndexingTests.hpp" 25 #include "vktSpvAsmComputeShaderCase.hpp" 26 #include "vktSpvAsmComputeShaderTestUtil.hpp" 27 #include "vktSpvAsmGraphicsShaderTestUtil.hpp" 28 29 #include "tcuStringTemplate.hpp" 30 31 namespace vkt 32 { 33 namespace SpirVAssembly 34 { 35 36 using namespace vk; 37 using std::map; 38 using std::string; 39 using std::vector; 40 using std::pair; 41 using tcu::IVec3; 42 using tcu::RGBA; 43 using tcu::UVec4; 44 using tcu::Mat4; 45 using tcu::StringTemplate; 46 47 namespace 48 { 49 50 enum ChainOp 51 { 52 CHAIN_OP_ACCESS_CHAIN = 0, 53 CHAIN_OP_IN_BOUNDS_ACCESS_CHAIN, 54 CHAIN_OP_PTR_ACCESS_CHAIN, 55 56 CHAIN_OP_LAST 57 }; 58 static const int idxSizes[] = { 16, 32, 64 }; 59 static const ComputeTestFeatures computeTestFeatures[] = { COMPUTE_TEST_USES_INT16, COMPUTE_TEST_USES_NONE, COMPUTE_TEST_USES_INT64 }; 60 static const string chainOpTestNames[] = { "opaccesschain", "opinboundsaccesschain", "opptraccesschain" }; 61 62 struct InputData 63 { 64 Mat4 matrix[32][32]; 65 }; 66 67 void addComputeIndexingTests (tcu::TestCaseGroup* group) 68 { 69 tcu::TestContext& testCtx = group->getTestContext(); 70 de::Random rnd (deStringHash(group->getName())); 71 const int numItems = 128; 72 const int numStructs = 2; 73 const int numInputFloats = (int)sizeof(InputData) / 4 * numStructs; 74 vector<float> inputData; 75 vector<UVec4> indexSelectorData; 76 77 inputData.reserve(numInputFloats); 78 for (deUint32 numIdx = 0; numIdx < numInputFloats; ++numIdx) 79 inputData.push_back(rnd.getFloat()); 80 81 indexSelectorData.reserve(numItems); 82 for (deUint32 numIdx = 0; numIdx < numItems; ++numIdx) 83 indexSelectorData.push_back(UVec4(rnd.getUint32() % 32, rnd.getUint32() % 32, rnd.getUint32() % 4, rnd.getUint32() % 4)); 84 85 for (int chainOpIdx = 0; chainOpIdx < CHAIN_OP_LAST; ++chainOpIdx) 86 { 87 for (int idxSizeIdx = 0; idxSizeIdx < DE_LENGTH_OF_ARRAY(idxSizes); ++idxSizeIdx) 88 { 89 for (int sign = 0; sign < 2; ++sign) 90 { 91 const int idxSize = idxSizes[idxSizeIdx]; 92 const string testName = chainOpTestNames[chainOpIdx] + string(sign == 0 ? "_u" : "_s") + de::toString(idxSize); 93 VulkanFeatures vulkanFeatures; 94 map<string, string> specs; 95 vector<float> outputData; 96 ComputeShaderSpec spec; 97 const ComputeTestFeatures features = computeTestFeatures[idxSizeIdx]; 98 int element = 0; 99 100 // Index an input buffer containing 2D array of 4x4 matrices. The indices are read from another 101 // input and converted to the desired bit size and sign. 102 const StringTemplate shaderSource( 103 " OpCapability Shader\n" 104 " ${intcaps:opt}\n" 105 " ${variablepointercaps:opt}\n" 106 " ${extensions:opt}\n" 107 " %1 = OpExtInstImport \"GLSL.std.450\"\n" 108 " OpMemoryModel Logical GLSL450\n" 109 " OpEntryPoint GLCompute %main \"main\" %gl_GlobalInvocationID\n" 110 " OpExecutionMode %main LocalSize 1 1 1\n" 111 " OpSource GLSL 430\n" 112 " OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId\n" 113 " OpDecorate %_arr_float_uint_128 ArrayStride 4\n" 114 " OpMemberDecorate %Output 0 Offset 0\n" 115 " OpDecorate %Output BufferBlock\n" 116 " OpDecorate %dataOutput DescriptorSet 0\n" 117 " OpDecorate %dataOutput Binding 2\n" 118 " OpDecorate %_arr_mat4v4float_uint_32 ArrayStride 64\n" 119 " OpDecorate %_arr__arr_mat4v4float_uint_32_uint_32 ArrayStride 2048\n" 120 " OpMemberDecorate %InputStruct 0 ColMajor\n" 121 " OpMemberDecorate %InputStruct 0 Offset 0\n" 122 " OpMemberDecorate %InputStruct 0 MatrixStride 16\n" 123 " OpDecorate %InputStructArr ArrayStride 65536\n" 124 " OpDecorate %Input ${inputdecoration}\n" 125 " OpMemberDecorate %Input 0 Offset 0\n" 126 " OpDecorate %dataInput DescriptorSet 0\n" 127 " OpDecorate %dataInput Binding 0\n" 128 " OpDecorate %_ptr_buffer_InputStruct ArrayStride 65536\n" 129 " OpDecorate %_arr_v4uint_uint_128 ArrayStride 16\n" 130 " OpMemberDecorate %DataSelector 0 Offset 0\n" 131 " OpDecorate %DataSelector BufferBlock\n" 132 " OpDecorate %selector DescriptorSet 0\n" 133 " OpDecorate %selector Binding 1\n" 134 " %void = OpTypeVoid\n" 135 " %3 = OpTypeFunction %void\n" 136 " %u32 = OpTypeInt 32 0\n" 137 " %i32 = OpTypeInt 32 1\n" 138 "${intdecl:opt}" 139 " %idx_0 = OpConstant ${idx_int} 0\n" 140 " %idx_1 = OpConstant ${idx_int} 1\n" 141 " %idx_2 = OpConstant ${idx_int} 2\n" 142 " %idx_3 = OpConstant ${idx_int} 3\n" 143 " %_ptr_Function_uint32 = OpTypePointer Function %u32\n" 144 " %v3uint32 = OpTypeVector %u32 3\n" 145 " %_ptr_Input_v3uint32 = OpTypePointer Input %v3uint32\n" 146 " %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint32 Input\n" 147 " %_ptr_Input_uint32 = OpTypePointer Input %u32\n" 148 " %float = OpTypeFloat 32\n" 149 " %uint_128 = OpConstant %u32 128\n" 150 " %uint_32 = OpConstant %u32 32\n" 151 " %uint_2 = OpConstant %u32 2\n" 152 " %_arr_float_uint_128 = OpTypeArray %float %uint_128\n" 153 " %Output = OpTypeStruct %_arr_float_uint_128\n" 154 " %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n" 155 " %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n" 156 " %v4float = OpTypeVector %float 4\n" 157 " %mat4v4float = OpTypeMatrix %v4float 4\n" 158 " %_arr_mat4v4float_uint_32 = OpTypeArray %mat4v4float %uint_32\n" 159 " %_arr__arr_mat4v4float_uint_32_uint_32 = OpTypeArray %_arr_mat4v4float_uint_32 %uint_32\n" 160 " %InputStruct = OpTypeStruct %_arr__arr_mat4v4float_uint_32_uint_32\n" 161 " %InputStructArr = OpTypeArray %InputStruct %uint_2\n" 162 " %Input = OpTypeStruct %InputStructArr\n" 163 " %_ptr_buffer_Input = OpTypePointer ${inputstorageclass} %Input\n" 164 " %dataInput = OpVariable %_ptr_buffer_Input ${inputstorageclass}\n" 165 " %_ptr_buffer_InputStruct = OpTypePointer ${inputstorageclass} %InputStruct\n" 166 " %v4uint32 = OpTypeVector %u32 4\n" 167 " %_arr_v4uint_uint_128 = OpTypeArray %v4uint32 %uint_128\n" 168 " %DataSelector = OpTypeStruct %_arr_v4uint_uint_128\n" 169 "%_ptr_Uniform_DataSelector = OpTypePointer Uniform %DataSelector\n" 170 " %selector = OpVariable %_ptr_Uniform_DataSelector Uniform\n" 171 " %_ptr_Uniform_uint32 = OpTypePointer Uniform %u32\n" 172 " %_ptr_Uniform_float = OpTypePointer Uniform %float\n" 173 " ${ptr_buffer_float:opt}\n" 174 175 " %main = OpFunction %void None %3\n" 176 " %5 = OpLabel\n" 177 " %i = OpVariable %_ptr_Function_uint32 Function\n" 178 " %14 = OpAccessChain %_ptr_Input_uint32 %gl_GlobalInvocationID %idx_0\n" 179 " %15 = OpLoad %u32 %14\n" 180 " OpStore %i %15\n" 181 " %uint_i = OpLoad %u32 %i\n" 182 " %39 = OpAccessChain %_ptr_Uniform_uint32 %selector %idx_0 %uint_i %idx_0\n" 183 " %40 = OpLoad %u32 %39\n" 184 " %43 = OpAccessChain %_ptr_Uniform_uint32 %selector %idx_0 %uint_i %idx_1\n" 185 " %44 = OpLoad %u32 %43\n" 186 " %47 = OpAccessChain %_ptr_Uniform_uint32 %selector %idx_0 %uint_i %idx_2\n" 187 " %48 = OpLoad %u32 %47\n" 188 " %51 = OpAccessChain %_ptr_Uniform_uint32 %selector %idx_0 %uint_i %idx_3\n" 189 " %52 = OpLoad %u32 %51\n" 190 " %i0 = ${convert} ${idx_int} %40\n" 191 " %i1 = ${convert} ${idx_int} %44\n" 192 " %i2 = ${convert} ${idx_int} %48\n" 193 " %i3 = ${convert} ${idx_int} %52\n" 194 " %inputFirstElement = OpAccessChain %_ptr_buffer_InputStruct %dataInput %idx_0 %idx_0\n" 195 " %54 = ${accesschain}\n" 196 " %55 = OpLoad %float %54\n" 197 " %56 = OpAccessChain %_ptr_Uniform_float %dataOutput %idx_0 %uint_i\n" 198 " OpStore %56 %55\n" 199 " OpReturn\n" 200 " OpFunctionEnd\n"); 201 202 203 switch (chainOpIdx) 204 { 205 case CHAIN_OP_ACCESS_CHAIN: 206 specs["accesschain"] = "OpAccessChain %_ptr_Uniform_float %inputFirstElement %idx_0 %i0 %i1 %i2 %i3\n"; 207 specs["inputdecoration"] = "BufferBlock"; 208 specs["inputstorageclass"] = "Uniform"; 209 break; 210 case CHAIN_OP_IN_BOUNDS_ACCESS_CHAIN: 211 specs["accesschain"] = "OpInBoundsAccessChain %_ptr_Uniform_float %inputFirstElement %idx_0 %i0 %i1 %i2 %i3\n"; 212 specs["inputdecoration"] = "BufferBlock"; 213 specs["inputstorageclass"] = "Uniform"; 214 break; 215 default: 216 DE_ASSERT(chainOpIdx == CHAIN_OP_PTR_ACCESS_CHAIN); 217 specs["accesschain"] = "OpPtrAccessChain %_ptr_StorageBuffer_float %inputFirstElement %idx_1 %idx_0 %i0 %i1 %i2 %i3\n"; 218 specs["inputdecoration"] = "Block"; 219 specs["inputstorageclass"] = "StorageBuffer"; 220 specs["variablepointercaps"] = "OpCapability VariablePointersStorageBuffer"; 221 specs["ptr_buffer_float"] = "%_ptr_StorageBuffer_float = OpTypePointer StorageBuffer %float"; 222 specs["extensions"] = "OpExtension \"SPV_KHR_variable_pointers\"\n " 223 "OpExtension \"SPV_KHR_storage_buffer_storage_class\""; 224 element = 1; 225 vulkanFeatures.extVariablePointers = EXTVARIABLEPOINTERSFEATURES_VARIABLE_POINTERS_STORAGEBUFFER; 226 spec.extensions.push_back("VK_KHR_variable_pointers"); 227 break; 228 }; 229 230 spec.inputs.push_back(BufferSp(new Float32Buffer(inputData))); 231 spec.inputs.push_back(BufferSp(new Buffer<UVec4>(indexSelectorData))); 232 233 outputData.reserve(numItems); 234 for (deUint32 numIdx = 0; numIdx < numItems; ++numIdx) 235 { 236 // Determine the selected output float for the selected indices. 237 const UVec4 vec = indexSelectorData[numIdx]; 238 outputData.push_back(inputData[element * sizeof(InputData) / 4 + vec.x() * (32 * 4 * 4) + vec.y() * 4 * 4 + vec.z() * 4 + vec.w()]); 239 } 240 241 if (idxSize == 16) 242 { 243 specs["intcaps"] = "OpCapability Int16"; 244 specs["convert"] = "OpSConvert"; 245 specs["intdecl"] = " %u16 = OpTypeInt 16 0\n" 246 " %i16 = OpTypeInt 16 1\n"; 247 } 248 else if (idxSize == 64) 249 { 250 specs["intcaps"] = "OpCapability Int64"; 251 specs["convert"] = "OpSConvert"; 252 specs["intdecl"] = " %u64 = OpTypeInt 64 0\n" 253 " %i64 = OpTypeInt 64 1\n"; 254 } else { 255 specs["convert"] = "OpCopyObject"; 256 } 257 258 specs["idx_uint"] = "%u" + de::toString(idxSize); 259 specs["idx_int"] = (sign ? "%i" : "%u") + de::toString(idxSize); 260 261 spec.assembly = shaderSource.specialize(specs); 262 spec.numWorkGroups = IVec3(numItems, 1, 1); 263 spec.requestedVulkanFeatures = vulkanFeatures; 264 spec.inputTypes[0] = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; 265 spec.inputTypes[1] = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; 266 267 spec.outputs.push_back(BufferSp(new Float32Buffer(outputData))); 268 269 group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testName.c_str(), spec, features)); 270 } 271 } 272 } 273 } 274 275 void addGraphicsIndexingTests (tcu::TestCaseGroup* group) 276 { 277 de::Random rnd (deStringHash(group->getName())); 278 const int numItems = 128; 279 const int numStructs = 2; 280 const int numInputFloats = (int)sizeof(InputData) / 4 * numStructs; 281 RGBA defaultColors[4]; 282 vector<float> inputData; 283 vector<UVec4> indexSelectorData; 284 285 inputData.reserve(numInputFloats); 286 for (deUint32 numIdx = 0; numIdx < numInputFloats; ++numIdx) 287 inputData.push_back(rnd.getFloat()); 288 289 indexSelectorData.reserve(numItems); 290 for (deUint32 numIdx = 0; numIdx < numItems; ++numIdx) 291 indexSelectorData.push_back(UVec4(rnd.getUint32() % 32, rnd.getUint32() % 32, rnd.getUint32() % 4, rnd.getUint32() % 4)); 292 293 getDefaultColors(defaultColors); 294 295 for (int chainOpIdx = 0; chainOpIdx < CHAIN_OP_LAST; ++chainOpIdx) 296 { 297 for (int idxSizeIdx = 0; idxSizeIdx < DE_LENGTH_OF_ARRAY(idxSizes); ++idxSizeIdx) 298 { 299 for (int sign = 0; sign < 2; sign++) 300 { 301 const int idxSize = idxSizes[idxSizeIdx]; 302 const string testName = chainOpTestNames[chainOpIdx] + string(sign == 0 ? "_u" : "_s") + de::toString(idxSize); 303 VulkanFeatures vulkanFeatures; 304 vector<string> extensions; 305 vector<string> features; 306 vector<deInt32> noSpecConstants; 307 PushConstants noPushConstants; 308 GraphicsInterfaces noInterfaces; 309 map<string, string> specs; 310 map<string, string> fragments; 311 vector<float> outputData; 312 ComputeShaderSpec spec; 313 int element = 0; 314 GraphicsResources resources; 315 316 const StringTemplate preMain( 317 "${intdecl:opt}" 318 " %c_i32_128 = OpConstant %i32 128\n" 319 " %uint_0 = OpConstant ${idx_uint} 0\n" 320 " %uint_128 = OpConstant %u32 128\n" 321 " %uint_32 = OpConstant %u32 32\n" 322 " %uint_1 = OpConstant ${idx_uint} 1\n" 323 " %uint_2 = OpConstant ${idx_uint} 2\n" 324 " %uint_3 = OpConstant ${idx_uint} 3\n" 325 " %_arr_float_uint_128 = OpTypeArray %f32 %uint_128\n" 326 " %Output = OpTypeStruct %_arr_float_uint_128\n" 327 " %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n" 328 " %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n" 329 " %int_0 = OpConstant ${idx_int} 0\n" 330 " %mat4v4float = OpTypeMatrix %v4f32 4\n" 331 " %_arr_mat4v4float_uint_32 = OpTypeArray %mat4v4float %uint_32\n" 332 " %_arr__arr_mat4v4float_uint_32_uint_32 = OpTypeArray %_arr_mat4v4float_uint_32 %uint_32\n" 333 " %InputStruct = OpTypeStruct %_arr__arr_mat4v4float_uint_32_uint_32\n" 334 " %InputStructArr = OpTypeArray %InputStruct %uint_2\n" 335 " %Input = OpTypeStruct %InputStructArr\n" 336 " %_ptr_buffer_Input = OpTypePointer ${inputstorageclass} %Input\n" 337 " %dataInput = OpVariable %_ptr_buffer_Input ${inputstorageclass}\n" 338 " %_ptr_buffer_InputStruct = OpTypePointer ${inputstorageclass} %InputStruct\n" 339 " %_arr_v4uint_uint_128 = OpTypeArray %v4u32 %uint_128\n" 340 " %DataSelector = OpTypeStruct %_arr_v4uint_uint_128\n" 341 "%_ptr_Uniform_DataSelector = OpTypePointer Uniform %DataSelector\n" 342 " %selector = OpVariable %_ptr_Uniform_DataSelector Uniform\n" 343 " %_ptr_Uniform_uint32 = OpTypePointer Uniform %u32\n" 344 " %_ptr_Uniform_float = OpTypePointer Uniform %f32\n" 345 " ${ptr_buffer_float:opt}\n"); 346 347 348 const StringTemplate decoration( 349 "OpDecorate %_arr_float_uint_128 ArrayStride 4\n" 350 "OpMemberDecorate %Output 0 Offset 0\n" 351 "OpDecorate %Output BufferBlock\n" 352 "OpDecorate %dataOutput DescriptorSet 0\n" 353 "OpDecorate %dataOutput Binding 2\n" 354 "OpDecorate %_arr_mat4v4float_uint_32 ArrayStride 64\n" 355 "OpDecorate %_arr__arr_mat4v4float_uint_32_uint_32 ArrayStride 2048\n" 356 "OpMemberDecorate %InputStruct 0 ColMajor\n" 357 "OpMemberDecorate %InputStruct 0 Offset 0\n" 358 "OpMemberDecorate %InputStruct 0 MatrixStride 16\n" 359 "OpDecorate %InputStructArr ArrayStride 65536\n" 360 "OpDecorate %Input ${inputdecoration}\n" 361 "OpMemberDecorate %Input 0 Offset 0\n" 362 "OpDecorate %dataInput DescriptorSet 0\n" 363 "OpDecorate %dataInput Binding 0\n" 364 "OpDecorate %_ptr_buffer_InputStruct ArrayStride 65536\n" 365 "OpDecorate %_arr_v4uint_uint_128 ArrayStride 16\n" 366 "OpMemberDecorate %DataSelector 0 Offset 0\n" 367 "OpDecorate %DataSelector BufferBlock\n" 368 "OpDecorate %selector DescriptorSet 0\n" 369 "OpDecorate %selector Binding 1\n"); 370 371 // Index an input buffer containing 2D array of 4x4 matrices. The indices are read from another 372 // input and converted to the desired bit size and sign. 373 const StringTemplate testFun( 374 " %test_code = OpFunction %v4f32 None %v4f32_function\n" 375 " %param = OpFunctionParameter %v4f32\n" 376 377 " %entry = OpLabel\n" 378 " %i = OpVariable %fp_i32 Function\n" 379 " OpStore %i %c_i32_0\n" 380 " OpBranch %loop\n" 381 382 " %loop = OpLabel\n" 383 " %15 = OpLoad %i32 %i\n" 384 " %lt = OpSLessThan %bool %15 %c_i32_128\n" 385 " OpLoopMerge %merge %inc None\n" 386 " OpBranchConditional %lt %write %merge\n" 387 388 " %write = OpLabel\n" 389 " %int_i = OpLoad %i32 %i\n" 390 " %39 = OpAccessChain %_ptr_Uniform_uint32 %selector %int_0 %int_i %uint_0\n" 391 " %40 = OpLoad %u32 %39\n" 392 " %43 = OpAccessChain %_ptr_Uniform_uint32 %selector %int_0 %int_i %uint_1\n" 393 " %44 = OpLoad %u32 %43\n" 394 " %47 = OpAccessChain %_ptr_Uniform_uint32 %selector %int_0 %int_i %uint_2\n" 395 " %48 = OpLoad %u32 %47\n" 396 " %51 = OpAccessChain %_ptr_Uniform_uint32 %selector %int_0 %int_i %uint_3\n" 397 " %52 = OpLoad %u32 %51\n" 398 " %i0 = ${convert} ${idx_uint} %40\n" 399 " %i1 = ${convert} ${idx_uint} %44\n" 400 " %i2 = ${convert} ${idx_uint} %48\n" 401 " %i3 = ${convert} ${idx_uint} %52\n" 402 "%inputFirstElement = OpAccessChain %_ptr_buffer_InputStruct %dataInput %uint_0 %uint_0\n" 403 " %54 = ${accesschain}\n" 404 " %55 = OpLoad %f32 %54\n" 405 " %56 = OpAccessChain %_ptr_Uniform_float %dataOutput %int_0 %int_i\n" 406 " OpStore %56 %55\n" 407 " OpBranch %inc\n" 408 409 " %inc = OpLabel\n" 410 " %67 = OpLoad %i32 %i\n" 411 " %69 = OpIAdd %i32 %67 %c_i32_1\n" 412 " OpStore %i %69\n" 413 " OpBranch %loop\n" 414 415 " %merge = OpLabel\n" 416 " OpReturnValue %param\n" 417 418 " OpFunctionEnd\n"); 419 420 resources.inputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float32Buffer(inputData)))); 421 resources.inputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Buffer<UVec4>(indexSelectorData)))); 422 423 if (idxSize == 16) 424 { 425 fragments["capability"] = "OpCapability Int16\n"; 426 features.push_back("shaderInt16"); 427 specs["convert"] = "OpUConvert"; 428 specs["intdecl"] = " %u16 = OpTypeInt 16 0\n" 429 " %i16 = OpTypeInt 16 1\n"; 430 } 431 else if (idxSize == 64) 432 { 433 fragments["capability"] = "OpCapability Int64\n"; 434 features.push_back("shaderInt64"); 435 specs["convert"] = "OpUConvert"; 436 specs["intdecl"] = " %u64 = OpTypeInt 64 0\n" 437 " %i64 = OpTypeInt 64 1\n"; 438 } else { 439 specs["convert"] = "OpCopyObject"; 440 } 441 442 specs["idx_uint"] = "%u" + de::toString(idxSize); 443 specs["idx_int"] = (sign ? "%i" : "%u") + de::toString(idxSize); 444 445 switch (chainOpIdx) 446 { 447 case CHAIN_OP_ACCESS_CHAIN: 448 specs["accesschain"] = "OpAccessChain %_ptr_Uniform_float %inputFirstElement %int_0 %i0 %i1 %i2 %i3\n"; 449 specs["inputdecoration"] = "BufferBlock"; 450 specs["inputstorageclass"] = "Uniform"; 451 break; 452 case CHAIN_OP_IN_BOUNDS_ACCESS_CHAIN: 453 specs["accesschain"] = "OpInBoundsAccessChain %_ptr_Uniform_float %inputFirstElement %int_0 %i0 %i1 %i2 %i3\n"; 454 specs["inputdecoration"] = "BufferBlock"; 455 specs["inputstorageclass"] = "Uniform"; 456 break; 457 default: 458 DE_ASSERT(chainOpIdx == CHAIN_OP_PTR_ACCESS_CHAIN); 459 specs["accesschain"] = "OpPtrAccessChain %_ptr_StorageBuffer_float %inputFirstElement %uint_1 %int_0 %i0 %i1 %i2 %i3\n"; 460 specs["inputdecoration"] = "Block"; 461 specs["inputstorageclass"] = "StorageBuffer"; 462 specs["ptr_buffer_float"] = "%_ptr_StorageBuffer_float = OpTypePointer StorageBuffer %f32"; 463 fragments["capability"] += "OpCapability VariablePointersStorageBuffer"; 464 fragments["extension"] = "OpExtension \"SPV_KHR_variable_pointers\"\nOpExtension \"SPV_KHR_storage_buffer_storage_class\""; 465 extensions.push_back ("VK_KHR_variable_pointers"); 466 vulkanFeatures.extVariablePointers = EXTVARIABLEPOINTERSFEATURES_VARIABLE_POINTERS_STORAGEBUFFER; 467 element = 1; 468 break; 469 }; 470 471 outputData.reserve(numItems); 472 for (deUint32 numIdx = 0; numIdx < numItems; ++numIdx) 473 { 474 // Determine the selected output float for the selected indices. 475 const UVec4 vec = indexSelectorData[numIdx]; 476 outputData.push_back(inputData[element * sizeof(InputData) / 4 + vec.x() * (32 * 4 * 4) + vec.y() * 4 * 4 + vec.z() * 4 + vec.w()]); 477 } 478 479 resources.outputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float32Buffer(outputData)))); 480 481 fragments["pre_main"] = preMain.specialize(specs); 482 fragments["decoration"] = decoration.specialize(specs); 483 fragments["testfun"] = testFun.specialize(specs); 484 485 createTestsForAllStages( 486 testName.c_str(), defaultColors, defaultColors, fragments, noSpecConstants, 487 noPushConstants, resources, noInterfaces, extensions, features, vulkanFeatures, group); 488 } 489 } 490 } 491 } 492 493 } // anonymous 494 495 tcu::TestCaseGroup* createIndexingComputeGroup (tcu::TestContext& testCtx) 496 { 497 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "indexing", "Compute tests for data indexing.")); 498 addComputeIndexingTests(group.get()); 499 500 return group.release(); 501 } 502 503 tcu::TestCaseGroup* createIndexingGraphicsGroup (tcu::TestContext& testCtx) 504 { 505 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "indexing", "Graphics tests for data indexing.")); 506 addGraphicsIndexingTests(group.get()); 507 508 return group.release(); 509 } 510 511 } // SpirVAssembly 512 } // vkt 513