rt: only draw last pass twice if the last pass is needed as feedback

This commit is contained in:
chyyran 2024-09-15 15:20:21 -04:00 committed by Ronny Chan
parent 0fe5bbd57b
commit d6f8950bdc
8 changed files with 156 additions and 129 deletions

View file

@ -52,6 +52,7 @@ pub struct FilterChainD3D11 {
history_framebuffers: VecDeque<OwnedImage>, history_framebuffers: VecDeque<OwnedImage>,
state: D3D11State, state: D3D11State,
default_options: FrameOptionsD3D11, default_options: FrameOptionsD3D11,
draw_last_pass_feedback: bool,
} }
pub(crate) struct Direct3D11 { pub(crate) struct Direct3D11 {
@ -187,6 +188,7 @@ impl FilterChainD3D11 {
let draw_quad = DrawQuad::new(device)?; let draw_quad = DrawQuad::new(device)?;
let state = D3D11State::new(device)?; let state = D3D11State::new(device)?;
Ok(FilterChainD3D11 { Ok(FilterChainD3D11 {
draw_last_pass_feedback: framebuffer_init.uses_final_pass_as_feedback(),
passes: filters, passes: filters,
output_framebuffers, output_framebuffers,
feedback_framebuffers, feedback_framebuffers,
@ -510,21 +512,23 @@ impl FilterChainD3D11 {
// Draw to output_framebuffers for proper handling of feedback. // Draw to output_framebuffers for proper handling of feedback.
let feedback_target = &self.output_framebuffers[index]; let feedback_target = &self.output_framebuffers[index];
pass.draw( if self.draw_last_pass_feedback {
&ctx, pass.draw(
index, &ctx,
&self.common, index,
pass.config.get_frame_count(frame_count), &self.common,
options, pass.config.get_frame_count(frame_count),
viewport, options,
&original,
&source,
RenderTarget::viewport_with_output(
&feedback_target.create_render_target_view()?,
viewport, viewport,
), &original,
QuadType::Final, &source,
)?; RenderTarget::viewport_with_output(
&feedback_target.create_render_target_view()?,
viewport,
),
QuadType::Final,
)?;
}
pass.draw( pass.draw(
&ctx, &ctx,

View file

@ -15,9 +15,9 @@ use librashader_runtime_d3d11::options::FilterChainOptionsD3D11;
// const FILTER_PATH: &str = "../test/shaders_slang/crt/crt-royale.slangp"; // const FILTER_PATH: &str = "../test/shaders_slang/crt/crt-royale.slangp";
// const FILTER_PATH: &str = "../test/slang-shaders/test/history.slangp"; // const FILTER_PATH: &str = "../test/slang-shaders/test/history.slangp";
// const FILTER_PATH: &str = "../test/shaders_slang/test/feedback.slangp"; const FILTER_PATH: &str = "../test/shaders_slang/test/feedback.slangp";
const FILTER_PATH: &str = "../test/shaders_slang/crt/crt-royale.slangp"; // const FILTER_PATH: &str = "../test/shaders_slang/crt/crt-geom-deluxe.slangp";
const IMAGE_PATH: &str = "../triangle.png"; const IMAGE_PATH: &str = "../triangle.png";
#[test] #[test]
fn triangle_d3d11_args() { fn triangle_d3d11_args() {

View file

@ -79,6 +79,7 @@ pub struct FilterChainD3D12 {
disable_mipmaps: bool, disable_mipmaps: bool,
default_options: FrameOptionsD3D12, default_options: FrameOptionsD3D12,
draw_last_pass_feedback: bool,
} }
pub(crate) struct FilterCommon { pub(crate) struct FilterCommon {
@ -386,6 +387,7 @@ impl FilterChainD3D12 {
let (history_framebuffers, history_textures) = framebuffer_init.init_history()?; let (history_framebuffers, history_textures) = framebuffer_init.init_history()?;
Ok(FilterChainD3D12 { Ok(FilterChainD3D12 {
draw_last_pass_feedback: framebuffer_init.uses_final_pass_as_feedback(),
common: FilterCommon { common: FilterCommon {
d3d12: device.clone(), d3d12: device.clone(),
samplers, samplers,
@ -848,48 +850,50 @@ impl FilterChainD3D12 {
source.filter = pass.config.filter; source.filter = pass.config.filter;
source.wrap_mode = pass.config.wrap_mode; source.wrap_mode = pass.config.wrap_mode;
let feedback_target = &self.output_framebuffers[index]; if self.draw_last_pass_feedback {
let feedback_target = &self.output_framebuffers[index];
if pass.pipeline.format != feedback_target.format { if pass.pipeline.format != feedback_target.format {
// eprintln!("recompiling final pipeline"); // eprintln!("recompiling final pipeline");
pass.pipeline.recompile( pass.pipeline.recompile(
feedback_target.format, feedback_target.format,
&self.common.root_signature, &self.common.root_signature,
&self.common.d3d12, &self.common.d3d12,
)?;
}
self.residuals
.dispose_barriers(util::d3d12_resource_transition(
cmd,
&feedback_target.handle.resource(),
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
D3D12_RESOURCE_STATE_RENDER_TARGET,
));
let view = feedback_target.create_render_target_view(&mut self.rtv_heap)?;
let out = RenderTarget::viewport_with_output(&view, viewport);
pass.draw(
cmd,
index,
&self.common,
pass.config.get_frame_count(frame_count),
options,
viewport,
&original,
&source,
&out,
QuadType::Final,
)?; )?;
self.residuals
.dispose_barriers(util::d3d12_resource_transition(
cmd,
&feedback_target.handle.resource(),
D3D12_RESOURCE_STATE_RENDER_TARGET,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
));
} }
self.residuals
.dispose_barriers(util::d3d12_resource_transition(
cmd,
&feedback_target.handle.resource(),
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
D3D12_RESOURCE_STATE_RENDER_TARGET,
));
let view = feedback_target.create_render_target_view(&mut self.rtv_heap)?;
let out = RenderTarget::viewport_with_output(&view, viewport);
pass.draw(
cmd,
index,
&self.common,
pass.config.get_frame_count(frame_count),
options,
viewport,
&original,
&source,
&out,
QuadType::Final,
)?;
self.residuals
.dispose_barriers(util::d3d12_resource_transition(
cmd,
&feedback_target.handle.resource(),
D3D12_RESOURCE_STATE_RENDER_TARGET,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
));
if pass.pipeline.format != viewport.output.format { if pass.pipeline.format != viewport.output.format {
// eprintln!("recompiling final pipeline"); // eprintln!("recompiling final pipeline");
pass.pipeline.recompile( pass.pipeline.recompile(

View file

@ -56,6 +56,7 @@ pub struct FilterChainD3D9 {
feedback_framebuffers: Box<[D3D9Texture]>, feedback_framebuffers: Box<[D3D9Texture]>,
history_framebuffers: VecDeque<D3D9Texture>, history_framebuffers: VecDeque<D3D9Texture>,
default_options: FrameOptionsD3D9, default_options: FrameOptionsD3D9,
draw_last_pass_feedback: bool,
} }
mod compile { mod compile {
@ -252,6 +253,7 @@ impl FilterChainD3D9 {
let draw_quad = DrawQuad::new(device)?; let draw_quad = DrawQuad::new(device)?;
Ok(FilterChainD3D9 { Ok(FilterChainD3D9 {
draw_last_pass_feedback: framebuffer_init.uses_final_pass_as_feedback(),
passes: filters, passes: filters,
output_framebuffers, output_framebuffers,
feedback_framebuffers, feedback_framebuffers,
@ -397,21 +399,23 @@ impl FilterChainD3D9 {
source.wrap = pass.config.wrap_mode; source.wrap = pass.config.wrap_mode;
source.is_srgb = pass.config.srgb_framebuffer; source.is_srgb = pass.config.srgb_framebuffer;
let feedback_target = &self.output_framebuffers[index]; if self.draw_last_pass_feedback {
let feedback_target_rtv = feedback_target.as_output()?; let feedback_target = &self.output_framebuffers[index];
let feedback_target_rtv = feedback_target.as_output()?;
pass.draw( pass.draw(
&self.common.d3d9, &self.common.d3d9,
index, index,
&self.common, &self.common,
pass.config.get_frame_count(frame_count), pass.config.get_frame_count(frame_count),
options, options,
viewport, viewport,
&original, &original,
&source, &source,
RenderTarget::viewport_with_output(&feedback_target_rtv, viewport), RenderTarget::viewport_with_output(&feedback_target_rtv, viewport),
QuadType::Final, QuadType::Final,
)?; )?;
}
pass.draw( pass.draw(
&self.common.d3d9, &self.common.d3d9,

View file

@ -39,6 +39,7 @@ pub(crate) struct FilterChainImpl<T: GLInterface> {
feedback_framebuffers: Box<[GLFramebuffer]>, feedback_framebuffers: Box<[GLFramebuffer]>,
history_framebuffers: VecDeque<GLFramebuffer>, history_framebuffers: VecDeque<GLFramebuffer>,
default_options: FrameOptionsGL, default_options: FrameOptionsGL,
draw_last_pass_feedback: bool,
} }
pub(crate) struct FilterCommon { pub(crate) struct FilterCommon {
@ -175,6 +176,7 @@ impl<T: GLInterface> FilterChainImpl<T> {
let draw_quad = T::DrawQuad::new(); let draw_quad = T::DrawQuad::new();
Ok(FilterChainImpl { Ok(FilterChainImpl {
draw_last_pass_feedback: framebuffer_init.uses_final_pass_as_feedback(),
passes: filters, passes: filters,
output_framebuffers, output_framebuffers,
feedback_framebuffers, feedback_framebuffers,
@ -373,17 +375,19 @@ impl<T: GLInterface> FilterChainImpl<T> {
source.mip_filter = pass.config.filter; source.mip_filter = pass.config.filter;
source.wrap_mode = pass.config.wrap_mode; source.wrap_mode = pass.config.wrap_mode;
let target = &self.output_framebuffers[index]; if self.draw_last_pass_feedback {
pass.draw( let target = &self.output_framebuffers[index];
index, pass.draw(
&self.common, index,
pass.config.get_frame_count(frame_count), &self.common,
options, pass.config.get_frame_count(frame_count),
viewport, options,
&original, viewport,
&source, &original,
RenderTarget::viewport_with_output(target, viewport), &source,
); RenderTarget::viewport_with_output(target, viewport),
);
}
pass.draw( pass.draw(
index, index,

View file

@ -82,6 +82,7 @@ pub struct FilterChainMetal {
prev_frame_history_buffer: OwnedTexture, prev_frame_history_buffer: OwnedTexture,
disable_mipmaps: bool, disable_mipmaps: bool,
default_options: FrameOptionsMetal, default_options: FrameOptionsMetal,
draw_last_pass_feedback: bool
} }
impl Debug for FilterChainMetal { impl Debug for FilterChainMetal {
@ -317,6 +318,7 @@ impl FilterChainMetal {
let draw_quad = DrawQuad::new(&device)?; let draw_quad = DrawQuad::new(&device)?;
Ok(FilterChainMetal { Ok(FilterChainMetal {
draw_last_pass_feedback: framebuffer_init.uses_final_pass_as_feedback(),
common: FilterCommon { common: FilterCommon {
luts, luts,
samplers, samplers,
@ -487,21 +489,22 @@ impl FilterChainMetal {
source.mip_filter = pass.config.filter; source.mip_filter = pass.config.filter;
let index = passes_len - 1; let index = passes_len - 1;
let output_image = &self.output_framebuffers[index].texture; if self.draw_last_pass_feedback {
let output_image = &self.output_framebuffers[index].texture;
let out = RenderTarget::viewport_with_output(output_image.as_ref(), viewport); let out = RenderTarget::viewport_with_output(output_image.as_ref(), viewport);
pass.draw( pass.draw(
&cmd, &cmd,
passes_len - 1, passes_len - 1,
&self.common, &self.common,
pass.config.get_frame_count(frame_count), pass.config.get_frame_count(frame_count),
options, options,
viewport, viewport,
&original, &original,
&source, &source,
&out, &out,
QuadType::Final, QuadType::Final,
)?; )?;
}
let output_image = viewport.output; let output_image = viewport.output;
let out = RenderTarget::viewport_with_output(output_image, viewport); let out = RenderTarget::viewport_with_output(output_image, viewport);

View file

@ -126,6 +126,7 @@ pub struct FilterChainVulkan {
disable_mipmaps: bool, disable_mipmaps: bool,
residuals: Box<[FrameResiduals]>, residuals: Box<[FrameResiduals]>,
default_options: FrameOptionsVulkan, default_options: FrameOptionsVulkan,
draw_last_pass_feedback: bool,
} }
pub(crate) struct FilterCommon { pub(crate) struct FilterCommon {
@ -386,6 +387,7 @@ impl FilterChainVulkan {
}); });
Ok(FilterChainVulkan { Ok(FilterChainVulkan {
draw_last_pass_feedback: framebuffer_init.uses_final_pass_as_feedback(),
common: FilterCommon { common: FilterCommon {
luts, luts,
samplers, samplers,
@ -727,28 +729,30 @@ impl FilterChainVulkan {
source.wrap_mode = pass.config.wrap_mode; source.wrap_mode = pass.config.wrap_mode;
source.mip_filter = pass.config.filter; source.mip_filter = pass.config.filter;
let target = &self.output_framebuffers[index]; if self.draw_last_pass_feedback {
let target = &self.output_framebuffers[index];
let output_image = OutputImage::new(&self.vulkan.device, target.image.clone())?; let output_image = OutputImage::new(&self.vulkan.device, target.image.clone())?;
let out = RenderTarget::viewport_with_output(&output_image, viewport); let out = RenderTarget::viewport_with_output(&output_image, viewport);
let residual_fb = pass.draw( let residual_fb = pass.draw(
cmd, cmd,
target.image.format, target.image.format,
index, index,
&self.common, &self.common,
pass.config.get_frame_count(frame_count), pass.config.get_frame_count(frame_count),
options, options,
viewport, viewport,
&original, &original,
&source, &source,
&out, &out,
QuadType::Final, QuadType::Final,
true, true,
)?; )?;
out.output.end_pass(&self.vulkan.device, cmd); out.output.end_pass(&self.vulkan.device, cmd);
intermediates.dispose_outputs(output_image); intermediates.dispose_outputs(output_image);
intermediates.dispose_framebuffers(residual_fb); intermediates.dispose_framebuffers(residual_fb);
}
let output_image = OutputImage::new(&self.vulkan.device, viewport.output.clone())?; let output_image = OutputImage::new(&self.vulkan.device, viewport.output.clone())?;
let out = RenderTarget::viewport_with_output(&output_image, viewport); let out = RenderTarget::viewport_with_output(&output_image, viewport);

View file

@ -74,6 +74,7 @@ pub struct FilterChainWgpu {
disable_mipmaps: bool, disable_mipmaps: bool,
mipmapper: MipmapGen, mipmapper: MipmapGen,
default_frame_options: FrameOptionsWgpu, default_frame_options: FrameOptionsWgpu,
draw_last_pass_feedback: bool,
} }
pub(crate) struct FilterCommon { pub(crate) struct FilterCommon {
@ -197,6 +198,7 @@ impl FilterChainWgpu {
let draw_quad = DrawQuad::new(&device); let draw_quad = DrawQuad::new(&device);
Ok(FilterChainWgpu { Ok(FilterChainWgpu {
draw_last_pass_feedback: framebuffer_init.uses_final_pass_as_feedback(),
common: FilterCommon { common: FilterCommon {
luts, luts,
samplers, samplers,
@ -492,22 +494,24 @@ impl FilterChainWgpu {
source.wrap_mode = pass.config.wrap_mode; source.wrap_mode = pass.config.wrap_mode;
source.mip_filter = pass.config.filter; source.mip_filter = pass.config.filter;
let target = &self.output_framebuffers[index]; if self.draw_last_pass_feedback {
let output_image = WgpuOutputView::from(target); let target = &self.output_framebuffers[index];
let out = RenderTarget::viewport_with_output(&output_image, viewport); let output_image = WgpuOutputView::from(target);
let out = RenderTarget::viewport_with_output(&output_image, viewport);
pass.draw( pass.draw(
cmd, cmd,
index, index,
&self.common, &self.common,
pass.config.get_frame_count(frame_count), pass.config.get_frame_count(frame_count),
options, options,
viewport, viewport,
&original, &original,
&source, &source,
&out, &out,
QuadType::Final, QuadType::Final,
)?; )?;
}
let output_image = &viewport.output; let output_image = &viewport.output;
let out = RenderTarget::viewport_with_output(output_image, viewport); let out = RenderTarget::viewport_with_output(output_image, viewport);