From 60487f5833664a27d9cac5e591db206818d6ede7 Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Thu, 8 Feb 2024 19:36:40 -0800 Subject: [PATCH] Document the `wgpu_hal::CommandEncoder` trait. --- wgpu-hal/src/lib.rs | 95 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 87 insertions(+), 8 deletions(-) diff --git a/wgpu-hal/src/lib.rs b/wgpu-hal/src/lib.rs index 5d8c6ddda..75e8a827b 100644 --- a/wgpu-hal/src/lib.rs +++ b/wgpu-hal/src/lib.rs @@ -329,6 +329,9 @@ pub trait Device: WasmNotSendSync { unsafe fn create_sampler(&self, desc: &SamplerDescriptor) -> Result; unsafe fn destroy_sampler(&self, sampler: A::Sampler); + /// Create a fresh [`CommandEncoder`]. + /// + /// The new `CommandEncoder` is in the "closed" state. unsafe fn create_command_encoder( &self, desc: &CommandEncoderDescriptor, @@ -429,19 +432,95 @@ pub trait Queue: WasmNotSendSync { unsafe fn get_timestamp_period(&self) -> f32; } -/// Encoder for commands in command buffers. -/// Serves as a parent for all the encoded command buffers. -/// Works in bursts of action: one or more command buffers are recorded, -/// then submitted to a queue, and then it needs to be `reset_all()`. +/// Encoder and allocation pool for `CommandBuffer`. +/// +/// The life cycle of a `CommandBuffer` is as follows: +/// +/// - Call [`Device::create_command_encoder`] to create a new +/// `CommandEncoder`, in the "closed" state. +/// +/// - Call `begin_encoding` on a closed `CommandEncoder` to begin +/// recording commands. This puts the `CommandEncoder` in the +/// "recording" state. +/// +/// - Call methods like `copy_buffer_to_buffer`, `begin_render_pass`, +/// etc. on a "recording" `CommandEncoder` to add commands to the +/// list. +/// +/// - Call `end_encoding` on a recording `CommandEncoder` to close the +/// encoder and construct a fresh `CommandBuffer` consisting of the +/// list of commands recorded up to that point. +/// +/// - Call `discard_encoding` on a recording `CommandEncoder` to drop +/// the commands recorded thus far and close the encoder. +/// +/// - Call `reset_all` on a closed `CommandEncoder`, passing all the +/// live `CommandBuffers` built from it. All the `CommandBuffer`s +/// are destroyed, and their resources are freed. +/// +/// # Safety +/// +/// - The `CommandEncoder` must be in the states described above to +/// make the given calls. +/// +/// - A `CommandBuffer` that has been submitted for execution on the +/// GPU must live until its execution is complete. +/// +/// - A `CommandBuffer` must not outlive the `CommandEncoder` that +/// built it. +/// +/// - A `CommandEncoder` must not outlive its `Device`. pub trait CommandEncoder: WasmNotSendSync + fmt::Debug { /// Begin encoding a new command buffer. + /// + /// This puts this `CommandEncoder` in the "recording" state. + /// + /// # Safety + /// + /// This `CommandEncoder` must be in the "closed" state. unsafe fn begin_encoding(&mut self, label: Label) -> Result<(), DeviceError>; - /// Discard currently recorded list, if any. + + /// Discard the command list under construction, if any. + /// + /// This puts this `CommandEncoder` in the "closed" state. + /// + /// # Safety + /// + /// This `CommandEncoder` must be in the "recording" state. unsafe fn discard_encoding(&mut self); + + /// Return a fresh [`CommandBuffer`] holding the recorded commands. + /// + /// The returned [`CommandBuffer`] holds all the commands recorded + /// on this `CommandEncoder` since the last call to + /// [`begin_encoding`]. + /// + /// This puts this `CommandEncoder` in the "closed" state. + /// + /// # Safety + /// + /// This `CommandEncoder` must be in the "recording" state. + /// + /// The returned [`CommandBuffer`] must not outlive this + /// `CommandEncoder`. Implementations are allowed to build + /// `CommandBuffer`s that depend on storage owned by this + /// `CommandEncoder`. + /// + /// [`CommandBuffer`]: Api::CommandBuffer + /// [`begin_encoding`]: CommandEncoder::begin_encoding unsafe fn end_encoding(&mut self) -> Result; - /// Reclaims all resources that are allocated for this encoder. - /// Must get all of the produced command buffers back, - /// and they must not be used by GPU at this moment. + + /// Reclaim all resources belonging to this `CommandEncoder`. + /// + /// # Safety + /// + /// This `CommandEncoder` must be in the "closed" state. + /// + /// The `command_buffers` iterator must produce all the live + /// [`CommandBuffer`]s built using this `CommandEncoder` --- that + /// is, every extant `CommandBuffer` returned from `end_encoding`. + /// + /// [`CommandBuffer`]: Api::CommandBuffer unsafe fn reset_all(&mut self, command_buffers: I) where I: Iterator;