1#!amber
2#
3# Copyright 2020 The Khronos Group Inc.
4# Copyright 2020 Valve Corporation.
5#
6# Licensed under the Apache License, Version 2.0 (the "License");
7# you may not use this file except in compliance with the License.
8# You may obtain a copy of the License at
9#
10#     https://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS,
14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15# See the License for the specific language governing permissions and
16# limitations under the License.
17
18SHADER compute comp SPIRV-ASM TARGET_ENV spv1.0
19; SPIR-V
20; Version: 1.0
21                     OpCapability Shader
22                     OpMemoryModel Logical GLSL450
23                     OpEntryPoint GLCompute %main "main"
24                     OpExecutionMode %main LocalSize 1 1 1
25                     OpMemberDecorate %InputBlock 0 Offset 0
26                     OpDecorate %InputBlock BufferBlock
27                     OpDecorate %inputBuffer DescriptorSet 0
28                     OpDecorate %inputBuffer Binding 0
29                     OpMemberDecorate %OutputBlock 0 Offset 0
30                     OpDecorate %OutputBlock BufferBlock
31                     OpDecorate %outputBuffer DescriptorSet 0
32                     OpDecorate %outputBuffer Binding 1
33             %void = OpTypeVoid
34         %voidFunc = OpTypeFunction %void
35             %uint = OpTypeInt 32 0
36           %uint_4 = OpConstant %uint 4
37           %uint_5 = OpConstant %uint 5
38           %uint_6 = OpConstant %uint 6
39           %uint_7 = OpConstant %uint 7
40           %uint_8 = OpConstant %uint 8
41       %InputBlock = OpTypeStruct %uint
42   %InputBlock_ptr = OpTypePointer Uniform %InputBlock
43      %inputBuffer = OpVariable %InputBlock_ptr Uniform
44              %int = OpTypeInt 32 1
45            %int_0 = OpConstant %int 0
46 %uint_uniform_ptr = OpTypePointer Uniform %uint
47%uint_Function_ptr = OpTypePointer Function %uint
48      %OutputBlock = OpTypeStruct %uint
49  %OutputBlock_ptr = OpTypePointer Uniform %OutputBlock
50     %outputBuffer = OpVariable %OutputBlock_ptr Uniform
51             %main = OpFunction %void None %voidFunc
52        %mainLabel = OpLabel
53;
54; %aux will contain value 4 by default and it should not be modified.
55;
56              %aux = OpVariable %uint_Function_ptr Function
57                     OpStore %aux %uint_4
58            %ptrIn = OpAccessChain %uint_uniform_ptr %inputBuffer %int_0
59         %inputVal = OpLoad %uint %ptrIn
60;
61; From fauly.asm in https://gitlab.freedesktop.org/mesa/mesa/-/issues/3460
62;
63;               OpSelectionMerge %3153 None
64;               OpSwitch %166 %3152 0 %3153 1 %3151 2 %3150 3 %3149
65;       %3152 = OpLabel
66;               OpBranch %3153
67;       %3151 = OpLabel
68;               OpBranch %3153
69;       %3150 = OpLabel
70;        %345 = OpAccessChain %_ptr_StorageBuffer_v4float %71 %uint_0 %uint_37
71;        %346 = OpLoad %v4float %345
72;        %347 = OpBitcast %v4uint %346
73;        %348 = OpCompositeExtract %uint %347 0
74;        %188 = OpShiftLeftLogical %uint %348 %uint_1
75;               OpBranch %3153
76;       %3149 = OpLabel
77;               OpBranch %3153
78;       %3153 = OpLabel
79;
80; Similar structure replicated below.
81; Value 0 jumps to the merge label while the others store unexpected values in %aux.
82;
83                     OpSelectionMerge %mergeLabel None
84                     OpSwitch %inputVal %defaultLabel 0 %mergeLabel 1 %val1Label 2 %val2Label 3 %val3Label
85     %defaultLabel = OpLabel
86                     OpStore %aux %uint_5
87                     OpBranch %mergeLabel
88        %val1Label = OpLabel
89                     OpStore %aux %uint_6
90                     OpBranch %mergeLabel
91        %val2Label = OpLabel
92                     OpStore %aux %uint_7
93                     OpBranch %mergeLabel
94        %val3Label = OpLabel
95                     OpStore %aux %uint_8
96                     OpBranch %mergeLabel
97       %mergeLabel = OpLabel
98           %ptrOut = OpAccessChain %uint_uniform_ptr %outputBuffer %int_0
99          %aux_val = OpLoad %uint %aux
100                     OpStore %ptrOut %aux_val
101                     OpReturn
102                     OpFunctionEnd
103END
104
105BUFFER inputBuffer  DATA_TYPE uint32 DATA 0 END
106BUFFER outputBuffer DATA_TYPE uint32 DATA 0 END
107
108# Store 0 as the input value to make the switch go directly to the merge label.
109PIPELINE compute compute_pipeline
110  ATTACH comp
111  BIND BUFFER inputBuffer  AS storage DESCRIPTOR_SET 0 BINDING 0
112  BIND BUFFER outputBuffer AS storage DESCRIPTOR_SET 0 BINDING 1
113END
114
115RUN compute_pipeline 1 1 1
116# Expect 4, the initial value stored in %aux before the switch.
117EXPECT outputBuffer IDX 0 EQ 4
118