Test variable pointers on dynamic descriptors
authorAri Suonpaa <ari.suonpaa@siru.fi>
Mon, 14 Sep 2020 07:17:09 +0000 (10:17 +0300)
committerAlexander Galazin <alexander.galazin@arm.com>
Fri, 19 Feb 2021 08:12:35 +0000 (09:12 +0100)
Added a variable pointer test for accessing descriptors
of dynamic type.

VK-GL-CTS Issue: 2373

New tests:

dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.dynamic_offset.*

Components: Vulkan
Change-Id: I37241cae2ba1c5870958a751de556047c3bae839

android/cts/master/vk-master-2020-03-01.txt
android/cts/master/vk-master.txt
external/vulkancts/data/vulkan/amber/spirv_assembly/instruction/compute/variable_pointer/dynamic_offset/select_descriptor_array.amber [new file with mode: 0644]
external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmVariablePointersTests.cpp
external/vulkancts/mustpass/master/vk-default.txt

index 9f49f82..e7ef20e 100644 (file)
@@ -174853,6 +174853,7 @@ dEQP-VK.spirv_assembly.instruction.compute.indexing.input.struct.opinboundsacces
 dEQP-VK.spirv_assembly.instruction.compute.indexing.input.struct.opinboundsaccesschain_s32
 dEQP-VK.spirv_assembly.instruction.compute.indexing.input.struct.opptraccesschain_u32
 dEQP-VK.spirv_assembly.instruction.compute.indexing.input.struct.opptraccesschain_s32
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.dynamic_offset.select_descriptor_array
 dEQP-VK.spirv_assembly.instruction.compute.physical_pointers.compute.reads_opselect_single_buffer
 dEQP-VK.spirv_assembly.instruction.compute.physical_pointers.compute.reads_opfunctioncall_single_buffer
 dEQP-VK.spirv_assembly.instruction.compute.physical_pointers.compute.reads_opphi_single_buffer
index 49cf2bc..cd20559 100644 (file)
@@ -413726,6 +413726,7 @@ dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.complex_types_compu
 dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.complex_types_compute.opptraccesschain_float_single_buffer_first_input
 dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.nullptr_compute.opvariable_initialized_null
 dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.nullptr_compute.opselect_null_or_valid_ptr
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.dynamic_offset.select_descriptor_array
 dEQP-VK.spirv_assembly.instruction.compute.physical_pointers.compute.reads_opselect_single_buffer
 dEQP-VK.spirv_assembly.instruction.compute.physical_pointers.compute.reads_opfunctioncall_single_buffer
 dEQP-VK.spirv_assembly.instruction.compute.physical_pointers.compute.reads_opphi_single_buffer
diff --git a/external/vulkancts/data/vulkan/amber/spirv_assembly/instruction/compute/variable_pointer/dynamic_offset/select_descriptor_array.amber b/external/vulkancts/data/vulkan/amber/spirv_assembly/instruction/compute/variable_pointer/dynamic_offset/select_descriptor_array.amber
new file mode 100644 (file)
index 0000000..66a2393
--- /dev/null
@@ -0,0 +1,166 @@
+#!amber
+# Copyright 2020 The Amber Authors.
+#
+# 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
+#
+#     https://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.
+
+DEVICE_EXTENSION VK_KHR_variable_pointers
+DEVICE_EXTENSION VK_KHR_storage_buffer_storage_class
+DEVICE_FEATURE VariablePointerFeatures.variablePointers
+DEVICE_FEATURE VariablePointerFeatures.variablePointersStorageBuffer
+
+# Based on the following GLSL shader pseudocode:
+#
+#SHADER compute compute_shader GLSL
+##version 430
+#
+#layout(set = 0, binding = 0) buffer InputData
+#{
+#    int data[10];
+#} input0[2];
+#
+#layout(set = 0, binding = 1) buffer InputData
+#{
+#    int data[10];
+#} input1[2];
+#
+#layout(set = 0, binding = 2) buffer Result
+#{
+#    int result;
+#};
+#
+#layout(push_constant) uniform Indices
+#{
+#    int idx0;
+#    int idx1;
+#    int idx2;
+#};
+#
+#
+#void main()
+#{
+#    InputData input[]* = (idx0 == 0) ? &input0 : &input1;
+#    result = input[idx1].data[idx2];
+#}
+#END
+
+SHADER compute compute_shader SPIRV-ASM
+               OpCapability Shader
+               OpCapability VariablePointers
+               OpExtension "SPV_KHR_variable_pointers"
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpSource GLSL 430
+               OpMemberDecorate %Indices 0 Offset 0
+               OpMemberDecorate %Indices 1 Offset 4
+               OpMemberDecorate %Indices 2 Offset 8
+               OpDecorate %Indices Block
+               OpMemberDecorate %Result 0 Offset 0
+               OpDecorate %Result Block
+               OpDecorate %result DescriptorSet 0
+               OpDecorate %result Binding 2
+               OpDecorate %_arr_int_int_10 ArrayStride 16
+               OpMemberDecorate %InputData 0 Offset 0
+               OpDecorate %InputData Block
+               OpDecorate %input0 DescriptorSet 0
+               OpDecorate %input0 Binding 0
+               OpDecorate %input1 DescriptorSet 0
+               OpDecorate %input1 Binding 1
+       %void = OpTypeVoid
+       %bool = OpTypeBool
+        %int = OpTypeInt 32 1
+  %void_func = OpTypeFunction %void
+    %Indices = OpTypeStruct %int %int %int
+%_ptr_PushConstant_Indices = OpTypePointer PushConstant %Indices
+    %indices = OpVariable %_ptr_PushConstant_Indices PushConstant
+      %int_0 = OpConstant %int 0
+      %int_1 = OpConstant %int 1
+      %int_2 = OpConstant %int 2
+     %int_10 = OpConstant %int 10
+%_ptr_PushConstant_int = OpTypePointer PushConstant %int
+     %Result = OpTypeStruct %int
+%_ptr_StorageBuffer_Result = OpTypePointer StorageBuffer %Result
+     %result = OpVariable %_ptr_StorageBuffer_Result StorageBuffer
+%_arr_int_int_10 = OpTypeArray %int %int_10
+  %InputData = OpTypeStruct %_arr_int_int_10
+%_arr_InputData_int_2 = OpTypeArray %InputData %int_2
+%_ptr_StorageBuffer__arr_InputData_int_2 = OpTypePointer StorageBuffer %_arr_InputData_int_2
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+     %input0 = OpVariable %_ptr_StorageBuffer__arr_InputData_int_2 StorageBuffer
+     %input1 = OpVariable %_ptr_StorageBuffer__arr_InputData_int_2 StorageBuffer
+       %main = OpFunction %void None %void_func
+      %label = OpLabel
+   %idx0_ptr = OpAccessChain %_ptr_PushConstant_int %indices %int_0
+       %idx0 = OpLoad %int %idx0_ptr
+   %idx1_ptr = OpAccessChain %_ptr_PushConstant_int %indices %int_1
+       %idx1 = OpLoad %int %idx1_ptr
+   %idx2_ptr = OpAccessChain %_ptr_PushConstant_int %indices %int_2
+       %idx2 = OpLoad %int %idx2_ptr
+  %idx0_zero = OpIEqual %bool %idx0 %int_0
+%variable_ptr = OpSelect %_ptr_StorageBuffer__arr_InputData_int_2 %idx0_zero %input0 %input1
+%input_data_ptr = OpAccessChain %_ptr_StorageBuffer_int %variable_ptr %idx1 %int_0 %idx2
+ %input_data = OpLoad %int %input_data_ptr
+%result_data_ptr = OpAccessChain %_ptr_StorageBuffer_int %result %int_0
+               OpStore %result_data_ptr %input_data
+               OpReturn
+               OpFunctionEnd
+END
+
+BUFFER buf0 DATA_TYPE int32 SIZE 1024 SERIES_FROM 0 INC_BY 1
+BUFFER buf1 DATA_TYPE int32 SIZE 1024 SERIES_FROM 1 INC_BY 1
+BUFFER buf2 DATA_TYPE int32 SIZE 1024 SERIES_FROM 2 INC_BY 1
+BUFFER buf3 DATA_TYPE int32 SIZE 1024 SERIES_FROM 3 INC_BY 1
+BUFFER indices0 DATA_TYPE int32 DATA
+0 1 2
+END
+BUFFER indices1 DATA_TYPE int32 DATA
+1 1 2
+END
+BUFFER result DATA_TYPE int32 DATA
+0
+END
+
+# This pipeline will select input from buf1 which has a dynamic offset of 256 bytes.
+# The sequence in that buffer starts from 1, and the array stride in the shader is
+# 16 bytes. The shader reads an array element number 2. Thus the expected value is:
+# 256/4 + 1 + 2 * 4 = 73.
+PIPELINE compute pipeline0
+  ATTACH compute_shader
+
+  BIND BUFFER_ARRAY buf0 buf1 AS storage_dynamic DESCRIPTOR_SET 0 BINDING 0 OFFSET 0 256
+  BIND BUFFER_ARRAY buf2 buf3 AS storage_dynamic DESCRIPTOR_SET 0 BINDING 1 OFFSET 512 768
+  BIND BUFFER indices0 AS push_constant
+  BIND BUFFER result AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+RUN pipeline0 1 1 1
+
+EXPECT result IDX 0 EQ 73
+
+# This pipeline will select input from buf3 which has a dynamic offset of 768 bytes.
+# The sequence in that buffer starts from 3, and the array stride in the shader is
+# 16 bytes. The shader reads an array element number 2. Thus the expected value is:
+# 768/4 + 3 + 2 * 4 = 203.
+PIPELINE compute pipeline1
+  ATTACH compute_shader
+
+  BIND BUFFER_ARRAY buf0 buf1 AS storage_dynamic DESCRIPTOR_SET 0 BINDING 0 OFFSET 0 256
+  BIND BUFFER_ARRAY buf2 buf3 AS storage_dynamic DESCRIPTOR_SET 0 BINDING 1 OFFSET 512 768
+  BIND BUFFER indices1 AS push_constant
+  BIND BUFFER result AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+RUN pipeline1 1 1 1
+
+EXPECT result IDX 0 EQ 203
index e20712b..11942e7 100644 (file)
@@ -49,6 +49,7 @@
 #include "vktSpvAsmVariablePointersTests.hpp"
 #include "vktTestCaseUtil.hpp"
 #include "vktTestGroupUtil.hpp"
+#include "vktAmberTestCase.hpp"
 
 #include <limits>
 #include <map>
@@ -1398,6 +1399,31 @@ void addNullptrVariablePointersComputeGroup (tcu::TestCaseGroup* group)
        }
 }
 
+void addDynamicOffsetComputeGroup (tcu::TestCaseGroup* group)
+{
+       tcu::TestContext &testCtx = group->getTestContext();
+
+       static const char dataDir[] = "spirv_assembly/instruction/compute/variable_pointer/dynamic_offset";
+
+       struct Case
+       {
+               string                  name;
+               string                  desc;
+       };
+
+       static const Case cases[] =
+       {
+               { "select_descriptor_array",    "Test accessing a descriptor array using a variable pointer from OpSelect"                      },
+       };
+
+       for (const auto& testCase : cases)
+       {
+               const string fileName = testCase.name + ".amber";
+
+               group->addChild(cts_amber::createAmberTestCase(testCtx, testCase.name.c_str(), testCase.desc.c_str(), dataDir, fileName, {"VK_KHR_variable_pointers", "VK_KHR_storage_buffer_storage_class", "VariablePointerFeatures.variablePointers", "VariablePointerFeatures.variablePointersStorageBuffer"}));
+       }
+}
+
 void addVariablePointersGraphicsGroup (tcu::TestCaseGroup* testGroup)
 {
        tcu::TestContext&                               testCtx                                 = testGroup->getTestContext();
@@ -2725,6 +2751,9 @@ tcu::TestCaseGroup* createVariablePointersComputeGroup (tcu::TestContext& testCt
                                 "nullptr_compute",
                                 "Test the usage of nullptr using the variable pointers extension in a compute shader",
                                 addNullptrVariablePointersComputeGroup);
+       addTestGroup(group.get(), "dynamic_offset",
+                                "Testing variable pointers referring to descriptors using dynamic offset",
+                                addDynamicOffsetComputeGroup);
 
        return group.release();
 }
index 4e229c6..7923d6b 100644 (file)
@@ -413732,6 +413732,7 @@ dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.complex_types_compu
 dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.complex_types_compute.opptraccesschain_float_single_buffer_first_input
 dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.nullptr_compute.opvariable_initialized_null
 dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.nullptr_compute.opselect_null_or_valid_ptr
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.dynamic_offset.select_descriptor_array
 dEQP-VK.spirv_assembly.instruction.compute.physical_pointers.compute.reads_opselect_single_buffer
 dEQP-VK.spirv_assembly.instruction.compute.physical_pointers.compute.reads_opfunctioncall_single_buffer
 dEQP-VK.spirv_assembly.instruction.compute.physical_pointers.compute.reads_opphi_single_buffer