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