gl: don't keep entire shaderpreset for final filter chain object

This commit is contained in:
chyyran 2022-11-28 01:16:09 -05:00
parent 43ec5173c1
commit 2081e00956
7 changed files with 68 additions and 33 deletions

View file

@ -9,5 +9,8 @@ edition = "2021"
thiserror = "1.0.37" thiserror = "1.0.37"
nom = "7.1.1" nom = "7.1.1"
nom_locate = "4.0.0" nom_locate = "4.0.0"
"librashader-common" = { path = "../librashader-common" } librashader-common = { path = "../librashader-common" }
num-traits = "0.2" num-traits = "0.2"
[features]
parse_legacy_glsl = []

View file

@ -48,6 +48,7 @@ pub fn resolve_values(mut values: Vec<Value>) -> ShaderPreset {
}) })
.unwrap_or(0); .unwrap_or(0);
#[cfg(feature = "parse_legacy_glsl")]
let feedback_pass = remove_if(&mut values, |v| matches!(*v, Value::FeedbackPass(_))) let feedback_pass = remove_if(&mut values, |v| matches!(*v, Value::FeedbackPass(_)))
.map(|value| { .map(|value| {
if let Value::FeedbackPass(pass) = value { if let Value::FeedbackPass(pass) = value {
@ -179,8 +180,9 @@ pub fn resolve_values(mut values: Vec<Value>) -> ShaderPreset {
} }
ShaderPreset { ShaderPreset {
shader_count, #[cfg(feature = "parse_legacy_glsl")]
feedback_pass, feedback_pass,
shader_count,
shaders, shaders,
textures, textures,
parameters, parameters,

View file

@ -113,10 +113,20 @@ pub struct ParameterConfig {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct ShaderPreset { 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, 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. // Everything is in Vecs because the expect number of values is well below 64.
/// Preset information for each shader.
pub shaders: Vec<ShaderPassConfig>, pub shaders: Vec<ShaderPassConfig>,
/// Preset information for each texture.
pub textures: Vec<TextureConfig>, pub textures: Vec<TextureConfig>,
/// Preset information for each user parameter.
pub parameters: Vec<ParameterConfig>, pub parameters: Vec<ParameterConfig>,
} }

View file

@ -37,7 +37,7 @@ pub struct FilterChain {
pub struct FilterCommon { pub struct FilterCommon {
// semantics: ReflectSemantics, // semantics: ReflectSemantics,
pub(crate) preset: ShaderPreset, pub(crate) config: FilterMutable,
pub(crate) luts: FxHashMap<usize, Texture>, pub(crate) luts: FxHashMap<usize, Texture>,
pub(crate) samplers: SamplerSet, pub(crate) samplers: SamplerSet,
pub output_textures: Box<[Texture]>, pub output_textures: Box<[Texture]>,
@ -46,6 +46,11 @@ pub struct FilterCommon {
pub(crate) draw_quad: DrawQuad, pub(crate) draw_quad: DrawQuad,
} }
pub struct FilterMutable {
pub(crate) passes_enabled: usize,
pub(crate) parameters: FxHashMap<String, f32>
}
impl FilterChain { impl FilterChain {
fn load_pass_semantics( fn load_pass_semantics(
uniform_semantics: &mut FxHashMap<String, UniformSemantic>, uniform_semantics: &mut FxHashMap<String, UniformSemantic>,
@ -124,8 +129,8 @@ impl FilterChain {
} }
} }
type ShaderPassMeta<'a> = ( type ShaderPassMeta = (
&'a ShaderPassConfig, ShaderPassConfig,
ShaderSource, ShaderSource,
CompilerBackend< CompilerBackend<
impl CompileShader<GLSL, Options = GlVersion, Context = GlslangGlslContext> + ReflectShader, impl CompileShader<GLSL, Options = GlVersion, Context = GlslangGlslContext> + ReflectShader,
@ -135,7 +140,7 @@ type ShaderPassMeta<'a> = (
impl FilterChain { impl FilterChain {
/// Load a filter chain from a pre-parsed `ShaderPreset`. /// Load a filter chain from a pre-parsed `ShaderPreset`.
pub fn load_from_preset(preset: ShaderPreset, options: Option<&FilterChainOptions>) -> Result<FilterChain> { pub fn load_from_preset(preset: ShaderPreset, options: Option<&FilterChainOptions>) -> Result<FilterChain> {
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)) let version = options.map(|o| gl_u16_to_version(o.gl_version))
.unwrap_or_else(|| gl_get_version()); .unwrap_or_else(|| gl_get_version());
@ -184,9 +189,11 @@ impl FilterChain {
history_framebuffers, history_framebuffers,
filter_vao, filter_vao,
common: FilterCommon { common: FilterCommon {
// we don't need the reflect semantics once all locations have been bound per pass. config: FilterMutable {
// semantics, passes_enabled: preset.shader_count as usize,
preset, parameters: preset.parameters.into_iter()
.map(|param| (param.name, param.value)).collect(),
},
luts, luts,
samplers, samplers,
output_textures: output_textures.into_boxed_slice(), output_textures: output_textures.into_boxed_slice(),
@ -205,15 +212,15 @@ impl FilterChain {
} }
fn load_preset( fn load_preset(
preset: &ShaderPreset, passes: Vec<ShaderPassConfig>,
textures: &[TextureConfig]
) -> Result<(Vec<ShaderPassMeta>, ReflectSemantics)> { ) -> Result<(Vec<ShaderPassMeta>, ReflectSemantics)> {
let mut uniform_semantics: FxHashMap<String, UniformSemantic> = Default::default(); let mut uniform_semantics: FxHashMap<String, UniformSemantic> = Default::default();
let mut texture_semantics: FxHashMap<String, SemanticMap<TextureSemantics>> = let mut texture_semantics: FxHashMap<String, SemanticMap<TextureSemantics>> =
Default::default(); Default::default();
let passes = preset let passes = passes
.shaders .into_iter()
.iter()
.map(|shader| { .map(|shader| {
eprintln!("[gl] loading {}", &shader.name.display()); eprintln!("[gl] loading {}", &shader.name.display());
let source: ShaderSource = ShaderSource::load(&shader.name)?; let source: ShaderSource = ShaderSource::load(&shader.name)?;
@ -233,18 +240,18 @@ impl FilterChain {
Ok::<_, FilterChainError>((shader, source, reflect)) Ok::<_, FilterChainError>((shader, source, reflect))
}) })
.into_iter() .into_iter()
.collect::<Result<Vec<(&ShaderPassConfig, ShaderSource, CompilerBackend<_>)>>>()?; .collect::<Result<Vec<(ShaderPassConfig, ShaderSource, CompilerBackend<_>)>>>()?;
for details in &passes { for details in &passes {
FilterChain::load_pass_semantics( FilterChain::load_pass_semantics(
&mut uniform_semantics, &mut uniform_semantics,
&mut texture_semantics, &mut texture_semantics,
details.0, &details.0,
) )
} }
// add lut params // add lut params
for (index, texture) in preset.textures.iter().enumerate() { for (index, texture) in textures.iter().enumerate() {
texture_semantics.insert( texture_semantics.insert(
texture.name.clone(), texture.name.clone(),
SemanticMap { SemanticMap {
@ -495,7 +502,7 @@ impl FilterChain {
push_buffer, push_buffer,
uniform_bindings, uniform_bindings,
source, source,
config: config.clone(), config
}); });
} }
@ -572,6 +579,8 @@ impl FilterChain {
/// ///
/// When this frame returns, GL_FRAMEBUFFER is bound to 0. /// 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<()> { 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 let Some(options) = options {
if options.clear_history { if options.clear_history {
for framebuffer in &self.history_framebuffers { for framebuffer in &self.history_framebuffers {
@ -580,7 +589,7 @@ impl FilterChain {
} }
} }
if self.passes.is_empty() { if passes.is_empty() {
return Ok(()); return Ok(());
} }
@ -590,8 +599,8 @@ impl FilterChain {
gl::BindVertexArray(self.filter_vao); gl::BindVertexArray(self.filter_vao);
} }
let filter = self.passes[0].config.filter; let filter = passes[0].config.filter;
let wrap_mode = self.passes[0].config.wrap_mode; let wrap_mode = passes[0].config.wrap_mode;
// update history // update history
for (texture, fbo) in self for (texture, fbo) in self
@ -608,7 +617,7 @@ impl FilterChain {
.feedback_textures .feedback_textures
.iter_mut() .iter_mut()
.zip(self.feedback_framebuffers.iter()) .zip(self.feedback_framebuffers.iter())
.zip(self.passes.iter()) .zip(passes.iter())
{ {
texture.image = fbo texture.image = fbo
.as_texture(pass.config.filter, pass.config.wrap_mode) .as_texture(pass.config.filter, pass.config.wrap_mode)
@ -626,7 +635,7 @@ impl FilterChain {
let mut source = original; let mut source = original;
// rescale render buffers to ensure all bindings are valid. // 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( self.output_framebuffers[index].scale(
pass.config.scaling.clone(), pass.config.scaling.clone(),
pass.get_format(), pass.get_format(),
@ -644,8 +653,8 @@ impl FilterChain {
)?; )?;
} }
let passes_len = self.passes.len(); let passes_len = passes.len();
let (pass, last) = self.passes.split_at_mut(passes_len - 1); let (pass, last) = passes.split_at_mut(passes_len - 1);
for (index, pass) in pass.iter_mut().enumerate() { for (index, pass) in pass.iter_mut().enumerate() {
let target = &self.output_framebuffers[index]; let target = &self.output_framebuffers[index];

View file

@ -506,13 +506,11 @@ impl FilterPass {
.map(|f| f.initial) .map(|f| f.initial)
.unwrap_or(0f32); .unwrap_or(0f32);
let value = parent let value = *parent
.preset .config
.parameters .parameters
.iter() .get(id)
.find(|&p| p.name == id) .unwrap_or(&default);
.map(|p| p.value)
.unwrap_or(default);
FilterPass::build_float(location.location(), &mut buffer[offset..][..4], value) FilterPass::build_float(location.location(), &mut buffer[offset..][..4], value)
} }

View file

@ -31,7 +31,7 @@ mod tests {
fn triangle_gl() { fn triangle_gl() {
let (glfw, window, events, shader, vao) = hello_triangle::setup(); let (glfw, window, events, shader, vao) = hello_triangle::setup();
let mut filter = 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(); .unwrap();
hello_triangle::do_loop(glfw, window, events, shader, vao, &mut filter); hello_triangle::do_loop(glfw, window, events, shader, vao, &mut filter);
} }

View file

@ -67,3 +67,16 @@ pub use librashader_common::{
WrapMode WrapMode
}; };
pub mod util {
use librashader_preprocess::{PreprocessError, ShaderParameter, ShaderSource};
use librashader_presets::ShaderPreset;
pub fn get_parameter_meta(preset: &ShaderPreset) -> Result<impl Iterator<Item = ShaderParameter>, PreprocessError> {
let iters: Result<Vec<Vec<ShaderParameter>>, 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())
}
}