use smallvec::SmallVec;
use std::{borrow::Borrow, fmt, iter, ops::Range};
use crate::{
buffer::Offset,
image::Layout,
pso::ShaderStageFlags,
Backend,
};
pub type DescriptorSetIndex = u16;
pub type DescriptorBinding = u32;
pub type DescriptorArrayIndex = usize;
#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum DescriptorType {
Sampler = 0,
CombinedImageSampler = 1,
SampledImage = 2,
StorageImage = 3,
UniformTexelBuffer = 4,
StorageTexelBuffer = 5,
UniformBuffer = 6,
StorageBuffer = 7,
UniformBufferDynamic = 8,
StorageBufferDynamic = 9,
InputAttachment = 10,
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct DescriptorSetLayoutBinding {
pub binding: DescriptorBinding,
pub ty: DescriptorType,
pub count: DescriptorArrayIndex,
pub stage_flags: ShaderStageFlags,
pub immutable_samplers: bool,
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct DescriptorRangeDesc {
pub ty: DescriptorType,
pub count: usize,
}
#[derive(Clone, Debug, PartialEq)]
pub enum AllocationError {
Host,
Device,
OutOfPoolMemory,
FragmentedPool,
IncompatibleLayout,
}
impl std::fmt::Display for AllocationError {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
AllocationError::Host => write!(fmt, "Failed to allocate descriptor set: Out of host memory"),
AllocationError::Device => write!(fmt, "Failed to allocate descriptor set: Out of device memory"),
AllocationError::OutOfPoolMemory => write!(fmt, "Failed to allocate descriptor set: Out of pool memory"),
AllocationError::FragmentedPool => write!(fmt, "Failed to allocate descriptor set: Pool is fragmented"),
AllocationError::IncompatibleLayout => write!(fmt, "Failed to allocate descriptor set: Incompatible layout"),
}
}
}
impl std::error::Error for AllocationError {}
pub trait DescriptorPool<B: Backend>: Send + Sync + fmt::Debug {
unsafe fn allocate_set(
&mut self,
layout: &B::DescriptorSetLayout,
) -> Result<B::DescriptorSet, AllocationError> {
let mut sets = SmallVec::new();
self.allocate_sets(iter::once(layout), &mut sets)
.map(|_| sets.remove(0))
}
unsafe fn allocate_sets<I>(
&mut self,
layouts: I,
sets: &mut SmallVec<[B::DescriptorSet; 1]>,
) -> Result<(), AllocationError>
where
I: IntoIterator,
I::Item: Borrow<B::DescriptorSetLayout>,
{
let base = sets.len();
for layout in layouts {
match self.allocate_set(layout.borrow()) {
Ok(set) => sets.push(set),
Err(e) => {
while sets.len() != base {
self.free_sets(sets.pop());
}
return Err(e);
}
}
}
Ok(())
}
unsafe fn free_sets<I>(&mut self, descriptor_sets: I)
where
I: IntoIterator<Item = B::DescriptorSet>;
unsafe fn reset(&mut self);
}
#[allow(missing_docs)]
#[derive(Debug)]
pub struct DescriptorSetWrite<'a, B: Backend, WI>
where
WI: IntoIterator,
WI::Item: Borrow<Descriptor<'a, B>>,
{
pub set: &'a B::DescriptorSet,
pub binding: DescriptorBinding,
pub array_offset: DescriptorArrayIndex,
pub descriptors: WI,
}
#[allow(missing_docs)]
#[derive(Clone, Debug)]
pub enum Descriptor<'a, B: Backend> {
Sampler(&'a B::Sampler),
Image(&'a B::ImageView, Layout),
CombinedImageSampler(&'a B::ImageView, Layout, &'a B::Sampler),
Buffer(&'a B::Buffer, Range<Option<Offset>>),
UniformTexelBuffer(&'a B::BufferView),
StorageTexelBuffer(&'a B::BufferView),
}
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug)]
pub struct DescriptorSetCopy<'a, B: Backend> {
pub src_set: &'a B::DescriptorSet,
pub src_binding: DescriptorBinding,
pub src_array_offset: DescriptorArrayIndex,
pub dst_set: &'a B::DescriptorSet,
pub dst_binding: DescriptorBinding,
pub dst_array_offset: DescriptorArrayIndex,
pub count: usize,
}
bitflags! {
pub struct DescriptorPoolCreateFlags: u32 {
const FREE_DESCRIPTOR_SET = 0x1;
}
}