From cb92cc64ab1c5a4da218d2b707e63597c4557172 Mon Sep 17 00:00:00 2001 From: Connor Fitzgerald Date: Sat, 4 Jun 2022 02:26:36 -0400 Subject: [PATCH] Unify Maintain in both wgc and wgpu --- deno_webgpu/src/buffer.rs | 2 +- player/src/bin/play.rs | 2 +- player/tests/test.rs | 2 +- wgpu-core/src/device/mod.rs | 25 +++++++------ wgpu-core/src/device/queue.rs | 2 +- wgpu-types/src/lib.rs | 37 +++++++++++++++++++ wgpu/examples/framework.rs | 2 +- wgpu/examples/hello-compute/main.rs | 2 +- wgpu/examples/mipmap/main.rs | 2 +- wgpu/src/backend/direct.rs | 11 ++---- wgpu/src/lib.rs | 18 ++------- wgpu/tests/common/mod.rs | 6 +-- wgpu/tests/poll.rs | 16 ++++---- wgpu/tests/vertex_indices/mod.rs | 2 +- wgpu/tests/zero_init_texture_after_discard.rs | 2 +- 15 files changed, 78 insertions(+), 53 deletions(-) diff --git a/deno_webgpu/src/buffer.rs b/deno_webgpu/src/buffer.rs index 1eb331863e2..23ba5ede9fa 100644 --- a/deno_webgpu/src/buffer.rs +++ b/deno_webgpu/src/buffer.rs @@ -128,7 +128,7 @@ pub async fn op_webgpu_buffer_get_map_async( { let state = state.borrow(); let instance = state.borrow::(); - 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; } diff --git a/player/src/bin/play.rs b/player/src/bin/play.rs index f05e66f56d2..9b5722490c1 100644 --- a/player/src/bin/play.rs +++ b/player/src/bin/play.rs @@ -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")] { diff --git a/player/tests/test.rs b/player/tests/test.rs index fd96f321733..7d1c156a260 100644 --- a/player/tests/test.rs +++ b/player/tests/test.rs @@ -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); diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index 495c62d299d..6e6574d7256 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -439,8 +439,7 @@ impl Device { fn maintain<'this, 'token: 'this, G: GlobalIdentityHandlerFactory>( &'this self, hub: &Hub, - force_wait: bool, - submission_index: Option, + maintain: wgt::Maintain, token: &mut Token<'token, Self>, ) -> Result<(UserClosures, bool), WaitIdleError> { profiling::scope!("maintain", "Device"); @@ -464,14 +463,14 @@ impl Device { ); 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 @@ -4975,11 +4974,10 @@ impl Global { pub fn device_poll( &self, device_id: id::DeviceId, - force_wait: bool, - submission_index: Option, + maintain: wgt::Maintain, ) -> Result { 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, @@ -4994,7 +4992,7 @@ impl Global { 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(); @@ -5022,7 +5020,12 @@ impl Global { 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 diff --git a/wgpu-core/src/device/queue.rs b/wgpu-core/src/device/queue.rs index 7246199c2b0..8b1a6622721 100644 --- a/wgpu-core/src/device/queue.rs +++ b/wgpu-core/src/device/queue.rs @@ -925,7 +925,7 @@ impl Global { // 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), diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index 7a74f713340..88e2a01205e 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -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 { + /// 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 Maintain { + /// 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(self, func: F) -> Maintain + 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`]. diff --git a/wgpu/examples/framework.rs b/wgpu/examples/framework.rs index ddab7ce68f9..0ed135f1cd9 100644 --- a/wgpu/examples/framework.rs +++ b/wgpu/examples/framework.rs @@ -518,7 +518,7 @@ pub fn test(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( diff --git a/wgpu/examples/hello-compute/main.rs b/wgpu/examples/hello-compute/main.rs index c5d58921abe..bbff9130f4e 100644 --- a/wgpu/examples/hello-compute/main.rs +++ b/wgpu/examples/hello-compute/main.rs @@ -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 { diff --git a/wgpu/examples/mipmap/main.rs b/wgpu/examples/mipmap/main.rs index 3570bdaf461..9603895d575 100644 --- a/wgpu/examples/mipmap/main.rs +++ b/wgpu/examples/mipmap/main.rs @@ -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 diff --git a/wgpu/src/backend/direct.rs b/wgpu/src/backend/direct.rs index 72dd6967598..e62ada1a001 100644 --- a/wgpu/src/backend/direct.rs +++ b/wgpu/src/backend/direct.rs @@ -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"), } @@ -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"), diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index 2bc59906b7c..b645927cad0 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -557,21 +557,6 @@ pub struct Device { #[derive(Debug, Copy, Clone)] pub struct SubmissionIndex(::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), - /// 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)] @@ -1263,6 +1248,9 @@ pub type TextureDescriptor<'a> = wgt::TextureDescriptor>; /// Corresponds to [WebGPU `GPUQuerySetDescriptor`]( /// https://gpuweb.github.io/gpuweb/#dictdef-gpuquerysetdescriptor). pub type QuerySetDescriptor<'a> = wgt::QuerySetDescriptor>; +pub use wgt::Maintain as MaintainBase; +/// Passed to [`Device::poll`] to control how and if it should block. +pub type Maintain = wgt::Maintain; /// Describes a [`TextureView`]. /// diff --git a/wgpu/tests/common/mod.rs b/wgpu/tests/common/mod.rs index 8daa0b71c67..b0df54d2f19 100644 --- a/wgpu/tests/common/mod.rs +++ b/wgpu/tests/common/mod.rs @@ -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, @@ -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, @@ -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), diff --git a/wgpu/tests/poll.rs b/wgpu/tests/poll.rs index 7409a96ffce..6113436d0bb 100644 --- a/wgpu/tests/poll.rs +++ b/wgpu/tests/poll.rs @@ -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); }) } @@ -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); }) } @@ -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)); }) } @@ -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)); }) } @@ -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)); }) } diff --git a/wgpu/tests/vertex_indices/mod.rs b/wgpu/tests/vertex_indices/mod.rs index 1bc362f7db0..fa85ae62d95 100644 --- a/wgpu/tests/vertex_indices/mod.rs +++ b/wgpu/tests/vertex_indices/mod.rs @@ -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 = bytemuck::cast_slice(&*slice.get_mapped_range()).to_vec(); assert_eq!(data, expected); diff --git a/wgpu/tests/zero_init_texture_after_discard.rs b/wgpu/tests/zero_init_texture_after_discard.rs index 488778aff13..ec77e909f0b 100644 --- a/wgpu/tests/zero_init_texture_after_discard.rs +++ b/wgpu/tests/zero_init_texture_after_discard.rs @@ -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!(