diff --git a/wgpu-core/src/device/queue.rs b/wgpu-core/src/device/queue.rs index 8d4da748887..f823579d849 100644 --- a/wgpu-core/src/device/queue.rs +++ b/wgpu-core/src/device/queue.rs @@ -126,7 +126,7 @@ impl Queue { texture: &Arc, ) -> Result<(), DeviceError> { let snatch_guard = self.device.snatchable_lock.read(); - let mut submission = self + let submission = self .allocate_submission(snatch_guard) .map_err(|(_index, e)| e)?; let device = &self.device; @@ -143,6 +143,8 @@ impl Queue { let mut pending_writes = self.pending_writes.lock(); if needs_clear { + // After encoding the clear operation, we must not return without + // adding the texture to `pending_writes`. let encoder = pending_writes.activate(); let mut trackers = device.trackers.lock(); crate::command::clear_texture( @@ -184,6 +186,12 @@ impl Queue { }; if pending.is_empty() { + // This assert checks that we don't return here if we encoded a + // clear operation for the texture, which would be a problem since + // we haven't done anything yet to ensure it stays alive. If we + // cleared the texture, then we must have produced a barrier to put + // it in PRESENT state, so `pending` will not be empty. + debug_assert!(!needs_clear); return Ok(()); } @@ -200,21 +208,20 @@ impl Queue { let encoder = pending_writes.activate(); // SAFETY: // - The encoder is in the recording state after `activate()` - // - The texture is kept alive by the Arc from `acquired_texture` + // - The texture is kept alive by adding it to `PendingWrites` below unsafe { encoder.transition_textures(&barriers); } } - // Keep the texture alive in the submission so its clear_view isn't - // destroyed before the GPU finishes the submitted commands. + // Add the texture to `PendingWrites`. This will cause `submit()` to: + // - Flush any pending writes to the texture. + // - Include the texture in `surface_textures` for the submission. + // - Keep the texture alive so the texture and its clear_view aren't + // destroyed before the GPU finishes the `clear_texture` operation + // encoded above. pending_writes.insert_texture(texture); - // Flush pending writes through the standard submission path. - submission - .surface_textures - .insert(Arc::as_ptr(texture), texture.clone()); - submission.submit(pending_writes)?; Ok(()) @@ -575,7 +582,7 @@ pub(crate) struct PendingSubmission<'a> { // Surface textures referenced by command buffers in this submission. These need to be // passed to the HAL `submit` call. Deduplicated using a hashmap to avoid vulkan // deadlocking from the same surface texture being submitted multiple times. - pub surface_textures: FastHashMap<*const Texture, Arc>, + surface_textures: FastHashMap<*const Texture, Arc>, pub index: SubmissionIndex, } @@ -1545,8 +1552,8 @@ impl Queue { /// The caller passes in the already-acquired [`SnatchGuard`]. This function acquires /// the fence lock and the command index lock. /// - /// The caller should update the [`PendingSubmission`] members `executions` and - /// `surface_textures` with details of the submission. + /// The caller should update [`PendingSubmission::executions`] with details of the + /// submission. /// /// To finalize and submit the submission, call [`PendingSubmission::submit`] (which is /// a convenience wrapper around [`Queue::submit_pending_submission`]).