From 3aee36a3615ef10e94f1d9daa71322eadb747198 Mon Sep 17 00:00:00 2001 From: chyyran Date: Sat, 19 Nov 2022 01:55:49 -0500 Subject: [PATCH] gl: use texture storage --- librashader-runtime-gl/src/filter_pass.rs | 147 +++++++++++++++---- librashader-runtime-gl/src/framebuffer.rs | 45 +++--- librashader-runtime-gl/src/hello_triangle.rs | 62 +++++++- librashader-runtime-gl/src/lib.rs | 84 +++++++++-- librashader-runtime-gl/src/util.rs | 2 +- 5 files changed, 264 insertions(+), 76 deletions(-) diff --git a/librashader-runtime-gl/src/filter_pass.rs b/librashader-runtime-gl/src/filter_pass.rs index 6039935..ae1e961 100644 --- a/librashader-runtime-gl/src/filter_pass.rs +++ b/librashader-runtime-gl/src/filter_pass.rs @@ -1,15 +1,15 @@ use std::iter::Filter; -use gl::types::{GLenum, GLint, GLuint}; +use gl::types::{GLenum, GLint, GLsizei, GLsizeiptr, GLuint}; use librashader_reflect::back::cross::GlslangGlslContext; use librashader_reflect::back::ShaderCompilerOutput; use librashader_reflect::reflect::ShaderReflection; use librashader_reflect::reflect::TextureSemanticMap; use librashader_reflect::reflect::VariableSemanticMap; use rustc_hash::FxHashMap; -use librashader::ShaderSource; +use librashader::{ShaderFormat, ShaderSource}; use librashader_presets::{Scale2D, ScaleType, Scaling, ShaderPassConfig, ShaderPreset}; use librashader_reflect::reflect::semantics::{MemberOffset, SemanticMap, TextureImage, TextureSemantics, VariableMeta, VariableSemantics}; -use crate::FilterChain; +use crate::{FilterChain, FilterCommon}; use crate::framebuffer::Framebuffer; use crate::util::{Location, VariableLocation, RingBuffer, Size, GlImage, Texture, Viewport}; @@ -84,6 +84,7 @@ impl FilterPass { fn set_texture(binding: &TextureImage, texture: &Texture) { unsafe { + // eprintln!("binding {} = texture {}", binding.binding, texture.image.handle); gl::ActiveTexture((gl::TEXTURE0 + binding.binding) as GLenum); gl::BindTexture(gl::TEXTURE_2D, texture.image.handle); @@ -94,7 +95,7 @@ impl FilterPass { } } - fn scale_framebuffer(&mut self, viewport: &Viewport, original: &Texture, source: &Texture) -> Size { + fn scale_framebuffer(&mut self, format: ShaderFormat, viewport: &Viewport, original: &Texture, source: &Texture) -> Size { let mut width = 0f32; let mut height = 0f32; @@ -145,20 +146,107 @@ impl FilterPass { height: height.round() as u32 }; - self.framebuffer.size = size; + if self.framebuffer.size != size { + self.framebuffer.size = size; + + self.framebuffer.init(size,if format == ShaderFormat::Unknown { + ShaderFormat::R8G8B8A8Unorm + } else { + format + }); + } size } - pub fn build_commands(&mut self, parent: &FilterChain, mvp: Option<&[f32]>, frame_count: u32, frame_direction: u32, viewport: &Viewport, original: &Texture, source: &Texture) { + pub fn build_commands(&mut self, parent: &FilterCommon, mvp: Option<&[f32]>, frame_count: u32, frame_direction: u32, viewport: &Viewport, original: &Texture, source: &Texture) { + let mut fb_format = ShaderFormat::R8G8B8A8Unorm; + if self.config.srgb_framebuffer { + fb_format = ShaderFormat::R8G8B8A8Srgb; + } else if self.config.float_framebuffer { + fb_format = ShaderFormat::R16G16B16A16Sfloat; + } + + let fb_size = self.scale_framebuffer(fb_format, viewport, original, source); + + // println!("[frame] Using framebuffer {}, image {}", self.framebuffer.framebuffer, self.framebuffer.image); unsafe { + gl::BindFramebuffer(gl::FRAMEBUFFER, self.framebuffer.framebuffer); gl::UseProgram(self.program); } + self.build_semantics(parent, mvp, frame_count, frame_direction, fb_size, viewport, original, source); + // shader_gl3:1514 + if !self.ubo_location.vertex == gl::INVALID_INDEX && !self.ubo_location.fragment == gl::INVALID_INDEX { + if let (Some(ubo), Some(ring)) = (&self.reflection.ubo, &mut self.ubo_ring) { + let size = ubo.size; + let buffer = ring.current(); + + unsafe { + gl::BindBuffer(gl::UNIFORM_BUFFER, *buffer); + gl::BufferSubData(gl::UNIFORM_BUFFER, 0, size as GLsizeiptr, self.uniform_buffer.as_ptr().cast()); + gl::BindBuffer(gl::UNIFORM_BUFFER, 0); + + if self.ubo_location.vertex != gl::INVALID_INDEX { + gl::BindBufferBase(gl::UNIFORM_BUFFER, self.ubo_location.vertex, *buffer); + } + if self.ubo_location.vertex != gl::INVALID_INDEX { + gl::BindBufferBase(gl::UNIFORM_BUFFER, self.ubo_location.fragment, *buffer); + } + } + ring.next() + } + } + + // todo: final pass? + + unsafe { + gl::BindFramebuffer(gl::FRAMEBUFFER, self.framebuffer.framebuffer); + gl::ColorMask(gl::TRUE, gl::TRUE, gl::TRUE, gl::TRUE); + gl::ClearColor(0.0f32, 0.0f32, 0.0f32, 0.0f32); + gl::Clear(gl::COLOR_BUFFER_BIT); + // + gl::Viewport(viewport.x, viewport.y, fb_size.width as GLsizei, fb_size.height as GLsizei); + + if self.framebuffer.format == gl::SRGB8_ALPHA8 { + gl::Enable(gl::FRAMEBUFFER_SRGB); + } else { + gl::Disable(gl::FRAMEBUFFER_SRGB); + } + + gl::Disable(gl::CULL_FACE); + gl::Disable(gl::BLEND); + gl::Disable(gl::DEPTH_TEST); + + gl::EnableVertexAttribArray(0); + gl::EnableVertexAttribArray(1); + gl::BindBuffer(gl::ARRAY_BUFFER, parent.quad_vbo); + + /// the provided pointers are of OpenGL provenance with respect to the buffer bound to quad_vbo, + /// and not a known provenance to the Rust abstract machine, therefore we give it invalid pointers. + /// that are inexpressible in Rust + gl::VertexAttribPointer(0, 2, gl::FLOAT, gl::FALSE, (4 * std::mem::size_of::()) as GLsizei, + std::ptr::invalid(0)); + gl::VertexAttribPointer(1, 2, gl::FLOAT, gl::FALSE, (4 * std::mem::size_of::()) as GLsizei, + std::ptr::invalid(2 * std::mem::size_of::())); + gl::DrawArrays(gl::TRIANGLE_STRIP, 0, 4); + + + gl::BindBuffer(gl::ARRAY_BUFFER, 0); + gl::DisableVertexAttribArray(0); + gl::DisableVertexAttribArray(1); + + gl::Disable(gl::FRAMEBUFFER_SRGB); + gl::BindFramebuffer(gl::FRAMEBUFFER, 0); + } + + + // todo: draw image onto fbo + // shader_gl3 1579 } + // framecount should be pre-modded - fn build_semantics(&mut self, parent: &FilterChain, mvp: Option<&[f32]>, frame_count: u32, frame_direction: u32, viewport: &Viewport, original: &Texture, source: &Texture) { - let fb_size = self.scale_framebuffer(viewport, original, source); + fn build_semantics(&mut self, parent: &FilterCommon, mvp: Option<&[f32]>, frame_count: u32, frame_direction: u32, fb_size: Size, viewport: &Viewport, original: &Texture, source: &Texture) { if let Some(variable) = self.reflection.meta.variable_meta.get(&VariableSemantics::MVP) { let mvp = mvp.unwrap_or(&[ @@ -172,7 +260,7 @@ impl FilterPass { MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, offset), MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset) }; - FilterPass::build_mvp(&mut buffer[offset..][..mvp.len()], mvp) + FilterPass::build_mvp(&mut buffer[offset..][..mvp.len() * std::mem::size_of::()], mvp) } if let Some(variable) = self.reflection.meta.variable_meta.get(&VariableSemantics::Output) { @@ -215,6 +303,11 @@ impl FilterPass { FilterPass::build_uint(location, &mut buffer[offset..][..4], frame_direction) } + + if let Some(binding) = self.reflection.meta.texture_meta.get(&TextureSemantics::Original.semantics(0)) { + eprintln!("setting original binding to {}", binding.binding); + FilterPass::set_texture(binding, original); + } if let Some(variable) = self.reflection.meta.texture_size_meta.get(&TextureSemantics::Original.semantics(0)) { let location = self.locations.get(&variable.id).expect("variable did not have location mapped").location(); let (buffer, offset) = match variable.offset { @@ -223,11 +316,13 @@ impl FilterPass { }; FilterPass::build_vec4(location, &mut buffer[offset..][..4], original.image.size); - if let Some(binding) = self.reflection.meta.texture_meta.get(&TextureSemantics::Original.semantics(0)) { - FilterPass::set_texture(binding, original); - } } + + if let Some(binding) = self.reflection.meta.texture_meta.get(&TextureSemantics::Source.semantics(0)) { + // eprintln!("setting source binding to {}", binding.binding); + FilterPass::set_texture(binding, source); + } if let Some(variable) = self.reflection.meta.texture_size_meta.get(&TextureSemantics::Source.semantics(0)) { let location = self.locations.get(&variable.id).expect("variable did not have location mapped").location(); let (buffer, offset) = match variable.offset { @@ -235,24 +330,22 @@ impl FilterPass { MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset) }; FilterPass::build_vec4(location, &mut buffer[offset..][..4], source.image.size); - - if let Some(binding) = self.reflection.meta.texture_meta.get(&TextureSemantics::Source.semantics(0)) { - FilterPass::set_texture(binding, source); - } } - if let Some(variable) = self.reflection.meta.texture_size_meta.get(&TextureSemantics::OriginalHistory.semantics(0)) { - let location = self.locations.get(&variable.id).expect("variable did not have location mapped").location(); - let (buffer, offset) = match variable.offset { - MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, offset), - MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset) - }; - FilterPass::build_vec4(location, &mut buffer[offset..][..4], original.image.size); - if let Some(binding) = self.reflection.meta.texture_meta.get(&TextureSemantics::OriginalHistory.semantics(0)) { - FilterPass::set_texture(binding, original); - } - } + // todo: history + + // if let Some(binding) = self.reflection.meta.texture_meta.get(&TextureSemantics::OriginalHistory.semantics(0)) { + // FilterPass::set_texture(binding, original); + // } + // if let Some(variable) = self.reflection.meta.texture_size_meta.get(&TextureSemantics::OriginalHistory.semantics(0)) { + // let location = self.locations.get(&variable.id).expect("variable did not have location mapped").location(); + // let (buffer, offset) = match variable.offset { + // MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, offset), + // MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset) + // }; + // FilterPass::build_vec4(location, &mut buffer[offset..][..4], original.image.size); + // } for variable in self.reflection.meta.parameter_meta.values() { let location = self.locations.get(&variable.id).expect("variable did not have location mapped").location(); diff --git a/librashader-runtime-gl/src/framebuffer.rs b/librashader-runtime-gl/src/framebuffer.rs index 58f0d7b..d28f277 100644 --- a/librashader-runtime-gl/src/framebuffer.rs +++ b/librashader-runtime-gl/src/framebuffer.rs @@ -13,29 +13,13 @@ pub struct Framebuffer { pub init: bool } -impl Drop for Framebuffer { - fn drop(&mut self) { - if self.framebuffer != 0 { - unsafe { - gl::DeleteFramebuffers(1, &self.framebuffer); - } - } - - if self.image != 0 { - unsafe { - gl::DeleteTextures(1, &self.image); - } - } - } -} - impl Framebuffer { pub fn new(max_levels: u32) -> Framebuffer { let mut framebuffer = 0; unsafe { gl::GenFramebuffers(1, &mut framebuffer); gl::BindFramebuffer(gl::FRAMEBUFFER, framebuffer); - gl::BindFramebuffer(gl::FRAMEBUFFER, framebuffer); + gl::BindFramebuffer(gl::FRAMEBUFFER, 0); } Framebuffer { @@ -49,12 +33,8 @@ impl Framebuffer { } } - fn init(&mut self, mut size: Size, mut format: ShaderFormat) { - if format == ShaderFormat::Unknown { - format = ShaderFormat::R8G8B8A8Unorm; - } - - self.format = GLenum::from(format); + pub(crate) fn init(&mut self, mut size: Size, mut format: impl Into) { + self.format = format.into(); self.size = size; unsafe { @@ -67,7 +47,7 @@ impl Framebuffer { } gl::GenTextures(1, &mut self.image); - gl::BindTexture(1, self.image); + gl::BindTexture(gl::TEXTURE_2D, self.image); if size.width == 0 { size.width = 1; @@ -108,12 +88,12 @@ impl Framebuffer { self.levels = 1; } - gl::TexStorage2D(gl::TEXTURE_2D, self.levels as GLsizei, gl::RGBA8, size.width as GLsizei, size.height as GLsizei); + gl::TexStorage2D(gl::TEXTURE_2D, self.levels as GLsizei, ShaderFormat::R8G8B8A8Unorm.into(), size.width as GLsizei, size.height as GLsizei); gl::FramebufferTexture2D(gl::FRAMEBUFFER, gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D, self.image, 0); self.init = gl::CheckFramebufferStatus(gl::FRAMEBUFFER) == gl::FRAMEBUFFER_COMPLETE; } - _ => panic!("failed to complete: {status}") + _ => panic!("failed to complete: {status:x}") } } else { self.init = true; @@ -124,3 +104,16 @@ impl Framebuffer { } } } + +impl Drop for Framebuffer { + fn drop(&mut self) { + unsafe { + if self.framebuffer != 0 { + gl::DeleteFramebuffers(1, &self.framebuffer); + } + if self.image != 0 { + gl::DeleteTextures(1, &self.image); + } + } + } +} \ No newline at end of file diff --git a/librashader-runtime-gl/src/hello_triangle.rs b/librashader-runtime-gl/src/hello_triangle.rs index 6e86090..29e7790 100644 --- a/librashader-runtime-gl/src/hello_triangle.rs +++ b/librashader-runtime-gl/src/hello_triangle.rs @@ -1,11 +1,14 @@ use std::convert::TryInto; +use std::ffi::{c_void, CStr}; use std::sync::mpsc::Receiver; use glfw; use glfw::{Context, Glfw, Window, WindowEvent}; use gl; -use gl::types::{GLint, GLsizei, GLuint}; +use gl::types::{GLchar, GLenum, GLint, GLsizei, GLuint}; use glfw::Key::P; +use crate::FilterChain; +use crate::util::{GlImage, Size, Viewport}; const WIDTH: u32 = 900; const HEIGHT: u32 = 700; @@ -72,12 +75,21 @@ pub fn compile_program(vertex: &str, fragment: &str) -> GLuint { shader_program } + +extern "system" fn debug_callback(source: GLenum, err_type: GLenum, id: GLuint, severity: GLenum, length: GLsizei, message: *const GLchar, _user: *mut c_void) { + unsafe { + let message = CStr::from_ptr(message); + eprintln!("{:?}", message); + } +} + pub fn setup() -> (Glfw, Window, Receiver<(f64, WindowEvent)>, GLuint, GLuint) { let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap(); glfw.window_hint(glfw::WindowHint::ContextVersion(3, 3)); glfw.window_hint(glfw::WindowHint::OpenGlProfile(glfw::OpenGlProfileHint::Core)); glfw.window_hint(glfw::WindowHint::OpenGlForwardCompat(true)); glfw.window_hint(glfw::WindowHint::Resizable(false)); + glfw.window_hint(glfw::WindowHint::OpenGlDebugContext(true)); let (mut window, events) = glfw.create_window(WIDTH, HEIGHT, TITLE, glfw::WindowMode::Windowed).unwrap(); let (screen_width, screen_height) = window.get_framebuffer_size(); @@ -86,6 +98,18 @@ pub fn setup() -> (Glfw, Window, Receiver<(f64, WindowEvent)>, GLuint, GLuint) { window.set_key_polling(true); gl::load_with(|ptr| window.get_proc_address(ptr) as *const _); + + unsafe { + gl::Enable(gl::DEBUG_OUTPUT); + gl::Enable(gl::DEBUG_OUTPUT_SYNCHRONOUS); + + gl::DebugMessageCallback(Some(debug_callback), std::ptr::null_mut()); + gl::DebugMessageControl(gl::DONT_CARE, + gl::DONT_CARE, + gl::DONT_CARE, + 0, std::ptr::null(), gl::TRUE); + } + unsafe { gl::Viewport(0, 0, screen_width, screen_height); clear_color(Color(0.4, 0.4, 0.4, 1.0)); @@ -192,7 +216,7 @@ void main() (glfw, window, events, shader_program, vao) } -pub fn do_loop(mut glfw: Glfw, mut window: Window, events: Receiver<(f64, WindowEvent)>, shader_program: GLuint, vao: GLuint) { +pub fn do_loop(mut glfw: Glfw, mut window: Window, events: Receiver<(f64, WindowEvent)>, triangle_program: GLuint, vao: GLuint, filter: &mut FilterChain) { let mut framebuffer_handle = 0; let mut rendered_texture = 0; let mut quad_vbuf = 0; @@ -207,7 +231,7 @@ pub fn do_loop(mut glfw: Glfw, mut window: Window, events: Receiver<(f64, Window gl::BindTexture(gl::TEXTURE_2D, rendered_texture); // empty image - gl::TexImage2D(gl::TEXTURE_2D, 0, gl::RGB as GLint, WIDTH as GLsizei, HEIGHT as GLsizei, 0, gl::RGB, gl::UNSIGNED_BYTE, std::ptr::null_mut()); + gl::TexStorage2D(gl::TEXTURE_2D, 1, gl::RGBA8, WIDTH as GLsizei, HEIGHT as GLsizei); gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as GLint); gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as GLint); @@ -215,7 +239,7 @@ pub fn do_loop(mut glfw: Glfw, mut window: Window, events: Receiver<(f64, Window gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as GLint); // set color attachment - gl::FramebufferTexture(gl::FRAMEBUFFER, gl::COLOR_ATTACHMENT0, rendered_texture, 0); + gl::FramebufferTexture2D(gl::FRAMEBUFFER, gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D, rendered_texture, 0); let buffers = [gl::COLOR_ATTACHMENT0]; gl::DrawBuffers(1, buffers.as_ptr()); @@ -290,12 +314,12 @@ void main() gl::Viewport(0, 0, WIDTH as GLsizei, HEIGHT as GLsizei); // clear color - // clear_color(Color(0.3, 0.4, 0.6, 1.0)); + clear_color(Color(0.3, 0.4, 0.6, 1.0)); gl::Clear(gl::COLOR_BUFFER_BIT); // do the drawing - gl::UseProgram(shader_program); + gl::UseProgram(triangle_program); // select vertices gl::BindVertexArray(vao); @@ -305,7 +329,33 @@ void main() // unselect vertices gl::BindVertexArray(0); + // unselect fbo + gl::BindFramebuffer(gl::FRAMEBUFFER, 0); + } + + // eprintln!("[core] rendered texture is {rendered_texture}"); + + unsafe { + filter.frame(0, &Viewport { + x: 0, + y: 0, + size: Size { + width: WIDTH, + height: HEIGHT + } + }, GlImage { + handle: rendered_texture, + format: gl::RGBA, + size: Size { + width: WIDTH, + height: HEIGHT + }, + padded_size: Default::default() + }, false) + } + + unsafe { // texture is done now. // todo: insert postprocessing stuff to rendered_texture diff --git a/librashader-runtime-gl/src/lib.rs b/librashader-runtime-gl/src/lib.rs index 98eac13..4299424 100644 --- a/librashader-runtime-gl/src/lib.rs +++ b/librashader-runtime-gl/src/lib.rs @@ -1,3 +1,5 @@ +#![feature(strict_provenance)] + mod hello_triangle; mod filter; mod filter_pass; @@ -42,6 +44,13 @@ unsafe fn gl_compile_shader(stage: GLenum, source: &str) -> GLuint { shader } +static QUAD_VBO_DATA: &'static [f32; 16] = &[ + 0.0f32, 0.0f32, 0.0f32, 0.0f32, + 1.0f32, 0.0f32, 1.0f32, 0.0f32, + 0.0f32, 1.0f32, 0.0f32, 1.0f32, + 1.0f32, 1.0f32, 1.0f32, 1.0f32, +]; + impl FilterChain { fn load_pass_semantics(uniform_semantics: &mut FxHashMap, texture_semantics: &mut FxHashMap>, config: &ShaderPassConfig) { @@ -114,12 +123,19 @@ impl FilterChain { pub struct FilterChain { passes: Vec, + common: FilterCommon, + pub quad_vao: GLuint, +} + +pub struct FilterCommon { semantics: ReflectSemantics, preset: ShaderPreset, original_history: Vec, history: Vec, feedback: Vec, - luts: FxHashMap + luts: FxHashMap, + pub quad_vbo: GLuint, + pub input_framebuffer: Framebuffer, } impl FilterChain { @@ -194,7 +210,8 @@ impl FilterChain { for res in &vertex_resources.stage_inputs { let loc = glsl.context.compiler.vertex.get_decoration(res.id, Decoration::Location)?; - let loc_name = format!("RARCH_ATTRIBUTE_{loc}"); + let loc_name = format!("RARCH_ATTRIBUTE_{loc}\0"); + eprintln!("{loc_name}"); gl::BindAttribLocation(program, loc, loc_name.as_str().as_ptr().cast()) } gl::LinkProgram(program); @@ -208,7 +225,7 @@ impl FilterChain { } for binding in &glsl.context.texture_fixups { - let loc_name = format!("RARCH_TEXTURE_{}", *binding); + let loc_name = format!("RARCH_TEXTURE_{}\0", *binding); unsafe { let location = gl::GetUniformLocation(program, loc_name.as_str().as_ptr().cast()); if location >= 0 { @@ -373,24 +390,51 @@ impl FilterChain { }); } + let mut quad_vbo = 0; + unsafe { + gl::GenBuffers(1, &mut quad_vbo); + gl::BindBuffer(gl::ARRAY_BUFFER, quad_vbo); + gl::BufferData(gl::ARRAY_BUFFER, std::mem::size_of_val(QUAD_VBO_DATA) as GLsizeiptr, + QUAD_VBO_DATA.as_ptr().cast(), gl::STATIC_DRAW); + gl::BindBuffer(gl::ARRAY_BUFFER, 0); + } + + let mut quad_vao = 0; + unsafe { + gl::GenVertexArrays(1, &mut quad_vao); + } + // todo: split params Ok(FilterChain { passes: filters, - semantics, - preset, - original_history: vec![], - history: vec![], - feedback: vec![], - luts, + quad_vao, + common: FilterCommon { + semantics, + preset, + original_history: vec![], + history: vec![], + feedback: vec![], + luts, + quad_vbo, + input_framebuffer: Framebuffer::new(1) + } }) } // how much info do we actually need? - fn frame(&mut self, count: u32, vp: &Viewport, input: GlImage, clear: bool) { + pub fn frame(&mut self, count: u32, vp: &Viewport, input: GlImage, clear: bool) { + // + // unsafe { + // gl::BindFramebuffer(gl::FRAMEBUFFER, 0); + // gl::BindVertexArray(self.quad_vao); + // } + + // todo: copy framebuffer + // shader_gl3: 2067 + let filter = self.common.preset.shaders.first().map(|f| f.filter).unwrap_or_default(); + let wrap_mode = self.common.preset.shaders.first().map(|f| f.wrap_mode).unwrap_or_default(); - let filter = self.preset.shaders.first().map(|f| f.filter).unwrap_or_default(); - let wrap_mode = self.preset.shaders.first().map(|f| f.wrap_mode).unwrap_or_default(); let original = Texture { image: input, filter, @@ -401,9 +445,15 @@ impl FilterChain { let mut source = original.clone(); for passes in &mut self.passes { + passes.build_commands(&self.common, None, count, 1, vp, &original, &source); // passes.build_semantics(&self, None, count, 1, vp, &original, &source); } + + // unsafe { + // gl::BindFramebuffer(gl::FRAMEBUFFER, 0); + // gl::BindVertexArray(0); + // } // todo: deal with the mess that is frame history } @@ -412,8 +462,8 @@ impl FilterChain { // todo: make copy // todo: get filter info from pass data. - let filter = self.preset.shaders.first().map(|f| f.filter).unwrap_or_default(); - let wrap_mode = self.preset.shaders.first().map(|f| f.wrap_mode).unwrap_or_default(); + let filter = self.common.preset.shaders.first().map(|f| f.filter).unwrap_or_default(); + let wrap_mode = self.common.preset.shaders.first().map(|f| f.wrap_mode).unwrap_or_default(); let original = Texture { image: input, filter, @@ -437,10 +487,12 @@ mod tests { #[test] fn triangle() { let (glfw, window, events, shader, vao) = hello_triangle::setup(); - FilterChain::load("../test/basic.slangp").unwrap(); + let mut filter = FilterChain::load("../test/basic.slangp").unwrap(); + + // FilterChain::load("../test/slang-shaders/crt/crt-royale.slangp").unwrap(); - hello_triangle::do_loop(glfw, window, events, shader, vao); + hello_triangle::do_loop(glfw, window, events, shader, vao, &mut filter ); } // #[test] diff --git a/librashader-runtime-gl/src/util.rs b/librashader-runtime-gl/src/util.rs index f4912d2..064d236 100644 --- a/librashader-runtime-gl/src/util.rs +++ b/librashader-runtime-gl/src/util.rs @@ -47,7 +47,7 @@ pub struct Viewport { pub size: Size, } -#[derive(Default, Debug, Copy, Clone)] +#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)] pub struct Size { pub width: u32, pub height: u32,