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. /// Trait for objects that can be used to create a binding map.
pub trait BindingUtil { pub trait BindingUtil {
/// Create the uniform binding map with the given reflection information. /// Create the uniform binding map with the given reflection information.
@ -357,7 +362,7 @@ pub trait BindingUtil {
) -> FastHashMap<UniformBinding, T>; ) -> FastHashMap<UniformBinding, T>;
/// Calculate the number of required images for history. /// 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 where
Self: 'a; Self: 'a;
} }
@ -383,32 +388,65 @@ impl BindingUtil for BindingMeta {
uniform_bindings 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 where
Self: 'a, Self: 'a,
{ {
let mut required_images = 0; let mut required_images = 0;
let mut len: i64 = 0;
let mut latest_feedback_pass: i64 = -1;
for pass in pass_meta { for pass in pass_meta {
len += 1;
// If a shader uses history size, but not history, we still need to keep the texture. // 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 .texture_meta
.iter() .iter()
.filter(|(semantics, _)| semantics.semantics == TextureSemantics::OriginalHistory) .filter(|(semantics, _)| semantics.semantics == TextureSemantics::OriginalHistory)
.map(|(semantic, _)| semantic.index) .map(|(semantic, _)| semantic.index)
.fold(0, std::cmp::max); .fold(0, std::cmp::max);
let texture_size_max_index = pass let history_texture_size_max_index = pass
.texture_size_meta .texture_size_meta
.iter() .iter()
.filter(|(semantics, _)| semantics.semantics == TextureSemantics::OriginalHistory) .filter(|(semantics, _)| semantics.semantics == TextureSemantics::OriginalHistory)
.map(|(semantic, _)| semantic.index) .map(|(semantic, _)| semantic.index)
.fold(0, std::cmp::max); .fold(0, std::cmp::max);
required_images = std::cmp::max(required_images, texture_max_index); let feedback_max_index = pass
required_images = std::cmp::max(required_images, texture_size_max_index); .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 librashader_reflect::reflect::semantics::BindingMeta;
use std::collections::VecDeque; use std::collections::VecDeque;
@ -6,7 +6,7 @@ use std::collections::VecDeque;
pub struct FramebufferInit<'a, F, I, E> { pub struct FramebufferInit<'a, F, I, E> {
owned_generator: &'a dyn Fn() -> Result<F, E>, owned_generator: &'a dyn Fn() -> Result<F, E>,
input_generator: &'a dyn Fn() -> I, input_generator: &'a dyn Fn() -> I,
required_history: usize, requirements: BindingRequirements,
filters_count: usize, filters_count: usize,
} }
@ -19,19 +19,20 @@ impl<'a, F, I, E> FramebufferInit<'a, F, I, E> {
input_generator: &'a dyn Fn() -> I, input_generator: &'a dyn Fn() -> I,
) -> Self { ) -> Self {
let filters_count = filters.len(); let filters_count = filters.len();
let required_history = BindingMeta::calculate_required_history(filters); let requirements = BindingMeta::calculate_requirements(filters);
Self { Self {
owned_generator, owned_generator,
input_generator, input_generator,
filters_count, filters_count,
required_history, requirements,
} }
} }
/// Initialize history framebuffers and views. /// Initialize history framebuffers and views.
pub fn init_history(&self) -> Result<(VecDeque<F>, Box<[I]>), E> { pub fn init_history(&self) -> Result<(VecDeque<F>, Box<[I]>), E> {
init_history( init_history(
self.required_history, self.requirements.required_history,
self.owned_generator, self.owned_generator,
self.input_generator, self.input_generator,
) )
@ -45,6 +46,11 @@ impl<'a, F, I, E> FramebufferInit<'a, F, I, E> {
self.input_generator, 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>( fn init_history<'a, F, I, E>(