feat(webgpu): HDR post-process primitives — float textures, storage-texture bindings, RESOLVE→HDR target (#27)
Adds the minimal WebGPU-backend surface an HDR bloom/post chain needs: 1. wgpuCreateStorageImage2D + StorageImage2D<>: runtime rgba16float (or other format) textures with STORAGE_BINDING|TEXTURE_BINDING usage, no CompressedTextureAsset upload — GPU-produced HDR targets. 2. UICustomBindingKind::StorageTexture (kind 5): write-only storage-texture binding carrying a texel format (the freed UICustomBinding::format byte), wired through all three binding paths (UI custom / RT / plain compute). Float textures already sample via SampledTexture (sampleType float). 3. PipelineRTWebGPU::Init(..., hdrOutputFormat): RESOLVE writes the linear accumulator into a user rgba16float texture (RTPass::outTexHandle) instead of the rgba8unorm canvas, leaving the composite→swapchain pass to the app. Default RGBA8Unorm keeps the canvas path byte-identical. Existing RT examples updated for the _pad→format field rename; the default paths are unchanged (verified RTStress builds + renders). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
2b266262ee
commit
097cc37347
12 changed files with 198 additions and 22 deletions
|
|
@ -31,6 +31,16 @@ import std;
|
|||
import :WebGPU;
|
||||
|
||||
export namespace Crafter {
|
||||
// Texel format for runtime-allocated textures and write-only storage-
|
||||
// texture bindings. Values are the wire contract with dom-webgpu.js's
|
||||
// texelFormatStr(); keep them in sync. rgba8unorm (0) is the default so
|
||||
// an unset `format` byte preserves prior behaviour.
|
||||
enum class WebGPUTexelFormat : std::uint8_t {
|
||||
RGBA8Unorm = 0,
|
||||
RGBA16Float = 1, // HDR post-process targets — filterable per spec
|
||||
R32Float = 2,
|
||||
};
|
||||
|
||||
enum class UICustomBindingKind : std::uint8_t {
|
||||
Buffer = 0, // read-only-storage SSBO, handle is a slot into heap.bufferTable
|
||||
SampledTexture = 1, // sampled texture_2d<f32>, handle is a slot into heap.imageTable
|
||||
|
|
@ -41,13 +51,20 @@ export namespace Crafter {
|
|||
// integrate node momentum, write brace stress, or output TLAS
|
||||
// instance transforms.
|
||||
BufferReadWrite = 4,
|
||||
// write-only storage texture (texture_storage_2d<FMT, write> in
|
||||
// WGSL). The `format` field carries the WebGPUTexelFormat. Lets a
|
||||
// compute pass write a user-owned texture (e.g. an rgba16float bloom
|
||||
// mip) at an arbitrary group/binding — the missing primitive for an
|
||||
// HDR mip pyramid. Bind the same texture as SampledTexture to read
|
||||
// it back in a later pass.
|
||||
StorageTexture = 5,
|
||||
};
|
||||
|
||||
struct UICustomBinding {
|
||||
std::uint8_t group; // @group(N), must be >= 2 (0 and 1 are reserved)
|
||||
std::uint8_t binding; // @binding(N)
|
||||
UICustomBindingKind kind;
|
||||
std::uint8_t _pad;
|
||||
std::uint8_t format; // WebGPUTexelFormat for StorageTexture; 0 otherwise
|
||||
std::uint32_t pushOffset; // offset in push data where the slot uint32 lives
|
||||
};
|
||||
static_assert(sizeof(UICustomBinding) == 8);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue