diff --git a/ffi/wgpu.h b/ffi/wgpu.h index 82864978c..c8a0cfce5 100644 --- a/ffi/wgpu.h +++ b/ffi/wgpu.h @@ -278,14 +278,14 @@ typedef void (*WGPUBufferMapReadCallback)(WGPUBufferMapAsyncStatus status, const typedef void (*WGPUBufferMapWriteCallback)(WGPUBufferMapAsyncStatus status, uint8_t *data, uint8_t *userdata); -typedef uint64_t WGPUId_ComputePass_Dummy; - -typedef WGPUId_ComputePass_Dummy WGPUComputePassId; - typedef uint64_t WGPUId_CommandBuffer_Dummy; typedef WGPUId_CommandBuffer_Dummy WGPUCommandBufferId; +typedef uint64_t WGPUId_ComputePass_Dummy; + +typedef WGPUId_ComputePass_Dummy WGPUComputePassId; + typedef WGPUCommandBufferId WGPUCommandEncoderId; typedef struct { @@ -686,6 +686,8 @@ void wgpu_buffer_map_write_async(WGPUBufferId buffer_id, void wgpu_buffer_unmap(WGPUBufferId buffer_id); +void wgpu_command_buffer_destroy(WGPUCommandBufferId command_buffer_id); + WGPUComputePassId wgpu_command_encoder_begin_compute_pass(WGPUCommandEncoderId encoder_id, const WGPUComputePassDescriptor *desc); @@ -714,6 +716,8 @@ void wgpu_command_encoder_copy_texture_to_texture(WGPUCommandEncoderId command_e const WGPUTextureCopyView *destination, WGPUExtent3d copy_size); +void wgpu_command_encoder_destroy(WGPUCommandEncoderId command_encoder_id); + WGPUCommandBufferId wgpu_command_encoder_finish(WGPUCommandEncoderId encoder_id, const WGPUCommandBufferDescriptor *desc); diff --git a/wgpu-core/src/command/allocator.rs b/wgpu-core/src/command/allocator.rs index 2c5c9eaa1..5a30d303a 100644 --- a/wgpu-core/src/command/allocator.rs +++ b/wgpu-core/src/command/allocator.rs @@ -140,6 +140,16 @@ impl CommandAllocator { pool.available.pop().unwrap() } + pub fn discard(&self, mut cmd_buf: CommandBuffer) { + cmd_buf.trackers.clear(); + self.inner + .lock() + .pools + .get_mut(&cmd_buf.recorded_thread_id) + .unwrap() + .recycle(cmd_buf); + } + pub fn after_submit(&self, mut cmd_buf: CommandBuffer, submit_index: SubmissionIndex) { cmd_buf.trackers.clear(); cmd_buf diff --git a/wgpu-core/src/device/life.rs b/wgpu-core/src/device/life.rs index 985a8e27e..4a731bd7e 100644 --- a/wgpu-core/src/device/life.rs +++ b/wgpu-core/src/device/life.rs @@ -45,7 +45,7 @@ impl SuspectedResources { self.bind_groups.clear(); } - fn extend(&mut self, other: &Self) { + pub fn extend(&mut self, other: &Self) { self.buffers.extend_from_slice(&other.buffers); self.textures.extend_from_slice(&other.textures); self.texture_views.extend_from_slice(&other.texture_views); diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index 586f381bc..d061f504a 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -1215,6 +1215,70 @@ impl> Global { hub.command_buffers .register_identity(id_in, comb, &mut token) } + + pub fn command_encoder_destroy( + &self, command_encoder_id: id::CommandEncoderId + ) { + let hub = B::hub(self); + let mut token = Token::root(); + + let comb = { + let (mut command_buffer_guard, _) = hub.command_buffers.write(&mut token); + command_buffer_guard.remove(command_encoder_id).unwrap() + }; + + let (mut device_guard, mut token) = hub.devices.write(&mut token); + let device = &mut device_guard[comb.device_id.value]; + device.temp_suspected.clear(); + // As the tracker is cleared/dropped, we need to consider all the resources + // that it references for destruction in the next GC pass. + { + let (bind_group_guard, mut token) = hub.bind_groups.read(&mut token); + let (buffer_guard, mut token) = hub.buffers.read(&mut token); + let (texture_guard, mut token) = hub.textures.read(&mut token); + let (texture_view_guard, mut token) = hub.texture_views.read(&mut token); + let (sampler_guard, _) = hub.samplers.read(&mut token); + + for id in comb.trackers.buffers.used() { + if buffer_guard[id].life_guard.ref_count.is_none() { + device.temp_suspected.buffers.push(id); + } + } + for id in comb.trackers.textures.used() { + if texture_guard[id].life_guard.ref_count.is_none() { + device.temp_suspected.textures.push(id); + } + } + for id in comb.trackers.views.used() { + if texture_view_guard[id].life_guard.ref_count.is_none() { + device.temp_suspected.texture_views.push(id); + } + } + for id in comb.trackers.bind_groups.used() { + if bind_group_guard[id].life_guard.ref_count.is_none() { + device.temp_suspected.bind_groups.push(id); + } + } + for id in comb.trackers.samplers.used() { + if sampler_guard[id].life_guard.ref_count.is_none() { + device.temp_suspected.samplers.push(id); + } + } + } + + device + .lock_life(&mut token) + .suspected_resources.extend(&device.temp_suspected); + device.com_allocator.discard(comb); + } +} + +impl> Global { + pub fn command_buffer_destroy( + &self, command_buffer_id: id::CommandBufferId + ) { + self.command_encoder_destroy::(command_buffer_id) + } } impl> Global { diff --git a/wgpu-native/src/device.rs b/wgpu-native/src/device.rs index ac4087456..81962131d 100644 --- a/wgpu-native/src/device.rs +++ b/wgpu-native/src/device.rs @@ -284,6 +284,16 @@ pub extern "C" fn wgpu_device_create_command_encoder( gfx_select!(device_id => GLOBAL.device_create_command_encoder(device_id, desc, PhantomData)) } +#[no_mangle] +pub extern "C" fn wgpu_command_encoder_destroy(command_encoder_id: id::CommandEncoderId) { + gfx_select!(command_encoder_id => GLOBAL.command_encoder_destroy(command_encoder_id)) +} + +#[no_mangle] +pub extern "C" fn wgpu_command_buffer_destroy(command_buffer_id: id::CommandBufferId) { + gfx_select!(command_buffer_id => GLOBAL.command_buffer_destroy(command_buffer_id)) +} + #[no_mangle] pub extern "C" fn wgpu_device_get_queue(device_id: id::DeviceId) -> id::QueueId { device_id