mod buffer;
mod image;
mod sampler;
pub use self::buffer::TypedBuffer;
use crate::{sealed::Sealed, DescriptorBindingFlags, DescriptorKind, Device, Encoder, OutOfMemory};
pub trait DescriptorBinding<K: DescriptorKind> {
const FLAGS: DescriptorBindingFlags;
fn is_compatible(&self, descriptor: &K::Descriptor) -> bool;
#[inline]
fn update_descriptor(
&mut self,
device: &Device,
encoder: &mut Encoder,
descriptor: &K::Descriptor,
) -> Result<(), OutOfMemory> {
let _ = device;
let _ = encoder;
let _ = descriptor;
Ok(())
}
fn get_descriptor(&self, device: &Device) -> Result<K::Descriptor, OutOfMemory>;
}
pub trait DescriptorBindingArray<K> {
const COUNT: u32;
const FLAGS: DescriptorBindingFlags;
type DescriptorArray;
fn is_compatible(&self, descriptors: &Self::DescriptorArray) -> bool;
#[inline]
fn update_descriptors(
&mut self,
device: &Device,
encoder: &mut Encoder,
descriptors: &Self::DescriptorArray,
) -> Result<(), OutOfMemory> {
let _ = device;
let _ = encoder;
let _ = descriptors;
Ok(())
}
fn get_descriptors(&self, device: &Device) -> Result<Self::DescriptorArray, OutOfMemory>;
}
impl<K, T> DescriptorBindingArray<K> for T
where
K: DescriptorKind,
T: DescriptorBinding<K> + Sealed,
{
const COUNT: u32 = 1;
const FLAGS: DescriptorBindingFlags = <T as DescriptorBinding<K>>::FLAGS;
type DescriptorArray = [K::Descriptor; 1];
#[inline]
fn is_compatible(&self, descriptors: &[K::Descriptor; 1]) -> bool {
<T as DescriptorBinding<K>>::is_compatible(self, &descriptors[0])
}
#[inline]
fn update_descriptors(
&mut self,
device: &Device,
encoder: &mut Encoder,
descriptors: &[K::Descriptor; 1],
) -> Result<(), OutOfMemory> {
<T as DescriptorBinding<K>>::update_descriptor(self, device, encoder, &descriptors[0])
}
#[inline]
fn get_descriptors(&self, device: &Device) -> Result<[K::Descriptor; 1], OutOfMemory> {
Ok([<T as DescriptorBinding<K>>::get_descriptor(self, device)?])
}
}
impl<K, T, const N: usize> DescriptorBindingArray<K> for [T; N]
where
K: DescriptorKind,
T: DescriptorBinding<K> + Sealed,
{
const COUNT: u32 = N as u32;
const FLAGS: DescriptorBindingFlags = <T as DescriptorBinding<K>>::FLAGS;
type DescriptorArray = [K::Descriptor; N];
#[inline]
fn is_compatible(&self, descriptors: &[K::Descriptor; N]) -> bool {
for i in 0..N {
if !<T as DescriptorBinding<K>>::is_compatible(&self[i], &descriptors[i]) {
return false;
}
}
true
}
#[inline]
fn update_descriptors(
&mut self,
device: &Device,
encoder: &mut Encoder,
descriptors: &[K::Descriptor; N],
) -> Result<(), OutOfMemory> {
for i in 0..N {
<T as DescriptorBinding<K>>::update_descriptor(
&mut self[i],
device,
encoder,
&descriptors[i],
)?;
}
Ok(())
}
#[inline]
fn get_descriptors(&self, device: &Device) -> Result<[K::Descriptor; N], OutOfMemory> {
Ok(array_fu::array![i => <T as DescriptorBinding<K>>::get_descriptor(&self[i], device)?; N])
}
}
impl<T, K, const N: usize> DescriptorBindingArray<K> for arrayvec::ArrayVec<T, N>
where
K: DescriptorKind,
T: DescriptorBinding<K>,
{
const COUNT: u32 = N as u32;
const FLAGS: DescriptorBindingFlags = with_partially_bound(<T as DescriptorBinding<K>>::FLAGS);
type DescriptorArray = arrayvec::ArrayVec<K::Descriptor, N>;
#[inline]
fn is_compatible(&self, descriptors: &arrayvec::ArrayVec<K::Descriptor, N>) -> bool {
if self.len() != descriptors.len() {
return false;
}
for i in 0..self.len() {
if !<T as DescriptorBinding<K>>::is_compatible(&self[i], &descriptors[i]) {
return false;
}
}
true
}
#[inline]
fn update_descriptors(
&mut self,
device: &Device,
encoder: &mut Encoder,
descriptors: &arrayvec::ArrayVec<K::Descriptor, N>,
) -> Result<(), OutOfMemory> {
assert_eq!(self.len(), descriptors.len());
for (i, elem) in self.iter_mut().enumerate() {
<T as DescriptorBinding<K>>::update_descriptor(elem, device, encoder, &descriptors[i])?;
}
Ok(())
}
#[inline]
fn get_descriptors(
&self,
device: &Device,
) -> Result<arrayvec::ArrayVec<K::Descriptor, N>, OutOfMemory> {
let mut result = arrayvec::ArrayVec::new_const();
for elem in self {
result.push(elem.get_descriptor(device)?);
}
Ok(result)
}
}
macro_rules! impl_for_refs {
(impl[$($bounds:tt)+] for $t:ty) => {
impl_for_refs!(exclusive impl[$($bounds)+] for &mut $t);
impl_for_refs!(exclusive impl[$($bounds)+] for Box<$t>);
};
(exclusive impl[$($bounds:tt)+] for $ref_ty:ty) => {
impl< $($bounds)+ > DescriptorBinding<K> for $ref_ty
where
K: DescriptorKind,
T: DescriptorBinding<K> + Sealed,
{
const FLAGS: DescriptorBindingFlags = T::FLAGS;
#[inline]
fn is_compatible(&self, descriptor: &K::Descriptor) -> bool {
T::is_compatible(self, descriptor)
}
#[inline]
fn update_descriptor(
&mut self,
device: &Device,
encoder: &mut Encoder,
descriptor: &K::Descriptor,
) -> Result<(), OutOfMemory> {
T::update_descriptor(self, device, encoder, descriptor)
}
#[inline]
fn get_descriptor(
&self,
device: &Device,
) -> Result<K::Descriptor, OutOfMemory> {
T::get_descriptor(&self, device)
}
}
};
(shared impl[$($bounds:tt)+] for $ref_ty:ty) => {
impl< $($bounds)+ > DescriptorBinding<K> for $ref_ty
where
K: DescriptorKind,
T: ShareableDescriptorBinding<K> + DescriptorBinding<K> + Sealed,
{
const FLAGS: DescriptorBindingFlags = T::FLAGS;
#[inline]
fn is_compatible(&self, descriptor: &K::Descriptor) -> bool {
T::is_compatible(self, descriptor)
}
#[inline]
fn get_descriptor(
&self,
device: &Device,
) -> Result<K::Descriptor, OutOfMemory> {
T::get_descriptor(&self, device)
}
}
};
}
impl_for_refs!(impl[K, T] for T);
const fn with_partially_bound(flags: DescriptorBindingFlags) -> DescriptorBindingFlags {
DescriptorBindingFlags::from_bits_truncate(
flags.bits() | DescriptorBindingFlags::PARTIALLY_BOUND.bits(),
)
}
macro_rules! impl_array_for_refs {
(impl<K, T, const N: usize> for $t:ty where $flags:expr; $descriptors:ty) => {
impl_array_for_refs!(exclusive impl<K, T, const N: usize> for &mut $t | $t where $flags; $descriptors);
impl_array_for_refs!(exclusive impl<K, T, const N: usize> for Box<$t> | $t where $flags; $descriptors);
};
(exclusive impl<K, T, const N: usize> for $ref_ty:ty | $t:ty where $flags:expr; $descriptors:ty) => {
impl<K, T, const N: usize> DescriptorBindingArray<K> for $ref_ty
where
K: DescriptorKind,
T: DescriptorBinding<K> + Sealed,
{
const COUNT: u32 = N as u32;
const FLAGS: DescriptorBindingFlags = $flags;
type DescriptorArray = $descriptors;
#[inline]
fn is_compatible(
&self,
descriptors: &$descriptors,
) -> bool {
<$t>::is_compatible(self, descriptors)
}
#[inline]
fn update_descriptors(
&mut self,
device: &Device,
encoder: &mut Encoder,
descriptors: &$descriptors
) -> Result<(), OutOfMemory> {
<$t>::update_descriptors(self, device, encoder, descriptors)
}
#[inline]
fn get_descriptors(
&self,
device: &Device,
) -> Result<$descriptors, OutOfMemory> {
<$t>::get_descriptors(self, device)
}
}
};
(shared impl<K, T, const N: usize> for $ref_ty:ty | $t:ty where $flags:expr; $descriptors:ty) => {
impl<K, T, const N: usize> DescriptorBindingArray<K> for $ref_ty
where
K: DescriptorKind,
T: ShareableDescriptorBinding<K> + Sealed,
{
const COUNT: u32 = N as u32;
const FLAGS: DescriptorBindingFlags = with_partially_bound(<T as DescriptorBinding<K>>::FLAGS);
type DescriptorArray = $descriptors;
#[inline]
fn is_compatible(
&self,
descriptors: &$descriptors,
) -> bool {
<$t>::is_compatible(self, descriptors)
}
#[inline]
fn get_descriptors(
&self,
device: &Device,
) -> Result<$descriptors, OutOfMemory> {
<$t>::get_descriptors(self, device)
}
}
};
}
impl_array_for_refs!(impl<K, T, const N: usize> for [T; N] where T::FLAGS; [K::Descriptor; N]);
impl_array_for_refs!(impl<K, T, const N: usize> for arrayvec::ArrayVec<T, N> where with_partially_bound(T::FLAGS); arrayvec::ArrayVec<K::Descriptor, N>);