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