• 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 		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