/*
Crafter®.Graphics
Copyright (C) 2026 Catcrafts®
catcrafts.net
*/

// DOM-mode RT pipeline. Mirrors PipelineRTVulkan's surface — Init takes
// the same kind of (raygen, miss, hit) shader-group spans plus an SBT.
// The big difference is implementation: there's no native RT pipeline on
// WebGPU, so Init assembles a single megakernel WGSL by concatenating
//   1. library prelude (types, bindings, ray-flag constants)
//   2. user closesthit / anyhit / miss source files
//   3. library mega-switches dispatched on per-hit hit-group index
//   4. library helpers (rayAabb / rayTriangle / traverseBlas / traverseTlas)
//   5. library traceRay function
//   6. user raygen source files
//   7. @compute entry calling the registered raygen
// and hands the result to wgpuLoadRTPipeline.
//
// The library WGSL itself lives in additional/dom-webgpu.js (rtWgslPrelude
// + rtWgslDispatchTemplate). C++ side only knows the substitution markers.

export module Crafter.Graphics:PipelineRTWebGPU;
#ifdef CRAFTER_GRAPHICS_WINDOW_DOM
import std;
import :RT;
import :WebGPU;
import :ShaderBindingTableWebGPU;
import :WebGPUComputeShader;

export namespace Crafter {
    class PipelineRTWebGPU {
    public:
        std::uint32_t pipelineHandle = 0;
        // Mirror of the bindings handed to Init. Kept for the example /
        // RTPass to consult when packing the handles[] array at dispatch
        // time (one resolved u32 handle per binding, in declaration order).
        std::vector<UICustomBinding> userBindings;
        // True when Init was given a non-default hdrOutputFormat: RESOLVE
        // writes a user storage texture instead of the canvas, and RTPass
        // must supply its handle via RTPass::outTexHandle.
        bool hdrOutput = false;

        // Build the megakernel pipeline. Groups carry indices into
        // `sbt.shaders`. The library generates one `case` per registered
        // group: closest-hit groups dispatch to their closestHitShader's
        // entryFn, miss groups to their generalShader's entryFn, etc.
        // The `cmd` parameter is unused on WebGPU; kept for API symmetry.
        // `userBindings` declares extra @group(2)+ resources the user's
        // closest-hit / miss / raygen WGSL touches (material SSBOs,
        // albedo textures, samplers).
        // `hdrOutputFormat` defaults to RGBA8Unorm — the canvas ping-pong
        // path, unchanged. Pass RGBA16Float (or another float format) to
        // have RESOLVE write the linear accumulator into a user storage
        // texture instead, for an HDR post-process chain. The app then owns
        // the composite→swapchain pass and must set RTPass::outTexHandle.
        void Init(WebGPUCommandEncoderRef                 cmd,
                  std::span<const RTShaderGroup>          raygenGroups,
                  std::span<const RTShaderGroup>          missGroups,
                  std::span<const RTShaderGroup>          hitGroups,
                  const ShaderBindingTableWebGPU&         sbt,
                  std::span<const UICustomBinding>        bindings = {},
                  WebGPUTexelFormat                       hdrOutputFormat
                      = WebGPUTexelFormat::RGBA8Unorm);

        PipelineRTWebGPU() = default;
        PipelineRTWebGPU(const PipelineRTWebGPU&) = delete;
        PipelineRTWebGPU& operator=(const PipelineRTWebGPU&) = delete;
    };
}
#endif // CRAFTER_GRAPHICS_WINDOW_DOM
