rt: respect viewport extents when rendering

This commit is contained in:
chyyran 2024-08-13 01:20:21 -04:00 committed by Ronny Chan
parent f0a7970b44
commit 0a87bcc657
12 changed files with 98 additions and 35 deletions

View file

@ -40,6 +40,7 @@ pub use viewport::Viewport;
use num_traits::{AsPrimitive, Num}; use num_traits::{AsPrimitive, Num};
use std::convert::Infallible; use std::convert::Infallible;
use std::ops::{Add, Sub};
use std::str::FromStr; use std::str::FromStr;
#[repr(u32)] #[repr(u32)]
@ -200,6 +201,51 @@ impl<T> Size<T> {
} }
} }
impl<T: Sub<Output=T>> Sub for Size<T> {
type Output = Size<T>;
fn sub(self, rhs: Self) -> Self::Output {
Self {
width: self.width - rhs.width,
height: self.height - rhs.height
}
}
}
impl<T: Sub<T, Output=T> + Copy> Sub<T> for Size<T> {
type Output = Size<T>;
fn sub(self, rhs: T) -> Self::Output {
Self {
width: self.width - rhs,
height: self.height - rhs
}
}
}
impl<T: Add<Output=T>> Add for Size<T> {
type Output = Size<T>;
fn add(self, rhs: Self) -> Self::Output {
Self {
width: self.width + rhs.width,
height: self.height + rhs.height
}
}
}
impl<T: Add<T, Output=T> + Copy> Add<T> for Size<T> {
type Output = Size<T>;
fn add(self, rhs: T) -> Self::Output {
Self {
width: self.width + rhs,
height: self.height + rhs
}
}
}
impl<T> From<Size<T>> for [f32; 4] impl<T> From<Size<T>> for [f32; 4]
where where
T: Copy + AsPrimitive<f32>, T: Copy + AsPrimitive<f32>,

View file

@ -1,8 +1,16 @@
use crate::Size; use crate::Size;
/// The rendering output of a filter chain. /// The rendering output of a filter chain.
///
/// Viewport coordinates are relative to the coordinate system of the
/// target runtime. For correct results, `x` and `y` should almost always be
/// 0, and `size` should be the same as the size of the output texture.
///
/// Size uniforms will always be passed the full size of the output texture,
/// regardless of the user-specified viewport size.
pub struct Viewport<'a, T> { pub struct Viewport<'a, T> {
/// The x offset to start rendering from. /// The x offset to start rendering from. For correct results, this should almost
/// always be 0 to indicate the origin.
pub x: f32, pub x: f32,
/// The y offset to begin rendering from. /// The y offset to begin rendering from.
pub y: f32, pub y: f32,

View file

@ -1,3 +1,4 @@
use windows::Win32::Foundation::RECT;
use crate::filter_chain::FilterCommon; use crate::filter_chain::FilterCommon;
use crate::options::FrameOptionsD3D11; use crate::options::FrameOptionsD3D11;
use crate::texture::InputTexture; use crate::texture::InputTexture;
@ -253,18 +254,24 @@ impl FilterPass {
ctx.RSSetViewports(Some(&[D3D11_VIEWPORT { ctx.RSSetViewports(Some(&[D3D11_VIEWPORT {
TopLeftX: output.x, TopLeftX: output.x,
TopLeftY: output.y, TopLeftY: output.y,
Width: output_size.width as f32, Width: output.size.width as f32,
Height: output_size.height as f32, Height: output.size.height as f32,
MinDepth: 0.0, MinDepth: 0.0,
MaxDepth: 1.0, MaxDepth: 1.0,
}])) }]));
ctx.RSSetScissorRects(Some(&[RECT {
left: output.x as i32,
top: output.y as i32,
right: output.size.width as i32,
bottom: output.size.height as i32,
}]));
} }
parent.draw_quad.draw_quad(ctx, vbo_type); parent.draw_quad.draw_quad(ctx, vbo_type);
unsafe { unsafe {
// unbind resources. // unbind resources.
ctx.PSSetShaderResources(0, Some(std::mem::transmute(NULL_TEXTURES.as_ref()))); ctx.PSSetShaderResources(0, Some(NULL_TEXTURES));
ctx.OMSetRenderTargets(None, None); ctx.OMSetRenderTargets(None, None);
} }
Ok(()) Ok(())

View file

@ -570,17 +570,20 @@ pub mod d3d11_hello_triangle {
// eprintln!("w: {} h: {}", backbuffer_desc.Width, backbuffer_desc.Height); // eprintln!("w: {} h: {}", backbuffer_desc.Width, backbuffer_desc.Height);
let output = resources.backbuffer_rtv.as_ref().unwrap().clone(); let output = resources.backbuffer_rtv.as_ref().unwrap().clone();
let size = output.size().unwrap(); let size: Size<u32> = output.size().unwrap();
self.filter self.filter
.frame( .frame(
None, None,
&srv, &srv,
&Viewport { &Viewport {
x: 0f32, x: 100f32,
y: 0f32, y: 100f32,
output, output,
mvp: None, mvp: None,
size, size: Size {
width: size.width - 200,
height: size.height - 200,
},
}, },
resources.frame_count, resources.frame_count,
None, None,

View file

@ -206,17 +206,17 @@ impl FilterPass {
cmd.RSSetViewports(&[D3D12_VIEWPORT { cmd.RSSetViewports(&[D3D12_VIEWPORT {
TopLeftX: output.x, TopLeftX: output.x,
TopLeftY: output.y, TopLeftY: output.y,
Width: output.output.size.width as f32, Width: output.size.width as f32,
Height: output.output.size.height as f32, Height: output.size.height as f32,
MinDepth: 0.0, MinDepth: 0.0,
MaxDepth: 1.0, MaxDepth: 1.0,
}]); }]);
cmd.RSSetScissorRects(&[RECT { cmd.RSSetScissorRects(&[RECT {
left: 0, left: output.x as i32,
top: 0, top: output.y as i32,
right: output.output.size.width as i32, right: output.size.width as i32,
bottom: output.output.size.height as i32, bottom: output.size.height as i32,
}]); }]);
parent.draw_quad.draw_quad(&cmd, vbo_type) parent.draw_quad.draw_quad(&cmd, vbo_type)

View file

@ -193,8 +193,8 @@ impl FilterPass {
device.SetViewport(&D3DVIEWPORT9 { device.SetViewport(&D3DVIEWPORT9 {
X: output.x as u32, X: output.x as u32,
Y: output.y as u32, Y: output.y as u32,
Width: output_size.width, Width: output.size.width,
Height: output_size.height, Height: output.size.height,
MinZ: 0.0, MinZ: 0.0,
MaxZ: 1.0, MaxZ: 1.0,
})?; })?;

View file

@ -133,12 +133,11 @@ impl<T: GLInterface> FilterPass<T> {
unsafe { unsafe {
framebuffer.clear::<T::FramebufferInterface, false>(); framebuffer.clear::<T::FramebufferInterface, false>();
let framebuffer_size = framebuffer.size;
parent.context.viewport( parent.context.viewport(
output.x, output.x,
output.y, output.y,
framebuffer_size.width as i32, output.size.width as i32,
framebuffer_size.height as i32, output.size.height as i32,
); );
if framebuffer.format == glow::SRGB8_ALPHA8 { if framebuffer.format == glow::SRGB8_ALPHA8 {

View file

@ -207,15 +207,15 @@ impl MetalGraphicsPipeline {
rpass.setScissorRect(MTLScissorRect { rpass.setScissorRect(MTLScissorRect {
x: output.x as usize, x: output.x as usize,
y: output.y as usize, y: output.y as usize,
width: output.output.width(), width: output.size.width as usize,
height: output.output.height(), height: output.size.height as usize
}); });
rpass.setViewport(MTLViewport { rpass.setViewport(MTLViewport {
originX: output.x as f64, originX: output.x as f64,
originY: output.y as f64, originY: output.y as f64,
width: output.output.width() as f64, width: output.size.width as f64,
height: output.output.height() as f64, height: output.size.height as f64,
znear: 0.0, znear: 0.0,
zfar: 1.0, zfar: 1.0,
}); });

View file

@ -183,13 +183,13 @@ impl FilterPass {
x: output.x as i32, x: output.x as i32,
y: output.y as i32, y: output.y as i32,
}, },
extent: output.output.size.into(), extent: output.size.into(),
}], }],
); );
parent parent
.device .device
.cmd_set_viewport(cmd, 0, &[output.output.size.into()]); .cmd_set_viewport(cmd, 0, &[output.size.into()]);
parent.draw_quad.draw_quad(&parent.device, cmd, vbo_type); parent.draw_quad.draw_quad(&parent.device, cmd, vbo_type);
self.graphics_pipeline.end_rendering(cmd); self.graphics_pipeline.end_rendering(cmd);
} }

View file

@ -23,7 +23,7 @@ use swapchain::VulkanSwapchain;
use syncobjects::SyncObjects; use syncobjects::SyncObjects;
use vulkan_base::VulkanBase; use vulkan_base::VulkanBase;
use librashader_common::Viewport; use librashader_common::{Size, Viewport};
use librashader_runtime_vk::options::FrameOptionsVulkan; use librashader_runtime_vk::options::FrameOptionsVulkan;
use winit::event::{Event, WindowEvent}; use winit::event::{Event, WindowEvent};

View file

@ -310,15 +310,15 @@ impl WgpuGraphicsPipeline {
render_pass.set_scissor_rect( render_pass.set_scissor_rect(
output.x as u32, output.x as u32,
output.y as u32, output.y as u32,
output.output.size.width, output.size.width,
output.output.size.height, output.size.height,
); );
render_pass.set_viewport( render_pass.set_viewport(
output.x, output.x,
output.y, output.y,
output.output.size.width as f32, output.size.width as f32,
output.output.size.height as f32, output.size.height as f32,
0.0, 0.0,
1.0, 1.0,
); );

View file

@ -4,7 +4,7 @@ use winit::{
window::{Window, WindowBuilder}, window::{Window, WindowBuilder},
}; };
use librashader_common::Viewport; use librashader_common::{Size, Viewport};
use librashader_presets::ShaderPreset; use librashader_presets::ShaderPreset;
use librashader_runtime_wgpu::FilterChainWgpu; use librashader_runtime_wgpu::FilterChainWgpu;
use wgpu::util::DeviceExt; use wgpu::util::DeviceExt;
@ -290,15 +290,15 @@ impl<'a> State<'a> {
.frame( .frame(
Arc::clone(&render_output), Arc::clone(&render_output),
&Viewport { &Viewport {
x: 0.0, x: 100.0,
y: 0.0, y: 100.0,
mvp: None, mvp: None,
output: librashader_runtime_wgpu::WgpuOutputView::new_from_raw( output: librashader_runtime_wgpu::WgpuOutputView::new_from_raw(
&filter_view, &filter_view,
filter_output.size().into(), filter_output.size().into(),
filter_output.format(), filter_output.format(),
), ),
size: filter_output.size().into(), size: (Size::from(filter_output.size())) - 200,
}, },
&mut encoder, &mut encoder,
self.frame_count, self.frame_count,