1 //! Graphics command list 2 3 use crate::{ 4 com::WeakPtr, resource::DiscardRegion, CommandAllocator, CpuDescriptor, DescriptorHeap, Format, 5 GpuAddress, GpuDescriptor, IndexCount, InstanceCount, PipelineState, Rect, Resource, RootIndex, 6 RootSignature, Subresource, VertexCount, VertexOffset, WorkGroupCount, HRESULT, 7 }; 8 use std::{mem, ptr}; 9 use winapi::um::d3d12; 10 11 #[repr(u32)] 12 #[derive(Clone, Copy)] 13 pub enum CmdListType { 14 Direct = d3d12::D3D12_COMMAND_LIST_TYPE_DIRECT, 15 Bundle = d3d12::D3D12_COMMAND_LIST_TYPE_BUNDLE, 16 Compute = d3d12::D3D12_COMMAND_LIST_TYPE_COMPUTE, 17 Copy = d3d12::D3D12_COMMAND_LIST_TYPE_COPY, 18 // VideoDecode = d3d12::D3D12_COMMAND_LIST_TYPE_VIDEO_DECODE, 19 // VideoProcess = d3d12::D3D12_COMMAND_LIST_TYPE_VIDEO_PROCESS, 20 } 21 22 bitflags! { 23 pub struct ClearFlags: u32 { 24 const DEPTH = d3d12::D3D12_CLEAR_FLAG_DEPTH; 25 const STENCIL = d3d12::D3D12_CLEAR_FLAG_STENCIL; 26 } 27 } 28 29 #[repr(transparent)] 30 pub struct IndirectArgument(d3d12::D3D12_INDIRECT_ARGUMENT_DESC); 31 32 impl IndirectArgument { draw() -> Self33 pub fn draw() -> Self { 34 IndirectArgument(d3d12::D3D12_INDIRECT_ARGUMENT_DESC { 35 Type: d3d12::D3D12_INDIRECT_ARGUMENT_TYPE_DRAW, 36 ..unsafe { mem::zeroed() } 37 }) 38 } 39 draw_indexed() -> Self40 pub fn draw_indexed() -> Self { 41 IndirectArgument(d3d12::D3D12_INDIRECT_ARGUMENT_DESC { 42 Type: d3d12::D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED, 43 ..unsafe { mem::zeroed() } 44 }) 45 } 46 dispatch() -> Self47 pub fn dispatch() -> Self { 48 IndirectArgument(d3d12::D3D12_INDIRECT_ARGUMENT_DESC { 49 Type: d3d12::D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH, 50 ..unsafe { mem::zeroed() } 51 }) 52 } 53 vertex_buffer(slot: u32) -> Self54 pub fn vertex_buffer(slot: u32) -> Self { 55 let mut desc = d3d12::D3D12_INDIRECT_ARGUMENT_DESC { 56 Type: d3d12::D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW, 57 ..unsafe { mem::zeroed() } 58 }; 59 *unsafe { desc.u.VertexBuffer_mut() } = 60 d3d12::D3D12_INDIRECT_ARGUMENT_DESC_VertexBuffer { Slot: slot }; 61 IndirectArgument(desc) 62 } 63 constant(root_index: RootIndex, dest_offset_words: u32, count: u32) -> Self64 pub fn constant(root_index: RootIndex, dest_offset_words: u32, count: u32) -> Self { 65 let mut desc = d3d12::D3D12_INDIRECT_ARGUMENT_DESC { 66 Type: d3d12::D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT, 67 ..unsafe { mem::zeroed() } 68 }; 69 *unsafe { desc.u.Constant_mut() } = d3d12::D3D12_INDIRECT_ARGUMENT_DESC_Constant { 70 RootParameterIndex: root_index, 71 DestOffsetIn32BitValues: dest_offset_words, 72 Num32BitValuesToSet: count, 73 }; 74 IndirectArgument(desc) 75 } 76 constant_buffer_view(root_index: RootIndex) -> Self77 pub fn constant_buffer_view(root_index: RootIndex) -> Self { 78 let mut desc = d3d12::D3D12_INDIRECT_ARGUMENT_DESC { 79 Type: d3d12::D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT_BUFFER_VIEW, 80 ..unsafe { mem::zeroed() } 81 }; 82 *unsafe { desc.u.ConstantBufferView_mut() } = 83 d3d12::D3D12_INDIRECT_ARGUMENT_DESC_ConstantBufferView { 84 RootParameterIndex: root_index, 85 }; 86 IndirectArgument(desc) 87 } 88 shader_resource_view(root_index: RootIndex) -> Self89 pub fn shader_resource_view(root_index: RootIndex) -> Self { 90 let mut desc = d3d12::D3D12_INDIRECT_ARGUMENT_DESC { 91 Type: d3d12::D3D12_INDIRECT_ARGUMENT_TYPE_SHADER_RESOURCE_VIEW, 92 ..unsafe { mem::zeroed() } 93 }; 94 *unsafe { desc.u.ShaderResourceView_mut() } = 95 d3d12::D3D12_INDIRECT_ARGUMENT_DESC_ShaderResourceView { 96 RootParameterIndex: root_index, 97 }; 98 IndirectArgument(desc) 99 } 100 unordered_access_view(root_index: RootIndex) -> Self101 pub fn unordered_access_view(root_index: RootIndex) -> Self { 102 let mut desc = d3d12::D3D12_INDIRECT_ARGUMENT_DESC { 103 Type: d3d12::D3D12_INDIRECT_ARGUMENT_TYPE_UNORDERED_ACCESS_VIEW, 104 ..unsafe { mem::zeroed() } 105 }; 106 *unsafe { desc.u.UnorderedAccessView_mut() } = 107 d3d12::D3D12_INDIRECT_ARGUMENT_DESC_UnorderedAccessView { 108 RootParameterIndex: root_index, 109 }; 110 IndirectArgument(desc) 111 } 112 } 113 114 #[repr(transparent)] 115 pub struct ResourceBarrier(d3d12::D3D12_RESOURCE_BARRIER); 116 117 impl ResourceBarrier { transition( resource: Resource, subresource: Subresource, state_before: d3d12::D3D12_RESOURCE_STATES, state_after: d3d12::D3D12_RESOURCE_STATES, flags: d3d12::D3D12_RESOURCE_BARRIER_FLAGS, ) -> Self118 pub fn transition( 119 resource: Resource, 120 subresource: Subresource, 121 state_before: d3d12::D3D12_RESOURCE_STATES, 122 state_after: d3d12::D3D12_RESOURCE_STATES, 123 flags: d3d12::D3D12_RESOURCE_BARRIER_FLAGS, 124 ) -> Self { 125 let mut barrier = d3d12::D3D12_RESOURCE_BARRIER { 126 Type: d3d12::D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, 127 Flags: flags, 128 ..unsafe { mem::zeroed() } 129 }; 130 unsafe { 131 *barrier.u.Transition_mut() = d3d12::D3D12_RESOURCE_TRANSITION_BARRIER { 132 pResource: resource.as_mut_ptr(), 133 Subresource: subresource, 134 StateBefore: state_before, 135 StateAfter: state_after, 136 }; 137 } 138 ResourceBarrier(barrier) 139 } 140 } 141 142 pub type CommandSignature = WeakPtr<d3d12::ID3D12CommandSignature>; 143 pub type CommandList = WeakPtr<d3d12::ID3D12CommandList>; 144 pub type GraphicsCommandList = WeakPtr<d3d12::ID3D12GraphicsCommandList>; 145 146 impl GraphicsCommandList { as_list(&self) -> CommandList147 pub fn as_list(&self) -> CommandList { 148 unsafe { CommandList::from_raw(self.as_mut_ptr() as *mut _) } 149 } 150 close(&self) -> HRESULT151 pub fn close(&self) -> HRESULT { 152 unsafe { self.Close() } 153 } 154 reset(&self, allocator: CommandAllocator, initial_pso: PipelineState) -> HRESULT155 pub fn reset(&self, allocator: CommandAllocator, initial_pso: PipelineState) -> HRESULT { 156 unsafe { self.Reset(allocator.as_mut_ptr(), initial_pso.as_mut_ptr()) } 157 } 158 discard_resource(&self, resource: Resource, region: DiscardRegion)159 pub fn discard_resource(&self, resource: Resource, region: DiscardRegion) { 160 debug_assert!(region.subregions.start < region.subregions.end); 161 unsafe { 162 self.DiscardResource( 163 resource.as_mut_ptr(), 164 &d3d12::D3D12_DISCARD_REGION { 165 NumRects: region.rects.len() as _, 166 pRects: region.rects.as_ptr(), 167 FirstSubresource: region.subregions.start, 168 NumSubresources: region.subregions.end - region.subregions.start - 1, 169 }, 170 ); 171 } 172 } 173 clear_depth_stencil_view( &self, dsv: CpuDescriptor, flags: ClearFlags, depth: f32, stencil: u8, rects: &[Rect], )174 pub fn clear_depth_stencil_view( 175 &self, 176 dsv: CpuDescriptor, 177 flags: ClearFlags, 178 depth: f32, 179 stencil: u8, 180 rects: &[Rect], 181 ) { 182 let num_rects = rects.len() as _; 183 let rects = if num_rects > 0 { 184 rects.as_ptr() 185 } else { 186 ptr::null() 187 }; 188 unsafe { 189 self.ClearDepthStencilView(dsv, flags.bits(), depth, stencil, num_rects, rects); 190 } 191 } 192 clear_render_target_view(&self, rtv: CpuDescriptor, color: [f32; 4], rects: &[Rect])193 pub fn clear_render_target_view(&self, rtv: CpuDescriptor, color: [f32; 4], rects: &[Rect]) { 194 let num_rects = rects.len() as _; 195 let rects = if num_rects > 0 { 196 rects.as_ptr() 197 } else { 198 ptr::null() 199 }; 200 unsafe { 201 self.ClearRenderTargetView(rtv, &color, num_rects, rects); 202 } 203 } 204 dispatch(&self, count: WorkGroupCount)205 pub fn dispatch(&self, count: WorkGroupCount) { 206 unsafe { 207 self.Dispatch(count[0], count[1], count[2]); 208 } 209 } 210 draw( &self, num_vertices: VertexCount, num_instances: InstanceCount, start_vertex: VertexCount, start_instance: InstanceCount, )211 pub fn draw( 212 &self, 213 num_vertices: VertexCount, 214 num_instances: InstanceCount, 215 start_vertex: VertexCount, 216 start_instance: InstanceCount, 217 ) { 218 unsafe { 219 self.DrawInstanced(num_vertices, num_instances, start_vertex, start_instance); 220 } 221 } 222 draw_indexed( &self, num_indices: IndexCount, num_instances: InstanceCount, start_index: IndexCount, base_vertex: VertexOffset, start_instance: InstanceCount, )223 pub fn draw_indexed( 224 &self, 225 num_indices: IndexCount, 226 num_instances: InstanceCount, 227 start_index: IndexCount, 228 base_vertex: VertexOffset, 229 start_instance: InstanceCount, 230 ) { 231 unsafe { 232 self.DrawIndexedInstanced( 233 num_indices, 234 num_instances, 235 start_index, 236 base_vertex, 237 start_instance, 238 ); 239 } 240 } 241 set_index_buffer(&self, gpu_address: GpuAddress, size: u32, format: Format)242 pub fn set_index_buffer(&self, gpu_address: GpuAddress, size: u32, format: Format) { 243 let ibv = d3d12::D3D12_INDEX_BUFFER_VIEW { 244 BufferLocation: gpu_address, 245 SizeInBytes: size, 246 Format: format, 247 }; 248 unsafe { 249 self.IASetIndexBuffer(&ibv); 250 } 251 } 252 set_blend_factor(&self, factor: [f32; 4])253 pub fn set_blend_factor(&self, factor: [f32; 4]) { 254 unsafe { 255 self.OMSetBlendFactor(&factor); 256 } 257 } 258 set_stencil_reference(&self, reference: u32)259 pub fn set_stencil_reference(&self, reference: u32) { 260 unsafe { 261 self.OMSetStencilRef(reference); 262 } 263 } 264 set_pipeline_state(&self, pso: PipelineState)265 pub fn set_pipeline_state(&self, pso: PipelineState) { 266 unsafe { 267 self.SetPipelineState(pso.as_mut_ptr()); 268 } 269 } 270 execute_bundle(&self, bundle: GraphicsCommandList)271 pub fn execute_bundle(&self, bundle: GraphicsCommandList) { 272 unsafe { 273 self.ExecuteBundle(bundle.as_mut_ptr()); 274 } 275 } 276 set_descriptor_heaps(&self, heaps: &[DescriptorHeap])277 pub fn set_descriptor_heaps(&self, heaps: &[DescriptorHeap]) { 278 unsafe { 279 self.SetDescriptorHeaps( 280 heaps.len() as _, 281 heaps.as_ptr() as *mut &DescriptorHeap as *mut _, 282 ); 283 } 284 } 285 set_compute_root_signature(&self, signature: RootSignature)286 pub fn set_compute_root_signature(&self, signature: RootSignature) { 287 unsafe { 288 self.SetComputeRootSignature(signature.as_mut_ptr()); 289 } 290 } 291 set_graphics_root_signature(&self, signature: RootSignature)292 pub fn set_graphics_root_signature(&self, signature: RootSignature) { 293 unsafe { 294 self.SetGraphicsRootSignature(signature.as_mut_ptr()); 295 } 296 } 297 set_compute_root_descriptor_table( &self, root_index: RootIndex, base_descriptor: GpuDescriptor, )298 pub fn set_compute_root_descriptor_table( 299 &self, 300 root_index: RootIndex, 301 base_descriptor: GpuDescriptor, 302 ) { 303 unsafe { 304 self.SetComputeRootDescriptorTable(root_index, base_descriptor); 305 } 306 } 307 set_compute_root_constant_buffer_view( &self, root_index: RootIndex, buffer_location: GpuAddress, )308 pub fn set_compute_root_constant_buffer_view( 309 &self, 310 root_index: RootIndex, 311 buffer_location: GpuAddress, 312 ) { 313 unsafe { 314 self.SetComputeRootConstantBufferView(root_index, buffer_location); 315 } 316 } 317 set_compute_root_shader_resource_view( &self, root_index: RootIndex, buffer_location: GpuAddress, )318 pub fn set_compute_root_shader_resource_view( 319 &self, 320 root_index: RootIndex, 321 buffer_location: GpuAddress, 322 ) { 323 unsafe { 324 self.SetComputeRootShaderResourceView(root_index, buffer_location); 325 } 326 } 327 set_compute_root_unordered_access_view( &self, root_index: RootIndex, buffer_location: GpuAddress, )328 pub fn set_compute_root_unordered_access_view( 329 &self, 330 root_index: RootIndex, 331 buffer_location: GpuAddress, 332 ) { 333 unsafe { 334 self.SetComputeRootUnorderedAccessView(root_index, buffer_location); 335 } 336 } 337 set_compute_root_constant( &self, root_index: RootIndex, value: u32, dest_offset_words: u32, )338 pub fn set_compute_root_constant( 339 &self, 340 root_index: RootIndex, 341 value: u32, 342 dest_offset_words: u32, 343 ) { 344 unsafe { 345 self.SetComputeRoot32BitConstant(root_index, value, dest_offset_words); 346 } 347 } 348 set_graphics_root_descriptor_table( &self, root_index: RootIndex, base_descriptor: GpuDescriptor, )349 pub fn set_graphics_root_descriptor_table( 350 &self, 351 root_index: RootIndex, 352 base_descriptor: GpuDescriptor, 353 ) { 354 unsafe { 355 self.SetGraphicsRootDescriptorTable(root_index, base_descriptor); 356 } 357 } 358 set_graphics_root_constant_buffer_view( &self, root_index: RootIndex, buffer_location: GpuAddress, )359 pub fn set_graphics_root_constant_buffer_view( 360 &self, 361 root_index: RootIndex, 362 buffer_location: GpuAddress, 363 ) { 364 unsafe { 365 self.SetGraphicsRootConstantBufferView(root_index, buffer_location); 366 } 367 } 368 set_graphics_root_shader_resource_view( &self, root_index: RootIndex, buffer_location: GpuAddress, )369 pub fn set_graphics_root_shader_resource_view( 370 &self, 371 root_index: RootIndex, 372 buffer_location: GpuAddress, 373 ) { 374 unsafe { 375 self.SetGraphicsRootShaderResourceView(root_index, buffer_location); 376 } 377 } 378 set_graphics_root_unordered_access_view( &self, root_index: RootIndex, buffer_location: GpuAddress, )379 pub fn set_graphics_root_unordered_access_view( 380 &self, 381 root_index: RootIndex, 382 buffer_location: GpuAddress, 383 ) { 384 unsafe { 385 self.SetGraphicsRootUnorderedAccessView(root_index, buffer_location); 386 } 387 } 388 set_graphics_root_constant( &self, root_index: RootIndex, value: u32, dest_offset_words: u32, )389 pub fn set_graphics_root_constant( 390 &self, 391 root_index: RootIndex, 392 value: u32, 393 dest_offset_words: u32, 394 ) { 395 unsafe { 396 self.SetGraphicsRoot32BitConstant(root_index, value, dest_offset_words); 397 } 398 } 399 resource_barrier(&self, barriers: &[ResourceBarrier])400 pub fn resource_barrier(&self, barriers: &[ResourceBarrier]) { 401 unsafe { 402 self.ResourceBarrier(barriers.len() as _, barriers.as_ptr() as _) // matches representation 403 } 404 } 405 } 406