From 095b06d5f1654487441a95e6dba5d84d1934d483 Mon Sep 17 00:00:00 2001 From: lisyarus Date: Sat, 30 Dec 2023 23:47:02 +0300 Subject: [PATCH] WebGPU wrapper wip: add queue methods --- libs/wgpu/include/psemek/wgpu/queue.hpp | 32 +++++++++++++++ libs/wgpu/include/psemek/wgpu/texture.hpp | 8 ++++ libs/wgpu/objects-todo | 4 +- libs/wgpu/source/queue.cpp | 49 +++++++++++++++++++++++ 4 files changed, 91 insertions(+), 2 deletions(-) diff --git a/libs/wgpu/include/psemek/wgpu/queue.hpp b/libs/wgpu/include/psemek/wgpu/queue.hpp index 115abb06..0ed56856 100644 --- a/libs/wgpu/include/psemek/wgpu/queue.hpp +++ b/libs/wgpu/include/psemek/wgpu/queue.hpp @@ -1,14 +1,30 @@ #pragma once #include +#include +#include +#include #include +#include +#include #include #include +#include +#include namespace psemek::wgpu { + struct image_copy_texture + { + std::vector chain = {}; + struct texture texture; + std::uint32_t mipLevel = 0; + geom::point origin = {0, 0, 0}; + texture::aspect aspect = texture::aspect::all; + }; + struct queue : detail::object { @@ -20,6 +36,22 @@ namespace psemek::wgpu std::string label = {}; }; + enum class work_done_status : std::uint32_t + { + success = 0x00000000, + error = 0x00000001, + unknown = 0x00000002, + device_lost = 0x00000003, + }; + + using work_done_callback = std::function; + + void submit(std::vector const & commands); + void write_buffer(buffer const & buffer, std::uint64_t offset, util::span data); + void write_texture(image_copy_texture const & dest, util::span data, texture::data_layout const & data_layout, geom::vector const & write_size); + void on_submitted_work_done(work_done_callback const & callback); + void set_label(std::string const & label); + static void reference(void * ptr); static void release(void * ptr); diff --git a/libs/wgpu/include/psemek/wgpu/texture.hpp b/libs/wgpu/include/psemek/wgpu/texture.hpp index f1e45c44..a3a165cd 100644 --- a/libs/wgpu/include/psemek/wgpu/texture.hpp +++ b/libs/wgpu/include/psemek/wgpu/texture.hpp @@ -154,6 +154,14 @@ namespace psemek::wgpu std::vector view_formats = {}; }; + struct data_layout + { + std::vector chain = {}; + std::uint64_t offset = 0; + std::uint32_t bytes_per_row; + std::uint32_t rows_per_image; + }; + texture_view create_view(texture_view::descriptor const & desc); void destroy(); std::uint32_t get_width(); diff --git a/libs/wgpu/objects-todo b/libs/wgpu/objects-todo index e275df3d..bfca3354 100644 --- a/libs/wgpu/objects-todo +++ b/libs/wgpu/objects-todo @@ -2,7 +2,7 @@ WGPUBindGroup WGPUBindGroupLayout + WGPUBuffer - WGPUCommandBuffer ++ WGPUCommandBuffer WGPUCommandEncoder WGPUComputePassEncoder WGPUComputePipeline @@ -10,7 +10,7 @@ + WGPUInstance WGPUPipelineLayout WGPUQuerySet - WGPUQueue ++ WGPUQueue WGPURenderBundle WGPURenderBundleEncoder WGPURenderPassEncoder diff --git a/libs/wgpu/source/queue.cpp b/libs/wgpu/source/queue.cpp index dd44841a..71b274d7 100644 --- a/libs/wgpu/source/queue.cpp +++ b/libs/wgpu/source/queue.cpp @@ -4,6 +4,55 @@ namespace psemek::wgpu { + void queue::submit(std::vector const & commands) + { + static_assert(sizeof(WGPUCommandBuffer) == sizeof(command_buffer)); + wgpuQueueSubmit((WGPUQueue)get(), commands.size(), (WGPUCommandBuffer*)commands.data()); + } + + void queue::write_buffer(buffer const & buffer, std::uint64_t offset, util::span data) + { + wgpuQueueWriteBuffer((WGPUQueue)get(), (WGPUBuffer)buffer.get(), offset, data.data(), data.size()); + } + + void queue::write_texture(image_copy_texture const & dest, util::span data, texture::data_layout const & data_layout, geom::vector const & write_size) + { + WGPUImageCopyTexture image_copy_texture = {}; + image_copy_texture.nextInChain = (WGPUChainedStruct const *)detail::fill_chain(dest.chain); + image_copy_texture.texture = (WGPUTexture)dest.texture.get(); + image_copy_texture.mipLevel = dest.mipLevel; + image_copy_texture.origin = {dest.origin[0], dest.origin[1], dest.origin[2]}; + image_copy_texture.aspect = (WGPUTextureAspect)dest.aspect; + + WGPUTextureDataLayout texture_data_layout = {}; + texture_data_layout.nextInChain = (WGPUChainedStruct const *)detail::fill_chain(data_layout.chain); + texture_data_layout.offset = data_layout.offset; + texture_data_layout.bytesPerRow = data_layout.bytes_per_row; + texture_data_layout.rowsPerImage = data_layout.rows_per_image; + + WGPUExtent3D extent = {write_size[0], write_size[1], write_size[2]}; + + wgpuQueueWriteTexture((WGPUQueue)get(), &image_copy_texture, data.data(), data.size(), &texture_data_layout, &extent); + } + + void queue::on_submitted_work_done(work_done_callback const & callback) + { + auto userdata = new work_done_callback(callback); + + auto real_callback = [](WGPUQueueWorkDoneStatus status, void * userdata) + { + std::unique_ptr callback((work_done_callback*)userdata); + if (*callback) (*callback)((work_done_status)status); + }; + + wgpuQueueOnSubmittedWorkDone((WGPUQueue)get(), real_callback, userdata); + } + + void queue::set_label(std::string const & label) + { + wgpuQueueSetLabel((WGPUQueue)get(), label.data()); + } + void queue::reference(void * ptr) { wgpuQueueReference((WGPUQueue)ptr);