Add VK_KHR_workgroup_memory_explicit_layout OpCopyMemory tests
authorCaio Marcelo de Oliveira Filho <caio.oliveira@intel.com>
Wed, 13 Jan 2021 22:14:33 +0000 (14:14 -0800)
committerAlexander Galazin <alexander.galazin@arm.com>
Mon, 15 Feb 2021 13:45:12 +0000 (14:45 +0100)
Component: Vulkan
VK-GL-CTS Issue: 2524
New Tests: dEQP-VK.compute.workgroup_memory_explicit_layout.copy_memory.*

Change-Id: I78287969904b67df21cf4f8f56935961a22cd6eb

android/cts/master/vk-master-2020-03-01.txt
android/cts/master/vk-master.txt
external/vulkancts/data/vulkan/amber/compute/workgroup_memory_explicit_layout/copy_memory_basic.amber [new file with mode: 0644]
external/vulkancts/data/vulkan/amber/compute/workgroup_memory_explicit_layout/copy_memory_two_invocations.amber [new file with mode: 0644]
external/vulkancts/data/vulkan/amber/compute/workgroup_memory_explicit_layout/copy_memory_variable_pointers.amber [new file with mode: 0644]
external/vulkancts/modules/vulkan/compute/vktComputeWorkgroupMemoryExplicitLayoutTests.cpp
external/vulkancts/mustpass/master/vk-default.txt

index 78ec0e8..05f8397 100644 (file)
@@ -204614,6 +204614,9 @@ dEQP-VK.compute.workgroup_memory_explicit_layout.size.16384
 dEQP-VK.compute.workgroup_memory_explicit_layout.size.32768
 dEQP-VK.compute.workgroup_memory_explicit_layout.size.49152
 dEQP-VK.compute.workgroup_memory_explicit_layout.size.65536
+dEQP-VK.compute.workgroup_memory_explicit_layout.copy_memory.basic
+dEQP-VK.compute.workgroup_memory_explicit_layout.copy_memory.two_invocations
+dEQP-VK.compute.workgroup_memory_explicit_layout.copy_memory.variable_pointers
 dEQP-VK.image.store.with_format.1d.b10g11r11_ufloat_pack32
 dEQP-VK.image.store.with_format.1d.r32g32_sfloat
 dEQP-VK.image.store.with_format.1d.r16g16_sfloat
index b35abe8..b85a6e2 100644 (file)
@@ -521436,6 +521436,9 @@ dEQP-VK.compute.workgroup_memory_explicit_layout.size.16384
 dEQP-VK.compute.workgroup_memory_explicit_layout.size.32768
 dEQP-VK.compute.workgroup_memory_explicit_layout.size.49152
 dEQP-VK.compute.workgroup_memory_explicit_layout.size.65536
+dEQP-VK.compute.workgroup_memory_explicit_layout.copy_memory.basic
+dEQP-VK.compute.workgroup_memory_explicit_layout.copy_memory.two_invocations
+dEQP-VK.compute.workgroup_memory_explicit_layout.copy_memory.variable_pointers
 dEQP-VK.image.store.with_format.1d.r32g32b32a32_sfloat
 dEQP-VK.image.store.with_format.1d.r16g16b16a16_sfloat
 dEQP-VK.image.store.with_format.1d.r32_sfloat
diff --git a/external/vulkancts/data/vulkan/amber/compute/workgroup_memory_explicit_layout/copy_memory_basic.amber b/external/vulkancts/data/vulkan/amber/compute/workgroup_memory_explicit_layout/copy_memory_basic.amber
new file mode 100644 (file)
index 0000000..f2edf53
--- /dev/null
@@ -0,0 +1,124 @@
+#!amber
+# Copyright 2021 Intel Corporation
+#
+# 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.
+
+DEVICE_EXTENSION VK_KHR_spirv_1_4
+DEVICE_EXTENSION VK_KHR_workgroup_memory_explicit_layout
+
+SHADER compute compute_shader SPIRV-ASM
+
+OpCapability Shader
+OpCapability WorkgroupMemoryExplicitLayoutKHR
+OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %input_buffer_0 %input_buffer_1 %output_buffer %wg %half_wg_0 %half_wg_1
+OpExecutionMode %main LocalSize 1 1 1
+
+OpDecorate %buffer_type Block
+OpDecorate %half_buffer_type Block
+OpDecorate %other_half_buffer_type Block
+OpMemberDecorate %buffer_type 0 Offset 0
+OpDecorate %array ArrayStride 4
+OpMemberDecorate %half_buffer_type 0 Offset 0
+OpMemberDecorate %other_half_buffer_type 0 Offset 64
+OpDecorate %half_array ArrayStride 4
+OpDecorate %input_buffer_0 DescriptorSet 0
+OpDecorate %input_buffer_0 Binding 0
+OpDecorate %input_buffer_1 DescriptorSet 0
+OpDecorate %input_buffer_1 Binding 1
+OpDecorate %output_buffer DescriptorSet 0
+OpDecorate %output_buffer Binding 2
+OpDecorate %wg Aliased
+OpDecorate %half_wg_0 Aliased
+OpDecorate %half_wg_1 Aliased
+
+%uint = OpTypeInt 32 0
+%const_uint_0 = OpConstant %uint 0
+%const_uint_16 = OpConstant %uint 16
+%const_uint_32 = OpConstant %uint 32
+%const_uint_64 = OpConstant %uint 64
+
+%void = OpTypeVoid
+%main_type = OpTypeFunction %void
+%array = OpTypeArray %uint %const_uint_32
+%half_array = OpTypeArray %uint %const_uint_16
+%half_array_wg_ptr = OpTypePointer Workgroup %half_array
+%half_array_sb_ptr = OpTypePointer StorageBuffer %half_array
+%buffer_type = OpTypeStruct %array
+%half_buffer_type = OpTypeStruct %half_array
+%other_half_buffer_type = OpTypeStruct %half_array
+%input_buffer_0_ptr = OpTypePointer StorageBuffer %half_buffer_type
+%input_buffer_1_ptr = OpTypePointer StorageBuffer %half_buffer_type
+%output_buffer_ptr = OpTypePointer StorageBuffer %buffer_type
+%wg_ptr = OpTypePointer Workgroup %buffer_type
+%half_wg_0_ptr = OpTypePointer Workgroup %half_buffer_type
+%half_wg_1_ptr = OpTypePointer Workgroup %other_half_buffer_type
+
+;;; Workgroup has a block covering the entire memory and another two
+;;; blocks covering each half of the former.
+
+%wg = OpVariable %wg_ptr Workgroup
+%half_wg_0 = OpVariable %half_wg_0_ptr Workgroup
+%half_wg_1 = OpVariable %half_wg_1_ptr Workgroup
+
+%input_buffer_0 = OpVariable %input_buffer_0_ptr StorageBuffer
+%input_buffer_1 = OpVariable %input_buffer_1_ptr StorageBuffer
+%output_buffer = OpVariable %output_buffer_ptr StorageBuffer
+
+%main = OpFunction %void None %main_type
+%entry = OpLabel
+
+;;; Copy first input into half of the workgroup memory.  Because the
+;;; whole types match here, we can afford to copy the Variables
+;;; directly.
+
+OpCopyMemory %half_wg_0 %input_buffer_0
+
+;;; Then copy the second input into the other half of Workgroup
+;;; memory, use OpAccessChain to extract the array pointers (what we
+;;; are copying), since the whole types don't match (different Offsets
+;;; in the block struct).
+
+%a = OpAccessChain %half_array_wg_ptr %half_wg_1 %const_uint_0
+%b = OpAccessChain %half_array_sb_ptr %input_buffer_1 %const_uint_0
+OpCopyMemory %a %b
+
+;;; The two halves of Workgroup memory were filled, now copy the large
+;;; Workgroup block that alias the halves into the output.
+
+OpCopyMemory %output_buffer %wg
+
+OpReturn
+OpFunctionEnd
+
+END
+
+BUFFER input_buffer_0 DATA_TYPE uint32 SIZE 16 SERIES_FROM 1 INC_BY 1
+BUFFER input_buffer_1 DATA_TYPE uint32 SIZE 16 SERIES_FROM 17 INC_BY 1
+
+BUFFER output_buffer DATA_TYPE uint32 SIZE 32 FILL 99
+
+BUFFER expected_buffer DATA_TYPE uint32 SIZE 32 SERIES_FROM 1 INC_BY 1
+
+PIPELINE compute pipeline
+  ATTACH compute_shader
+
+  BIND BUFFER input_buffer_0 AS storage DESCRIPTOR_SET 0 BINDING 0
+  BIND BUFFER input_buffer_1 AS storage DESCRIPTOR_SET 0 BINDING 1
+  BIND BUFFER output_buffer AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+RUN pipeline 1 1 1
+
+EXPECT output_buffer EQ_BUFFER expected_buffer
diff --git a/external/vulkancts/data/vulkan/amber/compute/workgroup_memory_explicit_layout/copy_memory_two_invocations.amber b/external/vulkancts/data/vulkan/amber/compute/workgroup_memory_explicit_layout/copy_memory_two_invocations.amber
new file mode 100644 (file)
index 0000000..a5179e3
--- /dev/null
@@ -0,0 +1,180 @@
+#!amber
+# Copyright 2021 Intel Corporation
+#
+# 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.
+
+DEVICE_EXTENSION VK_KHR_spirv_1_4
+DEVICE_EXTENSION VK_KHR_workgroup_memory_explicit_layout
+
+SHADER compute compute_shader SPIRV-ASM
+
+OpCapability Shader
+OpCapability WorkgroupMemoryExplicitLayoutKHR
+OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %index %push_constants %input_buffer_0 %input_buffer_1 %output_buffer %wg %half_wg_0 %half_wg_1
+OpExecutionMode %main LocalSize 128 4 1
+
+OpDecorate %index BuiltIn LocalInvocationIndex
+OpDecorate %buffer_type Block
+OpDecorate %half_buffer_type Block
+OpDecorate %other_half_buffer_type Block
+OpMemberDecorate %buffer_type 0 Offset 0
+OpDecorate %array ArrayStride 4
+OpMemberDecorate %half_buffer_type 0 Offset 0
+OpMemberDecorate %other_half_buffer_type 0 Offset 64
+OpDecorate %half_array ArrayStride 4
+OpDecorate %input_buffer_0 DescriptorSet 0
+OpDecorate %input_buffer_0 Binding 0
+OpDecorate %input_buffer_1 DescriptorSet 0
+OpDecorate %input_buffer_1 Binding 1
+OpDecorate %output_buffer DescriptorSet 0
+OpDecorate %output_buffer Binding 2
+OpDecorate %wg Aliased
+OpDecorate %half_wg_0 Aliased
+OpDecorate %half_wg_1 Aliased
+OpMemberDecorate %push_constants_type 0 Offset 0
+OpMemberDecorate %push_constants_type 1 Offset 4
+OpDecorate %push_constants_type Block
+
+%uint = OpTypeInt 32 0
+%const_uint_0 = OpConstant %uint 0
+%const_uint_1 = OpConstant %uint 1
+%const_uint_2 = OpConstant %uint 2
+%const_uint_16 = OpConstant %uint 16
+%const_uint_32 = OpConstant %uint 32
+%const_uint_64 = OpConstant %uint 64
+%const_uint_128 = OpConstant %uint 128
+%uint_input_ptr = OpTypePointer Input %uint
+%uint_pc_ptr = OpTypePointer PushConstant %uint
+
+%bool = OpTypeBool
+%void = OpTypeVoid
+%main_type = OpTypeFunction %void
+%array = OpTypeArray %uint %const_uint_32
+%half_array = OpTypeArray %uint %const_uint_16
+%half_array_wg_ptr = OpTypePointer Workgroup %half_array
+%half_array_sb_ptr = OpTypePointer StorageBuffer %half_array
+%buffer_type = OpTypeStruct %array
+%half_buffer_type = OpTypeStruct %half_array
+%other_half_buffer_type = OpTypeStruct %half_array
+%input_buffer_0_ptr = OpTypePointer StorageBuffer %half_buffer_type
+%input_buffer_1_ptr = OpTypePointer StorageBuffer %half_buffer_type
+%output_buffer_ptr = OpTypePointer StorageBuffer %buffer_type
+%wg_ptr = OpTypePointer Workgroup %buffer_type
+%half_wg_0_ptr = OpTypePointer Workgroup %half_buffer_type
+%half_wg_1_ptr = OpTypePointer Workgroup %other_half_buffer_type
+%push_constants_type = OpTypeStruct %uint %uint
+%push_constants_type_ptr = OpTypePointer PushConstant %push_constants_type
+
+;;; Workgroup has a block covering the entire memory and another two
+;;; blocks covering each half of the former.
+
+%wg = OpVariable %wg_ptr Workgroup
+%half_wg_0 = OpVariable %half_wg_0_ptr Workgroup
+%half_wg_1 = OpVariable %half_wg_1_ptr Workgroup
+
+%input_buffer_0 = OpVariable %input_buffer_0_ptr StorageBuffer
+%input_buffer_1 = OpVariable %input_buffer_1_ptr StorageBuffer
+%output_buffer = OpVariable %output_buffer_ptr StorageBuffer
+
+%index = OpVariable %uint_input_ptr Input
+%push_constants = OpVariable %push_constants_type_ptr PushConstant
+
+%main = OpFunction %void None %main_type
+%entry = OpLabel
+
+;;; Look up in the push constants values a and b that will be use to select
+;;; which invocation will do the work.
+
+%index_val = OpLoad %uint %index
+%first_ptr = OpAccessChain %uint_pc_ptr %push_constants %const_uint_0
+%second_ptr = OpAccessChain %uint_pc_ptr %push_constants %const_uint_1
+%first = OpLoad %uint %first_ptr
+%second = OpLoad %uint %second_ptr
+%is_first = OpIEqual %bool %index_val %first
+%is_second = OpIEqual %bool %index_val %second
+
+;;; Copy first input into half of the workgroup memory.  Because the
+;;; whole types match here, we can afford to copy the Variables
+;;; directly.  Only the first invocation specified will do that.
+
+OpSelectionMerge %after_first_copy None
+OpBranchConditional %is_first %first_copy %after_first_copy
+%first_copy = OpLabel
+
+OpCopyMemory %half_wg_0 %input_buffer_0
+
+OpBranch %after_first_copy
+%after_first_copy = OpLabel
+
+;;; Then copy the second input into the other half of Workgroup
+;;; memory, use OpAccessChain to extract the array pointers (what we
+;;; are copying), since the whole types don't match (different Offsets
+;;; in the block struct).  Only the second invocation specified will
+;;; do that.
+
+OpSelectionMerge %after_second_copy None
+OpBranchConditional %is_second %second_copy %after_second_copy
+%second_copy = OpLabel
+
+%a = OpAccessChain %half_array_wg_ptr %half_wg_1 %const_uint_0
+%b = OpAccessChain %half_array_sb_ptr %input_buffer_1 %const_uint_0
+OpCopyMemory %a %b
+
+OpBranch %after_second_copy
+%after_second_copy = OpLabel
+
+OpControlBarrier %const_uint_2 %const_uint_2 %const_uint_0
+
+;;; The two halves of Workgroup memory were filled, now copy the large
+;;; Workgroup block that alias the halves into the output.  Only the first
+;;; invocation specified will do that.
+
+OpSelectionMerge %after_third_copy None
+OpBranchConditional %is_first %third_copy %after_third_copy
+%third_copy = OpLabel
+
+OpCopyMemory %output_buffer %wg
+
+OpBranch %after_third_copy
+%after_third_copy = OpLabel
+
+OpReturn
+OpFunctionEnd
+
+END
+
+BUFFER input_buffer_0 DATA_TYPE uint32 SIZE 16 SERIES_FROM 1 INC_BY 1
+BUFFER input_buffer_1 DATA_TYPE uint32 SIZE 16 SERIES_FROM 17 INC_BY 1
+
+BUFFER output_buffer DATA_TYPE uint32 SIZE 32 FILL 99
+
+BUFFER expected_buffer DATA_TYPE uint32 SIZE 32 SERIES_FROM 1 INC_BY 1
+
+BUFFER const_buf DATA_TYPE uint32 DATA
+30 130
+END
+
+PIPELINE compute pipeline
+  ATTACH compute_shader
+
+  BIND BUFFER const_buf AS push_constant
+  BIND BUFFER input_buffer_0 AS storage DESCRIPTOR_SET 0 BINDING 0
+  BIND BUFFER input_buffer_1 AS storage DESCRIPTOR_SET 0 BINDING 1
+  BIND BUFFER output_buffer AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+RUN pipeline 1 1 1
+
+EXPECT output_buffer EQ_BUFFER expected_buffer
diff --git a/external/vulkancts/data/vulkan/amber/compute/workgroup_memory_explicit_layout/copy_memory_variable_pointers.amber b/external/vulkancts/data/vulkan/amber/compute/workgroup_memory_explicit_layout/copy_memory_variable_pointers.amber
new file mode 100644 (file)
index 0000000..e1f5bfd
--- /dev/null
@@ -0,0 +1,197 @@
+#!amber
+# Copyright 2021 Intel Corporation
+#
+# 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.
+
+DEVICE_EXTENSION VK_KHR_spirv_1_4
+DEVICE_EXTENSION VK_KHR_workgroup_memory_explicit_layout
+
+SHADER compute compute_shader SPIRV-ASM
+
+OpCapability Shader
+OpCapability WorkgroupMemoryExplicitLayoutKHR
+OpCapability VariablePointers
+OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %index %push_constants %input_buffer_0 %input_buffer_1 %output_buffer %wg %half_wg_0 %half_wg_1
+OpExecutionMode %main LocalSize 128 4 1
+
+OpDecorate %index BuiltIn LocalInvocationIndex
+OpDecorate %buffer_type Block
+OpDecorate %half_buffer_type Block
+OpDecorate %other_half_buffer_type Block
+OpMemberDecorate %buffer_type 0 Offset 0
+OpDecorate %array ArrayStride 4
+OpMemberDecorate %half_buffer_type 0 Offset 0
+OpMemberDecorate %other_half_buffer_type 0 Offset 64
+OpDecorate %half_array ArrayStride 4
+OpDecorate %input_buffer_0 DescriptorSet 0
+OpDecorate %input_buffer_0 Binding 0
+OpDecorate %input_buffer_1 DescriptorSet 0
+OpDecorate %input_buffer_1 Binding 1
+OpDecorate %output_buffer DescriptorSet 0
+OpDecorate %output_buffer Binding 2
+OpDecorate %wg Aliased
+OpDecorate %half_wg_0 Aliased
+OpDecorate %half_wg_1 Aliased
+OpMemberDecorate %push_constants_type 0 Offset 0
+OpMemberDecorate %push_constants_type 1 Offset 4
+OpDecorate %push_constants_type Block
+
+%uint = OpTypeInt 32 0
+%const_uint_0 = OpConstant %uint 0
+%const_uint_1 = OpConstant %uint 1
+%const_uint_2 = OpConstant %uint 2
+%const_uint_16 = OpConstant %uint 16
+%const_uint_32 = OpConstant %uint 32
+%const_uint_64 = OpConstant %uint 64
+%const_uint_128 = OpConstant %uint 128
+%uint_input_ptr = OpTypePointer Input %uint
+%uint_pc_ptr = OpTypePointer PushConstant %uint
+
+%bool = OpTypeBool
+%void = OpTypeVoid
+%main_type = OpTypeFunction %void
+%array = OpTypeArray %uint %const_uint_32
+%half_array = OpTypeArray %uint %const_uint_16
+%half_array_wg_ptr = OpTypePointer Workgroup %half_array
+%half_array_sb_ptr = OpTypePointer StorageBuffer %half_array
+%buffer_type = OpTypeStruct %array
+%half_buffer_type = OpTypeStruct %half_array
+%other_half_buffer_type = OpTypeStruct %half_array
+%input_buffer_0_ptr = OpTypePointer StorageBuffer %half_buffer_type
+%input_buffer_1_ptr = OpTypePointer StorageBuffer %half_buffer_type
+%output_buffer_ptr = OpTypePointer StorageBuffer %buffer_type
+%wg_ptr = OpTypePointer Workgroup %buffer_type
+%half_wg_0_ptr = OpTypePointer Workgroup %half_buffer_type
+%half_wg_1_ptr = OpTypePointer Workgroup %other_half_buffer_type
+%push_constants_type = OpTypeStruct %uint %uint
+%push_constants_type_ptr = OpTypePointer PushConstant %push_constants_type
+%null_src = OpConstantNull %half_array_sb_ptr
+
+;;; Workgroup has a block covering the entire memory and another two
+;;; blocks covering each half of the former.
+
+%wg = OpVariable %wg_ptr Workgroup
+%half_wg_0 = OpVariable %half_wg_0_ptr Workgroup
+%half_wg_1 = OpVariable %half_wg_1_ptr Workgroup
+
+%input_buffer_0 = OpVariable %input_buffer_0_ptr StorageBuffer
+%input_buffer_1 = OpVariable %input_buffer_1_ptr StorageBuffer
+%output_buffer = OpVariable %output_buffer_ptr StorageBuffer
+
+%index = OpVariable %uint_input_ptr Input
+%push_constants = OpVariable %push_constants_type_ptr PushConstant
+
+%main = OpFunction %void None %main_type
+%entry = OpLabel
+
+;;; Look up in the push constants values a and b that will be use to select
+;;; which invocation will do the work.
+
+%index_val = OpLoad %uint %index
+%first_ptr = OpAccessChain %uint_pc_ptr %push_constants %const_uint_0
+%second_ptr = OpAccessChain %uint_pc_ptr %push_constants %const_uint_1
+%first = OpLoad %uint %first_ptr
+%second = OpLoad %uint %second_ptr
+%is_first = OpIEqual %bool %index_val %first
+%is_second = OpIEqual %bool %index_val %second
+%is_first_or_second = OpLogicalOr %bool %is_first %is_second
+
+;;; Set the values for %dst using Select.
+
+%ptr_to_array_wg_0 = OpAccessChain %half_array_wg_ptr %half_wg_0 %const_uint_0
+%ptr_to_array_wg_1 = OpAccessChain %half_array_wg_ptr %half_wg_1 %const_uint_0
+%dst = OpSelect %half_array_wg_ptr %is_first %ptr_to_array_wg_0 %ptr_to_array_wg_1
+
+;;; Set the values for %src using OpPhi.
+
+OpSelectionMerge %after_src_choice None
+OpBranchConditional %is_first %src_for_first %next
+
+%src_for_first = OpLabel
+%first_src = OpAccessChain %half_array_sb_ptr %input_buffer_0 %const_uint_0
+OpBranch %after_src_choice
+
+%next = OpLabel
+OpSelectionMerge %merge_inner None
+OpBranchConditional %is_second %src_for_second %src_is_null
+
+%src_for_second = OpLabel
+%second_src = OpAccessChain %half_array_sb_ptr %input_buffer_1 %const_uint_0
+OpBranch %merge_inner
+
+%src_is_null = OpLabel
+OpBranch %merge_inner
+
+%merge_inner = OpLabel
+%inner_src = OpPhi %half_array_sb_ptr %second_src %src_for_second %null_src %src_is_null
+OpBranch %after_src_choice
+
+%after_src_choice = OpLabel
+%src = OpPhi %half_array_sb_ptr %first_src %src_for_first %inner_src %merge_inner
+
+;;; The first and second invocations identified will copy from src to
+;;; dst.
+
+OpSelectionMerge %after_var_copy None
+OpBranchConditional %is_first_or_second %var_copy %after_var_copy
+
+%var_copy = OpLabel
+OpCopyMemory %dst %src
+OpBranch %after_var_copy
+
+%after_var_copy = OpLabel
+
+OpControlBarrier %const_uint_2 %const_uint_2 %const_uint_0
+
+;;; The two halves of Workgroup memory were filled, now copy the large
+;;; Workgroup block that alias the halves into the output.  Only the first
+;;; invocation specified will do that.
+
+OpSelectionMerge %after_output_copy None
+OpBranchConditional %is_first %output_copy %after_output_copy
+
+%output_copy = OpLabel
+OpCopyMemory %output_buffer %wg
+OpBranch %after_output_copy
+
+%after_output_copy = OpLabel
+OpReturn
+OpFunctionEnd
+
+END
+
+BUFFER input_buffer_0 DATA_TYPE uint32 SIZE 16 SERIES_FROM 1 INC_BY 1
+BUFFER input_buffer_1 DATA_TYPE uint32 SIZE 16 SERIES_FROM 17 INC_BY 1
+
+BUFFER output_buffer DATA_TYPE uint32 SIZE 32 FILL 99
+
+BUFFER expected_buffer DATA_TYPE uint32 SIZE 32 SERIES_FROM 1 INC_BY 1
+
+BUFFER const_buf DATA_TYPE uint32 DATA
+30 130
+END
+
+PIPELINE compute pipeline
+  ATTACH compute_shader
+
+  BIND BUFFER const_buf AS push_constant
+  BIND BUFFER input_buffer_0 AS storage DESCRIPTOR_SET 0 BINDING 0
+  BIND BUFFER input_buffer_1 AS storage DESCRIPTOR_SET 0 BINDING 1
+  BIND BUFFER output_buffer AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+RUN pipeline 1 1 1
+
+EXPECT output_buffer EQ_BUFFER expected_buffer
index 8a03b5b..0c752d7 100644 (file)
@@ -23,6 +23,7 @@
  *//*--------------------------------------------------------------------*/
 
 #include "vktComputeWorkgroupMemoryExplicitLayoutTests.hpp"
+#include "vktAmberTestCase.hpp"
 #include "vktTestCase.hpp"
 #include "vktTestCaseUtil.hpp"
 #include "vktTestGroupUtil.hpp"
@@ -1323,6 +1324,31 @@ void AddSizeTests(tcu::TestCaseGroup* group)
                group->addChild(new SizeTest(group->getTestContext(), sizes[i]));
 }
 
+cts_amber::AmberTestCase* CreateAmberTestCase(tcu::TestContext& testCtx,
+                                                                                         const char* name,
+                                                                                         const char* description,
+                                                                                         const std::string& filename,
+                                                                                         const std::vector<std::string>& requirements = std::vector<std::string>())
+{
+       vk::SpirVAsmBuildOptions asm_options(VK_MAKE_VERSION(1, 1, 0), vk::SPIRV_VERSION_1_4);
+       asm_options.supports_VK_KHR_spirv_1_4 = true;
+
+       cts_amber::AmberTestCase *t = cts_amber::createAmberTestCase(testCtx, name, description, "compute/workgroup_memory_explicit_layout", filename, requirements);
+       t->setSpirVAsmBuildOptions(asm_options);
+       t->addRequirement("VK_KHR_workgroup_memory_explicit_layout");
+       return t;
+}
+
+void AddCopyMemoryTests(tcu::TestCaseGroup* group)
+{
+       tcu::TestContext& testCtx = group->getTestContext();
+
+       group->addChild(CreateAmberTestCase(testCtx, "basic", "", "copy_memory_basic.amber"));
+       group->addChild(CreateAmberTestCase(testCtx, "two_invocations", "", "copy_memory_two_invocations.amber"));
+       group->addChild(CreateAmberTestCase(testCtx, "variable_pointers", "", "copy_memory_variable_pointers.amber",
+                                                                               { "VariablePointerFeatures.variablePointers" }));
+}
+
 } // anonymous
 
 tcu::TestCaseGroup* createWorkgroupMemoryExplicitLayoutTests(tcu::TestContext& testCtx)
@@ -1345,6 +1371,10 @@ tcu::TestCaseGroup* createWorkgroupMemoryExplicitLayoutTests(tcu::TestContext& t
        AddSizeTests(size);
        tests->addChild(size);
 
+       tcu::TestCaseGroup* copy_memory = new tcu::TestCaseGroup(testCtx, "copy_memory", "Test OpCopyMemory with Workgroup memory");
+       AddCopyMemoryTests(copy_memory);
+       tests->addChild(copy_memory);
+
        return tests.release();
 }
 
index 55498d3..b348133 100644 (file)
@@ -521472,6 +521472,9 @@ dEQP-VK.compute.workgroup_memory_explicit_layout.size.16384
 dEQP-VK.compute.workgroup_memory_explicit_layout.size.32768
 dEQP-VK.compute.workgroup_memory_explicit_layout.size.49152
 dEQP-VK.compute.workgroup_memory_explicit_layout.size.65536
+dEQP-VK.compute.workgroup_memory_explicit_layout.copy_memory.basic
+dEQP-VK.compute.workgroup_memory_explicit_layout.copy_memory.two_invocations
+dEQP-VK.compute.workgroup_memory_explicit_layout.copy_memory.variable_pointers
 dEQP-VK.image.store.with_format.1d.r32g32b32a32_sfloat
 dEQP-VK.image.store.with_format.1d.r16g16b16a16_sfloat
 dEQP-VK.image.store.with_format.1d.r32_sfloat