/*
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
