1#!amber
2# Copyright 2020 The Amber Authors.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#     https://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16DEVICE_EXTENSION VK_KHR_variable_pointers
17DEVICE_EXTENSION VK_KHR_storage_buffer_storage_class
18DEVICE_FEATURE VariablePointerFeatures.variablePointers
19DEVICE_FEATURE VariablePointerFeatures.variablePointersStorageBuffer
20
21# Based on the following GLSL shader pseudocode:
22#
23#SHADER compute compute_shader GLSL
24##version 430
25#
26#layout(set = 0, binding = 0) buffer InputData
27#{
28#    int data[10];
29#} input0[2];
30#
31#layout(set = 0, binding = 1) buffer InputData
32#{
33#    int data[10];
34#} input1[2];
35#
36#layout(set = 0, binding = 2) buffer Result
37#{
38#    int result;
39#};
40#
41#layout(push_constant) uniform Indices
42#{
43#    int idx0;
44#    int idx1;
45#    int idx2;
46#};
47#
48#
49#void main()
50#{
51#    InputData input[]* = (idx0 == 0) ? &input0 : &input1;
52#    result = input[idx1].data[idx2];
53#}
54#END
55
56SHADER compute compute_shader SPIRV-ASM
57               OpCapability Shader
58               OpCapability VariablePointers
59               OpExtension "SPV_KHR_variable_pointers"
60          %1 = OpExtInstImport "GLSL.std.450"
61               OpMemoryModel Logical GLSL450
62               OpEntryPoint GLCompute %main "main"
63               OpExecutionMode %main LocalSize 1 1 1
64               OpSource GLSL 430
65               OpMemberDecorate %Indices 0 Offset 0
66               OpMemberDecorate %Indices 1 Offset 4
67               OpMemberDecorate %Indices 2 Offset 8
68               OpDecorate %Indices Block
69               OpMemberDecorate %Result 0 Offset 0
70               OpDecorate %Result Block
71               OpDecorate %result DescriptorSet 0
72               OpDecorate %result Binding 2
73               OpDecorate %_arr_int_int_10 ArrayStride 16
74               OpMemberDecorate %InputData 0 Offset 0
75               OpDecorate %InputData Block
76               OpDecorate %input0 DescriptorSet 0
77               OpDecorate %input0 Binding 0
78               OpDecorate %input1 DescriptorSet 0
79               OpDecorate %input1 Binding 1
80       %void = OpTypeVoid
81       %bool = OpTypeBool
82        %int = OpTypeInt 32 1
83  %void_func = OpTypeFunction %void
84    %Indices = OpTypeStruct %int %int %int
85%_ptr_PushConstant_Indices = OpTypePointer PushConstant %Indices
86    %indices = OpVariable %_ptr_PushConstant_Indices PushConstant
87      %int_0 = OpConstant %int 0
88      %int_1 = OpConstant %int 1
89      %int_2 = OpConstant %int 2
90     %int_10 = OpConstant %int 10
91%_ptr_PushConstant_int = OpTypePointer PushConstant %int
92     %Result = OpTypeStruct %int
93%_ptr_StorageBuffer_Result = OpTypePointer StorageBuffer %Result
94     %result = OpVariable %_ptr_StorageBuffer_Result StorageBuffer
95%_arr_int_int_10 = OpTypeArray %int %int_10
96  %InputData = OpTypeStruct %_arr_int_int_10
97%_arr_InputData_int_2 = OpTypeArray %InputData %int_2
98%_ptr_StorageBuffer__arr_InputData_int_2 = OpTypePointer StorageBuffer %_arr_InputData_int_2
99%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
100     %input0 = OpVariable %_ptr_StorageBuffer__arr_InputData_int_2 StorageBuffer
101     %input1 = OpVariable %_ptr_StorageBuffer__arr_InputData_int_2 StorageBuffer
102       %main = OpFunction %void None %void_func
103      %label = OpLabel
104   %idx0_ptr = OpAccessChain %_ptr_PushConstant_int %indices %int_0
105       %idx0 = OpLoad %int %idx0_ptr
106   %idx1_ptr = OpAccessChain %_ptr_PushConstant_int %indices %int_1
107       %idx1 = OpLoad %int %idx1_ptr
108   %idx2_ptr = OpAccessChain %_ptr_PushConstant_int %indices %int_2
109       %idx2 = OpLoad %int %idx2_ptr
110  %idx0_zero = OpIEqual %bool %idx0 %int_0
111%variable_ptr = OpSelect %_ptr_StorageBuffer__arr_InputData_int_2 %idx0_zero %input0 %input1
112%input_data_ptr = OpAccessChain %_ptr_StorageBuffer_int %variable_ptr %idx1 %int_0 %idx2
113 %input_data = OpLoad %int %input_data_ptr
114%result_data_ptr = OpAccessChain %_ptr_StorageBuffer_int %result %int_0
115               OpStore %result_data_ptr %input_data
116               OpReturn
117               OpFunctionEnd
118END
119
120BUFFER buf0 DATA_TYPE int32 SIZE 1024 SERIES_FROM 0 INC_BY 1
121BUFFER buf1 DATA_TYPE int32 SIZE 1024 SERIES_FROM 1 INC_BY 1
122BUFFER buf2 DATA_TYPE int32 SIZE 1024 SERIES_FROM 2 INC_BY 1
123BUFFER buf3 DATA_TYPE int32 SIZE 1024 SERIES_FROM 3 INC_BY 1
124BUFFER indices0 DATA_TYPE int32 DATA
1250 1 2
126END
127BUFFER indices1 DATA_TYPE int32 DATA
1281 1 2
129END
130BUFFER result DATA_TYPE int32 DATA
1310
132END
133
134# This pipeline will select input from buf1 which has a dynamic offset of 256 bytes.
135# The sequence in that buffer starts from 1, and the array stride in the shader is
136# 16 bytes. The shader reads an array element number 2. Thus the expected value is:
137# 256/4 + 1 + 2 * 4 = 73.
138PIPELINE compute pipeline0
139  ATTACH compute_shader
140
141  BIND BUFFER_ARRAY buf0 buf1 AS storage_dynamic DESCRIPTOR_SET 0 BINDING 0 OFFSET 0 256
142  BIND BUFFER_ARRAY buf2 buf3 AS storage_dynamic DESCRIPTOR_SET 0 BINDING 1 OFFSET 512 768
143  BIND BUFFER indices0 AS push_constant
144  BIND BUFFER result AS storage DESCRIPTOR_SET 0 BINDING 2
145END
146
147RUN pipeline0 1 1 1
148
149EXPECT result IDX 0 EQ 73
150
151# This pipeline will select input from buf3 which has a dynamic offset of 768 bytes.
152# The sequence in that buffer starts from 3, and the array stride in the shader is
153# 16 bytes. The shader reads an array element number 2. Thus the expected value is:
154# 768/4 + 3 + 2 * 4 = 203.
155PIPELINE compute pipeline1
156  ATTACH compute_shader
157
158  BIND BUFFER_ARRAY buf0 buf1 AS storage_dynamic DESCRIPTOR_SET 0 BINDING 0 OFFSET 0 256
159  BIND BUFFER_ARRAY buf2 buf3 AS storage_dynamic DESCRIPTOR_SET 0 BINDING 1 OFFSET 512 768
160  BIND BUFFER indices1 AS push_constant
161  BIND BUFFER result AS storage DESCRIPTOR_SET 0 BINDING 2
162END
163
164RUN pipeline1 1 1 1
165
166EXPECT result IDX 0 EQ 203
167