SkiaGameRendering.Core.ANGLE 0.15.0

dotnet add package SkiaGameRendering.Core.ANGLE --version 0.15.0
                    
NuGet\Install-Package SkiaGameRendering.Core.ANGLE -Version 0.15.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SkiaGameRendering.Core.ANGLE" Version="0.15.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SkiaGameRendering.Core.ANGLE" Version="0.15.0" />
                    
Directory.Packages.props
<PackageReference Include="SkiaGameRendering.Core.ANGLE" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add SkiaGameRendering.Core.ANGLE --version 0.15.0
                    
#r "nuget: SkiaGameRendering.Core.ANGLE, 0.15.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package SkiaGameRendering.Core.ANGLE@0.15.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=SkiaGameRendering.Core.ANGLE&version=0.15.0
                    
Install as a Cake Addin
#tool nuget:?package=SkiaGameRendering.Core.ANGLE&version=0.15.0
                    
Install as a Cake Tool

Skia Game Rendering

Join the chat

A library that lets MonoGame and KNI applications use SkiaSharp's GPU rendering to produce Texture2Ds — with zero-copy GPU texture sharing. Skia renders anti-aliased vector art, text, and 2D graphics directly into game-engine textures without any CPU readback.

Platform Support

Platform Backend Status How it works
MonoGame 3.8.4 DesktopGL OpenGL NuGet Shared GL context via SDL
MonoGame 3.8.4 WindowsDX D3D11 NuGet ANGLE (GL ES → D3D11 translation) on shared device
MonoGame 3.8.5 DirectX D3D11 Not started
MonoGame 3.8.5 Vulkan Vulkan Not started
KNI DesktopGL OpenGL NuGet Shared GL context via SDL
KNI WindowsDX D3D11 NuGet ANGLE (GL ES → D3D11 translation) on shared device
KNI Android GL ES Not started
KNI WebGL (Blazor) WebGL2 NuGet Cross-context texSubImage2D(canvas) through KNI's stock public API
raylib OpenGL NuGet (Windows + Linux) Second WGL (Windows) or GLX (Linux) context shares rlgl's GL namespace
Stride (D3D11) D3D11 NuGet (Windows) ANGLE (GL ES → D3D11 translation) on shared device
Stride (Vulkan) Vulkan NuGet (Linux, macOS, Windows) Skia's Vulkan backend on Stride's shared VkDevice/VkQueue, no separate context

Requirements

  • .NET 8 (.NET 10 for the Stride backend)
  • Visual Studio 2022
  • MonoGame 3.8.4.1 (DesktopGL or WindowsDX), KNI (DesktopGL, WindowsDX, or WebGL/Blazor), raylib, or Stride 4.4.0-beta5+ (D3D11 on Windows, or Vulkan on Windows/Linux/macOS; prerelease)
  • SkiaSharp 3.119.4 for WebGL and the KNI desktop backends; 3.119.2 for the MonoGame desktop projects

Quick Start

Install the NuGet package for your platform into an existing MonoGame/KNI project (see docs/desktop/quickstart.md for a full walkthrough of the four backends below):

  • MonoGame DesktopGL: dotnet add package SkiaGameRendering
  • MonoGame WindowsDX: dotnet add package SkiaGameRendering.WindowsDX
  • KNI DesktopGL: dotnet add package SkiaGameRendering.Kni.DesktopGL
  • KNI WindowsDX: dotnet add package SkiaGameRendering.Kni.WindowsDX
  • KNI WebGL (Blazor): dotnet add package SkiaGameRendering.Kni.WebGL — needs a couple of extra setup steps beyond the package install; see docs/webgl/quickstart.md.
  • raylib: dotnet add package SkiaGameRendering.Raylib.OGL — see docs/raylib/quickstart.md.
  • Stride (D3D11): dotnet add package SkiaGameRendering.Stride.D3D11 — see docs/stride/quickstart.md.
  • Stride (Vulkan): dotnet add package SkiaGameRendering.Stride.VK — see docs/stride/vulkan-quickstart.md.

No setup outside Game needed — Program.cs stays whatever the stock MonoGame/KNI template gives you (using var game = new Game1(); game.Run();). Inside Game, poll SkiaRenderer.IsReady before calling SkiaRenderer.Initialize, in Draw() (a rendering-setup concern, colocated with the rendering that follows it):

using SkiaGameRendering; // SkiaRenderer

protected override void Draw(GameTime gameTime)
{
    if (!SkiaRenderer.IsInitialized && SkiaRenderer.IsReady)
        SkiaRenderer.Initialize(GraphicsDevice);

    if (SkiaRenderer.IsInitialized)
    {
        // normal draw logic
    }
    base.Draw(gameTime);
}

This is deliberate, not just convenient: IsReady/Initialize(GraphicsDevice) are declared on SkiaRenderer's shared, platform-agnostic part, so this exact code also compiles and behaves correctly on KNI WebGL, where IsReady reflects a real async host-readiness check instead of always being true — see docs/webgl/quickstart.md. Game code never names a specific SkiaBackend type on any platform.

SkiaRenderTarget2D

SkiaRenderTarget2D is a GPU surface that SkiaSharp renders directly into, sized to match whatever you intend to draw it onto (typically the back buffer, or a RenderTarget2D the same size as the viewport). Its Begin/End shape works like SpriteBatch's own: place individual shapes with their own coordinates via Skia's drawing API — the same way a SpriteBatch.Draw call carries its own position — and End() composites the whole result onto whatever render target is currently bound, the same way SpriteBatch.End() needs no separate step to show its queued sprite draws:

using SkiaGameRendering; // SkiaRenderTarget2D
using SkiaSharp;          // SKPaint and the rest of the drawing API

var canvas = new SkiaRenderTarget2D(GraphicsDevice, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height);

// per frame:
canvas.Begin();
canvas.Canvas.DrawCircle(100, 100, 100, paint); // position is DrawCircle's job, not End's
canvas.End();
Member Description
Texture The underlying Texture2D, mainly useful with EndWithoutDrawing
Canvas The SKCanvas to draw on — only valid between Begin() and End(); throws otherwise
Begin(bool clear = true) Starts a render pass; throws if called again before End()
End() Ends the render pass and composites the whole surface, at native size and the origin, onto whatever's currently bound; throws if Begin() wasn't called first
EndWithoutDrawing() Same as End(), but skips the composite — use only when End()'s single whole-surface blit can't express what you need (drawing it more than once, at a different size/position, or sampling it in a shader). You then draw Texture yourself.
Dispose() Releases the underlying GPU resources; throws if called between Begin() and End()

Size is fixed for the object's lifetime, like RenderTarget2D — construct a new SkiaRenderTarget2D (and Dispose() the old one) if you need a different size. Set a render target before calling Begin() if you want End()'s composite to land somewhere other than the back buffer.

Tear the shared backend down (e.g. on exit, or before switching backends) with:

SkiaRenderer.Dispose();

Dispose your own SkiaRenderTarget2D instances first — this doesn't track or dispose them for you.

Sample Projects

  • samples/Sample.MonoGame.DesktopGL/ — DesktopGL sample (cross-platform: Windows, Linux, macOS)
  • samples/Sample.MonoGame.WindowsDX/ — WindowsDX sample (Windows only)
  • samples/Sample.Kni.DesktopGL/ — KNI DesktopGL sample (cross-platform: Windows, Linux, macOS)
  • samples/Sample.Kni.WindowsDX/ — KNI WindowsDX sample (Windows only)
  • samples/Sample.Kni.WebGL/ — KNI Blazor WebAssembly sample using the patched canvas-upload API
  • samples/Sample.Raylib.OGL/ — raylib sample (Windows + Linux)
  • samples/Sample.Stride.D3D11/ — Stride sample (Windows, D3D11 only)
  • samples/Sample.Stride.VK/ — Stride sample (Vulkan; builds on Windows via StrideGraphicsApi=Vulkan, runs on Windows/Linux/macOS)
  • samples/Test/ — More comprehensive test with dynamic add/remove, FPS counter, input handling

DesktopGL, WindowsDX, and KNI WindowsDX share the same Game1.cs via a linked file include; KNI DesktopGL has its own copy.

Architecture

The library uses a backend abstraction (SkiaBackend base class) so each graphics API gets its own implementation. Core source files are shared across platform-specific library projects via linked includes:

  • src/SkiaGameRendering/ — DesktopGL library (core + SkiaGlBackend)
  • src/SkiaGameRendering.Core.OGL/ — engine-agnostic raw-GL/Skia FBO interop shared by GL-based backends
  • src/SkiaGameRendering.Core.ANGLE/ — engine-agnostic D3D11/ANGLE interop shared by ANGLE-based backends
  • src/SkiaGameRendering.WindowsDX/ — MonoGame WindowsDX library (shared core + SkiaAngleBackend, on Core.ANGLE)
  • src/SkiaGameRendering.Kni.DesktopGL/ — KNI DesktopGL library (shared core + SkiaKniGlBackend)
  • src/SkiaGameRendering.Kni.WindowsDX/ — KNI WindowsDX library (shared core + SkiaKniAngleBackend, on Core.ANGLE)
  • src/SkiaGameRendering.Kni.WebGL/ — KNI/Blazor library (shared core + SkiaWebGlBackend)
  • src/SkiaGameRendering.Raylib.OGL/ — raylib library (shared Core.OGL + SkiaRaylibRenderTarget2D)
  • src/SkiaGameRendering.Stride.D3D11/ — Stride library (shared Core.ANGLE + SkiaStrideRenderTarget2D, Windows/D3D11 only)
  • src/SkiaGameRendering.Core.VK/ — engine-agnostic Vulkan/Skia interop shared by Vulkan-based backends
  • src/SkiaGameRendering.Stride.VK/ — Stride library (shared Core.VK + SkiaStrideVulkanRenderTarget2D, Windows/Linux/macOS)

See SkiaGameRendering-Notes.md for detailed technical documentation on how each backend works, including the ANGLE integration and D3D11 state management.

WebGL / WASM Status

The WebGL backend is implemented in SkiaGameRendering.Kni.WebGL. It creates a synchronous SkiaSharp WebGL2 source host, flushes the current Skia frame, and uploads that canvas directly into a preallocated KNI Texture2D with texSubImage2D. Production code has no readPixels, managed pixel buffer, or Texture2D.SetData(byte[]) path.

The browser backend consumes stock KNI from NuGet (no fork or patch); the one internal (the current WebGL rendering context) that KNI doesn't expose publicly is reached via reflection instead — see src/SkiaGameRendering.Kni.WebGL/WebGlCanvasUpload.cs.

dotnet workload install wasm-tools-net8
dotnet build samples\Sample.Kni.WebGL\Sample.Kni.WebGL.csproj -c Release
dotnet run --project samples\Sample.Kni.WebGL\Sample.Kni.WebGL.csproj -c Release --no-build

The sample proves SpriteBatch interleaving, render-target consumption, shader sampling, animated Gum/Skia content, pointer/touch/wheel/text input, fractional DPR handling, and backend recreation. See docs/webgl/quickstart.md, docs/webgl/validated-baseline.md, and docs/documentation/SkiaWebGlBackend.md for the exact contract and support status.

Firefox is not usable yet

Measured on real hardware (docs/webgl/performance-results.md), every upload path misses budget on Firefox by 60-300x (35-171ms per frame just for the upload, vs. a <1ms target), consistent with an internal CPU readback on cross-context canvas uploads. Chrome and Edge are unaffected (Tier 1). Fixing this needs a shared-GL-context redesign ("Option A" in docs/webgl/validated-baseline.md), which is unstarted.

Using SkiaSharp

Between Begin() and End(), SkiaRenderTarget2D.Canvas gives you a full GPU-accelerated SKCanvas. For example, drawing an anti-aliased circle:

canvas.Begin();
canvas.Canvas.DrawCircle(Radius, Radius, Radius, _paint);
canvas.End();

For more on SkiaSharp drawing, see the SkiaSharp documentation.

License

MIT License. See LICENSE.md.

Credits

Originally created by Miguel Anxo Figueirido. Multi-platform backend abstraction and WindowsDX/ANGLE support added by Victor Chelaru.

Product Compatible and additional computed target framework versions.
.NET net8.0-windows7.0 is compatible.  net9.0-windows was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on SkiaGameRendering.Core.ANGLE:

Package Downloads
SkiaGameRendering.WindowsDX

GPU SkiaSharp rendering into MonoGame WindowsDX Texture2D targets via ANGLE, with zero-copy GPU texture sharing.

SkiaGameRendering.Stride.D3D11

GPU SkiaSharp rendering into Stride Texture targets via D3D11/ANGLE, with zero-copy GPU texture sharing.

SkiaGameRendering.Kni.WindowsDX

GPU SkiaSharp rendering into KNI WindowsDX (D3D11) Texture2D targets via ANGLE, with zero-copy GPU texture sharing.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.15.0 449 9/8/2026
0.14.0 96 9/1/2026
0.13.0 102 9/1/2026