diff --git a/examples/simple/src/main.rs b/examples/simple/src/main.rs index f9175326c..84b8822bc 100644 --- a/examples/simple/src/main.rs +++ b/examples/simple/src/main.rs @@ -62,8 +62,12 @@ fn main() -> Result<()> { // Create a vello Surface let size = window.inner_size(); - let surface_future = - render_cx.create_surface(window.clone(), size.width, size.height); + let surface_future = render_cx.create_surface( + window.clone(), + size.width, + size.height, + wgpu::PresentMode::AutoVsync, + ); let surface = pollster::block_on(surface_future).expect("Error creating surface"); // Create a vello Renderer for the surface (using its device id) diff --git a/examples/with_winit/src/lib.rs b/examples/with_winit/src/lib.rs index eb50cb305..4d68cef44 100644 --- a/examples/with_winit/src/lib.rs +++ b/examples/with_winit/src/lib.rs @@ -4,6 +4,7 @@ use instant::{Duration, Instant}; use std::num::NonZeroUsize; use std::{collections::HashSet, sync::Arc}; +use wgpu_profiler::GpuProfilerSettings; use anyhow::Result; use clap::{CommandFactory, Parser}; @@ -39,6 +40,16 @@ struct Args { #[arg(long)] /// Whether to use CPU shaders use_cpu: bool, + /// Used to disable vsync at startup. Can be toggled with the "V" key. + /// + /// This setting is useful for Android, where it might be harder to press this key + #[arg(long)] + startup_vsync_off: bool, + /// Used to enable gpu profiling at startup. Can be toggled with the "G" key + /// + /// It is off by default because it has adverse performance characteristics + #[arg(long)] + startup_gpu_profiling_on: bool, /// Whether to force initialising the shaders serially (rather than spawning threads) /// This has no effect on wasm, and defaults to 1 on macOS for performance reasons /// @@ -116,7 +127,8 @@ fn run( #[allow(unused_mut)] let mut scene_complexity: Option = None; let mut complexity_shown = false; - let mut vsync_on = true; + let mut vsync_on = !args.startup_vsync_off; + let mut gpu_profiling_on = args.startup_gpu_profiling_on; const AA_CONFIGS: [AaConfig; 3] = [AaConfig::Area, AaConfig::Msaa8, AaConfig::Msaa16]; // We allow cycling through AA configs in either direction, so use a signed index @@ -241,6 +253,19 @@ fn run( }, ); } + "g"=> { + gpu_profiling_on = !gpu_profiling_on; + if let Some(renderer) = &mut renderers[render_state.surface.dev_id] { + renderer + .profiler + .change_settings(GpuProfilerSettings { + enable_timer_queries: gpu_profiling_on, + enable_debug_groups: gpu_profiling_on, + ..Default::default() + }) + .expect("Not setting max_num_pending_frames"); + } + } _ => {} } } @@ -528,7 +553,8 @@ fn run( .take() .unwrap_or_else(|| create_window(event_loop)); let size = window.inner_size(); - let surface_future = render_cx.create_surface(window.clone(), size.width, size.height); + let present_mode = if vsync_on { wgpu::PresentMode::AutoVsync } else { wgpu::PresentMode::AutoNoVsync }; + let surface_future = render_cx.create_surface(window.clone(), size.width, size.height, present_mode); // We need to block here, in case a Suspended event appeared let surface = pollster::block_on(surface_future).expect("Error creating surface"); @@ -538,7 +564,7 @@ fn run( let id = render_state.surface.dev_id; renderers[id].get_or_insert_with(|| { let start = Instant::now(); - let renderer = Renderer::new( + let mut renderer = Renderer::new( &render_cx.devices[id].device, RendererOptions { surface_format: Some(render_state.surface.format), @@ -549,6 +575,11 @@ fn run( ) .expect("Could create renderer"); eprintln!("Creating renderer {id} took {:?}", start.elapsed()); + renderer.profiler.change_settings(GpuProfilerSettings{ + enable_timer_queries: gpu_profiling_on, + enable_debug_groups: gpu_profiling_on, + ..Default::default() + }).expect("Not setting max_num_pending_frames"); renderer }); Some(render_state) @@ -651,7 +682,12 @@ pub fn main() -> Result<()> { winit::dpi::PhysicalSize::from_logical::<_, f64>((width, height), scale_factor); _ = window.request_inner_size(size); let surface = render_cx - .create_surface(window.clone(), size.width, size.height) + .create_surface( + window.clone(), + size.width, + size.height, + wgpu::PresentMode::AutoVsync, + ) .await; if let Ok(surface) = surface { let render_state = RenderState { window, surface }; diff --git a/src/lib.rs b/src/lib.rs index b1be33730..c1291ab67 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -175,7 +175,7 @@ pub struct Renderer { blit: Option, target: Option, #[cfg(feature = "wgpu-profiler")] - profiler: GpuProfiler, + pub profiler: GpuProfiler, #[cfg(feature = "wgpu-profiler")] pub profile_result: Option>, } diff --git a/src/util.rs b/src/util.rs index 919fed453..57545aec0 100644 --- a/src/util.rs +++ b/src/util.rs @@ -43,6 +43,7 @@ impl RenderContext { window: impl Into>, width: u32, height: u32, + present_mode: wgpu::PresentMode, ) -> Result> { let surface = self.instance.create_surface(window.into())?; let dev_id = self @@ -63,7 +64,7 @@ impl RenderContext { format, width, height, - present_mode: wgpu::PresentMode::AutoVsync, + present_mode, desired_maximum_frame_latency: 2, alpha_mode: wgpu::CompositeAlphaMode::Auto, view_formats: vec![], @@ -92,10 +93,6 @@ impl RenderContext { fn configure_surface(&self, surface: &RenderSurface) { let device = &self.devices[surface.dev_id].device; - // Temporary workaround for https://github.com/gfx-rs/wgpu/issues/4214 - // It's still possible for this to panic if the device is being used on another thread - // but this unbreaks most current users - device.poll(wgpu::MaintainBase::Wait); surface.surface.configure(device, &surface.config); }