1 //! Device
2 
3 use com::WeakPtr;
4 use command_list::{CmdListType, CommandSignature, IndirectArgument};
5 use descriptor::{CpuDescriptor, DescriptorHeapFlags, DescriptorHeapType, RenderTargetViewDesc};
6 use heap::{Heap, HeapFlags, HeapProperties};
7 use std::ops::Range;
8 use winapi::um::d3d12;
9 use winapi::Interface;
10 use {pso, query, queue};
11 use {
12     Blob, CachedPSO, CommandAllocator, CommandQueue, D3DResult, DescriptorHeap,
13     Fence, GraphicsCommandList, NodeMask, PipelineState, QueryHeap, Resource, RootSignature,
14     Shader, TextureAddressMode,
15 };
16 
17 pub type Device = WeakPtr<d3d12::ID3D12Device>;
18 
19 #[cfg(feature = "libloading")]
20 impl crate::D3D12Lib {
create_device<I: Interface>( &self, adapter: WeakPtr<I>, feature_level: crate::FeatureLevel, ) -> libloading::Result<D3DResult<Device>>21     pub fn create_device<I: Interface>(
22         &self,
23         adapter: WeakPtr<I>,
24         feature_level: crate::FeatureLevel,
25     ) -> libloading::Result<D3DResult<Device>> {
26         type Fun = extern "system" fn(
27             *mut winapi::um::unknwnbase::IUnknown,
28             winapi::um::d3dcommon::D3D_FEATURE_LEVEL,
29             winapi::shared::guiddef::REFGUID,
30             *mut *mut  winapi::ctypes::c_void,
31         ) -> crate::HRESULT;
32 
33         let mut device = Device::null();
34         let hr = unsafe {
35             let func: libloading::Symbol<Fun> = self.lib.get(b"D3D12CreateDevice")?;
36             func(
37                 adapter.as_unknown() as *const _ as *mut _,
38                 feature_level as _,
39                 &d3d12::ID3D12Device::uuidof(),
40                 device.mut_void(),
41             )
42         };
43 
44         Ok((device, hr))
45     }
46 }
47 
48 impl Device {
49     #[cfg(feature = "implicit-link")]
create<I: Interface>( adapter: WeakPtr<I>, feature_level: crate::FeatureLevel, ) -> D3DResult<Self>50     pub fn create<I: Interface>(
51         adapter: WeakPtr<I>,
52         feature_level: crate::FeatureLevel,
53     ) -> D3DResult<Self> {
54         let mut device = Device::null();
55         let hr = unsafe {
56             d3d12::D3D12CreateDevice(
57                 adapter.as_unknown() as *const _ as *mut _,
58                 feature_level as _,
59                 &d3d12::ID3D12Device::uuidof(),
60                 device.mut_void(),
61             )
62         };
63 
64         (device, hr)
65     }
66 
create_heap( &self, size_in_bytes: u64, properties: HeapProperties, alignment: u64, flags: HeapFlags, ) -> D3DResult<Heap>67     pub fn create_heap(
68         &self,
69         size_in_bytes: u64,
70         properties: HeapProperties,
71         alignment: u64,
72         flags: HeapFlags,
73     ) -> D3DResult<Heap> {
74         let mut heap = Heap::null();
75 
76         let desc = d3d12::D3D12_HEAP_DESC {
77             SizeInBytes: size_in_bytes,
78             Properties: properties.0,
79             Alignment: alignment,
80             Flags: flags.bits(),
81         };
82 
83         let hr = unsafe { self.CreateHeap(&desc, &d3d12::ID3D12Heap::uuidof(), heap.mut_void()) };
84 
85         (heap, hr)
86     }
87 
create_command_allocator(&self, list_type: CmdListType) -> D3DResult<CommandAllocator>88     pub fn create_command_allocator(&self, list_type: CmdListType) -> D3DResult<CommandAllocator> {
89         let mut allocator = CommandAllocator::null();
90         let hr = unsafe {
91             self.CreateCommandAllocator(
92                 list_type as _,
93                 &d3d12::ID3D12CommandAllocator::uuidof(),
94                 allocator.mut_void(),
95             )
96         };
97 
98         (allocator, hr)
99     }
100 
create_command_queue( &self, list_type: CmdListType, priority: queue::Priority, flags: queue::CommandQueueFlags, node_mask: NodeMask, ) -> D3DResult<CommandQueue>101     pub fn create_command_queue(
102         &self,
103         list_type: CmdListType,
104         priority: queue::Priority,
105         flags: queue::CommandQueueFlags,
106         node_mask: NodeMask,
107     ) -> D3DResult<CommandQueue> {
108         let desc = d3d12::D3D12_COMMAND_QUEUE_DESC {
109             Type: list_type as _,
110             Priority: priority as _,
111             Flags: flags.bits(),
112             NodeMask: node_mask,
113         };
114 
115         let mut queue = CommandQueue::null();
116         let hr = unsafe {
117             self.CreateCommandQueue(
118                 &desc,
119                 &d3d12::ID3D12CommandQueue::uuidof(),
120                 queue.mut_void(),
121             )
122         };
123 
124         (queue, hr)
125     }
126 
create_descriptor_heap( &self, num_descriptors: u32, heap_type: DescriptorHeapType, flags: DescriptorHeapFlags, node_mask: NodeMask, ) -> D3DResult<DescriptorHeap>127     pub fn create_descriptor_heap(
128         &self,
129         num_descriptors: u32,
130         heap_type: DescriptorHeapType,
131         flags: DescriptorHeapFlags,
132         node_mask: NodeMask,
133     ) -> D3DResult<DescriptorHeap> {
134         let desc = d3d12::D3D12_DESCRIPTOR_HEAP_DESC {
135             Type: heap_type as _,
136             NumDescriptors: num_descriptors,
137             Flags: flags.bits(),
138             NodeMask: node_mask,
139         };
140 
141         let mut heap = DescriptorHeap::null();
142         let hr = unsafe {
143             self.CreateDescriptorHeap(
144                 &desc,
145                 &d3d12::ID3D12DescriptorHeap::uuidof(),
146                 heap.mut_void(),
147             )
148         };
149 
150         (heap, hr)
151     }
152 
get_descriptor_increment_size(&self, heap_type: DescriptorHeapType) -> u32153     pub fn get_descriptor_increment_size(&self, heap_type: DescriptorHeapType) -> u32 {
154         unsafe { self.GetDescriptorHandleIncrementSize(heap_type as _) }
155     }
156 
create_graphics_command_list( &self, list_type: CmdListType, allocator: CommandAllocator, initial: PipelineState, node_mask: NodeMask, ) -> D3DResult<GraphicsCommandList>157     pub fn create_graphics_command_list(
158         &self,
159         list_type: CmdListType,
160         allocator: CommandAllocator,
161         initial: PipelineState,
162         node_mask: NodeMask,
163     ) -> D3DResult<GraphicsCommandList> {
164         let mut command_list = GraphicsCommandList::null();
165         let hr = unsafe {
166             self.CreateCommandList(
167                 node_mask,
168                 list_type as _,
169                 allocator.as_mut_ptr(),
170                 initial.as_mut_ptr(),
171                 &d3d12::ID3D12GraphicsCommandList::uuidof(),
172                 command_list.mut_void(),
173             )
174         };
175 
176         (command_list, hr)
177     }
178 
create_query_heap( &self, heap_ty: query::QueryHeapType, count: u32, node_mask: NodeMask, ) -> D3DResult<QueryHeap>179     pub fn create_query_heap(
180         &self,
181         heap_ty: query::QueryHeapType,
182         count: u32,
183         node_mask: NodeMask,
184     ) -> D3DResult<QueryHeap> {
185         let desc = d3d12::D3D12_QUERY_HEAP_DESC {
186             Type: heap_ty as _,
187             Count: count,
188             NodeMask: node_mask,
189         };
190 
191         let mut query_heap = QueryHeap::null();
192         let hr = unsafe {
193             self.CreateQueryHeap(
194                 &desc,
195                 &d3d12::ID3D12QueryHeap::uuidof(),
196                 query_heap.mut_void(),
197             )
198         };
199 
200         (query_heap, hr)
201     }
202 
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<PipelineState>203     pub fn create_graphics_pipeline_state(
204         &self,
205         _root_signature: RootSignature,
206         _vs: Shader,
207         _ps: Shader,
208         _gs: Shader,
209         _hs: Shader,
210         _ds: Shader,
211         _node_mask: NodeMask,
212         _cached_pso: CachedPSO,
213         _flags: pso::PipelineStateFlags,
214     ) -> D3DResult<PipelineState> {
215         unimplemented!()
216     }
217 
create_compute_pipeline_state( &self, root_signature: RootSignature, cs: Shader, node_mask: NodeMask, cached_pso: CachedPSO, flags: pso::PipelineStateFlags, ) -> D3DResult<PipelineState>218     pub fn create_compute_pipeline_state(
219         &self,
220         root_signature: RootSignature,
221         cs: Shader,
222         node_mask: NodeMask,
223         cached_pso: CachedPSO,
224         flags: pso::PipelineStateFlags,
225     ) -> D3DResult<PipelineState> {
226         let mut pipeline = PipelineState::null();
227         let desc = d3d12::D3D12_COMPUTE_PIPELINE_STATE_DESC {
228             pRootSignature: root_signature.as_mut_ptr(),
229             CS: *cs,
230             NodeMask: node_mask,
231             CachedPSO: *cached_pso,
232             Flags: flags.bits(),
233         };
234 
235         let hr = unsafe {
236             self.CreateComputePipelineState(
237                 &desc,
238                 &d3d12::ID3D12PipelineState::uuidof(),
239                 pipeline.mut_void(),
240             )
241         };
242 
243         (pipeline, hr)
244     }
245 
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<f32>, )246     pub fn create_sampler(
247         &self,
248         sampler: CpuDescriptor,
249         filter: d3d12::D3D12_FILTER,
250         address_mode: TextureAddressMode,
251         mip_lod_bias: f32,
252         max_anisotropy: u32,
253         comparison_op: d3d12::D3D12_COMPARISON_FUNC,
254         border_color: [f32; 4],
255         lod: Range<f32>,
256     ) {
257         let desc = d3d12::D3D12_SAMPLER_DESC {
258             Filter: filter,
259             AddressU: address_mode[0],
260             AddressV: address_mode[1],
261             AddressW: address_mode[2],
262             MipLODBias: mip_lod_bias,
263             MaxAnisotropy: max_anisotropy,
264             ComparisonFunc: comparison_op,
265             BorderColor: border_color,
266             MinLOD: lod.start,
267             MaxLOD: lod.end,
268         };
269 
270         unsafe {
271             self.CreateSampler(&desc, sampler);
272         }
273     }
274 
create_root_signature( &self, blob: Blob, node_mask: NodeMask, ) -> D3DResult<RootSignature>275     pub fn create_root_signature(
276         &self,
277         blob: Blob,
278         node_mask: NodeMask,
279     ) -> D3DResult<RootSignature> {
280         let mut signature = RootSignature::null();
281         let hr = unsafe {
282             self.CreateRootSignature(
283                 node_mask,
284                 blob.GetBufferPointer(),
285                 blob.GetBufferSize(),
286                 &d3d12::ID3D12RootSignature::uuidof(),
287                 signature.mut_void(),
288             )
289         };
290 
291         (signature, hr)
292     }
293 
create_command_signature( &self, root_signature: RootSignature, arguments: &[IndirectArgument], stride: u32, node_mask: NodeMask, ) -> D3DResult<CommandSignature>294     pub fn create_command_signature(
295         &self,
296         root_signature: RootSignature,
297         arguments: &[IndirectArgument],
298         stride: u32,
299         node_mask: NodeMask,
300     ) -> D3DResult<CommandSignature> {
301         let mut signature = CommandSignature::null();
302         let desc = d3d12::D3D12_COMMAND_SIGNATURE_DESC {
303             ByteStride: stride,
304             NumArgumentDescs: arguments.len() as _,
305             pArgumentDescs: arguments.as_ptr() as *const _,
306             NodeMask: node_mask,
307         };
308 
309         let hr = unsafe {
310             self.CreateCommandSignature(
311                 &desc,
312                 root_signature.as_mut_ptr(),
313                 &d3d12::ID3D12CommandSignature::uuidof(),
314                 signature.mut_void(),
315             )
316         };
317 
318         (signature, hr)
319     }
320 
create_render_target_view( &self, resource: Resource, desc: &RenderTargetViewDesc, descriptor: CpuDescriptor, )321     pub fn create_render_target_view(
322         &self,
323         resource: Resource,
324         desc: &RenderTargetViewDesc,
325         descriptor: CpuDescriptor,
326     ) {
327         unsafe {
328             self.CreateRenderTargetView(resource.as_mut_ptr(), &desc.0 as *const _, descriptor);
329         }
330     }
331 
332     // TODO: interface not complete
create_fence(&self, initial: u64) -> D3DResult<Fence>333     pub fn create_fence(&self, initial: u64) -> D3DResult<Fence> {
334         let mut fence = Fence::null();
335         let hr = unsafe {
336             self.CreateFence(
337                 initial,
338                 d3d12::D3D12_FENCE_FLAG_NONE,
339                 &d3d12::ID3D12Fence::uuidof(),
340                 fence.mut_void(),
341             )
342         };
343 
344         (fence, hr)
345     }
346 }
347