1 use std::{fmt, sync::Arc};
2 
3 use winapi::shared::winerror::SUCCEEDED;
4 
5 use crate::{command::CommandBuffer, Backend, Shared};
6 use hal::{command, pool};
7 
8 #[derive(Debug)]
9 pub enum CommandPoolAllocator {
10     Shared(native::CommandAllocator),
11     Individual(Vec<native::CommandAllocator>),
12 }
13 
14 pub struct CommandPool {
15     pub(crate) allocator: CommandPoolAllocator,
16     pub(crate) device: native::Device,
17     pub(crate) list_type: native::CmdListType,
18     pub(crate) shared: Arc<Shared>,
19     pub(crate) create_flags: pool::CommandPoolCreateFlags,
20 }
21 
22 impl fmt::Debug for CommandPool {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result23     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
24         fmt.write_str("CommandPool")
25     }
26 }
27 
28 impl CommandPool {
create_command_list(&mut self) -> (native::GraphicsCommandList, native::CommandAllocator)29     fn create_command_list(&mut self) -> (native::GraphicsCommandList, native::CommandAllocator) {
30         let command_allocator = match self.allocator {
31             CommandPoolAllocator::Shared(ref allocator) => allocator.clone(),
32             CommandPoolAllocator::Individual(ref mut allocators) => {
33                 let (command_allocator, hr) = self.device.create_command_allocator(self.list_type);
34 
35                 // TODO: error handling
36                 if !SUCCEEDED(hr) {
37                     error!("error on command allocator creation: {:x}", hr);
38                 }
39 
40                 allocators.push(command_allocator);
41                 command_allocator
42             }
43         };
44 
45         // allocate command lists
46         let (command_list, hr) = self.device.create_graphics_command_list(
47             self.list_type,
48             command_allocator,
49             native::PipelineState::null(),
50             0,
51         );
52 
53         if !SUCCEEDED(hr) {
54             error!("error on command list creation: {:x}", hr);
55         }
56 
57         // Close command list as they are initiated as recording.
58         // But only one command list can be recording for each allocator
59         let _hr = command_list.close();
60 
61         (command_list, command_allocator)
62     }
63 
destroy(self)64     pub(crate) fn destroy(self) {
65         match self.allocator {
66             CommandPoolAllocator::Shared(ref allocator) => unsafe {
67                 allocator.destroy();
68             },
69             CommandPoolAllocator::Individual(ref allocators) => {
70                 for allocator in allocators.iter() {
71                     unsafe {
72                         allocator.destroy();
73                     }
74                 }
75             }
76         }
77     }
78 }
79 
80 unsafe impl Send for CommandPool {}
81 unsafe impl Sync for CommandPool {}
82 
83 impl pool::CommandPool<Backend> for CommandPool {
reset(&mut self, _release_resources: bool)84     unsafe fn reset(&mut self, _release_resources: bool) {
85         match self.allocator {
86             CommandPoolAllocator::Shared(ref allocator) => {
87                 allocator.Reset();
88             }
89             CommandPoolAllocator::Individual(ref mut allocators) => {
90                 for allocator in allocators.iter_mut() {
91                     allocator.Reset();
92                 }
93             }
94         }
95     }
96 
allocate_one(&mut self, level: command::Level) -> CommandBuffer97     unsafe fn allocate_one(&mut self, level: command::Level) -> CommandBuffer {
98         // TODO: Implement secondary buffers
99         assert_eq!(level, command::Level::Primary);
100         let (command_list, command_allocator) = self.create_command_list();
101         CommandBuffer::new(
102             command_list,
103             command_allocator,
104             self.shared.clone(),
105             self.create_flags,
106         )
107     }
108 
free<I>(&mut self, cbufs: I) where I: IntoIterator<Item = CommandBuffer>,109     unsafe fn free<I>(&mut self, cbufs: I)
110     where
111         I: IntoIterator<Item = CommandBuffer>,
112     {
113         for mut cbuf in cbufs {
114             cbuf.destroy();
115         }
116     }
117 }
118