7@if(MESHLET_VISIBILITY_BUFFER_RASTER_PASS_OUTPUT) 8@group(0) @binding(0) var mip_0: texture_storage_2d<r64uint, read>; 10@group(0) @binding(0) var mip_0: texture_storage_2d<r32uint, read>; 12@group(0) @binding(0) var mip_0: texture_depth_multisampled_2d; 14@group(0) @binding(0) var mip_0: texture_depth_2d; 15@group(0) @binding(1) var mip_1: texture_storage_2d<r32float, write>; 16@group(0) @binding(2) var mip_2: texture_storage_2d<r32float, write>; 17@group(0) @binding(3) var mip_3: texture_storage_2d<r32float, write>; 18@group(0) @binding(4) var mip_4: texture_storage_2d<r32float, write>; 19@group(0) @binding(5) var mip_5: texture_storage_2d<r32float, write>; 20@group(0) @binding(6) var mip_6: texture_storage_2d<r32float, read_write>; 21@group(0) @binding(7) var mip_7: texture_storage_2d<r32float, write>; 22@group(0) @binding(8) var mip_8: texture_storage_2d<r32float, write>; 23@group(0) @binding(9) var mip_9: texture_storage_2d<r32float, write>; 24@group(0) @binding(10) var mip_10: texture_storage_2d<r32float, write>; 25@group(0) @binding(11) var mip_11: texture_storage_2d<r32float, write>; 26@group(0) @binding(12) var mip_12: texture_storage_2d<r32float, write>; 27@group(0) @binding(13) var samplr: sampler; 28struct Constants { max_mip_level: u32 } 29var<immediate> constants: Constants; 35var<workgroup> intermediate_memory: array<array<f32, 16>, 16>; 38@workgroup_size(256, 1, 1) 39fn downsample_depth_first( 40 @builtin(workgroup_id) workgroup_id: vec3u, 41 @builtin(local_invocation_index) local_invocation_index: u32, 43 let sub_xy = remap_for_wave_reduction(local_invocation_index % 64u); 44 let x = sub_xy.x + 8u * ((local_invocation_index >> 6u) % 2u); 45 let y = sub_xy.y + 8u * (local_invocation_index >> 7u); 47 downsample_mips_0_and_1(x, y, workgroup_id.xy, local_invocation_index); 49 downsample_mips_2_to_5(x, y, workgroup_id.xy, local_invocation_index); 53@workgroup_size(256, 1, 1) 54fn downsample_depth_second(@builtin(local_invocation_index) local_invocation_index: u32) { 55 let sub_xy = remap_for_wave_reduction(local_invocation_index % 64u); 56 let x = sub_xy.x + 8u * ((local_invocation_index >> 6u) % 2u); 57 let y = sub_xy.y + 8u * (local_invocation_index >> 7u); 59 downsample_mips_6_and_7(x, y); 61 downsample_mips_8_to_11(x, y, local_invocation_index); 64fn downsample_mips_0_and_1(x: u32, y: u32, workgroup_id: vec2u, local_invocation_index: u32) { 67 var tex = vec2(workgroup_id * 64u) + vec2(x * 2u, y * 2u); 68 var pix = vec2(workgroup_id * 32u) + vec2(x, y); 69 v[0] = reduce_load_mip_0(tex); 70 textureStore(mip_1, pix, vec4(v[0])); 72 tex = vec2(workgroup_id * 64u) + vec2(x * 2u + 32u, y * 2u); 73 pix = vec2(workgroup_id * 32u) + vec2(x + 16u, y); 74 v[1] = reduce_load_mip_0(tex); 75 textureStore(mip_1, pix, vec4(v[1])); 77 tex = vec2(workgroup_id * 64u) + vec2(x * 2u, y * 2u + 32u); 78 pix = vec2(workgroup_id * 32u) + vec2(x, y + 16u); 79 v[2] = reduce_load_mip_0(tex); 80 textureStore(mip_1, pix, vec4(v[2])); 82 tex = vec2(workgroup_id * 64u) + vec2(x * 2u + 32u, y * 2u + 32u); 83 pix = vec2(workgroup_id * 32u) + vec2(x + 16u, y + 16u); 84 v[3] = reduce_load_mip_0(tex); 85 textureStore(mip_1, pix, vec4(v[3])); 87 if constants.max_mip_level <= 1u { return; } 89 for (var i = 0u; i < 4u; i++) { 90 intermediate_memory[x][y] = v[i]; 92 if local_invocation_index < 64u { 94 intermediate_memory[x * 2u + 0u][y * 2u + 0u], 95 intermediate_memory[x * 2u + 1u][y * 2u + 0u], 96 intermediate_memory[x * 2u + 0u][y * 2u + 1u], 97 intermediate_memory[x * 2u + 1u][y * 2u + 1u], 99 pix = (workgroup_id * 16u) + vec2( 103 textureStore(mip_2, pix, vec4(v[i])); 108 if local_invocation_index < 64u { 109 intermediate_memory[x + 0u][y + 0u] = v[0]; 110 intermediate_memory[x + 8u][y + 0u] = v[1]; 111 intermediate_memory[x + 0u][y + 8u] = v[2]; 112 intermediate_memory[x + 8u][y + 8u] = v[3]; 116fn downsample_mips_2_to_5(x: u32, y: u32, workgroup_id: vec2u, local_invocation_index: u32) { 117 if constants.max_mip_level <= 2u { return; } 119 downsample_mip_2(x, y, workgroup_id, local_invocation_index); 121 if constants.max_mip_level <= 3u { return; } 123 downsample_mip_3(x, y, workgroup_id, local_invocation_index); 125 if constants.max_mip_level <= 4u { return; } 127 downsample_mip_4(x, y, workgroup_id, local_invocation_index); 129 if constants.max_mip_level <= 5u { return; } 131 downsample_mip_5(workgroup_id, local_invocation_index); 134fn downsample_mip_2(x: u32, y: u32, workgroup_id: vec2u, local_invocation_index: u32) { 135 if local_invocation_index < 64u { 136 let v = reduce_4(vec4( 137 intermediate_memory[x * 2u + 0u][y * 2u + 0u], 138 intermediate_memory[x * 2u + 1u][y * 2u + 0u], 139 intermediate_memory[x * 2u + 0u][y * 2u + 1u], 140 intermediate_memory[x * 2u + 1u][y * 2u + 1u], 142 textureStore(mip_3, (workgroup_id * 8u) + vec2(x, y), vec4(v)); 143 intermediate_memory[x * 2u + y % 2u][y * 2u] = v; 147fn downsample_mip_3(x: u32, y: u32, workgroup_id: vec2u, local_invocation_index: u32) { 148 if local_invocation_index < 16u { 149 let v = reduce_4(vec4( 150 intermediate_memory[x * 4u + 0u + 0u][y * 4u + 0u], 151 intermediate_memory[x * 4u + 2u + 0u][y * 4u + 0u], 152 intermediate_memory[x * 4u + 0u + 1u][y * 4u + 2u], 153 intermediate_memory[x * 4u + 2u + 1u][y * 4u + 2u], 155 textureStore(mip_4, (workgroup_id * 4u) + vec2(x, y), vec4(v)); 156 intermediate_memory[x * 4u + y][y * 4u] = v; 160fn downsample_mip_4(x: u32, y: u32, workgroup_id: vec2u, local_invocation_index: u32) { 161 if local_invocation_index < 4u { 162 let v = reduce_4(vec4( 163 intermediate_memory[x * 8u + 0u + 0u + y * 2u][y * 8u + 0u], 164 intermediate_memory[x * 8u + 4u + 0u + y * 2u][y * 8u + 0u], 165 intermediate_memory[x * 8u + 0u + 1u + y * 2u][y * 8u + 4u], 166 intermediate_memory[x * 8u + 4u + 1u + y * 2u][y * 8u + 4u], 168 textureStore(mip_5, (workgroup_id * 2u) + vec2(x, y), vec4(v)); 169 intermediate_memory[x + y * 2u][0u] = v; 173fn downsample_mip_5(workgroup_id: vec2u, local_invocation_index: u32) { 174 if local_invocation_index < 1u { 175 let v = reduce_4(vec4( 176 intermediate_memory[0u][0u], 177 intermediate_memory[1u][0u], 178 intermediate_memory[2u][0u], 179 intermediate_memory[3u][0u], 181 textureStore(mip_6, workgroup_id, vec4(v)); 185fn downsample_mips_6_and_7(x: u32, y: u32) { 188 var tex = vec2(x * 4u + 0u, y * 4u + 0u); 189 var pix = vec2(x * 2u + 0u, y * 2u + 0u); 190 v[0] = reduce_load_mip_6(tex); 191 textureStore(mip_7, pix, vec4(v[0])); 193 tex = vec2(x * 4u + 2u, y * 4u + 0u); 194 pix = vec2(x * 2u + 1u, y * 2u + 0u); 195 v[1] = reduce_load_mip_6(tex); 196 textureStore(mip_7, pix, vec4(v[1])); 198 tex = vec2(x * 4u + 0u, y * 4u + 2u); 199 pix = vec2(x * 2u + 0u, y * 2u + 1u); 200 v[2] = reduce_load_mip_6(tex); 201 textureStore(mip_7, pix, vec4(v[2])); 203 tex = vec2(x * 4u + 2u, y * 4u + 2u); 204 pix = vec2(x * 2u + 1u, y * 2u + 1u); 205 v[3] = reduce_load_mip_6(tex); 206 textureStore(mip_7, pix, vec4(v[3])); 208 if constants.max_mip_level <= 7u { return; } 210 let vr = reduce_4(v); 211 textureStore(mip_8, vec2(x, y), vec4(vr)); 212 intermediate_memory[x][y] = vr; 215fn downsample_mips_8_to_11(x: u32, y: u32, local_invocation_index: u32) { 216 if constants.max_mip_level <= 8u { return; } 218 downsample_mip_8(x, y, local_invocation_index); 220 if constants.max_mip_level <= 9u { return; } 222 downsample_mip_9(x, y, local_invocation_index); 224 if constants.max_mip_level <= 10u { return; } 226 downsample_mip_10(x, y, local_invocation_index); 228 if constants.max_mip_level <= 11u { return; } 230 downsample_mip_11(local_invocation_index); 233fn downsample_mip_8(x: u32, y: u32, local_invocation_index: u32) { 234 if local_invocation_index < 64u { 235 let v = reduce_4(vec4( 236 intermediate_memory[x * 2u + 0u][y * 2u + 0u], 237 intermediate_memory[x * 2u + 1u][y * 2u + 0u], 238 intermediate_memory[x * 2u + 0u][y * 2u + 1u], 239 intermediate_memory[x * 2u + 1u][y * 2u + 1u], 241 textureStore(mip_9, vec2(x, y), vec4(v)); 242 intermediate_memory[x * 2u + y % 2u][y * 2u] = v; 246fn downsample_mip_9(x: u32, y: u32, local_invocation_index: u32) { 247 if local_invocation_index < 16u { 248 let v = reduce_4(vec4( 249 intermediate_memory[x * 4u + 0u + 0u][y * 4u + 0u], 250 intermediate_memory[x * 4u + 2u + 0u][y * 4u + 0u], 251 intermediate_memory[x * 4u + 0u + 1u][y * 4u + 2u], 252 intermediate_memory[x * 4u + 2u + 1u][y * 4u + 2u], 254 textureStore(mip_10, vec2(x, y), vec4(v)); 255 intermediate_memory[x * 4u + y][y * 4u] = v; 259fn downsample_mip_10(x: u32, y: u32, local_invocation_index: u32) { 260 if local_invocation_index < 4u { 261 let v = reduce_4(vec4( 262 intermediate_memory[x * 8u + 0u + 0u + y * 2u][y * 8u + 0u], 263 intermediate_memory[x * 8u + 4u + 0u + y * 2u][y * 8u + 0u], 264 intermediate_memory[x * 8u + 0u + 1u + y * 2u][y * 8u + 4u], 265 intermediate_memory[x * 8u + 4u + 1u + y * 2u][y * 8u + 4u], 267 textureStore(mip_11, vec2(x, y), vec4(v)); 268 intermediate_memory[x + y * 2u][0u] = v; 272fn downsample_mip_11(local_invocation_index: u32) { 273 if local_invocation_index < 1u { 274 let v = reduce_4(vec4( 275 intermediate_memory[0u][0u], 276 intermediate_memory[1u][0u], 277 intermediate_memory[2u][0u], 278 intermediate_memory[3u][0u], 280 textureStore(mip_12, vec2(0u, 0u), vec4(v)); 284fn remap_for_wave_reduction(a: u32) -> vec2u { 286 insertBits(extractBits(a, 2u, 3u), a, 0u, 1u), 287 insertBits(extractBits(a, 3u, 3u), extractBits(a, 1u, 2u), 0u, 2u), 291fn reduce_load_mip_0(tex: vec2u) -> f32 { 292 let a = load_mip_0(tex.x, tex.y); 293 let b = load_mip_0(tex.x + 1u, tex.y); 294 let c = load_mip_0(tex.x, tex.y + 1u); 295 let d = load_mip_0(tex.x + 1u, tex.y + 1u); 296 return reduce_4(vec4(a, b, c, d)); 299fn reduce_load_mip_6(tex: vec2u) -> f32 { 300 return reduce_4(vec4( 301 textureLoad(mip_6, tex + vec2(0u, 0u)).r, 302 textureLoad(mip_6, tex + vec2(0u, 1u)).r, 303 textureLoad(mip_6, tex + vec2(1u, 0u)).r, 304 textureLoad(mip_6, tex + vec2(1u, 1u)).r, 316fn load_mip_0(x: u32, y: u32) -> f32 { 317 let actual_size = textureDimensions(mip_0).xy; 318 let virtual_size = vec2<u32>( 319 next_power_of_two(actual_size.x), 320 next_power_of_two(actual_size.y) 322 let virtual_uv = (vec2<f32>(f32(x), f32(y)) + 0.5) / vec2<f32>(virtual_size); 323 @if(MESHLET_VISIBILITY_BUFFER_RASTER_PASS_OUTPUT) { 324 let virtual_st = virtual_uv * vec2<f32>(actual_size); 325 let visibility = load_mip_0_meshlet(virtual_st, 32u); 326 return reduce_4(visibility); 328 let virtual_st = virtual_uv * vec2<f32>(actual_size); 329 let visibility = load_mip_0_meshlet(virtual_st, 0u); 330 return reduce_4(visibility); 331 } @elif(MULTISAMPLE) { 335 let virtual_st = virtual_uv * vec2<f32>(actual_size); 336 var result = load_mip_0_single_sample(virtual_st, 0); 337 let sample_count = i32(textureNumSamples(mip_0)); 338 for (var sample = 1; sample < sample_count; sample += 1) { 339 result = min(result, load_mip_0_single_sample(virtual_st, sample)); 343 return reduce_4(textureGather(mip_0, samplr, virtual_uv)); 353fn load_mip_0_meshlet(st: vec2<f32>, shift: u32) -> vec4<f32> { 354 let st0 = vec2<u32>(floor(st - 0.5)); 357 bitcast<f32>(u32(textureLoad(mip_0, vec2<u32>(st0.x, st0.y)).r) >> shift), 358 bitcast<f32>(u32(textureLoad(mip_0, vec2<u32>(st0.x, st1.y)).r) >> shift), 359 bitcast<f32>(u32(textureLoad(mip_0, vec2<u32>(st1.x, st0.y)).r) >> shift), 360 bitcast<f32>(u32(textureLoad(mip_0, vec2<u32>(st1.x, st1.y)).r) >> shift) 370fn load_mip_0_single_sample(st: vec2<f32>, sample: i32) -> f32 { 371 let st0 = vec2<u32>(floor(st - 0.5)); 374 textureLoad(mip_0, vec2<u32>(st0.x, st0.y), sample), 375 textureLoad(mip_0, vec2<u32>(st0.x, st1.y), sample), 376 textureLoad(mip_0, vec2<u32>(st1.x, st0.y), sample), 377 textureLoad(mip_0, vec2<u32>(st1.x, st1.y), sample) 382fn reduce_4(v: vec4f) -> f32 { 383 return min(min(v.x, v.y), min(v.z, v.w)); 390fn next_power_of_two(x: u32) -> u32 { 391 return 1u << (32u - countLeadingZeros(x));