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 group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), "Tests vector composite insert.", spec));
223 }
224 }
225
addGraphicsVectorCompositeInsertTests(tcu::TestCaseGroup * group)226 void addGraphicsVectorCompositeInsertTests (tcu::TestCaseGroup* group)
227 {
228 for (bool useUndef : { true, false })
229 for (deUint32 elements = 2; elements <= 4; elements++)
230 {
231 map<string, string> fragments;
232 RGBA defaultColors[4];
233 GraphicsResources resources;
234
235 SpecConstants noSpecConstants;
236 PushConstants noPushConstants;
237 GraphicsInterfaces noInterfaces;
238 vector<string> noExtensions;
239 VulkanFeatures vulkanFeatures = VulkanFeatures();
240 vector<float> refData;
241 const string testName = string(useUndef ? "undef_" : "") + "vec" + de::toString(elements);
242 const string vecType = string("%v") + de::toString(elements) + "f32";
243
244 // Expect running counter
245 for (deUint32 e = 0; e < elements; e++)
246 refData.push_back((float)e);
247 resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(refData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
248
249 getDefaultColors(defaultColors);
250
251 // Generate a vector using OpCompositeInsert
252 fragments["pre_main"] =
253 " %Output = OpTypeStruct " + vecType + "\n"
254 " %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
255 " %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n"
256 " %fp_v2f32 = OpTypePointer Function %v2f32\n"
257 " %fp_v3f32 = OpTypePointer Function %v3f32\n"
258 " %_ptr_Uniform_vec = OpTypePointer Uniform " + vecType + "\n"
259 " %c_f32_2 = OpConstant %f32 2\n"
260 " %c_f32_3 = OpConstant %f32 3\n";
261
262 fragments["decoration"] =
263 " OpMemberDecorate %Output 0 Offset 0\n"
264 " OpDecorate %Output BufferBlock\n"
265 " OpDecorate %dataOutput DescriptorSet 0\n"
266 " OpDecorate %dataOutput Binding 0\n";
267
268 fragments["testfun"] =
269 " %test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
270 " %param = OpFunctionParameter %v4f32\n"
271 " %entry = OpLabel\n"
272 " %vec = OpVariable %fp_v" + de::toString(elements) + "f32 Function\n"
273 + getVectorCompositeInserts(elements, useUndef) +
274 " %vecOutPtr = OpAccessChain %_ptr_Uniform_vec %dataOutput %c_i32_0\n"
275 " OpStore %vecOutPtr %tmp" + de::toString(elements) + "\n"
276 " OpReturnValue %param\n"
277 " OpFunctionEnd\n";
278
279 vulkanFeatures.coreFeatures.vertexPipelineStoresAndAtomics = DE_TRUE;
280 vulkanFeatures.coreFeatures.fragmentStoresAndAtomics = DE_FALSE;
281 createTestForStage(VK_SHADER_STAGE_VERTEX_BIT, (testName + "_vert").c_str(), defaultColors, defaultColors, fragments, noSpecConstants,
282 noPushConstants, resources, noInterfaces, noExtensions, vulkanFeatures, group);
283
284 createTestForStage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, (testName + "_tessc").c_str(), defaultColors, defaultColors, fragments, noSpecConstants,
285 noPushConstants, resources, noInterfaces, noExtensions, vulkanFeatures, group);
286
287 createTestForStage(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, (testName + "_tesse").c_str(), defaultColors, defaultColors, fragments, noSpecConstants,
288 noPushConstants, resources, noInterfaces, noExtensions, vulkanFeatures, group);
289
290 createTestForStage(VK_SHADER_STAGE_GEOMETRY_BIT, (testName + "_geom").c_str(), defaultColors, defaultColors, fragments, noSpecConstants,
291 noPushConstants, resources, noInterfaces, noExtensions, vulkanFeatures, group);
292
293 vulkanFeatures.coreFeatures.vertexPipelineStoresAndAtomics = DE_FALSE;
294 vulkanFeatures.coreFeatures.fragmentStoresAndAtomics = DE_TRUE;
295 createTestForStage(VK_SHADER_STAGE_FRAGMENT_BIT, (testName + "_frag").c_str(), defaultColors, defaultColors, fragments, noSpecConstants,
296 noPushConstants, resources, noInterfaces, noExtensions, vulkanFeatures, group);
297 }
298 }
299
addComputeMatrixCompositeInsertTests(tcu::TestCaseGroup * group)300 void addComputeMatrixCompositeInsertTests (tcu::TestCaseGroup* group)
301 {
302 tcu::TestContext& testCtx = group->getTestContext();
303
304 for (bool useUndef : { true, false })
305 for (deUint32 rows = 2; rows <= 4; rows++)
306 {
307 const deUint32 matrixStride = rows == 3 ? 16 : rows * 4;
308
309 for (deUint32 cols = 2; cols <= 4; cols++)
310 {
311 ComputeShaderSpec spec;
312 vector<float> identityData;
313 string colType = getColType(rows);
314 string matType = getMatrixType(cols, rows);
315
316 // Generate a matrix using OpCompositeInsert with identity vectors and write the matrix into output storage buffer.
317 const string shaderSource =
318 " OpCapability Shader\n"
319 " %1 = OpExtInstImport \"GLSL.std.450\"\n"
320 " OpMemoryModel Logical GLSL450\n"
321 " OpEntryPoint GLCompute %main \"main\"\n"
322 " OpExecutionMode %main LocalSize 1 1 1\n"
323 " OpSource GLSL 430\n"
324 " OpMemberDecorate %Output 0 Offset 0\n"
325 " OpMemberDecorate %Output 0 ColMajor\n"
326 " OpMemberDecorate %Output 0 MatrixStride " + de::toString(matrixStride) + "\n"
327 " OpDecorate %Output BufferBlock\n"
328 " OpDecorate %dataOutput DescriptorSet 0\n"
329 " OpDecorate %dataOutput Binding 0\n"
330 " %f32 = OpTypeFloat 32\n"
331 + getMatrixDeclarations(cols, rows) +
332 " %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
333 " %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n"
334 " %_ptr_Function_mat = OpTypePointer Function " + matType + "\n"
335 " %_ptr_Uniform_mat = OpTypePointer Uniform " + matType + "\n"
336 " %c_f32_0 = OpConstant %f32 0\n"
337 " %c_f32_1 = OpConstant %f32 1\n"
338 " %i32 = OpTypeInt 32 1\n"
339 " %c_i32_0 = OpConstant %i32 0\n"
340 + getIdentityVectors(cols, rows) +
341 " %void = OpTypeVoid\n"
342 " %3 = OpTypeFunction %void\n"
343 " %main = OpFunction %void None %3\n"
344 " %entry = OpLabel\n"
345 " %mat = OpVariable %_ptr_Function_mat Function\n"
346 + getMatrixCompositeInserts(cols, rows, useUndef) +
347 " %matOutPtr = OpAccessChain %_ptr_Uniform_mat %dataOutput %c_i32_0\n"
348 " OpStore %matOutPtr %tmp" + de::toString(cols) + "\n"
349 " OpReturn\n"
350 " OpFunctionEnd\n";
351
352
353 spec.assembly = shaderSource;
354 spec.numWorkGroups = IVec3(1, 1, 1);
355
356 // Expect identity matrix as output
357 for (deUint32 c = 0; c < cols; c++)
358 {
359 for (deUint32 r = 0; r < rows; r++)
360 identityData.push_back(c == r ? 1.0f : 0.0f);
361 if (rows == 3)
362 identityData.push_back(-1.0f); // Padding
363 }
364
365 spec.outputs.push_back(Resource(BufferSp(new Float32Buffer(identityData))));
366 spec.verifyIO = verifyMatrixOutput;
367
368 string testName = string(useUndef ? "undef_" : "") + "mat" + de::toString(cols) + "x" + de::toString(rows);
369
370 group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), "Tests matrix composite insert.", spec));
371 }
372 }
373 }
374
addGraphicsMatrixCompositeInsertTests(tcu::TestCaseGroup * group)375 void addGraphicsMatrixCompositeInsertTests (tcu::TestCaseGroup* group)
376 {
377 for (bool useUndef : { true, false })
378 for (deUint32 rows = 2; rows <= 4; rows++)
379 {
380 const deUint32 matrixStride = rows == 3 ? 16 : rows * 4;
381
382 for (deUint32 cols = 2; cols <= 4; cols++)
383 {
384 map<string, string> fragments;
385 RGBA defaultColors[4];
386 GraphicsResources resources;
387
388 SpecConstants noSpecConstants;
389 PushConstants noPushConstants;
390 GraphicsInterfaces noInterfaces;
391 vector<string> noExtensions;
392 VulkanFeatures vulkanFeatures = VulkanFeatures();
393 vector<float> identityData;
394 string testName = string(useUndef ? "undef_" : "") + "mat" + de::toString(cols) + "x" + de::toString(rows);
395 string matType = getMatrixType(cols, rows);
396
397 // Expect identity matrix as output
398 for (deUint32 c = 0; c < cols; c++)
399 {
400 for (deUint32 r = 0; r < rows; r++)
401 identityData.push_back(c == r ? 1.0f : 0.0f);
402 if (rows == 3)
403 identityData.push_back(-1.0f); // Padding
404 }
405 resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(identityData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
406 resources.verifyIO = verifyMatrixOutput;
407
408 getDefaultColors(defaultColors);
409
410 // Generate a matrix using OpCompositeInsert with identity vectors and write the matrix into output storage buffer.
411 fragments["pre_main"] =
412 getMatrixDeclarations(cols, rows, true) +
413 " %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
414 " %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n"
415 " %_ptr_Function_mat = OpTypePointer Function " + matType + "\n"
416 " %_ptr_Uniform_mat = OpTypePointer Uniform " + matType + "\n"
417 + getIdentityVectors(cols, rows);
418
419 fragments["decoration"] =
420 " OpMemberDecorate %Output 0 Offset 0\n"
421 " OpMemberDecorate %Output 0 ColMajor\n"
422 " OpMemberDecorate %Output 0 MatrixStride " + de::toString(matrixStride) + "\n"
423 " OpDecorate %Output BufferBlock\n"
424 " OpDecorate %dataOutput DescriptorSet 0\n"
425 " OpDecorate %dataOutput Binding 0\n";
426
427 fragments["testfun"] =
428 " %test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
429 " %param = OpFunctionParameter %v4f32\n"
430 " %entry = OpLabel\n"
431 " %mat = OpVariable %_ptr_Function_mat Function\n"
432 + getMatrixCompositeInserts(cols, rows, useUndef) +
433 " %matOutPtr = OpAccessChain %_ptr_Uniform_mat %dataOutput %c_i32_0\n"
434 " OpStore %matOutPtr %tmp" + de::toString(cols) + "\n"
435 " OpReturnValue %param\n"
436 " OpFunctionEnd\n";
437
438 vulkanFeatures.coreFeatures.vertexPipelineStoresAndAtomics = DE_TRUE;
439 vulkanFeatures.coreFeatures.fragmentStoresAndAtomics = DE_FALSE;
440 createTestForStage(VK_SHADER_STAGE_VERTEX_BIT, (testName + "_vert").c_str(), defaultColors, defaultColors, fragments, noSpecConstants,
441 noPushConstants, resources, noInterfaces, noExtensions, vulkanFeatures, group);
442
443 createTestForStage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, (testName + "_tessc").c_str(), defaultColors, defaultColors, fragments, noSpecConstants,
444 noPushConstants, resources, noInterfaces, noExtensions, vulkanFeatures, group);
445
446 createTestForStage(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, (testName + "_tesse").c_str(), defaultColors, defaultColors, fragments, noSpecConstants,
447 noPushConstants, resources, noInterfaces, noExtensions, vulkanFeatures, group);
448
449 createTestForStage(VK_SHADER_STAGE_GEOMETRY_BIT, (testName + "_geom").c_str(), defaultColors, defaultColors, fragments, noSpecConstants,
450 noPushConstants, resources, noInterfaces, noExtensions, vulkanFeatures, group);
451
452 vulkanFeatures.coreFeatures.vertexPipelineStoresAndAtomics = DE_FALSE;
453 vulkanFeatures.coreFeatures.fragmentStoresAndAtomics = DE_TRUE;
454 createTestForStage(VK_SHADER_STAGE_FRAGMENT_BIT, (testName + "_frag").c_str(), defaultColors, defaultColors, fragments, noSpecConstants,
455 noPushConstants, resources, noInterfaces, noExtensions, vulkanFeatures, group);
456 }
457 }
458 }
459
addComputeNestedStructCompositeInsertTests(tcu::TestCaseGroup * group)460 void addComputeNestedStructCompositeInsertTests (tcu::TestCaseGroup* group)
461 {
462 tcu::TestContext& testCtx = group->getTestContext();
463
464 for (bool useUndef : { true, false })
465 {
466 ComputeShaderSpec spec;
467 vector<float> identityData;
468 const deUint32 arraySize = 8u;
469 const string testName = string(useUndef ? "undef_" : "") + "nested_struct";
470
471 const string shaderSource =
472 " OpCapability Shader\n"
473 " %1 = OpExtInstImport \"GLSL.std.450\"\n"
474 " OpMemoryModel Logical GLSL450\n"
475 " OpEntryPoint GLCompute %main \"main\"\n"
476 " OpExecutionMode %main LocalSize 1 1 1\n"
477 " OpSource GLSL 430\n"
478 " OpDecorate %_arr_mat4v4f32_uint_8 ArrayStride 64\n"
479 " OpMemberDecorate %S 0 ColMajor\n"
480 " OpMemberDecorate %S 0 Offset 0\n"
481 " OpMemberDecorate %S 0 MatrixStride 16\n"
482 " OpMemberDecorate %Output 0 Offset 0\n"
483 " OpDecorate %Output BufferBlock\n"
484 " OpDecorate %dataOutput DescriptorSet 0\n"
485 " OpDecorate %dataOutput Binding 0\n"
486 " %f32 = OpTypeFloat 32\n"
487 " %v4f32 = OpTypeVector %f32 4\n"
488 " %mat4v4f32 = OpTypeMatrix %v4f32 4\n"
489 " %uint = OpTypeInt 32 0\n"
490 " %uint_8 = OpConstant %uint 8\n"
491 "%_arr_mat4v4f32_uint_8 = OpTypeArray %mat4v4f32 %uint_8\n"
492 " %S = OpTypeStruct %_arr_mat4v4f32_uint_8\n"
493 " %Output = OpTypeStruct %S\n"
494 " %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
495 " %_ptr_Function_Output = OpTypePointer Function %Output\n"
496 " %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n"
497 " %c_f32_0 = OpConstant %f32 0\n"
498 " %c_f32_1 = OpConstant %f32 1\n"
499 " %i32 = OpTypeInt 32 1\n"
500 " %c_i32_0 = OpConstant %i32 0\n"
501 + getIdentityVectors(4, 4) +
502 " %void = OpTypeVoid\n"
503 " %3 = OpTypeFunction %void\n"
504 " %main = OpFunction %void None %3\n"
505 " %entry = OpLabel\n"
506 " %nestedstruct = OpVariable %_ptr_Function_Output Function\n"
507 + getNestedStructCompositeInserts(arraySize, useUndef) +
508 " OpStore %dataOutput %tmp" + de::toString(arraySize * 4) + "\n"
509 " OpReturn\n"
510 " OpFunctionEnd\n";
511
512 spec.assembly = shaderSource;
513 spec.numWorkGroups = IVec3(1, 1, 1);
514
515 // Expect an array of identity matrix as output
516 for (deUint32 a = 0; a < arraySize; a++)
517 for (deUint32 c = 0; c < 4; c++)
518 for (deUint32 r = 0; r < 4; r++)
519 identityData.push_back(c == r ? 1.0f : 0.0f);
520
521 spec.outputs.push_back(Resource(BufferSp(new Float32Buffer(identityData))));
522
523 group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), "Tests nested struct composite insert.", spec));
524 }
525 }
526
addGraphicsNestedStructCompositeInsertTests(tcu::TestCaseGroup * group)527 void addGraphicsNestedStructCompositeInsertTests (tcu::TestCaseGroup* group)
528 {
529 for (bool useUndef : { true, false })
530 {
531 map<string, string> fragments;
532 RGBA defaultColors[4];
533 GraphicsResources resources;
534
535 SpecConstants noSpecConstants;
536 PushConstants noPushConstants;
537 GraphicsInterfaces noInterfaces;
538 vector<string> noExtensions;
539 VulkanFeatures vulkanFeatures = VulkanFeatures();
540 vector<float> identityData;
541 const deUint32 arraySize = 8u;
542 const string testName = string(useUndef ? "undef_" : "") + "nested_struct";
543
544 // Expect an array of identity matrix as output
545 for (deUint32 a = 0; a < arraySize; a++)
546 for (deUint32 c = 0; c < 4; c++)
547 for (deUint32 r = 0; r < 4; r++)
548 identityData.push_back(c == r ? 1.0f : 0.0f);
549 resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(identityData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
550
551 getDefaultColors(defaultColors);
552
553 fragments["pre_main"] =
554 " %uint_8 = OpConstant %u32 8\n"
555 " %mat4v4f32 = OpTypeMatrix %v4f32 4\n"
556 "%_arr_mat4v4f32_uint_8 = OpTypeArray %mat4v4f32 %uint_8\n"
557 " %S = OpTypeStruct %_arr_mat4v4f32_uint_8\n"
558 " %Output = OpTypeStruct %S\n"
559 " %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
560 " %_ptr_Function_Output = OpTypePointer Function %Output\n"
561 " %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n"
562 + getIdentityVectors(4, 4);
563
564 fragments["decoration"] =
565 " OpDecorate %_arr_mat4v4f32_uint_8 ArrayStride 64\n"
566 " OpMemberDecorate %S 0 ColMajor\n"
567 " OpMemberDecorate %S 0 Offset 0\n"
568 " OpMemberDecorate %S 0 MatrixStride 16\n"
569 " OpMemberDecorate %Output 0 Offset 0\n"
570 " OpDecorate %Output BufferBlock\n"
571 " OpDecorate %dataOutput DescriptorSet 0\n"
572 " OpDecorate %dataOutput Binding 0\n";
573
574 fragments["testfun"] =
575 " %test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
576 " %param = OpFunctionParameter %v4f32\n"
577 " %entry = OpLabel\n"
578 " %nestedstruct = OpVariable %_ptr_Function_Output Function\n"
579 + getNestedStructCompositeInserts(arraySize, useUndef) +
580 " OpStore %dataOutput %tmp" + de::toString(arraySize * 4) + "\n"
581 " OpReturnValue %param\n"
582 " OpFunctionEnd\n";
583
584 vulkanFeatures.coreFeatures.vertexPipelineStoresAndAtomics = DE_TRUE;
585 vulkanFeatures.coreFeatures.fragmentStoresAndAtomics = DE_FALSE;
586 createTestForStage(VK_SHADER_STAGE_VERTEX_BIT, (testName + "_vert").c_str(), defaultColors, defaultColors, fragments, noSpecConstants,
587 noPushConstants, resources, noInterfaces, noExtensions, vulkanFeatures, group);
588
589 createTestForStage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, (testName + "_tessc").c_str(), defaultColors, defaultColors, fragments, noSpecConstants,
590 noPushConstants, resources, noInterfaces, noExtensions, vulkanFeatures, group);
591
592 createTestForStage(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, (testName + "_tesse").c_str(), defaultColors, defaultColors, fragments, noSpecConstants,
593 noPushConstants, resources, noInterfaces, noExtensions, vulkanFeatures, group);
594
595 createTestForStage(VK_SHADER_STAGE_GEOMETRY_BIT, (testName + "_geom").c_str(), defaultColors, defaultColors, fragments, noSpecConstants,
596 noPushConstants, resources, noInterfaces, noExtensions, vulkanFeatures, group);
597
598 vulkanFeatures.coreFeatures.vertexPipelineStoresAndAtomics = DE_FALSE;
599 vulkanFeatures.coreFeatures.fragmentStoresAndAtomics = DE_TRUE;
600 createTestForStage(VK_SHADER_STAGE_FRAGMENT_BIT, (testName + "_frag").c_str(), defaultColors, defaultColors, fragments, noSpecConstants,
601 noPushConstants, resources, noInterfaces, noExtensions, vulkanFeatures, group);
602 }
603 }
604
605 } // anonymous
606
createCompositeInsertComputeGroup(tcu::TestContext & testCtx)607 tcu::TestCaseGroup* createCompositeInsertComputeGroup (tcu::TestContext& testCtx)
608 {
609 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "composite_insert", "Compute tests for composite insert."));
610 addComputeVectorCompositeInsertTests(group.get());
611 addComputeMatrixCompositeInsertTests(group.get());
612 addComputeNestedStructCompositeInsertTests(group.get());
613
614 return group.release();
615 }
616
createCompositeInsertGraphicsGroup(tcu::TestContext & testCtx)617 tcu::TestCaseGroup* createCompositeInsertGraphicsGroup (tcu::TestContext& testCtx)
618 {
619 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "composite_insert", "Graphics tests for composite insert."));
620 addGraphicsVectorCompositeInsertTests(group.get());
621 addGraphicsMatrixCompositeInsertTests(group.get());
622 addGraphicsNestedStructCompositeInsertTests(group.get());
623
624 return group.release();
625 }
626
627 } // SpirVAssembly
628 } // vkt
629