Logo FS-Skia-UI

Silk.NET Window Platform Failure Analysis

Date: 2026-05-26 22:27 Europe/Vienna

Summary

The persistent GUI runtime evidence run is currently blocked by a native window creation failure, not by missing GPU passthrough. The container can see the GPU and can create Vulkan/OpenGL device-level diagnostics, but Viewer.runApp fails before a persistent window is created:

status=unsupported mode=interactive-window command=dotnet-fsi-supported-host-runApp blocked-stage=Window classification=UnsupportedEnvironment category=Startup message=Silk.NET_persistent_viewer_launch_failed:_Couldn't_find_a_suitable_window_platform._(GlfwPlatform_-_not_applicable)_https://dotnet.github.io/Silk.NET/docs/hlu/troubleshooting.html

This matters because the evidence contract for 018-persistent-gui-runtime requires a supported-host persistent interactive launch artifact. Bounded smoke, first-frame evidence, screenshot evidence, pixel-readback evidence, and unsupported-host diagnostics are useful, but they cannot be treated as proof that a generated graphical app remains open for interactive play.

Observed Environment

The container presents desktop-session signals:

DISPLAY=:1
WAYLAND_DISPLAY=wayland-0
XDG_RUNTIME_DIR=/run/user/1000
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus

The expected sockets are present:

/run/user/1000/wayland-0
/tmp/.X11-unix/X1

GPU/device evidence is positive:

vulkaninfo --summary
  deviceName = AMD Radeon Graphics (RADV RENOIR)
  driverName = radv

glxinfo -B
  direct rendering: Yes
  OpenGL renderer string: AMD Radeon Graphics (radeonsi, renoir, ACO, ...)

Silk.NET package evidence is also not obviously missing:

Current Failure Boundary

The failing operation is the Silk.NET window platform selection path. The code reaches Window.Create / window.Initialize, and Silk reports:

Couldn't find a suitable window platform. (GlfwPlatform - not applicable)

This is distinct from:

The available evidence points at a platform/windowing bridge issue: Silk/GLFW does not consider the current X11/Wayland environment applicable for creating a native window, despite GPU and display variables being visible.

Why GPU Passthrough Is Not Sufficient

GPU passthrough proves that rendering devices can be discovered and used by tools such as Vulkan or GLX. A persistent GUI app needs additional layers:

  1. A usable display server connection.
  2. Window-system protocol compatibility: X11, Wayland, or a supported fallback.
  3. Authentication/permissions for the display socket.
  4. Native backend support in the chosen windowing library.
  5. Runtime asset loading for managed and native Silk/GLFW assemblies.
  6. The app's event loop successfully opening and holding a window.

This container satisfies at least some lower layers: GPU, Vulkan, GLX, visible display variables, and visible sockets. The failure occurs at layer 4 or 5 from the perspective of Silk.NET windowing.

Evidence Audit Impact

EvidenceAudit still fails for final readiness because:

The package-resolution blocker was narrowed: generated app-source restore/test can pass against the local 0.1.17-preview.1 package set. That does not clear the native persistent-window evidence requirement.

Likely Causes

1. GLFW rejects the proxied display setup

Silk.NET 2.23 uses the GLFW windowing backend here. The message names GlfwPlatform - not applicable, so GLFW platform discovery is the first suspect.

Possible reasons:

2. dotnet fsi is not representative of a normal executable

The recorded persistent launch attempt used an FSI script to load the built assemblies. FSI is useful for public API evidence, but native desktop windowing can differ from a normal executable because:

This does not make the failure meaningless, but it means the next confirmation should use a compiled executable.

3. Window backend support is too narrow

The runtime currently relies on Silk.NET/GLFW as the persistent window host. If GLFW is not robust in this container class, the project may need either:

4. Generated product matrix has a separate profile issue

GeneratedProductCheck also remains non-authoritative because the headless-scene/source profile is compiling app-oriented Program.fs code without the app package set. That is separate from the Silk window failure, but it prevents the final generated verification record from becoming authoritative.

Recommended Further Analysis

A. Reproduce with a compiled minimal executable

Create a tiny console project that references FS.Skia.UI.SkiaViewer, FS.Skia.UI.Scene, and the exact Silk package set, then calls Viewer.runApp with a host that closes on the first tick after the first frame. Run it with:

dotnet run --project /tmp/fs-skia-window-probe/WindowProbe.fsproj

Record:

If the compiled executable succeeds, the fix is to stop using FSI for native persistent launch readiness and use an executable probe for T050 evidence.

If it fails the same way, the issue is container/window-platform compatibility.

B. Run direct GLFW/Silk platform probes

Add a small diagnostic target or temporary probe that only does:

let windowOptions = WindowOptions.DefaultVulkan
let window = Window.Create windowOptions
window.Initialize()

Capture exception type, inner exceptions, loaded assemblies, and native probing paths. This should be separate from Skia rendering so we know whether failure happens before any renderer setup.

C. Check X authority and Wayland/X11 selection

Collect:

echo "$XAUTHORITY"
xauth list "$DISPLAY"
xdpyinfo -display "$DISPLAY"
WAYLAND_DEBUG=1 dotnet run --project <probe>

Also test forced protocol choices if GLFW/Silk honors them in this environment:

unset WAYLAND_DISPLAY
dotnet run --project <probe>

unset DISPLAY
dotnet run --project <probe>

This will show whether GLFW succeeds on one protocol and fails on the other.

D. Compare host vs container

Run the same compiled probe:

If host succeeds and container fails, document the container requirements:

E. Improve runtime diagnostics

The current failure is classified correctly as UnsupportedEnvironment, but the message is still generic. Improve SkiaViewer diagnostics to include:

This would make future audit evidence more actionable without weakening the readiness rules.

F. Fix generated product profile separation

The headless-scene generated profile should not compile app-only runtime code that references SkiaViewer, KeyboardInput, Controls, or Controls.Elmish unless those packages are selected. Possible fixes:

This fix is required for authoritative generated verification, independently of the Silk.NET container window issue.

Possible Fix Paths

Path 1: Use a compiled persistent-window probe for readiness

This is the narrowest change if FSI is the only failing context. Replace the current T050 native launch FSI exercise with a compiled app or generated product dotnet run evidence command. Keep FSI for pure API and MVU transition tests.

Expected outcome:

Path 2: Treat this container as unsupported and require host evidence

If compiled probes fail in the same way, the honest readiness state is:

Expected outcome:

Path 3: Update container/windowing setup

If diagnosis points at X11/Wayland auth or missing native runtime setup, fix the container invocation/image. Candidate changes:

Expected outcome:

Path 4: Add an alternate interactive backend

If GLFW remains unsuitable for the project's supported Linux container profile, evaluate an alternate supported windowing path. This is larger and should be planned explicitly because it changes runtime support scope.

Expected outcome:

Recommended Next Step

Start with the compiled minimal executable probe. It gives the highest signal with the least code churn:

  1. If it passes, switch readiness evidence to the executable probe and rerun EvidenceAudit.
  2. If it fails with the same GlfwPlatform - not applicable message, focus on container display/auth/backend compatibility.
  3. In parallel, fix the generated headless-scene profile separation so generated verification can become authoritative once the native window evidence is available.

Type something to start searching.