From 20a114eb411edeca85f846d95e42622d0b31bf1c Mon Sep 17 00:00:00 2001 From: lisyarus Date: Sun, 31 Dec 2023 02:13:28 +0300 Subject: [PATCH] WebGPU wrapper wip: clearing screen pipeline working --- .../include/psemek/wgpu/command_encoder.hpp | 39 +++++++++ libs/wgpu/include/psemek/wgpu/device.hpp | 4 + libs/wgpu/include/psemek/wgpu/query_set.hpp | 47 ++++++++++ libs/wgpu/include/psemek/wgpu/queue.hpp | 2 + .../psemek/wgpu/render_pass_encoder.hpp | 87 +++++++++++++++++++ libs/wgpu/objects-todo | 8 +- libs/wgpu/source/command_encoder.cpp | 58 +++++++++++++ libs/wgpu/source/device.cpp | 17 ++++ libs/wgpu/source/query_set.cpp | 37 ++++++++ libs/wgpu/source/render_pass_encoder.cpp | 22 +++++ 10 files changed, 317 insertions(+), 4 deletions(-) create mode 100644 libs/wgpu/include/psemek/wgpu/command_encoder.hpp create mode 100644 libs/wgpu/include/psemek/wgpu/query_set.hpp create mode 100644 libs/wgpu/include/psemek/wgpu/render_pass_encoder.hpp create mode 100644 libs/wgpu/source/command_encoder.cpp create mode 100644 libs/wgpu/source/query_set.cpp create mode 100644 libs/wgpu/source/render_pass_encoder.cpp diff --git a/libs/wgpu/include/psemek/wgpu/command_encoder.hpp b/libs/wgpu/include/psemek/wgpu/command_encoder.hpp new file mode 100644 index 00000000..45249ba1 --- /dev/null +++ b/libs/wgpu/include/psemek/wgpu/command_encoder.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include +#include +#include +#include + +#include +#include + +namespace psemek::wgpu +{ + + struct command_encoder + : detail::object + { + using detail::object::object; + + struct descriptor + { + std::vector chain = {}; + std::string label = {}; + }; + + render_pass_encoder begin_render_pass(render_pass_encoder::descriptor const & desc); + command_buffer finish(command_buffer::descriptor const & desc); + + static void reference(void * ptr); + static void release(void * ptr); + + private: + explicit command_encoder(void * ptr) + : detail::object(ptr) + {} + + friend struct device; + }; + +} diff --git a/libs/wgpu/include/psemek/wgpu/device.hpp b/libs/wgpu/include/psemek/wgpu/device.hpp index 16fb9626..2eb7f23e 100644 --- a/libs/wgpu/include/psemek/wgpu/device.hpp +++ b/libs/wgpu/include/psemek/wgpu/device.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -100,6 +101,9 @@ namespace psemek::wgpu using request_callback = std::function; + queue get_queue(); + command_encoder create_command_encoder(command_encoder::descriptor const & desc); + static void reference(void * ptr); static void release(void * ptr); diff --git a/libs/wgpu/include/psemek/wgpu/query_set.hpp b/libs/wgpu/include/psemek/wgpu/query_set.hpp new file mode 100644 index 00000000..052ac831 --- /dev/null +++ b/libs/wgpu/include/psemek/wgpu/query_set.hpp @@ -0,0 +1,47 @@ +#pragma once + +#include +#include + +#include +#include + +namespace psemek::wgpu +{ + + struct query_set + : detail::object + { + using detail::object::object; + + enum class type : std::uint32_t + { + occlusion = 0x00000000, + timestamp = 0x00000001, + }; + + struct descriptor + { + std::vector chain = {}; + std::string label = {}; + enum type type; + std::uint32_t count; + }; + + void destroy(); + std::uint32_t get_count(); + type get_type(); + void set_label(std::string const & label); + + static void reference(void * ptr); + static void release(void * ptr); + + private: + explicit query_set(void * ptr) + : detail::object(ptr) + {} + + friend struct command_encoder; + }; + +} diff --git a/libs/wgpu/include/psemek/wgpu/queue.hpp b/libs/wgpu/include/psemek/wgpu/queue.hpp index 0ed56856..fe825341 100644 --- a/libs/wgpu/include/psemek/wgpu/queue.hpp +++ b/libs/wgpu/include/psemek/wgpu/queue.hpp @@ -59,6 +59,8 @@ namespace psemek::wgpu explicit queue(void * ptr) : detail::object(ptr) {} + + friend struct device; }; } diff --git a/libs/wgpu/include/psemek/wgpu/render_pass_encoder.hpp b/libs/wgpu/include/psemek/wgpu/render_pass_encoder.hpp new file mode 100644 index 00000000..527353bd --- /dev/null +++ b/libs/wgpu/include/psemek/wgpu/render_pass_encoder.hpp @@ -0,0 +1,87 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace psemek::wgpu +{ + + enum class load_op : std::uint32_t + { + undefined = 0x00000000, + clear = 0x00000001, + load = 0x00000002, + }; + + enum class store_op : std::uint32_t + { + undefined = 0x00000000, + store = 0x00000001, + discard = 0x00000002, + }; + + struct render_pass_encoder + : detail::object + { + using detail::object::object; + + struct color_attachment + { + std::vector chain = {}; + texture_view view; + texture_view resolve_target = {}; + enum load_op load_op; + enum store_op store_op; + geom::vector clear_value; + }; + + struct depth_stencil_attachment + { + texture_view view; + load_op depth_load_pp; + store_op depth_store_op; + float depth_clear_value; + bool depth_read_only; + load_op stencil_load_op; + store_op stencil_store_op; + std::uint32_t stencil_clear_value; + bool stencil_read_only; + }; + + struct timestamp_writes { + struct query_set query_set; + std::uint32_t begin_index; + std::uint32_t end_index; + }; + + struct descriptor + { + std::vector chain = {}; + std::string label = {}; + std::vector color_attachments = {}; + std::optional depth_stencil_attachment = {}; + query_set occlusion_query_set = {}; + std::optional timestamp_writes = {}; + }; + + void end(); + + static void reference(void * ptr); + static void release(void * ptr); + + private: + explicit render_pass_encoder(void * ptr) + : detail::object(ptr) + {} + + friend struct command_encoder; + }; + +} diff --git a/libs/wgpu/objects-todo b/libs/wgpu/objects-todo index bfca3354..42ee9a61 100644 --- a/libs/wgpu/objects-todo +++ b/libs/wgpu/objects-todo @@ -3,17 +3,17 @@ WGPUBindGroupLayout + WGPUBuffer + WGPUCommandBuffer - WGPUCommandEncoder +- WGPUCommandEncoder WGPUComputePassEncoder WGPUComputePipeline - WGPUDevice +- WGPUDevice + WGPUInstance WGPUPipelineLayout - WGPUQuerySet ++ WGPUQuerySet + WGPUQueue WGPURenderBundle WGPURenderBundleEncoder - WGPURenderPassEncoder +- WGPURenderPassEncoder WGPURenderPipeline WGPUSampler WGPUShaderModule diff --git a/libs/wgpu/source/command_encoder.cpp b/libs/wgpu/source/command_encoder.cpp new file mode 100644 index 00000000..142e4eb4 --- /dev/null +++ b/libs/wgpu/source/command_encoder.cpp @@ -0,0 +1,58 @@ +#include +#include + +namespace psemek::wgpu +{ + + render_pass_encoder command_encoder::begin_render_pass(render_pass_encoder::descriptor const & desc) + { + std::vector color_attachments; + for (auto const & src : desc.color_attachments) + { + auto & dst = color_attachments.emplace_back(); + dst.nextInChain = (WGPUChainedStruct const *)detail::fill_chain(src.chain); + dst.view = (WGPUTextureView)src.view.get(); + dst.resolveTarget = (WGPUTextureView)src.resolve_target.get(); + dst.loadOp = (WGPULoadOp)src.load_op; + dst.storeOp = (WGPUStoreOp)src.store_op; + dst.clearValue = {src.clear_value[0], src.clear_value[1], src.clear_value[2], src.clear_value[3]}; + } + + WGPURenderPassTimestampWrites timestamp_writes = {}; + if (desc.timestamp_writes) + { + timestamp_writes.querySet = (WGPUQuerySet)desc.timestamp_writes->query_set.get(); + timestamp_writes.beginningOfPassWriteIndex = desc.timestamp_writes->begin_index; + timestamp_writes.endOfPassWriteIndex = desc.timestamp_writes->end_index; + } + + WGPURenderPassDescriptor descriptor = {}; + descriptor.nextInChain = (WGPUChainedStruct const *)detail::fill_chain(desc.chain); + descriptor.label = desc.label.data(); + descriptor.colorAttachmentCount = color_attachments.size(); + descriptor.colorAttachments = color_attachments.data(); + descriptor.occlusionQuerySet = (WGPUQuerySet)desc.occlusion_query_set.get(); + descriptor.timestampWrites = desc.timestamp_writes ? ×tamp_writes : nullptr; + + return render_pass_encoder(wgpuCommandEncoderBeginRenderPass((WGPUCommandEncoder)get(), &descriptor)); + } + + command_buffer command_encoder::finish(command_buffer::descriptor const & desc) + { + WGPUCommandBufferDescriptor descriptor = {}; + descriptor.nextInChain = (WGPUChainedStruct const *)detail::fill_chain(desc.chain); + descriptor.label = desc.label.data(); + return command_buffer(wgpuCommandEncoderFinish((WGPUCommandEncoder)get(), &descriptor)); + } + + void command_encoder::reference(void * ptr) + { + wgpuCommandEncoderReference((WGPUCommandEncoder)ptr); + } + + void command_encoder::release(void * ptr) + { + wgpuCommandEncoderRelease((WGPUCommandEncoder)ptr); + } + +} diff --git a/libs/wgpu/source/device.cpp b/libs/wgpu/source/device.cpp index a18c254e..1a3b41dd 100644 --- a/libs/wgpu/source/device.cpp +++ b/libs/wgpu/source/device.cpp @@ -4,6 +4,23 @@ namespace psemek::wgpu { + queue device::get_queue() + { + auto ptr = wgpuDeviceGetQueue((WGPUDevice)get()); + // Queue is actually owned by the device + // Reference it to prevent destroying + wgpuQueueReference(ptr); + return queue(ptr); + } + + command_encoder device::create_command_encoder(command_encoder::descriptor const & desc) + { + WGPUCommandEncoderDescriptor descriptor = {}; + descriptor.nextInChain = (WGPUChainedStruct const *)detail::fill_chain(desc.chain); + descriptor.label = desc.label.data(); + return command_encoder(wgpuDeviceCreateCommandEncoder((WGPUDevice)get(), &descriptor)); + } + void device::reference(void * ptr) { wgpuDeviceReference((WGPUDevice)ptr); diff --git a/libs/wgpu/source/query_set.cpp b/libs/wgpu/source/query_set.cpp new file mode 100644 index 00000000..3dab9410 --- /dev/null +++ b/libs/wgpu/source/query_set.cpp @@ -0,0 +1,37 @@ +#include +#include + +namespace psemek::wgpu +{ + + void query_set::destroy() + { + wgpuQuerySetDestroy((WGPUQuerySet)get()); + } + + std::uint32_t query_set::get_count() + { + return wgpuQuerySetGetCount((WGPUQuerySet)get()); + } + + query_set::type query_set::get_type() + { + return (type)wgpuQuerySetGetType((WGPUQuerySet)get()); + } + + void query_set::set_label(std::string const & label) + { + wgpuQuerySetSetLabel((WGPUQuerySet)get(), label.data()); + } + + void query_set::reference(void * ptr) + { + wgpuQuerySetReference((WGPUQuerySet)ptr); + } + + void query_set::release(void * ptr) + { + wgpuQuerySetRelease((WGPUQuerySet)ptr); + } + +} diff --git a/libs/wgpu/source/render_pass_encoder.cpp b/libs/wgpu/source/render_pass_encoder.cpp new file mode 100644 index 00000000..f8e11ca2 --- /dev/null +++ b/libs/wgpu/source/render_pass_encoder.cpp @@ -0,0 +1,22 @@ +#include +#include + +namespace psemek::wgpu +{ + + void render_pass_encoder::end() + { + wgpuRenderPassEncoderEnd((WGPURenderPassEncoder)get()); + } + + void render_pass_encoder::reference(void * ptr) + { + wgpuRenderPassEncoderReference((WGPURenderPassEncoder)ptr); + } + + void render_pass_encoder::release(void * ptr) + { + wgpuRenderPassEncoderRelease((WGPURenderPassEncoder)ptr); + } + +}