WIP bump allocator logging
diff --git a/Cargo.toml b/Cargo.toml
index 67eaecc..d751831 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -44,7 +44,7 @@
 bump_estimate = ["vello_encoding/bump_estimate"]
 hot_reload = []
 buffer_labels = []
-debug_layers = []
+debug_layers = ["bump_estimate"]
 
 [dependencies]
 bytemuck = { workspace = true }
diff --git a/crates/encoding/src/config.rs b/crates/encoding/src/config.rs
index 9a2eae3..ceb1a2b 100644
--- a/crates/encoding/src/config.rs
+++ b/crates/encoding/src/config.rs
@@ -382,12 +382,12 @@
         // The following buffer sizes have been hand picked to accommodate the vello test scenes as
         // well as paris-30k. These should instead get derived from the scene layout using
         // reasonable heuristics.
-        let bin_data = BufferSize::new(1 << 18);
-        let tiles = BufferSize::new(1 << 21);
-        let lines = BufferSize::new(1 << 21);
-        let seg_counts = BufferSize::new(1 << 21);
-        let segments = BufferSize::new(1 << 21);
-        let ptcl = BufferSize::new(1 << 23);
+        let bin_data = BufferSize::new(1 << 22);
+        let tiles = BufferSize::new(1 << 22);
+        let lines = BufferSize::new(1 << 22);
+        let seg_counts = BufferSize::new(1 << 22);
+        let segments = BufferSize::new(1 << 22);
+        let ptcl = BufferSize::new(1 << 22);
         Self {
             path_reduced,
             path_reduced2,
diff --git a/examples/scenes/src/lib.rs b/examples/scenes/src/lib.rs
index b0974f5..2d59917 100644
--- a/examples/scenes/src/lib.rs
+++ b/examples/scenes/src/lib.rs
@@ -16,7 +16,11 @@
 pub use svg::{default_scene, scene_from_files};
 pub use test_scenes::test_scenes;
 
-use vello::{kurbo::Vec2, peniko::Color, Scene};
+use vello::{
+    kurbo::{Affine, Vec2},
+    peniko::Color,
+    Scene,
+};
 
 pub struct SceneParams<'a> {
     pub time: f64,
@@ -29,6 +33,7 @@
     pub resolution: Option<Vec2>,
     pub base_color: Option<vello::peniko::Color>,
     pub complexity: usize,
+    pub transform: Option<&'a Affine>,
 }
 
 pub struct SceneConfig {
diff --git a/examples/scenes/src/mmark.rs b/examples/scenes/src/mmark.rs
index 1657338..666247d 100644
--- a/examples/scenes/src/mmark.rs
+++ b/examples/scenes/src/mmark.rs
@@ -92,7 +92,7 @@
                 // gets it from the first, but this should not matter.
                 scene.stroke(
                     &Stroke::new(element.width),
-                    Affine::IDENTITY,
+                    params.transform.map(|t| *t).unwrap_or(Affine::IDENTITY),
                     element.color,
                     None,
                     &path,
@@ -103,6 +103,7 @@
                 element.is_split ^= true;
             }
         }
+        /*
         let label = format!("mmark test: {} path elements (up/down to adjust)", n);
         params.text.add(
             scene,
@@ -111,7 +112,7 @@
             None,
             Affine::translate((100.0, 1100.0)),
             &label,
-        );
+        );*/
     }
 }
 
diff --git a/examples/scenes/src/test_scenes.rs b/examples/scenes/src/test_scenes.rs
index b43746e..cb0b455 100644
--- a/examples/scenes/src/test_scenes.rs
+++ b/examples/scenes/src/test_scenes.rs
@@ -2,7 +2,7 @@
 // SPDX-License-Identifier: Apache-2.0 OR MIT
 
 use crate::{ExampleScene, SceneConfig, SceneParams, SceneSet};
-use vello::kurbo::{Affine, BezPath, Cap, Ellipse, Join, PathEl, Point, Rect, Stroke};
+use vello::kurbo::{Affine, BezPath, Cap, Ellipse, Join, PathEl, Point, Rect, RoundedRect, Stroke};
 use vello::peniko::*;
 use vello::*;
 
@@ -31,7 +31,14 @@
 
 pub fn test_scenes() -> SceneSet {
     let scenes = vec![
+        scene!(single_curve(None, false), "single fill", false),
+        scene!(single_curve(Some(Cap::Butt), false), "stroke butt", false),
+        scene!(single_curve(Some(Cap::Round), false), "stroke round", false),
+        scene!(single_curve(None, true), "single fill", false),
+        scene!(single_curve(Some(Cap::Butt), true), "stroke butt", false),
+        scene!(single_curve(Some(Cap::Round), true), "stroke round", false),
         scene!(splash_with_tiger(), "splash_with_tiger", false),
+        scene!(zulip_hang),
         scene!(funky_paths),
         scene!(stroke_styles(Affine::IDENTITY), "stroke_styles", false),
         scene!(
@@ -67,7 +74,7 @@
 
 // Scenes
 
-fn funky_paths(scene: &mut Scene, _: &mut SceneParams) {
+fn funky_paths(scene: &mut Scene, params: &mut SceneParams) {
     use PathEl::*;
     let missing_movetos = [
         MoveTo((0., 0.).into()),
@@ -79,30 +86,31 @@
     ];
     let only_movetos = [MoveTo((0.0, 0.0).into()), MoveTo((100.0, 100.0).into())];
     let empty: [PathEl; 0] = [];
+    let t = params.transform.map(|t| *t).unwrap_or(Affine::IDENTITY);
     scene.fill(
         Fill::NonZero,
-        Affine::translate((100.0, 100.0)),
+        t * Affine::translate((100.0, 100.0)),
         Color::rgb8(0, 0, 255),
         None,
         &missing_movetos,
     );
     scene.fill(
         Fill::NonZero,
-        Affine::IDENTITY,
+        t,
         Color::rgb8(0, 0, 255),
         None,
         &empty,
     );
     scene.fill(
         Fill::NonZero,
-        Affine::IDENTITY,
+        t,
         Color::rgb8(0, 0, 255),
         None,
         &only_movetos,
     );
     scene.stroke(
         &Stroke::new(8.0),
-        Affine::translate((100.0, 100.0)),
+        t * Affine::translate((100.0, 100.0)),
         Color::rgb8(0, 255, 255),
         None,
         &missing_movetos,
@@ -280,7 +288,7 @@
 
 // This test has been adapted from Skia's "trickycubicstrokes" GM slide which can be found at
 // `github.com/google/skia/blob/0d4d11451c4f4e184305cbdbd67f6b3edfa4b0e3/gm/trickycubicstrokes.cpp`
-fn tricky_strokes(scene: &mut Scene, _: &mut SceneParams) {
+fn tricky_strokes(scene: &mut Scene, params: &mut SceneParams) {
     use PathEl::*;
     let colors = [
         Color::rgb8(140, 181, 236),
@@ -352,6 +360,7 @@
         let cell = Rect::new(x, y, x + CELL_SIZE, y + CELL_SIZE);
         let bounds = stroke_bounds(&cubic);
         let (t, s) = map_rect_to_rect(&bounds, &cell);
+        let t = params.transform.map(|t| *t).unwrap_or(Affine::IDENTITY) * t;
         scene.stroke(
             &Stroke::new(STROKE_WIDTH / s)
                 .with_caps(Cap::Butt)
@@ -462,7 +471,7 @@
 fn longpathdash(cap: Cap) -> impl FnMut(&mut Scene, &mut SceneParams) {
     use std::f64::consts::PI;
     use PathEl::*;
-    move |scene, _| {
+    move |scene, params| {
         let mut path = BezPath::new();
         let mut x = 32;
         while x < 256 {
@@ -496,7 +505,7 @@
                 .with_caps(cap)
                 .with_join(Join::Bevel)
                 .with_dashes(0.0, [1.0, 1.0]),
-            Affine::translate((50.0, 50.0)),
+            params.transform.map(|t| *t).unwrap_or(Affine::IDENTITY) * Affine::translate((50.0, 50.0)),
             Color::YELLOW,
             None,
             &path,
@@ -1439,3 +1448,472 @@
         splash_screen(scene, params);
     }
 }
+
+fn zulip_hang(scene: &mut Scene, params: &mut SceneParams) {
+    use PathEl::*;
+    let clip_alpha = 0.1;
+
+    {
+        let clip_rect = Rect::from_origin_size(Point::new(0., 0.), (800., 600.));
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+
+        let shape = [
+        	MoveTo(
+				(15.0, 27.0).into(),
+			),
+			CurveTo(
+				(14.999999999999998, 20.37258300203048).into(),
+				(20.372583002030478, 15.000000000000002).into(),
+				(26.999999999999996, 15.0).into(),
+			),
+			LineTo(
+				(773.0, 15.0).into(),
+			),
+			CurveTo(
+				(779.6274169979695, 14.999999999999998).into(),
+				(785.0, 20.372583002030478).into(),
+				(785.0, 26.999999999999996).into(),
+			),
+			LineTo(
+				(785.0, 573.0).into(),
+			),
+			CurveTo(
+				(785.0, 579.6274169979695).into(),
+				(779.6274169979695, 585.0).into(),
+				(773.0, 585.0).into(),
+			),
+			LineTo(
+				(27.0, 585.0).into(),
+			),
+			CurveTo(
+				(20.37258300203048, 585.0).into(),
+				(15.000000000000002, 579.6274169979695).into(),
+				(15.0, 573.0).into(),
+			),
+			ClosePath,
+        ];
+		scene.fill(Fill::NonZero, Affine::IDENTITY, &Brush::Solid(Color::WHITE), None, &shape);
+        scene.pop_layer();
+    }
+    {
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(0., 0.), (800., 600.)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(15., 15.), (770., 32.)),
+			(12., 12., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+
+        scene.pop_layer();
+        scene.pop_layer();
+    }
+    {
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(0., 0.), (800., 600.)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(15., 15.), (770., 32.)),
+			(12., 12., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(0., 0.), (770., 32.)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+
+        scene.pop_layer();
+        scene.pop_layer();
+        scene.pop_layer();
+    }
+    {
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(0., 0.), (800., 600.)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(15., 15.), (770., 32.)),
+			(12., 12., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(0., 0.), (770., 32.)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(369.6399984359741, 5.), (30.720003128051758, 22.)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+
+        params.text.add(scene, None, 10., None, Affine::IDENTITY, "hello");
+
+        scene.pop_layer();
+        scene.pop_layer();
+        scene.pop_layer();
+        scene.pop_layer();
+    }
+    {
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(0., 0.), (800., 600.)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(15., 47.), (770., 538.)),
+			(0., 0., 12., 12.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(0., 0.), (770., 538.)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+
+        scene.pop_layer();
+        scene.pop_layer();
+        scene.pop_layer();
+    }
+    {
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(0., 0.), (800., 600.)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(15., 47.), (770., 538.)),
+			(0., 0., 12., 12.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(0., 0.), (770., 538.)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(0., 0.), (770., 179.33333333333334)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+
+        scene.pop_layer();
+        scene.pop_layer();
+        scene.pop_layer();
+        scene.pop_layer();
+    }
+    {
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(0., 0.), (800., 600.)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(15., 47.), (770., 538.)),
+			(0., 0., 12., 12.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(0., 0.), (770., 538.)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(0., 0.), (770., 179.33333333333334)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(0., 0.), (104.56001281738281, 44.)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+
+        params.text.add(scene, None, 10., None, Affine::IDENTITY, "hello");
+
+        scene.pop_layer();
+        scene.pop_layer();
+        scene.pop_layer();
+        scene.pop_layer();
+        scene.pop_layer();
+    }
+    {
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(0., 0.), (800., 600.)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(15., 47.), (770., 538.)),
+			(0., 0., 12., 12.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(0., 0.), (770., 538.)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(0., 0.), (770., 179.33333333333334)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(110., 0.), (104.56001281738281, 44.)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+
+        params.text.add(scene, None, 10., None, Affine::IDENTITY, "hello");
+
+        scene.pop_layer();
+        scene.pop_layer();
+        scene.pop_layer();
+        scene.pop_layer();
+        scene.pop_layer();
+    }
+    {
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(0., 0.), (800., 600.)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(15., 47.), (770., 538.)),
+			(0., 0., 12., 12.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(0., 0.), (770., 538.)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(0., 0.), (770., 179.33333333333334)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(220., 0.), (104.56001281738281, 44.)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+
+        params.text.add(scene, None, 10., None, Affine::IDENTITY, "hello");
+
+        scene.pop_layer();
+        scene.pop_layer();
+        scene.pop_layer();
+        scene.pop_layer();
+        scene.pop_layer();
+    }
+    {
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(0., 0.), (800., 600.)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(15., 47.), (770., 538.)),
+			(0., 0., 12., 12.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(0., 0.), (770., 538.)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(0., 0.), (770., 179.33333333333334)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(330., 0.), (104.56001281738281, 44.)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+
+        params.text.add(scene, None, 10., None, Affine::IDENTITY, "hello");
+
+        scene.pop_layer();
+        scene.pop_layer();
+        scene.pop_layer();
+        scene.pop_layer();
+        scene.pop_layer();
+    }
+    {
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(0., 0.), (800., 600.)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(15., 47.), (770., 538.)),
+			(0., 0., 12., 12.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(0., 0.), (770., 538.)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(0., 0.), (770., 179.33333333333334)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(440., 0.), (104.56001281738281, 44.)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+
+        params.text.add(scene, None, 10., None, Affine::IDENTITY, "hello");
+
+        scene.pop_layer();
+        scene.pop_layer();
+        scene.pop_layer();
+        scene.pop_layer();
+        scene.pop_layer();
+    }
+    {
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(0., 0.), (800., 600.)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(15., 47.), (770., 538.)),
+			(0., 0., 12., 12.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(0., 0.), (770., 538.)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(0., 0.), (770., 179.33333333333334)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(550., 0.), (104.56001281738281, 44.)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+
+        params.text.add(scene, None, 10., None, Affine::IDENTITY, "hello");
+
+        scene.pop_layer();
+        scene.pop_layer();
+        scene.pop_layer();
+        scene.pop_layer();
+        scene.pop_layer();
+    }
+    {
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(0., 0.), (800., 600.)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(15., 47.), (770., 538.)),
+			(0., 0., 12., 12.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(0., 0.), (770., 538.)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(0., 0.), (770., 179.33333333333334)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(660., 0.), (104.56001281738281, 44.)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+
+        params.text.add(scene, None, 10., None, Affine::IDENTITY, "hello");
+
+        scene.pop_layer();
+        scene.pop_layer();
+        scene.pop_layer();
+        scene.pop_layer();
+        scene.pop_layer();
+    }
+    {
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(0., 0.), (800., 600.)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(15., 47.), (770., 538.)),
+			(0., 0., 12., 12.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(0., 0.), (770., 538.)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+        let clip_rect = RoundedRect::from_rect(
+			Rect::from_origin_size(Point::new(0., 0.), (770., 179.33333333333334)),
+			(0., 0., 0., 0.),
+        );
+        scene.push_layer(Mix::Clip, clip_alpha, Affine::IDENTITY, &clip_rect);
+
+        scene.pop_layer();
+        scene.pop_layer();
+        scene.pop_layer();
+        scene.pop_layer();
+    }
+}
+
+fn single_curve(cap: Option<Cap>, curvy: bool) -> impl FnMut(&mut Scene, &mut SceneParams) {
+    move |scene, params| {
+        use PathEl::*;
+        let path = if curvy {
+            [
+                MoveTo((140., 220.).into()),
+                CurveTo((454., 350.).into(), (54., 102.).into(), (386.,  242.).into()),
+            ]
+        } else {
+            [
+                MoveTo((50., 50.).into()),
+                CurveTo((200., 100.).into(), (280., 100.).into(), (300.,  50.).into()),
+            ]
+        };
+        match cap {
+            Some(c) => scene.stroke(
+                &Stroke::new(10.)
+                    .with_caps(c)
+                    .with_join(Join::Bevel),
+                    //.with_dashes(0.0, [1.0, 1.0]),
+                params.transform.map(|t| *t).unwrap_or(Affine::IDENTITY),
+                Color::YELLOW,
+                None,
+                &path,
+            ),
+            None => scene.fill(
+                Fill::NonZero,
+                params.transform.map(|t| *t).unwrap_or(Affine::IDENTITY),
+                Color::YELLOW,
+                None,
+                &path,
+            ),
+        }
+    }
+}
diff --git a/examples/with_winit/Cargo.toml b/examples/with_winit/Cargo.toml
index 214022b..a2658c1 100644
--- a/examples/with_winit/Cargo.toml
+++ b/examples/with_winit/Cargo.toml
@@ -37,7 +37,7 @@
 log = "0.4.17"
 
 [target.'cfg(not(any(target_arch = "wasm32", target_os = "android")))'.dependencies]
-vello = { path = "../../", features = ["hot_reload"] }
+vello = { path = "../../", features = ["hot_reload", "bump_estimate"] }
 notify-debouncer-mini = "0.3"
 
 
diff --git a/examples/with_winit/src/lib.rs b/examples/with_winit/src/lib.rs
index 7ee1776..6f45432 100644
--- a/examples/with_winit/src/lib.rs
+++ b/examples/with_winit/src/lib.rs
@@ -139,6 +139,8 @@
 
     #[cfg(feature = "debug_layers")]
     let mut debug = vello::DebugLayers::none();
+    //    #[cfg(feature = "debug_layers")]
+    let mut debug_dump_time = Instant::now();
 
     // _event_loop is used on non-wasm platforms to create new windows
     event_loop.run(move |event, _event_loop, control_flow| match event {
@@ -377,6 +379,7 @@
                 base_color: None,
                 interactive: true,
                 complexity,
+                transform: None, //Some(&transform),
             };
             example_scene
                 .function
@@ -439,6 +442,7 @@
                     );
                 }
             }
+            let new_time = Instant::now();
             let surface_texture = render_state
                 .surface
                 .surface
@@ -460,6 +464,27 @@
                         ),
                 )
                 .expect("failed to render to surface");
+                if (new_time - debug_dump_time).as_secs() > 2 {
+                    let bump_estimate = scene.bump_estimate(None);
+                    println!(
+                        "Last frame estimated bump buffer counts:{}\n",
+                        bump_estimate
+                    );
+                    debug_dump_time = new_time;
+                    #[cfg(feature = "debug_layers")]
+                    {
+                        let bump = scene_complexity.as_ref().unwrap();
+                        println!(
+                            "Last frame actual bump buffer counts:{}\n \
+                                 \tBlend:\t\t\t{}\n\
+                                 \tError Bits:\t\t0x{:#08x}\n\
+                                 --------\n",
+                            bump.memory(),
+                            bump.blend,
+                            bump.failed
+                        );
+                    }
+                }
             }
             // Note: in the wasm case, we're currently not running the robust
             // pipeline, as it requires more async wiring for the readback.
@@ -475,10 +500,10 @@
                     &render_params,
                 )
                 .expect("failed to render to surface");
+
             surface_texture.present();
             device_handle.device.poll(wgpu::Maintain::Poll);
 
-            let new_time = Instant::now();
             stats.add_sample(stats::Sample {
                 frame_time_us: (new_time - frame_start_time).as_micros() as u64,
             });
diff --git a/src/cpu_shader/flatten.rs b/src/cpu_shader/flatten.rs
index 3862616..d0ed267 100644
--- a/src/cpu_shader/flatten.rs
+++ b/src/cpu_shader/flatten.rs
@@ -326,7 +326,7 @@
     lines: &mut [LineSoup],
     bbox: &mut IntBbox,
 ) {
-    const MIN_THETA: f32 = 0.0001;
+    const MIN_THETA: f32 = 0.001;
 
     let mut p0 = transform.apply(begin);
     let mut r = begin - center;
@@ -774,4 +774,8 @@
         &mut bump,
         &mut lines,
     );
+
+    // TODO: this shouldn't happen here
+    //    #[cfg(feature = "debug_layers")]
+    //   crate::debug::validate::validate_line_soup(&lines[..bump.lines as usize]);
 }
diff --git a/src/lib.rs b/src/lib.rs
index 4c42af8..6b737eb 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -496,15 +496,17 @@
                     .expect("renderer should have configured surface_format to use on a surface");
                 let bump = result.bump.as_ref().unwrap();
                 // TODO: We could avoid this download if `DebugLayers::VALIDATION` is unset.
-                let downloads = DebugDownloads::map(&mut self.engine, &captured, bump).await?;
-                debug.render(
-                    &mut recording,
-                    surface_proxy,
-                    &captured,
-                    bump,
-                    &params,
-                    &downloads,
-                );
+                if let Ok(downloads) = DebugDownloads::map(&mut self.engine, &captured, bump).await
+                {
+                    debug.render(
+                        &mut recording,
+                        surface_proxy,
+                        &captured,
+                        bump,
+                        &params,
+                        &downloads,
+                    );
+                }
 
                 // TODO: this sucks. better to release everything in a helper
                 // TODO: it would be much better to have a way to safely destroy a buffer.
@@ -665,6 +667,10 @@
             return Err("could not download LineSoup buffer".into());
         };
 
+        if bump.lines == 0 {
+            return Err("bump indicates 0 LineSoup".into());
+        }
+
         let lines = lines_buf.slice(..bump.lines as u64 * std::mem::size_of::<LineSoup>() as u64);
         let (sender, receiver) = futures_intrusive::channel::shared::oneshot_channel();
         lines.map_async(wgpu::MapMode::Read, move |v| sender.send(v).unwrap());
diff --git a/src/scene.rs b/src/scene.rs
index 5c2ef5c..dace191 100644
--- a/src/scene.rs
+++ b/src/scene.rs
@@ -138,7 +138,7 @@
         const SHAPE_TOLERANCE: f64 = 0.01;
         const STROKE_TOLERANCE: f64 = SHAPE_TOLERANCE;
 
-        const GPU_STROKES: bool = false; // Set this to `true` to enable GPU-side stroking
+        const GPU_STROKES: bool = true; // Set this to `true` to enable GPU-side stroking
         if GPU_STROKES {
             let t = Transform::from_kurbo(&transform);
             self.encoding.encode_transform(t);