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#[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#[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#[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#[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#[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#[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#[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#[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#[derive(Clone, Copy, Debug, Default, PartialEq)]
394#[repr(transparent)]
395pub struct CpuDescriptorHandle(pub(crate) D3D12_CPU_DESCRIPTOR_HANDLE);
396
397impl CpuDescriptorHandle {
398 #[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#[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#[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#[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#[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#[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#[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#[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#[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#[derive(Clone, Copy, Debug, Default, PartialEq)]
845#[repr(transparent)]
846pub struct GpuDescriptorHandle(pub(crate) D3D12_GPU_DESCRIPTOR_HANDLE);
847
848impl GpuDescriptorHandle {
849 #[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[derive(Clone, Copy, Debug, Default, PartialEq)]
1888pub struct Rect(pub(crate) RECT);
1889
1890impl Rect {
1891 #[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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 #[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[derive(Clone, Copy, Debug, Default, PartialEq)]
4020pub struct Viewport(pub(crate) D3D12_VIEWPORT);
4021
4022impl Viewport {
4023 #[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 #[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}