Crafter.Graphics/interfaces/Crafter.Graphics-WebGPU.cppm
2026-05-19 00:27:09 +02:00

169 lines
10 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
Crafter®.Graphics
Copyright (C) 2026 Catcrafts®
catcrafts.net
*/
// JS bridge declarations for the DOM-mode WebGPU backend. Each function
// corresponds to one entry in `additional/dom-webgpu.js`. Handles are
// opaque uint32 cookies into the JS-side handle tables.
export module Crafter.Graphics:WebGPU;
#ifdef CRAFTER_GRAPHICS_WINDOW_DOM
import std;
export namespace Crafter {
using WebGPUBufferRef = std::uint32_t;
using WebGPUTextureRef = std::uint32_t;
using WebGPUSamplerRef = std::uint32_t;
using WebGPUCommandEncoderRef = std::uint32_t; // unused as a real handle; just a marker type for portability
}
namespace Crafter::WebGPU {
__attribute__((import_module("env"), import_name("wgpuGetCanvasWidth")))
extern "C" std::int32_t wgpuGetCanvasWidth();
__attribute__((import_module("env"), import_name("wgpuGetCanvasHeight")))
extern "C" std::int32_t wgpuGetCanvasHeight();
__attribute__((import_module("env"), import_name("wgpuSurfaceWidth")))
extern "C" std::int32_t wgpuSurfaceWidth();
__attribute__((import_module("env"), import_name("wgpuSurfaceHeight")))
extern "C" std::int32_t wgpuSurfaceHeight();
__attribute__((import_module("env"), import_name("wgpuInit")))
extern "C" void wgpuInit();
__attribute__((import_module("env"), import_name("wgpuCreateBuffer")))
extern "C" std::uint32_t wgpuCreateBuffer(std::int32_t byteSize);
__attribute__((import_module("env"), import_name("wgpuWriteBuffer")))
extern "C" void wgpuWriteBuffer(std::uint32_t handle, const void* srcPtr, std::int32_t byteSize);
__attribute__((import_module("env"), import_name("wgpuDestroyBuffer")))
extern "C" void wgpuDestroyBuffer(std::uint32_t handle);
__attribute__((import_module("env"), import_name("wgpuCreateAtlasTexture")))
extern "C" std::uint32_t wgpuCreateAtlasTexture(std::int32_t w, std::int32_t h);
__attribute__((import_module("env"), import_name("wgpuWriteAtlasRegion")))
extern "C" void wgpuWriteAtlasRegion(std::uint32_t handle, const void* srcPtr,
std::int32_t srcW, std::int32_t srcH,
std::int32_t srcBytesPerRow,
std::int32_t dstX, std::int32_t dstY,
std::int32_t copyW, std::int32_t copyH);
__attribute__((import_module("env"), import_name("wgpuDestroyTexture")))
extern "C" void wgpuDestroyTexture(std::uint32_t handle);
// General-purpose rgba8unorm 2D texture for material albedo etc.
// Separate from the atlas path because atlas uses r8unorm + sub-region
// writes; this one takes the whole image in one shot.
__attribute__((import_module("env"), import_name("wgpuCreateImage2D")))
extern "C" std::uint32_t wgpuCreateImage2D(std::int32_t w, std::int32_t h);
__attribute__((import_module("env"), import_name("wgpuWriteImage2D")))
extern "C" void wgpuWriteImage2D(std::uint32_t handle, const void* srcPtr,
std::int32_t byteSize,
std::int32_t w, std::int32_t h);
// 2D texture array — `layerCount` rgba8unorm layers of identical (w × h).
// Sampled via `texture_2d_array<f32>` in WGSL (UICustomBindingKind 3).
// Used by Image2DArray<RGBA8> to stack per-material albedos for one
// multi-material scene.
__attribute__((import_module("env"), import_name("wgpuCreateImage2DArray")))
extern "C" std::uint32_t wgpuCreateImage2DArray(std::int32_t w, std::int32_t h, std::int32_t layerCount);
__attribute__((import_module("env"), import_name("wgpuWriteImage2DLayer")))
extern "C" void wgpuWriteImage2DLayer(std::uint32_t handle, std::int32_t layer,
const void* srcPtr, std::int32_t byteSize,
std::int32_t w, std::int32_t h);
__attribute__((import_module("env"), import_name("wgpuCreateLinearClampSampler")))
extern "C" std::uint32_t wgpuCreateLinearClampSampler();
__attribute__((import_module("env"), import_name("wgpuFrameBegin")))
extern "C" void wgpuFrameBegin();
__attribute__((import_module("env"), import_name("wgpuFrameEnd")))
extern "C" void wgpuFrameEnd();
__attribute__((import_module("env"), import_name("wgpuDispatchQuads")))
extern "C" void wgpuDispatchQuads(std::uint32_t itemsHandle, const void* headerPtr,
std::int32_t gx, std::int32_t gy);
__attribute__((import_module("env"), import_name("wgpuDispatchCircles")))
extern "C" void wgpuDispatchCircles(std::uint32_t itemsHandle, const void* headerPtr,
std::int32_t gx, std::int32_t gy);
__attribute__((import_module("env"), import_name("wgpuDispatchImages")))
extern "C" void wgpuDispatchImages(std::uint32_t itemsHandle, const void* headerPtr,
std::int32_t gx, std::int32_t gy,
std::uint32_t texHandle, std::uint32_t sampHandle);
__attribute__((import_module("env"), import_name("wgpuDispatchText")))
extern "C" void wgpuDispatchText(std::uint32_t itemsHandle, const void* headerPtr,
std::int32_t gx, std::int32_t gy,
std::uint32_t atlasHandle, std::uint32_t sampHandle);
// ─── custom user-authored compute shaders ───────────────────────────
// rayQueryFlag = 1 swaps group(1) from the UI ping-pong pair to the RT
// data heaps (TLAS, BVH, meshRecs, verts, idx, primRemap, outImage) and
// prepends a WGSL prelude exposing the rayQuery* API. Shaders that set
// this MUST NOT declare their own @group(1) bindings.
__attribute__((import_module("env"), import_name("wgpuLoadCustomShader")))
extern "C" std::uint32_t wgpuLoadCustomShader(const void* wgslPtr, std::int32_t wgslLen,
const void* bindingsPtr, std::int32_t bindingsCount,
std::int32_t rayQueryFlag);
__attribute__((import_module("env"), import_name("wgpuDispatchCustom")))
extern "C" void wgpuDispatchCustom(std::uint32_t pipelineHandle,
const void* pushPtr, std::int32_t pushBytes,
const void* handlesPtr, std::int32_t handlesCount,
std::int32_t gx, std::int32_t gy, std::int32_t gz);
// ─── software raytracing ───────────────────────────────────────────
//
// Mesh::Build forwards vertex / index / BVH-node / primRemap arrays
// to the JS bridge, which queue.writeBuffers them into the global
// RT mesh heaps (growing if needed) and records the per-mesh offsets
// under a freshly-allocated u32 handle. The handle is what user code
// stores in RTInstance::accelerationStructureReference; the WebGPU
// TLAS-build compute shader resolves it back to root AABB + heap
// offsets at dispatch time. Returns 0 on failure.
// The optional `attribsPtr` / `attribsByteCount` carry per-vertex
// attribute payload (normals, UVs, etc. — layout is example-defined)
// that gets appended to a global attribs heap and exposed to RT
// closest-hit shaders as `vertexAttribs : array<u32>` at
// @group(1) @binding(7). Pass (nullptr, 0) for positions-only meshes.
__attribute__((import_module("env"), import_name("wgpuRegisterMeshBLAS")))
extern "C" std::uint32_t wgpuRegisterMeshBLAS(
float minX, float minY, float minZ,
float maxX, float maxY, float maxZ,
const void* verticesPtr, std::int32_t vertexCount,
const void* indicesPtr, std::int32_t indexCount,
const void* bvhNodesPtr, std::int32_t bvhNodeCount,
const void* primRemapPtr, std::int32_t primRemapCount,
const void* attribsPtr, std::int32_t attribsByteCount);
// RT pipeline build. The library composes WGSL by concatenating the
// traversal library, generated hit-group switches, and the user-
// supplied raygen / miss / closesthit / anyhit bodies. `bindings` is
// UICustomBinding-shaped (8 bytes each) declaring extra @group(2)+
// resources the user's closest-hit / miss / raygen WGSL references.
// Pass (nullptr, 0) for a pipeline with no user-declared bindings.
// Returns an opaque pipeline handle.
__attribute__((import_module("env"), import_name("wgpuLoadRTPipeline")))
extern "C" std::uint32_t wgpuLoadRTPipeline(const void* wgslPtr, std::int32_t wgslLen,
const void* bindingsPtr, std::int32_t bindingsCount);
// Dispatch a TraceRays-equivalent pass: the RT pipeline is dispatched
// over a (gx, gy) tile grid; the library writes the push data (camera,
// payload, etc. — opaque) into a uniform ring buffer, attaches the TLAS
// + global mesh heap, and runs one workgroup per 8x8 screen tile.
// `handles[]` carries resolved WebGPU resource handles for every user
// binding declared at pipeline-load time, in the same order. Pass
// (nullptr, 0) for a pipeline with no user bindings.
__attribute__((import_module("env"), import_name("wgpuDispatchRT")))
extern "C" void wgpuDispatchRT(std::uint32_t pipelineHandle,
const void* pushPtr, std::int32_t pushBytes,
std::uint32_t tlasBufHandle,
std::int32_t instanceCount,
std::int32_t gx, std::int32_t gy,
const void* handlesPtr, std::int32_t handlesCount);
// GPU TLAS-build dispatch. Reads the instance buffer (host-uploaded or
// GPU-written), produces per-instance world-space AABBs + per-instance
// transform matrices in a flat tlasBuf SSBO consumed by traceRay / rayQuery.
__attribute__((import_module("env"), import_name("wgpuBuildTLAS")))
extern "C" void wgpuBuildTLAS(std::uint32_t instanceBufHandle,
std::int32_t instanceCount,
std::uint32_t tlasOutBufHandle);
}
#endif // CRAFTER_GRAPHICS_WINDOW_DOM