From d0be7b775a07fde86a3a033e19b30583108431c3 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Fri, 5 Jun 2026 09:57:59 +1000 Subject: [PATCH] ifcviewer: move render pipelines into ViewportCore (#84-b) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the 15 pipeline + bind-group-layout + shader-module handles that buildPipelines / buildEdgePipeline / buildPickPipeline write to. Same pattern as #84-a: storage lives in ViewportCore, ViewportWindow keeps reference aliases so existing builder-method bodies don't have to acquire a `core_.` prefix at every touch point. Moved fields: Main render group: main_shader_module_, frame_bgl_ (group 0), model_bgl_ (group 1), pipeline_layout_, main_pipeline_, main_pipeline_transparent_ HiZ occlusion-cull group: hiz_shader_module_, hiz_bgl_, hiz_pipeline_layout_, hiz_pipeline_ Edge silhouette group: edge_shader_module_, edge_bgl_, edge_pipeline_layout_, edge_pipeline_ Pick pass: pick_pipeline_ (reuses pipeline_layout_ — same set of bindings) ViewportWindow's constructor binds 16 new alias references after the 7 lifecycle ones from #84-a; member-init order matches declaration order so core_ is constructed before any alias binds. Builds: desktop / bonsai / web all green. Tests 100/100. --- src/ifcviewer/ViewportCore.h | 33 ++++++++++++++++++++++++ src/ifcviewer/ViewportWindow.cpp | 17 ++++++++++++- src/ifcviewer/ViewportWindow.h | 43 ++++++++++++++++---------------- 3 files changed, 71 insertions(+), 22 deletions(-) diff --git a/src/ifcviewer/ViewportCore.h b/src/ifcviewer/ViewportCore.h index 37b517b4cd..8eda402cf0 100644 --- a/src/ifcviewer/ViewportCore.h +++ b/src/ifcviewer/ViewportCore.h @@ -69,6 +69,39 @@ private: WGPUSurface surface_ = nullptr; WGPUTextureFormat surface_format_ = WGPUTextureFormat_Undefined; bool surface_configured_ = false; + + // ---- Pipelines + bind-group layouts (built once after init) ------------- + // + // Main render pipeline group: one shader module + two bind group + // layouts (frame uniforms at group=0, per-model storages at + // group=1) feeding both the opaque-pass pipeline and the + // transparent-pass variant. The transparent pipeline shares the + // shader and layout; it differs only in depthWriteEnabled=False + // and the SrcAlpha / OneMinusSrcAlpha blend on the color target. + WGPUShaderModule main_shader_module_ = nullptr; + WGPUBindGroupLayout frame_bgl_ = nullptr; // group 0 + WGPUBindGroupLayout model_bgl_ = nullptr; // group 1 + WGPUPipelineLayout pipeline_layout_ = nullptr; + WGPURenderPipeline main_pipeline_ = nullptr; + WGPURenderPipeline main_pipeline_transparent_ = nullptr; + + // HiZ occlusion-cull pipeline group. Downsamples MSAA depth into a + // mip pyramid; consumed by next-frame cull. + WGPUShaderModule hiz_shader_module_ = nullptr; + WGPUBindGroupLayout hiz_bgl_ = nullptr; + WGPUPipelineLayout hiz_pipeline_layout_ = nullptr; + WGPURenderPipeline hiz_pipeline_ = nullptr; + + // Edge-silhouette pipeline group. Drawn after the main pass; reads + // the depth/normal attachments to emit dark outlines. + WGPUShaderModule edge_shader_module_ = nullptr; + WGPUBindGroupLayout edge_bgl_ = nullptr; + WGPUPipelineLayout edge_pipeline_layout_ = nullptr; + WGPURenderPipeline edge_pipeline_ = nullptr; + + // Pick pass. Reuses pipeline_layout_ — same set of bindings as the + // main pass since the pick fragment also vertex-pulls instance data. + WGPURenderPipeline pick_pipeline_ = nullptr; }; #endif // VIEWPORTCORE_H diff --git a/src/ifcviewer/ViewportWindow.cpp b/src/ifcviewer/ViewportWindow.cpp index ce553fc08b..b7c7b45f1f 100644 --- a/src/ifcviewer/ViewportWindow.cpp +++ b/src/ifcviewer/ViewportWindow.cpp @@ -618,7 +618,22 @@ ViewportWindow::ViewportWindow(QWindow* parent) queue_ (core_.queue_), surface_ (core_.surface_), surface_format_ (core_.surface_format_), - surface_configured_(core_.surface_configured_) { + surface_configured_(core_.surface_configured_), + main_shader_module_ (core_.main_shader_module_), + frame_bgl_ (core_.frame_bgl_), + model_bgl_ (core_.model_bgl_), + pipeline_layout_ (core_.pipeline_layout_), + main_pipeline_ (core_.main_pipeline_), + main_pipeline_transparent_(core_.main_pipeline_transparent_), + hiz_shader_module_ (core_.hiz_shader_module_), + hiz_bgl_ (core_.hiz_bgl_), + hiz_pipeline_layout_ (core_.hiz_pipeline_layout_), + hiz_pipeline_ (core_.hiz_pipeline_), + edge_shader_module_ (core_.edge_shader_module_), + edge_bgl_ (core_.edge_bgl_), + edge_pipeline_layout_ (core_.edge_pipeline_layout_), + edge_pipeline_ (core_.edge_pipeline_), + pick_pipeline_(core_.pick_pipeline_) { // wgpu doesn't need a GL context; we just need a real native window // whose backing layer matches the GPU API wgpu will drive. // diff --git a/src/ifcviewer/ViewportWindow.h b/src/ifcviewer/ViewportWindow.h index 1df4836043..3aed358e63 100644 --- a/src/ifcviewer/ViewportWindow.h +++ b/src/ifcviewer/ViewportWindow.h @@ -654,18 +654,16 @@ private: WGPUTextureFormat& surface_format_; bool& surface_configured_; - // Render pipeline + bind group layouts (built once after init). - WGPUShaderModule main_shader_module_ = nullptr; - WGPUBindGroupLayout frame_bgl_ = nullptr; // group 0 - WGPUBindGroupLayout model_bgl_ = nullptr; // group 1 - WGPUPipelineLayout pipeline_layout_ = nullptr; - WGPURenderPipeline main_pipeline_ = nullptr; - // Transparent-pass pipeline. Same shader / layout / vertex-pulling as - // main_pipeline_; differs only in depthWriteEnabled=False and a - // SrcAlpha / OneMinusSrcAlpha blend on the color target. render() - // does the opaque pass with main_pipeline_ first, then this one - // over the transparent partition of each chunk's visible_draws. - WGPURenderPipeline main_pipeline_transparent_ = nullptr; + // Pipeline + bind-group-layout alias references — actual storage + // lives in core_ (see ViewportCore.h). Each goes away as the + // building method (buildPipelines / buildEdgePipeline / + // buildPickPipeline) migrates into ViewportCore. + WGPUShaderModule& main_shader_module_; + WGPUBindGroupLayout& frame_bgl_; // group 0 + WGPUBindGroupLayout& model_bgl_; // group 1 + WGPUPipelineLayout& pipeline_layout_; + WGPURenderPipeline& main_pipeline_; + WGPURenderPipeline& main_pipeline_transparent_; // Per-frame uniform (view-proj + lighting), bound at group 0. WGPUBuffer frame_uniform_buffer_ = nullptr; @@ -712,10 +710,11 @@ private: // GL's HiZ default is 256 wide; we match. Height tracks viewport aspect. static constexpr uint32_t HIZ_BASE_W = 256; - WGPUShaderModule hiz_shader_module_ = nullptr; - WGPUBindGroupLayout hiz_bgl_ = nullptr; - WGPUPipelineLayout hiz_pipeline_layout_ = nullptr; - WGPURenderPipeline hiz_pipeline_ = nullptr; + // HiZ pipeline aliases (storage in core_). + WGPUShaderModule& hiz_shader_module_; + WGPUBindGroupLayout& hiz_bgl_; + WGPUPipelineLayout& hiz_pipeline_layout_; + WGPURenderPipeline& hiz_pipeline_; WGPUBuffer hiz_uniform_buffer_ = nullptr; WGPUBindGroup hiz_bind_group_ = nullptr; @@ -736,10 +735,11 @@ private: // texture in a fullscreen pass, computes a depth Laplacian, blends // dark lines into the resolved surface colour. Matches GL's // renderEdgePass() visually. - WGPUShaderModule edge_shader_module_ = nullptr; - WGPUBindGroupLayout edge_bgl_ = nullptr; - WGPUPipelineLayout edge_pipeline_layout_ = nullptr; - WGPURenderPipeline edge_pipeline_ = nullptr; + // Edge silhouette pipeline aliases (storage in core_). + WGPUShaderModule& edge_shader_module_; + WGPUBindGroupLayout& edge_bgl_; + WGPUPipelineLayout& edge_pipeline_layout_; + WGPURenderPipeline& edge_pipeline_; WGPUBindGroup edge_bind_group_ = nullptr; bool edges_enabled_ = true; @@ -783,7 +783,8 @@ private: // pass — pick fragment outputs the instance's object_id. The pick // pipeline reuses pipeline_layout_ because it needs the same set of // bindings (frame uniform at group=0, per-model storages at group=1). - WGPURenderPipeline pick_pipeline_ = nullptr; + // Pick pipeline alias (storage in core_). + WGPURenderPipeline& pick_pipeline_; WGPUTexture pick_color_texture_ = nullptr; WGPUTextureView pick_color_view_ = nullptr; // Second pick MRT: RGBA16F packed world-space normal. Sampled by