• 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 OpVariable initializer
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktSpvAsmVariableInitTests.hpp"
25 #include "vktSpvAsmComputeShaderCase.hpp"
26 #include "vktSpvAsmComputeShaderTestUtil.hpp"
27 #include "vktSpvAsmGraphicsShaderTestUtil.hpp"
28 #include "tcuStringTemplate.hpp"
29 
30 namespace vkt
31 {
32 namespace SpirVAssembly
33 {
34 
35 using namespace vk;
36 using std::map;
37 using std::string;
38 using std::vector;
39 using tcu::IVec3;
40 using tcu::Vec4;
41 using tcu::RGBA;
42 using tcu::StringTemplate;
43 
44 namespace
45 {
46 
47 enum InitializationSource
48 {
49 	INITIALIZATION_SOURCE_CONSTANT,	// Variable is initialized from a constant value
50 	INITIALIZATION_SOURCE_GLOBAL,	// Variable is initialized from a global variable, which in turn is initialized from a constant
51 };
52 
53 struct TestParams
54 {
55 	string						name;
56 	string						type;
57 	int							numComponents;
58 	InitializationSource		initializationSource;
59 };
60 
61 struct ShaderParams
62 {
63 	InstanceContext			context;
64 	string					type;
65 };
66 
67 const TestParams	testParams[]	=
68 {
69 	{ "float",							"f32",			1,				INITIALIZATION_SOURCE_CONSTANT	},
70 	{ "vec4",							"v4f32",		4,				INITIALIZATION_SOURCE_CONSTANT	},
71 	{ "matrix",							"matrix",		2 * 4,			INITIALIZATION_SOURCE_CONSTANT	},
72 	{ "floatarray",						"floatArray",	8,				INITIALIZATION_SOURCE_CONSTANT	},
73 	{ "struct",							"struct",		2 * 4 + 4 + 4,	INITIALIZATION_SOURCE_CONSTANT	},
74 
75 	{ "float_from_workgroup",			"f32",			1,				INITIALIZATION_SOURCE_GLOBAL	},
76 	{ "vec4_from_workgroup",			"v4f32",		4,				INITIALIZATION_SOURCE_GLOBAL	},
77 	{ "matrix_from_workgroup",			"matrix",		2 * 4,			INITIALIZATION_SOURCE_GLOBAL	},
78 	{ "floatarray_from_workgroup",		"floatArray",	8,				INITIALIZATION_SOURCE_GLOBAL	},
79 	{ "struct_from_workgroup",			"struct",		2 * 4 + 4 + 4,	INITIALIZATION_SOURCE_GLOBAL	}
80 };
81 
82 const string		common			=
83 	"                      %f32_1 = OpConstant %f32 1\n"
84 	"                    %v4f32_1 = OpConstantComposite %v4f32 %f32_1 %f32_1 %f32_1 %f32_1\n"
85 	"                     %matrix = OpTypeMatrix %v4f32 2\n"
86 	"                   %matrix_1 = OpConstantComposite %matrix %v4f32_1 %v4f32_1\n"
87 	"                     %struct = OpTypeStruct %matrix %v4f32 %f32 %f32 %f32 %f32\n"
88 	"                   %struct_1 = OpConstantComposite %struct %matrix_1 %v4f32_1 %f32_1 %f32_1 %f32_1 %f32_1\n"
89 	"                    %c_u32_8 = OpConstant %u32 8\n"
90 	"                 %floatArray = OpTypeArray %f32 %c_u32_8\n"
91 	"               %floatArray_1 = OpConstantComposite %floatArray %f32_1 %f32_1 %f32_1 %f32_1 %f32_1 %f32_1 %f32_1 %f32_1\n"
92 	"                %numElements = OpConstant %u32 ${count}\n"
93 	"                %outputArray = OpTypeArray %${type} %numElements\n"
94 	"                     %Output = OpTypeStruct %outputArray\n"
95 	"                %_ptr_Output = OpTypePointer StorageBuffer %Output\n"
96 	"                      %sbPtr = OpTypePointer StorageBuffer %${type}\n"
97 	"                 %dataOutput = OpVariable %_ptr_Output StorageBuffer\n";
98 
99 const string		globals			=
100 	"        %_ptr_${type}_global = OpTypePointer Workgroup %${type}\n"
101 	"           %${type}_global_1 = OpVariable %_ptr_${type}_global Workgroup\n";
102 
103 const string		decorations		=
104 	"${arrayStrideDecoration}"
105 	"                               OpMemberDecorate %Output 0 Offset 0\n"
106 	"                               OpDecorate %Output Block\n"
107 	"                               OpDecorate %dataOutput DescriptorSet 0\n"
108 	"                               OpDecorate %dataOutput Binding 0\n"
109 	"${extraDecorations:opt}"
110 	"                               OpDecorate %floatArray ArrayStride 4\n"
111 	"                               OpMemberDecorate %struct 0 ColMajor\n"
112 	"                               OpMemberDecorate %struct 0 Offset 0\n"
113 	"                               OpMemberDecorate %struct 0 MatrixStride 16\n"
114 	"                               OpMemberDecorate %struct 1 Offset 32\n"
115 	"                               OpMemberDecorate %struct 2 Offset 48\n"
116 	"                               OpMemberDecorate %struct 3 Offset 52\n"
117 	"                               OpMemberDecorate %struct 4 Offset 56\n"
118 	"                               OpMemberDecorate %struct 5 Offset 60\n";
119 
addComputeVariableInitPrivateTest(tcu::TestCaseGroup * group)120 void addComputeVariableInitPrivateTest (tcu::TestCaseGroup* group)
121 {
122 	tcu::TestContext&		testCtx					= group->getTestContext();
123 	const int				numFloats				= 128;
124 	tcu::TestCaseGroup*		privateGroup			= new tcu::TestCaseGroup(testCtx, "private", "Tests OpVariable initialization in private storage class.");
125 	vector<float>			expectedOutput			(numFloats, 1.0f);
126 
127 	group->addChild(privateGroup);
128 
129 	for (int paramIdx = 0; paramIdx < DE_LENGTH_OF_ARRAY(testParams); paramIdx++)
130 	{
131 		ComputeShaderSpec		spec;
132 		spec.outputs.push_back(BufferSp(new Float32Buffer(expectedOutput)));
133 
134 		map<string, string>		shaderSpec;
135 		const int				numComponents			= testParams[paramIdx].numComponents;
136 		const int				numElements				= numFloats / numComponents;
137 		const string			type					= testParams[paramIdx].type;
138 
139 		const StringTemplate	shaderSourceTemplate	(
140 			string(
141 			"                         OpCapability Shader\n"
142 			"${capabilities:opt}"
143 			"                         OpExtension \"SPV_KHR_storage_buffer_storage_class\"\n"
144 			"${extensions:opt}"
145 			"                    %1 = OpExtInstImport \"GLSL.std.450\"\n"
146 			"                         OpMemoryModel Logical GLSL450\n"
147 			"                         OpEntryPoint GLCompute %main \"main\" %gl_GlobalInvocationID\n"
148 			"                         OpExecutionMode %main LocalSize 1 1 1\n"
149 			"                         OpSource GLSL 430\n"
150 			"                         OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId\n")
151 			+ decorations + string(
152 			"                 %void = OpTypeVoid\n"
153 			"             %voidFunc = OpTypeFunction %void\n"
154 			"                  %f32 = OpTypeFloat 32\n"
155 			"                  %u32 = OpTypeInt 32 0\n"
156 			"              %c_u32_0 = OpConstant %u32 0\n"
157 			"                %v4f32 = OpTypeVector %f32 4\n")
158 			+ common
159 			+ (testParams[paramIdx].initializationSource == INITIALIZATION_SOURCE_GLOBAL ? globals : "")
160 			+ string(
161 			"              %dataPtr = OpTypePointer Private %${type}\n"
162 			"   %_ptr_Function_uint = OpTypePointer Function %u32\n"
163 			"               %v3uint = OpTypeVector %u32 3\n"
164 			"    %_ptr_Input_v3uint = OpTypePointer Input %v3uint\n"
165 			"%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input\n"
166 			"      %_ptr_Input_uint = OpTypePointer Input %u32\n"
167 			"                  %int = OpTypeInt 32 1\n"
168 			"                %int_0 = OpConstant %int 0\n"
169 			"${variableInit}"
170 			"                 %main = OpFunction %void None %voidFunc\n"
171 			"                %entry = OpLabel\n"
172 			"        %invocationPtr = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %c_u32_0\n"
173 			"           %invocation = OpLoad %u32 %invocationPtr\n"
174 			"${dataLoad}"
175 			"            %outputPtr = OpAccessChain %sbPtr %dataOutput %int_0 %invocation\n"
176 			"                         OpStore %outputPtr %outputData\n"
177 			"                         OpReturn\n"
178 			"                         OpFunctionEnd\n"));
179 
180 		shaderSpec["type"]					= type;
181 
182 		shaderSpec["arrayStrideDecoration"] = "OpDecorate %outputArray ArrayStride " + de::toString(numComponents * 4) + "\n";
183 		shaderSpec["count"]					= de::toString(numElements);
184 		shaderSpec["constData"]				= type + "_1";
185 
186 		switch(testParams[paramIdx].initializationSource)
187 		{
188 			case INITIALIZATION_SOURCE_CONSTANT:
189 				shaderSpec["variableInit"]	= "             %f1 = OpVariable %dataPtr Private %" + type + "_1\n";
190 				shaderSpec["dataLoad"]		= "     %outputData = OpLoad %" + type + " %f1\n";
191 				break;
192 			default:
193 				DE_ASSERT(testParams[paramIdx].initializationSource == INITIALIZATION_SOURCE_GLOBAL);
194 
195 				shaderSpec["capabilities"]			= "                   OpCapability VariablePointers\n";
196 				shaderSpec["extensions"]			= "                   OpExtension \"SPV_KHR_variable_pointers\"\n";
197 				shaderSpec["variableInit"]			= "     %dataPtrPtr = OpTypePointer Private %_ptr_" + type + "_global\n"
198 													  "             %f1 = OpVariable %dataPtrPtr Private %" + type + "_global_1\n";
199 				shaderSpec["dataLoad"]				= "  %outputDataPtr = OpLoad %_ptr_" + type + "_global %f1\n"
200 													  "                   OpStore %" + type + "_global_1 %" + type + "_1\n"
201 													  "     %outputData = OpLoad %" + type + " %outputDataPtr\n";
202 
203 				spec.requestedVulkanFeatures.extVariablePointers.variablePointers = true;
204 				spec.extensions.push_back("VK_KHR_variable_pointers");
205 				break;
206 		}
207 
208 		if (testParams[paramIdx].type == "matrix")
209 		{
210 			shaderSpec["extraDecorations"] +=
211 				"                         OpMemberDecorate %Output 0 ColMajor\n"
212 				"                         OpMemberDecorate %Output 0 MatrixStride 16\n";
213 		}
214 
215 		spec.assembly				= shaderSourceTemplate.specialize(shaderSpec);
216 		spec.numWorkGroups			= IVec3(numElements, 1, 1);
217 		spec.extensions.push_back("VK_KHR_storage_buffer_storage_class");
218 
219 		privateGroup->addChild(new SpvAsmComputeShaderCase(testCtx, testParams[paramIdx].name.c_str(), "", spec));
220 	}
221 }
222 
addGraphicsVariableInitPrivateTest(tcu::TestCaseGroup * group)223 void addGraphicsVariableInitPrivateTest (tcu::TestCaseGroup* group)
224 {
225 	tcu::TestContext&		testCtx				= group->getTestContext();
226 	map<string, string>		fragments;
227 	RGBA					defaultColors[4];
228 	VulkanFeatures			features;
229 	tcu::TestCaseGroup*		privateGroup		= new tcu::TestCaseGroup(testCtx, "private", "Tests OpVariable initialization in private storage class.");
230 	const int				numFloats			= 128;
231 	vector<float>			expectedOutput		(numFloats, 1.0f);
232 
233 	group->addChild(privateGroup);
234 	getDefaultColors(defaultColors);
235 
236 	features.coreFeatures.vertexPipelineStoresAndAtomics	= true;
237 	features.coreFeatures.fragmentStoresAndAtomics			= true;
238 
239 	for (int paramIdx = 0; paramIdx < DE_LENGTH_OF_ARRAY(testParams); paramIdx++)
240 	{
241 		if (testParams[paramIdx].initializationSource != INITIALIZATION_SOURCE_CONSTANT)
242 			continue;
243 
244 		GraphicsResources	resources;
245 		vector<string>		extensions;
246 
247 		resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(expectedOutput)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
248 		extensions.push_back("VK_KHR_storage_buffer_storage_class");
249 
250 		map<string, string> shaderSpec;
251 		const int			numComponents	= testParams[paramIdx].numComponents;
252 		const int			numElements		= numFloats / numComponents;
253 		const string		type			= testParams[paramIdx].type;
254 
255 		StringTemplate			preMain		(
256 			common
257 			+ string(
258 			"              %dataPtr = OpTypePointer Private %${type}\n"
259 			"${variableInit}"
260 			));
261 
262 		StringTemplate			decoration	(decorations);
263 
264 		StringTemplate			testFun		(
265 			"            %test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
266 			"                %param = OpFunctionParameter %v4f32\n"
267 			"                %entry = OpLabel\n"
268 			"                    %i = OpVariable %fp_i32 Function\n"
269 			"${dataLoad}"
270 			"                         OpStore %i %c_i32_0\n"
271 			"                         OpBranch %loop\n"
272 			"                 %loop = OpLabel\n"
273 			"                   %15 = OpLoad %i32 %i\n"
274 			"                   %lt = OpSLessThan %bool %15 %numElements\n"
275 			"                         OpLoopMerge %merge %inc None\n"
276 			"                         OpBranchConditional %lt %write %merge\n"
277 			"                %write = OpLabel\n"
278 			"                   %30 = OpLoad %i32 %i\n"
279 			"            %outputPtr = OpAccessChain %sbPtr %dataOutput %c_i32_0 %30\n"
280 			"                         OpStore %outputPtr %outputData\n"
281 			"                         OpBranch %inc\n"
282 			"                  %inc = OpLabel\n"
283 			"                   %37 = OpLoad %i32 %i\n"
284 			"                   %39 = OpIAdd %i32 %37 %c_i32_1\n"
285 			"                         OpStore %i %39\n"
286 			"                         OpBranch %loop\n"
287 			"                %merge = OpLabel\n"
288 			"                         OpReturnValue %param\n"
289 			"                         OpFunctionEnd\n");
290 
291 		shaderSpec["type"]					= type;
292 		shaderSpec["arrayStrideDecoration"] = "OpDecorate %outputArray ArrayStride " + de::toString(numComponents * 4) + "\n";
293 		shaderSpec["count"]					= de::toString(numElements);
294 		shaderSpec["constData"]				= type + "_1";
295 		shaderSpec["variableInit"]	= "             %f1 = OpVariable %dataPtr Private %" + type + "_1\n";
296 		shaderSpec["dataLoad"]		= "     %outputData = OpLoad %" + type + " %f1\n";
297 
298 		if (testParams[paramIdx].type == "matrix")
299 		{
300 			shaderSpec["extraDecorations"] +=
301 				"                         OpMemberDecorate %Output 0 ColMajor\n"
302 				"                         OpMemberDecorate %Output 0 MatrixStride 16\n";
303 		}
304 
305 		fragments["extension"]		+= "OpExtension \"SPV_KHR_storage_buffer_storage_class\"\n";
306 		fragments["pre_main"]		= preMain.specialize(shaderSpec);
307 		fragments["decoration"]		= decoration.specialize(shaderSpec);
308 		fragments["testfun"]		= testFun.specialize(shaderSpec);
309 
310 		createTestsForAllStages(testParams[paramIdx].name, defaultColors, defaultColors, fragments, resources, extensions, privateGroup, features);
311 	}
312 }
313 
outputTest(Context & context,ShaderParams params)314 tcu::TestStatus outputTest (Context& context, ShaderParams params)
315 {
316 	return runAndVerifyDefaultPipeline(context, params.context);
317 }
318 
addShaderCodeOutput(vk::SourceCollections & dst,ShaderParams params)319 void addShaderCodeOutput (vk::SourceCollections& dst, ShaderParams params)
320 {
321 
322 	SpirvVersion			targetSpirvVersion	= params.context.resources.spirvVersion;
323 	map<string, string>		spec;
324 	const deUint32			vulkanVersion		= dst.usedVulkanVersion;
325 
326 	spec["type"]		= params.type;
327 	spec["initSource"]	= params.type + "_1";
328 
329 	if (params.type == "struct")
330 	{
331 		// Output structure of matrix, vec4, and four floats all having values of 1.
332 		const StringTemplate	vertexShader	(
333 			"                            OpCapability Shader\n"
334 			"                       %1 = OpExtInstImport \"GLSL.std.450\"\n"
335 			"                            OpMemoryModel Logical GLSL450\n"
336 			"                            OpEntryPoint Vertex %main \"main\" %_ %position %vtxColor %color %outData\n"
337 			"                            OpSource GLSL 430\n"
338 			"                            OpMemberDecorate %gl_PerVertex 0 BuiltIn Position\n"
339 			"                            OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize\n"
340 			"                            OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance\n"
341 			"                            OpDecorate %gl_PerVertex Block\n"
342 			"                            OpDecorate %position Location 0\n"
343 			"                            OpDecorate %vtxColor Location 1\n"
344 			"                            OpDecorate %color Location 1\n"
345 			"                            OpDecorate %outData Location 2\n"
346 			"                            OpMemberDecorate %Data 0 ColMajor\n"
347 			"                            OpMemberDecorate %Data 0 Offset 0\n"
348 			"                            OpMemberDecorate %Data 0 MatrixStride 16\n"
349 			"                            OpMemberDecorate %Data 1 Offset 32\n"
350 			"                            OpMemberDecorate %Data 2 Offset 48\n"
351 			"                            OpMemberDecorate %Data 3 Offset 52\n"
352 			"                            OpMemberDecorate %Data 4 Offset 56\n"
353 			"                            OpMemberDecorate %Data 5 Offset 60\n"
354 			"                            OpMemberDecorate %DataOutput 0 Offset 0\n"
355 			"                    %void = OpTypeVoid\n"
356 			"                %voidFunc = OpTypeFunction %void\n"
357 			"                   %float = OpTypeFloat 32\n"
358 			"                 %v4float = OpTypeVector %float 4\n"
359 			"                    %uint = OpTypeInt 32 0\n"
360 			"                  %uint_1 = OpConstant %uint 1\n"
361 			"       %_arr_float_uint_1 = OpTypeArray %float %uint_1\n"
362 			"            %gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1\n"
363 			"%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex\n"
364 			"                       %_ = OpVariable %_ptr_Output_gl_PerVertex Output\n"
365 			"                     %int = OpTypeInt 32 1\n"
366 			"                   %int_0 = OpConstant %int 0\n"
367 			"      %_ptr_Input_v4float = OpTypePointer Input %v4float\n"
368 			"                %position = OpVariable %_ptr_Input_v4float Input\n"
369 			"     %_ptr_Output_v4float = OpTypePointer Output %v4float\n"
370 			"                %vtxColor = OpVariable %_ptr_Output_v4float Output\n"
371 			"                   %color = OpVariable %_ptr_Input_v4float Input\n"
372 			"             %mat2v4float = OpTypeMatrix %v4float 2\n"
373 			"                    %Data = OpTypeStruct %mat2v4float %v4float %float %float %float %float\n"
374 			"              %DataOutput = OpTypeStruct %Data\n"
375 			"  %_ptr_Output_DataOutput = OpTypePointer Output %DataOutput\n"
376 			"                 %float_1 = OpConstant %float 1\n"
377 			"                  %vec4_1 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1\n"
378 			"                %matrix_1 = OpConstantComposite %mat2v4float %vec4_1 %vec4_1\n"
379 			" %_ptr_Output_mat2v4float = OpTypePointer Output %mat2v4float\n"
380 			"       %_ptr_Output_float = OpTypePointer Output %float\n"
381 			"                  %data_1 = OpConstantComposite %Data %matrix_1 %vec4_1 %float_1 %float_1 %float_1 %float_1\n"
382 			"                %struct_1 = OpConstantComposite %DataOutput %data_1\n"
383 			"     %_ptr_struct_private = OpTypePointer Private %DataOutput\n"
384 			"         %struct_global_1 = OpVariable %_ptr_struct_private Private %struct_1\n"
385 			"                 %outData = OpVariable %_ptr_Output_DataOutput Output %${initSource}\n"
386 			"                    %main = OpFunction %void None %voidFunc\n"
387 			"                   %entry = OpLabel\n"
388 			"                 %posData = OpLoad %v4float %position\n"
389 			"                  %posPtr = OpAccessChain %_ptr_Output_v4float %_ %int_0\n"
390 			"                            OpStore %posPtr %posData\n"
391 			"               %colorData = OpLoad %v4float %color\n"
392 			"                            OpStore %vtxColor %colorData\n"
393 			"                            OpReturn\n"
394 			"                            OpFunctionEnd\n");
395 
396 		// Pass the incoming input struct into buffer.
397 		const string		fragmentShader	=
398 			"                            OpCapability Shader\n"
399 			"                            OpExtension \"SPV_KHR_storage_buffer_storage_class\"\n"
400 			"                       %1 = OpExtInstImport \"GLSL.std.450\"\n"
401 			"                            OpMemoryModel Logical GLSL450\n"
402 			"                            OpEntryPoint Fragment %main \"main\" %fragColor %vtxColor %inData\n"
403 			"                            OpExecutionMode %main OriginUpperLeft\n"
404 			"                            OpSource GLSL 430\n"
405 			"                            OpDecorate %fragColor Location 0\n"
406 			"                            OpDecorate %vtxColor Location 1\n"
407 			"                            OpMemberDecorate %Data 0 ColMajor\n"
408 			"                            OpMemberDecorate %Data 0 Offset 0\n"
409 			"                            OpMemberDecorate %Data 0 MatrixStride 16\n"
410 			"                            OpMemberDecorate %Data 1 Offset 32\n"
411 			"                            OpMemberDecorate %Data 2 Offset 48\n"
412 			"                            OpMemberDecorate %Data 3 Offset 52\n"
413 			"                            OpMemberDecorate %Data 4 Offset 56\n"
414 			"                            OpMemberDecorate %Data 5 Offset 60\n"
415 			"                            OpMemberDecorate %Output 0 Offset 0\n"
416 			"                            OpDecorate %Output Block\n"
417 			"                            OpDecorate %dataOutput DescriptorSet 0\n"
418 			"                            OpDecorate %dataOutput Binding 0\n"
419 			"                            OpDecorate %inData Location 2\n"
420 			"                    %void = OpTypeVoid\n"
421 			"                %voidFunc = OpTypeFunction %void\n"
422 			"                   %float = OpTypeFloat 32\n"
423 			"                 %v4float = OpTypeVector %float 4\n"
424 			"     %_ptr_Output_v4float = OpTypePointer Output %v4float\n"
425 			"               %fragColor = OpVariable %_ptr_Output_v4float Output\n"
426 			"      %_ptr_Input_v4float = OpTypePointer Input %v4float\n"
427 			"                %vtxColor = OpVariable %_ptr_Input_v4float Input\n"
428 			"             %mat2v4float = OpTypeMatrix %v4float 2\n"
429 			"                    %Data = OpTypeStruct %mat2v4float %v4float %float %float %float %float\n"
430 			"                  %Output = OpTypeStruct %Data\n"
431 			"             %_ptr_Output = OpTypePointer StorageBuffer %Output\n"
432 			"              %dataOutput = OpVariable %_ptr_Output StorageBuffer\n"
433 			"                     %int = OpTypeInt 32 1\n"
434 			"                   %int_0 = OpConstant %int 0\n"
435 			"               %DataInput = OpTypeStruct %Data\n"
436 			"    %_ptr_Input_DataInput = OpTypePointer Input %DataInput\n"
437 			"                  %inData = OpVariable %_ptr_Input_DataInput Input\n"
438 			"         %_ptr_Input_Data = OpTypePointer Input %Data\n"
439 			"               %_ptr_Data = OpTypePointer StorageBuffer %Data\n"
440 			"                    %main = OpFunction %void None %voidFunc\n"
441 			"                   %entry = OpLabel\n"
442 			"               %colorData = OpLoad %v4float %vtxColor\n"
443 			"                            OpStore %fragColor %colorData\n"
444 			"            %inputDataPtr = OpAccessChain %_ptr_Input_Data %inData %int_0\n"
445 			"               %inputData = OpLoad %Data %inputDataPtr\n"
446 			"           %outputDataPtr = OpAccessChain %_ptr_Data %dataOutput %int_0\n"
447 			"                            OpStore %outputDataPtr %inputData\n"
448 			"                            OpReturn\n"
449 			"                            OpFunctionEnd\n";
450 
451 		dst.spirvAsmSources.add("vert", DE_NULL) << vertexShader.specialize(spec) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
452 		dst.spirvAsmSources.add("frag", DE_NULL) << fragmentShader << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
453 	}
454 	else
455 	{
456 		// Needed for preventing duplicate pointer declarations.
457 		if (params.type == "v4f32")
458 		{
459 			spec["vec4ptrDeclOutput"]	= "";
460 			spec["vec4ptrOutput"]		= "outputPtr";
461 			spec["vec4ptrDeclInput"]	= "";
462 			spec["vec4ptrInput"]		= "inputPtr";
463 		}
464 		else
465 		{
466 			spec["vec4ptrDeclOutput"]	= "     %_ptr_Output_v4f32 = OpTypePointer Output %v4f32\n";
467 			spec["vec4ptrOutput"]		= "_ptr_Output_v4f32";
468 			spec["vec4ptrDeclInput"]	= "     %_ptr_Input_v4f32 = OpTypePointer Input %v4f32\n";
469 			spec["vec4ptrInput"]		= "_ptr_Input_v4f32";
470 		}
471 
472 		const string			types				=
473 			"                     %u32 = OpTypeInt 32 0\n"
474 			"                     %f32 = OpTypeFloat 32\n"
475 			"                   %v4f32 = OpTypeVector %f32 4\n"
476 			"                  %matrix = OpTypeMatrix %v4f32 2\n"
477 			"                 %c_u32_0 = OpConstant %u32 0\n"
478 			"                 %c_u32_8 = OpConstant %u32 8\n"
479 			"              %floatArray = OpTypeArray %f32 %c_u32_8\n";
480 
481 		if (params.type == "matrix")
482 		{
483 			spec["extraDecorations"] =
484 				"                       OpMemberDecorate %Output 0 ColMajor\n"
485 				"                       OpMemberDecorate %Output 0 MatrixStride 16\n";
486 		}
487 
488 		// Output selected data type with all components having value one.
489 		const StringTemplate	vertexShader		(
490 			string(
491 			"                            OpCapability Shader\n"
492 			"                       %1 = OpExtInstImport \"GLSL.std.450\"\n"
493 			"                            OpMemoryModel Logical GLSL450\n"
494 			"                            OpEntryPoint Vertex %main \"main\" %_ %position %vtxColor %color %outData\n"
495 			"                            OpSource GLSL 430\n"
496 			"                            OpMemberDecorate %gl_PerVertex 0 BuiltIn Position\n"
497 			"                            OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize\n"
498 			"                            OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance\n"
499 			"                            OpDecorate %gl_PerVertex Block\n"
500 			"                            OpDecorate %position Location 0\n"
501 			"                            OpDecorate %vtxColor Location 1\n"
502 			"                            OpDecorate %color Location 1\n"
503 			"                            OpDecorate %outData Location 2\n"
504 			"                            OpDecorate %floatArray ArrayStride 4\n"
505 			"                    %void = OpTypeVoid\n"
506 			"                       %3 = OpTypeFunction %void\n")
507 			+ types + string(
508 			"                   %f32_1 = OpConstant %f32 1\n"
509 			"        %_ptr_f32_private = OpTypePointer Private %f32\n"
510 			"            %f32_global_1 = OpVariable %_ptr_f32_private Private %f32_1\n"
511 			"                 %v4f32_1 = OpConstantComposite %v4f32 %f32_1 %f32_1 %f32_1 %f32_1\n"
512 			"      %_ptr_v4f32_private = OpTypePointer Private %v4f32\n"
513 			"          %v4f32_global_1 = OpVariable %_ptr_v4f32_private Private %v4f32_1\n"
514 			"                %matrix_1 = OpConstantComposite %matrix %v4f32_1 %v4f32_1\n"
515 			"     %_ptr_matrix_private = OpTypePointer Private %matrix\n"
516 			"         %matrix_global_1 = OpVariable %_ptr_matrix_private Private %matrix_1\n"
517 			"            %floatArray_1 = OpConstantComposite %floatArray %f32_1 %f32_1 %f32_1 %f32_1 %f32_1 %f32_1 %f32_1 %f32_1\n"
518 			" %_ptr_floatArray_private = OpTypePointer Private %floatArray\n"
519 			"     %floatArray_global_1 = OpVariable %_ptr_floatArray_private Private %floatArray_1\n"
520 			"                 %c_u32_1 = OpConstant %u32 1\n"
521 			"          %_arr_f32_u32_1 = OpTypeArray %f32 %c_u32_1\n"
522 			"            %gl_PerVertex = OpTypeStruct %v4f32 %f32 %_arr_f32_u32_1\n"
523 			"%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex\n"
524 			"                       %_ = OpVariable %_ptr_Output_gl_PerVertex Output\n"
525 			"               %outputPtr = OpTypePointer Output %${type}\n"
526 			"                 %outData = OpVariable %outputPtr Output %${initSource}\n"
527 			"        %_ptr_Input_v4f32 = OpTypePointer Input %v4f32\n"
528 			"                %position = OpVariable %_ptr_Input_v4f32 Input\n"
529 			"${vec4ptrDeclOutput}"
530 			"                %vtxColor = OpVariable %${vec4ptrOutput} Output\n"
531 			"                   %color = OpVariable %_ptr_Input_v4f32 Input\n"
532 			"                    %main = OpFunction %void None %3\n"
533 			"                   %entry = OpLabel\n"
534 			"                 %posData = OpLoad %v4f32 %position\n"
535 			"            %posOutputPtr = OpAccessChain %${vec4ptrOutput} %_ %c_u32_0\n"
536 			"                            OpStore %posOutputPtr %posData\n"
537 			"               %colorData = OpLoad %v4f32 %color\n"
538 			"                            OpStore %vtxColor %colorData\n"
539 			"                            OpReturn\n"
540 			"                            OpFunctionEnd\n"));
541 
542 		// Pass incoming data into buffer
543 		const StringTemplate	fragmentShader		(
544 			string(
545 			"                       OpCapability Shader\n"
546 			"                       OpExtension \"SPV_KHR_storage_buffer_storage_class\"\n"
547 			"                  %1 = OpExtInstImport \"GLSL.std.450\"\n"
548 			"                       OpMemoryModel Logical GLSL450\n"
549 			"                       OpEntryPoint Fragment %main \"main\" %fragColor %vtxColor %inData\n"
550 			"                       OpExecutionMode %main OriginUpperLeft\n"
551 			"                       OpSource GLSL 430\n"
552 			"                       OpDecorate %fragColor Location 0\n"
553 			"                       OpDecorate %vtxColor Location 1\n"
554 			"                       OpMemberDecorate %Output 0 Offset 0\n"
555 			"                       OpDecorate %Output Block\n"
556 			"                       OpDecorate %dataOutput DescriptorSet 0\n"
557 			"                       OpDecorate %dataOutput Binding 0\n"
558 			"                       OpDecorate %inData Location 2\n"
559 			"                       OpDecorate %floatArray ArrayStride 4\n"
560 			"${extraDecorations:opt}"
561 			"               %void = OpTypeVoid\n"
562 			"                  %3 = OpTypeFunction %void\n")
563 			+ types + string(
564 			"           %inputPtr = OpTypePointer Input %${type}\n"
565 			"             %inData = OpVariable %inputPtr Input\n"
566 			"  %_ptr_Output_v4f32 = OpTypePointer Output %v4f32\n"
567 			"          %fragColor = OpVariable %_ptr_Output_v4f32 Output\n"
568 			"${vec4ptrDeclInput}"
569 			"           %vtxColor = OpVariable %${vec4ptrInput} Input\n"
570 			"             %Output = OpTypeStruct %${type}\n"
571 			"        %_ptr_Output = OpTypePointer StorageBuffer %Output\n"
572 			"         %dataOutput = OpVariable %_ptr_Output StorageBuffer\n"
573 			"          %outputPtr = OpTypePointer StorageBuffer %${type}\n"
574 			"               %main = OpFunction %void None %3\n"
575 			"              %entry = OpLabel\n"
576 			"          %colorData = OpLoad %v4f32 %vtxColor\n"
577 			"                       OpStore %fragColor %colorData\n"
578 			"          %inputData = OpLoad %${type} %inData\n"
579 			"      %outputDataPtr = OpAccessChain %outputPtr %dataOutput %c_u32_0\n"
580 			"                       OpStore %outputDataPtr %inputData\n"
581 			"                       OpReturn\n"
582 			"                       OpFunctionEnd\n"));
583 
584 		dst.spirvAsmSources.add("vert", DE_NULL) << vertexShader.specialize(spec) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
585 		dst.spirvAsmSources.add("frag", DE_NULL) << fragmentShader.specialize(spec) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
586 	}
587 }
588 
addGraphicsVariableInitOutputTest(tcu::TestCaseGroup * group)589 void addGraphicsVariableInitOutputTest (tcu::TestCaseGroup* group)
590 {
591 	tcu::TestContext&		testCtx				= group->getTestContext();
592 	map<string, string>		fragments;
593 	RGBA					defaultColors[4];
594 	tcu::TestCaseGroup*		outputGroup			= new tcu::TestCaseGroup(testCtx, "output", "Tests OpVariable initialization in output storage class.");
595 	SpecConstants			noSpecConstants;
596 	PushConstants			noPushConstants;
597 	GraphicsInterfaces		noInterfaces;
598 	vector<string>			extensions;
599 	map<string, string>		noFragments;
600 	StageToSpecConstantMap	specConstantMap;
601 
602 	const ShaderElement		pipelineStages[]	=
603 	{
604 		ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT),
605 		ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT),
606 	};
607 
608 	specConstantMap[VK_SHADER_STAGE_VERTEX_BIT]		= noSpecConstants;
609 	specConstantMap[VK_SHADER_STAGE_FRAGMENT_BIT]	= noSpecConstants;
610 
611 	getDefaultColors(defaultColors);
612 
613 	group->addChild(outputGroup);
614 
615 	VulkanFeatures requiredFeatures;
616 	requiredFeatures.coreFeatures.fragmentStoresAndAtomics = VK_TRUE;
617 	extensions.push_back("VK_KHR_storage_buffer_storage_class");
618 
619 	for (int paramIdx = 0; paramIdx < DE_LENGTH_OF_ARRAY(testParams); paramIdx++)
620 	{
621 		if (testParams[paramIdx].initializationSource == INITIALIZATION_SOURCE_GLOBAL)
622 			continue;
623 
624 		GraphicsResources	resources;
625 		vector<float>		expectedOutput	(testParams[paramIdx].numComponents, 1.0f);
626 
627 		resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(expectedOutput)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
628 
629 		{
630 			const InstanceContext& instanceContext = createInstanceContext(pipelineStages,
631 																		   defaultColors,
632 																		   defaultColors,
633 																		   noFragments,
634 																		   specConstantMap,
635 																		   noPushConstants,
636 																		   resources,
637 																		   noInterfaces,
638 																		   extensions,
639 																		   requiredFeatures,
640 																		   VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
641 																		   QP_TEST_RESULT_FAIL,
642 																		   string());
643 			const ShaderParams		shaderParams	=
644 			{
645 				instanceContext,
646 				testParams[paramIdx].type
647 			};
648 
649 			addFunctionCaseWithPrograms<ShaderParams>(outputGroup,
650 													  testParams[paramIdx].name.c_str(),
651 													  "",
652 													  addShaderCodeOutput,
653 													  outputTest,
654 													  shaderParams);
655 		}
656 	}
657 }
658 
659 } // anonymous
660 
createVariableInitComputeGroup(tcu::TestContext & testCtx)661 tcu::TestCaseGroup* createVariableInitComputeGroup (tcu::TestContext& testCtx)
662 {
663 	de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "variable_init", "Compute tests for OpVariable initialization."));
664 	addComputeVariableInitPrivateTest(group.get());
665 
666 	return group.release();
667 }
668 
createVariableInitGraphicsGroup(tcu::TestContext & testCtx)669 tcu::TestCaseGroup* createVariableInitGraphicsGroup (tcu::TestContext& testCtx)
670 {
671 	de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "variable_init", "Graphics tests for OpVariable initialization."));
672 	addGraphicsVariableInitPrivateTest(group.get());
673 	addGraphicsVariableInitOutputTest(group.get());
674 
675 	return group.release();
676 }
677 
678 } // SpirVAssembly
679 } // vkt
680