summaryrefslogtreecommitdiffstats
path: root/third_party/rust/wgpu-core/src/command/allocator.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/wgpu-core/src/command/allocator.rs')
-rw-r--r--third_party/rust/wgpu-core/src/command/allocator.rs67
1 files changed, 67 insertions, 0 deletions
diff --git a/third_party/rust/wgpu-core/src/command/allocator.rs b/third_party/rust/wgpu-core/src/command/allocator.rs
new file mode 100644
index 0000000000..e17fd08d76
--- /dev/null
+++ b/third_party/rust/wgpu-core/src/command/allocator.rs
@@ -0,0 +1,67 @@
+use crate::hal_api::HalApi;
+use crate::resource_log;
+use hal::Device as _;
+
+use crate::lock::{rank, Mutex};
+
+/// A pool of free [`wgpu_hal::CommandEncoder`]s, owned by a `Device`.
+///
+/// Each encoder in this list is in the "closed" state.
+///
+/// Since a raw [`CommandEncoder`][ce] is itself a pool for allocating
+/// raw [`CommandBuffer`][cb]s, this is a pool of pools.
+///
+/// [`wgpu_hal::CommandEncoder`]: hal::CommandEncoder
+/// [ce]: hal::CommandEncoder
+/// [cb]: hal::Api::CommandBuffer
+pub(crate) struct CommandAllocator<A: HalApi> {
+ free_encoders: Mutex<Vec<A::CommandEncoder>>,
+}
+
+impl<A: HalApi> CommandAllocator<A> {
+ pub(crate) fn new() -> Self {
+ Self {
+ free_encoders: Mutex::new(rank::COMMAND_ALLOCATOR_FREE_ENCODERS, Vec::new()),
+ }
+ }
+
+ /// Return a fresh [`wgpu_hal::CommandEncoder`] in the "closed" state.
+ ///
+ /// If we have free encoders in the pool, take one of those. Otherwise,
+ /// create a new one on `device`.
+ ///
+ /// [`wgpu_hal::CommandEncoder`]: hal::CommandEncoder
+ pub(crate) fn acquire_encoder(
+ &self,
+ device: &A::Device,
+ queue: &A::Queue,
+ ) -> Result<A::CommandEncoder, hal::DeviceError> {
+ let mut free_encoders = self.free_encoders.lock();
+ match free_encoders.pop() {
+ Some(encoder) => Ok(encoder),
+ None => unsafe {
+ let hal_desc = hal::CommandEncoderDescriptor { label: None, queue };
+ device.create_command_encoder(&hal_desc)
+ },
+ }
+ }
+
+ /// Add `encoder` back to the free pool.
+ pub(crate) fn release_encoder(&self, encoder: A::CommandEncoder) {
+ let mut free_encoders = self.free_encoders.lock();
+ free_encoders.push(encoder);
+ }
+
+ /// Free the pool of command encoders.
+ ///
+ /// This is only called when the `Device` is dropped.
+ pub(crate) fn dispose(&self, device: &A::Device) {
+ let mut free_encoders = self.free_encoders.lock();
+ resource_log!("CommandAllocator::dispose encoders {}", free_encoders.len());
+ for cmd_encoder in free_encoders.drain(..) {
+ unsafe {
+ device.destroy_command_encoder(cmd_encoder);
+ }
+ }
+ }
+}