1 // Copyright (c) 2017 The vulkano developers 2 // Licensed under the Apache License, Version 2.0 3 // <LICENSE-APACHE or 4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT 5 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>, 6 // at your option. All files in the project carrying such 7 // notice may not be copied, modified, or distributed except 8 // according to those terms. 9 10 //! A simple, immutable descriptor set that is expected to be long-lived. 11 //! 12 //! Creating a persistent descriptor set allocates from a pool, and can't be modified once created. 13 //! You are therefore encouraged to create them at initialization and not the during 14 //! performance-critical paths. 15 //! 16 //! > **Note**: You can control of the pool that is used to create the descriptor set, if you wish 17 //! > so. By creating a implementation of the `DescriptorPool` trait that doesn't perform any 18 //! > actual allocation, you can skip this allocation and make it acceptable to use a persistent 19 //! > descriptor set in performance-critical paths.. 20 //! 21 //! # Examples 22 //! TODO: 23 24 use crate::{ 25 descriptor_set::{ 26 allocator::{DescriptorSetAlloc, DescriptorSetAllocator, StandardDescriptorSetAlloc}, 27 update::WriteDescriptorSet, 28 DescriptorSet, DescriptorSetCreationError, DescriptorSetInner, DescriptorSetLayout, 29 DescriptorSetResources, UnsafeDescriptorSet, 30 }, 31 device::{Device, DeviceOwned}, 32 VulkanObject, 33 }; 34 use std::{ 35 hash::{Hash, Hasher}, 36 sync::Arc, 37 }; 38 39 /// A simple, immutable descriptor set that is expected to be long-lived. 40 pub struct PersistentDescriptorSet<P = StandardDescriptorSetAlloc> { 41 alloc: P, 42 inner: DescriptorSetInner, 43 } 44 45 impl PersistentDescriptorSet { 46 /// Creates and returns a new descriptor set with a variable descriptor count of 0. 47 /// 48 /// See `new_with_pool` for more. 49 #[inline] new<A>( allocator: &A, layout: Arc<DescriptorSetLayout>, descriptor_writes: impl IntoIterator<Item = WriteDescriptorSet>, ) -> Result<Arc<PersistentDescriptorSet<A::Alloc>>, DescriptorSetCreationError> where A: DescriptorSetAllocator + ?Sized,50 pub fn new<A>( 51 allocator: &A, 52 layout: Arc<DescriptorSetLayout>, 53 descriptor_writes: impl IntoIterator<Item = WriteDescriptorSet>, 54 ) -> Result<Arc<PersistentDescriptorSet<A::Alloc>>, DescriptorSetCreationError> 55 where 56 A: DescriptorSetAllocator + ?Sized, 57 { 58 Self::new_variable(allocator, layout, 0, descriptor_writes) 59 } 60 61 /// Creates and returns a new descriptor set with the requested variable descriptor count, 62 /// allocating it from the provided pool. 63 /// 64 /// # Panics 65 /// 66 /// - Panics if `layout` was created for push descriptors rather than descriptor sets. 67 /// - Panics if `variable_descriptor_count` is too large for the given `layout`. new_variable<A>( allocator: &A, layout: Arc<DescriptorSetLayout>, variable_descriptor_count: u32, descriptor_writes: impl IntoIterator<Item = WriteDescriptorSet>, ) -> Result<Arc<PersistentDescriptorSet<A::Alloc>>, DescriptorSetCreationError> where A: DescriptorSetAllocator + ?Sized,68 pub fn new_variable<A>( 69 allocator: &A, 70 layout: Arc<DescriptorSetLayout>, 71 variable_descriptor_count: u32, 72 descriptor_writes: impl IntoIterator<Item = WriteDescriptorSet>, 73 ) -> Result<Arc<PersistentDescriptorSet<A::Alloc>>, DescriptorSetCreationError> 74 where 75 A: DescriptorSetAllocator + ?Sized, 76 { 77 assert!( 78 !layout.push_descriptor(), 79 "the provided descriptor set layout is for push descriptors, and cannot be used to \ 80 build a descriptor set object", 81 ); 82 83 let max_count = layout.variable_descriptor_count(); 84 85 assert!( 86 variable_descriptor_count <= max_count, 87 "the provided variable_descriptor_count ({}) is greater than the maximum number of \ 88 variable count descriptors in the set ({})", 89 variable_descriptor_count, 90 max_count, 91 ); 92 93 let alloc = allocator.allocate(&layout, variable_descriptor_count)?; 94 let inner = DescriptorSetInner::new( 95 alloc.inner().handle(), 96 layout, 97 variable_descriptor_count, 98 descriptor_writes, 99 )?; 100 101 Ok(Arc::new(PersistentDescriptorSet { alloc, inner })) 102 } 103 } 104 105 unsafe impl<P> DescriptorSet for PersistentDescriptorSet<P> 106 where 107 P: DescriptorSetAlloc, 108 { inner(&self) -> &UnsafeDescriptorSet109 fn inner(&self) -> &UnsafeDescriptorSet { 110 self.alloc.inner() 111 } 112 layout(&self) -> &Arc<DescriptorSetLayout>113 fn layout(&self) -> &Arc<DescriptorSetLayout> { 114 self.inner.layout() 115 } 116 variable_descriptor_count(&self) -> u32117 fn variable_descriptor_count(&self) -> u32 { 118 self.inner.variable_descriptor_count 119 } 120 resources(&self) -> &DescriptorSetResources121 fn resources(&self) -> &DescriptorSetResources { 122 self.inner.resources() 123 } 124 } 125 126 unsafe impl<P> DeviceOwned for PersistentDescriptorSet<P> 127 where 128 P: DescriptorSetAlloc, 129 { device(&self) -> &Arc<Device>130 fn device(&self) -> &Arc<Device> { 131 self.inner.layout().device() 132 } 133 } 134 135 impl<P> PartialEq for PersistentDescriptorSet<P> 136 where 137 P: DescriptorSetAlloc, 138 { eq(&self, other: &Self) -> bool139 fn eq(&self, other: &Self) -> bool { 140 self.inner() == other.inner() 141 } 142 } 143 144 impl<P> Eq for PersistentDescriptorSet<P> where P: DescriptorSetAlloc {} 145 146 impl<P> Hash for PersistentDescriptorSet<P> 147 where 148 P: DescriptorSetAlloc, 149 { hash<H: Hasher>(&self, state: &mut H)150 fn hash<H: Hasher>(&self, state: &mut H) { 151 self.inner().hash(state); 152 } 153 } 154