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 %gl_GlobalInvocationID BuiltIn GlobalInvocationId\n"
309 " %void = OpTypeVoid\n"
310 " %void_func = OpTypeFunction %void\n"
311 " %float = OpTypeFloat 32\n"
312 " %_ptr_Function_float = OpTypePointer Function %float\n"
313 " %float_5 = OpConstant %float 5\n"
314 " %float_2 = OpConstant %float 2\n"
315 " %uint = OpTypeInt 32 0\n"
316 " %_ptr_Function_uint = OpTypePointer Function %uint\n"
317 " %uint_16 = OpConstant %uint 16\n"
318 " %vec4 = OpTypeVector %float 4\n"
319 " %vec4_5 = OpConstantComposite %vec4 %float_5 %float_5 %float_5 %float_5\n"
320 " %vec4_2 = OpConstantComposite %vec4 %float_2 %float_2 %float_2 %float_2\n"
321 " %arr_vec4_16 = OpTypeArray %vec4 %uint_16\n"
322 " %arr_vec4_rt = OpTypeRuntimeArray %vec4\n"
323 " %arr_vec4_16_ptr = OpTypePointer StorageBuffer %arr_vec4_16\n"
324 " %arr_vec4_rt_ptr = OpTypePointer StorageBuffer %arr_vec4_rt\n"
325 " %func0_decl = OpTypeFunction %void %arr_vec4_16_ptr %_ptr_Function_uint\n"
326 " %func1_decl = OpTypeFunction %void %arr_vec4_rt_ptr %_ptr_Function_uint\n"
327 " %Output = OpTypeStruct %arr_vec4_16 %arr_vec4_rt\n"
328 " %_ptr_sb_Output = OpTypePointer StorageBuffer %Output\n"
329 " %dataOutput = OpVariable %_ptr_sb_Output StorageBuffer\n"
330 " %int = OpTypeInt 32 1\n"
331 " %int_0 = OpConstant %int 0\n"
332 " %int_1 = OpConstant %int 1\n"
333 " %v3uint = OpTypeVector %uint 3\n"
334 " %_ptr_Input_v3uint = OpTypePointer Input %v3uint\n"
335 " %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input\n"
336 " %uint_0 = OpConstant %uint 0\n"
337 " %_ptr_Input_uint = OpTypePointer Input %uint\n"
338 " %_ptr_sb_vec4 = OpTypePointer StorageBuffer %vec4\n"
339 " %main = OpFunction %void None %void_func\n"
340 " %entry = OpLabel\n"
341 " %idx = OpVariable %_ptr_Function_uint Function\n"
342 " %inv_id_ptr = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %uint_0\n"
343 " %inv_id = OpLoad %uint %inv_id_ptr\n"
344 " OpStore %idx %inv_id\n"
345 " %ptr0 = OpAccessChain %arr_vec4_16_ptr %dataOutput %int_0\n"
346 " %ptr1 = OpAccessChain %arr_vec4_rt_ptr %dataOutput %int_1\n"
347 " %ret0 = OpFunctionCall %void %func0 %ptr0 %idx\n"
348 " %ret1 = OpFunctionCall %void %func1 %ptr1 %idx\n"
349 " OpReturn\n"
350 " OpFunctionEnd\n"
351 " %func0 = OpFunction %void None %func0_decl\n"
352 " %f0 = OpFunctionParameter %arr_vec4_16_ptr\n"
353 " %i0 = OpFunctionParameter %_ptr_Function_uint\n"
354 " %func0_entry = OpLabel\n"
355 " %idx0 = OpLoad %uint %i0\n"
356 " %out_ptr0 = OpAccessChain %_ptr_sb_vec4 %f0 %idx0\n"
357 " OpStore %out_ptr0 %vec4_5\n"
358 " OpReturn\n"
359 " OpFunctionEnd\n"
360 " %func1 = OpFunction %void None %func1_decl\n"
361 " %f1 = OpFunctionParameter %arr_vec4_rt_ptr\n"
362 " %i1 = OpFunctionParameter %_ptr_Function_uint\n"
363 " %func1_entry = OpLabel\n"
364 " %idx1 = OpLoad %uint %i1\n"
365 " %out_ptr1 = OpAccessChain %_ptr_sb_vec4 %f1 %idx1\n"
366 " OpStore %out_ptr1 %vec4_2\n"
367 " OpReturn\n"
368 " OpFunctionEnd\n";
369
370 expectedOutput.reserve(numFloats);
371 for (deUint32 numIdx = 0; numIdx < numFloats / 2; ++numIdx)
372 expectedOutput.push_back(5.0f);
373 for (deUint32 numIdx = 0; numIdx < numFloats / 2; ++numIdx)
374 expectedOutput.push_back(2.0f);
375
376 requiredFeatures.extVariablePointers.variablePointersStorageBuffer = true;
377
378 spec.outputs.push_back(BufferSp(new Float32Buffer(expectedOutput)));
379
380 spec.assembly = shaderSource;
381 spec.numWorkGroups = IVec3(16, 1, 1);
382 spec.requestedVulkanFeatures = requiredFeatures;
383 spec.extensions.push_back("VK_KHR_variable_pointers");
384
385 group->addChild(new SpvAsmComputeShaderCase(testCtx, "buffer_memory", "", spec));
386 }
387
addComputePointerBufferMemoryVariablePointersTest(tcu::TestCaseGroup * group)388 void addComputePointerBufferMemoryVariablePointersTest (tcu::TestCaseGroup* group)
389 {
390 tcu::TestContext& testCtx = group->getTestContext();
391 const int numFloats = 128;
392 ComputeShaderSpec spec;
393 VulkanFeatures requiredFeatures;
394 vector<float> expectedOutput;
395
396 // Implements the following pseudo GLSL shader:
397 //
398 // layout (binding = 0) buffer Output
399 // {
400 // vec4 arr0[16];
401 // vec4 arr1[];
402 // } dataOutput;
403 //
404 // void func0(vec4* f0[16], uint i)
405 // {
406 // f0[i] = vec4(5.0);
407 // }
408 //
409 // void func1(vec4* f1[], uint i)
410 // {
411 // f1[i] = vec4(2.0);
412 // }
413 //
414 // void main()
415 // {
416 // uint idx = gl_GlobalInvocationID.x;
417 // func0(dataOutput.arr0, idx);
418 // func1(dataOutput.arr1, idx);
419 // }
420 const string shaderSource =
421 " OpCapability Shader\n"
422 " OpCapability VariablePointersStorageBuffer\n"
423 " OpExtension \"SPV_KHR_variable_pointers\"\n"
424 " OpExtension \"SPV_KHR_storage_buffer_storage_class\"\n"
425 " %1 = OpExtInstImport \"GLSL.std.450\"\n"
426 " OpMemoryModel Logical GLSL450\n"
427 " OpEntryPoint GLCompute %main \"main\" %gl_GlobalInvocationID\n"
428 " OpExecutionMode %main LocalSize 1 1 1\n"
429 " OpSource GLSL 430\n"
430 " OpMemberDecorate %Output 0 Offset 0\n"
431 " OpMemberDecorate %Output 1 Offset 256\n"
432 " OpDecorate %arr_vec4_16 ArrayStride 16\n"
433 " OpDecorate %arr_vec4_rt ArrayStride 16\n"
434 " OpDecorate %Output Block\n"
435 " OpDecorate %dataOutput DescriptorSet 0\n"
436 " OpDecorate %dataOutput Binding 0\n"
437 " OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId\n"
438 " %void = OpTypeVoid\n"
439 " %void_func = OpTypeFunction %void\n"
440 " %float = OpTypeFloat 32\n"
441 " %_ptr_Function_float = OpTypePointer Function %float\n"
442 " %float_5 = OpConstant %float 5\n"
443 " %float_2 = OpConstant %float 2\n"
444 " %uint = OpTypeInt 32 0\n"
445 " %_ptr_Function_uint = OpTypePointer Function %uint\n"
446 " %uint_16 = OpConstant %uint 16\n"
447 " %vec4 = OpTypeVector %float 4\n"
448 " %vec4_5 = OpConstantComposite %vec4 %float_5 %float_5 %float_5 %float_5\n"
449 " %vec4_2 = OpConstantComposite %vec4 %float_2 %float_2 %float_2 %float_2\n"
450 " %arr_vec4_16 = OpTypeArray %vec4 %uint_16\n"
451 " %arr_vec4_rt = OpTypeRuntimeArray %vec4\n"
452 " %arr_vec4_16_ptr = OpTypePointer StorageBuffer %arr_vec4_16\n"
453 " %arr_vec4_rt_ptr = OpTypePointer StorageBuffer %arr_vec4_rt\n"
454 " %func0_decl = OpTypeFunction %void %arr_vec4_16_ptr %_ptr_Function_uint\n"
455 " %func1_decl = OpTypeFunction %void %arr_vec4_rt_ptr %_ptr_Function_uint\n"
456 " %Output = OpTypeStruct %arr_vec4_16 %arr_vec4_rt\n"
457 " %_ptr_sb_Output = OpTypePointer StorageBuffer %Output\n"
458 " %dataOutput = OpVariable %_ptr_sb_Output StorageBuffer\n"
459 " %int = OpTypeInt 32 1\n"
460 " %int_0 = OpConstant %int 0\n"
461 " %int_1 = OpConstant %int 1\n"
462 " %v3uint = OpTypeVector %uint 3\n"
463 " %_ptr_Input_v3uint = OpTypePointer Input %v3uint\n"
464 " %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input\n"
465 " %uint_0 = OpConstant %uint 0\n"
466 " %_ptr_Input_uint = OpTypePointer Input %uint\n"
467 " %_ptr_sb_vec4 = OpTypePointer StorageBuffer %vec4\n"
468 " %main = OpFunction %void None %void_func\n"
469 " %entry = OpLabel\n"
470 " %idx = OpVariable %_ptr_Function_uint Function\n"
471 " %inv_id_ptr = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %uint_0\n"
472 " %inv_id = OpLoad %uint %inv_id_ptr\n"
473 " OpStore %idx %inv_id\n"
474 " %ptr0 = OpAccessChain %arr_vec4_16_ptr %dataOutput %int_0\n"
475 " %ptr1 = OpAccessChain %arr_vec4_rt_ptr %dataOutput %int_1\n"
476 " %ret0 = OpFunctionCall %void %func0 %ptr0 %idx\n"
477 " %ret1 = OpFunctionCall %void %func1 %ptr1 %idx\n"
478 " OpReturn\n"
479 " OpFunctionEnd\n"
480 " %func0 = OpFunction %void None %func0_decl\n"
481 " %f0 = OpFunctionParameter %arr_vec4_16_ptr\n"
482 " %i0 = OpFunctionParameter %_ptr_Function_uint\n"
483 " %func0_entry = OpLabel\n"
484 " %idx0 = OpLoad %uint %i0\n"
485 " %out_ptr0 = OpAccessChain %_ptr_sb_vec4 %f0 %idx0\n"
486 " OpStore %out_ptr0 %vec4_5\n"
487 " OpReturn\n"
488 " OpFunctionEnd\n"
489 " %func1 = OpFunction %void None %func1_decl\n"
490 " %f1 = OpFunctionParameter %arr_vec4_rt_ptr\n"
491 " %i1 = OpFunctionParameter %_ptr_Function_uint\n"
492 " %func1_entry = OpLabel\n"
493 " %idx1 = OpLoad %uint %i1\n"
494 " %out_ptr1 = OpAccessChain %_ptr_sb_vec4 %f1 %idx1\n"
495 " OpStore %out_ptr1 %vec4_2\n"
496 " OpReturn\n"
497 " OpFunctionEnd\n";
498
499 expectedOutput.reserve(numFloats);
500 for (deUint32 numIdx = 0; numIdx < numFloats / 2; ++numIdx)
501 expectedOutput.push_back(5.0f);
502 for (deUint32 numIdx = 0; numIdx < numFloats / 2; ++numIdx)
503 expectedOutput.push_back(2.0f);
504
505 requiredFeatures.extVariablePointers.variablePointersStorageBuffer = true;
506 spec.outputs.push_back(BufferSp(new Float32Buffer(expectedOutput)));
507 spec.extensions.push_back("VK_KHR_variable_pointers");
508
509 spec.assembly = shaderSource;
510 spec.numWorkGroups = IVec3(16, 1, 1);
511 spec.requestedVulkanFeatures = requiredFeatures;
512
513 group->addChild(new SpvAsmComputeShaderCase(testCtx, "buffer_memory_variable_pointers", "", spec));
514 }
515
addComputePointerWorkgroupMemoryVariablePointersTest(tcu::TestCaseGroup * group)516 void addComputePointerWorkgroupMemoryVariablePointersTest (tcu::TestCaseGroup* group)
517 {
518 tcu::TestContext& testCtx = group->getTestContext();
519 const int numFloats = 128;
520 ComputeShaderSpec spec;
521 VulkanFeatures requiredFeatures;
522 vector<float> expectedOutput;
523
524 // Implements the following pseudo GLSL shader:
525 //
526 // layout (local_size_x = 16, local_size_y = 1, local_size_z = 1) in;
527 //
528 // layout (binding = 0) buffer Output
529 // {
530 // vec4 arr0[16];
531 // vec4 arr1[];
532 // } dataOutput;
533 //
534 // shared struct
535 // {
536 // vec4 arr0[16];
537 // vec4 arr1[16];
538 // } sharedData;
539 //
540 // void func0(vec4* f0[16], uint i)
541 // {
542 // f0[i] = vec4(i);
543 // }
544 //
545 // void func1(vec4* f1[16], uint i)
546 // {
547 // f1[i] = vec4(i+5);
548 // }
549 //
550 // void main()
551 // {
552 // uint idx = gl_LocalInvocationID.x;
553 // func0(sharedData.arr0, idx);
554 // func1(sharedData.arr1, idx);
555 // barier();
556 // dataOutput.arr0[idx] = sharedData.arr1[(idx+1) % 16];
557 // dataOutput.arr1[idx] = sharedData.arr0[(idx+1) % 16];
558 // }
559 const string shaderSource =
560 " OpCapability Shader\n"
561 " OpCapability VariablePointers\n"
562 " OpExtension \"SPV_KHR_variable_pointers\"\n"
563 " OpExtension \"SPV_KHR_storage_buffer_storage_class\"\n"
564 " %1 = OpExtInstImport \"GLSL.std.450\"\n"
565 " OpMemoryModel Logical GLSL450\n"
566 " OpEntryPoint GLCompute %main \"main\" %gl_LocalInvocationID\n"
567 " OpExecutionMode %main LocalSize 16 1 1\n"
568 " OpSource GLSL 430\n"
569 " OpMemberDecorate %Output 0 Offset 0\n"
570 " OpMemberDecorate %Output 1 Offset 256\n"
571 " OpMemberDecorate %struct 0 Offset 0\n"
572 " OpMemberDecorate %struct 1 Offset 256\n"
573 " OpDecorate %arr_vec4_16 ArrayStride 16\n"
574 " OpDecorate %arr_vec4_rt ArrayStride 16\n"
575 " OpDecorate %Output Block\n"
576 " OpDecorate %dataOutput DescriptorSet 0\n"
577 " OpDecorate %dataOutput Binding 0\n"
578 " OpDecorate %gl_LocalInvocationID BuiltIn LocalInvocationId\n"
579 " %void = OpTypeVoid\n"
580 " %void_func = OpTypeFunction %void\n"
581 " %float = OpTypeFloat 32\n"
582 " %_ptr_Function_float = OpTypePointer Function %float\n"
583 " %uint = OpTypeInt 32 0\n"
584 " %_ptr_Function_uint = OpTypePointer Function %uint\n"
585 " %uint_1 = OpConstant %uint 1\n"
586 " %uint_2 = OpConstant %uint 2\n"
587 " %uint_5 = OpConstant %uint 5\n"
588 " %uint_16 = OpConstant %uint 16\n"
589 " %uint_264 = OpConstant %uint 264\n"
590 " %vec4 = OpTypeVector %float 4\n"
591 " %arr_vec4_16 = OpTypeArray %vec4 %uint_16\n"
592 " %arr_vec4_rt = OpTypeRuntimeArray %vec4\n"
593 " %arr_vec4_16_sb_ptr = OpTypePointer StorageBuffer %arr_vec4_16\n"
594 " %arr_vec4_rt_sb_ptr = OpTypePointer StorageBuffer %arr_vec4_rt\n"
595 " %arr_vec4_16_wg_ptr = OpTypePointer Workgroup %arr_vec4_16\n"
596 " %func_decl = OpTypeFunction %void %arr_vec4_16_wg_ptr %_ptr_Function_uint\n"
597 " %Output = OpTypeStruct %arr_vec4_16 %arr_vec4_rt\n"
598 " %struct = OpTypeStruct %arr_vec4_16 %arr_vec4_16\n"
599 " %_ptr_sb_struct = OpTypePointer StorageBuffer %Output\n"
600 " %_ptr_wg_struct = OpTypePointer Workgroup %struct\n"
601 " %dataOutput = OpVariable %_ptr_sb_struct StorageBuffer\n"
602 " %sharedData = OpVariable %_ptr_wg_struct Workgroup\n"
603 " %int = OpTypeInt 32 1\n"
604 " %int_0 = OpConstant %int 0\n"
605 " %int_1 = OpConstant %int 1\n"
606 " %v3uint = OpTypeVector %uint 3\n"
607 " %_ptr_Input_v3uint = OpTypePointer Input %v3uint\n"
608 " %gl_LocalInvocationID = OpVariable %_ptr_Input_v3uint Input\n"
609 " %uint_0 = OpConstant %uint 0\n"
610 " %_ptr_Input_uint = OpTypePointer Input %uint\n"
611 " %_ptr_sb_vec4 = OpTypePointer StorageBuffer %vec4\n"
612 " %_ptr_wg_vec4 = OpTypePointer Workgroup %vec4\n"
613 " %main = OpFunction %void None %void_func\n"
614 " %entry = OpLabel\n"
615 " %idx = OpVariable %_ptr_Function_uint Function\n"
616 " %inv_id_ptr = OpAccessChain %_ptr_Input_uint %gl_LocalInvocationID %uint_0\n"
617 " %inv_id = OpLoad %uint %inv_id_ptr\n"
618 " OpStore %idx %inv_id\n"
619 " %ptr0 = OpAccessChain %arr_vec4_16_wg_ptr %sharedData %int_0\n"
620 " %ptr1 = OpAccessChain %arr_vec4_16_wg_ptr %sharedData %int_1\n"
621 " %ret0 = OpFunctionCall %void %func0 %ptr0 %idx\n"
622 " %ret1 = OpFunctionCall %void %func1 %ptr1 %idx\n"
623 " OpControlBarrier %uint_2 %uint_2 %uint_264\n"
624 " %inv_id_plus1 = OpIAdd %uint %inv_id %uint_1\n"
625 " %inv_id_mod = OpUMod %uint %inv_id_plus1 %uint_16\n"
626 " %shared_arr1_ptr = OpAccessChain %_ptr_wg_vec4 %sharedData %int_1 %inv_id_mod\n"
627 " %shared_arr1_data = OpLoad %vec4 %shared_arr1_ptr\n"
628 " %outPtr0 = OpAccessChain %_ptr_sb_vec4 %dataOutput %int_0 %inv_id\n"
629 " OpStore %outPtr0 %shared_arr1_data\n"
630 " %shared_arr0_ptr = OpAccessChain %_ptr_wg_vec4 %sharedData %int_0 %inv_id_mod\n"
631 " %shared_arr0_data = OpLoad %vec4 %shared_arr0_ptr\n"
632 " %outPtr1 = OpAccessChain %_ptr_sb_vec4 %dataOutput %int_1 %inv_id\n"
633 " OpStore %outPtr1 %shared_arr0_data\n"
634 " OpReturn\n"
635 " OpFunctionEnd\n"
636 " %func0 = OpFunction %void None %func_decl\n"
637 " %f0 = OpFunctionParameter %arr_vec4_16_wg_ptr\n"
638 " %i0 = OpFunctionParameter %_ptr_Function_uint\n"
639 " %func0_entry = OpLabel\n"
640 " %idx0 = OpLoad %uint %i0\n"
641 " %out_ptr0 = OpAccessChain %_ptr_wg_vec4 %f0 %idx0\n"
642 " %idxFloat0 = OpConvertUToF %float %idx0\n"
643 " %outData0 = OpCompositeConstruct %vec4 %idxFloat0 %idxFloat0 %idxFloat0 %idxFloat0\n"
644 " OpStore %out_ptr0 %outData0\n"
645 " OpReturn\n"
646 " OpFunctionEnd\n"
647 " %func1 = OpFunction %void None %func_decl\n"
648 " %f1 = OpFunctionParameter %arr_vec4_16_wg_ptr\n"
649 " %i1 = OpFunctionParameter %_ptr_Function_uint\n"
650 " %func1_entry = OpLabel\n"
651 " %idx1 = OpLoad %uint %i1\n"
652 " %out_ptr1 = OpAccessChain %_ptr_wg_vec4 %f1 %idx1\n"
653 " %idxPlus5 = OpIAdd %uint %idx1 %uint_5\n"
654 " %idxFloat1 = OpConvertUToF %float %idxPlus5\n"
655 " %outData1 = OpCompositeConstruct %vec4 %idxFloat1 %idxFloat1 %idxFloat1 %idxFloat1\n"
656 " OpStore %out_ptr1 %outData1\n"
657 " OpReturn\n"
658 " OpFunctionEnd\n";
659
660 expectedOutput.reserve(numFloats);
661 for (deUint32 vecIdx = 0; vecIdx < numFloats / 8; ++vecIdx)
662 {
663 const deUint32 shuffleIdx = (vecIdx + 1) % 16;
664 const float val = (float)(shuffleIdx + 5);
665 for (deUint32 i = 0; i < 4; ++i)
666 expectedOutput.push_back(val);
667 }
668 for (deUint32 vecIdx = 0; vecIdx < numFloats / 8; ++vecIdx)
669 {
670 const deUint32 shuffleIdx = (vecIdx + 1) % 16;
671 const float val = (float)shuffleIdx;
672 for (deUint32 i = 0; i < 4; ++i)
673 expectedOutput.push_back(val);
674 }
675
676 spec.outputs.push_back(BufferSp(new Float32Buffer(expectedOutput)));
677 requiredFeatures.extVariablePointers.variablePointers = true;
678 spec.extensions.push_back("VK_KHR_variable_pointers");
679
680 spec.assembly = shaderSource;
681 spec.numWorkGroups = IVec3(1, 1, 1);
682 spec.requestedVulkanFeatures = requiredFeatures;
683
684 group->addChild(new SpvAsmComputeShaderCase(testCtx, "workgroup_memory_variable_pointers", "", spec));
685 }
686
addGraphicsPointerParamToParamTest(tcu::TestCaseGroup * group)687 void addGraphicsPointerParamToParamTest (tcu::TestCaseGroup* group)
688 {
689 map<string, string> fragments;
690 RGBA defaultColors[4];
691 GraphicsResources resources;
692 vector<string> extensions;
693 vector<float> expectedOutput;
694 VulkanFeatures requiredFeatures;
695
696 // Implements the following pseudo GLSL shader:
697 //
698 // float func(alias float* f, alias float* g)
699 // {
700 // *g = 5.0;
701 // *f = 2.0;
702 // return *g;
703 // }
704 //
705 // vec4 test_code(vec4 param)
706 // {
707 // float a = 0.0;
708 // o = func(&a, &a); // should return 2.0
709 // float b = 0.0;
710 // o += func(&a, &b); // should return 5.0
711 // return param;
712 // }
713 fragments["pre_main"] =
714 " %func0_decl = OpTypeFunction %f32 %fp_f32 %fp_f32\n"
715 " %c_f32_5 = OpConstant %f32 5\n"
716 " %c_f32_2 = OpConstant %f32 2\n"
717 " %Output = OpTypeStruct %f32\n"
718 " %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
719 " %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n"
720 " %_ptr_Uniform_f32 = OpTypePointer Uniform %f32\n"
721 " %func = OpFunction %f32 None %func0_decl\n"
722 " %f = OpFunctionParameter %fp_f32\n"
723 " %g = OpFunctionParameter %fp_f32\n"
724 " %func_entry = OpLabel\n"
725 " OpStore %g %c_f32_5\n"
726 " OpStore %f %c_f32_2\n"
727 " %ret = OpLoad %f32 %g\n"
728 " OpReturnValue %ret\n"
729 " OpFunctionEnd\n";
730
731 fragments["decoration"] =
732 " OpMemberDecorate %Output 0 Offset 0\n"
733 " OpDecorate %Output BufferBlock\n"
734 " OpDecorate %dataOutput DescriptorSet 0\n"
735 " OpDecorate %dataOutput Binding 0\n"
736 " OpDecorate %f Aliased\n"
737 " OpDecorate %g Aliased\n";
738
739 fragments["testfun"] =
740 " %test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
741 " %param = OpFunctionParameter %v4f32\n"
742 " %entry = OpLabel\n"
743 " %a = OpVariable %fp_f32 Function %c_f32_0\n"
744 " %b = OpVariable %fp_f32 Function %c_f32_0\n"
745 " %o = OpVariable %fp_f32 Function %c_f32_0\n"
746 " %ret0 = OpFunctionCall %f32 %func %a %a\n"
747 " OpStore %o %ret0\n"
748 " %ret1 = OpFunctionCall %f32 %func %a %b\n"
749 " %o_val = OpLoad %f32 %o\n"
750 " %sum = OpFAdd %f32 %o_val %ret1\n"
751 " %out_ptr = OpAccessChain %_ptr_Uniform_f32 %dataOutput %c_i32_0\n"
752 " OpStore %out_ptr %sum\n"
753 " OpReturnValue %param\n"
754 " OpFunctionEnd\n";
755
756 getDefaultColors(defaultColors);
757 expectedOutput.push_back(7.0f);
758 requiredFeatures.coreFeatures.vertexPipelineStoresAndAtomics = true;
759 requiredFeatures.coreFeatures.fragmentStoresAndAtomics = true;
760 resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(expectedOutput)), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
761
762 createTestsForAllStages("global_to_param", defaultColors, defaultColors, fragments, resources, extensions, group, requiredFeatures);
763 }
764
addGraphicsPointerParamToGlobalTest(tcu::TestCaseGroup * group)765 void addGraphicsPointerParamToGlobalTest (tcu::TestCaseGroup* group)
766 {
767 map<string, string> fragments;
768 RGBA defaultColors[4];
769 GraphicsResources resources;
770 vector<string> extensions;
771 vector<float> expectedOutput;
772 VulkanFeatures requiredFeatures;
773
774 // Implements the following pseudo GLSL shader:
775 //
776 // alias float a = 0.0;
777 //
778 // float func0(alias float* f0) // f in Private storage class
779 // {
780 // *a = 5.0;
781 // *f0 = 2.0;
782 // return *a;
783 // }
784 //
785 // float func1(alias float* f1) // f in Function storage class
786 // {
787 // *a = 5.0;
788 // *f1 = 2.0;
789 // return *a;
790 // }
791 //
792 // vec4 test_code(vec4 param)
793 // {
794 // o = func0(&a); // should return 2.0
795 // float b = 0.0;
796 // o += func1(&b); // should return 5.0
797 // return param;
798 // }
799 fragments["pre_main"] =
800 " %pp_f32 = OpTypePointer Private %f32\n"
801 " %func0_decl = OpTypeFunction %f32 %pp_f32\n"
802 " %func1_decl = OpTypeFunction %f32 %fp_f32\n"
803 " %c_f32_5 = OpConstant %f32 5\n"
804 " %c_f32_2 = OpConstant %f32 2\n"
805 " %Output = OpTypeStruct %f32\n"
806 " %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
807 " %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n"
808 " %_ptr_Uniform_f32 = OpTypePointer Uniform %f32\n"
809 " %a = OpVariable %pp_f32 Private %c_f32_0\n"
810 " %func0 = OpFunction %f32 None %func0_decl\n"
811 " %f0 = OpFunctionParameter %pp_f32\n"
812 " %func0_entry = OpLabel\n"
813 " OpStore %a %c_f32_5\n"
814 " OpStore %f0 %c_f32_2\n"
815 " %func0_ret = OpLoad %f32 %a\n"
816 " OpReturnValue %func0_ret\n"
817 " OpFunctionEnd\n"
818 " %func1 = OpFunction %f32 None %func1_decl\n"
819 " %f1 = OpFunctionParameter %fp_f32\n"
820 " %func1_entry = OpLabel\n"
821 " OpStore %a %c_f32_5\n"
822 " OpStore %f1 %c_f32_2\n"
823 " %func1_ret = OpLoad %f32 %a\n"
824 " OpReturnValue %func1_ret\n"
825 " OpFunctionEnd\n";
826
827 fragments["decoration"] =
828 " OpMemberDecorate %Output 0 Offset 0\n"
829 " OpDecorate %Output BufferBlock\n"
830 " OpDecorate %dataOutput DescriptorSet 0\n"
831 " OpDecorate %dataOutput Binding 0\n"
832 " OpDecorate %f0 Aliased\n"
833 " OpDecorate %f1 Aliased\n"
834 " OpDecorate %a Aliased\n";
835
836 fragments["testfun"] =
837 " %test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
838 " %param = OpFunctionParameter %v4f32\n"
839 " %entry = OpLabel\n"
840 " %b = OpVariable %fp_f32 Function %c_f32_0\n"
841 " %o = OpVariable %fp_f32 Function %c_f32_0\n"
842 " %ret0 = OpFunctionCall %f32 %func0 %a\n"
843 " OpStore %o %ret0\n"
844 " %ret1 = OpFunctionCall %f32 %func1 %b\n"
845 " %o_val = OpLoad %f32 %o\n"
846 " %sum = OpFAdd %f32 %o_val %ret1\n"
847 " %out_ptr = OpAccessChain %_ptr_Uniform_f32 %dataOutput %c_i32_0\n"
848 " OpStore %out_ptr %sum\n"
849 " OpReturnValue %param\n"
850 " OpFunctionEnd\n";
851
852 getDefaultColors(defaultColors);
853 expectedOutput.push_back(7.0f);
854 requiredFeatures.coreFeatures.vertexPipelineStoresAndAtomics = true;
855 requiredFeatures.coreFeatures.fragmentStoresAndAtomics = true;
856 resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(expectedOutput)), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
857
858 createTestsForAllStages("param_to_global", defaultColors, defaultColors, fragments, resources, extensions, group, requiredFeatures);
859 }
860
addGraphicsPointerBufferMemoryTest(tcu::TestCaseGroup * group)861 void addGraphicsPointerBufferMemoryTest (tcu::TestCaseGroup* group)
862 {
863 const int numFloats = 16;
864 map<string, string> fragments;
865 RGBA defaultColors[4];
866 GraphicsResources resources;
867 vector<string> extensions;
868 vector<float> expectedOutput;
869 VulkanFeatures requiredFeatures;
870
871 // Implements the following pseudo GLSL shader:
872 //
873 // layout (binding = 0) buffer Output
874 // {
875 // vec4 arr0[2];
876 // vec4 arr1[];
877 // } dataOutput;
878 //
879 // void func0(vec4* f0[2], uint i)
880 // {
881 // f0[i] = vec4(5.0);
882 // }
883 //
884 // void func1(vec4* f1[], uint i)
885 // {
886 // f1[i] = vec4(2.0);
887 // }
888 //
889 // vec4 test_code(vec4 param)
890 // {
891 // func0(dataOutput.arr0, idx);
892 // func1(dataOutput.arr1, idx);
893 // return param;
894 // }
895 fragments["pre_main"] =
896 " %arr_v4f32_2 = OpTypeArray %v4f32 %c_u32_2\n"
897 " %arr_v4f32_rt = OpTypeRuntimeArray %v4f32\n"
898 " %arr_v4f32_2_ptr = OpTypePointer StorageBuffer %arr_v4f32_2\n"
899 " %arr_v4f32_rt_ptr = OpTypePointer StorageBuffer %arr_v4f32_rt\n"
900 " %func0_decl = OpTypeFunction %void %arr_v4f32_2_ptr\n"
901 " %func1_decl = OpTypeFunction %void %arr_v4f32_rt_ptr\n"
902 " %c_f32_5 = OpConstant %f32 5\n"
903 " %c_f32_2 = OpConstant %f32 2\n"
904 " %c_v4f32_5 = OpConstantComposite %v4f32 %c_f32_5 %c_f32_5 %c_f32_5 %c_f32_5\n"
905 " %c_v4f32_2 = OpConstantComposite %v4f32 %c_f32_2 %c_f32_2 %c_f32_2 %c_f32_2\n"
906 " %Output = OpTypeStruct %arr_v4f32_2 %arr_v4f32_rt\n"
907 " %_ptr_sb_Output = OpTypePointer StorageBuffer %Output\n"
908 " %dataOutput = OpVariable %_ptr_sb_Output StorageBuffer\n"
909 " %_ptr_sb_v4f32 = OpTypePointer StorageBuffer %v4f32\n"
910 " %func0 = OpFunction %void None %func0_decl\n"
911 " %f0 = OpFunctionParameter %arr_v4f32_2_ptr\n"
912 " %func0Entry = OpLabel\n"
913 " %out_ptr0 = OpAccessChain %_ptr_sb_v4f32 %f0 %c_i32_0\n"
914 " OpStore %out_ptr0 %c_v4f32_5\n"
915 " %out_ptr1 = OpAccessChain %_ptr_sb_v4f32 %f0 %c_i32_1\n"
916 " OpStore %out_ptr1 %c_v4f32_5\n"
917 " OpReturn\n"
918 " OpFunctionEnd\n"
919 " %func1 = OpFunction %void None %func1_decl\n"
920 " %f1 = OpFunctionParameter %arr_v4f32_rt_ptr\n"
921 " %func1Entry = OpLabel\n"
922 " %out_ptr2 = OpAccessChain %_ptr_sb_v4f32 %f1 %c_i32_0\n"
923 " OpStore %out_ptr2 %c_v4f32_2\n"
924 " %out_ptr3 = OpAccessChain %_ptr_sb_v4f32 %f1 %c_i32_1\n"
925 " OpStore %out_ptr3 %c_v4f32_2\n"
926 " OpReturn\n"
927 " OpFunctionEnd\n";
928
929 fragments["decoration"] =
930 " OpMemberDecorate %Output 0 Offset 0\n"
931 " OpMemberDecorate %Output 1 Offset 32\n"
932 " OpDecorate %Output Block\n"
933 " OpDecorate %dataOutput DescriptorSet 0\n"
934 " OpDecorate %dataOutput Binding 0\n"
935 " OpDecorate %arr_v4f32_2 ArrayStride 16\n"
936 " OpDecorate %arr_v4f32_rt ArrayStride 16\n";
937
938 fragments["testfun"] =
939 " %test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
940 " %param = OpFunctionParameter %v4f32\n"
941 " %entry = OpLabel\n"
942 " %ptr0 = OpAccessChain %arr_v4f32_2_ptr %dataOutput %c_i32_0\n"
943 " %ptr1 = OpAccessChain %arr_v4f32_rt_ptr %dataOutput %c_i32_1\n"
944 " %ret0 = OpFunctionCall %void %func0 %ptr0\n"
945 " %ret1 = OpFunctionCall %void %func1 %ptr1\n"
946 " OpReturnValue %param\n"
947 " OpFunctionEnd\n";
948
949 fragments["extension"] =
950 "OpExtension \"SPV_KHR_storage_buffer_storage_class\"\n"
951 "OpExtension \"SPV_KHR_variable_pointers\"\n";
952
953 fragments["capability"] =
954 "OpCapability VariablePointersStorageBuffer\n";
955
956 getDefaultColors(defaultColors);
957
958 for (deUint32 numIdx = 0; numIdx < numFloats / 2; ++numIdx)
959 expectedOutput.push_back(5.0f);
960 for (deUint32 numIdx = 0; numIdx < numFloats / 2; ++numIdx)
961 expectedOutput.push_back(2.0f);
962
963 extensions.push_back("VK_KHR_variable_pointers");
964 requiredFeatures.coreFeatures.vertexPipelineStoresAndAtomics = true;
965 requiredFeatures.coreFeatures.fragmentStoresAndAtomics = true;
966 requiredFeatures.extVariablePointers.variablePointersStorageBuffer = true;
967 resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(expectedOutput)), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
968
969 createTestsForAllStages("buffer_memory", defaultColors, defaultColors, fragments, resources, extensions, group, requiredFeatures);
970 }
971
addGraphicsPointerBufferMemoryVariablePointersTest(tcu::TestCaseGroup * group)972 void addGraphicsPointerBufferMemoryVariablePointersTest (tcu::TestCaseGroup* group)
973 {
974 const int numFloats = 16;
975 map<string, string> fragments;
976 RGBA defaultColors[4];
977 GraphicsResources resources;
978 vector<string> extensions;
979 vector<float> expectedOutput;
980 VulkanFeatures requiredFeatures;
981
982 // Implements the following pseudo GLSL shader:
983 //
984 // layout (binding = 0) buffer Output
985 // {
986 // vec4 arr0[2];
987 // vec4 arr1[];
988 // } dataOutput;
989 //
990 // void func0(vec4* f0[2], uint i)
991 // {
992 // f0[i] = vec4(5.0);
993 // }
994 //
995 // void func1(vec4* f1[], uint i)
996 // {
997 // f1[i] = vec4(2.0);
998 // }
999 //
1000 // vec4 test_code(vec4 param)
1001 // {
1002 // func0(dataOutput.arr0, idx);
1003 // func1(dataOutput.arr1, idx);
1004 // return param;
1005 // }
1006 fragments["pre_main"] =
1007 " %arr_v4f32_2 = OpTypeArray %v4f32 %c_u32_2\n"
1008 " %arr_v4f32_rt = OpTypeRuntimeArray %v4f32\n"
1009 " %arr_v4f32_2_ptr = OpTypePointer StorageBuffer %arr_v4f32_2\n"
1010 " %arr_v4f32_rt_ptr = OpTypePointer StorageBuffer %arr_v4f32_rt\n"
1011 " %func0_decl = OpTypeFunction %void %arr_v4f32_2_ptr\n"
1012 " %func1_decl = OpTypeFunction %void %arr_v4f32_rt_ptr\n"
1013 " %c_f32_5 = OpConstant %f32 5\n"
1014 " %c_f32_2 = OpConstant %f32 2\n"
1015 " %c_v4f32_5 = OpConstantComposite %v4f32 %c_f32_5 %c_f32_5 %c_f32_5 %c_f32_5\n"
1016 " %c_v4f32_2 = OpConstantComposite %v4f32 %c_f32_2 %c_f32_2 %c_f32_2 %c_f32_2\n"
1017 " %Output = OpTypeStruct %arr_v4f32_2 %arr_v4f32_rt\n"
1018 " %_ptr_sb_Output = OpTypePointer StorageBuffer %Output\n"
1019 " %dataOutput = OpVariable %_ptr_sb_Output StorageBuffer\n"
1020 " %_ptr_sb_v4f32 = OpTypePointer StorageBuffer %v4f32\n"
1021 " %func0 = OpFunction %void None %func0_decl\n"
1022 " %f0 = OpFunctionParameter %arr_v4f32_2_ptr\n"
1023 " %func0Entry = OpLabel\n"
1024 " %out_ptr0 = OpAccessChain %_ptr_sb_v4f32 %f0 %c_i32_0\n"
1025 " OpStore %out_ptr0 %c_v4f32_5\n"
1026 " %out_ptr1 = OpAccessChain %_ptr_sb_v4f32 %f0 %c_i32_1\n"
1027 " OpStore %out_ptr1 %c_v4f32_5\n"
1028 " OpReturn\n"
1029 " OpFunctionEnd\n"
1030 " %func1 = OpFunction %void None %func1_decl\n"
1031 " %f1 = OpFunctionParameter %arr_v4f32_rt_ptr\n"
1032 " %func1Entry = OpLabel\n"
1033 " %out_ptr2 = OpAccessChain %_ptr_sb_v4f32 %f1 %c_i32_0\n"
1034 " OpStore %out_ptr2 %c_v4f32_2\n"
1035 " %out_ptr3 = OpAccessChain %_ptr_sb_v4f32 %f1 %c_i32_1\n"
1036 " OpStore %out_ptr3 %c_v4f32_2\n"
1037 " OpReturn\n"
1038 " OpFunctionEnd\n";
1039
1040 fragments["decoration"] =
1041 " OpMemberDecorate %Output 0 Offset 0\n"
1042 " OpMemberDecorate %Output 1 Offset 32\n"
1043 " OpDecorate %Output Block\n"
1044 " OpDecorate %dataOutput DescriptorSet 0\n"
1045 " OpDecorate %dataOutput Binding 0\n"
1046 " OpDecorate %arr_v4f32_2 ArrayStride 16\n"
1047 " OpDecorate %arr_v4f32_rt ArrayStride 16\n";
1048
1049 fragments["testfun"] =
1050 " %test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
1051 " %param = OpFunctionParameter %v4f32\n"
1052 " %entry = OpLabel\n"
1053 " %ptr0 = OpAccessChain %arr_v4f32_2_ptr %dataOutput %c_i32_0\n"
1054 " %ptr1 = OpAccessChain %arr_v4f32_rt_ptr %dataOutput %c_i32_1\n"
1055 " %ret0 = OpFunctionCall %void %func0 %ptr0\n"
1056 " %ret1 = OpFunctionCall %void %func1 %ptr1\n"
1057 " OpReturnValue %param\n"
1058 " OpFunctionEnd\n";
1059
1060 fragments["extension"] =
1061 "OpExtension \"SPV_KHR_variable_pointers\"\n"
1062 "OpExtension \"SPV_KHR_storage_buffer_storage_class\"\n";
1063
1064 fragments["capability"] =
1065 "OpCapability VariablePointersStorageBuffer\n";
1066
1067 getDefaultColors(defaultColors);
1068
1069 for (deUint32 numIdx = 0; numIdx < numFloats / 2; ++numIdx)
1070 expectedOutput.push_back(5.0f);
1071 for (deUint32 numIdx = 0; numIdx < numFloats / 2; ++numIdx)
1072 expectedOutput.push_back(2.0f);
1073
1074 extensions.push_back("VK_KHR_variable_pointers");
1075 requiredFeatures.coreFeatures.fragmentStoresAndAtomics = true;
1076 requiredFeatures.extVariablePointers.variablePointersStorageBuffer = true;
1077 requiredFeatures.coreFeatures.vertexPipelineStoresAndAtomics = DE_TRUE;
1078 resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(expectedOutput)), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
1079
1080 createTestsForAllStages("buffer_memory_variable_pointers", defaultColors, defaultColors, fragments, resources, extensions, group, requiredFeatures);
1081 }
1082
1083 } // anonymous
1084
createPointerParameterComputeGroup(tcu::TestContext & testCtx)1085 tcu::TestCaseGroup* createPointerParameterComputeGroup (tcu::TestContext& testCtx)
1086 {
1087 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "pointer_parameter", "Compute tests for pointer as function parameter."));
1088 addComputePointerParamToParamTest(group.get());
1089 addComputePointerParamToGlobalTest(group.get());
1090 addComputePointerBufferMemoryTest(group.get());
1091 addComputePointerBufferMemoryVariablePointersTest(group.get());
1092 addComputePointerWorkgroupMemoryVariablePointersTest(group.get());
1093
1094 return group.release();
1095 }
1096
createPointerParameterGraphicsGroup(tcu::TestContext & testCtx)1097 tcu::TestCaseGroup* createPointerParameterGraphicsGroup (tcu::TestContext& testCtx)
1098 {
1099 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "pointer_parameter", "Graphics tests for pointer as function parameter."));
1100 addGraphicsPointerParamToParamTest(group.get());
1101 addGraphicsPointerParamToGlobalTest(group.get());
1102 addGraphicsPointerBufferMemoryTest(group.get());
1103 addGraphicsPointerBufferMemoryVariablePointersTest(group.get());
1104
1105 return group.release();
1106 }
1107
1108 } // SpirVAssembly
1109 } // vkt
1110