rt: pass device context to uniform binder if needed

This commit is contained in:
chyyran 2024-03-04 02:10:08 -05:00 committed by Ronny Chan
parent af3ea252ba
commit 7593f9f9b5
5 changed files with 71 additions and 59 deletions

View file

@ -59,11 +59,11 @@ impl GlUniformScalar for u32 {
} }
pub(crate) struct GlUniformBinder; pub(crate) struct GlUniformBinder;
impl<T> BindUniform<VariableLocation, T> for GlUniformBinder impl<T> BindUniform<VariableLocation, T, ()> for GlUniformBinder
where where
T: GlUniformScalar, T: GlUniformScalar,
{ {
fn bind_uniform(block: UniformMemberBlock, value: T, location: VariableLocation) -> Option<()> { fn bind_uniform(block: UniformMemberBlock, value: T, location: VariableLocation, _: &()) -> Option<()> {
if let Some(location) = location.location(block) if let Some(location) = location.location(block)
&& location.bindable() && location.bindable()
{ {
@ -84,11 +84,12 @@ where
} }
} }
impl BindUniform<VariableLocation, &[f32; 4]> for GlUniformBinder { impl BindUniform<VariableLocation, &[f32; 4], ()> for GlUniformBinder {
fn bind_uniform( fn bind_uniform(
block: UniformMemberBlock, block: UniformMemberBlock,
vec4: &[f32; 4], vec4: &[f32; 4],
location: VariableLocation, location: VariableLocation,
_: &()
) -> Option<()> { ) -> Option<()> {
if let Some(location) = location.location(block) if let Some(location) = location.location(block)
&& location.bindable() && location.bindable()
@ -108,11 +109,12 @@ impl BindUniform<VariableLocation, &[f32; 4]> for GlUniformBinder {
} }
} }
impl BindUniform<VariableLocation, &[f32; 16]> for GlUniformBinder { impl BindUniform<VariableLocation, &[f32; 16], ()> for GlUniformBinder {
fn bind_uniform( fn bind_uniform(
block: UniformMemberBlock, block: UniformMemberBlock,
mat4: &[f32; 16], mat4: &[f32; 16],
location: VariableLocation, location: VariableLocation,
_: &()
) -> Option<()> { ) -> Option<()> {
if let Some(location) = location.location(block) if let Some(location) = location.location(block)
&& location.bindable() && location.bindable()

View file

@ -24,7 +24,7 @@ use std::sync::Arc;
pub struct FilterPass { pub struct FilterPass {
pub reflection: ShaderReflection, pub reflection: ShaderReflection,
pub(crate) uniform_storage: UniformStorage<NoUniformBinder, Option<()>, RawVulkanBuffer>, pub(crate) uniform_storage: UniformStorage<NoUniformBinder, Option<()>, RawVulkanBuffer, Box<[u8]>, Arc<ash::Device>>,
pub uniform_bindings: FastHashMap<UniformBinding, MemberOffset>, pub uniform_bindings: FastHashMap<UniformBinding, MemberOffset>,
pub source: ShaderSource, pub source: ShaderSource,
pub config: ShaderPassConfig, pub config: ShaderPassConfig,

View file

@ -26,7 +26,7 @@ pub struct FilterPass {
pub device: Arc<wgpu::Device>, pub device: Arc<wgpu::Device>,
pub reflection: ShaderReflection, pub reflection: ShaderReflection,
pub(crate) uniform_storage: pub(crate) uniform_storage:
UniformStorage<NoUniformBinder, Option<()>, WgpuStagedBuffer, WgpuStagedBuffer>, UniformStorage<NoUniformBinder, Option<()>, WgpuStagedBuffer, WgpuStagedBuffer, Arc<wgpu::Device>>,
pub uniform_bindings: FastHashMap<UniformBinding, MemberOffset>, pub uniform_bindings: FastHashMap<UniformBinding, MemberOffset>,
pub source: ShaderSource, pub source: ShaderSource,
pub config: ShaderPassConfig, pub config: ShaderPassConfig,

View file

@ -15,13 +15,13 @@ pub trait TextureInput {
} }
/// A uniform member offset with context that needs to be resolved. /// A uniform member offset with context that needs to be resolved.
pub trait ContextOffset<H, C> pub trait ContextOffset<H, C, D=()>
where where
H: BindUniform<C, f32>, H: BindUniform<C, f32, D>,
H: BindUniform<C, u32>, H: BindUniform<C, u32, D>,
H: BindUniform<C, i32>, H: BindUniform<C, i32, D>,
H: for<'a> BindUniform<C, &'a [f32; 4]>, H: for<'a> BindUniform<C, &'a [f32; 4], D>,
H: for<'a> BindUniform<C, &'a [f32; 16]>, H: for<'a> BindUniform<C, &'a [f32; 16], D>,
{ {
/// Gets the `MemberOffset` part of the offset. /// Gets the `MemberOffset` part of the offset.
fn offset(&self) -> MemberOffset; fn offset(&self) -> MemberOffset;
@ -30,13 +30,13 @@ where
fn context(&self) -> C; fn context(&self) -> C;
} }
impl<H> ContextOffset<H, Option<()>> for MemberOffset impl<D, H> ContextOffset<H, Option<()>, D> for MemberOffset
where where
H: BindUniform<Option<()>, f32>, H: BindUniform<Option<()>, f32, D>,
H: BindUniform<Option<()>, u32>, H: BindUniform<Option<()>, u32, D>,
H: BindUniform<Option<()>, i32>, H: BindUniform<Option<()>, i32, D>,
H: for<'a> BindUniform<Option<()>, &'a [f32; 4]>, H: for<'a> BindUniform<Option<()>, &'a [f32; 4], D>,
H: for<'a> BindUniform<Option<()>, &'a [f32; 16]>, H: for<'a> BindUniform<Option<()>, &'a [f32; 16], D>,
{ {
fn offset(&self) -> MemberOffset { fn offset(&self) -> MemberOffset {
*self *self
@ -73,11 +73,11 @@ where
C: Copy, C: Copy,
U: Deref<Target = [u8]> + DerefMut, U: Deref<Target = [u8]> + DerefMut,
P: Deref<Target = [u8]> + DerefMut, P: Deref<Target = [u8]> + DerefMut,
H: BindUniform<C, f32>, H: BindUniform<C, f32, Self::DeviceContext>,
H: BindUniform<C, u32>, H: BindUniform<C, u32, Self::DeviceContext>,
H: BindUniform<C, i32>, H: BindUniform<C, i32, Self::DeviceContext>,
H: for<'b> BindUniform<C, &'b [f32; 4]>, H: for<'b> BindUniform<C, &'b [f32; 4], Self::DeviceContext>,
H: for<'b> BindUniform<C, &'b [f32; 16]>, H: for<'b> BindUniform<C, &'b [f32; 16], Self::DeviceContext>,
{ {
/// The type of the input texture used for semantic binding. /// The type of the input texture used for semantic binding.
type InputTexture: TextureInput; type InputTexture: TextureInput;
@ -92,7 +92,7 @@ where
type DeviceContext; type DeviceContext;
/// The type of uniform offsets to use. /// The type of uniform offsets to use.
type UniformOffset: ContextOffset<H, C>; type UniformOffset: ContextOffset<H, C, Self::DeviceContext>;
/// Bind a texture to the input descriptor set /// Bind a texture to the input descriptor set
fn bind_texture<'a>( fn bind_texture<'a>(
@ -108,7 +108,7 @@ where
fn bind_semantics<'a>( fn bind_semantics<'a>(
device: &Self::DeviceContext, device: &Self::DeviceContext,
sampler_set: &Self::SamplerSet, sampler_set: &Self::SamplerSet,
uniform_storage: &mut UniformStorage<H, C, U, P>, uniform_storage: &mut UniformStorage<H, C, U, P, Self::DeviceContext>,
descriptor_set: &mut Self::DescriptorSet<'a>, descriptor_set: &mut Self::DescriptorSet<'a>,
uniform_inputs: UniformInputs<'_>, uniform_inputs: UniformInputs<'_>,
original: &Self::InputTexture, original: &Self::InputTexture,
@ -124,7 +124,7 @@ where
) { ) {
// Bind MVP // Bind MVP
if let Some(offset) = uniform_bindings.get(&UniqueSemantics::MVP.into()) { if let Some(offset) = uniform_bindings.get(&UniqueSemantics::MVP.into()) {
uniform_storage.bind_mat4(offset.offset(), uniform_inputs.mvp, offset.context()); uniform_storage.bind_mat4(offset.offset(), uniform_inputs.mvp, offset.context(), device);
} }
// Bind OutputSize // Bind OutputSize
@ -133,6 +133,7 @@ where
offset.offset(), offset.offset(),
uniform_inputs.framebuffer_size, uniform_inputs.framebuffer_size,
offset.context(), offset.context(),
device
); );
} }
@ -142,6 +143,7 @@ where
offset.offset(), offset.offset(),
uniform_inputs.viewport_size, uniform_inputs.viewport_size,
offset.context(), offset.context(),
device
); );
} }
@ -151,6 +153,7 @@ where
offset.offset(), offset.offset(),
uniform_inputs.frame_count, uniform_inputs.frame_count,
offset.context(), offset.context(),
device
); );
} }
@ -160,12 +163,13 @@ where
offset.offset(), offset.offset(),
uniform_inputs.frame_direction, uniform_inputs.frame_direction,
offset.context(), offset.context(),
device
); );
} }
// bind Rotation // bind Rotation
if let Some(offset) = uniform_bindings.get(&UniqueSemantics::Rotation.into()) { if let Some(offset) = uniform_bindings.get(&UniqueSemantics::Rotation.into()) {
uniform_storage.bind_scalar(offset.offset(), uniform_inputs.rotation, offset.context()); uniform_storage.bind_scalar(offset.offset(), uniform_inputs.rotation, offset.context(), device);
} }
// bind TotalSubFrames // bind TotalSubFrames
@ -174,6 +178,7 @@ where
offset.offset(), offset.offset(),
uniform_inputs.total_subframes, uniform_inputs.total_subframes,
offset.context(), offset.context(),
device
); );
} }
@ -183,6 +188,7 @@ where
offset.offset(), offset.offset(),
uniform_inputs.current_subframe, uniform_inputs.current_subframe,
offset.context(), offset.context(),
device
); );
} }
@ -194,7 +200,7 @@ where
// bind OriginalSize // bind OriginalSize
if let Some(offset) = uniform_bindings.get(&TextureSemantics::Original.semantics(0).into()) if let Some(offset) = uniform_bindings.get(&TextureSemantics::Original.semantics(0).into())
{ {
uniform_storage.bind_vec4(offset.offset(), original.size(), offset.context()); uniform_storage.bind_vec4(offset.offset(), original.size(), offset.context(), device);
} }
// bind Source sampler // bind Source sampler
@ -204,7 +210,7 @@ where
// bind SourceSize // bind SourceSize
if let Some(offset) = uniform_bindings.get(&TextureSemantics::Source.semantics(0).into()) { if let Some(offset) = uniform_bindings.get(&TextureSemantics::Source.semantics(0).into()) {
uniform_storage.bind_vec4(offset.offset(), source.size(), offset.context()); uniform_storage.bind_vec4(offset.offset(), source.size(), offset.context(), device);
} }
// OriginalHistory0 aliases OriginalHistory // OriginalHistory0 aliases OriginalHistory
@ -218,7 +224,7 @@ where
if let Some(offset) = if let Some(offset) =
uniform_bindings.get(&TextureSemantics::OriginalHistory.semantics(0).into()) uniform_bindings.get(&TextureSemantics::OriginalHistory.semantics(0).into())
{ {
uniform_storage.bind_vec4(offset.offset(), original.size(), offset.context()); uniform_storage.bind_vec4(offset.offset(), original.size(), offset.context(), device);
} }
// bind OriginalHistory1-.. // bind OriginalHistory1-..
@ -240,7 +246,7 @@ where
.semantics(index + 1) .semantics(index + 1)
.into(), .into(),
) { ) {
uniform_storage.bind_vec4(offset.offset(), history.size(), offset.context()); uniform_storage.bind_vec4(offset.offset(), history.size(), offset.context(), device);
} }
} }
@ -262,7 +268,7 @@ where
if let Some(offset) = if let Some(offset) =
uniform_bindings.get(&TextureSemantics::PassOutput.semantics(index).into()) uniform_bindings.get(&TextureSemantics::PassOutput.semantics(index).into())
{ {
uniform_storage.bind_vec4(offset.offset(), output.size(), offset.context()); uniform_storage.bind_vec4(offset.offset(), output.size(), offset.context(), device);
} }
} }
@ -283,7 +289,7 @@ where
if let Some(offset) = if let Some(offset) =
uniform_bindings.get(&TextureSemantics::PassFeedback.semantics(index).into()) uniform_bindings.get(&TextureSemantics::PassFeedback.semantics(index).into())
{ {
uniform_storage.bind_vec4(offset.offset(), feedback.size(), offset.context()); uniform_storage.bind_vec4(offset.offset(), feedback.size(), offset.context(), device);
} }
} }
@ -301,7 +307,7 @@ where
let value = *runtime_parameters.get(id).unwrap_or(&default); let value = *runtime_parameters.get(id).unwrap_or(&default);
uniform_storage.bind_scalar(offset.offset(), value, offset.context()); uniform_storage.bind_scalar(offset.offset(), value, offset.context(), device);
} }
// bind luts // bind luts
@ -314,7 +320,7 @@ where
if let Some(offset) = if let Some(offset) =
uniform_bindings.get(&TextureSemantics::User.semantics(index).into()) uniform_bindings.get(&TextureSemantics::User.semantics(index).into())
{ {
uniform_storage.bind_vec4(offset.offset(), lut.size(), offset.context()); uniform_storage.bind_vec4(offset.offset(), lut.size(), offset.context(), device);
} }
} }
} }

View file

@ -9,13 +9,13 @@ impl UniformScalar for i32 {}
impl UniformScalar for u32 {} impl UniformScalar for u32 {}
/// A trait for a binder that binds the given value and context into the uniform for a shader pass. /// A trait for a binder that binds the given value and context into the uniform for a shader pass.
pub trait BindUniform<C, T> { pub trait BindUniform<C, T, D> {
/// Bind the given value to the shader uniforms given the input context. /// Bind the given value to the shader uniforms given the input context.
/// ///
/// A `BindUniform` implementation should not write to a backing buffer from a [`UniformStorage`](crate::uniforms::UniformStorage). /// A `BindUniform` implementation should not write to a backing buffer from a [`UniformStorage`](crate::uniforms::UniformStorage).
/// If the binding is successful and no writes to a backing buffer is necessary, this function should return `Some(())`. /// If the binding is successful and no writes to a backing buffer is necessary, this function should return `Some(())`.
/// If this function returns `None`, then the value will instead be written to the backing buffer. /// If this function returns `None`, then the value will instead be written to the backing buffer.
fn bind_uniform(block: UniformMemberBlock, value: T, ctx: C) -> Option<()>; fn bind_uniform(block: UniformMemberBlock, value: T, ctx: C, device: &D) -> Option<()>;
} }
/// A trait to access the raw pointer to a backing uniform storage. /// A trait to access the raw pointer to a backing uniform storage.
@ -37,7 +37,7 @@ pub trait UniformStorageAccess {
fn push_slice(&self) -> &[u8]; fn push_slice(&self) -> &[u8];
} }
impl<T, H, U, P> UniformStorageAccess for UniformStorage<T, H, U, P> impl<D, T, H, U, P> UniformStorageAccess for UniformStorage<T, H, U, P, D>
where where
U: Deref<Target = [u8]> + DerefMut, U: Deref<Target = [u8]> + DerefMut,
P: Deref<Target = [u8]> + DerefMut, P: Deref<Target = [u8]> + DerefMut,
@ -62,14 +62,14 @@ where
/// A uniform binder that always returns `None`, and does not do any binding of uniforms. /// A uniform binder that always returns `None`, and does not do any binding of uniforms.
/// All uniform data is thus written into the backing buffer storage. /// All uniform data is thus written into the backing buffer storage.
pub struct NoUniformBinder; pub struct NoUniformBinder;
impl<T> BindUniform<Option<()>, T> for NoUniformBinder { impl<T, D> BindUniform<Option<()>, T, D> for NoUniformBinder {
fn bind_uniform(_: UniformMemberBlock, _: T, _: Option<()>) -> Option<()> { fn bind_uniform(_: UniformMemberBlock, _: T, _: Option<()>, _: &D) -> Option<()> {
None None
} }
} }
/// A helper to bind uniform variables to UBO or Push Constant Buffers. /// A helper to bind uniform variables to UBO or Push Constant Buffers.
pub struct UniformStorage<H = NoUniformBinder, C = Option<()>, U = Box<[u8]>, P = Box<[u8]>> pub struct UniformStorage<H = NoUniformBinder, C = Option<()>, U = Box<[u8]>, P = Box<[u8]>, D=()>
where where
U: Deref<Target = [u8]> + DerefMut, U: Deref<Target = [u8]> + DerefMut,
P: Deref<Target = [u8]> + DerefMut, P: Deref<Target = [u8]> + DerefMut,
@ -78,9 +78,10 @@ where
push: P, push: P,
_h: PhantomData<H>, _h: PhantomData<H>,
_c: PhantomData<C>, _c: PhantomData<C>,
_d: PhantomData<D>
} }
impl<H, C, U, P> UniformStorage<H, C, U, P> impl<H, C, U, P, D> UniformStorage<H, C, U, P, D>
where where
U: Deref<Target = [u8]> + DerefMut, U: Deref<Target = [u8]> + DerefMut,
P: Deref<Target = [u8]> + DerefMut, P: Deref<Target = [u8]> + DerefMut,
@ -103,7 +104,7 @@ where
} }
} }
impl<H, C, U, P> UniformStorage<H, C, U, P> impl<H, C, U, P, D> UniformStorage<H, C, U, P, D>
where where
C: Copy, C: Copy,
U: Deref<Target = [u8]> + DerefMut, U: Deref<Target = [u8]> + DerefMut,
@ -117,12 +118,12 @@ where
/// Bind a scalar to the given offset. /// Bind a scalar to the given offset.
#[inline(always)] #[inline(always)]
pub fn bind_scalar<T: UniformScalar>(&mut self, offset: MemberOffset, value: T, ctx: C) pub fn bind_scalar<T: UniformScalar>(&mut self, offset: MemberOffset, value: T, ctx: C, device: &D)
where where
H: BindUniform<C, T>, H: BindUniform<C, T, D>,
{ {
for ty in UniformMemberBlock::TYPES { for ty in UniformMemberBlock::TYPES {
if H::bind_uniform(ty, value, ctx).is_some() { if H::bind_uniform(ty, value, ctx, device).is_some() {
continue; continue;
} }
@ -134,17 +135,18 @@ where
} }
/// Create a new `UniformStorage` with the given backing storage /// Create a new `UniformStorage` with the given backing storage
pub fn new_with_storage(ubo: U, push: P) -> UniformStorage<H, C, U, P> { pub fn new_with_storage(ubo: U, push: P) -> UniformStorage<H, C, U, P, D> {
UniformStorage { UniformStorage {
ubo, ubo,
push, push,
_h: Default::default(), _h: Default::default(),
_c: Default::default(), _c: Default::default(),
_d: Default::default(),
} }
} }
} }
impl<H, C, U> UniformStorage<H, C, U, Box<[u8]>> impl<H, C, U, D> UniformStorage<H, C, U, Box<[u8]>, D>
where where
C: Copy, C: Copy,
U: Deref<Target = [u8]> + DerefMut, U: Deref<Target = [u8]> + DerefMut,
@ -153,34 +155,36 @@ where
pub fn new_with_ubo_storage( pub fn new_with_ubo_storage(
storage: U, storage: U,
push_size: usize, push_size: usize,
) -> UniformStorage<H, C, U, Box<[u8]>> { ) -> UniformStorage<H, C, U, Box<[u8]>, D> {
UniformStorage { UniformStorage {
ubo: storage, ubo: storage,
push: vec![0u8; push_size].into_boxed_slice(), push: vec![0u8; push_size].into_boxed_slice(),
_h: Default::default(), _h: Default::default(),
_c: Default::default(), _c: Default::default(),
_d: Default::default(),
} }
} }
} }
impl<H, C> UniformStorage<H, C, Box<[u8]>, Box<[u8]>> { impl<H, C, D> UniformStorage<H, C, Box<[u8]>, Box<[u8]>, D> {
/// Create a new `UniformStorage` with the given size for UBO and Push Constant Buffer sizes. /// Create a new `UniformStorage` with the given size for UBO and Push Constant Buffer sizes.
pub fn new(ubo_size: usize, push_size: usize) -> UniformStorage<H, C, Box<[u8]>> { pub fn new(ubo_size: usize, push_size: usize) -> UniformStorage<H, C, Box<[u8]>, Box<[u8]>, D> {
UniformStorage { UniformStorage {
ubo: vec![0u8; ubo_size].into_boxed_slice(), ubo: vec![0u8; ubo_size].into_boxed_slice(),
push: vec![0u8; push_size].into_boxed_slice(), push: vec![0u8; push_size].into_boxed_slice(),
_h: Default::default(), _h: Default::default(),
_c: Default::default(), _c: Default::default(),
_d: Default::default(),
} }
} }
} }
impl<H, C, U, P> UniformStorage<H, C, U, P> impl<H, C, U, P, D> UniformStorage<H, C, U, P, D>
where where
C: Copy, C: Copy,
U: Deref<Target = [u8]> + DerefMut, U: Deref<Target = [u8]> + DerefMut,
P: Deref<Target = [u8]> + DerefMut, P: Deref<Target = [u8]> + DerefMut,
H: for<'a> BindUniform<C, &'a [f32; 4]>, H: for<'a> BindUniform<C, &'a [f32; 4], D>,
{ {
#[inline(always)] #[inline(always)]
fn write_vec4_inner(buffer: &mut [u8], vec4: &[f32; 4]) { fn write_vec4_inner(buffer: &mut [u8], vec4: &[f32; 4]) {
@ -189,11 +193,11 @@ where
} }
/// Bind a `vec4` to the given offset. /// Bind a `vec4` to the given offset.
#[inline(always)] #[inline(always)]
pub fn bind_vec4(&mut self, offset: MemberOffset, value: impl Into<[f32; 4]>, ctx: C) { pub fn bind_vec4(&mut self, offset: MemberOffset, value: impl Into<[f32; 4]>, ctx: C, device: &D) {
let vec4 = value.into(); let vec4 = value.into();
for ty in UniformMemberBlock::TYPES { for ty in UniformMemberBlock::TYPES {
if H::bind_uniform(ty, &vec4, ctx).is_some() { if H::bind_uniform(ty, &vec4, ctx, device).is_some() {
continue; continue;
} }
if let Some(offset) = offset.offset(ty) { if let Some(offset) = offset.offset(ty) {
@ -207,12 +211,12 @@ where
} }
} }
impl<H, C, U, P> UniformStorage<H, C, U, P> impl<H, C, U, P, D> UniformStorage<H, C, U, P, D>
where where
C: Copy, C: Copy,
U: Deref<Target = [u8]> + DerefMut, U: Deref<Target = [u8]> + DerefMut,
P: Deref<Target = [u8]> + DerefMut, P: Deref<Target = [u8]> + DerefMut,
H: for<'a> BindUniform<C, &'a [f32; 16]>, H: for<'a> BindUniform<C, &'a [f32; 16], D>,
{ {
#[inline(always)] #[inline(always)]
fn write_mat4_inner(buffer: &mut [u8], mat4: &[f32; 16]) { fn write_mat4_inner(buffer: &mut [u8], mat4: &[f32; 16]) {
@ -222,9 +226,9 @@ where
/// Bind a `mat4` to the given offset. /// Bind a `mat4` to the given offset.
#[inline(always)] #[inline(always)]
pub fn bind_mat4(&mut self, offset: MemberOffset, value: &[f32; 16], ctx: C) { pub fn bind_mat4(&mut self, offset: MemberOffset, value: &[f32; 16], ctx: C, device: &D) {
for ty in UniformMemberBlock::TYPES { for ty in UniformMemberBlock::TYPES {
if H::bind_uniform(ty, value, ctx).is_some() { if H::bind_uniform(ty, value, ctx, device).is_some() {
continue; continue;
} }
if let Some(offset) = offset.offset(ty) { if let Some(offset) = offset.offset(ty) {