Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Debug and Validation Layers #416

Merged
merged 24 commits into from
Aug 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
23d34a5
Add engine support for draw calls
armansito May 16, 2024
90c18f0
Use a Recording for the blit render pipeline
armansito Dec 9, 2023
15ca4cb
debug_layers feature
armansito Dec 9, 2023
ce5abc9
[vello][engine] Buffer offset binding
armansito Dec 12, 2023
4f94209
Fix hot_reload when debug layers are enabled
armansito Dec 12, 2023
bfebc05
[debug_layers] Validation, LineSoup visualization, and UI toggles
armansito Dec 12, 2023
ed3e017
cargo fmt
armansito Jun 5, 2024
53b9c81
[debug] Thicken lines and show winding
armansito Jun 8, 2024
eefc505
Address review feedback
DJMcNab Jul 29, 2024
6f5d11a
Fix handling of debug layers memory management
DJMcNab Jul 29, 2024
9c3afa2
Reduce opacity of the `clear_tint` layer
DJMcNab Jul 29, 2024
02e7fc0
Add comment about alpha factor
DJMcNab Jul 29, 2024
1c9fc78
Fix clippy issues
DJMcNab Jul 29, 2024
f44d217
Always expose control over `DebugLayers`
DJMcNab Jul 30, 2024
bdf9e34
Add missing copyright header
DJMcNab Jul 30, 2024
aeb1968
Document `DebugLayers`
DJMcNab Jul 30, 2024
fe4b67b
Rename `check_bits` to `contains`
DJMcNab Jul 30, 2024
9944518
Add `{0}` in download error
DJMcNab Jul 30, 2024
9327ba2
Add a warning message if using debug_layers without the async pipeline
DJMcNab Jul 30, 2024
d6d436c
Address review feedback
DJMcNab Jul 30, 2024
7bf41f1
Always enable debug_layers in `with_winit`
DJMcNab Aug 2, 2024
c09d27f
Double check that CI still validates the without debug_layers scenario
DJMcNab Aug 2, 2024
58c9b38
Fix rebase change
DJMcNab Aug 2, 2024
f6abadf
Revert c09d27fd1a76406fbe195e3ff3eb8496d98a663a
DJMcNab Aug 2, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/headless/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ async fn render(mut scenes: SceneSet, index: usize, args: &Args) -> Result<()> {
width,
height,
antialiasing_method: vello::AaConfig::Area,
debug: vello::DebugLayers::none(),
};
let mut scene = Scene::new();
scene.append(&fragment, Some(transform));
Expand Down
3 changes: 2 additions & 1 deletion examples/simple/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::sync::Arc;
use vello::kurbo::{Affine, Circle, Ellipse, Line, RoundedRect, Stroke};
use vello::peniko::Color;
use vello::util::{RenderContext, RenderSurface};
use vello::{AaConfig, Renderer, RendererOptions, Scene};
use vello::{AaConfig, DebugLayers, Renderer, RendererOptions, Scene};
use winit::application::ApplicationHandler;
use winit::dpi::LogicalSize;
use winit::event::*;
Expand Down Expand Up @@ -151,6 +151,7 @@ impl<'s> ApplicationHandler for SimpleVelloApp<'s> {
width,
height,
antialiasing_method: AaConfig::Msaa16,
debug: DebugLayers::none(),
},
)
.expect("failed to render to surface");
Expand Down
3 changes: 2 additions & 1 deletion examples/with_winit/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ workspace = true
name = "with_winit_bin"
path = "src/main.rs"


[dependencies]
vello = { workspace = true, features = ["buffer_labels"] }
vello = { workspace = true, features = ["buffer_labels", "debug_layers"] }
scenes = { workspace = true }

anyhow = { workspace = true }
Expand Down
28 changes: 28 additions & 0 deletions examples/with_winit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ struct VelloApp<'s> {

prev_scene_ix: i32,
modifiers: ModifiersState,

debug: vello::DebugLayers,
}

impl<'s> ApplicationHandler<UserEvent> for VelloApp<'s> {
Expand Down Expand Up @@ -329,6 +331,27 @@ impl<'s> ApplicationHandler<UserEvent> for VelloApp<'s> {
},
);
}
debug_layer @ ("1" | "2" | "3" | "4") => {
match debug_layer {
"1" => {
self.debug.toggle(vello::DebugLayers::BOUNDING_BOXES);
}
"2" => {
self.debug
.toggle(vello::DebugLayers::LINESOUP_SEGMENTS);
}
"3" => {
self.debug.toggle(vello::DebugLayers::LINESOUP_POINTS);
}
"4" => {
self.debug.toggle(vello::DebugLayers::VALIDATION);
}
_ => unreachable!(),
}
if !self.debug.is_empty() && !self.async_pipeline {
log::warn!("Debug Layers won't work without using `--async-pipeline`. Requested {:?}", self.debug);
}
}
_ => {}
}
}
Expand Down Expand Up @@ -464,6 +487,7 @@ impl<'s> ApplicationHandler<UserEvent> for VelloApp<'s> {
width,
height,
antialiasing_method,
debug: self.debug,
};
self.scene.reset();
let mut transform = self.transform;
Expand Down Expand Up @@ -674,6 +698,8 @@ fn run(
Some(render_state)
};

let debug = vello::DebugLayers::none();

let mut app = VelloApp {
context: render_cx,
renderers,
Expand Down Expand Up @@ -718,6 +744,7 @@ fn run(
complexity: 0,
prev_scene_ix: 0,
modifiers: ModifiersState::default(),
debug,
};

event_loop.run_app(&mut app).expect("run to completion");
Expand Down Expand Up @@ -786,6 +813,7 @@ pub fn main() -> anyhow::Result<()> {
#[cfg(not(target_arch = "wasm32"))]
env_logger::builder()
.format_timestamp(Some(env_logger::TimestampPrecision::Millis))
.filter_level(log::LevelFilter::Warn)
.init();
let args = parse_arguments();
let scenes = args.args.select_scene_set()?;
Expand Down
1 change: 1 addition & 0 deletions vello/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ default = ["wgpu"]
bump_estimate = ["vello_encoding/bump_estimate"]
hot_reload = ["vello_shaders/compile"]
buffer_labels = []
debug_layers = []
wgpu = ["dep:wgpu"]
wgpu-profiler = ["dep:wgpu-profiler"]

Expand Down
119 changes: 119 additions & 0 deletions vello/src/debug.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// Copyright 2023 the Vello Authors
// SPDX-License-Identifier: Apache-2.0 OR MIT

#[cfg(all(feature = "debug_layers", feature = "wgpu"))]
mod renderer;
#[cfg(all(feature = "debug_layers", feature = "wgpu"))]
mod validate;

use std::fmt::Debug;

#[cfg(all(feature = "debug_layers", feature = "wgpu"))]
pub(crate) use renderer::*;

/// Bitflags for enabled debug operations.
///
/// Currently, all layers additionally require the `debug_layers` feature.
#[derive(Copy, Clone)]
pub struct DebugLayers(u8);

impl Debug for DebugLayers {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut tuple = f.debug_tuple("DebugLayers");
if self.contains(Self::BOUNDING_BOXES) {
tuple.field(&"BOUNDING_BOXES");
}
if self.contains(Self::LINESOUP_SEGMENTS) {
tuple.field(&"LINESOUP_SEGMENTS");
}
if self.contains(Self::LINESOUP_POINTS) {
tuple.field(&"LINESOUP_POINTS");
}
if self.contains(Self::VALIDATION) {
tuple.field(&"VALIDATION");
}

tuple.finish()
}
}

// TODO: Currently all layers require read-back of the BumpAllocators buffer. This isn't strictly
// necessary for layers other than `VALIDATION`. The debug visualizations use the bump buffer only
// to obtain various instance counts for draws and these could instead get written out to an
// indirect draw buffer. OTOH `VALIDATION` should always require readback since we want to be able
// to run the same CPU-side tests for both CPU and GPU shaders.
impl DebugLayers {
/// Visualize the bounding box of every path.
/// Requires the `debug_layers` feature.
pub const BOUNDING_BOXES: DebugLayers = DebugLayers(1 << 0);

/// Visualize the post-flattening line segments using line primitives.
/// Requires the `debug_layers` feature.
pub const LINESOUP_SEGMENTS: DebugLayers = DebugLayers(1 << 1);

/// Visualize the post-flattening line endpoints.
/// Requires the `debug_layers` feature.
pub const LINESOUP_POINTS: DebugLayers = DebugLayers(1 << 2);

/// Enable validation of internal buffer contents and visualize errors. Validation tests are
/// run on the CPU and require buffer contents to be read-back.
///
/// Supported validation tests:
///
/// - Watertightness: validate that every line segment within a path is connected without
/// any gaps. Line endpoints that don't precisely overlap another endpoint get visualized
/// as red circles and logged to stderr.
///
/// Requires the `debug_layers` feature.
pub const VALIDATION: DebugLayers = DebugLayers(1 << 3);

/// Construct a `DebugLayers` from the raw bits.
pub const fn from_bits(bits: u8) -> Self {
Self(bits)
}

/// Get the raw representation of this value.
pub const fn bits(self) -> u8 {
self.0
}

/// A `DebugLayers` with no layers enabled.
pub const fn none() -> Self {
Self(0)
}

/// A `DebugLayers` with all layers enabled.
pub const fn all() -> Self {
// Custom BitOr is not const, so need to manipulate the inner value here
Self(
Self::BOUNDING_BOXES.0
| Self::LINESOUP_SEGMENTS.0
| Self::LINESOUP_POINTS.0
| Self::VALIDATION.0,
)
}

/// True if this `DebugLayers` has no layers enabled.
pub const fn is_empty(self) -> bool {
self.0 == 0
}

/// Determine whether `self` is a superset of `mask`.
pub const fn contains(self, mask: DebugLayers) -> bool {
self.0 & mask.0 == mask.0
}

/// Toggle the value of the layers specified in mask.
pub fn toggle(&mut self, mask: DebugLayers) {
self.0 ^= mask.0;
}
}

/// Returns the union of the two input `DebugLayers`.
impl std::ops::BitOr for DebugLayers {
type Output = Self;

fn bitor(self, rhs: Self) -> Self {
Self(self.0 | rhs.0)
}
}
Loading