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
|
|
@ -47,8 +47,48 @@ import std;
|
|||
import Crafter.Asset;
|
||||
import :DescriptorHeapWebGPU;
|
||||
import :WebGPU;
|
||||
import :WebGPUComputeShader; // WebGPUTexelFormat
|
||||
|
||||
export namespace Crafter {
|
||||
// GPU-produced 2D texture with STORAGE_BINDING + TEXTURE_BINDING usage
|
||||
// and a runtime-chosen format. The HDR post-process building block: an
|
||||
// rgba16float target a compute pass can write through a StorageTexture
|
||||
// binding and a later pass can sample through a SampledTexture binding.
|
||||
// No CompressedTextureAsset / CPU upload — content comes from the GPU.
|
||||
// Distinct from Image2D<T> (rgba8unorm, sampled-only, asset-upload).
|
||||
class StorageImage2D {
|
||||
public:
|
||||
WebGPUTextureRef handle = 0;
|
||||
std::uint16_t width = 0;
|
||||
std::uint16_t height = 0;
|
||||
WebGPUTexelFormat format = WebGPUTexelFormat::RGBA16Float;
|
||||
|
||||
void Create(std::uint16_t w, std::uint16_t h,
|
||||
WebGPUTexelFormat fmt = WebGPUTexelFormat::RGBA16Float) {
|
||||
width = w;
|
||||
height = h;
|
||||
format = fmt;
|
||||
handle = WebGPU::wgpuCreateStorageImage2D(
|
||||
w, h, static_cast<std::int32_t>(fmt));
|
||||
}
|
||||
|
||||
// Register in a heap image slot so a UI custom shader can bind it
|
||||
// via UICustomBinding (SampledTexture to read, StorageTexture to
|
||||
// write). PlainComputeShader / RTPass take the raw `handle` directly.
|
||||
ImageSlot AllocateSlot(DescriptorHeapWebGPU& heap) {
|
||||
DescriptorRange r = heap.AllocateImageSlots(1);
|
||||
heap.imageTable[r.firstElement] = handle;
|
||||
return ImageSlot(&heap, r.firstElement);
|
||||
}
|
||||
|
||||
void Destroy() {
|
||||
if (handle != 0) {
|
||||
WebGPU::wgpuDestroyTexture(handle);
|
||||
handle = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename PixelType>
|
||||
class Image2D {
|
||||
public:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue