rt(gl): ensure framebuffers are bound

This commit is contained in:
chyyran 2024-09-24 01:59:01 -04:00 committed by Ronny Chan
parent 97ad0d64bf
commit e7fe96520e
10 changed files with 82 additions and 41 deletions

View file

@ -10,7 +10,7 @@ use thiserror::Error;
#[derive(Error, Debug)] #[derive(Error, Debug)]
#[non_exhaustive] #[non_exhaustive]
pub enum FilterChainError { pub enum FilterChainError {
#[error("fbo initialization error")] #[error("fbo initialization error {0:x}")]
FramebufferInit(u32), FramebufferInit(u32),
#[error("SPIRV reflection error")] #[error("SPIRV reflection error")]
SpirvCrossReflectError(#[from] spirv_cross2::SpirvCrossError), SpirvCrossReflectError(#[from] spirv_cross2::SpirvCrossError),

View file

@ -377,7 +377,7 @@ impl<T: GLInterface> FilterChainImpl<T> {
&original, &original,
&source, &source,
RenderTarget::identity(target)?, RenderTarget::identity(target)?,
); )?;
let target = target.as_texture(pass.config.filter, pass.config.wrap_mode); let target = target.as_texture(pass.config.filter, pass.config.wrap_mode);
self.common.output_textures[index] = target; self.common.output_textures[index] = target;
@ -409,7 +409,7 @@ impl<T: GLInterface> FilterChainImpl<T> {
&original, &original,
&source, &source,
RenderTarget::viewport_with_output(target, viewport), RenderTarget::viewport_with_output(target, viewport),
); )?;
} }
pass.draw( pass.draw(
@ -421,7 +421,7 @@ impl<T: GLInterface> FilterChainImpl<T> {
&original, &original,
&source, &source,
RenderTarget::viewport_with_output(final_viewport, viewport), RenderTarget::viewport_with_output(final_viewport, viewport),
); )?;
self.common.output_textures[passes_len - 1] = viewport self.common.output_textures[passes_len - 1] = viewport
.output .output
.as_texture(pass.config.filter, pass.config.wrap_mode); .as_texture(pass.config.filter, pass.config.wrap_mode);

View file

@ -15,7 +15,7 @@ use crate::filter_chain::FilterCommon;
use crate::gl::{BindTexture, GLFramebuffer, GLInterface, UboRing}; use crate::gl::{BindTexture, GLFramebuffer, GLInterface, UboRing};
use crate::options::FrameOptionsGL; use crate::options::FrameOptionsGL;
use crate::samplers::SamplerSet; use crate::samplers::SamplerSet;
use crate::GLImage; use crate::{error, GLImage};
use crate::texture::InputTexture; use crate::texture::InputTexture;
@ -86,7 +86,7 @@ impl<T: GLInterface> FilterPass<T> {
original: &InputTexture, original: &InputTexture,
source: &InputTexture, source: &InputTexture,
output: RenderTarget<GLFramebuffer, i32>, output: RenderTarget<GLFramebuffer, i32>,
) { ) -> error::Result<()> {
let framebuffer = output.output; let framebuffer = output.output;
if self.config.mipmap_input && !parent.disable_mipmaps { if self.config.mipmap_input && !parent.disable_mipmaps {
@ -94,9 +94,7 @@ impl<T: GLInterface> FilterPass<T> {
} }
unsafe { unsafe {
parent framebuffer.bind::<T::FramebufferInterface>()?;
.context
.bind_framebuffer(glow::FRAMEBUFFER, Some(framebuffer.fbo));
parent.context.use_program(Some(self.program)); parent.context.use_program(Some(self.program));
} }
@ -154,6 +152,8 @@ impl<T: GLInterface> FilterPass<T> {
parent.context.disable(glow::FRAMEBUFFER_SRGB); parent.context.disable(glow::FRAMEBUFFER_SRGB);
parent.context.bind_framebuffer(glow::FRAMEBUFFER, None); parent.context.bind_framebuffer(glow::FRAMEBUFFER, None);
} }
Ok(())
} }
} }

View file

@ -87,6 +87,10 @@ impl GLFramebuffer {
wrap_mode, wrap_mode,
} }
} }
pub(crate) fn bind<T: FramebufferInterface>(&self) -> Result<()> {
T::bind(self)
}
} }
/// A state-checked wrapper around a raw framebuffer, used exclusively for output images. /// A state-checked wrapper around a raw framebuffer, used exclusively for output images.

View file

@ -290,4 +290,23 @@ impl FramebufferInterface for Gl3Framebuffer {
Ok(()) Ok(())
} }
fn bind(fb: &GLFramebuffer) -> Result<()> {
unsafe {
fb.ctx.bind_framebuffer(glow::FRAMEBUFFER, Some(fb.fbo));
fb.ctx.framebuffer_texture_2d(
glow::FRAMEBUFFER,
glow::COLOR_ATTACHMENT0,
glow::TEXTURE_2D,
fb.image,
0,
);
let status = fb.ctx.check_framebuffer_status(glow::FRAMEBUFFER);
if status != glow::FRAMEBUFFER_COMPLETE {
return Err(FilterChainError::FramebufferInit(status));
}
}
Ok(())
}
} }

View file

@ -236,4 +236,16 @@ impl FramebufferInterface for Gl46Framebuffer {
} }
Ok(()) Ok(())
} }
fn bind(fb: &GLFramebuffer) -> Result<()> {
unsafe {
fb.ctx.bind_framebuffer(glow::FRAMEBUFFER, Some(fb.fbo));
let status = fb.ctx.check_framebuffer_status(glow::FRAMEBUFFER);
if status != glow::FRAMEBUFFER_COMPLETE {
return Err(FilterChainError::FramebufferInit(status));
}
}
Ok(())
}
} }

View file

@ -120,7 +120,11 @@ pub(crate) trait FramebufferInterface {
let size = source_size.scale_viewport(scaling, *viewport_size, *original_size); let size = source_size.scale_viewport(scaling, *viewport_size, *original_size);
if fb.size != size || (mipmap && fb.max_levels == 1) || (!mipmap && fb.max_levels != 1) { if fb.size != size
|| (mipmap && fb.max_levels == 1)
|| (!mipmap && fb.max_levels != 1)
|| fb.image.is_none()
{
fb.size = size; fb.size = size;
if mipmap { if mipmap {
@ -145,6 +149,7 @@ pub(crate) trait FramebufferInterface {
fn clear<const REBIND: bool>(fb: &GLFramebuffer); fn clear<const REBIND: bool>(fb: &GLFramebuffer);
fn copy_from(fb: &mut GLFramebuffer, image: &GLImage) -> Result<()>; fn copy_from(fb: &mut GLFramebuffer, image: &GLImage) -> Result<()>;
fn init(fb: &mut GLFramebuffer, size: Size<u32>, format: impl Into<u32>) -> Result<()>; fn init(fb: &mut GLFramebuffer, size: Size<u32>, format: impl Into<u32>) -> Result<()>;
fn bind(fb: &GLFramebuffer) -> Result<()>;
} }
pub(crate) trait BindTexture { pub(crate) trait BindTexture {

View file

@ -1,7 +1,7 @@
use std::sync::mpsc::Receiver; use std::sync::mpsc::Receiver;
use std::sync::Arc; use std::sync::Arc;
use glfw::{Context, Glfw, Window, WindowEvent}; use glfw::{fail_on_errors, Context, Glfw, GlfwReceiver, PWindow, Window, WindowEvent};
use glow::HasContext; use glow::HasContext;
use librashader_common::{GetSize, Size, Viewport}; use librashader_common::{GetSize, Size, Viewport};
@ -14,13 +14,13 @@ const TITLE: &str = "librashader OpenGL 3.3";
pub fn setup() -> ( pub fn setup() -> (
Glfw, Glfw,
Window, PWindow,
Receiver<(f64, WindowEvent)>, GlfwReceiver<(f64, WindowEvent)>,
glow::Program, glow::Program,
glow::VertexArray, glow::VertexArray,
Arc<glow::Context>, Arc<glow::Context>,
) { ) {
let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap(); let mut glfw = glfw::init(fail_on_errors!()).unwrap();
glfw.window_hint(glfw::WindowHint::ContextVersion(3, 3)); glfw.window_hint(glfw::WindowHint::ContextVersion(3, 3));
glfw.window_hint(glfw::WindowHint::OpenGlProfile( glfw.window_hint(glfw::WindowHint::OpenGlProfile(
glfw::OpenGlProfileHint::Core, glfw::OpenGlProfileHint::Core,
@ -171,8 +171,8 @@ void main()
pub fn do_loop( pub fn do_loop(
gl: &Arc<glow::Context>, gl: &Arc<glow::Context>,
mut glfw: Glfw, mut glfw: Glfw,
mut window: Window, mut window: PWindow,
events: Receiver<(f64, WindowEvent)>, events: GlfwReceiver<(f64, WindowEvent)>,
triangle_program: glow::Program, triangle_program: glow::Program,
triangle_vao: glow::VertexArray, triangle_vao: glow::VertexArray,
filter: &mut FilterChainGL, filter: &mut FilterChainGL,
@ -183,7 +183,7 @@ pub fn do_loop(
let quad_vbuf; let quad_vbuf;
let output_texture; let output_texture;
let output_framebuffer_handle; // let output_framebuffer_handle;
let output_quad_vbuf; let output_quad_vbuf;
unsafe { unsafe {
@ -270,10 +270,11 @@ pub fn do_loop(
} }
unsafe { unsafe {
gl.bind_framebuffer(glow::FRAMEBUFFER, None);
// do frmaebuffer // do frmaebuffer
output_framebuffer_handle = gl.create_framebuffer().unwrap(); // output_framebuffer_handle = gl.create_framebuffer().unwrap();
//
gl.bind_framebuffer(glow::FRAMEBUFFER, Some(output_framebuffer_handle)); // gl.bind_framebuffer(glow::FRAMEBUFFER, Some(output_framebuffer_handle));
// glow::ObjectLabel( // glow::ObjectLabel(
// glow::FRAMEBUFFER, // glow::FRAMEBUFFER,
@ -324,18 +325,18 @@ pub fn do_loop(
); );
// set color attachment // set color attachment
gl.framebuffer_texture_2d( // gl.framebuffer_texture_2d(
glow::FRAMEBUFFER, // glow::FRAMEBUFFER,
glow::COLOR_ATTACHMENT0, // glow::COLOR_ATTACHMENT0,
glow::TEXTURE_2D, // glow::TEXTURE_2D,
Some(output_texture), // Some(output_texture),
0, // 0,
); // );
gl.draw_buffer(glow::COLOR_ATTACHMENT0); // gl.draw_buffer(glow::COLOR_ATTACHMENT0);
if gl.check_framebuffer_status(glow::FRAMEBUFFER) != glow::FRAMEBUFFER_COMPLETE { // if gl.check_framebuffer_status(glow::FRAMEBUFFER) != glow::FRAMEBUFFER_COMPLETE {
panic!("failed to create fbo") // panic!("failed to create fbo")
} // }
let fullscreen_fbo = [ let fullscreen_fbo = [
-1.0f32, -1.0, 0.0, 1.0, -1.0, 0.0, -1.0, 1.0, 0.0, -1.0, 1.0, 0.0, 1.0, -1.0, 0.0, -1.0f32, -1.0, 0.0, 1.0, -1.0, 0.0, -1.0, 1.0, 0.0, -1.0, 1.0, 0.0, 1.0, -1.0, 0.0,

View file

@ -1,7 +1,7 @@
use std::sync::mpsc::Receiver; use std::sync::mpsc::Receiver;
use std::sync::Arc; use std::sync::Arc;
use glfw::{Context, Glfw, Window, WindowEvent}; use glfw::{fail_on_errors, Context, Glfw, GlfwReceiver, PWindow, Window, WindowEvent};
use glow::HasContext; use glow::HasContext;
use librashader_common::{GetSize, Size, Viewport}; use librashader_common::{GetSize, Size, Viewport};
@ -14,13 +14,13 @@ const TITLE: &str = "librashader OpenGL 4.6";
pub fn setup() -> ( pub fn setup() -> (
Glfw, Glfw,
Window, PWindow,
Receiver<(f64, WindowEvent)>, GlfwReceiver<(f64, WindowEvent)>,
glow::Program, glow::Program,
glow::VertexArray, glow::VertexArray,
Arc<glow::Context>, Arc<glow::Context>,
) { ) {
let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap(); let mut glfw = glfw::init(fail_on_errors!()).unwrap();
glfw.window_hint(glfw::WindowHint::ContextVersion(4, 6)); glfw.window_hint(glfw::WindowHint::ContextVersion(4, 6));
glfw.window_hint(glfw::WindowHint::OpenGlProfile( glfw.window_hint(glfw::WindowHint::OpenGlProfile(
glfw::OpenGlProfileHint::Core, glfw::OpenGlProfileHint::Core,
@ -155,8 +155,8 @@ void main()
pub fn do_loop( pub fn do_loop(
gl: &Arc<glow::Context>, gl: &Arc<glow::Context>,
mut glfw: Glfw, mut glfw: Glfw,
mut window: Window, mut window: PWindow,
events: Receiver<(f64, WindowEvent)>, events: GlfwReceiver<(f64, WindowEvent)>,
triangle_program: glow::Program, triangle_program: glow::Program,
triangle_vao: glow::VertexArray, triangle_vao: glow::VertexArray,
filter: &mut FilterChainGL, filter: &mut FilterChainGL,

View file

@ -11,17 +11,17 @@ fn triangle_gl() {
unsafe { unsafe {
let mut filter = FilterChainGL::load_from_path( let mut filter = FilterChainGL::load_from_path(
// "../test/basic.slangp", // "../test/basic.slangp",
"../test/shaders_slang/test/feedback.slangp", "../test/shaders_slang/crt/crt-royale.slangp",
Arc::clone(&context), Arc::clone(&context),
Some(&FilterChainOptionsGL { Some(&FilterChainOptionsGL {
glsl_version: 0, glsl_version: 0,
use_dsa: false, use_dsa: false,
force_no_mipmaps: false, force_no_mipmaps: false,
disable_cache: false, disable_cache: true,
}), }),
) )
// FilterChain::load_from_path("../test/slang-shaders/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp", None) // FilterChain::load_from_path("../test/slang-shaders/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp", None)
.unwrap(); .expect("Failed to load filter chain");
hello_triangle::gl3::do_loop(&context, glfw, window, events, shader, vao, &mut filter); hello_triangle::gl3::do_loop(&context, glfw, window, events, shader, vao, &mut filter);
} }
} }
@ -35,7 +35,7 @@ fn triangle_gl46() {
// "../test/slang-shaders/test/history.slangp", // "../test/slang-shaders/test/history.slangp",
// "../test/basic.slangp", // "../test/basic.slangp",
// "../test/shaders_slang/crt/crt-royale.slangp", // "../test/shaders_slang/crt/crt-royale.slangp",
"../test/shaders_slang/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp", "../test/shaders_slang/crt/crt-royale.slangp",
Arc::clone(&context), Arc::clone(&context),
Some(&FilterChainOptionsGL { Some(&FilterChainOptionsGL {
glsl_version: 330, glsl_version: 330,