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 pointers as function parameters.
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktSpvAsmPointerParameterTests.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::Vec4;
40 using tcu::RGBA;
41
42 namespace
43 {
44
addComputePointerParamToParamTest(tcu::TestCaseGroup * group)45 void addComputePointerParamToParamTest (tcu::TestCaseGroup* group)
46 {
47 tcu::TestContext& testCtx = group->getTestContext();
48 const int numFloats = 128;
49 ComputeShaderSpec spec;
50 vector<float> expectedOutput;
51
52 // Implements the following pseudo GLSL shader:
53 //
54 // float func(alias float* f, alias float* g)
55 // {
56 // *g = 5.0;
57 // *f = 2.0;
58 // return *g;
59 // }
60 //
61 // void main()
62 // {
63 // float a = 0.0;
64 // o = func(&a, &a); // should return 2.0
65 // float b = 0.0;
66 // o += func(&a, &b); // should return 5.0
67 // }
68 const string shaderSource =
69 " OpCapability Shader\n"
70 " %1 = OpExtInstImport \"GLSL.std.450\"\n"
71 " OpMemoryModel Logical GLSL450\n"
72 " OpEntryPoint GLCompute %main \"main\" %gl_GlobalInvocationID\n"
73 " OpExecutionMode %main LocalSize 1 1 1\n"
74 " OpSource GLSL 430\n"
75 " OpDecorate %_arr_float_uint_128 ArrayStride 4\n"
76 " OpMemberDecorate %Output 0 Offset 0\n"
77 " OpDecorate %Output BufferBlock\n"
78 " OpDecorate %dataOutput DescriptorSet 0\n"
79 " OpDecorate %dataOutput Binding 0\n"
80 " OpDecorate %f Aliased\n"
81 " OpDecorate %g Aliased\n"
82 " OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId\n"
83 " %void = OpTypeVoid\n"
84 " %void_func = OpTypeFunction %void\n"
85 " %float = OpTypeFloat 32\n"
86 " %_ptr_Function_float = OpTypePointer Function %float\n"
87 " %func0_decl = OpTypeFunction %float %_ptr_Function_float %_ptr_Function_float\n"
88 " %float_0 = OpConstant %float 0\n"
89 " %float_5 = OpConstant %float 5\n"
90 " %float_2 = OpConstant %float 2\n"
91 " %uint = OpTypeInt 32 0\n"
92 " %uint_128 = OpConstant %uint 128\n"
93 " %_arr_float_uint_128 = OpTypeArray %float %uint_128\n"
94 " %Output = OpTypeStruct %_arr_float_uint_128\n"
95 " %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
96 " %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n"
97 " %int = OpTypeInt 32 1\n"
98 " %int_0 = OpConstant %int 0\n"
99 " %v3uint = OpTypeVector %uint 3\n"
100 " %_ptr_Input_v3uint = OpTypePointer Input %v3uint\n"
101 " %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input\n"
102 " %uint_0 = OpConstant %uint 0\n"
103 " %_ptr_Input_uint = OpTypePointer Input %uint\n"
104 " %_ptr_Uniform_float = OpTypePointer Uniform %float\n"
105 " %main = OpFunction %void None %void_func\n"
106 " %entry = OpLabel\n"
107 " %a = OpVariable %_ptr_Function_float Function %float_0\n"
108 " %b = OpVariable %_ptr_Function_float Function %float_0\n"
109 " %o = OpVariable %_ptr_Function_float Function %float_0\n"
110 " %ret0 = OpFunctionCall %float %func %a %a\n"
111 " OpStore %o %ret0\n"
112 " %ret1 = OpFunctionCall %float %func %a %b\n"
113 " %o_val = OpLoad %float %o\n"
114 " %sum = OpFAdd %float %o_val %ret1\n"
115 " %inv_id_ptr = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %uint_0\n"
116 " %inv_id = OpLoad %uint %inv_id_ptr\n"
117 " %out_ptr = OpAccessChain %_ptr_Uniform_float %dataOutput %int_0 %inv_id\n"
118 " OpStore %out_ptr %sum\n"
119 " OpReturn\n"
120 " OpFunctionEnd\n"
121 " %func = OpFunction %float None %func0_decl\n"
122 " %f = OpFunctionParameter %_ptr_Function_float\n"
123 " %g = OpFunctionParameter %_ptr_Function_float\n"
124 " %func_entry = OpLabel\n"
125 " OpStore %g %float_5\n"
126 " OpStore %f %float_2\n"
127 " %ret = OpLoad %float %g\n"
128 " OpReturnValue %ret\n"
129 " OpFunctionEnd\n";
130
131 expectedOutput.reserve(numFloats);
132 for (deUint32 numIdx = 0; numIdx < numFloats; ++numIdx)
133 expectedOutput.push_back(7.0f);
134
135 spec.outputs.push_back(BufferSp(new Float32Buffer(expectedOutput)));
136
137 spec.assembly = shaderSource;
138 spec.numWorkGroups = IVec3(numFloats, 1, 1);
139
140 group->addChild(new SpvAsmComputeShaderCase(testCtx, "param_to_param", "", spec));
141 }
142
addComputePointerParamToGlobalTest(tcu::TestCaseGroup * group)143 void addComputePointerParamToGlobalTest (tcu::TestCaseGroup* group)
144 {
145 tcu::TestContext& testCtx = group->getTestContext();
146 const int numFloats = 128;
147 ComputeShaderSpec spec;
148 vector<float> expectedOutput;
149
150 // Implements the following pseudo GLSL shader:
151 //
152 // alias float a = 0.0;
153 //
154 // float func0(alias float* f0) // f in Private storage class
155 // {
156 // *a = 5.0;
157 // *f0 = 2.0;
158 // return *a;
159 // }
160 //
161 // float func1(alias float* f1) // f in Function storage class
162 // {
163 // *a = 5.0;
164 // *f1 = 2.0;
165 // return *a;
166 // }
167 //
168 // void main()
169 // {
170 // o = func0(&a); // should return 2.0
171 // float b = 0.0;
172 // o += func1(&b); // should return 5.0
173 // }
174 const string shaderSource =
175 " OpCapability Shader\n"
176 " %1 = OpExtInstImport \"GLSL.std.450\"\n"
177 " OpMemoryModel Logical GLSL450\n"
178 " OpEntryPoint GLCompute %main \"main\" %gl_GlobalInvocationID\n"
179 " OpExecutionMode %main LocalSize 1 1 1\n"
180 " OpSource GLSL 430\n"
181 " OpDecorate %_arr_float_uint_128 ArrayStride 4\n"
182 " OpMemberDecorate %Output 0 Offset 0\n"
183 " OpDecorate %Output BufferBlock\n"
184 " OpDecorate %dataOutput DescriptorSet 0\n"
185 " OpDecorate %dataOutput Binding 0\n"
186 " OpDecorate %f0 Aliased\n"
187 " OpDecorate %f1 Aliased\n"
188 " OpDecorate %a Aliased\n"
189 " OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId\n"
190 " %void = OpTypeVoid\n"
191 " %void_func = OpTypeFunction %void\n"
192 " %float = OpTypeFloat 32\n"
193 " %_ptr_Function_float = OpTypePointer Function %float\n"
194 " %_ptr_Private_float = OpTypePointer Private %float\n"
195 " %func0_decl = OpTypeFunction %float %_ptr_Private_float\n"
196 " %func1_decl = OpTypeFunction %float %_ptr_Function_float\n"
197 " %float_0 = OpConstant %float 0\n"
198 " %float_5 = OpConstant %float 5\n"
199 " %float_2 = OpConstant %float 2\n"
200 " %uint = OpTypeInt 32 0\n"
201 " %uint_128 = OpConstant %uint 128\n"
202 " %_arr_float_uint_128 = OpTypeArray %float %uint_128\n"
203 " %Output = OpTypeStruct %_arr_float_uint_128\n"
204 " %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
205 " %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n"
206 " %int = OpTypeInt 32 1\n"
207 " %int_0 = OpConstant %int 0\n"
208 " %v3uint = OpTypeVector %uint 3\n"
209 " %_ptr_Input_v3uint = OpTypePointer Input %v3uint\n"
210 " %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input\n"
211 " %uint_0 = OpConstant %uint 0\n"
212 " %_ptr_Input_uint = OpTypePointer Input %uint\n"
213 " %_ptr_Uniform_float = OpTypePointer Uniform %float\n"
214 " %a = OpVariable %_ptr_Private_float Private %float_0\n"
215 " %main = OpFunction %void None %void_func\n"
216 " %entry = OpLabel\n"
217 " %b = OpVariable %_ptr_Function_float Function %float_0\n"
218 " %o = OpVariable %_ptr_Function_float Function %float_0\n"
219 " %ret0 = OpFunctionCall %float %func0 %a\n"
220 " OpStore %o %ret0\n"
221 " %ret1 = OpFunctionCall %float %func1 %b\n"
222 " %o_val = OpLoad %float %o\n"
223 " %sum = OpFAdd %float %o_val %ret1\n"
224 " %inv_id_ptr = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %uint_0\n"
225 " %inv_id = OpLoad %uint %inv_id_ptr\n"
226 " %out_ptr = OpAccessChain %_ptr_Uniform_float %dataOutput %int_0 %inv_id\n"
227 " OpStore %out_ptr %sum\n"
228 " OpReturn\n"
229 " OpFunctionEnd\n"
230 " %func0 = OpFunction %float None %func0_decl\n"
231 " %f0 = OpFunctionParameter %_ptr_Private_float\n"
232 " %func0_entry = OpLabel\n"
233 " OpStore %a %float_5\n"
234 " OpStore %f0 %float_2\n"
235 " %func0_ret = OpLoad %float %a\n"
236 " OpReturnValue %func0_ret\n"
237 " OpFunctionEnd\n"
238 " %func1 = OpFunction %float None %func1_decl\n"
239 " %f1 = OpFunctionParameter %_ptr_Function_float\n"
240 " %func1_entry = OpLabel\n"
241 " OpStore %a %float_5\n"
242 " OpStore %f1 %float_2\n"
243 " %func1_ret = OpLoad %float %a\n"
244 " OpReturnValue %func1_ret\n"
245 " OpFunctionEnd\n";
246
247 expectedOutput.reserve(numFloats);
248 for (deUint32 numIdx = 0; numIdx < numFloats; ++numIdx)
249 expectedOutput.push_back(7.0f);
250
251 spec.outputs.push_back(BufferSp(new Float32Buffer(expectedOutput)));
252
253 spec.assembly = shaderSource;
254 spec.numWorkGroups = IVec3(numFloats, 1, 1);
255
256 group->addChild(new SpvAsmComputeShaderCase(testCtx, "param_to_global", "", spec));
257 }
258
addComputePointerBufferMemoryTest(tcu::TestCaseGroup * group)259 void addComputePointerBufferMemoryTest (tcu::TestCaseGroup* group)
260 {
261 tcu::TestContext& testCtx = group->getTestContext();
262 const int numFloats = 128;
263 ComputeShaderSpec spec;
264 vector<float> expectedOutput;
265 VulkanFeatures requiredFeatures;
266
267 // Implements the following pseudo GLSL shader:
268 //
269 // layout (binding = 0) buffer Output
270 // {
271 // vec4 arr0[16];
272 // vec4 arr1[];
273 // } dataOutput;
274 //
275 // void func0(vec4* f0[16], uint i)
276 // {
277 // f0[i] = vec4(5.0);
278 // }
279 //
280 // void func1(vec4* f1[], uint i)
281 // {
282 // f1[i] = vec4(2.0);
283 // }
284 //
285 // void main()
286 // {
287 // uint idx = gl_GlobalInvocationID.x;
288 // func0(dataOutput.arr0, idx);
289 // func1(dataOutput.arr1, idx);
290 // }
291 const string shaderSource =
292 " OpCapability Shader\n"
293 " OpCapability VariablePointersStorageBuffer\n"
294 " OpExtension \"SPV_KHR_storage_buffer_storage_class\"\n"
295 " OpExtension \"SPV_KHR_variable_pointers\"\n"
296 " %1 = OpExtInstImport \"GLSL.std.450\"\n"
297 " OpMemoryModel Logical GLSL450\n"
298 " OpEntryPoint GLCompute %main \"main\" %gl_GlobalInvocationID\n"
299 " OpExecutionMode %main LocalSize 1 1 1\n"
300 " OpSource GLSL 430\n"
301 " OpMemberDecorate %Output 0 Offset 0\n"
302 " OpMemberDecorate %Output 1 Offset 256\n"
303 " OpDecorate %arr_vec4_16 ArrayStride 16\n"
304 " OpDecorate %arr_vec4_rt ArrayStride 16\n"
305 " OpDecorate %Output Block\n"
306 " OpDecorate %dataOutput DescriptorSet 0\n"
307 " OpDecorate %dataOutput Binding 0\n"
308 " OpDecorate %f0 DescriptorSet 0\n"
309 " OpDecorate %f0 Binding 0\n"
310 " OpDecorate %f1 DescriptorSet 0\n"
311 " OpDecorate %f1 Binding 0\n"
312 " OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId\n"
313 " %void = OpTypeVoid\n"
314 " %void_func = OpTypeFunction %void\n"
315 " %float = OpTypeFloat 32\n"
316 " %_ptr_Function_float = OpTypePointer Function %float\n"
317 " %float_5 = OpConstant %float 5\n"
318 " %float_2 = OpConstant %float 2\n"
319 " %uint = OpTypeInt 32 0\n"
320 " %_ptr_Function_uint = OpTypePointer Function %uint\n"
321 " %uint_16 = OpConstant %uint 16\n"
322 " %vec4 = OpTypeVector %float 4\n"
323 " %vec4_5 = OpConstantComposite %vec4 %float_5 %float_5 %float_5 %float_5\n"
324 " %vec4_2 = OpConstantComposite %vec4 %float_2 %float_2 %float_2 %float_2\n"
325 " %arr_vec4_16 = OpTypeArray %vec4 %uint_16\n"
326 " %arr_vec4_rt = OpTypeRuntimeArray %vec4\n"
327 " %arr_vec4_16_ptr = OpTypePointer StorageBuffer %arr_vec4_16\n"
328 " %arr_vec4_rt_ptr = OpTypePointer StorageBuffer %arr_vec4_rt\n"
329 " %func0_decl = OpTypeFunction %void %arr_vec4_16_ptr %_ptr_Function_uint\n"
330 " %func1_decl = OpTypeFunction %void %arr_vec4_rt_ptr %_ptr_Function_uint\n"
331 " %Output = OpTypeStruct %arr_vec4_16 %arr_vec4_rt\n"
332 " %_ptr_sb_Output = OpTypePointer StorageBuffer %Output\n"
333 " %dataOutput = OpVariable %_ptr_sb_Output StorageBuffer\n"
334 " %int = OpTypeInt 32 1\n"
335 " %int_0 = OpConstant %int 0\n"
336 " %int_1 = OpConstant %int 1\n"
337 " %v3uint = OpTypeVector %uint 3\n"
338 " %_ptr_Input_v3uint = OpTypePointer Input %v3uint\n"
339 " %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input\n"
340 " %uint_0 = OpConstant %uint 0\n"
341 " %_ptr_Input_uint = OpTypePointer Input %uint\n"
342 " %_ptr_sb_vec4 = OpTypePointer StorageBuffer %vec4\n"
343 " %main = OpFunction %void None %void_func\n"
344 " %entry = OpLabel\n"
345 " %idx = OpVariable %_ptr_Function_uint Function\n"
346 " %inv_id_ptr = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %uint_0\n"
347 " %inv_id = OpLoad %uint %inv_id_ptr\n"
348 " OpStore %idx %inv_id\n"
349 " %ptr0 = OpAccessChain %arr_vec4_16_ptr %dataOutput %int_0\n"
350 " %ptr1 = OpAccessChain %arr_vec4_rt_ptr %dataOutput %int_1\n"
351 " %ret0 = OpFunctionCall %void %func0 %ptr0 %idx\n"
352 " %ret1 = OpFunctionCall %void %func1 %ptr1 %idx\n"
353 " OpReturn\n"
354 " OpFunctionEnd\n"
355 " %func0 = OpFunction %void None %func0_decl\n"
356 " %f0 = OpFunctionParameter %arr_vec4_16_ptr\n"
357 " %i0 = OpFunctionParameter %_ptr_Function_uint\n"
358 " %func0_entry = OpLabel\n"
359 " %idx0 = OpLoad %uint %i0\n"
360 " %out_ptr0 = OpAccessChain %_ptr_sb_vec4 %f0 %idx0\n"
361 " OpStore %out_ptr0 %vec4_5\n"
362 " OpReturn\n"
363 " OpFunctionEnd\n"
364 " %func1 = OpFunction %void None %func1_decl\n"
365 " %f1 = OpFunctionParameter %arr_vec4_rt_ptr\n"
366 " %i1 = OpFunctionParameter %_ptr_Function_uint\n"
367 " %func1_entry = OpLabel\n"
368 " %idx1 = OpLoad %uint %i1\n"
369 " %out_ptr1 = OpAccessChain %_ptr_sb_vec4 %f1 %idx1\n"
370 " OpStore %out_ptr1 %vec4_2\n"
371 " OpReturn\n"
372 " OpFunctionEnd\n";
373
374 expectedOutput.reserve(numFloats);
375 for (deUint32 numIdx = 0; numIdx < numFloats / 2; ++numIdx)
376 expectedOutput.push_back(5.0f);
377 for (deUint32 numIdx = 0; numIdx < numFloats / 2; ++numIdx)
378 expectedOutput.push_back(2.0f);
379
380 requiredFeatures.extVariablePointers = EXTVARIABLEPOINTERSFEATURES_VARIABLE_POINTERS_STORAGEBUFFER;
381
382 spec.outputs.push_back(BufferSp(new Float32Buffer(expectedOutput)));
383
384 spec.assembly = shaderSource;
385 spec.numWorkGroups = IVec3(16, 1, 1);
386 spec.requestedVulkanFeatures = requiredFeatures;
387 spec.extensions.push_back("VK_KHR_variable_pointers");
388
389 group->addChild(new SpvAsmComputeShaderCase(testCtx, "buffer_memory", "", spec));
390 }
391
addComputePointerBufferMemoryVariablePointersTest(tcu::TestCaseGroup * group)392 void addComputePointerBufferMemoryVariablePointersTest (tcu::TestCaseGroup* group)
393 {
394 tcu::TestContext& testCtx = group->getTestContext();
395 const int numFloats = 128;
396 ComputeShaderSpec spec;
397 VulkanFeatures requiredFeatures;
398 vector<float> expectedOutput;
399
400 // Implements the following pseudo GLSL shader:
401 //
402 // layout (binding = 0) buffer Output
403 // {
404 // vec4 arr0[16];
405 // vec4 arr1[];
406 // } dataOutput;
407 //
408 // void func0(vec4* f0[16], uint i)
409 // {
410 // f0[i] = vec4(5.0);
411 // }
412 //
413 // void func1(vec4* f1[], uint i)
414 // {
415 // f1[i] = vec4(2.0);
416 // }
417 //
418 // void main()
419 // {
420 // uint idx = gl_GlobalInvocationID.x;
421 // func0(dataOutput.arr0, idx);
422 // func1(dataOutput.arr1, idx);
423 // }
424 const string shaderSource =
425 " OpCapability Shader\n"
426 " OpCapability VariablePointersStorageBuffer\n"
427 " OpExtension \"SPV_KHR_variable_pointers\"\n"
428 " OpExtension \"SPV_KHR_storage_buffer_storage_class\"\n"
429 " %1 = OpExtInstImport \"GLSL.std.450\"\n"
430 " OpMemoryModel Logical GLSL450\n"
431 " OpEntryPoint GLCompute %main \"main\" %gl_GlobalInvocationID\n"
432 " OpExecutionMode %main LocalSize 1 1 1\n"
433 " OpSource GLSL 430\n"
434 " OpMemberDecorate %Output 0 Offset 0\n"
435 " OpMemberDecorate %Output 1 Offset 256\n"
436 " OpDecorate %arr_vec4_16 ArrayStride 16\n"
437 " OpDecorate %arr_vec4_rt ArrayStride 16\n"
438 " OpDecorate %Output Block\n"
439 " OpDecorate %dataOutput DescriptorSet 0\n"
440 " OpDecorate %dataOutput Binding 0\n"
441 " OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId\n"
442 " %void = OpTypeVoid\n"
443 " %void_func = OpTypeFunction %void\n"
444 " %float = OpTypeFloat 32\n"
445 " %_ptr_Function_float = OpTypePointer Function %float\n"
446 " %float_5 = OpConstant %float 5\n"
447 " %float_2 = OpConstant %float 2\n"
448 " %uint = OpTypeInt 32 0\n"
449 " %_ptr_Function_uint = OpTypePointer Function %uint\n"
450 " %uint_16 = OpConstant %uint 16\n"
451 " %vec4 = OpTypeVector %float 4\n"
452 " %vec4_5 = OpConstantComposite %vec4 %float_5 %float_5 %float_5 %float_5\n"
453 " %vec4_2 = OpConstantComposite %vec4 %float_2 %float_2 %float_2 %float_2\n"
454 " %arr_vec4_16 = OpTypeArray %vec4 %uint_16\n"
455 " %arr_vec4_rt = OpTypeRuntimeArray %vec4\n"
456 " %arr_vec4_16_ptr = OpTypePointer StorageBuffer %arr_vec4_16\n"
457 " %arr_vec4_rt_ptr = OpTypePointer StorageBuffer %arr_vec4_rt\n"
458 " %func0_decl = OpTypeFunction %void %arr_vec4_16_ptr %_ptr_Function_uint\n"
459 " %func1_decl = OpTypeFunction %void %arr_vec4_rt_ptr %_ptr_Function_uint\n"
460 " %Output = OpTypeStruct %arr_vec4_16 %arr_vec4_rt\n"
461 " %_ptr_sb_Output = OpTypePointer StorageBuffer %Output\n"
462 " %dataOutput = OpVariable %_ptr_sb_Output StorageBuffer\n"
463 " %int = OpTypeInt 32 1\n"
464 " %int_0 = OpConstant %int 0\n"
465 " %int_1 = OpConstant %int 1\n"
466 " %v3uint = OpTypeVector %uint 3\n"
467 " %_ptr_Input_v3uint = OpTypePointer Input %v3uint\n"
468 " %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input\n"
469 " %uint_0 = OpConstant %uint 0\n"
470 " %_ptr_Input_uint = OpTypePointer Input %uint\n"
471 " %_ptr_sb_vec4 = OpTypePointer StorageBuffer %vec4\n"
472 " %main = OpFunction %void None %void_func\n"
473 " %entry = OpLabel\n"
474 " %idx = OpVariable %_ptr_Function_uint Function\n"
475 " %inv_id_ptr = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %uint_0\n"
476 " %inv_id = OpLoad %uint %inv_id_ptr\n"
477 " OpStore %idx %inv_id\n"
478 " %ptr0 = OpAccessChain %arr_vec4_16_ptr %dataOutput %int_0\n"
479 " %ptr1 = OpAccessChain %arr_vec4_rt_ptr %dataOutput %int_1\n"
480 " %ret0 = OpFunctionCall %void %func0 %ptr0 %idx\n"
481 " %ret1 = OpFunctionCall %void %func1 %ptr1 %idx\n"
482 " OpReturn\n"
483 " OpFunctionEnd\n"
484 " %func0 = OpFunction %void None %func0_decl\n"
485 " %f0 = OpFunctionParameter %arr_vec4_16_ptr\n"
486 " %i0 = OpFunctionParameter %_ptr_Function_uint\n"
487 " %func0_entry = OpLabel\n"
488 " %idx0 = OpLoad %uint %i0\n"
489 " %out_ptr0 = OpAccessChain %_ptr_sb_vec4 %f0 %idx0\n"
490 " OpStore %out_ptr0 %vec4_5\n"
491 " OpReturn\n"
492 " OpFunctionEnd\n"
493 " %func1 = OpFunction %void None %func1_decl\n"
494 " %f1 = OpFunctionParameter %arr_vec4_rt_ptr\n"
495 " %i1 = OpFunctionParameter %_ptr_Function_uint\n"
496 " %func1_entry = OpLabel\n"
497 " %idx1 = OpLoad %uint %i1\n"
498 " %out_ptr1 = OpAccessChain %_ptr_sb_vec4 %f1 %idx1\n"
499 " OpStore %out_ptr1 %vec4_2\n"
500 " OpReturn\n"
501 " OpFunctionEnd\n";
502
503 expectedOutput.reserve(numFloats);
504 for (deUint32 numIdx = 0; numIdx < numFloats / 2; ++numIdx)
505 expectedOutput.push_back(5.0f);
506 for (deUint32 numIdx = 0; numIdx < numFloats / 2; ++numIdx)
507 expectedOutput.push_back(2.0f);
508
509 requiredFeatures.extVariablePointers = EXTVARIABLEPOINTERSFEATURES_VARIABLE_POINTERS_STORAGEBUFFER;
510 spec.outputs.push_back(BufferSp(new Float32Buffer(expectedOutput)));
511 spec.extensions.push_back("VK_KHR_variable_pointers");
512
513 spec.assembly = shaderSource;
514 spec.numWorkGroups = IVec3(16, 1, 1);
515 spec.requestedVulkanFeatures = requiredFeatures;
516
517 group->addChild(new SpvAsmComputeShaderCase(testCtx, "buffer_memory_variable_pointers", "", spec));
518 }
519
addComputePointerWorkgroupMemoryVariablePointersTest(tcu::TestCaseGroup * group)520 void addComputePointerWorkgroupMemoryVariablePointersTest (tcu::TestCaseGroup* group)
521 {
522 tcu::TestContext& testCtx = group->getTestContext();
523 const int numFloats = 128;
524 ComputeShaderSpec spec;
525 VulkanFeatures requiredFeatures;
526 vector<float> expectedOutput;
527
528 // Implements the following pseudo GLSL shader:
529 //
530 // layout (local_size_x = 16, local_size_y = 1, local_size_z = 1) in;
531 //
532 // layout (binding = 0) buffer Output
533 // {
534 // vec4 arr0[16];
535 // vec4 arr1[];
536 // } dataOutput;
537 //
538 // shared struct
539 // {
540 // vec4 arr0[16];
541 // vec4 arr1[16];
542 // } sharedData;
543 //
544 // void func0(vec4* f0[16], uint i)
545 // {
546 // f0[i] = vec4(i);
547 // }
548 //
549 // void func1(vec4* f1[16], uint i)
550 // {
551 // f1[i] = vec4(i+5);
552 // }
553 //
554 // void main()
555 // {
556 // uint idx = gl_LocalInvocationID.x;
557 // func0(sharedData.arr0, idx);
558 // func1(sharedData.arr1, idx);
559 // barier();
560 // dataOutput.arr0[idx] = sharedData.arr1[(idx+1) % 16];
561 // dataOutput.arr1[idx] = sharedData.arr0[(idx+1) % 16];
562 // }
563 const string shaderSource =
564 " OpCapability Shader\n"
565 " OpCapability VariablePointers\n"
566 " OpExtension \"SPV_KHR_variable_pointers\"\n"
567 " OpExtension \"SPV_KHR_storage_buffer_storage_class\"\n"
568 " %1 = OpExtInstImport \"GLSL.std.450\"\n"
569 " OpMemoryModel Logical GLSL450\n"
570 " OpEntryPoint GLCompute %main \"main\" %gl_LocalInvocationID\n"
571 " OpExecutionMode %main LocalSize 16 1 1\n"
572 " OpSource GLSL 430\n"
573 " OpMemberDecorate %Output 0 Offset 0\n"
574 " OpMemberDecorate %Output 1 Offset 256\n"
575 " OpMemberDecorate %struct 0 Offset 0\n"
576 " OpMemberDecorate %struct 1 Offset 256\n"
577 " OpDecorate %arr_vec4_16 ArrayStride 16\n"
578 " OpDecorate %arr_vec4_rt ArrayStride 16\n"
579 " OpDecorate %Output Block\n"
580 " OpDecorate %dataOutput DescriptorSet 0\n"
581 " OpDecorate %dataOutput Binding 0\n"
582 " OpDecorate %gl_LocalInvocationID BuiltIn LocalInvocationId\n"
583 " %void = OpTypeVoid\n"
584 " %void_func = OpTypeFunction %void\n"
585 " %float = OpTypeFloat 32\n"
586 " %_ptr_Function_float = OpTypePointer Function %float\n"
587 " %uint = OpTypeInt 32 0\n"
588 " %_ptr_Function_uint = OpTypePointer Function %uint\n"
589 " %uint_1 = OpConstant %uint 1\n"
590 " %uint_2 = OpConstant %uint 2\n"
591 " %uint_5 = OpConstant %uint 5\n"
592 " %uint_16 = OpConstant %uint 16\n"
593 " %uint_264 = OpConstant %uint 264\n"
594 " %vec4 = OpTypeVector %float 4\n"
595 " %arr_vec4_16 = OpTypeArray %vec4 %uint_16\n"
596 " %arr_vec4_rt = OpTypeRuntimeArray %vec4\n"
597 " %arr_vec4_16_sb_ptr = OpTypePointer StorageBuffer %arr_vec4_16\n"
598 " %arr_vec4_rt_sb_ptr = OpTypePointer StorageBuffer %arr_vec4_rt\n"
599 " %arr_vec4_16_wg_ptr = OpTypePointer Workgroup %arr_vec4_16\n"
600 " %func_decl = OpTypeFunction %void %arr_vec4_16_wg_ptr %_ptr_Function_uint\n"
601 " %Output = OpTypeStruct %arr_vec4_16 %arr_vec4_rt\n"
602 " %struct = OpTypeStruct %arr_vec4_16 %arr_vec4_16\n"
603 " %_ptr_sb_struct = OpTypePointer StorageBuffer %Output\n"
604 " %_ptr_wg_struct = OpTypePointer Workgroup %struct\n"
605 " %dataOutput = OpVariable %_ptr_sb_struct StorageBuffer\n"
606 " %sharedData = OpVariable %_ptr_wg_struct Workgroup\n"
607 " %int = OpTypeInt 32 1\n"
608 " %int_0 = OpConstant %int 0\n"
609 " %int_1 = OpConstant %int 1\n"
610 " %v3uint = OpTypeVector %uint 3\n"
611 " %_ptr_Input_v3uint = OpTypePointer Input %v3uint\n"
612 " %gl_LocalInvocationID = OpVariable %_ptr_Input_v3uint Input\n"
613 " %uint_0 = OpConstant %uint 0\n"
614 " %_ptr_Input_uint = OpTypePointer Input %uint\n"
615 " %_ptr_sb_vec4 = OpTypePointer StorageBuffer %vec4\n"
616 " %_ptr_wg_vec4 = OpTypePointer Workgroup %vec4\n"
617 " %main = OpFunction %void None %void_func\n"
618 " %entry = OpLabel\n"
619 " %idx = OpVariable %_ptr_Function_uint Function\n"
620 " %inv_id_ptr = OpAccessChain %_ptr_Input_uint %gl_LocalInvocationID %uint_0\n"
621 " %inv_id = OpLoad %uint %inv_id_ptr\n"
622 " OpStore %idx %inv_id\n"
623 " %ptr0 = OpAccessChain %arr_vec4_16_wg_ptr %sharedData %int_0\n"
624 " %ptr1 = OpAccessChain %arr_vec4_16_wg_ptr %sharedData %int_1\n"
625 " %ret0 = OpFunctionCall %void %func0 %ptr0 %idx\n"
626 " %ret1 = OpFunctionCall %void %func1 %ptr1 %idx\n"
627 " OpControlBarrier %uint_2 %uint_2 %uint_264\n"
628 " %inv_id_plus1 = OpIAdd %uint %inv_id %uint_1\n"
629 " %inv_id_mod = OpUMod %uint %inv_id_plus1 %uint_16\n"
630 " %shared_arr1_ptr = OpAccessChain %_ptr_wg_vec4 %sharedData %int_1 %inv_id_mod\n"
631 " %shared_arr1_data = OpLoad %vec4 %shared_arr1_ptr\n"
632 " %outPtr0 = OpAccessChain %_ptr_sb_vec4 %dataOutput %int_0 %inv_id\n"
633 " OpStore %outPtr0 %shared_arr1_data\n"
634 " %shared_arr0_ptr = OpAccessChain %_ptr_wg_vec4 %sharedData %int_0 %inv_id_mod\n"
635 " %shared_arr0_data = OpLoad %vec4 %shared_arr0_ptr\n"
636 " %outPtr1 = OpAccessChain %_ptr_sb_vec4 %dataOutput %int_1 %inv_id\n"
637 " OpStore %outPtr1 %shared_arr0_data\n"
638 " OpReturn\n"
639 " OpFunctionEnd\n"
640 " %func0 = OpFunction %void None %func_decl\n"
641 " %f0 = OpFunctionParameter %arr_vec4_16_wg_ptr\n"
642 " %i0 = OpFunctionParameter %_ptr_Function_uint\n"
643 " %func0_entry = OpLabel\n"
644 " %idx0 = OpLoad %uint %i0\n"
645 " %out_ptr0 = OpAccessChain %_ptr_wg_vec4 %f0 %idx0\n"
646 " %idxFloat0 = OpConvertUToF %float %idx0\n"
647 " %outData0 = OpCompositeConstruct %vec4 %idxFloat0 %idxFloat0 %idxFloat0 %idxFloat0\n"
648 " OpStore %out_ptr0 %outData0\n"
649 " OpReturn\n"
650 " OpFunctionEnd\n"
651 " %func1 = OpFunction %void None %func_decl\n"
652 " %f1 = OpFunctionParameter %arr_vec4_16_wg_ptr\n"
653 " %i1 = OpFunctionParameter %_ptr_Function_uint\n"
654 " %func1_entry = OpLabel\n"
655 " %idx1 = OpLoad %uint %i1\n"
656 " %out_ptr1 = OpAccessChain %_ptr_wg_vec4 %f1 %idx1\n"
657 " %idxPlus5 = OpIAdd %uint %idx1 %uint_5\n"
658 " %idxFloat1 = OpConvertUToF %float %idxPlus5\n"
659 " %outData1 = OpCompositeConstruct %vec4 %idxFloat1 %idxFloat1 %idxFloat1 %idxFloat1\n"
660 " OpStore %out_ptr1 %outData1\n"
661 " OpReturn\n"
662 " OpFunctionEnd\n";
663
664 expectedOutput.reserve(numFloats);
665 for (deUint32 vecIdx = 0; vecIdx < numFloats / 8; ++vecIdx)
666 {
667 const deUint32 shuffleIdx = (vecIdx + 1) % 16;
668 const float val = (float)(shuffleIdx + 5);
669 for (deUint32 i = 0; i < 4; ++i)
670 expectedOutput.push_back(val);
671 }
672 for (deUint32 vecIdx = 0; vecIdx < numFloats / 8; ++vecIdx)
673 {
674 const deUint32 shuffleIdx = (vecIdx + 1) % 16;
675 const float val = (float)shuffleIdx;
676 for (deUint32 i = 0; i < 4; ++i)
677 expectedOutput.push_back(val);
678 }
679
680 spec.outputs.push_back(BufferSp(new Float32Buffer(expectedOutput)));
681 requiredFeatures.extVariablePointers = EXTVARIABLEPOINTERSFEATURES_VARIABLE_POINTERS;
682 spec.extensions.push_back("VK_KHR_variable_pointers");
683
684 spec.assembly = shaderSource;
685 spec.numWorkGroups = IVec3(1, 1, 1);
686 spec.requestedVulkanFeatures = requiredFeatures;
687
688 group->addChild(new SpvAsmComputeShaderCase(testCtx, "workgroup_memory_variable_pointers", "", spec));
689 }
690
addGraphicsPointerParamToParamTest(tcu::TestCaseGroup * group)691 void addGraphicsPointerParamToParamTest (tcu::TestCaseGroup* group)
692 {
693 map<string, string> fragments;
694 RGBA defaultColors[4];
695 GraphicsResources resources;
696 vector<string> extensions;
697 vector<float> expectedOutput;
698 VulkanFeatures requiredFeatures;
699
700 // Implements the following pseudo GLSL shader:
701 //
702 // float func(alias float* f, alias float* g)
703 // {
704 // *g = 5.0;
705 // *f = 2.0;
706 // return *g;
707 // }
708 //
709 // vec4 test_code(vec4 param)
710 // {
711 // float a = 0.0;
712 // o = func(&a, &a); // should return 2.0
713 // float b = 0.0;
714 // o += func(&a, &b); // should return 5.0
715 // return param;
716 // }
717 fragments["pre_main"] =
718 " %func0_decl = OpTypeFunction %f32 %fp_f32 %fp_f32\n"
719 " %c_f32_5 = OpConstant %f32 5\n"
720 " %c_f32_2 = OpConstant %f32 2\n"
721 " %Output = OpTypeStruct %f32\n"
722 " %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
723 " %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n"
724 " %_ptr_Uniform_f32 = OpTypePointer Uniform %f32\n"
725 " %func = OpFunction %f32 None %func0_decl\n"
726 " %f = OpFunctionParameter %fp_f32\n"
727 " %g = OpFunctionParameter %fp_f32\n"
728 " %func_entry = OpLabel\n"
729 " OpStore %g %c_f32_5\n"
730 " OpStore %f %c_f32_2\n"
731 " %ret = OpLoad %f32 %g\n"
732 " OpReturnValue %ret\n"
733 " OpFunctionEnd\n";
734
735 fragments["decoration"] =
736 " OpMemberDecorate %Output 0 Offset 0\n"
737 " OpDecorate %Output BufferBlock\n"
738 " OpDecorate %dataOutput DescriptorSet 0\n"
739 " OpDecorate %dataOutput Binding 0\n"
740 " OpDecorate %f Aliased\n"
741 " OpDecorate %g Aliased\n";
742
743 fragments["testfun"] =
744 " %test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
745 " %param = OpFunctionParameter %v4f32\n"
746 " %entry = OpLabel\n"
747 " %a = OpVariable %fp_f32 Function %c_f32_0\n"
748 " %b = OpVariable %fp_f32 Function %c_f32_0\n"
749 " %o = OpVariable %fp_f32 Function %c_f32_0\n"
750 " %ret0 = OpFunctionCall %f32 %func %a %a\n"
751 " OpStore %o %ret0\n"
752 " %ret1 = OpFunctionCall %f32 %func %a %b\n"
753 " %o_val = OpLoad %f32 %o\n"
754 " %sum = OpFAdd %f32 %o_val %ret1\n"
755 " %out_ptr = OpAccessChain %_ptr_Uniform_f32 %dataOutput %c_i32_0\n"
756 " OpStore %out_ptr %sum\n"
757 " OpReturnValue %param\n"
758 " OpFunctionEnd\n";
759
760 getDefaultColors(defaultColors);
761 expectedOutput.push_back(7.0f);
762 requiredFeatures.coreFeatures.vertexPipelineStoresAndAtomics = true;
763 requiredFeatures.coreFeatures.fragmentStoresAndAtomics = true;
764 resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(expectedOutput)), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
765
766 createTestsForAllStages("global_to_param", defaultColors, defaultColors, fragments, resources, extensions, group, requiredFeatures);
767 }
768
addGraphicsPointerParamToGlobalTest(tcu::TestCaseGroup * group)769 void addGraphicsPointerParamToGlobalTest (tcu::TestCaseGroup* group)
770 {
771 map<string, string> fragments;
772 RGBA defaultColors[4];
773 GraphicsResources resources;
774 vector<string> extensions;
775 vector<float> expectedOutput;
776 VulkanFeatures requiredFeatures;
777
778 // Implements the following pseudo GLSL shader:
779 //
780 // alias float a = 0.0;
781 //
782 // float func0(alias float* f0) // f in Private storage class
783 // {
784 // *a = 5.0;
785 // *f0 = 2.0;
786 // return *a;
787 // }
788 //
789 // float func1(alias float* f1) // f in Function storage class
790 // {
791 // *a = 5.0;
792 // *f1 = 2.0;
793 // return *a;
794 // }
795 //
796 // vec4 test_code(vec4 param)
797 // {
798 // o = func0(&a); // should return 2.0
799 // float b = 0.0;
800 // o += func1(&b); // should return 5.0
801 // return param;
802 // }
803 fragments["pre_main"] =
804 " %pp_f32 = OpTypePointer Private %f32\n"
805 " %func0_decl = OpTypeFunction %f32 %pp_f32\n"
806 " %func1_decl = OpTypeFunction %f32 %fp_f32\n"
807 " %c_f32_5 = OpConstant %f32 5\n"
808 " %c_f32_2 = OpConstant %f32 2\n"
809 " %Output = OpTypeStruct %f32\n"
810 " %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
811 " %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n"
812 " %_ptr_Uniform_f32 = OpTypePointer Uniform %f32\n"
813 " %a = OpVariable %pp_f32 Private %c_f32_0\n"
814 " %func0 = OpFunction %f32 None %func0_decl\n"
815 " %f0 = OpFunctionParameter %pp_f32\n"
816 " %func0_entry = OpLabel\n"
817 " OpStore %a %c_f32_5\n"
818 " OpStore %f0 %c_f32_2\n"
819 " %func0_ret = OpLoad %f32 %a\n"
820 " OpReturnValue %func0_ret\n"
821 " OpFunctionEnd\n"
822 " %func1 = OpFunction %f32 None %func1_decl\n"
823 " %f1 = OpFunctionParameter %fp_f32\n"
824 " %func1_entry = OpLabel\n"
825 " OpStore %a %c_f32_5\n"
826 " OpStore %f1 %c_f32_2\n"
827 " %func1_ret = OpLoad %f32 %a\n"
828 " OpReturnValue %func1_ret\n"
829 " OpFunctionEnd\n";
830
831 fragments["decoration"] =
832 " OpMemberDecorate %Output 0 Offset 0\n"
833 " OpDecorate %Output BufferBlock\n"
834 " OpDecorate %dataOutput DescriptorSet 0\n"
835 " OpDecorate %dataOutput Binding 0\n"
836 " OpDecorate %f0 Aliased\n"
837 " OpDecorate %f1 Aliased\n"
838 " OpDecorate %a Aliased\n";
839
840 fragments["testfun"] =
841 " %test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
842 " %param = OpFunctionParameter %v4f32\n"
843 " %entry = OpLabel\n"
844 " %b = OpVariable %fp_f32 Function %c_f32_0\n"
845 " %o = OpVariable %fp_f32 Function %c_f32_0\n"
846 " %ret0 = OpFunctionCall %f32 %func0 %a\n"
847 " OpStore %o %ret0\n"
848 " %ret1 = OpFunctionCall %f32 %func1 %b\n"
849 " %o_val = OpLoad %f32 %o\n"
850 " %sum = OpFAdd %f32 %o_val %ret1\n"
851 " %out_ptr = OpAccessChain %_ptr_Uniform_f32 %dataOutput %c_i32_0\n"
852 " OpStore %out_ptr %sum\n"
853 " OpReturnValue %param\n"
854 " OpFunctionEnd\n";
855
856 getDefaultColors(defaultColors);
857 expectedOutput.push_back(7.0f);
858 requiredFeatures.coreFeatures.vertexPipelineStoresAndAtomics = true;
859 requiredFeatures.coreFeatures.fragmentStoresAndAtomics = true;
860 resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(expectedOutput)), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
861
862 createTestsForAllStages("param_to_global", defaultColors, defaultColors, fragments, resources, extensions, group, requiredFeatures);
863 }
864
addGraphicsPointerBufferMemoryTest(tcu::TestCaseGroup * group)865 void addGraphicsPointerBufferMemoryTest (tcu::TestCaseGroup* group)
866 {
867 const int numFloats = 16;
868 map<string, string> fragments;
869 RGBA defaultColors[4];
870 GraphicsResources resources;
871 vector<string> extensions;
872 vector<float> expectedOutput;
873 VulkanFeatures requiredFeatures;
874
875 // Implements the following pseudo GLSL shader:
876 //
877 // layout (binding = 0) buffer Output
878 // {
879 // vec4 arr0[2];
880 // vec4 arr1[];
881 // } dataOutput;
882 //
883 // void func0(vec4* f0[2], uint i)
884 // {
885 // f0[i] = vec4(5.0);
886 // }
887 //
888 // void func1(vec4* f1[], uint i)
889 // {
890 // f1[i] = vec4(2.0);
891 // }
892 //
893 // vec4 test_code(vec4 param)
894 // {
895 // func0(dataOutput.arr0, idx);
896 // func1(dataOutput.arr1, idx);
897 // return param;
898 // }
899 fragments["pre_main"] =
900 " %arr_v4f32_2 = OpTypeArray %v4f32 %c_u32_2\n"
901 " %arr_v4f32_rt = OpTypeRuntimeArray %v4f32\n"
902 " %arr_v4f32_2_ptr = OpTypePointer StorageBuffer %arr_v4f32_2\n"
903 " %arr_v4f32_rt_ptr = OpTypePointer StorageBuffer %arr_v4f32_rt\n"
904 " %func0_decl = OpTypeFunction %void %arr_v4f32_2_ptr\n"
905 " %func1_decl = OpTypeFunction %void %arr_v4f32_rt_ptr\n"
906 " %c_f32_5 = OpConstant %f32 5\n"
907 " %c_f32_2 = OpConstant %f32 2\n"
908 " %c_v4f32_5 = OpConstantComposite %v4f32 %c_f32_5 %c_f32_5 %c_f32_5 %c_f32_5\n"
909 " %c_v4f32_2 = OpConstantComposite %v4f32 %c_f32_2 %c_f32_2 %c_f32_2 %c_f32_2\n"
910 " %Output = OpTypeStruct %arr_v4f32_2 %arr_v4f32_rt\n"
911 " %_ptr_sb_Output = OpTypePointer StorageBuffer %Output\n"
912 " %dataOutput = OpVariable %_ptr_sb_Output StorageBuffer\n"
913 " %_ptr_sb_v4f32 = OpTypePointer StorageBuffer %v4f32\n"
914 " %func0 = OpFunction %void None %func0_decl\n"
915 " %f0 = OpFunctionParameter %arr_v4f32_2_ptr\n"
916 " %func0Entry = OpLabel\n"
917 " %out_ptr0 = OpAccessChain %_ptr_sb_v4f32 %f0 %c_i32_0\n"
918 " OpStore %out_ptr0 %c_v4f32_5\n"
919 " %out_ptr1 = OpAccessChain %_ptr_sb_v4f32 %f0 %c_i32_1\n"
920 " OpStore %out_ptr1 %c_v4f32_5\n"
921 " OpReturn\n"
922 " OpFunctionEnd\n"
923 " %func1 = OpFunction %void None %func1_decl\n"
924 " %f1 = OpFunctionParameter %arr_v4f32_rt_ptr\n"
925 " %func1Entry = OpLabel\n"
926 " %out_ptr2 = OpAccessChain %_ptr_sb_v4f32 %f1 %c_i32_0\n"
927 " OpStore %out_ptr2 %c_v4f32_2\n"
928 " %out_ptr3 = OpAccessChain %_ptr_sb_v4f32 %f1 %c_i32_1\n"
929 " OpStore %out_ptr3 %c_v4f32_2\n"
930 " OpReturn\n"
931 " OpFunctionEnd\n";
932
933 fragments["decoration"] =
934 " OpMemberDecorate %Output 0 Offset 0\n"
935 " OpMemberDecorate %Output 1 Offset 32\n"
936 " OpDecorate %Output Block\n"
937 " OpDecorate %dataOutput DescriptorSet 0\n"
938 " OpDecorate %dataOutput Binding 0\n"
939 " OpDecorate %f0 DescriptorSet 0\n"
940 " OpDecorate %f0 Binding 0\n"
941 " OpDecorate %f1 DescriptorSet 0\n"
942 " OpDecorate %f1 Binding 0\n"
943 " OpDecorate %arr_v4f32_2 ArrayStride 16\n"
944 " OpDecorate %arr_v4f32_rt ArrayStride 16\n";
945
946 fragments["testfun"] =
947 " %test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
948 " %param = OpFunctionParameter %v4f32\n"
949 " %entry = OpLabel\n"
950 " %ptr0 = OpAccessChain %arr_v4f32_2_ptr %dataOutput %c_i32_0\n"
951 " %ptr1 = OpAccessChain %arr_v4f32_rt_ptr %dataOutput %c_i32_1\n"
952 " %ret0 = OpFunctionCall %void %func0 %ptr0\n"
953 " %ret1 = OpFunctionCall %void %func1 %ptr1\n"
954 " OpReturnValue %param\n"
955 " OpFunctionEnd\n";
956
957 fragments["extension"] =
958 "OpExtension \"SPV_KHR_storage_buffer_storage_class\"\n"
959 "OpExtension \"SPV_KHR_variable_pointers\"\n";
960
961 fragments["capability"] =
962 "OpCapability VariablePointersStorageBuffer\n";
963
964 getDefaultColors(defaultColors);
965
966 for (deUint32 numIdx = 0; numIdx < numFloats / 2; ++numIdx)
967 expectedOutput.push_back(5.0f);
968 for (deUint32 numIdx = 0; numIdx < numFloats / 2; ++numIdx)
969 expectedOutput.push_back(2.0f);
970
971 extensions.push_back("VK_KHR_variable_pointers");
972 requiredFeatures.coreFeatures.vertexPipelineStoresAndAtomics = true;
973 requiredFeatures.coreFeatures.fragmentStoresAndAtomics = true;
974 requiredFeatures.extVariablePointers = EXTVARIABLEPOINTERSFEATURES_VARIABLE_POINTERS_STORAGEBUFFER;
975 resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(expectedOutput)), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
976
977 createTestsForAllStages("buffer_memory", defaultColors, defaultColors, fragments, resources, extensions, group, requiredFeatures);
978 }
979
addGraphicsPointerBufferMemoryVariablePointersTest(tcu::TestCaseGroup * group)980 void addGraphicsPointerBufferMemoryVariablePointersTest (tcu::TestCaseGroup* group)
981 {
982 const int numFloats = 16;
983 map<string, string> fragments;
984 RGBA defaultColors[4];
985 GraphicsResources resources;
986 vector<string> extensions;
987 vector<float> expectedOutput;
988 VulkanFeatures requiredFeatures;
989
990 // Implements the following pseudo GLSL shader:
991 //
992 // layout (binding = 0) buffer Output
993 // {
994 // vec4 arr0[2];
995 // vec4 arr1[];
996 // } dataOutput;
997 //
998 // void func0(vec4* f0[2], uint i)
999 // {
1000 // f0[i] = vec4(5.0);
1001 // }
1002 //
1003 // void func1(vec4* f1[], uint i)
1004 // {
1005 // f1[i] = vec4(2.0);
1006 // }
1007 //
1008 // vec4 test_code(vec4 param)
1009 // {
1010 // func0(dataOutput.arr0, idx);
1011 // func1(dataOutput.arr1, idx);
1012 // return param;
1013 // }
1014 fragments["pre_main"] =
1015 " %arr_v4f32_2 = OpTypeArray %v4f32 %c_u32_2\n"
1016 " %arr_v4f32_rt = OpTypeRuntimeArray %v4f32\n"
1017 " %arr_v4f32_2_ptr = OpTypePointer StorageBuffer %arr_v4f32_2\n"
1018 " %arr_v4f32_rt_ptr = OpTypePointer StorageBuffer %arr_v4f32_rt\n"
1019 " %func0_decl = OpTypeFunction %void %arr_v4f32_2_ptr\n"
1020 " %func1_decl = OpTypeFunction %void %arr_v4f32_rt_ptr\n"
1021 " %c_f32_5 = OpConstant %f32 5\n"
1022 " %c_f32_2 = OpConstant %f32 2\n"
1023 " %c_v4f32_5 = OpConstantComposite %v4f32 %c_f32_5 %c_f32_5 %c_f32_5 %c_f32_5\n"
1024 " %c_v4f32_2 = OpConstantComposite %v4f32 %c_f32_2 %c_f32_2 %c_f32_2 %c_f32_2\n"
1025 " %Output = OpTypeStruct %arr_v4f32_2 %arr_v4f32_rt\n"
1026 " %_ptr_sb_Output = OpTypePointer StorageBuffer %Output\n"
1027 " %dataOutput = OpVariable %_ptr_sb_Output StorageBuffer\n"
1028 " %_ptr_sb_v4f32 = OpTypePointer StorageBuffer %v4f32\n"
1029 " %func0 = OpFunction %void None %func0_decl\n"
1030 " %f0 = OpFunctionParameter %arr_v4f32_2_ptr\n"
1031 " %func0Entry = OpLabel\n"
1032 " %out_ptr0 = OpAccessChain %_ptr_sb_v4f32 %f0 %c_i32_0\n"
1033 " OpStore %out_ptr0 %c_v4f32_5\n"
1034 " %out_ptr1 = OpAccessChain %_ptr_sb_v4f32 %f0 %c_i32_1\n"
1035 " OpStore %out_ptr1 %c_v4f32_5\n"
1036 " OpReturn\n"
1037 " OpFunctionEnd\n"
1038 " %func1 = OpFunction %void None %func1_decl\n"
1039 " %f1 = OpFunctionParameter %arr_v4f32_rt_ptr\n"
1040 " %func1Entry = OpLabel\n"
1041 " %out_ptr2 = OpAccessChain %_ptr_sb_v4f32 %f1 %c_i32_0\n"
1042 " OpStore %out_ptr2 %c_v4f32_2\n"
1043 " %out_ptr3 = OpAccessChain %_ptr_sb_v4f32 %f1 %c_i32_1\n"
1044 " OpStore %out_ptr3 %c_v4f32_2\n"
1045 " OpReturn\n"
1046 " OpFunctionEnd\n";
1047
1048 fragments["decoration"] =
1049 " OpMemberDecorate %Output 0 Offset 0\n"
1050 " OpMemberDecorate %Output 1 Offset 32\n"
1051 " OpDecorate %Output Block\n"
1052 " OpDecorate %dataOutput DescriptorSet 0\n"
1053 " OpDecorate %dataOutput Binding 0\n"
1054 " OpDecorate %arr_v4f32_2 ArrayStride 16\n"
1055 " OpDecorate %arr_v4f32_rt ArrayStride 16\n";
1056
1057 fragments["testfun"] =
1058 " %test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
1059 " %param = OpFunctionParameter %v4f32\n"
1060 " %entry = OpLabel\n"
1061 " %ptr0 = OpAccessChain %arr_v4f32_2_ptr %dataOutput %c_i32_0\n"
1062 " %ptr1 = OpAccessChain %arr_v4f32_rt_ptr %dataOutput %c_i32_1\n"
1063 " %ret0 = OpFunctionCall %void %func0 %ptr0\n"
1064 " %ret1 = OpFunctionCall %void %func1 %ptr1\n"
1065 " OpReturnValue %param\n"
1066 " OpFunctionEnd\n";
1067
1068 fragments["extension"] =
1069 "OpExtension \"SPV_KHR_variable_pointers\"\n"
1070 "OpExtension \"SPV_KHR_storage_buffer_storage_class\"\n";
1071
1072 fragments["capability"] =
1073 "OpCapability VariablePointersStorageBuffer\n";
1074
1075 getDefaultColors(defaultColors);
1076
1077 for (deUint32 numIdx = 0; numIdx < numFloats / 2; ++numIdx)
1078 expectedOutput.push_back(5.0f);
1079 for (deUint32 numIdx = 0; numIdx < numFloats / 2; ++numIdx)
1080 expectedOutput.push_back(2.0f);
1081
1082 extensions.push_back("VK_KHR_variable_pointers");
1083 requiredFeatures.coreFeatures.fragmentStoresAndAtomics = true;
1084 requiredFeatures.extVariablePointers = EXTVARIABLEPOINTERSFEATURES_VARIABLE_POINTERS_STORAGEBUFFER;
1085 requiredFeatures.coreFeatures.vertexPipelineStoresAndAtomics = DE_TRUE;
1086 resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(expectedOutput)), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
1087
1088 createTestsForAllStages("buffer_memory_variable_pointers", defaultColors, defaultColors, fragments, resources, extensions, group, requiredFeatures);
1089 }
1090
1091 } // anonymous
1092
createPointerParameterComputeGroup(tcu::TestContext & testCtx)1093 tcu::TestCaseGroup* createPointerParameterComputeGroup (tcu::TestContext& testCtx)
1094 {
1095 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "pointer_parameter", "Compute tests for pointer as function parameter."));
1096 addComputePointerParamToParamTest(group.get());
1097 addComputePointerParamToGlobalTest(group.get());
1098 addComputePointerBufferMemoryTest(group.get());
1099 addComputePointerBufferMemoryVariablePointersTest(group.get());
1100 addComputePointerWorkgroupMemoryVariablePointersTest(group.get());
1101
1102 return group.release();
1103 }
1104
createPointerParameterGraphicsGroup(tcu::TestContext & testCtx)1105 tcu::TestCaseGroup* createPointerParameterGraphicsGroup (tcu::TestContext& testCtx)
1106 {
1107 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "pointer_parameter", "Graphics tests for pointer as function parameter."));
1108 addGraphicsPointerParamToParamTest(group.get());
1109 addGraphicsPointerParamToGlobalTest(group.get());
1110 addGraphicsPointerBufferMemoryTest(group.get());
1111 addGraphicsPointerBufferMemoryVariablePointersTest(group.get());
1112
1113 return group.release();
1114 }
1115
1116 } // SpirVAssembly
1117 } // vkt
1118