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::RGBA;
40 using tcu::Vec4;
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 (uint32_t 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 (uint32_t 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 (uint32_t numIdx = 0; numIdx < numFloats / 2; ++numIdx)
372         expectedOutput.push_back(5.0f);
373     for (uint32_t 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 (uint32_t numIdx = 0; numIdx < numFloats / 2; ++numIdx)
501         expectedOutput.push_back(5.0f);
502     for (uint32_t 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 (uint32_t vecIdx = 0; vecIdx < numFloats / 8; ++vecIdx)
662     {
663         const uint32_t shuffleIdx = (vecIdx + 1) % 16;
664         const float val           = (float)(shuffleIdx + 5);
665         for (uint32_t i = 0; i < 4; ++i)
666             expectedOutput.push_back(val);
667     }
668     for (uint32_t vecIdx = 0; vecIdx < numFloats / 8; ++vecIdx)
669     {
670         const uint32_t shuffleIdx = (vecIdx + 1) % 16;
671         const float val           = (float)shuffleIdx;
672         for (uint32_t 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"] = "            %func0_decl = OpTypeFunction %f32 %fp_f32 %fp_f32\n"
714                             "               %c_f32_5 = OpConstant %f32 5\n"
715                             "               %c_f32_2 = OpConstant %f32 2\n"
716                             "                %Output = OpTypeStruct %f32\n"
717                             "   %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
718                             "            %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n"
719                             "      %_ptr_Uniform_f32 = OpTypePointer Uniform %f32\n"
720                             "                  %func = OpFunction %f32 None %func0_decl\n"
721                             "                     %f = OpFunctionParameter %fp_f32\n"
722                             "                     %g = OpFunctionParameter %fp_f32\n"
723                             "            %func_entry = OpLabel\n"
724                             "                          OpStore %g %c_f32_5\n"
725                             "                          OpStore %f %c_f32_2\n"
726                             "                   %ret = OpLoad %f32 %g\n"
727                             "                          OpReturnValue %ret\n"
728                             "                          OpFunctionEnd\n";
729 
730     fragments["decoration"] = "                          OpMemberDecorate %Output 0 Offset 0\n"
731                               "                          OpDecorate %Output BufferBlock\n"
732                               "                          OpDecorate %dataOutput DescriptorSet 0\n"
733                               "                          OpDecorate %dataOutput Binding 0\n"
734                               "                          OpDecorate %f Aliased\n"
735                               "                          OpDecorate %g Aliased\n";
736 
737     fragments["testfun"] = "             %test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
738                            "                 %param = OpFunctionParameter %v4f32\n"
739                            "                 %entry = OpLabel\n"
740                            "                     %a = OpVariable %fp_f32 Function %c_f32_0\n"
741                            "                     %b = OpVariable %fp_f32 Function %c_f32_0\n"
742                            "                     %o = OpVariable %fp_f32 Function %c_f32_0\n"
743                            "                  %ret0 = OpFunctionCall %f32 %func %a %a\n"
744                            "                          OpStore %o %ret0\n"
745                            "                  %ret1 = OpFunctionCall %f32 %func %a %b\n"
746                            "                 %o_val = OpLoad %f32 %o\n"
747                            "                   %sum = OpFAdd %f32 %o_val %ret1\n"
748                            "               %out_ptr = OpAccessChain %_ptr_Uniform_f32 %dataOutput %c_i32_0\n"
749                            "                          OpStore %out_ptr %sum\n"
750                            "                          OpReturnValue %param\n"
751                            "                          OpFunctionEnd\n";
752 
753     getDefaultColors(defaultColors);
754     expectedOutput.push_back(7.0f);
755     requiredFeatures.coreFeatures.vertexPipelineStoresAndAtomics = true;
756     requiredFeatures.coreFeatures.fragmentStoresAndAtomics       = true;
757     resources.outputs.push_back(
758         Resource(BufferSp(new Float32Buffer(expectedOutput)), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
759 
760     createTestsForAllStages("global_to_param", defaultColors, defaultColors, fragments, resources, extensions, group,
761                             requiredFeatures);
762 }
763 
addGraphicsPointerParamToGlobalTest(tcu::TestCaseGroup * group)764 void addGraphicsPointerParamToGlobalTest(tcu::TestCaseGroup *group)
765 {
766     map<string, string> fragments;
767     RGBA defaultColors[4];
768     GraphicsResources resources;
769     vector<string> extensions;
770     vector<float> expectedOutput;
771     VulkanFeatures requiredFeatures;
772 
773     // Implements the following pseudo GLSL shader:
774     //
775     // alias float a = 0.0;
776     //
777     //    float func0(alias float* f0) // f in Private storage class
778     //    {
779     // *a = 5.0;
780     // *f0 = 2.0;
781     // return *a;
782     //    }
783     //
784     //    float func1(alias float* f1) // f in Function storage class
785     //    {
786     // *a = 5.0;
787     // *f1 = 2.0;
788     // return *a;
789     //    }
790     //
791     //    vec4 test_code(vec4 param)
792     //    {
793     //        o = func0(&a);  // should return 2.0
794     // float b = 0.0;
795     //        o += func1(&b); // should return 5.0
796     // return param;
797     //    }
798     fragments["pre_main"] = "                %pp_f32 = OpTypePointer Private %f32\n"
799                             "            %func0_decl = OpTypeFunction %f32 %pp_f32\n"
800                             "            %func1_decl = OpTypeFunction %f32 %fp_f32\n"
801                             "               %c_f32_5 = OpConstant %f32 5\n"
802                             "               %c_f32_2 = OpConstant %f32 2\n"
803                             "                %Output = OpTypeStruct %f32\n"
804                             "   %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
805                             "            %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n"
806                             "      %_ptr_Uniform_f32 = OpTypePointer Uniform %f32\n"
807                             "                     %a = OpVariable %pp_f32 Private %c_f32_0\n"
808                             "                 %func0 = OpFunction %f32 None %func0_decl\n"
809                             "                    %f0 = OpFunctionParameter %pp_f32\n"
810                             "           %func0_entry = OpLabel\n"
811                             "                          OpStore %a %c_f32_5\n"
812                             "                          OpStore %f0 %c_f32_2\n"
813                             "             %func0_ret = OpLoad %f32 %a\n"
814                             "                          OpReturnValue %func0_ret\n"
815                             "                          OpFunctionEnd\n"
816                             "                 %func1 = OpFunction %f32 None %func1_decl\n"
817                             "                    %f1 = OpFunctionParameter %fp_f32\n"
818                             "           %func1_entry = OpLabel\n"
819                             "                          OpStore %a %c_f32_5\n"
820                             "                          OpStore %f1 %c_f32_2\n"
821                             "             %func1_ret = OpLoad %f32 %a\n"
822                             "                          OpReturnValue %func1_ret\n"
823                             "                          OpFunctionEnd\n";
824 
825     fragments["decoration"] = "                          OpMemberDecorate %Output 0 Offset 0\n"
826                               "                          OpDecorate %Output BufferBlock\n"
827                               "                          OpDecorate %dataOutput DescriptorSet 0\n"
828                               "                          OpDecorate %dataOutput Binding 0\n"
829                               "                          OpDecorate %f0 Aliased\n"
830                               "                          OpDecorate %f1 Aliased\n"
831                               "                          OpDecorate %a Aliased\n";
832 
833     fragments["testfun"] = "             %test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
834                            "                 %param = OpFunctionParameter %v4f32\n"
835                            "                 %entry = OpLabel\n"
836                            "                     %b = OpVariable %fp_f32 Function %c_f32_0\n"
837                            "                     %o = OpVariable %fp_f32 Function %c_f32_0\n"
838                            "                  %ret0 = OpFunctionCall %f32 %func0 %a\n"
839                            "                          OpStore %o %ret0\n"
840                            "                  %ret1 = OpFunctionCall %f32 %func1 %b\n"
841                            "                 %o_val = OpLoad %f32 %o\n"
842                            "                   %sum = OpFAdd %f32 %o_val %ret1\n"
843                            "               %out_ptr = OpAccessChain %_ptr_Uniform_f32 %dataOutput %c_i32_0\n"
844                            "                          OpStore %out_ptr %sum\n"
845                            "                          OpReturnValue %param\n"
846                            "                          OpFunctionEnd\n";
847 
848     getDefaultColors(defaultColors);
849     expectedOutput.push_back(7.0f);
850     requiredFeatures.coreFeatures.vertexPipelineStoresAndAtomics = true;
851     requiredFeatures.coreFeatures.fragmentStoresAndAtomics       = true;
852     resources.outputs.push_back(
853         Resource(BufferSp(new Float32Buffer(expectedOutput)), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
854 
855     createTestsForAllStages("param_to_global", defaultColors, defaultColors, fragments, resources, extensions, group,
856                             requiredFeatures);
857 }
858 
addGraphicsPointerBufferMemoryTest(tcu::TestCaseGroup * group)859 void addGraphicsPointerBufferMemoryTest(tcu::TestCaseGroup *group)
860 {
861     const int numFloats = 16;
862     map<string, string> fragments;
863     RGBA defaultColors[4];
864     GraphicsResources resources;
865     vector<string> extensions;
866     vector<float> expectedOutput;
867     VulkanFeatures requiredFeatures;
868 
869     // Implements the following pseudo GLSL shader:
870     //
871     //    layout (binding = 0) buffer Output
872     //    {
873     // vec4 arr0[2];
874     // vec4 arr1[];
875     // } dataOutput;
876     //
877     //    void func0(vec4* f0[2], uint i)
878     //    {
879     // f0[i] = vec4(5.0);
880     //    }
881     //
882     //    void func1(vec4* f1[], uint i)
883     //    {
884     // f1[i] = vec4(2.0);
885     //    }
886     //
887     //    vec4 test_code(vec4 param)
888     //    {
889     // func0(dataOutput.arr0, idx);
890     // func1(dataOutput.arr1, idx);
891     // return param;
892     //    }
893     fragments["pre_main"] = "           %arr_v4f32_2 = OpTypeArray %v4f32 %c_u32_2\n"
894                             "          %arr_v4f32_rt = OpTypeRuntimeArray %v4f32\n"
895                             "       %arr_v4f32_2_ptr = OpTypePointer StorageBuffer %arr_v4f32_2\n"
896                             "      %arr_v4f32_rt_ptr = OpTypePointer StorageBuffer %arr_v4f32_rt\n"
897                             "            %func0_decl = OpTypeFunction %void %arr_v4f32_2_ptr\n"
898                             "            %func1_decl = OpTypeFunction %void %arr_v4f32_rt_ptr\n"
899                             "               %c_f32_5 = OpConstant %f32 5\n"
900                             "               %c_f32_2 = OpConstant %f32 2\n"
901                             "             %c_v4f32_5 = OpConstantComposite %v4f32 %c_f32_5 %c_f32_5 %c_f32_5 %c_f32_5\n"
902                             "             %c_v4f32_2 = OpConstantComposite %v4f32 %c_f32_2 %c_f32_2 %c_f32_2 %c_f32_2\n"
903                             "                %Output = OpTypeStruct %arr_v4f32_2 %arr_v4f32_rt\n"
904                             "        %_ptr_sb_Output = OpTypePointer StorageBuffer %Output\n"
905                             "            %dataOutput = OpVariable %_ptr_sb_Output StorageBuffer\n"
906                             "         %_ptr_sb_v4f32 = OpTypePointer StorageBuffer %v4f32\n"
907                             "                 %func0 = OpFunction %void None %func0_decl\n"
908                             "                    %f0 = OpFunctionParameter %arr_v4f32_2_ptr\n"
909                             "            %func0Entry = OpLabel\n"
910                             "              %out_ptr0 = OpAccessChain %_ptr_sb_v4f32 %f0 %c_i32_0\n"
911                             "                          OpStore %out_ptr0 %c_v4f32_5\n"
912                             "              %out_ptr1 = OpAccessChain %_ptr_sb_v4f32 %f0 %c_i32_1\n"
913                             "                          OpStore %out_ptr1 %c_v4f32_5\n"
914                             "                          OpReturn\n"
915                             "                          OpFunctionEnd\n"
916                             "                 %func1 = OpFunction %void None %func1_decl\n"
917                             "                    %f1 = OpFunctionParameter %arr_v4f32_rt_ptr\n"
918                             "            %func1Entry = OpLabel\n"
919                             "              %out_ptr2 = OpAccessChain %_ptr_sb_v4f32 %f1 %c_i32_0\n"
920                             "                          OpStore %out_ptr2 %c_v4f32_2\n"
921                             "              %out_ptr3 = OpAccessChain %_ptr_sb_v4f32 %f1 %c_i32_1\n"
922                             "                          OpStore %out_ptr3 %c_v4f32_2\n"
923                             "                          OpReturn\n"
924                             "                          OpFunctionEnd\n";
925 
926     fragments["decoration"] = "                          OpMemberDecorate %Output 0 Offset 0\n"
927                               "                          OpMemberDecorate %Output 1 Offset 32\n"
928                               "                          OpDecorate %Output Block\n"
929                               "                          OpDecorate %dataOutput DescriptorSet 0\n"
930                               "                          OpDecorate %dataOutput Binding 0\n"
931                               "                          OpDecorate %arr_v4f32_2 ArrayStride 16\n"
932                               "                          OpDecorate %arr_v4f32_rt ArrayStride 16\n";
933 
934     fragments["testfun"] = "             %test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
935                            "                 %param = OpFunctionParameter %v4f32\n"
936                            "                 %entry = OpLabel\n"
937                            "                  %ptr0 = OpAccessChain %arr_v4f32_2_ptr %dataOutput %c_i32_0\n"
938                            "                  %ptr1 = OpAccessChain %arr_v4f32_rt_ptr %dataOutput %c_i32_1\n"
939                            "                  %ret0 = OpFunctionCall %void %func0 %ptr0\n"
940                            "                  %ret1 = OpFunctionCall %void %func1 %ptr1\n"
941                            "                          OpReturnValue %param\n"
942                            "                          OpFunctionEnd\n";
943 
944     fragments["extension"] = "OpExtension \"SPV_KHR_storage_buffer_storage_class\"\n"
945                              "OpExtension \"SPV_KHR_variable_pointers\"\n";
946 
947     fragments["capability"] = "OpCapability VariablePointersStorageBuffer\n";
948 
949     getDefaultColors(defaultColors);
950 
951     for (uint32_t numIdx = 0; numIdx < numFloats / 2; ++numIdx)
952         expectedOutput.push_back(5.0f);
953     for (uint32_t numIdx = 0; numIdx < numFloats / 2; ++numIdx)
954         expectedOutput.push_back(2.0f);
955 
956     extensions.push_back("VK_KHR_variable_pointers");
957     requiredFeatures.coreFeatures.vertexPipelineStoresAndAtomics       = true;
958     requiredFeatures.coreFeatures.fragmentStoresAndAtomics             = true;
959     requiredFeatures.extVariablePointers.variablePointersStorageBuffer = true;
960     resources.outputs.push_back(
961         Resource(BufferSp(new Float32Buffer(expectedOutput)), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
962 
963     createTestsForAllStages("buffer_memory", defaultColors, defaultColors, fragments, resources, extensions, group,
964                             requiredFeatures);
965 }
966 
addGraphicsPointerBufferMemoryVariablePointersTest(tcu::TestCaseGroup * group)967 void addGraphicsPointerBufferMemoryVariablePointersTest(tcu::TestCaseGroup *group)
968 {
969     const int numFloats = 16;
970     map<string, string> fragments;
971     RGBA defaultColors[4];
972     GraphicsResources resources;
973     vector<string> extensions;
974     vector<float> expectedOutput;
975     VulkanFeatures requiredFeatures;
976 
977     // Implements the following pseudo GLSL shader:
978     //
979     //    layout (binding = 0) buffer Output
980     //    {
981     // vec4 arr0[2];
982     // vec4 arr1[];
983     // } dataOutput;
984     //
985     //    void func0(vec4* f0[2], uint i)
986     //    {
987     // f0[i] = vec4(5.0);
988     //    }
989     //
990     //    void func1(vec4* f1[], uint i)
991     //    {
992     // f1[i] = vec4(2.0);
993     //    }
994     //
995     //    vec4 test_code(vec4 param)
996     //    {
997     // func0(dataOutput.arr0, idx);
998     // func1(dataOutput.arr1, idx);
999     // return param;
1000     //    }
1001     fragments["pre_main"] = "           %arr_v4f32_2 = OpTypeArray %v4f32 %c_u32_2\n"
1002                             "          %arr_v4f32_rt = OpTypeRuntimeArray %v4f32\n"
1003                             "       %arr_v4f32_2_ptr = OpTypePointer StorageBuffer %arr_v4f32_2\n"
1004                             "      %arr_v4f32_rt_ptr = OpTypePointer StorageBuffer %arr_v4f32_rt\n"
1005                             "            %func0_decl = OpTypeFunction %void %arr_v4f32_2_ptr\n"
1006                             "            %func1_decl = OpTypeFunction %void %arr_v4f32_rt_ptr\n"
1007                             "               %c_f32_5 = OpConstant %f32 5\n"
1008                             "               %c_f32_2 = OpConstant %f32 2\n"
1009                             "             %c_v4f32_5 = OpConstantComposite %v4f32 %c_f32_5 %c_f32_5 %c_f32_5 %c_f32_5\n"
1010                             "             %c_v4f32_2 = OpConstantComposite %v4f32 %c_f32_2 %c_f32_2 %c_f32_2 %c_f32_2\n"
1011                             "                %Output = OpTypeStruct %arr_v4f32_2 %arr_v4f32_rt\n"
1012                             "        %_ptr_sb_Output = OpTypePointer StorageBuffer %Output\n"
1013                             "            %dataOutput = OpVariable %_ptr_sb_Output StorageBuffer\n"
1014                             "         %_ptr_sb_v4f32 = OpTypePointer StorageBuffer %v4f32\n"
1015                             "                 %func0 = OpFunction %void None %func0_decl\n"
1016                             "                    %f0 = OpFunctionParameter %arr_v4f32_2_ptr\n"
1017                             "            %func0Entry = OpLabel\n"
1018                             "              %out_ptr0 = OpAccessChain %_ptr_sb_v4f32 %f0 %c_i32_0\n"
1019                             "                          OpStore %out_ptr0 %c_v4f32_5\n"
1020                             "              %out_ptr1 = OpAccessChain %_ptr_sb_v4f32 %f0 %c_i32_1\n"
1021                             "                          OpStore %out_ptr1 %c_v4f32_5\n"
1022                             "                          OpReturn\n"
1023                             "                          OpFunctionEnd\n"
1024                             "                 %func1 = OpFunction %void None %func1_decl\n"
1025                             "                    %f1 = OpFunctionParameter %arr_v4f32_rt_ptr\n"
1026                             "            %func1Entry = OpLabel\n"
1027                             "              %out_ptr2 = OpAccessChain %_ptr_sb_v4f32 %f1 %c_i32_0\n"
1028                             "                          OpStore %out_ptr2 %c_v4f32_2\n"
1029                             "              %out_ptr3 = OpAccessChain %_ptr_sb_v4f32 %f1 %c_i32_1\n"
1030                             "                          OpStore %out_ptr3 %c_v4f32_2\n"
1031                             "                          OpReturn\n"
1032                             "                          OpFunctionEnd\n";
1033 
1034     fragments["decoration"] = "                          OpMemberDecorate %Output 0 Offset 0\n"
1035                               "                          OpMemberDecorate %Output 1 Offset 32\n"
1036                               "                          OpDecorate %Output Block\n"
1037                               "                          OpDecorate %dataOutput DescriptorSet 0\n"
1038                               "                          OpDecorate %dataOutput Binding 0\n"
1039                               "                          OpDecorate %arr_v4f32_2 ArrayStride 16\n"
1040                               "                          OpDecorate %arr_v4f32_rt ArrayStride 16\n";
1041 
1042     fragments["testfun"] = "             %test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
1043                            "                 %param = OpFunctionParameter %v4f32\n"
1044                            "                 %entry = OpLabel\n"
1045                            "                  %ptr0 = OpAccessChain %arr_v4f32_2_ptr %dataOutput %c_i32_0\n"
1046                            "                  %ptr1 = OpAccessChain %arr_v4f32_rt_ptr %dataOutput %c_i32_1\n"
1047                            "                  %ret0 = OpFunctionCall %void %func0 %ptr0\n"
1048                            "                  %ret1 = OpFunctionCall %void %func1 %ptr1\n"
1049                            "                          OpReturnValue %param\n"
1050                            "                          OpFunctionEnd\n";
1051 
1052     fragments["extension"] = "OpExtension \"SPV_KHR_variable_pointers\"\n"
1053                              "OpExtension \"SPV_KHR_storage_buffer_storage_class\"\n";
1054 
1055     fragments["capability"] = "OpCapability VariablePointersStorageBuffer\n";
1056 
1057     getDefaultColors(defaultColors);
1058 
1059     for (uint32_t numIdx = 0; numIdx < numFloats / 2; ++numIdx)
1060         expectedOutput.push_back(5.0f);
1061     for (uint32_t numIdx = 0; numIdx < numFloats / 2; ++numIdx)
1062         expectedOutput.push_back(2.0f);
1063 
1064     extensions.push_back("VK_KHR_variable_pointers");
1065     requiredFeatures.coreFeatures.fragmentStoresAndAtomics             = true;
1066     requiredFeatures.extVariablePointers.variablePointersStorageBuffer = true;
1067     requiredFeatures.coreFeatures.vertexPipelineStoresAndAtomics       = true;
1068     resources.outputs.push_back(
1069         Resource(BufferSp(new Float32Buffer(expectedOutput)), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
1070 
1071     createTestsForAllStages("buffer_memory_variable_pointers", defaultColors, defaultColors, fragments, resources,
1072                             extensions, group, requiredFeatures);
1073 }
1074 
1075 } // namespace
1076 
createPointerParameterComputeGroup(tcu::TestContext & testCtx)1077 tcu::TestCaseGroup *createPointerParameterComputeGroup(tcu::TestContext &testCtx)
1078 {
1079     // Compute tests for pointer as function parameter.
1080     de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "pointer_parameter"));
1081     addComputePointerParamToParamTest(group.get());
1082     addComputePointerParamToGlobalTest(group.get());
1083     addComputePointerBufferMemoryTest(group.get());
1084     addComputePointerBufferMemoryVariablePointersTest(group.get());
1085     addComputePointerWorkgroupMemoryVariablePointersTest(group.get());
1086 
1087     return group.release();
1088 }
1089 
createPointerParameterGraphicsGroup(tcu::TestContext & testCtx)1090 tcu::TestCaseGroup *createPointerParameterGraphicsGroup(tcu::TestContext &testCtx)
1091 {
1092     // Graphics tests for pointer as function parameter.
1093     de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "pointer_parameter"));
1094     addGraphicsPointerParamToParamTest(group.get());
1095     addGraphicsPointerParamToGlobalTest(group.get());
1096     addGraphicsPointerBufferMemoryTest(group.get());
1097     addGraphicsPointerBufferMemoryVariablePointersTest(group.get());
1098 
1099     return group.release();
1100 }
1101 
1102 } // namespace SpirVAssembly
1103 } // namespace vkt
1104