rt(gl): account for flipped coordinate space when blitting to output
This commit is contained in:
parent
bacfbf0791
commit
623c6776f7
|
@ -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;
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -392,7 +418,6 @@ impl<T: GLInterface> FilterChainImpl<T> {
|
|||
);
|
||||
|
||||
self.push_history(input)?;
|
||||
|
||||
self.draw_quad.unbind_vertices();
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
@ -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,
|
||||
);
|
||||
|
|
|
@ -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);
|
||||
|
@ -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,
|
||||
);
|
||||
|
|
|
@ -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<()>;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue