rt: do reflection to see if the final pass is needed as feedback

This commit is contained in:
chyyran 2024-09-15 15:13:48 -04:00 committed by Ronny Chan
parent eace595ebb
commit 0fe5bbd57b
2 changed files with 56 additions and 12 deletions

View file

@ -348,6 +348,11 @@ where
}
}
pub struct BindingRequirements {
pub(crate) required_history: usize,
pub(crate) uses_final_pass_as_feedback: bool,
}
/// Trait for objects that can be used to create a binding map.
pub trait BindingUtil {
/// Create the uniform binding map with the given reflection information.
@ -357,7 +362,7 @@ pub trait BindingUtil {
) -> FastHashMap<UniformBinding, T>;
/// Calculate the number of required images for history.
fn calculate_required_history<'a>(pass_meta: impl Iterator<Item = &'a Self>) -> usize
fn calculate_requirements<'a>(pass_meta: impl Iterator<Item = &'a Self>) -> BindingRequirements
where
Self: 'a;
}
@ -383,32 +388,65 @@ impl BindingUtil for BindingMeta {
uniform_bindings
}
fn calculate_required_history<'a>(pass_meta: impl Iterator<Item = &'a Self>) -> usize
fn calculate_requirements<'a>(pass_meta: impl Iterator<Item = &'a Self>) -> BindingRequirements
where
Self: 'a,
{
let mut required_images = 0;
let mut len: i64 = 0;
let mut latest_feedback_pass: i64 = -1;
for pass in pass_meta {
len += 1;
// If a shader uses history size, but not history, we still need to keep the texture.
let texture_max_index = pass
let history_texture_max_index = pass
.texture_meta
.iter()
.filter(|(semantics, _)| semantics.semantics == TextureSemantics::OriginalHistory)
.map(|(semantic, _)| semantic.index)
.fold(0, std::cmp::max);
let texture_size_max_index = pass
let history_texture_size_max_index = pass
.texture_size_meta
.iter()
.filter(|(semantics, _)| semantics.semantics == TextureSemantics::OriginalHistory)
.map(|(semantic, _)| semantic.index)
.fold(0, std::cmp::max);
required_images = std::cmp::max(required_images, texture_max_index);
required_images = std::cmp::max(required_images, texture_size_max_index);
let feedback_max_index = pass
.texture_meta
.iter()
.filter(|(semantics, _)| semantics.semantics == TextureSemantics::PassFeedback)
.map(|(semantic, _)| semantic.index as i64)
.fold(-1, std::cmp::max);
let feedback_max_size_index = pass
.texture_size_meta
.iter()
.filter(|(semantics, _)| semantics.semantics == TextureSemantics::PassFeedback)
.map(|(semantic, _)| semantic.index as i64)
.fold(-1, std::cmp::max);
latest_feedback_pass = std::cmp::max(latest_feedback_pass, feedback_max_index);
latest_feedback_pass = std::cmp::max(latest_feedback_pass, feedback_max_size_index);
required_images = std::cmp::max(required_images, history_texture_max_index);
required_images = std::cmp::max(required_images, history_texture_size_max_index);
}
required_images
let uses_feedback = if latest_feedback_pass.is_negative() {
false
} else {
// Technically = but we can be permissive here
// account for off by 1
latest_feedback_pass + 1 >= len
};
BindingRequirements {
required_history: required_images,
uses_final_pass_as_feedback: uses_feedback,
}
}
}

View file

@ -1,4 +1,4 @@
use crate::binding::BindingUtil;
use crate::binding::{BindingRequirements, BindingUtil};
use librashader_reflect::reflect::semantics::BindingMeta;
use std::collections::VecDeque;
@ -6,7 +6,7 @@ use std::collections::VecDeque;
pub struct FramebufferInit<'a, F, I, E> {
owned_generator: &'a dyn Fn() -> Result<F, E>,
input_generator: &'a dyn Fn() -> I,
required_history: usize,
requirements: BindingRequirements,
filters_count: usize,
}
@ -19,19 +19,20 @@ impl<'a, F, I, E> FramebufferInit<'a, F, I, E> {
input_generator: &'a dyn Fn() -> I,
) -> Self {
let filters_count = filters.len();
let required_history = BindingMeta::calculate_required_history(filters);
let requirements = BindingMeta::calculate_requirements(filters);
Self {
owned_generator,
input_generator,
filters_count,
required_history,
requirements,
}
}
/// Initialize history framebuffers and views.
pub fn init_history(&self) -> Result<(VecDeque<F>, Box<[I]>), E> {
init_history(
self.required_history,
self.requirements.required_history,
self.owned_generator,
self.input_generator,
)
@ -45,6 +46,11 @@ impl<'a, F, I, E> FramebufferInit<'a, F, I, E> {
self.input_generator,
)
}
/// Get if the final pass is used as feedback.
pub const fn uses_final_pass_as_feedback(&self) -> bool {
self.requirements.uses_final_pass_as_feedback
}
}
fn init_history<'a, F, I, E>(