Opt-in logging of egui-wgpu using puffin
This commit is contained in:
parent
b2edbe617e
commit
e225c6b8d0
6 changed files with 100 additions and 25 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -1175,6 +1175,7 @@ dependencies = [
|
|||
"document-features",
|
||||
"egui",
|
||||
"pollster",
|
||||
"puffin",
|
||||
"tracing",
|
||||
"type-map",
|
||||
"wgpu",
|
||||
|
|
|
@ -47,7 +47,7 @@ persistence = [
|
|||
##
|
||||
## Only enabled on native, because of the low resolution (1ms) of time keeping in browsers.
|
||||
## `eframe` will call `puffin::GlobalProfiler::lock().new_frame()` for you
|
||||
puffin = ["dep:puffin", "egui_glow?/puffin"]
|
||||
puffin = ["dep:puffin", "egui_glow?/puffin", "egui-wgpu?/puffin"]
|
||||
|
||||
## Enable screen reader support (requires `ctx.options().screen_reader = true;`)
|
||||
screen_reader = ["egui-winit/screen_reader", "tts"]
|
||||
|
|
|
@ -3,9 +3,9 @@ name = "egui-wgpu"
|
|||
version = "0.19.0"
|
||||
description = "Bindings for using egui natively using the wgpu library"
|
||||
authors = [
|
||||
"Nils Hasenbanck <nils@hasenbanck.de>",
|
||||
"embotech <opensource@embotech.com>",
|
||||
"Emil Ernerfeldt <emil.ernerfeldt@gmail.com>",
|
||||
"Nils Hasenbanck <nils@hasenbanck.de>",
|
||||
"embotech <opensource@embotech.com>",
|
||||
"Emil Ernerfeldt <emil.ernerfeldt@gmail.com>",
|
||||
]
|
||||
edition = "2021"
|
||||
rust-version = "1.62"
|
||||
|
@ -28,13 +28,16 @@ all-features = true
|
|||
|
||||
|
||||
[features]
|
||||
## Enable profiling with the [`puffin`](https://docs.rs/puffin) crate.
|
||||
puffin = ["dep:puffin"]
|
||||
|
||||
## Enable [`winit`](https://docs.rs/winit) integration.
|
||||
winit = ["dep:pollster", "dep:winit"]
|
||||
|
||||
|
||||
[dependencies]
|
||||
egui = { version = "0.19.0", path = "../egui", default-features = false, features = [
|
||||
"bytemuck",
|
||||
"bytemuck",
|
||||
] }
|
||||
|
||||
bytemuck = "1.7"
|
||||
|
@ -48,3 +51,7 @@ document-features = { version = "0.2", optional = true }
|
|||
|
||||
pollster = { version = "0.2", optional = true }
|
||||
winit = { version = "0.27.2", optional = true }
|
||||
|
||||
# Native:
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||
puffin = { version = "0.14", optional = true }
|
||||
|
|
|
@ -95,3 +95,25 @@ pub fn preferred_framebuffer_format(formats: &[wgpu::TextureFormat]) -> wgpu::Te
|
|||
}
|
||||
formats[0] // take the first
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Profiling macro for feature "puffin"
|
||||
macro_rules! profile_function {
|
||||
($($arg: tt)*) => {
|
||||
#[cfg(feature = "puffin")]
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
puffin::profile_function!($($arg)*);
|
||||
};
|
||||
}
|
||||
pub(crate) use profile_function;
|
||||
|
||||
/// Profiling macro for feature "puffin"
|
||||
macro_rules! profile_scope {
|
||||
($($arg: tt)*) => {
|
||||
#[cfg(feature = "puffin")]
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
puffin::profile_scope!($($arg)*);
|
||||
};
|
||||
}
|
||||
pub(crate) use profile_scope;
|
||||
|
|
|
@ -174,6 +174,8 @@ impl Renderer {
|
|||
output_depth_format: Option<wgpu::TextureFormat>,
|
||||
msaa_samples: u32,
|
||||
) -> Self {
|
||||
crate::profile_function!();
|
||||
|
||||
let shader = wgpu::ShaderModuleDescriptor {
|
||||
label: Some("egui"),
|
||||
source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!("egui.wgsl"))),
|
||||
|
@ -347,6 +349,8 @@ impl Renderer {
|
|||
paint_jobs: &[egui::epaint::ClippedPrimitive],
|
||||
screen_descriptor: &ScreenDescriptor,
|
||||
) {
|
||||
crate::profile_function!();
|
||||
|
||||
let pixels_per_point = screen_descriptor.pixels_per_point;
|
||||
let size_in_pixels = screen_descriptor.size_in_pixels;
|
||||
|
||||
|
@ -421,6 +425,8 @@ impl Renderer {
|
|||
};
|
||||
|
||||
if callback.rect.is_positive() {
|
||||
crate::profile_scope!("callback");
|
||||
|
||||
needs_reset = true;
|
||||
|
||||
{
|
||||
|
@ -472,6 +478,8 @@ impl Renderer {
|
|||
id: egui::TextureId,
|
||||
image_delta: &egui::epaint::ImageDelta,
|
||||
) {
|
||||
crate::profile_function!();
|
||||
|
||||
let width = image_delta.image.width() as u32;
|
||||
let height = image_delta.image.height() as u32;
|
||||
|
||||
|
@ -653,6 +661,8 @@ impl Renderer {
|
|||
texture: &wgpu::TextureView,
|
||||
sampler_descriptor: wgpu::SamplerDescriptor<'_>,
|
||||
) -> egui::TextureId {
|
||||
crate::profile_function!();
|
||||
|
||||
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
|
||||
compare: None,
|
||||
..sampler_descriptor
|
||||
|
@ -692,6 +702,8 @@ impl Renderer {
|
|||
sampler_descriptor: wgpu::SamplerDescriptor<'_>,
|
||||
id: egui::TextureId,
|
||||
) {
|
||||
crate::profile_function!();
|
||||
|
||||
let (_user_texture, user_texture_binding) = self
|
||||
.textures
|
||||
.get_mut(&id)
|
||||
|
@ -732,20 +744,26 @@ impl Renderer {
|
|||
paint_jobs: &[egui::epaint::ClippedPrimitive],
|
||||
screen_descriptor: &ScreenDescriptor,
|
||||
) -> Vec<wgpu::CommandBuffer> {
|
||||
crate::profile_function!();
|
||||
|
||||
let screen_size_in_points = screen_descriptor.screen_size_in_points();
|
||||
|
||||
// Update uniform buffer
|
||||
queue.write_buffer(
|
||||
&self.uniform_buffer,
|
||||
0,
|
||||
bytemuck::cast_slice(&[UniformBuffer {
|
||||
screen_size_in_points,
|
||||
_padding: Default::default(),
|
||||
}]),
|
||||
);
|
||||
{
|
||||
crate::profile_scope!("uniforms");
|
||||
// Update uniform buffer
|
||||
queue.write_buffer(
|
||||
&self.uniform_buffer,
|
||||
0,
|
||||
bytemuck::cast_slice(&[UniformBuffer {
|
||||
screen_size_in_points,
|
||||
_padding: Default::default(),
|
||||
}]),
|
||||
);
|
||||
}
|
||||
|
||||
// Determine how many vertices & indices need to be rendered.
|
||||
let (vertex_count, index_count) =
|
||||
let (vertex_count, index_count) = {
|
||||
crate::profile_scope!("count_vertices_indices");
|
||||
paint_jobs.iter().fold((0, 0), |acc, clipped_primitive| {
|
||||
match &clipped_primitive.primitive {
|
||||
Primitive::Mesh(mesh) => {
|
||||
|
@ -753,9 +771,11 @@ impl Renderer {
|
|||
}
|
||||
Primitive::Callback(_) => acc,
|
||||
}
|
||||
});
|
||||
// Resize index buffer if needed.
|
||||
})
|
||||
};
|
||||
|
||||
{
|
||||
// Resize index buffer if needed:
|
||||
self.index_buffer.slices.clear();
|
||||
let required_size = (std::mem::size_of::<u32>() * index_count) as u64;
|
||||
if self.index_buffer.capacity < required_size {
|
||||
|
@ -764,8 +784,9 @@ impl Renderer {
|
|||
self.index_buffer.buffer = create_index_buffer(device, self.index_buffer.capacity);
|
||||
}
|
||||
}
|
||||
// Resize vertex buffer if needed.
|
||||
|
||||
{
|
||||
// Resize vertex buffer if needed:
|
||||
self.vertex_buffer.slices.clear();
|
||||
let required_size = (std::mem::size_of::<Vertex>() * vertex_count) as u64;
|
||||
if self.vertex_buffer.capacity < required_size {
|
||||
|
@ -778,6 +799,8 @@ impl Renderer {
|
|||
|
||||
// Upload index & vertex data and call user callbacks
|
||||
let mut user_cmd_bufs = Vec::new(); // collect user command buffers
|
||||
|
||||
crate::profile_scope!("primitives");
|
||||
for egui::ClippedPrimitive { primitive, .. } in paint_jobs.iter() {
|
||||
match primitive {
|
||||
Primitive::Mesh(mesh) => {
|
||||
|
@ -806,6 +829,7 @@ impl Renderer {
|
|||
continue;
|
||||
};
|
||||
|
||||
crate::profile_scope!("callback");
|
||||
user_cmd_bufs.extend((cbfn.prepare)(
|
||||
device,
|
||||
queue,
|
||||
|
@ -841,6 +865,7 @@ fn create_sampler(options: egui::TextureOptions, device: &wgpu::Device) -> wgpu:
|
|||
}
|
||||
|
||||
fn create_vertex_buffer(device: &wgpu::Device, size: u64) -> wgpu::Buffer {
|
||||
crate::profile_function!();
|
||||
device.create_buffer(&wgpu::BufferDescriptor {
|
||||
label: Some("egui_vertex_buffer"),
|
||||
usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
|
||||
|
@ -850,6 +875,7 @@ fn create_vertex_buffer(device: &wgpu::Device, size: u64) -> wgpu::Buffer {
|
|||
}
|
||||
|
||||
fn create_index_buffer(device: &wgpu::Device, size: u64) -> wgpu::Buffer {
|
||||
crate::profile_function!();
|
||||
device.create_buffer(&wgpu::BufferDescriptor {
|
||||
label: Some("egui_index_buffer"),
|
||||
usage: wgpu::BufferUsages::INDEX | wgpu::BufferUsages::COPY_DST,
|
||||
|
|
|
@ -109,6 +109,8 @@ impl Painter {
|
|||
}
|
||||
|
||||
fn configure_surface(&mut self, width_in_pixels: u32, height_in_pixels: u32) {
|
||||
crate::profile_function!();
|
||||
|
||||
let render_state = self
|
||||
.render_state
|
||||
.as_ref()
|
||||
|
@ -227,6 +229,8 @@ impl Painter {
|
|||
clipped_primitives: &[egui::ClippedPrimitive],
|
||||
textures_delta: &egui::TexturesDelta,
|
||||
) {
|
||||
crate::profile_function!();
|
||||
|
||||
let render_state = match self.render_state.as_mut() {
|
||||
Some(rs) => rs,
|
||||
None => return,
|
||||
|
@ -237,7 +241,13 @@ impl Painter {
|
|||
};
|
||||
let (width, height) = (surface_state.width, surface_state.height);
|
||||
|
||||
let output_frame = match surface_state.surface.get_current_texture() {
|
||||
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 output_frame = match output_frame {
|
||||
Ok(frame) => frame,
|
||||
#[allow(clippy::single_match_else)]
|
||||
Err(e) => match (*self.configuration.on_surface_error)(e) {
|
||||
|
@ -326,15 +336,24 @@ impl Painter {
|
|||
}
|
||||
}
|
||||
|
||||
let encoded = {
|
||||
crate::profile_scope!("CommandEncoder::finish");
|
||||
encoder.finish()
|
||||
};
|
||||
|
||||
// Submit the commands: both the main buffer and user-defined ones.
|
||||
render_state.queue.submit(
|
||||
user_cmd_bufs
|
||||
.into_iter()
|
||||
.chain(std::iter::once(encoder.finish())),
|
||||
);
|
||||
{
|
||||
crate::profile_scope!("Queue::submit");
|
||||
render_state
|
||||
.queue
|
||||
.submit(user_cmd_bufs.into_iter().chain(std::iter::once(encoded)));
|
||||
};
|
||||
|
||||
// Redraw egui
|
||||
output_frame.present();
|
||||
{
|
||||
crate::profile_scope!("present");
|
||||
output_frame.present();
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::unused_self)]
|
||||
|
|
Loading…
Reference in a new issue