Skip to content

Commit

Permalink
rt(gl): account for flipped coordinate space when blitting to output
Browse files Browse the repository at this point in the history
  • Loading branch information
chyyran committed Mar 3, 2024
1 parent bacfbf0 commit 623c677
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 33 deletions.
51 changes: 38 additions & 13 deletions librashader-runtime-gl/src/filter_chain/filter_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::texture::InputTexture;
use crate::util::{gl_get_version, gl_u16_to_version};
use crate::{error, GLImage};
use gl::types::GLuint;
use librashader_common::Viewport;
use librashader_common::{FilterMode, Viewport, WrapMode};

use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig};
use librashader_reflect::back::glsl::GlslVersion;
Expand Down Expand Up @@ -250,7 +250,7 @@ impl<T: GLInterface> FilterChainImpl<T> {
T::FramebufferInterface::init(&mut back, input.size, input.format)?;
}

back.copy_from::<T::FramebufferInterface>(input)?;
back.copy_from::<T::FramebufferInterface>(input, false)?;
self.history_framebuffers.push_front(back)
}

Expand Down Expand Up @@ -302,12 +302,17 @@ impl<T: GLInterface> FilterChainImpl<T> {
}

// shader_gl3: 2067
let original = InputTexture {
image: *input,
filter,
mip_filter: filter,
wrap_mode,
};
// let original = InputTexture {
// image: *input,
// filter,
// mip_filter: filter,
// wrap_mode,
// };

let mut flipped = T::FramebufferInterface::new(1);
flipped.copy_from::<T::FramebufferInterface>(&input, true)?;

let original = flipped.as_texture(filter, wrap_mode);

let mut source = original;

Expand Down Expand Up @@ -363,9 +368,19 @@ impl<T: GLInterface> FilterChainImpl<T> {
}

self.draw_quad.bind_vertices(QuadType::Final);

// try to hint the optimizer
assert_eq!(last.len(), 1);
if let Some(pass) = last.iter_mut().next() {
// Need to flip the output, so we'll render to a backbuffer before blitting back to the viewport.
let mut output = T::FramebufferInterface::new(1);
output.right_size::<T::FramebufferInterface>(
&viewport
.output
.as_texture(FilterMode::Linear, WrapMode::ClampToEdge)
.image,
)?;

source.filter = pass.config.filter;
source.mip_filter = pass.config.filter;
source.wrap_mode = pass.config.wrap_mode;
Expand All @@ -378,11 +393,22 @@ impl<T: GLInterface> FilterChainImpl<T> {
viewport,
&original,
&source,
RenderTarget::viewport(viewport),
RenderTarget::viewport_with_output(&output, viewport),
);
self.common.output_textures[passes_len - 1] = viewport
.output
.as_texture(pass.config.filter, pass.config.wrap_mode);
self.common.output_textures[passes_len - 1] =
output.as_texture(pass.config.filter, pass.config.wrap_mode);

// SAFETY: viewport should be the same size as output texture.
unsafe {
viewport
.output
.copy_from_unchecked::<T::FramebufferInterface>(
&output
.as_texture(pass.config.filter, pass.config.wrap_mode)
.image,
true,
)?;
}
}

// swap feedback framebuffers with output
Expand All @@ -392,7 +418,6 @@ impl<T: GLInterface> FilterChainImpl<T> {
);

self.push_history(input)?;

self.draw_quad.unbind_vertices();

Ok(())
Expand Down
30 changes: 28 additions & 2 deletions librashader-runtime-gl/src/gl/framebuffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,34 @@ impl GLFramebuffer {
)
}

pub(crate) fn copy_from<T: FramebufferInterface>(&mut self, image: &GLImage) -> Result<()> {
T::copy_from(self, image)
pub(crate) unsafe fn copy_from_unchecked<T: FramebufferInterface>(
&self,
image: &GLImage,
flip_y: bool,
) -> Result<()> {
// SAFETY: checked size above.
unsafe { T::copy_from_unchecked(self, image, flip_y) }
}

pub(crate) fn right_size<T: FramebufferInterface>(&mut self, image: &GLImage) -> Result<()> {
if image.size != self.size || image.format != self.format {
T::init(self, image.size, image.format)?;
}

Ok(())
}

pub(crate) fn copy_from<T: FramebufferInterface>(
&mut self,
image: &GLImage,
flip_y: bool,
) -> Result<()> {
if image.size != self.size || image.format != self.format {
T::init(self, image.size, image.format)?;
}

// SAFETY: checked size above.
unsafe { self.copy_from_unchecked::<T>(image, flip_y) }
}

pub(crate) fn as_texture(&self, filter: FilterMode, wrap_mode: WrapMode) -> InputTexture {
Expand Down
10 changes: 3 additions & 7 deletions librashader-runtime-gl/src/gl/gl3/framebuffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,8 @@ impl FramebufferInterface for Gl3Framebuffer {
}
}
}
fn copy_from(fb: &mut GLFramebuffer, image: &GLImage) -> Result<()> {
// todo: may want to use a shader and draw a quad to be faster.
if image.size != fb.size || image.format != fb.format {
Self::init(fb, image.size, image.format)?;
}

unsafe fn copy_from_unchecked(fb: &GLFramebuffer, image: &GLImage, flip_y: bool) -> Result<()> {
unsafe {
gl::BindFramebuffer(gl::FRAMEBUFFER, fb.fbo);

Expand All @@ -112,9 +108,9 @@ impl FramebufferInterface for Gl3Framebuffer {
fb.size.width as GLint,
fb.size.height as GLint,
0,
0,
if flip_y { fb.size.height as GLint } else { 0 },
fb.size.width as GLint,
fb.size.height as GLint,
if flip_y { 0 } else { fb.size.height as GLint },
gl::COLOR_BUFFER_BIT,
gl::NEAREST,
);
Expand Down
11 changes: 3 additions & 8 deletions librashader-runtime-gl/src/gl/gl46/framebuffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,17 +77,12 @@ impl FramebufferInterface for Gl46Framebuffer {
);
}
}
fn copy_from(fb: &mut GLFramebuffer, image: &GLImage) -> Result<()> {
unsafe fn copy_from_unchecked(fb: &GLFramebuffer, image: &GLImage, flip_y: bool) -> Result<()> {
// todo: confirm this behaviour for unbound image.
if image.handle == 0 {
return Ok(());
}

// todo: may want to use a shader and draw a quad to be faster.
if image.size != fb.size || image.format != fb.format {
Self::init(fb, image.size, image.format)?;
}

unsafe {
// gl::NamedFramebufferDrawBuffer(fb.handle, gl::COLOR_ATTACHMENT1);
gl::NamedFramebufferReadBuffer(image.handle, gl::COLOR_ATTACHMENT0);
Expand All @@ -101,9 +96,9 @@ impl FramebufferInterface for Gl46Framebuffer {
image.size.width as GLint,
image.size.height as GLint,
0,
0,
if flip_y { fb.size.height as GLint } else { 0 },
fb.size.width as GLint,
fb.size.height as GLint,
if flip_y { 0 } else { fb.size.height as GLint },
gl::COLOR_BUFFER_BIT,
gl::NEAREST,
);
Expand Down
2 changes: 1 addition & 1 deletion librashader-runtime-gl/src/gl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ pub(crate) trait FramebufferInterface {
mipmap: bool,
) -> Result<Size<u32>>;
fn clear<const REBIND: bool>(fb: &GLFramebuffer);
fn copy_from(fb: &mut GLFramebuffer, image: &GLImage) -> Result<()>;
unsafe fn copy_from_unchecked(fb: &GLFramebuffer, image: &GLImage, flip_y: bool) -> Result<()>;
fn init(fb: &mut GLFramebuffer, size: Size<u32>, format: impl Into<GLenum>) -> Result<()>;
}

Expand Down
5 changes: 3 additions & 2 deletions librashader-runtime-gl/tests/triangle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ fn triangle_gl() {

unsafe {
let mut filter = FilterChainGL::load_from_path(
"../test/shaders_slang/crt/crt-royale.slangp",
"../test/shaders_slang/crt/crt-hyllian.slangp",
// "../test/shaders_slang/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp",
Some(&FilterChainOptionsGL {
glsl_version: 0,
use_dsa: false,
Expand All @@ -30,7 +31,7 @@ fn triangle_gl46() {
let mut filter = FilterChainGL::load_from_path(
// "../test/slang-shaders/vhs/VHSPro.slangp",
// "../test/slang-shaders/test/history.slangp",
"../test/shaders_slang/crt/crt-royale.slangp",
"../test/shaders_slang/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp",
// "../test/shadersslang/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp",
Some(&FilterChainOptionsGL {
glsl_version: 0,
Expand Down

0 comments on commit 623c677

Please sign in to comment.