rt: do reflection to see if the final pass is needed as feedback
This commit is contained in:
parent
eace595ebb
commit
0fe5bbd57b
|
@ -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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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>(
|
||||||
|
|
Loading…
Reference in a new issue