Repository navigation
feat(build_to_burn): Fluttercon 2026 talk deck and impeller_model GPU cost model - #15
Merged
timcreatedit merged 45 commits intoOct 6, 2026
Merged
Conversation
Override motor with the top of the rivership motor 2.0 PR stack (whynotmake-it/rivership#325, pinned to e3fd207) for the whole workspace. The old pins no longer resolve on current stable Flutter: rivership 0.3.x caps material_color_utilities below what the SDK pins. Bump rivership to ^0.4.0, which brings heroine ^0.7.2 and hooks_riverpod 3, and import StateNotifierProvider from riverpod's legacy library. Co-authored-by: Tim Lehmann <hi@timcreated.it>
Co-authored-by: Tim Lehmann <hi@timcreated.it>
A new talk app with a title slide and placeholder openers for the hook, frame pipeline, painting vs compositing, GPU profiling, fixes, and production + AI skill sections. The look follows motor 2.0's example gallery: its palette, Archivo and JetBrains Mono, and the shared logo glyph from example_design. Co-authored-by: Tim Lehmann <hi@timcreated.it>
…d README Co-authored-by: Tim Lehmann <hi@timcreated.it>
Co-authored-by: Tim Lehmann <hi@timcreated.it>
One slide per file, each with its own route and speaker notes, listed explicitly in main.dart; shared widgets in lib/shared; wnma_talk as a path dependency; a closing thanks slide. The top bar shows the speaker from wnma_talk's speaker-notes header convention. Co-authored-by: Tim Lehmann <hi@timcreated.it>
Co-authored-by: Tim Lehmann <hi@timcreated.it>
…sualizations Standalone, self-scaling motor 2.0 components that later slides can place and restyle freely: - FramePipeline: one frame on UI thread, raster thread and GPU lanes over a 120 Hz vsync ruler, revealed per FrameStage. - PaintVsComposite: a BackdropFilter search sheet twice, showing what repaints versus what re-renders, next to GPU work = how often x how hard, driven by a BlurScenario. Co-authored-by: Tim Lehmann <hi@timcreated.it>
One plain placeholder per agenda section with the facts in the speaker notes, plus the cold open and paint-vs-composite slides, which step through the two visualizations with deck navigation. Co-authored-by: Tim Lehmann <hi@timcreated.it>
…nder stack Tim's core concept: widget code at the bottom, pixels at the top, each level an isometric plane. One steppable motor 2.0 component shows planes building up, opening to show their contents, highlights, per-plane inputs and outputs, the CPU/GPU border, looping repaint/frame pulses, and a frame N / N+1 pipeline. Content is placeholder data in render_stack_content.dart until the spec lands. Co-authored-by: Tim Lehmann <hi@timcreated.it>
One data-driven motor 2.0 widget following docs/render-stack-visualization.md: nine tiers in four bands (plus the Scene handoff tray and a system-compositor cap), expandable tiers with their example content, off/dim/hot lighting, the thread, CPU/GPU and present borders, loop arcs pulsing at their real rate slowed x10, tool spotlights, and a frame token that climbs to the demo's pixels. Ships build-up steps 1 (cold open), 3 (UI half), 4 (raster half), 5 (aha: loops A, C and Scene only, RepaintBoundary, #192128) and 8 (profiling tools) as five slides. Co-authored-by: Tim Lehmann <hi@timcreated.it>
…able Give the thin borders one label each so they don't collide with the CPU/GPU border, leave more room above an expanded tier, and expand the UI half's tiers one at a time. Co-authored-by: Tim Lehmann <hi@timcreated.it>
…tiles and feedback Aha: a running Ticker means a full frame every vsync. Loop T (Ticker frame) is the bold arc from the vsync, counted at the measured ~119 frames/s with ~111 repainting nothing; the repaint loop C (~8/s) is a thin side branch; #192128 cuts T at tier 5. Tiers 2-4 follow the real dumps: picture 2 includes the text field's white box and hairline border, and the layer tree is the curated one with app-shell and helper chips and the FollowerLayer. Plane text is larger and more spaced, and planes above an expanded tier are more transparent. New build-up steps: the hook (the stack dims behind the demo on a phone with a live blur, a fading caret and the vote), why a blur costs (tile memory fills, flushes T0 to DRAM and re-seeds from it), and the back-pressure and completion arrows across the CPU/GPU border. Co-authored-by: Tim Lehmann <hi@timcreated.it>
Expanded planes now show a schematic of their detail in 3D, and the readable text sits in a flat card at the bottom left with a leader to its plane. The slide shows each step's caption above the stack, so the bottom left stays free for loop arcs. Co-authored-by: Tim Lehmann <hi@timcreated.it>
No-repaint ticker frames build no Scene, so the ticker arc is cut below the handoff. Captions and notes give the measured caret drop on master (~119 to ~7.9 Scenes/s) and 3.50 stable as the expected release. Co-authored-by: Tim Lehmann <hi@timcreated.it>
Co-authored-by: Tim Lehmann <hi@timcreated.it>
…r the arcs Co-authored-by: Tim Lehmann <hi@timcreated.it>
Co-authored-by: Tim Lehmann <hi@timcreated.it>
…vote Co-authored-by: Tim Lehmann <hi@timcreated.it>
Following Tim's build-up (spec section 7.1): the cold open is the code slide alone; in the pipeline sections each stage appears as its own flat slide with its input (the previous stage's output) and its output, then tilts and shrinks onto the stack as the next plane. After the last stage, frames in flight show N+1, N and N-1 on different planes at once, the 2-slot queue and 3 drawables, then what doesn't overlap (spec section 6), then the four-band zoom-out. The label list shows only number and title; the focused stage expands with its input, output and thread. Loops, borders, tool spotlights, frames and the feedback arrows are brackets beside the list, and rows light up with their planes. The renderer is split into part files. Co-authored-by: Tim Lehmann <hi@timcreated.it>
…tack Co-authored-by: Tim Lehmann <hi@timcreated.it>
Co-authored-by: Tim Lehmann <hi@timcreated.it>
… cut A fifth aha step: after the caret's ticker arc is cut, a custom spinner inside a RepaintBoundary keeps pulsing at full rate, since it paints one small picture every tick. Captions and notes call #192128 a partial, framework-side skip and lead with the main fix: stop or slow the ticker. Co-authored-by: Tim Lehmann <hi@timcreated.it>
…entered stack - The focused row's input, output and thread are readable and wrap; rows below it move down to make room. - Landed planes keep a faint schematic of their stage; only the top plane shows the demo pixels. - The stack and list are centered vertically on their visible extent, gliding as planes land. - Frames in flight spread the stack so each frame pill sits on its own band, level with its bracket. Co-authored-by: Tim Lehmann <hi@timcreated.it>
The previous pin (e3fd207) became unreachable after the rivership branch was rebased. The new pin is the head of the motor/2.0 integration branch, kept reachable by the rivership tag talks/motor-2.0-pin-aba0c4c. - motor, fixed_ticker and example_design resolve at aba0c4c - fixed_ticker is overridden to the same ref because motor there needs ^0.2.1, which is not on pub.dev yet - FontMotionConverter now extends MotionConverter so it inherits the new lerp default instead of having to implement it
- top bar: drop the motor logo and the section eyebrow; the speaker is now only the subtle colored dot, colored like the other talks (tim blueAccent, jesper green, shared via SlideSpeaker.color) - title slide: drop the speaker names, keep whynotmake.it - remove the section parameter from RenderStackSlide/SkeletonSlide - scaffold the linux runner so the deck runs as a desktop debug build
- Split the pipeline into one deck slide per layer; advancing lands the current card on the stack, then the next layer's card comes in. - Chained stack slides hand off live track values and velocities, so motion continues across slides instead of restarting from zero. - Landing runs on snappy springs: the card shrinks, then its corners fly to the live plane one by one, in the order that keeps the quad convex. - Slides headed "N: title" per layer; drop the progress strip and slide count. - Analyzer excludes for build output, macOS CocoaPods setup, drop slide tests per AGENTS.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d frame slots - Cold open shows the demo on a phone next to its code; the hook adds the vote. - Drop the full-screen code slide and the "Widgets by color" slide. - Render objects slide: second step opens the official docs' trees picture as a dialog, with a link and QR code to the architectural overview. - New "Inside paint()" slide with trimmed paint() methods from the Flutter sources, marking the FFI call into C++. - Paint calls slide: drop the two note lines. - Scene slide: label both frame-pipeline slots and explain why there are two. - Pipeline limits slide: show both slots taken and the next frame waiting. - Clear the speaker notes down to their speaker header. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A standalone package (outside the melos workspace) that captures a widget-test frame — recorded canvas ops + the debugLayer tree — and replays it through a Dart port of Impeller's Canvas::SaveLayer / FlipBackdrop / blur-pass decision logic across four capability profiles. Emits per-pass timelines (JSON + HTML) with sizes, reasons, flips and a memory-traffic estimate, so "did my widget change add a pass" becomes a deterministic widget-test signal instead of a noisy on-device benchmark. Engine-semantics fidelity work (verified against flutter 3.47.1 engine sources): saveLayer content-bound rewriting, unbounded/cull accumulation with has_valid_clip tracking, collective opacity/filter distribution via renderable-state flags, backdrop-group snapshots, per-pass MSAA traffic accounting, content-based picture↔layer matching, and scope-balanced op streams. FEASIBILITY.md documents accuracy, limitations, the upstream hooks needed, and a recommendation. CI runs the package's tests + analyzer on a pinned Flutter 3.47.1 (the model depends on private engine semantics that float on stable). Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…ender stack slides
…and reports - Pass model ported from Impeller 3.47.1 with every engine decision quoted (tool/engine_refs.dart verifies 143 quotes, --diff-to lists what an SDK upgrade touches). - Validated against real GPU traces: 14/14 scenes on macOS Metal (Metal System Trace) and on a Pixel 10 (Vulkan pass logger); predict_test fails when the model drifts from the committed results. - Memory traffic: resolve-only MSAA, BGRA10_XR (8 B/px) on iOS, per-device screen-equivalents; tests at device preset sizes. - Frame demand: sources, tickers and identical frames, measured on each device's platform. - estimateGpu API with device presets, JSON/HTML report and snaptest screenshot; example app with the talk's hook screen. - Agent skills: gpu-cost, frame-demand, gpu-profiling; engine-upgrade maintainer skill. README, MAINTAINING and FEASIBILITY rewritten. - CI runs the quote check, example and validation predictions. Thread: https://delta.dev/join/thread_01m41zp98qhmvxdcvyfaqswm86
The layer walk read Flutter's layer tree by type, so a package's own Layer subclass that pushes clips or filters in addToScene (liquid_glass_renderer's LiquidGlassCapture) was estimated as an empty container. The binding now wraps createSceneBuilder, records every push it forwards, and rebuilds custom layers from what they pushed. Their framework children keep their widget origins. A custom layer whose pushes cannot be found is reported in unmodeledLayers, only when the scene holds a push nobody accounts for. Also moves to snaptest 1.0.0-dev.3 (setTestViewForDevice, snap(device:)). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The report keeps only what a developer can act on: passes and memory traffic per device, the widgets that cause them with a one-line fix per cause, the frames drawn while idle with who requested them, and warnings when part of the estimate is a guess (approximate passes, uncounted pictures by location, unreadable custom layers). Tabs, cards, the pass timeline, the GPU capture table and the frame strip are gone from the page; the JSON keeps them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- A custom layer whose engine layer came from an unrecorded scene (a toImage snapshot) is now reported as unmodeled instead of silently estimated as a plain container. - Pushes no layer accounts for are reported even when a custom layer was read from the scene; the check is skipped when the recorded scene no longer matches the tree (a snapshot replaced engine layers after it). - Leaf layer subclasses (PictureLayer, TextureLayer, ...) draw like their framework type instead of being dropped. - Backdrops compare by BackdropKey whether framework- or scene-read. - estimateGpu takes the screenshot after the frame demand, so its toImage cannot hide custom layers from the demand's estimates. - The report says when idle frames do not stop on their own. - Framework layers are indexed once per walk; the owner's origin is computed once per custom layer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Merge the layer tree and Scene into one stack tier and one slide: the pictures cross to C++ first, then the SceneBuilder copies the layers - New animated DisplayList and render passes slides; the GPU chapter shows one frame and moves before the passes slide - Renumber the render stack to 8 tiers - Short titles instead of subtitles; trim the title slide - F toggles per-slide flow notes (question, takeaway, transition) - Speaker dots: 1-3 Tim, 4-6 Jesper, 7+ Tim Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every pass of one frame in order, with its size, share of the screen, cause and what ended it early; the pass role's explanation shows on hover. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Slide 10 shows the finished pass plan and announces the live demo - New slides: live demo, every frame, quiz answer, fast is not cheap - Ticker slide: expected 8 frames a second, then 120 in reality - Profiling slide shows our own captures of each tool next to the stack - Remove the GPU tiles, pixels, zoom-out and blur-cost slides; frames in flight and pipeline limits move to backup - Slow, readable line steps on the DisplayList slide, with a reading dot Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- New docs and skills slide with QR codes to the Impeller profiling guides and the impeller_model agent skills - Thank you slide as the end - Remove slides that didn't make the final deck: GPU tiles, pixels, zoom out, why blur costs, fixes, production, Monday checklist - Profiling slide: repaint highlighting as a looping clip, no frame capture step, no bracket labels next to the compressed stack Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lls slides - Title: "Beyond DevTools", "What is Flutter doing on my GPU?". - Hook: Xcode's energy report of the demo as a dialog, then the vote. The demo phone shows its keyboard; the quiz names the circles underneath, the fading cursor and the rounded clip. - Stage 5 ends on the written, flat DisplayList (two steps). - New takeaways slide (cost = frames x price per frame) and a skills slide that replaces docs and skills. - Work in progress on the GPU chapter, engine stage and render stack cards. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Redesign impeller_model HTML report Restructure the GPU estimate report with: - Device picker tabs instead of a table - Screenshot display in hero section - Visual bars for pass costs and frame strips - Updated styling with CSS variables for light/dark modes - Reorganized content layout for better scanning - Updated README to reflect new report structure
timcreatedit
marked this pull request as ready for review
October 6, 2026 08:49
timcreatedit
deleted the
tim-lehmann/fluttercon-2026-deck-scaffold-8218
branch
October 6, 2026 10:13
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
apps/build_to_burn, the complete Fluttercon 2026 lightning talk by Jesper Bellenbaum & Tim Lehmann, running on motor 2.0 — pluspackages/impeller_model, the GPU cost-estimation package built for the talk, its agent skills, a device-validation harness, and agpu_probeexperiment app.The deck. Cold open on the "you all write this" code slide, then the hook: a feed behind a
CupertinoAlertDialogthat looks static but pays several render passes per frame and never stops requesting them. The core visualization is the isometric render stack — each pipeline stage lands as its own flat slide (INPUT chip → picture → OUTPUT chip), then shrinks and tilts onto the stack; loops, tool spotlights, frames-in-flight and the feedback arrow are brackets beside the layer list, clamped to landed planes. Second half: live demo of the hook screen's real cost, engine internals from layer tree to Impeller passes, GPU profiling tools, takeaways, docs & skills slides.The aha. A running Ticker is a full frame every vsync (≈119/s, ≈111 repainting nothing); #192128 is shown as a partial, framework-side
drawFramegate that cuts the caret's arc while aRepaintBoundaryspinner keeps pulsing; the fix is to stop or slow the ticker (fixed_ticker).impeller_model. Ports Impeller's pass logic (pinned Flutter 3.47.1) into a
flutter_testbinding:estimateGpureports render passes, cost centers and nominal memory traffic per device class;measureFrameDemandattributes idle-time frame requests to tickers, carets and timers; reports are JSON + HTML + PNG. Every ported engine decision is quoted verbatim next to its Dart port and checked bytool/engine_refs.dart;validation/compares predictions against real GPU traces on macOS Metal and a Pixel 10 (14/14 scenes). Ships three agent skills (gpu-costestimate,frame-demand, devicegpu-profiling) plus docs.A stage slide
Frames in flight
Demo video
Motor 2.0.
motoris pinned to the rivershipmotor/2.0branch ataba0c4c. The workspace has one shared resolution, so the rootpubspec.yamlalso overrides motor for every package; the ref is repeated inapps/build_to_burn/pubspec.yaml— bump both together.Workspace migration. On current stable Flutter,
maindid not resolve:rivership→^0.4.0inwnma_talk,physical_uiandgaussian_splatting(requiresheroine ^0.7.2,hooks_riverpod ^3.0.0);physical_uiimportsStateNotifierProviderfromhooks_riverpod/legacy.dart;wnma_talkfixes 3 analyzer findings.Test plan
flutter testinapps/build_to_burn(fonts loaded, every slide and step walked, render-stack scripts tested)flutter testinpackages/impeller_model(model cases, report, frame demand)validation/scenes match real traces on macOS Metal and Pixel 10 (seeFEASIBILITY.md)flutter analyzeclean forbuild_to_burnandimpeller_modelphysical_uidepends on the privatewhynotmake-it/glibber; resolved locally against a stub — verify on a machine with accessGenerated with Devin