1 /*!
2 # DX11 backend internals.
3 
4 ## Pipeline Layout
5 
6 In D3D11 there are tables of CBVs, SRVs, UAVs, and samplers.
7 
8 Each descriptor type can take 1 or two of those entry points.
9 
10 The descriptor pool is just and array of handles, belonging to descriptor set 1, descriptor set 2, etc.
11 Each range of descriptors in a descriptor set area of the pool is split into shader stages,
12 which in turn is split into CBS/SRV/UAV/Sampler parts. That allows binding a descriptor set as a list
13 of continuous descriptor ranges (per type, per shader stage).
14 
15 !*/
16 
17 //#[deny(missing_docs)]
18 
19 #[macro_use]
20 extern crate bitflags;
21 #[macro_use]
22 extern crate log;
23 #[macro_use]
24 extern crate winapi;
25 
26 use hal::{
27     adapter,
28     buffer,
29     command,
30     format,
31     image,
32     memory,
33     pass,
34     pso,
35     query,
36     queue,
37     window,
38     DrawCount,
39     IndexCount,
40     InstanceCount,
41     Limits,
42     VertexCount,
43     VertexOffset,
44     WorkGroupCount,
45 };
46 
47 use range_alloc::RangeAllocator;
48 
49 use winapi::{
50     shared::{
51         dxgi::{IDXGIAdapter, IDXGIFactory, IDXGISwapChain},
52         dxgiformat,
53         minwindef::{FALSE, HMODULE, UINT},
54         windef::{HWND, RECT},
55         winerror,
56     },
57     um::{d3d11, d3dcommon, winuser::GetClientRect},
58     Interface as _,
59 };
60 
61 use wio::com::ComPtr;
62 
63 use parking_lot::{Condvar, Mutex};
64 
65 use std::{borrow::Borrow, cell::RefCell, fmt, mem, ops::Range, os::raw::c_void, ptr, sync::Arc};
66 
67 macro_rules! debug_scope {
68     ($context:expr, $($arg:tt)+) => ({
69         #[cfg(debug_assertions)]
70         {
71             $crate::debug::DebugScope::with_name(
72                 $context,
73                 format_args!($($arg)+),
74             )
75         }
76         #[cfg(not(debug_assertions))]
77         {
78             ()
79         }
80     });
81 }
82 
83 macro_rules! debug_marker {
84     ($context:expr, $($arg:tt)+) => ({
85         #[cfg(debug_assertions)]
86         {
87             $crate::debug::debug_marker(
88                 $context,
89                 format_args!($($arg)+),
90             );
91         }
92     });
93 }
94 
95 mod conv;
96 #[cfg(debug_assertions)]
97 mod debug;
98 mod device;
99 mod dxgi;
100 mod internal;
101 mod shader;
102 
103 type CreateFun = unsafe extern "system" fn(
104     *mut IDXGIAdapter,
105     UINT,
106     HMODULE,
107     UINT,
108     *const UINT,
109     UINT,
110     UINT,
111     *mut *mut d3d11::ID3D11Device,
112     *mut UINT,
113     *mut *mut d3d11::ID3D11DeviceContext,
114 ) -> winerror::HRESULT;
115 
116 #[derive(Clone)]
117 pub(crate) struct ViewInfo {
118     resource: *mut d3d11::ID3D11Resource,
119     kind: image::Kind,
120     caps: image::ViewCapabilities,
121     view_kind: image::ViewKind,
122     format: dxgiformat::DXGI_FORMAT,
123     range: image::SubresourceRange,
124 }
125 
126 impl fmt::Debug for ViewInfo {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result127     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
128         fmt.write_str("ViewInfo")
129     }
130 }
131 
132 #[derive(Debug)]
133 pub struct Instance {
134     pub(crate) factory: ComPtr<IDXGIFactory>,
135     pub(crate) dxgi_version: dxgi::DxgiVersion,
136     library_d3d11: Arc<libloading::Library>,
137     library_dxgi: libloading::Library,
138 }
139 
140 unsafe impl Send for Instance {}
141 unsafe impl Sync for Instance {}
142 
143 impl Instance {
create_surface_from_hwnd(&self, hwnd: *mut c_void) -> Surface144     pub fn create_surface_from_hwnd(&self, hwnd: *mut c_void) -> Surface {
145         Surface {
146             factory: self.factory.clone(),
147             wnd_handle: hwnd as *mut _,
148             presentation: None,
149         }
150     }
151 }
152 
get_features( _device: ComPtr<d3d11::ID3D11Device>, _feature_level: d3dcommon::D3D_FEATURE_LEVEL, ) -> hal::Features153 fn get_features(
154     _device: ComPtr<d3d11::ID3D11Device>,
155     _feature_level: d3dcommon::D3D_FEATURE_LEVEL,
156 ) -> hal::Features {
157     hal::Features::empty()
158         | hal::Features::ROBUST_BUFFER_ACCESS
159         | hal::Features::FULL_DRAW_INDEX_U32
160         | hal::Features::FORMAT_BC
161         | hal::Features::INSTANCE_RATE
162         | hal::Features::SAMPLER_MIP_LOD_BIAS
163         | hal::Features::SAMPLER_MIRROR_CLAMP_EDGE
164         | hal::Features::NDC_Y_UP
165 }
166 
get_format_properties( device: ComPtr<d3d11::ID3D11Device>, ) -> [format::Properties; format::NUM_FORMATS]167 fn get_format_properties(
168     device: ComPtr<d3d11::ID3D11Device>,
169 ) -> [format::Properties; format::NUM_FORMATS] {
170     let mut format_properties = [format::Properties::default(); format::NUM_FORMATS];
171     for (i, props) in &mut format_properties.iter_mut().enumerate().skip(1) {
172         let format: format::Format = unsafe { mem::transmute(i as u32) };
173 
174         let dxgi_format = match conv::map_format(format) {
175             Some(format) => format,
176             None => continue,
177         };
178 
179         let mut support = d3d11::D3D11_FEATURE_DATA_FORMAT_SUPPORT {
180             InFormat: dxgi_format,
181             OutFormatSupport: 0,
182         };
183         let mut support_2 = d3d11::D3D11_FEATURE_DATA_FORMAT_SUPPORT2 {
184             InFormat: dxgi_format,
185             OutFormatSupport2: 0,
186         };
187 
188         let hr = unsafe {
189             device.CheckFeatureSupport(
190                 d3d11::D3D11_FEATURE_FORMAT_SUPPORT,
191                 &mut support as *mut _ as *mut _,
192                 mem::size_of::<d3d11::D3D11_FEATURE_DATA_FORMAT_SUPPORT>() as UINT,
193             )
194         };
195 
196         if hr == winerror::S_OK {
197             let can_buffer = 0 != support.OutFormatSupport & d3d11::D3D11_FORMAT_SUPPORT_BUFFER;
198             let can_image = 0
199                 != support.OutFormatSupport
200                     & (d3d11::D3D11_FORMAT_SUPPORT_TEXTURE1D
201                         | d3d11::D3D11_FORMAT_SUPPORT_TEXTURE2D
202                         | d3d11::D3D11_FORMAT_SUPPORT_TEXTURE3D
203                         | d3d11::D3D11_FORMAT_SUPPORT_TEXTURECUBE);
204             let can_linear = can_image && !format.surface_desc().is_compressed();
205             if can_image {
206                 props.optimal_tiling |=
207                     format::ImageFeature::SAMPLED | format::ImageFeature::BLIT_SRC;
208             }
209             if can_linear {
210                 props.linear_tiling |=
211                     format::ImageFeature::SAMPLED | format::ImageFeature::BLIT_SRC;
212             }
213             if support.OutFormatSupport & d3d11::D3D11_FORMAT_SUPPORT_IA_VERTEX_BUFFER != 0 {
214                 props.buffer_features |= format::BufferFeature::VERTEX;
215             }
216             if support.OutFormatSupport & d3d11::D3D11_FORMAT_SUPPORT_SHADER_SAMPLE != 0 {
217                 props.optimal_tiling |= format::ImageFeature::SAMPLED_LINEAR;
218             }
219             if support.OutFormatSupport & d3d11::D3D11_FORMAT_SUPPORT_RENDER_TARGET != 0 {
220                 props.optimal_tiling |=
221                     format::ImageFeature::COLOR_ATTACHMENT | format::ImageFeature::BLIT_DST;
222                 if can_linear {
223                     props.linear_tiling |=
224                         format::ImageFeature::COLOR_ATTACHMENT | format::ImageFeature::BLIT_DST;
225                 }
226             }
227             if support.OutFormatSupport & d3d11::D3D11_FORMAT_SUPPORT_BLENDABLE != 0 {
228                 props.optimal_tiling |= format::ImageFeature::COLOR_ATTACHMENT_BLEND;
229             }
230             if support.OutFormatSupport & d3d11::D3D11_FORMAT_SUPPORT_DEPTH_STENCIL != 0 {
231                 props.optimal_tiling |= format::ImageFeature::DEPTH_STENCIL_ATTACHMENT;
232             }
233             if support.OutFormatSupport & d3d11::D3D11_FORMAT_SUPPORT_SHADER_LOAD != 0 {
234                 //TODO: check d3d12::D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD ?
235                 if can_buffer {
236                     props.buffer_features |= format::BufferFeature::UNIFORM_TEXEL;
237                 }
238             }
239 
240             let hr = unsafe {
241                 device.CheckFeatureSupport(
242                     d3d11::D3D11_FEATURE_FORMAT_SUPPORT2,
243                     &mut support_2 as *mut _ as *mut _,
244                     mem::size_of::<d3d11::D3D11_FEATURE_DATA_FORMAT_SUPPORT2>() as UINT,
245                 )
246             };
247             if hr == winerror::S_OK {
248                 if support_2.OutFormatSupport2 & d3d11::D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_ADD != 0 {
249                     //TODO: other atomic flags?
250                     if can_buffer {
251                         props.buffer_features |= format::BufferFeature::STORAGE_TEXEL_ATOMIC;
252                     }
253                     if can_image {
254                         props.optimal_tiling |= format::ImageFeature::STORAGE_ATOMIC;
255                     }
256                 }
257                 if support_2.OutFormatSupport2 & d3d11::D3D11_FORMAT_SUPPORT2_UAV_TYPED_STORE != 0 {
258                     if can_buffer {
259                         props.buffer_features |= format::BufferFeature::STORAGE_TEXEL;
260                     }
261                     if can_image {
262                         props.optimal_tiling |= format::ImageFeature::STORAGE;
263                     }
264                 }
265             }
266         }
267 
268         //TODO: blits, linear tiling
269     }
270 
271     format_properties
272 }
273 
274 impl hal::Instance<Backend> for Instance {
create(_: &str, _: u32) -> Result<Self, hal::UnsupportedBackend>275     fn create(_: &str, _: u32) -> Result<Self, hal::UnsupportedBackend> {
276         // TODO: get the latest factory we can find
277 
278         match dxgi::get_dxgi_factory() {
279             Ok((library_dxgi, factory, dxgi_version)) => {
280                 info!("DXGI version: {:?}", dxgi_version);
281                 let library_d3d11 = Arc::new(
282                     libloading::Library::new("d3d11.dll").map_err(|_| hal::UnsupportedBackend)?,
283                 );
284                 Ok(Instance {
285                     factory,
286                     dxgi_version,
287                     library_d3d11,
288                     library_dxgi,
289                 })
290             }
291             Err(hr) => {
292                 info!("Failed on factory creation: {:?}", hr);
293                 Err(hal::UnsupportedBackend)
294             }
295         }
296     }
297 
enumerate_adapters(&self) -> Vec<adapter::Adapter<Backend>>298     fn enumerate_adapters(&self) -> Vec<adapter::Adapter<Backend>> {
299         let mut adapters = Vec::new();
300         let mut idx = 0;
301 
302         let func: libloading::Symbol<CreateFun> =
303             match unsafe { self.library_d3d11.get(b"D3D11CreateDevice") } {
304                 Ok(func) => func,
305                 Err(e) => {
306                     error!("Unable to get device creation function: {:?}", e);
307                     return Vec::new();
308                 }
309             };
310 
311         while let Ok((adapter, info)) =
312             dxgi::get_adapter(idx, self.factory.as_raw(), self.dxgi_version)
313         {
314             idx += 1;
315 
316             use hal::memory::Properties;
317 
318             // TODO: move into function?
319             let (device, feature_level) = {
320                 let feature_level = get_feature_level(&func, adapter.as_raw());
321 
322                 let mut device = ptr::null_mut();
323                 let hr = unsafe {
324                     func(
325                         adapter.as_raw() as *mut _,
326                         d3dcommon::D3D_DRIVER_TYPE_UNKNOWN,
327                         ptr::null_mut(),
328                         0,
329                         [feature_level].as_ptr(),
330                         1,
331                         d3d11::D3D11_SDK_VERSION,
332                         &mut device as *mut *mut _ as *mut *mut _,
333                         ptr::null_mut(),
334                         ptr::null_mut(),
335                     )
336                 };
337 
338                 if !winerror::SUCCEEDED(hr) {
339                     continue;
340                 }
341 
342                 (
343                     unsafe { ComPtr::<d3d11::ID3D11Device>::from_raw(device) },
344                     feature_level,
345                 )
346             };
347 
348             let memory_properties = adapter::MemoryProperties {
349                 memory_types: vec![
350                     adapter::MemoryType {
351                         properties: Properties::DEVICE_LOCAL,
352                         heap_index: 0,
353                     },
354                     adapter::MemoryType {
355                         properties: Properties::CPU_VISIBLE
356                             | Properties::COHERENT
357                             | Properties::CPU_CACHED,
358                         heap_index: 1,
359                     },
360                     adapter::MemoryType {
361                         properties: Properties::CPU_VISIBLE | Properties::CPU_CACHED,
362                         heap_index: 1,
363                     },
364                 ],
365                 // TODO: would using *VideoMemory and *SystemMemory from
366                 //       DXGI_ADAPTER_DESC be too optimistic? :)
367                 memory_heaps: vec![!0, !0],
368             };
369 
370             let limits = hal::Limits {
371                 max_image_1d_size: d3d11::D3D11_REQ_TEXTURE1D_U_DIMENSION as _,
372                 max_image_2d_size: d3d11::D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION as _,
373                 max_image_3d_size: d3d11::D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION as _,
374                 max_image_cube_size: d3d11::D3D11_REQ_TEXTURECUBE_DIMENSION as _,
375                 max_image_array_layers: d3d11::D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION as _,
376                 max_texel_elements: d3d11::D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION as _, //TODO
377                 max_patch_size: 0,                                                    // TODO
378                 max_viewports: d3d11::D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE as _,
379                 max_viewport_dimensions: [d3d11::D3D11_VIEWPORT_BOUNDS_MAX; 2],
380                 max_framebuffer_extent: hal::image::Extent {
381                     //TODO
382                     width: 4096,
383                     height: 4096,
384                     depth: 1,
385                 },
386                 max_compute_work_group_count: [
387                     d3d11::D3D11_CS_THREAD_GROUP_MAX_X,
388                     d3d11::D3D11_CS_THREAD_GROUP_MAX_Y,
389                     d3d11::D3D11_CS_THREAD_GROUP_MAX_Z,
390                 ],
391                 max_compute_work_group_size: [
392                     d3d11::D3D11_CS_THREAD_GROUP_MAX_THREADS_PER_GROUP,
393                     1,
394                     1,
395                 ], // TODO
396                 max_vertex_input_attribute_offset: 255, // TODO
397                 max_vertex_input_attributes: d3d11::D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT as _,
398                 max_vertex_input_binding_stride:
399                     d3d11::D3D11_REQ_MULTI_ELEMENT_STRUCTURE_SIZE_IN_BYTES as _,
400                 max_vertex_input_bindings: d3d11::D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT as _, // TODO: verify same as attributes
401                 max_vertex_output_components: d3d11::D3D11_VS_OUTPUT_REGISTER_COUNT as _, // TODO
402                 min_texel_buffer_offset_alignment: 1,                                     // TODO
403                 min_uniform_buffer_offset_alignment: 16, // TODO: verify
404                 min_storage_buffer_offset_alignment: 1,  // TODO
405                 framebuffer_color_sample_counts: 1,      // TODO
406                 framebuffer_depth_sample_counts: 1,      // TODO
407                 framebuffer_stencil_sample_counts: 1,    // TODO
408                 max_color_attachments: d3d11::D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT as _,
409                 buffer_image_granularity: 1,
410                 non_coherent_atom_size: 1, // TODO
411                 max_sampler_anisotropy: 16.,
412                 optimal_buffer_copy_offset_alignment: 1, // TODO
413                 optimal_buffer_copy_pitch_alignment: 1,  // TODO
414                 min_vertex_input_binding_stride_alignment: 1,
415                 ..hal::Limits::default() //TODO
416             };
417 
418             let features = get_features(device.clone(), feature_level);
419             let format_properties = get_format_properties(device.clone());
420             let hints = hal::Hints::BASE_VERTEX_INSTANCE_DRAWING;
421 
422             let physical_device = PhysicalDevice {
423                 adapter,
424                 library_d3d11: Arc::clone(&self.library_d3d11),
425                 features,
426                 hints,
427                 limits,
428                 memory_properties,
429                 format_properties,
430             };
431 
432             info!("{:#?}", info);
433 
434             adapters.push(adapter::Adapter {
435                 info,
436                 physical_device,
437                 queue_families: vec![QueueFamily],
438             });
439         }
440 
441         adapters
442     }
443 
create_surface( &self, has_handle: &impl raw_window_handle::HasRawWindowHandle, ) -> Result<Surface, hal::window::InitError>444     unsafe fn create_surface(
445         &self,
446         has_handle: &impl raw_window_handle::HasRawWindowHandle,
447     ) -> Result<Surface, hal::window::InitError> {
448         match has_handle.raw_window_handle() {
449             raw_window_handle::RawWindowHandle::Windows(handle) => {
450                 Ok(self.create_surface_from_hwnd(handle.hwnd))
451             }
452             _ => Err(hal::window::InitError::UnsupportedWindowHandle),
453         }
454     }
455 
destroy_surface(&self, _surface: Surface)456     unsafe fn destroy_surface(&self, _surface: Surface) {
457         // TODO: Implement Surface cleanup
458     }
459 }
460 
461 pub struct PhysicalDevice {
462     adapter: ComPtr<IDXGIAdapter>,
463     library_d3d11: Arc<libloading::Library>,
464     features: hal::Features,
465     hints: hal::Hints,
466     limits: hal::Limits,
467     memory_properties: adapter::MemoryProperties,
468     format_properties: [format::Properties; format::NUM_FORMATS],
469 }
470 
471 impl fmt::Debug for PhysicalDevice {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result472     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
473         fmt.write_str("PhysicalDevice")
474     }
475 }
476 
477 unsafe impl Send for PhysicalDevice {}
478 unsafe impl Sync for PhysicalDevice {}
479 
480 // TODO: does the adapter we get earlier matter for feature level?
get_feature_level(func: &CreateFun, adapter: *mut IDXGIAdapter) -> d3dcommon::D3D_FEATURE_LEVEL481 fn get_feature_level(func: &CreateFun, adapter: *mut IDXGIAdapter) -> d3dcommon::D3D_FEATURE_LEVEL {
482     let requested_feature_levels = [
483         d3dcommon::D3D_FEATURE_LEVEL_11_1,
484         d3dcommon::D3D_FEATURE_LEVEL_11_0,
485         d3dcommon::D3D_FEATURE_LEVEL_10_1,
486         d3dcommon::D3D_FEATURE_LEVEL_10_0,
487         d3dcommon::D3D_FEATURE_LEVEL_9_3,
488         d3dcommon::D3D_FEATURE_LEVEL_9_2,
489         d3dcommon::D3D_FEATURE_LEVEL_9_1,
490     ];
491 
492     let mut feature_level = d3dcommon::D3D_FEATURE_LEVEL_9_1;
493     let hr = unsafe {
494         func(
495             adapter,
496             d3dcommon::D3D_DRIVER_TYPE_UNKNOWN,
497             ptr::null_mut(),
498             0,
499             requested_feature_levels[..].as_ptr(),
500             requested_feature_levels.len() as _,
501             d3d11::D3D11_SDK_VERSION,
502             ptr::null_mut(),
503             &mut feature_level as *mut _,
504             ptr::null_mut(),
505         )
506     };
507 
508     if !winerror::SUCCEEDED(hr) {
509         // if there is no 11.1 runtime installed, requesting
510         // `D3D_FEATURE_LEVEL_11_1` will return E_INVALIDARG so we just retry
511         // without that
512         if hr == winerror::E_INVALIDARG {
513             let hr = unsafe {
514                 func(
515                     adapter,
516                     d3dcommon::D3D_DRIVER_TYPE_UNKNOWN,
517                     ptr::null_mut(),
518                     0,
519                     requested_feature_levels[1 ..].as_ptr(),
520                     (requested_feature_levels.len() - 1) as _,
521                     d3d11::D3D11_SDK_VERSION,
522                     ptr::null_mut(),
523                     &mut feature_level as *mut _,
524                     ptr::null_mut(),
525                 )
526             };
527 
528             if !winerror::SUCCEEDED(hr) {
529                 // TODO: device might not support any feature levels?
530                 unimplemented!();
531             }
532         }
533     }
534 
535     feature_level
536 }
537 
538 // TODO: PhysicalDevice
539 impl adapter::PhysicalDevice<Backend> for PhysicalDevice {
open( &self, families: &[(&QueueFamily, &[queue::QueuePriority])], requested_features: hal::Features, ) -> Result<adapter::Gpu<Backend>, hal::device::CreationError>540     unsafe fn open(
541         &self,
542         families: &[(&QueueFamily, &[queue::QueuePriority])],
543         requested_features: hal::Features,
544     ) -> Result<adapter::Gpu<Backend>, hal::device::CreationError> {
545         let func: libloading::Symbol<CreateFun> =
546             self.library_d3d11.get(b"D3D11CreateDevice").unwrap();
547 
548         let (device, cxt) = {
549             if !self.features().contains(requested_features) {
550                 return Err(hal::device::CreationError::MissingFeature);
551             }
552 
553             let feature_level = get_feature_level(&func, self.adapter.as_raw());
554             let mut returned_level = d3dcommon::D3D_FEATURE_LEVEL_9_1;
555 
556             #[cfg(debug_assertions)]
557             let create_flags = d3d11::D3D11_CREATE_DEVICE_DEBUG;
558             #[cfg(not(debug_assertions))]
559             let create_flags = 0;
560 
561             // TODO: request debug device only on debug config?
562             let mut device = ptr::null_mut();
563             let mut cxt = ptr::null_mut();
564             let hr = func(
565                 self.adapter.as_raw() as *mut _,
566                 d3dcommon::D3D_DRIVER_TYPE_UNKNOWN,
567                 ptr::null_mut(),
568                 create_flags,
569                 [feature_level].as_ptr(),
570                 1,
571                 d3d11::D3D11_SDK_VERSION,
572                 &mut device as *mut *mut _ as *mut *mut _,
573                 &mut returned_level as *mut _,
574                 &mut cxt as *mut *mut _ as *mut *mut _,
575             );
576 
577             // NOTE: returns error if adapter argument is non-null and driver
578             // type is not unknown; or if debug device is requested but not
579             // present
580             if !winerror::SUCCEEDED(hr) {
581                 return Err(hal::device::CreationError::InitializationFailed);
582             }
583 
584             info!("feature level={:x}", feature_level);
585 
586             (ComPtr::from_raw(device), ComPtr::from_raw(cxt))
587         };
588 
589         let device = device::Device::new(
590             device,
591             cxt,
592             requested_features,
593             self.memory_properties.clone(),
594         );
595 
596         // TODO: deferred context => 1 cxt/queue?
597         let queue_groups = families
598             .into_iter()
599             .map(|&(_family, prio)| {
600                 assert_eq!(prio.len(), 1);
601                 let mut group = queue::QueueGroup::new(queue::QueueFamilyId(0));
602 
603                 // TODO: multiple queues?
604                 let queue = CommandQueue {
605                     context: device.context.clone(),
606                 };
607                 group.add_queue(queue);
608                 group
609             })
610             .collect();
611 
612         Ok(adapter::Gpu {
613             device,
614             queue_groups,
615         })
616     }
617 
format_properties(&self, fmt: Option<format::Format>) -> format::Properties618     fn format_properties(&self, fmt: Option<format::Format>) -> format::Properties {
619         let idx = fmt.map(|fmt| fmt as usize).unwrap_or(0);
620         self.format_properties[idx]
621     }
622 
image_format_properties( &self, format: format::Format, dimensions: u8, tiling: image::Tiling, usage: image::Usage, view_caps: image::ViewCapabilities, ) -> Option<image::FormatProperties>623     fn image_format_properties(
624         &self,
625         format: format::Format,
626         dimensions: u8,
627         tiling: image::Tiling,
628         usage: image::Usage,
629         view_caps: image::ViewCapabilities,
630     ) -> Option<image::FormatProperties> {
631         conv::map_format(format)?; //filter out unknown formats
632 
633         let supported_usage = {
634             use hal::image::Usage as U;
635             let format_props = &self.format_properties[format as usize];
636             let props = match tiling {
637                 image::Tiling::Optimal => format_props.optimal_tiling,
638                 image::Tiling::Linear => format_props.linear_tiling,
639             };
640             let mut flags = U::empty();
641             // Note: these checks would have been nicer if we had explicit BLIT usage
642             if props.contains(format::ImageFeature::BLIT_SRC) {
643                 flags |= U::TRANSFER_SRC;
644             }
645             if props.contains(format::ImageFeature::BLIT_DST) {
646                 flags |= U::TRANSFER_DST;
647             }
648             if props.contains(format::ImageFeature::SAMPLED) {
649                 flags |= U::SAMPLED;
650             }
651             if props.contains(format::ImageFeature::STORAGE) {
652                 flags |= U::STORAGE;
653             }
654             if props.contains(format::ImageFeature::COLOR_ATTACHMENT) {
655                 flags |= U::COLOR_ATTACHMENT;
656             }
657             if props.contains(format::ImageFeature::DEPTH_STENCIL_ATTACHMENT) {
658                 flags |= U::DEPTH_STENCIL_ATTACHMENT;
659             }
660             flags
661         };
662         if !supported_usage.contains(usage) {
663             return None;
664         }
665 
666         let max_resource_size =
667             (d3d11::D3D11_REQ_RESOURCE_SIZE_IN_MEGABYTES_EXPRESSION_A_TERM as usize) << 20;
668         Some(match tiling {
669             image::Tiling::Optimal => image::FormatProperties {
670                 max_extent: match dimensions {
671                     1 => image::Extent {
672                         width: d3d11::D3D11_REQ_TEXTURE1D_U_DIMENSION,
673                         height: 1,
674                         depth: 1,
675                     },
676                     2 => image::Extent {
677                         width: d3d11::D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION,
678                         height: d3d11::D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION,
679                         depth: 1,
680                     },
681                     3 => image::Extent {
682                         width: d3d11::D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION,
683                         height: d3d11::D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION,
684                         depth: d3d11::D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION,
685                     },
686                     _ => return None,
687                 },
688                 max_levels: d3d11::D3D11_REQ_MIP_LEVELS as _,
689                 max_layers: match dimensions {
690                     1 => d3d11::D3D11_REQ_TEXTURE1D_ARRAY_AXIS_DIMENSION as _,
691                     2 => d3d11::D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION as _,
692                     _ => return None,
693                 },
694                 sample_count_mask: if dimensions == 2
695                     && !view_caps.contains(image::ViewCapabilities::KIND_CUBE)
696                     && (usage.contains(image::Usage::COLOR_ATTACHMENT)
697                         | usage.contains(image::Usage::DEPTH_STENCIL_ATTACHMENT))
698                 {
699                     0x3F //TODO: use D3D12_FEATURE_DATA_FORMAT_SUPPORT
700                 } else {
701                     0x1
702                 },
703                 max_resource_size,
704             },
705             image::Tiling::Linear => image::FormatProperties {
706                 max_extent: match dimensions {
707                     2 => image::Extent {
708                         width: d3d11::D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION,
709                         height: d3d11::D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION,
710                         depth: 1,
711                     },
712                     _ => return None,
713                 },
714                 max_levels: 1,
715                 max_layers: 1,
716                 sample_count_mask: 0x1,
717                 max_resource_size,
718             },
719         })
720     }
721 
memory_properties(&self) -> adapter::MemoryProperties722     fn memory_properties(&self) -> adapter::MemoryProperties {
723         self.memory_properties.clone()
724     }
725 
features(&self) -> hal::Features726     fn features(&self) -> hal::Features {
727         self.features
728     }
729 
hints(&self) -> hal::Hints730     fn hints(&self) -> hal::Hints {
731         self.hints
732     }
733 
limits(&self) -> Limits734     fn limits(&self) -> Limits {
735         self.limits
736     }
737 }
738 
739 struct Presentation {
740     swapchain: ComPtr<IDXGISwapChain>,
741     view: ComPtr<d3d11::ID3D11RenderTargetView>,
742     format: format::Format,
743     size: window::Extent2D,
744 }
745 
746 pub struct Surface {
747     pub(crate) factory: ComPtr<IDXGIFactory>,
748     wnd_handle: HWND,
749     presentation: Option<Presentation>,
750 }
751 
752 impl fmt::Debug for Surface {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result753     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
754         fmt.write_str("Surface")
755     }
756 }
757 
758 unsafe impl Send for Surface {}
759 unsafe impl Sync for Surface {}
760 
761 impl window::Surface<Backend> for Surface {
supports_queue_family(&self, _queue_family: &QueueFamily) -> bool762     fn supports_queue_family(&self, _queue_family: &QueueFamily) -> bool {
763         true
764     }
765 
capabilities(&self, _physical_device: &PhysicalDevice) -> window::SurfaceCapabilities766     fn capabilities(&self, _physical_device: &PhysicalDevice) -> window::SurfaceCapabilities {
767         let current_extent = unsafe {
768             let mut rect: RECT = mem::zeroed();
769             assert_ne!(
770                 0,
771                 GetClientRect(self.wnd_handle as *mut _, &mut rect as *mut RECT)
772             );
773             Some(window::Extent2D {
774                 width: (rect.right - rect.left) as u32,
775                 height: (rect.bottom - rect.top) as u32,
776             })
777         };
778 
779         // TODO: flip swap effects require dx11.1/windows8
780         // NOTE: some swap effects affect msaa capabilities..
781         // TODO: _DISCARD swap effects can only have one image?
782         window::SurfaceCapabilities {
783             present_modes: window::PresentMode::FIFO, //TODO
784             composite_alpha_modes: window::CompositeAlphaMode::OPAQUE, //TODO
785             image_count: 1 ..= 16,                    // TODO:
786             current_extent,
787             extents: window::Extent2D {
788                 width: 16,
789                 height: 16,
790             } ..= window::Extent2D {
791                 width: 4096,
792                 height: 4096,
793             },
794             max_image_layers: 1,
795             usage: image::Usage::COLOR_ATTACHMENT | image::Usage::TRANSFER_SRC,
796         }
797     }
798 
supported_formats(&self, _physical_device: &PhysicalDevice) -> Option<Vec<format::Format>>799     fn supported_formats(&self, _physical_device: &PhysicalDevice) -> Option<Vec<format::Format>> {
800         Some(vec![
801             format::Format::Bgra8Srgb,
802             format::Format::Bgra8Unorm,
803             format::Format::Rgba8Srgb,
804             format::Format::Rgba8Unorm,
805             format::Format::A2b10g10r10Unorm,
806             format::Format::Rgba16Sfloat,
807         ])
808     }
809 }
810 
811 impl window::PresentationSurface<Backend> for Surface {
812     type SwapchainImage = ImageView;
813 
configure_swapchain( &mut self, device: &device::Device, config: window::SwapchainConfig, ) -> Result<(), window::CreationError>814     unsafe fn configure_swapchain(
815         &mut self,
816         device: &device::Device,
817         config: window::SwapchainConfig,
818     ) -> Result<(), window::CreationError> {
819         assert!(image::Usage::COLOR_ATTACHMENT.contains(config.image_usage));
820 
821         let swapchain = match self.presentation.take() {
822             Some(present) => {
823                 if present.format == config.format && present.size == config.extent {
824                     self.presentation = Some(present);
825                     return Ok(());
826                 }
827                 let non_srgb_format = conv::map_format_nosrgb(config.format).unwrap();
828                 drop(present.view);
829                 let result = present.swapchain.ResizeBuffers(
830                     config.image_count,
831                     config.extent.width,
832                     config.extent.height,
833                     non_srgb_format,
834                     0,
835                 );
836                 if result != winerror::S_OK {
837                     error!("ResizeBuffers failed with 0x{:x}", result as u32);
838                     return Err(window::CreationError::WindowInUse(hal::device::WindowInUse));
839                 }
840                 present.swapchain
841             }
842             None => {
843                 let (swapchain, _) =
844                     device.create_swapchain_impl(&config, self.wnd_handle, self.factory.clone())?;
845                 swapchain
846             }
847         };
848 
849         let mut resource: *mut d3d11::ID3D11Resource = ptr::null_mut();
850         assert_eq!(
851             winerror::S_OK,
852             swapchain.GetBuffer(
853                 0 as _,
854                 &d3d11::ID3D11Resource::uuidof(),
855                 &mut resource as *mut *mut _ as *mut *mut _,
856             )
857         );
858 
859         let kind = image::Kind::D2(config.extent.width, config.extent.height, 1, 1);
860         let format = conv::map_format(config.format).unwrap();
861         let decomposed = conv::DecomposedDxgiFormat::from_dxgi_format(format);
862 
863         let view_info = ViewInfo {
864             resource,
865             kind,
866             caps: image::ViewCapabilities::empty(),
867             view_kind: image::ViewKind::D2,
868             format: decomposed.rtv.unwrap(),
869             range: image::SubresourceRange {
870                 aspects: format::Aspects::COLOR,
871                 levels: 0 .. 1,
872                 layers: 0 .. 1,
873             },
874         };
875         let view = device.view_image_as_render_target(&view_info).unwrap();
876 
877         (*resource).Release();
878 
879         self.presentation = Some(Presentation {
880             swapchain,
881             view,
882             format: config.format,
883             size: config.extent,
884         });
885         Ok(())
886     }
887 
unconfigure_swapchain(&mut self, _device: &device::Device)888     unsafe fn unconfigure_swapchain(&mut self, _device: &device::Device) {
889         self.presentation = None;
890     }
891 
acquire_image( &mut self, _timeout_ns: u64, ) -> Result<(ImageView, Option<window::Suboptimal>), window::AcquireError>892     unsafe fn acquire_image(
893         &mut self,
894         _timeout_ns: u64, //TODO: use the timeout
895     ) -> Result<(ImageView, Option<window::Suboptimal>), window::AcquireError> {
896         let present = self.presentation.as_ref().unwrap();
897         let image_view = ImageView {
898             format: present.format,
899             rtv_handle: Some(present.view.clone()),
900             dsv_handle: None,
901             srv_handle: None,
902             uav_handle: None,
903         };
904         Ok((image_view, None))
905     }
906 }
907 
908 pub struct Swapchain {
909     dxgi_swapchain: ComPtr<IDXGISwapChain>,
910 }
911 
912 impl fmt::Debug for Swapchain {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result913     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
914         fmt.write_str("Swapchain")
915     }
916 }
917 
918 unsafe impl Send for Swapchain {}
919 unsafe impl Sync for Swapchain {}
920 
921 impl window::Swapchain<Backend> for Swapchain {
acquire_image( &mut self, _timeout_ns: u64, _semaphore: Option<&Semaphore>, _fence: Option<&Fence>, ) -> Result<(window::SwapImageIndex, Option<window::Suboptimal>), window::AcquireError>922     unsafe fn acquire_image(
923         &mut self,
924         _timeout_ns: u64,
925         _semaphore: Option<&Semaphore>,
926         _fence: Option<&Fence>,
927     ) -> Result<(window::SwapImageIndex, Option<window::Suboptimal>), window::AcquireError> {
928         // TODO: non-`_DISCARD` swap effects have more than one buffer, `FLIP`
929         //       effects are dxgi 1.3 (w10+?) in which case there is
930         //       `GetCurrentBackBufferIndex()` on the swapchain
931         Ok((0, None))
932     }
933 }
934 
935 #[derive(Debug, Clone, Copy)]
936 pub struct QueueFamily;
937 
938 impl queue::QueueFamily for QueueFamily {
queue_type(&self) -> queue::QueueType939     fn queue_type(&self) -> queue::QueueType {
940         queue::QueueType::General
941     }
max_queues(&self) -> usize942     fn max_queues(&self) -> usize {
943         1
944     }
id(&self) -> queue::QueueFamilyId945     fn id(&self) -> queue::QueueFamilyId {
946         queue::QueueFamilyId(0)
947     }
948 }
949 
950 #[derive(Clone)]
951 pub struct CommandQueue {
952     context: ComPtr<d3d11::ID3D11DeviceContext>,
953 }
954 
955 impl fmt::Debug for CommandQueue {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result956     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
957         fmt.write_str("CommandQueue")
958     }
959 }
960 
961 unsafe impl Send for CommandQueue {}
962 unsafe impl Sync for CommandQueue {}
963 
964 impl queue::CommandQueue<Backend> for CommandQueue {
submit<'a, T, Ic, S, Iw, Is>( &mut self, submission: queue::Submission<Ic, Iw, Is>, fence: Option<&Fence>, ) where T: 'a + Borrow<CommandBuffer>, Ic: IntoIterator<Item = &'a T>, S: 'a + Borrow<Semaphore>, Iw: IntoIterator<Item = (&'a S, pso::PipelineStage)>, Is: IntoIterator<Item = &'a S>,965     unsafe fn submit<'a, T, Ic, S, Iw, Is>(
966         &mut self,
967         submission: queue::Submission<Ic, Iw, Is>,
968         fence: Option<&Fence>,
969     ) where
970         T: 'a + Borrow<CommandBuffer>,
971         Ic: IntoIterator<Item = &'a T>,
972         S: 'a + Borrow<Semaphore>,
973         Iw: IntoIterator<Item = (&'a S, pso::PipelineStage)>,
974         Is: IntoIterator<Item = &'a S>,
975     {
976         let _scope = debug_scope!(&self.context, "Submit(fence={:?})", fence);
977         for cmd_buf in submission.command_buffers {
978             let cmd_buf = cmd_buf.borrow();
979 
980             let _scope = debug_scope!(
981                 &self.context,
982                 "CommandBuffer ({}/{})",
983                 cmd_buf.flush_coherent_memory.len(),
984                 cmd_buf.invalidate_coherent_memory.len()
985             );
986 
987             {
988                 let _scope = debug_scope!(&self.context, "Pre-Exec: Flush");
989                 for sync in &cmd_buf.flush_coherent_memory {
990                     sync.do_flush(&self.context);
991                 }
992             }
993             self.context
994                 .ExecuteCommandList(cmd_buf.as_raw_list().as_raw(), FALSE);
995             {
996                 let _scope = debug_scope!(&self.context, "Post-Exec: Invalidate");
997                 for sync in &cmd_buf.invalidate_coherent_memory {
998                     sync.do_invalidate(&self.context);
999                 }
1000             }
1001         }
1002 
1003         if let Some(fence) = fence {
1004             *fence.mutex.lock() = true;
1005             fence.condvar.notify_all();
1006         }
1007     }
1008 
present<'a, W, Is, S, Iw>( &mut self, swapchains: Is, _wait_semaphores: Iw, ) -> Result<Option<window::Suboptimal>, window::PresentError> where W: 'a + Borrow<Swapchain>, Is: IntoIterator<Item = (&'a W, window::SwapImageIndex)>, S: 'a + Borrow<Semaphore>, Iw: IntoIterator<Item = &'a S>,1009     unsafe fn present<'a, W, Is, S, Iw>(
1010         &mut self,
1011         swapchains: Is,
1012         _wait_semaphores: Iw,
1013     ) -> Result<Option<window::Suboptimal>, window::PresentError>
1014     where
1015         W: 'a + Borrow<Swapchain>,
1016         Is: IntoIterator<Item = (&'a W, window::SwapImageIndex)>,
1017         S: 'a + Borrow<Semaphore>,
1018         Iw: IntoIterator<Item = &'a S>,
1019     {
1020         for (swapchain, _idx) in swapchains {
1021             swapchain.borrow().dxgi_swapchain.Present(1, 0);
1022         }
1023 
1024         Ok(None)
1025     }
1026 
present_surface( &mut self, surface: &mut Surface, _image: ImageView, _wait_semaphore: Option<&Semaphore>, ) -> Result<Option<window::Suboptimal>, window::PresentError>1027     unsafe fn present_surface(
1028         &mut self,
1029         surface: &mut Surface,
1030         _image: ImageView,
1031         _wait_semaphore: Option<&Semaphore>,
1032     ) -> Result<Option<window::Suboptimal>, window::PresentError> {
1033         surface
1034             .presentation
1035             .as_ref()
1036             .unwrap()
1037             .swapchain
1038             .Present(1, 0);
1039         Ok(None)
1040     }
1041 
wait_idle(&self) -> Result<(), hal::device::OutOfMemory>1042     fn wait_idle(&self) -> Result<(), hal::device::OutOfMemory> {
1043         // unimplemented!()
1044         Ok(())
1045     }
1046 }
1047 
1048 #[derive(Debug)]
1049 pub struct AttachmentClear {
1050     subpass_id: Option<pass::SubpassId>,
1051     attachment_id: usize,
1052     raw: command::AttachmentClear,
1053 }
1054 
1055 #[derive(Debug)]
1056 pub struct RenderPassCache {
1057     pub render_pass: RenderPass,
1058     pub framebuffer: Framebuffer,
1059     pub attachment_clear_values: Vec<AttachmentClear>,
1060     pub target_rect: pso::Rect,
1061     pub current_subpass: pass::SubpassId,
1062 }
1063 
1064 impl RenderPassCache {
start_subpass( &mut self, internal: &mut internal::Internal, context: &ComPtr<d3d11::ID3D11DeviceContext>, cache: &mut CommandBufferState, )1065     pub fn start_subpass(
1066         &mut self,
1067         internal: &mut internal::Internal,
1068         context: &ComPtr<d3d11::ID3D11DeviceContext>,
1069         cache: &mut CommandBufferState,
1070     ) {
1071         let attachments = self
1072             .attachment_clear_values
1073             .iter()
1074             .filter(|clear| clear.subpass_id == Some(self.current_subpass))
1075             .map(|clear| clear.raw);
1076 
1077         cache
1078             .dirty_flag
1079             .insert(DirtyStateFlag::GRAPHICS_PIPELINE | DirtyStateFlag::VIEWPORTS);
1080         internal.clear_attachments(
1081             context,
1082             attachments,
1083             &[pso::ClearRect {
1084                 rect: self.target_rect,
1085                 layers: 0 .. 1,
1086             }],
1087             &self,
1088         );
1089 
1090         let subpass = &self.render_pass.subpasses[self.current_subpass as usize];
1091         let color_views = subpass
1092             .color_attachments
1093             .iter()
1094             .map(|&(id, _)| {
1095                 self.framebuffer.attachments[id]
1096                     .rtv_handle
1097                     .clone()
1098                     .unwrap()
1099                     .as_raw()
1100             })
1101             .collect::<Vec<_>>();
1102         let ds_view = match subpass.depth_stencil_attachment {
1103             Some((id, _)) => Some(
1104                 self.framebuffer.attachments[id]
1105                     .dsv_handle
1106                     .clone()
1107                     .unwrap()
1108                     .as_raw(),
1109             ),
1110             None => None,
1111         };
1112 
1113         cache.set_render_targets(&color_views, ds_view);
1114         cache.bind(context);
1115     }
1116 
next_subpass(&mut self)1117     pub fn next_subpass(&mut self) {
1118         self.current_subpass += 1;
1119     }
1120 }
1121 
1122 bitflags! {
1123     struct DirtyStateFlag : u32 {
1124         const RENDER_TARGETS = (1 << 1);
1125         const VERTEX_BUFFERS = (1 << 2);
1126         const GRAPHICS_PIPELINE = (1 << 3);
1127         const VIEWPORTS = (1 << 4);
1128         const BLEND_STATE = (1 << 5);
1129     }
1130 }
1131 
1132 pub struct CommandBufferState {
1133     dirty_flag: DirtyStateFlag,
1134 
1135     render_target_len: u32,
1136     render_targets: [*mut d3d11::ID3D11RenderTargetView; 8],
1137     depth_target: Option<*mut d3d11::ID3D11DepthStencilView>,
1138     graphics_pipeline: Option<GraphicsPipeline>,
1139 
1140     // a bitmask that keeps track of what vertex buffer bindings have been "bound" into
1141     // our vec
1142     bound_bindings: u32,
1143     // a bitmask that hold the required binding slots to be bound for the currently
1144     // bound pipeline
1145     required_bindings: Option<u32>,
1146     // the highest binding number in currently bound pipeline
1147     max_bindings: Option<u32>,
1148     viewports: Vec<d3d11::D3D11_VIEWPORT>,
1149     vertex_buffers: Vec<*mut d3d11::ID3D11Buffer>,
1150     vertex_offsets: Vec<u32>,
1151     vertex_strides: Vec<u32>,
1152     blend_factor: Option<[f32; 4]>,
1153     // we can only support one face (rather, both faces must have the same value)
1154     stencil_ref: Option<pso::StencilValue>,
1155     stencil_read_mask: Option<pso::StencilValue>,
1156     stencil_write_mask: Option<pso::StencilValue>,
1157     current_blend: Option<*mut d3d11::ID3D11BlendState>,
1158 }
1159 
1160 impl fmt::Debug for CommandBufferState {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result1161     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1162         fmt.write_str("CommandBufferState")
1163     }
1164 }
1165 
1166 impl CommandBufferState {
new() -> Self1167     fn new() -> Self {
1168         CommandBufferState {
1169             dirty_flag: DirtyStateFlag::empty(),
1170             render_target_len: 0,
1171             render_targets: [ptr::null_mut(); 8],
1172             depth_target: None,
1173             graphics_pipeline: None,
1174             bound_bindings: 0,
1175             required_bindings: None,
1176             max_bindings: None,
1177             viewports: Vec::new(),
1178             vertex_buffers: Vec::new(),
1179             vertex_offsets: Vec::new(),
1180             vertex_strides: Vec::new(),
1181             blend_factor: None,
1182             stencil_ref: None,
1183             stencil_read_mask: None,
1184             stencil_write_mask: None,
1185             current_blend: None,
1186         }
1187     }
1188 
clear(&mut self)1189     fn clear(&mut self) {
1190         self.render_target_len = 0;
1191         self.depth_target = None;
1192         self.graphics_pipeline = None;
1193         self.bound_bindings = 0;
1194         self.required_bindings = None;
1195         self.max_bindings = None;
1196         self.viewports.clear();
1197         self.vertex_buffers.clear();
1198         self.vertex_offsets.clear();
1199         self.vertex_strides.clear();
1200         self.blend_factor = None;
1201         self.stencil_ref = None;
1202         self.stencil_read_mask = None;
1203         self.stencil_write_mask = None;
1204         self.current_blend = None;
1205     }
1206 
set_vertex_buffer( &mut self, index: usize, offset: u32, buffer: *mut d3d11::ID3D11Buffer, )1207     pub fn set_vertex_buffer(
1208         &mut self,
1209         index: usize,
1210         offset: u32,
1211         buffer: *mut d3d11::ID3D11Buffer,
1212     ) {
1213         self.bound_bindings |= 1 << index as u32;
1214 
1215         if index >= self.vertex_buffers.len() {
1216             self.vertex_buffers.push(buffer);
1217             self.vertex_offsets.push(offset);
1218         } else {
1219             self.vertex_buffers[index] = buffer;
1220             self.vertex_offsets[index] = offset;
1221         }
1222 
1223         self.dirty_flag.insert(DirtyStateFlag::VERTEX_BUFFERS);
1224     }
1225 
bind_vertex_buffers(&mut self, context: &ComPtr<d3d11::ID3D11DeviceContext>)1226     pub fn bind_vertex_buffers(&mut self, context: &ComPtr<d3d11::ID3D11DeviceContext>) {
1227         if let Some(binding_count) = self.max_bindings {
1228             if self.vertex_buffers.len() >= binding_count as usize
1229                 && self.vertex_strides.len() >= binding_count as usize
1230             {
1231                 unsafe {
1232                     context.IASetVertexBuffers(
1233                         0,
1234                         binding_count,
1235                         self.vertex_buffers.as_ptr(),
1236                         self.vertex_strides.as_ptr(),
1237                         self.vertex_offsets.as_ptr(),
1238                     );
1239                 }
1240 
1241                 self.dirty_flag.remove(DirtyStateFlag::VERTEX_BUFFERS);
1242             }
1243         }
1244     }
1245 
set_viewports(&mut self, viewports: &[d3d11::D3D11_VIEWPORT])1246     pub fn set_viewports(&mut self, viewports: &[d3d11::D3D11_VIEWPORT]) {
1247         self.viewports.clear();
1248         self.viewports.extend(viewports);
1249 
1250         self.dirty_flag.insert(DirtyStateFlag::VIEWPORTS);
1251     }
1252 
bind_viewports(&mut self, context: &ComPtr<d3d11::ID3D11DeviceContext>)1253     pub fn bind_viewports(&mut self, context: &ComPtr<d3d11::ID3D11DeviceContext>) {
1254         if let Some(ref pipeline) = self.graphics_pipeline {
1255             if let Some(ref viewport) = pipeline.baked_states.viewport {
1256                 unsafe {
1257                     context.RSSetViewports(1, [conv::map_viewport(&viewport)].as_ptr());
1258                 }
1259             } else {
1260                 unsafe {
1261                     context.RSSetViewports(self.viewports.len() as u32, self.viewports.as_ptr());
1262                 }
1263             }
1264         } else {
1265             unsafe {
1266                 context.RSSetViewports(self.viewports.len() as u32, self.viewports.as_ptr());
1267             }
1268         }
1269 
1270         self.dirty_flag.remove(DirtyStateFlag::VIEWPORTS);
1271     }
1272 
set_render_targets( &mut self, render_targets: &[*mut d3d11::ID3D11RenderTargetView], depth_target: Option<*mut d3d11::ID3D11DepthStencilView>, )1273     pub fn set_render_targets(
1274         &mut self,
1275         render_targets: &[*mut d3d11::ID3D11RenderTargetView],
1276         depth_target: Option<*mut d3d11::ID3D11DepthStencilView>,
1277     ) {
1278         for (idx, &rt) in render_targets.iter().enumerate() {
1279             self.render_targets[idx] = rt;
1280         }
1281 
1282         self.render_target_len = render_targets.len() as u32;
1283         self.depth_target = depth_target;
1284 
1285         self.dirty_flag.insert(DirtyStateFlag::RENDER_TARGETS);
1286     }
1287 
bind_render_targets(&mut self, context: &ComPtr<d3d11::ID3D11DeviceContext>)1288     pub fn bind_render_targets(&mut self, context: &ComPtr<d3d11::ID3D11DeviceContext>) {
1289         unsafe {
1290             context.OMSetRenderTargets(
1291                 self.render_target_len,
1292                 self.render_targets.as_ptr(),
1293                 if let Some(dsv) = self.depth_target {
1294                     dsv
1295                 } else {
1296                     ptr::null_mut()
1297                 },
1298             );
1299         }
1300 
1301         self.dirty_flag.remove(DirtyStateFlag::RENDER_TARGETS);
1302     }
1303 
set_blend_factor(&mut self, factor: [f32; 4])1304     pub fn set_blend_factor(&mut self, factor: [f32; 4]) {
1305         self.blend_factor = Some(factor);
1306 
1307         self.dirty_flag.insert(DirtyStateFlag::BLEND_STATE);
1308     }
1309 
bind_blend_state(&mut self, context: &ComPtr<d3d11::ID3D11DeviceContext>)1310     pub fn bind_blend_state(&mut self, context: &ComPtr<d3d11::ID3D11DeviceContext>) {
1311         if let Some(blend) = self.current_blend {
1312             let blend_color = if let Some(ref pipeline) = self.graphics_pipeline {
1313                 pipeline
1314                     .baked_states
1315                     .blend_color
1316                     .or(self.blend_factor)
1317                     .unwrap_or([0f32; 4])
1318             } else {
1319                 self.blend_factor.unwrap_or([0f32; 4])
1320             };
1321 
1322             // TODO: MSAA
1323             unsafe {
1324                 context.OMSetBlendState(blend, &blend_color, !0);
1325             }
1326 
1327             self.dirty_flag.remove(DirtyStateFlag::BLEND_STATE);
1328         }
1329     }
1330 
set_graphics_pipeline(&mut self, pipeline: GraphicsPipeline)1331     pub fn set_graphics_pipeline(&mut self, pipeline: GraphicsPipeline) {
1332         self.graphics_pipeline = Some(pipeline);
1333 
1334         self.dirty_flag.insert(DirtyStateFlag::GRAPHICS_PIPELINE);
1335     }
1336 
bind_graphics_pipeline(&mut self, context: &ComPtr<d3d11::ID3D11DeviceContext>)1337     pub fn bind_graphics_pipeline(&mut self, context: &ComPtr<d3d11::ID3D11DeviceContext>) {
1338         if let Some(ref pipeline) = self.graphics_pipeline {
1339             self.vertex_strides.clear();
1340             self.vertex_strides.extend(&pipeline.strides);
1341 
1342             self.required_bindings = Some(pipeline.required_bindings);
1343             self.max_bindings = Some(pipeline.max_vertex_bindings);
1344         };
1345 
1346         self.bind_vertex_buffers(context);
1347 
1348         if let Some(ref pipeline) = self.graphics_pipeline {
1349             unsafe {
1350                 context.IASetPrimitiveTopology(pipeline.topology);
1351                 context.IASetInputLayout(pipeline.input_layout.as_raw());
1352 
1353                 context.VSSetShader(pipeline.vs.as_raw(), ptr::null_mut(), 0);
1354                 if let Some(ref ps) = pipeline.ps {
1355                     context.PSSetShader(ps.as_raw(), ptr::null_mut(), 0);
1356                 }
1357                 if let Some(ref gs) = pipeline.gs {
1358                     context.GSSetShader(gs.as_raw(), ptr::null_mut(), 0);
1359                 }
1360                 if let Some(ref hs) = pipeline.hs {
1361                     context.HSSetShader(hs.as_raw(), ptr::null_mut(), 0);
1362                 }
1363                 if let Some(ref ds) = pipeline.ds {
1364                     context.DSSetShader(ds.as_raw(), ptr::null_mut(), 0);
1365                 }
1366 
1367                 context.RSSetState(pipeline.rasterizer_state.as_raw());
1368                 if let Some(ref viewport) = pipeline.baked_states.viewport {
1369                     context.RSSetViewports(1, [conv::map_viewport(&viewport)].as_ptr());
1370                 }
1371                 if let Some(ref scissor) = pipeline.baked_states.scissor {
1372                     context.RSSetScissorRects(1, [conv::map_rect(&scissor)].as_ptr());
1373                 }
1374 
1375                 if let Some((ref state, reference)) = pipeline.depth_stencil_state {
1376                     let stencil_ref = if let pso::State::Static(reference) = reference {
1377                         reference
1378                     } else {
1379                         self.stencil_ref.unwrap_or(0)
1380                     };
1381 
1382                     context.OMSetDepthStencilState(state.as_raw(), stencil_ref);
1383                 }
1384                 self.current_blend = Some(pipeline.blend_state.as_raw());
1385             }
1386         };
1387 
1388         self.bind_blend_state(context);
1389 
1390         self.dirty_flag.remove(DirtyStateFlag::GRAPHICS_PIPELINE);
1391     }
1392 
bind(&mut self, context: &ComPtr<d3d11::ID3D11DeviceContext>)1393     pub fn bind(&mut self, context: &ComPtr<d3d11::ID3D11DeviceContext>) {
1394         if self.dirty_flag.contains(DirtyStateFlag::RENDER_TARGETS) {
1395             self.bind_render_targets(context);
1396         }
1397 
1398         if self.dirty_flag.contains(DirtyStateFlag::GRAPHICS_PIPELINE) {
1399             self.bind_graphics_pipeline(context);
1400         }
1401 
1402         if self.dirty_flag.contains(DirtyStateFlag::VERTEX_BUFFERS) {
1403             self.bind_vertex_buffers(context);
1404         }
1405 
1406         if self.dirty_flag.contains(DirtyStateFlag::VIEWPORTS) {
1407             self.bind_viewports(context);
1408         }
1409     }
1410 }
1411 
1412 pub struct CommandBuffer {
1413     // TODO: better way of sharing
1414     internal: internal::Internal,
1415     context: ComPtr<d3d11::ID3D11DeviceContext>,
1416     list: RefCell<Option<ComPtr<d3d11::ID3D11CommandList>>>,
1417 
1418     // since coherent memory needs to be synchronized at submission, we need to gather up all
1419     // coherent resources that are used in the command buffer and flush/invalidate them accordingly
1420     // before executing.
1421     flush_coherent_memory: Vec<MemoryFlush>,
1422     invalidate_coherent_memory: Vec<MemoryInvalidate>,
1423 
1424     // holds information about the active render pass
1425     render_pass_cache: Option<RenderPassCache>,
1426 
1427     cache: CommandBufferState,
1428 
1429     one_time_submit: bool,
1430 }
1431 
1432 impl fmt::Debug for CommandBuffer {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result1433     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1434         fmt.write_str("CommandBuffer")
1435     }
1436 }
1437 
1438 unsafe impl Send for CommandBuffer {}
1439 unsafe impl Sync for CommandBuffer {}
1440 
1441 impl CommandBuffer {
create_deferred(device: ComPtr<d3d11::ID3D11Device>, internal: internal::Internal) -> Self1442     fn create_deferred(device: ComPtr<d3d11::ID3D11Device>, internal: internal::Internal) -> Self {
1443         let mut context: *mut d3d11::ID3D11DeviceContext = ptr::null_mut();
1444         let hr =
1445             unsafe { device.CreateDeferredContext(0, &mut context as *mut *mut _ as *mut *mut _) };
1446         assert_eq!(hr, winerror::S_OK);
1447 
1448         CommandBuffer {
1449             internal,
1450             context: unsafe { ComPtr::from_raw(context) },
1451             list: RefCell::new(None),
1452             flush_coherent_memory: Vec::new(),
1453             invalidate_coherent_memory: Vec::new(),
1454             render_pass_cache: None,
1455             cache: CommandBufferState::new(),
1456             one_time_submit: false,
1457         }
1458     }
1459 
as_raw_list(&self) -> ComPtr<d3d11::ID3D11CommandList>1460     fn as_raw_list(&self) -> ComPtr<d3d11::ID3D11CommandList> {
1461         if self.one_time_submit {
1462             self.list.replace(None).unwrap()
1463         } else {
1464             self.list.borrow().clone().unwrap()
1465         }
1466     }
1467 
defer_coherent_flush(&mut self, buffer: &Buffer)1468     fn defer_coherent_flush(&mut self, buffer: &Buffer) {
1469         if !self
1470             .flush_coherent_memory
1471             .iter()
1472             .any(|m| m.buffer == buffer.internal.raw)
1473         {
1474             self.flush_coherent_memory.push(MemoryFlush {
1475                 host_memory: buffer.host_ptr,
1476                 sync_range: SyncRange::Whole,
1477                 buffer: buffer.internal.raw,
1478             });
1479         }
1480     }
1481 
defer_coherent_invalidate(&mut self, buffer: &Buffer)1482     fn defer_coherent_invalidate(&mut self, buffer: &Buffer) {
1483         if !self
1484             .invalidate_coherent_memory
1485             .iter()
1486             .any(|m| m.buffer == buffer.internal.raw)
1487         {
1488             self.invalidate_coherent_memory.push(MemoryInvalidate {
1489                 working_buffer: Some(self.internal.working_buffer.clone()),
1490                 working_buffer_size: self.internal.working_buffer_size,
1491                 host_memory: buffer.host_ptr,
1492                 sync_range: buffer.bound_range.clone(),
1493                 buffer: buffer.internal.raw,
1494             });
1495         }
1496     }
1497 
reset(&mut self)1498     fn reset(&mut self) {
1499         self.flush_coherent_memory.clear();
1500         self.invalidate_coherent_memory.clear();
1501         self.render_pass_cache = None;
1502         self.cache.clear();
1503     }
1504 }
1505 
1506 impl command::CommandBuffer<Backend> for CommandBuffer {
begin( &mut self, flags: command::CommandBufferFlags, _info: command::CommandBufferInheritanceInfo<Backend>, )1507     unsafe fn begin(
1508         &mut self,
1509         flags: command::CommandBufferFlags,
1510         _info: command::CommandBufferInheritanceInfo<Backend>,
1511     ) {
1512         self.one_time_submit = flags.contains(command::CommandBufferFlags::ONE_TIME_SUBMIT);
1513         self.reset();
1514     }
1515 
finish(&mut self)1516     unsafe fn finish(&mut self) {
1517         let mut list = ptr::null_mut();
1518         let hr = self
1519             .context
1520             .FinishCommandList(FALSE, &mut list as *mut *mut _ as *mut *mut _);
1521         assert_eq!(hr, winerror::S_OK);
1522 
1523         self.list.replace(Some(ComPtr::from_raw(list)));
1524     }
1525 
reset(&mut self, _release_resources: bool)1526     unsafe fn reset(&mut self, _release_resources: bool) {
1527         self.reset();
1528     }
1529 
begin_render_pass<T>( &mut self, render_pass: &RenderPass, framebuffer: &Framebuffer, target_rect: pso::Rect, clear_values: T, _first_subpass: command::SubpassContents, ) where T: IntoIterator, T::Item: Borrow<command::ClearValue>,1530     unsafe fn begin_render_pass<T>(
1531         &mut self,
1532         render_pass: &RenderPass,
1533         framebuffer: &Framebuffer,
1534         target_rect: pso::Rect,
1535         clear_values: T,
1536         _first_subpass: command::SubpassContents,
1537     ) where
1538         T: IntoIterator,
1539         T::Item: Borrow<command::ClearValue>,
1540     {
1541         use pass::AttachmentLoadOp as Alo;
1542 
1543         let mut clear_iter = clear_values.into_iter();
1544         let mut attachment_clears = Vec::new();
1545 
1546         for (idx, attachment) in render_pass.attachments.iter().enumerate() {
1547             //let attachment = render_pass.attachments[attachment_ref];
1548             let format = attachment.format.unwrap();
1549 
1550             let subpass_id = render_pass
1551                 .subpasses
1552                 .iter()
1553                 .position(|sp| sp.is_using(idx))
1554                 .map(|i| i as pass::SubpassId);
1555 
1556             if attachment.has_clears() {
1557                 let value = *clear_iter.next().unwrap().borrow();
1558 
1559                 match (attachment.ops.load, attachment.stencil_ops.load) {
1560                     (Alo::Clear, Alo::Clear) if format.is_depth() => {
1561                         attachment_clears.push(AttachmentClear {
1562                             subpass_id,
1563                             attachment_id: idx,
1564                             raw: command::AttachmentClear::DepthStencil {
1565                                 depth: Some(value.depth_stencil.depth),
1566                                 stencil: Some(value.depth_stencil.stencil),
1567                             },
1568                         });
1569                     }
1570                     (Alo::Clear, Alo::Clear) => {
1571                         attachment_clears.push(AttachmentClear {
1572                             subpass_id,
1573                             attachment_id: idx,
1574                             raw: command::AttachmentClear::Color {
1575                                 index: idx,
1576                                 value: value.color,
1577                             },
1578                         });
1579 
1580                         attachment_clears.push(AttachmentClear {
1581                             subpass_id,
1582                             attachment_id: idx,
1583                             raw: command::AttachmentClear::DepthStencil {
1584                                 depth: None,
1585                                 stencil: Some(value.depth_stencil.stencil),
1586                             },
1587                         });
1588                     }
1589                     (Alo::Clear, _) if format.is_depth() => {
1590                         attachment_clears.push(AttachmentClear {
1591                             subpass_id,
1592                             attachment_id: idx,
1593                             raw: command::AttachmentClear::DepthStencil {
1594                                 depth: Some(value.depth_stencil.depth),
1595                                 stencil: None,
1596                             },
1597                         });
1598                     }
1599                     (Alo::Clear, _) => {
1600                         attachment_clears.push(AttachmentClear {
1601                             subpass_id,
1602                             attachment_id: idx,
1603                             raw: command::AttachmentClear::Color {
1604                                 index: idx,
1605                                 value: value.color,
1606                             },
1607                         });
1608                     }
1609                     (_, Alo::Clear) => {
1610                         attachment_clears.push(AttachmentClear {
1611                             subpass_id,
1612                             attachment_id: idx,
1613                             raw: command::AttachmentClear::DepthStencil {
1614                                 depth: None,
1615                                 stencil: Some(value.depth_stencil.stencil),
1616                             },
1617                         });
1618                     }
1619                     _ => {}
1620                 }
1621             }
1622         }
1623 
1624         self.render_pass_cache = Some(RenderPassCache {
1625             render_pass: render_pass.clone(),
1626             framebuffer: framebuffer.clone(),
1627             attachment_clear_values: attachment_clears,
1628             target_rect,
1629             current_subpass: 0,
1630         });
1631 
1632         if let Some(ref mut current_render_pass) = self.render_pass_cache {
1633             current_render_pass.start_subpass(&mut self.internal, &self.context, &mut self.cache);
1634         }
1635     }
1636 
next_subpass(&mut self, _contents: command::SubpassContents)1637     unsafe fn next_subpass(&mut self, _contents: command::SubpassContents) {
1638         if let Some(ref mut current_render_pass) = self.render_pass_cache {
1639             // TODO: resolve msaa
1640             current_render_pass.next_subpass();
1641             current_render_pass.start_subpass(&mut self.internal, &self.context, &mut self.cache);
1642         }
1643     }
1644 
end_render_pass(&mut self)1645     unsafe fn end_render_pass(&mut self) {
1646         self.context
1647             .OMSetRenderTargets(8, [ptr::null_mut(); 8].as_ptr(), ptr::null_mut());
1648 
1649         self.render_pass_cache = None;
1650     }
1651 
pipeline_barrier<'a, T>( &mut self, _stages: Range<pso::PipelineStage>, _dependencies: memory::Dependencies, _barriers: T, ) where T: IntoIterator, T::Item: Borrow<memory::Barrier<'a, Backend>>,1652     unsafe fn pipeline_barrier<'a, T>(
1653         &mut self,
1654         _stages: Range<pso::PipelineStage>,
1655         _dependencies: memory::Dependencies,
1656         _barriers: T,
1657     ) where
1658         T: IntoIterator,
1659         T::Item: Borrow<memory::Barrier<'a, Backend>>,
1660     {
1661         // TODO: should we track and assert on resource states?
1662         // unimplemented!()
1663     }
1664 
clear_image<T>( &mut self, image: &Image, _: image::Layout, value: command::ClearValue, subresource_ranges: T, ) where T: IntoIterator, T::Item: Borrow<image::SubresourceRange>,1665     unsafe fn clear_image<T>(
1666         &mut self,
1667         image: &Image,
1668         _: image::Layout,
1669         value: command::ClearValue,
1670         subresource_ranges: T,
1671     ) where
1672         T: IntoIterator,
1673         T::Item: Borrow<image::SubresourceRange>,
1674     {
1675         for range in subresource_ranges {
1676             let range = range.borrow();
1677 
1678             // TODO: clear Int/Uint depending on format
1679             if range.aspects.contains(format::Aspects::COLOR) {
1680                 for layer in range.layers.clone() {
1681                     for level in range.levels.clone() {
1682                         self.context.ClearRenderTargetView(
1683                             image.get_rtv(level, layer).unwrap().as_raw(),
1684                             &value.color.float32,
1685                         );
1686                     }
1687                 }
1688             }
1689 
1690             let mut depth_stencil_flags = 0;
1691             if range.aspects.contains(format::Aspects::DEPTH) {
1692                 depth_stencil_flags |= d3d11::D3D11_CLEAR_DEPTH;
1693             }
1694 
1695             if range.aspects.contains(format::Aspects::STENCIL) {
1696                 depth_stencil_flags |= d3d11::D3D11_CLEAR_STENCIL;
1697             }
1698 
1699             if depth_stencil_flags != 0 {
1700                 for layer in range.layers.clone() {
1701                     for level in range.levels.clone() {
1702                         self.context.ClearDepthStencilView(
1703                             image.get_dsv(level, layer).unwrap().as_raw(),
1704                             depth_stencil_flags,
1705                             value.depth_stencil.depth,
1706                             value.depth_stencil.stencil as _,
1707                         );
1708                     }
1709                 }
1710             }
1711         }
1712     }
1713 
clear_attachments<T, U>(&mut self, clears: T, rects: U) where T: IntoIterator, T::Item: Borrow<command::AttachmentClear>, U: IntoIterator, U::Item: Borrow<pso::ClearRect>,1714     unsafe fn clear_attachments<T, U>(&mut self, clears: T, rects: U)
1715     where
1716         T: IntoIterator,
1717         T::Item: Borrow<command::AttachmentClear>,
1718         U: IntoIterator,
1719         U::Item: Borrow<pso::ClearRect>,
1720     {
1721         if let Some(ref pass) = self.render_pass_cache {
1722             self.cache.dirty_flag.insert(
1723                 DirtyStateFlag::GRAPHICS_PIPELINE
1724                     | DirtyStateFlag::VIEWPORTS
1725                     | DirtyStateFlag::RENDER_TARGETS,
1726             );
1727             self.internal
1728                 .clear_attachments(&self.context, clears, rects, pass);
1729             self.cache.bind(&self.context);
1730         } else {
1731             panic!("`clear_attachments` can only be called inside a renderpass")
1732         }
1733     }
1734 
resolve_image<T>( &mut self, _src: &Image, _src_layout: image::Layout, _dst: &Image, _dst_layout: image::Layout, _regions: T, ) where T: IntoIterator, T::Item: Borrow<command::ImageResolve>,1735     unsafe fn resolve_image<T>(
1736         &mut self,
1737         _src: &Image,
1738         _src_layout: image::Layout,
1739         _dst: &Image,
1740         _dst_layout: image::Layout,
1741         _regions: T,
1742     ) where
1743         T: IntoIterator,
1744         T::Item: Borrow<command::ImageResolve>,
1745     {
1746         unimplemented!()
1747     }
1748 
blit_image<T>( &mut self, src: &Image, _src_layout: image::Layout, dst: &Image, _dst_layout: image::Layout, filter: image::Filter, regions: T, ) where T: IntoIterator, T::Item: Borrow<command::ImageBlit>,1749     unsafe fn blit_image<T>(
1750         &mut self,
1751         src: &Image,
1752         _src_layout: image::Layout,
1753         dst: &Image,
1754         _dst_layout: image::Layout,
1755         filter: image::Filter,
1756         regions: T,
1757     ) where
1758         T: IntoIterator,
1759         T::Item: Borrow<command::ImageBlit>,
1760     {
1761         self.cache
1762             .dirty_flag
1763             .insert(DirtyStateFlag::GRAPHICS_PIPELINE);
1764 
1765         self.internal
1766             .blit_2d_image(&self.context, src, dst, filter, regions);
1767 
1768         self.cache.bind(&self.context);
1769     }
1770 
bind_index_buffer(&mut self, ibv: buffer::IndexBufferView<Backend>)1771     unsafe fn bind_index_buffer(&mut self, ibv: buffer::IndexBufferView<Backend>) {
1772         self.context.IASetIndexBuffer(
1773             ibv.buffer.internal.raw,
1774             conv::map_index_type(ibv.index_type),
1775             ibv.range.offset as u32,
1776         );
1777     }
1778 
bind_vertex_buffers<I, T>(&mut self, first_binding: pso::BufferIndex, buffers: I) where I: IntoIterator<Item = (T, buffer::SubRange)>, T: Borrow<Buffer>,1779     unsafe fn bind_vertex_buffers<I, T>(&mut self, first_binding: pso::BufferIndex, buffers: I)
1780     where
1781         I: IntoIterator<Item = (T, buffer::SubRange)>,
1782         T: Borrow<Buffer>,
1783     {
1784         for (i, (buf, sub)) in buffers.into_iter().enumerate() {
1785             let idx = i + first_binding as usize;
1786             let buf = buf.borrow();
1787 
1788             if buf.properties.contains(memory::Properties::COHERENT) {
1789                 self.defer_coherent_flush(buf);
1790             }
1791 
1792             self.cache
1793                 .set_vertex_buffer(idx, sub.offset as u32, buf.internal.raw);
1794         }
1795 
1796         self.cache.bind_vertex_buffers(&self.context);
1797     }
1798 
set_viewports<T>(&mut self, _first_viewport: u32, viewports: T) where T: IntoIterator, T::Item: Borrow<pso::Viewport>,1799     unsafe fn set_viewports<T>(&mut self, _first_viewport: u32, viewports: T)
1800     where
1801         T: IntoIterator,
1802         T::Item: Borrow<pso::Viewport>,
1803     {
1804         let viewports = viewports
1805             .into_iter()
1806             .map(|v| {
1807                 let v = v.borrow();
1808                 conv::map_viewport(v)
1809             })
1810             .collect::<Vec<_>>();
1811 
1812         // TODO: DX only lets us set all VPs at once, so cache in slice?
1813         self.cache.set_viewports(&viewports);
1814         self.cache.bind_viewports(&self.context);
1815     }
1816 
set_scissors<T>(&mut self, _first_scissor: u32, scissors: T) where T: IntoIterator, T::Item: Borrow<pso::Rect>,1817     unsafe fn set_scissors<T>(&mut self, _first_scissor: u32, scissors: T)
1818     where
1819         T: IntoIterator,
1820         T::Item: Borrow<pso::Rect>,
1821     {
1822         let scissors = scissors
1823             .into_iter()
1824             .map(|s| {
1825                 let s = s.borrow();
1826                 conv::map_rect(s)
1827             })
1828             .collect::<Vec<_>>();
1829 
1830         // TODO: same as for viewports
1831         self.context
1832             .RSSetScissorRects(scissors.len() as _, scissors.as_ptr());
1833     }
1834 
set_blend_constants(&mut self, color: pso::ColorValue)1835     unsafe fn set_blend_constants(&mut self, color: pso::ColorValue) {
1836         self.cache.set_blend_factor(color);
1837         self.cache.bind_blend_state(&self.context);
1838     }
1839 
set_stencil_reference(&mut self, _faces: pso::Face, value: pso::StencilValue)1840     unsafe fn set_stencil_reference(&mut self, _faces: pso::Face, value: pso::StencilValue) {
1841         self.cache.stencil_ref = Some(value);
1842     }
1843 
set_stencil_read_mask(&mut self, _faces: pso::Face, value: pso::StencilValue)1844     unsafe fn set_stencil_read_mask(&mut self, _faces: pso::Face, value: pso::StencilValue) {
1845         self.cache.stencil_read_mask = Some(value);
1846     }
1847 
set_stencil_write_mask(&mut self, _faces: pso::Face, value: pso::StencilValue)1848     unsafe fn set_stencil_write_mask(&mut self, _faces: pso::Face, value: pso::StencilValue) {
1849         self.cache.stencil_write_mask = Some(value);
1850     }
1851 
set_depth_bounds(&mut self, _bounds: Range<f32>)1852     unsafe fn set_depth_bounds(&mut self, _bounds: Range<f32>) {
1853         unimplemented!()
1854     }
1855 
set_line_width(&mut self, width: f32)1856     unsafe fn set_line_width(&mut self, width: f32) {
1857         validate_line_width(width);
1858     }
1859 
set_depth_bias(&mut self, _depth_bias: pso::DepthBias)1860     unsafe fn set_depth_bias(&mut self, _depth_bias: pso::DepthBias) {
1861         // TODO:
1862         // unimplemented!()
1863     }
1864 
bind_graphics_pipeline(&mut self, pipeline: &GraphicsPipeline)1865     unsafe fn bind_graphics_pipeline(&mut self, pipeline: &GraphicsPipeline) {
1866         self.cache.set_graphics_pipeline(pipeline.clone());
1867         self.cache.bind_graphics_pipeline(&self.context);
1868     }
1869 
bind_graphics_descriptor_sets<'a, I, J>( &mut self, layout: &PipelineLayout, first_set: usize, sets: I, _offsets: J, ) where I: IntoIterator, I::Item: Borrow<DescriptorSet>, J: IntoIterator, J::Item: Borrow<command::DescriptorSetOffset>,1870     unsafe fn bind_graphics_descriptor_sets<'a, I, J>(
1871         &mut self,
1872         layout: &PipelineLayout,
1873         first_set: usize,
1874         sets: I,
1875         _offsets: J,
1876     ) where
1877         I: IntoIterator,
1878         I::Item: Borrow<DescriptorSet>,
1879         J: IntoIterator,
1880         J::Item: Borrow<command::DescriptorSetOffset>,
1881     {
1882         let _scope = debug_scope!(&self.context, "BindGraphicsDescriptorSets");
1883 
1884         // TODO: find a better solution to invalidating old bindings..
1885         self.context.CSSetUnorderedAccessViews(
1886             0,
1887             16,
1888             [ptr::null_mut(); 16].as_ptr(),
1889             ptr::null_mut(),
1890         );
1891 
1892         //let offsets: Vec<command::DescriptorSetOffset> = offsets.into_iter().map(|o| *o.borrow()).collect();
1893 
1894         for (set, info) in sets.into_iter().zip(&layout.sets[first_set ..]) {
1895             let set = set.borrow();
1896 
1897             {
1898                 let coherent_buffers = set.coherent_buffers.lock();
1899                 for sync in coherent_buffers.flush_coherent_buffers.borrow().iter() {
1900                     // TODO: merge sync range if a flush already exists
1901                     if !self
1902                         .flush_coherent_memory
1903                         .iter()
1904                         .any(|m| m.buffer == sync.device_buffer)
1905                     {
1906                         self.flush_coherent_memory.push(MemoryFlush {
1907                             host_memory: sync.host_ptr,
1908                             sync_range: sync.range.clone(),
1909                             buffer: sync.device_buffer,
1910                         });
1911                     }
1912                 }
1913 
1914                 for sync in coherent_buffers.invalidate_coherent_buffers.borrow().iter() {
1915                     if !self
1916                         .invalidate_coherent_memory
1917                         .iter()
1918                         .any(|m| m.buffer == sync.device_buffer)
1919                     {
1920                         self.invalidate_coherent_memory.push(MemoryInvalidate {
1921                             working_buffer: Some(self.internal.working_buffer.clone()),
1922                             working_buffer_size: self.internal.working_buffer_size,
1923                             host_memory: sync.host_ptr,
1924                             sync_range: sync.range.clone(),
1925                             buffer: sync.device_buffer,
1926                         });
1927                     }
1928                 }
1929             }
1930 
1931             // TODO: offsets
1932 
1933             if let Some(rd) = info.registers.vs.c.as_some() {
1934                 self.context.VSSetConstantBuffers(
1935                     rd.res_index as u32,
1936                     rd.count as u32,
1937                     set.handles.offset(rd.pool_offset as isize) as *const *mut _ as *const *mut _,
1938                 );
1939             }
1940             if let Some(rd) = info.registers.vs.t.as_some() {
1941                 self.context.VSSetShaderResources(
1942                     rd.res_index as u32,
1943                     rd.count as u32,
1944                     set.handles.offset(rd.pool_offset as isize) as *const *mut _ as *const *mut _,
1945                 );
1946             }
1947             if let Some(rd) = info.registers.vs.s.as_some() {
1948                 self.context.VSSetSamplers(
1949                     rd.res_index as u32,
1950                     rd.count as u32,
1951                     set.handles.offset(rd.pool_offset as isize) as *const *mut _ as *const *mut _,
1952                 );
1953             }
1954 
1955             if let Some(rd) = info.registers.ps.c.as_some() {
1956                 self.context.PSSetConstantBuffers(
1957                     rd.res_index as u32,
1958                     rd.count as u32,
1959                     set.handles.offset(rd.pool_offset as isize) as *const *mut _ as *const *mut _,
1960                 );
1961             }
1962             if let Some(rd) = info.registers.ps.t.as_some() {
1963                 self.context.PSSetShaderResources(
1964                     rd.res_index as u32,
1965                     rd.count as u32,
1966                     set.handles.offset(rd.pool_offset as isize) as *const *mut _ as *const *mut _,
1967                 );
1968             }
1969             if let Some(rd) = info.registers.ps.s.as_some() {
1970                 self.context.PSSetSamplers(
1971                     rd.res_index as u32,
1972                     rd.count as u32,
1973                     set.handles.offset(rd.pool_offset as isize) as *const *mut _ as *const *mut _,
1974                 );
1975             }
1976         }
1977     }
1978 
bind_compute_pipeline(&mut self, pipeline: &ComputePipeline)1979     unsafe fn bind_compute_pipeline(&mut self, pipeline: &ComputePipeline) {
1980         self.context
1981             .CSSetShader(pipeline.cs.as_raw(), ptr::null_mut(), 0);
1982     }
1983 
bind_compute_descriptor_sets<I, J>( &mut self, layout: &PipelineLayout, first_set: usize, sets: I, _offsets: J, ) where I: IntoIterator, I::Item: Borrow<DescriptorSet>, J: IntoIterator, J::Item: Borrow<command::DescriptorSetOffset>,1984     unsafe fn bind_compute_descriptor_sets<I, J>(
1985         &mut self,
1986         layout: &PipelineLayout,
1987         first_set: usize,
1988         sets: I,
1989         _offsets: J,
1990     ) where
1991         I: IntoIterator,
1992         I::Item: Borrow<DescriptorSet>,
1993         J: IntoIterator,
1994         J::Item: Borrow<command::DescriptorSetOffset>,
1995     {
1996         let _scope = debug_scope!(&self.context, "BindComputeDescriptorSets");
1997 
1998         self.context.CSSetUnorderedAccessViews(
1999             0,
2000             16,
2001             [ptr::null_mut(); 16].as_ptr(),
2002             ptr::null_mut(),
2003         );
2004         for (set, info) in sets.into_iter().zip(&layout.sets[first_set ..]) {
2005             let set = set.borrow();
2006 
2007             {
2008                 let coherent_buffers = set.coherent_buffers.lock();
2009                 for sync in coherent_buffers.flush_coherent_buffers.borrow().iter() {
2010                     if !self
2011                         .flush_coherent_memory
2012                         .iter()
2013                         .any(|m| m.buffer == sync.device_buffer)
2014                     {
2015                         self.flush_coherent_memory.push(MemoryFlush {
2016                             host_memory: sync.host_ptr,
2017                             sync_range: sync.range.clone(),
2018                             buffer: sync.device_buffer,
2019                         });
2020                     }
2021                 }
2022 
2023                 for sync in coherent_buffers.invalidate_coherent_buffers.borrow().iter() {
2024                     if !self
2025                         .invalidate_coherent_memory
2026                         .iter()
2027                         .any(|m| m.buffer == sync.device_buffer)
2028                     {
2029                         self.invalidate_coherent_memory.push(MemoryInvalidate {
2030                             working_buffer: Some(self.internal.working_buffer.clone()),
2031                             working_buffer_size: self.internal.working_buffer_size,
2032                             host_memory: sync.host_ptr,
2033                             sync_range: sync.range.clone(),
2034                             buffer: sync.device_buffer,
2035                         });
2036                     }
2037                 }
2038             }
2039 
2040             // TODO: offsets
2041 
2042             if let Some(rd) = info.registers.cs.c.as_some() {
2043                 self.context.CSSetConstantBuffers(
2044                     rd.res_index as u32,
2045                     rd.count as u32,
2046                     set.handles.offset(rd.pool_offset as isize) as *const *mut _ as *const *mut _,
2047                 );
2048             }
2049             if let Some(rd) = info.registers.cs.t.as_some() {
2050                 self.context.CSSetShaderResources(
2051                     rd.res_index as u32,
2052                     rd.count as u32,
2053                     set.handles.offset(rd.pool_offset as isize) as *const *mut _ as *const *mut _,
2054                 );
2055             }
2056             if let Some(rd) = info.registers.cs.u.as_some() {
2057                 self.context.CSSetUnorderedAccessViews(
2058                     rd.res_index as u32,
2059                     rd.count as u32,
2060                     set.handles.offset(rd.pool_offset as isize) as *const *mut _ as *const *mut _,
2061                     ptr::null_mut(),
2062                 );
2063             }
2064             if let Some(rd) = info.registers.cs.s.as_some() {
2065                 self.context.CSSetSamplers(
2066                     rd.res_index as u32,
2067                     rd.count as u32,
2068                     set.handles.offset(rd.pool_offset as isize) as *const *mut _ as *const *mut _,
2069                 );
2070             }
2071         }
2072     }
2073 
dispatch(&mut self, count: WorkGroupCount)2074     unsafe fn dispatch(&mut self, count: WorkGroupCount) {
2075         self.context.Dispatch(count[0], count[1], count[2]);
2076     }
2077 
dispatch_indirect(&mut self, _buffer: &Buffer, _offset: buffer::Offset)2078     unsafe fn dispatch_indirect(&mut self, _buffer: &Buffer, _offset: buffer::Offset) {
2079         unimplemented!()
2080     }
2081 
fill_buffer(&mut self, _buffer: &Buffer, _sub: buffer::SubRange, _data: u32)2082     unsafe fn fill_buffer(&mut self, _buffer: &Buffer, _sub: buffer::SubRange, _data: u32) {
2083         unimplemented!()
2084     }
2085 
update_buffer(&mut self, _buffer: &Buffer, _offset: buffer::Offset, _data: &[u8])2086     unsafe fn update_buffer(&mut self, _buffer: &Buffer, _offset: buffer::Offset, _data: &[u8]) {
2087         unimplemented!()
2088     }
2089 
copy_buffer<T>(&mut self, src: &Buffer, dst: &Buffer, regions: T) where T: IntoIterator, T::Item: Borrow<command::BufferCopy>,2090     unsafe fn copy_buffer<T>(&mut self, src: &Buffer, dst: &Buffer, regions: T)
2091     where
2092         T: IntoIterator,
2093         T::Item: Borrow<command::BufferCopy>,
2094     {
2095         if src.properties.contains(memory::Properties::COHERENT) {
2096             self.defer_coherent_flush(src);
2097         }
2098 
2099         for region in regions.into_iter() {
2100             let info = region.borrow();
2101             let dst_box = d3d11::D3D11_BOX {
2102                 left: info.src as _,
2103                 top: 0,
2104                 front: 0,
2105                 right: (info.src + info.size) as _,
2106                 bottom: 1,
2107                 back: 1,
2108             };
2109 
2110             self.context.CopySubresourceRegion(
2111                 dst.internal.raw as _,
2112                 0,
2113                 info.dst as _,
2114                 0,
2115                 0,
2116                 src.internal.raw as _,
2117                 0,
2118                 &dst_box,
2119             );
2120 
2121             if let Some(disjoint_cb) = dst.internal.disjoint_cb {
2122                 self.context.CopySubresourceRegion(
2123                     disjoint_cb as _,
2124                     0,
2125                     info.dst as _,
2126                     0,
2127                     0,
2128                     src.internal.raw as _,
2129                     0,
2130                     &dst_box,
2131                 );
2132             }
2133         }
2134     }
2135 
copy_image<T>( &mut self, src: &Image, _: image::Layout, dst: &Image, _: image::Layout, regions: T, ) where T: IntoIterator, T::Item: Borrow<command::ImageCopy>,2136     unsafe fn copy_image<T>(
2137         &mut self,
2138         src: &Image,
2139         _: image::Layout,
2140         dst: &Image,
2141         _: image::Layout,
2142         regions: T,
2143     ) where
2144         T: IntoIterator,
2145         T::Item: Borrow<command::ImageCopy>,
2146     {
2147         self.internal
2148             .copy_image_2d(&self.context, src, dst, regions);
2149     }
2150 
copy_buffer_to_image<T>( &mut self, buffer: &Buffer, image: &Image, _: image::Layout, regions: T, ) where T: IntoIterator, T::Item: Borrow<command::BufferImageCopy>,2151     unsafe fn copy_buffer_to_image<T>(
2152         &mut self,
2153         buffer: &Buffer,
2154         image: &Image,
2155         _: image::Layout,
2156         regions: T,
2157     ) where
2158         T: IntoIterator,
2159         T::Item: Borrow<command::BufferImageCopy>,
2160     {
2161         if buffer.properties.contains(memory::Properties::COHERENT) {
2162             self.defer_coherent_flush(buffer);
2163         }
2164 
2165         self.internal
2166             .copy_buffer_to_image_2d(&self.context, buffer, image, regions);
2167     }
2168 
copy_image_to_buffer<T>( &mut self, image: &Image, _: image::Layout, buffer: &Buffer, regions: T, ) where T: IntoIterator, T::Item: Borrow<command::BufferImageCopy>,2169     unsafe fn copy_image_to_buffer<T>(
2170         &mut self,
2171         image: &Image,
2172         _: image::Layout,
2173         buffer: &Buffer,
2174         regions: T,
2175     ) where
2176         T: IntoIterator,
2177         T::Item: Borrow<command::BufferImageCopy>,
2178     {
2179         if buffer.properties.contains(memory::Properties::COHERENT) {
2180             self.defer_coherent_invalidate(buffer);
2181         }
2182 
2183         self.internal
2184             .copy_image_2d_to_buffer(&self.context, image, buffer, regions);
2185     }
2186 
draw(&mut self, vertices: Range<VertexCount>, instances: Range<InstanceCount>)2187     unsafe fn draw(&mut self, vertices: Range<VertexCount>, instances: Range<InstanceCount>) {
2188         self.context.DrawInstanced(
2189             vertices.end - vertices.start,
2190             instances.end - instances.start,
2191             vertices.start,
2192             instances.start,
2193         );
2194     }
2195 
draw_indexed( &mut self, indices: Range<IndexCount>, base_vertex: VertexOffset, instances: Range<InstanceCount>, )2196     unsafe fn draw_indexed(
2197         &mut self,
2198         indices: Range<IndexCount>,
2199         base_vertex: VertexOffset,
2200         instances: Range<InstanceCount>,
2201     ) {
2202         self.context.DrawIndexedInstanced(
2203             indices.end - indices.start,
2204             instances.end - instances.start,
2205             indices.start,
2206             base_vertex,
2207             instances.start,
2208         );
2209     }
2210 
draw_indirect( &mut self, _buffer: &Buffer, _offset: buffer::Offset, _draw_count: DrawCount, _stride: u32, )2211     unsafe fn draw_indirect(
2212         &mut self,
2213         _buffer: &Buffer,
2214         _offset: buffer::Offset,
2215         _draw_count: DrawCount,
2216         _stride: u32,
2217     ) {
2218         unimplemented!()
2219     }
2220 
draw_indexed_indirect( &mut self, _buffer: &Buffer, _offset: buffer::Offset, _draw_count: DrawCount, _stride: u32, )2221     unsafe fn draw_indexed_indirect(
2222         &mut self,
2223         _buffer: &Buffer,
2224         _offset: buffer::Offset,
2225         _draw_count: DrawCount,
2226         _stride: u32,
2227     ) {
2228         unimplemented!()
2229     }
2230 
set_event(&mut self, _: &(), _: pso::PipelineStage)2231     unsafe fn set_event(&mut self, _: &(), _: pso::PipelineStage) {
2232         unimplemented!()
2233     }
2234 
reset_event(&mut self, _: &(), _: pso::PipelineStage)2235     unsafe fn reset_event(&mut self, _: &(), _: pso::PipelineStage) {
2236         unimplemented!()
2237     }
2238 
wait_events<'a, I, J>(&mut self, _: I, _: Range<pso::PipelineStage>, _: J) where I: IntoIterator, I::Item: Borrow<()>, J: IntoIterator, J::Item: Borrow<memory::Barrier<'a, Backend>>,2239     unsafe fn wait_events<'a, I, J>(&mut self, _: I, _: Range<pso::PipelineStage>, _: J)
2240     where
2241         I: IntoIterator,
2242         I::Item: Borrow<()>,
2243         J: IntoIterator,
2244         J::Item: Borrow<memory::Barrier<'a, Backend>>,
2245     {
2246         unimplemented!()
2247     }
2248 
begin_query(&mut self, _query: query::Query<Backend>, _flags: query::ControlFlags)2249     unsafe fn begin_query(&mut self, _query: query::Query<Backend>, _flags: query::ControlFlags) {
2250         unimplemented!()
2251     }
2252 
end_query(&mut self, _query: query::Query<Backend>)2253     unsafe fn end_query(&mut self, _query: query::Query<Backend>) {
2254         unimplemented!()
2255     }
2256 
reset_query_pool(&mut self, _pool: &QueryPool, _queries: Range<query::Id>)2257     unsafe fn reset_query_pool(&mut self, _pool: &QueryPool, _queries: Range<query::Id>) {
2258         unimplemented!()
2259     }
2260 
copy_query_pool_results( &mut self, _pool: &QueryPool, _queries: Range<query::Id>, _buffer: &Buffer, _offset: buffer::Offset, _stride: buffer::Offset, _flags: query::ResultFlags, )2261     unsafe fn copy_query_pool_results(
2262         &mut self,
2263         _pool: &QueryPool,
2264         _queries: Range<query::Id>,
2265         _buffer: &Buffer,
2266         _offset: buffer::Offset,
2267         _stride: buffer::Offset,
2268         _flags: query::ResultFlags,
2269     ) {
2270         unimplemented!()
2271     }
2272 
write_timestamp(&mut self, _: pso::PipelineStage, _query: query::Query<Backend>)2273     unsafe fn write_timestamp(&mut self, _: pso::PipelineStage, _query: query::Query<Backend>) {
2274         unimplemented!()
2275     }
2276 
push_graphics_constants( &mut self, _layout: &PipelineLayout, _stages: pso::ShaderStageFlags, _offset: u32, _constants: &[u32], )2277     unsafe fn push_graphics_constants(
2278         &mut self,
2279         _layout: &PipelineLayout,
2280         _stages: pso::ShaderStageFlags,
2281         _offset: u32,
2282         _constants: &[u32],
2283     ) {
2284         // unimplemented!()
2285     }
2286 
push_compute_constants( &mut self, _layout: &PipelineLayout, _offset: u32, _constants: &[u32], )2287     unsafe fn push_compute_constants(
2288         &mut self,
2289         _layout: &PipelineLayout,
2290         _offset: u32,
2291         _constants: &[u32],
2292     ) {
2293         unimplemented!()
2294     }
2295 
execute_commands<'a, T, I>(&mut self, _buffers: I) where T: 'a + Borrow<CommandBuffer>, I: IntoIterator<Item = &'a T>,2296     unsafe fn execute_commands<'a, T, I>(&mut self, _buffers: I)
2297     where
2298         T: 'a + Borrow<CommandBuffer>,
2299         I: IntoIterator<Item = &'a T>,
2300     {
2301         unimplemented!()
2302     }
2303 
insert_debug_marker(&mut self, _name: &str, _color: u32)2304     unsafe fn insert_debug_marker(&mut self, _name: &str, _color: u32) {
2305         //TODO
2306     }
begin_debug_marker(&mut self, _name: &str, _color: u32)2307     unsafe fn begin_debug_marker(&mut self, _name: &str, _color: u32) {
2308         //TODO
2309     }
end_debug_marker(&mut self)2310     unsafe fn end_debug_marker(&mut self) {
2311         //TODO
2312     }
2313 }
2314 
2315 #[derive(Clone, Debug)]
2316 enum SyncRange {
2317     Whole,
2318     Partial(Range<u64>),
2319 }
2320 
2321 #[derive(Debug)]
2322 pub struct MemoryFlush {
2323     host_memory: *mut u8,
2324     sync_range: SyncRange,
2325     buffer: *mut d3d11::ID3D11Buffer,
2326 }
2327 
2328 pub struct MemoryInvalidate {
2329     working_buffer: Option<ComPtr<d3d11::ID3D11Buffer>>,
2330     working_buffer_size: u64,
2331     host_memory: *mut u8,
2332     sync_range: Range<u64>,
2333     buffer: *mut d3d11::ID3D11Buffer,
2334 }
2335 
2336 impl fmt::Debug for MemoryInvalidate {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result2337     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2338         fmt.write_str("MemoryInvalidate")
2339     }
2340 }
2341 
intersection(a: &Range<u64>, b: &Range<u64>) -> Option<Range<u64>>2342 fn intersection(a: &Range<u64>, b: &Range<u64>) -> Option<Range<u64>> {
2343     let min = if a.start < b.start { a } else { b };
2344     let max = if min == a { b } else { a };
2345 
2346     if min.end < max.start {
2347         None
2348     } else {
2349         let end = if min.end < max.end { min.end } else { max.end };
2350         Some(max.start .. end)
2351     }
2352 }
2353 
2354 impl MemoryFlush {
do_flush(&self, context: &ComPtr<d3d11::ID3D11DeviceContext>)2355     fn do_flush(&self, context: &ComPtr<d3d11::ID3D11DeviceContext>) {
2356         let src = self.host_memory;
2357 
2358         debug_marker!(context, "Flush({:?})", self.sync_range);
2359         let region = match self.sync_range {
2360             SyncRange::Partial(ref range) if range.start < range.end => Some(d3d11::D3D11_BOX {
2361                 left: range.start as u32,
2362                 top: 0,
2363                 front: 0,
2364                 right: range.end as u32,
2365                 bottom: 1,
2366                 back: 1,
2367             }),
2368             _ => None,
2369         };
2370 
2371         unsafe {
2372             context.UpdateSubresource(
2373                 self.buffer as _,
2374                 0,
2375                 if let Some(region) = region {
2376                     &region
2377                 } else {
2378                     ptr::null_mut()
2379                 },
2380                 src as _,
2381                 0,
2382                 0,
2383             );
2384         }
2385     }
2386 }
2387 
2388 impl MemoryInvalidate {
download( &self, context: &ComPtr<d3d11::ID3D11DeviceContext>, buffer: *mut d3d11::ID3D11Buffer, range: Range<u64>, )2389     fn download(
2390         &self,
2391         context: &ComPtr<d3d11::ID3D11DeviceContext>,
2392         buffer: *mut d3d11::ID3D11Buffer,
2393         range: Range<u64>,
2394     ) {
2395         unsafe {
2396             context.CopySubresourceRegion(
2397                 self.working_buffer.clone().unwrap().as_raw() as _,
2398                 0,
2399                 0,
2400                 0,
2401                 0,
2402                 buffer as _,
2403                 0,
2404                 &d3d11::D3D11_BOX {
2405                     left: range.start as _,
2406                     top: 0,
2407                     front: 0,
2408                     right: range.end as _,
2409                     bottom: 1,
2410                     back: 1,
2411                 },
2412             );
2413 
2414             // copy over to our vec
2415             let dst = self.host_memory.offset(range.start as isize);
2416             let src = self.map(&context);
2417             ptr::copy(src, dst, (range.end - range.start) as usize);
2418             self.unmap(&context);
2419         }
2420     }
2421 
do_invalidate(&self, context: &ComPtr<d3d11::ID3D11DeviceContext>)2422     fn do_invalidate(&self, context: &ComPtr<d3d11::ID3D11DeviceContext>) {
2423         let stride = self.working_buffer_size;
2424         let range = &self.sync_range;
2425         let len = range.end - range.start;
2426         let chunks = len / stride;
2427         let remainder = len % stride;
2428 
2429         // we split up the copies into chunks the size of our working buffer
2430         for i in 0 .. chunks {
2431             let offset = range.start + i * stride;
2432             let range = offset .. (offset + stride);
2433 
2434             self.download(context, self.buffer, range);
2435         }
2436 
2437         if remainder != 0 {
2438             self.download(context, self.buffer, (chunks * stride) .. range.end);
2439         }
2440     }
2441 
map(&self, context: &ComPtr<d3d11::ID3D11DeviceContext>) -> *mut u82442     fn map(&self, context: &ComPtr<d3d11::ID3D11DeviceContext>) -> *mut u8 {
2443         assert_eq!(self.working_buffer.is_some(), true);
2444 
2445         unsafe {
2446             let mut map = mem::zeroed();
2447             let hr = context.Map(
2448                 self.working_buffer.clone().unwrap().as_raw() as _,
2449                 0,
2450                 d3d11::D3D11_MAP_READ,
2451                 0,
2452                 &mut map,
2453             );
2454 
2455             assert_eq!(hr, winerror::S_OK);
2456 
2457             map.pData as _
2458         }
2459     }
2460 
unmap(&self, context: &ComPtr<d3d11::ID3D11DeviceContext>)2461     fn unmap(&self, context: &ComPtr<d3d11::ID3D11DeviceContext>) {
2462         unsafe {
2463             context.Unmap(self.working_buffer.clone().unwrap().as_raw() as _, 0);
2464         }
2465     }
2466 }
2467 
2468 // Since we dont have any heaps to work with directly, everytime we bind a
2469 // buffer/image to memory we allocate a dx11 resource and assign it a range.
2470 //
2471 // `HOST_VISIBLE` memory gets a `Vec<u8>` which covers the entire memory
2472 // range. This forces us to only expose non-coherent memory, as this
2473 // abstraction acts as a "cache" since the "staging buffer" vec is disjoint
2474 // from all the dx11 resources we store in the struct.
2475 pub struct Memory {
2476     properties: memory::Properties,
2477     size: u64,
2478 
2479     mapped_ptr: *mut u8,
2480 
2481     // staging buffer covering the whole memory region, if it's HOST_VISIBLE
2482     host_visible: Option<RefCell<Vec<u8>>>,
2483 
2484     // list of all buffers bound to this memory
2485     local_buffers: RefCell<Vec<(Range<u64>, InternalBuffer)>>,
2486 
2487     // list of all images bound to this memory
2488     _local_images: RefCell<Vec<(Range<u64>, InternalImage)>>,
2489 }
2490 
2491 impl fmt::Debug for Memory {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result2492     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2493         fmt.write_str("Memory")
2494     }
2495 }
2496 
2497 unsafe impl Send for Memory {}
2498 unsafe impl Sync for Memory {}
2499 
2500 impl Memory {
resolve(&self, segment: &memory::Segment) -> Range<u64>2501     pub fn resolve(&self, segment: &memory::Segment) -> Range<u64> {
2502         segment.offset .. segment.size.map_or(self.size, |s| segment.offset + s)
2503     }
2504 
bind_buffer(&self, range: Range<u64>, buffer: InternalBuffer)2505     pub fn bind_buffer(&self, range: Range<u64>, buffer: InternalBuffer) {
2506         self.local_buffers.borrow_mut().push((range, buffer));
2507     }
2508 
flush(&self, context: &ComPtr<d3d11::ID3D11DeviceContext>, range: Range<u64>)2509     pub fn flush(&self, context: &ComPtr<d3d11::ID3D11DeviceContext>, range: Range<u64>) {
2510         use buffer::Usage;
2511 
2512         for &(ref buffer_range, ref buffer) in self.local_buffers.borrow().iter() {
2513             if let Some(range) = intersection(&range, &buffer_range) {
2514                 let ptr = self.mapped_ptr;
2515 
2516                 // we need to handle 3 cases for updating buffers:
2517                 //
2518                 //   1. if our buffer was created as a `UNIFORM` buffer *and* other usage flags, we
2519                 //      also have a disjoint buffer which only has `D3D11_BIND_CONSTANT_BUFFER` due
2520                 //      to DX11 limitation. we then need to update both the original buffer and the
2521                 //      disjoint one with the *whole* range (TODO: allow for partial updates)
2522                 //
2523                 //   2. if our buffer was created with *only* `UNIFORM` usage we need to upload
2524                 //      the whole range (TODO: allow for partial updates)
2525                 //
2526                 //   3. the general case, without any `UNIFORM` usage has no restrictions on
2527                 //      partial updates, so we upload the specified range
2528                 //
2529                 if buffer.usage.contains(Usage::UNIFORM) && buffer.usage != Usage::UNIFORM {
2530                     MemoryFlush {
2531                         host_memory: unsafe { ptr.offset(buffer_range.start as _) },
2532                         sync_range: SyncRange::Whole,
2533                         buffer: buffer.raw,
2534                     }
2535                     .do_flush(&context);
2536 
2537                     if let Some(disjoint) = buffer.disjoint_cb {
2538                         MemoryFlush {
2539                             host_memory: unsafe { ptr.offset(buffer_range.start as _) },
2540                             sync_range: SyncRange::Whole,
2541                             buffer: disjoint,
2542                         }
2543                         .do_flush(&context);
2544                     }
2545                 } else if buffer.usage == Usage::UNIFORM {
2546                     MemoryFlush {
2547                         host_memory: unsafe { ptr.offset(buffer_range.start as _) },
2548                         sync_range: SyncRange::Whole,
2549                         buffer: buffer.raw,
2550                     }
2551                     .do_flush(&context);
2552                 } else {
2553                     let local_start = range.start - buffer_range.start;
2554                     let local_len = range.end - range.start;
2555 
2556                     MemoryFlush {
2557                         host_memory: unsafe { ptr.offset(range.start as _) },
2558                         sync_range: SyncRange::Partial(local_start .. (local_start + local_len)),
2559                         buffer: buffer.raw,
2560                     }
2561                     .do_flush(&context);
2562                 }
2563             }
2564         }
2565     }
2566 
invalidate( &self, context: &ComPtr<d3d11::ID3D11DeviceContext>, range: Range<u64>, working_buffer: ComPtr<d3d11::ID3D11Buffer>, working_buffer_size: u64, )2567     pub fn invalidate(
2568         &self,
2569         context: &ComPtr<d3d11::ID3D11DeviceContext>,
2570         range: Range<u64>,
2571         working_buffer: ComPtr<d3d11::ID3D11Buffer>,
2572         working_buffer_size: u64,
2573     ) {
2574         for &(ref buffer_range, ref buffer) in self.local_buffers.borrow().iter() {
2575             if let Some(range) = intersection(&range, &buffer_range) {
2576                 MemoryInvalidate {
2577                     working_buffer: Some(working_buffer.clone()),
2578                     working_buffer_size,
2579                     host_memory: self.mapped_ptr,
2580                     sync_range: range.clone(),
2581                     buffer: buffer.raw,
2582                 }
2583                 .do_invalidate(&context);
2584             }
2585         }
2586     }
2587 }
2588 
2589 #[derive(Debug)]
2590 pub struct CommandPool {
2591     device: ComPtr<d3d11::ID3D11Device>,
2592     internal: internal::Internal,
2593 }
2594 
2595 unsafe impl Send for CommandPool {}
2596 unsafe impl Sync for CommandPool {}
2597 
2598 impl hal::pool::CommandPool<Backend> for CommandPool {
reset(&mut self, _release_resources: bool)2599     unsafe fn reset(&mut self, _release_resources: bool) {
2600         //unimplemented!()
2601     }
2602 
allocate_one(&mut self, _level: command::Level) -> CommandBuffer2603     unsafe fn allocate_one(&mut self, _level: command::Level) -> CommandBuffer {
2604         CommandBuffer::create_deferred(self.device.clone(), self.internal.clone())
2605     }
2606 
free<I>(&mut self, _cbufs: I) where I: IntoIterator<Item = CommandBuffer>,2607     unsafe fn free<I>(&mut self, _cbufs: I)
2608     where
2609         I: IntoIterator<Item = CommandBuffer>,
2610     {
2611         // TODO:
2612         // unimplemented!()
2613     }
2614 }
2615 
2616 /// Similarily to dx12 backend, we can handle either precompiled dxbc or spirv
2617 pub enum ShaderModule {
2618     Dxbc(Vec<u8>),
2619     Spirv(Vec<u32>),
2620 }
2621 
2622 // TODO: temporary
2623 impl fmt::Debug for ShaderModule {
fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result2624     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
2625         write!(f, "{}", "ShaderModule { ... }")
2626     }
2627 }
2628 
2629 unsafe impl Send for ShaderModule {}
2630 unsafe impl Sync for ShaderModule {}
2631 
2632 #[derive(Clone, Debug)]
2633 pub struct SubpassDesc {
2634     pub color_attachments: Vec<pass::AttachmentRef>,
2635     pub depth_stencil_attachment: Option<pass::AttachmentRef>,
2636     pub input_attachments: Vec<pass::AttachmentRef>,
2637     pub resolve_attachments: Vec<pass::AttachmentRef>,
2638 }
2639 
2640 impl SubpassDesc {
is_using(&self, at_id: pass::AttachmentId) -> bool2641     pub(crate) fn is_using(&self, at_id: pass::AttachmentId) -> bool {
2642         self.color_attachments
2643             .iter()
2644             .chain(self.depth_stencil_attachment.iter())
2645             .chain(self.input_attachments.iter())
2646             .chain(self.resolve_attachments.iter())
2647             .any(|&(id, _)| id == at_id)
2648     }
2649 }
2650 
2651 #[derive(Clone, Debug)]
2652 pub struct RenderPass {
2653     pub attachments: Vec<pass::Attachment>,
2654     pub subpasses: Vec<SubpassDesc>,
2655 }
2656 
2657 #[derive(Clone, Debug)]
2658 pub struct Framebuffer {
2659     attachments: Vec<ImageView>,
2660     layers: image::Layer,
2661 }
2662 
2663 #[derive(Clone, Debug)]
2664 pub struct InternalBuffer {
2665     raw: *mut d3d11::ID3D11Buffer,
2666     // TODO: need to sync between `raw` and `disjoint_cb`, same way as we do with
2667     // `MemoryFlush/Invalidate`
2668     disjoint_cb: Option<*mut d3d11::ID3D11Buffer>, // if unbound this buffer might be null.
2669     srv: Option<*mut d3d11::ID3D11ShaderResourceView>,
2670     uav: Option<*mut d3d11::ID3D11UnorderedAccessView>,
2671     usage: buffer::Usage,
2672 }
2673 
2674 pub struct Buffer {
2675     internal: InternalBuffer,
2676     properties: memory::Properties, // empty if unbound
2677     host_ptr: *mut u8,              // null if unbound
2678     bound_range: Range<u64>,        // 0 if unbound
2679     requirements: memory::Requirements,
2680     bind: d3d11::D3D11_BIND_FLAG,
2681 }
2682 
2683 impl fmt::Debug for Buffer {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result2684     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2685         fmt.write_str("Buffer")
2686     }
2687 }
2688 
2689 unsafe impl Send for Buffer {}
2690 unsafe impl Sync for Buffer {}
2691 
2692 #[derive(Debug)]
2693 pub struct BufferView;
2694 
2695 pub struct Image {
2696     kind: image::Kind,
2697     usage: image::Usage,
2698     format: format::Format,
2699     view_caps: image::ViewCapabilities,
2700     decomposed_format: conv::DecomposedDxgiFormat,
2701     mip_levels: image::Level,
2702     internal: InternalImage,
2703     bind: d3d11::D3D11_BIND_FLAG,
2704     requirements: memory::Requirements,
2705 }
2706 
2707 impl fmt::Debug for Image {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result2708     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2709         fmt.write_str("Image")
2710     }
2711 }
2712 
2713 pub struct InternalImage {
2714     raw: *mut d3d11::ID3D11Resource,
2715     copy_srv: Option<ComPtr<d3d11::ID3D11ShaderResourceView>>,
2716     srv: Option<ComPtr<d3d11::ID3D11ShaderResourceView>>,
2717 
2718     /// Contains UAVs for all subresources
2719     unordered_access_views: Vec<ComPtr<d3d11::ID3D11UnorderedAccessView>>,
2720 
2721     /// Contains DSVs for all subresources
2722     depth_stencil_views: Vec<ComPtr<d3d11::ID3D11DepthStencilView>>,
2723 
2724     /// Contains RTVs for all subresources
2725     render_target_views: Vec<ComPtr<d3d11::ID3D11RenderTargetView>>,
2726 }
2727 
2728 impl fmt::Debug for InternalImage {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result2729     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2730         fmt.write_str("InternalImage")
2731     }
2732 }
2733 
2734 unsafe impl Send for Image {}
2735 unsafe impl Sync for Image {}
2736 
2737 impl Image {
calc_subresource(&self, mip_level: UINT, layer: UINT) -> UINT2738     pub fn calc_subresource(&self, mip_level: UINT, layer: UINT) -> UINT {
2739         mip_level + (layer * self.mip_levels as UINT)
2740     }
2741 
get_uav( &self, mip_level: image::Level, _layer: image::Layer, ) -> Option<&ComPtr<d3d11::ID3D11UnorderedAccessView>>2742     pub fn get_uav(
2743         &self,
2744         mip_level: image::Level,
2745         _layer: image::Layer,
2746     ) -> Option<&ComPtr<d3d11::ID3D11UnorderedAccessView>> {
2747         self.internal
2748             .unordered_access_views
2749             .get(self.calc_subresource(mip_level as _, 0) as usize)
2750     }
2751 
get_dsv( &self, mip_level: image::Level, layer: image::Layer, ) -> Option<&ComPtr<d3d11::ID3D11DepthStencilView>>2752     pub fn get_dsv(
2753         &self,
2754         mip_level: image::Level,
2755         layer: image::Layer,
2756     ) -> Option<&ComPtr<d3d11::ID3D11DepthStencilView>> {
2757         self.internal
2758             .depth_stencil_views
2759             .get(self.calc_subresource(mip_level as _, layer as _) as usize)
2760     }
2761 
get_rtv( &self, mip_level: image::Level, layer: image::Layer, ) -> Option<&ComPtr<d3d11::ID3D11RenderTargetView>>2762     pub fn get_rtv(
2763         &self,
2764         mip_level: image::Level,
2765         layer: image::Layer,
2766     ) -> Option<&ComPtr<d3d11::ID3D11RenderTargetView>> {
2767         self.internal
2768             .render_target_views
2769             .get(self.calc_subresource(mip_level as _, layer as _) as usize)
2770     }
2771 }
2772 
2773 #[derive(Clone)]
2774 pub struct ImageView {
2775     format: format::Format,
2776     rtv_handle: Option<ComPtr<d3d11::ID3D11RenderTargetView>>,
2777     srv_handle: Option<ComPtr<d3d11::ID3D11ShaderResourceView>>,
2778     dsv_handle: Option<ComPtr<d3d11::ID3D11DepthStencilView>>,
2779     uav_handle: Option<ComPtr<d3d11::ID3D11UnorderedAccessView>>,
2780 }
2781 
2782 impl fmt::Debug for ImageView {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result2783     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2784         fmt.write_str("ImageView")
2785     }
2786 }
2787 
2788 unsafe impl Send for ImageView {}
2789 unsafe impl Sync for ImageView {}
2790 
2791 pub struct Sampler {
2792     sampler_handle: ComPtr<d3d11::ID3D11SamplerState>,
2793 }
2794 
2795 impl fmt::Debug for Sampler {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result2796     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2797         fmt.write_str("Sampler")
2798     }
2799 }
2800 
2801 unsafe impl Send for Sampler {}
2802 unsafe impl Sync for Sampler {}
2803 
2804 pub struct ComputePipeline {
2805     cs: ComPtr<d3d11::ID3D11ComputeShader>,
2806 }
2807 
2808 impl fmt::Debug for ComputePipeline {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result2809     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2810         fmt.write_str("ComputePipeline")
2811     }
2812 }
2813 
2814 unsafe impl Send for ComputePipeline {}
2815 unsafe impl Sync for ComputePipeline {}
2816 
2817 /// NOTE: some objects are hashed internally and reused when created with the
2818 ///       same params[0], need to investigate which interfaces this applies
2819 ///       to.
2820 ///
2821 /// [0]: https://msdn.microsoft.com/en-us/library/windows/desktop/ff476500(v=vs.85).aspx
2822 #[derive(Clone)]
2823 pub struct GraphicsPipeline {
2824     vs: ComPtr<d3d11::ID3D11VertexShader>,
2825     gs: Option<ComPtr<d3d11::ID3D11GeometryShader>>,
2826     hs: Option<ComPtr<d3d11::ID3D11HullShader>>,
2827     ds: Option<ComPtr<d3d11::ID3D11DomainShader>>,
2828     ps: Option<ComPtr<d3d11::ID3D11PixelShader>>,
2829     topology: d3d11::D3D11_PRIMITIVE_TOPOLOGY,
2830     input_layout: ComPtr<d3d11::ID3D11InputLayout>,
2831     rasterizer_state: ComPtr<d3d11::ID3D11RasterizerState>,
2832     blend_state: ComPtr<d3d11::ID3D11BlendState>,
2833     depth_stencil_state: Option<(
2834         ComPtr<d3d11::ID3D11DepthStencilState>,
2835         pso::State<pso::StencilValue>,
2836     )>,
2837     baked_states: pso::BakedStates,
2838     required_bindings: u32,
2839     max_vertex_bindings: u32,
2840     strides: Vec<u32>,
2841 }
2842 
2843 impl fmt::Debug for GraphicsPipeline {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result2844     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2845         fmt.write_str("GraphicsPipeline")
2846     }
2847 }
2848 
2849 unsafe impl Send for GraphicsPipeline {}
2850 unsafe impl Sync for GraphicsPipeline {}
2851 
2852 type ResourceIndex = u8;
2853 type DescriptorIndex = u16;
2854 
2855 #[derive(Clone, Debug, Default)]
2856 struct RegisterData<T> {
2857     // CBV
2858     c: T,
2859     // SRV
2860     t: T,
2861     // UAV
2862     u: T,
2863     // Sampler
2864     s: T,
2865 }
2866 
2867 impl<T> RegisterData<T> {
map<U, F: Fn(&T) -> U>(&self, fun: F) -> RegisterData<U>2868     fn map<U, F: Fn(&T) -> U>(&self, fun: F) -> RegisterData<U> {
2869         RegisterData {
2870             c: fun(&self.c),
2871             t: fun(&self.t),
2872             u: fun(&self.u),
2873             s: fun(&self.s),
2874         }
2875     }
2876 }
2877 
2878 impl RegisterData<DescriptorIndex> {
add_content_many(&mut self, content: DescriptorContent, many: DescriptorIndex)2879     fn add_content_many(&mut self, content: DescriptorContent, many: DescriptorIndex) {
2880         if content.contains(DescriptorContent::CBV) {
2881             self.c += many;
2882         }
2883         if content.contains(DescriptorContent::SRV) {
2884             self.t += many;
2885         }
2886         if content.contains(DescriptorContent::UAV) {
2887             self.u += many;
2888         }
2889         if content.contains(DescriptorContent::SAMPLER) {
2890             self.s += many;
2891         }
2892     }
2893 
add_content(&mut self, content: DescriptorContent)2894     fn add_content(&mut self, content: DescriptorContent) {
2895         self.add_content_many(content, 1)
2896     }
2897 
sum(&self) -> DescriptorIndex2898     fn sum(&self) -> DescriptorIndex {
2899         self.c + self.t + self.u + self.s
2900     }
2901 }
2902 
2903 #[derive(Clone, Debug, Default)]
2904 struct MultiStageData<T> {
2905     vs: T,
2906     ps: T,
2907     cs: T,
2908 }
2909 
2910 impl<T> MultiStageData<T> {
select(self, stage: pso::Stage) -> T2911     fn select(self, stage: pso::Stage) -> T {
2912         match stage {
2913             pso::Stage::Vertex => self.vs,
2914             pso::Stage::Fragment => self.ps,
2915             pso::Stage::Compute => self.cs,
2916             _ => panic!("Unsupported stage {:?}", stage),
2917         }
2918     }
2919 }
2920 
2921 impl<T> MultiStageData<RegisterData<T>> {
map_register<U, F: Fn(&T) -> U>(&self, fun: F) -> MultiStageData<RegisterData<U>>2922     fn map_register<U, F: Fn(&T) -> U>(&self, fun: F) -> MultiStageData<RegisterData<U>> {
2923         MultiStageData {
2924             vs: self.vs.map(&fun),
2925             ps: self.ps.map(&fun),
2926             cs: self.cs.map(&fun),
2927         }
2928     }
2929 
map_other<U, F: Fn(&RegisterData<T>) -> U>(&self, fun: F) -> MultiStageData<U>2930     fn map_other<U, F: Fn(&RegisterData<T>) -> U>(&self, fun: F) -> MultiStageData<U> {
2931         MultiStageData {
2932             vs: fun(&self.vs),
2933             ps: fun(&self.ps),
2934             cs: fun(&self.cs),
2935         }
2936     }
2937 }
2938 
2939 impl MultiStageData<RegisterData<DescriptorIndex>> {
add_content(&mut self, content: DescriptorContent, stages: pso::ShaderStageFlags)2940     fn add_content(&mut self, content: DescriptorContent, stages: pso::ShaderStageFlags) {
2941         if stages.contains(pso::ShaderStageFlags::VERTEX) {
2942             self.vs.add_content(content);
2943         }
2944         if stages.contains(pso::ShaderStageFlags::FRAGMENT) {
2945             self.ps.add_content(content);
2946         }
2947         if stages.contains(pso::ShaderStageFlags::COMPUTE) {
2948             self.cs.add_content(content);
2949         }
2950     }
2951 
sum(&self) -> DescriptorIndex2952     fn sum(&self) -> DescriptorIndex {
2953         self.vs.sum() + self.ps.sum() + self.cs.sum()
2954     }
2955 }
2956 
2957 #[derive(Clone, Debug, Default)]
2958 struct RegisterPoolMapping {
2959     offset: DescriptorIndex,
2960     count: ResourceIndex,
2961 }
2962 
2963 #[derive(Clone, Debug, Default)]
2964 struct RegisterInfo {
2965     res_index: ResourceIndex,
2966     pool_offset: DescriptorIndex,
2967     count: ResourceIndex,
2968 }
2969 
2970 impl RegisterInfo {
as_some(&self) -> Option<&Self>2971     fn as_some(&self) -> Option<&Self> {
2972         if self.count == 0 {
2973             None
2974         } else {
2975             Some(self)
2976         }
2977     }
2978 }
2979 
2980 #[derive(Clone, Debug, Default)]
2981 struct RegisterAccumulator {
2982     res_index: ResourceIndex,
2983 }
2984 
2985 impl RegisterAccumulator {
to_mapping(&self, cur_offset: &mut DescriptorIndex) -> RegisterPoolMapping2986     fn to_mapping(&self, cur_offset: &mut DescriptorIndex) -> RegisterPoolMapping {
2987         let offset = *cur_offset;
2988         *cur_offset += self.res_index as DescriptorIndex;
2989 
2990         RegisterPoolMapping {
2991             offset,
2992             count: self.res_index,
2993         }
2994     }
2995 
advance(&mut self, mapping: &RegisterPoolMapping) -> RegisterInfo2996     fn advance(&mut self, mapping: &RegisterPoolMapping) -> RegisterInfo {
2997         let res_index = self.res_index;
2998         self.res_index += mapping.count;
2999         RegisterInfo {
3000             res_index,
3001             pool_offset: mapping.offset,
3002             count: mapping.count,
3003         }
3004     }
3005 }
3006 
3007 impl RegisterData<RegisterAccumulator> {
to_mapping(&self, pool_offset: &mut DescriptorIndex) -> RegisterData<RegisterPoolMapping>3008     fn to_mapping(&self, pool_offset: &mut DescriptorIndex) -> RegisterData<RegisterPoolMapping> {
3009         RegisterData {
3010             c: self.c.to_mapping(pool_offset),
3011             t: self.t.to_mapping(pool_offset),
3012             u: self.u.to_mapping(pool_offset),
3013             s: self.s.to_mapping(pool_offset),
3014         }
3015     }
3016 
advance( &mut self, mapping: &RegisterData<RegisterPoolMapping>, ) -> RegisterData<RegisterInfo>3017     fn advance(
3018         &mut self,
3019         mapping: &RegisterData<RegisterPoolMapping>,
3020     ) -> RegisterData<RegisterInfo> {
3021         RegisterData {
3022             c: self.c.advance(&mapping.c),
3023             t: self.t.advance(&mapping.t),
3024             u: self.u.advance(&mapping.u),
3025             s: self.s.advance(&mapping.s),
3026         }
3027     }
3028 }
3029 
3030 impl MultiStageData<RegisterData<RegisterAccumulator>> {
to_mapping(&self) -> MultiStageData<RegisterData<RegisterPoolMapping>>3031     fn to_mapping(&self) -> MultiStageData<RegisterData<RegisterPoolMapping>> {
3032         let mut pool_offset = 0;
3033         MultiStageData {
3034             vs: self.vs.to_mapping(&mut pool_offset),
3035             ps: self.ps.to_mapping(&mut pool_offset),
3036             cs: self.cs.to_mapping(&mut pool_offset),
3037         }
3038     }
3039 
advance( &mut self, mapping: &MultiStageData<RegisterData<RegisterPoolMapping>>, ) -> MultiStageData<RegisterData<RegisterInfo>>3040     fn advance(
3041         &mut self,
3042         mapping: &MultiStageData<RegisterData<RegisterPoolMapping>>,
3043     ) -> MultiStageData<RegisterData<RegisterInfo>> {
3044         MultiStageData {
3045             vs: self.vs.advance(&mapping.vs),
3046             ps: self.ps.advance(&mapping.ps),
3047             cs: self.cs.advance(&mapping.cs),
3048         }
3049     }
3050 }
3051 
3052 #[derive(Clone, Debug)]
3053 struct DescriptorSetInfo {
3054     bindings: Arc<Vec<pso::DescriptorSetLayoutBinding>>,
3055     registers: MultiStageData<RegisterData<RegisterInfo>>,
3056 }
3057 
3058 impl DescriptorSetInfo {
find_register( &self, stage: pso::Stage, binding_index: pso::DescriptorBinding, ) -> (DescriptorContent, RegisterData<ResourceIndex>)3059     fn find_register(
3060         &self,
3061         stage: pso::Stage,
3062         binding_index: pso::DescriptorBinding,
3063     ) -> (DescriptorContent, RegisterData<ResourceIndex>) {
3064         let mut res_offsets = self
3065             .registers
3066             .map_register(|info| info.res_index as DescriptorIndex)
3067             .select(stage);
3068         for binding in self.bindings.iter() {
3069             let content = DescriptorContent::from(binding.ty);
3070             if binding.binding == binding_index {
3071                 return (content, res_offsets.map(|offset| *offset as ResourceIndex));
3072             }
3073             res_offsets.add_content(content);
3074         }
3075         panic!("Unable to find binding {:?}", binding_index);
3076     }
3077 }
3078 
3079 /// The pipeline layout holds optimized (less api calls) ranges of objects for all descriptor sets
3080 /// belonging to the pipeline object.
3081 #[derive(Debug)]
3082 pub struct PipelineLayout {
3083     sets: Vec<DescriptorSetInfo>,
3084 }
3085 
3086 /// The descriptor set layout contains mappings from a given binding to the offset in our
3087 /// descriptor pool storage and what type of descriptor it is (combined image sampler takes up two
3088 /// handles).
3089 #[derive(Debug)]
3090 pub struct DescriptorSetLayout {
3091     bindings: Arc<Vec<pso::DescriptorSetLayoutBinding>>,
3092     pool_mapping: MultiStageData<RegisterData<RegisterPoolMapping>>,
3093 }
3094 
3095 #[derive(Debug)]
3096 struct CoherentBufferFlushRange {
3097     device_buffer: *mut d3d11::ID3D11Buffer,
3098     host_ptr: *mut u8,
3099     range: SyncRange,
3100 }
3101 
3102 #[derive(Debug)]
3103 struct CoherentBufferInvalidateRange {
3104     device_buffer: *mut d3d11::ID3D11Buffer,
3105     host_ptr: *mut u8,
3106     range: Range<u64>,
3107 }
3108 
3109 #[derive(Debug)]
3110 struct CoherentBuffers {
3111     // descriptor set writes containing coherent resources go into these vecs and are added to the
3112     // command buffers own Vec on binding the set.
3113     flush_coherent_buffers: RefCell<Vec<CoherentBufferFlushRange>>,
3114     invalidate_coherent_buffers: RefCell<Vec<CoherentBufferInvalidateRange>>,
3115 }
3116 
3117 impl CoherentBuffers {
_add_flush(&self, old: *mut d3d11::ID3D11Buffer, buffer: &Buffer)3118     fn _add_flush(&self, old: *mut d3d11::ID3D11Buffer, buffer: &Buffer) {
3119         let new = buffer.internal.raw;
3120 
3121         if old != new {
3122             let mut buffers = self.flush_coherent_buffers.borrow_mut();
3123 
3124             let pos = buffers.iter().position(|sync| old == sync.device_buffer);
3125 
3126             let sync_range = CoherentBufferFlushRange {
3127                 device_buffer: new,
3128                 host_ptr: buffer.host_ptr,
3129                 range: SyncRange::Whole,
3130             };
3131 
3132             if let Some(pos) = pos {
3133                 buffers[pos] = sync_range;
3134             } else {
3135                 buffers.push(sync_range);
3136             }
3137 
3138             if let Some(disjoint) = buffer.internal.disjoint_cb {
3139                 let pos = buffers
3140                     .iter()
3141                     .position(|sync| disjoint == sync.device_buffer);
3142 
3143                 let sync_range = CoherentBufferFlushRange {
3144                     device_buffer: disjoint,
3145                     host_ptr: buffer.host_ptr,
3146                     range: SyncRange::Whole,
3147                 };
3148 
3149                 if let Some(pos) = pos {
3150                     buffers[pos] = sync_range;
3151                 } else {
3152                     buffers.push(sync_range);
3153                 }
3154             }
3155         }
3156     }
3157 
_add_invalidate(&self, old: *mut d3d11::ID3D11Buffer, buffer: &Buffer)3158     fn _add_invalidate(&self, old: *mut d3d11::ID3D11Buffer, buffer: &Buffer) {
3159         let new = buffer.internal.raw;
3160 
3161         if old != new {
3162             let mut buffers = self.invalidate_coherent_buffers.borrow_mut();
3163 
3164             let pos = buffers.iter().position(|sync| old == sync.device_buffer);
3165 
3166             let sync_range = CoherentBufferInvalidateRange {
3167                 device_buffer: new,
3168                 host_ptr: buffer.host_ptr,
3169                 range: buffer.bound_range.clone(),
3170             };
3171 
3172             if let Some(pos) = pos {
3173                 buffers[pos] = sync_range;
3174             } else {
3175                 buffers.push(sync_range);
3176             }
3177         }
3178     }
3179 }
3180 
3181 /// Newtype around a common interface that all bindable resources inherit from.
3182 #[derive(Debug, Copy, Clone)]
3183 #[repr(C)]
3184 struct Descriptor(*mut d3d11::ID3D11DeviceChild);
3185 
3186 bitflags! {
3187     /// A set of D3D11 descriptor types that need to be associated
3188     /// with a single gfx-hal `DescriptorType`.
3189     #[derive(Default)]
3190     pub struct DescriptorContent: u8 {
3191         const CBV = 0x1;
3192         const SRV = 0x2;
3193         const UAV = 0x4;
3194         const SAMPLER = 0x8;
3195         /// Indicates if the descriptor is a dynamic uniform/storage buffer.
3196         /// Important as dynamic buffers are implemented as root descriptors.
3197         const DYNAMIC = 0x10;
3198     }
3199 }
3200 
3201 impl From<pso::DescriptorType> for DescriptorContent {
from(ty: pso::DescriptorType) -> Self3202     fn from(ty: pso::DescriptorType) -> Self {
3203         use hal::pso::{
3204             BufferDescriptorFormat as Bdf,
3205             BufferDescriptorType as Bdt,
3206             DescriptorType as Dt,
3207             ImageDescriptorType as Idt,
3208         };
3209         match ty {
3210             Dt::Sampler => DescriptorContent::SAMPLER,
3211             Dt::Image {
3212                 ty: Idt::Sampled { with_sampler: true },
3213             } => DescriptorContent::SRV | DescriptorContent::SAMPLER,
3214             Dt::Image {
3215                 ty: Idt::Sampled {
3216                     with_sampler: false,
3217                 },
3218             }
3219             | Dt::Image {
3220                 ty: Idt::Storage { read_only: true },
3221             }
3222             | Dt::InputAttachment => DescriptorContent::SRV,
3223             Dt::Image {
3224                 ty: Idt::Storage { read_only: false },
3225             } => DescriptorContent::SRV | DescriptorContent::UAV,
3226             Dt::Buffer {
3227                 ty: Bdt::Uniform,
3228                 format:
3229                     Bdf::Structured {
3230                         dynamic_offset: true,
3231                     },
3232             } => DescriptorContent::CBV | DescriptorContent::DYNAMIC,
3233             Dt::Buffer {
3234                 ty: Bdt::Uniform, ..
3235             } => DescriptorContent::CBV,
3236             Dt::Buffer {
3237                 ty: Bdt::Storage { read_only: true },
3238                 format:
3239                     Bdf::Structured {
3240                         dynamic_offset: true,
3241                     },
3242             } => DescriptorContent::SRV | DescriptorContent::DYNAMIC,
3243             Dt::Buffer {
3244                 ty: Bdt::Storage { read_only: false },
3245                 format:
3246                     Bdf::Structured {
3247                         dynamic_offset: true,
3248                     },
3249             } => DescriptorContent::SRV | DescriptorContent::UAV | DescriptorContent::DYNAMIC,
3250             Dt::Buffer {
3251                 ty: Bdt::Storage { read_only: true },
3252                 ..
3253             } => DescriptorContent::SRV,
3254             Dt::Buffer {
3255                 ty: Bdt::Storage { read_only: false },
3256                 ..
3257             } => DescriptorContent::SRV | DescriptorContent::UAV,
3258         }
3259     }
3260 }
3261 
3262 pub struct DescriptorSet {
3263     offset: DescriptorIndex,
3264     len: DescriptorIndex,
3265     handles: *mut Descriptor,
3266     coherent_buffers: Mutex<CoherentBuffers>,
3267     layout: DescriptorSetLayout,
3268 }
3269 
3270 impl fmt::Debug for DescriptorSet {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result3271     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
3272         fmt.write_str("DescriptorSet")
3273     }
3274 }
3275 
3276 unsafe impl Send for DescriptorSet {}
3277 unsafe impl Sync for DescriptorSet {}
3278 
3279 impl DescriptorSet {
_add_flush(&self, old: *mut d3d11::ID3D11Buffer, buffer: &Buffer)3280     fn _add_flush(&self, old: *mut d3d11::ID3D11Buffer, buffer: &Buffer) {
3281         let new = buffer.internal.raw;
3282 
3283         if old != new {
3284             self.coherent_buffers.lock()._add_flush(old, buffer);
3285         }
3286     }
3287 
_add_invalidate(&self, old: *mut d3d11::ID3D11Buffer, buffer: &Buffer)3288     fn _add_invalidate(&self, old: *mut d3d11::ID3D11Buffer, buffer: &Buffer) {
3289         let new = buffer.internal.raw;
3290 
3291         if old != new {
3292             self.coherent_buffers.lock()._add_invalidate(old, buffer);
3293         }
3294     }
3295 
assign(&self, offset: DescriptorIndex, value: *mut d3d11::ID3D11DeviceChild)3296     unsafe fn assign(&self, offset: DescriptorIndex, value: *mut d3d11::ID3D11DeviceChild) {
3297         *self.handles.offset(offset as isize) = Descriptor(value);
3298     }
3299 
assign_stages( &self, offsets: &MultiStageData<DescriptorIndex>, stages: pso::ShaderStageFlags, value: *mut d3d11::ID3D11DeviceChild, )3300     unsafe fn assign_stages(
3301         &self,
3302         offsets: &MultiStageData<DescriptorIndex>,
3303         stages: pso::ShaderStageFlags,
3304         value: *mut d3d11::ID3D11DeviceChild,
3305     ) {
3306         if stages.contains(pso::ShaderStageFlags::VERTEX) {
3307             self.assign(offsets.vs, value);
3308         }
3309         if stages.contains(pso::ShaderStageFlags::FRAGMENT) {
3310             self.assign(offsets.ps, value);
3311         }
3312         if stages.contains(pso::ShaderStageFlags::COMPUTE) {
3313             self.assign(offsets.cs, value);
3314         }
3315     }
3316 }
3317 
3318 #[derive(Debug)]
3319 pub struct DescriptorPool {
3320     handles: Vec<Descriptor>,
3321     allocator: RangeAllocator<DescriptorIndex>,
3322 }
3323 
3324 unsafe impl Send for DescriptorPool {}
3325 unsafe impl Sync for DescriptorPool {}
3326 
3327 impl DescriptorPool {
with_capacity(size: DescriptorIndex) -> Self3328     fn with_capacity(size: DescriptorIndex) -> Self {
3329         DescriptorPool {
3330             handles: vec![Descriptor(ptr::null_mut()); size as usize],
3331             allocator: RangeAllocator::new(0 .. size),
3332         }
3333     }
3334 }
3335 
3336 impl pso::DescriptorPool<Backend> for DescriptorPool {
allocate_set( &mut self, layout: &DescriptorSetLayout, ) -> Result<DescriptorSet, pso::AllocationError>3337     unsafe fn allocate_set(
3338         &mut self,
3339         layout: &DescriptorSetLayout,
3340     ) -> Result<DescriptorSet, pso::AllocationError> {
3341         let len = layout
3342             .pool_mapping
3343             .map_register(|mapping| mapping.count as DescriptorIndex)
3344             .sum()
3345             .max(1);
3346 
3347         self.allocator
3348             .allocate_range(len)
3349             .map(|range| {
3350                 for handle in &mut self.handles[range.start as usize .. range.end as usize] {
3351                     *handle = Descriptor(ptr::null_mut());
3352                 }
3353 
3354                 DescriptorSet {
3355                     offset: range.start,
3356                     len,
3357                     handles: self.handles.as_mut_ptr().offset(range.start as _),
3358                     coherent_buffers: Mutex::new(CoherentBuffers {
3359                         flush_coherent_buffers: RefCell::new(Vec::new()),
3360                         invalidate_coherent_buffers: RefCell::new(Vec::new()),
3361                     }),
3362                     layout: DescriptorSetLayout {
3363                         bindings: Arc::clone(&layout.bindings),
3364                         pool_mapping: layout.pool_mapping.clone(),
3365                     },
3366                 }
3367             })
3368             .map_err(|_| pso::AllocationError::OutOfPoolMemory)
3369     }
3370 
free_sets<I>(&mut self, descriptor_sets: I) where I: IntoIterator<Item = DescriptorSet>,3371     unsafe fn free_sets<I>(&mut self, descriptor_sets: I)
3372     where
3373         I: IntoIterator<Item = DescriptorSet>,
3374     {
3375         for set in descriptor_sets {
3376             self.allocator
3377                 .free_range(set.offset .. (set.offset + set.len))
3378         }
3379     }
3380 
reset(&mut self)3381     unsafe fn reset(&mut self) {
3382         self.allocator.reset();
3383     }
3384 }
3385 
3386 #[derive(Debug)]
3387 pub struct RawFence {
3388     mutex: Mutex<bool>,
3389     condvar: Condvar,
3390 }
3391 
3392 pub type Fence = Arc<RawFence>;
3393 
3394 #[derive(Debug)]
3395 pub struct Semaphore;
3396 #[derive(Debug)]
3397 pub struct QueryPool;
3398 
3399 #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
3400 pub enum Backend {}
3401 impl hal::Backend for Backend {
3402     type Instance = Instance;
3403     type PhysicalDevice = PhysicalDevice;
3404     type Device = device::Device;
3405 
3406     type Surface = Surface;
3407     type Swapchain = Swapchain;
3408 
3409     type QueueFamily = QueueFamily;
3410     type CommandQueue = CommandQueue;
3411     type CommandBuffer = CommandBuffer;
3412 
3413     type Memory = Memory;
3414     type CommandPool = CommandPool;
3415 
3416     type ShaderModule = ShaderModule;
3417     type RenderPass = RenderPass;
3418     type Framebuffer = Framebuffer;
3419 
3420     type Buffer = Buffer;
3421     type BufferView = BufferView;
3422     type Image = Image;
3423 
3424     type ImageView = ImageView;
3425     type Sampler = Sampler;
3426 
3427     type ComputePipeline = ComputePipeline;
3428     type GraphicsPipeline = GraphicsPipeline;
3429     type PipelineLayout = PipelineLayout;
3430     type PipelineCache = ();
3431     type DescriptorSetLayout = DescriptorSetLayout;
3432     type DescriptorPool = DescriptorPool;
3433     type DescriptorSet = DescriptorSet;
3434 
3435     type Fence = Fence;
3436     type Semaphore = Semaphore;
3437     type Event = ();
3438     type QueryPool = QueryPool;
3439 }
3440 
validate_line_width(width: f32)3441 fn validate_line_width(width: f32) {
3442     // Note from the Vulkan spec:
3443     // > If the wide lines feature is not enabled, lineWidth must be 1.0
3444     // Simply assert and no-op because DX11 never exposes `Features::LINE_WIDTH`
3445     assert_eq!(width, 1.0);
3446 }
3447