• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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