Skip to content

Commit 8c7c5c4

Browse files
committed
decouple device and queue IDs
Devices and queues can have different lifetimes, we shouldn't assume that their IDs match.
1 parent de960cc commit 8c7c5c4

File tree

11 files changed

+70
-57
lines changed

11 files changed

+70
-57
lines changed

player/src/bin/play.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ fn main() {
6161
}
6262
.unwrap();
6363

64-
let device = match actions.pop() {
64+
let (device, queue) = match actions.pop() {
6565
Some(trace::Action::Init { desc, backend }) => {
6666
log::info!("Initializing the device for backend: {:?}", backend);
6767
let adapter = global
@@ -80,18 +80,19 @@ fn main() {
8080

8181
let info = gfx_select!(adapter => global.adapter_get_info(adapter)).unwrap();
8282
log::info!("Picked '{}'", info.name);
83-
let id = wgc::id::Id::zip(1, 0, backend);
83+
let device_id = wgc::id::Id::zip(1, 0, backend);
84+
let queue_id = wgc::id::Id::zip(1, 0, backend);
8485
let (_, _, error) = gfx_select!(adapter => global.adapter_request_device(
8586
adapter,
8687
&desc,
8788
None,
88-
Some(id),
89-
Some(id.into_queue_id())
89+
Some(device_id),
90+
Some(queue_id)
9091
));
9192
if let Some(e) = error {
9293
panic!("{:?}", e);
9394
}
94-
id
95+
(device_id, queue_id)
9596
}
9697
_ => panic!("Expected Action::Init"),
9798
};
@@ -102,7 +103,7 @@ fn main() {
102103
gfx_select!(device => global.device_start_capture(device));
103104

104105
while let Some(action) = actions.pop() {
105-
gfx_select!(device => global.process(device, action, &dir, &mut command_buffer_id_manager));
106+
gfx_select!(device => global.process(device, queue, action, &dir, &mut command_buffer_id_manager));
106107
}
107108

108109
gfx_select!(device => global.device_stop_capture(device));
@@ -156,7 +157,7 @@ fn main() {
156157
target.exit();
157158
}
158159
Some(action) => {
159-
gfx_select!(device => global.process(device, action, &dir, &mut command_buffer_id_manager));
160+
gfx_select!(device => global.process(device, queue, action, &dir, &mut command_buffer_id_manager));
160161
}
161162
None => {
162163
if !done {

player/src/lib.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ pub trait GlobalPlay {
1616
fn process<A: wgc::hal_api::HalApi>(
1717
&self,
1818
device: wgc::id::DeviceId,
19+
queue: wgc::id::QueueId,
1920
action: trace::Action,
2021
dir: &Path,
2122
comb_manager: &mut wgc::identity::IdentityManager<wgc::id::markers::CommandBuffer>,
@@ -131,6 +132,7 @@ impl GlobalPlay for wgc::global::Global {
131132
fn process<A: wgc::hal_api::HalApi>(
132133
&self,
133134
device: wgc::id::DeviceId,
135+
queue: wgc::id::QueueId,
134136
action: trace::Action,
135137
dir: &Path,
136138
comb_manager: &mut wgc::identity::IdentityManager<wgc::id::markers::CommandBuffer>,
@@ -327,7 +329,7 @@ impl GlobalPlay for wgc::global::Global {
327329
let bin = std::fs::read(dir.join(data)).unwrap();
328330
let size = (range.end - range.start) as usize;
329331
if queued {
330-
self.queue_write_buffer::<A>(device.into_queue_id(), id, range.start, &bin)
332+
self.queue_write_buffer::<A>(queue, id, range.start, &bin)
331333
.unwrap();
332334
} else {
333335
self.device_set_buffer_data::<A>(id, range.start, &bin[..size])
@@ -341,11 +343,11 @@ impl GlobalPlay for wgc::global::Global {
341343
size,
342344
} => {
343345
let bin = std::fs::read(dir.join(data)).unwrap();
344-
self.queue_write_texture::<A>(device.into_queue_id(), &to, &bin, &layout, &size)
346+
self.queue_write_texture::<A>(queue, &to, &bin, &layout, &size)
345347
.unwrap();
346348
}
347349
Action::Submit(_index, ref commands) if commands.is_empty() => {
348-
self.queue_submit::<A>(device.into_queue_id(), &[]).unwrap();
350+
self.queue_submit::<A>(queue, &[]).unwrap();
349351
}
350352
Action::Submit(_index, commands) => {
351353
let (encoder, error) = self.device_create_command_encoder::<A>(
@@ -361,8 +363,7 @@ impl GlobalPlay for wgc::global::Global {
361363
panic!("{e}");
362364
}
363365
let cmdbuf = self.encode_commands::<A>(encoder, commands);
364-
self.queue_submit::<A>(device.into_queue_id(), &[cmdbuf])
365-
.unwrap();
366+
self.queue_submit::<A>(queue, &[cmdbuf]).unwrap();
366367
}
367368
}
368369
}

player/tests/test.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ impl Test<'_> {
106106
) {
107107
let backend = adapter.backend();
108108
let device_id = wgc::id::Id::zip(test_num, 0, backend);
109+
let queue_id = wgc::id::Id::zip(test_num, 0, backend);
109110
let (_, _, error) = wgc::gfx_select!(adapter => global.adapter_request_device(
110111
adapter,
111112
&wgt::DeviceDescriptor {
@@ -116,7 +117,7 @@ impl Test<'_> {
116117
},
117118
None,
118119
Some(device_id),
119-
Some(device_id.into_queue_id())
120+
Some(queue_id)
120121
));
121122
if let Some(e) = error {
122123
panic!("{:?}", e);
@@ -125,7 +126,7 @@ impl Test<'_> {
125126
let mut command_buffer_id_manager = wgc::identity::IdentityManager::new();
126127
println!("\t\t\tRunning...");
127128
for action in self.actions {
128-
wgc::gfx_select!(device_id => global.process(device_id, action, dir, &mut command_buffer_id_manager));
129+
wgc::gfx_select!(device_id => global.process(device_id, queue_id, action, dir, &mut command_buffer_id_manager));
129130
}
130131
println!("\t\t\tMapping...");
131132
for expect in &self.expectations {

tests/tests/device.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use std::sync::atomic::AtomicBool;
22

3-
use wgpu_test::{fail, gpu_test, FailureCase, GpuTestConfiguration, TestParameters};
3+
use wgpu_test::{
4+
fail, gpu_test, FailureCase, GpuTestConfiguration, TestParameters, TestingContext,
5+
};
46

57
#[gpu_test]
68
static CROSS_DEVICE_BIND_GROUP_USAGE: GpuTestConfiguration = GpuTestConfiguration::new()
@@ -908,3 +910,26 @@ static DEVICE_DESTROY_THEN_BUFFER_CLEANUP: GpuTestConfiguration = GpuTestConfigu
908910
// Poll the device, which should try to clean up its resources.
909911
ctx.instance.poll_all(true);
910912
});
913+
914+
#[gpu_test]
915+
static DEVICE_AND_QUEUE_HAVE_DIFFERENT_IDS: GpuTestConfiguration = GpuTestConfiguration::new()
916+
.parameters(TestParameters::default())
917+
.run_async(|ctx| async move {
918+
let TestingContext {
919+
adapter,
920+
device_features,
921+
device_limits,
922+
device,
923+
queue,
924+
..
925+
} = ctx;
926+
927+
drop(device);
928+
929+
let (device2, queue2) =
930+
wgpu_test::initialize_device(&adapter, device_features, device_limits).await;
931+
932+
drop(queue);
933+
drop(device2);
934+
drop(queue2); // this would previously panic since we would try to use the Device ID to drop the Queue
935+
});

wgpu-core/src/device/global.rs

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::{
77
ResolvedBindGroupEntry, ResolvedBindingResource, ResolvedBufferBinding,
88
},
99
command, conv,
10-
device::{bgl, life::WaitIdleError, queue, DeviceError, DeviceLostClosure, DeviceLostReason},
10+
device::{bgl, life::WaitIdleError, DeviceError, DeviceLostClosure, DeviceLostReason},
1111
global::Global,
1212
hal_api::HalApi,
1313
id::{self, AdapterId, DeviceId, QueueId, SurfaceId},
@@ -2040,7 +2040,7 @@ impl Global {
20402040
pub fn device_poll<A: HalApi>(
20412041
&self,
20422042
device_id: DeviceId,
2043-
maintain: wgt::Maintain<queue::WrappedSubmissionIndex>,
2043+
maintain: wgt::Maintain<crate::SubmissionIndex>,
20442044
) -> Result<bool, WaitIdleError> {
20452045
api_log!("Device::poll {maintain:?}");
20462046

@@ -2050,15 +2050,6 @@ impl Global {
20502050
.get(device_id)
20512051
.map_err(|_| DeviceError::InvalidDeviceId)?;
20522052

2053-
if let wgt::Maintain::WaitForSubmissionIndex(submission_index) = maintain {
2054-
if submission_index.queue_id != device_id.into_queue_id() {
2055-
return Err(WaitIdleError::WrongSubmissionIndex(
2056-
submission_index.queue_id,
2057-
device_id,
2058-
));
2059-
}
2060-
}
2061-
20622053
let DevicePoll {
20632054
closures,
20642055
queue_empty,
@@ -2071,7 +2062,7 @@ impl Global {
20712062

20722063
fn poll_single_device<A: HalApi>(
20732064
device: &crate::device::Device<A>,
2074-
maintain: wgt::Maintain<queue::WrappedSubmissionIndex>,
2065+
maintain: wgt::Maintain<crate::SubmissionIndex>,
20752066
) -> Result<DevicePoll, WaitIdleError> {
20762067
let snatch_guard = device.snatchable_lock.read();
20772068
let fence = device.fence.read();

wgpu-core/src/device/life.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use crate::{
44
DeviceError, DeviceLostClosure,
55
},
66
hal_api::HalApi,
7-
id,
87
resource::{self, Buffer, Texture, Trackable},
98
snatch::SnatchGuard,
109
SubmissionIndex,
@@ -112,8 +111,8 @@ impl<A: HalApi> ActiveSubmission<A> {
112111
pub enum WaitIdleError {
113112
#[error(transparent)]
114113
Device(#[from] DeviceError),
115-
#[error("Tried to wait using a submission index from the wrong device. Submission index is from device {0:?}. Called poll on device {1:?}.")]
116-
WrongSubmissionIndex(id::QueueId, id::DeviceId),
114+
#[error("Tried to wait using a submission index ({0}) that has not been returned by a successful submission (last successful submission: {1})")]
115+
WrongSubmissionIndex(SubmissionIndex, SubmissionIndex),
117116
#[error("GPU got stuck :(")]
118117
StuckGpu,
119118
}

wgpu-core/src/device/queue.rs

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -131,13 +131,6 @@ impl SubmittedWorkDoneClosure {
131131
}
132132
}
133133

134-
#[repr(C)]
135-
#[derive(Debug, Copy, Clone)]
136-
pub struct WrappedSubmissionIndex {
137-
pub queue_id: QueueId,
138-
pub index: SubmissionIndex,
139-
}
140-
141134
/// A texture or buffer to be freed soon.
142135
///
143136
/// This is just a tagged raw texture or buffer, generally about to be added to
@@ -1044,7 +1037,7 @@ impl Global {
10441037
&self,
10451038
queue_id: QueueId,
10461039
command_buffer_ids: &[id::CommandBufferId],
1047-
) -> Result<WrappedSubmissionIndex, QueueSubmitError> {
1040+
) -> Result<SubmissionIndex, QueueSubmitError> {
10481041
profiling::scope!("Queue::submit");
10491042
api_log!("Queue::submit {queue_id:?}");
10501043

@@ -1351,10 +1344,7 @@ impl Global {
13511344

13521345
api_log!("Queue::submit to {queue_id:?} returned submit index {submit_index}");
13531346

1354-
Ok(WrappedSubmissionIndex {
1355-
queue_id,
1356-
index: submit_index,
1357-
})
1347+
Ok(submit_index)
13581348
}
13591349

13601350
pub fn queue_get_timestamp_period<A: HalApi>(

wgpu-core/src/device/resource.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ use std::{
5555
};
5656

5757
use super::{
58-
queue::{self, Queue},
59-
DeviceDescriptor, DeviceError, UserClosures, ENTRYPOINT_FAILURE_ERROR, ZERO_BUFFER_SIZE,
58+
queue::Queue, DeviceDescriptor, DeviceError, UserClosures, ENTRYPOINT_FAILURE_ERROR,
59+
ZERO_BUFFER_SIZE,
6060
};
6161

6262
/// Structure describing a logical device. Some members are internally mutable,
@@ -407,7 +407,7 @@ impl<A: HalApi> Device<A> {
407407
pub(crate) fn maintain<'this>(
408408
&'this self,
409409
fence_guard: crate::lock::RwLockReadGuard<Option<A::Fence>>,
410-
maintain: wgt::Maintain<queue::WrappedSubmissionIndex>,
410+
maintain: wgt::Maintain<crate::SubmissionIndex>,
411411
snatch_guard: SnatchGuard,
412412
) -> Result<(UserClosures, bool), WaitIdleError> {
413413
profiling::scope!("Device::maintain");
@@ -417,9 +417,20 @@ impl<A: HalApi> Device<A> {
417417
// Determine which submission index `maintain` represents.
418418
let submission_index = match maintain {
419419
wgt::Maintain::WaitForSubmissionIndex(submission_index) => {
420-
// We don't need to check to see if the queue id matches
421-
// as we already checked this from inside the poll call.
422-
submission_index.index
420+
let last_successful_submission_index = self
421+
.last_successful_submission_index
422+
.load(Ordering::Acquire);
423+
424+
if let wgt::Maintain::WaitForSubmissionIndex(submission_index) = maintain {
425+
if submission_index > last_successful_submission_index {
426+
return Err(WaitIdleError::WrongSubmissionIndex(
427+
submission_index,
428+
last_successful_submission_index,
429+
));
430+
}
431+
}
432+
433+
submission_index
423434
}
424435
wgt::Maintain::Wait => self
425436
.last_successful_submission_index

wgpu-core/src/id.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -326,12 +326,6 @@ impl CommandBufferId {
326326
}
327327
}
328328

329-
impl DeviceId {
330-
pub fn into_queue_id(self) -> QueueId {
331-
Id(self.0, PhantomData)
332-
}
333-
}
334-
335329
#[test]
336330
fn test_id_backend() {
337331
for &b in &[

wgpu-core/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ pub(crate) use hash_utils::*;
102102
/// The index of a queue submission.
103103
///
104104
/// These are the values stored in `Device::fence`.
105-
type SubmissionIndex = hal::FenceValue;
105+
pub type SubmissionIndex = hal::FenceValue;
106106

107107
type Index = u32;
108108
type Epoch = u32;

0 commit comments

Comments
 (0)