mirror of
https://github.com/italicsjenga/vello.git
synced 2025-01-08 20:01:30 +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.
|
||||
- S toggles the frame statistics layer
|
||||
- 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)
|
||||
- Escape exits the program.
|
||||
|
|
|
@ -27,7 +27,7 @@ use vello::{
|
|||
util::RenderContext,
|
||||
Renderer, Scene, SceneBuilder,
|
||||
};
|
||||
use vello::{RendererOptions, SceneFragment};
|
||||
use vello::{BumpAllocators, RendererOptions, SceneFragment};
|
||||
|
||||
use winit::{
|
||||
event_loop::{EventLoop, EventLoopBuilder},
|
||||
|
@ -100,6 +100,8 @@ fn run(
|
|||
let mut images = ImageCache::new();
|
||||
let mut stats = stats::Stats::new();
|
||||
let mut stats_shown = true;
|
||||
let mut scene_complexity: Option<BumpAllocators> = None;
|
||||
let mut complexity_shown = false;
|
||||
let mut vsync_on = true;
|
||||
let mut frame_start_time = Instant::now();
|
||||
let start = Instant::now();
|
||||
|
@ -150,6 +152,9 @@ fn run(
|
|||
Some(VirtualKeyCode::S) => {
|
||||
stats_shown = !stats_shown;
|
||||
}
|
||||
Some(VirtualKeyCode::D) => {
|
||||
complexity_shown = !complexity_shown;
|
||||
}
|
||||
Some(VirtualKeyCode::C) => {
|
||||
stats.clear_min_and_max();
|
||||
}
|
||||
|
@ -326,6 +331,7 @@ fn run(
|
|||
width as f64,
|
||||
height as f64,
|
||||
stats.samples(),
|
||||
complexity_shown.then_some(scene_complexity).flatten(),
|
||||
vsync_on,
|
||||
);
|
||||
}
|
||||
|
@ -336,7 +342,7 @@ fn run(
|
|||
.expect("failed to get surface texture");
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
{
|
||||
vello::block_on_wgpu(
|
||||
scene_complexity = vello::block_on_wgpu(
|
||||
&device_handle.device,
|
||||
renderers[render_state.surface.dev_id]
|
||||
.as_mut()
|
||||
|
|
|
@ -19,7 +19,7 @@ use std::collections::VecDeque;
|
|||
use vello::{
|
||||
kurbo::{Affine, PathEl, Rect},
|
||||
peniko::{Brush, Color, Fill, Stroke},
|
||||
SceneBuilder,
|
||||
BumpAllocators, SceneBuilder,
|
||||
};
|
||||
|
||||
const SLIDING_WINDOW_SIZE: usize = 100;
|
||||
|
@ -40,6 +40,7 @@ impl Snapshot {
|
|||
viewport_width: f64,
|
||||
viewport_height: f64,
|
||||
samples: T,
|
||||
bump: Option<BumpAllocators>,
|
||||
vsync: bool,
|
||||
) where
|
||||
T: Iterator<Item = &'a u64>,
|
||||
|
@ -59,13 +60,23 @@ impl Snapshot {
|
|||
&Rect::new(0., 0., width, height),
|
||||
);
|
||||
|
||||
let labels = [
|
||||
let mut labels = vec![
|
||||
format!("Frame Time: {:.2} ms", self.frame_time_ms),
|
||||
format!("Frame Time (min): {:.2} ms", self.frame_time_min_ms),
|
||||
format!("Frame Time (max): {:.2} ms", self.frame_time_max_ms),
|
||||
format!("VSync: {}", if vsync { "on" } else { "off" }),
|
||||
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.
|
||||
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 shaders::FullShaders;
|
||||
|
||||
/// Temporary export, used in with_winit for stats
|
||||
pub use vello_encoding::BumpAllocators;
|
||||
use wgpu::{Device, Queue, SurfaceTexture, TextureFormat, TextureView};
|
||||
|
||||
/// 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 [wgpu::TextureFormat::Rgba8Unorm] format and the [wgpu::TextureUsages::STORAGE_BINDING]
|
||||
/// 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(
|
||||
&mut self,
|
||||
device: &Device,
|
||||
|
@ -203,13 +211,15 @@ impl Renderer {
|
|||
scene: &Scene,
|
||||
texture: &TextureView,
|
||||
params: &RenderParams,
|
||||
) -> Result<()> {
|
||||
) -> Result<Option<BumpAllocators>> {
|
||||
let mut render = Render::new();
|
||||
let encoding = scene.data();
|
||||
let recording = render.render_encoding_coarse(encoding, &self.shaders, params, true);
|
||||
let target = render.out_image();
|
||||
let bump_buf = render.bump_buf();
|
||||
self.engine.run_recording(device, queue, &recording, &[])?;
|
||||
|
||||
let mut bump: Option<BumpAllocators> = None;
|
||||
if let Some(bump_buf) = self.engine.get_download(bump_buf) {
|
||||
let buf_slice = bump_buf.slice(..);
|
||||
let (sender, receiver) = futures_intrusive::channel::shared::oneshot_channel();
|
||||
|
@ -219,8 +229,8 @@ impl Renderer {
|
|||
} else {
|
||||
return Err("channel was closed".into());
|
||||
}
|
||||
let _mapped = buf_slice.get_mapped_range();
|
||||
// println!("{:?}", bytemuck::cast_slice::<_, u32>(&mapped));
|
||||
let mapped = buf_slice.get_mapped_range();
|
||||
bump = Some(bytemuck::pod_read_unaligned(&*mapped));
|
||||
}
|
||||
// TODO: apply logic to determine whether we need to rerun coarse, and also
|
||||
// allocate the blend stack as needed.
|
||||
|
@ -231,7 +241,7 @@ impl Renderer {
|
|||
let external_resources = [ExternalResource::Image(target, texture)];
|
||||
self.engine
|
||||
.run_recording(device, queue, &recording, &external_resources)?;
|
||||
Ok(())
|
||||
Ok(bump)
|
||||
}
|
||||
|
||||
/// See [Self::render_to_surface]
|
||||
|
@ -242,7 +252,7 @@ impl Renderer {
|
|||
scene: &Scene,
|
||||
surface: &SurfaceTexture,
|
||||
params: &RenderParams,
|
||||
) -> Result<()> {
|
||||
) -> Result<Option<BumpAllocators>> {
|
||||
let width = params.width;
|
||||
let height = params.height;
|
||||
let mut target = self
|
||||
|
@ -254,7 +264,8 @@ impl Renderer {
|
|||
if target.width != width || target.height != 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?;
|
||||
let blit = self
|
||||
.blit
|
||||
|
@ -292,7 +303,7 @@ impl Renderer {
|
|||
}
|
||||
queue.submit(Some(encoder.finish()));
|
||||
self.target = Some(target);
|
||||
Ok(())
|
||||
Ok(bump)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue