• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!amber
2# Copyright 2022 Google LLC
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#     http://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
16SHADER vertex vert_shader PASSTHROUGH
17
18SHADER fragment frag_shader GLSL TARGET_ENV spv1.3
19#version 460
20#extension GL_EXT_demote_to_helper_invocation : require
21#extension GL_KHR_shader_subgroup_quad : require
22
23layout(binding = 0) readonly buffer Block0
24{
25    float alpha[];
26};
27
28layout(binding = 1) buffer Block1
29{
30    uint atomics[];
31};
32
33layout(location = 0) out vec4 color;
34
35float build_alpha_shuffle(float v)
36{
37    v = (helperInvocationEXT() ? 8.0 : roundEven(v));
38    vec4 helpers;
39    helpers.x = subgroupQuadBroadcast(v, 0u);
40    helpers.y = subgroupQuadBroadcast(v, 1u);
41    helpers.z = subgroupQuadBroadcast(v, 2u);
42    helpers.w = subgroupQuadBroadcast(v, 3u);
43
44    return dot(helpers, vec4(1, 10, 100, 1000));
45}
46
47void main()
48{
49    ivec2 coord = ivec2(gl_FragCoord.xy);
50    int linear_coord = coord.y * 2 + coord.x;
51
52    float alpha_value = alpha[linear_coord];
53    float mask0 = build_alpha_shuffle(alpha_value);
54
55    // Lane 1 and 2 should be nuked by this.
56    if (fract(alpha_value) < 0.5)
57    {
58        demote;
59    }
60
61    float mask1 = build_alpha_shuffle(alpha_value);
62    uint last_value = 0u;
63
64    last_value = atomicAdd(atomics[linear_coord], 101u);
65
66    if (linear_coord == 3 || last_value > 1000)
67    {
68        demote;
69    }
70
71    float mask2 = build_alpha_shuffle(alpha_value);
72
73    color = vec4(1.0, mask0, mask1, mask2);
74}
75END
76
77SHADER compute comp_shader GLSL
78#version 460
79layout(local_size_x=1,local_size_y=1) in;
80uniform layout(set=0, binding=0, rgba32f) image2D resultImage;
81
82layout(set = 0, binding = 1) buffer block0
83{
84    vec4 results[];
85};
86
87layout(set = 0, binding = 2) readonly buffer Block1
88{
89    uvec4 atomics;
90};
91
92void main()
93{
94    vec4 colorValues = imageLoad(resultImage, ivec2(0, 0));
95
96    results[0] = vec4(0.0, .0, 0.0, 0.0);
97    results[1] = imageLoad(resultImage, ivec2(1, 0));
98    results[2] = imageLoad(resultImage, ivec2(0, 1));
99    results[3] = imageLoad(resultImage, ivec2(1, 1));
100
101    // We don't know if the invocations are helpers or not at the start
102    // and therefore all the possible outcomes are allowed.
103    for (int x = 0; x < 2; x++)
104    {
105        for (int y = 0; y < 2; y++)
106        {
107            for (int z = 0; z < 2; z++)
108            {
109                for (int w = 0; w < 2; w++)
110                {
111                    vec4 testVec = vec4(x * 1.0, y * 2.0, z * 3.0, w * 4.0);
112                    uvec4 atomicVec = uvec4(0, 0, 0, 0);
113
114                    for (int j = 0; j < 4; j++)
115                    {
116                        if (testVec[j] > 0.0)
117                        {
118                            testVec[j] = 8.0;
119                            atomicVec[j] = 0;
120                        }
121                        else
122                        {
123                            testVec[j] = j + 1.0;
124                            atomicVec[j] = 101;
125                        }
126                    }
127
128                    float mask0 = dot(testVec, vec4(1, 10, 100, 1000));
129                    float mask1 = dot(vec4(testVec.x, 8.0, 8.0, testVec.w), vec4(1, 10, 100, 1000));
130                    float mask2 = dot(vec4(testVec.x, 8.0, 8.0, 8.0), vec4(1, 10, 100, 1000));
131
132                    atomicVec[1] = 0;
133                    atomicVec[2] = 0;
134
135                    if (colorValues.x == 1.0 && atomics.x == atomicVec.x
136                    && colorValues.y == mask0 && atomics.y == atomicVec.y
137                    && colorValues.z == mask1 && atomics.z == atomicVec.z
138                    && colorValues.w == mask2 && atomics.w == atomicVec.w)
139                    {
140                        results[0] = vec4(1.0, 1.0, 1.0, 1.0);
141                    }
142                }
143            }
144        }
145    }
146}
147END
148
149BUFFER alpha_keys DATA_TYPE float DATA
150    0.75
151    2.25
152    3.25
153    3.75
154END
155
156BUFFER atomics DATA_TYPE uint32 DATA
157    0
158    0
159    0
160    0
161END
162
163BUFFER results DATA_TYPE float SIZE 16 FILL 0.0
164BUFFER ref_buffer DATA_TYPE float SIZE 16 FILL 1.0
165
166BUFFER framebuffer FORMAT R32G32B32A32_SFLOAT
167
168PIPELINE graphics myPipeline
169    ATTACH vert_shader
170    ATTACH frag_shader
171
172    FRAMEBUFFER_SIZE 2 2
173
174    BIND BUFFER framebuffer AS color LOCATION 0
175    BIND BUFFER alpha_keys AS storage DESCRIPTOR_SET 0 BINDING 0
176    BIND BUFFER atomics AS storage DESCRIPTOR_SET 0 BINDING 1
177END
178
179PIPELINE compute verifyPipeline
180    ATTACH comp_shader
181    FRAMEBUFFER_SIZE 2 2
182    BIND BUFFER framebuffer AS storage_image DESCRIPTOR_SET 0 BINDING 0
183    BIND BUFFER results AS storage DESCRIPTOR_SET 0 BINDING 1
184    BIND BUFFER atomics AS storage DESCRIPTOR_SET 0 BINDING 2
185END
186
187CLEAR_COLOR myPipeline 255 255 255 255
188CLEAR myPipeline
189
190RUN myPipeline DRAW_RECT POS 0 0 SIZE 2 2
191RUN verifyPipeline 1 1 1
192
193EXPECT results EQ_BUFFER ref_buffer