Skip to content

Commit

Permalink
Disable the async pipeline by default (#500)
Browse files Browse the repository at this point in the history
* Handle profiling in the non-async pipeline

* Make the async pipeline optional

* Profile the blit stage

* Apply review suggestions

Co-Authored-By: "Spencer C. Imbleau" <[email protected]>

---------

Co-authored-by: "Spencer C. Imbleau" <[email protected]>
  • Loading branch information
DJMcNab and simbleau authored Mar 5, 2024
1 parent e39e340 commit ec5c8a4
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 23 deletions.
42 changes: 26 additions & 16 deletions examples/with_winit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,16 @@ struct Args {
/// Use `0` for an automatic choice
#[arg(long, default_value_t=default_threads())]
num_init_threads: usize,
/// Use the asynchronous pipeline (if available) for rendering
///
/// The asynchronous pipeline is one approach for robust memory - see
/// <https://github.com/linebender/vello/issues/366>
///
/// However, it also has potential latency issues, especially for
/// accessibility technology, as it (currently) blocks the main thread for
/// extended periods
#[arg(long)]
async_pipeline: bool,
}

fn default_threads() -> usize {
Expand Down Expand Up @@ -451,8 +461,10 @@ fn run(
.surface
.get_current_texture()
.expect("failed to get surface texture");
#[cfg(not(target_arch = "wasm32"))]
{
// Note: we don't run the async/"robust" pipeline, as
// it requires more async wiring for the readback. See
// [#gpu > async on wasm](https://xi.zulipchat.com/#narrow/stream/197075-gpu/topic/async.20on.20wasm)
if args.async_pipeline && cfg!(not(target_arch = "wasm32")) {
scene_complexity = vello::block_on_wgpu(
&device_handle.device,
renderers[render_state.surface.dev_id]
Expand All @@ -467,21 +479,19 @@ fn run(
),
)
.expect("failed to render to surface");
} else {
renderers[render_state.surface.dev_id]
.as_mut()
.unwrap()
.render_to_surface(
&device_handle.device,
&device_handle.queue,
&scene,
&surface_texture,
&render_params,
)
.expect("failed to render to surface");
}
// Note: in the wasm case, we're currently not running the robust
// pipeline, as it requires more async wiring for the readback.
#[cfg(target_arch = "wasm32")]
renderers[render_state.surface.dev_id]
.as_mut()
.unwrap()
.render_to_surface(
&device_handle.device,
&device_handle.queue,
&scene,
&surface_texture,
&render_params,
)
.expect("failed to render to surface");
surface_texture.present();
device_handle.device.poll(wgpu::Maintain::Poll);

Expand Down
31 changes: 25 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,12 +362,27 @@ impl Renderer {
occlusion_query_set: None,
timestamp_writes: None,
});
let mut render_pass = self
.profiler
.scope("blit to surface", &mut render_pass, device);
render_pass.set_pipeline(&blit.pipeline);
render_pass.set_bind_group(0, &bind_group, &[]);
render_pass.draw(0..6, 0..1);
}
#[cfg(feature = "wgpu-profiler")]
self.profiler.resolve_queries(&mut encoder);
queue.submit(Some(encoder.finish()));
self.target = Some(target);
#[cfg(feature = "wgpu-profiler")]
{
self.profiler.end_frame().unwrap();
if let Some(result) = self
.profiler
.process_finished_frame(queue.get_timestamp_period())
{
self.profile_result = Some(result);
}
}
Ok(())
}

Expand Down Expand Up @@ -510,6 +525,9 @@ impl Renderer {
timestamp_writes: None,
occlusion_query_set: None,
});
let mut render_pass = self
.profiler
.scope("blit to surface", &mut render_pass, device);
render_pass.set_pipeline(&blit.pipeline);
render_pass.set_bind_group(0, &bind_group, &[]);
render_pass.draw(0..6, 0..1);
Expand All @@ -519,13 +537,14 @@ impl Renderer {
queue.submit(Some(encoder.finish()));
self.target = Some(target);
#[cfg(feature = "wgpu-profiler")]
self.profiler.end_frame().unwrap();
#[cfg(feature = "wgpu-profiler")]
if let Some(result) = self
.profiler
.process_finished_frame(queue.get_timestamp_period())
{
self.profile_result = Some(result);
self.profiler.end_frame().unwrap();
if let Some(result) = self
.profiler
.process_finished_frame(queue.get_timestamp_period())
{
self.profile_result = Some(result);
}
}
Ok(bump)
}
Expand Down
5 changes: 4 additions & 1 deletion src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,13 @@ impl std::task::Wake for NullWake {
///
/// This will deadlock if the future is awaiting anything other than GPU progress.
pub fn block_on_wgpu<F: Future>(device: &Device, mut fut: F) -> F::Output {
if cfg!(target_arch = "wasm32") {
panic!("Blocking can't work on WASM, so");
}
let waker = std::task::Waker::from(std::sync::Arc::new(NullWake));
let mut context = std::task::Context::from_waker(&waker);
// Same logic as `pin_mut!` macro from `pin_utils`.
let mut fut = unsafe { std::pin::Pin::new_unchecked(&mut fut) };
let mut fut = std::pin::pin!(fut);
loop {
match fut.as_mut().poll(&mut context) {
std::task::Poll::Pending => {
Expand Down

0 comments on commit ec5c8a4

Please sign in to comment.