1 use std::{
2     borrow::Borrow,
3     collections::{BTreeMap, VecDeque},
4     ffi,
5     mem,
6     ops::Range,
7     ptr,
8     slice,
9 };
10 
11 use range_alloc::RangeAllocator;
12 use smallvec::SmallVec;
13 use spirv_cross::{hlsl, spirv, ErrorCode as SpirvErrorCode};
14 
15 use winapi::{
16     shared::{
17         dxgi,
18         dxgi1_2,
19         dxgi1_4,
20         dxgiformat,
21         dxgitype,
22         minwindef::{FALSE, TRUE, UINT},
23         windef,
24         winerror,
25     },
26     um::{d3d12, d3dcompiler, synchapi, winbase, winnt},
27     Interface,
28 };
29 
30 use auxil::spirv_cross_specialize_ast;
31 use hal::{
32     self,
33     buffer,
34     device as d,
35     format,
36     format::Aspects,
37     image,
38     memory,
39     memory::Requirements,
40     pass,
41     pool::CommandPoolCreateFlags,
42     pso,
43     pso::VertexInputRate,
44     query,
45     queue::{CommandQueue as _, QueueFamilyId},
46     window as w,
47 };
48 
49 use crate::{
50     command as cmd,
51     conv,
52     descriptors_cpu,
53     pool::{CommandPool, CommandPoolAllocator},
54     resource as r,
55     root_constants,
56     root_constants::RootConstant,
57     window::{Surface, Swapchain},
58     Backend as B,
59     Device,
60     MemoryGroup,
61     MAX_VERTEX_BUFFERS,
62     NUM_HEAP_PROPERTIES,
63     QUEUE_FAMILIES,
64 };
65 use native::{PipelineStateSubobject, Subobject};
66 
67 // Register space used for root constants.
68 const ROOT_CONSTANT_SPACE: u32 = 0;
69 
70 const MEM_TYPE_MASK: u64 = 0x7;
71 const MEM_TYPE_SHIFT: u64 = 3;
72 
73 const MEM_TYPE_UNIVERSAL_SHIFT: u64 = MEM_TYPE_SHIFT * MemoryGroup::Universal as u64;
74 const MEM_TYPE_BUFFER_SHIFT: u64 = MEM_TYPE_SHIFT * MemoryGroup::BufferOnly as u64;
75 const MEM_TYPE_IMAGE_SHIFT: u64 = MEM_TYPE_SHIFT * MemoryGroup::ImageOnly as u64;
76 const MEM_TYPE_TARGET_SHIFT: u64 = MEM_TYPE_SHIFT * MemoryGroup::TargetOnly as u64;
77 
78 pub const IDENTITY_MAPPING: UINT = 0x1688; // D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING
79 
80 /// Emit error during shader module creation. Used if we don't expect an error
81 /// but might panic due to an exception in SPIRV-Cross.
gen_unexpected_error(err: SpirvErrorCode) -> d::ShaderError82 fn gen_unexpected_error(err: SpirvErrorCode) -> d::ShaderError {
83     let msg = match err {
84         SpirvErrorCode::CompilationError(msg) => msg,
85         SpirvErrorCode::Unhandled => "Unexpected error".into(),
86     };
87     d::ShaderError::CompilationFailed(msg)
88 }
89 
90 /// Emit error during shader module creation. Used if we execute an query command.
gen_query_error(err: SpirvErrorCode) -> d::ShaderError91 fn gen_query_error(err: SpirvErrorCode) -> d::ShaderError {
92     let msg = match err {
93         SpirvErrorCode::CompilationError(msg) => msg,
94         SpirvErrorCode::Unhandled => "Unknown query error".into(),
95     };
96     d::ShaderError::CompilationFailed(msg)
97 }
98 
99 #[derive(Clone, Debug)]
100 pub(crate) struct ViewInfo {
101     pub(crate) resource: native::Resource,
102     pub(crate) kind: image::Kind,
103     pub(crate) caps: image::ViewCapabilities,
104     pub(crate) view_kind: image::ViewKind,
105     pub(crate) format: dxgiformat::DXGI_FORMAT,
106     pub(crate) component_mapping: UINT,
107     pub(crate) range: image::SubresourceRange,
108 }
109 
110 pub(crate) enum CommandSignature {
111     Draw,
112     DrawIndexed,
113     Dispatch,
114 }
115 
116 /// Compile a single shader entry point from a HLSL text shader
compile_shader( stage: pso::Stage, shader_model: hlsl::ShaderModel, entry: &str, code: &[u8], ) -> Result<native::Blob, d::ShaderError>117 pub(crate) fn compile_shader(
118     stage: pso::Stage,
119     shader_model: hlsl::ShaderModel,
120     entry: &str,
121     code: &[u8],
122 ) -> Result<native::Blob, d::ShaderError> {
123     let stage_to_str = |stage, shader_model| {
124         let stage = match stage {
125             pso::Stage::Vertex => "vs",
126             pso::Stage::Fragment => "ps",
127             pso::Stage::Compute => "cs",
128             _ => unimplemented!(),
129         };
130 
131         let model = match shader_model {
132             hlsl::ShaderModel::V5_0 => "5_0",
133             hlsl::ShaderModel::V5_1 => "5_1",
134             hlsl::ShaderModel::V6_0 => "6_0",
135             _ => unimplemented!(),
136         };
137 
138         format!("{}_{}\0", stage, model)
139     };
140 
141     let mut shader_data = native::Blob::null();
142     let mut error = native::Blob::null();
143     let entry = ffi::CString::new(entry).unwrap();
144     let hr = unsafe {
145         d3dcompiler::D3DCompile(
146             code.as_ptr() as *const _,
147             code.len(),
148             ptr::null(),
149             ptr::null(),
150             ptr::null_mut(),
151             entry.as_ptr() as *const _,
152             stage_to_str(stage, shader_model).as_ptr() as *const i8,
153             1,
154             0,
155             shader_data.mut_void() as *mut *mut _,
156             error.mut_void() as *mut *mut _,
157         )
158     };
159     if !winerror::SUCCEEDED(hr) {
160         error!("D3DCompile error {:x}", hr);
161         let message = unsafe {
162             let pointer = error.GetBufferPointer();
163             let size = error.GetBufferSize();
164             let slice = slice::from_raw_parts(pointer as *const u8, size as usize);
165             String::from_utf8_lossy(slice).into_owned()
166         };
167         unsafe {
168             error.destroy();
169         }
170         Err(d::ShaderError::CompilationFailed(message))
171     } else {
172         Ok(shader_data)
173     }
174 }
175 
176 #[repr(C)]
177 struct GraphicsPipelineStateSubobjectStream {
178     root_signature: PipelineStateSubobject<*mut d3d12::ID3D12RootSignature>,
179     vs: PipelineStateSubobject<d3d12::D3D12_SHADER_BYTECODE>,
180     ps: PipelineStateSubobject<d3d12::D3D12_SHADER_BYTECODE>,
181     ds: PipelineStateSubobject<d3d12::D3D12_SHADER_BYTECODE>,
182     hs: PipelineStateSubobject<d3d12::D3D12_SHADER_BYTECODE>,
183     gs: PipelineStateSubobject<d3d12::D3D12_SHADER_BYTECODE>,
184     stream_output: PipelineStateSubobject<d3d12::D3D12_STREAM_OUTPUT_DESC>,
185     blend: PipelineStateSubobject<d3d12::D3D12_BLEND_DESC>,
186     sample_mask: PipelineStateSubobject<UINT>,
187     rasterizer: PipelineStateSubobject<d3d12::D3D12_RASTERIZER_DESC>,
188     depth_stencil: PipelineStateSubobject<d3d12::D3D12_DEPTH_STENCIL_DESC1>,
189     input_layout: PipelineStateSubobject<d3d12::D3D12_INPUT_LAYOUT_DESC>,
190     ib_strip_cut_value: PipelineStateSubobject<d3d12::D3D12_INDEX_BUFFER_STRIP_CUT_VALUE>,
191     primitive_topology: PipelineStateSubobject<d3d12::D3D12_PRIMITIVE_TOPOLOGY_TYPE>,
192     render_target_formats: PipelineStateSubobject<d3d12::D3D12_RT_FORMAT_ARRAY>,
193     depth_stencil_format: PipelineStateSubobject<dxgiformat::DXGI_FORMAT>,
194     sample_desc: PipelineStateSubobject<dxgitype::DXGI_SAMPLE_DESC>,
195     node_mask: PipelineStateSubobject<UINT>,
196     cached_pso: PipelineStateSubobject<d3d12::D3D12_CACHED_PIPELINE_STATE>,
197     flags: PipelineStateSubobject<d3d12::D3D12_PIPELINE_STATE_FLAGS>,
198 }
199 
200 impl GraphicsPipelineStateSubobjectStream {
new( pso_desc: &d3d12::D3D12_GRAPHICS_PIPELINE_STATE_DESC, depth_bounds_test_enable: bool, ) -> Self201     fn new(
202         pso_desc: &d3d12::D3D12_GRAPHICS_PIPELINE_STATE_DESC,
203         depth_bounds_test_enable: bool,
204     ) -> Self {
205         GraphicsPipelineStateSubobjectStream {
206             root_signature: PipelineStateSubobject::new(
207                 Subobject::RootSignature,
208                 pso_desc.pRootSignature,
209             ),
210             vs: PipelineStateSubobject::new(Subobject::VS, pso_desc.VS),
211             ps: PipelineStateSubobject::new(Subobject::PS, pso_desc.PS),
212             ds: PipelineStateSubobject::new(Subobject::DS, pso_desc.DS),
213             hs: PipelineStateSubobject::new(Subobject::HS, pso_desc.HS),
214             gs: PipelineStateSubobject::new(Subobject::GS, pso_desc.GS),
215             stream_output: PipelineStateSubobject::new(
216                 Subobject::StreamOutput,
217                 pso_desc.StreamOutput,
218             ),
219             blend: PipelineStateSubobject::new(Subobject::Blend, pso_desc.BlendState),
220             sample_mask: PipelineStateSubobject::new(Subobject::SampleMask, pso_desc.SampleMask),
221             rasterizer: PipelineStateSubobject::new(
222                 Subobject::Rasterizer,
223                 pso_desc.RasterizerState,
224             ),
225             depth_stencil: PipelineStateSubobject::new(
226                 Subobject::DepthStencil1,
227                 d3d12::D3D12_DEPTH_STENCIL_DESC1 {
228                     DepthEnable: pso_desc.DepthStencilState.DepthEnable,
229                     DepthWriteMask: pso_desc.DepthStencilState.DepthWriteMask,
230                     DepthFunc: pso_desc.DepthStencilState.DepthFunc,
231                     StencilEnable: pso_desc.DepthStencilState.StencilEnable,
232                     StencilReadMask: pso_desc.DepthStencilState.StencilReadMask,
233                     StencilWriteMask: pso_desc.DepthStencilState.StencilWriteMask,
234                     FrontFace: pso_desc.DepthStencilState.FrontFace,
235                     BackFace: pso_desc.DepthStencilState.BackFace,
236                     DepthBoundsTestEnable: depth_bounds_test_enable as _,
237                 },
238             ),
239             input_layout: PipelineStateSubobject::new(Subobject::InputLayout, pso_desc.InputLayout),
240             ib_strip_cut_value: PipelineStateSubobject::new(
241                 Subobject::IBStripCut,
242                 pso_desc.IBStripCutValue,
243             ),
244             primitive_topology: PipelineStateSubobject::new(
245                 Subobject::PrimitiveTopology,
246                 pso_desc.PrimitiveTopologyType,
247             ),
248             render_target_formats: PipelineStateSubobject::new(
249                 Subobject::RTFormats,
250                 d3d12::D3D12_RT_FORMAT_ARRAY {
251                     RTFormats: pso_desc.RTVFormats,
252                     NumRenderTargets: pso_desc.NumRenderTargets,
253                 },
254             ),
255             depth_stencil_format: PipelineStateSubobject::new(
256                 Subobject::DSFormat,
257                 pso_desc.DSVFormat,
258             ),
259             sample_desc: PipelineStateSubobject::new(Subobject::SampleDesc, pso_desc.SampleDesc),
260             node_mask: PipelineStateSubobject::new(Subobject::NodeMask, pso_desc.NodeMask),
261             cached_pso: PipelineStateSubobject::new(Subobject::CachedPSO, pso_desc.CachedPSO),
262             flags: PipelineStateSubobject::new(Subobject::Flags, pso_desc.Flags),
263         }
264     }
265 }
266 
267 impl Device {
parse_spirv(raw_data: &[u32]) -> Result<spirv::Ast<hlsl::Target>, d::ShaderError>268     fn parse_spirv(raw_data: &[u32]) -> Result<spirv::Ast<hlsl::Target>, d::ShaderError> {
269         let module = spirv::Module::from_words(raw_data);
270 
271         spirv::Ast::parse(&module).map_err(|err| {
272             let msg = match err {
273                 SpirvErrorCode::CompilationError(msg) => msg,
274                 SpirvErrorCode::Unhandled => "Unknown parsing error".into(),
275             };
276             d::ShaderError::CompilationFailed(msg)
277         })
278     }
279 
patch_spirv_resources( ast: &mut spirv::Ast<hlsl::Target>, layout: &r::PipelineLayout, ) -> Result<(), d::ShaderError>280     fn patch_spirv_resources(
281         ast: &mut spirv::Ast<hlsl::Target>,
282         layout: &r::PipelineLayout,
283     ) -> Result<(), d::ShaderError> {
284         // Move the descriptor sets away to yield for the root constants at "space0".
285         let space_offset = if layout.constants.is_empty() { 0 } else { 1 };
286         let shader_resources = ast.get_shader_resources().map_err(gen_query_error)?;
287 
288         if space_offset != 0 {
289             for image in &shader_resources.separate_images {
290                 let set = ast
291                     .get_decoration(image.id, spirv::Decoration::DescriptorSet)
292                     .map_err(gen_query_error)?;
293                 ast.set_decoration(
294                     image.id,
295                     spirv::Decoration::DescriptorSet,
296                     space_offset + set,
297                 )
298                 .map_err(gen_unexpected_error)?;
299             }
300         }
301 
302         if space_offset != 0 {
303             for uniform_buffer in &shader_resources.uniform_buffers {
304                 let set = ast
305                     .get_decoration(uniform_buffer.id, spirv::Decoration::DescriptorSet)
306                     .map_err(gen_query_error)?;
307                 ast.set_decoration(
308                     uniform_buffer.id,
309                     spirv::Decoration::DescriptorSet,
310                     space_offset + set,
311                 )
312                 .map_err(gen_unexpected_error)?;
313             }
314         }
315 
316         for storage_buffer in &shader_resources.storage_buffers {
317             let set = ast
318                 .get_decoration(storage_buffer.id, spirv::Decoration::DescriptorSet)
319                 .map_err(gen_query_error)?;
320             let binding = ast
321                 .get_decoration(storage_buffer.id, spirv::Decoration::Binding)
322                 .map_err(gen_query_error)?;
323             if space_offset != 0 {
324                 ast.set_decoration(
325                     storage_buffer.id,
326                     spirv::Decoration::DescriptorSet,
327                     space_offset + set,
328                 )
329                 .map_err(gen_unexpected_error)?;
330             }
331             if !layout.elements[set as usize].mutable_bindings.contains(&binding) {
332                 ast.set_decoration(
333                     storage_buffer.id,
334                     spirv::Decoration::NonWritable,
335                     0,
336                 )
337                 .map_err(gen_unexpected_error)?
338             }
339         }
340 
341         for image in &shader_resources.storage_images {
342             let set = ast
343                 .get_decoration(image.id, spirv::Decoration::DescriptorSet)
344                 .map_err(gen_query_error)?;
345             let binding = ast
346                 .get_decoration(image.id, spirv::Decoration::Binding)
347                 .map_err(gen_query_error)?;
348             if space_offset != 0 {
349                 ast.set_decoration(
350                     image.id,
351                     spirv::Decoration::DescriptorSet,
352                     space_offset + set,
353                 )
354                 .map_err(gen_unexpected_error)?;
355             }
356             if !layout.elements[set as usize].mutable_bindings.contains(&binding) {
357                 ast.set_decoration(
358                     image.id,
359                     spirv::Decoration::NonWritable,
360                     0,
361                 )
362                 .map_err(gen_unexpected_error)?
363             }
364         }
365 
366         if space_offset != 0 {
367             for sampler in &shader_resources.separate_samplers {
368                 let set = ast
369                     .get_decoration(sampler.id, spirv::Decoration::DescriptorSet)
370                     .map_err(gen_query_error)?;
371                 ast.set_decoration(
372                     sampler.id,
373                     spirv::Decoration::DescriptorSet,
374                     space_offset + set,
375                 )
376                 .map_err(gen_unexpected_error)?;
377             }
378         }
379 
380         if space_offset != 0 {
381             for image in &shader_resources.sampled_images {
382                 let set = ast
383                     .get_decoration(image.id, spirv::Decoration::DescriptorSet)
384                     .map_err(gen_query_error)?;
385                 ast.set_decoration(
386                     image.id,
387                     spirv::Decoration::DescriptorSet,
388                     space_offset + set,
389                 )
390                 .map_err(gen_unexpected_error)?;
391             }
392         }
393 
394         if space_offset != 0 {
395             for input in &shader_resources.subpass_inputs {
396                 let set = ast
397                     .get_decoration(input.id, spirv::Decoration::DescriptorSet)
398                     .map_err(gen_query_error)?;
399                 ast.set_decoration(
400                     input.id,
401                     spirv::Decoration::DescriptorSet,
402                     space_offset + set,
403                 )
404                 .map_err(gen_unexpected_error)?;
405             }
406         }
407 
408         Ok(())
409     }
410 
translate_spirv( ast: &mut spirv::Ast<hlsl::Target>, shader_model: hlsl::ShaderModel, layout: &r::PipelineLayout, stage: pso::Stage, features: &hal::Features, ) -> Result<String, d::ShaderError>411     fn translate_spirv(
412         ast: &mut spirv::Ast<hlsl::Target>,
413         shader_model: hlsl::ShaderModel,
414         layout: &r::PipelineLayout,
415         stage: pso::Stage,
416         features: &hal::Features,
417     ) -> Result<String, d::ShaderError> {
418         let mut compile_options = hlsl::CompilerOptions::default();
419         compile_options.shader_model = shader_model;
420         compile_options.vertex.invert_y = !features.contains(hal::Features::NDC_Y_UP);
421 
422         let stage_flag = stage.into();
423         let root_constant_layout = layout
424             .constants
425             .iter()
426             .filter_map(|constant| {
427                 if constant.stages.contains(stage_flag) {
428                     Some(hlsl::RootConstant {
429                         start: constant.range.start * 4,
430                         end: constant.range.end * 4,
431                         binding: constant.range.start,
432                         space: 0,
433                     })
434                 } else {
435                     None
436                 }
437             })
438             .collect();
439         ast.set_compiler_options(&compile_options)
440             .map_err(gen_unexpected_error)?;
441         ast.set_root_constant_layout(root_constant_layout)
442             .map_err(gen_unexpected_error)?;
443         ast.compile().map_err(|err| {
444             let msg = match err {
445                 SpirvErrorCode::CompilationError(msg) => msg,
446                 SpirvErrorCode::Unhandled => "Unknown compile error".into(),
447             };
448             d::ShaderError::CompilationFailed(msg)
449         })
450     }
451 
452     // Extract entry point from shader module on pipeline creation.
453     // Returns compiled shader blob and bool to indicate if the shader should be
454     // destroyed after pipeline creation
extract_entry_point( stage: pso::Stage, source: &pso::EntryPoint<B>, layout: &r::PipelineLayout, features: &hal::Features, ) -> Result<(native::Blob, bool), d::ShaderError>455     fn extract_entry_point(
456         stage: pso::Stage,
457         source: &pso::EntryPoint<B>,
458         layout: &r::PipelineLayout,
459         features: &hal::Features,
460     ) -> Result<(native::Blob, bool), d::ShaderError> {
461         match *source.module {
462             r::ShaderModule::Compiled(ref shaders) => {
463                 // TODO: do we need to check for specialization constants?
464                 // Use precompiled shader, ignore specialization or layout.
465                 shaders
466                     .get(source.entry)
467                     .map(|src| (*src, false))
468                     .ok_or(d::ShaderError::MissingEntryPoint(source.entry.into()))
469             }
470             r::ShaderModule::Spirv(ref raw_data) => {
471                 let mut ast = Self::parse_spirv(raw_data)?;
472                 spirv_cross_specialize_ast(&mut ast, &source.specialization)?;
473                 Self::patch_spirv_resources(&mut ast, layout)?;
474 
475                 let shader_model = hlsl::ShaderModel::V5_1;
476                 let shader_code =
477                     Self::translate_spirv(&mut ast, shader_model, layout, stage, features)?;
478                 debug!("SPIRV-Cross generated shader:\n{}", shader_code);
479 
480                 let real_name = ast
481                     .get_cleansed_entry_point_name(source.entry, conv::map_stage(stage))
482                     .map_err(gen_query_error)?;
483                 // TODO: opt: don't query *all* entry points.
484                 let entry_points = ast.get_entry_points().map_err(gen_query_error)?;
485                 entry_points
486                     .iter()
487                     .find(|entry_point| entry_point.name == real_name)
488                     .ok_or(d::ShaderError::MissingEntryPoint(source.entry.into()))
489                     .and_then(|entry_point| {
490                         let stage = conv::map_execution_model(entry_point.execution_model);
491                         let shader = compile_shader(
492                             stage,
493                             shader_model,
494                             &entry_point.name,
495                             shader_code.as_bytes(),
496                         )?;
497                         Ok((shader, true))
498                     })
499             }
500         }
501     }
502 
503     /// Create a shader module from HLSL with a single entry point
create_shader_module_from_source( &self, stage: pso::Stage, hlsl_entry: &str, entry_point: &str, code: &[u8], ) -> Result<r::ShaderModule, d::ShaderError>504     pub fn create_shader_module_from_source(
505         &self,
506         stage: pso::Stage,
507         hlsl_entry: &str,
508         entry_point: &str,
509         code: &[u8],
510     ) -> Result<r::ShaderModule, d::ShaderError> {
511         let mut shader_map = BTreeMap::new();
512         let blob = compile_shader(stage, hlsl::ShaderModel::V5_1, hlsl_entry, code)?;
513         shader_map.insert(entry_point.into(), blob);
514         Ok(r::ShaderModule::Compiled(shader_map))
515     }
516 
create_command_signature( device: native::Device, ty: CommandSignature, ) -> native::CommandSignature517     pub(crate) fn create_command_signature(
518         device: native::Device,
519         ty: CommandSignature,
520     ) -> native::CommandSignature {
521         let (arg, stride) = match ty {
522             CommandSignature::Draw => (native::IndirectArgument::draw(), 16),
523             CommandSignature::DrawIndexed => (native::IndirectArgument::draw_indexed(), 20),
524             CommandSignature::Dispatch => (native::IndirectArgument::dispatch(), 12),
525         };
526 
527         let (signature, hr) =
528             device.create_command_signature(native::RootSignature::null(), &[arg], stride, 0);
529 
530         if !winerror::SUCCEEDED(hr) {
531             error!("error on command signature creation: {:x}", hr);
532         }
533         signature
534     }
535 
create_descriptor_heap_impl( device: native::Device, heap_type: native::DescriptorHeapType, shader_visible: bool, capacity: usize, ) -> r::DescriptorHeap536     pub(crate) fn create_descriptor_heap_impl(
537         device: native::Device,
538         heap_type: native::DescriptorHeapType,
539         shader_visible: bool,
540         capacity: usize,
541     ) -> r::DescriptorHeap {
542         assert_ne!(capacity, 0);
543 
544         let (heap, _hr) = device.create_descriptor_heap(
545             capacity as _,
546             heap_type,
547             if shader_visible {
548                 native::DescriptorHeapFlags::SHADER_VISIBLE
549             } else {
550                 native::DescriptorHeapFlags::empty()
551             },
552             0,
553         );
554 
555         let descriptor_size = device.get_descriptor_increment_size(heap_type);
556         let cpu_handle = heap.start_cpu_descriptor();
557         let gpu_handle = heap.start_gpu_descriptor();
558 
559         let range_allocator = RangeAllocator::new(0 .. (capacity as u64));
560 
561         r::DescriptorHeap {
562             raw: heap,
563             handle_size: descriptor_size as _,
564             total_handles: capacity as _,
565             start: r::DualHandle {
566                 cpu: cpu_handle,
567                 gpu: gpu_handle,
568                 size: 0,
569             },
570             range_allocator,
571         }
572     }
573 
view_image_as_render_target_impl( device: native::Device, handle: d3d12::D3D12_CPU_DESCRIPTOR_HANDLE, info: ViewInfo, ) -> Result<(), image::ViewCreationError>574     pub(crate) fn view_image_as_render_target_impl(
575         device: native::Device,
576         handle: d3d12::D3D12_CPU_DESCRIPTOR_HANDLE,
577         info: ViewInfo,
578     ) -> Result<(), image::ViewCreationError> {
579         #![allow(non_snake_case)]
580 
581         let mut desc = d3d12::D3D12_RENDER_TARGET_VIEW_DESC {
582             Format: info.format,
583             ViewDimension: 0,
584             u: unsafe { mem::zeroed() },
585         };
586 
587         let MipSlice = info.range.levels.start as _;
588         let FirstArraySlice = info.range.layers.start as _;
589         let ArraySize = (info.range.layers.end - info.range.layers.start) as _;
590         let is_msaa = info.kind.num_samples() > 1;
591         if info.range.levels.start + 1 != info.range.levels.end {
592             return Err(image::ViewCreationError::Level(info.range.levels.start));
593         }
594         if info.range.layers.end > info.kind.num_layers() {
595             return Err(image::ViewCreationError::Layer(
596                 image::LayerError::OutOfBounds(info.range.layers),
597             ));
598         }
599 
600         match info.view_kind {
601             image::ViewKind::D1 => {
602                 assert_eq!(info.range.layers, 0 .. 1);
603                 desc.ViewDimension = d3d12::D3D12_RTV_DIMENSION_TEXTURE1D;
604                 *unsafe { desc.u.Texture1D_mut() } = d3d12::D3D12_TEX1D_RTV { MipSlice }
605             }
606             image::ViewKind::D1Array => {
607                 desc.ViewDimension = d3d12::D3D12_RTV_DIMENSION_TEXTURE1DARRAY;
608                 *unsafe { desc.u.Texture1DArray_mut() } = d3d12::D3D12_TEX1D_ARRAY_RTV {
609                     MipSlice,
610                     FirstArraySlice,
611                     ArraySize,
612                 }
613             }
614             image::ViewKind::D2 if is_msaa => {
615                 assert_eq!(info.range.layers, 0 .. 1);
616                 desc.ViewDimension = d3d12::D3D12_RTV_DIMENSION_TEXTURE2DMS;
617                 *unsafe { desc.u.Texture2DMS_mut() } = d3d12::D3D12_TEX2DMS_RTV {
618                     UnusedField_NothingToDefine: 0,
619                 }
620             }
621             image::ViewKind::D2 => {
622                 assert_eq!(info.range.layers, 0 .. 1);
623                 desc.ViewDimension = d3d12::D3D12_RTV_DIMENSION_TEXTURE2D;
624                 *unsafe { desc.u.Texture2D_mut() } = d3d12::D3D12_TEX2D_RTV {
625                     MipSlice,
626                     PlaneSlice: 0, //TODO
627                 }
628             }
629             image::ViewKind::D2Array if is_msaa => {
630                 desc.ViewDimension = d3d12::D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY;
631                 *unsafe { desc.u.Texture2DMSArray_mut() } = d3d12::D3D12_TEX2DMS_ARRAY_RTV {
632                     FirstArraySlice,
633                     ArraySize,
634                 }
635             }
636             image::ViewKind::D2Array => {
637                 desc.ViewDimension = d3d12::D3D12_RTV_DIMENSION_TEXTURE2DARRAY;
638                 *unsafe { desc.u.Texture2DArray_mut() } = d3d12::D3D12_TEX2D_ARRAY_RTV {
639                     MipSlice,
640                     FirstArraySlice,
641                     ArraySize,
642                     PlaneSlice: 0, //TODO
643                 }
644             }
645             image::ViewKind::D3 => {
646                 assert_eq!(info.range.layers, 0 .. 1);
647                 desc.ViewDimension = d3d12::D3D12_RTV_DIMENSION_TEXTURE3D;
648                 *unsafe { desc.u.Texture3D_mut() } = d3d12::D3D12_TEX3D_RTV {
649                     MipSlice,
650                     FirstWSlice: 0,
651                     WSize: info.kind.extent().depth as _,
652                 }
653             }
654             image::ViewKind::Cube | image::ViewKind::CubeArray => {
655                 desc.ViewDimension = d3d12::D3D12_RTV_DIMENSION_TEXTURE2DARRAY;
656                 //TODO: double-check if any *6 are needed
657                 *unsafe { desc.u.Texture2DArray_mut() } = d3d12::D3D12_TEX2D_ARRAY_RTV {
658                     MipSlice,
659                     FirstArraySlice,
660                     ArraySize,
661                     PlaneSlice: 0, //TODO
662                 }
663             }
664         };
665 
666         unsafe {
667             device.CreateRenderTargetView(info.resource.as_mut_ptr(), &desc, handle);
668         }
669 
670         Ok(())
671     }
672 
view_image_as_render_target( &self, info: ViewInfo, ) -> Result<d3d12::D3D12_CPU_DESCRIPTOR_HANDLE, image::ViewCreationError>673     fn view_image_as_render_target(
674         &self,
675         info: ViewInfo,
676     ) -> Result<d3d12::D3D12_CPU_DESCRIPTOR_HANDLE, image::ViewCreationError> {
677         let handle = self.rtv_pool.lock().unwrap().alloc_handle();
678         Self::view_image_as_render_target_impl(self.raw, handle, info).map(|_| handle)
679     }
680 
view_image_as_depth_stencil_impl( device: native::Device, handle: d3d12::D3D12_CPU_DESCRIPTOR_HANDLE, info: ViewInfo, ) -> Result<(), image::ViewCreationError>681     pub(crate) fn view_image_as_depth_stencil_impl(
682         device: native::Device,
683         handle: d3d12::D3D12_CPU_DESCRIPTOR_HANDLE,
684         info: ViewInfo,
685     ) -> Result<(), image::ViewCreationError> {
686         #![allow(non_snake_case)]
687 
688         let mut desc = d3d12::D3D12_DEPTH_STENCIL_VIEW_DESC {
689             Format: info.format,
690             ViewDimension: 0,
691             Flags: 0,
692             u: unsafe { mem::zeroed() },
693         };
694 
695         let MipSlice = info.range.levels.start as _;
696         let FirstArraySlice = info.range.layers.start as _;
697         let ArraySize = (info.range.layers.end - info.range.layers.start) as _;
698         let is_msaa = info.kind.num_samples() > 1;
699         if info.range.levels.start + 1 != info.range.levels.end {
700             return Err(image::ViewCreationError::Level(info.range.levels.start));
701         }
702         if info.range.layers.end > info.kind.num_layers() {
703             return Err(image::ViewCreationError::Layer(
704                 image::LayerError::OutOfBounds(info.range.layers),
705             ));
706         }
707 
708         match info.view_kind {
709             image::ViewKind::D1 => {
710                 assert_eq!(info.range.layers, 0 .. 1);
711                 desc.ViewDimension = d3d12::D3D12_DSV_DIMENSION_TEXTURE1D;
712                 *unsafe { desc.u.Texture1D_mut() } = d3d12::D3D12_TEX1D_DSV { MipSlice }
713             }
714             image::ViewKind::D1Array => {
715                 desc.ViewDimension = d3d12::D3D12_DSV_DIMENSION_TEXTURE1DARRAY;
716                 *unsafe { desc.u.Texture1DArray_mut() } = d3d12::D3D12_TEX1D_ARRAY_DSV {
717                     MipSlice,
718                     FirstArraySlice,
719                     ArraySize,
720                 }
721             }
722             image::ViewKind::D2 if is_msaa => {
723                 assert_eq!(info.range.layers, 0 .. 1);
724                 desc.ViewDimension = d3d12::D3D12_DSV_DIMENSION_TEXTURE2DMS;
725                 *unsafe { desc.u.Texture2DMS_mut() } = d3d12::D3D12_TEX2DMS_DSV {
726                     UnusedField_NothingToDefine: 0,
727                 }
728             }
729             image::ViewKind::D2 => {
730                 assert_eq!(info.range.layers, 0 .. 1);
731                 desc.ViewDimension = d3d12::D3D12_DSV_DIMENSION_TEXTURE2D;
732                 *unsafe { desc.u.Texture2D_mut() } = d3d12::D3D12_TEX2D_DSV { MipSlice }
733             }
734             image::ViewKind::D2Array if is_msaa => {
735                 desc.ViewDimension = d3d12::D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY;
736                 *unsafe { desc.u.Texture2DMSArray_mut() } = d3d12::D3D12_TEX2DMS_ARRAY_DSV {
737                     FirstArraySlice,
738                     ArraySize,
739                 }
740             }
741             image::ViewKind::D2Array => {
742                 desc.ViewDimension = d3d12::D3D12_DSV_DIMENSION_TEXTURE2DARRAY;
743                 *unsafe { desc.u.Texture2DArray_mut() } = d3d12::D3D12_TEX2D_ARRAY_DSV {
744                     MipSlice,
745                     FirstArraySlice,
746                     ArraySize,
747                 }
748             }
749             image::ViewKind::D3 | image::ViewKind::Cube | image::ViewKind::CubeArray => {
750                 unimplemented!()
751             }
752         };
753 
754         unsafe {
755             device.CreateDepthStencilView(info.resource.as_mut_ptr(), &desc, handle);
756         }
757 
758         Ok(())
759     }
760 
view_image_as_depth_stencil( &self, info: ViewInfo, ) -> Result<d3d12::D3D12_CPU_DESCRIPTOR_HANDLE, image::ViewCreationError>761     fn view_image_as_depth_stencil(
762         &self,
763         info: ViewInfo,
764     ) -> Result<d3d12::D3D12_CPU_DESCRIPTOR_HANDLE, image::ViewCreationError> {
765         let handle = self.dsv_pool.lock().unwrap().alloc_handle();
766         Self::view_image_as_depth_stencil_impl(self.raw, handle, info).map(|_| handle)
767     }
768 
build_image_as_shader_resource_desc( info: &ViewInfo, ) -> Result<d3d12::D3D12_SHADER_RESOURCE_VIEW_DESC, image::ViewCreationError>769     pub(crate) fn build_image_as_shader_resource_desc(
770         info: &ViewInfo,
771     ) -> Result<d3d12::D3D12_SHADER_RESOURCE_VIEW_DESC, image::ViewCreationError> {
772         #![allow(non_snake_case)]
773 
774         let mut desc = d3d12::D3D12_SHADER_RESOURCE_VIEW_DESC {
775             Format: info.format,
776             ViewDimension: 0,
777             Shader4ComponentMapping: info.component_mapping,
778             u: unsafe { mem::zeroed() },
779         };
780 
781         let MostDetailedMip = info.range.levels.start as _;
782         let MipLevels = (info.range.levels.end - info.range.levels.start) as _;
783         let FirstArraySlice = info.range.layers.start as _;
784         let ArraySize = (info.range.layers.end - info.range.layers.start) as _;
785 
786         if info.range.layers.end > info.kind.num_layers() {
787             return Err(image::ViewCreationError::Layer(
788                 image::LayerError::OutOfBounds(info.range.layers.clone()),
789             ));
790         }
791         let is_msaa = info.kind.num_samples() > 1;
792         let is_cube = info.caps.contains(image::ViewCapabilities::KIND_CUBE);
793 
794         match info.view_kind {
795             image::ViewKind::D1 => {
796                 assert_eq!(info.range.layers, 0 .. 1);
797                 desc.ViewDimension = d3d12::D3D12_SRV_DIMENSION_TEXTURE1D;
798                 *unsafe { desc.u.Texture1D_mut() } = d3d12::D3D12_TEX1D_SRV {
799                     MostDetailedMip,
800                     MipLevels,
801                     ResourceMinLODClamp: 0.0,
802                 }
803             }
804             image::ViewKind::D1Array => {
805                 desc.ViewDimension = d3d12::D3D12_SRV_DIMENSION_TEXTURE1DARRAY;
806                 *unsafe { desc.u.Texture1DArray_mut() } = d3d12::D3D12_TEX1D_ARRAY_SRV {
807                     MostDetailedMip,
808                     MipLevels,
809                     FirstArraySlice,
810                     ArraySize,
811                     ResourceMinLODClamp: 0.0,
812                 }
813             }
814             image::ViewKind::D2 if is_msaa => {
815                 assert_eq!(info.range.layers, 0 .. 1);
816                 desc.ViewDimension = d3d12::D3D12_SRV_DIMENSION_TEXTURE2DMS;
817                 *unsafe { desc.u.Texture2DMS_mut() } = d3d12::D3D12_TEX2DMS_SRV {
818                     UnusedField_NothingToDefine: 0,
819                 }
820             }
821             image::ViewKind::D2 => {
822                 assert_eq!(info.range.layers, 0 .. 1);
823                 desc.ViewDimension = d3d12::D3D12_SRV_DIMENSION_TEXTURE2D;
824                 *unsafe { desc.u.Texture2D_mut() } = d3d12::D3D12_TEX2D_SRV {
825                     MostDetailedMip,
826                     MipLevels,
827                     PlaneSlice: 0, //TODO
828                     ResourceMinLODClamp: 0.0,
829                 }
830             }
831             image::ViewKind::D2Array if is_msaa => {
832                 desc.ViewDimension = d3d12::D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY;
833                 *unsafe { desc.u.Texture2DMSArray_mut() } = d3d12::D3D12_TEX2DMS_ARRAY_SRV {
834                     FirstArraySlice,
835                     ArraySize,
836                 }
837             }
838             image::ViewKind::D2Array => {
839                 desc.ViewDimension = d3d12::D3D12_SRV_DIMENSION_TEXTURE2DARRAY;
840                 *unsafe { desc.u.Texture2DArray_mut() } = d3d12::D3D12_TEX2D_ARRAY_SRV {
841                     MostDetailedMip,
842                     MipLevels,
843                     FirstArraySlice,
844                     ArraySize,
845                     PlaneSlice: 0, //TODO
846                     ResourceMinLODClamp: 0.0,
847                 }
848             }
849             image::ViewKind::D3 => {
850                 assert_eq!(info.range.layers, 0 .. 1);
851                 desc.ViewDimension = d3d12::D3D12_SRV_DIMENSION_TEXTURE3D;
852                 *unsafe { desc.u.Texture3D_mut() } = d3d12::D3D12_TEX3D_SRV {
853                     MostDetailedMip,
854                     MipLevels,
855                     ResourceMinLODClamp: 0.0,
856                 }
857             }
858             image::ViewKind::Cube if is_cube => {
859                 desc.ViewDimension = d3d12::D3D12_SRV_DIMENSION_TEXTURECUBE;
860                 *unsafe { desc.u.TextureCube_mut() } = d3d12::D3D12_TEXCUBE_SRV {
861                     MostDetailedMip,
862                     MipLevels,
863                     ResourceMinLODClamp: 0.0,
864                 }
865             }
866             image::ViewKind::CubeArray if is_cube => {
867                 assert_eq!(0, ArraySize % 6);
868                 desc.ViewDimension = d3d12::D3D12_SRV_DIMENSION_TEXTURECUBEARRAY;
869                 *unsafe { desc.u.TextureCubeArray_mut() } = d3d12::D3D12_TEXCUBE_ARRAY_SRV {
870                     MostDetailedMip,
871                     MipLevels,
872                     First2DArrayFace: FirstArraySlice,
873                     NumCubes: ArraySize / 6,
874                     ResourceMinLODClamp: 0.0,
875                 }
876             }
877             image::ViewKind::Cube | image::ViewKind::CubeArray => {
878                 error!(
879                     "Cube views are not supported for the image, kind: {:?}",
880                     info.kind
881                 );
882                 return Err(image::ViewCreationError::BadKind(info.view_kind));
883             }
884         }
885 
886         Ok(desc)
887     }
888 
view_image_as_shader_resource( &self, mut info: ViewInfo, ) -> Result<d3d12::D3D12_CPU_DESCRIPTOR_HANDLE, image::ViewCreationError>889     fn view_image_as_shader_resource(
890         &self,
891         mut info: ViewInfo,
892     ) -> Result<d3d12::D3D12_CPU_DESCRIPTOR_HANDLE, image::ViewCreationError> {
893         #![allow(non_snake_case)]
894 
895         // Depth-stencil formats can't be used for SRVs.
896         info.format = match info.format {
897             dxgiformat::DXGI_FORMAT_D16_UNORM => dxgiformat::DXGI_FORMAT_R16_UNORM,
898             dxgiformat::DXGI_FORMAT_D32_FLOAT => dxgiformat::DXGI_FORMAT_R32_FLOAT,
899             format => format,
900         };
901 
902         let desc = Self::build_image_as_shader_resource_desc(&info)?;
903         let handle = self.srv_uav_pool.lock().unwrap().alloc_handle();
904         unsafe {
905             self.raw
906                 .CreateShaderResourceView(info.resource.as_mut_ptr(), &desc, handle);
907         }
908 
909         Ok(handle)
910     }
911 
view_image_as_storage( &self, info: ViewInfo, ) -> Result<d3d12::D3D12_CPU_DESCRIPTOR_HANDLE, image::ViewCreationError>912     fn view_image_as_storage(
913         &self,
914         info: ViewInfo,
915     ) -> Result<d3d12::D3D12_CPU_DESCRIPTOR_HANDLE, image::ViewCreationError> {
916         #![allow(non_snake_case)]
917         assert_eq!(info.range.levels.start + 1, info.range.levels.end);
918 
919         let mut desc = d3d12::D3D12_UNORDERED_ACCESS_VIEW_DESC {
920             Format: info.format,
921             ViewDimension: 0,
922             u: unsafe { mem::zeroed() },
923         };
924 
925         let MipSlice = info.range.levels.start as _;
926         let FirstArraySlice = info.range.layers.start as _;
927         let ArraySize = (info.range.layers.end - info.range.layers.start) as _;
928 
929         if info.range.layers.end > info.kind.num_layers() {
930             return Err(image::ViewCreationError::Layer(
931                 image::LayerError::OutOfBounds(info.range.layers),
932             ));
933         }
934         if info.kind.num_samples() > 1 {
935             error!("MSAA images can't be viewed as UAV");
936             return Err(image::ViewCreationError::Unsupported);
937         }
938 
939         match info.view_kind {
940             image::ViewKind::D1 => {
941                 assert_eq!(info.range.layers, 0 .. 1);
942                 desc.ViewDimension = d3d12::D3D12_UAV_DIMENSION_TEXTURE1D;
943                 *unsafe { desc.u.Texture1D_mut() } = d3d12::D3D12_TEX1D_UAV { MipSlice }
944             }
945             image::ViewKind::D1Array => {
946                 desc.ViewDimension = d3d12::D3D12_UAV_DIMENSION_TEXTURE1DARRAY;
947                 *unsafe { desc.u.Texture1DArray_mut() } = d3d12::D3D12_TEX1D_ARRAY_UAV {
948                     MipSlice,
949                     FirstArraySlice,
950                     ArraySize,
951                 }
952             }
953             image::ViewKind::D2 => {
954                 assert_eq!(info.range.layers, 0 .. 1);
955                 desc.ViewDimension = d3d12::D3D12_UAV_DIMENSION_TEXTURE2D;
956                 *unsafe { desc.u.Texture2D_mut() } = d3d12::D3D12_TEX2D_UAV {
957                     MipSlice,
958                     PlaneSlice: 0, //TODO
959                 }
960             }
961             image::ViewKind::D2Array => {
962                 desc.ViewDimension = d3d12::D3D12_UAV_DIMENSION_TEXTURE2DARRAY;
963                 *unsafe { desc.u.Texture2DArray_mut() } = d3d12::D3D12_TEX2D_ARRAY_UAV {
964                     MipSlice,
965                     FirstArraySlice,
966                     ArraySize,
967                     PlaneSlice: 0, //TODO
968                 }
969             }
970             image::ViewKind::D3 => {
971                 assert_eq!(info.range.layers, 0 .. 1);
972                 desc.ViewDimension = d3d12::D3D12_UAV_DIMENSION_TEXTURE3D;
973                 *unsafe { desc.u.Texture3D_mut() } = d3d12::D3D12_TEX3D_UAV {
974                     MipSlice,
975                     FirstWSlice: 0,
976                     WSize: info.kind.extent().depth as _,
977                 }
978             }
979             image::ViewKind::Cube | image::ViewKind::CubeArray => {
980                 error!("Cubic images can't be viewed as UAV");
981                 return Err(image::ViewCreationError::Unsupported);
982             }
983         }
984 
985         let handle = self.srv_uav_pool.lock().unwrap().alloc_handle();
986         unsafe {
987             self.raw.CreateUnorderedAccessView(
988                 info.resource.as_mut_ptr(),
989                 ptr::null_mut(),
990                 &desc,
991                 handle,
992             );
993         }
994 
995         Ok(handle)
996     }
997 
create_raw_fence(&self, signalled: bool) -> native::Fence998     pub(crate) fn create_raw_fence(&self, signalled: bool) -> native::Fence {
999         let mut handle = native::Fence::null();
1000         assert_eq!(winerror::S_OK, unsafe {
1001             self.raw.CreateFence(
1002                 if signalled { 1 } else { 0 },
1003                 d3d12::D3D12_FENCE_FLAG_NONE,
1004                 &d3d12::ID3D12Fence::uuidof(),
1005                 handle.mut_void(),
1006             )
1007         });
1008         handle
1009     }
1010 
create_swapchain_impl( &self, config: &w::SwapchainConfig, window_handle: windef::HWND, factory: native::WeakPtr<dxgi1_4::IDXGIFactory4>, ) -> Result< ( native::WeakPtr<dxgi1_4::IDXGISwapChain3>, dxgiformat::DXGI_FORMAT, ), w::CreationError, >1011     pub(crate) fn create_swapchain_impl(
1012         &self,
1013         config: &w::SwapchainConfig,
1014         window_handle: windef::HWND,
1015         factory: native::WeakPtr<dxgi1_4::IDXGIFactory4>,
1016     ) -> Result<
1017         (
1018             native::WeakPtr<dxgi1_4::IDXGISwapChain3>,
1019             dxgiformat::DXGI_FORMAT,
1020         ),
1021         w::CreationError,
1022     > {
1023         let mut swap_chain1 = native::WeakPtr::<dxgi1_2::IDXGISwapChain1>::null();
1024 
1025         //TODO: proper error type?
1026         let non_srgb_format = conv::map_format_nosrgb(config.format).unwrap();
1027 
1028         // TODO: double-check values
1029         let desc = dxgi1_2::DXGI_SWAP_CHAIN_DESC1 {
1030             AlphaMode: dxgi1_2::DXGI_ALPHA_MODE_IGNORE,
1031             BufferCount: config.image_count,
1032             Width: config.extent.width,
1033             Height: config.extent.height,
1034             Format: non_srgb_format,
1035             Flags: dxgi::DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT,
1036             BufferUsage: dxgitype::DXGI_USAGE_RENDER_TARGET_OUTPUT,
1037             SampleDesc: dxgitype::DXGI_SAMPLE_DESC {
1038                 Count: 1,
1039                 Quality: 0,
1040             },
1041             Scaling: dxgi1_2::DXGI_SCALING_STRETCH,
1042             Stereo: FALSE,
1043             SwapEffect: dxgi::DXGI_SWAP_EFFECT_FLIP_DISCARD,
1044         };
1045 
1046         unsafe {
1047             let hr = factory.CreateSwapChainForHwnd(
1048                 self.present_queue.as_mut_ptr() as *mut _,
1049                 window_handle,
1050                 &desc,
1051                 ptr::null(),
1052                 ptr::null_mut(),
1053                 swap_chain1.mut_void() as *mut *mut _,
1054             );
1055 
1056             if !winerror::SUCCEEDED(hr) {
1057                 error!("error on swapchain creation 0x{:x}", hr);
1058             }
1059 
1060             let (swap_chain3, hr3) = swap_chain1.cast::<dxgi1_4::IDXGISwapChain3>();
1061             if !winerror::SUCCEEDED(hr3) {
1062                 error!("error on swapchain cast 0x{:x}", hr3);
1063             }
1064 
1065             swap_chain1.destroy();
1066             Ok((swap_chain3, non_srgb_format))
1067         }
1068     }
1069 
wrap_swapchain( &self, inner: native::WeakPtr<dxgi1_4::IDXGISwapChain3>, config: &w::SwapchainConfig, ) -> Swapchain1070     pub(crate) fn wrap_swapchain(
1071         &self,
1072         inner: native::WeakPtr<dxgi1_4::IDXGISwapChain3>,
1073         config: &w::SwapchainConfig,
1074     ) -> Swapchain {
1075         let waitable = unsafe {
1076             inner.SetMaximumFrameLatency(config.image_count);
1077             inner.GetFrameLatencyWaitableObject()
1078         };
1079 
1080         let rtv_desc = d3d12::D3D12_RENDER_TARGET_VIEW_DESC {
1081             Format: conv::map_format(config.format).unwrap(),
1082             ViewDimension: d3d12::D3D12_RTV_DIMENSION_TEXTURE2D,
1083             ..unsafe { mem::zeroed() }
1084         };
1085         let rtv_heap = Device::create_descriptor_heap_impl(
1086             self.raw,
1087             native::DescriptorHeapType::Rtv,
1088             false,
1089             config.image_count as _,
1090         );
1091 
1092         let mut resources = vec![native::Resource::null(); config.image_count as usize];
1093         for (i, res) in resources.iter_mut().enumerate() {
1094             let rtv_handle = rtv_heap.at(i as _, 0).cpu;
1095             unsafe {
1096                 inner.GetBuffer(i as _, &d3d12::ID3D12Resource::uuidof(), res.mut_void());
1097                 self.raw
1098                     .CreateRenderTargetView(res.as_mut_ptr(), &rtv_desc, rtv_handle);
1099             }
1100         }
1101 
1102         Swapchain {
1103             inner,
1104             frame_queue: VecDeque::new(),
1105             rtv_heap,
1106             resources,
1107             waitable,
1108         }
1109     }
1110 }
1111 
1112 impl d::Device<B> for Device {
allocate_memory( &self, mem_type: hal::MemoryTypeId, size: u64, ) -> Result<r::Memory, d::AllocationError>1113     unsafe fn allocate_memory(
1114         &self,
1115         mem_type: hal::MemoryTypeId,
1116         size: u64,
1117     ) -> Result<r::Memory, d::AllocationError> {
1118         let mem_type = mem_type.0;
1119         let mem_base_id = mem_type % NUM_HEAP_PROPERTIES;
1120         let heap_property = &self.heap_properties[mem_base_id];
1121 
1122         let properties = d3d12::D3D12_HEAP_PROPERTIES {
1123             Type: d3d12::D3D12_HEAP_TYPE_CUSTOM,
1124             CPUPageProperty: heap_property.page_property,
1125             MemoryPoolPreference: heap_property.memory_pool,
1126             CreationNodeMask: 0,
1127             VisibleNodeMask: 0,
1128         };
1129 
1130         // Exposed memory types are grouped according to their capabilities.
1131         // See `MemoryGroup` for more details.
1132         let mem_group = mem_type / NUM_HEAP_PROPERTIES;
1133 
1134         let desc = d3d12::D3D12_HEAP_DESC {
1135             SizeInBytes: size,
1136             Properties: properties,
1137             Alignment: d3d12::D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT as _, // TODO: not always..?
1138             Flags: match mem_group {
1139                 0 => d3d12::D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES,
1140                 1 => d3d12::D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS,
1141                 2 => d3d12::D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES,
1142                 3 => d3d12::D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES,
1143                 _ => unreachable!(),
1144             },
1145         };
1146 
1147         let mut heap = native::Heap::null();
1148         let hr = self
1149             .raw
1150             .clone()
1151             .CreateHeap(&desc, &d3d12::ID3D12Heap::uuidof(), heap.mut_void());
1152         if hr == winerror::E_OUTOFMEMORY {
1153             return Err(d::OutOfMemory::Device.into());
1154         }
1155         assert_eq!(winerror::S_OK, hr);
1156 
1157         // The first memory heap of each group corresponds to the default heap, which is can never
1158         // be mapped.
1159         // Devices supporting heap tier 1 can only created buffers on mem group 1 (ALLOW_ONLY_BUFFERS).
1160         // Devices supporting heap tier 2 always expose only mem group 0 and don't have any further restrictions.
1161         let is_mapable = mem_base_id != 0
1162             && (mem_group == MemoryGroup::Universal as _
1163                 || mem_group == MemoryGroup::BufferOnly as _);
1164 
1165         // Create a buffer resource covering the whole memory slice to be able to map the whole memory.
1166         let resource = if is_mapable {
1167             let mut resource = native::Resource::null();
1168             let desc = d3d12::D3D12_RESOURCE_DESC {
1169                 Dimension: d3d12::D3D12_RESOURCE_DIMENSION_BUFFER,
1170                 Alignment: 0,
1171                 Width: size,
1172                 Height: 1,
1173                 DepthOrArraySize: 1,
1174                 MipLevels: 1,
1175                 Format: dxgiformat::DXGI_FORMAT_UNKNOWN,
1176                 SampleDesc: dxgitype::DXGI_SAMPLE_DESC {
1177                     Count: 1,
1178                     Quality: 0,
1179                 },
1180                 Layout: d3d12::D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
1181                 Flags: d3d12::D3D12_RESOURCE_FLAG_NONE,
1182             };
1183 
1184             assert_eq!(
1185                 winerror::S_OK,
1186                 self.raw.clone().CreatePlacedResource(
1187                     heap.as_mut_ptr(),
1188                     0,
1189                     &desc,
1190                     d3d12::D3D12_RESOURCE_STATE_COMMON,
1191                     ptr::null(),
1192                     &d3d12::ID3D12Resource::uuidof(),
1193                     resource.mut_void(),
1194                 )
1195             );
1196 
1197             Some(resource)
1198         } else {
1199             None
1200         };
1201 
1202         Ok(r::Memory {
1203             heap,
1204             type_id: mem_type,
1205             size,
1206             resource,
1207         })
1208     }
1209 
create_command_pool( &self, family: QueueFamilyId, create_flags: CommandPoolCreateFlags, ) -> Result<CommandPool, d::OutOfMemory>1210     unsafe fn create_command_pool(
1211         &self,
1212         family: QueueFamilyId,
1213         create_flags: CommandPoolCreateFlags,
1214     ) -> Result<CommandPool, d::OutOfMemory> {
1215         let list_type = QUEUE_FAMILIES[family.0].native_type();
1216 
1217         let allocator = if create_flags.contains(CommandPoolCreateFlags::RESET_INDIVIDUAL) {
1218             // Allocators are created per individual ID3D12GraphicsCommandList
1219             CommandPoolAllocator::Individual(Vec::new())
1220         } else {
1221             let (command_allocator, hr) = self.raw.create_command_allocator(list_type);
1222 
1223             // TODO: error handling
1224             if !winerror::SUCCEEDED(hr) {
1225                 error!("error on command allocator creation: {:x}", hr);
1226             }
1227 
1228             CommandPoolAllocator::Shared(command_allocator)
1229         };
1230 
1231         Ok(CommandPool {
1232             allocator,
1233             device: self.raw,
1234             list_type,
1235             shared: self.shared.clone(),
1236             create_flags,
1237         })
1238     }
1239 
destroy_command_pool(&self, pool: CommandPool)1240     unsafe fn destroy_command_pool(&self, pool: CommandPool) {
1241         pool.destroy();
1242     }
1243 
create_render_pass<'a, IA, IS, ID>( &self, attachments: IA, subpasses: IS, dependencies: ID, ) -> Result<r::RenderPass, d::OutOfMemory> where IA: IntoIterator, IA::Item: Borrow<pass::Attachment>, IS: IntoIterator, IS::Item: Borrow<pass::SubpassDesc<'a>>, ID: IntoIterator, ID::Item: Borrow<pass::SubpassDependency>,1244     unsafe fn create_render_pass<'a, IA, IS, ID>(
1245         &self,
1246         attachments: IA,
1247         subpasses: IS,
1248         dependencies: ID,
1249     ) -> Result<r::RenderPass, d::OutOfMemory>
1250     where
1251         IA: IntoIterator,
1252         IA::Item: Borrow<pass::Attachment>,
1253         IS: IntoIterator,
1254         IS::Item: Borrow<pass::SubpassDesc<'a>>,
1255         ID: IntoIterator,
1256         ID::Item: Borrow<pass::SubpassDependency>,
1257     {
1258         #[derive(Copy, Clone, Debug, PartialEq)]
1259         enum SubState {
1260             New(d3d12::D3D12_RESOURCE_STATES),
1261             // Color attachment which will be resolved at the end of the subpass
1262             Resolve(d3d12::D3D12_RESOURCE_STATES),
1263             Preserve,
1264             Undefined,
1265         }
1266         /// Temporary information about every sub-pass
1267         struct SubInfo<'a> {
1268             desc: pass::SubpassDesc<'a>,
1269             /// States before the render-pass (in self.start)
1270             /// and after the render-pass (in self.end).
1271             external_dependencies: Range<image::Access>,
1272             /// Counts the number of dependencies that need to be resolved
1273             /// before starting this subpass.
1274             unresolved_dependencies: u16,
1275         }
1276         struct AttachmentInfo {
1277             sub_states: Vec<SubState>,
1278             last_state: d3d12::D3D12_RESOURCE_STATES,
1279             barrier_start_index: usize,
1280         }
1281 
1282         let attachments = attachments
1283             .into_iter()
1284             .map(|attachment| attachment.borrow().clone())
1285             .collect::<SmallVec<[_; 5]>>();
1286         let mut sub_infos = subpasses
1287             .into_iter()
1288             .map(|desc| SubInfo {
1289                 desc: desc.borrow().clone(),
1290                 external_dependencies: image::Access::empty() .. image::Access::empty(),
1291                 unresolved_dependencies: 0,
1292             })
1293             .collect::<SmallVec<[_; 1]>>();
1294         let dependencies = dependencies.into_iter().collect::<SmallVec<[_; 2]>>();
1295 
1296         let mut att_infos = (0 .. attachments.len())
1297             .map(|_| AttachmentInfo {
1298                 sub_states: vec![SubState::Undefined; sub_infos.len()],
1299                 last_state: d3d12::D3D12_RESOURCE_STATE_COMMON, // is to be overwritten
1300                 barrier_start_index: 0,
1301             })
1302             .collect::<SmallVec<[_; 5]>>();
1303 
1304         for dep in &dependencies {
1305             let dep = dep.borrow();
1306             match dep.passes {
1307                 Range {
1308                     start: None,
1309                     end: None,
1310                 } => {
1311                     error!("Unexpected external-external dependency!");
1312                 }
1313                 Range {
1314                     start: None,
1315                     end: Some(sid),
1316                 } => {
1317                     sub_infos[sid as usize].external_dependencies.start |= dep.accesses.start;
1318                 }
1319                 Range {
1320                     start: Some(sid),
1321                     end: None,
1322                 } => {
1323                     sub_infos[sid as usize].external_dependencies.end |= dep.accesses.end;
1324                 }
1325                 Range {
1326                     start: Some(from_sid),
1327                     end: Some(sid),
1328                 } => {
1329                     //Note: self-dependencies are ignored
1330                     if from_sid != sid {
1331                         sub_infos[sid as usize].unresolved_dependencies += 1;
1332                     }
1333                 }
1334             }
1335         }
1336 
1337         // Fill out subpass known layouts
1338         for (sid, sub_info) in sub_infos.iter().enumerate() {
1339             let sub = &sub_info.desc;
1340             for (i, &(id, _layout)) in sub.colors.iter().enumerate() {
1341                 let target_state = d3d12::D3D12_RESOURCE_STATE_RENDER_TARGET;
1342                 let state = match sub.resolves.get(i) {
1343                     Some(_) => SubState::Resolve(target_state),
1344                     None => SubState::New(target_state),
1345                 };
1346                 let old = mem::replace(&mut att_infos[id].sub_states[sid], state);
1347                 debug_assert_eq!(SubState::Undefined, old);
1348             }
1349             for &(id, layout) in sub.depth_stencil {
1350                 let state = SubState::New(match layout {
1351                     image::Layout::DepthStencilAttachmentOptimal => {
1352                         d3d12::D3D12_RESOURCE_STATE_DEPTH_WRITE
1353                     }
1354                     image::Layout::DepthStencilReadOnlyOptimal => {
1355                         d3d12::D3D12_RESOURCE_STATE_DEPTH_READ
1356                     }
1357                     image::Layout::General => d3d12::D3D12_RESOURCE_STATE_DEPTH_WRITE,
1358                     _ => {
1359                         error!("Unexpected depth/stencil layout: {:?}", layout);
1360                         d3d12::D3D12_RESOURCE_STATE_COMMON
1361                     }
1362                 });
1363                 let old = mem::replace(&mut att_infos[id].sub_states[sid], state);
1364                 debug_assert_eq!(SubState::Undefined, old);
1365             }
1366             for &(id, _layout) in sub.inputs {
1367                 let state = SubState::New(d3d12::D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
1368                 let old = mem::replace(&mut att_infos[id].sub_states[sid], state);
1369                 debug_assert_eq!(SubState::Undefined, old);
1370             }
1371             for &(id, _layout) in sub.resolves {
1372                 let state = SubState::New(d3d12::D3D12_RESOURCE_STATE_RESOLVE_DEST);
1373                 let old = mem::replace(&mut att_infos[id].sub_states[sid], state);
1374                 debug_assert_eq!(SubState::Undefined, old);
1375             }
1376             for &id in sub.preserves {
1377                 let old = mem::replace(&mut att_infos[id].sub_states[sid], SubState::Preserve);
1378                 debug_assert_eq!(SubState::Undefined, old);
1379             }
1380         }
1381 
1382         let mut rp = r::RenderPass {
1383             attachments: attachments.iter().cloned().collect(),
1384             subpasses: Vec::new(),
1385             post_barriers: Vec::new(),
1386         };
1387 
1388         while let Some(sid) = sub_infos
1389             .iter()
1390             .position(|si| si.unresolved_dependencies == 0)
1391         {
1392             for dep in &dependencies {
1393                 let dep = dep.borrow();
1394                 if dep.passes.start != dep.passes.end
1395                     && dep.passes.start == Some(sid as pass::SubpassId)
1396                 {
1397                     if let Some(other) = dep.passes.end {
1398                         sub_infos[other as usize].unresolved_dependencies -= 1;
1399                     }
1400                 }
1401             }
1402 
1403             let si = &mut sub_infos[sid];
1404             si.unresolved_dependencies = !0; // mark as done
1405 
1406             // Subpass barriers
1407             let mut pre_barriers = Vec::new();
1408             let mut post_barriers = Vec::new();
1409             for (att_id, (ai, att)) in att_infos.iter_mut().zip(attachments.iter()).enumerate() {
1410                 // Attachment wasn't used before, figure out the initial state
1411                 if ai.barrier_start_index == 0 {
1412                     //Note: the external dependencies are provided for all attachments that are
1413                     // first used in this sub-pass, so they may contain more states than we expect
1414                     // for this particular attachment.
1415                     ai.last_state = conv::map_image_resource_state(
1416                         si.external_dependencies.start,
1417                         att.layouts.start,
1418                     );
1419                 }
1420                 // Barrier from previous subpass to current or following subpasses.
1421                 match ai.sub_states[sid] {
1422                     SubState::Preserve => {
1423                         ai.barrier_start_index = rp.subpasses.len() + 1;
1424                     }
1425                     SubState::New(state) if state != ai.last_state => {
1426                         let barrier = r::BarrierDesc::new(att_id, ai.last_state .. state);
1427                         match rp.subpasses.get_mut(ai.barrier_start_index) {
1428                             Some(past_subpass) => {
1429                                 let split = barrier.split();
1430                                 past_subpass.pre_barriers.push(split.start);
1431                                 pre_barriers.push(split.end);
1432                             }
1433                             None => pre_barriers.push(barrier),
1434                         }
1435                         ai.last_state = state;
1436                         ai.barrier_start_index = rp.subpasses.len() + 1;
1437                     }
1438                     SubState::Resolve(state) => {
1439                         // 1. Standard pre barrier to update state from previous pass into desired substate.
1440                         if state != ai.last_state {
1441                             let barrier = r::BarrierDesc::new(att_id, ai.last_state .. state);
1442                             match rp.subpasses.get_mut(ai.barrier_start_index) {
1443                                 Some(past_subpass) => {
1444                                     let split = barrier.split();
1445                                     past_subpass.pre_barriers.push(split.start);
1446                                     pre_barriers.push(split.end);
1447                                 }
1448                                 None => pre_barriers.push(barrier),
1449                             }
1450                         }
1451 
1452                         // 2. Post Barrier at the end of the subpass into RESOLVE_SOURCE.
1453                         let resolve_state = d3d12::D3D12_RESOURCE_STATE_RESOLVE_SOURCE;
1454                         let barrier = r::BarrierDesc::new(att_id, state .. resolve_state);
1455                         post_barriers.push(barrier);
1456 
1457                         ai.last_state = resolve_state;
1458                         ai.barrier_start_index = rp.subpasses.len() + 1;
1459                     }
1460                     SubState::Undefined | SubState::New(_) => {}
1461                 };
1462             }
1463 
1464             rp.subpasses.push(r::SubpassDesc {
1465                 color_attachments: si.desc.colors.iter().cloned().collect(),
1466                 depth_stencil_attachment: si.desc.depth_stencil.cloned(),
1467                 input_attachments: si.desc.inputs.iter().cloned().collect(),
1468                 resolve_attachments: si.desc.resolves.iter().cloned().collect(),
1469                 pre_barriers,
1470                 post_barriers,
1471             });
1472         }
1473         // if this fails, our graph has cycles
1474         assert_eq!(rp.subpasses.len(), sub_infos.len());
1475         assert!(sub_infos.iter().all(|si| si.unresolved_dependencies == !0));
1476 
1477         // take care of the post-pass transitions at the end of the renderpass.
1478         for (att_id, (ai, att)) in att_infos.iter().zip(attachments.iter()).enumerate() {
1479             let state_dst = if ai.barrier_start_index == 0 {
1480                 // attachment wasn't used in any sub-pass?
1481                 continue;
1482             } else {
1483                 let si = &sub_infos[ai.barrier_start_index - 1];
1484                 conv::map_image_resource_state(si.external_dependencies.end, att.layouts.end)
1485             };
1486             if state_dst == ai.last_state {
1487                 continue;
1488             }
1489             let barrier = r::BarrierDesc::new(att_id, ai.last_state .. state_dst);
1490             match rp.subpasses.get_mut(ai.barrier_start_index) {
1491                 Some(past_subpass) => {
1492                     let split = barrier.split();
1493                     past_subpass.pre_barriers.push(split.start);
1494                     rp.post_barriers.push(split.end);
1495                 }
1496                 None => rp.post_barriers.push(barrier),
1497             }
1498         }
1499 
1500         Ok(rp)
1501     }
1502 
create_pipeline_layout<IS, IR>( &self, sets: IS, push_constant_ranges: IR, ) -> Result<r::PipelineLayout, d::OutOfMemory> where IS: IntoIterator, IS::Item: Borrow<r::DescriptorSetLayout>, IR: IntoIterator, IR::Item: Borrow<(pso::ShaderStageFlags, Range<u32>)>,1503     unsafe fn create_pipeline_layout<IS, IR>(
1504         &self,
1505         sets: IS,
1506         push_constant_ranges: IR,
1507     ) -> Result<r::PipelineLayout, d::OutOfMemory>
1508     where
1509         IS: IntoIterator,
1510         IS::Item: Borrow<r::DescriptorSetLayout>,
1511         IR: IntoIterator,
1512         IR::Item: Borrow<(pso::ShaderStageFlags, Range<u32>)>,
1513     {
1514         // Pipeline layouts are implemented as RootSignature for D3D12.
1515         //
1516         // Push Constants are implemented as root constants.
1517         //
1518         // Each descriptor set layout will be one table entry of the root signature.
1519         // We have the additional restriction that SRV/CBV/UAV and samplers need to be
1520         // separated, so each set layout will actually occupy up to 2 entries!
1521         // SRV/CBV/UAV tables are added to the signature first, then Sampler tables,
1522         // and finally dynamic uniform descriptors.
1523         //
1524         // Dynamic uniform buffers are implemented as root descriptors.
1525         // This allows to handle the dynamic offsets properly, which would not be feasible
1526         // with a combination of root constant and descriptor table.
1527         //
1528         // Root signature layout:
1529         //     Root Constants: Register: Offest/4, Space: 0
1530         //     ...
1531         // DescriptorTable0: Space: 1 (SrvCbvUav)
1532         // DescriptorTable0: Space: 1 (Sampler)
1533         // Root Descriptors 0
1534         // DescriptorTable1: Space: 2 (SrvCbvUav)
1535         // Root Descriptors 1
1536         //     ...
1537 
1538         let sets = sets.into_iter().collect::<Vec<_>>();
1539 
1540         let mut root_offset = 0;
1541         let root_constants = root_constants::split(push_constant_ranges)
1542             .iter()
1543             .map(|constant| {
1544                 assert!(constant.range.start <= constant.range.end);
1545                 root_offset += (constant.range.end - constant.range.start) as usize;
1546 
1547                 RootConstant {
1548                     stages: constant.stages,
1549                     range: constant.range.start .. constant.range.end,
1550                 }
1551             })
1552             .collect::<Vec<_>>();
1553 
1554         info!(
1555             "Creating a pipeline layout with {} sets and {} root constants",
1556             sets.len(),
1557             root_constants.len()
1558         );
1559 
1560         // Number of elements in the root signature.
1561         // Guarantees that no re-allocation is done, and our pointers are valid
1562         let mut parameters = Vec::with_capacity(root_constants.len() + sets.len() * 2);
1563 
1564         // Convert root signature descriptions into root signature parameters.
1565         for root_constant in root_constants.iter() {
1566             debug!(
1567                 "\tRoot constant set={} range {:?}",
1568                 ROOT_CONSTANT_SPACE, root_constant.range
1569             );
1570             parameters.push(native::RootParameter::constants(
1571                 conv::map_shader_visibility(root_constant.stages),
1572                 native::Binding {
1573                     register: root_constant.range.start as _,
1574                     space: ROOT_CONSTANT_SPACE,
1575                 },
1576                 (root_constant.range.end - root_constant.range.start) as _,
1577             ));
1578         }
1579 
1580         // Offest of `spaceN` for descriptor tables. Root constants will be in
1581         // `space0`.
1582         // This has to match `patch_spirv_resources` logic.
1583         let root_space_offset = if !root_constants.is_empty() { 1 } else { 0 };
1584 
1585         // Collect the whole number of bindings we will create upfront.
1586         // It allows us to preallocate enough storage to avoid reallocation,
1587         // which could cause invalid pointers.
1588         let total = sets
1589             .iter()
1590             .map(|desc_set| {
1591                 let mut sum = 0;
1592                 for binding in desc_set.borrow().bindings.iter() {
1593                     let content = r::DescriptorContent::from(binding.ty);
1594                     if !content.is_dynamic() {
1595                         sum += content.bits().count_ones() as usize;
1596                     }
1597                 }
1598                 sum
1599             })
1600             .sum();
1601         let mut ranges = Vec::with_capacity(total);
1602 
1603         let elements = sets
1604             .iter()
1605             .enumerate()
1606             .map(|(i, set)| {
1607                 let set = set.borrow();
1608                 let space = (root_space_offset + i) as u32;
1609                 let mut table_type = r::SetTableTypes::empty();
1610                 let root_table_offset = root_offset;
1611 
1612                 //TODO: split between sampler and non-sampler tables
1613                 let visibility = conv::map_shader_visibility(
1614                     set.bindings
1615                         .iter()
1616                         .fold(pso::ShaderStageFlags::empty(), |u, bind| {
1617                             u | bind.stage_flags
1618                         }),
1619                 );
1620 
1621                 for bind in set.bindings.iter() {
1622                     debug!("\tRange {:?} at space={}", bind, space);
1623                 }
1624 
1625                 let describe = |bind: &pso::DescriptorSetLayoutBinding, ty| {
1626                     native::DescriptorRange::new(
1627                         ty,
1628                         bind.count as _,
1629                         native::Binding {
1630                             register: bind.binding as _,
1631                             space,
1632                         },
1633                         d3d12::D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND,
1634                     )
1635                 };
1636 
1637                 let mut descriptors = Vec::new();
1638                 let mut mutable_bindings = auxil::FastHashSet::default();
1639 
1640                 // SRV/CBV/UAV descriptor tables
1641                 let mut range_base = ranges.len();
1642                 for bind in set.bindings.iter() {
1643                     let content = r::DescriptorContent::from(bind.ty);
1644                     if !content.is_dynamic() {
1645                         // Descriptor table ranges
1646                         if content.contains(r::DescriptorContent::CBV) {
1647                             ranges.push(describe(bind, native::DescriptorRangeType::CBV));
1648                         }
1649                         if content.contains(r::DescriptorContent::SRV) {
1650                             ranges.push(describe(bind, native::DescriptorRangeType::SRV));
1651                         }
1652                         if content.contains(r::DescriptorContent::UAV) {
1653                             ranges.push(describe(bind, native::DescriptorRangeType::UAV));
1654                             mutable_bindings.insert(bind.binding);
1655                         }
1656                     }
1657                 }
1658                 if ranges.len() > range_base {
1659                     parameters.push(native::RootParameter::descriptor_table(
1660                         visibility,
1661                         &ranges[range_base ..],
1662                     ));
1663                     table_type |= r::SRV_CBV_UAV;
1664                     root_offset += 1;
1665                 }
1666 
1667                 // Sampler descriptor tables
1668                 range_base = ranges.len();
1669                 for bind in set.bindings.iter() {
1670                     let content = r::DescriptorContent::from(bind.ty);
1671                     if content.contains(r::DescriptorContent::SAMPLER) {
1672                         ranges.push(describe(bind, native::DescriptorRangeType::Sampler));
1673                     }
1674                 }
1675                 if ranges.len() > range_base {
1676                     parameters.push(native::RootParameter::descriptor_table(
1677                         visibility,
1678                         &ranges[range_base ..],
1679                     ));
1680                     table_type |= r::SAMPLERS;
1681                     root_offset += 1;
1682                 }
1683 
1684                 // Root (dynamic) descriptor tables
1685                 for bind in set.bindings.iter() {
1686                     let content = r::DescriptorContent::from(bind.ty);
1687                     if content.is_dynamic() {
1688                         let binding = native::Binding {
1689                             register: bind.binding as _,
1690                             space,
1691                         };
1692 
1693                         if content.contains(r::DescriptorContent::CBV) {
1694                             descriptors.push(r::RootDescriptor {
1695                                 offset: root_offset,
1696                             });
1697                             parameters
1698                                 .push(native::RootParameter::cbv_descriptor(visibility, binding));
1699                             root_offset += 2;
1700                         } else {
1701                             // SRV and UAV not implemented so far
1702                             unimplemented!()
1703                         }
1704                     }
1705                 }
1706 
1707                 r::RootElement {
1708                     table: r::RootTable {
1709                         ty: table_type,
1710                         offset: root_table_offset as _,
1711                     },
1712                     descriptors,
1713                     mutable_bindings,
1714                 }
1715             })
1716             .collect();
1717 
1718         // Ensure that we didn't reallocate!
1719         debug_assert_eq!(ranges.len(), total);
1720 
1721         // TODO: error handling
1722         let (signature_raw, error) = match self.library.serialize_root_signature(
1723             native::RootSignatureVersion::V1_0,
1724             &parameters,
1725             &[],
1726             native::RootSignatureFlags::ALLOW_IA_INPUT_LAYOUT,
1727         ) {
1728             Ok((pair, hr)) if winerror::SUCCEEDED(hr) => pair,
1729             Ok((_, hr)) => panic!("Can't serialize root signature: {:?}", hr),
1730             Err(e) => panic!("Can't find serialization function: {:?}", e),
1731         };
1732 
1733         if !error.is_null() {
1734             error!(
1735                 "Root signature serialization error: {:?}",
1736                 error.as_c_str().to_str().unwrap()
1737             );
1738             error.destroy();
1739         }
1740 
1741         // TODO: error handling
1742         let (signature, _hr) = self.raw.create_root_signature(signature_raw, 0);
1743         signature_raw.destroy();
1744 
1745         Ok(r::PipelineLayout {
1746             raw: signature,
1747             constants: root_constants,
1748             elements,
1749             num_parameter_slots: parameters.len(),
1750         })
1751     }
1752 
create_pipeline_cache(&self, _data: Option<&[u8]>) -> Result<(), d::OutOfMemory>1753     unsafe fn create_pipeline_cache(&self, _data: Option<&[u8]>) -> Result<(), d::OutOfMemory> {
1754         Ok(())
1755     }
1756 
get_pipeline_cache_data(&self, _cache: &()) -> Result<Vec<u8>, d::OutOfMemory>1757     unsafe fn get_pipeline_cache_data(&self, _cache: &()) -> Result<Vec<u8>, d::OutOfMemory> {
1758         //empty
1759         Ok(Vec::new())
1760     }
1761 
destroy_pipeline_cache(&self, _: ())1762     unsafe fn destroy_pipeline_cache(&self, _: ()) {
1763         //empty
1764     }
1765 
merge_pipeline_caches<I>(&self, _: &(), _: I) -> Result<(), d::OutOfMemory> where I: IntoIterator, I::Item: Borrow<()>,1766     unsafe fn merge_pipeline_caches<I>(&self, _: &(), _: I) -> Result<(), d::OutOfMemory>
1767     where
1768         I: IntoIterator,
1769         I::Item: Borrow<()>,
1770     {
1771         //empty
1772         Ok(())
1773     }
1774 
create_graphics_pipeline<'a>( &self, desc: &pso::GraphicsPipelineDesc<'a, B>, _cache: Option<&()>, ) -> Result<r::GraphicsPipeline, pso::CreationError>1775     unsafe fn create_graphics_pipeline<'a>(
1776         &self,
1777         desc: &pso::GraphicsPipelineDesc<'a, B>,
1778         _cache: Option<&()>,
1779     ) -> Result<r::GraphicsPipeline, pso::CreationError> {
1780         enum ShaderBc {
1781             Owned(native::Blob),
1782             Borrowed(native::Blob),
1783             None,
1784         }
1785         let features = &self.features;
1786         impl ShaderBc {
1787             pub fn shader(&self) -> native::Shader {
1788                 match *self {
1789                     ShaderBc::Owned(ref bc) | ShaderBc::Borrowed(ref bc) => {
1790                         native::Shader::from_blob(*bc)
1791                     }
1792                     ShaderBc::None => native::Shader::null(),
1793                 }
1794             }
1795         }
1796 
1797         let build_shader = |stage: pso::Stage, source: Option<&pso::EntryPoint<'a, B>>| {
1798             let source = match source {
1799                 Some(src) => src,
1800                 None => return Ok(ShaderBc::None),
1801             };
1802 
1803             match Self::extract_entry_point(stage, source, desc.layout, features) {
1804                 Ok((shader, true)) => Ok(ShaderBc::Owned(shader)),
1805                 Ok((shader, false)) => Ok(ShaderBc::Borrowed(shader)),
1806                 Err(err) => Err(pso::CreationError::Shader(err)),
1807             }
1808         };
1809 
1810         let vs = build_shader(pso::Stage::Vertex, Some(&desc.shaders.vertex))?;
1811         let ps = build_shader(pso::Stage::Fragment, desc.shaders.fragment.as_ref())?;
1812         let gs = build_shader(pso::Stage::Geometry, desc.shaders.geometry.as_ref())?;
1813         let ds = build_shader(pso::Stage::Domain, desc.shaders.domain.as_ref())?;
1814         let hs = build_shader(pso::Stage::Hull, desc.shaders.hull.as_ref())?;
1815 
1816         // Rebind vertex buffers, see native.rs for more details.
1817         let mut vertex_bindings = [None; MAX_VERTEX_BUFFERS];
1818         let mut vertex_strides = [0; MAX_VERTEX_BUFFERS];
1819 
1820         for buffer in &desc.vertex_buffers {
1821             vertex_strides[buffer.binding as usize] = buffer.stride;
1822         }
1823         // Fill in identity mapping where we don't need to adjust anything.
1824         for attrib in &desc.attributes {
1825             let binding = attrib.binding as usize;
1826             let stride = vertex_strides[attrib.binding as usize];
1827             if attrib.element.offset < stride {
1828                 vertex_bindings[binding] = Some(r::VertexBinding {
1829                     stride: vertex_strides[attrib.binding as usize],
1830                     offset: 0,
1831                     mapped_binding: binding,
1832                 });
1833             }
1834         }
1835 
1836         // Define input element descriptions
1837         let input_element_descs = desc
1838             .attributes
1839             .iter()
1840             .filter_map(|attrib| {
1841                 let buffer_desc = match desc
1842                     .vertex_buffers
1843                     .iter()
1844                     .find(|buffer_desc| buffer_desc.binding == attrib.binding)
1845                 {
1846                     Some(buffer_desc) => buffer_desc,
1847                     None => {
1848                         error!(
1849                             "Couldn't find associated vertex buffer description {:?}",
1850                             attrib.binding
1851                         );
1852                         return Some(Err(pso::CreationError::Other));
1853                     }
1854                 };
1855 
1856                 let (slot_class, step_rate) = match buffer_desc.rate {
1857                     VertexInputRate::Vertex => {
1858                         (d3d12::D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0)
1859                     }
1860                     VertexInputRate::Instance(divisor) => {
1861                         (d3d12::D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA, divisor)
1862                     }
1863                 };
1864                 let format = attrib.element.format;
1865 
1866                 // Check if we need to add a new remapping in-case the offset is
1867                 // higher than the vertex stride.
1868                 // In this case we rebase the attribute to zero offset.
1869                 let binding = attrib.binding as usize;
1870                 let stride = vertex_strides[binding];
1871                 let offset = attrib.element.offset;
1872                 let (input_slot, offset) = if stride <= offset {
1873                     // Number of input attributes may not exceed bindings, see limits.
1874                     // We will always find at least one free binding.
1875                     let mapping = vertex_bindings.iter().position(Option::is_none).unwrap();
1876                     vertex_bindings[mapping] = Some(r::VertexBinding {
1877                         stride: vertex_strides[binding],
1878                         offset: offset,
1879                         mapped_binding: binding,
1880                     });
1881 
1882                     (mapping, 0)
1883                 } else {
1884                     (binding, offset)
1885                 };
1886 
1887                 Some(Ok(d3d12::D3D12_INPUT_ELEMENT_DESC {
1888                     SemanticName: "TEXCOORD\0".as_ptr() as *const _, // Semantic name used by SPIRV-Cross
1889                     SemanticIndex: attrib.location,
1890                     Format: match conv::map_format(format) {
1891                         Some(fm) => fm,
1892                         None => {
1893                             error!("Unable to find DXGI format for {:?}", format);
1894                             return Some(Err(pso::CreationError::Other));
1895                         }
1896                     },
1897                     InputSlot: input_slot as _,
1898                     AlignedByteOffset: offset,
1899                     InputSlotClass: slot_class,
1900                     InstanceDataStepRate: step_rate as _,
1901                 }))
1902             })
1903             .collect::<Result<Vec<_>, _>>()?;
1904 
1905         // TODO: check maximum number of rtvs
1906         // Get associated subpass information
1907         let pass = {
1908             let subpass = &desc.subpass;
1909             match subpass.main_pass.subpasses.get(subpass.index as usize) {
1910                 Some(subpass) => subpass,
1911                 None => return Err(pso::CreationError::InvalidSubpass(subpass.index)),
1912             }
1913         };
1914 
1915         // Get color attachment formats from subpass
1916         let (rtvs, num_rtvs) = {
1917             let mut rtvs = [dxgiformat::DXGI_FORMAT_UNKNOWN; 8];
1918             let mut num_rtvs = 0;
1919             for (rtv, target) in rtvs.iter_mut().zip(pass.color_attachments.iter()) {
1920                 let format = desc.subpass.main_pass.attachments[target.0].format;
1921                 *rtv = format
1922                     .and_then(conv::map_format)
1923                     .unwrap_or(dxgiformat::DXGI_FORMAT_UNKNOWN);
1924                 num_rtvs += 1;
1925             }
1926             (rtvs, num_rtvs)
1927         };
1928 
1929         let sample_desc = dxgitype::DXGI_SAMPLE_DESC {
1930             Count: match desc.multisampling {
1931                 Some(ref ms) => ms.rasterization_samples as _,
1932                 None => 1,
1933             },
1934             Quality: 0,
1935         };
1936 
1937         // Setup pipeline description
1938         let pso_desc = d3d12::D3D12_GRAPHICS_PIPELINE_STATE_DESC {
1939             pRootSignature: desc.layout.raw.as_mut_ptr(),
1940             VS: *vs.shader(),
1941             PS: *ps.shader(),
1942             GS: *gs.shader(),
1943             DS: *ds.shader(),
1944             HS: *hs.shader(),
1945             StreamOutput: d3d12::D3D12_STREAM_OUTPUT_DESC {
1946                 pSODeclaration: ptr::null(),
1947                 NumEntries: 0,
1948                 pBufferStrides: ptr::null(),
1949                 NumStrides: 0,
1950                 RasterizedStream: 0,
1951             },
1952             BlendState: d3d12::D3D12_BLEND_DESC {
1953                 AlphaToCoverageEnable: desc.multisampling.as_ref().map_or(FALSE, |ms| {
1954                     if ms.alpha_coverage {
1955                         TRUE
1956                     } else {
1957                         FALSE
1958                     }
1959                 }),
1960                 IndependentBlendEnable: TRUE,
1961                 RenderTarget: conv::map_render_targets(&desc.blender.targets),
1962             },
1963             SampleMask: UINT::max_value(),
1964             RasterizerState: conv::map_rasterizer(&desc.rasterizer),
1965             DepthStencilState: conv::map_depth_stencil(&desc.depth_stencil),
1966             InputLayout: d3d12::D3D12_INPUT_LAYOUT_DESC {
1967                 pInputElementDescs: if input_element_descs.is_empty() {
1968                     ptr::null()
1969                 } else {
1970                     input_element_descs.as_ptr()
1971                 },
1972                 NumElements: input_element_descs.len() as u32,
1973             },
1974             IBStripCutValue: d3d12::D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED, // TODO
1975             PrimitiveTopologyType: conv::map_topology_type(desc.input_assembler.primitive),
1976             NumRenderTargets: num_rtvs,
1977             RTVFormats: rtvs,
1978             DSVFormat: pass
1979                 .depth_stencil_attachment
1980                 .and_then(|att_ref| {
1981                     desc.subpass.main_pass.attachments[att_ref.0]
1982                         .format
1983                         .and_then(|f| conv::map_format_dsv(f.base_format().0))
1984                 })
1985                 .unwrap_or(dxgiformat::DXGI_FORMAT_UNKNOWN),
1986             SampleDesc: sample_desc,
1987             NodeMask: 0,
1988             CachedPSO: d3d12::D3D12_CACHED_PIPELINE_STATE {
1989                 pCachedBlob: ptr::null(),
1990                 CachedBlobSizeInBytes: 0,
1991             },
1992             Flags: d3d12::D3D12_PIPELINE_STATE_FLAG_NONE,
1993         };
1994 
1995         let topology = conv::map_topology(&desc.input_assembler);
1996 
1997         // Create PSO
1998         let mut pipeline = native::PipelineState::null();
1999         let hr = if desc.depth_stencil.depth_bounds {
2000             // The DepthBoundsTestEnable option isn't available in the original D3D12_GRAPHICS_PIPELINE_STATE_DESC struct.
2001             // Instead, we must use the newer subobject stream method.
2002             let (device2, hr) = self.raw.cast::<d3d12::ID3D12Device2>();
2003             if winerror::SUCCEEDED(hr) {
2004                 let mut pss_stream = GraphicsPipelineStateSubobjectStream::new(&pso_desc, true);
2005                 let pss_desc = d3d12::D3D12_PIPELINE_STATE_STREAM_DESC {
2006                     SizeInBytes: mem::size_of_val(&pss_stream),
2007                     pPipelineStateSubobjectStream: &mut pss_stream as *mut _ as _,
2008                 };
2009                 device2.CreatePipelineState(
2010                     &pss_desc,
2011                     &d3d12::ID3D12PipelineState::uuidof(),
2012                     pipeline.mut_void(),
2013                 )
2014             } else {
2015                 hr
2016             }
2017         } else {
2018             self.raw.clone().CreateGraphicsPipelineState(
2019                 &pso_desc,
2020                 &d3d12::ID3D12PipelineState::uuidof(),
2021                 pipeline.mut_void(),
2022             )
2023         };
2024 
2025         let destroy_shader = |shader: ShaderBc| {
2026             if let ShaderBc::Owned(bc) = shader {
2027                 bc.destroy();
2028             }
2029         };
2030 
2031         destroy_shader(vs);
2032         destroy_shader(ps);
2033         destroy_shader(gs);
2034         destroy_shader(hs);
2035         destroy_shader(ds);
2036 
2037         if winerror::SUCCEEDED(hr) {
2038             let mut baked_states = desc.baked_states.clone();
2039             if !desc.depth_stencil.depth_bounds {
2040                 baked_states.depth_bounds = None;
2041             }
2042 
2043             Ok(r::GraphicsPipeline {
2044                 raw: pipeline,
2045                 signature: desc.layout.raw,
2046                 num_parameter_slots: desc.layout.num_parameter_slots,
2047                 topology,
2048                 constants: desc.layout.constants.clone(),
2049                 vertex_bindings,
2050                 baked_states,
2051             })
2052         } else {
2053             Err(pso::CreationError::Other)
2054         }
2055     }
2056 
create_compute_pipeline<'a>( &self, desc: &pso::ComputePipelineDesc<'a, B>, _cache: Option<&()>, ) -> Result<r::ComputePipeline, pso::CreationError>2057     unsafe fn create_compute_pipeline<'a>(
2058         &self,
2059         desc: &pso::ComputePipelineDesc<'a, B>,
2060         _cache: Option<&()>,
2061     ) -> Result<r::ComputePipeline, pso::CreationError> {
2062         let (cs, cs_destroy) = Self::extract_entry_point(
2063             pso::Stage::Compute,
2064             &desc.shader,
2065             desc.layout,
2066             &self.features,
2067         )
2068         .map_err(|err| pso::CreationError::Shader(err))?;
2069 
2070         let (pipeline, hr) = self.raw.create_compute_pipeline_state(
2071             desc.layout.raw,
2072             native::Shader::from_blob(cs),
2073             0,
2074             native::CachedPSO::null(),
2075             native::PipelineStateFlags::empty(),
2076         );
2077 
2078         if cs_destroy {
2079             cs.destroy();
2080         }
2081 
2082         if winerror::SUCCEEDED(hr) {
2083             Ok(r::ComputePipeline {
2084                 raw: pipeline,
2085                 signature: desc.layout.raw,
2086                 num_parameter_slots: desc.layout.num_parameter_slots,
2087                 constants: desc.layout.constants.clone(),
2088             })
2089         } else {
2090             Err(pso::CreationError::Other)
2091         }
2092     }
2093 
create_framebuffer<I>( &self, _renderpass: &r::RenderPass, attachments: I, extent: image::Extent, ) -> Result<r::Framebuffer, d::OutOfMemory> where I: IntoIterator, I::Item: Borrow<r::ImageView>,2094     unsafe fn create_framebuffer<I>(
2095         &self,
2096         _renderpass: &r::RenderPass,
2097         attachments: I,
2098         extent: image::Extent,
2099     ) -> Result<r::Framebuffer, d::OutOfMemory>
2100     where
2101         I: IntoIterator,
2102         I::Item: Borrow<r::ImageView>,
2103     {
2104         Ok(r::Framebuffer {
2105             attachments: attachments.into_iter().map(|att| *att.borrow()).collect(),
2106             layers: extent.depth as _,
2107         })
2108     }
2109 
create_shader_module( &self, raw_data: &[u32], ) -> Result<r::ShaderModule, d::ShaderError>2110     unsafe fn create_shader_module(
2111         &self,
2112         raw_data: &[u32],
2113     ) -> Result<r::ShaderModule, d::ShaderError> {
2114         Ok(r::ShaderModule::Spirv(raw_data.into()))
2115     }
2116 
create_buffer( &self, mut size: u64, usage: buffer::Usage, ) -> Result<r::Buffer, buffer::CreationError>2117     unsafe fn create_buffer(
2118         &self,
2119         mut size: u64,
2120         usage: buffer::Usage,
2121     ) -> Result<r::Buffer, buffer::CreationError> {
2122         if usage.contains(buffer::Usage::UNIFORM) {
2123             // Constant buffer view sizes need to be aligned.
2124             // Coupled with the offset alignment we can enforce an aligned CBV size
2125             // on descriptor updates.
2126             size = (size + 255) & !255;
2127         }
2128         if usage.contains(buffer::Usage::TRANSFER_DST) {
2129             // minimum of 1 word for the clear UAV
2130             size = size.max(4);
2131         }
2132 
2133         let type_mask_shift = if self.private_caps.heterogeneous_resource_heaps {
2134             MEM_TYPE_UNIVERSAL_SHIFT
2135         } else {
2136             MEM_TYPE_BUFFER_SHIFT
2137         };
2138 
2139         let requirements = memory::Requirements {
2140             size,
2141             alignment: d3d12::D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT as u64,
2142             type_mask: MEM_TYPE_MASK << type_mask_shift,
2143         };
2144 
2145         Ok(r::Buffer::Unbound(r::BufferUnbound {
2146             requirements,
2147             usage,
2148         }))
2149     }
2150 
get_buffer_requirements(&self, buffer: &r::Buffer) -> Requirements2151     unsafe fn get_buffer_requirements(&self, buffer: &r::Buffer) -> Requirements {
2152         match buffer {
2153             r::Buffer::Unbound(b) => b.requirements,
2154             r::Buffer::Bound(b) => b.requirements,
2155         }
2156     }
2157 
bind_buffer_memory( &self, memory: &r::Memory, offset: u64, buffer: &mut r::Buffer, ) -> Result<(), d::BindError>2158     unsafe fn bind_buffer_memory(
2159         &self,
2160         memory: &r::Memory,
2161         offset: u64,
2162         buffer: &mut r::Buffer,
2163     ) -> Result<(), d::BindError> {
2164         let buffer_unbound = *buffer.expect_unbound();
2165         if buffer_unbound.requirements.type_mask & (1 << memory.type_id) == 0 {
2166             error!(
2167                 "Bind memory failure: supported mask 0x{:x}, given id {}",
2168                 buffer_unbound.requirements.type_mask, memory.type_id
2169             );
2170             return Err(d::BindError::WrongMemory);
2171         }
2172         if offset + buffer_unbound.requirements.size > memory.size {
2173             return Err(d::BindError::OutOfBounds);
2174         }
2175 
2176         let mut resource = native::Resource::null();
2177         let desc = d3d12::D3D12_RESOURCE_DESC {
2178             Dimension: d3d12::D3D12_RESOURCE_DIMENSION_BUFFER,
2179             Alignment: 0,
2180             Width: buffer_unbound.requirements.size,
2181             Height: 1,
2182             DepthOrArraySize: 1,
2183             MipLevels: 1,
2184             Format: dxgiformat::DXGI_FORMAT_UNKNOWN,
2185             SampleDesc: dxgitype::DXGI_SAMPLE_DESC {
2186                 Count: 1,
2187                 Quality: 0,
2188             },
2189             Layout: d3d12::D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
2190             Flags: conv::map_buffer_flags(buffer_unbound.usage),
2191         };
2192 
2193         assert_eq!(
2194             winerror::S_OK,
2195             self.raw.clone().CreatePlacedResource(
2196                 memory.heap.as_mut_ptr(),
2197                 offset,
2198                 &desc,
2199                 d3d12::D3D12_RESOURCE_STATE_COMMON,
2200                 ptr::null(),
2201                 &d3d12::ID3D12Resource::uuidof(),
2202                 resource.mut_void(),
2203             )
2204         );
2205 
2206         let clear_uav = if buffer_unbound.usage.contains(buffer::Usage::TRANSFER_DST) {
2207             let handle = self.srv_uav_pool.lock().unwrap().alloc_handle();
2208             let mut view_desc = d3d12::D3D12_UNORDERED_ACCESS_VIEW_DESC {
2209                 Format: dxgiformat::DXGI_FORMAT_R32_TYPELESS,
2210                 ViewDimension: d3d12::D3D12_UAV_DIMENSION_BUFFER,
2211                 u: mem::zeroed(),
2212             };
2213 
2214             *view_desc.u.Buffer_mut() = d3d12::D3D12_BUFFER_UAV {
2215                 FirstElement: 0,
2216                 NumElements: (buffer_unbound.requirements.size / 4) as _,
2217                 StructureByteStride: 0,
2218                 CounterOffsetInBytes: 0,
2219                 Flags: d3d12::D3D12_BUFFER_UAV_FLAG_RAW,
2220             };
2221 
2222             self.raw.CreateUnorderedAccessView(
2223                 resource.as_mut_ptr(),
2224                 ptr::null_mut(),
2225                 &view_desc,
2226                 handle,
2227             );
2228             Some(handle)
2229         } else {
2230             None
2231         };
2232 
2233         *buffer = r::Buffer::Bound(r::BufferBound {
2234             resource,
2235             requirements: buffer_unbound.requirements,
2236             clear_uav,
2237         });
2238 
2239         Ok(())
2240     }
2241 
create_buffer_view( &self, buffer: &r::Buffer, format: Option<format::Format>, sub: buffer::SubRange, ) -> Result<r::BufferView, buffer::ViewCreationError>2242     unsafe fn create_buffer_view(
2243         &self,
2244         buffer: &r::Buffer,
2245         format: Option<format::Format>,
2246         sub: buffer::SubRange,
2247     ) -> Result<r::BufferView, buffer::ViewCreationError> {
2248         let buffer = buffer.expect_bound();
2249         let buffer_features = {
2250             let idx = format.map(|fmt| fmt as usize).unwrap_or(0);
2251             self.format_properties.get(idx).properties.buffer_features
2252         };
2253         let (format, format_desc) = match format.and_then(conv::map_format) {
2254             Some(fmt) => (fmt, format.unwrap().surface_desc()),
2255             None => return Err(buffer::ViewCreationError::UnsupportedFormat(format)),
2256         };
2257 
2258         let start = sub.offset;
2259         let size = sub.size.unwrap_or(buffer.requirements.size - start);
2260 
2261         let bytes_per_texel = (format_desc.bits / 8) as u64;
2262         // Check if it adheres to the texel buffer offset limit
2263         assert_eq!(start % bytes_per_texel, 0);
2264         let first_element = start / bytes_per_texel;
2265         let num_elements = size / bytes_per_texel; // rounds down to next smaller size
2266 
2267         let handle_srv = if buffer_features.contains(format::BufferFeature::UNIFORM_TEXEL) {
2268             let mut desc = d3d12::D3D12_SHADER_RESOURCE_VIEW_DESC {
2269                 Format: format,
2270                 ViewDimension: d3d12::D3D12_SRV_DIMENSION_BUFFER,
2271                 Shader4ComponentMapping: IDENTITY_MAPPING,
2272                 u: mem::zeroed(),
2273             };
2274 
2275             *desc.u.Buffer_mut() = d3d12::D3D12_BUFFER_SRV {
2276                 FirstElement: first_element,
2277                 NumElements: num_elements as _,
2278                 StructureByteStride: bytes_per_texel as _,
2279                 Flags: d3d12::D3D12_BUFFER_SRV_FLAG_NONE,
2280             };
2281 
2282             let handle = self.srv_uav_pool.lock().unwrap().alloc_handle();
2283             self.raw
2284                 .clone()
2285                 .CreateShaderResourceView(buffer.resource.as_mut_ptr(), &desc, handle);
2286             handle
2287         } else {
2288             d3d12::D3D12_CPU_DESCRIPTOR_HANDLE { ptr: 0 }
2289         };
2290 
2291         let handle_uav = if buffer_features.intersects(
2292             format::BufferFeature::STORAGE_TEXEL | format::BufferFeature::STORAGE_TEXEL_ATOMIC,
2293         ) {
2294             let mut desc = d3d12::D3D12_UNORDERED_ACCESS_VIEW_DESC {
2295                 Format: format,
2296                 ViewDimension: d3d12::D3D12_UAV_DIMENSION_BUFFER,
2297                 u: mem::zeroed(),
2298             };
2299 
2300             *desc.u.Buffer_mut() = d3d12::D3D12_BUFFER_UAV {
2301                 FirstElement: first_element,
2302                 NumElements: num_elements as _,
2303                 StructureByteStride: bytes_per_texel as _,
2304                 Flags: d3d12::D3D12_BUFFER_UAV_FLAG_NONE,
2305                 CounterOffsetInBytes: 0,
2306             };
2307 
2308             let handle = self.srv_uav_pool.lock().unwrap().alloc_handle();
2309             self.raw.clone().CreateUnorderedAccessView(
2310                 buffer.resource.as_mut_ptr(),
2311                 ptr::null_mut(),
2312                 &desc,
2313                 handle,
2314             );
2315             handle
2316         } else {
2317             d3d12::D3D12_CPU_DESCRIPTOR_HANDLE { ptr: 0 }
2318         };
2319 
2320         return Ok(r::BufferView {
2321             handle_srv,
2322             handle_uav,
2323         });
2324     }
2325 
create_image( &self, kind: image::Kind, mip_levels: image::Level, format: format::Format, tiling: image::Tiling, usage: image::Usage, view_caps: image::ViewCapabilities, ) -> Result<r::Image, image::CreationError>2326     unsafe fn create_image(
2327         &self,
2328         kind: image::Kind,
2329         mip_levels: image::Level,
2330         format: format::Format,
2331         tiling: image::Tiling,
2332         usage: image::Usage,
2333         view_caps: image::ViewCapabilities,
2334     ) -> Result<r::Image, image::CreationError> {
2335         assert!(mip_levels <= kind.num_levels());
2336 
2337         let base_format = format.base_format();
2338         let format_desc = base_format.0.desc();
2339         let bytes_per_block = (format_desc.bits / 8) as _;
2340         let block_dim = format_desc.dim;
2341         let extent = kind.extent();
2342 
2343         let format_info = self.format_properties.get(format as usize);
2344         let (layout, features) = match tiling {
2345             image::Tiling::Optimal => (
2346                 d3d12::D3D12_TEXTURE_LAYOUT_UNKNOWN,
2347                 format_info.properties.optimal_tiling,
2348             ),
2349             image::Tiling::Linear => (
2350                 d3d12::D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
2351                 format_info.properties.linear_tiling,
2352             ),
2353         };
2354         if format_info.sample_count_mask & kind.num_samples() == 0 {
2355             return Err(image::CreationError::Samples(kind.num_samples()));
2356         }
2357 
2358         let desc = d3d12::D3D12_RESOURCE_DESC {
2359             Dimension: match kind {
2360                 image::Kind::D1(..) => d3d12::D3D12_RESOURCE_DIMENSION_TEXTURE1D,
2361                 image::Kind::D2(..) => d3d12::D3D12_RESOURCE_DIMENSION_TEXTURE2D,
2362                 image::Kind::D3(..) => d3d12::D3D12_RESOURCE_DIMENSION_TEXTURE3D,
2363             },
2364             Alignment: 0,
2365             Width: extent.width as _,
2366             Height: extent.height as _,
2367             DepthOrArraySize: if extent.depth > 1 {
2368                 extent.depth as _
2369             } else {
2370                 kind.num_layers() as _
2371             },
2372             MipLevels: mip_levels as _,
2373             Format: match conv::map_surface_type(base_format.0) {
2374                 Some(format) => format,
2375                 None => return Err(image::CreationError::Format(format)),
2376             },
2377             SampleDesc: dxgitype::DXGI_SAMPLE_DESC {
2378                 Count: kind.num_samples() as _,
2379                 Quality: 0,
2380             },
2381             Layout: layout,
2382             Flags: conv::map_image_flags(usage, features),
2383         };
2384 
2385         let alloc_info = self.raw.clone().GetResourceAllocationInfo(0, 1, &desc);
2386 
2387         // Image usages which require RT/DS heap due to internal implementation.
2388         let target_usage = image::Usage::COLOR_ATTACHMENT
2389             | image::Usage::DEPTH_STENCIL_ATTACHMENT
2390             | image::Usage::TRANSFER_DST;
2391 
2392         let type_mask_shift = if self.private_caps.heterogeneous_resource_heaps {
2393             MEM_TYPE_UNIVERSAL_SHIFT
2394         } else if usage.intersects(target_usage) {
2395             MEM_TYPE_TARGET_SHIFT
2396         } else {
2397             MEM_TYPE_IMAGE_SHIFT
2398         };
2399 
2400         Ok(r::Image::Unbound(r::ImageUnbound {
2401             view_format: conv::map_format(format),
2402             dsv_format: conv::map_format_dsv(base_format.0),
2403             desc,
2404             requirements: memory::Requirements {
2405                 size: alloc_info.SizeInBytes,
2406                 alignment: alloc_info.Alignment,
2407                 type_mask: MEM_TYPE_MASK << type_mask_shift,
2408             },
2409             format,
2410             kind,
2411             usage,
2412             tiling,
2413             view_caps,
2414             bytes_per_block,
2415             block_dim,
2416         }))
2417     }
2418 
get_image_requirements(&self, image: &r::Image) -> Requirements2419     unsafe fn get_image_requirements(&self, image: &r::Image) -> Requirements {
2420         match image {
2421             r::Image::Bound(i) => i.requirements,
2422             r::Image::Unbound(i) => i.requirements,
2423         }
2424     }
2425 
get_image_subresource_footprint( &self, image: &r::Image, sub: image::Subresource, ) -> image::SubresourceFootprint2426     unsafe fn get_image_subresource_footprint(
2427         &self,
2428         image: &r::Image,
2429         sub: image::Subresource,
2430     ) -> image::SubresourceFootprint {
2431         let mut num_rows = 0;
2432         let mut total_bytes = 0;
2433         let _desc = match image {
2434             r::Image::Bound(i) => i.descriptor,
2435             r::Image::Unbound(i) => i.desc,
2436         };
2437         let footprint = {
2438             let mut footprint = mem::zeroed();
2439             self.raw.GetCopyableFootprints(
2440                 image.get_desc(),
2441                 image.calc_subresource(sub.level as _, sub.layer as _, 0),
2442                 1,
2443                 0,
2444                 &mut footprint,
2445                 &mut num_rows,
2446                 ptr::null_mut(), // row size in bytes
2447                 &mut total_bytes,
2448             );
2449             footprint
2450         };
2451 
2452         let depth_pitch = (footprint.Footprint.RowPitch * num_rows) as buffer::Offset;
2453         let array_pitch = footprint.Footprint.Depth as buffer::Offset * depth_pitch;
2454         image::SubresourceFootprint {
2455             slice: footprint.Offset .. footprint.Offset + total_bytes,
2456             row_pitch: footprint.Footprint.RowPitch as _,
2457             depth_pitch,
2458             array_pitch,
2459         }
2460     }
2461 
bind_image_memory( &self, memory: &r::Memory, offset: u64, image: &mut r::Image, ) -> Result<(), d::BindError>2462     unsafe fn bind_image_memory(
2463         &self,
2464         memory: &r::Memory,
2465         offset: u64,
2466         image: &mut r::Image,
2467     ) -> Result<(), d::BindError> {
2468         use self::image::Usage;
2469 
2470         let image_unbound = *image.expect_unbound();
2471         if image_unbound.requirements.type_mask & (1 << memory.type_id) == 0 {
2472             error!(
2473                 "Bind memory failure: supported mask 0x{:x}, given id {}",
2474                 image_unbound.requirements.type_mask, memory.type_id
2475             );
2476             return Err(d::BindError::WrongMemory);
2477         }
2478         if offset + image_unbound.requirements.size > memory.size {
2479             return Err(d::BindError::OutOfBounds);
2480         }
2481 
2482         let mut resource = native::Resource::null();
2483         let num_layers = image_unbound.kind.num_layers();
2484 
2485         assert_eq!(
2486             winerror::S_OK,
2487             self.raw.clone().CreatePlacedResource(
2488                 memory.heap.as_mut_ptr(),
2489                 offset,
2490                 &image_unbound.desc,
2491                 d3d12::D3D12_RESOURCE_STATE_COMMON,
2492                 ptr::null(),
2493                 &d3d12::ID3D12Resource::uuidof(),
2494                 resource.mut_void(),
2495             )
2496         );
2497 
2498         let info = ViewInfo {
2499             resource,
2500             kind: image_unbound.kind,
2501             caps: image::ViewCapabilities::empty(),
2502             view_kind: match image_unbound.kind {
2503                 image::Kind::D1(..) => image::ViewKind::D1Array,
2504                 image::Kind::D2(..) => image::ViewKind::D2Array,
2505                 image::Kind::D3(..) => image::ViewKind::D3,
2506             },
2507             format: image_unbound.desc.Format,
2508             component_mapping: IDENTITY_MAPPING,
2509             range: image::SubresourceRange {
2510                 aspects: Aspects::empty(),
2511                 levels: 0 .. 0,
2512                 layers: 0 .. 0,
2513             },
2514         };
2515 
2516         //TODO: the clear_Xv is incomplete. We should support clearing images created without XXX_ATTACHMENT usage.
2517         // for this, we need to check the format and force the `RENDER_TARGET` flag behind the user's back
2518         // if the format supports being rendered into, allowing us to create clear_Xv
2519         let format_properties = self
2520             .format_properties
2521             .get(image_unbound.format as usize)
2522             .properties;
2523         let props = match image_unbound.tiling {
2524             image::Tiling::Optimal => format_properties.optimal_tiling,
2525             image::Tiling::Linear => format_properties.linear_tiling,
2526         };
2527         let can_clear_color = image_unbound
2528             .usage
2529             .intersects(Usage::TRANSFER_DST | Usage::COLOR_ATTACHMENT)
2530             && props.contains(format::ImageFeature::COLOR_ATTACHMENT);
2531         let can_clear_depth = image_unbound
2532             .usage
2533             .intersects(Usage::TRANSFER_DST | Usage::DEPTH_STENCIL_ATTACHMENT)
2534             && props.contains(format::ImageFeature::DEPTH_STENCIL_ATTACHMENT);
2535         let aspects = image_unbound.format.surface_desc().aspects;
2536 
2537         *image = r::Image::Bound(r::ImageBound {
2538             resource: resource,
2539             place: r::Place::Heap {
2540                 raw: memory.heap.clone(),
2541                 offset,
2542             },
2543             surface_type: image_unbound.format.base_format().0,
2544             kind: image_unbound.kind,
2545             usage: image_unbound.usage,
2546             default_view_format: image_unbound.view_format,
2547             view_caps: image_unbound.view_caps,
2548             descriptor: image_unbound.desc,
2549             bytes_per_block: image_unbound.bytes_per_block,
2550             block_dim: image_unbound.block_dim,
2551             clear_cv: if aspects.contains(Aspects::COLOR) && can_clear_color {
2552                 let format = image_unbound.view_format.unwrap();
2553                 (0 .. num_layers)
2554                     .map(|layer| {
2555                         self.view_image_as_render_target(ViewInfo {
2556                             format,
2557                             range: image::SubresourceRange {
2558                                 aspects: Aspects::COLOR,
2559                                 levels: 0 .. 1, //TODO?
2560                                 layers: layer .. layer + 1,
2561                             },
2562                             ..info.clone()
2563                         })
2564                         .unwrap()
2565                     })
2566                     .collect()
2567             } else {
2568                 Vec::new()
2569             },
2570             clear_dv: if aspects.contains(Aspects::DEPTH) && can_clear_depth {
2571                 let format = image_unbound.dsv_format.unwrap();
2572                 (0 .. num_layers)
2573                     .map(|layer| {
2574                         self.view_image_as_depth_stencil(ViewInfo {
2575                             format,
2576                             range: image::SubresourceRange {
2577                                 aspects: Aspects::DEPTH,
2578                                 levels: 0 .. 1, //TODO?
2579                                 layers: layer .. layer + 1,
2580                             },
2581                             ..info.clone()
2582                         })
2583                         .unwrap()
2584                     })
2585                     .collect()
2586             } else {
2587                 Vec::new()
2588             },
2589             clear_sv: if aspects.contains(Aspects::STENCIL) && can_clear_depth {
2590                 let format = image_unbound.dsv_format.unwrap();
2591                 (0 .. num_layers)
2592                     .map(|layer| {
2593                         self.view_image_as_depth_stencil(ViewInfo {
2594                             format,
2595                             range: image::SubresourceRange {
2596                                 aspects: Aspects::STENCIL,
2597                                 levels: 0 .. 1, //TODO?
2598                                 layers: layer .. layer + 1,
2599                             },
2600                             ..info.clone()
2601                         })
2602                         .unwrap()
2603                     })
2604                     .collect()
2605             } else {
2606                 Vec::new()
2607             },
2608             requirements: image_unbound.requirements,
2609         });
2610 
2611         Ok(())
2612     }
2613 
create_image_view( &self, image: &r::Image, view_kind: image::ViewKind, format: format::Format, swizzle: format::Swizzle, range: image::SubresourceRange, ) -> Result<r::ImageView, image::ViewCreationError>2614     unsafe fn create_image_view(
2615         &self,
2616         image: &r::Image,
2617         view_kind: image::ViewKind,
2618         format: format::Format,
2619         swizzle: format::Swizzle,
2620         range: image::SubresourceRange,
2621     ) -> Result<r::ImageView, image::ViewCreationError> {
2622         let image = image.expect_bound();
2623         let is_array = image.kind.num_layers() > 1;
2624         let mip_levels = (range.levels.start, range.levels.end);
2625         let layers = (range.layers.start, range.layers.end);
2626 
2627         let info = ViewInfo {
2628             resource: image.resource,
2629             kind: image.kind,
2630             caps: image.view_caps,
2631             // D3D12 doesn't allow looking at a single slice of an array as a non-array
2632             view_kind: if is_array && view_kind == image::ViewKind::D2 {
2633                 image::ViewKind::D2Array
2634             } else if is_array && view_kind == image::ViewKind::D1 {
2635                 image::ViewKind::D1Array
2636             } else {
2637                 view_kind
2638             },
2639             format: conv::map_format(format).ok_or(image::ViewCreationError::BadFormat(format))?,
2640             component_mapping: conv::map_swizzle(swizzle),
2641             range,
2642         };
2643 
2644         //Note: we allow RTV/DSV/SRV/UAV views to fail to be created here,
2645         // because we don't know if the user will even need to use them.
2646 
2647         Ok(r::ImageView {
2648             resource: image.resource,
2649             handle_srv: if image
2650                 .usage
2651                 .intersects(image::Usage::SAMPLED | image::Usage::INPUT_ATTACHMENT)
2652             {
2653                 self.view_image_as_shader_resource(info.clone()).ok()
2654             } else {
2655                 None
2656             },
2657             handle_rtv: if image.usage.contains(image::Usage::COLOR_ATTACHMENT) {
2658                 self.view_image_as_render_target(info.clone()).ok()
2659             } else {
2660                 None
2661             },
2662             handle_uav: if image.usage.contains(image::Usage::STORAGE) {
2663                 self.view_image_as_storage(info.clone()).ok()
2664             } else {
2665                 None
2666             },
2667             handle_dsv: if image.usage.contains(image::Usage::DEPTH_STENCIL_ATTACHMENT) {
2668                 match conv::map_format_dsv(format.base_format().0) {
2669                     Some(dsv_format) => self
2670                         .view_image_as_depth_stencil(ViewInfo {
2671                             format: dsv_format,
2672                             ..info
2673                         })
2674                         .ok(),
2675                     None => None,
2676                 }
2677             } else {
2678                 None
2679             },
2680             dxgi_format: image.default_view_format.unwrap(),
2681             num_levels: image.descriptor.MipLevels as image::Level,
2682             mip_levels,
2683             layers,
2684             kind: info.kind,
2685         })
2686     }
2687 
create_sampler( &self, info: &image::SamplerDesc, ) -> Result<r::Sampler, d::AllocationError>2688     unsafe fn create_sampler(
2689         &self,
2690         info: &image::SamplerDesc,
2691     ) -> Result<r::Sampler, d::AllocationError> {
2692         assert!(info.normalized);
2693         let handle = self.sampler_pool.lock().unwrap().alloc_handle();
2694 
2695         let op = match info.comparison {
2696             Some(_) => d3d12::D3D12_FILTER_REDUCTION_TYPE_COMPARISON,
2697             None => d3d12::D3D12_FILTER_REDUCTION_TYPE_STANDARD,
2698         };
2699         self.raw.create_sampler(
2700             handle,
2701             conv::map_filter(
2702                 info.mag_filter,
2703                 info.min_filter,
2704                 info.mip_filter,
2705                 op,
2706                 info.anisotropy_clamp,
2707             ),
2708             [
2709                 conv::map_wrap(info.wrap_mode.0),
2710                 conv::map_wrap(info.wrap_mode.1),
2711                 conv::map_wrap(info.wrap_mode.2),
2712             ],
2713             info.lod_bias.0,
2714             info.anisotropy_clamp.map_or(0, |aniso| aniso as u32),
2715             conv::map_comparison(info.comparison.unwrap_or(pso::Comparison::Always)),
2716             info.border.into(),
2717             info.lod_range.start.0 .. info.lod_range.end.0,
2718         );
2719 
2720         Ok(r::Sampler { handle })
2721     }
2722 
create_descriptor_pool<I>( &self, max_sets: usize, descriptor_pools: I, _flags: pso::DescriptorPoolCreateFlags, ) -> Result<r::DescriptorPool, d::OutOfMemory> where I: IntoIterator, I::Item: Borrow<pso::DescriptorRangeDesc>,2723     unsafe fn create_descriptor_pool<I>(
2724         &self,
2725         max_sets: usize,
2726         descriptor_pools: I,
2727         _flags: pso::DescriptorPoolCreateFlags,
2728     ) -> Result<r::DescriptorPool, d::OutOfMemory>
2729     where
2730         I: IntoIterator,
2731         I::Item: Borrow<pso::DescriptorRangeDesc>,
2732     {
2733         // Descriptor pools are implemented as slices of the global descriptor heaps.
2734         // A descriptor pool will occupy a contiguous space in each heap (CBV/SRV/UAV and Sampler) depending
2735         // on the total requested amount of descriptors.
2736 
2737         let mut num_srv_cbv_uav = 0;
2738         let mut num_samplers = 0;
2739 
2740         let descriptor_pools = descriptor_pools
2741             .into_iter()
2742             .map(|desc| *desc.borrow())
2743             .collect::<Vec<_>>();
2744 
2745         info!("create_descriptor_pool with {} max sets", max_sets);
2746         for desc in &descriptor_pools {
2747             let content = r::DescriptorContent::from(desc.ty);
2748             debug!("\tcontent {:?}", content);
2749             if content.contains(r::DescriptorContent::CBV) {
2750                 num_srv_cbv_uav += desc.count;
2751             }
2752             if content.contains(r::DescriptorContent::SRV) {
2753                 num_srv_cbv_uav += desc.count;
2754             }
2755             if content.contains(r::DescriptorContent::UAV) {
2756                 num_srv_cbv_uav += desc.count;
2757             }
2758             if content.contains(r::DescriptorContent::SAMPLER) {
2759                 num_samplers += desc.count;
2760             }
2761         }
2762 
2763         info!(
2764             "total {} views and {} samplers",
2765             num_srv_cbv_uav, num_samplers
2766         );
2767 
2768         // Allocate slices of the global GPU descriptor heaps.
2769         let heap_srv_cbv_uav = {
2770             let mut heap_srv_cbv_uav = self.heap_srv_cbv_uav.lock().unwrap();
2771 
2772             let range = match num_srv_cbv_uav {
2773                 0 => 0 .. 0,
2774                 _ => heap_srv_cbv_uav
2775                     .range_allocator
2776                     .allocate_range(num_srv_cbv_uav as _)
2777                     .unwrap(), // TODO: error/resize
2778             };
2779 
2780             r::DescriptorHeapSlice {
2781                 heap: heap_srv_cbv_uav.raw.clone(),
2782                 handle_size: heap_srv_cbv_uav.handle_size as _,
2783                 range_allocator: RangeAllocator::new(range),
2784                 start: heap_srv_cbv_uav.start,
2785             }
2786         };
2787 
2788         let heap_sampler = {
2789             let mut heap_sampler = self.heap_sampler.lock().unwrap();
2790 
2791             let range = match num_samplers {
2792                 0 => 0 .. 0,
2793                 _ => heap_sampler
2794                     .range_allocator
2795                     .allocate_range(num_samplers as _)
2796                     .unwrap(), // TODO: error/resize
2797             };
2798 
2799             r::DescriptorHeapSlice {
2800                 heap: heap_sampler.raw.clone(),
2801                 handle_size: heap_sampler.handle_size as _,
2802                 range_allocator: RangeAllocator::new(range),
2803                 start: heap_sampler.start,
2804             }
2805         };
2806 
2807         Ok(r::DescriptorPool {
2808             heap_srv_cbv_uav,
2809             heap_sampler,
2810             pools: descriptor_pools,
2811             max_size: max_sets as _,
2812         })
2813     }
2814 
create_descriptor_set_layout<I, J>( &self, bindings: I, _immutable_samplers: J, ) -> Result<r::DescriptorSetLayout, d::OutOfMemory> where I: IntoIterator, I::Item: Borrow<pso::DescriptorSetLayoutBinding>, J: IntoIterator, J::Item: Borrow<r::Sampler>,2815     unsafe fn create_descriptor_set_layout<I, J>(
2816         &self,
2817         bindings: I,
2818         _immutable_samplers: J,
2819     ) -> Result<r::DescriptorSetLayout, d::OutOfMemory>
2820     where
2821         I: IntoIterator,
2822         I::Item: Borrow<pso::DescriptorSetLayoutBinding>,
2823         J: IntoIterator,
2824         J::Item: Borrow<r::Sampler>,
2825     {
2826         Ok(r::DescriptorSetLayout {
2827             bindings: bindings.into_iter().map(|b| b.borrow().clone()).collect(),
2828         })
2829     }
2830 
write_descriptor_sets<'a, I, J>(&self, write_iter: I) where I: IntoIterator<Item = pso::DescriptorSetWrite<'a, B, J>>, J: IntoIterator, J::Item: Borrow<pso::Descriptor<'a, B>>,2831     unsafe fn write_descriptor_sets<'a, I, J>(&self, write_iter: I)
2832     where
2833         I: IntoIterator<Item = pso::DescriptorSetWrite<'a, B, J>>,
2834         J: IntoIterator,
2835         J::Item: Borrow<pso::Descriptor<'a, B>>,
2836     {
2837         let mut descriptor_update_pools = self.descriptor_update_pools.lock().unwrap();
2838         let mut update_pool_index = 0;
2839 
2840         //TODO: combine destination ranges
2841         let mut dst_samplers = Vec::new();
2842         let mut dst_views = Vec::new();
2843         let mut src_samplers = Vec::new();
2844         let mut src_views = Vec::new();
2845         let mut num_samplers = Vec::new();
2846         let mut num_views = Vec::new();
2847         debug!("write_descriptor_sets");
2848 
2849         for write in write_iter {
2850             let mut offset = write.array_offset as u64;
2851             let mut target_binding = write.binding as usize;
2852             let mut bind_info = &write.set.binding_infos[target_binding];
2853             debug!(
2854                 "\t{:?} binding {} array offset {}",
2855                 bind_info, target_binding, offset
2856             );
2857             for descriptor in write.descriptors {
2858                 // spill over the writes onto the next binding
2859                 while offset >= bind_info.count {
2860                     assert_eq!(offset, bind_info.count);
2861                     target_binding += 1;
2862                     bind_info = &write.set.binding_infos[target_binding];
2863                     offset = 0;
2864                 }
2865                 let mut src_cbv = None;
2866                 let mut src_srv = None;
2867                 let mut src_uav = None;
2868                 let mut src_sampler = None;
2869 
2870                 match *descriptor.borrow() {
2871                     pso::Descriptor::Buffer(buffer, ref sub) => {
2872                         let buffer = buffer.expect_bound();
2873 
2874                         if bind_info.content.is_dynamic() {
2875                             // Root Descriptor
2876                             let buffer_address = (*buffer.resource).GetGPUVirtualAddress();
2877                             // Descriptor sets need to be externally synchronized according to specification
2878                             let dynamic_descriptors = &mut *bind_info.dynamic_descriptors.get();
2879                             dynamic_descriptors[offset as usize].gpu_buffer_location =
2880                                 buffer_address + sub.offset;
2881                         } else {
2882                             // Descriptor table
2883                             if update_pool_index == descriptor_update_pools.len() {
2884                                 let max_size = 1u64 << 12; //arbitrary
2885                                 descriptor_update_pools.push(descriptors_cpu::HeapLinear::new(
2886                                     self.raw,
2887                                     native::DescriptorHeapType::CbvSrvUav,
2888                                     max_size as _,
2889                                 ));
2890                             }
2891                             let mut heap = descriptor_update_pools.pop().unwrap();
2892                             let size = sub.size_to(buffer.requirements.size);
2893 
2894                             if bind_info.content.contains(r::DescriptorContent::CBV) {
2895                                 // Making the size field of buffer requirements for uniform
2896                                 // buffers a multiple of 256 and setting the required offset
2897                                 // alignment to 256 allows us to patch the size here.
2898                                 // We can always enforce the size to be aligned to 256 for
2899                                 // CBVs without going out-of-bounds.
2900                                 let desc = d3d12::D3D12_CONSTANT_BUFFER_VIEW_DESC {
2901                                     BufferLocation: (*buffer.resource).GetGPUVirtualAddress()
2902                                         + sub.offset,
2903                                     SizeInBytes: ((size + 0xFF) & !0xFF) as _,
2904                                 };
2905                                 let handle = heap.alloc_handle();
2906                                 self.raw.CreateConstantBufferView(&desc, handle);
2907                                 src_cbv = Some(handle);
2908                             }
2909                             if bind_info.content.contains(r::DescriptorContent::SRV) {
2910                                 assert_eq!(size % 4, 0);
2911                                 let mut desc = d3d12::D3D12_SHADER_RESOURCE_VIEW_DESC {
2912                                     Format: dxgiformat::DXGI_FORMAT_R32_TYPELESS,
2913                                     Shader4ComponentMapping: IDENTITY_MAPPING,
2914                                     ViewDimension: d3d12::D3D12_SRV_DIMENSION_BUFFER,
2915                                     u: mem::zeroed(),
2916                                 };
2917                                 *desc.u.Buffer_mut() = d3d12::D3D12_BUFFER_SRV {
2918                                     FirstElement: sub.offset as _,
2919                                     NumElements: (size / 4) as _,
2920                                     StructureByteStride: 0,
2921                                     Flags: d3d12::D3D12_BUFFER_SRV_FLAG_RAW,
2922                                 };
2923                                 let handle = heap.alloc_handle();
2924                                 self.raw.CreateShaderResourceView(
2925                                     buffer.resource.as_mut_ptr(),
2926                                     &desc,
2927                                     handle,
2928                                 );
2929                                 src_srv = Some(handle);
2930                             }
2931                             if bind_info.content.contains(r::DescriptorContent::UAV) {
2932                                 assert_eq!(size % 4, 0);
2933                                 let mut desc = d3d12::D3D12_UNORDERED_ACCESS_VIEW_DESC {
2934                                     Format: dxgiformat::DXGI_FORMAT_R32_TYPELESS,
2935                                     ViewDimension: d3d12::D3D12_UAV_DIMENSION_BUFFER,
2936                                     u: mem::zeroed(),
2937                                 };
2938                                 *desc.u.Buffer_mut() = d3d12::D3D12_BUFFER_UAV {
2939                                     FirstElement: sub.offset as _,
2940                                     NumElements: (size / 4) as _,
2941                                     StructureByteStride: 0,
2942                                     CounterOffsetInBytes: 0,
2943                                     Flags: d3d12::D3D12_BUFFER_UAV_FLAG_RAW,
2944                                 };
2945                                 if heap.is_full() {
2946                                     // pool is full, move to the next one
2947                                     update_pool_index += 1;
2948                                     let max_size = 1u64 << 12; //arbitrary
2949                                     let full_heap = mem::replace(
2950                                         &mut heap,
2951                                         descriptors_cpu::HeapLinear::new(
2952                                             self.raw,
2953                                             native::DescriptorHeapType::CbvSrvUav,
2954                                             max_size as _,
2955                                         ),
2956                                     );
2957                                     descriptor_update_pools.push(full_heap);
2958                                 }
2959                                 let handle = heap.alloc_handle();
2960                                 self.raw.CreateUnorderedAccessView(
2961                                     buffer.resource.as_mut_ptr(),
2962                                     ptr::null_mut(),
2963                                     &desc,
2964                                     handle,
2965                                 );
2966                                 src_uav = Some(handle);
2967                             }
2968 
2969                             // always leave this block of code prepared
2970                             if heap.is_full() {
2971                                 // pool is full, move to the next one
2972                                 update_pool_index += 1;
2973                             }
2974                             descriptor_update_pools.push(heap);
2975                         }
2976                     }
2977                     pso::Descriptor::Image(image, _layout) => {
2978                         if bind_info.content.contains(r::DescriptorContent::SRV) {
2979                             src_srv = image.handle_srv;
2980                         }
2981                         if bind_info.content.contains(r::DescriptorContent::UAV) {
2982                             src_uav = image.handle_uav;
2983                         }
2984                     }
2985                     pso::Descriptor::CombinedImageSampler(image, _layout, sampler) => {
2986                         src_srv = image.handle_srv;
2987                         src_sampler = Some(sampler.handle);
2988                     }
2989                     pso::Descriptor::Sampler(sampler) => {
2990                         src_sampler = Some(sampler.handle);
2991                     }
2992                     pso::Descriptor::TexelBuffer(buffer_view) => {
2993                         if bind_info.content.contains(r::DescriptorContent::SRV) {
2994                             let handle = buffer_view.handle_srv;
2995                             src_srv = Some(handle);
2996                             if handle.ptr == 0 {
2997                                 error!("SRV handle of the storage texel buffer is zero (not supported by specified format).");
2998                             }
2999                         }
3000                         if bind_info.content.contains(r::DescriptorContent::UAV) {
3001                             let handle = buffer_view.handle_uav;
3002                             src_uav = Some(handle);
3003                             if handle.ptr == 0 {
3004                                 error!("UAV handle of the storage texel buffer is zero (not supported by specified format).");
3005                             }
3006                         }
3007                     }
3008                 }
3009 
3010                 if let Some(handle) = src_cbv {
3011                     trace!("\tcbv offset {}", offset);
3012                     src_views.push(handle);
3013                     dst_views.push(bind_info.view_range.as_ref().unwrap().at(offset));
3014                     num_views.push(1);
3015                 }
3016                 if let Some(handle) = src_srv {
3017                     trace!("\tsrv offset {}", offset);
3018                     src_views.push(handle);
3019                     dst_views.push(bind_info.view_range.as_ref().unwrap().at(offset));
3020                     num_views.push(1);
3021                 }
3022                 if let Some(handle) = src_uav {
3023                     let uav_offset = if bind_info.content.contains(r::DescriptorContent::SRV) {
3024                         bind_info.count + offset
3025                     } else {
3026                         offset
3027                     };
3028                     trace!("\tuav offset {}", uav_offset);
3029                     src_views.push(handle);
3030                     dst_views.push(bind_info.view_range.as_ref().unwrap().at(uav_offset));
3031                     num_views.push(1);
3032                 }
3033                 if let Some(handle) = src_sampler {
3034                     trace!("\tsampler offset {}", offset);
3035                     src_samplers.push(handle);
3036                     dst_samplers.push(bind_info.sampler_range.as_ref().unwrap().at(offset));
3037                     num_samplers.push(1);
3038                 }
3039 
3040                 offset += 1;
3041             }
3042         }
3043 
3044         if !num_views.is_empty() {
3045             self.raw.clone().CopyDescriptors(
3046                 dst_views.len() as u32,
3047                 dst_views.as_ptr(),
3048                 num_views.as_ptr(),
3049                 src_views.len() as u32,
3050                 src_views.as_ptr(),
3051                 num_views.as_ptr(),
3052                 d3d12::D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
3053             );
3054         }
3055         if !num_samplers.is_empty() {
3056             self.raw.clone().CopyDescriptors(
3057                 dst_samplers.len() as u32,
3058                 dst_samplers.as_ptr(),
3059                 num_samplers.as_ptr(),
3060                 src_samplers.len() as u32,
3061                 src_samplers.as_ptr(),
3062                 num_samplers.as_ptr(),
3063                 d3d12::D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
3064             );
3065         }
3066 
3067         // reset the temporary CPU-size descriptor pools
3068         for buffer_desc_pool in descriptor_update_pools.iter_mut() {
3069             buffer_desc_pool.clear();
3070         }
3071     }
3072 
copy_descriptor_sets<'a, I>(&self, copy_iter: I) where I: IntoIterator, I::Item: Borrow<pso::DescriptorSetCopy<'a, B>>,3073     unsafe fn copy_descriptor_sets<'a, I>(&self, copy_iter: I)
3074     where
3075         I: IntoIterator,
3076         I::Item: Borrow<pso::DescriptorSetCopy<'a, B>>,
3077     {
3078         let mut dst_samplers = Vec::new();
3079         let mut dst_views = Vec::new();
3080         let mut src_samplers = Vec::new();
3081         let mut src_views = Vec::new();
3082         let mut num_samplers = Vec::new();
3083         let mut num_views = Vec::new();
3084 
3085         for copy_wrap in copy_iter {
3086             let copy = copy_wrap.borrow();
3087             let src_info = &copy.src_set.binding_infos[copy.src_binding as usize];
3088             let dst_info = &copy.dst_set.binding_infos[copy.dst_binding as usize];
3089             if let (Some(src_range), Some(dst_range)) =
3090                 (src_info.view_range.as_ref(), dst_info.view_range.as_ref())
3091             {
3092                 assert!(copy.src_array_offset + copy.count <= src_range.count as usize);
3093                 assert!(copy.dst_array_offset + copy.count <= dst_range.count as usize);
3094                 src_views.push(src_range.at(copy.src_array_offset as _));
3095                 dst_views.push(dst_range.at(copy.dst_array_offset as _));
3096                 num_views.push(copy.count as u32);
3097 
3098                 if (src_info.content & dst_info.content)
3099                     .contains(r::DescriptorContent::SRV | r::DescriptorContent::UAV)
3100                 {
3101                     assert!(
3102                         src_info.count as usize + copy.src_array_offset + copy.count
3103                             <= src_range.count as usize
3104                     );
3105                     assert!(
3106                         dst_info.count as usize + copy.dst_array_offset + copy.count
3107                             <= dst_range.count as usize
3108                     );
3109                     src_views.push(src_range.at(src_info.count + copy.src_array_offset as u64));
3110                     dst_views.push(dst_range.at(dst_info.count + copy.dst_array_offset as u64));
3111                     num_views.push(copy.count as u32);
3112                 }
3113             }
3114             if let (Some(src_range), Some(dst_range)) = (
3115                 src_info.sampler_range.as_ref(),
3116                 dst_info.sampler_range.as_ref(),
3117             ) {
3118                 assert!(copy.src_array_offset + copy.count <= src_range.count as usize);
3119                 assert!(copy.dst_array_offset + copy.count <= dst_range.count as usize);
3120                 src_samplers.push(src_range.at(copy.src_array_offset as _));
3121                 dst_samplers.push(dst_range.at(copy.dst_array_offset as _));
3122                 num_samplers.push(copy.count as u32);
3123             }
3124         }
3125 
3126         if !num_views.is_empty() {
3127             self.raw.clone().CopyDescriptors(
3128                 dst_views.len() as u32,
3129                 dst_views.as_ptr(),
3130                 num_views.as_ptr(),
3131                 src_views.len() as u32,
3132                 src_views.as_ptr(),
3133                 num_views.as_ptr(),
3134                 d3d12::D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
3135             );
3136         }
3137         if !num_samplers.is_empty() {
3138             self.raw.clone().CopyDescriptors(
3139                 dst_samplers.len() as u32,
3140                 dst_samplers.as_ptr(),
3141                 num_samplers.as_ptr(),
3142                 src_samplers.len() as u32,
3143                 src_samplers.as_ptr(),
3144                 num_samplers.as_ptr(),
3145                 d3d12::D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
3146             );
3147         }
3148     }
3149 
map_memory( &self, memory: &r::Memory, segment: memory::Segment, ) -> Result<*mut u8, d::MapError>3150     unsafe fn map_memory(
3151         &self,
3152         memory: &r::Memory,
3153         segment: memory::Segment,
3154     ) -> Result<*mut u8, d::MapError> {
3155         let mem = memory
3156             .resource
3157             .expect("Memory not created with a memory type exposing `CPU_VISIBLE`");
3158         let mut ptr = ptr::null_mut();
3159         assert_eq!(
3160             winerror::S_OK,
3161             (*mem).Map(0, &d3d12::D3D12_RANGE { Begin: 0, End: 0 }, &mut ptr)
3162         );
3163         ptr = ptr.offset(segment.offset as isize);
3164         Ok(ptr as *mut _)
3165     }
3166 
unmap_memory(&self, memory: &r::Memory)3167     unsafe fn unmap_memory(&self, memory: &r::Memory) {
3168         if let Some(mem) = memory.resource {
3169             (*mem).Unmap(0, &d3d12::D3D12_RANGE { Begin: 0, End: 0 });
3170         }
3171     }
3172 
flush_mapped_memory_ranges<'a, I>(&self, ranges: I) -> Result<(), d::OutOfMemory> where I: IntoIterator, I::Item: Borrow<(&'a r::Memory, memory::Segment)>,3173     unsafe fn flush_mapped_memory_ranges<'a, I>(&self, ranges: I) -> Result<(), d::OutOfMemory>
3174     where
3175         I: IntoIterator,
3176         I::Item: Borrow<(&'a r::Memory, memory::Segment)>,
3177     {
3178         for range in ranges {
3179             let &(ref memory, ref segment) = range.borrow();
3180             if let Some(mem) = memory.resource {
3181                 // map and immediately unmap, hoping that dx12 drivers internally cache
3182                 // currently mapped buffers.
3183                 assert_eq!(
3184                     winerror::S_OK,
3185                     (*mem).Map(0, &d3d12::D3D12_RANGE { Begin: 0, End: 0 }, ptr::null_mut())
3186                 );
3187 
3188                 let start = segment.offset;
3189                 let end = segment.size.map_or(memory.size, |s| start + s); // TODO: only need to be end of current mapping
3190 
3191                 (*mem).Unmap(
3192                     0,
3193                     &d3d12::D3D12_RANGE {
3194                         Begin: start as _,
3195                         End: end as _,
3196                     },
3197                 );
3198             }
3199         }
3200 
3201         Ok(())
3202     }
3203 
invalidate_mapped_memory_ranges<'a, I>(&self, ranges: I) -> Result<(), d::OutOfMemory> where I: IntoIterator, I::Item: Borrow<(&'a r::Memory, memory::Segment)>,3204     unsafe fn invalidate_mapped_memory_ranges<'a, I>(&self, ranges: I) -> Result<(), d::OutOfMemory>
3205     where
3206         I: IntoIterator,
3207         I::Item: Borrow<(&'a r::Memory, memory::Segment)>,
3208     {
3209         for range in ranges {
3210             let &(ref memory, ref segment) = range.borrow();
3211             if let Some(mem) = memory.resource {
3212                 let start = segment.offset;
3213                 let end = segment.size.map_or(memory.size, |s| start + s); // TODO: only need to be end of current mapping
3214 
3215                 // map and immediately unmap, hoping that dx12 drivers internally cache
3216                 // currently mapped buffers.
3217                 assert_eq!(
3218                     winerror::S_OK,
3219                     (*mem).Map(
3220                         0,
3221                         &d3d12::D3D12_RANGE {
3222                             Begin: start as _,
3223                             End: end as _,
3224                         },
3225                         ptr::null_mut(),
3226                     )
3227                 );
3228 
3229                 (*mem).Unmap(0, &d3d12::D3D12_RANGE { Begin: 0, End: 0 });
3230             }
3231         }
3232 
3233         Ok(())
3234     }
3235 
create_semaphore(&self) -> Result<r::Semaphore, d::OutOfMemory>3236     fn create_semaphore(&self) -> Result<r::Semaphore, d::OutOfMemory> {
3237         let fence = self.create_fence(false)?;
3238         Ok(r::Semaphore { raw: fence.raw })
3239     }
3240 
create_fence(&self, signalled: bool) -> Result<r::Fence, d::OutOfMemory>3241     fn create_fence(&self, signalled: bool) -> Result<r::Fence, d::OutOfMemory> {
3242         Ok(r::Fence {
3243             raw: self.create_raw_fence(signalled),
3244         })
3245     }
3246 
reset_fence(&self, fence: &r::Fence) -> Result<(), d::OutOfMemory>3247     unsafe fn reset_fence(&self, fence: &r::Fence) -> Result<(), d::OutOfMemory> {
3248         assert_eq!(winerror::S_OK, fence.raw.signal(0));
3249         Ok(())
3250     }
3251 
wait_for_fences<I>( &self, fences: I, wait: d::WaitFor, timeout_ns: u64, ) -> Result<bool, d::OomOrDeviceLost> where I: IntoIterator, I::Item: Borrow<r::Fence>,3252     unsafe fn wait_for_fences<I>(
3253         &self,
3254         fences: I,
3255         wait: d::WaitFor,
3256         timeout_ns: u64,
3257     ) -> Result<bool, d::OomOrDeviceLost>
3258     where
3259         I: IntoIterator,
3260         I::Item: Borrow<r::Fence>,
3261     {
3262         let fences = fences.into_iter().collect::<Vec<_>>();
3263         let mut events = self.events.lock().unwrap();
3264         for _ in events.len() .. fences.len() {
3265             events.push(native::Event::create(false, false));
3266         }
3267 
3268         for (&event, fence) in events.iter().zip(fences.iter()) {
3269             synchapi::ResetEvent(event.0);
3270             assert_eq!(
3271                 winerror::S_OK,
3272                 fence.borrow().raw.set_event_on_completion(event, 1)
3273             );
3274         }
3275 
3276         let all = match wait {
3277             d::WaitFor::Any => FALSE,
3278             d::WaitFor::All => TRUE,
3279         };
3280 
3281         let hr = {
3282             // This block handles overflow when converting to u32 and always rounds up
3283             // The Vulkan specification allows to wait more than specified
3284             let timeout_ms = {
3285                 if timeout_ns > (<u32>::max_value() as u64) * 1_000_000 {
3286                     <u32>::max_value()
3287                 } else {
3288                     ((timeout_ns + 999_999) / 1_000_000) as u32
3289                 }
3290             };
3291 
3292             synchapi::WaitForMultipleObjects(
3293                 fences.len() as u32,
3294                 events.as_ptr() as *const _,
3295                 all,
3296                 timeout_ms,
3297             )
3298         };
3299 
3300         const WAIT_OBJECT_LAST: u32 = winbase::WAIT_OBJECT_0 + winnt::MAXIMUM_WAIT_OBJECTS;
3301         const WAIT_ABANDONED_LAST: u32 = winbase::WAIT_ABANDONED_0 + winnt::MAXIMUM_WAIT_OBJECTS;
3302         match hr {
3303             winbase::WAIT_FAILED => Err(d::OomOrDeviceLost::DeviceLost(d::DeviceLost)),
3304             winbase::WAIT_OBJECT_0 ..= WAIT_OBJECT_LAST => Ok(true),
3305             winbase::WAIT_ABANDONED_0 ..= WAIT_ABANDONED_LAST => Ok(true), //TODO?
3306             winerror::WAIT_TIMEOUT => Ok(false),
3307             _ => panic!("Unexpected wait status 0x{:X}", hr),
3308         }
3309     }
3310 
get_fence_status(&self, fence: &r::Fence) -> Result<bool, d::DeviceLost>3311     unsafe fn get_fence_status(&self, fence: &r::Fence) -> Result<bool, d::DeviceLost> {
3312         match fence.raw.GetCompletedValue() {
3313             0 => Ok(false),
3314             1 => Ok(true),
3315             _ => Err(d::DeviceLost),
3316         }
3317     }
3318 
create_event(&self) -> Result<(), d::OutOfMemory>3319     fn create_event(&self) -> Result<(), d::OutOfMemory> {
3320         unimplemented!()
3321     }
3322 
get_event_status(&self, _event: &()) -> Result<bool, d::OomOrDeviceLost>3323     unsafe fn get_event_status(&self, _event: &()) -> Result<bool, d::OomOrDeviceLost> {
3324         unimplemented!()
3325     }
3326 
set_event(&self, _event: &()) -> Result<(), d::OutOfMemory>3327     unsafe fn set_event(&self, _event: &()) -> Result<(), d::OutOfMemory> {
3328         unimplemented!()
3329     }
3330 
reset_event(&self, _event: &()) -> Result<(), d::OutOfMemory>3331     unsafe fn reset_event(&self, _event: &()) -> Result<(), d::OutOfMemory> {
3332         unimplemented!()
3333     }
3334 
free_memory(&self, memory: r::Memory)3335     unsafe fn free_memory(&self, memory: r::Memory) {
3336         memory.heap.destroy();
3337         if let Some(buffer) = memory.resource {
3338             buffer.destroy();
3339         }
3340     }
3341 
create_query_pool( &self, query_ty: query::Type, count: query::Id, ) -> Result<r::QueryPool, query::CreationError>3342     unsafe fn create_query_pool(
3343         &self,
3344         query_ty: query::Type,
3345         count: query::Id,
3346     ) -> Result<r::QueryPool, query::CreationError> {
3347         let heap_ty = match query_ty {
3348             query::Type::Occlusion => native::QueryHeapType::Occlusion,
3349             query::Type::PipelineStatistics(_) => native::QueryHeapType::PipelineStatistics,
3350             query::Type::Timestamp => native::QueryHeapType::Timestamp,
3351         };
3352 
3353         let (query_heap, hr) = self.raw.create_query_heap(heap_ty, count, 0);
3354         assert_eq!(winerror::S_OK, hr);
3355 
3356         Ok(r::QueryPool {
3357             raw: query_heap,
3358             ty: heap_ty,
3359         })
3360     }
3361 
destroy_query_pool(&self, pool: r::QueryPool)3362     unsafe fn destroy_query_pool(&self, pool: r::QueryPool) {
3363         pool.raw.destroy();
3364     }
3365 
get_query_pool_results( &self, _pool: &r::QueryPool, _queries: Range<query::Id>, _data: &mut [u8], _stride: buffer::Offset, _flags: query::ResultFlags, ) -> Result<bool, d::OomOrDeviceLost>3366     unsafe fn get_query_pool_results(
3367         &self,
3368         _pool: &r::QueryPool,
3369         _queries: Range<query::Id>,
3370         _data: &mut [u8],
3371         _stride: buffer::Offset,
3372         _flags: query::ResultFlags,
3373     ) -> Result<bool, d::OomOrDeviceLost> {
3374         unimplemented!()
3375     }
3376 
destroy_shader_module(&self, shader_lib: r::ShaderModule)3377     unsafe fn destroy_shader_module(&self, shader_lib: r::ShaderModule) {
3378         if let r::ShaderModule::Compiled(shaders) = shader_lib {
3379             for (_, blob) in shaders {
3380                 blob.destroy();
3381             }
3382         }
3383     }
3384 
destroy_render_pass(&self, _rp: r::RenderPass)3385     unsafe fn destroy_render_pass(&self, _rp: r::RenderPass) {
3386         // Just drop
3387     }
3388 
destroy_pipeline_layout(&self, layout: r::PipelineLayout)3389     unsafe fn destroy_pipeline_layout(&self, layout: r::PipelineLayout) {
3390         layout.raw.destroy();
3391     }
3392 
destroy_graphics_pipeline(&self, pipeline: r::GraphicsPipeline)3393     unsafe fn destroy_graphics_pipeline(&self, pipeline: r::GraphicsPipeline) {
3394         pipeline.raw.destroy();
3395     }
3396 
destroy_compute_pipeline(&self, pipeline: r::ComputePipeline)3397     unsafe fn destroy_compute_pipeline(&self, pipeline: r::ComputePipeline) {
3398         pipeline.raw.destroy();
3399     }
3400 
destroy_framebuffer(&self, _fb: r::Framebuffer)3401     unsafe fn destroy_framebuffer(&self, _fb: r::Framebuffer) {
3402         // Just drop
3403     }
3404 
destroy_buffer(&self, buffer: r::Buffer)3405     unsafe fn destroy_buffer(&self, buffer: r::Buffer) {
3406         match buffer {
3407             r::Buffer::Bound(buffer) => {
3408                 buffer.resource.destroy();
3409             }
3410             r::Buffer::Unbound(_) => {}
3411         }
3412     }
3413 
destroy_buffer_view(&self, _view: r::BufferView)3414     unsafe fn destroy_buffer_view(&self, _view: r::BufferView) {
3415         // empty
3416     }
3417 
destroy_image(&self, image: r::Image)3418     unsafe fn destroy_image(&self, image: r::Image) {
3419         match image {
3420             r::Image::Bound(image) => {
3421                 image.resource.destroy();
3422             }
3423             r::Image::Unbound(_) => {}
3424         }
3425     }
3426 
destroy_image_view(&self, _view: r::ImageView)3427     unsafe fn destroy_image_view(&self, _view: r::ImageView) {
3428         // Just drop
3429     }
3430 
destroy_sampler(&self, _sampler: r::Sampler)3431     unsafe fn destroy_sampler(&self, _sampler: r::Sampler) {
3432         // Just drop
3433     }
3434 
destroy_descriptor_pool(&self, _pool: r::DescriptorPool)3435     unsafe fn destroy_descriptor_pool(&self, _pool: r::DescriptorPool) {
3436         // Just drop
3437         // Allocated descriptor sets don't need to be freed beforehand.
3438     }
3439 
destroy_descriptor_set_layout(&self, _layout: r::DescriptorSetLayout)3440     unsafe fn destroy_descriptor_set_layout(&self, _layout: r::DescriptorSetLayout) {
3441         // Just drop
3442     }
3443 
destroy_fence(&self, fence: r::Fence)3444     unsafe fn destroy_fence(&self, fence: r::Fence) {
3445         fence.raw.destroy();
3446     }
3447 
destroy_semaphore(&self, semaphore: r::Semaphore)3448     unsafe fn destroy_semaphore(&self, semaphore: r::Semaphore) {
3449         semaphore.raw.destroy();
3450     }
3451 
destroy_event(&self, _event: ())3452     unsafe fn destroy_event(&self, _event: ()) {
3453         unimplemented!()
3454     }
3455 
create_swapchain( &self, surface: &mut Surface, config: w::SwapchainConfig, old_swapchain: Option<Swapchain>, ) -> Result<(Swapchain, Vec<r::Image>), w::CreationError>3456     unsafe fn create_swapchain(
3457         &self,
3458         surface: &mut Surface,
3459         config: w::SwapchainConfig,
3460         old_swapchain: Option<Swapchain>,
3461     ) -> Result<(Swapchain, Vec<r::Image>), w::CreationError> {
3462         if let Some(old_swapchain) = old_swapchain {
3463             self.destroy_swapchain(old_swapchain);
3464         }
3465 
3466         let (swap_chain3, non_srgb_format) =
3467             self.create_swapchain_impl(&config, surface.wnd_handle, surface.factory)?;
3468 
3469         let swapchain = self.wrap_swapchain(swap_chain3, &config);
3470 
3471         let mut images = Vec::with_capacity(config.image_count as usize);
3472         for (i, &resource) in swapchain.resources.iter().enumerate() {
3473             let rtv_handle = swapchain.rtv_heap.at(i as _, 0).cpu;
3474             let surface_type = config.format.base_format().0;
3475             let format_desc = surface_type.desc();
3476 
3477             let bytes_per_block = (format_desc.bits / 8) as _;
3478             let block_dim = format_desc.dim;
3479             let kind = image::Kind::D2(config.extent.width, config.extent.height, 1, 1);
3480 
3481             images.push(r::Image::Bound(r::ImageBound {
3482                 resource,
3483                 place: r::Place::SwapChain,
3484                 surface_type,
3485                 kind,
3486                 usage: config.image_usage,
3487                 default_view_format: Some(non_srgb_format),
3488                 view_caps: image::ViewCapabilities::empty(),
3489                 descriptor: d3d12::D3D12_RESOURCE_DESC {
3490                     Dimension: d3d12::D3D12_RESOURCE_DIMENSION_TEXTURE2D,
3491                     Alignment: 0,
3492                     Width: config.extent.width as _,
3493                     Height: config.extent.height as _,
3494                     DepthOrArraySize: 1,
3495                     MipLevels: 1,
3496                     Format: non_srgb_format,
3497                     SampleDesc: dxgitype::DXGI_SAMPLE_DESC {
3498                         Count: 1,
3499                         Quality: 0,
3500                     },
3501                     Layout: d3d12::D3D12_TEXTURE_LAYOUT_UNKNOWN,
3502                     Flags: 0,
3503                 },
3504                 bytes_per_block,
3505                 block_dim,
3506                 clear_cv: vec![rtv_handle],
3507                 clear_dv: Vec::new(),
3508                 clear_sv: Vec::new(),
3509                 // Dummy values, image is already bound
3510                 requirements: memory::Requirements {
3511                     alignment: 1,
3512                     size: 1,
3513                     type_mask: MEM_TYPE_MASK,
3514                 },
3515             }));
3516         }
3517 
3518         Ok((swapchain, images))
3519     }
3520 
destroy_swapchain(&self, swapchain: Swapchain)3521     unsafe fn destroy_swapchain(&self, swapchain: Swapchain) {
3522         let inner = swapchain.release_resources();
3523         inner.destroy();
3524     }
3525 
wait_idle(&self) -> Result<(), d::OutOfMemory>3526     fn wait_idle(&self) -> Result<(), d::OutOfMemory> {
3527         for queue in &self.queues {
3528             queue.wait_idle()?;
3529         }
3530         Ok(())
3531     }
3532 
set_image_name(&self, _image: &mut r::Image, _name: &str)3533     unsafe fn set_image_name(&self, _image: &mut r::Image, _name: &str) {
3534         // TODO
3535     }
3536 
set_buffer_name(&self, _buffer: &mut r::Buffer, _name: &str)3537     unsafe fn set_buffer_name(&self, _buffer: &mut r::Buffer, _name: &str) {
3538         // TODO
3539     }
3540 
set_command_buffer_name( &self, _command_buffer: &mut cmd::CommandBuffer, _name: &str, )3541     unsafe fn set_command_buffer_name(
3542         &self,
3543         _command_buffer: &mut cmd::CommandBuffer,
3544         _name: &str,
3545     ) {
3546         // TODO
3547     }
3548 
set_semaphore_name(&self, _semaphore: &mut r::Semaphore, _name: &str)3549     unsafe fn set_semaphore_name(&self, _semaphore: &mut r::Semaphore, _name: &str) {
3550         // TODO
3551     }
3552 
set_fence_name(&self, _fence: &mut r::Fence, _name: &str)3553     unsafe fn set_fence_name(&self, _fence: &mut r::Fence, _name: &str) {
3554         // TODO
3555     }
3556 
set_framebuffer_name(&self, _framebuffer: &mut r::Framebuffer, _name: &str)3557     unsafe fn set_framebuffer_name(&self, _framebuffer: &mut r::Framebuffer, _name: &str) {
3558         // TODO
3559     }
3560 
set_render_pass_name(&self, _render_pass: &mut r::RenderPass, _name: &str)3561     unsafe fn set_render_pass_name(&self, _render_pass: &mut r::RenderPass, _name: &str) {
3562         // TODO
3563     }
3564 
set_descriptor_set_name(&self, _descriptor_set: &mut r::DescriptorSet, _name: &str)3565     unsafe fn set_descriptor_set_name(&self, _descriptor_set: &mut r::DescriptorSet, _name: &str) {
3566         // TODO
3567     }
3568 
set_descriptor_set_layout_name( &self, _descriptor_set_layout: &mut r::DescriptorSetLayout, _name: &str, )3569     unsafe fn set_descriptor_set_layout_name(
3570         &self,
3571         _descriptor_set_layout: &mut r::DescriptorSetLayout,
3572         _name: &str,
3573     ) {
3574         // TODO
3575     }
3576 }
3577 
3578 #[test]
test_identity_mapping()3579 fn test_identity_mapping() {
3580     assert_eq!(conv::map_swizzle(format::Swizzle::NO), IDENTITY_MAPPING);
3581 }
3582