Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 21 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions librashader-common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,12 @@ impl<T> Size<T> {
}
}

impl AsPrimitive<u64> for Size<u32> {
fn as_(self) -> u64 {
((self.width as u64) << 32) | (self.height as u64)
}
}

impl<T: AsPrimitive<f32>> Size<T> {
/// Get the aspect ratio of the size.
#[inline(always)]
Expand Down
179 changes: 83 additions & 96 deletions librashader-runtime-d3d11/src/filter_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use librashader_presets::context::VideoDriver;
use librashader_reflect::reflect::cross::SpirvCross;
use librashader_reflect::reflect::presets::{CompilePresetTarget, ShaderPassArtifact};
use librashader_runtime::binding::{BindingUtil, TextureInput};
use librashader_runtime::framebuffer::FramebufferInit;
use librashader_runtime::framebuffer::{FramebufferInit, FramebufferPool};
use librashader_runtime::quad::QuadType;
use librashader_runtime::render_target::RenderTarget;
use librashader_runtime::scaling::ScaleFramebuffer;
Expand All @@ -48,8 +48,8 @@ use windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT_R8G8B8A8_UNORM;
pub struct FilterChainD3D11 {
pub(crate) common: FilterCommon,
passes: Vec<FilterPass>,
output_framebuffers: Box<[OwnedImage]>,
feedback_framebuffers: Box<[OwnedImage]>,
output_framebuffers: FramebufferPool<OwnedImage>,
feedback_framebuffers: FramebufferPool<OwnedImage>,
history_framebuffers: VecDeque<OwnedImage>,
state: D3D11State,
default_options: FrameOptionsD3D11,
Expand Down Expand Up @@ -223,8 +223,7 @@ impl FilterChainD3D11 {
let (output_framebuffers, output_textures) = framebuffer_init.init_output_framebuffers()?;

// initialize feedback framebuffers
let (feedback_framebuffers, feedback_textures) =
framebuffer_init.init_output_framebuffers()?;
let (feedback_framebuffers, feedback_textures) = framebuffer_init.init_feedback_framebuffers()?;

// initialize history
let (history_framebuffers, history_textures) = framebuffer_init.init_history()?;
Expand Down Expand Up @@ -493,117 +492,105 @@ impl FilterChainD3D11 {

let mut source = original.clone();

// rescale render buffers to ensure all bindings are valid.
OwnedImage::scale_framebuffers(
source.size(),
viewport.output.size()?,
original.view.size()?,
&mut self.output_framebuffers,
let viewport_size = viewport.output.size()?;
let original_size = original.view.size()?;
let source_size = source.size();
let passes_len = passes.len();

OwnedImage::scale_feedback_framebuffers(
source_size,
viewport_size,
original_size,
&mut self.feedback_framebuffers,
passes,
None,
|index, pass, fb| {
self.common.feedback_textures[index] = Some(InputTexture::from_framebuffer(
fb,
pass.meta.wrap_mode,
pass.meta.filter,
)?);
Ok(())
},
)?;

// Refresh inputs for feedback textures.
// Don't need to do this for outputs because they are yet to be bound.
for ((texture, fbo), pass) in self
.common
.feedback_textures
.iter_mut()
.zip(self.feedback_framebuffers.iter())
.zip(passes.iter())
{
*texture = Some(InputTexture::from_framebuffer(
fbo,
pass.meta.wrap_mode,
pass.meta.filter,
)?);
}

let passes_len = passes.len();
let (pass, last) = passes.split_at_mut(passes_len - 1);

let state_guard = self.state.enter_filter_state(ctx);
self.common.draw_quad.bind_vbo_for_frame(ctx);

for (index, pass) in pass.iter_mut().enumerate() {
source.filter = pass.meta.filter;
source.wrap_mode = pass.meta.wrap_mode;
let target = &self.output_framebuffers[index];
pass.draw(
ctx,
index,
&self.common,
pass.meta.get_frame_count(frame_count),
options,
viewport,
&original,
&source,
RenderTarget::identity(&target.create_render_target_view()?)?,
None,
QuadType::Offscreen,
)?;

source = InputTexture {
view: target.create_shader_resource_view()?,
filter: pass.meta.filter,
wrap_mode: pass.meta.wrap_mode,
};
self.common.output_textures[index] = Some(source.clone());
}
OwnedImage::scale_output_framebuffers(
source_size,
viewport_size,
original_size,
&mut self.output_framebuffers,
passes,
|index, pass, target, size| {
source.filter = pass.meta.filter;
source.wrap_mode = pass.meta.wrap_mode;
let is_last = index == passes_len - 1;
let frame_count_pass = pass.meta.get_frame_count(frame_count);

if is_last && !self.draw_last_pass_feedback {
pass.draw(
ctx,
index,
&self.common,
frame_count_pass,
options,
viewport,
&original,
&source,
RenderTarget::viewport(viewport),
None,
QuadType::Final,
)?;
return Ok(());
}

// try to hint the optimizer
assert_eq!(last.len(), 1);
if let Some(pass) = last.iter_mut().next() {
let index = passes_len - 1;
source.filter = pass.meta.filter;
source.wrap_mode = pass.meta.wrap_mode;

// When feedback is enabled, render the last pass to the intermediate
// framebuffer first then render to the viewport with the OutputSize semantic
// overridden to the FB scale.
//
// Shaders need to see the pass's declared scale rather than the viewport size,
// or they won't render correctly for feedback.
let feedback_target = &self.output_framebuffers[index];
let output_size_override = if self.draw_last_pass_feedback {
let target_rtv = target.create_render_target_view()?;
pass.draw(
&ctx,
ctx,
index,
&self.common,
pass.meta.get_frame_count(frame_count),
frame_count_pass,
options,
viewport,
&original,
&source,
RenderTarget::identity(&feedback_target.create_render_target_view()?)?,
RenderTarget::identity(&target_rtv)?,
None,
QuadType::Offscreen,
)?;
Some(feedback_target.size)
} else {
None
};

pass.draw(
&ctx,
index,
&self.common,
pass.meta.get_frame_count(frame_count),
options,
viewport,
&original,
&source,
RenderTarget::viewport(viewport),
output_size_override,
QuadType::Final,
)?;
}
if is_last {
pass.draw(
ctx,
index,
&self.common,
frame_count_pass,
options,
viewport,
&original,
&source,
RenderTarget::viewport(viewport),
Some(size),
QuadType::Final,
)?;
} else {
source = InputTexture {
view: target.create_shader_resource_view()?,
filter: pass.meta.filter,
wrap_mode: pass.meta.wrap_mode,
};
self.common.output_textures[index] = Some(source.clone());
}
Ok(())
},
)?;

std::mem::swap(
&mut self.output_framebuffers,
&mut self.feedback_framebuffers,
);
for index in 0..passes_len {
if self.feedback_framebuffers.contains(index) {
std::mem::swap(&mut self.output_framebuffers[index], &mut self.feedback_framebuffers[index]);
}
}

drop(state_guard);

Expand Down
Loading
Loading