//! Device use crate::{ com::ComPtr, command_list::{CmdListType, CommandSignature, IndirectArgument}, descriptor::{CpuDescriptor, DescriptorHeapFlags, DescriptorHeapType, RenderTargetViewDesc}, heap::{Heap, HeapFlags, HeapProperties}, pso, query, queue, Blob, CachedPSO, CommandAllocator, CommandQueue, D3DResult, DescriptorHeap, Fence, GraphicsCommandList, NodeMask, PipelineState, QueryHeap, Resource, RootSignature, Shader, TextureAddressMode, }; use std::ops::Range; use winapi::{um::d3d12, Interface}; pub type Device = ComPtr; #[cfg(feature = "libloading")] impl crate::D3D12Lib { pub fn create_device( &self, adapter: &ComPtr, feature_level: crate::FeatureLevel, ) -> Result, libloading::Error> { type Fun = extern "system" fn( *mut winapi::um::unknwnbase::IUnknown, winapi::um::d3dcommon::D3D_FEATURE_LEVEL, winapi::shared::guiddef::REFGUID, *mut *mut winapi::ctypes::c_void, ) -> crate::HRESULT; let mut device = Device::null(); let hr = unsafe { let func: libloading::Symbol = self.lib.get(b"D3D12CreateDevice")?; func( adapter.as_unknown() as *const _ as *mut _, feature_level as _, &d3d12::ID3D12Device::uuidof(), device.mut_void(), ) }; Ok((device, hr)) } } impl Device { #[cfg(feature = "implicit-link")] pub fn create( adapter: ComPtr, feature_level: crate::FeatureLevel, ) -> D3DResult { let mut device = Device::null(); let hr = unsafe { d3d12::D3D12CreateDevice( adapter.as_unknown() as *const _ as *mut _, feature_level as _, &d3d12::ID3D12Device::uuidof(), device.mut_void(), ) }; (device, hr) } pub fn create_heap( &self, size_in_bytes: u64, properties: HeapProperties, alignment: u64, flags: HeapFlags, ) -> D3DResult { let mut heap = Heap::null(); let desc = d3d12::D3D12_HEAP_DESC { SizeInBytes: size_in_bytes, Properties: properties.0, Alignment: alignment, Flags: flags.bits(), }; let hr = unsafe { self.CreateHeap(&desc, &d3d12::ID3D12Heap::uuidof(), heap.mut_void()) }; (heap, hr) } pub fn create_command_allocator(&self, list_type: CmdListType) -> D3DResult { let mut allocator = CommandAllocator::null(); let hr = unsafe { self.CreateCommandAllocator( list_type as _, &d3d12::ID3D12CommandAllocator::uuidof(), allocator.mut_void(), ) }; (allocator, hr) } pub fn create_command_queue( &self, list_type: CmdListType, priority: queue::Priority, flags: queue::CommandQueueFlags, node_mask: NodeMask, ) -> D3DResult { let desc = d3d12::D3D12_COMMAND_QUEUE_DESC { Type: list_type as _, Priority: priority as _, Flags: flags.bits(), NodeMask: node_mask, }; let mut queue = CommandQueue::null(); let hr = unsafe { self.CreateCommandQueue( &desc, &d3d12::ID3D12CommandQueue::uuidof(), queue.mut_void(), ) }; (queue, hr) } pub fn create_descriptor_heap( &self, num_descriptors: u32, heap_type: DescriptorHeapType, flags: DescriptorHeapFlags, node_mask: NodeMask, ) -> D3DResult { let desc = d3d12::D3D12_DESCRIPTOR_HEAP_DESC { Type: heap_type as _, NumDescriptors: num_descriptors, Flags: flags.bits(), NodeMask: node_mask, }; let mut heap = DescriptorHeap::null(); let hr = unsafe { self.CreateDescriptorHeap( &desc, &d3d12::ID3D12DescriptorHeap::uuidof(), heap.mut_void(), ) }; (heap, hr) } pub fn get_descriptor_increment_size(&self, heap_type: DescriptorHeapType) -> u32 { unsafe { self.GetDescriptorHandleIncrementSize(heap_type as _) } } pub fn create_graphics_command_list( &self, list_type: CmdListType, allocator: &CommandAllocator, initial: PipelineState, node_mask: NodeMask, ) -> D3DResult { let mut command_list = GraphicsCommandList::null(); let hr = unsafe { self.CreateCommandList( node_mask, list_type as _, allocator.as_mut_ptr(), initial.as_mut_ptr(), &d3d12::ID3D12GraphicsCommandList::uuidof(), command_list.mut_void(), ) }; (command_list, hr) } pub fn create_query_heap( &self, heap_ty: query::QueryHeapType, count: u32, node_mask: NodeMask, ) -> D3DResult { let desc = d3d12::D3D12_QUERY_HEAP_DESC { Type: heap_ty as _, Count: count, NodeMask: node_mask, }; let mut query_heap = QueryHeap::null(); let hr = unsafe { self.CreateQueryHeap( &desc, &d3d12::ID3D12QueryHeap::uuidof(), query_heap.mut_void(), ) }; (query_heap, hr) } pub fn create_graphics_pipeline_state( &self, _root_signature: RootSignature, _vs: Shader, _ps: Shader, _gs: Shader, _hs: Shader, _ds: Shader, _node_mask: NodeMask, _cached_pso: CachedPSO, _flags: pso::PipelineStateFlags, ) -> D3DResult { unimplemented!() } pub fn create_compute_pipeline_state( &self, root_signature: &RootSignature, cs: Shader, node_mask: NodeMask, cached_pso: CachedPSO, flags: pso::PipelineStateFlags, ) -> D3DResult { let mut pipeline = PipelineState::null(); let desc = d3d12::D3D12_COMPUTE_PIPELINE_STATE_DESC { pRootSignature: root_signature.as_mut_ptr(), CS: *cs, NodeMask: node_mask, CachedPSO: *cached_pso, Flags: flags.bits(), }; let hr = unsafe { self.CreateComputePipelineState( &desc, &d3d12::ID3D12PipelineState::uuidof(), pipeline.mut_void(), ) }; (pipeline, hr) } pub fn create_sampler( &self, sampler: CpuDescriptor, filter: d3d12::D3D12_FILTER, address_mode: TextureAddressMode, mip_lod_bias: f32, max_anisotropy: u32, comparison_op: d3d12::D3D12_COMPARISON_FUNC, border_color: [f32; 4], lod: Range, ) { let desc = d3d12::D3D12_SAMPLER_DESC { Filter: filter, AddressU: address_mode[0], AddressV: address_mode[1], AddressW: address_mode[2], MipLODBias: mip_lod_bias, MaxAnisotropy: max_anisotropy, ComparisonFunc: comparison_op, BorderColor: border_color, MinLOD: lod.start, MaxLOD: lod.end, }; unsafe { self.CreateSampler(&desc, sampler); } } pub fn create_root_signature( &self, blob: Blob, node_mask: NodeMask, ) -> D3DResult { let mut signature = RootSignature::null(); let hr = unsafe { self.CreateRootSignature( node_mask, blob.GetBufferPointer(), blob.GetBufferSize(), &d3d12::ID3D12RootSignature::uuidof(), signature.mut_void(), ) }; (signature, hr) } pub fn create_command_signature( &self, root_signature: RootSignature, arguments: &[IndirectArgument], stride: u32, node_mask: NodeMask, ) -> D3DResult { let mut signature = CommandSignature::null(); let desc = d3d12::D3D12_COMMAND_SIGNATURE_DESC { ByteStride: stride, NumArgumentDescs: arguments.len() as _, pArgumentDescs: arguments.as_ptr() as *const _, NodeMask: node_mask, }; let hr = unsafe { self.CreateCommandSignature( &desc, root_signature.as_mut_ptr(), &d3d12::ID3D12CommandSignature::uuidof(), signature.mut_void(), ) }; (signature, hr) } pub fn create_render_target_view( &self, resource: Resource, desc: &RenderTargetViewDesc, descriptor: CpuDescriptor, ) { unsafe { self.CreateRenderTargetView(resource.as_mut_ptr(), &desc.0 as *const _, descriptor); } } // TODO: interface not complete pub fn create_fence(&self, initial: u64) -> D3DResult { let mut fence = Fence::null(); let hr = unsafe { self.CreateFence( initial, d3d12::D3D12_FENCE_FLAG_NONE, &d3d12::ID3D12Fence::uuidof(), fence.mut_void(), ) }; (fence, hr) } }