Add Avalonia 11/12 ProGPU rendering integration#36
Merged
Conversation
wieslawsoltes
marked this pull request as ready for review
July 24, 2026 13:45
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
This pull request moves the Avalonia ProGPU integration out of the Avalonia
source tree and into ProGPU as a standalone, packageable integration lane.
It includes:
with narrowly scoped
AVALONIA11conditionals;SkiaSharp compatibility implementation;
Skia compatibility path;
versions.
The Avalonia fork is a pinned submodule rather than copied source. Each
source-linked project contains a
PORTING-NOTICE.txtthat records its sourcerepository, original path, tag, exact source commit, and the small set of local
overrides.
Motivation
The ProGPU Avalonia renderer and Silk.NET backend previously lived in an
Avalonia feature branch, which coupled development and validation to the
Avalonia monorepo. Avalonia 11 compatibility also required a second
implementation lane.
This change makes ProGPU the owner of the integration while keeping a single
shared renderer and platform-backend implementation. Applications can consume
the integration through ordinary packages, and both supported Avalonia
versions can be validated without building the Avalonia source tree as a
project graph; the pinned checkout supplies linked source only.
Source provenance
The port is based on these immutable Avalonia revisions:
wieslawsoltes/Avalonia, tagprogpu-avalonia-v12.0.5-preview.19,commit
5378af03f17a4d9d2845882229ffed7f67350037;AvaloniaUI/Avalonia, tag12.0.5, commitfee9c561ce036e8a3e8cee2397c75ca599b4790d, for the effective unchangedsrc/Skia/Avalonia.Skiasource set.external/Avaloniapins the fork tagprogpu-avalonia-v12.0.5-preview.19at5378af03f17a4d9d2845882229ffed7f67350037. The Skia shim, ControlCatalog,and RenderDemo source-link their unchanged implementation, XAML, and resources
from that checkout. Only one Skia file, two ControlCatalog files, and fifteen
RenderDemo files remain locally as explicit overrides.
The Avalonia Skia adapter includes the upstream license and a detailed source
record. The fork tag changed
GlyphRunImpl.cs, so the local override restoresthe original Avalonia 12.0.5 file. A dedicated integrity test substitutes that
override and checks the effective 54-file set against the fixed upstream
SHA-256 digest.
Renderer and platform integration
Avalonia 12
ProGPU.Avalonia.Renderingimplements Avalonia's platform render interface ontop of the local ProGPU Backend, Vector, Text, Compute, Scene, and SkiaSharp
projects. It includes geometry, drawing-context, bitmap, glyph, text-shaping,
tile-brush, cache, render-target, and API-lease integration.
ProGPU.Avalonia.SilkNetprovides the desktop window, screen, cursor,clipboard, dispatcher, input mapping, icon, render-timer, and framebuffer
implementation. Window framebuffers use physical framebuffer dimensions while
Avalonia continues to operate in logical coordinates.
Avalonia 11
The Avalonia 11 renderer and Silk.NET projects contain only project
configuration and source-link the Avalonia 12 implementation directories.
They define
AVALONIA11for the small number of API differences and pin theAvalonia dependency to 11.3.18.
This avoids maintaining divergent copies while preserving version-specific
package identities:
ProGPU.Avalonia.Rendering12.0.5-preview.26;ProGPU.Avalonia.SilkNet12.0.5-preview.26;ProGPU.Avalonia.Rendering11.3.18-preview.26;ProGPU.Avalonia.SilkNet11.3.18-preview.26.Avalonia Skia compatibility
The previous out-of-tree Skia modifications were removed. The
ProGPU.Avalonia.SkiaShimproject now source-links the effectivebyte-identical Avalonia 12.0.5 Skia implementation against ProGPU's local
SkiaSharp project.
ProGPU-specific presentation is implemented below the Avalonia source:
GpuFramebufferPresentationRegistryassociates a CPU framebuffer addresswith a typed GPU presenter;
GpuTextureSurfacePresenterblits the rendered ProGPU texture directly tothe acquired WebGPU surface texture;
SKSurfaceregisters CPU-backed surfaces and can present the GPU texturewithout performing a live-surface CPU readback;
original Avalonia framebuffer backend completes the frame.
The direct ProGPU rendering path does not request the framebuffer address, so
it does not allocate the compatibility CPU buffer.
Bitmap-backed immutable
SKImageinstances retain one tightly packed RGBAsnapshot and lazily materialize one GPU texture per target
WgpuContext.Subsequent draws reuse that context-local texture; GPU-only and borrowed images
still reject cross-context use. Silk paint callbacks now push the exact
window-owned context, and window disposal releases that same instance. This
fixes the resize-time cross-context exception without modifying the effective
Avalonia Skia sources or adding a GPU readback.
Path rendering and atlas validation
The ControlCatalog follow-up fixes both the WebGPU copy validation error and
the malformed title-bar border:
rejected before placement or upload;
source staging-buffer range before recording a WebGPU command;
contours with even-odd fill instead of using the general GPU boolean solver;
the page-width atlas allocation that caused the original error;
implicit closing edge uses the direct two-triangle path only when it cannot
fit the maximum atlas; smaller rectangles keep their existing atlas
antialiasing;
unchanged after direct comparison with Avalonia
mainon the native Skiabackend confirmed the same three-contour silhouette.
Focused regressions cover oversized single rasters, both copy-range guards,
exact elliptical rounded-rectangle differences, the transition icon's two
implicitly closed fill contours, and the partial rounded title border with a
zero-width bottom edge. They also cover the oversized canonical-rectangle
fallback, the unchanged atlas path for a fitting rectangle, and explicit
failure for an oversized arbitrary path.
Release before/after measurements compared commit
b682d0cddirectly withits parent over four alternating processes per revision:
0.0254 ms median, with all frames hitting the scene cache;
median and showed no material allocation change;
median frame time, while compilation fell from 6.8087 ms to 0.2068 ms and
managed allocation fell by 72.7%;
Vector Shapesbenchmark showed no compositor orcompilation regression.
A separate Release image benchmark compared the parent revision with the final
source over four processes per case. The unchanged same-context path measured
1.4852 ms/frame before and 1.4796 ms/frame after (-0.4%, within noise), with a
23-byte/frame allocation difference. Cross-context materialization cost
17.8708 ms once; cached cross-context draws measured 1.5415 ms/frame and 8,718
managed bytes/frame, confirming there is no per-frame CPU upload.
Samples
The following applications and support projects are standalone projects while
their unchanged sample sources are linked from the pinned Avalonia submodule:
ControlCatalog, RenderDemo, and ProGpuSandbox use
UseSilkNet().UseProGpu()bydefault. ControlCatalog and RenderDemo can also exercise the unchanged Avalonia
Skia backend over ProGPU's SkiaSharp compatibility layer.
Packaging
The integration has a dedicated package manifest and pack/publish scripts
because the Avalonia 11 and Avalonia 12 projects share package IDs while
publishing different exact versions.
The repository package audit now classifies:
The isolated
integration/ProGpuPackageAppconsumer restores only from packagefeeds and contains no project references. Its runner supports both Avalonia
12.0.5 and Avalonia 11.3.18 through explicit version properties and isolated
NuGet configuration/cache directories.
Tests and validation
Validation performed on the final source state:
src/ProGPU.slnxbuild succeeded;regressions passed;
tests passed;
11.3.18;
validation errors; the title border rendered without the former diagonal
fill;
--skiashim;--skiashimRetina resize sequence covering 1280x760,1420x900, 1210x680, and 1360x820 completed without cross-context,
oversized-path, or WebGPU validation errors;
The full solution currently reports known warnings from Avalonia private API
usage and pre-existing dependency advisories/conflicts; it completes with no
errors.
Rendering research
The implementation includes a research record comparing the integration
against Skia/SkParagraph, DirectWrite/Direct2D and Win2D, WebRender,
Vello/Parley, and HarfBuzz. It records the decisions around lazy
initialization, shaped-text reuse, retained scenes, cache ownership, culling
and upload, physical framebuffer sizing, subpixel positioning, font fallback,
and device-loss handling.