summaryrefslogtreecommitdiff
path: root/src/gpu/pipeline_builder.cc
diff options
context:
space:
mode:
authorskal <pascal.massimino@gmail.com>2026-02-28 08:45:28 +0100
committerskal <pascal.massimino@gmail.com>2026-02-28 08:45:28 +0100
commite07f87cba89ef738781399b079840615f27e1667 (patch)
tree8a6cd84a3e9b40e781300c3acccc8ad0f7300b7b /src/gpu/pipeline_builder.cc
parentaf06b3512598c81c472fdbbeb4994c7eb8621d4c (diff)
refactor(gpu): move RenderPipelineBuilder impl to pipeline_builder.cc
Keeps .h as declarations only; moves all method bodies to .cc. Adds pipeline_builder.cc to COMMON_GPU_EFFECTS in DemoSourceLists.cmake. handoff(Claude): pipeline_builder split to .h/.cc, builds clean.
Diffstat (limited to 'src/gpu/pipeline_builder.cc')
-rw-r--r--src/gpu/pipeline_builder.cc91
1 files changed, 91 insertions, 0 deletions
diff --git a/src/gpu/pipeline_builder.cc b/src/gpu/pipeline_builder.cc
new file mode 100644
index 0000000..b3fa5f8
--- /dev/null
+++ b/src/gpu/pipeline_builder.cc
@@ -0,0 +1,91 @@
+// WGPU render pipeline builder - implementation
+#include "gpu/pipeline_builder.h"
+#include "util/fatal_error.h"
+
+RenderPipelineBuilder::RenderPipelineBuilder(WGPUDevice device)
+ : device_(device) {
+ desc_.primitive.topology = WGPUPrimitiveTopology_TriangleList;
+ desc_.primitive.cullMode = WGPUCullMode_None;
+ desc_.multisample.count = 1;
+ desc_.multisample.mask = 0xFFFFFFFF;
+}
+
+RenderPipelineBuilder& RenderPipelineBuilder::shader(const char* wgsl,
+ bool compose) {
+ shader_text_ = compose ? ShaderComposer::Get().Compose({}, wgsl) : wgsl;
+ if (device_ == nullptr)
+ return *this;
+ 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& RenderPipelineBuilder::bind_group_layout(
+ WGPUBindGroupLayout layout) {
+ layouts_.push_back(layout);
+ return *this;
+}
+
+RenderPipelineBuilder& RenderPipelineBuilder::format(WGPUTextureFormat fmt) {
+ color_.format = fmt;
+ return *this;
+}
+
+RenderPipelineBuilder& 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& RenderPipelineBuilder::depth(
+ WGPUTextureFormat depth_fmt) {
+ has_depth_ = true;
+ depth_.format = depth_fmt;
+ depth_.depthWriteEnabled = WGPUOptionalBool_True;
+ depth_.depthCompare = WGPUCompareFunction_Less;
+ return *this;
+}
+
+RenderPipelineBuilder& RenderPipelineBuilder::cull_back() {
+ desc_.primitive.cullMode = WGPUCullMode_Back;
+ return *this;
+}
+
+WGPURenderPipeline RenderPipelineBuilder::build() {
+ HEADLESS_RETURN_VAL_IF_NULL(device_, nullptr);
+
+ 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;
+}