Postpone call to get_current_texture (#3914)
This should help slightly with CPU/GPU parallelism when vsync is on. I also return the time spent on vsync, which can help users figure out how much CPU wall-time was used on non-vsync stuff
This commit is contained in:
parent
1d1b07c6b2
commit
21253d844e
|
|
@ -1239,6 +1239,7 @@ dependencies = [
|
|||
"puffin",
|
||||
"thiserror",
|
||||
"type-map",
|
||||
"web-time",
|
||||
"wgpu",
|
||||
"winit",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ glow = "0.13"
|
|||
puffin = "0.18"
|
||||
raw-window-handle = "0.6.0"
|
||||
thiserror = "1.0.37"
|
||||
web-time = "0.2" # Timekeeping for native and web
|
||||
wgpu = { version = "0.19.1", default-features = false, features = [
|
||||
# Make the renderer `Sync` even on wasm32, because it makes the code simpler:
|
||||
"fragile-send-sync-non-atomic-wasm",
|
||||
|
|
|
|||
|
|
@ -644,7 +644,7 @@ impl WgpuWinitRunning {
|
|||
let clipped_primitives = egui_ctx.tessellate(shapes, pixels_per_point);
|
||||
|
||||
let screenshot_requested = std::mem::take(&mut viewport.screenshot_requested);
|
||||
let screenshot = painter.paint_and_update_textures(
|
||||
let (_vsync_secs, screenshot) = painter.paint_and_update_textures(
|
||||
viewport_id,
|
||||
pixels_per_point,
|
||||
app.clear_color(&egui_ctx.style().visuals),
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ bytemuck = "1.7"
|
|||
log = { version = "0.4", features = ["std"] }
|
||||
thiserror.workspace = true
|
||||
type-map = "0.5.0"
|
||||
web-time.workspace = true
|
||||
wgpu = { workspace = true, features = ["wgsl"] }
|
||||
|
||||
#! ### Optional dependencies
|
||||
|
|
|
|||
|
|
@ -504,7 +504,10 @@ impl Painter {
|
|||
})
|
||||
}
|
||||
|
||||
// Returns a vector with the frame's pixel data if it was requested.
|
||||
/// Returns two things:
|
||||
///
|
||||
/// The approximate number of seconds spent on vsync-waiting (if any),
|
||||
/// and the captures captured screenshot if it was requested.
|
||||
pub fn paint_and_update_textures(
|
||||
&mut self,
|
||||
viewport_id: ViewportId,
|
||||
|
|
@ -513,29 +516,16 @@ impl Painter {
|
|||
clipped_primitives: &[epaint::ClippedPrimitive],
|
||||
textures_delta: &epaint::textures::TexturesDelta,
|
||||
capture: bool,
|
||||
) -> Option<epaint::ColorImage> {
|
||||
) -> (f32, Option<epaint::ColorImage>) {
|
||||
crate::profile_function!();
|
||||
|
||||
let render_state = self.render_state.as_mut()?;
|
||||
let surface_state = self.surfaces.get(&viewport_id)?;
|
||||
let mut vsync_sec = 0.0;
|
||||
|
||||
let output_frame = {
|
||||
crate::profile_scope!("get_current_texture");
|
||||
// This is what vsync-waiting happens, at least on Mac.
|
||||
surface_state.surface.get_current_texture()
|
||||
let Some(render_state) = self.render_state.as_mut() else {
|
||||
return (vsync_sec, None);
|
||||
};
|
||||
|
||||
let output_frame = match output_frame {
|
||||
Ok(frame) => frame,
|
||||
Err(err) => match (*self.configuration.on_surface_error)(err) {
|
||||
SurfaceErrorAction::RecreateSurface => {
|
||||
Self::configure_surface(surface_state, render_state, &self.configuration);
|
||||
return None;
|
||||
}
|
||||
SurfaceErrorAction::SkipFrame => {
|
||||
return None;
|
||||
}
|
||||
},
|
||||
let Some(surface_state) = self.surfaces.get(&viewport_id) else {
|
||||
return (vsync_sec, None);
|
||||
};
|
||||
|
||||
let mut encoder =
|
||||
|
|
@ -580,6 +570,28 @@ impl Painter {
|
|||
}
|
||||
};
|
||||
|
||||
let output_frame = {
|
||||
crate::profile_scope!("get_current_texture");
|
||||
// This is what vsync-waiting happens on my Mac.
|
||||
let start = web_time::Instant::now();
|
||||
let output_frame = surface_state.surface.get_current_texture();
|
||||
vsync_sec += start.elapsed().as_secs_f32();
|
||||
output_frame
|
||||
};
|
||||
|
||||
let output_frame = match output_frame {
|
||||
Ok(frame) => frame,
|
||||
Err(err) => match (*self.configuration.on_surface_error)(err) {
|
||||
SurfaceErrorAction::RecreateSurface => {
|
||||
Self::configure_surface(surface_state, render_state, &self.configuration);
|
||||
return (vsync_sec, None);
|
||||
}
|
||||
SurfaceErrorAction::SkipFrame => {
|
||||
return (vsync_sec, None);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
{
|
||||
let renderer = render_state.renderer.read();
|
||||
let frame_view = if capture {
|
||||
|
|
@ -589,8 +601,11 @@ impl Painter {
|
|||
render_state,
|
||||
);
|
||||
self.screen_capture_state
|
||||
.as_ref()?
|
||||
.texture
|
||||
.as_ref()
|
||||
.map_or_else(
|
||||
|| &output_frame.texture,
|
||||
|capture_state| &capture_state.texture,
|
||||
)
|
||||
.create_view(&wgpu::TextureViewDescriptor::default())
|
||||
} else {
|
||||
output_frame
|
||||
|
|
@ -654,23 +669,33 @@ impl Painter {
|
|||
// Submit the commands: both the main buffer and user-defined ones.
|
||||
{
|
||||
crate::profile_scope!("Queue::submit");
|
||||
// wgpu doesn't document where vsync can happen. Maybe here?
|
||||
let start = web_time::Instant::now();
|
||||
render_state
|
||||
.queue
|
||||
.submit(user_cmd_bufs.into_iter().chain([encoded]));
|
||||
vsync_sec += start.elapsed().as_secs_f32();
|
||||
};
|
||||
|
||||
let screenshot = if capture {
|
||||
let screen_capture_state = self.screen_capture_state.as_ref()?;
|
||||
Self::read_screen_rgba(screen_capture_state, render_state, &output_frame)
|
||||
self.screen_capture_state
|
||||
.as_ref()
|
||||
.and_then(|screen_capture_state| {
|
||||
Self::read_screen_rgba(screen_capture_state, render_state, &output_frame)
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
{
|
||||
crate::profile_scope!("present");
|
||||
// wgpu doesn't document where vsync can happen. Maybe here?
|
||||
let start = web_time::Instant::now();
|
||||
output_frame.present();
|
||||
vsync_sec += start.elapsed().as_secs_f32();
|
||||
}
|
||||
screenshot
|
||||
|
||||
(vsync_sec, screenshot)
|
||||
}
|
||||
|
||||
pub fn gc_viewports(&mut self, active_viewports: &ViewportIdSet) {
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ egui = { version = "0.25.0", path = "../egui", default-features = false, feature
|
|||
] }
|
||||
log = { version = "0.4", features = ["std"] }
|
||||
raw-window-handle.workspace = true
|
||||
web-time = { version = "0.2" } # We use web-time so we can (maybe) compile for web
|
||||
web-time.workspace = true
|
||||
winit = { workspace = true, default-features = false, features = ["rwh_06"] }
|
||||
|
||||
#! ### Optional dependencies
|
||||
|
|
|
|||
Loading…
Reference in New Issue