Split the tracker into stateful/stateless to reduce the overhead

This commit is contained in:
Dzmitry Malyshau 2021-05-31 14:18:44 -04:00
parent f62d0d5edc
commit 7b7e72b1c2
6 changed files with 75 additions and 37 deletions

View File

@ -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) => {

View File

@ -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<id::ComputePipelineId>,
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<G: GlobalIdentityHandlerFactory> Global<G> {
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();

View File

@ -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<B: GfxBackend> CommandBuffer<B> {
pub(crate) fn insert_barriers(
raw: &mut B::CommandBuffer,
base: &mut TrackerSet,
head: &TrackerSet,
head_buffers: &ResourceTracker<BufferState>,
head_textures: &ResourceTracker<TextureState>,
buffer_guard: &Storage<Buffer<B>, id::BufferId>,
texture_guard: &Storage<Texture<B>, id::TextureId>,
) {
@ -82,25 +83,17 @@ impl<B: GfxBackend> CommandBuffer<B> {
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(

View File

@ -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<RenderAttachment<'a>>,
used_swap_chain: Option<Stored<id::SwapChainId>>,
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<B>,
cmd_buf: &mut CommandBuffer<B>,
device: &Device<B>,
view_guard: &'a Storage<TextureView<B>, id::TextureViewId>,
) -> Result<Self, RenderPassErrorInner> {
@ -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::<Stored<id::SwapChainId>>;
let mut trackers = TrackerSet::new(B::VARIANT);
let mut add_view = |view: &TextureView<B>, 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<Texture<B>, id::TextureId>,
) -> Result<(TrackerSet, Option<Stored<id::SwapChainId>>), RenderPassErrorInner> {
) -> Result<(StatefulTrackerSubset, Option<Stored<id::SwapChainId>>), RenderPassErrorInner>
{
profiling::scope!("finish", "RenderPassInfo");
for ra in self.render_attachments {
@ -1122,7 +1125,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
);
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<G: GlobalIdentityHandlerFactory> Global<G> {
.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<G: GlobalIdentityHandlerFactory> Global<G> {
continue;
}
let pipeline = info
let pipeline = cmd_buf
.trackers
.render_pipes
.use_extend(&*pipeline_guard, pipeline_id, (), ())
@ -1826,7 +1831,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
} => {
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<G: GlobalIdentityHandlerFactory> Global<G> {
} => {
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<G: GlobalIdentityHandlerFactory> Global<G> {
}
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<G: GlobalIdentityHandlerFactory> Global<G> {
super::CommandBuffer::insert_barriers(
last_cmd_buf,
&mut cmd_buf.trackers,
&trackers,
&trackers.buffers,
&trackers.textures,
&*buffer_guard,
&*texture_guard,
);

View File

@ -760,10 +760,12 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
.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,
);

View File

@ -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<BufferState>,
pub textures: ResourceTracker<TextureState>,
}
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(())
}
}