1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2018 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 composite insert.
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktSpvAsmCompositeInsertTests.hpp"
25 #include "vktSpvAsmComputeShaderCase.hpp"
26 #include "vktSpvAsmComputeShaderTestUtil.hpp"
27 #include "vktSpvAsmGraphicsShaderTestUtil.hpp"
28
29 namespace vkt
30 {
31 namespace SpirVAssembly
32 {
33
34 using namespace vk;
35 using std::map;
36 using std::string;
37 using std::vector;
38 using tcu::IVec3;
39 using tcu::RGBA;
40
41 namespace
42 {
43
getColType(uint32_t rows)44 string getColType(uint32_t rows)
45 {
46 return string("%v") + de::toString(rows) + "f32";
47 }
48
getMatrixType(uint32_t cols,uint32_t rows)49 string getMatrixType(uint32_t cols, uint32_t rows)
50 {
51 return string("%mat") + de::toString(cols) + "v" + de::toString(rows) + "f";
52 }
53
getMatrixDeclarations(uint32_t cols,uint32_t rows,bool skipColDecl=false)54 string getMatrixDeclarations(uint32_t cols, uint32_t rows, bool skipColDecl = false)
55 {
56 string colType = getColType(rows);
57 string colDecl =
58 skipColDecl ? "" : string(" ") + colType + " = OpTypeVector %f32 " + de::toString(rows) + "\n";
59 string matType = getMatrixType(cols, rows);
60 string matDecl =
61 string(" ") + matType + " = OpTypeMatrix " + colType + " " + de::toString(cols) + "\n";
62 string outputDecl = string(" %Output = OpTypeStruct ") + matType + "\n";
63
64 return colDecl + matDecl + outputDecl;
65 }
66
getIdentityVectors(uint32_t cols,uint32_t rows)67 string getIdentityVectors(uint32_t cols, uint32_t rows)
68 {
69 string ret;
70
71 for (uint32_t c = 0; c < cols; c++)
72 {
73 string identity =
74 " %identity" + de::toString(c) + " = OpConstantComposite " + getColType(rows) + " ";
75
76 for (uint32_t r = 0; r < rows; r++)
77 {
78 identity += string("%c_f32_") + (c == r ? "1" : "0") + " ";
79 }
80
81 identity += "\n";
82 ret += identity;
83 }
84
85 return ret;
86 }
87
getVectorCompositeInserts(uint32_t elements,bool useUndef)88 string getVectorCompositeInserts(uint32_t elements, bool useUndef)
89 {
90 string ret;
91
92 if (useUndef)
93 ret = " %tmp0 = OpUndef %v" + de::toString(elements) + "f32\n";
94 else
95 ret = " %tmp0 = OpLoad %v" + de::toString(elements) + "f32 %vec\n";
96
97 for (uint32_t e = 0; e < elements; e++)
98 ret += " %tmp" + de::toString(e + 1) + " = OpCompositeInsert %v" + de::toString(elements) +
99 "f32 %c_f32_" + de::toString(e) + " %tmp" + de::toString(e) + " " + de::toString(e) + "\n";
100
101 return ret;
102 }
103
getMatrixCompositeInserts(uint32_t cols,uint32_t rows,bool useUndef)104 string getMatrixCompositeInserts(uint32_t cols, uint32_t rows, bool useUndef)
105 {
106 string matType = getMatrixType(cols, rows);
107 string ret;
108
109 if (useUndef)
110 ret = " %tmp0 = OpUndef " + matType + "\n";
111 else
112 ret = " %tmp0 = OpLoad " + matType + " %mat\n";
113
114 for (uint32_t c = 0; c < cols; c++)
115 ret += " %tmp" + de::toString(c + 1) + " = OpCompositeInsert " + matType + " %identity" +
116 de::toString(c) + " %tmp" + de::toString(c) + " " + de::toString(c) + "\n";
117
118 return ret;
119 }
120
verifyMatrixOutput(const std::vector<Resource> & inputs,const vector<AllocationSp> & outputAllocs,const std::vector<Resource> & expectedOutputs,tcu::TestLog & log)121 bool verifyMatrixOutput(const std::vector<Resource> &inputs, const vector<AllocationSp> &outputAllocs,
122 const std::vector<Resource> &expectedOutputs, tcu::TestLog &log)
123 {
124 DE_UNREF(inputs);
125
126 if (outputAllocs.size() != 1)
127 return false;
128
129 vector<uint8_t> expectedBytes;
130 expectedOutputs[0].getBytes(expectedBytes);
131
132 const float *const expectedOutputAsFloat = reinterpret_cast<const float *>(&expectedBytes.front());
133 const float *const outputAsFloat = static_cast<const float *>(outputAllocs[0]->getHostPtr());
134 bool ret = true;
135
136 for (size_t idx = 0; idx < expectedBytes.size() / sizeof(float); ++idx)
137 {
138 if (outputAsFloat[idx] != expectedOutputAsFloat[idx] && expectedOutputAsFloat[idx] != -1.0f)
139 {
140 log << tcu::TestLog::Message << "ERROR: Result data at index " << idx
141 << " failed. Expected: " << expectedOutputAsFloat[idx] << ", got: " << outputAsFloat[idx]
142 << tcu::TestLog::EndMessage;
143 ret = false;
144 }
145 }
146 return ret;
147 }
148
getNestedStructCompositeInserts(uint32_t arraySize,bool useUndef)149 string getNestedStructCompositeInserts(uint32_t arraySize, bool useUndef)
150 {
151 string ret;
152
153 if (useUndef)
154 ret = " %tmp0 = OpUndef %Output\n";
155 else
156 ret = " %tmp0 = OpLoad %Output %nestedstruct\n";
157
158 for (uint32_t arrayIdx = 0; arrayIdx < arraySize; arrayIdx++)
159 for (uint32_t vectorIdx = 0; vectorIdx < 4; vectorIdx++)
160 ret += string("%tmp") + de::toString(arrayIdx * 4 + vectorIdx + 1) +
161 " = OpCompositeInsert %Output %identity" + de::toString(vectorIdx) + " %tmp" +
162 de::toString(arrayIdx * 4 + vectorIdx) + " 0 0 " + de::toString(arrayIdx) + " " +
163 de::toString(vectorIdx) + "\n";
164
165 return ret;
166 }
167
addComputeVectorCompositeInsertTests(tcu::TestCaseGroup * group)168 void addComputeVectorCompositeInsertTests(tcu::TestCaseGroup *group)
169 {
170 tcu::TestContext &testCtx = group->getTestContext();
171
172 for (bool useUndef : {true, false})
173 for (uint32_t elements = 2; elements <= 4; elements++)
174 {
175 ComputeShaderSpec spec;
176 vector<float> refData;
177 const string vecType = string("%v") + de::toString(elements) + "f32";
178
179 // Generate a vector using OpCompositeInsert
180 const string shaderSource =
181 " OpCapability Shader\n"
182 " %1 = OpExtInstImport \"GLSL.std.450\"\n"
183 " OpMemoryModel Logical GLSL450\n"
184 " OpEntryPoint GLCompute %main \"main\"\n"
185 " OpExecutionMode %main LocalSize 1 1 1\n"
186 " OpSource GLSL 430\n"
187 " OpMemberDecorate %Output 0 Offset 0\n"
188 " OpDecorate %Output BufferBlock\n"
189 " OpDecorate %dataOutput DescriptorSet 0\n"
190 " OpDecorate %dataOutput Binding 0\n"
191 " %f32 = OpTypeFloat 32\n"
192 " %v2f32 = OpTypeVector %f32 2\n"
193 " %v3f32 = OpTypeVector %f32 3\n"
194 " %v4f32 = OpTypeVector %f32 4\n"
195 " %Output = OpTypeStruct " +
196 vecType +
197 "\n"
198 " %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
199 " %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n"
200 " %_ptr_Function_vec = OpTypePointer Function " +
201 vecType +
202 "\n"
203 " %_ptr_Uniform_vec = OpTypePointer Uniform " +
204 vecType +
205 "\n"
206 " %c_f32_0 = OpConstant %f32 0\n"
207 " %c_f32_1 = OpConstant %f32 1\n"
208 " %c_f32_2 = OpConstant %f32 2\n"
209 " %c_f32_3 = OpConstant %f32 3\n"
210 " %i32 = OpTypeInt 32 1\n"
211 " %c_i32_0 = OpConstant %i32 0\n"
212 " %void = OpTypeVoid\n"
213 " %3 = OpTypeFunction %void\n"
214 " %main = OpFunction %void None %3\n"
215 " %entry = OpLabel\n"
216 " %vec = OpVariable %_ptr_Function_vec Function\n" +
217 getVectorCompositeInserts(elements, useUndef) +
218 " %vecOutPtr = OpAccessChain %_ptr_Uniform_vec %dataOutput %c_i32_0\n"
219 " OpStore %vecOutPtr %tmp" +
220 de::toString(elements) +
221 "\n"
222 " OpReturn\n"
223 " OpFunctionEnd\n";
224
225 spec.assembly = shaderSource;
226 spec.numWorkGroups = IVec3(1, 1, 1);
227
228 // Expect running counter
229 for (uint32_t e = 0; e < elements; e++)
230 refData.push_back((float)e);
231
232 spec.outputs.push_back(Resource(BufferSp(new Float32Buffer(refData))));
233
234 string testName;
235
236 if (useUndef)
237 testName += "undef_";
238
239 testName += string("vec") + de::toString(elements);
240
241 // Tests vector composite insert.
242 group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), spec));
243 }
244 }
245
addGraphicsVectorCompositeInsertTests(tcu::TestCaseGroup * group)246 void addGraphicsVectorCompositeInsertTests(tcu::TestCaseGroup *group)
247 {
248 for (bool useUndef : {true, false})
249 for (uint32_t elements = 2; elements <= 4; elements++)
250 {
251 map<string, string> fragments;
252 RGBA defaultColors[4];
253 GraphicsResources resources;
254
255 SpecConstants noSpecConstants;
256 PushConstants noPushConstants;
257 GraphicsInterfaces noInterfaces;
258 vector<string> noExtensions;
259 VulkanFeatures vulkanFeatures = VulkanFeatures();
260 vector<float> refData;
261 const string testName = string(useUndef ? "undef_" : "") + "vec" + de::toString(elements);
262 const string vecType = string("%v") + de::toString(elements) + "f32";
263
264 // Expect running counter
265 for (uint32_t e = 0; e < elements; e++)
266 refData.push_back((float)e);
267 resources.outputs.push_back(
268 Resource(BufferSp(new Float32Buffer(refData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
269
270 getDefaultColors(defaultColors);
271
272 // Generate a vector using OpCompositeInsert
273 fragments["pre_main"] = " %Output = OpTypeStruct " + vecType +
274 "\n"
275 " %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
276 " %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n"
277 " %fp_v2f32 = OpTypePointer Function %v2f32\n"
278 " %fp_v3f32 = OpTypePointer Function %v3f32\n"
279 " %_ptr_Uniform_vec = OpTypePointer Uniform " +
280 vecType +
281 "\n"
282 " %c_f32_2 = OpConstant %f32 2\n"
283 " %c_f32_3 = OpConstant %f32 3\n";
284
285 fragments["decoration"] = " OpMemberDecorate %Output 0 Offset 0\n"
286 " OpDecorate %Output BufferBlock\n"
287 " OpDecorate %dataOutput DescriptorSet 0\n"
288 " OpDecorate %dataOutput Binding 0\n";
289
290 fragments["testfun"] = " %test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
291 " %param = OpFunctionParameter %v4f32\n"
292 " %entry = OpLabel\n"
293 " %vec = OpVariable %fp_v" +
294 de::toString(elements) + "f32 Function\n" +
295 getVectorCompositeInserts(elements, useUndef) +
296 " %vecOutPtr = OpAccessChain %_ptr_Uniform_vec %dataOutput %c_i32_0\n"
297 " OpStore %vecOutPtr %tmp" +
298 de::toString(elements) +
299 "\n"
300 " OpReturnValue %param\n"
301 " OpFunctionEnd\n";
302
303 vulkanFeatures.coreFeatures.vertexPipelineStoresAndAtomics = true;
304 vulkanFeatures.coreFeatures.fragmentStoresAndAtomics = false;
305 createTestForStage(VK_SHADER_STAGE_VERTEX_BIT, (testName + "_vert").c_str(), defaultColors, defaultColors,
306 fragments, noSpecConstants, noPushConstants, resources, noInterfaces, noExtensions,
307 vulkanFeatures, group);
308
309 createTestForStage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, (testName + "_tessc").c_str(), defaultColors,
310 defaultColors, fragments, noSpecConstants, noPushConstants, resources, noInterfaces,
311 noExtensions, vulkanFeatures, group);
312
313 createTestForStage(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, (testName + "_tesse").c_str(),
314 defaultColors, defaultColors, fragments, noSpecConstants, noPushConstants, resources,
315 noInterfaces, noExtensions, vulkanFeatures, group);
316
317 createTestForStage(VK_SHADER_STAGE_GEOMETRY_BIT, (testName + "_geom").c_str(), defaultColors, defaultColors,
318 fragments, noSpecConstants, noPushConstants, resources, noInterfaces, noExtensions,
319 vulkanFeatures, group);
320
321 vulkanFeatures.coreFeatures.vertexPipelineStoresAndAtomics = false;
322 vulkanFeatures.coreFeatures.fragmentStoresAndAtomics = true;
323 createTestForStage(VK_SHADER_STAGE_FRAGMENT_BIT, (testName + "_frag").c_str(), defaultColors, defaultColors,
324 fragments, noSpecConstants, noPushConstants, resources, noInterfaces, noExtensions,
325 vulkanFeatures, group);
326 }
327 }
328
addComputeMatrixCompositeInsertTests(tcu::TestCaseGroup * group)329 void addComputeMatrixCompositeInsertTests(tcu::TestCaseGroup *group)
330 {
331 tcu::TestContext &testCtx = group->getTestContext();
332
333 for (bool useUndef : {true, false})
334 for (uint32_t rows = 2; rows <= 4; rows++)
335 {
336 const uint32_t matrixStride = rows == 3 ? 16 : rows * 4;
337
338 for (uint32_t cols = 2; cols <= 4; cols++)
339 {
340 ComputeShaderSpec spec;
341 vector<float> identityData;
342 string colType = getColType(rows);
343 string matType = getMatrixType(cols, rows);
344
345 // Generate a matrix using OpCompositeInsert with identity vectors and write the matrix into output storage buffer.
346 const string shaderSource =
347 " OpCapability Shader\n"
348 " %1 = OpExtInstImport \"GLSL.std.450\"\n"
349 " OpMemoryModel Logical GLSL450\n"
350 " OpEntryPoint GLCompute %main \"main\"\n"
351 " OpExecutionMode %main LocalSize 1 1 1\n"
352 " OpSource GLSL 430\n"
353 " OpMemberDecorate %Output 0 Offset 0\n"
354 " OpMemberDecorate %Output 0 ColMajor\n"
355 " OpMemberDecorate %Output 0 MatrixStride " +
356 de::toString(matrixStride) +
357 "\n"
358 " OpDecorate %Output BufferBlock\n"
359 " OpDecorate %dataOutput DescriptorSet 0\n"
360 " OpDecorate %dataOutput Binding 0\n"
361 " %f32 = OpTypeFloat 32\n" +
362 getMatrixDeclarations(cols, rows) +
363 " %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
364 " %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n"
365 " %_ptr_Function_mat = OpTypePointer Function " +
366 matType +
367 "\n"
368 " %_ptr_Uniform_mat = OpTypePointer Uniform " +
369 matType +
370 "\n"
371 " %c_f32_0 = OpConstant %f32 0\n"
372 " %c_f32_1 = OpConstant %f32 1\n"
373 " %i32 = OpTypeInt 32 1\n"
374 " %c_i32_0 = OpConstant %i32 0\n" +
375 getIdentityVectors(cols, rows) +
376 " %void = OpTypeVoid\n"
377 " %3 = OpTypeFunction %void\n"
378 " %main = OpFunction %void None %3\n"
379 " %entry = OpLabel\n"
380 " %mat = OpVariable %_ptr_Function_mat Function\n" +
381 getMatrixCompositeInserts(cols, rows, useUndef) +
382 " %matOutPtr = OpAccessChain %_ptr_Uniform_mat %dataOutput %c_i32_0\n"
383 " OpStore %matOutPtr %tmp" +
384 de::toString(cols) +
385 "\n"
386 " OpReturn\n"
387 " OpFunctionEnd\n";
388
389 spec.assembly = shaderSource;
390 spec.numWorkGroups = IVec3(1, 1, 1);
391
392 // Expect identity matrix as output
393 for (uint32_t c = 0; c < cols; c++)
394 {
395 for (uint32_t r = 0; r < rows; r++)
396 identityData.push_back(c == r ? 1.0f : 0.0f);
397 if (rows == 3)
398 identityData.push_back(-1.0f); // Padding
399 }
400
401 spec.outputs.push_back(Resource(BufferSp(new Float32Buffer(identityData))));
402 spec.verifyIO = verifyMatrixOutput;
403
404 string testName =
405 string(useUndef ? "undef_" : "") + "mat" + de::toString(cols) + "x" + de::toString(rows);
406
407 // Tests matrix composite insert.
408 group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), spec));
409 }
410 }
411 }
412
addGraphicsMatrixCompositeInsertTests(tcu::TestCaseGroup * group)413 void addGraphicsMatrixCompositeInsertTests(tcu::TestCaseGroup *group)
414 {
415 for (bool useUndef : {true, false})
416 for (uint32_t rows = 2; rows <= 4; rows++)
417 {
418 const uint32_t matrixStride = rows == 3 ? 16 : rows * 4;
419
420 for (uint32_t cols = 2; cols <= 4; cols++)
421 {
422 map<string, string> fragments;
423 RGBA defaultColors[4];
424 GraphicsResources resources;
425
426 SpecConstants noSpecConstants;
427 PushConstants noPushConstants;
428 GraphicsInterfaces noInterfaces;
429 vector<string> noExtensions;
430 VulkanFeatures vulkanFeatures = VulkanFeatures();
431 vector<float> identityData;
432 string testName =
433 string(useUndef ? "undef_" : "") + "mat" + de::toString(cols) + "x" + de::toString(rows);
434 string matType = getMatrixType(cols, rows);
435
436 // Expect identity matrix as output
437 for (uint32_t c = 0; c < cols; c++)
438 {
439 for (uint32_t r = 0; r < rows; r++)
440 identityData.push_back(c == r ? 1.0f : 0.0f);
441 if (rows == 3)
442 identityData.push_back(-1.0f); // Padding
443 }
444 resources.outputs.push_back(
445 Resource(BufferSp(new Float32Buffer(identityData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
446 resources.verifyIO = verifyMatrixOutput;
447
448 getDefaultColors(defaultColors);
449
450 // Generate a matrix using OpCompositeInsert with identity vectors and write the matrix into output storage buffer.
451 fragments["pre_main"] = getMatrixDeclarations(cols, rows, true) +
452 " %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
453 " %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n"
454 " %_ptr_Function_mat = OpTypePointer Function " +
455 matType +
456 "\n"
457 " %_ptr_Uniform_mat = OpTypePointer Uniform " +
458 matType + "\n" + getIdentityVectors(cols, rows);
459
460 fragments["decoration"] = " OpMemberDecorate %Output 0 Offset 0\n"
461 " OpMemberDecorate %Output 0 ColMajor\n"
462 " OpMemberDecorate %Output 0 MatrixStride " +
463 de::toString(matrixStride) +
464 "\n"
465 " OpDecorate %Output BufferBlock\n"
466 " OpDecorate %dataOutput DescriptorSet 0\n"
467 " OpDecorate %dataOutput Binding 0\n";
468
469 fragments["testfun"] = " %test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
470 " %param = OpFunctionParameter %v4f32\n"
471 " %entry = OpLabel\n"
472 " %mat = OpVariable %_ptr_Function_mat Function\n" +
473 getMatrixCompositeInserts(cols, rows, useUndef) +
474 " %matOutPtr = OpAccessChain %_ptr_Uniform_mat %dataOutput %c_i32_0\n"
475 " OpStore %matOutPtr %tmp" +
476 de::toString(cols) +
477 "\n"
478 " OpReturnValue %param\n"
479 " OpFunctionEnd\n";
480
481 vulkanFeatures.coreFeatures.vertexPipelineStoresAndAtomics = true;
482 vulkanFeatures.coreFeatures.fragmentStoresAndAtomics = false;
483 createTestForStage(VK_SHADER_STAGE_VERTEX_BIT, (testName + "_vert").c_str(), defaultColors,
484 defaultColors, fragments, noSpecConstants, noPushConstants, resources, noInterfaces,
485 noExtensions, vulkanFeatures, group);
486
487 createTestForStage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, (testName + "_tessc").c_str(),
488 defaultColors, defaultColors, fragments, noSpecConstants, noPushConstants, resources,
489 noInterfaces, noExtensions, vulkanFeatures, group);
490
491 createTestForStage(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, (testName + "_tesse").c_str(),
492 defaultColors, defaultColors, fragments, noSpecConstants, noPushConstants, resources,
493 noInterfaces, noExtensions, vulkanFeatures, group);
494
495 createTestForStage(VK_SHADER_STAGE_GEOMETRY_BIT, (testName + "_geom").c_str(), defaultColors,
496 defaultColors, fragments, noSpecConstants, noPushConstants, resources, noInterfaces,
497 noExtensions, vulkanFeatures, group);
498
499 vulkanFeatures.coreFeatures.vertexPipelineStoresAndAtomics = false;
500 vulkanFeatures.coreFeatures.fragmentStoresAndAtomics = true;
501 createTestForStage(VK_SHADER_STAGE_FRAGMENT_BIT, (testName + "_frag").c_str(), defaultColors,
502 defaultColors, fragments, noSpecConstants, noPushConstants, resources, noInterfaces,
503 noExtensions, vulkanFeatures, group);
504 }
505 }
506 }
507
addComputeNestedStructCompositeInsertTests(tcu::TestCaseGroup * group)508 void addComputeNestedStructCompositeInsertTests(tcu::TestCaseGroup *group)
509 {
510 tcu::TestContext &testCtx = group->getTestContext();
511
512 for (bool useUndef : {true, false})
513 {
514 ComputeShaderSpec spec;
515 vector<float> identityData;
516 const uint32_t arraySize = 8u;
517 const string testName = string(useUndef ? "undef_" : "") + "nested_struct";
518
519 const string shaderSource = " OpCapability Shader\n"
520 " %1 = OpExtInstImport \"GLSL.std.450\"\n"
521 " OpMemoryModel Logical GLSL450\n"
522 " OpEntryPoint GLCompute %main \"main\"\n"
523 " OpExecutionMode %main LocalSize 1 1 1\n"
524 " OpSource GLSL 430\n"
525 " OpDecorate %_arr_mat4v4f32_uint_8 ArrayStride 64\n"
526 " OpMemberDecorate %S 0 ColMajor\n"
527 " OpMemberDecorate %S 0 Offset 0\n"
528 " OpMemberDecorate %S 0 MatrixStride 16\n"
529 " OpMemberDecorate %Output 0 Offset 0\n"
530 " OpDecorate %Output BufferBlock\n"
531 " OpDecorate %dataOutput DescriptorSet 0\n"
532 " OpDecorate %dataOutput Binding 0\n"
533 " %f32 = OpTypeFloat 32\n"
534 " %v4f32 = OpTypeVector %f32 4\n"
535 " %mat4v4f32 = OpTypeMatrix %v4f32 4\n"
536 " %uint = OpTypeInt 32 0\n"
537 " %uint_8 = OpConstant %uint 8\n"
538 "%_arr_mat4v4f32_uint_8 = OpTypeArray %mat4v4f32 %uint_8\n"
539 " %S = OpTypeStruct %_arr_mat4v4f32_uint_8\n"
540 " %Output = OpTypeStruct %S\n"
541 " %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
542 " %_ptr_Function_Output = OpTypePointer Function %Output\n"
543 " %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n"
544 " %c_f32_0 = OpConstant %f32 0\n"
545 " %c_f32_1 = OpConstant %f32 1\n"
546 " %i32 = OpTypeInt 32 1\n"
547 " %c_i32_0 = OpConstant %i32 0\n" +
548 getIdentityVectors(4, 4) +
549 " %void = OpTypeVoid\n"
550 " %3 = OpTypeFunction %void\n"
551 " %main = OpFunction %void None %3\n"
552 " %entry = OpLabel\n"
553 " %nestedstruct = OpVariable %_ptr_Function_Output Function\n" +
554 getNestedStructCompositeInserts(arraySize, useUndef) +
555 " OpStore %dataOutput %tmp" + de::toString(arraySize * 4) +
556 "\n"
557 " OpReturn\n"
558 " OpFunctionEnd\n";
559
560 spec.assembly = shaderSource;
561 spec.numWorkGroups = IVec3(1, 1, 1);
562
563 // Expect an array of identity matrix as output
564 for (uint32_t a = 0; a < arraySize; a++)
565 for (uint32_t c = 0; c < 4; c++)
566 for (uint32_t r = 0; r < 4; r++)
567 identityData.push_back(c == r ? 1.0f : 0.0f);
568
569 spec.outputs.push_back(Resource(BufferSp(new Float32Buffer(identityData))));
570
571 // Tests nested struct composite insert.
572 group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), spec));
573 }
574 }
575
addGraphicsNestedStructCompositeInsertTests(tcu::TestCaseGroup * group)576 void addGraphicsNestedStructCompositeInsertTests(tcu::TestCaseGroup *group)
577 {
578 for (bool useUndef : {true, false})
579 {
580 map<string, string> fragments;
581 RGBA defaultColors[4];
582 GraphicsResources resources;
583
584 SpecConstants noSpecConstants;
585 PushConstants noPushConstants;
586 GraphicsInterfaces noInterfaces;
587 vector<string> noExtensions;
588 VulkanFeatures vulkanFeatures = VulkanFeatures();
589 vector<float> identityData;
590 const uint32_t arraySize = 8u;
591 const string testName = string(useUndef ? "undef_" : "") + "nested_struct";
592
593 // Expect an array of identity matrix as output
594 for (uint32_t a = 0; a < arraySize; a++)
595 for (uint32_t c = 0; c < 4; c++)
596 for (uint32_t r = 0; r < 4; r++)
597 identityData.push_back(c == r ? 1.0f : 0.0f);
598 resources.outputs.push_back(
599 Resource(BufferSp(new Float32Buffer(identityData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
600
601 getDefaultColors(defaultColors);
602
603 fragments["pre_main"] = " %uint_8 = OpConstant %u32 8\n"
604 " %mat4v4f32 = OpTypeMatrix %v4f32 4\n"
605 "%_arr_mat4v4f32_uint_8 = OpTypeArray %mat4v4f32 %uint_8\n"
606 " %S = OpTypeStruct %_arr_mat4v4f32_uint_8\n"
607 " %Output = OpTypeStruct %S\n"
608 " %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
609 " %_ptr_Function_Output = OpTypePointer Function %Output\n"
610 " %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n" +
611 getIdentityVectors(4, 4);
612
613 fragments["decoration"] = " OpDecorate %_arr_mat4v4f32_uint_8 ArrayStride 64\n"
614 " OpMemberDecorate %S 0 ColMajor\n"
615 " OpMemberDecorate %S 0 Offset 0\n"
616 " OpMemberDecorate %S 0 MatrixStride 16\n"
617 " OpMemberDecorate %Output 0 Offset 0\n"
618 " OpDecorate %Output BufferBlock\n"
619 " OpDecorate %dataOutput DescriptorSet 0\n"
620 " OpDecorate %dataOutput Binding 0\n";
621
622 fragments["testfun"] = " %test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
623 " %param = OpFunctionParameter %v4f32\n"
624 " %entry = OpLabel\n"
625 " %nestedstruct = OpVariable %_ptr_Function_Output Function\n" +
626 getNestedStructCompositeInserts(arraySize, useUndef) +
627 " OpStore %dataOutput %tmp" + de::toString(arraySize * 4) +
628 "\n"
629 " OpReturnValue %param\n"
630 " OpFunctionEnd\n";
631
632 vulkanFeatures.coreFeatures.vertexPipelineStoresAndAtomics = true;
633 vulkanFeatures.coreFeatures.fragmentStoresAndAtomics = false;
634 createTestForStage(VK_SHADER_STAGE_VERTEX_BIT, (testName + "_vert").c_str(), defaultColors, defaultColors,
635 fragments, noSpecConstants, noPushConstants, resources, noInterfaces, noExtensions,
636 vulkanFeatures, group);
637
638 createTestForStage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, (testName + "_tessc").c_str(), defaultColors,
639 defaultColors, fragments, noSpecConstants, noPushConstants, resources, noInterfaces,
640 noExtensions, vulkanFeatures, group);
641
642 createTestForStage(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, (testName + "_tesse").c_str(), defaultColors,
643 defaultColors, fragments, noSpecConstants, noPushConstants, resources, noInterfaces,
644 noExtensions, vulkanFeatures, group);
645
646 createTestForStage(VK_SHADER_STAGE_GEOMETRY_BIT, (testName + "_geom").c_str(), defaultColors, defaultColors,
647 fragments, noSpecConstants, noPushConstants, resources, noInterfaces, noExtensions,
648 vulkanFeatures, group);
649
650 vulkanFeatures.coreFeatures.vertexPipelineStoresAndAtomics = false;
651 vulkanFeatures.coreFeatures.fragmentStoresAndAtomics = true;
652 createTestForStage(VK_SHADER_STAGE_FRAGMENT_BIT, (testName + "_frag").c_str(), defaultColors, defaultColors,
653 fragments, noSpecConstants, noPushConstants, resources, noInterfaces, noExtensions,
654 vulkanFeatures, group);
655 }
656 }
657
658 } // namespace
659
createCompositeInsertComputeGroup(tcu::TestContext & testCtx)660 tcu::TestCaseGroup *createCompositeInsertComputeGroup(tcu::TestContext &testCtx)
661 {
662 // Compute tests for composite insert.
663 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "composite_insert"));
664 addComputeVectorCompositeInsertTests(group.get());
665 addComputeMatrixCompositeInsertTests(group.get());
666 addComputeNestedStructCompositeInsertTests(group.get());
667
668 return group.release();
669 }
670
createCompositeInsertGraphicsGroup(tcu::TestContext & testCtx)671 tcu::TestCaseGroup *createCompositeInsertGraphicsGroup(tcu::TestContext &testCtx)
672 {
673 // Graphics tests for composite insert.
674 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "composite_insert"));
675 addGraphicsVectorCompositeInsertTests(group.get());
676 addGraphicsMatrixCompositeInsertTests(group.get());
677 addGraphicsNestedStructCompositeInsertTests(group.get());
678
679 return group.release();
680 }
681
682 } // namespace SpirVAssembly
683 } // namespace vkt
684