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"
|
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 = []
|
|
@ -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,
|
||||||
|
|
|
@ -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>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue