oxidx/types/
structs.rs

1use std::{ffi::CStr, marker::PhantomData, mem::ManuallyDrop, ops::Range};
2
3use windows::{
4    core::PCSTR,
5    Win32::{
6        Foundation::{CloseHandle, HANDLE, LUID, POINT, RECT},
7        Graphics::Direct3D::D3D_SHADER_MACRO,
8    },
9};
10
11use crate::{
12    blob::Blob,
13    dx::{BlobbyInternal, Resource},
14    error::DxError,
15    root_signature::RootSignature,
16};
17
18use super::*;
19
20/// Describes an adapter (or video card) using DXGI 1.1.
21///
22/// For more information: [`DXGI_ADAPTER_DESC1 structure`](https://learn.microsoft.com/en-us/windows/win32/api/dxgi/ns-dxgi-dxgi_adapter_desc1)
23#[derive(Clone, Copy, Debug, PartialEq)]
24#[repr(transparent)]
25pub struct AdapterDesc1(pub(crate) DXGI_ADAPTER_DESC1);
26
27impl AdapterDesc1 {
28    #[inline]
29    pub fn description(&self) -> String {
30        String::from_utf16_lossy(&self.0.Description)
31    }
32
33    #[inline]
34    pub fn vendor_id(&self) -> u32 {
35        self.0.VendorId
36    }
37
38    #[inline]
39    pub fn sub_sys_id(&self) -> u32 {
40        self.0.SubSysId
41    }
42
43    #[inline]
44    pub fn revision(&self) -> u32 {
45        self.0.Revision
46    }
47
48    #[inline]
49    pub fn dedicated_video_memory(&self) -> usize {
50        self.0.DedicatedVideoMemory
51    }
52
53    #[inline]
54    pub fn dedicated_system_memory(&self) -> usize {
55        self.0.DedicatedSystemMemory
56    }
57
58    #[inline]
59    pub fn shared_system_memory(&self) -> usize {
60        self.0.DedicatedSystemMemory
61    }
62
63    #[inline]
64    pub fn adapter_luid(&self) -> Luid {
65        Luid(self.0.AdapterLuid)
66    }
67
68    #[inline]
69    pub fn flags(&self) -> AdapterFlags {
70        AdapterFlags::from_bits_retain(self.0.Flags as i32)
71    }
72}
73
74/// Describes the blend state.
75///
76/// For more information: [`D3D12_BLEND_DESC structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_blend_desc)
77#[derive(Clone, Copy, Debug, PartialEq)]
78#[repr(transparent)]
79pub struct BlendDesc(pub(crate) D3D12_BLEND_DESC);
80
81impl BlendDesc {
82    #[inline]
83    pub fn with_render_targets(
84        mut self,
85        render_targets: impl IntoIterator<Item = RenderTargetBlendDesc>,
86    ) -> Self {
87        let mut rts = [D3D12_RENDER_TARGET_BLEND_DESC::default(); 8];
88
89        for (i, desc) in render_targets.into_iter().take(8).enumerate() {
90            rts[i] = desc.0;
91        }
92
93        self.0.RenderTarget = rts;
94        self
95    }
96
97    #[inline]
98    pub fn enable_alpha_to_coverage(mut self) -> Self {
99        self.0.AlphaToCoverageEnable = true.into();
100        self
101    }
102
103    #[inline]
104    pub fn enable_independent_blend(mut self) -> Self {
105        self.0.IndependentBlendEnable = true.into();
106        self
107    }
108}
109
110impl Default for BlendDesc {
111    fn default() -> Self {
112        Self(D3D12_BLEND_DESC {
113            RenderTarget: std::array::from_fn(|_| RenderTargetBlendDesc::default().0),
114            ..Default::default()
115        })
116    }
117}
118
119/// Describes a 3D box.
120///
121/// For more information: [`D3D12_BOX structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_box)
122#[derive(Clone, Copy, Debug, Default, PartialEq)]
123#[repr(transparent)]
124pub struct DxBox(pub(crate) D3D12_BOX);
125
126impl DxBox {
127    #[inline]
128    pub fn with_left(mut self, val: u32) -> Self {
129        self.0.left = val;
130        self
131    }
132
133    #[inline]
134    pub fn with_top(mut self, val: u32) -> Self {
135        self.0.top = val;
136        self
137    }
138
139    #[inline]
140    pub fn with_front(mut self, val: u32) -> Self {
141        self.0.front = val;
142        self
143    }
144
145    #[inline]
146    pub fn with_right(mut self, val: u32) -> Self {
147        self.0.right = val;
148        self
149    }
150
151    #[inline]
152    pub fn with_bottom(mut self, val: u32) -> Self {
153        self.0.bottom = val;
154        self
155    }
156
157    #[inline]
158    pub fn with_back(mut self, val: u32) -> Self {
159        self.0.back = val;
160        self
161    }
162}
163
164/// Describes a value used to optimize clear operations for a particular resource.
165///
166/// For more information: [`D3D12_CLEAR_VALUE structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_clear_value)
167#[derive(Clone, Copy)]
168#[repr(transparent)]
169pub struct ClearValue(pub(crate) D3D12_CLEAR_VALUE);
170
171impl ClearValue {
172    #[inline]
173    pub fn color(format: Format, value: impl Into<[f32; 4]>) -> Self {
174        Self(D3D12_CLEAR_VALUE {
175            Format: format.as_raw(),
176            Anonymous: D3D12_CLEAR_VALUE_0 {
177                Color: value.into(),
178            },
179        })
180    }
181
182    #[inline]
183    pub fn depth(format: Format, depth: f32, stencil: u8) -> Self {
184        Self(D3D12_CLEAR_VALUE {
185            Format: format.as_raw(),
186            Anonymous: D3D12_CLEAR_VALUE_0 {
187                DepthStencil: D3D12_DEPTH_STENCIL_VALUE {
188                    Depth: depth,
189                    Stencil: stencil,
190                },
191            },
192        })
193    }
194}
195
196/// Describes a command queue.
197///
198/// For more information: [`D3D12_COMMAND_QUEUE_DESC structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_command_queue_desc)
199#[derive(Clone, Copy, Debug, Default, PartialEq)]
200#[repr(transparent)]
201pub struct CommandQueueDesc(pub(crate) D3D12_COMMAND_QUEUE_DESC);
202
203impl CommandQueueDesc {
204    #[inline]
205    pub fn new(ty: CommandListType) -> Self {
206        Self(D3D12_COMMAND_QUEUE_DESC {
207            Type: ty.as_raw(),
208            ..Default::default()
209        })
210    }
211
212    #[inline]
213    pub fn direct() -> Self {
214        Self(D3D12_COMMAND_QUEUE_DESC {
215            Type: D3D12_COMMAND_LIST_TYPE_DIRECT,
216            ..Default::default()
217        })
218    }
219
220    #[inline]
221    pub fn compute() -> Self {
222        Self(D3D12_COMMAND_QUEUE_DESC {
223            Type: D3D12_COMMAND_LIST_TYPE_COMPUTE,
224            ..Default::default()
225        })
226    }
227
228    #[inline]
229    pub fn copy() -> Self {
230        Self(D3D12_COMMAND_QUEUE_DESC {
231            Type: D3D12_COMMAND_LIST_TYPE_COPY,
232            ..Default::default()
233        })
234    }
235
236    #[inline]
237    pub fn video_decode() -> Self {
238        Self(D3D12_COMMAND_QUEUE_DESC {
239            Type: D3D12_COMMAND_LIST_TYPE_VIDEO_DECODE,
240            ..Default::default()
241        })
242    }
243
244    #[inline]
245    pub fn video_process() -> Self {
246        Self(D3D12_COMMAND_QUEUE_DESC {
247            Type: D3D12_COMMAND_LIST_TYPE_VIDEO_PROCESS,
248            ..Default::default()
249        })
250    }
251
252    #[inline]
253    pub fn video_encode() -> Self {
254        Self(D3D12_COMMAND_QUEUE_DESC {
255            Type: D3D12_COMMAND_LIST_TYPE_VIDEO_ENCODE,
256            ..Default::default()
257        })
258    }
259
260    #[inline]
261    pub fn with_priority(mut self, priority: CommandQueuePriority) -> Self {
262        self.0.Priority = priority.as_raw();
263        self
264    }
265
266    #[inline]
267    pub fn with_flags(mut self, flags: CommandQueueFlags) -> Self {
268        self.0.Flags = flags.as_raw();
269        self
270    }
271
272    #[inline]
273    pub fn with_node_mask(mut self, node_mask: u32) -> Self {
274        self.0.NodeMask = node_mask;
275        self
276    }
277
278    #[inline]
279    pub fn r#type(&self) -> CommandListType {
280        self.0.Type.into()
281    }
282
283    #[inline]
284    pub fn priority(&self) -> CommandQueuePriority {
285        self.0.Priority.into()
286    }
287
288    #[inline]
289    pub fn flags(&self) -> CommandQueueFlags {
290        self.0.Flags.into()
291    }
292
293    #[inline]
294    pub fn node_mask(&self) -> u32 {
295        self.0.NodeMask
296    }
297}
298
299/// Describes the arguments (parameters) of a command signature.
300///
301/// For more information: [`D3D12_COMMAND_SIGNATURE_DESC structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_command_signature_desc)
302#[derive(Clone, Copy, Debug, Default, PartialEq)]
303#[repr(transparent)]
304pub struct CommandSignatureDesc<'a>(pub(crate) D3D12_COMMAND_SIGNATURE_DESC, PhantomData<&'a ()>);
305
306impl<'a> CommandSignatureDesc<'a> {
307    #[inline]
308    pub fn with_byte_stride(mut self, byte_stride: u32) -> Self {
309        self.0.ByteStride = byte_stride;
310        self
311    }
312
313    #[inline]
314    pub fn with_indirect_arguments(
315        mut self,
316        indirect_arguments: &'a [IndirectArgumentDesc],
317    ) -> Self {
318        self.0.NumArgumentDescs = indirect_arguments.len() as u32;
319        self.0.pArgumentDescs = indirect_arguments.as_ptr() as *const _;
320        self
321    }
322
323    #[inline]
324    pub fn with_node_mask(mut self, node_mask: u32) -> Self {
325        self.0.NodeMask = node_mask;
326        self
327    }
328}
329
330/// Describes a compute pipeline state object.
331///
332/// For more information: [`D3D12_COMPUTE_PIPELINE_STATE_DESC structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_compute_pipeline_state_desc)
333#[derive(Clone, Debug, PartialEq)]
334#[repr(transparent)]
335pub struct ComputePipelineStateDesc<'a>(
336    pub(crate) D3D12_COMPUTE_PIPELINE_STATE_DESC,
337    PhantomData<&'a ()>,
338);
339
340impl<'a> ComputePipelineStateDesc<'a> {
341    #[inline]
342    pub fn new(cs: &'a Blob) -> Self {
343        Self(
344            D3D12_COMPUTE_PIPELINE_STATE_DESC {
345                CS: cs.as_shader_bytecode(),
346                ..Default::default()
347            },
348            Default::default(),
349        )
350    }
351
352    #[inline]
353    pub fn with_root_signature(mut self, root_signature: &'a RootSignature) -> Self {
354        unsafe {
355            self.0.pRootSignature = std::mem::transmute_copy(&root_signature.0);
356            self
357        }
358    }
359
360    #[inline]
361    pub fn with_cache(mut self, cache: &'a Blob) -> Self {
362        self.0.CachedPSO = cache.as_cached_pipeline_state();
363        self
364    }
365
366    #[inline]
367    pub fn with_flags(mut self, flags: PipelineStateFlags) -> Self {
368        self.0.Flags = flags.as_raw();
369        self
370    }
371}
372
373/// Describes a constant buffer to view.
374///
375/// For more information: [`D3D12_CONSTANT_BUFFER_VIEW_DESC structure `](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_constant_buffer_view_desc)
376#[derive(Clone, Copy, Debug, Default, PartialEq)]
377#[repr(transparent)]
378pub struct ConstantBufferViewDesc(pub(crate) D3D12_CONSTANT_BUFFER_VIEW_DESC);
379
380impl ConstantBufferViewDesc {
381    #[inline]
382    pub fn new(buffer_location: u64, size: u32) -> Self {
383        Self(D3D12_CONSTANT_BUFFER_VIEW_DESC {
384            BufferLocation: buffer_location,
385            SizeInBytes: size,
386        })
387    }
388}
389
390/// Describes a CPU descriptor handle.
391///
392/// For more information: [`D3D12_CPU_DESCRIPTOR_HANDLE structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_cpu_descriptor_handle)
393#[derive(Clone, Copy, Debug, Default, PartialEq)]
394#[repr(transparent)]
395pub struct CpuDescriptorHandle(pub(crate) D3D12_CPU_DESCRIPTOR_HANDLE);
396
397impl CpuDescriptorHandle {
398    /// Returns a new handle with offset relative to the current handle.
399    #[inline]
400    pub fn offset(&self, offset: usize) -> Self {
401        Self(D3D12_CPU_DESCRIPTOR_HANDLE {
402            ptr: self.0.ptr + offset,
403        })
404    }
405
406    #[inline]
407    pub fn advance(&self, distance: usize, handle_size: usize) -> Self {
408        self.offset(distance * handle_size)
409    }
410
411    #[inline]
412    pub fn step(&mut self, step: usize, handle_size: usize) {
413        self.0.ptr += step * handle_size;
414    }
415}
416
417/// Describes a vertex element in a vertex buffer in an output slot.
418///
419/// For more information: [`D3D12_SO_DECLARATION_ENTRY structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_so_declaration_entry)
420#[derive(Clone, Copy, Debug, PartialEq)]
421#[repr(transparent)]
422pub struct DeclarationEntry(pub(crate) D3D12_SO_DECLARATION_ENTRY);
423
424impl DeclarationEntry {
425    #[inline]
426    pub fn new(
427        semantic: SemanticName,
428        stream: u32,
429        components: Range<u8>,
430        output_slot: u8,
431    ) -> Self {
432        let semantic_name = PCSTR::from_raw(semantic.name().as_ptr() as *const _);
433
434        Self(D3D12_SO_DECLARATION_ENTRY {
435            Stream: stream,
436            SemanticName: semantic_name,
437            SemanticIndex: semantic.index() as u32,
438            StartComponent: components.start,
439            ComponentCount: components.count() as u8,
440            OutputSlot: output_slot,
441        })
442    }
443}
444
445/// Describes depth-stencil state.
446///
447/// For more information: [`D3D12_DEPTH_STENCIL_DESC structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_depth_stencil_desc)
448#[derive(Clone, Copy, Debug, PartialEq)]
449#[repr(transparent)]
450pub struct DepthStencilDesc(pub(crate) D3D12_DEPTH_STENCIL_DESC);
451
452impl DepthStencilDesc {
453    #[inline]
454    pub fn enable_depth(mut self, depth_func: ComparisonFunc) -> Self {
455        self.0.DepthEnable = true.into();
456        self.0.DepthFunc = depth_func.as_raw();
457        self
458    }
459
460    #[inline]
461    pub fn with_depth_write_mask(mut self, mask: DepthWriteMask) -> Self {
462        self.0.DepthWriteMask = mask.as_raw();
463        self
464    }
465
466    #[inline]
467    pub fn enable_stencil(mut self, stencil_read_mask: u8, stencil_write_mask: u8) -> Self {
468        self.0.StencilEnable = true.into();
469        self.0.StencilReadMask = stencil_read_mask;
470        self.0.StencilWriteMask = stencil_write_mask;
471        self
472    }
473
474    #[inline]
475    pub fn with_front_face(mut self, front_face: DepthStencilOpDesc) -> Self {
476        self.0.FrontFace = front_face.0;
477        self
478    }
479
480    #[inline]
481    pub fn with_back_face(mut self, back_face: DepthStencilOpDesc) -> Self {
482        self.0.BackFace = back_face.0;
483        self
484    }
485}
486
487impl Default for DepthStencilDesc {
488    fn default() -> Self {
489        Self(D3D12_DEPTH_STENCIL_DESC {
490            DepthWriteMask: D3D12_DEPTH_WRITE_MASK_ALL,
491            ..Default::default()
492        })
493    }
494}
495
496/// Describes stencil operations that can be performed based on the results of stencil test.
497///
498/// For more information: [`D3D12_DEPTH_STENCILOP_DESC structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_depth_stencilop_desc)
499#[derive(Clone, Copy, Debug, Default, PartialEq)]
500#[repr(transparent)]
501pub struct DepthStencilOpDesc(pub(crate) D3D12_DEPTH_STENCILOP_DESC);
502
503impl DepthStencilOpDesc {
504    #[inline]
505    pub fn with_stencil_fail_op(mut self, stencil_fail_op: StencilOp) -> Self {
506        self.0.StencilFailOp = stencil_fail_op.as_raw();
507        self
508    }
509
510    #[inline]
511    pub fn with_stencil_depth_fail_op(mut self, stencil_depth_fail_op: StencilOp) -> Self {
512        self.0.StencilDepthFailOp = stencil_depth_fail_op.as_raw();
513        self
514    }
515
516    #[inline]
517    pub fn with_stencil_pass_op(mut self, stencil_pass_op: StencilOp) -> Self {
518        self.0.StencilPassOp = stencil_pass_op.as_raw();
519        self
520    }
521
522    #[inline]
523    pub fn with_stencil_func(mut self, stencil_func: ComparisonFunc) -> Self {
524        self.0.StencilFunc = stencil_func.as_raw();
525        self
526    }
527}
528
529/// Describes the subresources of a texture that are accessible from a depth-stencil view.
530///
531/// For more information: [`D3D12_DEPTH_STENCIL_VIEW_DESC structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_depth_stencil_view_desc)
532#[derive(Clone, Copy)]
533#[repr(transparent)]
534pub struct DepthStencilViewDesc(pub(crate) D3D12_DEPTH_STENCIL_VIEW_DESC);
535
536impl DepthStencilViewDesc {
537    #[inline]
538    pub fn texture_1d(format: Format, mip_slice: u32) -> Self {
539        Self(D3D12_DEPTH_STENCIL_VIEW_DESC {
540            Format: format.as_raw(),
541            ViewDimension: D3D12_DSV_DIMENSION_TEXTURE1D,
542            Anonymous: D3D12_DEPTH_STENCIL_VIEW_DESC_0 {
543                Texture1D: D3D12_TEX1D_DSV {
544                    MipSlice: mip_slice,
545                },
546            },
547            Flags: D3D12_DSV_FLAG_NONE,
548        })
549    }
550
551    #[inline]
552    pub fn texture_1d_array(format: Format, mip_slice: u32, array: Range<u32>) -> Self {
553        Self(D3D12_DEPTH_STENCIL_VIEW_DESC {
554            Format: format.as_raw(),
555            ViewDimension: D3D12_DSV_DIMENSION_TEXTURE1DARRAY,
556            Anonymous: D3D12_DEPTH_STENCIL_VIEW_DESC_0 {
557                Texture1DArray: D3D12_TEX1D_ARRAY_DSV {
558                    MipSlice: mip_slice,
559                    FirstArraySlice: array.start,
560                    ArraySize: array.count() as u32,
561                },
562            },
563            Flags: D3D12_DSV_FLAG_NONE,
564        })
565    }
566
567    #[inline]
568    pub fn texture_2d(format: Format, mip_slice: u32) -> Self {
569        Self(D3D12_DEPTH_STENCIL_VIEW_DESC {
570            Format: format.as_raw(),
571            ViewDimension: D3D12_DSV_DIMENSION_TEXTURE2D,
572            Anonymous: D3D12_DEPTH_STENCIL_VIEW_DESC_0 {
573                Texture2D: D3D12_TEX2D_DSV {
574                    MipSlice: mip_slice,
575                },
576            },
577            Flags: D3D12_DSV_FLAG_NONE,
578        })
579    }
580
581    #[inline]
582    pub fn texture_2d_array(format: Format, mip_slice: u32, array: Range<u32>) -> Self {
583        Self(D3D12_DEPTH_STENCIL_VIEW_DESC {
584            Format: format.as_raw(),
585            ViewDimension: D3D12_DSV_DIMENSION_TEXTURE2DARRAY,
586            Anonymous: D3D12_DEPTH_STENCIL_VIEW_DESC_0 {
587                Texture2DArray: D3D12_TEX2D_ARRAY_DSV {
588                    MipSlice: mip_slice,
589                    FirstArraySlice: array.start,
590                    ArraySize: array.count() as u32,
591                },
592            },
593            Flags: D3D12_DSV_FLAG_NONE,
594        })
595    }
596
597    #[inline]
598    pub fn texture_2d_ms(format: Format) -> Self {
599        Self(D3D12_DEPTH_STENCIL_VIEW_DESC {
600            Format: format.as_raw(),
601            ViewDimension: D3D12_DSV_DIMENSION_TEXTURE2DMS,
602            Anonymous: D3D12_DEPTH_STENCIL_VIEW_DESC_0 {
603                Texture2DMS: D3D12_TEX2DMS_DSV::default(),
604            },
605            Flags: D3D12_DSV_FLAG_NONE,
606        })
607    }
608
609    #[inline]
610    pub fn texture_2d_ms_array(format: Format, array: Range<u32>) -> Self {
611        Self(D3D12_DEPTH_STENCIL_VIEW_DESC {
612            Format: format.as_raw(),
613            ViewDimension: D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY,
614            Anonymous: D3D12_DEPTH_STENCIL_VIEW_DESC_0 {
615                Texture2DMSArray: D3D12_TEX2DMS_ARRAY_DSV {
616                    FirstArraySlice: array.start,
617                    ArraySize: array.count() as u32,
618                },
619            },
620            Flags: D3D12_DSV_FLAG_NONE,
621        })
622    }
623}
624
625/// Describes the descriptor heap.
626///
627/// For more information: [`D3D12_DESCRIPTOR_HEAP_DESC structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_descriptor_heap_desc)
628#[derive(Clone, Copy, Debug, PartialEq)]
629#[repr(transparent)]
630pub struct DescriptorHeapDesc(pub(crate) D3D12_DESCRIPTOR_HEAP_DESC);
631
632impl DescriptorHeapDesc {
633    #[inline]
634    pub fn new(ty: DescriptorHeapType, num: u32) -> Self {
635        Self(D3D12_DESCRIPTOR_HEAP_DESC {
636            Type: ty.as_raw(),
637            NumDescriptors: num,
638            ..Default::default()
639        })
640    }
641
642    #[inline]
643    pub fn rtv(num: u32) -> Self {
644        Self(D3D12_DESCRIPTOR_HEAP_DESC {
645            Type: D3D12_DESCRIPTOR_HEAP_TYPE_RTV,
646            NumDescriptors: num,
647            ..Default::default()
648        })
649    }
650
651    #[inline]
652    pub fn dsv(num: u32) -> Self {
653        Self(D3D12_DESCRIPTOR_HEAP_DESC {
654            Type: D3D12_DESCRIPTOR_HEAP_TYPE_DSV,
655            NumDescriptors: num,
656            ..Default::default()
657        })
658    }
659
660    #[inline]
661    pub fn cbr_srv_uav(num: u32) -> Self {
662        Self(D3D12_DESCRIPTOR_HEAP_DESC {
663            Type: D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
664            NumDescriptors: num,
665            ..Default::default()
666        })
667    }
668
669    #[inline]
670    pub fn sampler(num: u32) -> Self {
671        Self(D3D12_DESCRIPTOR_HEAP_DESC {
672            Type: D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
673            NumDescriptors: num,
674            ..Default::default()
675        })
676    }
677
678    #[inline]
679    pub fn with_flags(mut self, flags: DescriptorHeapFlags) -> Self {
680        self.0.Flags = flags.as_raw();
681        self
682    }
683
684    #[inline]
685    pub fn with_node_mask(mut self, node_mask: u32) -> Self {
686        self.0.NodeMask = node_mask;
687        self
688    }
689
690    #[inline]
691    pub fn r#type(&self) -> DescriptorHeapType {
692        self.0.Type.into()
693    }
694
695    #[inline]
696    pub fn num_descriptors(&self) -> u32 {
697        self.0.NumDescriptors
698    }
699
700    #[inline]
701    pub fn flags(&self) -> DescriptorHeapFlags {
702        self.0.Flags.into()
703    }
704}
705
706/// Describes a descriptor range.
707///
708/// For more information: [`D3D12_DESCRIPTOR_RANGE structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_descriptor_range)
709#[derive(Clone, Copy, Debug, PartialEq)]
710#[repr(transparent)]
711pub struct DescriptorRange(pub(crate) D3D12_DESCRIPTOR_RANGE);
712
713impl DescriptorRange {
714    #[inline]
715    pub fn new(ty: DescriptorRangeType, num: u32) -> Self {
716        Self(D3D12_DESCRIPTOR_RANGE {
717            RangeType: ty.as_raw(),
718            NumDescriptors: num,
719            ..Default::default()
720        })
721    }
722
723    #[inline]
724    pub fn cbv(num: u32, base_shader_register: u32) -> Self {
725        Self(D3D12_DESCRIPTOR_RANGE {
726            RangeType: D3D12_DESCRIPTOR_RANGE_TYPE_CBV,
727            NumDescriptors: num,
728            BaseShaderRegister: base_shader_register,
729            ..Default::default()
730        })
731    }
732
733    #[inline]
734    pub fn srv(num: u32, base_shader_register: u32) -> Self {
735        Self(D3D12_DESCRIPTOR_RANGE {
736            RangeType: D3D12_DESCRIPTOR_RANGE_TYPE_SRV,
737            NumDescriptors: num,
738            BaseShaderRegister: base_shader_register,
739            ..Default::default()
740        })
741    }
742
743    #[inline]
744    pub fn sampler(num: u32, base_shader_register: u32) -> Self {
745        Self(D3D12_DESCRIPTOR_RANGE {
746            RangeType: D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER,
747            NumDescriptors: num,
748            BaseShaderRegister: base_shader_register,
749            ..Default::default()
750        })
751    }
752
753    #[inline]
754    pub fn uav(num: u32, base_shader_register: u32) -> Self {
755        Self(D3D12_DESCRIPTOR_RANGE {
756            RangeType: D3D12_DESCRIPTOR_RANGE_TYPE_UAV,
757            NumDescriptors: num,
758            BaseShaderRegister: base_shader_register,
759            ..Default::default()
760        })
761    }
762
763    #[inline]
764    pub fn with_base_shader_register(mut self, base_shader_register: u32) -> Self {
765        self.0.BaseShaderRegister = base_shader_register;
766        self
767    }
768
769    #[inline]
770    pub fn with_register_space(mut self, register_space: u32) -> Self {
771        self.0.RegisterSpace = register_space;
772        self
773    }
774
775    #[inline]
776    pub fn with_offset_in_descriptors_from_table_start(
777        mut self,
778        offset_in_descriptors_from_table_start: u32,
779    ) -> Self {
780        self.0.OffsetInDescriptorsFromTableStart = offset_in_descriptors_from_table_start;
781        self
782    }
783}
784
785/// Describes details for the discard-resource operation.
786///
787/// For more information: [`D3D12_DISCARD_REGION structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_discard_region)
788#[derive(Clone, Copy, Debug, PartialEq)]
789#[repr(transparent)]
790pub struct DiscardRegion<'a>(pub(crate) D3D12_DISCARD_REGION, PhantomData<&'a ()>);
791
792impl<'a> DiscardRegion<'a> {
793    #[inline]
794    pub fn new(rects: &'a [Rect], subresource: Range<u32>) -> Self {
795        Self(
796            D3D12_DISCARD_REGION {
797                NumRects: rects.len() as u32,
798                pRects: rects.as_ptr() as *const _,
799                FirstSubresource: subresource.start,
800                NumSubresources: subresource.count() as u32,
801            },
802            Default::default(),
803        )
804    }
805}
806
807/// Describes timing and presentation statistics for a frame.
808///
809/// For more information: [`DXGI_FRAME_STATISTICS structure`](https://learn.microsoft.com/en-us/windows/win32/api/dxgi/ns-dxgi-dxgi_frame_statistics)
810#[derive(Clone, Copy, Debug, Default, PartialEq)]
811#[repr(transparent)]
812pub struct FrameStatistics(pub(crate) DXGI_FRAME_STATISTICS);
813
814impl FrameStatistics {
815    #[inline]
816    pub fn present_count(&self) -> u32 {
817        self.0.PresentCount
818    }
819
820    #[inline]
821    pub fn present_refresh_count(&self) -> u32 {
822        self.0.PresentRefreshCount
823    }
824
825    #[inline]
826    pub fn sync_refresh_count(&self) -> u32 {
827        self.0.SyncRefreshCount
828    }
829
830    #[inline]
831    pub fn sync_qpc_time(&self) -> i64 {
832        self.0.SyncQPCTime
833    }
834
835    #[inline]
836    pub fn sync_gpu_time(&self) -> i64 {
837        self.0.SyncGPUTime
838    }
839}
840
841/// Describes a GPU descriptor handle.
842///
843/// For more information: [`D3D12_GPU_DESCRIPTOR_HANDLE structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_gpu_descriptor_handle)
844#[derive(Clone, Copy, Debug, Default, PartialEq)]
845#[repr(transparent)]
846pub struct GpuDescriptorHandle(pub(crate) D3D12_GPU_DESCRIPTOR_HANDLE);
847
848impl GpuDescriptorHandle {
849    /// Returns a new handle with offset relative to the current handle.
850    #[inline]
851    pub fn offset(&self, offset: usize) -> Self {
852        Self(D3D12_GPU_DESCRIPTOR_HANDLE {
853            ptr: self.0.ptr + offset as u64,
854        })
855    }
856
857    #[inline]
858    pub fn advance(&self, distance: usize, handle_size: usize) -> Self {
859        self.offset(distance * handle_size)
860    }
861}
862
863/// Describes a graphics pipeline state object.
864///
865/// For more information: [`D3D12_GRAPHICS_PIPELINE_STATE_DESC structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_graphics_pipeline_state_desc)
866#[derive(Clone, Debug, PartialEq)]
867#[repr(transparent)]
868pub struct GraphicsPipelineDesc<'a>(
869    pub(crate) D3D12_GRAPHICS_PIPELINE_STATE_DESC,
870    PhantomData<&'a ()>,
871);
872
873impl<'a> GraphicsPipelineDesc<'a> {
874    #[inline]
875    pub fn new(vs: &'a Blob) -> Self {
876        Self(
877            D3D12_GRAPHICS_PIPELINE_STATE_DESC {
878                VS: vs.as_shader_bytecode(),
879                SampleDesc: DXGI_SAMPLE_DESC {
880                    Count: 1,
881                    Quality: 0,
882                },
883                SampleMask: u32::MAX,
884                BlendState: BlendDesc::default().0,
885                ..Default::default()
886            },
887            Default::default(),
888        )
889    }
890
891    #[inline]
892    pub fn with_root_signature(mut self, root_signature: &'a RootSignature) -> Self {
893        unsafe {
894            self.0.pRootSignature = std::mem::transmute_copy(&root_signature.0);
895            self
896        }
897    }
898
899    #[inline]
900    pub fn with_ps(mut self, ps: &'a Blob) -> Self {
901        self.0.PS = ps.as_shader_bytecode();
902        self
903    }
904
905    #[inline]
906    pub fn with_ds(mut self, ds: &'a Blob) -> Self {
907        self.0.DS = ds.as_shader_bytecode();
908        self
909    }
910
911    #[inline]
912    pub fn with_hs(mut self, hs: &'a Blob) -> Self {
913        self.0.HS = hs.as_shader_bytecode();
914        self
915    }
916
917    #[inline]
918    pub fn with_gs(mut self, gs: &'a Blob) -> Self {
919        self.0.GS = gs.as_shader_bytecode();
920        self
921    }
922
923    #[inline]
924    pub fn with_stream_output(mut self, stream_output: StreamOutputDesc<'a>) -> Self {
925        self.0.StreamOutput = stream_output.0;
926        self
927    }
928
929    #[inline]
930    pub fn with_blend_desc(mut self, blend_desc: BlendDesc) -> Self {
931        self.0.BlendState = blend_desc.0;
932        self
933    }
934
935    #[inline]
936    pub fn with_sample_mask(mut self, sample_mask: u32) -> Self {
937        self.0.SampleMask = sample_mask;
938        self
939    }
940
941    #[inline]
942    pub fn with_rasterizer_state(mut self, rasterizer_state: RasterizerDesc) -> Self {
943        self.0.RasterizerState = rasterizer_state.0;
944        self
945    }
946
947    #[inline]
948    pub fn with_depth_stencil(mut self, depth_stencil: DepthStencilDesc, format: Format) -> Self {
949        self.0.DepthStencilState = depth_stencil.0;
950        self.0.DSVFormat = format.as_raw();
951        self
952    }
953
954    #[inline]
955    pub fn with_input_layout(mut self, input_layout: &'a [InputElementDesc]) -> Self {
956        self.0.InputLayout = D3D12_INPUT_LAYOUT_DESC {
957            pInputElementDescs: input_layout.as_ptr() as *const _,
958            NumElements: input_layout.len() as u32,
959        };
960        self
961    }
962
963    #[inline]
964    pub fn with_ib_strip_cut_value(mut self, ib_strip_cut_value: IndexBufferStripCutValue) -> Self {
965        self.0.IBStripCutValue = ib_strip_cut_value.as_raw();
966        self
967    }
968
969    #[inline]
970    pub fn with_primitive_topology(
971        mut self,
972        primitive_topology: PipelinePrimitiveTopology,
973    ) -> Self {
974        self.0.PrimitiveTopologyType = primitive_topology.as_raw();
975        self
976    }
977
978    #[inline]
979    pub fn with_render_targets(mut self, render_targets: impl IntoIterator<Item = Format>) -> Self {
980        let mut rts = [DXGI_FORMAT_UNKNOWN; 8];
981        let mut count = 0;
982
983        for (i, desc) in render_targets.into_iter().take(8).enumerate() {
984            rts[i] = desc.as_raw();
985            count += 1;
986        }
987
988        self.0.RTVFormats = rts;
989        self.0.NumRenderTargets = count;
990        self
991    }
992
993    #[inline]
994    pub fn with_sample_desc(mut self, sample_desc: SampleDesc) -> Self {
995        self.0.SampleDesc = sample_desc.0;
996        self
997    }
998
999    #[inline]
1000    pub fn with_node_mask(mut self, node_mask: u32) -> Self {
1001        self.0.NodeMask = node_mask;
1002        self
1003    }
1004
1005    #[inline]
1006    pub fn with_cache(mut self, cache: &'a Blob) -> Self {
1007        self.0.CachedPSO = cache.as_cached_pipeline_state();
1008        self
1009    }
1010
1011    #[inline]
1012    pub fn with_flags(mut self, flags: PipelineStateFlags) -> Self {
1013        self.0.Flags = flags.as_raw();
1014        self
1015    }
1016}
1017
1018/// Describes a heap.
1019///
1020/// For more information: [`D3D12_HEAP_DESC structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_heap_desc)
1021#[derive(Clone, Copy, Debug, PartialEq)]
1022#[repr(transparent)]
1023pub struct HeapDesc(pub(crate) D3D12_HEAP_DESC);
1024
1025impl HeapDesc {
1026    #[inline]
1027    pub fn new(size: u64, props: HeapProperties) -> Self {
1028        Self(D3D12_HEAP_DESC {
1029            SizeInBytes: size,
1030            Properties: props.0,
1031            ..Default::default()
1032        })
1033    }
1034
1035    #[inline]
1036    pub fn with_alignment(mut self, alignment: HeapAlignment) -> Self {
1037        self.0.Alignment = alignment.as_raw();
1038        self
1039    }
1040
1041    #[inline]
1042    pub fn with_flags(mut self, flags: HeapFlags) -> Self {
1043        self.0.Flags = flags.as_raw();
1044        self
1045    }
1046
1047    #[inline]
1048    pub fn size(&self) -> u64 {
1049        self.0.SizeInBytes
1050    }
1051
1052    #[inline]
1053    pub fn properties(&self) -> &HeapProperties {
1054        unsafe { std::mem::transmute(&self.0.Properties) }
1055    }
1056
1057    #[inline]
1058    pub fn alignement(&self) -> HeapAlignment {
1059        self.0.Alignment.into()
1060    }
1061
1062    #[inline]
1063    pub fn flags(&self) -> HeapFlags {
1064        self.0.Flags.into()
1065    }
1066}
1067
1068/// Describes heap properties.
1069///
1070/// For more information: [`D3D12_HEAP_PROPERTIES structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_heap_properties)
1071#[derive(Clone, Copy, Debug, PartialEq)]
1072#[repr(transparent)]
1073pub struct HeapProperties(pub(crate) D3D12_HEAP_PROPERTIES);
1074
1075impl HeapProperties {
1076    #[inline]
1077    pub fn new(
1078        r#type: HeapType,
1079        cpu_page_property: CpuPageProperty,
1080        memory_pool_preference: MemoryPool,
1081    ) -> Self {
1082        Self(D3D12_HEAP_PROPERTIES {
1083            Type: r#type.as_raw(),
1084            CPUPageProperty: cpu_page_property.as_raw(),
1085            MemoryPoolPreference: memory_pool_preference.as_raw(),
1086            ..Default::default()
1087        })
1088    }
1089
1090    #[inline]
1091    pub fn upload() -> Self {
1092        Self(D3D12_HEAP_PROPERTIES {
1093            Type: D3D12_HEAP_TYPE_UPLOAD,
1094            ..Default::default()
1095        })
1096    }
1097
1098    #[inline]
1099    pub fn readback() -> Self {
1100        Self(D3D12_HEAP_PROPERTIES {
1101            Type: D3D12_HEAP_TYPE_READBACK,
1102            ..Default::default()
1103        })
1104    }
1105
1106    #[inline]
1107    pub fn custom() -> Self {
1108        Self(D3D12_HEAP_PROPERTIES {
1109            Type: D3D12_HEAP_TYPE_CUSTOM,
1110            ..Default::default()
1111        })
1112    }
1113
1114    #[inline]
1115    pub fn gpu_upload() -> Self {
1116        Self(D3D12_HEAP_PROPERTIES {
1117            Type: D3D12_HEAP_TYPE_GPU_UPLOAD,
1118            ..Default::default()
1119        })
1120    }
1121
1122    #[inline]
1123    pub fn with_cpu_page_property(mut self, cpu_page_property: CpuPageProperty) -> Self {
1124        self.0.CPUPageProperty = cpu_page_property.as_raw();
1125        self
1126    }
1127
1128    #[inline]
1129    pub fn with_memory_pool_preference(mut self, memory_pool_preference: MemoryPool) -> Self {
1130        self.0.MemoryPoolPreference = memory_pool_preference.as_raw();
1131        self
1132    }
1133
1134    #[inline]
1135    pub fn with_creation_node_mask(mut self, mask: u32) -> Self {
1136        self.0.CreationNodeMask = mask;
1137        self
1138    }
1139
1140    #[inline]
1141    pub fn with_visible_node_mask(mut self, mask: u32) -> Self {
1142        self.0.VisibleNodeMask = mask;
1143        self
1144    }
1145
1146    #[inline]
1147    pub fn r#type(&self) -> HeapType {
1148        self.0.Type.into()
1149    }
1150
1151    #[inline]
1152    pub fn cpu_page_property(&self) -> CpuPageProperty {
1153        self.0.CPUPageProperty.into()
1154    }
1155
1156    #[inline]
1157    pub fn memory_pool_preference(&self) -> MemoryPool {
1158        self.0.MemoryPoolPreference.into()
1159    }
1160
1161    #[inline]
1162    pub fn visible_node_mask(&self) -> u32 {
1163        self.0.VisibleNodeMask
1164    }
1165
1166    #[inline]
1167    pub fn creation_node_mask(&self) -> u32 {
1168        self.0.CreationNodeMask
1169    }
1170}
1171
1172impl Default for HeapProperties {
1173    fn default() -> Self {
1174        Self(D3D12_HEAP_PROPERTIES {
1175            Type: D3D12_HEAP_TYPE_DEFAULT,
1176            CPUPageProperty: D3D12_CPU_PAGE_PROPERTY_UNKNOWN,
1177            MemoryPoolPreference: D3D12_MEMORY_POOL_UNKNOWN,
1178            CreationNodeMask: 0,
1179            VisibleNodeMask: 0,
1180        })
1181    }
1182}
1183
1184/// Describes the index buffer to view.
1185///
1186/// For more information: [`D3D12_INDEX_BUFFER_VIEW structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_index_buffer_view)
1187#[derive(Clone, Copy, Debug, PartialEq)]
1188#[repr(transparent)]
1189pub struct IndexBufferView(pub(crate) D3D12_INDEX_BUFFER_VIEW);
1190
1191impl IndexBufferView {
1192    #[inline]
1193    pub fn new(buffer_location: GpuVirtualAddress, size: u32, format: Format) -> Self {
1194        Self(D3D12_INDEX_BUFFER_VIEW {
1195            BufferLocation: buffer_location,
1196            SizeInBytes: size,
1197            Format: format.as_raw(),
1198        })
1199    }
1200}
1201
1202/// Specifies the type of the indirect parameter.
1203///
1204/// For more information: [`D3D12_INDIRECT_ARGUMENT_DESC structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_indirect_argument_desc)
1205#[derive(Clone, Copy)]
1206#[repr(transparent)]
1207pub struct IndirectArgumentDesc(pub(crate) D3D12_INDIRECT_ARGUMENT_DESC);
1208
1209impl IndirectArgumentDesc {
1210    #[inline]
1211    pub fn draw() -> Self {
1212        Self(D3D12_INDIRECT_ARGUMENT_DESC {
1213            Type: D3D12_INDIRECT_ARGUMENT_TYPE_DRAW,
1214            Anonymous: Default::default(),
1215        })
1216    }
1217
1218    #[inline]
1219    pub fn draw_indexed() -> Self {
1220        Self(D3D12_INDIRECT_ARGUMENT_DESC {
1221            Type: D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED,
1222            Anonymous: Default::default(),
1223        })
1224    }
1225
1226    #[inline]
1227    pub fn dispatch() -> Self {
1228        Self(D3D12_INDIRECT_ARGUMENT_DESC {
1229            Type: D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH,
1230            Anonymous: Default::default(),
1231        })
1232    }
1233
1234    #[inline]
1235    pub fn vertex_buffer_view(slot: u32) -> Self {
1236        Self(D3D12_INDIRECT_ARGUMENT_DESC {
1237            Type: D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW,
1238            Anonymous: D3D12_INDIRECT_ARGUMENT_DESC_0 {
1239                VertexBuffer: D3D12_INDIRECT_ARGUMENT_DESC_0_0 { Slot: slot },
1240            },
1241        })
1242    }
1243
1244    #[inline]
1245    pub fn index_buffer_view() -> Self {
1246        Self(D3D12_INDIRECT_ARGUMENT_DESC {
1247            Type: D3D12_INDIRECT_ARGUMENT_TYPE_INDEX_BUFFER_VIEW,
1248            Anonymous: Default::default(),
1249        })
1250    }
1251
1252    #[inline]
1253    pub fn constant(
1254        root_parameter_index: u32,
1255        dest_offset_in32_bit_values: u32,
1256        num32_bit_values_to_set: u32,
1257    ) -> Self {
1258        Self(D3D12_INDIRECT_ARGUMENT_DESC {
1259            Type: D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT,
1260            Anonymous: D3D12_INDIRECT_ARGUMENT_DESC_0 {
1261                Constant: D3D12_INDIRECT_ARGUMENT_DESC_0_1 {
1262                    RootParameterIndex: root_parameter_index,
1263                    DestOffsetIn32BitValues: dest_offset_in32_bit_values,
1264                    Num32BitValuesToSet: num32_bit_values_to_set,
1265                },
1266            },
1267        })
1268    }
1269
1270    #[inline]
1271    pub fn constant_buffer_view(root_parameter_index: u32) -> Self {
1272        Self(D3D12_INDIRECT_ARGUMENT_DESC {
1273            Type: D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT_BUFFER_VIEW,
1274            Anonymous: D3D12_INDIRECT_ARGUMENT_DESC_0 {
1275                ConstantBufferView: D3D12_INDIRECT_ARGUMENT_DESC_0_2 {
1276                    RootParameterIndex: root_parameter_index,
1277                },
1278            },
1279        })
1280    }
1281
1282    #[inline]
1283    pub fn shader_resource_view(root_parameter_index: u32) -> Self {
1284        Self(D3D12_INDIRECT_ARGUMENT_DESC {
1285            Type: D3D12_INDIRECT_ARGUMENT_TYPE_SHADER_RESOURCE_VIEW,
1286            Anonymous: D3D12_INDIRECT_ARGUMENT_DESC_0 {
1287                ShaderResourceView: D3D12_INDIRECT_ARGUMENT_DESC_0_3 {
1288                    RootParameterIndex: root_parameter_index,
1289                },
1290            },
1291        })
1292    }
1293
1294    #[inline]
1295    pub fn unordered_access_view(root_parameter_index: u32) -> Self {
1296        Self(D3D12_INDIRECT_ARGUMENT_DESC {
1297            Type: D3D12_INDIRECT_ARGUMENT_TYPE_UNORDERED_ACCESS_VIEW,
1298            Anonymous: D3D12_INDIRECT_ARGUMENT_DESC_0 {
1299                UnorderedAccessView: D3D12_INDIRECT_ARGUMENT_DESC_0_4 {
1300                    RootParameterIndex: root_parameter_index,
1301                },
1302            },
1303        })
1304    }
1305}
1306
1307/// Describes a single element for the input-assembler stage of the graphics pipeline.
1308///
1309/// For more information: [`D3D12_INPUT_ELEMENT_DESC structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_input_element_desc)
1310#[derive(Clone, Copy, Debug, PartialEq)]
1311#[repr(transparent)]
1312pub struct InputElementDesc<'a>(pub(crate) D3D12_INPUT_ELEMENT_DESC, PhantomData<&'a ()>);
1313
1314impl<'a> InputElementDesc<'a> {
1315    #[inline]
1316    pub fn from_raw_per_vertex(
1317        semantic_name: &'a CStr,
1318        semantic_index: u32,
1319        format: Format,
1320        input_slot: u32,
1321    ) -> Self {
1322        let semantic_name = PCSTR::from_raw(semantic_name.as_ptr() as *const _);
1323
1324        Self(
1325            D3D12_INPUT_ELEMENT_DESC {
1326                SemanticName: semantic_name,
1327                SemanticIndex: semantic_index,
1328                Format: format.as_raw(),
1329                InputSlot: input_slot,
1330                AlignedByteOffset: APPEND_ALIGNED_ELEMENT,
1331                InputSlotClass: D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,
1332                InstanceDataStepRate: 0,
1333            },
1334            PhantomData,
1335        )
1336    }
1337
1338    #[inline]
1339    pub fn per_vertex(semantic: SemanticName, format: Format, input_slot: u32) -> Self {
1340        let semantic_name = PCSTR::from_raw(semantic.name().as_ptr() as *const _);
1341
1342        Self(
1343            D3D12_INPUT_ELEMENT_DESC {
1344                SemanticName: semantic_name,
1345                SemanticIndex: semantic.index() as u32,
1346                Format: format.as_raw(),
1347                InputSlot: input_slot,
1348                AlignedByteOffset: APPEND_ALIGNED_ELEMENT,
1349                InputSlotClass: D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,
1350                InstanceDataStepRate: 0,
1351            },
1352            PhantomData::<&'static ()>,
1353        )
1354    }
1355
1356    #[inline]
1357    pub fn per_instance(
1358        semantic: SemanticName,
1359        format: Format,
1360        input_slot: u32,
1361        instance_data_step_rate: u32,
1362    ) -> Self {
1363        let semantic_name = PCSTR::from_raw(semantic.name().as_ptr() as *const _);
1364
1365        Self(
1366            D3D12_INPUT_ELEMENT_DESC {
1367                SemanticName: semantic_name,
1368                SemanticIndex: semantic.index() as u32,
1369                Format: format.as_raw(),
1370                InputSlot: input_slot,
1371                AlignedByteOffset: APPEND_ALIGNED_ELEMENT,
1372                InputSlotClass: D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA,
1373                InstanceDataStepRate: instance_data_step_rate,
1374            },
1375            PhantomData::<&'static ()>,
1376        )
1377    }
1378
1379    #[inline]
1380    pub fn with_offset(mut self, offset: u32) -> Self {
1381        self.0.AlignedByteOffset = offset;
1382        self
1383    }
1384}
1385
1386/// The LUID structure is an opaque structure that specifies an identifier that is guaranteed to be unique on the local machine.
1387///
1388/// For more information: [`LUID structure`](https://learn.microsoft.com/en-us/windows/win32/api/ntdef/ns-ntdef-luid)
1389#[derive(Clone, Copy, Debug, Default, PartialEq)]
1390#[repr(transparent)]
1391pub struct Luid(pub(crate) LUID);
1392
1393impl Luid {
1394    #[inline]
1395    pub fn high_part(&self) -> i32 {
1396        self.0.HighPart
1397    }
1398
1399    #[inline]
1400    pub fn low_part(&self) -> u32 {
1401        self.0.LowPart
1402    }
1403}
1404
1405/// Describes a display mode.
1406///
1407/// For more information: [`DXGI_MODE_DESC structure`](https://learn.microsoft.com/en-us/previous-versions/windows/desktop/legacy/bb173064(v=vs.85))
1408#[derive(Clone, Copy, Debug, Default, PartialEq)]
1409#[repr(transparent)]
1410pub struct ModeDesc(pub(crate) DXGI_MODE_DESC);
1411
1412impl ModeDesc {
1413    #[inline]
1414    pub fn width(&self) -> u32 {
1415        self.0.Width
1416    }
1417
1418    #[inline]
1419    pub fn height(&self) -> u32 {
1420        self.0.Height
1421    }
1422
1423    #[inline]
1424    pub fn refresh_rate(&self) -> &Rational {
1425        unsafe { std::mem::transmute(&self.0.RefreshRate) }
1426    }
1427
1428    #[inline]
1429    pub fn format(&self) -> Format {
1430        self.0.Format.into()
1431    }
1432
1433    #[inline]
1434    pub fn scaling(&self) -> Scaling {
1435        self.0.Scaling.into()
1436    }
1437
1438    #[inline]
1439    pub fn scanline_ordering(&self) -> ScanlineOrdering {
1440        self.0.ScanlineOrdering.into()
1441    }
1442
1443    #[inline]
1444    pub fn set_width(&mut self, width: u32) {
1445        self.0.Width = width;
1446    }
1447
1448    #[inline]
1449    pub fn set_height(&mut self, height: u32) {
1450        self.0.Height = height;
1451    }
1452
1453    #[inline]
1454    pub fn set_refresh_rate(&mut self, refresh_rate: Rational) {
1455        self.0.RefreshRate = refresh_rate.0;
1456    }
1457
1458    #[inline]
1459    pub fn set_format(&mut self, format: Format) {
1460        self.0.Format = format.as_raw();
1461    }
1462
1463    #[inline]
1464    pub fn set_scaling(&mut self, scaling: ScalingMode) {
1465        self.0.Scaling = scaling.as_raw();
1466    }
1467
1468    #[inline]
1469    pub fn set_scanline_ordering(&mut self, so: ScanlineOrdering) {
1470        self.0.ScanlineOrdering = so.as_raw();
1471    }
1472}
1473
1474/// Describes a display mode and whether the display mode supports stereo.
1475///
1476/// For more information: [`DXGI_MODE_DESC1 structure`](https://learn.microsoft.com/en-us/windows/win32/api/dxgi1_2/ns-dxgi1_2-dxgi_mode_desc1)
1477#[derive(Clone, Copy, Debug, PartialEq)]
1478#[repr(transparent)]
1479pub struct ModeDesc1(pub(crate) DXGI_MODE_DESC1);
1480
1481impl ModeDesc1 {
1482    #[inline]
1483    pub fn width(&self) -> u32 {
1484        self.0.Width
1485    }
1486
1487    #[inline]
1488    pub fn height(&self) -> u32 {
1489        self.0.Height
1490    }
1491
1492    #[inline]
1493    pub fn refresh_rate(&self) -> &Rational {
1494        unsafe { std::mem::transmute(&self.0.RefreshRate) }
1495    }
1496
1497    #[inline]
1498    pub fn format(&self) -> Format {
1499        self.0.Format.into()
1500    }
1501
1502    #[inline]
1503    pub fn scaling(&self) -> ScalingMode {
1504        self.0.Scaling.into()
1505    }
1506
1507    #[inline]
1508    pub fn scanline_ordering(&self) -> ScanlineOrdering {
1509        self.0.ScanlineOrdering.into()
1510    }
1511
1512    #[inline]
1513    pub fn stereo(&self) -> bool {
1514        self.0.Stereo.into()
1515    }
1516}
1517
1518/// Describes the destination of a memory copy operation.
1519///
1520/// For more information: [`D3D12_MEMCPY_DEST structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_memcpy_dest)
1521#[derive(Clone, Copy, Debug, PartialEq)]
1522pub struct MemcpyDest<'a, T>(
1523    pub(crate) D3D12_MEMCPY_DEST,
1524    pub(crate) usize,
1525    PhantomData<&'a mut T>,
1526);
1527
1528impl<'a, T> MemcpyDest<'a, T> {
1529    #[inline]
1530    pub fn new(data: &'a mut [T]) -> Self {
1531        Self(
1532            D3D12_MEMCPY_DEST {
1533                pData: data.as_ptr() as *mut _,
1534                RowPitch: size_of_val(data),
1535                SlicePitch: size_of_val(data),
1536            },
1537            data.len(),
1538            Default::default(),
1539        )
1540    }
1541
1542    #[inline]
1543    pub fn with_slice_pitch(mut self, slice_pitch: usize) -> Self {
1544        self.0.SlicePitch = slice_pitch;
1545        self
1546    }
1547
1548    #[inline]
1549    pub fn with_row_pitch(mut self, row_pitch: usize) -> Self {
1550        self.0.RowPitch = row_pitch;
1551        self
1552    }
1553
1554    #[inline]
1555    pub fn slice_pitch(&self) -> usize {
1556        self.0.SlicePitch / size_of::<T>()
1557    }
1558
1559    #[inline]
1560    pub fn row_pitch(&self) -> usize {
1561        self.0.RowPitch / size_of::<T>()
1562    }
1563
1564    #[inline]
1565    pub fn as_slice_mut(&mut self) -> &'a mut [T] {
1566        unsafe { std::slice::from_raw_parts_mut(self.0.pData as *mut _, self.1) }
1567    }
1568}
1569
1570/// Describes an output or physical connection between the adapter (video card) and a device.
1571///
1572/// For more information: [`DXGI_OUTPUT_DESC structure`](https://learn.microsoft.com/en-us/windows/win32/api/dxgi/ns-dxgi-dxgi_output_desc)
1573#[derive(Clone, Copy, Debug, PartialEq)]
1574#[repr(transparent)]
1575pub struct OutputDesc(pub(crate) DXGI_OUTPUT_DESC);
1576
1577impl OutputDesc {
1578    #[inline]
1579    pub fn device_name(&self) -> String {
1580        String::from_utf16_lossy(&self.0.DeviceName)
1581    }
1582
1583    #[inline]
1584    pub fn desktop_coordinates(&self) -> &Rect {
1585        unsafe { std::mem::transmute(&self.0.DesktopCoordinates) }
1586    }
1587
1588    #[inline]
1589    pub fn attached_to_desktop(&self) -> bool {
1590        self.0.AttachedToDesktop.into()
1591    }
1592
1593    #[inline]
1594    pub fn rotation(&self) -> RotationMode {
1595        self.0.Rotation.into()
1596    }
1597
1598    #[inline]
1599    pub fn monitor(&self) -> std::ptr::NonNull<()> {
1600        std::ptr::NonNull::new(self.0.Monitor.0 as *mut ()).unwrap()
1601    }
1602}
1603
1604/// Describes the tile structure of a tiled resource with mipmaps.
1605///
1606/// For more information: [`D3D12_PACKED_MIP_INFO structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_packed_mip_info)
1607#[derive(Clone, Copy, Debug, Default, PartialEq)]
1608#[repr(transparent)]
1609pub struct PackedMipDesc(pub(crate) D3D12_PACKED_MIP_INFO);
1610
1611impl PackedMipDesc {
1612    #[inline]
1613    pub fn num_standard_mips(&self) -> u8 {
1614        self.0.NumStandardMips
1615    }
1616
1617    #[inline]
1618    pub fn num_packed_mips(&self) -> u8 {
1619        self.0.NumPackedMips
1620    }
1621
1622    #[inline]
1623    pub fn num_tiles_for_packed_mips(&self) -> u32 {
1624        self.0.NumTilesForPackedMips
1625    }
1626
1627    #[inline]
1628    pub fn start_tile_index_in_overall_resource(&self) -> u32 {
1629        self.0.StartTileIndexInOverallResource
1630    }
1631}
1632
1633/// Describes the footprint of a placed subresource, including the offset and the [`SubresourceFootprint`].
1634///
1635/// For more information: [`D3D12_PLACED_SUBRESOURCE_FOOTPRINT structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_placed_subresource_footprint)
1636#[derive(Clone, Copy, Debug, Default, PartialEq)]
1637#[repr(transparent)]
1638pub struct PlacedSubresourceFootprint(pub(crate) D3D12_PLACED_SUBRESOURCE_FOOTPRINT);
1639
1640impl PlacedSubresourceFootprint {
1641    #[inline]
1642    pub fn new(offset: u64, footprint: SubresourceFootprint) -> Self {
1643        Self(D3D12_PLACED_SUBRESOURCE_FOOTPRINT {
1644            Offset: offset,
1645            Footprint: footprint.0,
1646        })
1647    }
1648
1649    #[inline]
1650    pub fn offset(&self) -> u64 {
1651        self.0.Offset
1652    }
1653
1654    #[inline]
1655    pub fn footprint(&self) -> &SubresourceFootprint {
1656        unsafe { std::mem::transmute(&self.0.Footprint) }
1657    }
1658}
1659
1660/// The POINT structure defines the x- and y-coordinates of a point.
1661///
1662/// For more information: [`POINT structure`](https://learn.microsoft.com/en-us/windows/win32/api/windef/ns-windef-point)
1663#[derive(Clone, Copy, Debug, Default, PartialEq)]
1664#[repr(transparent)]
1665pub struct Point(pub(crate) POINT);
1666
1667impl Point {
1668    #[inline]
1669    pub fn set_x(&mut self, x: i32) {
1670        self.0.x = x;
1671    }
1672
1673    #[inline]
1674    pub fn set_y(&mut self, y: i32) {
1675        self.0.y = y;
1676    }
1677}
1678
1679/// Describes information about present that helps the operating system optimize presentation.
1680///
1681/// For more information: [`DXGI_PRESENT_PARAMETERS structure`](https://learn.microsoft.com/en-us/windows/win32/api/dxgi1_2/ns-dxgi1_2-dxgi_present_parameters)
1682#[derive(Clone, Copy, Debug, Default, PartialEq)]
1683#[repr(transparent)]
1684pub struct PresentParameters<'a>(pub(crate) DXGI_PRESENT_PARAMETERS, PhantomData<&'a ()>);
1685
1686impl<'a> PresentParameters<'a> {
1687    #[inline]
1688    pub fn set_dirty_rects(&mut self, rects: &'a mut [Rect]) {
1689        self.0.DirtyRectsCount = rects.len() as u32;
1690        self.0.pDirtyRects = rects.as_mut_ptr() as *mut _;
1691    }
1692
1693    #[inline]
1694    pub fn set_scroll_rect(&mut self, rects: &'a mut [Rect]) {
1695        self.0.pScrollRect = rects.as_mut_ptr() as *mut _;
1696    }
1697
1698    #[inline]
1699    pub fn set_scroll_offset(&mut self, points: &'a mut [Point]) {
1700        self.0.pScrollOffset = points.as_mut_ptr() as *mut _;
1701    }
1702}
1703
1704/// Describes the purpose of a query heap. A query heap contains an array of individual queries.
1705///
1706/// For more information: [`D3D12_QUERY_HEAP_DESC structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_query_heap_desc)
1707#[derive(Clone, Copy, Debug, PartialEq)]
1708#[repr(transparent)]
1709pub struct QueryHeapDesc(pub(crate) D3D12_QUERY_HEAP_DESC);
1710
1711impl QueryHeapDesc {
1712    #[inline]
1713    pub fn occlusion(count: u32) -> Self {
1714        Self(D3D12_QUERY_HEAP_DESC {
1715            Type: D3D12_QUERY_HEAP_TYPE_OCCLUSION,
1716            Count: count,
1717            NodeMask: 0,
1718        })
1719    }
1720
1721    #[inline]
1722    pub fn timestamp(count: u32) -> Self {
1723        Self(D3D12_QUERY_HEAP_DESC {
1724            Type: D3D12_QUERY_HEAP_TYPE_TIMESTAMP,
1725            Count: count,
1726            NodeMask: 0,
1727        })
1728    }
1729
1730    #[inline]
1731    pub fn pipeline_statistics(count: u32) -> Self {
1732        Self(D3D12_QUERY_HEAP_DESC {
1733            Type: D3D12_QUERY_HEAP_TYPE_PIPELINE_STATISTICS,
1734            Count: count,
1735            NodeMask: 0,
1736        })
1737    }
1738
1739    #[inline]
1740    pub fn so_statistics(count: u32) -> Self {
1741        Self(D3D12_QUERY_HEAP_DESC {
1742            Type: D3D12_QUERY_HEAP_TYPE_SO_STATISTICS,
1743            Count: count,
1744            NodeMask: 0,
1745        })
1746    }
1747
1748    #[inline]
1749    pub fn video_decode_statistics(count: u32) -> Self {
1750        Self(D3D12_QUERY_HEAP_DESC {
1751            Type: D3D12_QUERY_HEAP_TYPE_VIDEO_DECODE_STATISTICS,
1752            Count: count,
1753            NodeMask: 0,
1754        })
1755    }
1756
1757    #[inline]
1758    pub fn copy_queue_timestamp(count: u32) -> Self {
1759        Self(D3D12_QUERY_HEAP_DESC {
1760            Type: D3D12_QUERY_HEAP_TYPE_COPY_QUEUE_TIMESTAMP,
1761            Count: count,
1762            NodeMask: 0,
1763        })
1764    }
1765
1766    #[inline]
1767    pub fn pipeline_statistics1(count: u32) -> Self {
1768        Self(D3D12_QUERY_HEAP_DESC {
1769            Type: D3D12_QUERY_HEAP_TYPE_PIPELINE_STATISTICS1,
1770            Count: count,
1771            NodeMask: 0,
1772        })
1773    }
1774
1775    #[inline]
1776    pub fn with_node_mask(mut self, node_mask: u32) -> Self {
1777        self.0.NodeMask = node_mask;
1778        self
1779    }
1780}
1781
1782/// Describes rasterizer state.
1783///
1784/// For more information: [`D3D12_RASTERIZER_DESC structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_rasterizer_desc)
1785#[derive(Clone, Copy, Debug, PartialEq)]
1786#[repr(transparent)]
1787pub struct RasterizerDesc(pub(crate) D3D12_RASTERIZER_DESC);
1788
1789impl RasterizerDesc {
1790    #[inline]
1791    pub fn with_fill_mode(mut self, fill_mode: FillMode) -> Self {
1792        self.0.FillMode = fill_mode.as_raw();
1793        self
1794    }
1795
1796    #[inline]
1797    pub fn with_cull_mode(mut self, cull_mode: CullMode) -> Self {
1798        self.0.CullMode = cull_mode.as_raw();
1799        self
1800    }
1801
1802    #[inline]
1803    pub fn enable_front_counter_clockwise(mut self) -> Self {
1804        self.0.FrontCounterClockwise = true.into();
1805        self
1806    }
1807
1808    #[inline]
1809    pub fn with_depth_bias(mut self, depth_bias: i32) -> Self {
1810        self.0.DepthBias = depth_bias;
1811        self
1812    }
1813
1814    #[inline]
1815    pub fn with_depth_bias_clamp(mut self, depth_bias_clamp: f32) -> Self {
1816        self.0.DepthBiasClamp = depth_bias_clamp;
1817        self
1818    }
1819
1820    #[inline]
1821    pub fn with_slope_scaled_depth_bias(mut self, slope_scaled_depth_bias: f32) -> Self {
1822        self.0.SlopeScaledDepthBias = slope_scaled_depth_bias;
1823        self
1824    }
1825
1826    #[inline]
1827    pub fn enable_multisample(mut self) -> Self {
1828        self.0.MultisampleEnable = true.into();
1829        self
1830    }
1831
1832    #[inline]
1833    pub fn enable_antialiased_line(mut self) -> Self {
1834        self.0.AntialiasedLineEnable = true.into();
1835        self
1836    }
1837
1838    #[inline]
1839    pub fn enable_depth_clip(mut self) -> Self {
1840        self.0.DepthClipEnable = true.into();
1841        self
1842    }
1843
1844    #[inline]
1845    pub fn with_forced_sample_count(mut self, forced_sample_count: u32) -> Self {
1846        self.0.ForcedSampleCount = forced_sample_count;
1847        self
1848    }
1849
1850    #[inline]
1851    pub fn with_conservative_raster(mut self, conservative_raster: ConservativeRaster) -> Self {
1852        self.0.ConservativeRaster = conservative_raster.as_raw();
1853        self
1854    }
1855}
1856
1857impl Default for RasterizerDesc {
1858    fn default() -> Self {
1859        Self(D3D12_RASTERIZER_DESC {
1860            FillMode: D3D12_FILL_MODE_SOLID,
1861            CullMode: D3D12_CULL_MODE_BACK,
1862            ..Default::default()
1863        })
1864    }
1865}
1866
1867/// Represents a rational number.
1868///
1869/// For more information: [`DXGI_RATIONAL structure`](https://learn.microsoft.com/en-us/windows/win32/api/dxgicommon/ns-dxgicommon-dxgi_rational)
1870#[derive(Clone, Copy, Debug, PartialEq)]
1871#[repr(transparent)]
1872pub struct Rational(pub(crate) DXGI_RATIONAL);
1873
1874impl Rational {
1875    #[inline]
1876    pub fn new(numerator: u32, denominator: u32) -> Self {
1877        Self(DXGI_RATIONAL {
1878            Numerator: numerator,
1879            Denominator: denominator,
1880        })
1881    }
1882}
1883
1884/// The RECT structure defines a rectangle by the coordinates of its upper-left and lower-right corners.
1885///
1886/// For more information: [`RECT structure`](https://learn.microsoft.com/en-us/windows/win32/api/windef/ns-windef-rect)
1887#[derive(Clone, Copy, Debug, Default, PartialEq)]
1888pub struct Rect(pub(crate) RECT);
1889
1890impl Rect {
1891    /// Create rect with left and top equal to 0.
1892    #[inline]
1893    pub fn with_size(mut self, (width, height): (i32, i32)) -> Self {
1894        self.0.bottom = height;
1895        self.0.right = width;
1896        self
1897    }
1898
1899    #[inline]
1900    pub fn with_left(mut self, left: i32) -> Self {
1901        self.0.left = left;
1902        self
1903    }
1904
1905    #[inline]
1906    pub fn with_top(mut self, top: i32) -> Self {
1907        self.0.top = top;
1908        self
1909    }
1910}
1911
1912/// Describes the blend state for a render target.
1913///
1914/// For more information: [`D3D12_RENDER_TARGET_BLEND_DESC structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_render_target_blend_desc)
1915#[derive(Clone, Copy, Debug, PartialEq)]
1916#[repr(transparent)]
1917pub struct RenderTargetBlendDesc(pub(crate) D3D12_RENDER_TARGET_BLEND_DESC);
1918
1919impl RenderTargetBlendDesc {
1920    #[inline]
1921    pub fn blend(
1922        src_blend: Blend,
1923        dst_blend: Blend,
1924        blend_op: BlendOp,
1925        mask: ColorWriteEnable,
1926    ) -> Self {
1927        Self(D3D12_RENDER_TARGET_BLEND_DESC {
1928            BlendEnable: true.into(),
1929            SrcBlend: src_blend.as_raw(),
1930            DestBlend: dst_blend.as_raw(),
1931            BlendOp: blend_op.as_raw(),
1932            RenderTargetWriteMask: mask.bits() as u8,
1933            ..Default::default()
1934        })
1935    }
1936
1937    #[inline]
1938    pub fn blend_with_alpha(
1939        src_blend: Blend,
1940        dst_blend: Blend,
1941        blend_op: BlendOp,
1942        src_blend_alpha: Blend,
1943        dst_blend_alpha: Blend,
1944        blend_op_alpha: BlendOp,
1945        mask: ColorWriteEnable,
1946    ) -> Self {
1947        Self(D3D12_RENDER_TARGET_BLEND_DESC {
1948            BlendEnable: true.into(),
1949            SrcBlend: src_blend.as_raw(),
1950            DestBlend: dst_blend.as_raw(),
1951            BlendOp: blend_op.as_raw(),
1952            SrcBlendAlpha: src_blend_alpha.as_raw(),
1953            DestBlendAlpha: dst_blend_alpha.as_raw(),
1954            BlendOpAlpha: blend_op_alpha.as_raw(),
1955            RenderTargetWriteMask: mask.bits() as u8,
1956            ..Default::default()
1957        })
1958    }
1959
1960    #[inline]
1961    pub fn logic(logic_op: LogicOp, mask: ColorWriteEnable) -> Self {
1962        Self(D3D12_RENDER_TARGET_BLEND_DESC {
1963            LogicOpEnable: true.into(),
1964            LogicOp: logic_op.as_raw(),
1965            RenderTargetWriteMask: mask.bits() as u8,
1966            ..Default::default()
1967        })
1968    }
1969
1970    #[inline]
1971    pub fn with_write_mask(mut self, mask: ColorWriteEnable) -> Self {
1972        self.0.RenderTargetWriteMask = mask.bits() as u8;
1973        self
1974    }
1975}
1976
1977impl Default for RenderTargetBlendDesc {
1978    fn default() -> Self {
1979        Self(D3D12_RENDER_TARGET_BLEND_DESC {
1980            RenderTargetWriteMask: ColorWriteEnable::all().bits() as u8,
1981            ..Default::default()
1982        })
1983    }
1984}
1985
1986/// Describes the subresources from a resource that are accessible by using a render-target view.
1987///
1988/// For more information: [`D3D12_RENDER_TARGET_VIEW_DESC structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_render_target_view_desc)
1989#[derive(Clone, Copy)]
1990#[repr(transparent)]
1991pub struct RenderTargetViewDesc(pub(crate) D3D12_RENDER_TARGET_VIEW_DESC);
1992
1993impl RenderTargetViewDesc {
1994    #[inline]
1995    pub fn buffer(format: Format, elements_range: Range<u64>) -> Self {
1996        Self(D3D12_RENDER_TARGET_VIEW_DESC {
1997            Format: format.as_raw(),
1998            ViewDimension: D3D12_RTV_DIMENSION_BUFFER,
1999            Anonymous: D3D12_RENDER_TARGET_VIEW_DESC_0 {
2000                Buffer: D3D12_BUFFER_RTV {
2001                    FirstElement: elements_range.start,
2002                    NumElements: elements_range.count() as u32,
2003                },
2004            },
2005        })
2006    }
2007
2008    #[inline]
2009    pub fn texture_1d(format: Format, mip_slice: u32) -> Self {
2010        Self(D3D12_RENDER_TARGET_VIEW_DESC {
2011            Format: format.as_raw(),
2012            ViewDimension: D3D12_RTV_DIMENSION_TEXTURE1D,
2013            Anonymous: D3D12_RENDER_TARGET_VIEW_DESC_0 {
2014                Texture1D: D3D12_TEX1D_RTV {
2015                    MipSlice: mip_slice,
2016                },
2017            },
2018        })
2019    }
2020
2021    #[inline]
2022    pub fn texture_2d(format: Format, mip_slice: u32, plane_slice: u32) -> Self {
2023        Self(D3D12_RENDER_TARGET_VIEW_DESC {
2024            Format: format.as_raw(),
2025            ViewDimension: D3D12_RTV_DIMENSION_TEXTURE2D,
2026            Anonymous: D3D12_RENDER_TARGET_VIEW_DESC_0 {
2027                Texture2D: D3D12_TEX2D_RTV {
2028                    MipSlice: mip_slice,
2029                    PlaneSlice: plane_slice,
2030                },
2031            },
2032        })
2033    }
2034
2035    #[inline]
2036    pub fn texture_3d(format: Format, mip_slice: u32, w_slices: Range<u32>) -> Self {
2037        Self(D3D12_RENDER_TARGET_VIEW_DESC {
2038            Format: format.as_raw(),
2039            ViewDimension: D3D12_RTV_DIMENSION_TEXTURE3D,
2040            Anonymous: D3D12_RENDER_TARGET_VIEW_DESC_0 {
2041                Texture3D: D3D12_TEX3D_RTV {
2042                    MipSlice: mip_slice,
2043                    FirstWSlice: w_slices.start,
2044                    WSize: w_slices.count() as u32,
2045                },
2046            },
2047        })
2048    }
2049
2050    #[inline]
2051    pub fn texture_1d_array(format: Format, mip_slice: u32, array: Range<u32>) -> Self {
2052        Self(D3D12_RENDER_TARGET_VIEW_DESC {
2053            Format: format.as_raw(),
2054            ViewDimension: D3D12_RTV_DIMENSION_TEXTURE1DARRAY,
2055            Anonymous: D3D12_RENDER_TARGET_VIEW_DESC_0 {
2056                Texture1DArray: D3D12_TEX1D_ARRAY_RTV {
2057                    MipSlice: mip_slice,
2058                    FirstArraySlice: array.start,
2059                    ArraySize: array.count() as u32,
2060                },
2061            },
2062        })
2063    }
2064
2065    #[inline]
2066    pub fn texture_2d_array(
2067        format: Format,
2068        mip_slice: u32,
2069        plane_slice: u32,
2070        array: Range<u32>,
2071    ) -> Self {
2072        Self(D3D12_RENDER_TARGET_VIEW_DESC {
2073            Format: format.as_raw(),
2074            ViewDimension: D3D12_RTV_DIMENSION_TEXTURE2DARRAY,
2075            Anonymous: D3D12_RENDER_TARGET_VIEW_DESC_0 {
2076                Texture2DArray: D3D12_TEX2D_ARRAY_RTV {
2077                    MipSlice: mip_slice,
2078                    PlaneSlice: plane_slice,
2079                    FirstArraySlice: array.start,
2080                    ArraySize: array.count() as u32,
2081                },
2082            },
2083        })
2084    }
2085
2086    #[inline]
2087    pub fn texture_2d_ms(format: Format) -> Self {
2088        Self(D3D12_RENDER_TARGET_VIEW_DESC {
2089            Format: format.as_raw(),
2090            ViewDimension: D3D12_RTV_DIMENSION_TEXTURE2DMS,
2091            Anonymous: D3D12_RENDER_TARGET_VIEW_DESC_0 {
2092                Texture2DMS: Default::default(),
2093            },
2094        })
2095    }
2096
2097    #[inline]
2098    pub fn texture_2d_ms_array(format: Format, array: Range<u32>) -> Self {
2099        Self(D3D12_RENDER_TARGET_VIEW_DESC {
2100            Format: format.as_raw(),
2101            ViewDimension: D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY,
2102            Anonymous: D3D12_RENDER_TARGET_VIEW_DESC_0 {
2103                Texture2DMSArray: D3D12_TEX2DMS_ARRAY_RTV {
2104                    FirstArraySlice: array.start,
2105                    ArraySize: array.count() as u32,
2106                },
2107            },
2108        })
2109    }
2110}
2111
2112/// Describes parameters needed to allocate resources.
2113///
2114/// For more information: [`D3D12_RESOURCE_ALLOCATION_INFO structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_resource_allocation_info)
2115#[derive(Clone, Copy, Debug, Default, PartialEq)]
2116#[repr(transparent)]
2117pub struct ResourceAllocationInfo(pub(crate) D3D12_RESOURCE_ALLOCATION_INFO);
2118
2119impl ResourceAllocationInfo {
2120    #[inline]
2121    pub fn size(&self) -> u64 {
2122        self.0.SizeInBytes
2123    }
2124
2125    #[inline]
2126    pub fn alignment(&self) -> u64 {
2127        self.0.Alignment
2128    }
2129}
2130
2131/// Describes a resource barrier (transition in resource use).
2132///
2133/// For more information: [`D3D12_RESOURCE_BARRIER structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_resource_barrier)
2134#[derive(Clone)]
2135#[repr(transparent)]
2136pub struct ResourceBarrier<'a>(pub(crate) D3D12_RESOURCE_BARRIER, PhantomData<&'a ()>);
2137
2138impl<'a> ResourceBarrier<'a> {
2139    #[inline]
2140    pub fn transition(
2141        resource: &'a Resource,
2142        before: ResourceStates,
2143        after: ResourceStates,
2144        subresource: Option<u32>,
2145    ) -> Self {
2146        Self(
2147            D3D12_RESOURCE_BARRIER {
2148                Type: D3D12_RESOURCE_BARRIER_TYPE_TRANSITION,
2149                Flags: D3D12_RESOURCE_BARRIER_FLAG_NONE,
2150                Anonymous: D3D12_RESOURCE_BARRIER_0 {
2151                    Transition: ManuallyDrop::new(D3D12_RESOURCE_TRANSITION_BARRIER {
2152                        pResource: unsafe { std::mem::transmute_copy(&resource.0) },
2153                        Subresource: subresource.unwrap_or(BARRIER_ALL_SUBRESOURCES),
2154                        StateBefore: before.as_raw(),
2155                        StateAfter: after.as_raw(),
2156                    }),
2157                },
2158            },
2159            Default::default(),
2160        )
2161    }
2162
2163    #[inline]
2164    pub fn aliasing(before: &'a Resource, after: &'a Resource) -> Self {
2165        Self(
2166            D3D12_RESOURCE_BARRIER {
2167                Type: D3D12_RESOURCE_BARRIER_TYPE_ALIASING,
2168                Flags: D3D12_RESOURCE_BARRIER_FLAG_NONE,
2169                Anonymous: D3D12_RESOURCE_BARRIER_0 {
2170                    Aliasing: ManuallyDrop::new(D3D12_RESOURCE_ALIASING_BARRIER {
2171                        pResourceBefore: unsafe { std::mem::transmute_copy(&before.0) },
2172                        pResourceAfter: unsafe { std::mem::transmute_copy(&after.0) },
2173                    }),
2174                },
2175            },
2176            Default::default(),
2177        )
2178    }
2179
2180    #[inline]
2181    pub fn uav(resource: &'a Resource) -> Self {
2182        Self(
2183            D3D12_RESOURCE_BARRIER {
2184                Type: D3D12_RESOURCE_BARRIER_TYPE_UAV,
2185                Flags: D3D12_RESOURCE_BARRIER_FLAG_NONE,
2186                Anonymous: D3D12_RESOURCE_BARRIER_0 {
2187                    UAV: ManuallyDrop::new(D3D12_RESOURCE_UAV_BARRIER {
2188                        pResource: unsafe { std::mem::transmute_copy(&resource.0) },
2189                    }),
2190                },
2191            },
2192            Default::default(),
2193        )
2194    }
2195
2196    #[inline]
2197    pub fn with_flags(mut self, flags: ResourceBarrierFlags) -> Self {
2198        self.0.Flags = flags.as_raw();
2199        self
2200    }
2201}
2202
2203/// Describes a resource, such as a texture. This structure is used extensively.
2204///
2205/// For more information: [`D3D12_RESOURCE_DESC structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_resource_desc)
2206#[derive(Clone, Copy, Debug, PartialEq)]
2207#[repr(transparent)]
2208pub struct ResourceDesc(pub(crate) D3D12_RESOURCE_DESC);
2209
2210impl ResourceDesc {
2211    #[inline]
2212    pub fn buffer(size: u64) -> Self {
2213        Self(D3D12_RESOURCE_DESC {
2214            Dimension: D3D12_RESOURCE_DIMENSION_BUFFER,
2215            Width: size,
2216            Height: 1,
2217            DepthOrArraySize: 1,
2218            MipLevels: 1,
2219            Alignment: HeapAlignment::Default.as_raw(),
2220            Format: DXGI_FORMAT_UNKNOWN,
2221            SampleDesc: DXGI_SAMPLE_DESC {
2222                Count: 1,
2223                Quality: 0,
2224            },
2225            Layout: D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
2226            ..Default::default()
2227        })
2228    }
2229
2230    #[inline]
2231    pub fn texture_1d(width: u64) -> Self {
2232        Self(D3D12_RESOURCE_DESC {
2233            Dimension: D3D12_RESOURCE_DIMENSION_TEXTURE1D,
2234            Width: width,
2235            Height: 1,
2236            DepthOrArraySize: 1,
2237            MipLevels: 1,
2238            SampleDesc: DXGI_SAMPLE_DESC {
2239                Count: 1,
2240                Quality: 0,
2241            },
2242            ..Default::default()
2243        })
2244    }
2245
2246    #[inline]
2247    pub fn texture_2d(width: u64, height: u32) -> Self {
2248        Self(D3D12_RESOURCE_DESC {
2249            Dimension: D3D12_RESOURCE_DIMENSION_TEXTURE2D,
2250            Width: width,
2251            Height: height,
2252            DepthOrArraySize: 1,
2253            MipLevels: 1,
2254            SampleDesc: DXGI_SAMPLE_DESC {
2255                Count: 1,
2256                Quality: 0,
2257            },
2258            ..Default::default()
2259        })
2260    }
2261
2262    #[inline]
2263    pub fn texture_3d(width: u64, height: u32, depth: u16) -> Self {
2264        Self(D3D12_RESOURCE_DESC {
2265            Dimension: D3D12_RESOURCE_DIMENSION_TEXTURE2D,
2266            Width: width,
2267            Height: height,
2268            DepthOrArraySize: depth,
2269            MipLevels: 1,
2270            SampleDesc: DXGI_SAMPLE_DESC {
2271                Count: 1,
2272                Quality: 0,
2273            },
2274            ..Default::default()
2275        })
2276    }
2277
2278    #[inline]
2279    pub fn with_alignment(mut self, alignment: HeapAlignment) -> Self {
2280        self.0.Alignment = alignment.as_raw();
2281        self
2282    }
2283
2284    #[inline]
2285    pub fn with_array_size(mut self, size: u16) -> Self {
2286        self.0.DepthOrArraySize = size;
2287        self
2288    }
2289
2290    #[inline]
2291    pub fn with_format(mut self, format: Format) -> Self {
2292        self.0.Format = format.as_raw();
2293        self
2294    }
2295
2296    #[inline]
2297    pub fn with_mip_levels(mut self, mip_levels: u16) -> Self {
2298        self.0.MipLevels = mip_levels;
2299        self
2300    }
2301
2302    #[inline]
2303    pub fn with_sample_desc(mut self, sample_desc: SampleDesc) -> Self {
2304        self.0.SampleDesc = sample_desc.0;
2305        self
2306    }
2307
2308    #[inline]
2309    pub fn with_layout(mut self, layout: TextureLayout) -> Self {
2310        self.0.Layout = layout.as_raw();
2311        self
2312    }
2313
2314    #[inline]
2315    pub fn with_flags(mut self, flags: ResourceFlags) -> Self {
2316        self.0.Flags = flags.as_raw();
2317        self
2318    }
2319
2320    #[inline]
2321    pub fn dimension(&self) -> ResourceDimension {
2322        self.0.Dimension.into()
2323    }
2324
2325    #[inline]
2326    pub fn width(&self) -> u64 {
2327        self.0.Width
2328    }
2329
2330    #[inline]
2331    pub fn height(&self) -> u32 {
2332        self.0.Height
2333    }
2334
2335    #[inline]
2336    pub fn depth_or_array_size(&self) -> u16 {
2337        self.0.DepthOrArraySize
2338    }
2339
2340    #[inline]
2341    pub fn alignment(&self) -> HeapAlignment {
2342        self.0.Alignment.into()
2343    }
2344
2345    #[inline]
2346    pub fn format(&self) -> Format {
2347        self.0.Format.into()
2348    }
2349
2350    #[inline]
2351    pub fn mip_levels(&self) -> u16 {
2352        self.0.MipLevels
2353    }
2354
2355    #[inline]
2356    pub fn sample_desc(&self) -> SampleDesc {
2357        SampleDesc(self.0.SampleDesc)
2358    }
2359
2360    #[inline]
2361    pub fn layout(&self) -> TextureLayout {
2362        self.0.Layout.into()
2363    }
2364
2365    #[inline]
2366    pub fn flags(&self) -> ResourceFlags {
2367        self.0.Flags.into()
2368    }
2369}
2370
2371/// Describes the slot of a root signature version 1.0.
2372///
2373/// For more information: [`D3D12_ROOT_PARAMETER structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_root_parameter)
2374#[derive(Clone, Copy)]
2375#[repr(transparent)]
2376pub struct RootParameter<'a>(pub(crate) D3D12_ROOT_PARAMETER, PhantomData<&'a ()>);
2377
2378impl<'a> RootParameter<'a> {
2379    #[inline]
2380    pub fn descriptor_table(ranges: &'a [DescriptorRange]) -> Self {
2381        Self(
2382            D3D12_ROOT_PARAMETER {
2383                ParameterType: D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE,
2384                Anonymous: D3D12_ROOT_PARAMETER_0 {
2385                    DescriptorTable: D3D12_ROOT_DESCRIPTOR_TABLE {
2386                        NumDescriptorRanges: ranges.len() as u32,
2387                        pDescriptorRanges: ranges.as_ptr() as *const _,
2388                    },
2389                },
2390                ..Default::default()
2391            },
2392            Default::default(),
2393        )
2394    }
2395
2396    #[inline]
2397    pub fn constant_32bit(
2398        shader_register: u32,
2399        register_space: u32,
2400        num_32bit_values: u32,
2401    ) -> Self {
2402        Self(
2403            D3D12_ROOT_PARAMETER {
2404                ParameterType: D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS,
2405                Anonymous: D3D12_ROOT_PARAMETER_0 {
2406                    Constants: D3D12_ROOT_CONSTANTS {
2407                        ShaderRegister: shader_register,
2408                        RegisterSpace: register_space,
2409                        Num32BitValues: num_32bit_values,
2410                    },
2411                },
2412                ..Default::default()
2413            },
2414            Default::default(),
2415        )
2416    }
2417
2418    #[inline]
2419    pub fn cbv(shader_register: u32, register_space: u32) -> Self {
2420        Self(
2421            D3D12_ROOT_PARAMETER {
2422                ParameterType: D3D12_ROOT_PARAMETER_TYPE_CBV,
2423                Anonymous: D3D12_ROOT_PARAMETER_0 {
2424                    Descriptor: D3D12_ROOT_DESCRIPTOR {
2425                        ShaderRegister: shader_register,
2426                        RegisterSpace: register_space,
2427                    },
2428                },
2429                ..Default::default()
2430            },
2431            Default::default(),
2432        )
2433    }
2434
2435    #[inline]
2436    pub fn srv(shader_register: u32, register_space: u32) -> Self {
2437        Self(
2438            D3D12_ROOT_PARAMETER {
2439                ParameterType: D3D12_ROOT_PARAMETER_TYPE_SRV,
2440                Anonymous: D3D12_ROOT_PARAMETER_0 {
2441                    Descriptor: D3D12_ROOT_DESCRIPTOR {
2442                        ShaderRegister: shader_register,
2443                        RegisterSpace: register_space,
2444                    },
2445                },
2446                ..Default::default()
2447            },
2448            Default::default(),
2449        )
2450    }
2451
2452    #[inline]
2453    pub fn uav(shader_register: u32, register_space: u32) -> Self {
2454        Self(
2455            D3D12_ROOT_PARAMETER {
2456                ParameterType: D3D12_ROOT_PARAMETER_TYPE_UAV,
2457                Anonymous: D3D12_ROOT_PARAMETER_0 {
2458                    Descriptor: D3D12_ROOT_DESCRIPTOR {
2459                        ShaderRegister: shader_register,
2460                        RegisterSpace: register_space,
2461                    },
2462                },
2463                ..Default::default()
2464            },
2465            Default::default(),
2466        )
2467    }
2468
2469    #[inline]
2470    pub fn with_visibility(mut self, visibility: ShaderVisibility) -> Self {
2471        self.0.ShaderVisibility = visibility.as_raw();
2472        self
2473    }
2474}
2475
2476/// Describes the layout of a root signature version 1.0.
2477///
2478/// For more information: [`D3D12_ROOT_SIGNATURE_DESC structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_root_signature_desc)
2479#[derive(Clone, Copy, Debug, Default, PartialEq)]
2480#[repr(transparent)]
2481pub struct RootSignatureDesc<'a>(pub(crate) D3D12_ROOT_SIGNATURE_DESC, PhantomData<&'a ()>);
2482
2483impl<'a> RootSignatureDesc<'a> {
2484    #[inline]
2485    pub fn with_parameters<'b>(mut self, parameters: &'a [RootParameter<'b>]) -> Self
2486    where
2487        'a: 'b,
2488    {
2489        self.0.NumParameters = parameters.len() as u32;
2490        self.0.pParameters = parameters.as_ptr() as *const _;
2491        self
2492    }
2493
2494    #[inline]
2495    pub fn with_samplers<'b>(mut self, samplers: &'a [StaticSamplerDesc]) -> Self
2496    where
2497        'a: 'b,
2498    {
2499        self.0.NumStaticSamplers = samplers.len() as u32;
2500        self.0.pStaticSamplers = samplers.as_ptr() as *const _;
2501        self
2502    }
2503
2504    #[inline]
2505    pub fn with_flags(mut self, flags: RootSignatureFlags) -> Self {
2506        self.0.Flags = flags.as_raw();
2507        self
2508    }
2509}
2510
2511/// Describes multi-sampling parameters for a resource.
2512///
2513/// For more information: [`DXGI_SAMPLE_DESC structure`](https://learn.microsoft.com/en-us/windows/win32/api/dxgicommon/ns-dxgicommon-dxgi_sample_desc)
2514#[derive(Clone, Copy, Debug, PartialEq)]
2515#[repr(transparent)]
2516pub struct SampleDesc(pub(crate) DXGI_SAMPLE_DESC);
2517
2518impl SampleDesc {
2519    #[inline]
2520    pub fn new(count: u32, quality: u32) -> Self {
2521        Self(DXGI_SAMPLE_DESC {
2522            Count: count,
2523            Quality: quality,
2524        })
2525    }
2526}
2527
2528impl Default for SampleDesc {
2529    fn default() -> Self {
2530        Self::new(1, 0)
2531    }
2532}
2533
2534/// Describes a sampler state.
2535///
2536/// For more information: [`D3D12_SAMPLER_DESC structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_sampler_desc)
2537#[derive(Clone, Copy, Debug, Default, PartialEq)]
2538#[repr(transparent)]
2539pub struct SamplerDesc(pub(crate) D3D12_SAMPLER_DESC);
2540
2541impl SamplerDesc {
2542    #[inline]
2543    pub fn new(filter: Filter) -> Self {
2544        Self::default().with_filter(filter)
2545    }
2546
2547    #[inline]
2548    pub fn point() -> Self {
2549        Self::default().with_filter(Filter::Point)
2550    }
2551
2552    #[inline]
2553    pub fn linear() -> Self {
2554        Self::default().with_filter(Filter::Linear)
2555    }
2556
2557    #[inline]
2558    pub fn anisotropic() -> Self {
2559        Self::default().with_filter(Filter::Anisotropic)
2560    }
2561
2562    #[inline]
2563    pub fn with_filter(mut self, filter: Filter) -> Self {
2564        self.0.Filter = filter.as_raw();
2565        self
2566    }
2567
2568    #[inline]
2569    pub fn with_address_u(mut self, address: AddressMode) -> Self {
2570        self.0.AddressU = address.as_raw();
2571        self
2572    }
2573
2574    #[inline]
2575    pub fn with_address_v(mut self, address: AddressMode) -> Self {
2576        self.0.AddressV = address.as_raw();
2577        self
2578    }
2579
2580    #[inline]
2581    pub fn with_address_w(mut self, address: AddressMode) -> Self {
2582        self.0.AddressW = address.as_raw();
2583        self
2584    }
2585
2586    #[inline]
2587    pub fn with_mip_lod_bias(mut self, mip_lod_bias: f32) -> Self {
2588        self.0.MipLODBias = mip_lod_bias;
2589        self
2590    }
2591
2592    #[inline]
2593    pub fn with_max_anisotropy(mut self, max_anisotropy: u32) -> Self {
2594        self.0.MaxAnisotropy = max_anisotropy;
2595        self
2596    }
2597
2598    #[inline]
2599    pub fn with_comparison_func(mut self, comparison_func: ComparisonFunc) -> Self {
2600        self.0.ComparisonFunc = comparison_func.as_raw();
2601        self
2602    }
2603
2604    #[inline]
2605    pub fn with_border_color(mut self, border_color: impl Into<[f32; 4]>) -> Self {
2606        self.0.BorderColor = border_color.into();
2607        self
2608    }
2609
2610    #[inline]
2611    pub fn with_lod(mut self, lod: Range<f32>) -> Self {
2612        self.0.MinLOD = lod.start;
2613        self.0.MaxLOD = lod.end;
2614        self
2615    }
2616}
2617
2618/// Describes a shader.
2619///
2620/// For more information: [`D3D12_SHADER_DESC structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12shader/ns-d3d12shader-d3d12_shader_desc)
2621#[derive(Clone, Copy, Debug, PartialEq)]
2622#[repr(transparent)]
2623pub struct ShaderDesc(pub(crate) D3D12_SHADER_DESC);
2624
2625impl ShaderDesc {
2626    #[inline]
2627    pub fn get_version(&self) -> u32 {
2628        self.0.Version
2629    }
2630
2631    #[inline]
2632    pub fn get_creator(&self) -> &CStr {
2633        unsafe { CStr::from_ptr(self.0.Creator.as_ptr() as *const _) }
2634    }
2635
2636    #[inline]
2637    pub fn get_flags(&self) -> u32 {
2638        self.0.Flags
2639    }
2640
2641    #[inline]
2642    pub fn get_constant_buffers(&self) -> u32 {
2643        self.0.ConstantBuffers
2644    }
2645
2646    #[inline]
2647    pub fn get_bound_resources(&self) -> u32 {
2648        self.0.BoundResources
2649    }
2650
2651    #[inline]
2652    pub fn get_input_parameters(&self) -> u32 {
2653        self.0.InputParameters
2654    }
2655
2656    #[inline]
2657    pub fn get_output_parameters(&self) -> u32 {
2658        self.0.OutputParameters
2659    }
2660
2661    #[inline]
2662    pub fn get_instruction_count(&self) -> u32 {
2663        self.0.InstructionCount
2664    }
2665
2666    #[inline]
2667    pub fn get_temp_register_count(&self) -> u32 {
2668        self.0.TempRegisterCount
2669    }
2670
2671    #[inline]
2672    pub fn get_temp_array_count(&self) -> u32 {
2673        self.0.TempArrayCount
2674    }
2675
2676    #[inline]
2677    pub fn get_def_count(&self) -> u32 {
2678        self.0.DefCount
2679    }
2680
2681    #[inline]
2682    pub fn get_dcl_count(&self) -> u32 {
2683        self.0.DclCount
2684    }
2685
2686    #[inline]
2687    pub fn get_texture_normal_instructions(&self) -> u32 {
2688        self.0.TextureNormalInstructions
2689    }
2690
2691    #[inline]
2692    pub fn get_texture_load_instructions(&self) -> u32 {
2693        self.0.TextureLoadInstructions
2694    }
2695
2696    #[inline]
2697    pub fn get_texture_comp_instructions(&self) -> u32 {
2698        self.0.TextureCompInstructions
2699    }
2700
2701    #[inline]
2702    pub fn get_texture_bias_instructions(&self) -> u32 {
2703        self.0.TextureBiasInstructions
2704    }
2705
2706    #[inline]
2707    pub fn get_texture_gradient_instructions(&self) -> u32 {
2708        self.0.TextureGradientInstructions
2709    }
2710
2711    #[inline]
2712    pub fn get_float_instruction_count(&self) -> u32 {
2713        self.0.FloatInstructionCount
2714    }
2715
2716    #[inline]
2717    pub fn get_int_instruction_count(&self) -> u32 {
2718        self.0.IntInstructionCount
2719    }
2720
2721    #[inline]
2722    pub fn get_uint_instruction_count(&self) -> u32 {
2723        self.0.UintInstructionCount
2724    }
2725
2726    #[inline]
2727    pub fn get_static_flow_control_count(&self) -> u32 {
2728        self.0.StaticFlowControlCount
2729    }
2730
2731    #[inline]
2732    pub fn get_dynamic_flow_control_count(&self) -> u32 {
2733        self.0.DynamicFlowControlCount
2734    }
2735
2736    #[inline]
2737    pub fn get_macro_instruction_count(&self) -> u32 {
2738        self.0.MacroInstructionCount
2739    }
2740
2741    #[inline]
2742    pub fn get_array_instruction_count(&self) -> u32 {
2743        self.0.ArrayInstructionCount
2744    }
2745
2746    #[inline]
2747    pub fn get_cut_instruction_count(&self) -> u32 {
2748        self.0.CutInstructionCount
2749    }
2750
2751    #[inline]
2752    pub fn get_emit_instruction_count(&self) -> u32 {
2753        self.0.EmitInstructionCount
2754    }
2755
2756    #[inline]
2757    pub fn get_gs_output_topology(&self) -> PrimitiveTopology {
2758        self.0.GSOutputTopology.into()
2759    }
2760
2761    #[inline]
2762    pub fn get_gs_max_output_vertex_count(&self) -> u32 {
2763        self.0.GSMaxOutputVertexCount
2764    }
2765
2766    #[inline]
2767    pub fn get_input_primitive(&self) -> Primitive {
2768        self.0.InputPrimitive.into()
2769    }
2770
2771    #[inline]
2772    pub fn get_patch_constant_parameters(&self) -> u32 {
2773        self.0.PatchConstantParameters
2774    }
2775
2776    #[inline]
2777    pub fn get_cgs_instance_count(&self) -> u32 {
2778        self.0.cGSInstanceCount
2779    }
2780
2781    #[inline]
2782    pub fn get_c_control_points(&self) -> u32 {
2783        self.0.cControlPoints
2784    }
2785
2786    #[inline]
2787    pub fn get_hs_output_primitive(&self) -> TessellatorOutputPrimitive {
2788        self.0.HSOutputPrimitive.into()
2789    }
2790
2791    #[inline]
2792    pub fn get_hs_partitioning(&self) -> TessellatorPartitioning {
2793        self.0.HSPartitioning.into()
2794    }
2795
2796    #[inline]
2797    pub fn get_tessellator_domain(&self) -> TessellatorDomain {
2798        self.0.TessellatorDomain.into()
2799    }
2800
2801    #[inline]
2802    pub fn get_c_barrier_instructions(&self) -> u32 {
2803        self.0.cBarrierInstructions
2804    }
2805
2806    #[inline]
2807    pub fn get_c_interlocked_instructions(&self) -> u32 {
2808        self.0.cInterlockedInstructions
2809    }
2810
2811    #[inline]
2812    pub fn get_c_texture_store_instructions(&self) -> u32 {
2813        self.0.cTextureStoreInstructions
2814    }
2815}
2816
2817/// Describes a shader constant-buffer.
2818///
2819/// For more information: [`D3D12_SHADER_BUFFER_DESC structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12shader/ns-d3d12shader-d3d12_shader_buffer_desc)
2820#[derive(Clone, Copy, Debug, PartialEq)]
2821#[repr(transparent)]
2822pub struct ShaderBufferDesc(pub(crate) D3D12_SHADER_BUFFER_DESC);
2823
2824impl ShaderBufferDesc {
2825    #[inline]
2826    pub fn name(&self) -> &CStr {
2827        unsafe { CStr::from_ptr(self.0.Name.as_ptr() as *const _) }
2828    }
2829
2830    #[inline]
2831    pub fn ty(&self) -> CbufferType {
2832        self.0.Type.into()
2833    }
2834
2835    #[inline]
2836    pub fn variable(&self) -> u32 {
2837        self.0.Variables
2838    }
2839
2840    #[inline]
2841    pub fn size(&self) -> u32 {
2842        self.0.Size
2843    }
2844
2845    #[inline]
2846    pub fn flags(&self) -> CbufferFlags {
2847        self.0.uFlags.into()
2848    }
2849}
2850
2851/// Defines a shader macro.
2852///
2853/// For more information: [`D3D_SHADER_MACRO structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3dcommon/ns-d3dcommon-d3d_shader_macro)
2854#[derive(Clone, Copy, Debug, Default, PartialEq)]
2855#[repr(transparent)]
2856pub struct ShaderMacro<'a>(pub(crate) D3D_SHADER_MACRO, PhantomData<&'a ()>);
2857
2858impl<'a> ShaderMacro<'a> {
2859    #[inline]
2860    pub fn new(name: &'a CStr, definition: &'a CStr) -> Self {
2861        let k = PCSTR::from_raw(name.as_ref().as_ptr() as *const _);
2862        let v = PCSTR::from_raw(definition.as_ref().as_ptr() as *const _);
2863
2864        Self(
2865            D3D_SHADER_MACRO {
2866                Name: k,
2867                Definition: v,
2868            },
2869            Default::default(),
2870        )
2871    }
2872}
2873
2874/// Describes how a shader resource is bound to a shader input.
2875///
2876/// For more information: [`D3D12_SHADER_INPUT_BIND_DESC structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12shader/ns-d3d12shader-d3d12_shader_input_bind_desc)
2877#[derive(Clone, Copy, Debug, Default, PartialEq)]
2878#[repr(transparent)]
2879pub struct ShaderInputBindDesc(pub(crate) D3D12_SHADER_INPUT_BIND_DESC);
2880
2881impl ShaderInputBindDesc {
2882    #[inline]
2883    pub fn name(&self) -> &CStr {
2884        unsafe { CStr::from_ptr(self.0.Name.as_ptr() as *const _) }
2885    }
2886
2887    #[inline]
2888    pub fn input_type(&self) -> ShaderInputType {
2889        self.0.Type.into()
2890    }
2891
2892    #[inline]
2893    pub fn bind_point(&self) -> u32 {
2894        self.0.BindPoint
2895    }
2896
2897    #[inline]
2898    pub fn bind_count(&self) -> u32 {
2899        self.0.BindCount
2900    }
2901
2902    #[inline]
2903    pub fn flags(&self) -> u32 {
2904        self.0.uFlags
2905    }
2906
2907    #[inline]
2908    pub fn return_type(&self) -> ResourceReturnType {
2909        self.0.ReturnType.into()
2910    }
2911
2912    #[inline]
2913    pub fn dimension(&self) -> SrvDimension {
2914        self.0.Dimension.into()
2915    }
2916
2917    #[inline]
2918    pub fn num_samples(&self) -> u32 {
2919        self.0.NumSamples
2920    }
2921
2922    #[inline]
2923    pub fn space(&self) -> u32 {
2924        self.0.Space
2925    }
2926
2927    #[inline]
2928    pub fn id(&self) -> u32 {
2929        self.0.uID
2930    }
2931}
2932
2933/// Describes a shader-resource view (SRV).
2934///
2935/// For more information: [`D3D12_SHADER_RESOURCE_VIEW_DESC structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_shader_resource_view_desc)
2936#[derive(Clone, Copy)]
2937#[repr(transparent)]
2938pub struct ShaderResourceViewDesc(pub(crate) D3D12_SHADER_RESOURCE_VIEW_DESC);
2939
2940impl ShaderResourceViewDesc {
2941    #[inline]
2942    pub fn buffer(
2943        format: Format,
2944        elements: Range<u64>,
2945        structure_byte_stride: u32,
2946        flags: BufferSrvFlags,
2947    ) -> Self {
2948        Self(D3D12_SHADER_RESOURCE_VIEW_DESC {
2949            Format: format.as_raw(),
2950            ViewDimension: D3D12_SRV_DIMENSION_BUFFER,
2951            Anonymous: D3D12_SHADER_RESOURCE_VIEW_DESC_0 {
2952                Buffer: D3D12_BUFFER_SRV {
2953                    FirstElement: elements.start,
2954                    NumElements: elements.count() as u32,
2955                    StructureByteStride: structure_byte_stride,
2956                    Flags: flags.as_raw(),
2957                },
2958            },
2959            Shader4ComponentMapping: D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
2960        })
2961    }
2962
2963    #[inline]
2964    pub fn texture_1d(
2965        format: Format,
2966        most_detailed_mip: u32,
2967        mip_levels: u32,
2968        resource_min_lod_clamp: f32,
2969    ) -> Self {
2970        Self(D3D12_SHADER_RESOURCE_VIEW_DESC {
2971            Format: format.as_raw(),
2972            ViewDimension: D3D12_SRV_DIMENSION_TEXTURE1D,
2973            Anonymous: D3D12_SHADER_RESOURCE_VIEW_DESC_0 {
2974                Texture1D: D3D12_TEX1D_SRV {
2975                    MostDetailedMip: most_detailed_mip,
2976                    MipLevels: mip_levels,
2977                    ResourceMinLODClamp: resource_min_lod_clamp,
2978                },
2979            },
2980            Shader4ComponentMapping: D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
2981        })
2982    }
2983
2984    #[inline]
2985    pub fn texture_2d(
2986        format: Format,
2987        most_detailed_mip: u32,
2988        mip_levels: u32,
2989        resource_min_lod_clamp: f32,
2990        plane_slice: u32,
2991    ) -> Self {
2992        Self(D3D12_SHADER_RESOURCE_VIEW_DESC {
2993            Format: format.as_raw(),
2994            ViewDimension: D3D12_SRV_DIMENSION_TEXTURE2D,
2995            Anonymous: D3D12_SHADER_RESOURCE_VIEW_DESC_0 {
2996                Texture2D: D3D12_TEX2D_SRV {
2997                    MostDetailedMip: most_detailed_mip,
2998                    MipLevels: mip_levels,
2999                    ResourceMinLODClamp: resource_min_lod_clamp,
3000                    PlaneSlice: plane_slice,
3001                },
3002            },
3003            Shader4ComponentMapping: D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
3004        })
3005    }
3006
3007    #[inline]
3008    pub fn texture_3d(
3009        format: Format,
3010        most_detailed_mip: u32,
3011        mip_levels: u32,
3012        resource_min_lod_clamp: f32,
3013    ) -> Self {
3014        Self(D3D12_SHADER_RESOURCE_VIEW_DESC {
3015            Format: format.as_raw(),
3016            ViewDimension: D3D12_SRV_DIMENSION_TEXTURE3D,
3017            Anonymous: D3D12_SHADER_RESOURCE_VIEW_DESC_0 {
3018                Texture3D: D3D12_TEX3D_SRV {
3019                    MostDetailedMip: most_detailed_mip,
3020                    MipLevels: mip_levels,
3021                    ResourceMinLODClamp: resource_min_lod_clamp,
3022                },
3023            },
3024            Shader4ComponentMapping: D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
3025        })
3026    }
3027
3028    #[inline]
3029    pub fn texture_1d_array(
3030        format: Format,
3031        most_detailed_mip: u32,
3032        mip_levels: u32,
3033        resource_min_lod_clamp: f32,
3034        array: Range<u32>,
3035    ) -> Self {
3036        Self(D3D12_SHADER_RESOURCE_VIEW_DESC {
3037            Format: format.as_raw(),
3038            ViewDimension: D3D12_SRV_DIMENSION_TEXTURE1DARRAY,
3039            Anonymous: D3D12_SHADER_RESOURCE_VIEW_DESC_0 {
3040                Texture1DArray: D3D12_TEX1D_ARRAY_SRV {
3041                    MostDetailedMip: most_detailed_mip,
3042                    MipLevels: mip_levels,
3043                    ResourceMinLODClamp: resource_min_lod_clamp,
3044                    FirstArraySlice: array.start,
3045                    ArraySize: array.count() as u32,
3046                },
3047            },
3048            Shader4ComponentMapping: D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
3049        })
3050    }
3051
3052    #[inline]
3053    pub fn texture_2d_array(
3054        format: Format,
3055        most_detailed_mip: u32,
3056        mip_levels: u32,
3057        resource_min_lod_clamp: f32,
3058        plane_slice: u32,
3059        array: Range<u32>,
3060    ) -> Self {
3061        Self(D3D12_SHADER_RESOURCE_VIEW_DESC {
3062            Format: format.as_raw(),
3063            ViewDimension: D3D12_SRV_DIMENSION_TEXTURE2DARRAY,
3064            Anonymous: D3D12_SHADER_RESOURCE_VIEW_DESC_0 {
3065                Texture2DArray: D3D12_TEX2D_ARRAY_SRV {
3066                    MostDetailedMip: most_detailed_mip,
3067                    MipLevels: mip_levels,
3068                    ResourceMinLODClamp: resource_min_lod_clamp,
3069                    PlaneSlice: plane_slice,
3070                    FirstArraySlice: array.start,
3071                    ArraySize: array.count() as u32,
3072                },
3073            },
3074            Shader4ComponentMapping: D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
3075        })
3076    }
3077
3078    #[inline]
3079    pub fn texture_2d_ms(format: Format) -> Self {
3080        Self(D3D12_SHADER_RESOURCE_VIEW_DESC {
3081            Format: format.as_raw(),
3082            ViewDimension: D3D12_SRV_DIMENSION_TEXTURE2DMS,
3083            Anonymous: D3D12_SHADER_RESOURCE_VIEW_DESC_0 {
3084                Texture2DMS: D3D12_TEX2DMS_SRV::default(),
3085            },
3086            Shader4ComponentMapping: D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
3087        })
3088    }
3089
3090    #[inline]
3091    pub fn texture_2d_ms_array(format: Format, array: Range<u32>) -> Self {
3092        Self(D3D12_SHADER_RESOURCE_VIEW_DESC {
3093            Format: format.as_raw(),
3094            ViewDimension: D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY,
3095            Anonymous: D3D12_SHADER_RESOURCE_VIEW_DESC_0 {
3096                Texture2DMSArray: D3D12_TEX2DMS_ARRAY_SRV {
3097                    FirstArraySlice: array.start,
3098                    ArraySize: array.count() as u32,
3099                },
3100            },
3101            Shader4ComponentMapping: D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
3102        })
3103    }
3104
3105    #[inline]
3106    pub fn texture_cube(
3107        format: Format,
3108        most_detailed_mip: u32,
3109        mip_levels: u32,
3110        resource_min_lod_clamp: f32,
3111    ) -> Self {
3112        Self(D3D12_SHADER_RESOURCE_VIEW_DESC {
3113            Format: format.as_raw(),
3114            ViewDimension: D3D12_SRV_DIMENSION_TEXTURECUBE,
3115            Anonymous: D3D12_SHADER_RESOURCE_VIEW_DESC_0 {
3116                TextureCube: D3D12_TEXCUBE_SRV {
3117                    MostDetailedMip: most_detailed_mip,
3118                    MipLevels: mip_levels,
3119                    ResourceMinLODClamp: resource_min_lod_clamp,
3120                },
3121            },
3122            Shader4ComponentMapping: D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
3123        })
3124    }
3125
3126    #[inline]
3127    pub fn texture_cube_array(
3128        format: Format,
3129        most_detailed_mip: u32,
3130        mip_levels: u32,
3131        resource_min_lod_clamp: f32,
3132        array: Range<u32>,
3133    ) -> Self {
3134        Self(D3D12_SHADER_RESOURCE_VIEW_DESC {
3135            Format: format.as_raw(),
3136            ViewDimension: D3D12_SRV_DIMENSION_TEXTURECUBEARRAY,
3137            Anonymous: D3D12_SHADER_RESOURCE_VIEW_DESC_0 {
3138                TextureCubeArray: D3D12_TEXCUBE_ARRAY_SRV {
3139                    MostDetailedMip: most_detailed_mip,
3140                    MipLevels: mip_levels,
3141                    ResourceMinLODClamp: resource_min_lod_clamp,
3142                    First2DArrayFace: array.start,
3143                    NumCubes: array.count() as u32,
3144                },
3145            },
3146            Shader4ComponentMapping: D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
3147        })
3148    }
3149
3150    #[inline]
3151    pub fn raytracing_acceleration_structure(format: Format, location: GpuVirtualAddress) -> Self {
3152        Self(D3D12_SHADER_RESOURCE_VIEW_DESC {
3153            Format: format.as_raw(),
3154            ViewDimension: D3D12_SRV_DIMENSION_RAYTRACING_ACCELERATION_STRUCTURE,
3155            Anonymous: D3D12_SHADER_RESOURCE_VIEW_DESC_0 {
3156                RaytracingAccelerationStructure: D3D12_RAYTRACING_ACCELERATION_STRUCTURE_SRV {
3157                    Location: location,
3158                },
3159            },
3160            Shader4ComponentMapping: D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
3161        })
3162    }
3163}
3164
3165/// A handle to the object of event.
3166#[derive(Clone, Copy, Debug, PartialEq)]
3167#[repr(transparent)]
3168pub struct SharedHandle(pub(crate) HANDLE);
3169
3170impl SharedHandle {
3171    pub fn close(self) -> Result<(), DxError> {
3172        unsafe { CloseHandle(self.0).map_err(DxError::from) }
3173    }
3174}
3175
3176/// Describes a shader-variable type.
3177///
3178/// For more information: [`D3D12_SHADER_TYPE_DESC structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12shader/ns-d3d12shader-d3d12_shader_type_desc)
3179#[derive(Clone, Copy, Debug, PartialEq)]
3180#[repr(transparent)]
3181pub struct ShaderTypeDesc(pub(crate) D3D12_SHADER_TYPE_DESC);
3182
3183impl ShaderTypeDesc {
3184    #[inline]
3185    pub fn class(&self) -> ShaderVariableClass {
3186        self.0.Class.into()
3187    }
3188
3189    #[inline]
3190    pub fn ty(&self) -> ShaderVariableType {
3191        self.0.Type.into()
3192    }
3193
3194    #[inline]
3195    pub fn rows(&self) -> u32 {
3196        self.0.Rows
3197    }
3198
3199    #[inline]
3200    pub fn columns(&self) -> u32 {
3201        self.0.Columns
3202    }
3203
3204    #[inline]
3205    pub fn elements(&self) -> u32 {
3206        self.0.Elements
3207    }
3208
3209    #[inline]
3210    pub fn members(&self) -> u32 {
3211        self.0.Members
3212    }
3213
3214    #[inline]
3215    pub fn offset(&self) -> u32 {
3216        self.0.Offset
3217    }
3218
3219    #[inline]
3220    pub fn name(&self) -> &CStr {
3221        unsafe { CStr::from_ptr(self.0.Name.as_ptr() as *const _) }
3222    }
3223}
3224
3225/// Describes a shader variable.
3226///
3227/// For more information: [`D3D12_SHADER_VARIABLE_DESC structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12shader/ns-d3d12shader-d3d12_shader_variable_desc)
3228#[derive(Clone, Copy, Debug, PartialEq)]
3229#[repr(transparent)]
3230pub struct ShaderVariableDesc(pub(crate) D3D12_SHADER_VARIABLE_DESC);
3231
3232impl ShaderVariableDesc {
3233    #[inline]
3234    pub fn name(&self) -> &CStr {
3235        unsafe { CStr::from_ptr(self.0.Name.as_ptr() as *const _) }
3236    }
3237
3238    #[inline]
3239    pub fn size(&self) -> u32 {
3240        self.0.Size
3241    }
3242
3243    #[inline]
3244    pub fn flags(&self) -> ShaderVariableFlags {
3245        windows::Win32::Graphics::Direct3D::D3D_SHADER_VARIABLE_FLAGS(self.0.uFlags as i32).into()
3246    }
3247
3248    /// # Safety
3249    ///
3250    /// The size of T must match the value of the Size field.
3251    #[inline]
3252    pub unsafe fn default_value<T: Copy + 'static>(&self) -> &T {
3253        debug_assert_eq!(size_of::<T>(), self.0.Size as usize);
3254        &*(self.0.DefaultValue as *const _)
3255    }
3256
3257    #[inline]
3258    pub fn start_texture(&self) -> u32 {
3259        self.0.StartTexture
3260    }
3261
3262    #[inline]
3263    pub fn texture_size(&self) -> u32 {
3264        self.0.TextureSize
3265    }
3266
3267    #[inline]
3268    pub fn start_sampler(&self) -> u32 {
3269        self.0.StartSampler
3270    }
3271
3272    #[inline]
3273    pub fn sampler_size(&self) -> u32 {
3274        self.0.SamplerSize
3275    }
3276}
3277
3278/// Describes a shader signature.
3279///
3280/// For more information: [`D3D12_SIGNATURE_PARAMETER_DESC structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12shader/ns-d3d12shader-d3d12_signature_parameter_desc)
3281#[derive(Clone, Copy, Debug, Default, PartialEq)]
3282#[repr(transparent)]
3283pub struct SignatureParameterDesc(pub(crate) D3D12_SIGNATURE_PARAMETER_DESC);
3284
3285impl SignatureParameterDesc {
3286    #[inline]
3287    pub fn semantic_name(&self) -> &CStr {
3288        unsafe { CStr::from_ptr(self.0.SemanticName.as_ptr() as *const _) }
3289    }
3290
3291    #[inline]
3292    pub fn semantic_index(&self) -> u32 {
3293        self.0.SemanticIndex
3294    }
3295
3296    #[inline]
3297    pub fn register(&self) -> u32 {
3298        self.0.Register
3299    }
3300
3301    #[inline]
3302    pub fn system_value_type(&self) -> ShaderVarName {
3303        self.0.SystemValueType.into()
3304    }
3305
3306    #[inline]
3307    pub fn component_type(&self) -> RegisterComponentType {
3308        self.0.ComponentType.into()
3309    }
3310
3311    #[inline]
3312    pub fn mask(&self) -> u8 {
3313        self.0.Mask
3314    }
3315
3316    #[inline]
3317    pub fn read_write_mask(&self) -> u8 {
3318        self.0.ReadWriteMask
3319    }
3320
3321    #[inline]
3322    pub fn stream(&self) -> u32 {
3323        self.0.Stream
3324    }
3325
3326    #[inline]
3327    pub fn min_precision(&self) -> MinPrecision {
3328        self.0.MinPrecision.into()
3329    }
3330}
3331
3332/// Describes a static sampler.
3333///
3334/// For more information: [`D3D12_STATIC_SAMPLER_DESC structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_static_sampler_desc)
3335#[derive(Clone, Copy, Debug, Default, PartialEq)]
3336#[repr(transparent)]
3337pub struct StaticSamplerDesc(pub(crate) D3D12_STATIC_SAMPLER_DESC);
3338
3339impl StaticSamplerDesc {
3340    #[inline]
3341    pub fn point() -> Self {
3342        Self::default().with_filter(Filter::Point)
3343    }
3344
3345    #[inline]
3346    pub fn linear() -> Self {
3347        Self::default().with_filter(Filter::Linear)
3348    }
3349
3350    #[inline]
3351    pub fn anisotropic() -> Self {
3352        Self::default().with_filter(Filter::Anisotropic)
3353    }
3354
3355    #[inline]
3356    pub fn with_filter(mut self, filter: Filter) -> Self {
3357        self.0.Filter = filter.as_raw();
3358        self
3359    }
3360
3361    #[inline]
3362    pub fn with_address_u(mut self, address: AddressMode) -> Self {
3363        self.0.AddressU = address.as_raw();
3364        self
3365    }
3366
3367    #[inline]
3368    pub fn with_address_v(mut self, address: AddressMode) -> Self {
3369        self.0.AddressV = address.as_raw();
3370        self
3371    }
3372
3373    #[inline]
3374    pub fn with_address_w(mut self, address: AddressMode) -> Self {
3375        self.0.AddressW = address.as_raw();
3376        self
3377    }
3378
3379    #[inline]
3380    pub fn with_mip_lod_bias(mut self, mip_lod_bias: f32) -> Self {
3381        self.0.MipLODBias = mip_lod_bias;
3382        self
3383    }
3384
3385    #[inline]
3386    pub fn with_max_anisotropy(mut self, max_anisotropy: u32) -> Self {
3387        self.0.MaxAnisotropy = max_anisotropy;
3388        self
3389    }
3390
3391    #[inline]
3392    pub fn with_comparison_func(mut self, comparison_func: ComparisonFunc) -> Self {
3393        self.0.ComparisonFunc = comparison_func.as_raw();
3394        self
3395    }
3396
3397    #[inline]
3398    pub fn with_border_color(mut self, border_color: BorderColor) -> Self {
3399        self.0.BorderColor = border_color.as_raw();
3400        self
3401    }
3402
3403    #[inline]
3404    pub fn with_lod(mut self, lod: Range<f32>) -> Self {
3405        self.0.MinLOD = lod.start;
3406        self.0.MaxLOD = lod.end;
3407        self
3408    }
3409
3410    #[inline]
3411    pub fn with_shader_register(mut self, shader_register: u32) -> Self {
3412        self.0.ShaderRegister = shader_register;
3413        self
3414    }
3415
3416    #[inline]
3417    pub fn with_register_space(mut self, register_space: u32) -> Self {
3418        self.0.RegisterSpace = register_space;
3419        self
3420    }
3421
3422    #[inline]
3423    pub fn with_visibility(mut self, visibility: ShaderVisibility) -> Self {
3424        self.0.ShaderVisibility = visibility.as_raw();
3425        self
3426    }
3427}
3428
3429/// Describes a stream output buffer.
3430///
3431/// For more information: [`D3D12_STREAM_OUTPUT_BUFFER_VIEW structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_stream_output_buffer_view)
3432#[derive(Clone, Copy, Debug, PartialEq)]
3433#[repr(transparent)]
3434pub struct StreamOutputBufferView(pub(crate) D3D12_STREAM_OUTPUT_BUFFER_VIEW);
3435
3436impl StreamOutputBufferView {
3437    #[inline]
3438    pub fn new(
3439        buffer_location: GpuVirtualAddress,
3440        size: u64,
3441        buffer_filled_size_location: u64,
3442    ) -> Self {
3443        Self(D3D12_STREAM_OUTPUT_BUFFER_VIEW {
3444            BufferLocation: buffer_location,
3445            SizeInBytes: size,
3446            BufferFilledSizeLocation: buffer_filled_size_location,
3447        })
3448    }
3449}
3450
3451/// Describes a streaming output buffer.
3452///
3453/// For more information: [`D3D12_STREAM_OUTPUT_DESC structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_stream_output_desc)
3454#[derive(Clone, Copy, Debug, PartialEq)]
3455#[repr(transparent)]
3456pub struct StreamOutputDesc<'a>(pub(crate) D3D12_STREAM_OUTPUT_DESC, PhantomData<&'a ()>);
3457
3458impl<'a> StreamOutputDesc<'a> {
3459    #[inline]
3460    pub fn new(entries: &'a [DeclarationEntry]) -> Self {
3461        Self(
3462            D3D12_STREAM_OUTPUT_DESC {
3463                pSODeclaration: entries.as_ptr() as *const _,
3464                NumEntries: entries.len() as u32,
3465                ..Default::default()
3466            },
3467            Default::default(),
3468        )
3469    }
3470
3471    #[inline]
3472    pub fn with_buffer_strides(mut self, buffer_strides: &'a [u32]) -> Self {
3473        self.0.pBufferStrides = buffer_strides.as_ptr();
3474        self.0.NumStrides = buffer_strides.len() as u32;
3475        self
3476    }
3477
3478    #[inline]
3479    pub fn with_rasterized_stream(mut self, rasterized_stream: u32) -> Self {
3480        self.0.RasterizedStream = rasterized_stream;
3481        self
3482    }
3483}
3484
3485/// Describes subresource data.
3486///
3487/// For more information: [`D3D12_SUBRESOURCE_DATA structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_subresource_data)
3488#[derive(Clone, Copy, Debug, PartialEq)]
3489pub struct SubresourceData<'a, T>(
3490    pub(crate) D3D12_SUBRESOURCE_DATA,
3491    pub(crate) usize,
3492    PhantomData<&'a T>,
3493);
3494
3495impl<'a, T> SubresourceData<'a, T> {
3496    #[inline]
3497    pub fn new(data: &'a [T]) -> Self {
3498        Self(
3499            D3D12_SUBRESOURCE_DATA {
3500                pData: data.as_ptr() as *const _,
3501                RowPitch: size_of_val(data) as isize,
3502                SlicePitch: size_of_val(data) as isize,
3503            },
3504            data.len(),
3505            Default::default(),
3506        )
3507    }
3508
3509    #[inline]
3510    pub fn with_slice_pitch(mut self, slice_pitch: isize) -> Self {
3511        self.0.SlicePitch = slice_pitch;
3512        self
3513    }
3514
3515    #[inline]
3516    pub fn with_row_pitch(mut self, row_pitch: isize) -> Self {
3517        self.0.RowPitch = row_pitch;
3518        self
3519    }
3520
3521    #[inline]
3522    pub fn slice_pitch(&self) -> usize {
3523        self.0.SlicePitch as usize / size_of::<T>()
3524    }
3525
3526    #[inline]
3527    pub fn row_pitch(&self) -> usize {
3528        self.0.RowPitch as usize / size_of::<T>()
3529    }
3530
3531    #[inline]
3532    pub fn as_slice(&self) -> &'a [T] {
3533        unsafe { std::slice::from_raw_parts(self.0.pData as *const _, self.1) }
3534    }
3535}
3536
3537/// Describes the format, width, height, depth, and row-pitch of the subresource into the parent resource.
3538///
3539/// For more information: [`D3D12_SUBRESOURCE_FOOTPRINT structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_subresource_footprint)
3540#[derive(Clone, Copy, Debug, Default, PartialEq)]
3541#[repr(transparent)]
3542pub struct SubresourceFootprint(pub(crate) D3D12_SUBRESOURCE_FOOTPRINT);
3543
3544impl SubresourceFootprint {
3545    #[inline]
3546    pub fn with_format(mut self, format: Format) -> Self {
3547        self.0.Format = format.as_raw();
3548        self
3549    }
3550
3551    #[inline]
3552    pub fn with_width(mut self, width: u32) -> Self {
3553        self.0.Width = width;
3554        self
3555    }
3556
3557    #[inline]
3558    pub fn with_height(mut self, height: u32) -> Self {
3559        self.0.Height = height;
3560        self
3561    }
3562
3563    #[inline]
3564    pub fn with_depth(mut self, depth: u32) -> Self {
3565        self.0.Depth = depth;
3566        self
3567    }
3568
3569    #[inline]
3570    pub fn with_row_pitch(mut self, row_pitch: u32) -> Self {
3571        self.0.RowPitch = row_pitch;
3572        self
3573    }
3574
3575    #[inline]
3576    pub fn format(&self) -> Format {
3577        self.0.Format.into()
3578    }
3579
3580    #[inline]
3581    pub fn width(&self) -> u32 {
3582        self.0.Width
3583    }
3584
3585    #[inline]
3586    pub fn height(&self) -> u32 {
3587        self.0.Height
3588    }
3589
3590    #[inline]
3591    pub fn depth(&self) -> u32 {
3592        self.0.Depth
3593    }
3594
3595    #[inline]
3596    pub fn row_pitch(&self) -> u32 {
3597        self.0.RowPitch
3598    }
3599}
3600
3601/// Describes a tiled subresource volume.
3602///
3603/// For more information: [`D3D12_SUBRESOURCE_TILING structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_subresource_tiling)
3604#[derive(Clone, Copy, Debug, Default, PartialEq)]
3605#[repr(transparent)]
3606pub struct SubresourceTiling(pub(crate) D3D12_SUBRESOURCE_TILING);
3607
3608impl SubresourceTiling {
3609    #[inline]
3610    pub fn width(&self) -> u32 {
3611        self.0.WidthInTiles
3612    }
3613
3614    #[inline]
3615    pub fn height(&self) -> u16 {
3616        self.0.HeightInTiles
3617    }
3618
3619    #[inline]
3620    pub fn depth(&self) -> u16 {
3621        self.0.DepthInTiles
3622    }
3623
3624    #[inline]
3625    pub fn start_tile_index_in_overall_resource(&self) -> u32 {
3626        self.0.StartTileIndexInOverallResource
3627    }
3628}
3629
3630/// Describes a swap chain.
3631///
3632/// For more information: [`DXGI_SWAP_CHAIN_DESC1 structure`](https://learn.microsoft.com/en-us/windows/win32/api/dxgi1_2/ns-dxgi1_2-dxgi_swap_chain_desc1)
3633#[derive(Clone, Copy, Debug, PartialEq)]
3634#[repr(transparent)]
3635pub struct SwapchainDesc1(pub(crate) DXGI_SWAP_CHAIN_DESC1);
3636
3637impl SwapchainDesc1 {
3638    #[inline]
3639    pub fn new(width: u32, height: u32) -> Self {
3640        Self(DXGI_SWAP_CHAIN_DESC1 {
3641            Width: width,
3642            Height: height,
3643            SampleDesc: DXGI_SAMPLE_DESC {
3644                Count: 1,
3645                Quality: 0,
3646            },
3647            BufferUsage: DXGI_USAGE_RENDER_TARGET_OUTPUT,
3648            BufferCount: 1,
3649            AlphaMode: DXGI_ALPHA_MODE_UNSPECIFIED,
3650            ..Default::default()
3651        })
3652    }
3653
3654    #[inline]
3655    pub fn with_format(mut self, format: Format) -> Self {
3656        self.0.Format = format.as_raw();
3657        self
3658    }
3659
3660    #[inline]
3661    pub fn enable_stereo(mut self) -> Self {
3662        self.0.Stereo = true.into();
3663        self
3664    }
3665
3666    #[inline]
3667    pub fn with_sample_desc(mut self, sample_desc: SampleDesc) -> Self {
3668        self.0.SampleDesc = sample_desc.0;
3669        self
3670    }
3671
3672    #[inline]
3673    pub fn with_usage(mut self, usage: FrameBufferUsage) -> Self {
3674        self.0.BufferUsage = usage.as_raw();
3675        self
3676    }
3677
3678    #[inline]
3679    pub fn with_buffer_count(mut self, buffer_count: u32) -> Self {
3680        self.0.BufferCount = buffer_count;
3681        self
3682    }
3683
3684    #[inline]
3685    pub fn with_scaling(mut self, scaling: Scaling) -> Self {
3686        self.0.Scaling = scaling.as_raw();
3687        self
3688    }
3689
3690    #[inline]
3691    pub fn with_swap_effect(mut self, swap_effect: SwapEffect) -> Self {
3692        self.0.SwapEffect = swap_effect.as_raw();
3693        self
3694    }
3695
3696    #[inline]
3697    pub fn with_alpha_mode(mut self, alpha_mode: AlphaMode) -> Self {
3698        self.0.AlphaMode = alpha_mode.as_raw();
3699        self
3700    }
3701
3702    #[inline]
3703    pub fn with_flags(mut self, flags: SwapchainFlags) -> Self {
3704        self.0.Flags = flags.bits() as u32;
3705        self
3706    }
3707}
3708
3709/// Describes a swap chain.
3710///
3711/// For more information: [`DXGI_SWAP_CHAIN_FULLSCREEN_DESC structure`](https://learn.microsoft.com/en-us/windows/win32/api/dxgi1_2/ns-dxgi1_2-dxgi_swap_chain_fullscreen_desc)
3712#[derive(Clone, Copy, Debug, Default, PartialEq)]
3713#[repr(transparent)]
3714pub struct SwapchainFullscreenDesc(pub(crate) DXGI_SWAP_CHAIN_FULLSCREEN_DESC);
3715
3716impl SwapchainFullscreenDesc {
3717    #[inline]
3718    pub fn with_refresh_rate(mut self, refresh_rate: Rational) -> Self {
3719        self.0.RefreshRate = refresh_rate.0;
3720        self
3721    }
3722
3723    #[inline]
3724    pub fn with_scanline_ordering(mut self, scanline_ordering: ScanlineOrdering) -> Self {
3725        self.0.ScanlineOrdering = scanline_ordering.as_raw();
3726        self
3727    }
3728
3729    #[inline]
3730    pub fn with_scanline(mut self, scaling: ScalingMode) -> Self {
3731        self.0.Scaling = scaling.as_raw();
3732        self
3733    }
3734
3735    #[inline]
3736    pub fn windowed(mut self) -> Self {
3737        self.0.Windowed = true.into();
3738        self
3739    }
3740}
3741
3742/// Describes a portion of a texture for the purpose of texture copies.
3743///
3744/// For more information: [`D3D12_TEXTURE_COPY_LOCATION structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_texture_copy_location)
3745#[derive(Clone)]
3746#[repr(transparent)]
3747pub struct TextureCopyLocation<'a>(pub(crate) D3D12_TEXTURE_COPY_LOCATION, PhantomData<&'a ()>);
3748
3749impl<'a> TextureCopyLocation<'a> {
3750    #[inline]
3751    pub fn subresource(resource: impl AsRef<Resource>, index: u32) -> Self {
3752        Self(
3753            D3D12_TEXTURE_COPY_LOCATION {
3754                pResource: unsafe { std::mem::transmute_copy(&resource.as_ref().0) },
3755                Type: D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
3756                Anonymous: D3D12_TEXTURE_COPY_LOCATION_0 {
3757                    SubresourceIndex: index,
3758                },
3759            },
3760            Default::default(),
3761        )
3762    }
3763
3764    #[inline]
3765    pub fn placed_footprint(
3766        resource: impl AsRef<Resource>,
3767        footprint: PlacedSubresourceFootprint,
3768    ) -> Self {
3769        Self(
3770            D3D12_TEXTURE_COPY_LOCATION {
3771                pResource: unsafe { std::mem::transmute_copy(&resource.as_ref().0) },
3772                Type: D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT,
3773                Anonymous: D3D12_TEXTURE_COPY_LOCATION_0 {
3774                    PlacedFootprint: footprint.0,
3775                },
3776            },
3777            Default::default(),
3778        )
3779    }
3780}
3781
3782/// Describes the size of a tiled region.
3783///
3784/// For more information: [`D3D12_TILE_REGION_SIZE structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_tile_region_size)
3785#[derive(Clone, Copy, Debug, Default, PartialEq)]
3786#[repr(transparent)]
3787pub struct TileRegionSize(pub(crate) D3D12_TILE_REGION_SIZE);
3788
3789impl TileRegionSize {
3790    #[inline]
3791    pub fn with_tiles(mut self, num_tiles: u32) -> Self {
3792        self.0.NumTiles = num_tiles;
3793        self
3794    }
3795
3796    #[inline]
3797    pub fn with_width(mut self, width: u32) -> Self {
3798        self.0.Width = width;
3799        self
3800    }
3801
3802    #[inline]
3803    pub fn with_height(mut self, height: u16) -> Self {
3804        self.0.Height = height;
3805        self
3806    }
3807
3808    #[inline]
3809    pub fn with_depth(mut self, depth: u16) -> Self {
3810        self.0.Depth = depth;
3811        self
3812    }
3813
3814    #[inline]
3815    pub fn use_box(mut self) -> Self {
3816        self.0.UseBox = true.into();
3817        self
3818    }
3819}
3820
3821/// Describes the shape of a tile by specifying its dimensions.
3822///
3823/// For more information: [`D3D12_TILE_SHAPE structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_tile_shape)
3824#[derive(Clone, Copy, Debug, PartialEq)]
3825#[repr(transparent)]
3826pub struct TileShape(pub(crate) D3D12_TILE_SHAPE);
3827
3828impl TileShape {
3829    #[inline]
3830    pub fn width(&self) -> u32 {
3831        self.0.WidthInTexels
3832    }
3833
3834    #[inline]
3835    pub fn height(&self) -> u32 {
3836        self.0.HeightInTexels
3837    }
3838
3839    #[inline]
3840    pub fn depth(&self) -> u32 {
3841        self.0.DepthInTexels
3842    }
3843}
3844
3845/// Describes the coordinates of a tiled resource.
3846///
3847/// For more information: [`D3D12_TILED_RESOURCE_COORDINATE structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_tiled_resource_coordinate)
3848#[derive(Clone, Copy, Debug, PartialEq)]
3849#[repr(transparent)]
3850pub struct TiledResourceCoordinate(pub(crate) D3D12_TILED_RESOURCE_COORDINATE);
3851
3852impl TiledResourceCoordinate {
3853    #[inline]
3854    pub fn new(x: u32, y: u32, z: u32, subresource: u32) -> Self {
3855        Self(D3D12_TILED_RESOURCE_COORDINATE {
3856            X: x,
3857            Y: y,
3858            Z: z,
3859            Subresource: subresource,
3860        })
3861    }
3862}
3863
3864/// Describes the subresources from a resource that are accessible by using an unordered-access view.
3865///
3866/// For more information: [`D3D12_UNORDERED_ACCESS_VIEW_DESC structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_unordered_access_view_desc)
3867#[derive(Clone, Copy)]
3868#[repr(transparent)]
3869pub struct UnorderedAccessViewDesc(pub(crate) D3D12_UNORDERED_ACCESS_VIEW_DESC);
3870impl UnorderedAccessViewDesc {
3871    #[inline]
3872    pub fn buffer(
3873        format: Format,
3874        elements: Range<u64>,
3875        structure_byte_stride: u32,
3876        counter_offset: u64,
3877        flags: BufferUavFlags,
3878    ) -> Self {
3879        Self(D3D12_UNORDERED_ACCESS_VIEW_DESC {
3880            Format: format.as_raw(),
3881            ViewDimension: D3D12_UAV_DIMENSION_BUFFER,
3882            Anonymous: D3D12_UNORDERED_ACCESS_VIEW_DESC_0 {
3883                Buffer: D3D12_BUFFER_UAV {
3884                    FirstElement: elements.start,
3885                    NumElements: elements.count() as u32,
3886                    StructureByteStride: structure_byte_stride,
3887                    CounterOffsetInBytes: counter_offset,
3888                    Flags: flags.as_raw(),
3889                },
3890            },
3891        })
3892    }
3893
3894    #[inline]
3895    pub fn texture_1d(format: Format, mip_slice: u32) -> Self {
3896        Self(D3D12_UNORDERED_ACCESS_VIEW_DESC {
3897            Format: format.as_raw(),
3898            ViewDimension: D3D12_UAV_DIMENSION_TEXTURE1D,
3899            Anonymous: D3D12_UNORDERED_ACCESS_VIEW_DESC_0 {
3900                Texture1D: D3D12_TEX1D_UAV {
3901                    MipSlice: mip_slice,
3902                },
3903            },
3904        })
3905    }
3906
3907    #[inline]
3908    pub fn texture_2d(format: Format, mip_slice: u32, plane_slice: u32) -> Self {
3909        Self(D3D12_UNORDERED_ACCESS_VIEW_DESC {
3910            Format: format.as_raw(),
3911            ViewDimension: D3D12_UAV_DIMENSION_TEXTURE2D,
3912            Anonymous: D3D12_UNORDERED_ACCESS_VIEW_DESC_0 {
3913                Texture2D: D3D12_TEX2D_UAV {
3914                    MipSlice: mip_slice,
3915                    PlaneSlice: plane_slice,
3916                },
3917            },
3918        })
3919    }
3920
3921    #[inline]
3922    pub fn texture_3d(format: Format, mip_slice: u32, slices: Range<u32>) -> Self {
3923        Self(D3D12_UNORDERED_ACCESS_VIEW_DESC {
3924            Format: format.as_raw(),
3925            ViewDimension: D3D12_UAV_DIMENSION_TEXTURE3D,
3926            Anonymous: D3D12_UNORDERED_ACCESS_VIEW_DESC_0 {
3927                Texture3D: D3D12_TEX3D_UAV {
3928                    MipSlice: mip_slice,
3929                    FirstWSlice: slices.start,
3930                    WSize: slices.count() as u32,
3931                },
3932            },
3933        })
3934    }
3935
3936    #[inline]
3937    pub fn texture_1d_array(format: Format, mip_slice: u32, array: Range<u32>) -> Self {
3938        Self(D3D12_UNORDERED_ACCESS_VIEW_DESC {
3939            Format: format.as_raw(),
3940            ViewDimension: D3D12_UAV_DIMENSION_TEXTURE1DARRAY,
3941            Anonymous: D3D12_UNORDERED_ACCESS_VIEW_DESC_0 {
3942                Texture1DArray: D3D12_TEX1D_ARRAY_UAV {
3943                    MipSlice: mip_slice,
3944                    FirstArraySlice: array.start,
3945                    ArraySize: array.count() as u32,
3946                },
3947            },
3948        })
3949    }
3950
3951    #[inline]
3952    pub fn texture_2d_array(
3953        format: Format,
3954        mip_slice: u32,
3955        plane_slice: u32,
3956        array: Range<u32>,
3957    ) -> Self {
3958        Self(D3D12_UNORDERED_ACCESS_VIEW_DESC {
3959            Format: format.as_raw(),
3960            ViewDimension: D3D12_UAV_DIMENSION_TEXTURE2DARRAY,
3961            Anonymous: D3D12_UNORDERED_ACCESS_VIEW_DESC_0 {
3962                Texture2DArray: D3D12_TEX2D_ARRAY_UAV {
3963                    MipSlice: mip_slice,
3964                    PlaneSlice: plane_slice,
3965                    FirstArraySlice: array.start,
3966                    ArraySize: array.count() as u32,
3967                },
3968            },
3969        })
3970    }
3971
3972    #[inline]
3973    pub fn texture_2d_ms(format: Format) -> Self {
3974        Self(D3D12_UNORDERED_ACCESS_VIEW_DESC {
3975            Format: format.as_raw(),
3976            ViewDimension: D3D12_UAV_DIMENSION_TEXTURE2DMS,
3977            Anonymous: D3D12_UNORDERED_ACCESS_VIEW_DESC_0 {
3978                Texture2DMS: D3D12_TEX2DMS_UAV::default(),
3979            },
3980        })
3981    }
3982
3983    #[inline]
3984    pub fn texture_2d_ms_array(format: Format, array: Range<u32>) -> Self {
3985        Self(D3D12_UNORDERED_ACCESS_VIEW_DESC {
3986            Format: format.as_raw(),
3987            ViewDimension: D3D12_UAV_DIMENSION_TEXTURE2DMSARRAY,
3988            Anonymous: D3D12_UNORDERED_ACCESS_VIEW_DESC_0 {
3989                Texture2DMSArray: D3D12_TEX2DMS_ARRAY_UAV {
3990                    FirstArraySlice: array.start,
3991                    ArraySize: array.count() as u32,
3992                },
3993            },
3994        })
3995    }
3996}
3997
3998/// Describes a vertex buffer view.
3999///
4000/// For more information: [`D3D12_VERTEX_BUFFER_VIEW structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_vertex_buffer_view)
4001#[derive(Clone, Copy, Debug, PartialEq)]
4002#[repr(transparent)]
4003pub struct VertexBufferView(pub(crate) D3D12_VERTEX_BUFFER_VIEW);
4004
4005impl VertexBufferView {
4006    #[inline]
4007    pub fn new(buffer_location: GpuVirtualAddress, stride: u32, size: u32) -> Self {
4008        Self(D3D12_VERTEX_BUFFER_VIEW {
4009            BufferLocation: buffer_location,
4010            StrideInBytes: stride,
4011            SizeInBytes: size,
4012        })
4013    }
4014}
4015
4016/// Describes the dimensions of a viewport.
4017///
4018/// For more information: [`D3D12_VIEWPORT structure`](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_viewport)
4019#[derive(Clone, Copy, Debug, Default, PartialEq)]
4020pub struct Viewport(pub(crate) D3D12_VIEWPORT);
4021
4022impl Viewport {
4023    /// Creates a viewport with a minimum depth of 0 and a maximum depth of 1.
4024    #[inline]
4025    pub fn from_position_and_size(
4026        position: impl Into<(f32, f32)>,
4027        size: impl Into<(f32, f32)>,
4028    ) -> Self {
4029        let (width, height) = size.into();
4030        let (x, y) = position.into();
4031
4032        Self(D3D12_VIEWPORT {
4033            TopLeftX: x,
4034            TopLeftY: y,
4035            Width: width,
4036            Height: height,
4037            MinDepth: MIN_DEPTH,
4038            MaxDepth: MAX_DEPTH,
4039        })
4040    }
4041
4042    /// Creates a viewport with a minimum depth of 0 and a maximum depth of 1 and with position in (0, 0).
4043    #[inline]
4044    pub fn from_size(size: impl Into<(f32, f32)>) -> Self {
4045        Self::from_position_and_size((0.0, 0.0), size)
4046    }
4047}