rt: pass device context to uniform binder if needed
This commit is contained in:
parent
af3ea252ba
commit
7593f9f9b5
5 changed files with 71 additions and 59 deletions
|
@ -59,11 +59,11 @@ impl GlUniformScalar for u32 {
|
|||
}
|
||||
|
||||
pub(crate) struct GlUniformBinder;
|
||||
impl<T> BindUniform<VariableLocation, T> for GlUniformBinder
|
||||
impl<T> BindUniform<VariableLocation, T, ()> for GlUniformBinder
|
||||
where
|
||||
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)
|
||||
&& location.bindable()
|
||||
{
|
||||
|
@ -84,11 +84,12 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl BindUniform<VariableLocation, &[f32; 4]> for GlUniformBinder {
|
||||
impl BindUniform<VariableLocation, &[f32; 4], ()> for GlUniformBinder {
|
||||
fn bind_uniform(
|
||||
block: UniformMemberBlock,
|
||||
vec4: &[f32; 4],
|
||||
location: VariableLocation,
|
||||
_: &()
|
||||
) -> Option<()> {
|
||||
if let Some(location) = location.location(block)
|
||||
&& 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(
|
||||
block: UniformMemberBlock,
|
||||
mat4: &[f32; 16],
|
||||
location: VariableLocation,
|
||||
_: &()
|
||||
) -> Option<()> {
|
||||
if let Some(location) = location.location(block)
|
||||
&& location.bindable()
|
||||
|
|
|
@ -24,7 +24,7 @@ use std::sync::Arc;
|
|||
|
||||
pub struct FilterPass {
|
||||
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 source: ShaderSource,
|
||||
pub config: ShaderPassConfig,
|
||||
|
|
|
@ -26,7 +26,7 @@ pub struct FilterPass {
|
|||
pub device: Arc<wgpu::Device>,
|
||||
pub reflection: ShaderReflection,
|
||||
pub(crate) uniform_storage:
|
||||
UniformStorage<NoUniformBinder, Option<()>, WgpuStagedBuffer, WgpuStagedBuffer>,
|
||||
UniformStorage<NoUniformBinder, Option<()>, WgpuStagedBuffer, WgpuStagedBuffer, Arc<wgpu::Device>>,
|
||||
pub uniform_bindings: FastHashMap<UniformBinding, MemberOffset>,
|
||||
pub source: ShaderSource,
|
||||
pub config: ShaderPassConfig,
|
||||
|
|
|
@ -15,13 +15,13 @@ pub trait TextureInput {
|
|||
}
|
||||
|
||||
/// A uniform member offset with context that needs to be resolved.
|
||||
pub trait ContextOffset<H, C>
|
||||
pub trait ContextOffset<H, C, D=()>
|
||||
where
|
||||
H: BindUniform<C, f32>,
|
||||
H: BindUniform<C, u32>,
|
||||
H: BindUniform<C, i32>,
|
||||
H: for<'a> BindUniform<C, &'a [f32; 4]>,
|
||||
H: for<'a> BindUniform<C, &'a [f32; 16]>,
|
||||
H: BindUniform<C, f32, D>,
|
||||
H: BindUniform<C, u32, D>,
|
||||
H: BindUniform<C, i32, D>,
|
||||
H: for<'a> BindUniform<C, &'a [f32; 4], D>,
|
||||
H: for<'a> BindUniform<C, &'a [f32; 16], D>,
|
||||
{
|
||||
/// Gets the `MemberOffset` part of the offset.
|
||||
fn offset(&self) -> MemberOffset;
|
||||
|
@ -30,13 +30,13 @@ where
|
|||
fn context(&self) -> C;
|
||||
}
|
||||
|
||||
impl<H> ContextOffset<H, Option<()>> for MemberOffset
|
||||
impl<D, H> ContextOffset<H, Option<()>, D> for MemberOffset
|
||||
where
|
||||
H: BindUniform<Option<()>, f32>,
|
||||
H: BindUniform<Option<()>, u32>,
|
||||
H: BindUniform<Option<()>, i32>,
|
||||
H: for<'a> BindUniform<Option<()>, &'a [f32; 4]>,
|
||||
H: for<'a> BindUniform<Option<()>, &'a [f32; 16]>,
|
||||
H: BindUniform<Option<()>, f32, D>,
|
||||
H: BindUniform<Option<()>, u32, D>,
|
||||
H: BindUniform<Option<()>, i32, D>,
|
||||
H: for<'a> BindUniform<Option<()>, &'a [f32; 4], D>,
|
||||
H: for<'a> BindUniform<Option<()>, &'a [f32; 16], D>,
|
||||
{
|
||||
fn offset(&self) -> MemberOffset {
|
||||
*self
|
||||
|
@ -73,11 +73,11 @@ where
|
|||
C: Copy,
|
||||
U: Deref<Target = [u8]> + DerefMut,
|
||||
P: Deref<Target = [u8]> + DerefMut,
|
||||
H: BindUniform<C, f32>,
|
||||
H: BindUniform<C, u32>,
|
||||
H: BindUniform<C, i32>,
|
||||
H: for<'b> BindUniform<C, &'b [f32; 4]>,
|
||||
H: for<'b> BindUniform<C, &'b [f32; 16]>,
|
||||
H: BindUniform<C, f32, Self::DeviceContext>,
|
||||
H: BindUniform<C, u32, Self::DeviceContext>,
|
||||
H: BindUniform<C, i32, Self::DeviceContext>,
|
||||
H: for<'b> BindUniform<C, &'b [f32; 4], Self::DeviceContext>,
|
||||
H: for<'b> BindUniform<C, &'b [f32; 16], Self::DeviceContext>,
|
||||
{
|
||||
/// The type of the input texture used for semantic binding.
|
||||
type InputTexture: TextureInput;
|
||||
|
@ -92,7 +92,7 @@ where
|
|||
type DeviceContext;
|
||||
|
||||
/// 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
|
||||
fn bind_texture<'a>(
|
||||
|
@ -108,7 +108,7 @@ where
|
|||
fn bind_semantics<'a>(
|
||||
device: &Self::DeviceContext,
|
||||
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>,
|
||||
uniform_inputs: UniformInputs<'_>,
|
||||
original: &Self::InputTexture,
|
||||
|
@ -124,7 +124,7 @@ where
|
|||
) {
|
||||
// Bind MVP
|
||||
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
|
||||
|
@ -133,6 +133,7 @@ where
|
|||
offset.offset(),
|
||||
uniform_inputs.framebuffer_size,
|
||||
offset.context(),
|
||||
device
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -142,6 +143,7 @@ where
|
|||
offset.offset(),
|
||||
uniform_inputs.viewport_size,
|
||||
offset.context(),
|
||||
device
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -151,6 +153,7 @@ where
|
|||
offset.offset(),
|
||||
uniform_inputs.frame_count,
|
||||
offset.context(),
|
||||
device
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -160,12 +163,13 @@ where
|
|||
offset.offset(),
|
||||
uniform_inputs.frame_direction,
|
||||
offset.context(),
|
||||
device
|
||||
);
|
||||
}
|
||||
|
||||
// bind Rotation
|
||||
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
|
||||
|
@ -174,6 +178,7 @@ where
|
|||
offset.offset(),
|
||||
uniform_inputs.total_subframes,
|
||||
offset.context(),
|
||||
device
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -183,6 +188,7 @@ where
|
|||
offset.offset(),
|
||||
uniform_inputs.current_subframe,
|
||||
offset.context(),
|
||||
device
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -194,7 +200,7 @@ where
|
|||
// bind OriginalSize
|
||||
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
|
||||
|
@ -204,7 +210,7 @@ where
|
|||
|
||||
// bind SourceSize
|
||||
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
|
||||
|
@ -218,7 +224,7 @@ where
|
|||
if let Some(offset) =
|
||||
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-..
|
||||
|
@ -240,7 +246,7 @@ where
|
|||
.semantics(index + 1)
|
||||
.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) =
|
||||
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) =
|
||||
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);
|
||||
|
||||
uniform_storage.bind_scalar(offset.offset(), value, offset.context());
|
||||
uniform_storage.bind_scalar(offset.offset(), value, offset.context(), device);
|
||||
}
|
||||
|
||||
// bind luts
|
||||
|
@ -314,7 +320,7 @@ where
|
|||
if let Some(offset) =
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,13 +9,13 @@ impl UniformScalar for i32 {}
|
|||
impl UniformScalar for u32 {}
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// 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 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.
|
||||
|
@ -37,7 +37,7 @@ pub trait UniformStorageAccess {
|
|||
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
|
||||
U: 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.
|
||||
/// All uniform data is thus written into the backing buffer storage.
|
||||
pub struct NoUniformBinder;
|
||||
impl<T> BindUniform<Option<()>, T> for NoUniformBinder {
|
||||
fn bind_uniform(_: UniformMemberBlock, _: T, _: Option<()>) -> Option<()> {
|
||||
impl<T, D> BindUniform<Option<()>, T, D> for NoUniformBinder {
|
||||
fn bind_uniform(_: UniformMemberBlock, _: T, _: Option<()>, _: &D) -> Option<()> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// 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
|
||||
U: Deref<Target = [u8]> + DerefMut,
|
||||
P: Deref<Target = [u8]> + DerefMut,
|
||||
|
@ -78,9 +78,10 @@ where
|
|||
push: P,
|
||||
_h: PhantomData<H>,
|
||||
_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
|
||||
U: 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
|
||||
C: Copy,
|
||||
U: Deref<Target = [u8]> + DerefMut,
|
||||
|
@ -117,12 +118,12 @@ where
|
|||
|
||||
/// Bind a scalar to the given offset.
|
||||
#[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
|
||||
H: BindUniform<C, T>,
|
||||
H: BindUniform<C, T, D>,
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -134,17 +135,18 @@ where
|
|||
}
|
||||
|
||||
/// 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 {
|
||||
ubo,
|
||||
push,
|
||||
_h: 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
|
||||
C: Copy,
|
||||
U: Deref<Target = [u8]> + DerefMut,
|
||||
|
@ -153,34 +155,36 @@ where
|
|||
pub fn new_with_ubo_storage(
|
||||
storage: U,
|
||||
push_size: usize,
|
||||
) -> UniformStorage<H, C, U, Box<[u8]>> {
|
||||
) -> UniformStorage<H, C, U, Box<[u8]>, D> {
|
||||
UniformStorage {
|
||||
ubo: storage,
|
||||
push: vec![0u8; push_size].into_boxed_slice(),
|
||||
_h: 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.
|
||||
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 {
|
||||
ubo: vec![0u8; ubo_size].into_boxed_slice(),
|
||||
push: vec![0u8; push_size].into_boxed_slice(),
|
||||
_h: 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
|
||||
C: Copy,
|
||||
U: 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)]
|
||||
fn write_vec4_inner(buffer: &mut [u8], vec4: &[f32; 4]) {
|
||||
|
@ -189,11 +193,11 @@ where
|
|||
}
|
||||
/// Bind a `vec4` to the given offset.
|
||||
#[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();
|
||||
|
||||
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;
|
||||
}
|
||||
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
|
||||
C: Copy,
|
||||
U: 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)]
|
||||
fn write_mat4_inner(buffer: &mut [u8], mat4: &[f32; 16]) {
|
||||
|
@ -222,9 +226,9 @@ where
|
|||
|
||||
/// Bind a `mat4` to the given offset.
|
||||
#[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 {
|
||||
if H::bind_uniform(ty, value, ctx).is_some() {
|
||||
if H::bind_uniform(ty, value, ctx, device).is_some() {
|
||||
continue;
|
||||
}
|
||||
if let Some(offset) = offset.offset(ty) {
|
||||
|
|
Loading…
Add table
Reference in a new issue