| /*------------------------------------------------------------------------- |
| * Vulkan Conformance Tests |
| * ------------------------ |
| * |
| * Copyright (c) 2018 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| *//*! |
| * \file |
| * \brief SPIR-V Assembly Tests for pointers as function parameters. |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "vktSpvAsmPointerParameterTests.hpp" |
| #include "vktSpvAsmComputeShaderCase.hpp" |
| #include "vktSpvAsmComputeShaderTestUtil.hpp" |
| #include "vktSpvAsmGraphicsShaderTestUtil.hpp" |
| |
| namespace vkt |
| { |
| namespace SpirVAssembly |
| { |
| |
| using namespace vk; |
| using std::map; |
| using std::string; |
| using std::vector; |
| using tcu::IVec3; |
| using tcu::Vec4; |
| using tcu::RGBA; |
| |
| namespace |
| { |
| |
| void addComputePointerParamToParamTest (tcu::TestCaseGroup* group) |
| { |
| tcu::TestContext& testCtx = group->getTestContext(); |
| const int numFloats = 128; |
| ComputeShaderSpec spec; |
| vector<float> expectedOutput; |
| |
| // Implements the following pseudo GLSL shader: |
| // |
| // float func(alias float* f, alias float* g) |
| // { |
| // *g = 5.0; |
| // *f = 2.0; |
| // return *g; |
| // } |
| // |
| // void main() |
| // { |
| // float a = 0.0; |
| // o = func(&a, &a); // should return 2.0 |
| // float b = 0.0; |
| // o += func(&a, &b); // should return 5.0 |
| // } |
| const string shaderSource = |
| " OpCapability Shader\n" |
| " %1 = OpExtInstImport \"GLSL.std.450\"\n" |
| " OpMemoryModel Logical GLSL450\n" |
| " OpEntryPoint GLCompute %main \"main\" %gl_GlobalInvocationID\n" |
| " OpExecutionMode %main LocalSize 1 1 1\n" |
| " OpSource GLSL 430\n" |
| " OpDecorate %_arr_float_uint_128 ArrayStride 4\n" |
| " OpMemberDecorate %Output 0 Offset 0\n" |
| " OpDecorate %Output BufferBlock\n" |
| " OpDecorate %dataOutput DescriptorSet 0\n" |
| " OpDecorate %dataOutput Binding 0\n" |
| " OpDecorate %f Aliased\n" |
| " OpDecorate %g Aliased\n" |
| " OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId\n" |
| " %void = OpTypeVoid\n" |
| " %void_func = OpTypeFunction %void\n" |
| " %float = OpTypeFloat 32\n" |
| " %_ptr_Function_float = OpTypePointer Function %float\n" |
| " %func0_decl = OpTypeFunction %float %_ptr_Function_float %_ptr_Function_float\n" |
| " %float_0 = OpConstant %float 0\n" |
| " %float_5 = OpConstant %float 5\n" |
| " %float_2 = OpConstant %float 2\n" |
| " %uint = OpTypeInt 32 0\n" |
| " %uint_128 = OpConstant %uint 128\n" |
| " %_arr_float_uint_128 = OpTypeArray %float %uint_128\n" |
| " %Output = OpTypeStruct %_arr_float_uint_128\n" |
| " %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n" |
| " %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n" |
| " %int = OpTypeInt 32 1\n" |
| " %int_0 = OpConstant %int 0\n" |
| " %v3uint = OpTypeVector %uint 3\n" |
| " %_ptr_Input_v3uint = OpTypePointer Input %v3uint\n" |
| " %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input\n" |
| " %uint_0 = OpConstant %uint 0\n" |
| " %_ptr_Input_uint = OpTypePointer Input %uint\n" |
| " %_ptr_Uniform_float = OpTypePointer Uniform %float\n" |
| " %main = OpFunction %void None %void_func\n" |
| " %entry = OpLabel\n" |
| " %a = OpVariable %_ptr_Function_float Function %float_0\n" |
| " %b = OpVariable %_ptr_Function_float Function %float_0\n" |
| " %o = OpVariable %_ptr_Function_float Function %float_0\n" |
| " %ret0 = OpFunctionCall %float %func %a %a\n" |
| " OpStore %o %ret0\n" |
| " %ret1 = OpFunctionCall %float %func %a %b\n" |
| " %o_val = OpLoad %float %o\n" |
| " %sum = OpFAdd %float %o_val %ret1\n" |
| " %inv_id_ptr = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %uint_0\n" |
| " %inv_id = OpLoad %uint %inv_id_ptr\n" |
| " %out_ptr = OpAccessChain %_ptr_Uniform_float %dataOutput %int_0 %inv_id\n" |
| " OpStore %out_ptr %sum\n" |
| " OpReturn\n" |
| " OpFunctionEnd\n" |
| " %func = OpFunction %float None %func0_decl\n" |
| " %f = OpFunctionParameter %_ptr_Function_float\n" |
| " %g = OpFunctionParameter %_ptr_Function_float\n" |
| " %func_entry = OpLabel\n" |
| " OpStore %g %float_5\n" |
| " OpStore %f %float_2\n" |
| " %ret = OpLoad %float %g\n" |
| " OpReturnValue %ret\n" |
| " OpFunctionEnd\n"; |
| |
| expectedOutput.reserve(numFloats); |
| for (deUint32 numIdx = 0; numIdx < numFloats; ++numIdx) |
| expectedOutput.push_back(7.0f); |
| |
| spec.outputs.push_back(BufferSp(new Float32Buffer(expectedOutput))); |
| |
| spec.assembly = shaderSource; |
| spec.numWorkGroups = IVec3(numFloats, 1, 1); |
| |
| group->addChild(new SpvAsmComputeShaderCase(testCtx, "param_to_param", "", spec)); |
| } |
| |
| void addComputePointerParamToGlobalTest (tcu::TestCaseGroup* group) |
| { |
| tcu::TestContext& testCtx = group->getTestContext(); |
| const int numFloats = 128; |
| ComputeShaderSpec spec; |
| vector<float> expectedOutput; |
| |
| // Implements the following pseudo GLSL shader: |
| // |
| // alias float a = 0.0; |
| // |
| // float func0(alias float* f0) // f in Private storage class |
| // { |
| // *a = 5.0; |
| // *f0 = 2.0; |
| // return *a; |
| // } |
| // |
| // float func1(alias float* f1) // f in Function storage class |
| // { |
| // *a = 5.0; |
| // *f1 = 2.0; |
| // return *a; |
| // } |
| // |
| // void main() |
| // { |
| // o = func0(&a); // should return 2.0 |
| // float b = 0.0; |
| // o += func1(&b); // should return 5.0 |
| // } |
| const string shaderSource = |
| " OpCapability Shader\n" |
| " %1 = OpExtInstImport \"GLSL.std.450\"\n" |
| " OpMemoryModel Logical GLSL450\n" |
| " OpEntryPoint GLCompute %main \"main\" %gl_GlobalInvocationID\n" |
| " OpExecutionMode %main LocalSize 1 1 1\n" |
| " OpSource GLSL 430\n" |
| " OpDecorate %_arr_float_uint_128 ArrayStride 4\n" |
| " OpMemberDecorate %Output 0 Offset 0\n" |
| " OpDecorate %Output BufferBlock\n" |
| " OpDecorate %dataOutput DescriptorSet 0\n" |
| " OpDecorate %dataOutput Binding 0\n" |
| " OpDecorate %f0 Aliased\n" |
| " OpDecorate %f1 Aliased\n" |
| " OpDecorate %a Aliased\n" |
| " OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId\n" |
| " %void = OpTypeVoid\n" |
| " %void_func = OpTypeFunction %void\n" |
| " %float = OpTypeFloat 32\n" |
| " %_ptr_Function_float = OpTypePointer Function %float\n" |
| " %_ptr_Private_float = OpTypePointer Private %float\n" |
| " %func0_decl = OpTypeFunction %float %_ptr_Private_float\n" |
| " %func1_decl = OpTypeFunction %float %_ptr_Function_float\n" |
| " %float_0 = OpConstant %float 0\n" |
| " %float_5 = OpConstant %float 5\n" |
| " %float_2 = OpConstant %float 2\n" |
| " %uint = OpTypeInt 32 0\n" |
| " %uint_128 = OpConstant %uint 128\n" |
| " %_arr_float_uint_128 = OpTypeArray %float %uint_128\n" |
| " %Output = OpTypeStruct %_arr_float_uint_128\n" |
| " %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n" |
| " %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n" |
| " %int = OpTypeInt 32 1\n" |
| " %int_0 = OpConstant %int 0\n" |
| " %v3uint = OpTypeVector %uint 3\n" |
| " %_ptr_Input_v3uint = OpTypePointer Input %v3uint\n" |
| " %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input\n" |
| " %uint_0 = OpConstant %uint 0\n" |
| " %_ptr_Input_uint = OpTypePointer Input %uint\n" |
| " %_ptr_Uniform_float = OpTypePointer Uniform %float\n" |
| " %a = OpVariable %_ptr_Private_float Private %float_0\n" |
| " %main = OpFunction %void None %void_func\n" |
| " %entry = OpLabel\n" |
| " %b = OpVariable %_ptr_Function_float Function %float_0\n" |
| " %o = OpVariable %_ptr_Function_float Function %float_0\n" |
| " %ret0 = OpFunctionCall %float %func0 %a\n" |
| " OpStore %o %ret0\n" |
| " %ret1 = OpFunctionCall %float %func1 %b\n" |
| " %o_val = OpLoad %float %o\n" |
| " %sum = OpFAdd %float %o_val %ret1\n" |
| " %inv_id_ptr = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %uint_0\n" |
| " %inv_id = OpLoad %uint %inv_id_ptr\n" |
| " %out_ptr = OpAccessChain %_ptr_Uniform_float %dataOutput %int_0 %inv_id\n" |
| " OpStore %out_ptr %sum\n" |
| " OpReturn\n" |
| " OpFunctionEnd\n" |
| " %func0 = OpFunction %float None %func0_decl\n" |
| " %f0 = OpFunctionParameter %_ptr_Private_float\n" |
| " %func0_entry = OpLabel\n" |
| " OpStore %a %float_5\n" |
| " OpStore %f0 %float_2\n" |
| " %func0_ret = OpLoad %float %a\n" |
| " OpReturnValue %func0_ret\n" |
| " OpFunctionEnd\n" |
| " %func1 = OpFunction %float None %func1_decl\n" |
| " %f1 = OpFunctionParameter %_ptr_Function_float\n" |
| " %func1_entry = OpLabel\n" |
| " OpStore %a %float_5\n" |
| " OpStore %f1 %float_2\n" |
| " %func1_ret = OpLoad %float %a\n" |
| " OpReturnValue %func1_ret\n" |
| " OpFunctionEnd\n"; |
| |
| expectedOutput.reserve(numFloats); |
| for (deUint32 numIdx = 0; numIdx < numFloats; ++numIdx) |
| expectedOutput.push_back(7.0f); |
| |
| spec.outputs.push_back(BufferSp(new Float32Buffer(expectedOutput))); |
| |
| spec.assembly = shaderSource; |
| spec.numWorkGroups = IVec3(numFloats, 1, 1); |
| |
| group->addChild(new SpvAsmComputeShaderCase(testCtx, "param_to_global", "", spec)); |
| } |
| |
| void addComputePointerBufferMemoryTest (tcu::TestCaseGroup* group) |
| { |
| tcu::TestContext& testCtx = group->getTestContext(); |
| const int numFloats = 128; |
| ComputeShaderSpec spec; |
| vector<float> expectedOutput; |
| VulkanFeatures requiredFeatures; |
| |
| // Implements the following pseudo GLSL shader: |
| // |
| // layout (binding = 0) buffer Output |
| // { |
| // vec4 arr0[16]; |
| // vec4 arr1[]; |
| // } dataOutput; |
| // |
| // void func0(vec4* f0[16], uint i) |
| // { |
| // f0[i] = vec4(5.0); |
| // } |
| // |
| // void func1(vec4* f1[], uint i) |
| // { |
| // f1[i] = vec4(2.0); |
| // } |
| // |
| // void main() |
| // { |
| // uint idx = gl_GlobalInvocationID.x; |
| // func0(dataOutput.arr0, idx); |
| // func1(dataOutput.arr1, idx); |
| // } |
| const string shaderSource = |
| " OpCapability Shader\n" |
| " OpCapability VariablePointersStorageBuffer\n" |
| " OpExtension \"SPV_KHR_storage_buffer_storage_class\"\n" |
| " OpExtension \"SPV_KHR_variable_pointers\"\n" |
| " %1 = OpExtInstImport \"GLSL.std.450\"\n" |
| " OpMemoryModel Logical GLSL450\n" |
| " OpEntryPoint GLCompute %main \"main\" %gl_GlobalInvocationID\n" |
| " OpExecutionMode %main LocalSize 1 1 1\n" |
| " OpSource GLSL 430\n" |
| " OpMemberDecorate %Output 0 Offset 0\n" |
| " OpMemberDecorate %Output 1 Offset 256\n" |
| " OpDecorate %arr_vec4_16 ArrayStride 16\n" |
| " OpDecorate %arr_vec4_rt ArrayStride 16\n" |
| " OpDecorate %Output Block\n" |
| " OpDecorate %dataOutput DescriptorSet 0\n" |
| " OpDecorate %dataOutput Binding 0\n" |
| " OpDecorate %f0 DescriptorSet 0\n" |
| " OpDecorate %f0 Binding 0\n" |
| " OpDecorate %f1 DescriptorSet 0\n" |
| " OpDecorate %f1 Binding 0\n" |
| " OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId\n" |
| " %void = OpTypeVoid\n" |
| " %void_func = OpTypeFunction %void\n" |
| " %float = OpTypeFloat 32\n" |
| " %_ptr_Function_float = OpTypePointer Function %float\n" |
| " %float_5 = OpConstant %float 5\n" |
| " %float_2 = OpConstant %float 2\n" |
| " %uint = OpTypeInt 32 0\n" |
| " %_ptr_Function_uint = OpTypePointer Function %uint\n" |
| " %uint_16 = OpConstant %uint 16\n" |
| " %vec4 = OpTypeVector %float 4\n" |
| " %vec4_5 = OpConstantComposite %vec4 %float_5 %float_5 %float_5 %float_5\n" |
| " %vec4_2 = OpConstantComposite %vec4 %float_2 %float_2 %float_2 %float_2\n" |
| " %arr_vec4_16 = OpTypeArray %vec4 %uint_16\n" |
| " %arr_vec4_rt = OpTypeRuntimeArray %vec4\n" |
| " %arr_vec4_16_ptr = OpTypePointer StorageBuffer %arr_vec4_16\n" |
| " %arr_vec4_rt_ptr = OpTypePointer StorageBuffer %arr_vec4_rt\n" |
| " %func0_decl = OpTypeFunction %void %arr_vec4_16_ptr %_ptr_Function_uint\n" |
| " %func1_decl = OpTypeFunction %void %arr_vec4_rt_ptr %_ptr_Function_uint\n" |
| " %Output = OpTypeStruct %arr_vec4_16 %arr_vec4_rt\n" |
| " %_ptr_sb_Output = OpTypePointer StorageBuffer %Output\n" |
| " %dataOutput = OpVariable %_ptr_sb_Output StorageBuffer\n" |
| " %int = OpTypeInt 32 1\n" |
| " %int_0 = OpConstant %int 0\n" |
| " %int_1 = OpConstant %int 1\n" |
| " %v3uint = OpTypeVector %uint 3\n" |
| " %_ptr_Input_v3uint = OpTypePointer Input %v3uint\n" |
| " %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input\n" |
| " %uint_0 = OpConstant %uint 0\n" |
| " %_ptr_Input_uint = OpTypePointer Input %uint\n" |
| " %_ptr_sb_vec4 = OpTypePointer StorageBuffer %vec4\n" |
| " %main = OpFunction %void None %void_func\n" |
| " %entry = OpLabel\n" |
| " %idx = OpVariable %_ptr_Function_uint Function\n" |
| " %inv_id_ptr = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %uint_0\n" |
| " %inv_id = OpLoad %uint %inv_id_ptr\n" |
| " OpStore %idx %inv_id\n" |
| " %ptr0 = OpAccessChain %arr_vec4_16_ptr %dataOutput %int_0\n" |
| " %ptr1 = OpAccessChain %arr_vec4_rt_ptr %dataOutput %int_1\n" |
| " %ret0 = OpFunctionCall %void %func0 %ptr0 %idx\n" |
| " %ret1 = OpFunctionCall %void %func1 %ptr1 %idx\n" |
| " OpReturn\n" |
| " OpFunctionEnd\n" |
| " %func0 = OpFunction %void None %func0_decl\n" |
| " %f0 = OpFunctionParameter %arr_vec4_16_ptr\n" |
| " %i0 = OpFunctionParameter %_ptr_Function_uint\n" |
| " %func0_entry = OpLabel\n" |
| " %idx0 = OpLoad %uint %i0\n" |
| " %out_ptr0 = OpAccessChain %_ptr_sb_vec4 %f0 %idx0\n" |
| " OpStore %out_ptr0 %vec4_5\n" |
| " OpReturn\n" |
| " OpFunctionEnd\n" |
| " %func1 = OpFunction %void None %func1_decl\n" |
| " %f1 = OpFunctionParameter %arr_vec4_rt_ptr\n" |
| " %i1 = OpFunctionParameter %_ptr_Function_uint\n" |
| " %func1_entry = OpLabel\n" |
| " %idx1 = OpLoad %uint %i1\n" |
| " %out_ptr1 = OpAccessChain %_ptr_sb_vec4 %f1 %idx1\n" |
| " OpStore %out_ptr1 %vec4_2\n" |
| " OpReturn\n" |
| " OpFunctionEnd\n"; |
| |
| expectedOutput.reserve(numFloats); |
| for (deUint32 numIdx = 0; numIdx < numFloats / 2; ++numIdx) |
| expectedOutput.push_back(5.0f); |
| for (deUint32 numIdx = 0; numIdx < numFloats / 2; ++numIdx) |
| expectedOutput.push_back(2.0f); |
| |
| requiredFeatures.extVariablePointers = EXTVARIABLEPOINTERSFEATURES_VARIABLE_POINTERS_STORAGEBUFFER; |
| |
| spec.outputs.push_back(BufferSp(new Float32Buffer(expectedOutput))); |
| |
| spec.assembly = shaderSource; |
| spec.numWorkGroups = IVec3(16, 1, 1); |
| spec.requestedVulkanFeatures = requiredFeatures; |
| spec.extensions.push_back("VK_KHR_variable_pointers"); |
| |
| group->addChild(new SpvAsmComputeShaderCase(testCtx, "buffer_memory", "", spec)); |
| } |
| |
| void addComputePointerBufferMemoryVariablePointersTest (tcu::TestCaseGroup* group) |
| { |
| tcu::TestContext& testCtx = group->getTestContext(); |
| const int numFloats = 128; |
| ComputeShaderSpec spec; |
| VulkanFeatures requiredFeatures; |
| vector<float> expectedOutput; |
| |
| // Implements the following pseudo GLSL shader: |
| // |
| // layout (binding = 0) buffer Output |
| // { |
| // vec4 arr0[16]; |
| // vec4 arr1[]; |
| // } dataOutput; |
| // |
| // void func0(vec4* f0[16], uint i) |
| // { |
| // f0[i] = vec4(5.0); |
| // } |
| // |
| // void func1(vec4* f1[], uint i) |
| // { |
| // f1[i] = vec4(2.0); |
| // } |
| // |
| // void main() |
| // { |
| // uint idx = gl_GlobalInvocationID.x; |
| // func0(dataOutput.arr0, idx); |
| // func1(dataOutput.arr1, idx); |
| // } |
| const string shaderSource = |
| " OpCapability Shader\n" |
| " OpCapability VariablePointersStorageBuffer\n" |
| " OpExtension \"SPV_KHR_variable_pointers\"\n" |
| " OpExtension \"SPV_KHR_storage_buffer_storage_class\"\n" |
| " %1 = OpExtInstImport \"GLSL.std.450\"\n" |
| " OpMemoryModel Logical GLSL450\n" |
| " OpEntryPoint GLCompute %main \"main\" %gl_GlobalInvocationID\n" |
| " OpExecutionMode %main LocalSize 1 1 1\n" |
| " OpSource GLSL 430\n" |
| " OpMemberDecorate %Output 0 Offset 0\n" |
| " OpMemberDecorate %Output 1 Offset 256\n" |
| " OpDecorate %arr_vec4_16 ArrayStride 16\n" |
| " OpDecorate %arr_vec4_rt ArrayStride 16\n" |
| " OpDecorate %Output Block\n" |
| " OpDecorate %dataOutput DescriptorSet 0\n" |
| " OpDecorate %dataOutput Binding 0\n" |
| " OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId\n" |
| " %void = OpTypeVoid\n" |
| " %void_func = OpTypeFunction %void\n" |
| " %float = OpTypeFloat 32\n" |
| " %_ptr_Function_float = OpTypePointer Function %float\n" |
| " %float_5 = OpConstant %float 5\n" |
| " %float_2 = OpConstant %float 2\n" |
| " %uint = OpTypeInt 32 0\n" |
| " %_ptr_Function_uint = OpTypePointer Function %uint\n" |
| " %uint_16 = OpConstant %uint 16\n" |
| " %vec4 = OpTypeVector %float 4\n" |
| " %vec4_5 = OpConstantComposite %vec4 %float_5 %float_5 %float_5 %float_5\n" |
| " %vec4_2 = OpConstantComposite %vec4 %float_2 %float_2 %float_2 %float_2\n" |
| " %arr_vec4_16 = OpTypeArray %vec4 %uint_16\n" |
| " %arr_vec4_rt = OpTypeRuntimeArray %vec4\n" |
| " %arr_vec4_16_ptr = OpTypePointer StorageBuffer %arr_vec4_16\n" |
| " %arr_vec4_rt_ptr = OpTypePointer StorageBuffer %arr_vec4_rt\n" |
| " %func0_decl = OpTypeFunction %void %arr_vec4_16_ptr %_ptr_Function_uint\n" |
| " %func1_decl = OpTypeFunction %void %arr_vec4_rt_ptr %_ptr_Function_uint\n" |
| " %Output = OpTypeStruct %arr_vec4_16 %arr_vec4_rt\n" |
| " %_ptr_sb_Output = OpTypePointer StorageBuffer %Output\n" |
| " %dataOutput = OpVariable %_ptr_sb_Output StorageBuffer\n" |
| " %int = OpTypeInt 32 1\n" |
| " %int_0 = OpConstant %int 0\n" |
| " %int_1 = OpConstant %int 1\n" |
| " %v3uint = OpTypeVector %uint 3\n" |
| " %_ptr_Input_v3uint = OpTypePointer Input %v3uint\n" |
| " %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input\n" |
| " %uint_0 = OpConstant %uint 0\n" |
| " %_ptr_Input_uint = OpTypePointer Input %uint\n" |
| " %_ptr_sb_vec4 = OpTypePointer StorageBuffer %vec4\n" |
| " %main = OpFunction %void None %void_func\n" |
| " %entry = OpLabel\n" |
| " %idx = OpVariable %_ptr_Function_uint Function\n" |
| " %inv_id_ptr = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %uint_0\n" |
| " %inv_id = OpLoad %uint %inv_id_ptr\n" |
| " OpStore %idx %inv_id\n" |
| " %ptr0 = OpAccessChain %arr_vec4_16_ptr %dataOutput %int_0\n" |
| " %ptr1 = OpAccessChain %arr_vec4_rt_ptr %dataOutput %int_1\n" |
| " %ret0 = OpFunctionCall %void %func0 %ptr0 %idx\n" |
| " %ret1 = OpFunctionCall %void %func1 %ptr1 %idx\n" |
| " OpReturn\n" |
| " OpFunctionEnd\n" |
| " %func0 = OpFunction %void None %func0_decl\n" |
| " %f0 = OpFunctionParameter %arr_vec4_16_ptr\n" |
| " %i0 = OpFunctionParameter %_ptr_Function_uint\n" |
| " %func0_entry = OpLabel\n" |
| " %idx0 = OpLoad %uint %i0\n" |
| " %out_ptr0 = OpAccessChain %_ptr_sb_vec4 %f0 %idx0\n" |
| " OpStore %out_ptr0 %vec4_5\n" |
| " OpReturn\n" |
| " OpFunctionEnd\n" |
| " %func1 = OpFunction %void None %func1_decl\n" |
| " %f1 = OpFunctionParameter %arr_vec4_rt_ptr\n" |
| " %i1 = OpFunctionParameter %_ptr_Function_uint\n" |
| " %func1_entry = OpLabel\n" |
| " %idx1 = OpLoad %uint %i1\n" |
| " %out_ptr1 = OpAccessChain %_ptr_sb_vec4 %f1 %idx1\n" |
| " OpStore %out_ptr1 %vec4_2\n" |
| " OpReturn\n" |
| " OpFunctionEnd\n"; |
| |
| expectedOutput.reserve(numFloats); |
| for (deUint32 numIdx = 0; numIdx < numFloats / 2; ++numIdx) |
| expectedOutput.push_back(5.0f); |
| for (deUint32 numIdx = 0; numIdx < numFloats / 2; ++numIdx) |
| expectedOutput.push_back(2.0f); |
| |
| requiredFeatures.extVariablePointers = EXTVARIABLEPOINTERSFEATURES_VARIABLE_POINTERS_STORAGEBUFFER; |
| spec.outputs.push_back(BufferSp(new Float32Buffer(expectedOutput))); |
| spec.extensions.push_back("VK_KHR_variable_pointers"); |
| |
| spec.assembly = shaderSource; |
| spec.numWorkGroups = IVec3(16, 1, 1); |
| spec.requestedVulkanFeatures = requiredFeatures; |
| |
| group->addChild(new SpvAsmComputeShaderCase(testCtx, "buffer_memory_variable_pointers", "", spec)); |
| } |
| |
| void addComputePointerWorkgroupMemoryVariablePointersTest (tcu::TestCaseGroup* group) |
| { |
| tcu::TestContext& testCtx = group->getTestContext(); |
| const int numFloats = 128; |
| ComputeShaderSpec spec; |
| VulkanFeatures requiredFeatures; |
| vector<float> expectedOutput; |
| |
| // Implements the following pseudo GLSL shader: |
| // |
| // layout (local_size_x = 16, local_size_y = 1, local_size_z = 1) in; |
| // |
| // layout (binding = 0) buffer Output |
| // { |
| // vec4 arr0[16]; |
| // vec4 arr1[]; |
| // } dataOutput; |
| // |
| // shared struct |
| // { |
| // vec4 arr0[16]; |
| // vec4 arr1[16]; |
| // } sharedData; |
| // |
| // void func0(vec4* f0[16], uint i) |
| // { |
| // f0[i] = vec4(i); |
| // } |
| // |
| // void func1(vec4* f1[16], uint i) |
| // { |
| // f1[i] = vec4(i+5); |
| // } |
| // |
| // void main() |
| // { |
| // uint idx = gl_LocalInvocationID.x; |
| // func0(sharedData.arr0, idx); |
| // func1(sharedData.arr1, idx); |
| // barier(); |
| // dataOutput.arr0[idx] = sharedData.arr1[(idx+1) % 16]; |
| // dataOutput.arr1[idx] = sharedData.arr0[(idx+1) % 16]; |
| // } |
| const string shaderSource = |
| " OpCapability Shader\n" |
| " OpCapability VariablePointers\n" |
| " OpExtension \"SPV_KHR_variable_pointers\"\n" |
| " OpExtension \"SPV_KHR_storage_buffer_storage_class\"\n" |
| " %1 = OpExtInstImport \"GLSL.std.450\"\n" |
| " OpMemoryModel Logical GLSL450\n" |
| " OpEntryPoint GLCompute %main \"main\" %gl_LocalInvocationID\n" |
| " OpExecutionMode %main LocalSize 16 1 1\n" |
| " OpSource GLSL 430\n" |
| " OpMemberDecorate %Output 0 Offset 0\n" |
| " OpMemberDecorate %Output 1 Offset 256\n" |
| " OpMemberDecorate %struct 0 Offset 0\n" |
| " OpMemberDecorate %struct 1 Offset 256\n" |
| " OpDecorate %arr_vec4_16 ArrayStride 16\n" |
| " OpDecorate %arr_vec4_rt ArrayStride 16\n" |
| " OpDecorate %Output Block\n" |
| " OpDecorate %dataOutput DescriptorSet 0\n" |
| " OpDecorate %dataOutput Binding 0\n" |
| " OpDecorate %gl_LocalInvocationID BuiltIn LocalInvocationId\n" |
| " %void = OpTypeVoid\n" |
| " %void_func = OpTypeFunction %void\n" |
| " %float = OpTypeFloat 32\n" |
| " %_ptr_Function_float = OpTypePointer Function %float\n" |
| " %uint = OpTypeInt 32 0\n" |
| " %_ptr_Function_uint = OpTypePointer Function %uint\n" |
| " %uint_1 = OpConstant %uint 1\n" |
| " %uint_2 = OpConstant %uint 2\n" |
| " %uint_5 = OpConstant %uint 5\n" |
| " %uint_16 = OpConstant %uint 16\n" |
| " %uint_264 = OpConstant %uint 264\n" |
| " %vec4 = OpTypeVector %float 4\n" |
| " %arr_vec4_16 = OpTypeArray %vec4 %uint_16\n" |
| " %arr_vec4_rt = OpTypeRuntimeArray %vec4\n" |
| " %arr_vec4_16_sb_ptr = OpTypePointer StorageBuffer %arr_vec4_16\n" |
| " %arr_vec4_rt_sb_ptr = OpTypePointer StorageBuffer %arr_vec4_rt\n" |
| " %arr_vec4_16_wg_ptr = OpTypePointer Workgroup %arr_vec4_16\n" |
| " %func_decl = OpTypeFunction %void %arr_vec4_16_wg_ptr %_ptr_Function_uint\n" |
| " %Output = OpTypeStruct %arr_vec4_16 %arr_vec4_rt\n" |
| " %struct = OpTypeStruct %arr_vec4_16 %arr_vec4_16\n" |
| " %_ptr_sb_struct = OpTypePointer StorageBuffer %Output\n" |
| " %_ptr_wg_struct = OpTypePointer Workgroup %struct\n" |
| " %dataOutput = OpVariable %_ptr_sb_struct StorageBuffer\n" |
| " %sharedData = OpVariable %_ptr_wg_struct Workgroup\n" |
| " %int = OpTypeInt 32 1\n" |
| " %int_0 = OpConstant %int 0\n" |
| " %int_1 = OpConstant %int 1\n" |
| " %v3uint = OpTypeVector %uint 3\n" |
| " %_ptr_Input_v3uint = OpTypePointer Input %v3uint\n" |
| " %gl_LocalInvocationID = OpVariable %_ptr_Input_v3uint Input\n" |
| " %uint_0 = OpConstant %uint 0\n" |
| " %_ptr_Input_uint = OpTypePointer Input %uint\n" |
| " %_ptr_sb_vec4 = OpTypePointer StorageBuffer %vec4\n" |
| " %_ptr_wg_vec4 = OpTypePointer Workgroup %vec4\n" |
| " %main = OpFunction %void None %void_func\n" |
| " %entry = OpLabel\n" |
| " %idx = OpVariable %_ptr_Function_uint Function\n" |
| " %inv_id_ptr = OpAccessChain %_ptr_Input_uint %gl_LocalInvocationID %uint_0\n" |
| " %inv_id = OpLoad %uint %inv_id_ptr\n" |
| " OpStore %idx %inv_id\n" |
| " %ptr0 = OpAccessChain %arr_vec4_16_wg_ptr %sharedData %int_0\n" |
| " %ptr1 = OpAccessChain %arr_vec4_16_wg_ptr %sharedData %int_1\n" |
| " %ret0 = OpFunctionCall %void %func0 %ptr0 %idx\n" |
| " %ret1 = OpFunctionCall %void %func1 %ptr1 %idx\n" |
| " OpControlBarrier %uint_2 %uint_2 %uint_264\n" |
| " %inv_id_plus1 = OpIAdd %uint %inv_id %uint_1\n" |
| " %inv_id_mod = OpUMod %uint %inv_id_plus1 %uint_16\n" |
| " %shared_arr1_ptr = OpAccessChain %_ptr_wg_vec4 %sharedData %int_1 %inv_id_mod\n" |
| " %shared_arr1_data = OpLoad %vec4 %shared_arr1_ptr\n" |
| " %outPtr0 = OpAccessChain %_ptr_sb_vec4 %dataOutput %int_0 %inv_id\n" |
| " OpStore %outPtr0 %shared_arr1_data\n" |
| " %shared_arr0_ptr = OpAccessChain %_ptr_wg_vec4 %sharedData %int_0 %inv_id_mod\n" |
| " %shared_arr0_data = OpLoad %vec4 %shared_arr0_ptr\n" |
| " %outPtr1 = OpAccessChain %_ptr_sb_vec4 %dataOutput %int_1 %inv_id\n" |
| " OpStore %outPtr1 %shared_arr0_data\n" |
| " OpReturn\n" |
| " OpFunctionEnd\n" |
| " %func0 = OpFunction %void None %func_decl\n" |
| " %f0 = OpFunctionParameter %arr_vec4_16_wg_ptr\n" |
| " %i0 = OpFunctionParameter %_ptr_Function_uint\n" |
| " %func0_entry = OpLabel\n" |
| " %idx0 = OpLoad %uint %i0\n" |
| " %out_ptr0 = OpAccessChain %_ptr_wg_vec4 %f0 %idx0\n" |
| " %idxFloat0 = OpConvertUToF %float %idx0\n" |
| " %outData0 = OpCompositeConstruct %vec4 %idxFloat0 %idxFloat0 %idxFloat0 %idxFloat0\n" |
| " OpStore %out_ptr0 %outData0\n" |
| " OpReturn\n" |
| " OpFunctionEnd\n" |
| " %func1 = OpFunction %void None %func_decl\n" |
| " %f1 = OpFunctionParameter %arr_vec4_16_wg_ptr\n" |
| " %i1 = OpFunctionParameter %_ptr_Function_uint\n" |
| " %func1_entry = OpLabel\n" |
| " %idx1 = OpLoad %uint %i1\n" |
| " %out_ptr1 = OpAccessChain %_ptr_wg_vec4 %f1 %idx1\n" |
| " %idxPlus5 = OpIAdd %uint %idx1 %uint_5\n" |
| " %idxFloat1 = OpConvertUToF %float %idxPlus5\n" |
| " %outData1 = OpCompositeConstruct %vec4 %idxFloat1 %idxFloat1 %idxFloat1 %idxFloat1\n" |
| " OpStore %out_ptr1 %outData1\n" |
| " OpReturn\n" |
| " OpFunctionEnd\n"; |
| |
| expectedOutput.reserve(numFloats); |
| for (deUint32 vecIdx = 0; vecIdx < numFloats / 8; ++vecIdx) |
| { |
| const deUint32 shuffleIdx = (vecIdx + 1) % 16; |
| const float val = (float)(shuffleIdx + 5); |
| for (deUint32 i = 0; i < 4; ++i) |
| expectedOutput.push_back(val); |
| } |
| for (deUint32 vecIdx = 0; vecIdx < numFloats / 8; ++vecIdx) |
| { |
| const deUint32 shuffleIdx = (vecIdx + 1) % 16; |
| const float val = (float)shuffleIdx; |
| for (deUint32 i = 0; i < 4; ++i) |
| expectedOutput.push_back(val); |
| } |
| |
| spec.outputs.push_back(BufferSp(new Float32Buffer(expectedOutput))); |
| requiredFeatures.extVariablePointers = EXTVARIABLEPOINTERSFEATURES_VARIABLE_POINTERS; |
| spec.extensions.push_back("VK_KHR_variable_pointers"); |
| |
| spec.assembly = shaderSource; |
| spec.numWorkGroups = IVec3(1, 1, 1); |
| spec.requestedVulkanFeatures = requiredFeatures; |
| |
| group->addChild(new SpvAsmComputeShaderCase(testCtx, "workgroup_memory_variable_pointers", "", spec)); |
| } |
| |
| void addGraphicsPointerParamToParamTest (tcu::TestCaseGroup* group) |
| { |
| map<string, string> fragments; |
| RGBA defaultColors[4]; |
| GraphicsResources resources; |
| vector<string> extensions; |
| vector<float> expectedOutput; |
| VulkanFeatures requiredFeatures; |
| |
| // Implements the following pseudo GLSL shader: |
| // |
| // float func(alias float* f, alias float* g) |
| // { |
| // *g = 5.0; |
| // *f = 2.0; |
| // return *g; |
| // } |
| // |
| // vec4 test_code(vec4 param) |
| // { |
| // float a = 0.0; |
| // o = func(&a, &a); // should return 2.0 |
| // float b = 0.0; |
| // o += func(&a, &b); // should return 5.0 |
| // return param; |
| // } |
| fragments["pre_main"] = |
| " %func0_decl = OpTypeFunction %f32 %fp_f32 %fp_f32\n" |
| " %c_f32_5 = OpConstant %f32 5\n" |
| " %c_f32_2 = OpConstant %f32 2\n" |
| " %Output = OpTypeStruct %f32\n" |
| " %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n" |
| " %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n" |
| " %_ptr_Uniform_f32 = OpTypePointer Uniform %f32\n" |
| " %func = OpFunction %f32 None %func0_decl\n" |
| " %f = OpFunctionParameter %fp_f32\n" |
| " %g = OpFunctionParameter %fp_f32\n" |
| " %func_entry = OpLabel\n" |
| " OpStore %g %c_f32_5\n" |
| " OpStore %f %c_f32_2\n" |
| " %ret = OpLoad %f32 %g\n" |
| " OpReturnValue %ret\n" |
| " OpFunctionEnd\n"; |
| |
| fragments["decoration"] = |
| " OpMemberDecorate %Output 0 Offset 0\n" |
| " OpDecorate %Output BufferBlock\n" |
| " OpDecorate %dataOutput DescriptorSet 0\n" |
| " OpDecorate %dataOutput Binding 0\n" |
| " OpDecorate %f Aliased\n" |
| " OpDecorate %g Aliased\n"; |
| |
| fragments["testfun"] = |
| " %test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n" |
| " %param = OpFunctionParameter %v4f32\n" |
| " %entry = OpLabel\n" |
| " %a = OpVariable %fp_f32 Function %c_f32_0\n" |
| " %b = OpVariable %fp_f32 Function %c_f32_0\n" |
| " %o = OpVariable %fp_f32 Function %c_f32_0\n" |
| " %ret0 = OpFunctionCall %f32 %func %a %a\n" |
| " OpStore %o %ret0\n" |
| " %ret1 = OpFunctionCall %f32 %func %a %b\n" |
| " %o_val = OpLoad %f32 %o\n" |
| " %sum = OpFAdd %f32 %o_val %ret1\n" |
| " %out_ptr = OpAccessChain %_ptr_Uniform_f32 %dataOutput %c_i32_0\n" |
| " OpStore %out_ptr %sum\n" |
| " OpReturnValue %param\n" |
| " OpFunctionEnd\n"; |
| |
| getDefaultColors(defaultColors); |
| expectedOutput.push_back(7.0f); |
| requiredFeatures.coreFeatures.vertexPipelineStoresAndAtomics = DE_TRUE; |
| resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(expectedOutput)), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)); |
| |
| createTestsForAllStages("global_to_param", defaultColors, defaultColors, fragments, resources, extensions, group, requiredFeatures); |
| } |
| |
| void addGraphicsPointerParamToGlobalTest (tcu::TestCaseGroup* group) |
| { |
| map<string, string> fragments; |
| RGBA defaultColors[4]; |
| GraphicsResources resources; |
| vector<string> extensions; |
| vector<float> expectedOutput; |
| VulkanFeatures requiredFeatures; |
| |
| // Implements the following pseudo GLSL shader: |
| // |
| // alias float a = 0.0; |
| // |
| // float func0(alias float* f0) // f in Private storage class |
| // { |
| // *a = 5.0; |
| // *f0 = 2.0; |
| // return *a; |
| // } |
| // |
| // float func1(alias float* f1) // f in Function storage class |
| // { |
| // *a = 5.0; |
| // *f1 = 2.0; |
| // return *a; |
| // } |
| // |
| // vec4 test_code(vec4 param) |
| // { |
| // o = func0(&a); // should return 2.0 |
| // float b = 0.0; |
| // o += func1(&b); // should return 5.0 |
| // return param; |
| // } |
| fragments["pre_main"] = |
| " %pp_f32 = OpTypePointer Private %f32\n" |
| " %func0_decl = OpTypeFunction %f32 %pp_f32\n" |
| " %func1_decl = OpTypeFunction %f32 %fp_f32\n" |
| " %c_f32_5 = OpConstant %f32 5\n" |
| " %c_f32_2 = OpConstant %f32 2\n" |
| " %Output = OpTypeStruct %f32\n" |
| " %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n" |
| " %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n" |
| " %_ptr_Uniform_f32 = OpTypePointer Uniform %f32\n" |
| " %a = OpVariable %pp_f32 Private %c_f32_0\n" |
| " %func0 = OpFunction %f32 None %func0_decl\n" |
| " %f0 = OpFunctionParameter %pp_f32\n" |
| " %func0_entry = OpLabel\n" |
| " OpStore %a %c_f32_5\n" |
| " OpStore %f0 %c_f32_2\n" |
| " %func0_ret = OpLoad %f32 %a\n" |
| " OpReturnValue %func0_ret\n" |
| " OpFunctionEnd\n" |
| " %func1 = OpFunction %f32 None %func1_decl\n" |
| " %f1 = OpFunctionParameter %fp_f32\n" |
| " %func1_entry = OpLabel\n" |
| " OpStore %a %c_f32_5\n" |
| " OpStore %f1 %c_f32_2\n" |
| " %func1_ret = OpLoad %f32 %a\n" |
| " OpReturnValue %func1_ret\n" |
| " OpFunctionEnd\n"; |
| |
| fragments["decoration"] = |
| " OpMemberDecorate %Output 0 Offset 0\n" |
| " OpDecorate %Output BufferBlock\n" |
| " OpDecorate %dataOutput DescriptorSet 0\n" |
| " OpDecorate %dataOutput Binding 0\n" |
| " OpDecorate %f0 Aliased\n" |
| " OpDecorate %f1 Aliased\n" |
| " OpDecorate %a Aliased\n"; |
| |
| fragments["testfun"] = |
| " %test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n" |
| " %param = OpFunctionParameter %v4f32\n" |
| " %entry = OpLabel\n" |
| " %b = OpVariable %fp_f32 Function %c_f32_0\n" |
| " %o = OpVariable %fp_f32 Function %c_f32_0\n" |
| " %ret0 = OpFunctionCall %f32 %func0 %a\n" |
| " OpStore %o %ret0\n" |
| " %ret1 = OpFunctionCall %f32 %func1 %b\n" |
| " %o_val = OpLoad %f32 %o\n" |
| " %sum = OpFAdd %f32 %o_val %ret1\n" |
| " %out_ptr = OpAccessChain %_ptr_Uniform_f32 %dataOutput %c_i32_0\n" |
| " OpStore %out_ptr %sum\n" |
| " OpReturnValue %param\n" |
| " OpFunctionEnd\n"; |
| |
| getDefaultColors(defaultColors); |
| expectedOutput.push_back(7.0f); |
| requiredFeatures.coreFeatures.vertexPipelineStoresAndAtomics = DE_TRUE; |
| resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(expectedOutput)), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)); |
| |
| createTestsForAllStages("param_to_global", defaultColors, defaultColors, fragments, resources, extensions, group, requiredFeatures); |
| } |
| |
| void addGraphicsPointerBufferMemoryTest (tcu::TestCaseGroup* group) |
| { |
| const int numFloats = 16; |
| map<string, string> fragments; |
| RGBA defaultColors[4]; |
| GraphicsResources resources; |
| vector<string> extensions; |
| vector<float> expectedOutput; |
| VulkanFeatures requiredFeatures; |
| |
| // Implements the following pseudo GLSL shader: |
| // |
| // layout (binding = 0) buffer Output |
| // { |
| // vec4 arr0[2]; |
| // vec4 arr1[]; |
| // } dataOutput; |
| // |
| // void func0(vec4* f0[2], uint i) |
| // { |
| // f0[i] = vec4(5.0); |
| // } |
| // |
| // void func1(vec4* f1[], uint i) |
| // { |
| // f1[i] = vec4(2.0); |
| // } |
| // |
| // vec4 test_code(vec4 param) |
| // { |
| // func0(dataOutput.arr0, idx); |
| // func1(dataOutput.arr1, idx); |
| // return param; |
| // } |
| fragments["pre_main"] = |
| " %arr_v4f32_2 = OpTypeArray %v4f32 %c_u32_2\n" |
| " %arr_v4f32_rt = OpTypeRuntimeArray %v4f32\n" |
| " %arr_v4f32_2_ptr = OpTypePointer StorageBuffer %arr_v4f32_2\n" |
| " %arr_v4f32_rt_ptr = OpTypePointer StorageBuffer %arr_v4f32_rt\n" |
| " %func0_decl = OpTypeFunction %void %arr_v4f32_2_ptr\n" |
| " %func1_decl = OpTypeFunction %void %arr_v4f32_rt_ptr\n" |
| " %c_f32_5 = OpConstant %f32 5\n" |
| " %c_f32_2 = OpConstant %f32 2\n" |
| " %c_v4f32_5 = OpConstantComposite %v4f32 %c_f32_5 %c_f32_5 %c_f32_5 %c_f32_5\n" |
| " %c_v4f32_2 = OpConstantComposite %v4f32 %c_f32_2 %c_f32_2 %c_f32_2 %c_f32_2\n" |
| " %Output = OpTypeStruct %arr_v4f32_2 %arr_v4f32_rt\n" |
| " %_ptr_sb_Output = OpTypePointer StorageBuffer %Output\n" |
| " %dataOutput = OpVariable %_ptr_sb_Output StorageBuffer\n" |
| " %_ptr_sb_v4f32 = OpTypePointer StorageBuffer %v4f32\n" |
| " %func0 = OpFunction %void None %func0_decl\n" |
| " %f0 = OpFunctionParameter %arr_v4f32_2_ptr\n" |
| " %func0Entry = OpLabel\n" |
| " %out_ptr0 = OpAccessChain %_ptr_sb_v4f32 %f0 %c_i32_0\n" |
| " OpStore %out_ptr0 %c_v4f32_5\n" |
| " %out_ptr1 = OpAccessChain %_ptr_sb_v4f32 %f0 %c_i32_1\n" |
| " OpStore %out_ptr1 %c_v4f32_5\n" |
| " OpReturn\n" |
| " OpFunctionEnd\n" |
| " %func1 = OpFunction %void None %func1_decl\n" |
| " %f1 = OpFunctionParameter %arr_v4f32_rt_ptr\n" |
| " %func1Entry = OpLabel\n" |
| " %out_ptr2 = OpAccessChain %_ptr_sb_v4f32 %f1 %c_i32_0\n" |
| " OpStore %out_ptr2 %c_v4f32_2\n" |
| " %out_ptr3 = OpAccessChain %_ptr_sb_v4f32 %f1 %c_i32_1\n" |
| " OpStore %out_ptr3 %c_v4f32_2\n" |
| " OpReturn\n" |
| " OpFunctionEnd\n"; |
| |
| fragments["decoration"] = |
| " OpMemberDecorate %Output 0 Offset 0\n" |
| " OpMemberDecorate %Output 1 Offset 32\n" |
| " OpDecorate %Output Block\n" |
| " OpDecorate %dataOutput DescriptorSet 0\n" |
| " OpDecorate %dataOutput Binding 0\n" |
| " OpDecorate %f0 DescriptorSet 0\n" |
| " OpDecorate %f0 Binding 0\n" |
| " OpDecorate %f1 DescriptorSet 0\n" |
| " OpDecorate %f1 Binding 0\n" |
| " OpDecorate %arr_v4f32_2 ArrayStride 16\n" |
| " OpDecorate %arr_v4f32_rt ArrayStride 16\n"; |
| |
| fragments["testfun"] = |
| " %test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n" |
| " %param = OpFunctionParameter %v4f32\n" |
| " %entry = OpLabel\n" |
| " %ptr0 = OpAccessChain %arr_v4f32_2_ptr %dataOutput %c_i32_0\n" |
| " %ptr1 = OpAccessChain %arr_v4f32_rt_ptr %dataOutput %c_i32_1\n" |
| " %ret0 = OpFunctionCall %void %func0 %ptr0\n" |
| " %ret1 = OpFunctionCall %void %func1 %ptr1\n" |
| " OpReturnValue %param\n" |
| " OpFunctionEnd\n"; |
| |
| fragments["extension"] = |
| "OpExtension \"SPV_KHR_storage_buffer_storage_class\"\n" |
| "OpExtension \"SPV_KHR_variable_pointers\"\n"; |
| |
| fragments["capability"] = |
| "OpCapability VariablePointersStorageBuffer\n"; |
| |
| getDefaultColors(defaultColors); |
| |
| for (deUint32 numIdx = 0; numIdx < numFloats / 2; ++numIdx) |
| expectedOutput.push_back(5.0f); |
| for (deUint32 numIdx = 0; numIdx < numFloats / 2; ++numIdx) |
| expectedOutput.push_back(2.0f); |
| |
| extensions.push_back("VK_KHR_variable_pointers"); |
| requiredFeatures.extVariablePointers = EXTVARIABLEPOINTERSFEATURES_VARIABLE_POINTERS_STORAGEBUFFER; |
| requiredFeatures.coreFeatures.vertexPipelineStoresAndAtomics = DE_TRUE; |
| resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(expectedOutput)), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)); |
| |
| createTestsForAllStages("buffer_memory", defaultColors, defaultColors, fragments, resources, extensions, group, requiredFeatures); |
| } |
| |
| void addGraphicsPointerBufferMemoryVariablePointersTest (tcu::TestCaseGroup* group) |
| { |
| const int numFloats = 16; |
| map<string, string> fragments; |
| RGBA defaultColors[4]; |
| GraphicsResources resources; |
| vector<string> extensions; |
| vector<float> expectedOutput; |
| VulkanFeatures requiredFeatures; |
| |
| // Implements the following pseudo GLSL shader: |
| // |
| // layout (binding = 0) buffer Output |
| // { |
| // vec4 arr0[2]; |
| // vec4 arr1[]; |
| // } dataOutput; |
| // |
| // void func0(vec4* f0[2], uint i) |
| // { |
| // f0[i] = vec4(5.0); |
| // } |
| // |
| // void func1(vec4* f1[], uint i) |
| // { |
| // f1[i] = vec4(2.0); |
| // } |
| // |
| // vec4 test_code(vec4 param) |
| // { |
| // func0(dataOutput.arr0, idx); |
| // func1(dataOutput.arr1, idx); |
| // return param; |
| // } |
| fragments["pre_main"] = |
| " %arr_v4f32_2 = OpTypeArray %v4f32 %c_u32_2\n" |
| " %arr_v4f32_rt = OpTypeRuntimeArray %v4f32\n" |
| " %arr_v4f32_2_ptr = OpTypePointer StorageBuffer %arr_v4f32_2\n" |
| " %arr_v4f32_rt_ptr = OpTypePointer StorageBuffer %arr_v4f32_rt\n" |
| " %func0_decl = OpTypeFunction %void %arr_v4f32_2_ptr\n" |
| " %func1_decl = OpTypeFunction %void %arr_v4f32_rt_ptr\n" |
| " %c_f32_5 = OpConstant %f32 5\n" |
| " %c_f32_2 = OpConstant %f32 2\n" |
| " %c_v4f32_5 = OpConstantComposite %v4f32 %c_f32_5 %c_f32_5 %c_f32_5 %c_f32_5\n" |
| " %c_v4f32_2 = OpConstantComposite %v4f32 %c_f32_2 %c_f32_2 %c_f32_2 %c_f32_2\n" |
| " %Output = OpTypeStruct %arr_v4f32_2 %arr_v4f32_rt\n" |
| " %_ptr_sb_Output = OpTypePointer StorageBuffer %Output\n" |
| " %dataOutput = OpVariable %_ptr_sb_Output StorageBuffer\n" |
| " %_ptr_sb_v4f32 = OpTypePointer StorageBuffer %v4f32\n" |
| " %func0 = OpFunction %void None %func0_decl\n" |
| " %f0 = OpFunctionParameter %arr_v4f32_2_ptr\n" |
| " %func0Entry = OpLabel\n" |
| " %out_ptr0 = OpAccessChain %_ptr_sb_v4f32 %f0 %c_i32_0\n" |
| " OpStore %out_ptr0 %c_v4f32_5\n" |
| " %out_ptr1 = OpAccessChain %_ptr_sb_v4f32 %f0 %c_i32_1\n" |
| " OpStore %out_ptr1 %c_v4f32_5\n" |
| " OpReturn\n" |
| " OpFunctionEnd\n" |
| " %func1 = OpFunction %void None %func1_decl\n" |
| " %f1 = OpFunctionParameter %arr_v4f32_rt_ptr\n" |
| " %func1Entry = OpLabel\n" |
| " %out_ptr2 = OpAccessChain %_ptr_sb_v4f32 %f1 %c_i32_0\n" |
| " OpStore %out_ptr2 %c_v4f32_2\n" |
| " %out_ptr3 = OpAccessChain %_ptr_sb_v4f32 %f1 %c_i32_1\n" |
| " OpStore %out_ptr3 %c_v4f32_2\n" |
| " OpReturn\n" |
| " OpFunctionEnd\n"; |
| |
| fragments["decoration"] = |
| " OpMemberDecorate %Output 0 Offset 0\n" |
| " OpMemberDecorate %Output 1 Offset 32\n" |
| " OpDecorate %Output Block\n" |
| " OpDecorate %dataOutput DescriptorSet 0\n" |
| " OpDecorate %dataOutput Binding 0\n" |
| " OpDecorate %arr_v4f32_2 ArrayStride 16\n" |
| " OpDecorate %arr_v4f32_rt ArrayStride 16\n"; |
| |
| fragments["testfun"] = |
| " %test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n" |
| " %param = OpFunctionParameter %v4f32\n" |
| " %entry = OpLabel\n" |
| " %ptr0 = OpAccessChain %arr_v4f32_2_ptr %dataOutput %c_i32_0\n" |
| " %ptr1 = OpAccessChain %arr_v4f32_rt_ptr %dataOutput %c_i32_1\n" |
| " %ret0 = OpFunctionCall %void %func0 %ptr0\n" |
| " %ret1 = OpFunctionCall %void %func1 %ptr1\n" |
| " OpReturnValue %param\n" |
| " OpFunctionEnd\n"; |
| |
| fragments["extension"] = |
| "OpExtension \"SPV_KHR_variable_pointers\"\n" |
| "OpExtension \"SPV_KHR_storage_buffer_storage_class\"\n"; |
| |
| fragments["capability"] = |
| "OpCapability VariablePointersStorageBuffer\n"; |
| |
| getDefaultColors(defaultColors); |
| |
| for (deUint32 numIdx = 0; numIdx < numFloats / 2; ++numIdx) |
| expectedOutput.push_back(5.0f); |
| for (deUint32 numIdx = 0; numIdx < numFloats / 2; ++numIdx) |
| expectedOutput.push_back(2.0f); |
| |
| extensions.push_back("VK_KHR_variable_pointers"); |
| requiredFeatures.coreFeatures.vertexPipelineStoresAndAtomics = DE_TRUE; |
| resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(expectedOutput)), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)); |
| |
| createTestsForAllStages("buffer_memory_variable_pointers", defaultColors, defaultColors, fragments, resources, extensions, group, requiredFeatures); |
| } |
| |
| } // anonymous |
| |
| tcu::TestCaseGroup* createPointerParameterComputeGroup (tcu::TestContext& testCtx) |
| { |
| de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "pointer_parameter", "Compute tests for pointer as function parameter.")); |
| addComputePointerParamToParamTest(group.get()); |
| addComputePointerParamToGlobalTest(group.get()); |
| addComputePointerBufferMemoryTest(group.get()); |
| addComputePointerBufferMemoryVariablePointersTest(group.get()); |
| addComputePointerWorkgroupMemoryVariablePointersTest(group.get()); |
| |
| return group.release(); |
| } |
| |
| tcu::TestCaseGroup* createPointerParameterGraphicsGroup (tcu::TestContext& testCtx) |
| { |
| de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "pointer_parameter", "Graphics tests for pointer as function parameter.")); |
| addGraphicsPointerParamToParamTest(group.get()); |
| addGraphicsPointerParamToGlobalTest(group.get()); |
| addGraphicsPointerBufferMemoryTest(group.get()); |
| addGraphicsPointerBufferMemoryVariablePointersTest(group.get()); |
| |
| return group.release(); |
| } |
| |
| } // SpirVAssembly |
| } // vkt |