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",
|
"puffin",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"type-map",
|
"type-map",
|
||||||
|
"web-time",
|
||||||
"wgpu",
|
"wgpu",
|
||||||
"winit",
|
"winit",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@ glow = "0.13"
|
||||||
puffin = "0.18"
|
puffin = "0.18"
|
||||||
raw-window-handle = "0.6.0"
|
raw-window-handle = "0.6.0"
|
||||||
thiserror = "1.0.37"
|
thiserror = "1.0.37"
|
||||||
|
web-time = "0.2" # Timekeeping for native and web
|
||||||
wgpu = { version = "0.19.1", default-features = false, features = [
|
wgpu = { version = "0.19.1", default-features = false, features = [
|
||||||
# Make the renderer `Sync` even on wasm32, because it makes the code simpler:
|
# Make the renderer `Sync` even on wasm32, because it makes the code simpler:
|
||||||
"fragile-send-sync-non-atomic-wasm",
|
"fragile-send-sync-non-atomic-wasm",
|
||||||
|
|
|
||||||
|
|
@ -644,7 +644,7 @@ impl WgpuWinitRunning {
|
||||||
let clipped_primitives = egui_ctx.tessellate(shapes, pixels_per_point);
|
let clipped_primitives = egui_ctx.tessellate(shapes, pixels_per_point);
|
||||||
|
|
||||||
let screenshot_requested = std::mem::take(&mut viewport.screenshot_requested);
|
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,
|
viewport_id,
|
||||||
pixels_per_point,
|
pixels_per_point,
|
||||||
app.clear_color(&egui_ctx.style().visuals),
|
app.clear_color(&egui_ctx.style().visuals),
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ bytemuck = "1.7"
|
||||||
log = { version = "0.4", features = ["std"] }
|
log = { version = "0.4", features = ["std"] }
|
||||||
thiserror.workspace = true
|
thiserror.workspace = true
|
||||||
type-map = "0.5.0"
|
type-map = "0.5.0"
|
||||||
|
web-time.workspace = true
|
||||||
wgpu = { workspace = true, features = ["wgsl"] }
|
wgpu = { workspace = true, features = ["wgsl"] }
|
||||||
|
|
||||||
#! ### Optional dependencies
|
#! ### 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(
|
pub fn paint_and_update_textures(
|
||||||
&mut self,
|
&mut self,
|
||||||
viewport_id: ViewportId,
|
viewport_id: ViewportId,
|
||||||
|
|
@ -513,29 +516,16 @@ impl Painter {
|
||||||
clipped_primitives: &[epaint::ClippedPrimitive],
|
clipped_primitives: &[epaint::ClippedPrimitive],
|
||||||
textures_delta: &epaint::textures::TexturesDelta,
|
textures_delta: &epaint::textures::TexturesDelta,
|
||||||
capture: bool,
|
capture: bool,
|
||||||
) -> Option<epaint::ColorImage> {
|
) -> (f32, Option<epaint::ColorImage>) {
|
||||||
crate::profile_function!();
|
crate::profile_function!();
|
||||||
|
|
||||||
let render_state = self.render_state.as_mut()?;
|
let mut vsync_sec = 0.0;
|
||||||
let surface_state = self.surfaces.get(&viewport_id)?;
|
|
||||||
|
|
||||||
let output_frame = {
|
let Some(render_state) = self.render_state.as_mut() else {
|
||||||
crate::profile_scope!("get_current_texture");
|
return (vsync_sec, None);
|
||||||
// This is what vsync-waiting happens, at least on Mac.
|
|
||||||
surface_state.surface.get_current_texture()
|
|
||||||
};
|
};
|
||||||
|
let Some(surface_state) = self.surfaces.get(&viewport_id) else {
|
||||||
let output_frame = match output_frame {
|
return (vsync_sec, None);
|
||||||
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 mut encoder =
|
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 renderer = render_state.renderer.read();
|
||||||
let frame_view = if capture {
|
let frame_view = if capture {
|
||||||
|
|
@ -589,8 +601,11 @@ impl Painter {
|
||||||
render_state,
|
render_state,
|
||||||
);
|
);
|
||||||
self.screen_capture_state
|
self.screen_capture_state
|
||||||
.as_ref()?
|
.as_ref()
|
||||||
.texture
|
.map_or_else(
|
||||||
|
|| &output_frame.texture,
|
||||||
|
|capture_state| &capture_state.texture,
|
||||||
|
)
|
||||||
.create_view(&wgpu::TextureViewDescriptor::default())
|
.create_view(&wgpu::TextureViewDescriptor::default())
|
||||||
} else {
|
} else {
|
||||||
output_frame
|
output_frame
|
||||||
|
|
@ -654,23 +669,33 @@ impl Painter {
|
||||||
// Submit the commands: both the main buffer and user-defined ones.
|
// Submit the commands: both the main buffer and user-defined ones.
|
||||||
{
|
{
|
||||||
crate::profile_scope!("Queue::submit");
|
crate::profile_scope!("Queue::submit");
|
||||||
|
// wgpu doesn't document where vsync can happen. Maybe here?
|
||||||
|
let start = web_time::Instant::now();
|
||||||
render_state
|
render_state
|
||||||
.queue
|
.queue
|
||||||
.submit(user_cmd_bufs.into_iter().chain([encoded]));
|
.submit(user_cmd_bufs.into_iter().chain([encoded]));
|
||||||
|
vsync_sec += start.elapsed().as_secs_f32();
|
||||||
};
|
};
|
||||||
|
|
||||||
let screenshot = if capture {
|
let screenshot = if capture {
|
||||||
let screen_capture_state = self.screen_capture_state.as_ref()?;
|
self.screen_capture_state
|
||||||
Self::read_screen_rgba(screen_capture_state, render_state, &output_frame)
|
.as_ref()
|
||||||
|
.and_then(|screen_capture_state| {
|
||||||
|
Self::read_screen_rgba(screen_capture_state, render_state, &output_frame)
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
crate::profile_scope!("present");
|
crate::profile_scope!("present");
|
||||||
|
// wgpu doesn't document where vsync can happen. Maybe here?
|
||||||
|
let start = web_time::Instant::now();
|
||||||
output_frame.present();
|
output_frame.present();
|
||||||
|
vsync_sec += start.elapsed().as_secs_f32();
|
||||||
}
|
}
|
||||||
screenshot
|
|
||||||
|
(vsync_sec, screenshot)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gc_viewports(&mut self, active_viewports: &ViewportIdSet) {
|
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"] }
|
log = { version = "0.4", features = ["std"] }
|
||||||
raw-window-handle.workspace = true
|
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"] }
|
winit = { workspace = true, default-features = false, features = ["rwh_06"] }
|
||||||
|
|
||||||
#! ### Optional dependencies
|
#! ### Optional dependencies
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue