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