From b3eded8d56219fa19029a1b9bb7e7e7584f093d9 Mon Sep 17 00:00:00 2001 From: skal Date: Tue, 17 Feb 2026 12:35:59 +0100 Subject: refactor(effects): Factor shared initialization into Effect base class Eliminate ~100 lines of duplicated code across effect subclasses by moving common resource initialization to the base Effect class. Most effects repeatedly created uniforms buffers, samplers, and dummy textures with identical configurations. Changes: - Add shared members to Effect: uniforms_buffer_, sampler_, dummy_texture_* - Add helpers: init_uniforms_buffer(), create_*_sampler(), create_dummy_scene_texture() - Add gpu_create_*_sampler() and gpu_create_dummy_scene_texture() to gpu.h - Move HEADLESS_RETURN_IF_NULL to Effect constructor - Update 7 effects to use base class helpers (Flash, Heptagon, Passthrough, Placeholder, GaussianBlur, Particles, PeakMeter) Benefits: Improved consistency, easier maintenance, reduced binary size. Co-Authored-By: Claude Sonnet 4.5 --- src/effects/flash_effect.cc | 28 +++++----------------------- src/effects/flash_effect.h | 4 ---- src/effects/gaussian_blur_effect.cc | 22 +++++----------------- src/effects/gaussian_blur_effect.h | 2 -- src/effects/heptagon_effect.cc | 30 ++++-------------------------- src/effects/heptagon_effect.h | 4 ---- src/effects/particles_effect.cc | 10 ++++------ src/effects/particles_effect.h | 1 - src/effects/passthrough_effect.cc | 20 ++++---------------- src/effects/passthrough_effect.h | 2 -- src/effects/peak_meter_effect.cc | 2 +- src/effects/peak_meter_effect.h | 1 - src/effects/placeholder_effect.cc | 18 ++++-------------- src/effects/placeholder_effect.h | 2 -- 14 files changed, 27 insertions(+), 119 deletions(-) (limited to 'src/effects') diff --git a/src/effects/flash_effect.cc b/src/effects/flash_effect.cc index 7baf6a2..2eba2ff 100644 --- a/src/effects/flash_effect.cc +++ b/src/effects/flash_effect.cc @@ -10,33 +10,15 @@ Flash::Flash(const GpuContext& ctx, const std::vector& inputs, const std::vector& outputs, float start_time, float end_time) : Effect(ctx, inputs, outputs, start_time, end_time), pipeline_(nullptr), - bind_group_(nullptr), sampler_(nullptr), dummy_texture_(nullptr), - dummy_texture_view_(nullptr) { + bind_group_(nullptr) { HEADLESS_RETURN_IF_NULL(ctx_.device); - uniforms_buffer_.init(ctx_.device); + init_uniforms_buffer(); + create_nearest_sampler(); + create_dummy_scene_texture(); + pipeline_ = create_post_process_pipeline( ctx_.device, WGPUTextureFormat_RGBA8Unorm, flash_shader_wgsl); - - // Create dummy sampler (scene effects don't use texture input) - WGPUSamplerDescriptor sampler_desc = {}; - sampler_desc.addressModeU = WGPUAddressMode_ClampToEdge; - sampler_desc.addressModeV = WGPUAddressMode_ClampToEdge; - sampler_desc.magFilter = WGPUFilterMode_Nearest; - sampler_desc.minFilter = WGPUFilterMode_Nearest; - sampler_desc.maxAnisotropy = 1; - sampler_ = wgpuDeviceCreateSampler(ctx_.device, &sampler_desc); - - // Create 1×1 dummy texture - WGPUTextureDescriptor tex_desc = {}; - tex_desc.size = {1, 1, 1}; - tex_desc.format = WGPUTextureFormat_RGBA8Unorm; - tex_desc.usage = WGPUTextureUsage_TextureBinding; - tex_desc.dimension = WGPUTextureDimension_2D; - tex_desc.mipLevelCount = 1; - tex_desc.sampleCount = 1; - dummy_texture_ = wgpuDeviceCreateTexture(ctx_.device, &tex_desc); - dummy_texture_view_ = wgpuTextureCreateView(dummy_texture_, nullptr); } Flash::~Flash() { diff --git a/src/effects/flash_effect.h b/src/effects/flash_effect.h index 1117e0a..d46cd56 100644 --- a/src/effects/flash_effect.h +++ b/src/effects/flash_effect.h @@ -18,8 +18,4 @@ class Flash : public Effect { private: WGPURenderPipeline pipeline_; WGPUBindGroup bind_group_; - WGPUSampler sampler_; - WGPUTexture dummy_texture_; - WGPUTextureView dummy_texture_view_; - UniformBuffer uniforms_buffer_; }; diff --git a/src/effects/gaussian_blur_effect.cc b/src/effects/gaussian_blur_effect.cc index 7304321..1d39256 100644 --- a/src/effects/gaussian_blur_effect.cc +++ b/src/effects/gaussian_blur_effect.cc @@ -9,27 +9,15 @@ GaussianBlur::GaussianBlur(const GpuContext& ctx, const std::vector& inputs, const std::vector& outputs, float start_time, float end_time) - : Effect(ctx, inputs, outputs, start_time, end_time), pipeline_(nullptr), bind_group_(nullptr), - sampler_(nullptr) { - // Headless mode: skip GPU resource creation (compiled out in STRIP_ALL) + : Effect(ctx, inputs, outputs, start_time, end_time), pipeline_(nullptr), bind_group_(nullptr) { HEADLESS_RETURN_IF_NULL(ctx_.device); - // Create pipeline + init_uniforms_buffer(); + create_linear_sampler(); + params_buffer_.init(ctx_.device); + pipeline_ = create_post_process_pipeline( ctx_.device, WGPUTextureFormat_RGBA8Unorm, gaussian_blur_shader_wgsl); - - // Create sampler - WGPUSamplerDescriptor sampler_desc = {}; - sampler_desc.addressModeU = WGPUAddressMode_ClampToEdge; - sampler_desc.addressModeV = WGPUAddressMode_ClampToEdge; - sampler_desc.magFilter = WGPUFilterMode_Linear; - sampler_desc.minFilter = WGPUFilterMode_Linear; - sampler_desc.maxAnisotropy = 1; - sampler_ = wgpuDeviceCreateSampler(ctx_.device, &sampler_desc); - - // Init uniform buffers - params_buffer_.init(ctx_.device); - uniforms_buffer_.init(ctx_.device); } void GaussianBlur::render(WGPUCommandEncoder encoder, diff --git a/src/effects/gaussian_blur_effect.h b/src/effects/gaussian_blur_effect.h index cc9ff56..f4b8fcf 100644 --- a/src/effects/gaussian_blur_effect.h +++ b/src/effects/gaussian_blur_effect.h @@ -26,8 +26,6 @@ class GaussianBlur : public Effect { private: WGPURenderPipeline pipeline_; WGPUBindGroup bind_group_; - WGPUSampler sampler_; GaussianBlurParams blur_params_; UniformBuffer params_buffer_; - UniformBuffer uniforms_buffer_; }; diff --git a/src/effects/heptagon_effect.cc b/src/effects/heptagon_effect.cc index c472f2f..46d6f7f 100644 --- a/src/effects/heptagon_effect.cc +++ b/src/effects/heptagon_effect.cc @@ -10,37 +10,15 @@ Heptagon::Heptagon(const GpuContext& ctx, const std::vector& inputs, const std::vector& outputs, float start_time, float end_time) - : Effect(ctx, inputs, outputs, start_time, end_time), pipeline_(nullptr), bind_group_(nullptr), - sampler_(nullptr) { - // Headless mode: skip GPU resource creation (compiled out in STRIP_ALL) + : Effect(ctx, inputs, outputs, start_time, end_time), pipeline_(nullptr), bind_group_(nullptr) { HEADLESS_RETURN_IF_NULL(ctx_.device); - // Init uniforms - uniforms_buffer_.init(ctx_.device); + init_uniforms_buffer(); + create_nearest_sampler(); + create_dummy_scene_texture(); - // Create pipeline (standard post-process, no depth) pipeline_ = create_post_process_pipeline( ctx_.device, WGPUTextureFormat_RGBA8Unorm, heptagon_shader_wgsl); - - // Create dummy sampler (scene effects don't use texture input) - WGPUSamplerDescriptor sampler_desc = {}; - sampler_desc.addressModeU = WGPUAddressMode_ClampToEdge; - sampler_desc.addressModeV = WGPUAddressMode_ClampToEdge; - sampler_desc.magFilter = WGPUFilterMode_Nearest; - sampler_desc.minFilter = WGPUFilterMode_Nearest; - sampler_desc.maxAnisotropy = 1; - sampler_ = wgpuDeviceCreateSampler(ctx_.device, &sampler_desc); - - // Create 1×1 dummy texture - WGPUTextureDescriptor tex_desc = {}; - tex_desc.size = {1, 1, 1}; - tex_desc.format = WGPUTextureFormat_RGBA8Unorm; - tex_desc.usage = WGPUTextureUsage_TextureBinding; - tex_desc.dimension = WGPUTextureDimension_2D; - tex_desc.mipLevelCount = 1; - tex_desc.sampleCount = 1; - dummy_texture_ = wgpuDeviceCreateTexture(ctx_.device, &tex_desc); - dummy_texture_view_ = wgpuTextureCreateView(dummy_texture_, nullptr); } Heptagon::~Heptagon() { diff --git a/src/effects/heptagon_effect.h b/src/effects/heptagon_effect.h index ef05d79..4b7b887 100644 --- a/src/effects/heptagon_effect.h +++ b/src/effects/heptagon_effect.h @@ -18,8 +18,4 @@ class Heptagon : public Effect { private: WGPURenderPipeline pipeline_; WGPUBindGroup bind_group_; - WGPUSampler sampler_; - WGPUTexture dummy_texture_; - WGPUTextureView dummy_texture_view_; - UniformBuffer uniforms_buffer_; }; diff --git a/src/effects/particles_effect.cc b/src/effects/particles_effect.cc index d83f303..3c9feb7 100644 --- a/src/effects/particles_effect.cc +++ b/src/effects/particles_effect.cc @@ -12,11 +12,9 @@ Particles::Particles(const GpuContext& ctx, const std::vector& outputs, float start_time, float end_time) : Effect(ctx, inputs, outputs, start_time, end_time) { - // Headless mode: skip GPU resource creation (compiled out in STRIP_ALL) HEADLESS_RETURN_IF_NULL(ctx_.device); - // Initialize uniforms - uniforms_.init(ctx_.device); + init_uniforms_buffer(); // Initialize particles buffer std::vector init_p(NUM_PARTICLES); @@ -49,7 +47,7 @@ Particles::Particles(const GpuContext& ctx, // Create compute shader (particle simulation) ResourceBinding compute_bindings[] = { {particles_buffer_, WGPUBufferBindingType_Storage}, - {uniforms_.get(), WGPUBufferBindingType_Uniform}}; + {uniforms_buffer_.get(), WGPUBufferBindingType_Uniform}}; compute_pass_ = gpu_create_compute_pass(ctx_.device, particle_compute_wgsl, compute_bindings, 2); compute_pass_.workgroup_size_x = (NUM_PARTICLES + 63) / 64; @@ -57,7 +55,7 @@ Particles::Particles(const GpuContext& ctx, // Create render shader (particle rendering) ResourceBinding render_bindings[] = { {particles_buffer_, WGPUBufferBindingType_ReadOnlyStorage}, - {uniforms_.get(), WGPUBufferBindingType_Uniform}}; + {uniforms_buffer_.get(), WGPUBufferBindingType_Uniform}}; render_pass_ = gpu_create_render_pass(ctx_.device, WGPUTextureFormat_RGBA8Unorm, particle_render_wgsl, render_bindings, 2); @@ -69,7 +67,7 @@ void Particles::render(WGPUCommandEncoder encoder, const UniformsSequenceParams& params, NodeRegistry& nodes) { // Update uniforms - uniforms_.update(ctx_.queue, params); + uniforms_buffer_.update(ctx_.queue, params); // Run compute pass (particle simulation) WGPUComputePassEncoder compute = diff --git a/src/effects/particles_effect.h b/src/effects/particles_effect.h index 38c60d7..e855b7b 100644 --- a/src/effects/particles_effect.h +++ b/src/effects/particles_effect.h @@ -30,5 +30,4 @@ class Particles : public Effect { ComputePass compute_pass_; RenderPass render_pass_; GpuBuffer particles_buffer_; - UniformBuffer uniforms_; }; diff --git a/src/effects/passthrough_effect.cc b/src/effects/passthrough_effect.cc index b9d9337..02f14da 100644 --- a/src/effects/passthrough_effect.cc +++ b/src/effects/passthrough_effect.cc @@ -10,26 +10,14 @@ Passthrough::Passthrough(const GpuContext& ctx, const std::vector& outputs, float start_time, float end_time) : Effect(ctx, inputs, outputs, start_time, end_time), pipeline_(nullptr), - bind_group_(nullptr), sampler_(nullptr) { - // Headless mode: skip GPU resource creation (compiled out in STRIP_ALL) + bind_group_(nullptr) { HEADLESS_RETURN_IF_NULL(ctx_.device); - // Init uniform buffer - uniforms_buffer_.init(ctx_.device); - // Create pipeline (simple version without effect params) + init_uniforms_buffer(); + create_linear_sampler(); + pipeline_ = create_post_process_pipeline_simple( ctx_.device, WGPUTextureFormat_RGBA8Unorm, passthrough_shader_wgsl); - - // Create sampler - WGPUSamplerDescriptor sampler_desc = {}; - sampler_desc.addressModeU = WGPUAddressMode_ClampToEdge; - sampler_desc.addressModeV = WGPUAddressMode_ClampToEdge; - sampler_desc.addressModeW = WGPUAddressMode_ClampToEdge; - sampler_desc.magFilter = WGPUFilterMode_Linear; - sampler_desc.minFilter = WGPUFilterMode_Linear; - sampler_desc.mipmapFilter = WGPUMipmapFilterMode_Nearest; - sampler_desc.maxAnisotropy = 1; - sampler_ = wgpuDeviceCreateSampler(ctx_.device, &sampler_desc); } void Passthrough::render(WGPUCommandEncoder encoder, diff --git a/src/effects/passthrough_effect.h b/src/effects/passthrough_effect.h index f684b9b..3813fa8 100644 --- a/src/effects/passthrough_effect.h +++ b/src/effects/passthrough_effect.h @@ -17,6 +17,4 @@ class Passthrough : public Effect { private: WGPURenderPipeline pipeline_; WGPUBindGroup bind_group_; - WGPUSampler sampler_; - UniformBuffer uniforms_buffer_; }; diff --git a/src/effects/peak_meter_effect.cc b/src/effects/peak_meter_effect.cc index d823e20..d077302 100644 --- a/src/effects/peak_meter_effect.cc +++ b/src/effects/peak_meter_effect.cc @@ -12,7 +12,7 @@ PeakMeter::PeakMeter(const GpuContext& ctx, : Effect(ctx, inputs, outputs, start_time, end_time), pipeline_(nullptr), bind_group_(nullptr) { HEADLESS_RETURN_IF_NULL(ctx_.device); - uniforms_buffer_.init(ctx_.device); + init_uniforms_buffer(); const char* shader_main = R"( struct VertexOutput { diff --git a/src/effects/peak_meter_effect.h b/src/effects/peak_meter_effect.h index e397a71..1786522 100644 --- a/src/effects/peak_meter_effect.h +++ b/src/effects/peak_meter_effect.h @@ -18,5 +18,4 @@ class PeakMeter : public Effect { private: WGPURenderPipeline pipeline_; WGPUBindGroup bind_group_; - UniformBuffer uniforms_buffer_; }; diff --git a/src/effects/placeholder_effect.cc b/src/effects/placeholder_effect.cc index 3367f1c..e024a6b 100644 --- a/src/effects/placeholder_effect.cc +++ b/src/effects/placeholder_effect.cc @@ -12,26 +12,16 @@ Placeholder::Placeholder(const GpuContext& ctx, float start_time, float end_time, const char* placeholder_name) : Effect(ctx, inputs, outputs, start_time, end_time), pipeline_(nullptr), - bind_group_(nullptr), sampler_(nullptr), name_(placeholder_name) { - // Log once on construction + bind_group_(nullptr), name_(placeholder_name) { fprintf(stderr, "TODO: %s not yet implemented, using passthrough\n", name_); - // Headless mode: skip GPU resource creation (compiled out in STRIP_ALL) HEADLESS_RETURN_IF_NULL(ctx_.device); - uniforms_buffer_.init(ctx_.device); + init_uniforms_buffer(); + create_linear_sampler(); + pipeline_ = create_post_process_pipeline( ctx_.device, WGPUTextureFormat_RGBA8Unorm, passthrough_shader_wgsl); - - WGPUSamplerDescriptor sampler_desc = {}; - sampler_desc.addressModeU = WGPUAddressMode_ClampToEdge; - sampler_desc.addressModeV = WGPUAddressMode_ClampToEdge; - sampler_desc.addressModeW = WGPUAddressMode_ClampToEdge; - sampler_desc.magFilter = WGPUFilterMode_Linear; - sampler_desc.minFilter = WGPUFilterMode_Linear; - sampler_desc.mipmapFilter = WGPUMipmapFilterMode_Nearest; - sampler_desc.maxAnisotropy = 1; - sampler_ = wgpuDeviceCreateSampler(ctx_.device, &sampler_desc); } void Placeholder::render(WGPUCommandEncoder encoder, diff --git a/src/effects/placeholder_effect.h b/src/effects/placeholder_effect.h index 24cf3f4..72b156f 100644 --- a/src/effects/placeholder_effect.h +++ b/src/effects/placeholder_effect.h @@ -18,7 +18,5 @@ class Placeholder : public Effect { private: WGPURenderPipeline pipeline_; WGPUBindGroup bind_group_; - WGPUSampler sampler_; - UniformBuffer uniforms_buffer_; const char* name_; }; -- cgit v1.2.3