Skip to content

[Feature] Default pipelines to opaque blending (blend: None) #102

@vmarcella

Description

@vmarcella

Overview

Pipelines always enable ALPHA_BLENDING, which adds costs on some GPUs when blending isn't needed. Most geometry is opaque and doesn't require blending, so the default should be blend: None (replace) with an opt-in with_blend(state) method for cases that need transparency.

Current State

RenderPipelineBuilder::build() hardcodes ALPHA_BLENDING for all color targets:

// crates/lambda-rs-platform/src/wgpu/pipeline.rs
let color_targets: Vec<Option<wgpu::ColorTargetState>> =
  match &self.color_target_format {
    Some(fmt) => vec![Some(wgpu::ColorTargetState {
      format: *fmt,
      blend: Some(wgpu::BlendState::ALPHA_BLENDING),
      write_mask: wgpu::ColorWrites::ALL,
    })],
    None => Vec::new(),
  };

This forces alpha blending overhead even for fully opaque geometry, which can hurt performance on tile-based GPUs (mobile, Apple Silicon) where blending requires additional memory bandwidth.

Scope

Goals:

  • Default to blend: None (opaque/replace mode) for better default performance
  • Expose with_blend(BlendState) method on RenderPipelineBuilder for opt-in blending
  • Maintain backwards compatibility for users who need alpha blending

Non-Goals:

  • Automatic blend state detection based on shader analysis
  • Per-attachment blend state configuration (future work)

Proposed API

// In crates/lambda-rs-platform/src/wgpu/pipeline.rs
pub enum BlendMode {
  /// No blending, replace destination (default).
  None,
  /// Standard alpha blending.
  AlphaBlending,
  /// Premultiplied alpha blending.
  PremultipliedAlpha,
  /// Additive blending.
  Additive,
  /// Custom blend state.
  Custom(wgpu::BlendState),
}

impl RenderPipelineBuilder<'a> {
  /// Set the blend mode for the color target. Defaults to `BlendMode::None`.
  pub fn with_blend(mut self, mode: BlendMode) -> Self {
    self.blend_mode = mode;
    return self;
  }
}

Example Usage:

let pipeline = RenderPipelineBuilder::new()
  .with_color_target(TextureFormat::Bgra8Unorm)
  .with_blend(BlendMode::AlphaBlending) // Opt-in for transparent geometry
  .build(&gpu, &vertex_shader, Some(&fragment_shader));

Acceptance Criteria

  • RenderPipelineBuilder defaults to blend: None
  • with_blend(BlendMode) method added to RenderPipelineBuilder
  • BlendMode enum provides common presets (None, AlphaBlending, PremultipliedAlpha, Additive)
  • BlendMode::Custom(wgpu::BlendState) variant for advanced use cases
  • Existing examples updated to use with_blend() where transparency is needed
  • Documentation updated with blending guidance
  • Unit test verifying default blend state is None

Affected Crates

lambda-rs-platform

Notes

  • This is a breaking change for users relying on implicit alpha blending; migration is straightforward (add .with_blend(BlendMode::AlphaBlending))
  • Future work: per-attachment blend states for MRT (Multiple Render Targets)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions