WebGPU wrapper wip: add render pipeline object
This commit is contained in:
parent
cde91b55a9
commit
ea71e1878e
7 changed files with 446 additions and 3 deletions
25
libs/wgpu/include/psemek/wgpu/bind_group_layout.hpp
Normal file
25
libs/wgpu/include/psemek/wgpu/bind_group_layout.hpp
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#pragma once
|
||||
|
||||
#include <psemek/wgpu/detail/object.hpp>
|
||||
|
||||
namespace psemek::wgpu
|
||||
{
|
||||
|
||||
struct bind_group_layout
|
||||
: detail::object<bind_group_layout>
|
||||
{
|
||||
using detail::object<bind_group_layout>::object;
|
||||
|
||||
static void reference(void * ptr);
|
||||
static void release(void * ptr);
|
||||
|
||||
private:
|
||||
explicit bind_group_layout(void * ptr)
|
||||
: detail::object<bind_group_layout>(ptr)
|
||||
{}
|
||||
|
||||
friend struct device;
|
||||
friend struct render_pipeline;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -3,11 +3,12 @@
|
|||
#include <psemek/wgpu/chained_struct.hpp>
|
||||
#include <psemek/wgpu/queue.hpp>
|
||||
#include <psemek/wgpu/buffer.hpp>
|
||||
#include <psemek/wgpu/command_encoder.hpp>
|
||||
#include <psemek/wgpu/query_set.hpp>
|
||||
#include <psemek/wgpu/render_pipeline.hpp>
|
||||
#include <psemek/wgpu/sampler.hpp>
|
||||
#include <psemek/wgpu/shader_module.hpp>
|
||||
#include <psemek/wgpu/texture.hpp>
|
||||
#include <psemek/wgpu/command_encoder.hpp>
|
||||
#include <psemek/wgpu/detail/object.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
|
|
@ -110,6 +111,7 @@ namespace psemek::wgpu
|
|||
buffer create_buffer(buffer::descriptor const & desc);
|
||||
command_encoder create_command_encoder(command_encoder::descriptor const & desc);
|
||||
query_set create_query_set(query_set::descriptor const & desc);
|
||||
render_pipeline create_render_pipeline(render_pipeline::descriptor const & desc);
|
||||
sampler create_sampler(sampler::descriptor const & desc);
|
||||
shader_module create_shader_module(shader_module::descriptor const & desc);
|
||||
texture create_texture(texture::descriptor const & desc);
|
||||
|
|
|
|||
268
libs/wgpu/include/psemek/wgpu/render_pipeline.hpp
Normal file
268
libs/wgpu/include/psemek/wgpu/render_pipeline.hpp
Normal file
|
|
@ -0,0 +1,268 @@
|
|||
#pragma once
|
||||
|
||||
#include <psemek/wgpu/pipeline_layout.hpp>
|
||||
#include <psemek/wgpu/bind_group_layout.hpp>
|
||||
#include <psemek/wgpu/shader_module.hpp>
|
||||
#include <psemek/wgpu/sampler.hpp>
|
||||
#include <psemek/wgpu/texture.hpp>
|
||||
#include <psemek/wgpu/detail/object.hpp>
|
||||
#include <psemek/wgpu/chained_struct.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
|
||||
namespace psemek::wgpu
|
||||
{
|
||||
|
||||
struct constant_entry
|
||||
{
|
||||
std::vector<chained_struct> chain;
|
||||
std::string key;
|
||||
double value;
|
||||
};
|
||||
|
||||
enum class vertex_step_mode : std::uint32_t
|
||||
{
|
||||
vertex = 0x00000000,
|
||||
instance = 0x00000001,
|
||||
vertex_buffer_not_used = 0x00000002,
|
||||
};
|
||||
|
||||
enum class vertex_format : std::uint32_t
|
||||
{
|
||||
undefined = 0x00000000,
|
||||
uint8x2 = 0x00000001,
|
||||
uint8x4 = 0x00000002,
|
||||
sint8x2 = 0x00000003,
|
||||
sint8x4 = 0x00000004,
|
||||
unorm8x2 = 0x00000005,
|
||||
unorm8x4 = 0x00000006,
|
||||
snorm8x2 = 0x00000007,
|
||||
snorm8x4 = 0x00000008,
|
||||
uint16x2 = 0x00000009,
|
||||
uint16x4 = 0x0000000a,
|
||||
sint16x2 = 0x0000000b,
|
||||
sint16x4 = 0x0000000c,
|
||||
unorm16x2 = 0x0000000d,
|
||||
unorm16x4 = 0x0000000e,
|
||||
snorm16x2 = 0x0000000f,
|
||||
snorm16x4 = 0x00000010,
|
||||
float16x2 = 0x00000011,
|
||||
float16x4 = 0x00000012,
|
||||
float32 = 0x00000013,
|
||||
float32x2 = 0x00000014,
|
||||
float32x3 = 0x00000015,
|
||||
float32x4 = 0x00000016,
|
||||
uint32 = 0x00000017,
|
||||
uint32x2 = 0x00000018,
|
||||
uint32x3 = 0x00000019,
|
||||
uint32x4 = 0x0000001a,
|
||||
sint32 = 0x0000001b,
|
||||
sint32x2 = 0x0000001c,
|
||||
sint32x3 = 0x0000001d,
|
||||
sint32x4 = 0x0000001e,
|
||||
};
|
||||
|
||||
struct vertex_attribute
|
||||
{
|
||||
vertex_format format;
|
||||
std::uint64_t offset;
|
||||
std::uint32_t shader_location;
|
||||
};
|
||||
|
||||
struct vertex_buffer_layout
|
||||
{
|
||||
std::uint64_t array_stride;
|
||||
vertex_step_mode step_mode;
|
||||
std::vector<vertex_attribute> attributes;
|
||||
};
|
||||
|
||||
struct vertex_state
|
||||
{
|
||||
std::vector<chained_struct> chain = {};
|
||||
shader_module module;
|
||||
std::string entry_point;
|
||||
std::vector<constant_entry> constants = {};
|
||||
std::vector<vertex_buffer_layout> buffers;
|
||||
};
|
||||
|
||||
enum class primitive_topology : std::uint32_t
|
||||
{
|
||||
point_list = 0x00000000,
|
||||
line_list = 0x00000001,
|
||||
line_strip = 0x00000002,
|
||||
triangle_list = 0x00000003,
|
||||
triangle_strip = 0x00000004,
|
||||
};
|
||||
|
||||
enum class index_format : std::uint32_t
|
||||
{
|
||||
undefined = 0x00000000,
|
||||
uint16 = 0x00000001,
|
||||
uint32 = 0x00000002,
|
||||
};
|
||||
|
||||
enum class front_face : std::uint32_t
|
||||
{
|
||||
ccw = 0x00000000,
|
||||
cw = 0x00000001,
|
||||
};
|
||||
|
||||
enum class cull_mode : std::uint32_t
|
||||
{
|
||||
none = 0x00000000,
|
||||
front = 0x00000001,
|
||||
back = 0x00000002,
|
||||
};
|
||||
|
||||
struct primitive_state
|
||||
{
|
||||
std::vector<chained_struct> chain = {};
|
||||
primitive_topology topology;
|
||||
index_format strip_index_format = index_format::undefined;
|
||||
enum front_face front_face;
|
||||
enum cull_mode cull_mode;
|
||||
};
|
||||
|
||||
enum class stencil_operation : std::uint32_t
|
||||
{
|
||||
keep = 0x00000000,
|
||||
zero = 0x00000001,
|
||||
replace = 0x00000002,
|
||||
invert = 0x00000003,
|
||||
increment_clamp = 0x00000004,
|
||||
decrement_clamp = 0x00000005,
|
||||
increment_wrap = 0x00000006,
|
||||
decrement_wrap = 0x00000007,
|
||||
};
|
||||
|
||||
struct stencil_face_state
|
||||
{
|
||||
compare_function compare = compare_function::always;
|
||||
stencil_operation fail_op = stencil_operation::keep;
|
||||
stencil_operation depth_fail_op = stencil_operation::keep;
|
||||
stencil_operation pass_op = stencil_operation::keep;
|
||||
};
|
||||
|
||||
struct depth_stencil_state
|
||||
{
|
||||
std::vector<chained_struct> chain = {};
|
||||
texture::format format;
|
||||
bool depth_write = true;
|
||||
compare_function depth_compare;
|
||||
stencil_face_state stencil_front = {};
|
||||
stencil_face_state stencil_back = {};
|
||||
std::uint32_t stencil_read_mask = 0;
|
||||
std::uint32_t stencil_write_mask = 0;
|
||||
std::int32_t depth_bias = 0;
|
||||
float depth_bias_slope_scale = 0.f;
|
||||
float depth_bias_clamp = 0.f;
|
||||
};
|
||||
|
||||
struct multisample_state
|
||||
{
|
||||
std::vector<chained_struct> chain = {};
|
||||
std::uint32_t count = 1;
|
||||
std::uint32_t mask = -1;
|
||||
bool alpha_to_coverage = false;
|
||||
};
|
||||
|
||||
enum class blend_operation : std::uint32_t
|
||||
{
|
||||
add = 0x00000000,
|
||||
subtract = 0x00000001,
|
||||
reverse_subtract = 0x00000002,
|
||||
min = 0x00000003,
|
||||
max = 0x00000004,
|
||||
};
|
||||
|
||||
enum class blend_factor : std::uint32_t
|
||||
{
|
||||
zero = 0x00000000,
|
||||
one = 0x00000001,
|
||||
src = 0x00000002,
|
||||
one_minus_src = 0x00000003,
|
||||
src_alpha = 0x00000004,
|
||||
one_minus_src_alpha = 0x00000005,
|
||||
dst = 0x00000006,
|
||||
one_minus_dst = 0x00000007,
|
||||
dst_alpha = 0x00000008,
|
||||
one_minus_dst_alpha = 0x00000009,
|
||||
src_alpha_saturated = 0x0000000a,
|
||||
constant = 0x0000000b,
|
||||
one_minus_constant = 0x0000000c,
|
||||
};
|
||||
|
||||
struct blend_component
|
||||
{
|
||||
blend_operation operation;
|
||||
blend_factor src_factor;
|
||||
blend_factor dst_factor;
|
||||
};
|
||||
|
||||
struct blend_state
|
||||
{
|
||||
blend_component color;
|
||||
blend_component alpha;
|
||||
};
|
||||
|
||||
enum color_write_mask : std::uint32_t
|
||||
{
|
||||
none = 0x00000000,
|
||||
red = 0x00000001,
|
||||
green = 0x00000002,
|
||||
blue = 0x00000004,
|
||||
alpha = 0x00000008,
|
||||
all = 0x0000000f,
|
||||
};
|
||||
|
||||
struct color_target_state
|
||||
{
|
||||
std::vector<chained_struct> chain = {};
|
||||
texture::format format;
|
||||
std::optional<blend_state> blend = {};
|
||||
color_write_mask write_mask = color_write_mask::all;
|
||||
};
|
||||
|
||||
struct fragment_state {
|
||||
std::vector<chained_struct> chain = {};
|
||||
shader_module module;
|
||||
std::string entry_point;
|
||||
std::vector<constant_entry> constants = {};
|
||||
std::vector<color_target_state> targets;
|
||||
};
|
||||
|
||||
struct render_pipeline
|
||||
: detail::object<render_pipeline>
|
||||
{
|
||||
using detail::object<render_pipeline>::object;
|
||||
|
||||
struct descriptor
|
||||
{
|
||||
std::vector<chained_struct> chain = {};
|
||||
std::string label = {};
|
||||
pipeline_layout layout;
|
||||
vertex_state vertex;
|
||||
primitive_state primitive;
|
||||
std::optional<depth_stencil_state> depth_stencil = {};
|
||||
multisample_state multisample = {};
|
||||
std::optional<fragment_state> fragment = {};
|
||||
};
|
||||
|
||||
bind_group_layout get_bind_group_layout(std::uint32_t index);
|
||||
void set_label(std::string const & label);
|
||||
|
||||
static void reference(void * ptr);
|
||||
static void release(void * ptr);
|
||||
|
||||
private:
|
||||
explicit render_pipeline(void * ptr)
|
||||
: detail::object<render_pipeline>(ptr)
|
||||
{}
|
||||
|
||||
friend struct device;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
+ WGPUAdapter
|
||||
WGPUBindGroup
|
||||
WGPUBindGroupLayout
|
||||
- WGPUBindGroupLayout
|
||||
+ WGPUBuffer
|
||||
+ WGPUCommandBuffer
|
||||
- WGPUCommandEncoder
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
WGPURenderBundle
|
||||
WGPURenderBundleEncoder
|
||||
- WGPURenderPassEncoder
|
||||
WGPURenderPipeline
|
||||
+ WGPURenderPipeline
|
||||
+ WGPUSampler
|
||||
+ WGPUShaderModule
|
||||
+ WGPUSurface
|
||||
|
|
|
|||
17
libs/wgpu/source/bind_group_layout.cpp
Normal file
17
libs/wgpu/source/bind_group_layout.cpp
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#include <psemek/wgpu/bind_group_layout.hpp>
|
||||
#include <psemek/wgpu/external/webgpu.h>
|
||||
|
||||
namespace psemek::wgpu
|
||||
{
|
||||
|
||||
void bind_group_layout::reference(void * ptr)
|
||||
{
|
||||
wgpuBindGroupLayoutReference((WGPUBindGroupLayout)ptr);
|
||||
}
|
||||
|
||||
void bind_group_layout::release(void * ptr)
|
||||
{
|
||||
wgpuBindGroupLayoutRelease((WGPUBindGroupLayout)ptr);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -42,6 +42,110 @@ namespace psemek::wgpu
|
|||
return query_set(wgpuDeviceCreateQuerySet((WGPUDevice)get(), &descriptor));
|
||||
}
|
||||
|
||||
render_pipeline device::create_render_pipeline(render_pipeline::descriptor const & desc)
|
||||
{
|
||||
WGPURenderPipelineDescriptor descriptor = {};
|
||||
|
||||
std::vector<WGPUConstantEntry> vertex_constants;
|
||||
for (auto const & constant_in : desc.vertex.constants)
|
||||
{
|
||||
auto & constant_out = vertex_constants.emplace_back();
|
||||
constant_out.nextInChain = (WGPUChainedStruct const *)detail::fill_chain(constant_in.chain);
|
||||
constant_out.key = constant_in.key.data();
|
||||
constant_out.value = constant_in.value;
|
||||
}
|
||||
|
||||
std::vector<WGPUVertexBufferLayout> vertex_buffers;
|
||||
for (auto const & buffer_in : desc.vertex.buffers)
|
||||
{
|
||||
auto & buffer_out = vertex_buffers.emplace_back();
|
||||
buffer_out.arrayStride = buffer_in.array_stride;
|
||||
buffer_out.stepMode = (WGPUVertexStepMode)buffer_in.step_mode;
|
||||
buffer_out.attributeCount = buffer_in.attributes.size();
|
||||
static_assert(sizeof(WGPUVertexAttribute) == sizeof(vertex_attribute));
|
||||
buffer_out.attributes = (WGPUVertexAttribute const *)buffer_in.attributes.data();
|
||||
}
|
||||
|
||||
descriptor.vertex.nextInChain = (WGPUChainedStruct const *)detail::fill_chain(desc.vertex.chain);
|
||||
descriptor.vertex.module = (WGPUShaderModule)desc.vertex.module.get();
|
||||
descriptor.vertex.entryPoint = desc.vertex.entry_point.data();
|
||||
descriptor.vertex.constantCount = vertex_constants.size();
|
||||
descriptor.vertex.constants = vertex_constants.data();
|
||||
descriptor.vertex.bufferCount = vertex_buffers.size();
|
||||
descriptor.vertex.buffers = vertex_buffers.data();
|
||||
|
||||
descriptor.primitive.nextInChain = (WGPUChainedStruct const *)detail::fill_chain(desc.primitive.chain);
|
||||
descriptor.primitive.topology = (WGPUPrimitiveTopology)desc.primitive.topology;
|
||||
descriptor.primitive.stripIndexFormat = (WGPUIndexFormat)desc.primitive.strip_index_format;
|
||||
descriptor.primitive.frontFace = (WGPUFrontFace)desc.primitive.front_face;
|
||||
descriptor.primitive.cullMode = (WGPUCullMode)desc.primitive.cull_mode;
|
||||
|
||||
WGPUDepthStencilState depth_stencil_state = {};
|
||||
if (desc.depth_stencil)
|
||||
{
|
||||
depth_stencil_state.nextInChain = (WGPUChainedStruct const *)detail::fill_chain(desc.depth_stencil->chain);
|
||||
depth_stencil_state.format = (WGPUTextureFormat)desc.depth_stencil->format;
|
||||
depth_stencil_state.depthWriteEnabled = desc.depth_stencil->depth_write;
|
||||
depth_stencil_state.depthCompare = (WGPUCompareFunction)desc.depth_stencil->depth_compare;
|
||||
depth_stencil_state.stencilFront.compare = (WGPUCompareFunction)desc.depth_stencil->stencil_front.compare;
|
||||
depth_stencil_state.stencilFront.failOp = (WGPUStencilOperation)desc.depth_stencil->stencil_front.fail_op;
|
||||
depth_stencil_state.stencilFront.depthFailOp = (WGPUStencilOperation)desc.depth_stencil->stencil_front.depth_fail_op;
|
||||
depth_stencil_state.stencilFront.passOp = (WGPUStencilOperation)desc.depth_stencil->stencil_front.pass_op;
|
||||
depth_stencil_state.stencilBack.compare = (WGPUCompareFunction)desc.depth_stencil->stencil_back.compare;
|
||||
depth_stencil_state.stencilBack.failOp = (WGPUStencilOperation)desc.depth_stencil->stencil_back.fail_op;
|
||||
depth_stencil_state.stencilBack.depthFailOp = (WGPUStencilOperation)desc.depth_stencil->stencil_back.depth_fail_op;
|
||||
depth_stencil_state.stencilBack.passOp = (WGPUStencilOperation)desc.depth_stencil->stencil_back.pass_op;
|
||||
depth_stencil_state.stencilReadMask = desc.depth_stencil->stencil_read_mask;
|
||||
depth_stencil_state.stencilWriteMask = desc.depth_stencil->stencil_write_mask;
|
||||
depth_stencil_state.depthBias = desc.depth_stencil->depth_bias;
|
||||
depth_stencil_state.depthBiasSlopeScale = desc.depth_stencil->depth_bias_slope_scale;
|
||||
depth_stencil_state.depthBiasClamp = desc.depth_stencil->depth_bias_clamp;
|
||||
|
||||
descriptor.depthStencil = &depth_stencil_state;
|
||||
}
|
||||
|
||||
descriptor.multisample.nextInChain = (WGPUChainedStruct const *)detail::fill_chain(desc.multisample.chain);
|
||||
descriptor.multisample.count = desc.multisample.count;
|
||||
descriptor.multisample.mask = desc.multisample.mask;
|
||||
descriptor.multisample.alphaToCoverageEnabled = desc.multisample.alpha_to_coverage;
|
||||
|
||||
WGPUFragmentState fragment_state = {};
|
||||
std::vector<WGPUConstantEntry> fragment_constants;
|
||||
std::vector<WGPUColorTargetState> color_targets;
|
||||
if (desc.fragment)
|
||||
{
|
||||
for (auto const & constant_in : desc.fragment->constants)
|
||||
{
|
||||
auto & constant_out = fragment_constants.emplace_back();
|
||||
constant_out.nextInChain = (WGPUChainedStruct const *)detail::fill_chain(constant_in.chain);
|
||||
constant_out.key = constant_in.key.data();
|
||||
constant_out.value = constant_in.value;
|
||||
}
|
||||
|
||||
for (auto const & target_in : desc.fragment->targets)
|
||||
{
|
||||
auto & target_out = color_targets.emplace_back();
|
||||
target_out.nextInChain = (WGPUChainedStruct const *)detail::fill_chain(target_in.chain);
|
||||
target_out.format = (WGPUTextureFormat)target_in.format;
|
||||
static_assert(sizeof(WGPUBlendState) == sizeof(blend_state));
|
||||
target_out.blend = (WGPUBlendState *)(target_in.blend ? &(*target_in.blend) : nullptr);
|
||||
target_out.writeMask = (WGPUColorWriteMaskFlags)target_in.write_mask;
|
||||
}
|
||||
|
||||
fragment_state.nextInChain = (WGPUChainedStruct const *)detail::fill_chain(desc.fragment->chain);
|
||||
fragment_state.module = (WGPUShaderModule)desc.fragment->module.get();
|
||||
fragment_state.entryPoint = desc.fragment->entry_point.data();
|
||||
fragment_state.constantCount = fragment_constants.size();
|
||||
fragment_state.constants = fragment_constants.data();
|
||||
fragment_state.targetCount = color_targets.size();
|
||||
fragment_state.targets = color_targets.data();
|
||||
|
||||
descriptor.fragment = &fragment_state;
|
||||
}
|
||||
|
||||
return render_pipeline(wgpuDeviceCreateRenderPipeline((WGPUDevice)get(), &descriptor));
|
||||
}
|
||||
|
||||
sampler device::create_sampler(sampler::descriptor const & desc)
|
||||
{
|
||||
WGPUSamplerDescriptor descriptor = {};
|
||||
|
|
|
|||
27
libs/wgpu/source/render_pipeline.cpp
Normal file
27
libs/wgpu/source/render_pipeline.cpp
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
#include <psemek/wgpu/render_pipeline.hpp>
|
||||
#include <psemek/wgpu/external/webgpu.h>
|
||||
|
||||
namespace psemek::wgpu
|
||||
{
|
||||
|
||||
bind_group_layout render_pipeline::get_bind_group_layout(std::uint32_t index)
|
||||
{
|
||||
return bind_group_layout(wgpuRenderPipelineGetBindGroupLayout((WGPURenderPipeline)get(), index));
|
||||
}
|
||||
|
||||
void render_pipeline::set_label(std::string const & label)
|
||||
{
|
||||
wgpuRenderPipelineSetLabel((WGPURenderPipeline)get(), label.data());
|
||||
}
|
||||
|
||||
void render_pipeline::reference(void * ptr)
|
||||
{
|
||||
wgpuRenderPipelineReference((WGPURenderPipeline)ptr);
|
||||
}
|
||||
|
||||
void render_pipeline::release(void * ptr)
|
||||
{
|
||||
wgpuRenderPipelineRelease((WGPURenderPipeline)ptr);
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue