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