Windows ~40% slower than Linux on the same machine (4070: ~60 vs ~100 FPS) #247

Open
opened 2026-10-02 11:43:53 +00:00 by sky_line · 0 comments
Owner

Report

Same user, same machine (RTX 4070), same scene:

  • Linux: ~100 FPS
  • Windows: ~60 FPS

NVIDIA's Windows driver is usually the faster one, so the gap is probably ours: build, platform layer, or presentation.

Suspects, in rough order

  1. Presentation / vsync. A number that sits at ~60 hints at FIFO present on a 60 Hz display, or DWM composition. Check the present mode chosen on Windows, the vsync setting, the monitor refresh rate, and whether the window is borderless or exclusive. With VK on Windows, FIFO/MAILBOX availability differs, and windowed presents go through DWM.
  2. Timer resolution. The Windows build uses USE_SDL_WINDOW=ON, so LLWindowWin32's timeBeginPeriod(1) never runs.
    • RenderFPSLimit's sleep_until would overshoot by up to ~15.6 ms; it keeps only 2 ms of slack.
    • Worker threads that sleep (texture fetch/decode, the ingest worker, the fill worker handoff) also wake late, which stalls vk_fillJoinWait / decode-driven frames.
    • Fix: call timeBeginPeriod(1) at startup on Windows (and timeEndPeriod at exit), or use a high-resolution waitable timer.
  3. Codegen.
    • The Linux build may target a higher ISA level (see fix_isa_note.py); the Windows clang-cl build may be baseline SSE2.
    • Compare /arch, /O2 and LTO/PGO flags between scripts/wincross/configure.sh and the Linux configure.
    • Debug iterators / _ITERATOR_DEBUG_LEVEL must be 0.
    • The CRT allocator: Linux glibc malloc vs the UCRT heap on a heavy-allocation codebase. Consider mimalloc.
  4. WDDM residency / paging. The budget behaviour from #244 could also cause per-frame paging or eviction on Windows.
  5. Background yield. BackgroundYieldTime (40 ms) applies when the window isn't foreground. Make sure focus is detected correctly with SDL on Windows.

Asks

From the reporter, with RenderVKSectionLog and RenderVKGpuTimers on, same spot on both OSes:

  • Slipstream.log with the GPU ms/frame, GPU sub ms/frame and SECTIONS avg lines. These show whether Windows is CPU-bound (renderFrame / LL sections), GPU-bound (pass timings) or present-bound (vk_acquireWait high with low GPU total).
  • Monitor refresh rate, vsync setting, RenderFPSLimit, windowed or fullscreen.
## Report Same user, same machine (RTX 4070), same scene: - **Linux: ~100 FPS** - **Windows: ~60 FPS** NVIDIA's Windows driver is usually the faster one, so the gap is probably ours: build, platform layer, or presentation. ## Suspects, in rough order 1. **Presentation / vsync.** A number that sits at ~60 hints at FIFO present on a 60 Hz display, or DWM composition. Check the present mode chosen on Windows, the vsync setting, the monitor refresh rate, and whether the window is borderless or exclusive. With VK on Windows, FIFO/MAILBOX availability differs, and windowed presents go through DWM. 2. **Timer resolution.** The Windows build uses `USE_SDL_WINDOW=ON`, so `LLWindowWin32`'s `timeBeginPeriod(1)` never runs. - `RenderFPSLimit`'s `sleep_until` would overshoot by up to ~15.6 ms; it keeps only 2 ms of slack. - Worker threads that sleep (texture fetch/decode, the ingest worker, the fill worker handoff) also wake late, which stalls `vk_fillJoinWait` / decode-driven frames. - Fix: call `timeBeginPeriod(1)` at startup on Windows (and `timeEndPeriod` at exit), or use a high-resolution waitable timer. 3. **Codegen.** - The Linux build may target a higher ISA level (see `fix_isa_note.py`); the Windows clang-cl build may be baseline SSE2. - Compare `/arch`, `/O2` and LTO/PGO flags between `scripts/wincross/configure.sh` and the Linux configure. - Debug iterators / `_ITERATOR_DEBUG_LEVEL` must be 0. - The CRT allocator: Linux glibc malloc vs the UCRT heap on a heavy-allocation codebase. Consider mimalloc. 4. **WDDM residency / paging.** The budget behaviour from #244 could also cause per-frame paging or eviction on Windows. 5. **Background yield.** `BackgroundYieldTime` (40 ms) applies when the window isn't foreground. Make sure focus is detected correctly with SDL on Windows. ## Asks From the reporter, with `RenderVKSectionLog` and `RenderVKGpuTimers` on, same spot on both OSes: - `Slipstream.log` with the `GPU ms/frame`, `GPU sub ms/frame` and `SECTIONS avg` lines. These show whether Windows is CPU-bound (renderFrame / LL sections), GPU-bound (pass timings) or present-bound (`vk_acquireWait` high with low GPU total). - Monitor refresh rate, vsync setting, `RenderFPSLimit`, windowed or fullscreen.
sky_line added this to the Slipstream project 2026-10-06 15:04:15 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
sky_line/Slipstream#247
No description provided.