rt: only draw last pass twice if the last pass is needed as feedback
This commit is contained in:
parent
0fe5bbd57b
commit
d6f8950bdc
|
@ -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,
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue