Repository navigation
Wine Role and Fallback Tiers
Audience: Programmers
Thread Context: N/A at this layer — this is an execution-environment and tooling decision. The thread-creation hazards specific to Wine + gVisor are covered in Wine No-JobSystem Breakthrough.
Platform/Backend Scope: Linux developer hosts (and sandboxes) running the MinGW-cross PE binary under Wine, software-rendered via Lavapipe (CPU Vulkan) or llvmpipe (CPU OpenGL), with NullRHIDevice as the no-graphics floor.
Wine in SparkEngine is a live execution path, not just a CI smoke test. The intent: a developer without a GPU — or inside a sandbox with no GPU passthrough — can cross-compile the engine on Linux with MinGW-w64, run it under Wine, and see real frame-by-frame rendering via Lavapipe or llvmpipe. The build-linux-mingw-wine CI job exists to protect this path, not define it. Decisions about Wine version, DXVK pairing, fork choice, and escape hatches should optimize for live developer experience first, CI second.
A future session asking "should we swap upstream Wine for ValveSoftware/wine?" or "should we drop the flaky Wine job?" should read this page first. Both answers are no, for the reasons below.
ValveSoftware/wine is the base of Proton, optimized for shipping games to players via Steam — not for headless/sandboxed/software-rendered developer use:
- Valve carries upstream
dlls/ntdll/unix/*verbatim — that's exactly where the bugs we care about live. Same syscalls, same gVisor failure modes, no benefit. - Valve's value-add is graphics/audio/input shims (fsync, DXVK pairing, Wayland fixes, anticheat shims). None help a CPU-rasterized headless binary.
- Proton is a moving target tied to Steam releases, not tagged upstream — CI reproducibility tanks if we rebase on it.
- Our carried patches (wine-mirror/wine #61, #62, #63) are written against tagged upstream Wine; carrying them against an unpredictably-rebasing fork multiplies maintenance cost.
The only legitimate reason to add real Proton would be a separate Steam Deck / Proton compatibility tier — a CI job that downloads a pinned Proton release and runs a GameModules/SparkGame* DLL through it on a real Linux host (not gVisor — Proton hates sandboxed syscalls). That's a future enhancement, not a base swap.
The Wine + software-rendering stack has multiple legitimate paths. Each lower tier is slower but uses a different code path in Wine, DXVK, Mesa, and the kernel — so when one tier breaks, the next often still works. Always preserve all rungs. Never delete a slow tier "because the fast one works."
| Tier | Path | When used | Speed |
|---|---|---|---|
| 0 — Native | Real Windows + real GPU | Primary dev/ship target | ~1× |
| 1 — Wine + DXVK + Lavapipe | MinGW PE → Wine → DXVK → Vulkan → Lavapipe (CPU) | Default Linux developer path; tools/wine-run.sh first choice |
~10–50× slower |
| 2 — Wine + WineD3D + llvmpipe | MinGW PE → Wine → WineD3D → OpenGL → llvmpipe (CPU) | Tier 1 unavailable / Lavapipe broken / DXVK trips a gVisor syscall | ~100–500× slower |
| 3 — Wine + NullRHIDevice | MinGW PE → Wine → NullRHI (no graphics calls) | Logic-only smoke; tier 2 also broken | ~wall-clock |
| 4 — Native Linux + NullRHIDevice | GCC ELF → NullRHI (no Wine) | Wine itself broken in the environment | Fastest, but skips the PE/Win32 path |
The intended selection logic:
if DXVK present and Lavapipe importable and ! gvisor_known_bad: use tier 1
elif WineD3D + llvmpipe importable: use tier 2
elif Wine itself runs: use tier 3 (-rhi=null)
else: use tier 4 (skip Wine, native Linux)
Each layer needs an opt-out so a developer can isolate which layer is failing without rebuilding the world. Several originally-"needed" hatches have since landed.
| Hatch | Purpose | Status |
|---|---|---|
WINEDEBUG=+seh,+virtual |
Verbose signal/memory trace | Built-in |
WINEPRELOADRESERVE= |
Disable Wine's address-space preloader | Built-in (no help under gVisor) |
SPARK_WINE_PROBE=…probe.exe |
Pre-flight a known-good PE so we fail fast | Landed |
SPARK_WINE_GVISOR_SHIM=1 |
LD_PRELOAD the gs.base shim | Landed (now auto-detected) |
SPARK_SKIP_WINE=1 |
Skip Wine, fall through to tier 4 |
Landed (present in tools/wine-run.sh) |
SPARK_WINE_VERSION=…/wine64 |
Pick a specific Wine binary | Still not present — script auto-selects |
| Hatch | Purpose | Status |
|---|---|---|
WINEDLLOVERRIDES=d3d11=n,b |
Force WineD3D over DXVK (tier 1→2) | Built-in |
DXVK_HUD=fps,memory |
Confirm DXVK is executing | Built-in |
SPARK_WINE_BACKEND={dxvk|wined3d|null} |
One var picks the tier |
Landed (present in tools/wine-run.sh) |
DXVK_LOG_LEVEL=info |
DXVK self-diagnostics | Built-in |
| Hatch | Purpose | Status |
|---|---|---|
VK_ICD_FILENAMES=…lvp_icd…json |
Force Lavapipe | Built-in |
LIBGL_ALWAYS_SOFTWARE=1 |
Force llvmpipe (OpenGL) | Built-in |
MESA_LOADER_DRIVER_OVERRIDE=llvmpipe |
Same, targeted | Built-in |
GALLIUM_DRIVER=llvmpipe |
Same, lower-level | Built-in |
SPARK_FORCE_SOFTWARE_GFX=1 |
Umbrella: sets all the above + WineD3D override |
Landed (present in tools/wine-run.sh) |
| Hatch | Purpose | Status |
|---|---|---|
-rhi=null |
Force NullRHIDevice from start |
Built-in |
-rhi=opengl |
OpenGL backend (bypass DXVK) | Built-in |
-headless |
Skip window creation | Built-in |
-test-frames N |
Render N frames then exit | Built-in |
SPARK_RHI_BACKEND=null|opengl|d3d11|vulkan |
Env-var equivalent of -rhi=
|
Landed (present in tools/wine-run.sh) |
| Hatch | Purpose | Status |
|---|---|---|
EngineContext::Get()->IsRunningUnderWine() |
Runtime branch for Wine quirks | Landed (Utils/WineDetection.h) |
Spark::LogWineEnvironmentIfApplicable() |
Startup banner Running under Wine 9.0
|
Landed |
IsRunningUnderGvisor() |
Detect gVisor to auto-pick a safer tier |
Landed (Utils/WineDetection.{h,cpp}, also used by Graphics/RHI/RHIFactory.cpp) |
The instinct on a gVisor regression is "fix tier 1." Correct as the long-term goal (patches #61/#62/#63), but even when tier 1 is healthy, tiers 2–3 must remain working code paths:
- Mesa drift — Lavapipe correctness has regressed on edge cases (timeline semaphores, sparse bindings); tier 2 keeps the engine visible while you wait for the next Mesa release.
- DXVK drift — DXVK occasionally bumps its minimum Vulkan driver version; older distros fall out of tier 1 and tier 2 picks up the slack.
- Sandbox proliferation — gVisor is one example; Firecracker, runD, and future harness sandboxes each may break a different layer. A working ladder means "swap rungs," not "won't run."
- Test-signal granularity — when tier 1 fails and tier 2 succeeds, you know the bug is in DXVK or Lavapipe, not Wine or SparkEngine.
Rule of thumb: if tempted to delete a slower path because the faster one works, add it as an escape hatch instead.
-
Original entry date: 2026-04-14 (
wine-role-and-fallback-tiers-2026-04-14.md, type: Decision + Observation) - Verified against codebase 2026-06-08.
- Status bullets:
- Still holds. The "upstream Wine, not Valve" rationale and the five-tier ladder are unchanged.
-
Most "needed" action items have landed:
SPARK_WINE_BACKEND,SPARK_FORCE_SOFTWARE_GFX,SPARK_SKIP_WINE, andSPARK_RHI_BACKENDare all present intools/wine-run.sh;IsRunningUnderGvisor()is implemented inUtils/WineDetection.{h,cpp}and consumed byGraphics/RHI/RHIFactory.cpp. -
One item still open:
SPARK_WINE_VERSIONis not present intools/wine-run.sh(script still auto-selects the Wine binary).
- Wine No-JobSystem Breakthrough — the tier-1-under-gVisor reliability fix
- GPU/CPU Separation Plan — RHI backend parity and NullRHIDevice
- SparkBuild In-Tree — sibling developer tooling
Published from 2b03dc797148. Edit the canonical source in wiki/.
- Documentation
- Docs route
- Wiki index
- Guides
- Tutorials
- Samples
- Examples
- API Reference
- API route
- Reference
- Build Guide
- Dependencies
- FAQ
- Changelog
- Roadmap
- Contributing
- Code of Conduct
- Home
- FAQ
- Getting Started
- Quick-Start Tutorial
- Making Your First Game
- Making Your First Multiplayer Game
- Artist Workflow Guide
- Editor Walkthrough
- Migration Guide
- How SparkEngine Works
- Architecture Overview
- Engine Architecture Flowchart
- Creating a Game Module
- Game Modules (catalog)
- Entity Component System
- Rendering and Graphics
- Physics
- Cloth Simulation
- Audio
- Input System
- Camera System
- Scripting with AngelScript
- Visual Scripting
- AI and Navigation
- Animation
- 2D Systems
- Networking
- Dedicated Server
- Multiplayer Quick Start
- Area Server Architecture
- Scene Management
- Large World Support
- Collaborative Editing
- Coroutine System
- Event System
- Event Response System
- Job System
- UI System
- UI Layout Extensions
- Localization
- Dialogue System
- Destruction System
- Replay System
- Achievement System
- Loading System
- Mod System
- Content Delivery
- Tween System
- Memory Integrity
- Gameplay Systems
- Terrain and Procedural Generation
- Save System
- Persistence System
- Day Night Cycle and Weather
- Cinematic Sequencer
- Runtime Prefabs
- SparkEditor
- Editor Tutorials
- SparkConsole
- SparkDaemon
- Shader Pipeline
- Asset Pipeline
- Asset Validation
- Asset Migration
- Game Packaging
- Online Services
- DataTable System
- Loot and Crafting System
- CSG System
- Font System
- Timer Manager
- Movie Render Pipeline
- HLOD and World Partition
- Remote Debug System
- Selection Manager
- Asset Dependency Graph
- Editor Automation
- File Watcher
- Project Templates
- System Requirements
- VR Support
- Mobile Platform
- Accessibility
- Platform Input
- Platform Certification
- Cross-Compilation: Wine Testing
- RHI Abstraction Layer
- D3D11 Backend
- D3D12 Backend
- Vulkan Backend
- OpenGL Backend
- Metal Backend
- DXR Raytracing
- Hybrid Ray Tracing
- Upscaling (DLSS/FSR)
- Render Graph
- Shader Graph
- GPU Particles
- GPU-Driven Rendering
- Volumetric Fog
- Volumetric Clouds
- Global Illumination
- Virtual Texturing
- Water Rendering
- Clustered Lighting
- Material System
- Post-Processing
- Shadow System
- Particle System
- Decal System
- Sky and Atmosphere
- Foliage System
- Mesh Shaders
- Neural Rendering
- Configuration Reference
- Performance Tips
- Benchmark Framework
- Threading Model
- Fuzz Policy and Parser Security
- Memory Safety
- Memory Management Patterns
- Build System and CMake Modules
- Profiler and Debugging
- Performance Profiling Guide
- Telemetry System
- Crash Reporting
- Golden Image Testing
- Utilities
- Testing
- Fuzz Policy and Parser Security
- Codebase Statistics
- Codebase Health
- Error Handling Patterns
- Hot Reload Overview
- Troubleshooting
- Contributing
- Workflow Patterns
- Build Optimizations
- CI Reproducible Builds
- GitHub API and PR Checks
- Git Rebase Conflicts
- Clang-Format
- Code Quality Violations
- AI Bloat Pattern
- MinGW + Wine Cross-Compilation
- Live Editor Testing
- Engine & Renderer Landscape
- DuetOS Portability Catalog
- Five-Engine Analysis
- Eleven-Engine Analysis
- ThorVG / Unity Graphics Analysis
- Advanced Techniques Catalog
- Third-Party Library Evaluation
- Engine Viability Evaluation
- Engine Feature Recommendations
- Project Recommendations
- Mac Compatibility Analysis
- Codebase Observations
- Codebase Bloat Audit
- Test Suite Audit
- Documentation Coverage Audit
- ThirdParty Dependencies Audit
- Load Test Baseline
- Gameplay Systems Status
- SparkGame Module Status
- Stub and Abandoned Features
- Memory Integrity System
- Memory Safety Evaluation
- Hardware Acceleration Systems
- Jolt Physics Integration
- GPU/CPU Separation Plan
- Daemon Services Architecture
- Reflection & Polymorphism Refactoring Plan
- SparkBuild In-Tree
- Wine No-JobSystem Breakthrough
- Wine Role and Fallback Tiers