@@ -979,6 +979,80 @@ main build and resolves the packaged RID-native WebGPU directory on Linux,
979979macOS, and Windows. This fixes the prior Ubuntu ` libwgpu_native ` loader failure
980980without skipping the GPU workload or relaxing comparison evidence.
981981
982+ ### Avalonia immutable-image upload and deferred-draw checkpoint
983+
984+ The source-built Avalonia 12 ` WriteableBitmapImpl ` creates an immutable image
985+ with ` SKImage.FromPixels(info, address, rowBytes) ` whenever its writable pixel
986+ version changes, then reuses that image across draws. ProGPU now copies common
987+ RGBA, sRGBA, and BGRA rows directly into one tight immutable portable snapshot
988+ and uploads that same snapshot to WebGPU. The former temporary ` SKBitmap `
989+ wrapper and its second row walk are gone; arbitrary supported formats keep the
990+ conservative conversion fallback. Snapshot work remains ` O(P) ` time and
991+ storage for ` P ` pixels because the public pointer is caller-owned and the image
992+ must remain immutable after the writable framebuffer changes.
993+
994+ Whole images drawn in the same WebGPU device now cross the retained-command
995+ boundary through ` IProGpuContextTextureLeaseSource ` . The first draw records one
996+ bounded lifetime lease and every subsequent draw in that context reuses the
997+ same ` GpuTexture ` , texture view, and bindable identity. Disposal of the public
998+ ` SKImage ` releases its ownership but cannot destroy the texture while a
999+ deferred context or picture still holds a lease. Subsets, cross-device images,
1000+ and mipmap generation retain their normalized materialization paths. This makes
1001+ ordinary same-device recording ` O(C) ` command work for ` C ` draws with one GPU
1002+ texture and one lease, rather than ` O(C * P) ` texture allocation and copy
1003+ bandwidth.
1004+
1005+ The clean-room design follows Skia's public
1006+ [ immutable image contract] ( https://api.skia.org/classSkImage.html ) , WebGPU's
1007+ [ texture ownership and copy model] ( https://www.w3.org/TR/webgpu/#textures ) ,
1008+ Direct2D's
1009+ [ device-context bitmap drawing contract] ( https://learn.microsoft.com/windows/win32/direct2d/id2d1devicecontext-drawbitmap-overload ) ,
1010+ Win2D's
1011+ [ CanvasBitmap contract] ( https://learn.microsoft.com/uwp/api/microsoft.graphics.canvas.canvasbitmap ) ,
1012+ WebRender's
1013+ [ external-image frame split] ( https://firefox-source-docs.mozilla.org/gfx/RenderingOverview.html ) ,
1014+ and Vello's
1015+ [ explicit wgpu scene-to-texture pipeline] ( https://github.com/linebender/vello ) .
1016+ ProGPU adopts immutable CPU ownership at the public pointer boundary and typed
1017+ same-device leases at the deferred GPU boundary; it rejects borrowed pointer
1018+ lifetime assumptions, per-draw GPU copies, reflection, and backend-specific
1019+ public handles. Text shaping remains unchanged at the reusable CPU-result
1020+ boundary established by SkParagraph, DirectWrite, Parley, and HarfBuzz.
1021+
1022+ On the Apple M3 Pro Release baseline, the 16-by-16 Avalonia snapshot workload
1023+ improved from ` 13,356.445 ` to ` 10,934.730 ` ns/op and from ` 1,568 ` to ` 1,424 `
1024+ managed B/op with the exact native checksum. The new 1,000-draw retained-picture
1025+ workload isolates reuse of that immutable image: replacing one GPU texture copy
1026+ per draw with one lifetime lease reduced ProGPU from ` 69,164.500 ` to ` 608.354 `
1027+ ns/draw and from ` 2,831.500 ` to ` 2,486.000 ` managed B/draw. Native measured
1028+ ` 48.479 ` ns/draw and ` 2 ` managed B/draw because its retained command storage is
1029+ native and outside the managed counter. The remaining ProGPU command-storage
1030+ and snapshot gaps are explicit optimization targets; these shared-machine
1031+ figures establish the direction and do not claim final cross-platform parity.
1032+
1033+ Matched final-binary macOS profiling compared exact pre-lease commit
1034+ ` 1c60239b ` with exact candidate ` 79d86548 ` on the same Apple M3 Pro, macOS
1035+ 26.4.1, and .NET 10.0.5 workload. Time Profiler measured ` 327,088.874 ` versus
1036+ ` 816.041 ` median ns/draw; Allocations plus VM Tracker measured ` 82,988.745 `
1037+ versus ` 929.165 ` ; Metal System Trace measured ` 49,527.290 ` versus ` 797.290 ` ;
1038+ and EventPipe measured ` 60,615.875 ` versus ` 627.041 ` . EventPipe retained the
1039+ exact checksum while managed allocation fell from ` 2,831 ` to ` 2,486 ` B/draw
1040+ (` 12.2% ` ). Profiler overhead perturbs the absolute latency, so the ordinary
1041+ Release process numbers above remain the throughput result and these matched
1042+ captures provide causal evidence.
1043+
1044+ The Metal capture reduced target resource-allocation rows from ` 188 ` to ` 53 `
1045+ and target application command-buffer submission rows from ` 5,627 ` to zero.
1046+ The baseline target stack contains WebGPU ` copy_texture_to_texture ` ; the
1047+ candidate target stack does not. Both captures reported zero Metal
1048+ command-buffer errors, compiler spills, and hang risks. Completion and
1049+ ` currentAllocatedSize ` row counts include process/device sampling and are not
1050+ interpreted as bytes or per-draw totals. The Allocations template did not
1051+ export a native retained-byte table on this Xcode version, so no unsupported
1052+ native-memory claim is made. Compact results are recorded here; the 221 MiB of
1053+ raw trace and EventPipe data, temporary publishes, packages, and exact-baseline
1054+ worktree were removed after the audit.
1055+
9821056### Retained canvas contract and empty-clip checkpoint
9831057
9841058` SKCanvas ` now closes all 45 missing entries in its official 4.151.0 owner
0 commit comments