wgpu_core/command/
allocator.rs

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