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"
nom = "7.1.1"
nom_locate = "4.0.0"
"librashader-common" = { path = "../librashader-common" }
num-traits = "0.2"
librashader-common = { path = "../librashader-common" }
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);
#[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<Value>) -> ShaderPreset {
}
ShaderPreset {
shader_count,
#[cfg(feature = "parse_legacy_glsl")]
feedback_pass,
shader_count,
shaders,
textures,
parameters,

View file

@ -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<ShaderPassConfig>,
/// Preset information for each texture.
pub textures: Vec<TextureConfig>,
/// Preset information for each user parameter.
pub parameters: Vec<ParameterConfig>,
}

View file

@ -37,7 +37,7 @@ pub struct FilterChain {
pub struct FilterCommon {
// semantics: ReflectSemantics,
pub(crate) preset: ShaderPreset,
pub(crate) config: FilterMutable,
pub(crate) luts: FxHashMap<usize, Texture>,
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<String, f32>
}
impl FilterChain {
fn load_pass_semantics(
uniform_semantics: &mut FxHashMap<String, UniformSemantic>,
@ -124,8 +129,8 @@ impl FilterChain {
}
}
type ShaderPassMeta<'a> = (
&'a ShaderPassConfig,
type ShaderPassMeta = (
ShaderPassConfig,
ShaderSource,
CompilerBackend<
impl CompileShader<GLSL, Options = GlVersion, Context = GlslangGlslContext> + 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<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))
.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<ShaderPassConfig>,
textures: &[TextureConfig]
) -> Result<(Vec<ShaderPassMeta>, ReflectSemantics)> {
let mut uniform_semantics: FxHashMap<String, UniformSemantic> = Default::default();
let mut texture_semantics: FxHashMap<String, SemanticMap<TextureSemantics>> =
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::<Result<Vec<(&ShaderPassConfig, ShaderSource, CompilerBackend<_>)>>>()?;
.collect::<Result<Vec<(ShaderPassConfig, ShaderSource, CompilerBackend<_>)>>>()?;
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];

View file

@ -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)
}

View file

@ -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);
}

View file

@ -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<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())
}
}