1 //! Graphics command list
2 
3 use com::WeakPtr;
4 use resource::DiscardRegion;
5 use std::{mem, ptr};
6 use winapi::um::d3d12;
7 use {
8     CommandAllocator, CpuDescriptor, DescriptorHeap, Format, GpuAddress, GpuDescriptor, IndexCount,
9     InstanceCount, PipelineState, Rect, Resource, RootSignature, VertexCount, VertexOffset,
10     WorkGroupCount, HRESULT,
11 };
12 
13 #[repr(u32)]
14 #[derive(Clone, Copy)]
15 pub enum CmdListType {
16     Direct = d3d12::D3D12_COMMAND_LIST_TYPE_DIRECT,
17     Bundle = d3d12::D3D12_COMMAND_LIST_TYPE_BUNDLE,
18     Compute = d3d12::D3D12_COMMAND_LIST_TYPE_COMPUTE,
19     Copy = d3d12::D3D12_COMMAND_LIST_TYPE_COPY,
20     // VideoDecode = d3d12::D3D12_COMMAND_LIST_TYPE_VIDEO_DECODE,
21     // VideoProcess = d3d12::D3D12_COMMAND_LIST_TYPE_VIDEO_PROCESS,
22 }
23 
24 bitflags! {
25     pub struct ClearFlags: u32 {
26         const DEPTH = d3d12::D3D12_CLEAR_FLAG_DEPTH;
27         const STENCIL = d3d12::D3D12_CLEAR_FLAG_STENCIL;
28     }
29 }
30 
31 #[repr(transparent)]
32 pub struct IndirectArgument(d3d12::D3D12_INDIRECT_ARGUMENT_DESC);
33 
34 impl IndirectArgument {
draw() -> Self35     pub fn draw() -> Self {
36         IndirectArgument(d3d12::D3D12_INDIRECT_ARGUMENT_DESC {
37             Type: d3d12::D3D12_INDIRECT_ARGUMENT_TYPE_DRAW,
38             ..unsafe { mem::zeroed() }
39         })
40     }
41 
draw_indexed() -> Self42     pub fn draw_indexed() -> Self {
43         IndirectArgument(d3d12::D3D12_INDIRECT_ARGUMENT_DESC {
44             Type: d3d12::D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED,
45             ..unsafe { mem::zeroed() }
46         })
47     }
48 
dispatch() -> Self49     pub fn dispatch() -> Self {
50         IndirectArgument(d3d12::D3D12_INDIRECT_ARGUMENT_DESC {
51             Type: d3d12::D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH,
52             ..unsafe { mem::zeroed() }
53         })
54     }
55 
56     // TODO: missing variants
57 }
58 
59 #[repr(transparent)]
60 pub struct ResourceBarrier(d3d12::D3D12_RESOURCE_BARRIER);
61 
62 impl ResourceBarrier {
transition( resource: Resource, subresource: u32, state_before: d3d12::D3D12_RESOURCE_STATES, state_after: d3d12::D3D12_RESOURCE_STATES, flags: d3d12::D3D12_RESOURCE_BARRIER_FLAGS, ) -> Self63     pub fn transition(
64         resource: Resource,
65         subresource: u32,
66         state_before: d3d12::D3D12_RESOURCE_STATES,
67         state_after: d3d12::D3D12_RESOURCE_STATES,
68         flags: d3d12::D3D12_RESOURCE_BARRIER_FLAGS,
69     ) -> Self {
70         let mut barrier = d3d12::D3D12_RESOURCE_BARRIER {
71             Type: d3d12::D3D12_RESOURCE_BARRIER_TYPE_TRANSITION,
72             Flags: flags,
73             ..unsafe { mem::zeroed() }
74         };
75         unsafe {
76             *barrier.u.Transition_mut() = d3d12::D3D12_RESOURCE_TRANSITION_BARRIER {
77                 pResource: resource.as_mut_ptr(),
78                 Subresource: subresource,
79                 StateBefore: state_before,
80                 StateAfter: state_after,
81             };
82         }
83         ResourceBarrier(barrier)
84     }
85 }
86 
87 pub type CommandSignature = WeakPtr<d3d12::ID3D12CommandSignature>;
88 pub type CommandList = WeakPtr<d3d12::ID3D12CommandList>;
89 pub type GraphicsCommandList = WeakPtr<d3d12::ID3D12GraphicsCommandList>;
90 
91 impl GraphicsCommandList {
as_list(&self) -> CommandList92     pub fn as_list(&self) -> CommandList {
93         unsafe { CommandList::from_raw(self.as_mut_ptr() as *mut _) }
94     }
95 
close(&self) -> HRESULT96     pub fn close(&self) -> HRESULT {
97         unsafe { self.Close() }
98     }
99 
reset(&self, allocator: CommandAllocator, initial_pso: PipelineState) -> HRESULT100     pub fn reset(&self, allocator: CommandAllocator, initial_pso: PipelineState) -> HRESULT {
101         unsafe { self.Reset(allocator.as_mut_ptr(), initial_pso.as_mut_ptr()) }
102     }
103 
discard_resource(&self, resource: Resource, region: DiscardRegion)104     pub fn discard_resource(&self, resource: Resource, region: DiscardRegion) {
105         debug_assert!(region.subregions.start < region.subregions.end);
106         unsafe {
107             self.DiscardResource(
108                 resource.as_mut_ptr(),
109                 &d3d12::D3D12_DISCARD_REGION {
110                     NumRects: region.rects.len() as _,
111                     pRects: region.rects.as_ptr(),
112                     FirstSubresource: region.subregions.start,
113                     NumSubresources: region.subregions.end - region.subregions.start - 1,
114                 },
115             );
116         }
117     }
118 
clear_depth_stencil_view( &self, dsv: CpuDescriptor, flags: ClearFlags, depth: f32, stencil: u8, rects: &[Rect], )119     pub fn clear_depth_stencil_view(
120         &self,
121         dsv: CpuDescriptor,
122         flags: ClearFlags,
123         depth: f32,
124         stencil: u8,
125         rects: &[Rect],
126     ) {
127         let num_rects = rects.len() as _;
128         let rects = if num_rects > 0 {
129             rects.as_ptr()
130         } else {
131             ptr::null()
132         };
133         unsafe {
134             self.ClearDepthStencilView(dsv, flags.bits(), depth, stencil, num_rects, rects);
135         }
136     }
137 
clear_render_target_view(&self, rtv: CpuDescriptor, color: [f32; 4], rects: &[Rect])138     pub fn clear_render_target_view(&self, rtv: CpuDescriptor, color: [f32; 4], rects: &[Rect]) {
139         let num_rects = rects.len() as _;
140         let rects = if num_rects > 0 {
141             rects.as_ptr()
142         } else {
143             ptr::null()
144         };
145         unsafe {
146             self.ClearRenderTargetView(rtv, &color, num_rects, rects);
147         }
148     }
149 
dispatch(&self, count: WorkGroupCount)150     pub fn dispatch(&self, count: WorkGroupCount) {
151         unsafe {
152             self.Dispatch(count[0], count[1], count[2]);
153         }
154     }
155 
draw( &self, num_vertices: VertexCount, num_instances: InstanceCount, start_vertex: VertexCount, start_instance: InstanceCount, )156     pub fn draw(
157         &self,
158         num_vertices: VertexCount,
159         num_instances: InstanceCount,
160         start_vertex: VertexCount,
161         start_instance: InstanceCount,
162     ) {
163         unsafe {
164             self.DrawInstanced(num_vertices, num_instances, start_vertex, start_instance);
165         }
166     }
167 
draw_indexed( &self, num_indices: IndexCount, num_instances: InstanceCount, start_index: IndexCount, base_vertex: VertexOffset, start_instance: InstanceCount, )168     pub fn draw_indexed(
169         &self,
170         num_indices: IndexCount,
171         num_instances: InstanceCount,
172         start_index: IndexCount,
173         base_vertex: VertexOffset,
174         start_instance: InstanceCount,
175     ) {
176         unsafe {
177             self.DrawIndexedInstanced(
178                 num_indices,
179                 num_instances,
180                 start_index,
181                 base_vertex,
182                 start_instance,
183             );
184         }
185     }
186 
set_index_buffer(&self, gpu_address: GpuAddress, size: u32, format: Format)187     pub fn set_index_buffer(&self, gpu_address: GpuAddress, size: u32, format: Format) {
188         let mut ibv = d3d12::D3D12_INDEX_BUFFER_VIEW {
189             BufferLocation: gpu_address,
190             SizeInBytes: size,
191             Format: format,
192         };
193         unsafe {
194             self.IASetIndexBuffer(&mut ibv);
195         }
196     }
197 
set_blend_factor(&self, factor: [f32; 4])198     pub fn set_blend_factor(&self, factor: [f32; 4]) {
199         unsafe {
200             self.OMSetBlendFactor(&factor);
201         }
202     }
203 
set_stencil_reference(&self, reference: u32)204     pub fn set_stencil_reference(&self, reference: u32) {
205         unsafe {
206             self.OMSetStencilRef(reference);
207         }
208     }
209 
set_pipeline_state(&self, pso: PipelineState)210     pub fn set_pipeline_state(&self, pso: PipelineState) {
211         unsafe {
212             self.SetPipelineState(pso.as_mut_ptr());
213         }
214     }
215 
execute_bundle(&self, bundle: GraphicsCommandList)216     pub fn execute_bundle(&self, bundle: GraphicsCommandList) {
217         unsafe {
218             self.ExecuteBundle(bundle.as_mut_ptr());
219         }
220     }
221 
set_descriptor_heaps(&self, heaps: &[DescriptorHeap])222     pub fn set_descriptor_heaps(&self, heaps: &[DescriptorHeap]) {
223         unsafe {
224             self.SetDescriptorHeaps(
225                 heaps.len() as _,
226                 heaps.as_ptr() as *mut &DescriptorHeap as *mut _,
227             );
228         }
229     }
230 
set_compute_root_signature(&self, signature: RootSignature)231     pub fn set_compute_root_signature(&self, signature: RootSignature) {
232         unsafe {
233             self.SetComputeRootSignature(signature.as_mut_ptr());
234         }
235     }
236 
set_graphics_root_signature(&self, signature: RootSignature)237     pub fn set_graphics_root_signature(&self, signature: RootSignature) {
238         unsafe {
239             self.SetGraphicsRootSignature(signature.as_mut_ptr());
240         }
241     }
242 
set_compute_root_descriptor_table( &self, root_index: u32, base_descriptor: GpuDescriptor, )243     pub fn set_compute_root_descriptor_table(
244         &self,
245         root_index: u32,
246         base_descriptor: GpuDescriptor,
247     ) {
248         unsafe {
249             self.SetComputeRootDescriptorTable(root_index, base_descriptor);
250         }
251     }
252 
set_compute_root_constant_buffer_view( &self, root_index: u32, buffer_location: GpuAddress, )253     pub fn set_compute_root_constant_buffer_view(
254         &self,
255         root_index: u32,
256         buffer_location: GpuAddress,
257     ) {
258         unsafe {
259             self.SetComputeRootConstantBufferView(root_index, buffer_location);
260         }
261     }
262 
set_compute_root_shader_resource_view( &self, root_index: u32, buffer_location: GpuAddress, )263     pub fn set_compute_root_shader_resource_view(
264         &self,
265         root_index: u32,
266         buffer_location: GpuAddress,
267     ) {
268         unsafe {
269             self.SetComputeRootShaderResourceView(root_index, buffer_location);
270         }
271     }
272 
set_compute_root_unordered_access_view( &self, root_index: u32, buffer_location: GpuAddress, )273     pub fn set_compute_root_unordered_access_view(
274         &self,
275         root_index: u32,
276         buffer_location: GpuAddress,
277     ) {
278         unsafe {
279             self.SetComputeRootUnorderedAccessView(root_index, buffer_location);
280         }
281     }
282 
set_graphics_root_descriptor_table( &self, root_index: u32, base_descriptor: GpuDescriptor, )283     pub fn set_graphics_root_descriptor_table(
284         &self,
285         root_index: u32,
286         base_descriptor: GpuDescriptor,
287     ) {
288         unsafe {
289             self.SetGraphicsRootDescriptorTable(root_index, base_descriptor);
290         }
291     }
292 
set_graphics_root_constant_buffer_view( &self, root_index: u32, buffer_location: GpuAddress, )293     pub fn set_graphics_root_constant_buffer_view(
294         &self,
295         root_index: u32,
296         buffer_location: GpuAddress,
297     ) {
298         unsafe {
299             self.SetGraphicsRootConstantBufferView(root_index, buffer_location);
300         }
301     }
302 
set_graphics_root_shader_resource_view( &self, root_index: u32, buffer_location: GpuAddress, )303     pub fn set_graphics_root_shader_resource_view(
304         &self,
305         root_index: u32,
306         buffer_location: GpuAddress,
307     ) {
308         unsafe {
309             self.SetGraphicsRootShaderResourceView(root_index, buffer_location);
310         }
311     }
312 
set_graphics_root_unordered_access_view( &self, root_index: u32, buffer_location: GpuAddress, )313     pub fn set_graphics_root_unordered_access_view(
314         &self,
315         root_index: u32,
316         buffer_location: GpuAddress,
317     ) {
318         unsafe {
319             self.SetGraphicsRootUnorderedAccessView(root_index, buffer_location);
320         }
321     }
322 
resource_barrier(&self, barriers: &[ResourceBarrier])323     pub fn resource_barrier(&self, barriers: &[ResourceBarrier]) {
324         unsafe {
325             self.ResourceBarrier(barriers.len() as _, barriers.as_ptr() as _) // matches representation
326         }
327     }
328 }
329