Fix trying to use a renderpass inside a compute pass (#3828)

* Fix trying to use a renderpass inside a compute pass

* Fix pipeline statistics test on mac

* Changelog
This commit is contained in:
Connor Fitzgerald 2023-06-05 09:05:59 -04:00 committed by GitHub
parent 3db51e74bd
commit 1d2a667b71
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 58 additions and 36 deletions

View File

@ -62,6 +62,10 @@ Bottom level categories:
- Fix order of arguments to glPolygonOffset by @komadori in [#3783](https://github.com/gfx-rs/wgpu/pull/3783).
#### Metal
- Fix renderpasses being used inside of renderpasses. By @cwfitzgerald in [#3828](https://github.com/gfx-rs/wgpu/pull/3828)
#### General
- Fix Multiview to disable validation of TextureViewDimension and ArrayLayerCount. By @MalekiRe in [#3779](https://github.com/gfx-rs/wgpu/pull/3779#issue-1713269437).

View File

@ -1,5 +1,5 @@
(
features: 0x0000_0000_0000_0100, // PIPELINE_STATISTICS_QUERY
features: 0x0000_0001_0000_0000, // PIPELINE_STATISTICS_QUERY
expectations: [
(
name: "Queried number of compute invocations is correct",

View File

@ -348,7 +348,12 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let cmd_buf: &mut CommandBuffer<A> =
CommandBuffer::get_encoder_mut(&mut *cmd_buf_guard, encoder_id)
.map_pass_err(init_scope)?;
// will be reset to true if recording is done without errors
// We automatically keep extending command buffers over time, and because
// we want to insert a command buffer _before_ what we're about to record,
// we need to make sure to close the previous one.
cmd_buf.encoder.close();
// We will reset this to `Recording` if we succeed, acts as a fail-safe.
cmd_buf.status = CommandEncoderStatus::Error;
let raw = cmd_buf.encoder.open();
@ -397,6 +402,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
raw.begin_compute_pass(&hal_desc);
}
let mut intermediate_trackers = Tracker::<A>::new();
// Immediate texture inits required because of prior discards. Need to
// be inserted before texture reads.
let mut pending_discard_init_fixups = SurfacesInDiscardState::new();
@ -584,19 +591,11 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
pipeline: state.pipeline,
};
fixup_discarded_surfaces(
pending_discard_init_fixups.drain(..),
raw,
&texture_guard,
&mut cmd_buf.trackers.textures,
device,
);
state.is_ready().map_pass_err(scope)?;
state
.flush_states(
raw,
&mut cmd_buf.trackers,
&mut intermediate_trackers,
&*bind_group_guard,
&*buffer_guard,
&*texture_guard,
@ -672,7 +671,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
state
.flush_states(
raw,
&mut cmd_buf.trackers,
&mut intermediate_trackers,
&*bind_group_guard,
&*buffer_guard,
&*texture_guard,
@ -768,20 +767,33 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
unsafe {
raw.end_compute_pass();
}
// We've successfully recorded the compute pass, bring the
// command buffer out of the error state.
cmd_buf.status = CommandEncoderStatus::Recording;
// There can be entries left in pending_discard_init_fixups if a bind
// group was set, but not used (i.e. no Dispatch occurred)
// Stop the current command buffer.
cmd_buf.encoder.close();
// Create a new command buffer, which we will insert _before_ the body of the compute pass.
//
// However, we already altered the discard/init_action state on this
// cmd_buf, so we need to apply the promised changes.
// Use that buffer to insert barriers and clear discarded images.
let transit = cmd_buf.encoder.open();
fixup_discarded_surfaces(
pending_discard_init_fixups.into_iter(),
raw,
transit,
&texture_guard,
&mut cmd_buf.trackers.textures,
device,
);
CommandBuffer::insert_barriers_from_tracker(
transit,
&mut cmd_buf.trackers,
&intermediate_trackers,
&*buffer_guard,
&*texture_guard,
);
// Close the command buffer, and swap it with the previous.
cmd_buf.encoder.close_and_swap();
Ok(())
}

View File

@ -55,6 +55,15 @@ struct CommandEncoder<A: hal::Api> {
//TODO: handle errors better
impl<A: hal::Api> CommandEncoder<A> {
/// Closes the live encoder
fn close_and_swap(&mut self) {
if self.is_open {
self.is_open = false;
let new = unsafe { self.raw.end_encoding().unwrap() };
self.list.insert(self.list.len() - 1, new);
}
}
fn close(&mut self) {
if self.is_open {
self.is_open = false;

View File

@ -1227,9 +1227,12 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let cmd_buf: &mut CommandBuffer<A> =
CommandBuffer::get_encoder_mut(&mut *cmb_guard, encoder_id)
.map_pass_err(init_scope)?;
// close everything while the new command encoder is filled
// We automatically keep extending command buffers over time, and because
// we want to insert a command buffer _before_ what we're about to record,
// we need to make sure to close the previous one.
cmd_buf.encoder.close();
// will be reset to true if recording is done without errors
// We will reset this to `Recording` if we succeed, acts as a fail-safe.
cmd_buf.status = CommandEncoderStatus::Error;
#[cfg(feature = "trace")]
@ -2179,15 +2182,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
);
}
// Before we finish the auxiliary encoder, let's
// get our pass back and place it after.
//Note: we could just hold onto this raw pass while recording the
// auxiliary encoder, but then handling errors and cleaning up
// would be more complicated, so we re-use `open()`/`close()`.
let pass_raw = cmd_buf.encoder.list.pop().unwrap();
cmd_buf.encoder.close();
cmd_buf.encoder.list.push(pass_raw);
cmd_buf.status = CommandEncoderStatus::Recording;
cmd_buf.encoder.close_and_swap();
Ok(())
}

View File

@ -127,8 +127,8 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
unsafe fn end_encoding(&mut self) -> Result<super::CommandBuffer, crate::DeviceError> {
self.leave_blit();
assert!(self.state.render.is_none());
assert!(self.state.compute.is_none());
debug_assert!(self.state.render.is_none());
debug_assert!(self.state.compute.is_none());
Ok(super::CommandBuffer {
raw: self.raw_cmd_buf.take().unwrap(),
})
@ -355,6 +355,10 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
self.begin_pass();
self.state.index = None;
assert!(self.state.blit.is_none());
assert!(self.state.compute.is_none());
assert!(self.state.render.is_none());
objc::rc::autoreleasepool(|| {
let descriptor = metal::RenderPassDescriptor::new();
//TODO: set visibility results buffer
@ -910,6 +914,9 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
self.begin_pass();
let raw = self.raw_cmd_buf.as_ref().unwrap();
debug_assert!(self.state.blit.is_none());
debug_assert!(self.state.compute.is_none());
debug_assert!(self.state.render.is_none());
objc::rc::autoreleasepool(|| {
let encoder = raw.new_compute_command_encoder();
if let Some(label) = desc.label {

View File

@ -43,13 +43,7 @@ fn discarding_depth_target_resets_texture_init_state_check_visible_on_copy_in_sa
.downlevel_flags(
DownlevelFlags::DEPTH_TEXTURE_AND_BUFFER_COPIES | DownlevelFlags::COMPUTE_SHADERS,
)
.limits(Limits::downlevel_defaults())
.specific_failure(
Some(wgpu::Backends::DX12),
Some(5140),
Some("Microsoft Basic Render Driver"),
false,
),
.limits(Limits::downlevel_defaults()),
|mut ctx| {
for format in [
TextureFormat::Stencil8,