blob: 620fe0a609c5b620948044797c2e9d1a32664f6e [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_FEATURE VariablePointerFeatures.variablePointers
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 32 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 90
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 4 1 1
EXPECT output_buffer EQ_BUFFER expected_buffer