FS.GG.UI.SkiaViewer
0.15.0
Prefix Reserved
dotnet add package FS.GG.UI.SkiaViewer --version 0.15.0
NuGet\Install-Package FS.GG.UI.SkiaViewer -Version 0.15.0
<PackageReference Include="FS.GG.UI.SkiaViewer" Version="0.15.0" />
<PackageVersion Include="FS.GG.UI.SkiaViewer" Version="0.15.0" />
<PackageReference Include="FS.GG.UI.SkiaViewer" />
paket add FS.GG.UI.SkiaViewer --version 0.15.0
#r "nuget: FS.GG.UI.SkiaViewer, 0.15.0"
#:package FS.GG.UI.SkiaViewer@0.15.0
#addin nuget:?package=FS.GG.UI.SkiaViewer&version=0.15.0
#tool nuget:?package=FS.GG.UI.SkiaViewer&version=0.15.0
FS.GG.UI.SkiaViewer
Skia viewer host workflow contracts for FS.GG.UI V3 products.
FS.GG.UI.SkiaViewer is one of the FS.GG.UI distribution packages — an F# / Elmish UI and 2D
scene-graph framework for .NET 10 desktop, rendered through Vulkan + SkiaSharp.
Install
dotnet add package FS.GG.UI.SkiaViewer
Or scaffold a full governed project that wires the FS.GG.UI packages together:
dotnet new install FS.GG.UI.Template
dotnet new fs-gg-ui -o MyApp
Usage
Viewer.run opens the Vulkan + Skia viewer for a single scene. It returns a Result, so a host
that has no usable desktop session (or fails to present) reports a typed ViewerRunFailure rather
than throwing — match on it instead of assuming success.
open FS.GG.UI.Scene
open FS.GG.UI.SkiaViewer
let options: ViewerOptions =
{ Title = "My App"
InitialSize = { Width = 1280; Height = 720 } }
// The rendered content is any SceneNode from FS.GG.UI.Scene.
let scene: SceneNode = Rectangle((0.0, 0.0, 1280.0, 720.0), Colors.white)
match Viewer.run options scene with
| Ok outcome ->
printfn "Window opened: %b, first frame presented: %b" outcome.WindowOpened outcome.FirstFramePresented
| Error failure ->
printfn "Viewer blocked at %A (%A): %s" failure.BlockedStage failure.Classification failure.Message
For an Elmish-style application, build a GeneratedAppHost (with Init / Update / View /
MapKey / Tick / Diagnostics) and run it with Viewer.runApp options host, which returns the
same Result<ViewerLaunchOutcome, ViewerRunFailure>.
Portable scene packages from FS.GG.UI.Scene.SceneCodec can be rendered through the
ReferenceRendering oracle to produce a PNG artifact plus protocol, capability, resource, and
renderer metadata. Unsupported host conditions return ReferenceEnvironmentLimited rather than a
false pass.
API at a glance
Viewer.run/Viewer.runApp— open the viewer for a singleSceneNode, or for a fullGeneratedAppHost<'model,'msg>; both returnResult<ViewerLaunchOutcome, ViewerRunFailure>.Viewer.runBounded/runUntilFirstFrame/runForFrames— headless, bounded evidence runs that render to aViewerRunFailure-or-ViewerRunEvidenceResultfor CI and screenshots.Viewer.captureScreenshotEvidence— drive aScreenshotEvidenceRequestto aScreenshotEvidenceResultrecording capture source, pixel-content validation, and proof status.
Readback frame size vs logical canvas (issue #885). The bounded/evidence readback rasterizes the scene 1:1 into an
InitialSize-sized frame. WithLogicalSize = None(the default) there is no logical→physical mapping: the frame is the coordinate space, and content a product authored beyondInitialSizeis clipped — no scale, no letterbox, no warning. SetViewerOptions.LogicalSizeto the canvas the product renders in (e.g.{ Width = 1280; Height = 720 }) and the host scales, centers and letterboxes that whole canvas into whatever readback surface it is given (#246), so nothing is silently dropped. If you leaveLogicalSizeunset, sizeInitialSizeto cover the authored content — a smaller readback frame captures only its top-left corner. The emitted evidence records the captureSize, so compare it against your design canvas when a screenshot looks cropped.
ReferenceRendering.init/update/run— MVU-style reference rendering for portable scene packages, with explicit inspect/render/write effects and Skia-backed PNG evidence.Viewer.desktopSessionDiagnostic/runtimeCapability— probe the host for a usable desktop session and the renderer/keyboard/window capabilities currently available.ViewerOptions,ViewerRunRequest,GeneratedAppHost<'model,'msg>— the core input contracts: window title/size, bounded-run target plus diagnostics, and the Elmish app surface.- Responsiveness diagnostics —
ViewerLatencyRecord,ViewerResponsivenessSummary,ViewerResponsivenessBudget, stable token helpers, JSONL/Markdown summary writers, and default budgets for input receipt, input-to-visible latency, and long-frame reporting. - Input queue helpers —
Viewer.enqueueInput,drainInputQueue,dirtyState, anddirtyStateRequiresRecomposemodel the live scheduler boundary: discrete input preserves order, continuous pointer movement coalesces, and retained recomposition is requested once per dirty frame. FS.GG.UI.SkiaViewer.Host.Viewer— the lower-level Elmish host edge (create,withSubscription/withEventMapping/withEffectMapping,run) overViewerProgram<'model,'msg>.Host.Diagnostics— constructors for structuredRenderDiagnosticvalues (vulkanUnavailable,unsupportedPlatform,frameRenderFailed,startupFailed, and more), keyed byDiagnosticStage.CompositorProof/Host.GlHost.ScissorDecision— Feature147/148 proof and scissor policy contracts. Damage-scissored redraw remains proof-gated: missing, stale, failed, host-mismatched, synthetic, or environment-limited proof keeps the viewer on a full-redraw fallback until fresh sentinel/damage readback evidence is available for the active host profile. Snapshot and timing readiness likewise require parity-clean evidence and resource/timing artifacts before claiming performance value.
Responsiveness Evidence
The viewer exposes additive responsiveness contracts for diagnostic runs and readiness tooling. A
run writes records.jsonl, summary.json, summary.md, and environment.md; environment-limited
hosts must report statuses such as headless-substitute, missing-boundary, or
no-visible-surface instead of claiming accepted live latency.
Use Viewer.summarizeResponsivenessRecords with Viewer.defaultResponsivenessBudget to aggregate
latency records, then Viewer.writeResponsivenessRun to persist reviewer-readable and
machine-readable evidence.
Versioning
All FS.GG.UI.* libraries share one version and move together. In a generated project a
single <FsGgUiVersion> in Directory.Packages.props pins every package — upgrading is one
edit; see docs/UPGRADING.md. Pre-release versions use a -preview.N suffix.
Links
- Repository & issues: https://github.com/FS-Skia-UI/FS-Skia-UI
- License: MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Fable.Elmish (>= 5.0.2)
- FS.GG.Audio.Core (>= 0.1.0)
- FS.GG.UI.Canvas (>= 0.15.0)
- FS.GG.UI.Diagnostics (>= 0.15.0)
- FS.GG.UI.KeyboardInput (>= 0.15.0)
- FS.GG.UI.Scene (>= 0.15.0)
- FSharp.Core (>= 10.1.302)
- HarfBuzzSharp.NativeAssets.Linux (>= 14.2.1)
- HarfBuzzSharp.NativeAssets.Win32 (>= 14.2.1)
- Silk.NET.GLFW (>= 2.23.0)
- Silk.NET.Input (>= 2.23.0)
- Silk.NET.OpenGL (>= 2.23.0)
- Silk.NET.Windowing (>= 2.23.0)
- Silk.NET.Windowing.Extensions (>= 2.23.0)
- Silk.NET.Windowing.Glfw (>= 2.23.0)
- SkiaSharp (>= 4.150.0)
- SkiaSharp.HarfBuzz (>= 4.150.0)
- SkiaSharp.NativeAssets.Linux (>= 4.150.0)
- SkiaSharp.NativeAssets.Win32 (>= 4.150.0)
NuGet packages (4)
Showing the top 4 NuGet packages that depend on FS.GG.UI.SkiaViewer:
| Package | Downloads |
|---|---|
|
FS.GG.UI.Controls.Elmish
Elmish command, subscription, and program adapters for Controls and KeyboardInput runtime effects. |
|
|
FS.GG.UI.Elmish
Elmish adapter contracts for FS.GG.UI V3 products. |
|
|
FS.GG.UI.Symbology.Render
Thin headless Scene to PNG bridge for the symbology design loop. Wraps the public SkiaViewer ReferenceRendering path via a SceneCodec round-trip and fails loud on any non-passing verdict. |
|
|
FS.GG.UI
Optional BOM / metapackage for the FS.GG.UI framework. Reference this single package at one version to pin the entire coherent FS.GG.UI.* set to that version; any attempt to mix a member at a different version fails loudly at restore/build. Ships no assembly — dependencies only. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.15.0 | 140 | 7/20/2026 |
| 0.14.0 | 117 | 7/19/2026 |
| 0.13.0 | 164 | 7/18/2026 |
| 0.12.0 | 283 | 7/17/2026 |
| 0.11.0 | 384 | 7/16/2026 |
| 0.10.0 | 712 | 7/14/2026 |
| 0.9.2 | 595 | 7/13/2026 |
| 0.9.0 | 1,249 | 7/11/2026 |
| 0.8.0 | 261 | 7/11/2026 |
| 0.7.0 | 212 | 7/11/2026 |
| 0.6.0 | 183 | 7/10/2026 |
| 0.5.0 | 334 | 7/10/2026 |
| 0.4.0 | 336 | 7/9/2026 |
| 0.4.0-preview.1 | 75 | 7/9/2026 |
| 0.3.0-preview.1 | 87 | 7/7/2026 |
| 0.2.0-preview.1 | 77 | 7/6/2026 |
| 0.1.64-preview.1 | 96 | 7/5/2026 |
| 0.1.63-preview.1 | 102 | 7/4/2026 |
| 0.1.62-preview.1 | 73 | 7/4/2026 |
| 0.1.61-preview.1 | 70 | 7/2/2026 |