feat(webgpu-rt): add intersection stage, procedural hit group, AABB BLAS API

Extends the cross-backend RT type surface for procedural geometry +
any-hit on the WebGPU path:

- RTShaderGroupType::ProceduralHitGroup + RTShaderGroup::intersectionShader
  (mirror VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR).
- WebGPURTStage::Intersection for AABB intersection shaders.
- Mesh::BuildProcedural(span<RTAabb>, opaque) — the WebGPU analog of a
  VK_GEOMETRY_TYPE_AABBS_KHR geometry.
- wgpuRegisterMeshBLAS gains geomType / opaqueFlag / primCount.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
catbot 2026-06-02 22:09:14 +00:00
commit 321fe596a7
4 changed files with 66 additions and 15 deletions

View file

@ -14,15 +14,23 @@ import std;
export namespace Crafter {
enum class WebGPURTStage : std::uint8_t {
Raygen = 0,
Miss = 1,
ClosestHit = 2,
AnyHit = 3,
Raygen = 0,
Miss = 1,
ClosestHit = 2,
AnyHit = 3,
// Wavefront RESOLVE-stage tonemap/output hook. Optional: if no
// Resolve shader is registered, RESOLVE writes the linear accum
// buffer through unchanged. Signature:
// fn <entryFn>(coord: vec2<u32>, hdr: vec4<f32>) -> vec4<f32>
Resolve = 4,
Resolve = 4,
// Intersection shader for AABB (procedural) geometry. Run for each
// AABB primitive the ray enters during TRACE; reports whether the
// procedural surface is hit and at what distance. Signature:
// fn <entryFn>(ray: RayDesc, aabbMin: vec3<f32>, aabbMax: vec3<f32>,
// primitiveId: u32) -> IntersectionResult
// `ray` is in object space. IntersectionResult{ hit, t, attribs,
// hitKind } is declared by the library prelude.
Intersection = 5,
};
// One WGSL shader source + the function name PipelineRTWebGPU should
@ -35,6 +43,9 @@ export namespace Crafter {
// ClosestHit: fn <entryFn>(ray: RayDesc, hit: HitInfo, payload: ptr<function, Payload>)
// AnyHit: fn <entryFn>(ray: RayDesc, hit: HitInfo, payload: ptr<function, Payload>) -> u32
// returns RT_ANYHIT_ACCEPT / RT_ANYHIT_IGNORE / RT_ANYHIT_END_SEARCH.
// Intersection: fn <entryFn>(ray: RayDesc, aabbMin: vec3<f32>, aabbMax: vec3<f32>,
// primitiveId: u32) -> IntersectionResult
// IntersectionResult{ hit: bool, t: f32, attribs: vec2<f32>, hitKind: u32 }.
//
// `RayDesc`, `HitInfo`, the `RT_*` flag/return constants, the `tlas` /
// BLAS / mesh-record bindings, and the `traceRay` function are all