×ばつ1049 timeline squashed into ×ばつ432. What is in it 8dcd8e6e Price the existing resize step, and add tools/gpu-image-fixture — the only vehicle that can reach the texture ceiling, because every showcase app on Windows draws zero bitmaps. ab77da31 Create the D3D11/D2D1.1 device stack. 38984652 Present through a DXGI flip-model swap chain. A regression on its own — 3.23 → 3.66 ms — and the setup for the next commit. 54799796 Keep the texture cache across a resize. Upload 1.51 → 0.00 ms. 1bee7997 Copy and present only the damaged region. 4018a3d8 Rebuild the whole stack on device loss. 6e90ea39 Pin the flip-model invariants, retire the GDI ones. 9de236e0 Identify surfaces in the profile log. c1501246 Allocate swap buffers on a 128 px grid and let SCALING_NONE crop them, so a drag stops calling ResizeBuffers every step. 7c4aef36, 69137cec, 948d39a8 Profiler arguments; link d3d11/dxgi where the renderer now needs them. 90f4b76e Stamp every profile line with the monotonic clock. Per-event durations cannot express how far apart a surface's consecutive frames land, which is the question a resize actually poses. 5cf804e4 Anchor a resized surface's retained image instead of stretching it. The last two are new since the previous revision. readColorAt had to move with the target: it read pixels through ID2D1GdiInteropRenderTarget::GetDC, which requires the backing surface to be GDI_COMPATIBLE, and that flag lives on the CreateCompatibleRenderTarget call this deletes. Results Fixture at the 16 MiB texture ceiling, three runs each way, per resize step: before after image upload 1.51 ms 0.00 ms blit 1.79 ms 0.42 ms blit p90 1.30 ms 0.31 ms Present 0.41 ms 0.14 ms buffer allocations over the sweep 82 13 The anchoring commit is free: an interleaved 6-round A/B against the same build without it measured a median of 267 Hz against 259 Hz, and narrowed the spread (255–279 against 210–299). Treat any single sweep as noise — the same binary measured six times in one sitting ranged 210–299 Hz. Three things worth a reviewer's attention The swap chain alone is a regression, and structurally so. Reading 38984652's numbers in isolation reads as a failed migration; it is the setup for 54799796, which is where the win is. SetSourceSize is deliberately absent. DXGI documents it as "an effective resize without calling the more-expensive ResizeBuffers", which is exactly this job — but paired with DXGI_SCALING_NONE it renders a surface whose buffer is much taller than its window (a 38 px header rounded up to a 128 px buffer) as a fragment at the top-left on a field of background colour. It also measured as worth nothing: 0.428 ms against 0.426 ms per step. A test pins the call absent, not the type name, so the comment explaining why cannot satisfy its own pin. Anchoring keeps a sub-pixel escape hatch, per axis. The backing surface is sized from the packet (ceil(logical * scale)) and the swap chain from GetClientRect, so at fractional DPI the two differ by a pixel indefinitely — 44% of paints in the measured sweep. Anchoring that would leave a permanent hairline of cleared pixels down two edges, so a disagreement within one device pixel still scales and only a larger one anchors. Validation Full suite on Windows, against pristine main at the same commit as the control: steps tests failed main b25cefe 478/481 3277/3333 4 this branch 478/481 3280/3336 4 — identical set Net +3 passing tests, no new failures. The four are pre-existing on main on a Windows host; two of them are macOS DMG packaging tests that cannot pass there at all. 🤖 Generated with Claude Code">
Skip to content

Navigation Menu

Sign in
Sign up

perf(windows): present the canvas through a DXGI flip-model swap chain #330

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

Draft
jhodges10 wants to merge 14 commits into vercel-labs:main
base: main
Choose a base branch
Loading
from jhodges10:perf/windows-resize-continuity
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
14 commits
Select commit Hold shift + click to select a range
8dcd8e6
perf(windows): measure the Direct2D resize step
jhodges10 Aug 12, 2026
ab77da3
feat(windows): create the D3D11/D2D1.1 device stack
jhodges10 Aug 12, 2026
3898465
feat(windows): present through a DXGI flip-model swap chain
jhodges10 Aug 12, 2026
5479979
perf(windows): keep the texture cache across a resize
jhodges10 Aug 12, 2026
1bee799
feat(windows): copy and present only the damaged region
jhodges10 Aug 12, 2026
4018a3d
feat(windows): rebuild the whole stack on device loss
jhodges10 Aug 12, 2026
6e90ea3
test(windows): pin the flip-model invariants, retire the GDI ones
jhodges10 Aug 12, 2026
9de236e
fix(windows): identify surfaces in the GPU profile log
jhodges10 Aug 12, 2026
c150124
perf(windows): allocate swap buffers on a grid, crop them to the window
jhodges10 Aug 12, 2026
7c4aef3
tools(windows): pass app arguments and run the modal drag alone
jhodges10 Aug 12, 2026
69137ce
fix(windows): link flip-model renderer dependencies
jhodges10 Aug 12, 2026
948d39a
fix(scaffold): link flip-model renderer dependencies
jhodges10 Aug 12, 2026
90f4b76
test(windows): timestamp every profile line
jhodges10 Aug 17, 2026
5cf804e
fix(windows): anchor a resized surface's retained image instead of st...
jhodges10 Aug 17, 2026
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
8 changes: 7 additions & 1 deletion build.zig
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -1270,7 +1270,7 @@ pub fn build(b: *std.Build) void {
.{ .path = "src/platform/windows/webview2_host.cpp", .pattern = "InvalidateRect(view.hwnd, &info.dirty_rects[index], FALSE)" },
.{ .path = "src/platform/windows/webview2_host.cpp", .pattern = "for (size_t y_index = y0; y_index < y1; ++y_index)" },
.{ .path = "src/platform/windows/webview2_host.cpp", .pattern = "InvalidateRect(view.hwnd, partial_update ? &dirty_pixels : nullptr, FALSE)" },
.{ .path = "src/platform/windows/gpu_surface_renderer.cpp", .pattern = "D2D1_RENDER_TARGET_TYPE_HARDWARE" },
.{ .path = "src/platform/windows/gpu_surface_renderer.cpp", .pattern = "D3D11_CREATE_DEVICE_BGRA_SUPPORT" },
.{ .path = "src/platform/windows/gpu_surface_renderer.cpp", .pattern = "retained_commands_ = std::move(next_retained)" },
.{ .path = "src/platform/windows/gpu_surface_renderer.cpp", .pattern = "PushAxisAlignedClip(d2dRect(requested)" },
.{ .path = "src/platform/windows/gpu_surface_renderer.cpp", .pattern = "const float expansion = effect.spread + blur" },
Expand Down Expand Up @@ -1720,6 +1720,12 @@ pub fn build(b: *std.Build) void {
addExampleTestStep(b, host_cli_exe, native_examples_step, "test-example-service-feed-reader", "Run TypeScript service feed-reader example tests", "examples/service-feed-reader", .managed),
addExampleTestStep(b, host_cli_exe, native_examples_step, "test-example-canvas-preview", "Run canvas preview example tests", "examples/canvas-preview", .managed),
addExampleTestStep(b, host_cli_exe, native_examples_step, "test-example-capabilities", "Run capabilities example tests", "examples/capabilities", .owned),
// Not an example — a measurement fixture (tools/gpu-image-fixture),
// registered here because its whole job is to hold the runtime's
// registered-image ceiling and its tests are what catch that
// ceiling moving out from under it. `scripts/gate.sh fast` already
// maps a tools/ diff to this group, so this is where it belongs.
addExampleTestStep(b, host_cli_exe, native_examples_step, "test-tool-gpu-image-fixture", "Run GPU image fixture limit pins", "tools/gpu-image-fixture", .managed),
};
for (native_example_shard_steps) |shard_step| {
native_examples_step.dependOn(shard_step);
Expand Down
5 changes: 5 additions & 0 deletions build/app.zig
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -2379,7 +2379,12 @@ fn linkPlatform(b: *std.Build, dep: *std.Build.Dependency, target: std.Build.Res
// Retained gpu_surface packets are composited into a hardware
// Direct2D target; DirectWrite draws the engine-measured text
// runs (including registered in-memory fonts) on that target.
// The D2D device sits on a D3D11 device created with
// BGRA_SUPPORT, and reaches the compositor through a DXGI 1.2
// flip-model swap chain -- hence d3d11 and dxgi.
app_mod.linkSystemLibrary("d2d1", .{});
app_mod.linkSystemLibrary("d3d11", .{});
app_mod.linkSystemLibrary("dxgi", .{});
app_mod.linkSystemLibrary("dwrite", .{});
app_mod.linkSystemLibrary("imm32", .{});
app_mod.linkSystemLibrary("comctl32", .{});
Expand Down
2 changes: 2 additions & 0 deletions examples/browser/build.zig
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,8 @@ fn linkPlatform(b: *std.Build, target: std.Build.ResolvedTarget, app_mod: *std.B
app_mod.linkSystemLibrary("user32", .{});
app_mod.linkSystemLibrary("gdi32", .{});
app_mod.linkSystemLibrary("d2d1", .{});
app_mod.linkSystemLibrary("d3d11", .{});
app_mod.linkSystemLibrary("dxgi", .{});
app_mod.linkSystemLibrary("dwrite", .{});
app_mod.linkSystemLibrary("imm32", .{});
app_mod.linkSystemLibrary("comctl32", .{});
Expand Down
2 changes: 2 additions & 0 deletions examples/capabilities/build.zig
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,8 @@ fn linkPlatform(b: *std.Build, target: std.Build.ResolvedTarget, app_mod: *std.B
app_mod.linkSystemLibrary("user32", .{});
app_mod.linkSystemLibrary("gdi32", .{});
app_mod.linkSystemLibrary("d2d1", .{});
app_mod.linkSystemLibrary("d3d11", .{});
app_mod.linkSystemLibrary("dxgi", .{});
app_mod.linkSystemLibrary("dwrite", .{});
app_mod.linkSystemLibrary("imm32", .{});
app_mod.linkSystemLibrary("comctl32", .{});
Expand Down
2 changes: 2 additions & 0 deletions examples/command-app/build.zig
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,8 @@ fn linkPlatform(b: *std.Build, target: std.Build.ResolvedTarget, app_mod: *std.B
app_mod.linkSystemLibrary("user32", .{});
app_mod.linkSystemLibrary("gdi32", .{});
app_mod.linkSystemLibrary("d2d1", .{});
app_mod.linkSystemLibrary("d3d11", .{});
app_mod.linkSystemLibrary("dxgi", .{});
app_mod.linkSystemLibrary("dwrite", .{});
app_mod.linkSystemLibrary("imm32", .{});
app_mod.linkSystemLibrary("comctl32", .{});
Expand Down
2 changes: 2 additions & 0 deletions examples/hello/build.zig
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,8 @@ fn linkPlatform(b: *std.Build, target: std.Build.ResolvedTarget, app_mod: *std.B
app_mod.linkSystemLibrary("user32", .{});
app_mod.linkSystemLibrary("gdi32", .{});
app_mod.linkSystemLibrary("d2d1", .{});
app_mod.linkSystemLibrary("d3d11", .{});
app_mod.linkSystemLibrary("dxgi", .{});
app_mod.linkSystemLibrary("dwrite", .{});
app_mod.linkSystemLibrary("imm32", .{});
app_mod.linkSystemLibrary("comctl32", .{});
Expand Down
2 changes: 2 additions & 0 deletions examples/native-panels/build.zig
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,8 @@ fn linkPlatform(b: *std.Build, target: std.Build.ResolvedTarget, app_mod: *std.B
app_mod.linkSystemLibrary("user32", .{});
app_mod.linkSystemLibrary("gdi32", .{});
app_mod.linkSystemLibrary("d2d1", .{});
app_mod.linkSystemLibrary("d3d11", .{});
app_mod.linkSystemLibrary("dxgi", .{});
app_mod.linkSystemLibrary("dwrite", .{});
app_mod.linkSystemLibrary("imm32", .{});
app_mod.linkSystemLibrary("comctl32", .{});
Expand Down
2 changes: 2 additions & 0 deletions examples/native-shell/build.zig
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,8 @@ fn linkPlatform(b: *std.Build, target: std.Build.ResolvedTarget, app_mod: *std.B
app_mod.linkSystemLibrary("user32", .{});
app_mod.linkSystemLibrary("gdi32", .{});
app_mod.linkSystemLibrary("d2d1", .{});
app_mod.linkSystemLibrary("d3d11", .{});
app_mod.linkSystemLibrary("dxgi", .{});
app_mod.linkSystemLibrary("dwrite", .{});
app_mod.linkSystemLibrary("imm32", .{});
app_mod.linkSystemLibrary("comctl32", .{});
Expand Down
2 changes: 2 additions & 0 deletions examples/next/build.zig
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,8 @@ fn linkPlatform(b: *std.Build, target: std.Build.ResolvedTarget, app_mod: *std.B
app_mod.linkSystemLibrary("user32", .{});
app_mod.linkSystemLibrary("gdi32", .{});
app_mod.linkSystemLibrary("d2d1", .{});
app_mod.linkSystemLibrary("d3d11", .{});
app_mod.linkSystemLibrary("dxgi", .{});
app_mod.linkSystemLibrary("dwrite", .{});
app_mod.linkSystemLibrary("imm32", .{});
app_mod.linkSystemLibrary("comctl32", .{});
Expand Down
2 changes: 2 additions & 0 deletions examples/react/build.zig
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,8 @@ fn linkPlatform(b: *std.Build, target: std.Build.ResolvedTarget, app_mod: *std.B
app_mod.linkSystemLibrary("user32", .{});
app_mod.linkSystemLibrary("gdi32", .{});
app_mod.linkSystemLibrary("d2d1", .{});
app_mod.linkSystemLibrary("d3d11", .{});
app_mod.linkSystemLibrary("dxgi", .{});
app_mod.linkSystemLibrary("dwrite", .{});
app_mod.linkSystemLibrary("imm32", .{});
app_mod.linkSystemLibrary("comctl32", .{});
Expand Down
2 changes: 2 additions & 0 deletions examples/svelte/build.zig
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,8 @@ fn linkPlatform(b: *std.Build, target: std.Build.ResolvedTarget, app_mod: *std.B
app_mod.linkSystemLibrary("user32", .{});
app_mod.linkSystemLibrary("gdi32", .{});
app_mod.linkSystemLibrary("d2d1", .{});
app_mod.linkSystemLibrary("d3d11", .{});
app_mod.linkSystemLibrary("dxgi", .{});
app_mod.linkSystemLibrary("dwrite", .{});
app_mod.linkSystemLibrary("imm32", .{});
app_mod.linkSystemLibrary("comctl32", .{});
Expand Down
2 changes: 2 additions & 0 deletions examples/vue/build.zig
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,8 @@ fn linkPlatform(b: *std.Build, target: std.Build.ResolvedTarget, app_mod: *std.B
app_mod.linkSystemLibrary("user32", .{});
app_mod.linkSystemLibrary("gdi32", .{});
app_mod.linkSystemLibrary("d2d1", .{});
app_mod.linkSystemLibrary("d3d11", .{});
app_mod.linkSystemLibrary("dxgi", .{});
app_mod.linkSystemLibrary("dwrite", .{});
app_mod.linkSystemLibrary("imm32", .{});
app_mod.linkSystemLibrary("comctl32", .{});
Expand Down
2 changes: 2 additions & 0 deletions examples/webview/build.zig
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,8 @@ fn linkPlatform(b: *std.Build, target: std.Build.ResolvedTarget, app_mod: *std.B
app_mod.linkSystemLibrary("user32", .{});
app_mod.linkSystemLibrary("gdi32", .{});
app_mod.linkSystemLibrary("d2d1", .{});
app_mod.linkSystemLibrary("d3d11", .{});
app_mod.linkSystemLibrary("dxgi", .{});
app_mod.linkSystemLibrary("dwrite", .{});
app_mod.linkSystemLibrary("imm32", .{});
app_mod.linkSystemLibrary("comctl32", .{});
Expand Down
Loading
Loading

AltStyle によって変換されたページ (->オリジナル) /