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