From b9781ee6e2c194be97fbac74374207c81134abbf Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Mon, 15 Apr 2024 11:43:19 -0700 Subject: [PATCH] [core] Move `CommandAllocator` into its own module. No intended change in behavior. --- wgpu-core/src/command/allocator.rs | 62 ++++++++++++++++++++++++++++++ wgpu-core/src/command/mod.rs | 2 + wgpu-core/src/device/life.rs | 2 +- wgpu-core/src/device/mod.rs | 54 -------------------------- wgpu-core/src/device/queue.rs | 4 +- wgpu-core/src/device/resource.rs | 10 ++--- 6 files changed, 71 insertions(+), 63 deletions(-) create mode 100644 wgpu-core/src/command/allocator.rs diff --git a/wgpu-core/src/command/allocator.rs b/wgpu-core/src/command/allocator.rs new file mode 100644 index 000000000..ddbb16c15 --- /dev/null +++ b/wgpu-core/src/command/allocator.rs @@ -0,0 +1,62 @@ +use crate::hal_api::HalApi; +use crate::resource_log; +use hal::Device as _; + +/// 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. +/// +/// [ce]: wgpu_hal::CommandEncoder +/// [cb]: wgpu_hal::Api::CommandBuffer +pub(crate) struct CommandAllocator { + free_encoders: Vec, +} + +impl CommandAllocator { + pub(crate) fn new() -> Self { + Self { + 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`. + pub(crate) fn acquire_encoder( + &mut self, + device: &A::Device, + queue: &A::Queue, + ) -> Result { + match self.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(&mut self, encoder: A::CommandEncoder) { + self.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) { + resource_log!( + "CommandAllocator::dispose encoders {}", + self.free_encoders.len() + ); + for cmd_encoder in self.free_encoders { + unsafe { + device.destroy_command_encoder(cmd_encoder); + } + } + } +} diff --git a/wgpu-core/src/command/mod.rs b/wgpu-core/src/command/mod.rs index e3f5e3a4d..17ddef697 100644 --- a/wgpu-core/src/command/mod.rs +++ b/wgpu-core/src/command/mod.rs @@ -1,3 +1,4 @@ +mod allocator; mod bind; mod bundle; mod clear; @@ -15,6 +16,7 @@ pub(crate) use self::clear::clear_texture; pub use self::{ bundle::*, clear::ClearError, compute::*, draw::*, query::*, render::*, transfer::*, }; +pub(crate) use allocator::CommandAllocator; use self::memory_init::CommandBufferTextureMemoryActions; diff --git a/wgpu-core/src/device/life.rs b/wgpu-core/src/device/life.rs index e63147961..ca79a17c2 100644 --- a/wgpu-core/src/device/life.rs +++ b/wgpu-core/src/device/life.rs @@ -361,7 +361,7 @@ impl LifetimeTracker { pub fn triage_submissions( &mut self, last_done: SubmissionIndex, - command_allocator: &mut super::CommandAllocator, + command_allocator: &mut crate::command::CommandAllocator, ) -> SmallVec<[SubmittedWorkDoneClosure; 1]> { profiling::scope!("triage_submissions"); diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index 951ddcc90..e9da11b7a 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -4,7 +4,6 @@ use crate::{ hub::Hub, id::{BindGroupLayoutId, PipelineLayoutId}, resource::{Buffer, BufferAccessError, BufferAccessResult, BufferMapOperation}, - resource_log, snatch::SnatchGuard, Label, DOWNLEVEL_ERROR_MESSAGE, }; @@ -377,59 +376,6 @@ fn map_buffer( Ok(mapping.ptr) } -/// 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. -/// -/// [ce]: wgpu_hal::CommandEncoder -/// [cb]: wgpu_hal::Api::CommandBuffer -pub(crate) struct CommandAllocator { - free_encoders: Vec, -} - -impl CommandAllocator { - /// 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`. - fn acquire_encoder( - &mut self, - device: &A::Device, - queue: &A::Queue, - ) -> Result { - match self.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. - fn release_encoder(&mut self, encoder: A::CommandEncoder) { - self.free_encoders.push(encoder); - } - - /// Free the pool of command encoders. - /// - /// This is only called when the `Device` is dropped. - fn dispose(self, device: &A::Device) { - resource_log!( - "CommandAllocator::dispose encoders {}", - self.free_encoders.len() - ); - for cmd_encoder in self.free_encoders { - unsafe { - device.destroy_command_encoder(cmd_encoder); - } - } - } -} - #[derive(Clone, Debug, Error)] #[error("Device is invalid")] pub struct InvalidDevice; diff --git a/wgpu-core/src/device/queue.rs b/wgpu-core/src/device/queue.rs index e663a3eff..972fbcb95 100644 --- a/wgpu-core/src/device/queue.rs +++ b/wgpu-core/src/device/queue.rs @@ -4,7 +4,7 @@ use crate::{ api_log, command::{ extract_texture_selector, validate_linear_texture_data, validate_texture_copy_range, - ClearError, CommandBuffer, CopySide, ImageCopyTexture, TransferError, + ClearError, CommandAllocator, CommandBuffer, CopySide, ImageCopyTexture, TransferError, }, conv, device::{life::ResourceMaps, DeviceError, WaitIdleError}, @@ -258,7 +258,7 @@ impl PendingWrites { #[must_use] fn post_submit( &mut self, - command_allocator: &mut super::CommandAllocator, + command_allocator: &mut CommandAllocator, device: &A::Device, queue: &A::Queue, ) -> Option> { diff --git a/wgpu-core/src/device/resource.rs b/wgpu-core/src/device/resource.rs index cce6d6741..9cf08a913 100644 --- a/wgpu-core/src/device/resource.rs +++ b/wgpu-core/src/device/resource.rs @@ -7,8 +7,8 @@ use crate::{ bgl, life::{LifetimeTracker, WaitIdleError}, queue::PendingWrites, - AttachmentData, CommandAllocator, DeviceLostInvocation, MissingDownlevelFlags, - MissingFeatures, RenderPassContext, CLEANUP_WAIT_MS, + AttachmentData, DeviceLostInvocation, MissingDownlevelFlags, MissingFeatures, + RenderPassContext, CLEANUP_WAIT_MS, }, hal_api::HalApi, hal_label, @@ -97,7 +97,7 @@ pub struct Device { pub(crate) zero_buffer: Option, pub(crate) info: ResourceInfo>, - pub(crate) command_allocator: Mutex>>, + pub(crate) command_allocator: Mutex>>, //Note: The submission index here corresponds to the last submission that is done. pub(crate) active_submission_index: AtomicU64, //SubmissionIndex, // NOTE: if both are needed, the `snatchable_lock` must be consistently acquired before the @@ -223,9 +223,7 @@ impl Device { let fence = unsafe { raw_device.create_fence() }.map_err(|_| CreateDeviceError::OutOfMemory)?; - let mut com_alloc = CommandAllocator { - free_encoders: Vec::new(), - }; + let mut com_alloc = command::CommandAllocator::new(); let pending_encoder = com_alloc .acquire_encoder(&raw_device, raw_queue) .map_err(|_| CreateDeviceError::OutOfMemory)?;