Skip to content

Commit 3c3b532

Browse files
authored
Remove latest_submission_index (#5976)
* Remove latest_submission_index * CI * Comments
1 parent 278d278 commit 3c3b532

File tree

9 files changed

+165
-150
lines changed

9 files changed

+165
-150
lines changed

benches/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,4 @@ pollster.workspace = true
4343
profiling.workspace = true
4444
rayon.workspace = true
4545
tracy-client = { workspace = true, optional = true }
46-
wgpu = { workspace = true, features = ["wgsl"] }
46+
wgpu = { workspace = true, features = ["wgsl", "metal", "dx12"] }

wgpu-core/src/device/global.rs

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ use crate::{
1919
present,
2020
resource::{
2121
self, BufferAccessError, BufferAccessResult, BufferMapOperation, CreateBufferError,
22-
Trackable,
2322
},
2423
storage::Storage,
2524
Label,
@@ -260,15 +259,25 @@ impl Global {
260259
) -> Result<(), WaitIdleError> {
261260
let hub = A::hub(self);
262261

263-
let last_submission = match hub.buffers.read().get(buffer_id) {
264-
Ok(buffer) => buffer.submission_index(),
262+
let device = hub
263+
.devices
264+
.get(device_id)
265+
.map_err(|_| DeviceError::InvalidDeviceId)?;
266+
267+
let buffer = match hub.buffers.get(buffer_id) {
268+
Ok(buffer) => buffer,
265269
Err(_) => return Ok(()),
266270
};
267271

268-
hub.devices
269-
.get(device_id)
270-
.map_err(|_| DeviceError::InvalidDeviceId)?
271-
.wait_for_submit(last_submission)
272+
let last_submission = device
273+
.lock_life()
274+
.get_buffer_latest_submission_index(&buffer);
275+
276+
if let Some(last_submission) = last_submission {
277+
device.wait_for_submit(last_submission)
278+
} else {
279+
Ok(())
280+
}
272281
}
273282

274283
#[doc(hidden)]
@@ -424,7 +433,13 @@ impl Global {
424433
);
425434

426435
if wait {
427-
let last_submit_index = buffer.submission_index();
436+
let Some(last_submit_index) = buffer
437+
.device
438+
.lock_life()
439+
.get_buffer_latest_submission_index(&buffer)
440+
else {
441+
return;
442+
};
428443
match buffer.device.wait_for_submit(last_submit_index) {
429444
Ok(()) => (),
430445
Err(e) => log::error!("Failed to wait for buffer {:?}: {}", buffer_id, e),
@@ -599,7 +614,13 @@ impl Global {
599614
}
600615

601616
if wait {
602-
let last_submit_index = texture.submission_index();
617+
let Some(last_submit_index) = texture
618+
.device
619+
.lock_life()
620+
.get_texture_latest_submission_index(&texture)
621+
else {
622+
return;
623+
};
603624
match texture.device.wait_for_submit(last_submit_index) {
604625
Ok(()) => (),
605626
Err(e) => log::error!("Failed to wait for texture {texture_id:?}: {e}"),
@@ -672,7 +693,13 @@ impl Global {
672693
}
673694

674695
if wait {
675-
let last_submit_index = view.submission_index();
696+
let Some(last_submit_index) = view
697+
.device
698+
.lock_life()
699+
.get_texture_latest_submission_index(&view.parent)
700+
else {
701+
return Ok(());
702+
};
676703
match view.device.wait_for_submit(last_submit_index) {
677704
Ok(()) => (),
678705
Err(e) => {

wgpu-core/src/device/life.rs

Lines changed: 96 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::{
55
},
66
hal_api::HalApi,
77
id,
8-
resource::{self, Buffer, Labeled, Trackable},
8+
resource::{self, Buffer, Labeled, Texture, Trackable},
99
snatch::SnatchGuard,
1010
SubmissionIndex,
1111
};
@@ -55,6 +55,58 @@ struct ActiveSubmission<A: HalApi> {
5555
work_done_closures: SmallVec<[SubmittedWorkDoneClosure; 1]>,
5656
}
5757

58+
impl<A: HalApi> ActiveSubmission<A> {
59+
/// Returns true if this submission contains the given buffer.
60+
///
61+
/// This only uses constant-time operations.
62+
pub fn contains_buffer(&self, buffer: &Buffer<A>) -> bool {
63+
for encoder in &self.encoders {
64+
// The ownership location of buffers depends on where the command encoder
65+
// came from. If it is the staging command encoder on the queue, it is
66+
// in the pending buffer list. If it came from a user command encoder,
67+
// it is in the tracker.
68+
69+
if encoder.trackers.buffers.contains(buffer) {
70+
return true;
71+
}
72+
73+
if encoder
74+
.pending_buffers
75+
.contains_key(&buffer.tracker_index())
76+
{
77+
return true;
78+
}
79+
}
80+
81+
false
82+
}
83+
84+
/// Returns true if this submission contains the given texture.
85+
///
86+
/// This only uses constant-time operations.
87+
pub fn contains_texture(&self, texture: &Texture<A>) -> bool {
88+
for encoder in &self.encoders {
89+
// The ownership location of textures depends on where the command encoder
90+
// came from. If it is the staging command encoder on the queue, it is
91+
// in the pending buffer list. If it came from a user command encoder,
92+
// it is in the tracker.
93+
94+
if encoder.trackers.textures.contains(texture) {
95+
return true;
96+
}
97+
98+
if encoder
99+
.pending_textures
100+
.contains_key(&texture.tracker_index())
101+
{
102+
return true;
103+
}
104+
}
105+
106+
false
107+
}
108+
}
109+
58110
#[derive(Clone, Debug, Error)]
59111
#[non_exhaustive]
60112
pub enum WaitIdleError {
@@ -165,6 +217,40 @@ impl<A: HalApi> LifetimeTracker<A> {
165217
self.mapped.push(value.clone());
166218
}
167219

220+
/// Returns the submission index of the most recent submission that uses the
221+
/// given buffer.
222+
pub fn get_buffer_latest_submission_index(
223+
&self,
224+
buffer: &Buffer<A>,
225+
) -> Option<SubmissionIndex> {
226+
// We iterate in reverse order, so that we can bail out early as soon
227+
// as we find a hit.
228+
self.active.iter().rev().find_map(|submission| {
229+
if submission.contains_buffer(buffer) {
230+
Some(submission.index)
231+
} else {
232+
None
233+
}
234+
})
235+
}
236+
237+
/// Returns the submission index of the most recent submission that uses the
238+
/// given texture.
239+
pub fn get_texture_latest_submission_index(
240+
&self,
241+
texture: &Texture<A>,
242+
) -> Option<SubmissionIndex> {
243+
// We iterate in reverse order, so that we can bail out early as soon
244+
// as we find a hit.
245+
self.active.iter().rev().find_map(|submission| {
246+
if submission.contains_texture(texture) {
247+
Some(submission.index)
248+
} else {
249+
None
250+
}
251+
})
252+
}
253+
168254
/// Sort out the consequences of completed submissions.
169255
///
170256
/// Assume that all submissions up through `last_done` have completed.
@@ -236,9 +322,7 @@ impl<A: HalApi> LifetimeTracker<A> {
236322
}
237323
}
238324
}
239-
}
240325

241-
impl<A: HalApi> LifetimeTracker<A> {
242326
/// Determine which buffers are ready to map, and which must wait for the
243327
/// GPU.
244328
///
@@ -249,17 +333,19 @@ impl<A: HalApi> LifetimeTracker<A> {
249333
}
250334

251335
for buffer in self.mapped.drain(..) {
252-
let submit_index = buffer.submission_index();
336+
let submission = self
337+
.active
338+
.iter_mut()
339+
.rev()
340+
.find(|a| a.contains_buffer(&buffer));
341+
253342
log::trace!(
254-
"Mapping of {} at submission {:?} gets assigned to active {:?}",
343+
"Mapping of {} at submission {:?}",
255344
buffer.error_ident(),
256-
submit_index,
257-
self.active.iter().position(|a| a.index == submit_index)
345+
submission.as_deref().map(|s| s.index)
258346
);
259347

260-
self.active
261-
.iter_mut()
262-
.find(|a| a.index == submit_index)
348+
submission
263349
.map_or(&mut self.ready_to_map, |a| &mut a.mapped)
264350
.push(buffer);
265351
}

wgpu-core/src/device/queue.rs

Lines changed: 8 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -149,12 +149,12 @@ pub enum TempResource<A: HalApi> {
149149
pub(crate) struct EncoderInFlight<A: HalApi> {
150150
raw: A::CommandEncoder,
151151
cmd_buffers: Vec<A::CommandBuffer>,
152-
trackers: Tracker<A>,
152+
pub(crate) trackers: Tracker<A>,
153153

154154
/// These are the buffers that have been tracked by `PendingWrites`.
155-
pending_buffers: Vec<Arc<Buffer<A>>>,
155+
pub(crate) pending_buffers: FastHashMap<TrackerIndex, Arc<Buffer<A>>>,
156156
/// These are the textures that have been tracked by `PendingWrites`.
157-
pending_textures: Vec<Arc<Texture<A>>>,
157+
pub(crate) pending_textures: FastHashMap<TrackerIndex, Arc<Texture<A>>>,
158158
}
159159

160160
impl<A: HalApi> EncoderInFlight<A> {
@@ -268,8 +268,8 @@ impl<A: HalApi> PendingWrites<A> {
268268
queue: &A::Queue,
269269
) -> Result<Option<EncoderInFlight<A>>, DeviceError> {
270270
if self.is_recording {
271-
let pending_buffers = self.dst_buffers.drain().map(|(_, b)| b).collect();
272-
let pending_textures = self.dst_textures.drain().map(|(_, t)| t).collect();
271+
let pending_buffers = mem::take(&mut self.dst_buffers);
272+
let pending_textures = mem::take(&mut self.dst_textures);
273273

274274
let cmd_buf = unsafe { self.command_encoder.end_encoding()? };
275275
self.is_recording = false;
@@ -570,8 +570,6 @@ impl Global {
570570

571571
self.queue_validate_write_buffer_impl(&dst, buffer_offset, staging_buffer.size)?;
572572

573-
dst.use_at(device.active_submission_index.load(Ordering::Relaxed) + 1);
574-
575573
let region = hal::BufferCopy {
576574
src_offset: 0,
577575
dst_offset: buffer_offset,
@@ -762,7 +760,6 @@ impl Global {
762760
// call above. Since we've held `texture_guard` the whole time, we know
763761
// the texture hasn't gone away in the mean time, so we can unwrap.
764762
let dst = hub.textures.get(destination.texture).unwrap();
765-
dst.use_at(device.active_submission_index.load(Ordering::Relaxed) + 1);
766763

767764
let dst_raw = dst.try_raw(&snatch_guard)?;
768765

@@ -1007,7 +1004,6 @@ impl Global {
10071004
.drain(init_layer_range);
10081005
}
10091006
}
1010-
dst.use_at(device.active_submission_index.load(Ordering::Relaxed) + 1);
10111007

10121008
let snatch_guard = device.snatchable_lock.read();
10131009
let dst_raw = dst.try_raw(&snatch_guard)?;
@@ -1126,7 +1122,7 @@ impl Global {
11261122
}
11271123

11281124
{
1129-
profiling::scope!("update submission ids");
1125+
profiling::scope!("check resource state");
11301126

11311127
let cmd_buf_data = cmdbuf.data.lock();
11321128
let cmd_buf_trackers = &cmd_buf_data.as_ref().unwrap().trackers;
@@ -1136,7 +1132,6 @@ impl Global {
11361132
profiling::scope!("buffers");
11371133
for buffer in cmd_buf_trackers.buffers.used_resources() {
11381134
buffer.check_destroyed(&snatch_guard)?;
1139-
buffer.use_at(submit_index);
11401135

11411136
match *buffer.map_state.lock() {
11421137
BufferMapState::Idle => (),
@@ -1163,7 +1158,6 @@ impl Global {
11631158
true
11641159
}
11651160
};
1166-
texture.use_at(submit_index);
11671161
if should_extend {
11681162
unsafe {
11691163
used_surface_textures
@@ -1177,69 +1171,6 @@ impl Global {
11771171
}
11781172
}
11791173
}
1180-
{
1181-
profiling::scope!("views");
1182-
for texture_view in cmd_buf_trackers.views.used_resources() {
1183-
texture_view.use_at(submit_index);
1184-
}
1185-
}
1186-
{
1187-
profiling::scope!("bind groups (+ referenced views/samplers)");
1188-
for bg in cmd_buf_trackers.bind_groups.used_resources() {
1189-
bg.use_at(submit_index);
1190-
// We need to update the submission indices for the contained
1191-
// state-less (!) resources as well, so that they don't get
1192-
// deleted too early if the parent bind group goes out of scope.
1193-
for view in bg.used.views.used_resources() {
1194-
view.use_at(submit_index);
1195-
}
1196-
for sampler in bg.used.samplers.used_resources() {
1197-
sampler.use_at(submit_index);
1198-
}
1199-
}
1200-
}
1201-
{
1202-
profiling::scope!("compute pipelines");
1203-
for compute_pipeline in
1204-
cmd_buf_trackers.compute_pipelines.used_resources()
1205-
{
1206-
compute_pipeline.use_at(submit_index);
1207-
}
1208-
}
1209-
{
1210-
profiling::scope!("render pipelines");
1211-
for render_pipeline in
1212-
cmd_buf_trackers.render_pipelines.used_resources()
1213-
{
1214-
render_pipeline.use_at(submit_index);
1215-
}
1216-
}
1217-
{
1218-
profiling::scope!("query sets");
1219-
for query_set in cmd_buf_trackers.query_sets.used_resources() {
1220-
query_set.use_at(submit_index);
1221-
}
1222-
}
1223-
{
1224-
profiling::scope!(
1225-
"render bundles (+ referenced pipelines/query sets)"
1226-
);
1227-
for bundle in cmd_buf_trackers.bundles.used_resources() {
1228-
bundle.use_at(submit_index);
1229-
// We need to update the submission indices for the contained
1230-
// state-less (!) resources as well, excluding the bind groups.
1231-
// They don't get deleted too early if the bundle goes out of scope.
1232-
for render_pipeline in
1233-
bundle.used.render_pipelines.read().used_resources()
1234-
{
1235-
render_pipeline.use_at(submit_index);
1236-
}
1237-
for query_set in bundle.used.query_sets.read().used_resources()
1238-
{
1239-
query_set.use_at(submit_index);
1240-
}
1241-
}
1242-
}
12431174
}
12441175
let mut baked = cmdbuf.from_arc_into_baked();
12451176

@@ -1303,8 +1234,8 @@ impl Global {
13031234
raw: baked.encoder,
13041235
cmd_buffers: baked.list,
13051236
trackers: baked.trackers,
1306-
pending_buffers: Vec::new(),
1307-
pending_textures: Vec::new(),
1237+
pending_buffers: FastHashMap::default(),
1238+
pending_textures: FastHashMap::default(),
13081239
});
13091240
}
13101241

0 commit comments

Comments
 (0)