1use alloc::{boxed::Box, vec::Vec};
23use crate::lock::{rank, Mutex};
45/// A pool of free [`wgpu_hal::CommandEncoder`]s, owned by a `Device`.
6///
7/// Each encoder in this list is in the "closed" state.
8///
9/// Since a raw [`CommandEncoder`][ce] is itself a pool for allocating
10/// raw [`CommandBuffer`][cb]s, this is a pool of pools.
11///
12/// [`wgpu_hal::CommandEncoder`]: hal::CommandEncoder
13/// [ce]: hal::CommandEncoder
14/// [cb]: hal::Api::CommandBuffer
15pub(crate) struct CommandAllocator {
16 free_encoders: Mutex<Vec<Box<dyn hal::DynCommandEncoder>>>,
17}
1819impl CommandAllocator {
20pub(crate) fn new() -> Self {
21Self {
22 free_encoders: Mutex::new(rank::COMMAND_ALLOCATOR_FREE_ENCODERS, Vec::new()),
23 }
24 }
2526/// Return a fresh [`wgpu_hal::CommandEncoder`] in the "closed" state.
27 ///
28 /// If we have free encoders in the pool, take one of those. Otherwise,
29 /// create a new one on `device`.
30 ///
31 /// [`wgpu_hal::CommandEncoder`]: hal::CommandEncoder
32pub(crate) fn acquire_encoder(
33&self,
34 device: &dyn hal::DynDevice,
35 queue: &dyn hal::DynQueue,
36 ) -> Result<Box<dyn hal::DynCommandEncoder>, hal::DeviceError> {
37let mut free_encoders = self.free_encoders.lock();
38match free_encoders.pop() {
39Some(encoder) => Ok(encoder),
40None => unsafe {
41let hal_desc = hal::CommandEncoderDescriptor { label: None, queue };
42 device.create_command_encoder(&hal_desc)
43 },
44 }
45 }
4647/// Add `encoder` back to the free pool.
48pub(crate) fn release_encoder(&self, encoder: Box<dyn hal::DynCommandEncoder>) {
49let mut free_encoders = self.free_encoders.lock();
50 free_encoders.push(encoder);
51 }
52}