diff --git a/wgpu-core/src/command/bundle.rs b/wgpu-core/src/command/bundle.rs index aff2eb434..ea25c6efd 100644 --- a/wgpu-core/src/command/bundle.rs +++ b/wgpu-core/src/command/bundle.rs @@ -214,7 +214,7 @@ impl RenderBundleEncoder { state.set_bind_group(index, bind_group_id, bind_group.layout_id, offsets); state .trackers - .merge_extend(&bind_group.used) + .merge_extend_all(&bind_group.used) .map_pass_err(scope)?; } RenderCommand::SetPipeline(pipeline_id) => { diff --git a/wgpu-core/src/command/compute.rs b/wgpu-core/src/command/compute.rs index a44f17a0b..c15692276 100644 --- a/wgpu-core/src/command/compute.rs +++ b/wgpu-core/src/command/compute.rs @@ -12,7 +12,7 @@ use crate::{ id, memory_init_tracker::{MemoryInitKind, MemoryInitTrackerAction}, resource::{Buffer, BufferUse, Texture}, - track::{TrackerSet, UsageConflict}, + track::{StatefulTrackerSubset, TrackerSet, UsageConflict}, validation::{check_buffer_usage, MissingBufferUsageError}, Label, DOWNLEVEL_ERROR_WARNING_MESSAGE, }; @@ -193,7 +193,7 @@ where struct State { binder: Binder, pipeline: StateChange, - trackers: TrackerSet, + trackers: StatefulTrackerSubset, debug_scope_depth: u32, } @@ -223,6 +223,7 @@ impl State { ) -> Result<(), UsageConflict> { for id in self.binder.list_active() { self.trackers.merge_extend(&bind_group_guard[id].used)?; + base_trackers.merge_extend_stateless(&bind_group_guard[id].used); } log::trace!("Encoding dispatch barriers"); @@ -230,7 +231,8 @@ impl State { CommandBuffer::insert_barriers( raw_cmd_buf, base_trackers, - &self.trackers, + &self.trackers.buffers, + &self.trackers.textures, buffer_guard, texture_guard, ); @@ -303,7 +305,7 @@ impl Global { let mut state = State { binder: Binder::new(), pipeline: StateChange::new(), - trackers: TrackerSet::new(B::VARIANT), + trackers: StatefulTrackerSubset::new(B::VARIANT), debug_scope_depth: 0, }; let mut temp_offsets = Vec::new(); diff --git a/wgpu-core/src/command/mod.rs b/wgpu-core/src/command/mod.rs index 78363f474..a31152a0c 100644 --- a/wgpu-core/src/command/mod.rs +++ b/wgpu-core/src/command/mod.rs @@ -27,7 +27,7 @@ use crate::{ id, memory_init_tracker::MemoryInitTrackerAction, resource::{Buffer, Texture}, - track::TrackerSet, + track::{BufferState, ResourceTracker, TextureState, TrackerSet}, Label, PrivateFeatures, Stored, }; @@ -74,7 +74,8 @@ impl CommandBuffer { pub(crate) fn insert_barriers( raw: &mut B::CommandBuffer, base: &mut TrackerSet, - head: &TrackerSet, + head_buffers: &ResourceTracker, + head_textures: &ResourceTracker, buffer_guard: &Storage, id::BufferId>, texture_guard: &Storage, id::TextureId>, ) { @@ -82,25 +83,17 @@ impl CommandBuffer { profiling::scope!("insert_barriers"); debug_assert_eq!(B::VARIANT, base.backend()); - debug_assert_eq!(B::VARIANT, head.backend()); - let buffer_barriers = base.buffers.merge_replace(&head.buffers).map(|pending| { + let buffer_barriers = base.buffers.merge_replace(head_buffers).map(|pending| { let buf = &buffer_guard[pending.id]; pending.into_hal(buf) }); - let texture_barriers = base.textures.merge_replace(&head.textures).map(|pending| { + let texture_barriers = base.textures.merge_replace(head_textures).map(|pending| { let tex = &texture_guard[pending.id]; pending.into_hal(tex) }); - base.views.merge_extend(&head.views).unwrap(); - base.bind_groups.merge_extend(&head.bind_groups).unwrap(); - base.samplers.merge_extend(&head.samplers).unwrap(); - base.compute_pipes - .merge_extend(&head.compute_pipes) - .unwrap(); - base.render_pipes.merge_extend(&head.render_pipes).unwrap(); - base.bundles.merge_extend(&head.bundles).unwrap(); + //TODO: be more deliberate about the stages let stages = all_buffer_stages() | all_image_stages(); unsafe { raw.pipeline_barrier( diff --git a/wgpu-core/src/command/render.rs b/wgpu-core/src/command/render.rs index 79526de1e..ef995ac62 100644 --- a/wgpu-core/src/command/render.rs +++ b/wgpu-core/src/command/render.rs @@ -19,7 +19,7 @@ use crate::{ memory_init_tracker::{MemoryInitKind, MemoryInitTrackerAction}, pipeline::PipelineFlags, resource::{BufferUse, Texture, TextureUse, TextureView, TextureViewInner}, - track::{TextureSelector, TrackerSet, UsageConflict}, + track::{StatefulTrackerSubset, TextureSelector, UsageConflict}, validation::{ check_buffer_usage, check_texture_usage, MissingBufferUsageError, MissingTextureUsageError, }, @@ -504,7 +504,7 @@ struct RenderAttachment<'a> { struct RenderPassInfo<'a, B: hal::Backend> { context: RenderPassContext, - trackers: TrackerSet, + trackers: StatefulTrackerSubset, render_attachments: AttachmentDataVec>, used_swap_chain: Option>, is_ds_read_only: bool, @@ -517,7 +517,7 @@ impl<'a, B: GfxBackend> RenderPassInfo<'a, B> { raw: &mut B::CommandBuffer, color_attachments: &[RenderPassColorAttachment], depth_stencil_attachment: Option<&RenderPassDepthStencilAttachment>, - cmd_buf: &CommandBuffer, + cmd_buf: &mut CommandBuffer, device: &Device, view_guard: &'a Storage, id::TextureViewId>, ) -> Result { @@ -536,7 +536,6 @@ impl<'a, B: GfxBackend> RenderPassInfo<'a, B> { let mut sample_count = 0; let mut depth_stencil_aspects = hal::format::Aspects::empty(); let mut used_swap_chain = None::>; - let mut trackers = TrackerSet::new(B::VARIANT); let mut add_view = |view: &TextureView, type_name| { if let Some(ex) = extent { @@ -564,7 +563,8 @@ impl<'a, B: GfxBackend> RenderPassInfo<'a, B> { let rp_key = { let depth_stencil = match depth_stencil_attachment { Some(at) => { - let view = trackers + let view = cmd_buf + .trackers .views .use_extend(&*view_guard, at.view, (), ()) .map_err(|_| RenderPassErrorInner::InvalidAttachment(at.view))?; @@ -627,7 +627,8 @@ impl<'a, B: GfxBackend> RenderPassInfo<'a, B> { let mut resolves = ArrayVec::new(); for at in color_attachments { - let view = trackers + let view = cmd_buf + .trackers .views .use_extend(&*view_guard, at.view, (), ()) .map_err(|_| RenderPassErrorInner::InvalidAttachment(at.view))?; @@ -690,7 +691,8 @@ impl<'a, B: GfxBackend> RenderPassInfo<'a, B> { } for resolve_target in color_attachments.iter().flat_map(|at| at.resolve_target) { - let view = trackers + let view = cmd_buf + .trackers .views .use_extend(&*view_guard, resolve_target, (), ()) .map_err(|_| RenderPassErrorInner::InvalidAttachment(resolve_target))?; @@ -961,7 +963,7 @@ impl<'a, B: GfxBackend> RenderPassInfo<'a, B> { Ok(Self { context, - trackers, + trackers: StatefulTrackerSubset::new(B::VARIANT), render_attachments, used_swap_chain, is_ds_read_only, @@ -973,7 +975,8 @@ impl<'a, B: GfxBackend> RenderPassInfo<'a, B> { fn finish( mut self, texture_guard: &Storage, id::TextureId>, - ) -> Result<(TrackerSet, Option>), RenderPassErrorInner> { + ) -> Result<(StatefulTrackerSubset, Option>), RenderPassErrorInner> + { profiling::scope!("finish", "RenderPassInfo"); for ra in self.render_attachments { @@ -1122,7 +1125,7 @@ impl Global { ); dynamic_offset_count += num_dynamic_offsets as usize; - let bind_group = info + let bind_group = cmd_buf .trackers .bind_groups .use_extend(&*bind_group_guard, bind_group_id, (), ()) @@ -1132,9 +1135,11 @@ impl Global { .validate_dynamic_bindings(&temp_offsets) .map_pass_err(scope)?; + // merge the resource tracker in info.trackers .merge_extend(&bind_group.used) .map_pass_err(scope)?; + cmd_buf.trackers.merge_extend_stateless(&bind_group.used); cmd_buf.buffer_memory_init_actions.extend( bind_group.used_buffer_ranges.iter().filter_map(|action| { @@ -1184,7 +1189,7 @@ impl Global { continue; } - let pipeline = info + let pipeline = cmd_buf .trackers .render_pipes .use_extend(&*pipeline_guard, pipeline_id, (), ()) @@ -1826,7 +1831,7 @@ impl Global { } => { let scope = PassErrorScope::WriteTimestamp; - let query_set = info + let query_set = cmd_buf .trackers .query_sets .use_extend(&*query_set_guard, query_set_id, (), ()) @@ -1853,7 +1858,7 @@ impl Global { } => { let scope = PassErrorScope::BeginPipelineStatisticsQuery; - let query_set = info + let query_set = cmd_buf .trackers .query_sets .use_extend(&*query_set_guard, query_set_id, (), ()) @@ -1887,7 +1892,7 @@ impl Global { } RenderCommand::ExecuteBundle(bundle_id) => { let scope = PassErrorScope::ExecuteBundle; - let bundle = info + let bundle = cmd_buf .trackers .bundles .use_extend(&*bundle_guard, bundle_id, (), ()) @@ -1984,7 +1989,8 @@ impl Global { super::CommandBuffer::insert_barriers( last_cmd_buf, &mut cmd_buf.trackers, - &trackers, + &trackers.buffers, + &trackers.textures, &*buffer_guard, &*texture_guard, ); diff --git a/wgpu-core/src/device/queue.rs b/wgpu-core/src/device/queue.rs index b0ad90710..574156642 100644 --- a/wgpu-core/src/device/queue.rs +++ b/wgpu-core/src/device/queue.rs @@ -760,10 +760,12 @@ impl Global { .begin_primary(hal::command::CommandBufferFlags::ONE_TIME_SUBMIT); } log::trace!("Stitching command buffer {:?} before submission", cmb_id); + trackers.merge_extend_stateless(&cmdbuf.trackers); CommandBuffer::insert_barriers( &mut transit, &mut *trackers, - &cmdbuf.trackers, + &cmdbuf.trackers.buffers, + &cmdbuf.trackers.textures, &*buffer_guard, &*texture_guard, ); diff --git a/wgpu-core/src/track/mod.rs b/wgpu-core/src/track/mod.rs index 9313fc17d..e61765969 100644 --- a/wgpu-core/src/track/mod.rs +++ b/wgpu-core/src/track/mod.rs @@ -625,10 +625,17 @@ impl TrackerSet { } /// Merge all the trackers of another instance by extending - /// the usage. Panics on a conflict. - pub fn merge_extend(&mut self, other: &Self) -> Result<(), UsageConflict> { + /// the usage. Panics on a stateless conflict, returns a conflict otherwise. + pub fn merge_extend_all(&mut self, other: &Self) -> Result<(), UsageConflict> { self.buffers.merge_extend(&other.buffers)?; self.textures.merge_extend(&other.textures)?; + self.merge_extend_stateless(other); + Ok(()) + } + + /// Merge all the stateless trackers of another instance by extending + /// the usage. Panics on a conflict. + pub fn merge_extend_stateless(&mut self, other: &Self) { self.views.merge_extend(&other.views).unwrap(); self.bind_groups.merge_extend(&other.bind_groups).unwrap(); self.samplers.merge_extend(&other.samplers).unwrap(); @@ -638,10 +645,38 @@ impl TrackerSet { self.render_pipes.merge_extend(&other.render_pipes).unwrap(); self.bundles.merge_extend(&other.bundles).unwrap(); self.query_sets.merge_extend(&other.query_sets).unwrap(); - Ok(()) } pub fn backend(&self) -> wgt::Backend { self.buffers.backend } } + +#[derive(Debug)] +pub(crate) struct StatefulTrackerSubset { + pub buffers: ResourceTracker, + pub textures: ResourceTracker, +} + +impl StatefulTrackerSubset { + /// Create an empty set. + pub fn new(backend: wgt::Backend) -> Self { + Self { + buffers: ResourceTracker::new(backend), + textures: ResourceTracker::new(backend), + } + } + + /// Clear all the trackers. + pub fn clear(&mut self) { + self.buffers.clear(); + self.textures.clear(); + } + + /// Merge all the trackers of another tracker the usage. + pub fn merge_extend(&mut self, other: &TrackerSet) -> Result<(), UsageConflict> { + self.buffers.merge_extend(&other.buffers)?; + self.textures.merge_extend(&other.textures)?; + Ok(()) + } +}