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