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