diff --git a/librashader-presets/Cargo.toml b/librashader-presets/Cargo.toml index e426ce3..05a2de3 100644 --- a/librashader-presets/Cargo.toml +++ b/librashader-presets/Cargo.toml @@ -9,5 +9,8 @@ edition = "2021" thiserror = "1.0.37" nom = "7.1.1" nom_locate = "4.0.0" -"librashader-common" = { path = "../librashader-common" } -num-traits = "0.2" \ No newline at end of file +librashader-common = { path = "../librashader-common" } +num-traits = "0.2" + +[features] +parse_legacy_glsl = [] \ No newline at end of file diff --git a/librashader-presets/src/parse/preset.rs b/librashader-presets/src/parse/preset.rs index da31823..a632927 100644 --- a/librashader-presets/src/parse/preset.rs +++ b/librashader-presets/src/parse/preset.rs @@ -48,6 +48,7 @@ pub fn resolve_values(mut values: Vec) -> ShaderPreset { }) .unwrap_or(0); + #[cfg(feature = "parse_legacy_glsl")] let feedback_pass = remove_if(&mut values, |v| matches!(*v, Value::FeedbackPass(_))) .map(|value| { if let Value::FeedbackPass(pass) = value { @@ -179,8 +180,9 @@ pub fn resolve_values(mut values: Vec) -> ShaderPreset { } ShaderPreset { - shader_count, + #[cfg(feature = "parse_legacy_glsl")] feedback_pass, + shader_count, shaders, textures, parameters, diff --git a/librashader-presets/src/preset.rs b/librashader-presets/src/preset.rs index 61f35a7..b3d2261 100644 --- a/librashader-presets/src/preset.rs +++ b/librashader-presets/src/preset.rs @@ -113,10 +113,20 @@ pub struct ParameterConfig { #[derive(Debug, Clone)] pub struct ShaderPreset { - pub shader_count: i32, + /// Used in legacy GLSL shader semantics. If < 0, no feedback pass is used. + /// Otherwise, the FBO after pass #N is passed a texture to next frame + #[cfg(feature = "parse_legacy_glsl")] pub feedback_pass: i32, + + /// The number of shaders enabled in the filter chain. + pub shader_count: i32, // Everything is in Vecs because the expect number of values is well below 64. + /// Preset information for each shader. pub shaders: Vec, + + /// Preset information for each texture. pub textures: Vec, + + /// Preset information for each user parameter. pub parameters: Vec, } diff --git a/librashader-runtime-gl/src/filter_chain.rs b/librashader-runtime-gl/src/filter_chain.rs index 2bc56fe..1fec799 100644 --- a/librashader-runtime-gl/src/filter_chain.rs +++ b/librashader-runtime-gl/src/filter_chain.rs @@ -37,7 +37,7 @@ pub struct FilterChain { pub struct FilterCommon { // semantics: ReflectSemantics, - pub(crate) preset: ShaderPreset, + pub(crate) config: FilterMutable, pub(crate) luts: FxHashMap, pub(crate) samplers: SamplerSet, pub output_textures: Box<[Texture]>, @@ -46,6 +46,11 @@ pub struct FilterCommon { pub(crate) draw_quad: DrawQuad, } +pub struct FilterMutable { + pub(crate) passes_enabled: usize, + pub(crate) parameters: FxHashMap +} + impl FilterChain { fn load_pass_semantics( uniform_semantics: &mut FxHashMap, @@ -124,8 +129,8 @@ impl FilterChain { } } -type ShaderPassMeta<'a> = ( - &'a ShaderPassConfig, +type ShaderPassMeta = ( + ShaderPassConfig, ShaderSource, CompilerBackend< impl CompileShader + ReflectShader, @@ -135,7 +140,7 @@ type ShaderPassMeta<'a> = ( impl FilterChain { /// Load a filter chain from a pre-parsed `ShaderPreset`. pub fn load_from_preset(preset: ShaderPreset, options: Option<&FilterChainOptions>) -> Result { - let (passes, semantics) = FilterChain::load_preset(&preset)?; + let (passes, semantics) = FilterChain::load_preset(preset.shaders, &preset.textures)?; let version = options.map(|o| gl_u16_to_version(o.gl_version)) .unwrap_or_else(|| gl_get_version()); @@ -184,9 +189,11 @@ impl FilterChain { history_framebuffers, filter_vao, common: FilterCommon { - // we don't need the reflect semantics once all locations have been bound per pass. - // semantics, - preset, + config: FilterMutable { + passes_enabled: preset.shader_count as usize, + parameters: preset.parameters.into_iter() + .map(|param| (param.name, param.value)).collect(), + }, luts, samplers, output_textures: output_textures.into_boxed_slice(), @@ -205,15 +212,15 @@ impl FilterChain { } fn load_preset( - preset: &ShaderPreset, + passes: Vec, + textures: &[TextureConfig] ) -> Result<(Vec, ReflectSemantics)> { let mut uniform_semantics: FxHashMap = Default::default(); let mut texture_semantics: FxHashMap> = Default::default(); - let passes = preset - .shaders - .iter() + let passes = passes + .into_iter() .map(|shader| { eprintln!("[gl] loading {}", &shader.name.display()); let source: ShaderSource = ShaderSource::load(&shader.name)?; @@ -233,18 +240,18 @@ impl FilterChain { Ok::<_, FilterChainError>((shader, source, reflect)) }) .into_iter() - .collect::)>>>()?; + .collect::)>>>()?; for details in &passes { FilterChain::load_pass_semantics( &mut uniform_semantics, &mut texture_semantics, - details.0, + &details.0, ) } // add lut params - for (index, texture) in preset.textures.iter().enumerate() { + for (index, texture) in textures.iter().enumerate() { texture_semantics.insert( texture.name.clone(), SemanticMap { @@ -495,7 +502,7 @@ impl FilterChain { push_buffer, uniform_bindings, source, - config: config.clone(), + config }); } @@ -572,6 +579,8 @@ impl FilterChain { /// /// When this frame returns, GL_FRAMEBUFFER is bound to 0. pub fn frame(&mut self, count: usize, viewport: &Viewport, input: &GlImage, options: Option<&FrameOptions>) -> Result<()> { + // limit number of passes to those enabled. + let passes = &mut self.passes[0..self.common.config.passes_enabled]; if let Some(options) = options { if options.clear_history { for framebuffer in &self.history_framebuffers { @@ -580,7 +589,7 @@ impl FilterChain { } } - if self.passes.is_empty() { + if passes.is_empty() { return Ok(()); } @@ -590,8 +599,8 @@ impl FilterChain { gl::BindVertexArray(self.filter_vao); } - let filter = self.passes[0].config.filter; - let wrap_mode = self.passes[0].config.wrap_mode; + let filter = passes[0].config.filter; + let wrap_mode = passes[0].config.wrap_mode; // update history for (texture, fbo) in self @@ -608,7 +617,7 @@ impl FilterChain { .feedback_textures .iter_mut() .zip(self.feedback_framebuffers.iter()) - .zip(self.passes.iter()) + .zip(passes.iter()) { texture.image = fbo .as_texture(pass.config.filter, pass.config.wrap_mode) @@ -626,7 +635,7 @@ impl FilterChain { let mut source = original; // rescale render buffers to ensure all bindings are valid. - for (index, pass) in self.passes.iter_mut().enumerate() { + for (index, pass) in passes.iter_mut().enumerate() { self.output_framebuffers[index].scale( pass.config.scaling.clone(), pass.get_format(), @@ -644,8 +653,8 @@ impl FilterChain { )?; } - let passes_len = self.passes.len(); - let (pass, last) = self.passes.split_at_mut(passes_len - 1); + let passes_len = passes.len(); + let (pass, last) = passes.split_at_mut(passes_len - 1); for (index, pass) in pass.iter_mut().enumerate() { let target = &self.output_framebuffers[index]; diff --git a/librashader-runtime-gl/src/filter_pass.rs b/librashader-runtime-gl/src/filter_pass.rs index d67043c..40dd89f 100644 --- a/librashader-runtime-gl/src/filter_pass.rs +++ b/librashader-runtime-gl/src/filter_pass.rs @@ -506,13 +506,11 @@ impl FilterPass { .map(|f| f.initial) .unwrap_or(0f32); - let value = parent - .preset + let value = *parent + .config .parameters - .iter() - .find(|&p| p.name == id) - .map(|p| p.value) - .unwrap_or(default); + .get(id) + .unwrap_or(&default); FilterPass::build_float(location.location(), &mut buffer[offset..][..4], value) } diff --git a/librashader-runtime-gl/src/lib.rs b/librashader-runtime-gl/src/lib.rs index 669e0f7..fdfa43e 100644 --- a/librashader-runtime-gl/src/lib.rs +++ b/librashader-runtime-gl/src/lib.rs @@ -31,7 +31,7 @@ mod tests { fn triangle_gl() { let (glfw, window, events, shader, vao) = hello_triangle::setup(); let mut filter = - FilterChain::load_from_path("../test/slang-shaders/crt/crt-royale.slangp", None) + FilterChain::load_from_path("../test/slang-shaders/vhs/VHSPro.slangp", None) .unwrap(); hello_triangle::do_loop(glfw, window, events, shader, vao, &mut filter); } diff --git a/librashader/src/lib.rs b/librashader/src/lib.rs index 74a6665..e155258 100644 --- a/librashader/src/lib.rs +++ b/librashader/src/lib.rs @@ -67,3 +67,16 @@ pub use librashader_common::{ WrapMode }; +pub mod util { + use librashader_preprocess::{PreprocessError, ShaderParameter, ShaderSource}; + use librashader_presets::ShaderPreset; + + pub fn get_parameter_meta(preset: &ShaderPreset) -> Result, PreprocessError> { + let iters: Result>, PreprocessError> = preset.shaders.iter() + .map(|s| ShaderSource::load(&s.name).map(|s| s.parameters)) + .into_iter() + .collect(); + let iters = iters?; + Ok(iters.into_iter().flatten()) + } +}