bedrock/
shading.rs

1//! Vulkan Shading(Shader/Pipeline)
2
3use crate::ffi_helper::slice_as_ptr_empty_null;
4use crate::*;
5use core::{
6    ffi::{CStr, c_void},
7    marker::PhantomData,
8    ops::*,
9};
10use derives::{bitflags_newtype, implements};
11
12#[repr(u32)]
13#[derive(Debug, Clone, PartialEq, Eq, Copy, PartialOrd, Ord, Hash)]
14pub enum ShaderStage {
15    Vertex = VK_SHADER_STAGE_VERTEX_BIT,
16    TessellationControl = VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
17    TessellationEvaluation = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
18    Geometry = VK_SHADER_STAGE_GEOMETRY_BIT,
19    Fragment = VK_SHADER_STAGE_FRAGMENT_BIT,
20    Compute = VK_SHADER_STAGE_COMPUTE_BIT,
21}
22
23/// Stencil comparison function
24#[repr(i32)]
25#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
26pub enum CompareOp {
27    /// The test never passes
28    Never = VK_COMPARE_OP_NEVER,
29    /// The test passes when `Ref < Stencil`
30    Less = VK_COMPARE_OP_LESS,
31    /// The test passes when `Ref == Stencil`
32    Equal = VK_COMPARE_OP_EQUAL,
33    /// The test passes when `Ref <= Stencil`
34    LessOrEqual = VK_COMPARE_OP_LESS_OR_EQUAL,
35    /// The test passes when `Ref > Stencil`
36    Greater = VK_COMPARE_OP_GREATER,
37    /// The test passes when `Ref != Stencil`
38    NotEqual = VK_COMPARE_OP_NOT_EQUAL,
39    /// The test passes when `Ref >= Stencil`
40    GreaterOrEqual = VK_COMPARE_OP_GREATER_OR_EQUAL,
41    /// The test always passes
42    Always = VK_COMPARE_OP_ALWAYS,
43}
44
45/// Stencil action function
46#[repr(i32)]
47#[derive(Debug, Clone, Copy, PartialEq, Eq)]
48pub enum StencilOp {
49    /// Keeps the current value
50    Keep = VK_STENCIL_OP_KEEP,
51    /// Sets the value to 0
52    Zero = VK_STENCIL_OP_ZERO,
53    /// Sets the value to `reference`
54    Replace = VK_STENCIL_OP_REPLACE,
55    /// Increments the current value and clamps to the maximum representable unsigned value
56    IncrementClamp = VK_STENCIL_OP_INCREMENT_AND_CLAMP,
57    /// Decrements the current value and clamps to 0
58    DecrementClamp = VK_STENCIL_OP_DECREMENT_AND_CLAMP,
59    /// Bitwise-inverts the current value
60    Invert = VK_STENCIL_OP_INVERT,
61    /// Increments the current value and wraps to 0 when the maximum value would have been exceeded
62    IncrementWrap = VK_STENCIL_OP_INCREMENT_AND_WRAP,
63    /// Decrements the current value and wraps to the maximum possible value when the value would go below 0
64    DecrementWrap = VK_STENCIL_OP_DECREMENT_AND_WRAP,
65}
66
67/// Framebuffer logical operations
68#[repr(i32)]
69#[derive(Debug, Clone, Copy, PartialEq, Eq)]
70pub enum LogicOp {
71    /// 0
72    Clear = VK_LOGIC_OP_CLEAR,
73    /// source & dest
74    And = VK_LOGIC_OP_AND,
75    /// source & ~dest
76    AndReverse = VK_LOGIC_OP_AND_REVERSE,
77    /// source
78    Copy = VK_LOGIC_OP_COPY,
79    /// ~source & dest
80    AndInverted = VK_LOGIC_OP_AND_INVERTED,
81    /// dest
82    NoOp = VK_LOGIC_OP_NO_OP,
83    /// source ^ dest
84    Xor = VK_LOGIC_OP_XOR,
85    /// source | dest
86    Or = VK_LOGIC_OP_OR,
87    /// ~(source | dest)
88    Nor = VK_LOGIC_OP_NOR,
89    /// ~(source ^ dest)
90    Equivalent = VK_LOGIC_OP_EQUIVALENT,
91    /// ~dest
92    Invert = VK_LOGIC_OP_INVERT,
93    /// source | ~dest
94    OrReverse = VK_LOGIC_OP_OR_REVERSE,
95    /// ~source
96    CopyInverted = VK_LOGIC_OP_COPY_INVERTED,
97    /// ~source | dest
98    OrInverted = VK_LOGIC_OP_OR_INVERTED,
99    /// ~(source & dest)
100    Nand = VK_LOGIC_OP_NAND,
101    /// 1
102    Set = VK_LOGIC_OP_SET,
103}
104
105/// Bitmask specifying sets of stencil state for which to update the compare mask
106#[repr(u32)]
107#[derive(Debug, Clone, PartialEq, Eq, Copy)]
108pub enum StencilFaceMask {
109    /// Only the front set of stencil state
110    Front = VK_STENCIL_FACE_FRONT_BIT,
111    /// Only the back set of stencil state
112    Back = VK_STENCIL_FACE_BACK_BIT,
113    /// Both sets of stencil state
114    Both = VK_STENCIL_FACE_FRONT_AND_BACK,
115}
116
117pub type StencilOpState = VkStencilOpState;
118impl StencilOpState {
119    pub const NOP: Self = Self::always_forall(StencilOp::Keep);
120
121    pub const fn always(pass: StencilOp, fail: StencilOp, depth_fail: StencilOp) -> Self {
122        Self {
123            passOp: pass as _,
124            failOp: fail as _,
125            depthFailOp: depth_fail as _,
126            compareOp: CompareOp::Always as _,
127            compareMask: 0,
128            writeMask: 0,
129            reference: 0,
130        }
131    }
132
133    pub const fn always_forall(op: StencilOp) -> Self {
134        Self::always(op, op, op)
135    }
136
137    pub const fn write_mask(mut self, mask: u32) -> Self {
138        self.writeMask = mask;
139        self
140    }
141
142    pub const fn set_compare(mut self, op: CompareOp, reference: u32, mask: u32) -> Self {
143        self.compareOp = op as _;
144        self.reference = reference;
145        self.compareMask = mask;
146        self
147    }
148
149    pub const fn always_pass(mut self) -> Self {
150        self.compareOp = CompareOp::Always as _;
151        self
152    }
153}
154
155#[repr(transparent)]
156#[derive(Clone)]
157pub struct ShaderModuleCreateInfo<'d>(VkShaderModuleCreateInfo, core::marker::PhantomData<&'d [u32]>);
158impl<'d> ShaderModuleCreateInfo<'d> {
159    pub const fn new(code: &'d [u32]) -> Self {
160        Self(
161            VkShaderModuleCreateInfo {
162                sType: VkShaderModuleCreateInfo::TYPE,
163                pNext: core::ptr::null(),
164                flags: 0,
165                // Note: ここはbyte単位
166                codeSize: code.len() << 2,
167                pCode: slice_as_ptr_empty_null(code),
168            },
169            core::marker::PhantomData,
170        )
171    }
172
173    pub const unsafe fn from_raw(raw: VkShaderModuleCreateInfo) -> Self {
174        Self(raw, core::marker::PhantomData)
175    }
176
177    pub const fn into_raw(self) -> VkShaderModuleCreateInfo {
178        self.0
179    }
180}
181
182/// Opaque handle to a shader module object
183#[derive(VkHandle, VkObject)]
184#[VkObject(type = VkShaderModule::OBJECT_TYPE)]
185pub struct ShaderModuleObject<Device: VkHandle<Handle = VkDevice>>(VkShaderModule, Device);
186#[implements]
187impl<Device: VkHandle<Handle = VkDevice>> Drop for ShaderModuleObject<Device> {
188    #[inline(always)]
189    fn drop(&mut self) {
190        unsafe {
191            crate::vkfn::destroy_shader_module(self.1.native_ptr(), self.0, core::ptr::null());
192        }
193    }
194}
195unsafe impl<Device: VkHandle<Handle = VkDevice> + Sync> Sync for ShaderModuleObject<Device> {}
196unsafe impl<Device: VkHandle<Handle = VkDevice> + Send> Send for ShaderModuleObject<Device> {}
197impl<Device: VkHandle<Handle = VkDevice>> ShaderModule for ShaderModuleObject<Device> {}
198impl<Device: VkHandle<Handle = VkDevice>> ShaderModuleObject<Device> {
199    /// Constructs from raw values
200    /// # Safety
201    /// the resource must be created from the device and not freed anywhere
202    pub const unsafe fn manage(handle: VkShaderModule, parent: Device) -> Self {
203        Self(handle, parent)
204    }
205
206    /// Purges the construct (Drop will not be called for this resource)
207    pub const fn unmanage(self) -> (VkShaderModule, Device) {
208        let h = self.0;
209        let p = unsafe { core::ptr::read(&self.1) };
210        core::mem::forget(self);
211
212        (h, p)
213    }
214}
215impl<Device: VkHandle<Handle = VkDevice> + Clone> ShaderModuleObject<&'_ Device> {
216    /// Owning parent object by cloning it.
217    #[inline(always)]
218    pub fn clone_parent(self) -> ShaderModuleObject<Device> {
219        let r = ShaderModuleObject(self.0, self.1.clone());
220        core::mem::forget(self);
221
222        r
223    }
224}
225impl<Device: crate::Device> ShaderModuleObject<Device> {
226    /// Creates a new shader module object
227    /// # Failures
228    /// On failure, this command returns
229    ///
230    /// * [`VK_ERROR_OUT_OF_HOST_MEMORY`]
231    /// * [`VK_ERROR_OUT_OF_DEVICE_MEMORY`]
232    /// * [`VK_ERROR_INVALID_SHADER_NV`]
233    #[implements]
234    #[inline]
235    pub fn new(device: Device, info: &ShaderModuleCreateInfo) -> crate::Result<Self> {
236        Ok(unsafe { Self::manage(device.new_shader_module_raw(info, None)?, device) })
237    }
238}
239
240pub trait ShaderModule: VkHandle<Handle = VkShaderModule> {
241    /// Constructs a new [`PipelineShaderStage`] data.
242    #[inline(always)]
243    fn on_stage<'m, 's>(&'m self, stage: ShaderStage, entry_point: &'m CStr) -> PipelineShaderStage<'m, 's> {
244        PipelineShaderStage::new(stage, self, entry_point)
245    }
246}
247DerefContainerBracketImpl!(for ShaderModule {});
248GuardsImpl!(for ShaderModule {});
249
250#[repr(transparent)]
251#[derive(Clone)]
252pub struct PipelineCacheCreateInfo<'d>(VkPipelineCacheCreateInfo, core::marker::PhantomData<&'d [u8]>);
253impl<'d> PipelineCacheCreateInfo<'d> {
254    pub const fn new(initial_data: &'d [u8]) -> Self {
255        Self(
256            VkPipelineCacheCreateInfo {
257                sType: VkPipelineCacheCreateInfo::TYPE,
258                pNext: core::ptr::null(),
259                flags: 0,
260                initialDataSize: initial_data.len() as _,
261                pInitialData: slice_as_ptr_empty_null(initial_data) as _,
262            },
263            core::marker::PhantomData,
264        )
265    }
266
267    pub const unsafe fn from_raw(raw: VkPipelineCacheCreateInfo) -> Self {
268        Self(raw, core::marker::PhantomData)
269    }
270
271    pub const fn into_raw(self) -> VkPipelineCacheCreateInfo {
272        self.0
273    }
274}
275
276/// Opaque handle to a pipeline cache object
277#[derive(VkHandle, VkObject)]
278#[VkObject(type = VkPipelineCache::OBJECT_TYPE)]
279pub struct PipelineCacheObject<Device: VkHandle<Handle = VkDevice>>(VkPipelineCache, Device);
280#[implements]
281impl<Device: VkHandle<Handle = VkDevice>> Drop for PipelineCacheObject<Device> {
282    #[inline(always)]
283    fn drop(&mut self) {
284        unsafe {
285            crate::vkfn::destroy_pipeline_cache(self.1.native_ptr(), self.0, core::ptr::null());
286        }
287    }
288}
289unsafe impl<Device: VkHandle<Handle = VkDevice> + Sync> Sync for PipelineCacheObject<Device> {}
290unsafe impl<Device: VkHandle<Handle = VkDevice> + Send> Send for PipelineCacheObject<Device> {}
291impl<Device: VkHandle<Handle = VkDevice>> DeviceChildHandle for PipelineCacheObject<Device> {
292    #[inline(always)]
293    fn device_handle(&self) -> VkDevice {
294        self.1.native_ptr()
295    }
296}
297impl<Device: VkHandle<Handle = VkDevice>> PipelineCache for PipelineCacheObject<Device> {}
298impl<Device: VkHandle<Handle = VkDevice>> PipelineCacheMut for PipelineCacheObject<Device> {}
299impl<Device: VkHandle<Handle = VkDevice>> PipelineCacheObject<Device> {
300    /// Constructs from raw values
301    /// # Safety
302    /// the resource must be created from the device and not freed anywhere
303    pub const unsafe fn manage(handle: VkPipelineCache, parent: Device) -> Self {
304        Self(handle, parent)
305    }
306
307    /// Purges the construct (Drop will not be called for this resource)
308    pub const fn unmanage(self) -> (VkPipelineCache, Device) {
309        let h = self.0;
310        let p = unsafe { core::ptr::read(&self.1) };
311        core::mem::forget(self);
312
313        (h, p)
314    }
315}
316impl<Device: VkHandle<Handle = VkDevice> + Clone> PipelineCacheObject<&'_ Device> {
317    /// Owning parent object by cloning it.
318    #[inline(always)]
319    pub fn clone_parent(self) -> PipelineCacheObject<Device> {
320        let r = PipelineCacheObject(self.0, self.1.clone());
321        core::mem::forget(self);
322
323        r
324    }
325}
326impl<Device: crate::Device> PipelineCacheObject<Device> {
327    /// Create a new pipeline cache
328    /// # Failures
329    /// On failure, this command returns
330    ///
331    /// * [`VK_ERROR_OUT_OF_HOST_MEMORY`]
332    /// * [`VK_ERROR_OUT_OF_DEVICE_MEMORY`]
333    #[implements]
334    pub fn new(device: Device, create_info: &PipelineCacheCreateInfo) -> crate::Result<Self> {
335        Ok(unsafe { Self::manage(device.new_pipeline_cache_raw(create_info, None)?, device) })
336    }
337}
338
339pub trait PipelineCache: VkHandle<Handle = VkPipelineCache> + DeviceChildHandle {
340    /// Get the size of the data store from a pipeline cache
341    /// # Failures
342    /// On failure, this command returns
343    ///
344    /// * [`VK_ERROR_OUT_OF_HOST_MEMORY`]
345    /// * [`VK_ERROR_OUT_OF_DEVICE_MEMORY`]
346    #[implements]
347    #[inline]
348    fn data_len(&self) -> crate::Result<usize> {
349        let mut n = 0;
350        unsafe {
351            crate::vkfn::get_pipeline_cache_data(
352                self.device_handle(),
353                self.native_ptr(),
354                &mut n,
355                core::ptr::null_mut(),
356            )
357            .into_result()?;
358        }
359
360        Ok(n)
361    }
362
363    /// Get the content of the data store from a pipeline cache
364    /// # Failures
365    /// On failure, this command returns
366    ///
367    /// * [`VK_ERROR_OUT_OF_HOST_MEMORY`]
368    /// * [`VK_ERROR_OUT_OF_DEVICE_MEMORY`]
369    #[implements]
370    #[inline]
371    fn data_into(&self, store: &mut [u8]) -> crate::Result<usize> {
372        let mut dl = store.len();
373        unsafe {
374            crate::vkfn::get_pipeline_cache_data(
375                self.device_handle(),
376                self.native_ptr(),
377                &mut dl,
378                store.as_mut_ptr() as _,
379            )
380            .into_result()?;
381        }
382
383        Ok(dl)
384    }
385}
386DerefContainerBracketImpl!(for PipelineCache {});
387GuardsImpl!(for PipelineCache {});
388
389pub trait PipelineCacheMut: PipelineCache + VkHandleMut {
390    /// Combine the data stores of pipeline caches into `self`
391    /// # Failures
392    /// On failure, this command returns
393    ///
394    /// * [`VK_ERROR_OUT_OF_HOST_MEMORY`]
395    /// * [`VK_ERROR_OUT_OF_DEVICE_MEMORY`]
396    #[implements]
397    #[inline]
398    fn merge(&mut self, srcs: &[VkHandleRef<VkPipelineCache>]) -> crate::Result<()> {
399        unsafe {
400            crate::vkfn::merge_pipeline_caches(
401                self.device_handle(),
402                self.native_ptr_mut(),
403                srcs.len() as _,
404                slice_as_ptr_empty_null(srcs) as _,
405            )
406            .into_result()
407            .map(drop)
408        }
409    }
410}
411DerefContainerBracketImpl!(for mut PipelineCacheMut {});
412GuardsImpl!(for mut PipelineCacheMut {});
413
414#[repr(transparent)]
415#[derive(Clone)]
416pub struct PipelineLayoutCreateInfo<'d>(
417    VkPipelineLayoutCreateInfo,
418    core::marker::PhantomData<(
419        &'d dyn VkHandle<Handle = VkDescriptorSetLayout>,
420        &'d [PushConstantRange],
421    )>,
422);
423impl<'d> PipelineLayoutCreateInfo<'d> {
424    pub const fn new(
425        descriptor_set_layouts: &'d [VkHandleRef<'d, VkDescriptorSetLayout>],
426        push_constant_ranges: &'d [PushConstantRange],
427    ) -> Self {
428        Self(
429            VkPipelineLayoutCreateInfo {
430                sType: VkPipelineLayoutCreateInfo::TYPE,
431                pNext: core::ptr::null(),
432                flags: 0,
433                setLayoutCount: descriptor_set_layouts.len() as _,
434                pSetLayouts: slice_as_ptr_empty_null(descriptor_set_layouts) as _,
435                pushConstantRangeCount: push_constant_ranges.len() as _,
436                pPushConstantRanges: slice_as_ptr_empty_null(push_constant_ranges),
437            },
438            core::marker::PhantomData,
439        )
440    }
441
442    pub const unsafe fn from_raw(raw: VkPipelineLayoutCreateInfo) -> Self {
443        Self(raw, core::marker::PhantomData)
444    }
445
446    pub const fn into_raw(self) -> VkPipelineLayoutCreateInfo {
447        self.0
448    }
449}
450
451/// Opaque handle to a pipeline layout object
452#[derive(VkHandle, VkObject)]
453#[VkObject(type = VkPipelineLayout::OBJECT_TYPE)]
454pub struct PipelineLayoutObject<Device: VkHandle<Handle = VkDevice>>(VkPipelineLayout, Device);
455#[implements]
456impl<Device: VkHandle<Handle = VkDevice>> Drop for PipelineLayoutObject<Device> {
457    #[inline(always)]
458    fn drop(&mut self) {
459        unsafe {
460            crate::vkfn::destroy_pipeline_layout(self.1.native_ptr(), self.0, core::ptr::null());
461        }
462    }
463}
464unsafe impl<Device: VkHandle<Handle = VkDevice> + Sync> Sync for PipelineLayoutObject<Device> {}
465unsafe impl<Device: VkHandle<Handle = VkDevice> + Send> Send for PipelineLayoutObject<Device> {}
466impl<Device: VkHandle<Handle = VkDevice>> DeviceChildHandle for PipelineLayoutObject<Device> {
467    #[inline]
468    fn device_handle(&self) -> VkDevice {
469        self.1.native_ptr()
470    }
471}
472impl<Device: crate::Device> DeviceChild for PipelineLayoutObject<Device> {
473    type ConcreteDevice = Device;
474
475    #[inline]
476    fn device(&self) -> &Self::ConcreteDevice {
477        &self.1
478    }
479}
480impl<Device: VkHandle<Handle = VkDevice>> PipelineLayout for PipelineLayoutObject<Device> {}
481impl<Device: VkHandle<Handle = VkDevice>> PipelineLayoutObject<Device> {
482    /// Constructs from raw values
483    /// # Safety
484    /// the resource must be created from the device and not freed anywhere
485    pub const unsafe fn manage(handle: VkPipelineLayout, parent: Device) -> Self {
486        Self(handle, parent)
487    }
488
489    /// Purges the construct (Drop will not be called for this resource)
490    pub const fn unmanage(self) -> (VkPipelineLayout, Device) {
491        let r = unsafe { (self.0, core::ptr::read(&self.1)) };
492        core::mem::forget(self);
493
494        r
495    }
496}
497impl<Device: VkHandle<Handle = VkDevice> + Clone> PipelineLayoutObject<&'_ Device> {
498    /// Owning parent object by cloning it.
499    #[inline(always)]
500    pub fn clone_parent(self) -> PipelineLayoutObject<Device> {
501        let r = PipelineLayoutObject(self.0, self.1.clone());
502        core::mem::forget(self);
503
504        r
505    }
506}
507impl<Device: crate::Device> PipelineLayoutObject<Device> {
508    /// Creates a new pipeline layout object
509    /// # Failures
510    /// On failure, this command returns
511    ///
512    /// * [`VK_ERROR_OUT_OF_HOST_MEMORY`]
513    /// * [`VK_ERROR_OUT_OF_DEVICE_MEMORY`]
514    #[implements]
515    #[inline]
516    pub fn new(device: Device, info: &PipelineLayoutCreateInfo) -> crate::Result<Self> {
517        Ok(unsafe { Self::manage(device.new_pipeline_layout_raw(info, None)?, device) })
518    }
519}
520
521pub type PushConstantRange = VkPushConstantRange;
522impl PushConstantRange {
523    pub const fn new(shader_stage: VkShaderStageFlags, byte_range: Range<u32>) -> Self {
524        Self {
525            stageFlags: shader_stage,
526            offset: byte_range.start,
527            size: byte_range.end - byte_range.start,
528        }
529    }
530
531    pub const fn for_type<T>(shader_stage: VkShaderStageFlags, offset: u32) -> Self {
532        Self {
533            stageFlags: shader_stage,
534            offset,
535            size: core::mem::size_of::<T>() as _,
536        }
537    }
538}
539
540pub trait PipelineLayout: VkHandle<Handle = VkPipelineLayout> {}
541DerefContainerBracketImpl!(for PipelineLayout {});
542GuardsImpl!(for PipelineLayout {});
543
544/// Opaque handle to a pipeline object
545#[derive(VkHandle, VkObject)]
546#[VkObject(type = VkPipeline::OBJECT_TYPE)]
547pub struct PipelineObject<Device: VkHandle<Handle = VkDevice>>(VkPipeline, Device);
548#[implements]
549impl<Device: VkHandle<Handle = VkDevice>> Drop for PipelineObject<Device> {
550    #[inline(always)]
551    fn drop(&mut self) {
552        unsafe {
553            crate::vkfn::destroy_pipeline(self.1.native_ptr(), self.0, core::ptr::null());
554        }
555    }
556}
557unsafe impl<Device: VkHandle<Handle = VkDevice> + Sync> Sync for PipelineObject<Device> {}
558unsafe impl<Device: VkHandle<Handle = VkDevice> + Send> Send for PipelineObject<Device> {}
559impl<Device: VkHandle<Handle = VkDevice>> DeviceChildHandle for PipelineObject<Device> {
560    #[inline]
561    fn device_handle(&self) -> VkDevice {
562        self.1.native_ptr()
563    }
564}
565impl<Device: crate::Device> DeviceChild for PipelineObject<Device> {
566    type ConcreteDevice = Device;
567
568    #[inline]
569    fn device(&self) -> &Self::ConcreteDevice {
570        &self.1
571    }
572}
573impl<Device: VkHandle<Handle = VkDevice>> Pipeline for PipelineObject<Device> {}
574impl<Device: VkHandle<Handle = VkDevice>> PipelineObject<Device> {
575    /// Constructs from raw values
576    /// # Safety
577    /// the resource must be created from the device and not freed anywhere
578    pub const unsafe fn manage(handle: VkPipeline, parent: Device) -> Self {
579        Self(handle, parent)
580    }
581
582    /// Purges the construct (Drop will not be called for this resource)
583    pub const fn unmanage(self) -> (VkPipeline, Device) {
584        let r = unsafe { (self.0, core::ptr::read(&self.1)) };
585        core::mem::forget(self);
586
587        r
588    }
589}
590impl<Device: VkHandle<Handle = VkDevice> + Clone> PipelineObject<&'_ Device> {
591    /// Owning parent object by cloning it.
592    #[inline(always)]
593    pub fn clone_parent(self) -> PipelineObject<Device> {
594        let r = PipelineObject(self.0, self.1.clone());
595        core::mem::forget(self);
596
597        r
598    }
599}
600
601pub trait Pipeline: VkHandle<Handle = VkPipeline> {}
602DerefContainerBracketImpl!(for Pipeline {});
603GuardsImpl!(for Pipeline {});
604
605/// Structure specifying parameters of a newly created pipeline dynamic state
606#[repr(transparent)]
607#[derive(Clone)]
608pub struct PipelineDynamicStateCreateInfo<'d>(
609    VkPipelineDynamicStateCreateInfo,
610    core::marker::PhantomData<&'d [VkDynamicState]>,
611);
612impl<'d> PipelineDynamicStateCreateInfo<'d> {
613    pub const fn new(states: &'d [VkDynamicState]) -> Self {
614        Self(
615            VkPipelineDynamicStateCreateInfo {
616                sType: VkPipelineDynamicStateCreateInfo::TYPE,
617                pNext: core::ptr::null(),
618                flags: 0,
619                dynamicStateCount: states.len() as _,
620                pDynamicStates: slice_as_ptr_empty_null(states),
621            },
622            core::marker::PhantomData,
623        )
624    }
625
626    pub const unsafe fn from_raw(raw: VkPipelineDynamicStateCreateInfo) -> Self {
627        Self(raw, core::marker::PhantomData)
628    }
629
630    pub const fn into_raw(self) -> VkPipelineDynamicStateCreateInfo {
631        self.0
632    }
633}
634
635#[repr(transparent)]
636#[derive(Clone)]
637pub struct PipelineShaderStage<'d, 's>(
638    pub(crate) VkPipelineShaderStageCreateInfo,
639    core::marker::PhantomData<(
640        Option<&'d dyn VulkanStructure>,
641        &'d dyn VkHandle<Handle = VkShaderModule>,
642        &'d core::ffi::CStr,
643        Option<&'s SpecializationInfo<'d>>,
644    )>,
645);
646impl<'d, 's> PipelineShaderStage<'d, 's> {
647    #[inline(always)]
648    pub fn new(
649        stage: ShaderStage,
650        shader: &'d (impl VkHandle<Handle = VkShaderModule> + ?Sized),
651        entrypoint_name: &'d core::ffi::CStr,
652    ) -> Self {
653        Self(
654            VkPipelineShaderStageCreateInfo {
655                sType: VkPipelineShaderStageCreateInfo::TYPE,
656                pNext: core::ptr::null(),
657                flags: 0,
658                stage: stage as _,
659                module: shader.native_ptr(),
660                pName: entrypoint_name.as_ptr(),
661                pSpecializationInfo: core::ptr::null(),
662            },
663            core::marker::PhantomData,
664        )
665    }
666
667    pub const unsafe fn from_raw(raw: VkPipelineShaderStageCreateInfo) -> Self {
668        Self(raw, core::marker::PhantomData)
669    }
670
671    pub const fn into_raw(self) -> VkPipelineShaderStageCreateInfo {
672        self.0
673    }
674
675    #[inline(always)]
676    pub fn with_next(mut self, next: &'d (impl TypedVulkanStructure + ?Sized)) -> Self {
677        self.0.pNext = next.as_generic() as *const _ as _;
678        self
679    }
680
681    pub const fn with_specialization_info(mut self, info: &'s SpecializationInfo<'d>) -> Self {
682        self.0.pSpecializationInfo = info as *const _ as _;
683        self
684    }
685}
686
687pub unsafe trait SpecializationConstants {
688    const ENTRIES: &'static [SpecializationMapEntry];
689
690    fn as_ptr(&self) -> *const c_void;
691}
692DerefContainerBracketImpl!(unsafe for SpecializationConstants {
693    const ENTRIES: &'static [SpecializationMapEntry] = T::ENTRIES;
694
695    #[inline(always)]
696    fn as_ptr(&self) -> *const c_void {
697        T::as_ptr(&**self)
698    }
699});
700
701pub type SpecializationMapEntry = VkSpecializationMapEntry;
702impl SpecializationMapEntry {
703    pub const fn for_byte_range(constant_id: u32, byte_range: core::ops::Range<u32>) -> Self {
704        Self {
705            constantID: constant_id,
706            offset: byte_range.start,
707            size: (byte_range.end - byte_range.start) as _,
708        }
709    }
710
711    pub const fn for_type<T>(constant_id: u32, offset: u32) -> Self {
712        Self {
713            constantID: constant_id,
714            offset,
715            size: core::mem::size_of::<T>(),
716        }
717    }
718}
719
720#[repr(transparent)]
721#[derive(Clone)]
722pub struct SpecializationInfo<'d>(
723    VkSpecializationInfo,
724    core::marker::PhantomData<(&'d [VkSpecializationMapEntry], &'d dyn core::any::Any)>,
725);
726impl<'d> SpecializationInfo<'d> {
727    pub fn new<T: 'd + SpecializationConstants>(data: &'d T) -> Self {
728        Self(
729            VkSpecializationInfo {
730                mapEntryCount: T::ENTRIES.len() as _,
731                pMapEntries: slice_as_ptr_empty_null(T::ENTRIES),
732                dataSize: core::mem::size_of::<T>() as _,
733                pData: data.as_ptr(),
734            },
735            core::marker::PhantomData,
736        )
737    }
738
739    /// # Safety
740    /// `data` must have enough size.
741    pub const unsafe fn from_any_type<T: 'd>(entries: &'d [SpecializationMapEntry], data: &'d T) -> Self {
742        Self(
743            VkSpecializationInfo {
744                mapEntryCount: entries.len() as _,
745                pMapEntries: slice_as_ptr_empty_null(entries),
746                dataSize: core::mem::size_of::<T>() as _,
747                pData: data as *const _ as _,
748            },
749            core::marker::PhantomData,
750        )
751    }
752
753    /// # Safety
754    /// `data` must have enough size.
755    pub const unsafe fn from_binary(entries: &'d [SpecializationMapEntry], data: &'d [u8]) -> Self {
756        Self(
757            VkSpecializationInfo {
758                mapEntryCount: entries.len() as _,
759                pMapEntries: slice_as_ptr_empty_null(entries),
760                dataSize: data.len() as _,
761                pData: data.as_ptr() as _,
762            },
763            core::marker::PhantomData,
764        )
765    }
766
767    pub const unsafe fn from_raw(raw: VkSpecializationInfo) -> Self {
768        Self(raw, core::marker::PhantomData)
769    }
770
771    pub const fn into_raw(self) -> VkSpecializationInfo {
772        self.0
773    }
774}
775
776pub type VertexInputBindingDescription = VkVertexInputBindingDescription;
777impl VertexInputBindingDescription {
778    /// Consumed per vertex with stride
779    pub const fn per_vertex(binding: u32, stride: u32) -> Self {
780        Self {
781            binding,
782            stride,
783            inputRate: VK_VERTEX_INPUT_RATE_VERTEX,
784        }
785    }
786
787    /// Consumed per instance with stride
788    pub const fn per_instance(binding: u32, stride: u32) -> Self {
789        Self {
790            binding,
791            stride,
792            inputRate: VK_VERTEX_INPUT_RATE_INSTANCE,
793        }
794    }
795
796    /// Consumed per vertex the structured data
797    pub const fn per_vertex_typed<T>(binding: u32) -> Self {
798        Self::per_vertex(binding, core::mem::size_of::<T>() as _)
799    }
800
801    /// Consumed per instance the structured data
802    pub const fn per_instance_typed<T>(binding: u32) -> Self {
803        Self::per_instance(binding, core::mem::size_of::<T>() as _)
804    }
805}
806
807pub type VertexInputAttributeDescription = VkVertexInputAttributeDescription;
808
809/// Structure specifying parameters of a newly created pipeline vertex input state
810#[repr(transparent)]
811#[derive(Clone)]
812pub struct PipelineVertexInputStateCreateInfo<'d>(
813    VkPipelineVertexInputStateCreateInfo,
814    core::marker::PhantomData<(
815        &'d [VertexInputBindingDescription],
816        &'d [VertexInputAttributeDescription],
817    )>,
818);
819impl<'d> PipelineVertexInputStateCreateInfo<'d> {
820    pub const fn new(
821        bindings: &'d [VertexInputBindingDescription],
822        attributes: &'d [VertexInputAttributeDescription],
823    ) -> Self {
824        Self(
825            VkPipelineVertexInputStateCreateInfo {
826                sType: VkPipelineVertexInputStateCreateInfo::TYPE,
827                pNext: core::ptr::null(),
828                flags: 0,
829                vertexBindingDescriptionCount: bindings.len() as _,
830                pVertexBindingDescriptions: slice_as_ptr_empty_null(bindings),
831                vertexAttributeDescriptionCount: attributes.len() as _,
832                pVertexAttributeDescriptions: slice_as_ptr_empty_null(attributes),
833            },
834            core::marker::PhantomData,
835        )
836    }
837
838    pub const unsafe fn from_raw(raw: VkPipelineVertexInputStateCreateInfo) -> Self {
839        Self(raw, core::marker::PhantomData)
840    }
841
842    pub const fn into_raw(self) -> VkPipelineVertexInputStateCreateInfo {
843        self.0
844    }
845}
846
847/// Supported primitive topologies
848#[repr(i32)]
849#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
850pub enum PrimitiveTopology {
851    /// A series of [separate point primitives](https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#drawing-point-lists)
852    PointList = VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
853    /// A series of [separate line primitives](https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#drawing-line-lists)
854    LineList = VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
855    /// A series of [connected line primitives](https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#drawing-line-strips)
856    /// with consecutive lines sharing a vertex
857    LineStrip = VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,
858    /// A series of [separate triangle primitives](https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#drawing-triangle-lists)
859    TriangleList = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
860    /// A series of [connected triangle primitives](https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#drawing-triangle-strips)
861    /// with consecutive triangles sharing an edge
862    TriangleStrip = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
863    /// A series of [connected triangle primitives](https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#drawing-triangle-strips)
864    /// with all triangles sharing a common vertex
865    TriangleFan = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,
866    /// A series of [separate line primitives with adjacency](https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#drawing-line-lists-with-adjacency)
867    LineListWithAdjacency = VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,
868    /// A series of [connected line primitives with adjacency](https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#drawing-line-strips-with-adjacency)
869    /// with consecutive primitives sharing three vertices
870    LineStripWithAdjacency = VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY,
871    /// A series of [separate triangle primitives with adjacency](https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#drawing-triangle-lists-with-adjacency)
872    TriangleListWithAdjacency = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,
873    /// [Connected triangle primitives with adjacency](https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#drawing-triangle-strips-with-adjacency)
874    /// with consecutive triangles sharing an edge
875    TriangleStripWithAdjacency = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY,
876    /// [Separate patch primitives](https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#drawing-patch-lists)
877    PatchList = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,
878}
879
880/// Structure specifying parameters of a newly created pipeline input assembly state
881#[repr(transparent)]
882#[derive(Clone)]
883pub struct PipelineInputAssemblyStateCreateInfo(VkPipelineInputAssemblyStateCreateInfo);
884impl PipelineInputAssemblyStateCreateInfo {
885    pub const fn new(topology: PrimitiveTopology) -> Self {
886        Self(VkPipelineInputAssemblyStateCreateInfo {
887            sType: VkPipelineInputAssemblyStateCreateInfo::TYPE,
888            pNext: core::ptr::null(),
889            flags: 0,
890            topology: topology as _,
891            primitiveRestartEnable: false as _,
892        })
893    }
894
895    pub const unsafe fn from_raw(raw: VkPipelineInputAssemblyStateCreateInfo) -> Self {
896        Self(raw)
897    }
898
899    pub const fn into_raw(self) -> VkPipelineInputAssemblyStateCreateInfo {
900        self.0
901    }
902
903    pub const fn enable_primitive_restart(mut self) -> Self {
904        self.0.primitiveRestartEnable = true as _;
905        self
906    }
907}
908
909/// Structure specifying parameters of a newly created pipeline tessellation state
910#[repr(transparent)]
911#[derive(Clone)]
912pub struct PipelineTessellationStateCreateInfo(VkPipelineTessellationStateCreateInfo);
913impl PipelineTessellationStateCreateInfo {
914    pub const fn new(patch_control_points: u32) -> Self {
915        Self(VkPipelineTessellationStateCreateInfo {
916            sType: VkPipelineTessellationStateCreateInfo::TYPE,
917            pNext: core::ptr::null(),
918            flags: 0,
919            patchControlPoints: patch_control_points,
920        })
921    }
922
923    pub const unsafe fn from_raw(raw: VkPipelineTessellationStateCreateInfo) -> Self {
924        Self(raw)
925    }
926
927    pub const fn into_raw(self) -> VkPipelineTessellationStateCreateInfo {
928        self.0
929    }
930}
931
932/// Structure specifying parameters of a newly created pipeline viewport state
933#[repr(transparent)]
934#[derive(Clone)]
935pub struct PipelineViewportStateCreateInfo<'d>(
936    VkPipelineViewportStateCreateInfo,
937    core::marker::PhantomData<(&'d [VkViewport], &'d [VkRect2D])>,
938);
939impl<'d> PipelineViewportStateCreateInfo<'d> {
940    pub const unsafe fn new_unchecked(viewports: &'d [VkViewport], scissors: &'d [VkRect2D]) -> Self {
941        Self(
942            VkPipelineViewportStateCreateInfo {
943                sType: VkPipelineViewportStateCreateInfo::TYPE,
944                pNext: core::ptr::null(),
945                flags: 0,
946                viewportCount: viewports.len() as _,
947                pViewports: slice_as_ptr_empty_null(viewports),
948                scissorCount: scissors.len() as _,
949                pScissors: slice_as_ptr_empty_null(scissors),
950            },
951            core::marker::PhantomData,
952        )
953    }
954
955    #[inline]
956    pub fn new(viewports: &'d [VkViewport], scissors: &'d [VkRect2D]) -> Self {
957        assert_eq!(viewports.len(), scissors.len());
958
959        unsafe { Self::new_unchecked(viewports, scissors) }
960    }
961
962    pub const fn new_array<const N: usize>(viewports: &'d [VkViewport; N], scissors: &'d [VkRect2D; N]) -> Self {
963        // checked that both length are identitcal by const generic parameter
964        unsafe { Self::new_unchecked(viewports, scissors) }
965    }
966
967    pub const fn new_dynamic(count: u32) -> Self {
968        Self(
969            VkPipelineViewportStateCreateInfo {
970                sType: VkPipelineViewportStateCreateInfo::TYPE,
971                pNext: core::ptr::null(),
972                flags: 0,
973                viewportCount: count,
974                pViewports: core::ptr::null(),
975                scissorCount: count,
976                pScissors: core::ptr::null(),
977            },
978            core::marker::PhantomData,
979        )
980    }
981
982    pub const fn new_dynamic_with_count() -> Self {
983        Self::new_dynamic(0)
984    }
985
986    pub const unsafe fn from_raw(raw: VkPipelineViewportStateCreateInfo) -> Self {
987        Self(raw, core::marker::PhantomData)
988    }
989
990    pub const fn into_raw(self) -> VkPipelineViewportStateCreateInfo {
991        self.0
992    }
993}
994
995#[repr(i32)]
996#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
997pub enum PolygonMode {
998    Fill = VK_POLYGON_MODE_FILL,
999    Line = VK_POLYGON_MODE_LINE,
1000    Point = VK_POLYGON_MODE_POINT,
1001}
1002
1003#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1004#[bitflags_newtype]
1005pub struct CullModeFlags(VkCullModeFlags);
1006impl CullModeFlags {
1007    pub const NONE: Self = Self(VK_CULL_MODE_NONE);
1008    pub const FRONT: Self = Self(VK_CULL_MODE_FRONT_BIT);
1009    pub const BACK: Self = Self(VK_CULL_MODE_BACK_BIT);
1010    pub const FRONT_AND_BACK: Self = Self(VK_CULL_MODE_FRONT_AND_BACK);
1011}
1012
1013#[repr(i32)]
1014#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1015pub enum FrontFace {
1016    Clockwise = VK_FRONT_FACE_CLOCKWISE,
1017    CounterClockwise = VK_FRONT_FACE_COUNTER_CLOCKWISE,
1018}
1019
1020/// Structure specifying parameters of a newly created pipeline rasterization state
1021#[repr(transparent)]
1022#[derive(Clone)]
1023pub struct PipelineRasterizationStateCreateInfo<'d>(
1024    VkPipelineRasterizationStateCreateInfo,
1025    core::marker::PhantomData<Option<&'d dyn VulkanStructure>>,
1026);
1027impl<'d> PipelineRasterizationStateCreateInfo<'d> {
1028    pub const fn new(polygon_mode: PolygonMode, cull_mode: CullModeFlags, front_face: FrontFace) -> Self {
1029        Self(
1030            VkPipelineRasterizationStateCreateInfo {
1031                sType: VkPipelineRasterizationStateCreateInfo::TYPE,
1032                pNext: core::ptr::null(),
1033                flags: 0,
1034                depthClampEnable: false as _,
1035                rasterizerDiscardEnable: false as _,
1036                polygonMode: polygon_mode as _,
1037                cullMode: cull_mode.bits(),
1038                frontFace: front_face as _,
1039                depthBiasEnable: false as _,
1040                depthBiasConstantFactor: 0.0,
1041                depthBiasClamp: 0.0,
1042                depthBiasSlopeFactor: 0.0,
1043                lineWidth: 1.0,
1044            },
1045            core::marker::PhantomData,
1046        )
1047    }
1048
1049    pub const unsafe fn from_raw(raw: VkPipelineRasterizationStateCreateInfo) -> Self {
1050        Self(raw, core::marker::PhantomData)
1051    }
1052
1053    pub const fn into_raw(self) -> VkPipelineRasterizationStateCreateInfo {
1054        self.0
1055    }
1056
1057    #[inline]
1058    pub fn with_next(mut self, next: &'d (impl VulkanStructure + ?Sized)) -> Self {
1059        self.0.pNext = next as *const _ as _;
1060        self
1061    }
1062
1063    pub const fn enable_depth_clamp(mut self) -> Self {
1064        self.0.depthClampEnable = true as _;
1065        self
1066    }
1067
1068    pub const fn enable_rasterizer_discard(mut self) -> Self {
1069        self.0.rasterizerDiscardEnable = true as _;
1070        self
1071    }
1072
1073    pub const fn enable_depth_bias(mut self, constant_factor: f32, clamp: f32, slope_factor: f32) -> Self {
1074        self.0.depthBiasEnable = true as _;
1075        self.0.depthBiasConstantFactor = constant_factor;
1076        self.0.depthBiasClamp = clamp;
1077        self.0.depthBiasSlopeFactor = slope_factor;
1078        self
1079    }
1080
1081    pub const fn line_width(mut self, w: f32) -> Self {
1082        self.0.lineWidth = w;
1083        self
1084    }
1085}
1086
1087/// Specify the conservative rasterization mode
1088#[cfg(feature = "VK_EXT_conservative_rasterization")]
1089#[repr(i32)]
1090#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1091pub enum ConservativeRasterizationMode {
1092    /// Conservative rasterization is disabled and rasterization proceeds as normal
1093    Disabled = VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT,
1094    /// Conservative rasterization is enabled in overestimation mode
1095    Overestimate = VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT,
1096    /// Conservative rasterization is enabled in underestimation mode
1097    Underestimate = VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT,
1098}
1099
1100/// Structure specifying conservative raster state
1101#[cfg(feature = "VK_EXT_conservative_rasterization")]
1102#[repr(transparent)]
1103#[derive(Debug, Clone, PartialEq)]
1104pub struct PipelineRasterizationConservativeStateCreateInfo<'d>(
1105    VkPipelineRasterizationConservativeStateCreateInfoEXT,
1106    core::marker::PhantomData<Option<&'d dyn VulkanStructure>>,
1107);
1108#[cfg(feature = "VK_EXT_conservative_rasterization")]
1109unsafe impl VulkanStructure for PipelineRasterizationConservativeStateCreateInfo<'_> {
1110    #[inline(always)]
1111    fn as_generic(&self) -> &GenericVulkanStructure {
1112        unsafe { core::mem::transmute(self) }
1113    }
1114
1115    #[inline(always)]
1116    fn as_generic_mut(&mut self) -> &mut GenericVulkanStructure {
1117        unsafe { core::mem::transmute(self) }
1118    }
1119}
1120#[cfg(feature = "VK_EXT_conservative_rasterization")]
1121impl<'d> PipelineRasterizationConservativeStateCreateInfo<'d> {
1122    pub const fn new(mode: ConservativeRasterizationMode, extra_primitive_overestimation_size: f32) -> Self {
1123        Self(
1124            VkPipelineRasterizationConservativeStateCreateInfoEXT {
1125                sType: VkPipelineRasterizationConservativeStateCreateInfoEXT::TYPE,
1126                pNext: core::ptr::null(),
1127                flags: 0,
1128                conservativeRasterizationMode: mode as _,
1129                extraPrimitiveOverestimationSize: extra_primitive_overestimation_size,
1130            },
1131            core::marker::PhantomData,
1132        )
1133    }
1134
1135    pub const unsafe fn from_raw(raw: VkPipelineRasterizationConservativeStateCreateInfoEXT) -> Self {
1136        Self(raw, core::marker::PhantomData)
1137    }
1138
1139    pub const fn into_raw(self) -> VkPipelineRasterizationConservativeStateCreateInfoEXT {
1140        self.0
1141    }
1142
1143    #[inline]
1144    pub fn with_next(mut self, next: &'d (impl VulkanStructure + ?Sized)) -> Self {
1145        self.0.pNext = next as *const _ as _;
1146        self
1147    }
1148}
1149
1150/// Line rasterization modes
1151#[cfg(feature = "VK_KHR_line_rasterization")]
1152#[repr(i32)]
1153#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1154pub enum LineRasterizationMode {
1155    /// Equivalent to [`LineRasterizationMode::Rectangular`] if [`VkPhysicalDeviceLimits::strictLines`] is true,
1156    /// otherwise lines are drawn as non-`strictLines` parallelograms.
1157    /// Both of these modes are defined in [Basic Line Segment Rasterization](https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#primsrast-lines-basic)
1158    Default = VK_LINE_RASTERIZATION_MODE_DEFAULT_KHR,
1159    /// Lines drawn as if they were rectangles extruded from the line
1160    Rectangular = VK_LINE_RASTERIZATION_MODE_RECTANGULAR_KHR,
1161    /// Lines drawn by determining which pixel diamonds the line intersects and exits,
1162    /// as defined in [Bresenham Line Segment Rasterization](https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#primsrast-lines-bresenham)
1163    Bresenham = VK_LINE_RASTERIZATION_MODE_BRESENHAM_KHR,
1164    /// Lines drawn if they were rectangles extruded from the line, with alpha falloff,
1165    /// as defined in [Smooth Lines](https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#primsrast-lines-smooth)
1166    RectangularSmooth = VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_KHR,
1167}
1168
1169/// Structure specifying parameters of a newly created pipeline line rasterization state
1170#[cfg(feature = "VK_KHR_line_rasterization")]
1171#[repr(transparent)]
1172#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1173pub struct PipelineRasterizationLineStateCreateInfo<'d>(
1174    VkPipelineRasterizationLineStateCreateInfoKHR,
1175    core::marker::PhantomData<Option<&'d dyn VulkanStructure>>,
1176);
1177#[cfg(feature = "VK_KHR_line_rasterization")]
1178unsafe impl VulkanStructure for PipelineRasterizationLineStateCreateInfo<'_> {
1179    #[inline(always)]
1180    fn as_generic(&self) -> &GenericVulkanStructure {
1181        unsafe { core::mem::transmute(self) }
1182    }
1183
1184    #[inline(always)]
1185    fn as_generic_mut(&mut self) -> &mut GenericVulkanStructure {
1186        unsafe { core::mem::transmute(self) }
1187    }
1188}
1189#[cfg(feature = "VK_KHR_line_rasterization")]
1190impl<'d> PipelineRasterizationLineStateCreateInfo<'d> {
1191    pub const fn new(mode: LineRasterizationMode) -> Self {
1192        Self(
1193            VkPipelineRasterizationLineStateCreateInfoKHR {
1194                sType: VkPipelineRasterizationLineStateCreateInfoKHR::TYPE,
1195                pNext: core::ptr::null(),
1196                lineRasterizationMode: mode as _,
1197                stippledLineEnable: false as _,
1198                lineStippleFactor: 0,
1199                lineStipplePattern: 0,
1200            },
1201            core::marker::PhantomData,
1202        )
1203    }
1204
1205    pub const unsafe fn from_raw(raw: VkPipelineRasterizationLineStateCreateInfoKHR) -> Self {
1206        Self(raw, core::marker::PhantomData)
1207    }
1208
1209    pub const fn into_raw(self) -> VkPipelineRasterizationLineStateCreateInfoKHR {
1210        self.0
1211    }
1212
1213    #[inline]
1214    pub fn with_next(mut self, next: &'d (impl VulkanStructure + ?Sized)) -> Self {
1215        self.0.pNext = next as *const _ as _;
1216        self
1217    }
1218
1219    pub const fn stippled(mut self, factor: u32, pattern: u16) -> Self {
1220        self.0.stippledLineEnable = true as _;
1221        self.0.lineStippleFactor = factor;
1222        self.0.lineStipplePattern = pattern;
1223        self
1224    }
1225}
1226
1227/// Structure specifying parameters of a newly created pipeline multisample state
1228#[repr(transparent)]
1229#[derive(Clone)]
1230pub struct PipelineMultisampleStateCreateInfo<'d> {
1231    data: VkPipelineMultisampleStateCreateInfo,
1232    samplemask_lifetime_binder: PhantomData<&'d [VkSampleMask]>,
1233}
1234impl<'d> PipelineMultisampleStateCreateInfo<'d> {
1235    #[allow(clippy::new_without_default)]
1236    pub const fn new() -> Self {
1237        Self {
1238            data: VkPipelineMultisampleStateCreateInfo {
1239                sType: VkPipelineMultisampleStateCreateInfo::TYPE,
1240                pNext: core::ptr::null(),
1241                flags: 0,
1242                rasterizationSamples: 1,
1243                sampleShadingEnable: VK_FALSE,
1244                minSampleShading: 1.0,
1245                pSampleMask: core::ptr::null(),
1246                alphaToCoverageEnable: VK_FALSE,
1247                alphaToOneEnable: VK_FALSE,
1248            },
1249            samplemask_lifetime_binder: PhantomData,
1250        }
1251    }
1252
1253    pub const unsafe fn from_raw(raw: VkPipelineMultisampleStateCreateInfo) -> Self {
1254        Self {
1255            data: raw,
1256            samplemask_lifetime_binder: core::marker::PhantomData,
1257        }
1258    }
1259
1260    pub const fn into_raw(self) -> VkPipelineMultisampleStateCreateInfo {
1261        self.data
1262    }
1263
1264    /// Specifies the number of samples per pixel used in rasterization. default=1
1265    pub const fn rasterization_samples(mut self, samples: usize) -> Self {
1266        self.data.rasterizationSamples = samples as _;
1267        self
1268    }
1269
1270    /// A bitmask of static coverage information that is ANDed with the coverage information generated
1271    /// during rasterization, as described in [Sample Mask](https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#fragops-samplemask).
1272    pub fn sample_mask(mut self, mask: &'d [VkSampleMask]) -> Self {
1273        if mask.is_empty() {
1274            self.data.pSampleMask = core::ptr::null();
1275            return self;
1276        }
1277
1278        assert_eq!(mask.len(), (self.data.rasterizationSamples as usize + 31) / 32);
1279        self.data.pSampleMask = mask.as_ptr();
1280        self
1281    }
1282
1283    /// Specifies a minimum fraction of sample shading(must be in the range [0, 1]).
1284    /// Pass a `None` to disable [Sample Shading](https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#primsrast-sampleshading).
1285    pub const fn sample_shading(mut self, min: f32) -> Self {
1286        assert!(
1287            0.0 <= min && min <= 1.0,
1288            "Invalid usage: VkPipelineMultisampleStateCreateInfo::minSampleShading must be in the range [0, 1]"
1289        );
1290
1291        self.data.sampleShadingEnable = true as _;
1292        self.data.minSampleShading = min;
1293        self
1294    }
1295
1296    /// Controls whether a temporary coverage value is generated based on the alpha component of the fragment's
1297    /// first color output as specified in the [Multisample Coverage](https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#fragops-covg) section.
1298    pub const fn enable_alpha_to_coverage(mut self) -> Self {
1299        self.data.alphaToCoverageEnable = true as _;
1300        self
1301    }
1302
1303    /// Controls whether the alpha component of the fragment's first color output is replaced with one as described in
1304    /// [Multisample Coverage](https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#fragops-covg).
1305    pub const fn replace_alpha_to_one(mut self) -> Self {
1306        self.data.alphaToOneEnable = true as _;
1307        self
1308    }
1309}
1310
1311/// Structure specifying parameters of a newly created pipeline depth stencil state
1312#[repr(transparent)]
1313#[derive(Clone)]
1314pub struct PipelineDepthStencilStateCreateInfo(VkPipelineDepthStencilStateCreateInfo);
1315impl PipelineDepthStencilStateCreateInfo {
1316    pub const fn new() -> Self {
1317        Self(VkPipelineDepthStencilStateCreateInfo {
1318            sType: VkPipelineDepthStencilStateCreateInfo::TYPE,
1319            pNext: core::ptr::null(),
1320            flags: 0,
1321            depthTestEnable: VK_FALSE,
1322            depthWriteEnable: VK_FALSE,
1323            depthCompareOp: VK_COMPARE_OP_LESS,
1324            depthBoundsTestEnable: VK_FALSE,
1325            stencilTestEnable: VK_FALSE,
1326            front: VkStencilOpState {
1327                failOp: VK_STENCIL_OP_KEEP,
1328                passOp: VK_STENCIL_OP_KEEP,
1329                depthFailOp: VK_STENCIL_OP_KEEP,
1330                compareOp: VK_COMPARE_OP_ALWAYS,
1331                compareMask: 0,
1332                writeMask: 0,
1333                reference: 0,
1334            },
1335            back: VkStencilOpState {
1336                failOp: VK_STENCIL_OP_KEEP,
1337                passOp: VK_STENCIL_OP_KEEP,
1338                depthFailOp: VK_STENCIL_OP_KEEP,
1339                compareOp: VK_COMPARE_OP_ALWAYS,
1340                compareMask: 0,
1341                writeMask: 0,
1342                reference: 0,
1343            },
1344            minDepthBounds: 0.0,
1345            maxDepthBounds: 1.0,
1346        })
1347    }
1348
1349    pub const unsafe fn from_raw(raw: VkPipelineDepthStencilStateCreateInfo) -> Self {
1350        Self(raw)
1351    }
1352
1353    pub const fn into_raw(self) -> VkPipelineDepthStencilStateCreateInfo {
1354        self.0
1355    }
1356
1357    /// Configures depth operation
1358    ///
1359    /// Controls whether depth testing is enabled, depth writes are enabled, and the comparison operator used in the depth test
1360    /// Specifying `None` to `compare_to` disables depth testing
1361    pub const fn config_depth(mut self, compare_op: Option<CompareOp>, write_enable: bool) -> Self {
1362        self.0.depthTestEnable = compare_op.is_some() as _;
1363        self.0.depthCompareOp = match compare_op {
1364            Some(x) => x,
1365            None => CompareOp::Always,
1366        } as _;
1367        self.0.depthWriteEnable = write_enable as _;
1368
1369        self
1370    }
1371
1372    /// Disables depth testing
1373    pub const fn disable_depth_test(mut self) -> Self {
1374        self.0.depthTestEnable = false as _;
1375        self
1376    }
1377
1378    /// Controls whether depth writes are enabled, or always disabled
1379    pub const fn depth_write(mut self, enable: bool) -> Self {
1380        self.0.depthWriteEnable = enable as _;
1381        self
1382    }
1383
1384    /// Sets depth bounds. Specifying `None` to disable depth bounds test
1385    pub const fn depth_bounds(mut self, bounds: Option<core::ops::Range<f32>>) -> Self {
1386        self.0.depthBoundsTestEnable = bounds.is_some() as _;
1387        self.0.minDepthBounds = match bounds {
1388            Some(ref r) => r.start,
1389            None => 0.0,
1390        };
1391        self.0.maxDepthBounds = match bounds {
1392            Some(ref r) => r.end,
1393            None => 0.0,
1394        };
1395
1396        self
1397    }
1398
1399    /// Controls whether stencil testing is enabled
1400    pub const fn stencil_test(mut self, enable: bool) -> Self {
1401        self.0.stencilTestEnable = enable as _;
1402        self
1403    }
1404
1405    /// Sets the state parameters for the front-face stencil test
1406    pub const fn stencil_state_front(mut self, state: VkStencilOpState) -> Self {
1407        self.0.front = state;
1408        self
1409    }
1410
1411    /// Sets the state parameters for the back-face stencil test
1412    pub const fn stencil_state_back(mut self, state: VkStencilOpState) -> Self {
1413        self.0.back = state;
1414        self
1415    }
1416}
1417
1418/// Structure specifying parameters of a newly created pipeline color blend state
1419#[repr(transparent)]
1420#[derive(Clone)]
1421pub struct PipelineColorBlendStateCreateInfo<'d>(
1422    VkPipelineColorBlendStateCreateInfo,
1423    core::marker::PhantomData<&'d [VkPipelineColorBlendAttachmentState]>,
1424);
1425impl<'d> PipelineColorBlendStateCreateInfo<'d> {
1426    pub const fn new(attachments: &'d [VkPipelineColorBlendAttachmentState]) -> Self {
1427        Self(
1428            VkPipelineColorBlendStateCreateInfo {
1429                sType: VkPipelineColorBlendStateCreateInfo::TYPE,
1430                pNext: core::ptr::null(),
1431                flags: 0,
1432                logicOpEnable: false as _,
1433                logicOp: LogicOp::NoOp as _,
1434                attachmentCount: attachments.len() as _,
1435                pAttachments: slice_as_ptr_empty_null(attachments),
1436                blendConstants: [0.0; 4],
1437            },
1438            core::marker::PhantomData,
1439        )
1440    }
1441
1442    pub const unsafe fn from_raw(raw: VkPipelineColorBlendStateCreateInfo) -> Self {
1443        Self(raw, core::marker::PhantomData)
1444    }
1445
1446    pub const fn into_raw(self) -> VkPipelineColorBlendStateCreateInfo {
1447        self.0
1448    }
1449
1450    pub const fn logic_op(mut self, logic_op: LogicOp) -> Self {
1451        self.0.logicOpEnable = true as _;
1452        self.0.logicOp = logic_op as _;
1453        self
1454    }
1455
1456    pub const fn blend_constants(mut self, constants: [f32; 4]) -> Self {
1457        self.0.blendConstants = constants;
1458        self
1459    }
1460}
1461
1462impl VkPipelineColorBlendAttachmentState {
1463    pub const NOBLEND: Self = Self {
1464        colorWriteMask: VK_COLOR_COMPONENT_A_BIT
1465            | VK_COLOR_COMPONENT_R_BIT
1466            | VK_COLOR_COMPONENT_G_BIT
1467            | VK_COLOR_COMPONENT_B_BIT,
1468        blendEnable: VK_FALSE,
1469        ..unsafe { std::mem::MaybeUninit::zeroed().assume_init() }
1470    };
1471
1472    /// `src * 1 + dst * (1 - src.a)` for both color and alpha.
1473    ///
1474    /// https://stackoverflow.com/questions/18918643/how-to-achieve-d3d-output-with-premultiplied-alpha-for-use-with-d3dimage-in-wpf
1475    pub const PREMULTIPLIED: Self = Self {
1476        colorWriteMask: VK_COLOR_COMPONENT_A_BIT
1477            | VK_COLOR_COMPONENT_R_BIT
1478            | VK_COLOR_COMPONENT_G_BIT
1479            | VK_COLOR_COMPONENT_B_BIT,
1480        blendEnable: VK_TRUE,
1481        srcColorBlendFactor: VK_BLEND_FACTOR_ONE,
1482        dstColorBlendFactor: VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
1483        colorBlendOp: VK_BLEND_OP_ADD,
1484        // srcAlphaBlendFactor: BlendFactor::OneMinusDestAlpha as _,
1485        // dstAlphaBlendFactor: BlendFactor::One as _,
1486        srcAlphaBlendFactor: VK_BLEND_FACTOR_ONE,
1487        dstAlphaBlendFactor: VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
1488        alphaBlendOp: VK_BLEND_OP_ADD,
1489    };
1490
1491    pub const fn enabled(self) -> Self {
1492        Self {
1493            blendEnable: VK_TRUE,
1494            ..self
1495        }
1496    }
1497
1498    pub const fn disabled(self) -> Self {
1499        Self {
1500            blendEnable: VK_FALSE,
1501            ..self
1502        }
1503    }
1504
1505    pub const fn color_blend_factor_src(self, f: VkBlendFactor) -> Self {
1506        Self {
1507            srcColorBlendFactor: f,
1508            ..self
1509        }
1510    }
1511
1512    pub const fn color_blend_factor_dst(self, f: VkBlendFactor) -> Self {
1513        Self {
1514            dstColorBlendFactor: f,
1515            ..self
1516        }
1517    }
1518
1519    pub const fn alpha_blend_factor_src(self, f: VkBlendFactor) -> Self {
1520        Self {
1521            srcAlphaBlendFactor: f,
1522            ..self
1523        }
1524    }
1525
1526    pub const fn alpha_blend_factor_dst(self, f: VkBlendFactor) -> Self {
1527        Self {
1528            dstAlphaBlendFactor: f,
1529            ..self
1530        }
1531    }
1532
1533    pub const fn color_blend_op(self, op: VkBlendOp) -> Self {
1534        Self {
1535            colorBlendOp: op,
1536            ..self
1537        }
1538    }
1539
1540    pub const fn alpha_blend_op(self, op: VkBlendOp) -> Self {
1541        Self {
1542            alphaBlendOp: op,
1543            ..self
1544        }
1545    }
1546
1547    pub const fn color_blend(self, src: VkBlendFactor, op: VkBlendOp, dst: VkBlendFactor) -> Self {
1548        Self {
1549            srcColorBlendFactor: src,
1550            dstColorBlendFactor: dst,
1551            colorBlendOp: op,
1552            ..self
1553        }
1554    }
1555
1556    pub const fn alpha_blend(self, src: VkBlendFactor, op: VkBlendOp, dst: VkBlendFactor) -> Self {
1557        Self {
1558            srcAlphaBlendFactor: src,
1559            dstAlphaBlendFactor: dst,
1560            alphaBlendOp: op,
1561            ..self
1562        }
1563    }
1564}
1565
1566#[repr(transparent)]
1567#[derive(Clone)]
1568pub struct GraphicsPipelineCreateInfo<'d>(
1569    VkGraphicsPipelineCreateInfo,
1570    core::marker::PhantomData<(
1571        &'d dyn VkHandle<Handle = VkPipelineLayout>,
1572        &'d dyn VkHandle<Handle = VkRenderPass>,
1573        &'d [PipelineShaderStage<'d, 'd>],
1574        &'d PipelineVertexInputStateCreateInfo<'d>,
1575        &'d PipelineInputAssemblyStateCreateInfo,
1576        Option<&'d PipelineTessellationStateCreateInfo>,
1577        &'d PipelineViewportStateCreateInfo<'d>,
1578        &'d PipelineRasterizationStateCreateInfo<'d>,
1579        Option<&'d PipelineMultisampleStateCreateInfo<'d>>,
1580        Option<&'d PipelineDepthStencilStateCreateInfo>,
1581        &'d PipelineColorBlendStateCreateInfo<'d>,
1582        Option<&'d PipelineDynamicStateCreateInfo<'d>>,
1583        Option<&'d dyn VkHandle<Handle = VkPipeline>>,
1584    )>,
1585);
1586impl<'d> GraphicsPipelineCreateInfo<'d> {
1587    #[inline]
1588    pub fn new(
1589        layout: &'d (impl VkHandle<Handle = VkPipelineLayout> + ?Sized),
1590        pass: SubpassRef<'d, impl VkHandle<Handle = VkRenderPass> + ?Sized>,
1591        stages: &'d [PipelineShaderStage<'d, 'd>],
1592        vertex_input_state: &'d PipelineVertexInputStateCreateInfo<'d>,
1593        input_assembly_state: &'d PipelineInputAssemblyStateCreateInfo,
1594        viewport_state: &'d PipelineViewportStateCreateInfo<'d>,
1595        rasterization_state: &'d PipelineRasterizationStateCreateInfo<'d>,
1596        color_blend_state: &'d PipelineColorBlendStateCreateInfo<'d>,
1597    ) -> Self {
1598        Self(
1599            VkGraphicsPipelineCreateInfo {
1600                sType: VkGraphicsPipelineCreateInfo::TYPE,
1601                pNext: core::ptr::null(),
1602                flags: 0,
1603                stageCount: stages.len() as _,
1604                pStages: slice_as_ptr_empty_null(stages) as _,
1605                pVertexInputState: vertex_input_state as *const _ as _,
1606                pInputAssemblyState: input_assembly_state as *const _ as _,
1607                pTessellationState: core::ptr::null(),
1608                pViewportState: viewport_state as *const _ as _,
1609                pRasterizationState: rasterization_state as *const _ as _,
1610                pMultisampleState: core::ptr::null(),
1611                pDepthStencilState: core::ptr::null(),
1612                pColorBlendState: color_blend_state as *const _ as _,
1613                pDynamicState: core::ptr::null(),
1614                layout: layout.native_ptr(),
1615                renderPass: pass.0.native_ptr(),
1616                subpass: pass.1,
1617                basePipelineHandle: VkPipeline::NULL,
1618                basePipelineIndex: -1,
1619            },
1620            core::marker::PhantomData,
1621        )
1622    }
1623
1624    #[inline]
1625    pub fn derived_by_handle(parent: &'d (impl VkHandle<Handle = VkPipeline> + ?Sized)) -> Self {
1626        Self(
1627            VkGraphicsPipelineCreateInfo {
1628                sType: VkGraphicsPipelineCreateInfo::TYPE,
1629                pNext: core::ptr::null(),
1630                flags: VK_PIPELINE_CREATE_DERIVATIVE_BIT,
1631                stageCount: 0,
1632                pStages: core::ptr::null(),
1633                pVertexInputState: core::ptr::null(),
1634                pInputAssemblyState: core::ptr::null(),
1635                pTessellationState: core::ptr::null(),
1636                pViewportState: core::ptr::null(),
1637                pRasterizationState: core::ptr::null(),
1638                pMultisampleState: core::ptr::null(),
1639                pDepthStencilState: core::ptr::null(),
1640                pColorBlendState: core::ptr::null(),
1641                pDynamicState: core::ptr::null(),
1642                layout: VkPipelineLayout::NULL,
1643                renderPass: VkRenderPass::NULL,
1644                subpass: 0,
1645                basePipelineHandle: parent.native_ptr(),
1646                basePipelineIndex: -1,
1647            },
1648            core::marker::PhantomData,
1649        )
1650    }
1651
1652    pub const fn derived_by_index(parent: i32) -> Self {
1653        Self(
1654            VkGraphicsPipelineCreateInfo {
1655                sType: VkGraphicsPipelineCreateInfo::TYPE,
1656                pNext: core::ptr::null(),
1657                flags: VK_PIPELINE_CREATE_DERIVATIVE_BIT,
1658                stageCount: 0,
1659                pStages: core::ptr::null(),
1660                pVertexInputState: core::ptr::null(),
1661                pInputAssemblyState: core::ptr::null(),
1662                pTessellationState: core::ptr::null(),
1663                pViewportState: core::ptr::null(),
1664                pRasterizationState: core::ptr::null(),
1665                pMultisampleState: core::ptr::null(),
1666                pDepthStencilState: core::ptr::null(),
1667                pColorBlendState: core::ptr::null(),
1668                pDynamicState: core::ptr::null(),
1669                layout: VkPipelineLayout::NULL,
1670                renderPass: VkRenderPass::NULL,
1671                subpass: 0,
1672                basePipelineHandle: VkPipeline::NULL,
1673                basePipelineIndex: parent,
1674            },
1675            core::marker::PhantomData,
1676        )
1677    }
1678
1679    pub const unsafe fn from_raw(raw: VkGraphicsPipelineCreateInfo) -> Self {
1680        Self(raw, core::marker::PhantomData)
1681    }
1682
1683    pub const fn into_raw(self) -> VkGraphicsPipelineCreateInfo {
1684        self.0
1685    }
1686
1687    pub const fn allow_derivatives(mut self) -> Self {
1688        self.0.flags |= VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT;
1689        self
1690    }
1691
1692    #[inline(always)]
1693    pub fn set_layout(mut self, layout: &'d (impl VkHandle<Handle = VkPipelineLayout> + ?Sized)) -> Self {
1694        self.0.layout = layout.native_ptr();
1695        self
1696    }
1697
1698    #[inline(always)]
1699    pub fn set_pass(mut self, pass: SubpassRef<'d, impl VkHandle<Handle = VkRenderPass> + ?Sized>) -> Self {
1700        self.0.renderPass = pass.0.native_ptr();
1701        self.0.subpass = pass.1;
1702        self
1703    }
1704
1705    pub const fn set_stages(mut self, stages: &'d [PipelineShaderStage<'d, 'd>]) -> Self {
1706        self.0.pStages = slice_as_ptr_empty_null(stages) as _;
1707        self
1708    }
1709
1710    pub const fn set_vertex_input_state(mut self, state: &'d PipelineVertexInputStateCreateInfo<'d>) -> Self {
1711        self.0.pVertexInputState = state as *const _ as _;
1712        self
1713    }
1714
1715    pub const fn set_input_assembly_state(mut self, state: &'d PipelineInputAssemblyStateCreateInfo) -> Self {
1716        self.0.pInputAssemblyState = state as *const _ as _;
1717        self
1718    }
1719
1720    pub const fn set_tessellation_state(mut self, state: &'d PipelineTessellationStateCreateInfo) -> Self {
1721        self.0.pTessellationState = state as *const _ as _;
1722        self
1723    }
1724
1725    pub const fn set_viewport_state(mut self, state: &'d PipelineViewportStateCreateInfo<'d>) -> Self {
1726        self.0.pViewportState = state as *const _ as _;
1727        self
1728    }
1729
1730    pub const fn set_rasterization_state(mut self, state: &'d PipelineRasterizationStateCreateInfo<'d>) -> Self {
1731        self.0.pRasterizationState = state as *const _ as _;
1732        self
1733    }
1734
1735    pub const fn set_multisample_state(mut self, state: &'d PipelineMultisampleStateCreateInfo<'d>) -> Self {
1736        self.0.pMultisampleState = state as *const _ as _;
1737        self
1738    }
1739
1740    pub const fn set_depth_stencil_state(mut self, state: &'d PipelineDepthStencilStateCreateInfo) -> Self {
1741        self.0.pDepthStencilState = state as *const _ as _;
1742        self
1743    }
1744
1745    pub const fn set_color_blend_state(mut self, state: &'d PipelineColorBlendStateCreateInfo<'d>) -> Self {
1746        self.0.pColorBlendState = state as *const _ as _;
1747        self
1748    }
1749
1750    pub const fn set_dynamic_state(mut self, states: &'d PipelineDynamicStateCreateInfo) -> Self {
1751        self.0.pDynamicState = states as *const _ as _;
1752        self
1753    }
1754}
1755
1756/// Structure specifying parameters of a newly created compute pipeline
1757#[repr(transparent)]
1758#[derive(Clone)]
1759pub struct ComputePipelineCreateInfo<'d>(
1760    VkComputePipelineCreateInfo,
1761    core::marker::PhantomData<(
1762        &'d dyn VkHandle<Handle = VkPipelineLayout>,
1763        PipelineShaderStage<'d, 'd>,
1764        Option<&'d dyn VkHandle<Handle = VkPipeline>>,
1765    )>,
1766);
1767impl<'d> ComputePipelineCreateInfo<'d> {
1768    #[inline]
1769    pub fn new(
1770        layout: &'d (impl VkHandle<Handle = VkPipelineLayout> + ?Sized),
1771        stage: PipelineShaderStage<'d, 'd>,
1772    ) -> Self {
1773        Self(
1774            VkComputePipelineCreateInfo {
1775                sType: VkComputePipelineCreateInfo::TYPE,
1776                pNext: core::ptr::null(),
1777                flags: 0,
1778                stage: stage.0,
1779                layout: layout.native_ptr(),
1780                basePipelineHandle: VkPipeline::NULL,
1781                basePipelineIndex: -1,
1782            },
1783            core::marker::PhantomData,
1784        )
1785    }
1786
1787    #[inline]
1788    pub fn derived_by_handle(parent: &'d (impl VkHandle<Handle = VkPipeline> + ?Sized)) -> Self {
1789        Self(
1790            VkComputePipelineCreateInfo {
1791                sType: VkComputePipelineCreateInfo::TYPE,
1792                pNext: core::ptr::null(),
1793                flags: VK_PIPELINE_CREATE_DERIVATIVE_BIT,
1794                stage: VkPipelineShaderStageCreateInfo {
1795                    sType: VkPipelineShaderStageCreateInfo::TYPE,
1796                    pNext: core::ptr::null(),
1797                    flags: 0,
1798                    stage: 0,
1799                    module: VkShaderModule::NULL,
1800                    pName: core::ptr::null(),
1801                    pSpecializationInfo: core::ptr::null(),
1802                },
1803                layout: VkPipelineLayout::NULL,
1804                basePipelineHandle: parent.native_ptr(),
1805                basePipelineIndex: -1,
1806            },
1807            core::marker::PhantomData,
1808        )
1809    }
1810
1811    #[inline]
1812    pub fn derived_by_index(parent: i32) -> Self {
1813        Self(
1814            VkComputePipelineCreateInfo {
1815                sType: VkComputePipelineCreateInfo::TYPE,
1816                pNext: core::ptr::null(),
1817                flags: VK_PIPELINE_CREATE_DERIVATIVE_BIT,
1818                stage: VkPipelineShaderStageCreateInfo {
1819                    sType: VkPipelineShaderStageCreateInfo::TYPE,
1820                    pNext: core::ptr::null(),
1821                    flags: 0,
1822                    stage: 0,
1823                    module: VkShaderModule::NULL,
1824                    pName: core::ptr::null(),
1825                    pSpecializationInfo: core::ptr::null(),
1826                },
1827                layout: VkPipelineLayout::NULL,
1828                basePipelineHandle: VkPipeline::NULL,
1829                basePipelineIndex: parent,
1830            },
1831            core::marker::PhantomData,
1832        )
1833    }
1834
1835    pub const unsafe fn from_raw(raw: VkComputePipelineCreateInfo) -> Self {
1836        Self(raw, core::marker::PhantomData)
1837    }
1838
1839    pub const fn into_raw(self) -> VkComputePipelineCreateInfo {
1840        self.0
1841    }
1842
1843    pub const fn allow_derivatives(mut self) -> Self {
1844        self.0.flags |= VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT;
1845        self
1846    }
1847
1848    pub const fn set_stage(mut self, stage: PipelineShaderStage<'d, 'd>) -> Self {
1849        self.0.stage = stage.0;
1850        self
1851    }
1852
1853    #[inline]
1854    pub fn set_layout(mut self, layout: &'d (impl VkHandle<Handle = VkPipelineLayout> + ?Sized)) -> Self {
1855        self.0.layout = layout.native_ptr();
1856        self
1857    }
1858}
1859
1860/// Bitmask specifying pipeline stages
1861#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
1862#[bitflags_newtype]
1863pub struct PipelineStageFlags(pub VkPipelineStageFlags);
1864impl PipelineStageFlags {
1865    /// The stage of the pipeline where any commands are initially received by the queue
1866    pub const TOP_OF_PIPE: Self = Self(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
1867    /// The stage of the pipeline where Draw/DispatchIndirect data structures are consumed
1868    pub const DRAW_INDIRECT: Self = Self(VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT);
1869    /// The stage of the pipeline where vertex and index buffers are consumed
1870    pub const VERTEX_INPUT: Self = Self(VK_PIPELINE_STAGE_VERTEX_INPUT_BIT);
1871    /// The vertex shader stage
1872    pub const VERTEX_SHADER: Self = Self(VK_PIPELINE_STAGE_VERTEX_SHADER_BIT);
1873    /// The tessellation control shader stage
1874    pub const TESSELLATION_CONTROL_SHADER: Self = Self(VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT);
1875    /// The tessellation evaluation shader stage
1876    pub const TESSELLATION_EVALUATION_SHADER: Self = Self(VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT);
1877    /// The geometry shader stage
1878    pub const GEOMETRY_SHADER: Self = Self(VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT);
1879    /// The fragment shader stage
1880    pub const FRAGMENT_SHADER: Self = Self(VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
1881    /// The stage of the pipeline where early fragment tests (depth and stencil tests before fragment shading) are performed
1882    pub const EARLY_FRAGMENT_TESTS: Self = Self(VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT);
1883    /// The stage of the pipeline where late fragment tests (depth and stencil tests after fragment shading) are performed
1884    pub const LATE_FRAGMENT_TESTS: Self = Self(VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
1885    /// The stage of the pipeline after blending where the final color values are output from the pipeline
1886    pub const COLOR_ATTACHMENT_OUTPUT: Self = Self(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
1887    /// The execution of copy commands
1888    pub const TRANSFER: Self = Self(VK_PIPELINE_STAGE_TRANSFER_BIT);
1889    /// The execution of a compute shader
1890    pub const COMPUTE_SHADER: Self = Self(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
1891    /// The final stage in the pipeline where operations generated by all commands complete execution
1892    pub const BOTTOM_OF_PIPE: Self = Self(VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
1893    /// A pseudo-stage indicating execution on the host of reads/writes of device memory
1894    pub const HOST: Self = Self(VK_PIPELINE_STAGE_HOST_BIT);
1895    /// The execution of all graphics pipeline stages
1896    pub const ALL_GRAPHICS: Self = Self(VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT);
1897    /// Equivalent to the logical OR of every other pipeline stage flag that is supported on the quue it is used with
1898    pub const ALL_COMMANDS: Self = Self(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
1899}
1900
1901/// Bitmask specifying pipeline stages (extended)
1902#[cfg(feature = "VK_KHR_synchronization2")]
1903#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
1904#[bitflags_newtype]
1905pub struct PipelineStageFlags2(pub VkPipelineStageFlags2KHR);
1906#[cfg(feature = "VK_KHR_synchronization2")]
1907impl PipelineStageFlags2 {
1908    pub const TOP_OF_PIPE: Self = Self(VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR);
1909    pub const DRAW_INDIRECT: Self = Self(VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT_KHR);
1910    pub const VERTEX_INPUT: Self = Self(VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT_KHR);
1911    pub const VERTEX_SHADER: Self = Self(VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT_KHR);
1912    pub const TESSELLATION_CONTROL_SHADER: Self = Self(VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT_KHR);
1913    pub const TESSELLATION_EVALUATION_SHADER: Self = Self(VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT_KHR);
1914    pub const GEOMETRY_SHADER: Self = Self(VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT_KHR);
1915    pub const FRAGMENT_SHADER: Self = Self(VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT_KHR);
1916    pub const EARLY_FRAGMENT_TESTS: Self = Self(VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT_KHR);
1917    pub const LATE_FRAGMENT_TESTS: Self = Self(VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT_KHR);
1918    pub const COLOR_ATTACHMENT_OUTPUT: Self = Self(VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR);
1919    pub const COMPUTE_SHADER: Self = Self(VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT_KHR);
1920    pub const ALL_TRANSFER: Self = Self(VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT_KHR);
1921    pub const BOTTOM_OF_PIPE: Self = Self(VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR);
1922    pub const HOST: Self = Self(VK_PIPELINE_STAGE_2_HOST_BIT_KHR);
1923    pub const ALL_GRAPHICS: Self = Self(VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT_KHR);
1924    pub const ALL_COMMANDS: Self = Self(VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT_KHR);
1925    pub const COPY: Self = Self(VK_PIPELINE_STAGE_2_COPY_BIT_KHR);
1926    pub const RESOLVE: Self = Self(VK_PIPELINE_STAGE_2_RESOLVE_BIT_KHR);
1927    pub const BLIT: Self = Self(VK_PIPELINE_STAGE_2_BLIT_BIT_KHR);
1928    pub const CLEAR: Self = Self(VK_PIPELINE_STAGE_2_CLEAR_BIT_KHR);
1929    pub const INDEX_INPUT: Self = Self(VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT_KHR);
1930    pub const VERTEX_ATTRIBUTE_INPUT: Self = Self(VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT_KHR);
1931    pub const PRE_RASTERIZATION_SHADERS: Self = Self(VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT_KHR);
1932}