Crafter.Graphics/interfaces/Crafter.Graphics-WebGPU.cppm

169 lines
10 KiB
Text
Raw Normal View History

2026-05-18 04:58:52 +02:00
/*
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);
2026-05-19 00:27:09 +02:00
// 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);
2026-05-18 04:58:52 +02:00
__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);
2026-05-18 05:39:17 +02:00
// ─── custom user-authored compute shaders ───────────────────────────
2026-05-18 18:43:30 +02:00
// 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.
2026-05-18 05:39:17 +02:00
__attribute__((import_module("env"), import_name("wgpuLoadCustomShader")))
extern "C" std::uint32_t wgpuLoadCustomShader(const void* wgslPtr, std::int32_t wgslLen,
2026-05-18 18:43:30 +02:00
const void* bindingsPtr, std::int32_t bindingsCount,
std::int32_t rayQueryFlag);
2026-05-18 05:39:17 +02:00
__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);
2026-05-18 18:43:30 +02:00
// ─── 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.
2026-05-19 00:27:09 +02:00
// 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.
2026-05-18 18:43:30 +02:00
__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,
2026-05-19 00:27:09 +02:00
const void* primRemapPtr, std::int32_t primRemapCount,
const void* attribsPtr, std::int32_t attribsByteCount);
2026-05-18 18:43:30 +02:00
// RT pipeline build. The library composes WGSL by concatenating the
// traversal library, generated hit-group switches, and the user-
2026-05-19 00:27:09 +02:00
// 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.
2026-05-18 18:43:30 +02:00
__attribute__((import_module("env"), import_name("wgpuLoadRTPipeline")))
2026-05-19 00:27:09 +02:00
extern "C" std::uint32_t wgpuLoadRTPipeline(const void* wgslPtr, std::int32_t wgslLen,
const void* bindingsPtr, std::int32_t bindingsCount);
2026-05-18 18:43:30 +02:00
// 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.
2026-05-19 00:27:09 +02:00
// `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.
2026-05-18 18:43:30 +02:00
__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,
2026-05-19 00:27:09 +02:00
std::int32_t gx, std::int32_t gy,
const void* handlesPtr, std::int32_t handlesCount);
2026-05-18 18:43:30 +02:00
// 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);
2026-05-18 04:58:52 +02:00
}
#endif // CRAFTER_GRAPHICS_WINDOW_DOM