summaryrefslogtreecommitdiff
path: root/src/gpu/pipeline_builder.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpu/pipeline_builder.h')
-rw-r--r--src/gpu/pipeline_builder.h109
1 files changed, 109 insertions, 0 deletions
diff --git a/src/gpu/pipeline_builder.h b/src/gpu/pipeline_builder.h
new file mode 100644
index 0000000..06b4ceb
--- /dev/null
+++ b/src/gpu/pipeline_builder.h
@@ -0,0 +1,109 @@
+// WGPU render pipeline builder - reduces pipeline creation boilerplate
+#pragma once
+#include <vector>
+#include <string>
+
+// Forward declarations (users must include gpu.h and shader_composer.h)
+struct WGPUDeviceImpl;
+typedef struct WGPUDeviceImpl* WGPUDevice;
+struct WGPUBindGroupLayoutImpl;
+typedef struct WGPUBindGroupLayoutImpl* WGPUBindGroupLayout;
+struct WGPURenderPipelineImpl;
+typedef struct WGPURenderPipelineImpl* WGPURenderPipeline;
+struct WGPUShaderModuleImpl;
+typedef struct WGPUShaderModuleImpl* WGPUShaderModule;
+
+#include "platform/platform.h"
+#include "gpu/effects/shader_composer.h"
+
+class RenderPipelineBuilder {
+ WGPUDevice device_;
+ WGPURenderPipelineDescriptor desc_{};
+ WGPUColorTargetState color_{};
+ WGPUBlendState blend_{};
+ WGPUDepthStencilState depth_{};
+ std::vector<WGPUBindGroupLayout> layouts_;
+ std::string shader_text_;
+ WGPUShaderModule shader_module_ = nullptr;
+ bool has_blend_ = false;
+ bool has_depth_ = false;
+
+public:
+ explicit RenderPipelineBuilder(WGPUDevice device) : device_(device) {
+ desc_.primitive.topology = WGPUPrimitiveTopology_TriangleList;
+ desc_.primitive.cullMode = WGPUCullMode_None;
+ desc_.multisample.count = 1;
+ desc_.multisample.mask = 0xFFFFFFFF;
+ }
+
+ RenderPipelineBuilder& shader(const char* wgsl, bool compose = true) {
+ shader_text_ = compose ? ShaderComposer::Get().Compose({}, wgsl) : wgsl;
+ WGPUShaderSourceWGSL wgsl_src{};
+ wgsl_src.chain.sType = WGPUSType_ShaderSourceWGSL;
+ wgsl_src.code = str_view(shader_text_.c_str());
+ WGPUShaderModuleDescriptor shader_desc{};
+ shader_desc.nextInChain = &wgsl_src.chain;
+ shader_module_ = wgpuDeviceCreateShaderModule(device_, &shader_desc);
+ desc_.vertex.module = shader_module_;
+ desc_.vertex.entryPoint = str_view("vs_main");
+ return *this;
+ }
+
+ RenderPipelineBuilder& bind_group_layout(WGPUBindGroupLayout layout) {
+ layouts_.push_back(layout);
+ return *this;
+ }
+
+ RenderPipelineBuilder& format(WGPUTextureFormat fmt) {
+ color_.format = fmt;
+ return *this;
+ }
+
+ RenderPipelineBuilder& blend_alpha() {
+ has_blend_ = true;
+ blend_.color.operation = WGPUBlendOperation_Add;
+ blend_.color.srcFactor = WGPUBlendFactor_SrcAlpha;
+ blend_.color.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha;
+ blend_.alpha.operation = WGPUBlendOperation_Add;
+ blend_.alpha.srcFactor = WGPUBlendFactor_One;
+ blend_.alpha.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha;
+ return *this;
+ }
+
+ RenderPipelineBuilder& depth(WGPUTextureFormat depth_fmt = WGPUTextureFormat_Depth24Plus) {
+ has_depth_ = true;
+ depth_.format = depth_fmt;
+ depth_.depthWriteEnabled = WGPUOptionalBool_True;
+ depth_.depthCompare = WGPUCompareFunction_Less;
+ return *this;
+ }
+
+ RenderPipelineBuilder& cull_back() {
+ desc_.primitive.cullMode = WGPUCullMode_Back;
+ return *this;
+ }
+
+ WGPURenderPipeline build() {
+ color_.writeMask = WGPUColorWriteMask_All;
+ if (has_blend_) color_.blend = &blend_;
+
+ WGPUFragmentState fragment{};
+ fragment.module = shader_module_;
+ fragment.entryPoint = str_view("fs_main");
+ fragment.targetCount = 1;
+ fragment.targets = &color_;
+
+ WGPUPipelineLayoutDescriptor pl_desc{};
+ pl_desc.bindGroupLayoutCount = layouts_.size();
+ pl_desc.bindGroupLayouts = layouts_.data();
+ WGPUPipelineLayout layout = wgpuDeviceCreatePipelineLayout(device_, &pl_desc);
+
+ desc_.layout = layout;
+ desc_.fragment = &fragment;
+ if (has_depth_) desc_.depthStencil = &depth_;
+
+ WGPURenderPipeline pipeline = wgpuDeviceCreateRenderPipeline(device_, &desc_);
+ wgpuPipelineLayoutRelease(layout);
+ return pipeline;
+ }
+};