Defer destroyed resource errors until cmdbuf submission

This commit is contained in:
Andy Leiserson 2025-06-12 14:56:21 -07:00
parent 41badaedfb
commit 7722c341e0
2 changed files with 38 additions and 6 deletions

View File

@ -5,7 +5,17 @@ webgpu:api,operation,compute,basic:memcpy:*
//FAIL: webgpu:api,operation,compute,basic:large_dispatch:*
webgpu:api,operation,compute_pipeline,overrides:*
webgpu:api,operation,device,lost:*
webgpu:api,validation,encoding,cmds,clearBuffer:out_of_bounds,*
webgpu:api,validation,encoding,cmds,clearBuffer:buffer_state:bufferState="valid"
//FAIL: webgpu:api,validation,encoding,cmds,clearBuffer:buffer_state:bufferState="invalid"
// https://github.com/gfx-rs/wgpu/issues/7796 (Mac only)
webgpu:api,validation,encoding,cmds,clearBuffer:buffer_state:bufferState="destroyed"
webgpu:api,validation,encoding,cmds,clearBuffer:buffer,device_mismatch:*
webgpu:api,validation,encoding,cmds,clearBuffer:default_args:*
webgpu:api,validation,encoding,cmds,clearBuffer:buffer_usage:*
webgpu:api,validation,encoding,cmds,clearBuffer:size_alignment:*
webgpu:api,validation,encoding,cmds,clearBuffer:offset_alignment:*
webgpu:api,validation,encoding,cmds,clearBuffer:overflow:*
webgpu:api,validation,encoding,cmds,clearBuffer:out_of_bounds:*
webgpu:api,validation,encoding,cmds,compute_pass:set_pipeline:*
webgpu:api,validation,encoding,cmds,compute_pass:dispatch_sizes:*
webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_with_invalid_or_destroyed_texture:*

View File

@ -803,15 +803,16 @@ impl CommandBuffer {
}
impl CommandBuffer {
pub fn take_finished<'a>(&'a self) -> Result<CommandBufferMutable, InvalidResourceError> {
pub fn take_finished(&self) -> Result<CommandBufferMutable, CommandEncoderError> {
use CommandEncoderStatus as St;
match mem::replace(
&mut *self.data.lock(),
CommandEncoderStatus::Error(EncoderStateError::Submitted.into()),
) {
St::Finished(command_buffer_mutable) => Ok(command_buffer_mutable),
St::Recording(_) | St::Locked(_) | St::Error(_) => {
Err(InvalidResourceError(self.error_ident()))
St::Error(err) => Err(err),
St::Recording(_) | St::Locked(_) => {
Err(InvalidResourceError(self.error_ident()).into())
}
St::Transitioning => unreachable!(),
}
@ -1003,6 +1004,25 @@ pub enum CommandEncoderError {
RenderPass(#[from] RenderPassError),
}
impl CommandEncoderError {
fn is_destroyed_error(&self) -> bool {
matches!(
self,
Self::DestroyedResource(_)
| Self::Clear(ClearError::DestroyedResource(_))
| Self::Query(QueryError::DestroyedResource(_))
| Self::ComputePass(ComputePassError {
inner: ComputePassErrorInner::DestroyedResource(_),
..
})
| Self::RenderPass(RenderPassError {
inner: RenderPassErrorInner::DestroyedResource(_),
..
})
)
}
}
#[derive(Clone, Debug, Error)]
#[non_exhaustive]
pub enum TimestampWritesError {
@ -1026,9 +1046,11 @@ impl Global {
let cmd_buf = hub.command_buffers.get(encoder_id.into_command_buffer_id());
// Errors related to destroyed resources are not reported until the
// command buffer is submitted.
let error = match cmd_buf.data.lock().finish() {
Ok(_) => None,
Err(e) => Some(e),
Err(e) if !e.is_destroyed_error() => Some(e),
_ => None,
};
(encoder_id.into_command_buffer_id(), error)