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