/* Crafter®.Graphics Copyright (C) 2026 Catcrafts® catcrafts.net */ // WebGPU buffer wrapper — DOM-mode parallel to VulkanBuffer. // Holds a JS-side GPUBuffer handle + (when Mapped) a wasm-memory staging // array. `.value` points to the staging memory; the user writes into it // directly, and `.Flush(cmd)` copies to the GPU via queue.writeBuffer. export module Crafter.Graphics:WebGPUBuffer; #ifdef CRAFTER_GRAPHICS_WINDOW_DOM import std; import :WebGPU; export namespace Crafter { class WebGPUBufferBase { public: WebGPUBufferRef handle = 0; std::uint32_t size = 0; // bytes }; template class WebGPUBufferMapped { public: T* value = nullptr; }; class WebGPUBufferMappedEmpty {}; template using WebGPUBufferMappedConditional = std::conditional_t, WebGPUBufferMappedEmpty>; template class WebGPUBuffer : public WebGPUBufferBase, public WebGPUBufferMappedConditional { public: WebGPUBuffer() = default; WebGPUBuffer(const WebGPUBuffer&) = delete; WebGPUBuffer& operator=(const WebGPUBuffer&) = delete; WebGPUBuffer(WebGPUBuffer&& other) noexcept { handle = other.handle; size = other.size; other.handle = 0; if constexpr (Mapped) { this->value = other.value; other.value = nullptr; } } void Create(std::uint32_t count) { size = static_cast(count * sizeof(T)); handle = WebGPU::wgpuCreateBuffer(static_cast(size)); if constexpr (Mapped) { this->value = new T[count](); } } void Clear() { if (handle != 0) { WebGPU::wgpuDestroyBuffer(handle); handle = 0; } if constexpr (Mapped) { if (this->value) { delete[] this->value; this->value = nullptr; } } } void Resize(std::uint32_t count) { if (handle != 0) Clear(); Create(count); } void Flush(WebGPUCommandEncoderRef /*cmd*/) requires(Mapped) { WebGPU::wgpuWriteBuffer(handle, this->value, static_cast(size)); } void FlushDevice() requires(Mapped) { WebGPU::wgpuWriteBuffer(handle, this->value, static_cast(size)); } ~WebGPUBuffer() { Clear(); } }; } #endif // CRAFTER_GRAPHICS_WINDOW_DOM