gl: clean up visibility in some APIs

This commit is contained in:
chyyran 2022-11-21 02:56:03 -05:00
parent df03fdc5eb
commit 4124ae3955
7 changed files with 123 additions and 117 deletions

View file

@ -1,15 +1,15 @@
use std::collections::VecDeque; use std::collections::VecDeque;
use crate::binding::{UniformBinding, UniformLocation, VariableLocation}; use crate::binding::{UniformBinding, UniformLocation, VariableLocation};
use crate::filter_pass::FilterPass; use crate::filter_pass::FilterPass;
use crate::framebuffer::Framebuffer; use crate::framebuffer::{Framebuffer, GlImage, Size, Viewport};
use crate::render_target::RenderTarget; use crate::render_target::RenderTarget;
use crate::util; use crate::util;
use crate::util::{GlImage, InlineRingBuffer, Size, Texture, Viewport}; use crate::util::{InlineRingBuffer, Texture};
use gl::types::{GLenum, GLint, GLsizei, GLsizeiptr, GLuint}; use gl::types::{GLenum, GLint, GLsizei, GLsizeiptr, GLuint};
use librashader::image::Image; use librashader::image::Image;
use librashader::{FilterMode, ShaderSource, WrapMode}; use librashader::{FilterMode, ShaderSource, WrapMode};
use librashader_presets::{ScaleType, ShaderPassConfig, ShaderPreset, TextureConfig}; use librashader_presets::{ScaleType, ShaderPassConfig, ShaderPreset, TextureConfig};
use librashader_reflect::back::cross::{GlVersion, GlslangGlslContext}; use librashader_reflect::back::cross::{GlslangGlslContext, GlVersion};
use librashader_reflect::back::targets::{CompilerBackend, FromCompilation, GLSL}; use librashader_reflect::back::targets::{CompilerBackend, FromCompilation, GLSL};
use librashader_reflect::back::CompileShader; use librashader_reflect::back::CompileShader;
use librashader_reflect::reflect::semantics::{ use librashader_reflect::reflect::semantics::{
@ -131,6 +131,68 @@ type ShaderPassMeta<'a> = (
); );
impl FilterChain { impl FilterChain {
/// Load a filter chain from a pre-parsed `ShaderPreset`.
pub fn load_from_preset(preset: ShaderPreset) -> Result<FilterChain, Box<dyn Error>> {
let (passes, semantics) = FilterChain::load_preset(&preset);
// initialize passes
let filters = FilterChain::init_passes(passes, &semantics)?;
let default_filter = filters.first().map(|f| f.config.filter).unwrap_or_default();
let default_wrap = filters.first().map(|f| f.config.wrap_mode).unwrap_or_default();
// initialize output framebuffers
let mut output_framebuffers = Vec::new();
output_framebuffers.resize_with(filters.len(), || Framebuffer::new(1));
let mut output_textures = Vec::new();
output_textures.resize_with(filters.len(), Texture::default);
// initialize feedback framebuffers
let mut feedback_framebuffers = Vec::new();
feedback_framebuffers.resize_with(filters.len(), || Framebuffer::new(1));
let mut feedback_textures = Vec::new();
feedback_textures.resize_with(filters.len(), Texture::default);
// load luts
let luts = FilterChain::load_luts(&preset.textures)?;
let (history_framebuffers, history_textures) =
FilterChain::init_history(&filters, default_filter, default_wrap);
// create VBO objects
let draw_quad = DrawQuad::new();
let mut filter_vao = 0;
unsafe {
gl::GenVertexArrays(1, &mut filter_vao);
}
Ok(FilterChain {
passes: filters,
output_framebuffers: output_framebuffers.into_boxed_slice(),
feedback_framebuffers: feedback_framebuffers.into_boxed_slice(),
history_framebuffers,
filter_vao,
common: FilterCommon {
semantics,
preset,
luts,
output_textures: output_textures.into_boxed_slice(),
feedback_textures: feedback_textures.into_boxed_slice(),
history_textures,
draw_quad,
},
})
}
/// Load the shader preset at the given path into a filter chain.
pub fn load_from_path(path: impl AsRef<Path>) -> Result<FilterChain, Box<dyn Error>> {
// load passes from preset
let preset = ShaderPreset::try_parse(path)?;
Self::load_from_preset(preset)
}
fn load_preset(preset: &ShaderPreset) -> (Vec<ShaderPassMeta>, ReflectSemantics) { fn load_preset(preset: &ShaderPreset) -> (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>> =
@ -300,7 +362,7 @@ impl FilterChain {
Ok(luts) Ok(luts)
} }
pub fn init_passes( fn init_passes(
passes: Vec<ShaderPassMeta>, passes: Vec<ShaderPassMeta>,
semantics: &ReflectSemantics, semantics: &ReflectSemantics,
) -> Result<Box<[FilterPass]>, Box<dyn Error>> { ) -> Result<Box<[FilterPass]>, Box<dyn Error>> {
@ -467,7 +529,7 @@ impl FilterChain {
Ok(filters.into_boxed_slice()) Ok(filters.into_boxed_slice())
} }
pub fn init_history(filters: &[FilterPass], filter: FilterMode, wrap_mode: WrapMode) -> (VecDeque<Framebuffer>, Box<[Texture]>) { fn init_history(filters: &[FilterPass], filter: FilterMode, wrap_mode: WrapMode) -> (VecDeque<Framebuffer>, Box<[Texture]>) {
let mut required_images = 0; let mut required_images = 0;
for pass in filters { for pass in filters {
@ -514,68 +576,7 @@ impl FilterChain {
(framebuffers, history_textures.into_boxed_slice()) (framebuffers, history_textures.into_boxed_slice())
} }
pub fn load(path: impl AsRef<Path>) -> Result<FilterChain, Box<dyn Error>> { fn push_history(&mut self, input: &GlImage) {
// load passes from preset
let preset = ShaderPreset::try_parse(path)?;
let (passes, semantics) = FilterChain::load_preset(&preset);
// initialize passes
let filters = FilterChain::init_passes(passes, &semantics)?;
let default_filter = filters.first().map(|f| f.config.filter).unwrap_or_default();
let default_wrap = filters.first().map(|f| f.config.wrap_mode).unwrap_or_default();
// initialize output framebuffers
let mut output_framebuffers = Vec::new();
output_framebuffers.resize_with(filters.len(), || Framebuffer::new(1));
let mut output_textures = Vec::new();
output_textures.resize_with(filters.len(), Texture::default);
// initialize feedback framebuffers
let mut feedback_framebuffers = Vec::new();
feedback_framebuffers.resize_with(filters.len(), || Framebuffer::new(1));
let mut feedback_textures = Vec::new();
feedback_textures.resize_with(filters.len(), Texture::default);
// load luts
let luts = FilterChain::load_luts(&preset.textures)?;
let (history_framebuffers, history_textures) =
FilterChain::init_history(&filters, default_filter, default_wrap);
// create VBO objects
let draw_quad = DrawQuad::new();
let mut filter_vao = 0;
unsafe {
gl::GenVertexArrays(1, &mut filter_vao);
}
Ok(FilterChain {
passes: filters,
output_framebuffers: output_framebuffers.into_boxed_slice(),
feedback_framebuffers: feedback_framebuffers.into_boxed_slice(),
history_framebuffers,
filter_vao,
common: FilterCommon {
semantics,
preset,
luts,
output_textures: output_textures.into_boxed_slice(),
feedback_textures: feedback_textures.into_boxed_slice(),
history_textures,
draw_quad,
},
})
}
pub(crate) fn get_output_texture(&self, index: usize) -> Texture {
let config = &self.passes[index].config;
self.output_framebuffers[index].as_texture(config.filter, config.wrap_mode)
}
pub fn push_history(&mut self, input: &GlImage) {
if let Some(mut back) = self.history_framebuffers.pop_back() { if let Some(mut back) = self.history_framebuffers.pop_back() {
if back.size != input.size if back.size != input.size
@ -584,9 +585,7 @@ impl FilterChain {
back.init(input.size, input.format); back.init(input.size, input.format);
} }
if back.is_initialized() { back.copy_from(&input);
back.copy_from(&input);
}
self.history_framebuffers.push_front(back) self.history_framebuffers.push_front(back)
} }

View file

@ -12,8 +12,9 @@ use rustc_hash::FxHashMap;
use crate::binding::{UniformBinding, UniformLocation, VariableLocation}; use crate::binding::{UniformBinding, UniformLocation, VariableLocation};
use crate::filter_chain::FilterCommon; use crate::filter_chain::FilterCommon;
use crate::framebuffer::{Size, Viewport};
use crate::render_target::RenderTarget; use crate::render_target::RenderTarget;
use crate::util::{InlineRingBuffer, RingBuffer, Size, Texture, Viewport}; use crate::util::{InlineRingBuffer, RingBuffer, Texture};
pub struct FilterPass { pub struct FilterPass {
pub reflection: ShaderReflection, pub reflection: ShaderReflection,

View file

@ -1,5 +1,5 @@
use crate::util; use crate::util;
use crate::util::{GlImage, Size, Texture, Viewport}; use crate::util::Texture;
use gl::types::{GLenum, GLint, GLsizei, GLuint}; use gl::types::{GLenum, GLint, GLsizei, GLuint};
use librashader::{FilterMode, ShaderFormat, WrapMode}; use librashader::{FilterMode, ShaderFormat, WrapMode};
use librashader_presets::{Scale2D, ScaleType, Scaling}; use librashader_presets::{Scale2D, ScaleType, Scaling};
@ -7,12 +7,12 @@ use librashader_presets::{Scale2D, ScaleType, Scaling};
#[derive(Debug)] #[derive(Debug)]
pub struct Framebuffer { pub struct Framebuffer {
pub image: GLuint, pub image: GLuint,
pub handle: GLuint,
pub size: Size, pub size: Size,
pub format: GLenum, pub format: GLenum,
pub max_levels: u32, pub max_levels: u32,
pub levels: u32, pub levels: u32,
pub handle: GLuint, is_raw: bool,
pub init: bool,
} }
impl Framebuffer { impl Framebuffer {
@ -34,7 +34,7 @@ impl Framebuffer {
max_levels, max_levels,
levels: 0, levels: 0,
handle: framebuffer, handle: framebuffer,
init: false, is_raw: false
} }
} }
@ -52,11 +52,11 @@ impl Framebuffer {
max_levels: miplevels, max_levels: miplevels,
levels: miplevels, levels: miplevels,
handle, handle,
init: true, is_raw: true
} }
} }
pub fn as_texture(&self, filter: FilterMode, wrap_mode: WrapMode) -> Texture { pub(crate) fn as_texture(&self, filter: FilterMode, wrap_mode: WrapMode) -> Texture {
Texture { Texture {
image: GlImage { image: GlImage {
handle: self.image, handle: self.image,
@ -70,7 +70,7 @@ impl Framebuffer {
} }
} }
pub fn scale( pub(crate) fn scale(
&mut self, &mut self,
scaling: Scale2D, scaling: Scale2D,
format: ShaderFormat, format: ShaderFormat,
@ -78,6 +78,10 @@ impl Framebuffer {
_original: &Texture, _original: &Texture,
source: &Texture, source: &Texture,
) -> Size { ) -> Size {
if self.is_raw {
return self.size;
}
let mut width = 0f32; let mut width = 0f32;
let mut height = 0f32; let mut height = 0f32;
@ -131,11 +135,7 @@ impl Framebuffer {
size size
} }
pub(crate) fn is_initialized(&self) -> bool { pub(crate) fn clear(&self) {
self.init
}
pub fn clear(&self) {
unsafe { unsafe {
gl::BindFramebuffer(gl::FRAMEBUFFER, self.handle); gl::BindFramebuffer(gl::FRAMEBUFFER, self.handle);
gl::ColorMask(gl::TRUE, gl::TRUE, gl::TRUE, gl::TRUE); gl::ColorMask(gl::TRUE, gl::TRUE, gl::TRUE, gl::TRUE);
@ -145,7 +145,7 @@ impl Framebuffer {
} }
} }
pub fn copy_from(&mut self, image: &GlImage) { pub(crate) fn copy_from(&mut self, image: &GlImage) {
if image.size != self.size || image.format != self.format { if image.size != self.size || image.format != self.format {
self.init(image.size, image.format); self.init(image.size, image.format);
} }
@ -190,9 +190,12 @@ impl Framebuffer {
gl::BindFramebuffer(gl::FRAMEBUFFER, 0); gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
} }
} }
// todo: fix panic // todo: fix panic
pub(crate) fn init(&mut self, mut size: Size, format: impl Into<GLenum>) { pub(crate) fn init(&mut self, mut size: Size, format: impl Into<GLenum>) {
self.init = false; if self.is_raw {
return;
}
self.format = format.into(); self.format = format.into();
self.size = size; self.size = size;
@ -283,13 +286,11 @@ impl Framebuffer {
self.image, self.image,
0, 0,
); );
self.init = // self.init =
gl::CheckFramebufferStatus(gl::FRAMEBUFFER) == gl::FRAMEBUFFER_COMPLETE; // gl::CheckFramebufferStatus(gl::FRAMEBUFFER) == gl::FRAMEBUFFER_COMPLETE;
} }
_ => panic!("failed to complete: {status:x}"), _ => panic!("failed to complete: {status:x}"),
} }
} else {
self.init = true;
} }
gl::BindFramebuffer(gl::FRAMEBUFFER, 0); gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
@ -310,3 +311,25 @@ impl Drop for Framebuffer {
} }
} }
} }
#[derive(Debug, Copy, Clone)]
pub struct Viewport<'a> {
pub x: i32,
pub y: i32,
pub output: &'a Framebuffer,
pub mvp: Option<&'a [f32]>,
}
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
pub struct Size {
pub width: u32,
pub height: u32,
}
#[derive(Default, Debug, Copy, Clone)]
pub struct GlImage {
pub handle: GLuint,
pub format: GLenum,
pub size: Size,
pub padded_size: Size,
}

View file

@ -7,8 +7,7 @@ use glfw::{Context, Glfw, Window, WindowEvent};
use gl::types::{GLchar, GLenum, GLint, GLsizei, GLuint}; use gl::types::{GLchar, GLenum, GLint, GLsizei, GLuint};
use crate::filter_chain::FilterChain; use crate::filter_chain::FilterChain;
use crate::framebuffer::Framebuffer; use crate::framebuffer::{Framebuffer, GlImage, Size, Viewport};
use crate::util::{GlImage, Size, Viewport};
const WIDTH: u32 = 900; const WIDTH: u32 = 900;
const HEIGHT: u32 = 700; const HEIGHT: u32 = 700;

View file

@ -10,6 +10,12 @@ mod render_target;
mod util; mod util;
mod quad_render; mod quad_render;
pub use filter_chain::FilterChain;
pub use framebuffer::Viewport;
pub use framebuffer::GlImage;
pub use framebuffer::Size;
pub use framebuffer::Framebuffer;
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
@ -18,7 +24,7 @@ mod tests {
#[test] #[test]
fn triangle() { fn triangle() {
let (glfw, window, events, shader, vao) = hello_triangle::setup(); let (glfw, window, events, shader, vao) = hello_triangle::setup();
let mut filter = FilterChain::load("../test/slang-shaders/crt/crt-royale-fake-bloom.slangp").unwrap(); let mut filter = FilterChain::load_from_path("../test/slang-shaders/crt/crt-royale-fake-bloom.slangp").unwrap();
// FilterChain::load("../test/slang-shaders/crt/crt-royale.slangp").unwrap(); // FilterChain::load("../test/slang-shaders/crt/crt-royale.slangp").unwrap();

View file

@ -1,5 +1,5 @@
use crate::framebuffer::Framebuffer; use crate::framebuffer::{Framebuffer, Viewport};
use crate::util::{Texture, Viewport}; use crate::util::Texture;
#[rustfmt::skip] #[rustfmt::skip]
static DEFAULT_MVP: &[f32] = &[ static DEFAULT_MVP: &[f32] = &[

View file

@ -1,4 +1,4 @@
use crate::framebuffer::Framebuffer; use crate::framebuffer::{Framebuffer, GlImage};
use gl::types::{GLenum, GLuint}; use gl::types::{GLenum, GLuint};
use librashader::{FilterMode, WrapMode}; use librashader::{FilterMode, WrapMode};
@ -21,28 +21,6 @@ pub struct Texture {
pub wrap_mode: WrapMode, pub wrap_mode: WrapMode,
} }
#[derive(Debug, Copy, Clone)]
pub struct Viewport<'a> {
pub x: i32,
pub y: i32,
pub output: &'a Framebuffer,
pub mvp: Option<&'a [f32]>,
}
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
pub struct Size {
pub width: u32,
pub height: u32,
}
#[derive(Default, Debug, Copy, Clone)]
pub struct GlImage {
pub handle: GLuint,
pub format: GLenum,
pub size: Size,
pub padded_size: Size,
}
pub trait RingBuffer<T> { pub trait RingBuffer<T> {
fn current(&self) -> &T; fn current(&self) -> &T;
fn current_mut(&mut self) -> &mut T; fn current_mut(&mut self) -> &mut T;