WebGPU wrapper wip: clearing screen pipeline working

This commit is contained in:
Nikita Lisitsa 2023-12-31 02:13:28 +03:00
parent 095b06d5f1
commit 20a114eb41
10 changed files with 317 additions and 4 deletions

View file

@ -0,0 +1,39 @@
#pragma once
#include <psemek/wgpu/detail/object.hpp>
#include <psemek/wgpu/chained_struct.hpp>
#include <psemek/wgpu/render_pass_encoder.hpp>
#include <psemek/wgpu/command_buffer.hpp>
#include <vector>
#include <string>
namespace psemek::wgpu
{
struct command_encoder
: detail::object<command_encoder>
{
using detail::object<command_encoder>::object;
struct descriptor
{
std::vector<chained_struct> 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<command_encoder>(ptr)
{}
friend struct device;
};
}

View file

@ -2,6 +2,7 @@
#include <psemek/wgpu/chained_struct.hpp>
#include <psemek/wgpu/queue.hpp>
#include <psemek/wgpu/command_encoder.hpp>
#include <psemek/wgpu/detail/object.hpp>
#include <cstdint>
@ -100,6 +101,9 @@ namespace psemek::wgpu
using request_callback = std::function<void(request_status, device, std::string const & message)>;
queue get_queue();
command_encoder create_command_encoder(command_encoder::descriptor const & desc);
static void reference(void * ptr);
static void release(void * ptr);

View file

@ -0,0 +1,47 @@
#pragma once
#include <psemek/wgpu/chained_struct.hpp>
#include <psemek/wgpu/detail/object.hpp>
#include <string>
#include <cstdint>
namespace psemek::wgpu
{
struct query_set
: detail::object<query_set>
{
using detail::object<query_set>::object;
enum class type : std::uint32_t
{
occlusion = 0x00000000,
timestamp = 0x00000001,
};
struct descriptor
{
std::vector<chained_struct> 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<query_set>(ptr)
{}
friend struct command_encoder;
};
}

View file

@ -59,6 +59,8 @@ namespace psemek::wgpu
explicit queue(void * ptr)
: detail::object<queue>(ptr)
{}
friend struct device;
};
}

View file

@ -0,0 +1,87 @@
#pragma once
#include <psemek/wgpu/chained_struct.hpp>
#include <psemek/wgpu/texture_view.hpp>
#include <psemek/wgpu/query_set.hpp>
#include <psemek/wgpu/detail/object.hpp>
#include <psemek/geom/vector.hpp>
#include <cstdint>
#include <vector>
#include <optional>
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<render_pass_encoder>
{
using detail::object<render_pass_encoder>::object;
struct color_attachment
{
std::vector<chained_struct> chain = {};
texture_view view;
texture_view resolve_target = {};
enum load_op load_op;
enum store_op store_op;
geom::vector<double, 4> 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<chained_struct> chain = {};
std::string label = {};
std::vector<color_attachment> color_attachments = {};
std::optional<struct depth_stencil_attachment> depth_stencil_attachment = {};
query_set occlusion_query_set = {};
std::optional<struct timestamp_writes> timestamp_writes = {};
};
void end();
static void reference(void * ptr);
static void release(void * ptr);
private:
explicit render_pass_encoder(void * ptr)
: detail::object<render_pass_encoder>(ptr)
{}
friend struct command_encoder;
};
}

View file

@ -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

View file

@ -0,0 +1,58 @@
#include <psemek/wgpu/command_encoder.hpp>
#include <psemek/wgpu/external/webgpu.h>
namespace psemek::wgpu
{
render_pass_encoder command_encoder::begin_render_pass(render_pass_encoder::descriptor const & desc)
{
std::vector<WGPURenderPassColorAttachment> 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 ? &timestamp_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);
}
}

View file

@ -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);

View file

@ -0,0 +1,37 @@
#include <psemek/wgpu/query_set.hpp>
#include <psemek/wgpu/external/webgpu.h>
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);
}
}

View file

@ -0,0 +1,22 @@
#include <psemek/wgpu/render_pass_encoder.hpp>
#include <psemek/wgpu/external/webgpu.h>
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);
}
}