test(webgpu): HDRBloom example exercising the HDR post-process primitives (#27)

RT→rgba16float→threshold→blur→composite, end-to-end proof of the three
primitives. threshold/blur run from onBeforeUpdate (one submit each) so the
storage-write→sampled-read dependency gets WebGPU's per-submit barrier
(there is none between dispatches within a compute pass); the composite is a
UI custom shader so it owns the canvas ping-pong. Documents the Vulkan
symmetry (gap 4): the native present path records passes generically and
barriers between them, so the same chain is wireable today.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
catbot 2026-06-09 12:55:14 +00:00
commit bbe1b21c22
10 changed files with 518 additions and 0 deletions

View file

@ -0,0 +1,27 @@
// HDRBloom threshold pass (PlainComputeShader). Reads the linear HDR scene
// (rgba16float, written by the RT RESOLVE stage), keeps only the radiance
// above 1.0, and writes it into the bloom mip (also rgba16float). This is
// the primitive the issue asks for: sample a float texture (group 1
// binding 0) and WRITE a user-owned float storage texture (group 1
// binding 1) at an app-chosen binding.
//
// Layout (PlainComputeShader, no rayQuery user groups start at 1):
// @group(0) @binding(0) uniform Dim (surface size)
// @group(1) @binding(0) texture_2d<f32> src (sampled, float)
// @group(1) @binding(1) storage rgba16float dst (write)
struct Dim { w: u32, h: u32, _0: u32, _1: u32 };
@group(0) @binding(0) var<uniform> dim : Dim;
@group(1) @binding(0) var src : texture_2d<f32>;
@group(1) @binding(1) var dst : texture_storage_2d<rgba16float, write>;
@compute @workgroup_size(8, 8, 1)
fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
if (gid.x >= dim.w || gid.y >= dim.h) { return; }
let coord = vec2<i32>(i32(gid.x), i32(gid.y));
let c = textureLoad(src, coord, 0).rgb;
// Soft knee around 1.0 so the extracted highlights ramp in smoothly.
let lum = dot(c, vec3<f32>(0.2126, 0.7152, 0.0722));
let keep = max(0.0, lum - 1.0) / max(lum, 1e-4);
textureStore(dst, coord, vec4<f32>(c * keep, 1.0));
}