aboutsummaryrefslogtreecommitdiff
path: root/rendy-descriptor/src/ranges.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rendy-descriptor/src/ranges.rs')
-rw-r--r--rendy-descriptor/src/ranges.rs278
1 files changed, 278 insertions, 0 deletions
diff --git a/rendy-descriptor/src/ranges.rs b/rendy-descriptor/src/ranges.rs
new file mode 100644
index 0000000..d936ab1
--- /dev/null
+++ b/rendy-descriptor/src/ranges.rs
@@ -0,0 +1,278 @@
+use std::{
+ cmp::Ordering,
+ ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign},
+};
+
+pub use gfx_hal::pso::{
+ BufferDescriptorFormat, BufferDescriptorType, DescriptorRangeDesc, DescriptorSetLayoutBinding,
+ DescriptorType, ImageDescriptorType,
+};
+
+const DESCRIPTOR_TYPES_COUNT: usize = 11;
+
+const DESCRIPTOR_TYPES: [DescriptorType; DESCRIPTOR_TYPES_COUNT] = [
+ DescriptorType::Sampler,
+ DescriptorType::Image {
+ ty: ImageDescriptorType::Sampled { with_sampler: true },
+ },
+ DescriptorType::Image {
+ ty: ImageDescriptorType::Sampled {
+ with_sampler: false,
+ },
+ },
+ DescriptorType::Image {
+ ty: ImageDescriptorType::Storage { read_only: false },
+ },
+ DescriptorType::Buffer {
+ ty: BufferDescriptorType::Storage { read_only: false },
+ format: BufferDescriptorFormat::Structured {
+ dynamic_offset: true,
+ },
+ },
+ DescriptorType::Buffer {
+ ty: BufferDescriptorType::Uniform,
+ format: BufferDescriptorFormat::Structured {
+ dynamic_offset: true,
+ },
+ },
+ DescriptorType::Buffer {
+ ty: BufferDescriptorType::Storage { read_only: false },
+ format: BufferDescriptorFormat::Structured {
+ dynamic_offset: false,
+ },
+ },
+ DescriptorType::Buffer {
+ ty: BufferDescriptorType::Uniform,
+ format: BufferDescriptorFormat::Structured {
+ dynamic_offset: false,
+ },
+ },
+ DescriptorType::Buffer {
+ ty: BufferDescriptorType::Storage { read_only: false },
+ format: BufferDescriptorFormat::Texel,
+ },
+ DescriptorType::Buffer {
+ ty: BufferDescriptorType::Uniform,
+ format: BufferDescriptorFormat::Texel,
+ },
+ DescriptorType::InputAttachment,
+];
+
+fn descriptor_type_index(ty: &DescriptorType) -> usize {
+ match ty {
+ DescriptorType::Sampler => 0,
+ DescriptorType::Image {
+ ty: ImageDescriptorType::Sampled { with_sampler: true },
+ } => 1,
+ DescriptorType::Image {
+ ty: ImageDescriptorType::Sampled {
+ with_sampler: false,
+ },
+ } => 2,
+ DescriptorType::Image {
+ ty: ImageDescriptorType::Storage { read_only: _ },
+ } => 3,
+ DescriptorType::Buffer {
+ ty: BufferDescriptorType::Storage { read_only: _ },
+ format:
+ BufferDescriptorFormat::Structured {
+ dynamic_offset: true,
+ },
+ } => 4,
+ DescriptorType::Buffer {
+ ty: BufferDescriptorType::Uniform,
+ format:
+ BufferDescriptorFormat::Structured {
+ dynamic_offset: true,
+ },
+ } => 5,
+ DescriptorType::Buffer {
+ ty: BufferDescriptorType::Storage { read_only: _ },
+ format:
+ BufferDescriptorFormat::Structured {
+ dynamic_offset: false,
+ },
+ } => 6,
+ DescriptorType::Buffer {
+ ty: BufferDescriptorType::Uniform,
+ format:
+ BufferDescriptorFormat::Structured {
+ dynamic_offset: false,
+ },
+ } => 7,
+ DescriptorType::Buffer {
+ ty: BufferDescriptorType::Storage { read_only: _ },
+ format: BufferDescriptorFormat::Texel,
+ } => 8,
+ DescriptorType::Buffer {
+ ty: BufferDescriptorType::Uniform,
+ format: BufferDescriptorFormat::Texel,
+ } => 9,
+ DescriptorType::InputAttachment => 10,
+ }
+}
+
+/// Number of descriptors per type.
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+pub struct DescriptorRanges {
+ counts: [u32; DESCRIPTOR_TYPES_COUNT],
+}
+
+impl DescriptorRanges {
+ /// Create new instance without descriptors.
+ pub fn zero() -> Self {
+ DescriptorRanges {
+ counts: [0; DESCRIPTOR_TYPES_COUNT],
+ }
+ }
+
+ /// Add a single layout binding.
+ /// Useful when created with `DescriptorRanges::zero()`.
+ pub fn add_binding(&mut self, binding: DescriptorSetLayoutBinding) {
+ self.counts[descriptor_type_index(&binding.ty)] += binding.count as u32;
+ }
+
+ /// Iterate through ranges yelding
+ /// descriptor types and their amount.
+ pub fn iter(&self) -> DescriptorRangesIter<'_> {
+ DescriptorRangesIter {
+ counts: &self.counts,
+ index: 0,
+ }
+ }
+
+ /// Read as slice.
+ pub fn counts(&self) -> &[u32] {
+ &self.counts
+ }
+
+ /// Read or write as slice.
+ pub fn counts_mut(&mut self) -> &mut [u32] {
+ &mut self.counts
+ }
+
+ /// Calculate ranges from bindings.
+ pub fn from_bindings(bindings: &[DescriptorSetLayoutBinding]) -> Self {
+ let mut descs = Self::zero();
+
+ for binding in bindings {
+ descs.counts[descriptor_type_index(&binding.ty)] += binding.count as u32;
+ }
+
+ descs
+ }
+
+ /// Calculate ranges from bindings, specified with an iterator.
+ pub fn from_binding_iter<I>(bindings: I) -> Self
+ where
+ I: Iterator<Item = DescriptorSetLayoutBinding>,
+ {
+ let mut descs = Self::zero();
+
+ for binding in bindings {
+ descs.counts[descriptor_type_index(&binding.ty)] += binding.count as u32;
+ }
+
+ descs
+ }
+}
+
+impl PartialOrd for DescriptorRanges {
+ fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
+ let mut ord = self.counts[0].partial_cmp(&other.counts[0])?;
+ for i in 1..DESCRIPTOR_TYPES_COUNT {
+ match (ord, self.counts[i].partial_cmp(&other.counts[i])?) {
+ (Ordering::Less, Ordering::Greater) | (Ordering::Greater, Ordering::Less) => {
+ return None;
+ }
+ (Ordering::Equal, new) => ord = new,
+ _ => (),
+ }
+ }
+ Some(ord)
+ }
+}
+
+impl Add for DescriptorRanges {
+ type Output = Self;
+ fn add(mut self, rhs: Self) -> Self {
+ self += rhs;
+ self
+ }
+}
+
+impl AddAssign for DescriptorRanges {
+ fn add_assign(&mut self, rhs: Self) {
+ for i in 0..DESCRIPTOR_TYPES_COUNT {
+ self.counts[i] += rhs.counts[i];
+ }
+ }
+}
+
+impl Sub for DescriptorRanges {
+ type Output = Self;
+ fn sub(mut self, rhs: Self) -> Self {
+ self -= rhs;
+ self
+ }
+}
+
+impl SubAssign for DescriptorRanges {
+ fn sub_assign(&mut self, rhs: Self) {
+ for i in 0..DESCRIPTOR_TYPES_COUNT {
+ self.counts[i] -= rhs.counts[i];
+ }
+ }
+}
+
+impl Mul<u32> for DescriptorRanges {
+ type Output = Self;
+ fn mul(mut self, rhs: u32) -> Self {
+ self *= rhs;
+ self
+ }
+}
+
+impl MulAssign<u32> for DescriptorRanges {
+ fn mul_assign(&mut self, rhs: u32) {
+ for i in 0..DESCRIPTOR_TYPES_COUNT {
+ self.counts[i] *= rhs;
+ }
+ }
+}
+
+impl<'a> IntoIterator for &'a DescriptorRanges {
+ type Item = DescriptorRangeDesc;
+ type IntoIter = DescriptorRangesIter<'a>;
+
+ fn into_iter(self) -> DescriptorRangesIter<'a> {
+ self.iter()
+ }
+}
+
+/// Iterator over descriptor ranges.
+pub struct DescriptorRangesIter<'a> {
+ counts: &'a [u32; DESCRIPTOR_TYPES_COUNT],
+ index: u8,
+}
+
+impl<'a> Iterator for DescriptorRangesIter<'a> {
+ type Item = DescriptorRangeDesc;
+
+ fn next(&mut self) -> Option<DescriptorRangeDesc> {
+ loop {
+ let index = self.index as usize;
+ if index >= DESCRIPTOR_TYPES_COUNT {
+ return None;
+ } else {
+ self.index += 1;
+ if self.counts[index] > 0 {
+ return Some(DescriptorRangeDesc {
+ count: self.counts[index] as usize,
+ ty: DESCRIPTOR_TYPES[index],
+ });
+ }
+ }
+ }
+ }
+}