Skip to content

[Feature] WGSL Shader Support with Hot-Reload #79

@vmarcella

Description

@vmarcella

Overview

Extend the shader compilation pipeline to support WGSL alongside GLSL by adding a shader language field to VirtualShader

Current State

VirtualShader currently assumes GLSL and compiles to SPIR-V:

// crates/lambda-rs-platform/src/shader/types.rs
pub enum VirtualShader {
  File {
    path: String,
    kind: ShaderKind,
    name: String,
    entry_point: String,
  },
  Source {
    source: String,
    kind: ShaderKind,
    name: String,
    entry_point: String,
  },

There is no way to specify the shader language. WGSL is wgpu's native shader language and can be passed directly without SPIR-V conversion.

Proposed Design

Add ShaderLanguage enum:

// crates/lambda-rs-platform/src/shader/types.rs

/// Shader source language.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum ShaderLanguage {
  /// GLSL source, compiled to SPIR-V via naga or shaderc.
  #[default]
  Glsl,
  /// WGSL source, passed directly to wgpu.
  Wgsl,
  /// Pre-compiled SPIR-V binary.
  SpirV,
}

Extend VritualShader variants with a language field:

pub enum VirtualShader {
  File {
    path: String,
    kind: ShaderKind,
    name: String,
    entry_point: String,
    language: ShaderLanguage,  // NEW
  },
  Source {
    source: String,
    kind: ShaderKind,
    name: String,
    entry_point: String,
    language: ShaderLanguage,  // NEW
  },
}

Update ShaderCompiler to compile based on language:

impl ShaderCompiler {
  pub fn compile(&self, shader: &VirtualShader) -> CompiledShader {
    match shader.language() {
      ShaderLanguage::Glsl => self.compile_glsl_to_spirv(shader),
      ShaderLanguage::Wgsl => self.pass_through_wgsl(shader),
      ShaderLanguage::SpirV => self.load_spirv_binary(shader),
    }
  }
}

Add new builder methods in ShaderBuilder:

// crates/lambda-rs/src/render/shader.rs
impl ShaderBuilder {
  /// Build from a GLSL file (default behavior, backward compatible).
  pub fn from_glsl_file(path: &str, kind: ShaderKind) -> VirtualShader;
  
  /// Build from a WGSL file.
  pub fn from_wgsl_file(path: &str, kind: ShaderKind) -> VirtualShader;
  
  /// Build from inline WGSL source.
  pub fn from_wgsl_source(source: &str, kind: ShaderKind) -> VirtualShader;
}

Hot-reload

  • Implement file timestamp watching for shader source files
  • Queue pipeline recreation on the next frame when a shader file changes
  • Provide safe pipeline swap that does not interrupt in-flight rendering
  • Gate behind a Cargo feature shader-hot-reloading (or something similarly named)

Acceptance criteria

  • ShaderLanguage enum with Glsl, Wgsl, and SpirV variants
  • language field added to VirtualShader::File and VirtualShader::Source
  • ShaderCompiler dispatches compilation based on language
  • WGSL sources passed directly to wgpu without SPIR-V conversion
  • Convenience builder methods for GLSL and WGSL in lambda-rs
  • Backward compatibility maintained (GLSL default)
  • File watcher detects shader modifications (timestamp-based)
  • Safe pipeline swap on next frame without render interruption
  • shader-hot-reload feature flag documented in features.md
  • Example demonstrating WGSL shader usage
  • Example or documentation for hot-reload workflow

Notes

  • Hot-reload SHOULD be disabled by default in release builds
  • Consider using notify crate or simple timestamp polling for file watching
  • Pipeline recreation errors SHOULD be logged but not crash the application
  • ShaderKind remains unchanged (Vertex, Fragment, Compute)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions