bedrock/
descriptor.rs

1//! Vulkan Descriptors
2
3use derives::implements;
4
5use crate::ffi_helper::{ArrayFFIExtensions, slice_as_ptr_empty_null};
6use crate::*;
7
8/// Opaque handle to a descriptor set layout object
9#[derive(VkHandle, VkObject)]
10#[VkObject(type = VkDescriptorSetLayout::OBJECT_TYPE)]
11pub struct DescriptorSetLayoutObject<Device: VkHandle<Handle = VkDevice>>(
12    pub(crate) VkDescriptorSetLayout,
13    pub(crate) Device,
14);
15#[implements]
16impl<Device: VkHandle<Handle = VkDevice>> Drop for DescriptorSetLayoutObject<Device> {
17    #[inline(always)]
18    fn drop(&mut self) {
19        unsafe {
20            crate::vkfn::destroy_descriptor_set_layout(self.1.native_ptr(), self.0, core::ptr::null());
21        }
22    }
23}
24unsafe impl<Device: VkHandle<Handle = VkDevice> + Sync> Sync for DescriptorSetLayoutObject<Device> {}
25unsafe impl<Device: VkHandle<Handle = VkDevice> + Send> Send for DescriptorSetLayoutObject<Device> {}
26impl<Device: VkHandle<Handle = VkDevice>> DeviceChildHandle for DescriptorSetLayoutObject<Device> {
27    #[inline(always)]
28    fn device_handle(&self) -> VkDevice {
29        self.1.native_ptr()
30    }
31}
32impl<Device: crate::Device> DeviceChild for DescriptorSetLayoutObject<Device> {
33    type ConcreteDevice = Device;
34
35    #[inline(always)]
36    fn device(&self) -> &Self::ConcreteDevice {
37        &self.1
38    }
39}
40impl<Device: crate::Device> DescriptorSetLayout for DescriptorSetLayoutObject<Device> {}
41impl<Device: VkHandle<Handle = VkDevice>> DescriptorSetLayoutObject<Device> {
42    /// Create a new descriptor set layout
43    /// # Failures
44    /// On failure, this command returns
45    ///
46    /// - [`VK_ERROR_OUT_OF_HOST_MEMORY`]
47    /// - [`VK_ERROR_OUT_OF_DEVICE_MEMORY`]
48    #[implements]
49    pub fn new(device: Device, info: &DescriptorSetLayoutCreateInfo) -> crate::Result<Self> {
50        let mut h = core::mem::MaybeUninit::uninit();
51
52        unsafe {
53            crate::vkfn::create_descriptor_set_layout(device.native_ptr(), &info.0, core::ptr::null(), h.as_mut_ptr())
54                .into_result()?;
55
56            Ok(Self(h.assume_init(), device))
57        }
58    }
59
60    /// Constructs from raw values
61    /// # Safety
62    /// the resource must be created from the device and not freed anywhere
63    pub const unsafe fn manage(handle: VkDescriptorSetLayout, parent: Device) -> Self {
64        Self(handle, parent)
65    }
66
67    /// Purges the construct (Drop will not be called for this resource)
68    pub const fn unmanage(self) -> (VkDescriptorSetLayout, Device) {
69        let h = self.0;
70        let p = unsafe { core::ptr::read(&self.1) };
71        core::mem::forget(self);
72
73        (h, p)
74    }
75}
76impl<Device: VkHandle<Handle = VkDevice> + Clone> DescriptorSetLayoutObject<&'_ Device> {
77    /// Owning parent object by cloning it.
78    #[inline(always)]
79    pub fn clone_parent(self) -> DescriptorSetLayoutObject<Device> {
80        let r = DescriptorSetLayoutObject(self.0, self.1.clone());
81        core::mem::forget(self);
82
83        r
84    }
85}
86
87#[derive(VkHandle, VkObject)]
88#[VkObject(type = VkDescriptorPool::OBJECT_TYPE)]
89pub struct DescriptorPoolObject<Device: VkHandle<Handle = VkDevice>>(pub(crate) VkDescriptorPool, pub(crate) Device);
90#[implements]
91impl<Device: VkHandle<Handle = VkDevice>> Drop for DescriptorPoolObject<Device> {
92    #[inline(always)]
93    fn drop(&mut self) {
94        unsafe {
95            crate::vkfn::destroy_descriptor_pool(self.1.native_ptr(), self.0, core::ptr::null());
96        }
97    }
98}
99unsafe impl<Device: VkHandle<Handle = VkDevice> + Sync> Sync for DescriptorPoolObject<Device> {}
100unsafe impl<Device: VkHandle<Handle = VkDevice> + Send> Send for DescriptorPoolObject<Device> {}
101impl<Device: VkHandle<Handle = VkDevice>> DeviceChildHandle for DescriptorPoolObject<Device> {
102    #[inline(always)]
103    fn device_handle(&self) -> VkDevice {
104        self.1.native_ptr()
105    }
106}
107impl<Device: crate::Device> DeviceChild for DescriptorPoolObject<Device> {
108    type ConcreteDevice = Device;
109
110    #[inline(always)]
111    fn device(&self) -> &Self::ConcreteDevice {
112        &self.1
113    }
114}
115impl<Device: VkHandle<Handle = VkDevice>> DescriptorPool for DescriptorPoolObject<Device> {}
116impl<Device: VkHandle<Handle = VkDevice>> DescriptorPoolMut for DescriptorPoolObject<Device> {}
117impl<Device: VkHandle<Handle = VkDevice>> DescriptorPoolObject<Device> {
118    /// Creates a descriptor pool object
119    /// # Failures
120    /// On failure, this command returns
121    ///
122    /// - VK_ERROR_OUT_OF_HOST_MEMORY
123    /// - VK_ERROR_OUT_OF_DEVICE_MEMORY
124    #[implements]
125    pub fn new(device: Device, info: &DescriptorPoolCreateInfo) -> crate::Result<Self> {
126        let mut h = core::mem::MaybeUninit::uninit();
127
128        unsafe {
129            crate::vkfn::create_descriptor_pool(device.native_ptr(), &info.0, core::ptr::null(), h.as_mut_ptr())
130                .into_result()?;
131
132            Ok(Self(h.assume_init(), device))
133        }
134    }
135
136    /// Constructs from raw values
137    /// # Safety
138    /// the resource must be created from the device and not freed anywhere
139    pub const unsafe fn manage(handle: VkDescriptorPool, parent: Device) -> Self {
140        Self(handle, parent)
141    }
142
143    /// Purges the construct (Drop will not be called for this resource)
144    pub const fn unmanage(self) -> (VkDescriptorPool, Device) {
145        let h = self.0;
146        let p = unsafe { core::ptr::read(&self.1) };
147        core::mem::forget(self);
148
149        (h, p)
150    }
151}
152impl<Device: VkHandle<Handle = VkDevice> + Clone> DescriptorPoolObject<&'_ Device> {
153    /// Owning parent object by cloning it.
154    #[inline(always)]
155    pub fn clone_parent(self) -> DescriptorPoolObject<Device> {
156        let r = DescriptorPoolObject(self.0, self.1.clone());
157        core::mem::forget(self);
158
159        r
160    }
161}
162
163#[repr(transparent)]
164#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
165pub struct DescriptorSet(pub VkDescriptorSet);
166impl From<DescriptorSet> for VkDescriptorSet {
167    fn from(v: DescriptorSet) -> Self {
168        v.0
169    }
170}
171impl AsRef<VkDescriptorSet> for DescriptorSet {
172    fn as_ref(&self) -> &VkDescriptorSet {
173        &self.0
174    }
175}
176impl core::ops::Deref for DescriptorSet {
177    type Target = VkDescriptorSet;
178
179    fn deref(&self) -> &VkDescriptorSet {
180        &self.0
181    }
182}
183unsafe impl Sync for DescriptorSet {}
184unsafe impl Send for DescriptorSet {}
185impl DescriptorSet {
186    #[inline]
187    pub const fn binding_at(&self, b: u32) -> DescriptorPointer {
188        DescriptorPointer::new(self.0, b)
189    }
190}
191
192/// Specified the type of a descriptor in a descriptor set
193#[repr(C)]
194#[derive(Debug, Clone, PartialEq, Eq, Copy, PartialOrd, Ord, Hash)]
195pub enum DescriptorType {
196    Sampler = VK_DESCRIPTOR_TYPE_SAMPLER as _,
197    CombinedImageSampler = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER as _,
198    SampledImage = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE as _,
199    StorageImage = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE as _,
200    UniformTexelBuffer = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER as _,
201    StorageTexelBuffer = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER as _,
202    UniformBuffer = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER as _,
203    StorageBuffer = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER as _,
204    UniformBufferDynamic = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC as _,
205    StorageBufferDynamic = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC as _,
206    InputAttachment = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT as _,
207}
208impl DescriptorType {
209    pub const fn make_size(self, count: u32) -> VkDescriptorPoolSize {
210        VkDescriptorPoolSize {
211            r#type: self as _,
212            descriptorCount: count,
213        }
214    }
215
216    pub const fn make_binding<'a>(self, binding: u32, count: u32) -> DescriptorSetLayoutBinding<'a> {
217        DescriptorSetLayoutBinding::new(binding, self, count, VK_SHADER_STAGE_ALL)
218    }
219}
220
221#[repr(transparent)]
222#[derive(Clone)]
223pub struct DescriptorSetLayoutBinding<'s> {
224    raw: VkDescriptorSetLayoutBinding,
225    immutable_samplers: core::marker::PhantomData<&'s dyn VkHandle<Handle = VkSampler>>,
226}
227impl<'s> DescriptorSetLayoutBinding<'s> {
228    pub const fn new(binding: u32, r#type: DescriptorType, count: u32, shader_stage: VkShaderStageFlags) -> Self {
229        Self {
230            raw: VkDescriptorSetLayoutBinding {
231                binding,
232                descriptorType: r#type as _,
233                descriptorCount: count,
234                stageFlags: shader_stage,
235                pImmutableSamplers: core::ptr::null(),
236            },
237            immutable_samplers: core::marker::PhantomData,
238        }
239    }
240
241    #[inline(always)]
242    pub fn with_immutable_samplers(self, samplers: &'s [VkHandleRef<VkSampler>]) -> Self {
243        assert_eq!(samplers.len(), self.raw.descriptorCount as usize);
244        unsafe { self.with_immutable_samplers_unchecked(samplers) }
245    }
246
247    pub const unsafe fn with_immutable_samplers_unchecked(mut self, samplers: &'s [VkHandleRef<VkSampler>]) -> Self {
248        self.raw.pImmutableSamplers = slice_as_ptr_empty_null(samplers) as _;
249        self
250    }
251
252    pub const fn for_shader_stage(mut self, mask: VkShaderStageFlags) -> Self {
253        self.raw.stageFlags = mask;
254        self
255    }
256
257    pub const fn only_for_vertex(self) -> Self {
258        self.for_shader_stage(VK_SHADER_STAGE_VERTEX_BIT)
259    }
260
261    pub const fn only_for_tess_control(self) -> Self {
262        self.for_shader_stage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
263    }
264
265    pub const fn only_for_tess_evaluation(self) -> Self {
266        self.for_shader_stage(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
267    }
268
269    pub const fn only_for_tessellation(self) -> Self {
270        self.for_shader_stage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
271    }
272
273    pub const fn only_for_geometry(self) -> Self {
274        self.for_shader_stage(VK_SHADER_STAGE_GEOMETRY_BIT)
275    }
276
277    pub const fn only_for_fragment(self) -> Self {
278        self.for_shader_stage(VK_SHADER_STAGE_FRAGMENT_BIT)
279    }
280
281    pub const fn only_for_compute(self) -> Self {
282        self.for_shader_stage(VK_SHADER_STAGE_COMPUTE_BIT)
283    }
284}
285
286#[repr(transparent)]
287#[derive(Clone)]
288pub struct DescriptorSetLayoutCreateInfo<'d, 's>(
289    VkDescriptorSetLayoutCreateInfo,
290    core::marker::PhantomData<&'d [DescriptorSetLayoutBinding<'s>]>,
291);
292impl<'d, 's> DescriptorSetLayoutCreateInfo<'d, 's> {
293    #[inline(always)]
294    pub const fn new(bindings: &'d [DescriptorSetLayoutBinding<'s>]) -> Self {
295        Self(
296            VkDescriptorSetLayoutCreateInfo {
297                sType: VkDescriptorSetLayoutCreateInfo::TYPE,
298                pNext: core::ptr::null(),
299                flags: 0,
300                bindingCount: bindings.len() as _,
301                pBindings: slice_as_ptr_empty_null(bindings) as _,
302            },
303            core::marker::PhantomData,
304        )
305    }
306}
307
308pub trait DescriptorSetLayout: VkHandle<Handle = VkDescriptorSetLayout> + DeviceChild {}
309DerefContainerBracketImpl!(for DescriptorSetLayout {});
310GuardsImpl!(for DescriptorSetLayout {});
311
312/*
313# DescriptorPoolのフラグメンテーションについてメモ(from `VkDescriptorPoolCreateInfo` Manual)
314
315`VkDescriptorPoolSize`構造体が`pPoolSizes`配列内に複数ある場合、プールはそれぞれのタイプの合計分のデスクリプタが十分入るように確保されます。
316
317DescriptorPoolはフラグメンテーションを起こすことがあり、DescriptorSetの確保に失敗することがあります。
318フラグメンテーションに起因する失敗は、確保したDescriptorSetの数+確保を要求したDescriptorSetの数が`maxSets`に満たない場合でも
319"DescriptorSetの確保の失敗"と定義されます。(たぶんあってるはず)
320実装は、以下に記述されるような"フラグメンテーションが確保の失敗を引き起こさない場合"について確固たる保証を提供します。
321(言い換えると、「以下に示す場合はフラグメンテーション状態でも確保に成功する」)
322
323DescriptorPoolが、生成されてから/間近にリセットされてから今までに開放されたDescriptorSetがない場合、
324フラグメンテーションは確保の失敗を引き起こしません。(`VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT`を伴わずに生成されたプールに対しては常に満たすものとします?)
325また、
326- プールが生成されてから/間近にリセットされてから確保された、すべてのDescriptorSetが各タイプ同じ数のDescriptorを使う場合、そして
327- 要求した確保も各タイプ同じ数のDescriptorを使う場合、
328フラグメンテーションは確保の失敗を引き起こしません。
329
330もしフラグメンテーションによって確保が失敗した場合、アプリケーションは続けてDescriptorSetの確保を行うために追加のDescriptorPoolを生成することができます
331*/
332
333#[repr(transparent)]
334#[derive(Clone)]
335pub struct DescriptorPoolCreateInfo<'d>(
336    VkDescriptorPoolCreateInfo,
337    core::marker::PhantomData<&'d [VkDescriptorPoolSize]>,
338);
339impl<'d> DescriptorPoolCreateInfo<'d> {
340    pub const fn new(max_sets: u32, sizes: &'d [VkDescriptorPoolSize]) -> Self {
341        Self(
342            VkDescriptorPoolCreateInfo {
343                sType: VkDescriptorPoolCreateInfo::TYPE,
344                pNext: core::ptr::null(),
345                flags: 0,
346                maxSets: max_sets,
347                poolSizeCount: sizes.len() as _,
348                pPoolSizes: slice_as_ptr_empty_null(sizes),
349            },
350            core::marker::PhantomData,
351        )
352    }
353
354    pub const unsafe fn from_raw(raw: VkDescriptorPoolCreateInfo) -> Self {
355        Self(raw, core::marker::PhantomData)
356    }
357
358    pub const fn into_raw(self) -> VkDescriptorPoolCreateInfo {
359        self.0
360    }
361
362    pub const fn allow_individual_free(mut self) -> Self {
363        self.0.flags |= VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
364        self
365    }
366}
367
368pub trait DescriptorPool: VkHandle<Handle = VkDescriptorPool> {}
369DerefContainerBracketImpl!(for DescriptorPool {});
370GuardsImpl!(for DescriptorPool {});
371
372pub trait DescriptorPoolMut: DescriptorPool + VkHandleMut + DeviceChildHandle {
373    /// Allocate one or more descriptor sets
374    /// # Failures
375    /// On failure, this command returns
376    /// - VK_ERROR_OUT_OF_HOST_MEMORY
377    /// - VK_ERROR_OUT_OF_DEVICE_MEMORY
378    /// - VK_ERROR_FRAGMENTED_POOL
379    ///
380    /// # Safety
381    /// no guarantees will be provided (simply calls under api)
382    #[implements]
383    #[inline]
384    unsafe fn alloc_raw(
385        &mut self,
386        info: &VkDescriptorSetAllocateInfo,
387        objects: &mut [VkDescriptorSet],
388    ) -> crate::Result<()> {
389        unsafe {
390            crate::vkfn::allocate_descriptor_sets(self.device_handle(), info, objects.as_mut_ptr())
391                .into_result()
392                .map(drop)
393        }
394    }
395
396    /// Allocate one or more descriptor sets
397    /// # Failures
398    /// On failure, this command returns
399    /// - VK_ERROR_OUT_OF_HOST_MEMORY
400    /// - VK_ERROR_OUT_OF_DEVICE_MEMORY
401    /// - VK_ERROR_FRAGMENTED_POOL
402    #[implements]
403    fn alloc(&mut self, layouts: &[VkHandleRef<VkDescriptorSetLayout>]) -> crate::Result<Vec<DescriptorSet>> {
404        let ainfo = VkDescriptorSetAllocateInfo {
405            sType: VkDescriptorSetAllocateInfo::TYPE,
406            pNext: core::ptr::null(),
407            descriptorPool: self.native_ptr_mut(),
408            descriptorSetCount: layouts.len() as _,
409            pSetLayouts: layouts.as_ptr_empty_null() as _,
410        };
411        let mut hs = vec![VkDescriptorSet::NULL; layouts.len()];
412
413        unsafe {
414            self.alloc_raw(&ainfo, &mut hs)?;
415
416            Ok(core::mem::transmute(hs))
417        }
418    }
419
420    /// Allocate one or more descriptor sets
421    /// # Failures
422    /// On failure, this command returns
423    /// - VK_ERROR_OUT_OF_HOST_MEMORY
424    /// - VK_ERROR_OUT_OF_DEVICE_MEMORY
425    /// - VK_ERROR_FRAGMENTED_POOL
426    #[implements]
427    fn alloc_array<const N: usize>(
428        &mut self,
429        layouts: &[VkHandleRef<VkDescriptorSetLayout>; N],
430    ) -> crate::Result<[DescriptorSet; N]> {
431        let ainfo = VkDescriptorSetAllocateInfo {
432            sType: VkDescriptorSetAllocateInfo::TYPE,
433            pNext: core::ptr::null(),
434            descriptorPool: self.native_ptr_mut(),
435            descriptorSetCount: N as _,
436            pSetLayouts: layouts.as_ptr_empty_null() as _,
437        };
438        let mut hs = [VkDescriptorSet::NULL; N];
439
440        unsafe {
441            self.alloc_raw(&ainfo, &mut hs)?;
442
443            // Note: transmuteだと変換できない(要素数がジェネリックだとダメっぽい?)
444            Ok(*(&hs as *const _ as *const [DescriptorSet; N]))
445        }
446    }
447
448    /// Resets a descriptor pool object
449    /// # Safety
450    /// Application must not use descriptor sets after this call
451    /// # Failures
452    /// On failure, this command returns
453    /// - VK_ERROR_OUT_OF_HOST_MEMORY
454    /// - VK_ERROR_OUT_OF_DEVICE_MEMORY
455    #[implements]
456    #[inline]
457    unsafe fn reset(&mut self, flags: VkDescriptorPoolResetFlags) -> crate::Result<()> {
458        unsafe {
459            crate::vkfn::reset_descriptor_pool(self.device_handle(), self.native_ptr_mut(), flags)
460                .into_result()
461                .map(drop)
462        }
463    }
464
465    /// Free one or more descriptor sets
466    /// # Safety
467    /// Host access to each member of pDescriptorSets must be externally synchronized
468    /// # Failures
469    /// On failure, this command returns
470    /// - VK_ERROR_OUT_OF_HOST_MEMORY
471    /// - VK_ERROR_OUT_OF_DEVICE_MEMORY
472    #[implements]
473    #[inline]
474    unsafe fn free(&mut self, sets: &[DescriptorSet]) -> crate::Result<()> {
475        unsafe {
476            crate::vkfn::free_descriptor_sets(
477                self.device_handle(),
478                self.native_ptr(),
479                sets.len() as _,
480                sets.as_ptr_empty_null() as _,
481            )
482            .into_result()
483            .map(drop)
484        }
485    }
486}
487DerefContainerBracketImpl!(for mut DescriptorPoolMut {});
488GuardsImpl!(for mut DescriptorPoolMut {});
489
490/// Pointer for descriptor array in set
491#[derive(Clone)]
492pub struct DescriptorPointer {
493    pub set: VkDescriptorSet,
494    pub binding: u32,
495    pub array_offset: u32,
496}
497impl DescriptorPointer {
498    pub const fn new(set: VkDescriptorSet, binding: u32) -> Self {
499        Self {
500            set,
501            binding,
502            array_offset: 0,
503        }
504    }
505
506    pub const fn array_offset(self, offset: u32) -> Self {
507        Self {
508            array_offset: offset,
509            ..self
510        }
511    }
512
513    pub const fn write<'r>(self, contents: DescriptorContents<'r>) -> DescriptorSetWriteInfo<'r> {
514        DescriptorSetWriteInfo(self, contents)
515    }
516
517    pub const fn copy(self, count: u32, dest: DescriptorPointer) -> DescriptorSetCopyInfo {
518        DescriptorSetCopyInfo(self, dest, count)
519    }
520
521    pub fn write_continuous_bindings<'r>(
522        self,
523        contents: impl IntoIterator<Item = DescriptorContents<'r>>,
524    ) -> impl Iterator<Item = DescriptorSetWriteInfo<'r>> {
525        let base_binding = self.binding;
526
527        contents.into_iter().enumerate().map(move |(n, c)| {
528            Self {
529                binding: base_binding + n as u32,
530                ..self.clone()
531            }
532            .write(c)
533        })
534    }
535}
536
537#[repr(transparent)]
538#[derive(Clone)]
539pub struct DescriptorBufferInfo<'r>(
540    VkDescriptorBufferInfo,
541    core::marker::PhantomData<&'r dyn VkHandle<Handle = VkBuffer>>,
542);
543impl<'r> DescriptorBufferInfo<'r> {
544    #[inline(always)]
545    pub fn new(r: &'r (impl VkHandle<Handle = VkBuffer> + ?Sized), range: core::ops::Range<VkDeviceSize>) -> Self {
546        Self(
547            VkDescriptorBufferInfo {
548                buffer: r.native_ptr(),
549                offset: range.start,
550                range: range.end - range.start,
551            },
552            core::marker::PhantomData,
553        )
554    }
555
556    #[inline(always)]
557    pub const fn unbounded(h: VkBuffer, range: core::ops::Range<VkDeviceSize>) -> Self {
558        Self(
559            VkDescriptorBufferInfo {
560                buffer: h,
561                offset: range.start,
562                range: range.end - range.start,
563            },
564            core::marker::PhantomData,
565        )
566    }
567}
568
569#[repr(transparent)]
570#[derive(Clone)]
571pub struct DescriptorImageInfo<'r>(
572    VkDescriptorImageInfo,
573    core::marker::PhantomData<(
574        &'r dyn VkHandle<Handle = VkImageView>,
575        Option<&'r dyn VkHandle<Handle = VkSampler>>,
576    )>,
577);
578impl<'r> DescriptorImageInfo<'r> {
579    #[inline(always)]
580    pub fn new(r: &'r (impl VkHandle<Handle = VkImageView> + ?Sized), layout: ImageLayout) -> Self {
581        Self(
582            VkDescriptorImageInfo {
583                imageView: r.native_ptr(),
584                imageLayout: layout as _,
585                sampler: VkSampler::NULL,
586            },
587            core::marker::PhantomData,
588        )
589    }
590
591    #[inline(always)]
592    pub const fn unbounded(h: VkImageView, layout: ImageLayout) -> Self {
593        Self(
594            VkDescriptorImageInfo {
595                imageView: h,
596                imageLayout: layout as _,
597                sampler: VkSampler::NULL,
598            },
599            core::marker::PhantomData,
600        )
601    }
602
603    #[inline(always)]
604    pub fn with_sampler(mut self, sampler: &'r (impl VkHandle<Handle = VkSampler> + ?Sized)) -> Self {
605        self.0.sampler = sampler.native_ptr();
606        self
607    }
608
609    #[inline(always)]
610    pub const fn with_unbounded_sampler(mut self, sampler: VkSampler) -> Self {
611        self.0.sampler = sampler;
612        self
613    }
614}
615
616#[derive(Clone)]
617pub enum DescriptorContents<'r> {
618    Sampler(Vec<DescriptorImageInfo<'r>>),
619    CombinedImageSampler(Vec<DescriptorImageInfo<'r>>),
620    SampledImage(Vec<DescriptorImageInfo<'r>>),
621    StorageImage(Vec<DescriptorImageInfo<'r>>),
622    InputAttachment(Vec<DescriptorImageInfo<'r>>),
623    UniformBuffer(Vec<DescriptorBufferInfo<'r>>),
624    StorageBuffer(Vec<DescriptorBufferInfo<'r>>),
625    UniformBufferDynamic(Vec<DescriptorBufferInfo<'r>>),
626    StorageBufferDynamic(Vec<DescriptorBufferInfo<'r>>),
627    UniformTexelBuffer(Vec<VkHandleRef<'r, VkBufferView>>),
628    StorageTexelBuffer(Vec<VkHandleRef<'r, VkBufferView>>),
629}
630impl<'d> DescriptorContents<'d> {
631    pub fn type_count(&self) -> (DescriptorType, usize) {
632        match self {
633            Self::Sampler(rs) => (DescriptorType::Sampler, rs.len()),
634            Self::CombinedImageSampler(rs) => (DescriptorType::CombinedImageSampler, rs.len()),
635            Self::SampledImage(rs) => (DescriptorType::SampledImage, rs.len()),
636            Self::StorageImage(rs) => (DescriptorType::StorageImage, rs.len()),
637            Self::InputAttachment(rs) => (DescriptorType::InputAttachment, rs.len()),
638            Self::UniformBuffer(rs) => (DescriptorType::UniformBuffer, rs.len()),
639            Self::StorageBuffer(rs) => (DescriptorType::StorageBuffer, rs.len()),
640            Self::UniformBufferDynamic(rs) => (DescriptorType::UniformBufferDynamic, rs.len()),
641            Self::StorageBufferDynamic(rs) => (DescriptorType::StorageBufferDynamic, rs.len()),
642            Self::UniformTexelBuffer(rs) => (DescriptorType::UniformTexelBuffer, rs.len()),
643            Self::StorageTexelBuffer(rs) => (DescriptorType::StorageTexelBuffer, rs.len()),
644        }
645    }
646
647    // single content utilities
648
649    #[inline(always)]
650    pub fn sampler(obj: &'d (impl VkHandle<Handle = VkImageView> + ?Sized), layout: ImageLayout) -> Self {
651        Self::Sampler(vec![DescriptorImageInfo::new(obj, layout)])
652    }
653    #[inline(always)]
654    pub fn combined_image_sampler(
655        obj: &'d (impl VkHandle<Handle = VkImageView> + ?Sized),
656        layout: ImageLayout,
657    ) -> Self {
658        Self::CombinedImageSampler(vec![DescriptorImageInfo::new(obj, layout)])
659    }
660    #[inline(always)]
661    pub fn sampled_image(obj: &'d (impl VkHandle<Handle = VkImageView> + ?Sized), layout: ImageLayout) -> Self {
662        Self::SampledImage(vec![DescriptorImageInfo::new(obj, layout)])
663    }
664    #[inline(always)]
665    pub fn storage_image(obj: &'d (impl VkHandle<Handle = VkImageView> + ?Sized), layout: ImageLayout) -> Self {
666        Self::StorageImage(vec![DescriptorImageInfo::new(obj, layout)])
667    }
668    #[inline(always)]
669    pub fn input_attachment(obj: &'d (impl VkHandle<Handle = VkImageView> + ?Sized), layout: ImageLayout) -> Self {
670        Self::InputAttachment(vec![DescriptorImageInfo::new(obj, layout)])
671    }
672    #[inline(always)]
673    pub fn uniform_buffer(
674        obj: &'d (impl VkHandle<Handle = VkBuffer> + ?Sized),
675        range: core::ops::Range<VkDeviceSize>,
676    ) -> Self {
677        Self::UniformBuffer(vec![DescriptorBufferInfo::new(obj, range)])
678    }
679    #[inline(always)]
680    pub fn storage_buffer(
681        obj: &'d (impl VkHandle<Handle = VkBuffer> + ?Sized),
682        range: core::ops::Range<VkDeviceSize>,
683    ) -> Self {
684        Self::StorageBuffer(vec![DescriptorBufferInfo::new(obj, range)])
685    }
686    #[inline(always)]
687    pub fn uniform_buffer_dynamic(
688        obj: &'d (impl VkHandle<Handle = VkBuffer> + ?Sized),
689        range: core::ops::Range<VkDeviceSize>,
690    ) -> Self {
691        Self::UniformBufferDynamic(vec![DescriptorBufferInfo::new(obj, range)])
692    }
693    #[inline(always)]
694    pub fn storage_buffer_dynamic(
695        obj: &'d (impl VkHandle<Handle = VkBuffer> + ?Sized),
696        range: core::ops::Range<VkDeviceSize>,
697    ) -> Self {
698        Self::StorageBufferDynamic(vec![DescriptorBufferInfo::new(obj, range)])
699    }
700    #[inline(always)]
701    pub fn uniform_texel_buffer(obj: &'d (impl VkHandle<Handle = VkBufferView> + ?Sized)) -> Self {
702        Self::UniformTexelBuffer(vec![VkHandleRef::new(obj)])
703    }
704    #[inline(always)]
705    pub fn storage_texel_buffer(obj: &'d (impl VkHandle<Handle = VkBufferView> + ?Sized)) -> Self {
706        Self::StorageTexelBuffer(vec![VkHandleRef::new(obj)])
707    }
708}
709
710#[derive(Clone)]
711pub struct DescriptorSetWriteInfo<'s>(pub DescriptorPointer, pub DescriptorContents<'s>);
712impl DescriptorSetWriteInfo<'_> {
713    pub fn make_structure(&self) -> VkWriteDescriptorSet {
714        let (r#type, count) = self.1.type_count();
715        let (buffers, images, buffer_views) = match self.1 {
716            DescriptorContents::Sampler(ref res)
717            | DescriptorContents::CombinedImageSampler(ref res)
718            | DescriptorContents::SampledImage(ref res)
719            | DescriptorContents::StorageImage(ref res)
720            | DescriptorContents::InputAttachment(ref res) => {
721                (core::ptr::null(), res.as_ptr_empty_null(), core::ptr::null())
722            }
723            DescriptorContents::UniformBuffer(ref res)
724            | DescriptorContents::StorageBuffer(ref res)
725            | DescriptorContents::UniformBufferDynamic(ref res)
726            | DescriptorContents::StorageBufferDynamic(ref res) => {
727                (res.as_ptr_empty_null(), core::ptr::null(), core::ptr::null())
728            }
729            DescriptorContents::UniformTexelBuffer(ref res) | DescriptorContents::StorageTexelBuffer(ref res) => {
730                (core::ptr::null(), core::ptr::null(), res.as_ptr_empty_null())
731            }
732        };
733
734        VkWriteDescriptorSet {
735            sType: VkWriteDescriptorSet::TYPE,
736            pNext: core::ptr::null(),
737            dstSet: self.0.set,
738            dstBinding: self.0.binding,
739            dstArrayElement: self.0.array_offset,
740            descriptorType: r#type as _,
741            descriptorCount: count as _,
742            pImageInfo: images as _,
743            pBufferInfo: buffers as _,
744            pTexelBufferView: buffer_views as _,
745        }
746    }
747}
748
749#[derive(Clone)]
750pub struct DescriptorSetCopyInfo(pub DescriptorPointer, pub DescriptorPointer, u32);
751impl DescriptorSetCopyInfo {
752    pub fn make_structure(&self) -> VkCopyDescriptorSet {
753        VkCopyDescriptorSet {
754            sType: VkCopyDescriptorSet::TYPE,
755            pNext: core::ptr::null(),
756            srcSet: self.0.set,
757            srcBinding: self.0.binding,
758            srcArrayElement: self.0.array_offset,
759            dstSet: self.1.set,
760            dstBinding: self.1.binding,
761            dstArrayElement: self.1.array_offset,
762            descriptorCount: self.2,
763        }
764    }
765}
766
767#[macro_export]
768macro_rules! DescriptorUpdateTemplateEntry {
769    { ($b: expr, $a: expr) .. : [$ty: expr; $c: expr] = $o: expr, $s: expr } => {
770        VkDescriptorUpdateTemplateEntry
771        {
772            descriptorType: $ty, descriptorCount: $c,
773            dstBinding: $b, dstArrayElement: $a, offset: $o, stride: $s
774        }
775    };
776}
777#[macro_export]
778macro_rules! DescriptorUpdateTemplateEntries {
779    { { $(($b: expr, $a: expr) .. : [$ty: expr; $c: expr] = $o: expr, $s: expr),* } } => { {
780        $(DescriptorUpdateTemplateEntry! { ($b, $a) ..: [$ty; $c] = $o, $s }),*
781    } };
782}
783
784#[cfg(feature = "VK_KHR_descriptor_update_template")]
785mod update_template;
786#[cfg(feature = "VK_KHR_descriptor_update_template")]
787pub use self::update_template::*;