gl: don't keep entire shaderpreset for final filter chain object
This commit is contained in:
parent
43ec5173c1
commit
2081e00956
7 changed files with 68 additions and 33 deletions
|
@ -9,5 +9,8 @@ edition = "2021"
|
|||
thiserror = "1.0.37"
|
||||
nom = "7.1.1"
|
||||
nom_locate = "4.0.0"
|
||||
"librashader-common" = { path = "../librashader-common" }
|
||||
librashader-common = { path = "../librashader-common" }
|
||||
num-traits = "0.2"
|
||||
|
||||
[features]
|
||||
parse_legacy_glsl = []
|
|
@ -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,
|
||||
|
|
|
@ -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>,
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue