diff --git a/librashader-runtime-gl/src/filter_chain.rs b/librashader-runtime-gl/src/filter_chain.rs index 692ae7d..7193a58 100644 --- a/librashader-runtime-gl/src/filter_chain.rs +++ b/librashader-runtime-gl/src/filter_chain.rs @@ -14,6 +14,7 @@ use librashader_reflect::back::CompileShader; use crate::binding::{UniformBinding, UniformLocation, VariableLocation}; use crate::filter_pass::FilterPass; use crate::framebuffer::Framebuffer; +use crate::render_target::RenderTarget; use crate::util; use crate::util::{GlImage, RingBuffer, Size, Texture, Viewport}; @@ -97,23 +98,23 @@ impl FilterChain { pub struct FilterChain { passes: Vec, common: FilterCommon, - pub quad_vao: GLuint, + quad_vao: GLuint, } pub struct FilterCommon { semantics: ReflectSemantics, - preset: ShaderPreset, + pub(crate) preset: ShaderPreset, original_history: Vec, history: Vec, feedback: Vec, - luts: FxHashMap, + pub(crate) luts: FxHashMap, outputs: Vec, - pub quad_vbo: GLuint, + pub(crate) quad_vbo: GLuint, } impl FilterChain { pub fn load(path: impl AsRef) -> Result> { - let preset = librashader_presets::ShaderPreset::try_parse(path)?; + let preset = ShaderPreset::try_parse(path)?; let mut uniform_semantics: FxHashMap = Default::default(); let mut texture_semantics: FxHashMap> = Default::default(); @@ -274,9 +275,6 @@ impl FilterChain { push_buffer, variable_bindings: locations, source, - // no idea if this works. - // retroarch checks if feedback frames are used but we'll just init it tbh. - feedback_framebuffer: Framebuffer::new(1), config: config.clone() }); } @@ -382,7 +380,10 @@ impl FilterChain { } pub fn frame(&mut self, count: u32, vp: &Viewport, input: GlImage, clear: bool) { - // + if self.passes.is_empty() { + return; + } + unsafe { gl::BindFramebuffer(gl::FRAMEBUFFER, 0); gl::BindVertexArray(self.quad_vao); @@ -411,7 +412,7 @@ impl FilterChain { let framebuffer_size = target.scale(pass.config.scaling.clone(), pass.get_format(), vp, &original, &source); } let target = &self.common.outputs[index]; - pass.draw(&self.common, None, count, 1, vp, &original, &source, &target); + pass.draw(&self.common, count, 1, vp, &original, &source, RenderTarget::new(target, None)); let target = target.as_texture(pass.config.filter, pass.config.wrap_mode); // todo: update-pass-outputs @@ -423,7 +424,7 @@ impl FilterChain { for pass in last { source.filter = pass.config.filter; source.mip_filter = pass.config.filter; - pass.draw(&self.common, None, count, 1, vp, &original, &source, &vp.output); + pass.draw(&self.common, count, 1, vp, &original, &source, RenderTarget::new(&vp.output, vp.mvp)); } unsafe { diff --git a/librashader-runtime-gl/src/filter_pass.rs b/librashader-runtime-gl/src/filter_pass.rs index b46605a..e3f4089 100644 --- a/librashader-runtime-gl/src/filter_pass.rs +++ b/librashader-runtime-gl/src/filter_pass.rs @@ -13,6 +13,7 @@ use librashader_reflect::reflect::semantics::{MemberOffset, SemanticMap, Texture use crate::framebuffer::Framebuffer; use crate::binding::{UniformBinding, UniformLocation, VariableLocation}; use crate::filter_chain::{FilterChain, FilterCommon}; +use crate::render_target::RenderTarget; use crate::util::{GlImage, RingBuffer, Size, Texture, Viewport}; pub struct FilterPass { @@ -24,7 +25,6 @@ pub struct FilterPass { pub uniform_buffer: Box<[u8]>, pub push_buffer: Box<[u8]>, pub variable_bindings: FxHashMap, - pub feedback_framebuffer: Framebuffer, pub source: ShaderSource, pub config: ShaderPassConfig } @@ -107,14 +107,17 @@ impl FilterPass { } // todo: fix rendertargets (i.e. non-final pass is internal, final pass is user provided fbo) - pub fn draw(&mut self, parent: &FilterCommon, mvp: Option<&[f32]>, frame_count: u32, - frame_direction: i32, viewport: &Viewport, original: &Texture, source: &Texture, output: &Framebuffer) { + pub fn draw(&mut self, parent: &FilterCommon, frame_count: u32, + frame_direction: i32, viewport: &Viewport, original: &Texture, source: &Texture, output: RenderTarget) { + + let framebuffer = output.framebuffer; + unsafe { - gl::BindFramebuffer(gl::FRAMEBUFFER, output.framebuffer); + gl::BindFramebuffer(gl::FRAMEBUFFER, framebuffer.handle); gl::UseProgram(self.program); } - self.build_semantics(parent, mvp, frame_count, frame_direction, output.size, viewport, original, source); + self.build_semantics(parent, output.mvp, frame_count, frame_direction, framebuffer.size, viewport, original, source); // shader_gl3:1514 if self.ubo_location.vertex != gl::INVALID_INDEX && self.ubo_location.fragment != gl::INVALID_INDEX { @@ -142,14 +145,14 @@ impl FilterPass { // todo: final pass? unsafe { - gl::BindFramebuffer(gl::FRAMEBUFFER, output.framebuffer); + gl::BindFramebuffer(gl::FRAMEBUFFER, framebuffer.handle); 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(0, 0, output.size.width as GLsizei, output.size.height as GLsizei); + gl::Viewport(0, 0, framebuffer.size.width as GLsizei, framebuffer.size.height as GLsizei); - if output.format == gl::SRGB8_ALPHA8 { + if framebuffer.format == gl::SRGB8_ALPHA8 { gl::Enable(gl::FRAMEBUFFER_SRGB); } else { gl::Disable(gl::FRAMEBUFFER_SRGB); @@ -161,6 +164,7 @@ impl FilterPass { 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, @@ -187,14 +191,8 @@ impl FilterPass { } // framecount should be pre-modded - fn build_semantics(&mut self, parent: &FilterCommon, mvp: Option<&[f32]>, frame_count: u32, frame_direction: i32, fb_size: Size, viewport: &Viewport, original: &Texture, source: &Texture) { + fn build_semantics(&mut self, parent: &FilterCommon, mvp: &[f32], frame_count: u32, frame_direction: i32, fb_size: Size, viewport: &Viewport, original: &Texture, source: &Texture) { if let Some((_location, offset)) = self.variable_bindings.get(&VariableSemantics::MVP.into()) { - let mvp = mvp.unwrap_or(&[ - 2f32, 0.0, 0.0, 0.0, - 0.0, 2.0, 0.0, 0.0, - 0.0, 0.0, 2.0, 0.0, - -1.0, -1.0, 0.0, 1.0 - ]); let mvp_size = mvp.len() * std::mem::size_of::(); let (buffer, offset) = match offset { MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset), diff --git a/librashader-runtime-gl/src/framebuffer.rs b/librashader-runtime-gl/src/framebuffer.rs index 5774f44..78a18ae 100644 --- a/librashader-runtime-gl/src/framebuffer.rs +++ b/librashader-runtime-gl/src/framebuffer.rs @@ -11,7 +11,7 @@ pub struct Framebuffer { pub format: GLenum, pub max_levels: u32, pub levels: u32, - pub framebuffer: GLuint, + pub handle: GLuint, pub init: bool } @@ -30,7 +30,7 @@ impl Framebuffer { format: 0, max_levels, levels: 0, - framebuffer, + handle: framebuffer, init: false } } @@ -42,7 +42,7 @@ impl Framebuffer { format, max_levels: miplevels, levels: miplevels, - framebuffer: handle, + handle: handle, init: true } } @@ -129,7 +129,7 @@ impl Framebuffer { self.size = size; unsafe { - gl::BindFramebuffer(gl::FRAMEBUFFER, self.framebuffer); + gl::BindFramebuffer(gl::FRAMEBUFFER, self.handle); // reset the framebuffer image if self.image != 0 { @@ -199,8 +199,8 @@ impl Framebuffer { impl Drop for Framebuffer { fn drop(&mut self) { unsafe { - if self.framebuffer != 0 { - gl::DeleteFramebuffers(1, &self.framebuffer); + if self.handle != 0 { + gl::DeleteFramebuffers(1, &self.handle); } if self.image != 0 { gl::DeleteTextures(1, &self.image); diff --git a/librashader-runtime-gl/src/hello_triangle.rs b/librashader-runtime-gl/src/hello_triangle.rs index 7a2d6f9..b0ba899 100644 --- a/librashader-runtime-gl/src/hello_triangle.rs +++ b/librashader-runtime-gl/src/hello_triangle.rs @@ -418,7 +418,8 @@ void main() filter.frame(0, &Viewport { x: 0, y: 0, - output: &fb + output: &fb, + mvp: None }, GlImage { handle: rendered_texture, format: gl::RGBA8, diff --git a/librashader-runtime-gl/src/lib.rs b/librashader-runtime-gl/src/lib.rs index d6f9850..69cdfd1 100644 --- a/librashader-runtime-gl/src/lib.rs +++ b/librashader-runtime-gl/src/lib.rs @@ -6,33 +6,7 @@ mod util; mod framebuffer; mod binding; mod filter_chain; - -use std::collections::HashMap; -use std::error::Error; -use std::iter::Filter; -use std::ops::Deref; -use std::path::Path; -use gl::types::{GLenum, GLint, GLsizei, GLsizeiptr, GLuint}; -use glfw::Key::P; -use rustc_hash::FxHashMap; -use spirv_cross::spirv::Decoration; -use filter_pass::FilterPass; -use framebuffer::Framebuffer; - -use librashader::{FilterMode, ShaderFormat, ShaderSource, WrapMode}; -use librashader::image::Image; -use librashader_presets::{ShaderPassConfig, ShaderPreset}; -use librashader_reflect::back::{CompileShader, ShaderCompilerOutput}; -use librashader_reflect::back::cross::{GlslangGlslContext, GlVersion}; -use librashader_reflect::back::targets::{FromCompilation, GLSL}; -use librashader_reflect::front::shaderc::GlslangCompilation; -use librashader_reflect::reflect::cross::CrossReflect; -use librashader_reflect::reflect::{ReflectSemantics, ReflectShader, ShaderReflection, UniformSemantic}; -use librashader_reflect::reflect::semantics::{MemberOffset, SemanticMap, TextureSemantics, UniformMeta, VariableMeta, VariableSemantics}; -use librashader_reflect::reflect::{TextureSemanticMap, VariableSemanticMap}; -use binding::{UniformLocation, VariableLocation}; -use util::{GlImage, RingBuffer, Size, Texture, Viewport}; -use crate::binding::UniformBinding; +mod render_target; #[cfg(test)] diff --git a/librashader-runtime-gl/src/render_target.rs b/librashader-runtime-gl/src/render_target.rs new file mode 100644 index 0000000..d5479df --- /dev/null +++ b/librashader-runtime-gl/src/render_target.rs @@ -0,0 +1,37 @@ +use crate::framebuffer::Framebuffer; +use crate::util::Viewport; + +static DEFAULT_MVP: &[f32] = &[ + 2f32, 0.0, 0.0, 0.0, + 0.0, 2.0, 0.0, 0.0, + 0.0, 0.0, 2.0, 0.0, + -1.0, -1.0, 0.0, 1.0 +]; + +#[derive(Debug, Copy, Clone)] +pub struct RenderTarget<'a> { + pub mvp: &'a [f32], + pub framebuffer: &'a Framebuffer +} + +impl <'a> RenderTarget<'a> { + pub fn new(backbuffer: &'a Framebuffer, mvp: Option<&'a [f32]>) -> Self { + if let Some(mvp) = mvp { + RenderTarget { + framebuffer: backbuffer, + mvp + } + } else { + RenderTarget { + framebuffer: backbuffer, + mvp: DEFAULT_MVP + } + } + } +} + +impl <'a> From<&Viewport<'a>> for RenderTarget<'a> { + fn from(value: &Viewport<'a>) -> Self { + RenderTarget::new(value.output, value.mvp) + } +} \ No newline at end of file diff --git a/librashader-runtime-gl/src/util.rs b/librashader-runtime-gl/src/util.rs index 0d7cebd..512778e 100644 --- a/librashader-runtime-gl/src/util.rs +++ b/librashader-runtime-gl/src/util.rs @@ -26,6 +26,7 @@ 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)]