Skip to content

Commit

Permalink
Unify Maintain in both wgc and wgpu
Browse files Browse the repository at this point in the history
  • Loading branch information
cwfitzgerald committed Jun 4, 2022
1 parent 882602f commit cb92cc6
Show file tree
Hide file tree
Showing 15 changed files with 78 additions and 53 deletions.
2 changes: 1 addition & 1 deletion deno_webgpu/src/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ pub async fn op_webgpu_buffer_get_map_async(
{
let state = state.borrow();
let instance = state.borrow::<super::Instance>();
gfx_select!(device => instance.device_poll(device, false, None)).unwrap();
gfx_select!(device => instance.device_poll(device, wgpu_types::Maintain::Wait)).unwrap();
}
tokio::time::sleep(Duration::from_millis(10)).await;
}
Expand Down
2 changes: 1 addition & 1 deletion player/src/bin/play.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ fn main() {
}

gfx_select!(device => global.device_stop_capture(device));
gfx_select!(device => global.device_poll(device, true, None)).unwrap();
gfx_select!(device => global.device_poll(device, wgt::Maintain::Wait)).unwrap();
}
#[cfg(feature = "winit")]
{
Expand Down
2 changes: 1 addition & 1 deletion player/tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ impl Test<'_> {
}

println!("\t\t\tWaiting...");
wgc::gfx_select!(device => global.device_poll(device, true, None)).unwrap();
wgc::gfx_select!(device => global.device_poll(device, wgt::Maintain::Wait)).unwrap();

for expect in self.expectations {
println!("\t\t\tChecking {}", expect.name);
Expand Down
25 changes: 14 additions & 11 deletions wgpu-core/src/device/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -439,8 +439,7 @@ impl<A: HalApi> Device<A> {
fn maintain<'this, 'token: 'this, G: GlobalIdentityHandlerFactory>(
&'this self,
hub: &Hub<A, G>,
force_wait: bool,
submission_index: Option<queue::WrappedSubmissionIndex>,
maintain: wgt::Maintain<queue::WrappedSubmissionIndex>,
token: &mut Token<'token, Self>,
) -> Result<(UserClosures, bool), WaitIdleError> {
profiling::scope!("maintain", "Device");
Expand All @@ -464,14 +463,14 @@ impl<A: HalApi> Device<A> {
);
life_tracker.triage_mapped(hub, token);

let last_done_index = if force_wait {
let index_to_wait_for = match submission_index {
Some(submission_index) => {
let last_done_index = if maintain.is_wait() {
let index_to_wait_for = match maintain {
wgt::Maintain::WaitForSubmissionIndex(submission_index) => {
// We don't need to check to see if the queue id matches
// as we already checked this from inside the poll call.
submission_index.index
}
None => self.active_submission_index,
_ => self.active_submission_index,
};
unsafe {
self.raw
Expand Down Expand Up @@ -4975,11 +4974,10 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
pub fn device_poll<A: HalApi>(
&self,
device_id: id::DeviceId,
force_wait: bool,
submission_index: Option<queue::WrappedSubmissionIndex>,
maintain: wgt::Maintain<queue::WrappedSubmissionIndex>,
) -> Result<bool, WaitIdleError> {
let (closures, queue_empty) = {
if let Some(submission_index) = submission_index {
if let wgt::Maintain::WaitForSubmissionIndex(submission_index) = maintain {
if submission_index.queue_id != device_id {
return Err(WaitIdleError::WrongSubmissionIndex(
submission_index.queue_id,
Expand All @@ -4994,7 +4992,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
device_guard
.get(device_id)
.map_err(|_| DeviceError::Invalid)?
.maintain(hub, force_wait, submission_index, &mut token)?
.maintain(hub, maintain, &mut token)?
};
unsafe {
closures.fire();
Expand Down Expand Up @@ -5022,7 +5020,12 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let (device_guard, mut token) = hub.devices.read(&mut token);

for (id, device) in device_guard.iter(A::VARIANT) {
let (cbs, queue_empty) = device.maintain(hub, force_wait, None, &mut token)?;
let maintain = if force_wait {
wgt::Maintain::Wait
} else {
wgt::Maintain::Poll
};
let (cbs, queue_empty) = device.maintain(hub, maintain, &mut token)?;
all_queue_empty = all_queue_empty && queue_empty;

// If the device's own `RefCount` clone is the only one left, and
Expand Down
2 changes: 1 addition & 1 deletion wgpu-core/src/device/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -925,7 +925,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {

// This will schedule destruction of all resources that are no longer needed
// by the user but used in the command stream, among other things.
let (closures, _) = match device.maintain(hub, false, None, &mut token) {
let (closures, _) = match device.maintain(hub, wgt::Maintain::Wait, &mut token) {
Ok(closures) => closures,
Err(WaitIdleError::Device(err)) => return Err(QueueSubmitError::Queue(err)),
Err(WaitIdleError::StuckGpu) => return Err(QueueSubmitError::StuckGpu),
Expand Down
37 changes: 37 additions & 0 deletions wgpu-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2273,6 +2273,43 @@ impl Default for ColorWrites {
}
}

/// Passed to `Device::poll` to control how and if it should block.
#[derive(Clone)]
pub enum Maintain<T> {
/// On native backends, block until the given submission has
/// completed execution, and any callbacks have been invoked.
///
/// On the web, this has no effect. Callbacks are invoked from the
/// window event loop.
WaitForSubmissionIndex(T),
/// Same as WaitForSubmissionIndex but waits for the most recent submission.
Wait,
/// Check the device for a single time without blocking.
Poll,
}

impl<T> Maintain<T> {
/// This maintain represents a wait of some kind.
pub fn is_wait(&self) -> bool {
match *self {
Self::WaitForSubmissionIndex(..) | Self::Wait => true,
Self::Poll => false,
}
}

/// Map on the wait index type.
pub fn map_index<U, F>(self, func: F) -> Maintain<U>
where
F: FnOnce(T) -> U,
{
match self {
Self::WaitForSubmissionIndex(i) => Maintain::WaitForSubmissionIndex(func(i)),
Self::Wait => Maintain::Wait,
Self::Poll => Maintain::Poll,
}
}
}

/// State of the stencil operation (fixed-pipeline stage).
///
/// For use in [`DepthStencilState`].
Expand Down
2 changes: 1 addition & 1 deletion wgpu/examples/framework.rs
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@ pub fn test<E: Example>(mut params: FrameworkRefTest) {

let dst_buffer_slice = dst_buffer.slice(..);
let _ = dst_buffer_slice.map_async(wgpu::MapMode::Read);
ctx.device.poll(wgpu::Maintain::Wait(None));
ctx.device.poll(wgpu::Maintain::Wait);
let bytes = dst_buffer_slice.get_mapped_range().to_vec();

test_common::image::compare_image_output(
Expand Down
2 changes: 1 addition & 1 deletion wgpu/examples/hello-compute/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ async fn execute_gpu_inner(
// Poll the device in a blocking manner so that our future resolves.
// In an actual application, `device.poll(...)` should
// be called in an event loop or on another thread.
device.poll(wgpu::Maintain::Wait(None));
device.poll(wgpu::Maintain::Wait);

// Awaits until `buffer_future` can be read from
if let Ok(()) = buffer_future.await {
Expand Down
2 changes: 1 addition & 1 deletion wgpu/examples/mipmap/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ impl framework::Example for Example {
.slice(..)
.map_async(wgpu::MapMode::Read);
// Wait for device to be done rendering mipmaps
device.poll(wgpu::Maintain::Wait(None));
device.poll(wgpu::Maintain::Wait);
// This is guaranteed to be ready.
let timestamp_view = query_sets
.data_buffer
Expand Down
11 changes: 4 additions & 7 deletions wgpu/src/backend/direct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1572,7 +1572,8 @@ impl crate::Context for Context {

#[cfg(any(not(target_arch = "wasm32"), feature = "emscripten"))]
{
match wgc::gfx_select!(device.id => global.device_poll(device.id, true, None)) {
match wgc::gfx_select!(device.id => global.device_poll(device.id, wgt::Maintain::Wait))
{
Ok(_) => (),
Err(err) => self.handle_error_fatal(err, "Device::drop"),
}
Expand All @@ -1583,14 +1584,10 @@ impl crate::Context for Context {

fn device_poll(&self, device: &Self::DeviceId, maintain: crate::Maintain) -> bool {
let global = &self.0;
let (wait, index) = match maintain {
crate::Maintain::Poll => (false, None),
crate::Maintain::Wait(index) => (true, index.map(|i| i.0)),
};
let maintain_inner = maintain.map_index(|i| i.0);
match wgc::gfx_select!(device.id => global.device_poll(
device.id,
wait,
index
maintain_inner
)) {
Ok(queue_empty) => queue_empty,
Err(err) => self.handle_error_fatal(err, "Device::poll"),
Expand Down
18 changes: 3 additions & 15 deletions wgpu/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -557,21 +557,6 @@ pub struct Device {
#[derive(Debug, Copy, Clone)]
pub struct SubmissionIndex(<C as Context>::SubmissionIndex);

/// Passed to [`Device::poll`] to control how and if it should block.
#[derive(Clone)]
pub enum Maintain {
/// On native backends, block until the given submission has
/// completed execution, and any callbacks have been invoked.
///
/// On the web, this has no effect. Callbacks are invoked from the
/// window event loop.
///
/// If the submission index is `None`, wait for the most recent submission.
Wait(Option<SubmissionIndex>),
/// Check the device for a single time without blocking.
Poll,
}

/// The main purpose of this struct is to resolve mapped ranges (convert sizes
/// to end points), and to ensure that the sub-ranges don't intersect.
#[derive(Debug)]
Expand Down Expand Up @@ -1263,6 +1248,9 @@ pub type TextureDescriptor<'a> = wgt::TextureDescriptor<Label<'a>>;
/// Corresponds to [WebGPU `GPUQuerySetDescriptor`](
/// https://gpuweb.github.io/gpuweb/#dictdef-gpuquerysetdescriptor).
pub type QuerySetDescriptor<'a> = wgt::QuerySetDescriptor<Label<'a>>;
pub use wgt::Maintain as MaintainBase;
/// Passed to [`Device::poll`] to control how and if it should block.
pub type Maintain = wgt::Maintain<SubmissionIndex>;

/// Describes a [`TextureView`].
///
Expand Down
6 changes: 3 additions & 3 deletions wgpu/tests/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ impl TestParameters {
self
}

/// Mark the test as always failing, equivilant to specific_failure(None, None, None)
/// Mark the test as always failing, equivalent to specific_failure(None, None, None)
pub fn failure(mut self) -> Self {
self.failures.push(FailureCase {
backends: None,
Expand All @@ -121,7 +121,7 @@ impl TestParameters {
self
}

/// Mark the test as always failing and needing to be skipped, equivilant to specific_failure(None, None, None)
/// Mark the test as always failing and needing to be skipped, equivalent to specific_failure(None, None, None)
pub fn skip(mut self) -> Self {
self.failures.push(FailureCase {
backends: None,
Expand All @@ -132,7 +132,7 @@ impl TestParameters {
self
}

/// Mark the test as always failing on a specific backend, equivilant to specific_failure(backend, None, None)
/// Mark the test as always failing on a specific backend, equivalent to specific_failure(backend, None, None)
pub fn backend_failure(mut self, backends: wgpu::Backends) -> Self {
self.failures.push(FailureCase {
backends: Some(backends),
Expand Down
16 changes: 8 additions & 8 deletions wgpu/tests/poll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ fn wait() {
let cmd_buf = generate_dummy_work(&ctx);

ctx.queue.submit(Some(cmd_buf));
ctx.device.poll(Maintain::Wait(None));
ctx.device.poll(Maintain::Wait);
})
}

Expand All @@ -68,8 +68,8 @@ fn double_wait() {
let cmd_buf = generate_dummy_work(&ctx);

ctx.queue.submit(Some(cmd_buf));
ctx.device.poll(Maintain::Wait(None));
ctx.device.poll(Maintain::Wait(None));
ctx.device.poll(Maintain::Wait);
ctx.device.poll(Maintain::Wait);
})
}

Expand All @@ -79,7 +79,7 @@ fn wait_on_submission() {
let cmd_buf = generate_dummy_work(&ctx);

let index = ctx.queue.submit(Some(cmd_buf));
ctx.device.poll(Maintain::Wait(Some(index)));
ctx.device.poll(Maintain::WaitForSubmissionIndex(index));
})
}

Expand All @@ -89,8 +89,8 @@ fn double_wait_on_submission() {
let cmd_buf = generate_dummy_work(&ctx);

let index = ctx.queue.submit(Some(cmd_buf));
ctx.device.poll(Maintain::Wait(Some(index)));
ctx.device.poll(Maintain::Wait(Some(index)));
ctx.device.poll(Maintain::WaitForSubmissionIndex(index));
ctx.device.poll(Maintain::WaitForSubmissionIndex(index));
})
}

Expand All @@ -102,7 +102,7 @@ fn wait_out_of_order() {

let index1 = ctx.queue.submit(Some(cmd_buf1));
let index2 = ctx.queue.submit(Some(cmd_buf2));
ctx.device.poll(Maintain::Wait(Some(index2)));
ctx.device.poll(Maintain::Wait(Some(index1)));
ctx.device.poll(Maintain::WaitForSubmissionIndex(index2));
ctx.device.poll(Maintain::WaitForSubmissionIndex(index1));
})
}
2 changes: 1 addition & 1 deletion wgpu/tests/vertex_indices/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ fn pulling_common(
ctx.queue.submit(Some(encoder.finish()));
let slice = buffer.slice(..);
let _ = slice.map_async(wgpu::MapMode::Read);
ctx.device.poll(wgpu::Maintain::Wait(None));
ctx.device.poll(wgpu::Maintain::Wait);
let data: Vec<u32> = bytemuck::cast_slice(&*slice.get_mapped_range()).to_vec();

assert_eq!(data, expected);
Expand Down
2 changes: 1 addition & 1 deletion wgpu/tests/zero_init_texture_after_discard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ fn assert_buffer_is_zero(readback_buffer: &wgpu::Buffer, device: &wgpu::Device)
{
let buffer_slice = readback_buffer.slice(..);
let _ = buffer_slice.map_async(wgpu::MapMode::Read);
device.poll(wgpu::Maintain::Wait(None));
device.poll(wgpu::Maintain::Wait);
let buffer_view = buffer_slice.get_mapped_range();

assert!(
Expand Down

0 comments on commit cb92cc6

Please sign in to comment.