mirror of
https://github.com/italicsjenga/vello.git
synced 2025-01-09 20:31:29 +11:00
Add a stats display for scene complexity (#322)
This commit is contained in:
parent
2c394aa265
commit
abfe9fbb56
|
@ -20,5 +20,6 @@ $ cargo run -p with_winit --release -- [SVG FILES]
|
||||||
- Space resets the position and zoom of the image.
|
- Space resets the position and zoom of the image.
|
||||||
- S toggles the frame statistics layer
|
- S toggles the frame statistics layer
|
||||||
- C resets the min/max frame time tracked by statistics
|
- C resets the min/max frame time tracked by statistics
|
||||||
|
- D toggles displaying the required number of each kind of dynamically allocated element (default: off)
|
||||||
- V toggles VSync on/off (default: on)
|
- V toggles VSync on/off (default: on)
|
||||||
- Escape exits the program.
|
- Escape exits the program.
|
||||||
|
|
|
@ -27,7 +27,7 @@ use vello::{
|
||||||
util::RenderContext,
|
util::RenderContext,
|
||||||
Renderer, Scene, SceneBuilder,
|
Renderer, Scene, SceneBuilder,
|
||||||
};
|
};
|
||||||
use vello::{RendererOptions, SceneFragment};
|
use vello::{BumpAllocators, RendererOptions, SceneFragment};
|
||||||
|
|
||||||
use winit::{
|
use winit::{
|
||||||
event_loop::{EventLoop, EventLoopBuilder},
|
event_loop::{EventLoop, EventLoopBuilder},
|
||||||
|
@ -100,6 +100,8 @@ fn run(
|
||||||
let mut images = ImageCache::new();
|
let mut images = ImageCache::new();
|
||||||
let mut stats = stats::Stats::new();
|
let mut stats = stats::Stats::new();
|
||||||
let mut stats_shown = true;
|
let mut stats_shown = true;
|
||||||
|
let mut scene_complexity: Option<BumpAllocators> = None;
|
||||||
|
let mut complexity_shown = false;
|
||||||
let mut vsync_on = true;
|
let mut vsync_on = true;
|
||||||
let mut frame_start_time = Instant::now();
|
let mut frame_start_time = Instant::now();
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
|
@ -150,6 +152,9 @@ fn run(
|
||||||
Some(VirtualKeyCode::S) => {
|
Some(VirtualKeyCode::S) => {
|
||||||
stats_shown = !stats_shown;
|
stats_shown = !stats_shown;
|
||||||
}
|
}
|
||||||
|
Some(VirtualKeyCode::D) => {
|
||||||
|
complexity_shown = !complexity_shown;
|
||||||
|
}
|
||||||
Some(VirtualKeyCode::C) => {
|
Some(VirtualKeyCode::C) => {
|
||||||
stats.clear_min_and_max();
|
stats.clear_min_and_max();
|
||||||
}
|
}
|
||||||
|
@ -326,6 +331,7 @@ fn run(
|
||||||
width as f64,
|
width as f64,
|
||||||
height as f64,
|
height as f64,
|
||||||
stats.samples(),
|
stats.samples(),
|
||||||
|
complexity_shown.then_some(scene_complexity).flatten(),
|
||||||
vsync_on,
|
vsync_on,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -336,7 +342,7 @@ fn run(
|
||||||
.expect("failed to get surface texture");
|
.expect("failed to get surface texture");
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
{
|
{
|
||||||
vello::block_on_wgpu(
|
scene_complexity = vello::block_on_wgpu(
|
||||||
&device_handle.device,
|
&device_handle.device,
|
||||||
renderers[render_state.surface.dev_id]
|
renderers[render_state.surface.dev_id]
|
||||||
.as_mut()
|
.as_mut()
|
||||||
|
|
|
@ -19,7 +19,7 @@ use std::collections::VecDeque;
|
||||||
use vello::{
|
use vello::{
|
||||||
kurbo::{Affine, PathEl, Rect},
|
kurbo::{Affine, PathEl, Rect},
|
||||||
peniko::{Brush, Color, Fill, Stroke},
|
peniko::{Brush, Color, Fill, Stroke},
|
||||||
SceneBuilder,
|
BumpAllocators, SceneBuilder,
|
||||||
};
|
};
|
||||||
|
|
||||||
const SLIDING_WINDOW_SIZE: usize = 100;
|
const SLIDING_WINDOW_SIZE: usize = 100;
|
||||||
|
@ -40,6 +40,7 @@ impl Snapshot {
|
||||||
viewport_width: f64,
|
viewport_width: f64,
|
||||||
viewport_height: f64,
|
viewport_height: f64,
|
||||||
samples: T,
|
samples: T,
|
||||||
|
bump: Option<BumpAllocators>,
|
||||||
vsync: bool,
|
vsync: bool,
|
||||||
) where
|
) where
|
||||||
T: Iterator<Item = &'a u64>,
|
T: Iterator<Item = &'a u64>,
|
||||||
|
@ -59,13 +60,23 @@ impl Snapshot {
|
||||||
&Rect::new(0., 0., width, height),
|
&Rect::new(0., 0., width, height),
|
||||||
);
|
);
|
||||||
|
|
||||||
let labels = [
|
let mut labels = vec![
|
||||||
format!("Frame Time: {:.2} ms", self.frame_time_ms),
|
format!("Frame Time: {:.2} ms", self.frame_time_ms),
|
||||||
format!("Frame Time (min): {:.2} ms", self.frame_time_min_ms),
|
format!("Frame Time (min): {:.2} ms", self.frame_time_min_ms),
|
||||||
format!("Frame Time (max): {:.2} ms", self.frame_time_max_ms),
|
format!("Frame Time (max): {:.2} ms", self.frame_time_max_ms),
|
||||||
format!("VSync: {}", if vsync { "on" } else { "off" }),
|
format!("VSync: {}", if vsync { "on" } else { "off" }),
|
||||||
format!("Resolution: {viewport_width}x{viewport_height}"),
|
format!("Resolution: {viewport_width}x{viewport_height}"),
|
||||||
];
|
];
|
||||||
|
if let Some(bump) = &bump {
|
||||||
|
if bump.failed >= 1 {
|
||||||
|
labels.push(format!("Allocation Failed!"));
|
||||||
|
}
|
||||||
|
labels.push(format!("binning: {}", bump.binning));
|
||||||
|
labels.push(format!("ptcl: {}", bump.ptcl));
|
||||||
|
labels.push(format!("tile: {}", bump.tile));
|
||||||
|
labels.push(format!("segments: {}", bump.segments));
|
||||||
|
labels.push(format!("blend: {}", bump.blend));
|
||||||
|
}
|
||||||
|
|
||||||
// height / 2 is dedicated to the text labels and the rest is filled by the bar graph.
|
// height / 2 is dedicated to the text labels and the rest is filled by the bar graph.
|
||||||
let text_height = height * 0.5 / (1 + labels.len()) as f64;
|
let text_height = height * 0.5 / (1 + labels.len()) as f64;
|
||||||
|
|
25
src/lib.rs
25
src/lib.rs
|
@ -37,6 +37,8 @@ pub use util::block_on_wgpu;
|
||||||
use engine::{Engine, ExternalResource, Recording};
|
use engine::{Engine, ExternalResource, Recording};
|
||||||
use shaders::FullShaders;
|
use shaders::FullShaders;
|
||||||
|
|
||||||
|
/// Temporary export, used in with_winit for stats
|
||||||
|
pub use vello_encoding::BumpAllocators;
|
||||||
use wgpu::{Device, Queue, SurfaceTexture, TextureFormat, TextureView};
|
use wgpu::{Device, Queue, SurfaceTexture, TextureFormat, TextureView};
|
||||||
|
|
||||||
/// Catch-all error type.
|
/// Catch-all error type.
|
||||||
|
@ -196,6 +198,12 @@ impl Renderer {
|
||||||
/// The texture is assumed to be of the specified dimensions and have been created with
|
/// The texture is assumed to be of the specified dimensions and have been created with
|
||||||
/// the [wgpu::TextureFormat::Rgba8Unorm] format and the [wgpu::TextureUsages::STORAGE_BINDING]
|
/// the [wgpu::TextureFormat::Rgba8Unorm] format and the [wgpu::TextureUsages::STORAGE_BINDING]
|
||||||
/// flag set.
|
/// flag set.
|
||||||
|
///
|
||||||
|
/// The return value is the value of the `BumpAllocators` in this rendering, which is currently used
|
||||||
|
/// for debug output.
|
||||||
|
///
|
||||||
|
/// This return type is not stable, and will likely be changed when a more principled way to access
|
||||||
|
/// relevant statistics is implemented
|
||||||
pub async fn render_to_texture_async(
|
pub async fn render_to_texture_async(
|
||||||
&mut self,
|
&mut self,
|
||||||
device: &Device,
|
device: &Device,
|
||||||
|
@ -203,13 +211,15 @@ impl Renderer {
|
||||||
scene: &Scene,
|
scene: &Scene,
|
||||||
texture: &TextureView,
|
texture: &TextureView,
|
||||||
params: &RenderParams,
|
params: &RenderParams,
|
||||||
) -> Result<()> {
|
) -> Result<Option<BumpAllocators>> {
|
||||||
let mut render = Render::new();
|
let mut render = Render::new();
|
||||||
let encoding = scene.data();
|
let encoding = scene.data();
|
||||||
let recording = render.render_encoding_coarse(encoding, &self.shaders, params, true);
|
let recording = render.render_encoding_coarse(encoding, &self.shaders, params, true);
|
||||||
let target = render.out_image();
|
let target = render.out_image();
|
||||||
let bump_buf = render.bump_buf();
|
let bump_buf = render.bump_buf();
|
||||||
self.engine.run_recording(device, queue, &recording, &[])?;
|
self.engine.run_recording(device, queue, &recording, &[])?;
|
||||||
|
|
||||||
|
let mut bump: Option<BumpAllocators> = None;
|
||||||
if let Some(bump_buf) = self.engine.get_download(bump_buf) {
|
if let Some(bump_buf) = self.engine.get_download(bump_buf) {
|
||||||
let buf_slice = bump_buf.slice(..);
|
let buf_slice = bump_buf.slice(..);
|
||||||
let (sender, receiver) = futures_intrusive::channel::shared::oneshot_channel();
|
let (sender, receiver) = futures_intrusive::channel::shared::oneshot_channel();
|
||||||
|
@ -219,8 +229,8 @@ impl Renderer {
|
||||||
} else {
|
} else {
|
||||||
return Err("channel was closed".into());
|
return Err("channel was closed".into());
|
||||||
}
|
}
|
||||||
let _mapped = buf_slice.get_mapped_range();
|
let mapped = buf_slice.get_mapped_range();
|
||||||
// println!("{:?}", bytemuck::cast_slice::<_, u32>(&mapped));
|
bump = Some(bytemuck::pod_read_unaligned(&*mapped));
|
||||||
}
|
}
|
||||||
// TODO: apply logic to determine whether we need to rerun coarse, and also
|
// TODO: apply logic to determine whether we need to rerun coarse, and also
|
||||||
// allocate the blend stack as needed.
|
// allocate the blend stack as needed.
|
||||||
|
@ -231,7 +241,7 @@ impl Renderer {
|
||||||
let external_resources = [ExternalResource::Image(target, texture)];
|
let external_resources = [ExternalResource::Image(target, texture)];
|
||||||
self.engine
|
self.engine
|
||||||
.run_recording(device, queue, &recording, &external_resources)?;
|
.run_recording(device, queue, &recording, &external_resources)?;
|
||||||
Ok(())
|
Ok(bump)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See [Self::render_to_surface]
|
/// See [Self::render_to_surface]
|
||||||
|
@ -242,7 +252,7 @@ impl Renderer {
|
||||||
scene: &Scene,
|
scene: &Scene,
|
||||||
surface: &SurfaceTexture,
|
surface: &SurfaceTexture,
|
||||||
params: &RenderParams,
|
params: &RenderParams,
|
||||||
) -> Result<()> {
|
) -> Result<Option<BumpAllocators>> {
|
||||||
let width = params.width;
|
let width = params.width;
|
||||||
let height = params.height;
|
let height = params.height;
|
||||||
let mut target = self
|
let mut target = self
|
||||||
|
@ -254,7 +264,8 @@ impl Renderer {
|
||||||
if target.width != width || target.height != height {
|
if target.width != width || target.height != height {
|
||||||
target = TargetTexture::new(device, width, height);
|
target = TargetTexture::new(device, width, height);
|
||||||
}
|
}
|
||||||
self.render_to_texture_async(device, queue, scene, &target.view, params)
|
let bump = self
|
||||||
|
.render_to_texture_async(device, queue, scene, &target.view, params)
|
||||||
.await?;
|
.await?;
|
||||||
let blit = self
|
let blit = self
|
||||||
.blit
|
.blit
|
||||||
|
@ -292,7 +303,7 @@ impl Renderer {
|
||||||
}
|
}
|
||||||
queue.submit(Some(encoder.finish()));
|
queue.submit(Some(encoder.finish()));
|
||||||
self.target = Some(target);
|
self.target = Some(target);
|
||||||
Ok(())
|
Ok(bump)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue