webgpu improvements
This commit is contained in:
parent
5a75571ffd
commit
8347467e1e
18 changed files with 1932 additions and 153 deletions
113
interfaces/Crafter.Graphics-PlainComputeShader.cppm
Normal file
113
interfaces/Crafter.Graphics-PlainComputeShader.cppm
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
Crafter®.Graphics
|
||||
Copyright (C) 2026 Catcrafts®
|
||||
catcrafts.net
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License version 3.0 as published by the Free Software Foundation;
|
||||
*/
|
||||
|
||||
// Standalone compute pipeline. Dispatches at any point in the frame
|
||||
// (inside or outside the UI render pass) via the JS bridge's
|
||||
// wgpuDispatchCompute, which mirrors the wgpuBuildTLAS pattern of
|
||||
// attaching to the active encoder when one exists or creating an
|
||||
// ephemeral encoder+submit when not.
|
||||
//
|
||||
// This is the WebGPU counterpart to the Vulkan `:ComputeShader` partition.
|
||||
// They expose the same conceptual API — Load + Dispatch — but with
|
||||
// backend-specific binding plumbing. See `:GraphicsTypes` for the
|
||||
// `GraphicsComputeShader` alias picking the right one per target.
|
||||
//
|
||||
// WGSL contract:
|
||||
// @group(0) @binding(0) uniform PushData // optional; only if pushUniformSize>0
|
||||
// @group(1+) @binding(N) // user bindings via UICustomBinding
|
||||
// When rayQuery is on, @group(1) is reserved for the RT heap; user
|
||||
// bindings start at @group(2).
|
||||
|
||||
module;
|
||||
export module Crafter.Graphics:PlainComputeShader;
|
||||
#ifdef CRAFTER_GRAPHICS_WINDOW_DOM
|
||||
import std;
|
||||
import :WebGPU;
|
||||
import :WebGPUComputeShader; // for UICustomBinding + UICustomBindingKind
|
||||
|
||||
export namespace Crafter {
|
||||
class PlainComputeShader {
|
||||
public:
|
||||
std::uint32_t pipelineHandle = 0;
|
||||
std::uint32_t pushUniformSize = 0;
|
||||
bool rayQueryCapable = false;
|
||||
std::vector<UICustomBinding> customBindings;
|
||||
|
||||
PlainComputeShader() = default;
|
||||
PlainComputeShader(const PlainComputeShader&) = delete;
|
||||
PlainComputeShader& operator=(const PlainComputeShader&) = delete;
|
||||
PlainComputeShader(PlainComputeShader&& o) noexcept
|
||||
: pipelineHandle(o.pipelineHandle),
|
||||
pushUniformSize(o.pushUniformSize),
|
||||
rayQueryCapable(o.rayQueryCapable),
|
||||
customBindings(std::move(o.customBindings)) {
|
||||
o.pipelineHandle = 0;
|
||||
}
|
||||
|
||||
// Compile + link a standalone compute shader.
|
||||
// wgsl — source.
|
||||
// pushUniformSize — byte size of the @group(0)@binding(0) uniform
|
||||
// struct, or 0 if the shader doesn't declare one.
|
||||
// bindings — every user-declared resource the dispatch
|
||||
// should bind (groups 1+ if no rayQuery, 2+ if
|
||||
// rayQuery). Order MUST match `handles` at
|
||||
// Dispatch time.
|
||||
// rayQuery — prepend the RT prelude + rayQuery library
|
||||
// so the shader can call `rayQuery*` helpers.
|
||||
void Load(std::string_view wgsl,
|
||||
std::uint32_t pushUniformSize_,
|
||||
std::span<const UICustomBinding> bindings = {},
|
||||
bool rayQuery = false) {
|
||||
pushUniformSize = pushUniformSize_;
|
||||
rayQueryCapable = rayQuery;
|
||||
customBindings.assign(bindings.begin(), bindings.end());
|
||||
pipelineHandle = WebGPU::wgpuLoadComputePipeline(
|
||||
wgsl.data(), static_cast<std::int32_t>(wgsl.size()),
|
||||
static_cast<std::int32_t>(pushUniformSize),
|
||||
customBindings.empty() ? nullptr : customBindings.data(),
|
||||
static_cast<std::int32_t>(customBindings.size()),
|
||||
rayQuery ? 1 : 0);
|
||||
}
|
||||
|
||||
void Load(const std::filesystem::path& wgslPath,
|
||||
std::uint32_t pushUniformSize_,
|
||||
std::span<const UICustomBinding> bindings = {},
|
||||
bool rayQuery = false) {
|
||||
std::ifstream f(wgslPath, std::ios::binary);
|
||||
if (!f) {
|
||||
std::println(std::cerr,
|
||||
"PlainComputeShader::Load: cannot open {}", wgslPath.string());
|
||||
std::abort();
|
||||
}
|
||||
std::string wgsl((std::istreambuf_iterator<char>(f)),
|
||||
std::istreambuf_iterator<char>());
|
||||
Load(std::string_view{wgsl}, pushUniformSize_, bindings, rayQuery);
|
||||
}
|
||||
|
||||
// Bind, push, dispatch. `handles` is parallel to the
|
||||
// UICustomBinding[] passed at Load — order matches.
|
||||
void Dispatch(const void* push, std::uint32_t pushBytes,
|
||||
std::span<const std::uint32_t> handles,
|
||||
std::uint32_t gx,
|
||||
std::uint32_t gy = 1,
|
||||
std::uint32_t gz = 1) const {
|
||||
if (pipelineHandle == 0) return;
|
||||
WebGPU::wgpuDispatchCompute(
|
||||
pipelineHandle,
|
||||
push, static_cast<std::int32_t>(pushBytes),
|
||||
handles.empty() ? nullptr : handles.data(),
|
||||
static_cast<std::int32_t>(handles.size()),
|
||||
static_cast<std::int32_t>(gx),
|
||||
static_cast<std::int32_t>(gy),
|
||||
static_cast<std::int32_t>(gz));
|
||||
}
|
||||
};
|
||||
}
|
||||
#endif // CRAFTER_GRAPHICS_WINDOW_DOM
|
||||
Loading…
Add table
Add a link
Reference in a new issue