Skip to main content

par_term_render/custom_shader_renderer/
hot_reload.rs

1//! Hot-reload watcher callbacks for custom shader renderer.
2//!
3//! Provides the ability to reload a shader from a new GLSL source string at
4//! runtime without recreating the full renderer.  This is called by the
5//! file-watcher when the shader file on disk changes.
6
7use anyhow::{Context, Result};
8use wgpu::*;
9
10use super::CustomShaderRenderer;
11use super::pipeline::create_render_pipeline;
12use super::transpiler::transpile_glsl_to_wgsl_source;
13
14impl CustomShaderRenderer {
15    /// Reload the shader from a GLSL source string.
16    ///
17    /// Transpiles the provided GLSL source to WGSL, validates it, and
18    /// recreates the render pipeline.  The uniform buffer and all textures
19    /// remain intact; only the pipeline is replaced.
20    ///
21    /// # Arguments
22    /// * `device` - The wgpu device
23    /// * `source` - GLSL shader source code
24    /// * `name`   - Shader name used for diagnostic messages and WGSL debug output
25    pub fn reload_from_source(&mut self, device: &Device, source: &str, name: &str) -> Result<()> {
26        let wgsl_source = transpile_glsl_to_wgsl_source(source, name)?;
27
28        log::info!(
29            "Reloading custom shader from source ({} bytes GLSL -> {} bytes WGSL)",
30            source.len(),
31            wgsl_source.len()
32        );
33        log::debug!("Generated WGSL:\n{}", wgsl_source);
34
35        // Pre-validate WGSL
36        let module = naga::front::wgsl::parse_str(&wgsl_source)
37            .context("Custom shader WGSL parse failed")?;
38        let _info = naga::valid::Validator::new(
39            naga::valid::ValidationFlags::all(),
40            naga::valid::Capabilities::empty(),
41        )
42        .validate(&module)
43        .context("Custom shader WGSL validation failed")?;
44
45        let shader_module = device.create_shader_module(ShaderModuleDescriptor {
46            label: Some("Custom Shader Module (reloaded)"),
47            source: ShaderSource::Wgsl(wgsl_source.into()),
48        });
49
50        self.pipeline = create_render_pipeline(
51            device,
52            &shader_module,
53            &self.bind_group_layout,
54            self.surface_format,
55            Some("Custom Shader Pipeline (reloaded)"),
56        );
57
58        self.start_time = std::time::Instant::now();
59
60        log::info!("Custom shader reloaded successfully from source");
61        Ok(())
62    }
63}