diff --git a/wgpu/src/backend/direct.rs b/wgpu/src/backend/direct.rs index 5cc32891b1..75da20ff44 100644 --- a/wgpu/src/backend/direct.rs +++ b/wgpu/src/backend/direct.rs @@ -605,6 +605,7 @@ pub(crate) struct Texture { pub(crate) struct CommandEncoder { id: wgc::id::CommandEncoderId, error_sink: ErrorSink, + open: bool, } impl crate::Context for Context { @@ -1195,6 +1196,7 @@ impl crate::Context for Context { CommandEncoder { id, error_sink: Arc::clone(&device.error_sink), + open: true, } } @@ -1450,6 +1452,12 @@ impl crate::Context for Context { let global = &self.0; wgc::gfx_select!(*shader_module => global.shader_module_drop(*shader_module)) } + fn command_encoder_drop(&self, command_encoder: &Self::CommandEncoderId) { + if command_encoder.open { + let global = &self.0; + wgc::gfx_select!(command_encoder.id => global.command_encoder_drop(command_encoder.id)) + } + } fn command_buffer_drop(&self, command_buffer: &Self::CommandBufferId) { let global = &self.0; wgc::gfx_select!(*command_buffer => global.command_buffer_drop(*command_buffer)) @@ -1717,8 +1725,9 @@ impl crate::Context for Context { } } - fn command_encoder_finish(&self, encoder: &Self::CommandEncoderId) -> Self::CommandBufferId { + fn command_encoder_finish(&self, mut encoder: Self::CommandEncoderId) -> Self::CommandBufferId { let descriptor = wgt::CommandBufferDescriptor::default(); + encoder.open = false; // prevent the drop let global = &self.0; let (id, error) = wgc::gfx_select!(encoder.id => global.command_encoder_finish(encoder.id, &descriptor)); diff --git a/wgpu/src/backend/web.rs b/wgpu/src/backend/web.rs index 026ab094c5..3109d343c5 100644 --- a/wgpu/src/backend/web.rs +++ b/wgpu/src/backend/web.rs @@ -1670,6 +1670,10 @@ impl crate::Context for Context { // Dropped automatically } + fn command_encoder_drop(&self, _command_encoder: &Self::CommandEncoderId) { + // Dropped automatically + } + fn command_buffer_drop(&self, _command_buffer: &Self::CommandBufferId) { // Dropped automatically } @@ -1868,7 +1872,7 @@ impl crate::Context for Context { pass.0.end_pass(); } - fn command_encoder_finish(&self, encoder: &Self::CommandEncoderId) -> Self::CommandBufferId { + fn command_encoder_finish(&self, encoder: Self::CommandEncoderId) -> Self::CommandBufferId { Sendable(match encoder.label() { Some(ref label) => { let mut mapped_desc = web_sys::GpuCommandBufferDescriptor::new(); diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index 7804c91adc..7c29a87143 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -328,6 +328,7 @@ trait Context: Debug + Send + Sized + Sync { fn bind_group_layout_drop(&self, bind_group_layout: &Self::BindGroupLayoutId); fn pipeline_layout_drop(&self, pipeline_layout: &Self::PipelineLayoutId); fn shader_module_drop(&self, shader_module: &Self::ShaderModuleId); + fn command_encoder_drop(&self, command_encoder: &Self::CommandEncoderId); fn command_buffer_drop(&self, command_buffer: &Self::CommandBufferId); fn render_bundle_drop(&self, render_bundle: &Self::RenderBundleId); fn compute_pipeline_drop(&self, pipeline: &Self::ComputePipelineId); @@ -395,7 +396,7 @@ trait Context: Debug + Send + Sized + Sync { encoder: &Self::CommandEncoderId, pass: &mut Self::RenderPassId, ); - fn command_encoder_finish(&self, encoder: &Self::CommandEncoderId) -> Self::CommandBufferId; + fn command_encoder_finish(&self, encoder: Self::CommandEncoderId) -> Self::CommandBufferId; fn command_encoder_insert_debug_marker(&self, encoder: &Self::CommandEncoderId, label: &str); fn command_encoder_push_debug_group(&self, encoder: &Self::CommandEncoderId, label: &str); @@ -844,12 +845,22 @@ impl Drop for CommandBuffer { #[derive(Debug)] pub struct CommandEncoder { context: Arc, - id: ::CommandEncoderId, + id: Option<::CommandEncoderId>, /// This type should be !Send !Sync, because it represents an allocation on this thread's /// command buffer. _p: PhantomData<*const u8>, } +impl Drop for CommandEncoder { + fn drop(&mut self) { + if !thread::panicking() { + if let Some(id) = self.id.take() { + self.context.command_encoder_drop(&id); + } + } + } +} + /// In-progress recording of a render pass. #[derive(Debug)] pub struct RenderPass<'a> { @@ -1514,7 +1525,11 @@ impl Device { pub fn create_command_encoder(&self, desc: &CommandEncoderDescriptor) -> CommandEncoder { CommandEncoder { context: Arc::clone(&self.context), - id: Context::device_create_command_encoder(&*self.context, &self.id, desc), + id: Some(Context::device_create_command_encoder( + &*self.context, + &self.id, + desc, + )), _p: Default::default(), } } @@ -1939,10 +1954,13 @@ impl Drop for TextureView { impl CommandEncoder { /// Finishes recording and returns a [`CommandBuffer`] that can be submitted for execution. - pub fn finish(self) -> CommandBuffer { + pub fn finish(mut self) -> CommandBuffer { CommandBuffer { context: Arc::clone(&self.context), - id: Some(Context::command_encoder_finish(&*self.context, &self.id)), + id: Some(Context::command_encoder_finish( + &*self.context, + self.id.take().unwrap(), + )), } } @@ -1953,8 +1971,9 @@ impl CommandEncoder { &'a mut self, desc: &RenderPassDescriptor<'a, '_>, ) -> RenderPass<'a> { + let id = self.id.as_ref().unwrap(); RenderPass { - id: Context::command_encoder_begin_render_pass(&*self.context, &self.id, desc), + id: Context::command_encoder_begin_render_pass(&*self.context, id, desc), parent: self, } } @@ -1963,8 +1982,9 @@ impl CommandEncoder { /// /// This function returns a [`ComputePass`] object which records a single compute pass. pub fn begin_compute_pass(&mut self, desc: &ComputePassDescriptor) -> ComputePass { + let id = self.id.as_ref().unwrap(); ComputePass { - id: Context::command_encoder_begin_compute_pass(&*self.context, &self.id, desc), + id: Context::command_encoder_begin_compute_pass(&*self.context, id, desc), parent: self, } } @@ -1985,7 +2005,7 @@ impl CommandEncoder { ) { Context::command_encoder_copy_buffer_to_buffer( &*self.context, - &self.id, + self.id.as_ref().unwrap(), &source.id, source_offset, &destination.id, @@ -2009,7 +2029,7 @@ impl CommandEncoder { ) { Context::command_encoder_copy_buffer_to_texture( &*self.context, - &self.id, + self.id.as_ref().unwrap(), source, destination, copy_size, @@ -2031,7 +2051,7 @@ impl CommandEncoder { ) { Context::command_encoder_copy_texture_to_buffer( &*self.context, - &self.id, + self.id.as_ref().unwrap(), source, destination, copy_size, @@ -2053,7 +2073,7 @@ impl CommandEncoder { ) { Context::command_encoder_copy_texture_to_texture( &*self.context, - &self.id, + self.id.as_ref().unwrap(), source, destination, copy_size, @@ -2062,17 +2082,20 @@ impl CommandEncoder { /// Inserts debug marker. pub fn insert_debug_marker(&mut self, label: &str) { - Context::command_encoder_insert_debug_marker(&*self.context, &self.id, label); + let id = self.id.as_ref().unwrap(); + Context::command_encoder_insert_debug_marker(&*self.context, id, label); } /// Start record commands and group it into debug marker group. pub fn push_debug_group(&mut self, label: &str) { - Context::command_encoder_push_debug_group(&*self.context, &self.id, label); + let id = self.id.as_ref().unwrap(); + Context::command_encoder_push_debug_group(&*self.context, id, label); } /// Stops command recording and creates debug group. pub fn pop_debug_group(&mut self) { - Context::command_encoder_pop_debug_group(&*self.context, &self.id); + let id = self.id.as_ref().unwrap(); + Context::command_encoder_pop_debug_group(&*self.context, id); } } @@ -2088,7 +2111,7 @@ impl CommandEncoder { pub fn write_timestamp(&mut self, query_set: &QuerySet, query_index: u32) { Context::command_encoder_write_timestamp( &*self.context, - &self.id, + self.id.as_ref().unwrap(), &query_set.id, query_index, ) @@ -2109,7 +2132,7 @@ impl CommandEncoder { ) { Context::command_encoder_resolve_query_set( &*self.context, - &self.id, + self.id.as_ref().unwrap(), &query_set.id, query_range.start, query_range.end - query_range.start, @@ -2515,9 +2538,10 @@ impl<'a> RenderPass<'a> { impl<'a> Drop for RenderPass<'a> { fn drop(&mut self) { if !thread::panicking() { + let parent_id = self.parent.id.as_ref().unwrap(); self.parent .context - .command_encoder_end_render_pass(&self.parent.id, &mut self.id); + .command_encoder_end_render_pass(parent_id, &mut self.id); } } } @@ -2620,9 +2644,10 @@ impl<'a> ComputePass<'a> { impl<'a> Drop for ComputePass<'a> { fn drop(&mut self) { if !thread::panicking() { + let parent_id = self.parent.id.as_ref().unwrap(); self.parent .context - .command_encoder_end_compute_pass(&self.parent.id, &mut self.id); + .command_encoder_end_compute_pass(parent_id, &mut self.id); } } }