acdream/docs/plans/2026-07-26-modern-runtime-slice-l.md

14 KiB
Raw Blame History

Modern runtime Slice L — Linux graphical host and evidence-gated GPU work

Status: DEFERRED 2026-07-27 — L0 COMPLETE; L1 IMPLEMENTATION CHECKPOINT COMPLETE; PHYSICAL-LINUX DRIVER GATE AND L2L6 PARKED Parent: 2026-07-24-modern-runtime-architecture.md, Slice L Authorization: the user approved Slices FL on 2026-07-24 Purpose: ship the existing modern OpenGL client on supported Linux drivers with identical Runtime behavior and accepted visual presentation, then make only GPU changes whose measured bottleneck and visual equivalence are proven.

1. Entry contract

Slice L begins only after Slice K proves Linux Runtime/Core.Net/Content, portable paths/config/credentials, one production headless host, deterministic wire timing, shared immutable content, and a clean 30-session stress gate.

L does not fork the game client into a second Linux implementation. The same AcDream.App, GameRuntime, retained UI, rendering pipeline, shaders, and resource owners run on both platforms. Platform-specific behavior is confined to typed host services selected once at startup.

2. Mandatory renderer boundary

The modern path remains mandatory:

  • OpenGL 4.3 core;
  • GL_ARB_bindless_texture;
  • GL_ARB_shader_draw_parameters;
  • the current bindless texture/SSBO/MDI layouts and shaders.

There is no legacy renderer, texture-unit fallback, reduced-distance mode, or platform-specific gameplay/render path. An unsupported driver fails startup with a precise capability report.

Driver acceptance begins with a committed matrix:

  • AMD Mesa/RadeonSI on X11;
  • AMD Mesa/RadeonSI on Wayland;
  • NVIDIA proprietary driver on X11;
  • NVIDIA proprietary driver on Wayland where Silk's backend is supported;
  • Intel only if the hardware/driver exposes every mandatory extension.

Each row records distribution/kernel, display protocol, compositor, GPU, driver, OpenGL vendor/renderer/version, extension presence, swap interval, monitor refresh, and audio backend. A row may be “unsupported” only because a mandatory capability is absent or the native window backend cannot create the required context—not because a visual mismatch was waived.

3. Initial platform inventory

Portable foundations already exist:

  • Silk.NET owns window/input/OpenGL APIs;
  • OpenAL Soft is designed for PulseAudio/PipeWire/CoreAudio as well as Windows;
  • shader and UI asset paths use AppContext.BaseDirectory/Path.Combine;
  • BitmapFont.TryLoadSystemMonospaceFont already includes common Linux font paths;
  • Runtime/Core.Net/Content are presentation-independent after J/K.

Known Linux blockers and audit targets:

  • FramePacingController unconditionally constructs WindowsHighResolutionFramePacingWaiter, which throws off Windows.
  • The OpenAL Soft native package/runtime assets must be verified for each Linux RID rather than assumed.
  • Silk window backend/native dependency publication is not packaged or tested.
  • the smoke-plugin MSBuild copy target uses Windows path separators;
  • key bindings, cursor creation, clipboard, relative mouse, monitor refresh, window-state callbacks, and high-DPI scaling need live X11/Wayland evidence;
  • settings, layouts, keymaps, logs, screenshots, and diagnostics must use the portable path owner established in K rather than %LOCALAPPDATA% wording or ad hoc paths;
  • no Linux graphical CI/smoke environment exists;
  • no Linux driver timer-query validation or screenshot baseline exists;
  • no package/install/uninstall contract exists.

4. Platform-service contracts

Frame pacing

Keep the existing display-aware policy:

  • VSync uses the driver's swap wait.
  • VSync-off normal play uses a refresh-matched low-CPU software deadline.
  • explicit uncapped diagnostics perform no wait.

Replace direct Windows construction with IFramePacingWaiterFactory. Windows retains the high-resolution waitable timer. Linux uses an absolute-monotonic deadline wait (clock_nanosleep or a proven equivalent) with cancellation-safe disposal. Neither path busy-spins for the normal wait. The same missed-deadline rebase rule prevents catch-up bursts.

Gate both waiters for deadline error, CPU usage, cancellation, disposal, missed deadlines, monitor changes, and long stalls.

Paths and persistence

Reuse K's portable path owner for:

  • settings and key bindings;
  • retained UI layouts;
  • logs and diagnostic captures;
  • screenshots and automation artifacts;
  • plugins;
  • prepared assets and DAT location overrides.

No feature reads a Windows-only environment variable/path at its call site.

Input/window

Test the exact retained-input pipeline on X11 and Wayland:

  • keyboard keys, modifiers, text input, repeat, and configurable bindings;
  • mouse buttons, wheel, press-time selection, dragging, resizing, and cursors;
  • relative mouse capture, recenter/release, and focus loss;
  • clipboard;
  • window move/resize/minimize/restore/close and monitor transition;
  • DPI/framebuffer size versus logical size.

Retail input behavior remains the acceptance oracle; Linux key/scancode adaptation cannot alter action semantics.

Audio

OpenAL initialization remains fail-open only for the existing explicit no-audio mode or unavailable device. Package the correct OpenAL Soft native asset, identify PulseAudio/PipeWire device/context selection, and prove source/buffer/context teardown. Audio absence must not stall the frame or change Runtime/VFX timing.

5. Packaging contract

Produce repeatable linux-x64 artifacts first; add linux-arm64 only after the complete native dependency and GL extension matrix passes.

Artifacts contain:

  • the App and managed dependency closure;
  • Silk window/input/OpenGL native dependencies;
  • OpenAL Soft;
  • shaders and retained-UI XML;
  • plugin directory/manifest support;
  • a launch entry point and version/provenance record.

DATs, account credentials, and the machine-local acdream.pak are not bundled. Startup diagnostics identify their configured paths without exposing secrets.

Provide:

  • framework-dependent development publish;
  • self-contained release publish if native/runtime size and licenses are acceptable;
  • desktop entry/icon/install documentation;
  • package validation on a clean Linux user account.

6. Execution

L0 — platform services and Linux build

Complete at 66f114b2 (2026-07-27). Runtime now owns the shared XDG/Windows ApplicationPathSet; App owns one typed graphical platform/native manifest and factory-selected Windows/Linux kernel waiter. Settings, keybindings, Studio, diagnostics, and user plugins consume the portable paths, with no-overwrite Windows legacy migration. The RID-aware smoke-plugin build and publish paths and the Ubuntu graphical CI/package guard pass. Exact Windows/Linux evidence and rollback are recorded in ../research/2026-07-27-slice-l0-platform-services.md.

  • Add Linux App build/publish jobs to CI after K's non-graphical Linux jobs.
  • Add typed platform capability, path, pacing, and native-dependency owners.
  • Implement the Linux monotonic frame waiter and factory selection.
  • Correct cross-platform MSBuild paths and packaging assumptions.
  • Add source/dependency guards against platform checks outside platform-owner classes.

Gate: App restores/builds/publishes for linux-x64; unit tests prove both frame waiters and portable paths; no Windows P/Invoke executes on Linux.

L1 — context, extensions, and native backends

Implementation checkpoint at 11501d52 (2026-07-27). The exact packaged GLFW 3.4 backend is selected before window creation; X11/Wayland choice, complete passive capabilities, active modern-GL calls, optional OpenAL smoke, atomic reports, actionable exit 4, and zero-debt successful/rejected Studio shutdown are implemented. Windows AMD passes the supported smoke. WSLg X11, Wayland, and AMD D3D12 paths correctly reject only missing GL_ARB_bindless_texture. These are negative rows. At the user's direction on 2026-07-27, physical Mesa/RadeonSI/NVIDIA supported-driver evidence and L2L6 are deferred; when Slice L resumes, that physical gate remains first and L2 must not begin before it passes. Exact evidence is ../research/2026-07-27-slice-l1-graphical-capability-checkpoint.md.

  • Create a Linux window and OpenGL 4.3 core context under X11 and Wayland.
  • Capture the full capability record before renderer construction.
  • Verify mandatory bindless and shader-draw-parameter calls, MDI, SSBOs, persistent resource ownership, timer queries, framebuffer sRGB/depth/stencil, and swap behavior.
  • Initialize input and OpenAL Soft.
  • Fail unsupported rows with one actionable diagnostic.

Gate: a packaged smoke scene opens, renders, accepts input, plays optional audio, captures a screenshot, and shuts down with zero GL/OpenAL/window debt on each supported matrix row.

L2 — complete graphical connected route

  • Run the same exact-binary lifecycle/reconnect route used on Windows.
  • Run the canonical nine-stop route with movement, jump, combat, portal, revisit, and graceful shutdown.
  • Verify radar, retained UI, inventory paperdoll, Use/approach, combat facing, spell effects, portal tunnel/materialization/exit, cursors, chat, and audio.
  • Compare pinned-camera images against accepted Windows references using the existing per-channel tolerance and differing-pixel-fraction rule.
  • Record CPU/GPU frame history, allocation, managed/native/GPU residency, handles, threads, and driver facts.

Gate: lifecycle/resource invariants and retail behavior match; screenshot differences are within the committed driver-aware threshold and individually inspected; no resource growth survives repeated portals.

L3 — packaging and clean-machine gate

  • Publish versioned Linux artifacts.
  • Test install, first launch, configuration discovery, plugin discovery, upgrade, and uninstall on a clean user account.
  • Prove no implicit write occurs beside a read-only installed binary.
  • Prove missing DAT/pak/driver/audio conditions produce actionable, credential-safe errors.

Gate: a clean machine reaches world, completes the route, exits gracefully, and preserves settings/layout/key bindings under XDG paths.

L4 — accurate Linux profiling

  • Validate GL timer-query attribution on each accepted driver.
  • Capture capped and uncapped canonical route, dense-town, portal-window, and long-duration profiles on a physical local display.
  • Attribute CPU update, render submission, GPU passes, allocations, upload, particle, light, culling, and command-compaction costs.
  • Compare Windows and Linux without mixing RDP/display protocol populations.

Gate: the dominant remaining CPU/GPU stages are named with reliable samples. If no GPU stage is material, do not migrate work merely because the roadmap lists candidates.

L5 — evidence-gated GPU changes

For each candidate independently:

  1. show it is a dominant stage in L4 evidence;
  2. write a focused plan with ownership, synchronization, fallback/error, and teardown contracts;
  3. implement one bisectable change;
  4. run deterministic/Release/connected/resource gates;
  5. publish CPU and GPU before/after plus visual equivalence;
  6. keep the change only if the intended metric materially improves without regressions.

Candidate order, only when evidence supports it:

  • GPU visibility culling;
  • indirect command compaction;
  • particle simulation;
  • bounded light selection.

No candidate changes server authority, physics, animation ordering, DAT effect semantics, retained UI, or visible draw range.

L6 — closeout

  • Repeat the accepted Linux driver, packaging, connected, screenshot, resource, and performance matrices.
  • Run Windows regression gates.
  • Audit every GPU migration and exact rollback.
  • Update architecture, milestones, roadmap, issues/divergences, AGENTS/CLAUDE, and durable memory.

Gate: supported Linux graphical artifacts ship the same intended client behavior; every retained GPU change has measured evidence and visual parity; all teardown ledgers converge.

7. Adversarial matrix

  • X11 versus Wayland, compositor on/off where practical;
  • AMD versus NVIDIA extension/function-pointer behavior;
  • mandatory extension advertised but call returns invalid handle/error;
  • no display, no audio device, missing font, missing clipboard service;
  • monitor hotplug, refresh change, DPI change, minimize, suspend/resume, focus loss, and close during portal;
  • VSync ignored, adaptive sync, software pacing stall, timer interruption, and clock discontinuity;
  • read-only install directory and XDG paths with spaces/non-ASCII;
  • missing/corrupt pak, DAT mismatch, plugin failure, shader compile failure;
  • GL context loss/failure during construction and teardown;
  • audio context/buffer/source partial construction failure;
  • screenshot differences from gamma, texture filtering, precision, clip origin, or driver shader compilation;
  • GPU migration overflow, indirect count mismatch, fence delay, stale generation, device reset, and visibility false-negative;
  • Windows regression after each platform abstraction.

8. Non-goals

  • No legacy renderer or extension fallback.
  • No reduced visual distance or Linux-specific quality default.
  • No renderer rewrite solely for portability.
  • No GPU migration without measured dominance.
  • No macOS graphical support in Slice L; the portable Runtime/headless work and typed platform services should make a later macOS plan smaller, but Apple OpenGL capability constraints require a separate decision.
  • No bundled DAT files, credentials, or local server.

9. Commit and rollback discipline

Land L0L6 as separate buildable commits. Record the full production SHA and exact git revert <sha> after each focused/Linux/Windows/connected/visual gate. GPU candidates each receive their own plan, commit, measurement, visual gate, and rollback; rejected experiments are reverted rather than hidden behind dormant alternate paths.

L0 rollback:

git revert 66f114b258c0c37b51a7c0e04ca0d6441f4b1699

L1 implementation-checkpoint rollback:

git revert 11501d52cad942850d88f83490710faf1d5cdf28