Deferred error reporting for render passes

This commit is contained in:
Andy Leiserson 2025-06-06 15:14:42 -07:00
parent 460f073a67
commit fc26fbc561
3 changed files with 618 additions and 566 deletions

View File

@ -449,8 +449,11 @@ impl Global {
}
pub fn compute_pass_end(&self, pass: &mut ComputePass) -> Result<(), EncoderStateError> {
profiling::scope!("CommandEncoder::run_compute_pass");
let pass_scope = PassErrorScope::Pass;
profiling::scope!(
"CommandEncoder::run_compute_pass {}",
base.label.as_deref().unwrap_or("")
);
let cmd_buf = pass.parent.take().ok_or(EncoderStateError::Ended)?;
let mut cmd_buf_data = cmd_buf.data.lock();
@ -1169,18 +1172,17 @@ impl Global {
) -> Result<(), PassStateError> {
let scope = PassErrorScope::SetBindGroup;
let redundant = pass.current_bind_groups.set_and_check_redundant(
bind_group_id,
index,
&mut pass.base.dynamic_offsets,
offsets,
);
// This statement will return an error if the pass is ended.
// Its important the error check comes before the early-out for `redundant`.
// This statement will return an error if the pass is ended. It's
// important the error check comes before the early-out for
// `set_and_check_redundant`.
let base = pass_base!(pass, scope);
if redundant {
if pass.current_bind_groups.set_and_check_redundant(
bind_group_id,
index,
&mut base.dynamic_offsets,
offsets,
) {
return Ok(());
}
@ -1192,7 +1194,7 @@ impl Global {
bind_group = Some(pass_try!(
base,
scope,
hub.bind_groups.get(bind_group_id).get()
hub.bind_groups.get(bind_group_id).get(),
));
}

View File

@ -214,33 +214,6 @@ impl CommandEncoderStatus {
}
}
/// Unlocks the [`CommandBuffer`] and puts it back into the [`Self::Recording`] state.
///
/// This function is the unlocking counterpart to [`Self::lock_encoder`].
///
/// It is only valid to call this function if the encoder is in the [`Self::Locked`] state.
fn unlock_encoder(&mut self) -> Result<RecordingGuard<'_>, EncoderStateError> {
match mem::replace(self, Self::Transitioning) {
Self::Locked(inner) => {
*self = Self::Recording(inner);
Ok(RecordingGuard { inner: self })
}
st @ Self::Finished(_) => {
// Attempting to end a pass on a finished encoder raises a
// validation error but does not invalidate the encoder. This is
// related to https://github.com/gpuweb/gpuweb/issues/5207.
*self = st;
Err(EncoderStateError::Ended)
}
Self::Recording(_) => Err(self.invalidate(EncoderStateError::Unlocked)),
st @ Self::Error(_) => {
*self = st;
Err(EncoderStateError::Invalid)
}
Self::Transitioning => unreachable!(),
}
}
/// Unlocks the [`CommandBuffer`] and puts it back into the
/// [`Self::Recording`] state, then records commands using the supplied
/// closure.
@ -1007,10 +980,6 @@ pub enum CommandEncoderError {
#[error(transparent)]
Device(#[from] DeviceError),
#[error(transparent)]
InvalidColorAttachment(#[from] ColorAttachmentError),
#[error(transparent)]
InvalidAttachment(#[from] AttachmentError),
#[error(transparent)]
InvalidResource(#[from] InvalidResourceError),
#[error(transparent)]
DestroyedResource(#[from] DestroyedResourceError),
@ -1030,13 +999,8 @@ pub enum CommandEncoderError {
TransitionResources(#[from] TransitionResourcesError),
#[error(transparent)]
ComputePass(#[from] ComputePassError),
// TODO: The following are temporary and can be removed once error handling
// is updated for render passes. (They will report via RenderPassError
// instead.)
#[error(transparent)]
QueryUse(#[from] QueryUseError),
#[error(transparent)]
TimestampWrites(#[from] TimestampWritesError),
RenderPass(#[from] RenderPassError),
}
#[derive(Clone, Debug, Error)]

File diff suppressed because it is too large Load Diff