blob: a5179e3e6a1a3481f0fb829c1cc5bbf3b5f67dc2 [file] [log] [blame]
#!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