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>
80 lines
3.5 KiB
C++
80 lines
3.5 KiB
C++
/*
|
|
Crafter®.Graphics
|
|
Copyright (C) 2026 Catcrafts®
|
|
catcrafts.net
|
|
*/
|
|
|
|
// DOM-mode shader-binding-table analog. Stores raw WGSL source strings
|
|
// plus an explicit entry-function name per shader. PipelineRTWebGPU::Init
|
|
// concatenates these into the megakernel WGSL at pipeline-build time.
|
|
|
|
export module Crafter.Graphics:ShaderBindingTableWebGPU;
|
|
#ifdef CRAFTER_GRAPHICS_WINDOW_DOM
|
|
import std;
|
|
|
|
export namespace Crafter {
|
|
enum class WebGPURTStage : std::uint8_t {
|
|
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,
|
|
// 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
|
|
// call from the megakernel switch. The source may declare any helper
|
|
// functions and (in exactly one raygen file) the `Payload` struct.
|
|
//
|
|
// Required signatures inside `source` for `entryFn`:
|
|
// Raygen: fn <entryFn>(gid: vec3<u32>)
|
|
// Miss: fn <entryFn>(ray: RayDesc, payload: ptr<function, Payload>)
|
|
// 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
|
|
// injected by the library prelude — see the rtWgslPrelude block in
|
|
// additional/dom-webgpu.js.
|
|
struct WebGPUShader {
|
|
std::string source;
|
|
std::string entryFn;
|
|
WebGPURTStage stage = WebGPURTStage::Raygen;
|
|
|
|
WebGPUShader() = default;
|
|
WebGPUShader(std::string src, std::string fn, WebGPURTStage s)
|
|
: source(std::move(src)), entryFn(std::move(fn)), stage(s) {}
|
|
|
|
// Construct from a WGSL source file path. Reads via the WASI VFS
|
|
// so apps shipping their shaders as static files (see the
|
|
// `cfg.files.emplace_back("raygen.wgsl")` pattern in
|
|
// examples/VulkanTriangle/project.cpp) get them at runtime.
|
|
WebGPUShader(const std::filesystem::path& wgslPath,
|
|
std::string fn,
|
|
WebGPURTStage s);
|
|
};
|
|
|
|
class ShaderBindingTableWebGPU {
|
|
public:
|
|
std::vector<WebGPUShader> shaders;
|
|
void Init(std::span<const WebGPUShader> shaders_) {
|
|
shaders.assign(shaders_.begin(), shaders_.end());
|
|
}
|
|
};
|
|
}
|
|
#endif // CRAFTER_GRAPHICS_WINDOW_DOM
|