Steam Deck Performance Guide
The Steam Deck is the toughest UE5 target in the consumer market. Eight RDNA 2 compute units, no hardware ray tracing, 15 W shared TDP, and a 1280x800 panel that the public expects you to also tune for OLED at 90 Hz. Every shipped UE5 title that runs on Deck has made the same fundamental compromise: 30 fps locked, FSR2 Balanced, Lumen tuned down or off. This tutorial covers the hardware, the runtime detection trap, and the specific .ini overrides that make a UE5 build playable on the Deck.
Why Steam Deck is hard
The Deck is a fixed target with the constraints of a budget gaming laptop and the cooling of a mid-range phone. Eight RDNA 2 CUs at up to 1.6 GHz is roughly 1.6 TFLOPs of GPU — a quarter of XSS, a sixth of PS5. There's no hardware ray tracing path; HWRT-Lumen and DXR materials silently fall back or fail. The CPU is four Zen 2 cores; UE5 game-thread budget on Deck is tighter than on any console.
And critically: the Deck is shipping now, with millions of units. Steam Deck Verified is a real cert process; titles that fail get demoted from "Verified" to "Playable" or "Unsupported", and players see the badge before they buy.
The Van Gogh APU and RDNA 2 specifics
| Spec | LCD Deck | OLED Deck |
|---|---|---|
| APU | AMD Van Gogh 7nm | AMD Van Gogh 6nm (refresh) |
| CPU | 4 Zen 2 cores @ 2.4–3.5 GHz | same |
| GPU | 8 RDNA 2 CUs @ 1.0–1.6 GHz | same silicon, better thermals |
| Memory | 16 GB LPDDR5 @ 5500 MT/s | 16 GB LPDDR5 @ 6400 MT/s |
| TDP | 4–15 W | 4–15 W |
| Display | 1280x800 60 Hz | 1280x800 90 Hz HDR (1000 nit) |
OLED isn't faster — same CUs, same clocks. The 6 nm process shrink yields better sustained thermals and battery; LPDDR5 is faster (~16% memory bandwidth bump). Don't ship a separate "OLED preset" expecting more frames — ship a "90 Hz target if you have headroom" mode that benefits OLED automatically.
A common community misconception is that the OLED Deck has a lower TDP cap. It doesn't — both LCD and OLED are configurable to 15 W via Steam OS settings.
Detecting Steam Deck at runtime
This is the trap that catches every team's first attempt: UE's IsRunningOnPlatform macros do not return Steam Deck. Under Proton, the binary thinks it's running on Windows. Native Linux builds report Linux but not Deck specifically.
The right way to detect:
// Option 1: Steamworks SDK (preferred) if (SteamUtils() && SteamUtils()->IsSteamRunningOnSteamDeck()) { // Apply Deck-specific scalability UDeviceProfileManager::Get().SetActiveDeviceProfile(TEXT("SteamDeck")); } // Option 2: Environment variable FString DeckVar = FPlatformMisc::GetEnvironmentVariable(TEXT("SteamDeck")); if (DeckVar == TEXT("1")) { // Same }
The Steamworks SDK approach is more reliable; the env var is set by Valve's launch wrapper but can be missing in development scenarios.
Configure your .uplugin to use LoadingPhase=EarliestPossible for the module containing this detection — the device profile must be applied before scalability tier evaluation, which happens early in startup.
Building a SteamDeck device profile
Per Epic's Steam Deck Quick Start, the canonical structure is a Config/SteamDeck/ overlay plus a DeviceProfile entry:
[SteamDeck DeviceProfile] DeviceType=Windows BaseProfileName=Windows +CVars=r.AntiAliasingMethod=4 ; TSR (or set 2 for FSR2 plugin) +CVars=r.TemporalAA.Upsampling=1 +CVars=r.ScreenPercentage=70 +CVars=r.Lumen.HardwareRayTracing=0 ; Van Gogh has no HW RT +CVars=r.Lumen.ScreenProbeGather.IntegrateDownsampleFactor=2 +CVars=r.DynamicGlobalIlluminationMethod=2 +CVars=sg.ResolutionQuality=80 +CVars=sg.PostProcessQuality=2 +CVars=sg.ShadowQuality=2 +CVars=sg.GlobalIlluminationQuality=1 +CVars=sg.ReflectionQuality=1 +CVars=sg.ViewDistanceQuality=2 +CVars=sg.EffectsQuality=2 +CVars=sg.FoliageQuality=1 +CVars=t.MaxFPS=30 +CVars=r.VSync=1 +CVars=r.SetRes=1280x800f +CVars=r.DynamicRes.OperationMode=1 +CVars=r.DynamicRes.MinScreenPercentage=60 +CVars=r.DynamicRes.MaxScreenPercentage=85 +CVars=r.DynamicRes.FrameTimeBudget=33.3
The DeviceType=Windows is intentional — under Proton the Deck runs Windows binaries, and most Deck-shipped UE5 titles ship the Windows depot. Native Linux builds historically run slower than Windows-on-Proton (Triple-Aye reported 12–16 fps native vs 30 fps Proton on the same UE5 build).
TDP / FPS contract
Pick one before you tune anything else. Three reasonable choices:
- 30 fps locked at 15 W (cinematic UE5). The default for Lumen-on / Nanite-on UE5 ports. Hellblade II Enhanced, Robocop: Rogue City both target this.
- 40 fps for OLED 90 Hz. Half-rate of 90 Hz; viable on lighter UE5 content with FSR2 Quality.
- 60 fps with Lumen disabled. Possible on lighter Lyra-class projects; not viable on most Lumen+Nanite-shipped titles.
Pick at the device-profile level via t.MaxFPS. Pair with r.VSync=1 and Dynamic Resolution between 60% and 85% screen percentage. The 30 fps floor matches the "30 fps is sticky" community consensus on Deck-shipped UE5 titles.
Lumen on Deck — keep, downgrade, or kill
Hardware ray tracing must be off — Van Gogh has no RT cores. The decision tree:
- Keep Lumen GI (SW): viable for Quality-mode 30 fps with aggressive tuning. Set
r.Lumen.HardwareRayTracing=0,r.Lumen.ScreenProbeGather.IntegrateDownsampleFactor=2,r.Lumen.ScreenProbeGather.MaxRayIntensity=10, drop spatial filter passes to 1. - Downgrade Lumen reflections:
r.Lumen.Reflections.DownsampleFactor=2,r.Lumen.Reflections.MaxRoughnessToTrace=0.3. - Kill Lumen entirely:
r.DynamicGlobalIlluminationMethod=0+r.ReflectionMethod=2(SSR) for 60 fps mode. Bake static lighting;r.GenerateMeshDistanceFields=0.
For the deep mechanics see the Lumen Performance Deep Dive; the Lumen defaults gotcha covers the disable-it-properly recipe.
Nanite tradeoffs
Keep Nanite on for high-poly hero meshes; the cluster culling pays off even on 8 CUs. Disable Nanite on:
- Foliage — software VRS path on Van Gogh is expensive; baked LODs win on Deck.
- Translucent / masked content — programmable raster cost is amplified on weaker silicon.
- Distance-rendered set-dressing — HLOD or low-poly proxies beat Nanite at low screen-pixel sizes.
Hellblade II Enhanced demonstrates the workable case: 30 fps, FSR2 Balanced, full Nanite + SW Lumen, mostly-baked indirect lighting on Deck. They got Steam Deck Verified status post-launch, with frame-time spikes acknowledged.
FSR2/FSR3 on RDNA 2
FSR is the right upscaler for Deck — AMD's own algorithm, tuned for RDNA 2, no NVIDIA hardware required. Setup:
- Install AMD's FSR3 UE Plugin from GPUOpen.
- Set
r.AntiAliasingMethod=4(TSR) ANDr.TemporalAA.Upsampling=1— the FSR plugin requires Temporal Upsampling enabled. (TSR's own internals get bypassed when FSR3 takes over.) r.FidelityFX.FSR3.Enabled=1,r.FidelityFX.FSR3.QualityMode=2(Balanced; 1.7× scale = 753x470 input at 1280x800 output).- Avoid Frame Generation on Deck — the 30 fps floor means frame-gen would target 60 fps from a 30 fps base; latency cost is too high for the visual gain.
FSR2 still works and may be more performant than FSR3 for a 30 fps locked target. FSR3 plugin requires UE 5.1.1+; 5.1.0 has an ABI incompatibility.
Proton / SteamOS gotchas
- Shader compilation hitches on first run — the DXVK/VKD3D state cache is empty. PSO precaching (UE 5.2+) is essential; see the PSO Precaching tutorial. Hellblade II at launch suffered badly here.
- EAC SDK on Linux — if you use Easy Anti-Cheat, the Linux .so swap is required for SteamOS. Test specifically; cert-equivalent failure mode.
- DefaultGraphicsRHI — some UE5 titles ship DX11 RHI on Deck for stability under Proton. Modern UE 5.5+ Vulkan-on-DXVK is generally fine; test both.
- Wayland clipboard / overlay quirks — Steam overlay can interact poorly with custom UE5 input handlers on Wayland. Test the overlay-on-overlay-off pattern.
- Immutable filesystem — SteamOS is read-only by default. Don't write outside the prefix or save folder.
Profiling on Deck itself
Tools that work on Deck:
- MangoHud — the Deck-equivalent of Afterburner; CPU/GPU/RAM overlay. Free, ships with SteamOS.
- Unreal Insights over network — launch dev kit and target Deck IP via
-tracehost. stat unit/stat gpu/DumpGPUin a Development build.- RGP captures on a Deck-class RDNA 2 GPU on a desktop machine, transferred over — the patterns translate (occupancy, async overlap).
Shipping checklist
Before submitting for Steam Deck Verified review:
- Default settings are Deck-tuned out of the box — the Verified bar is "playable at recommended settings" without the player tinkering.
- Controller glyphs and Steam Input — Verified requires the right glyphs surface, including for any non-controller HUD prompts.
- 800p default with Dynamic Resolution band 60–85%.
- 30 fps locked with
t.MaxFPS=30in the Deck device profile. - FSR2 Balanced as the default upscaler.
- HWRT explicitly off —
r.Lumen.HardwareRayTracing=0. - PSO precaching enabled with bundled cache from QA playthrough — first-run hitches are an instant Verified rejection signal.
- Sleep/resume tested — close the Deck lid, open it, verify the game resumes correctly.
- Battery-life test — 90 minutes of gameplay at 15 W; if you're throttled below 30 fps mid-test, your TDP target is too aggressive.
- OLED + LCD both tested — the LPDDR5 bandwidth difference is small but real on memory-bound scenes.
The Steam Deck is a uniquely good fit for PerfGuard's baseline workflow because the hardware is identical across millions of units — unlike PC, where regressions get masked by GPU variance. A single PerfGuard run on a dev Deck applies to every player.
- Upscaler Tuning — FSR setup and quality regression checklist.
- Lumen Performance — the SW Lumen tuning the Deck profile uses.
- PSO Precaching — mandatory for surviving the first-run experience on Proton.