GregOrigin - TargetFrame: Automatic runtime scalability for mainstream PC's

Watch it in action

Read the manual

A functional open source version is available at https://github.com/gregorik/TargetFrame-Core, please file Issues there if appropriate. Fab hosts the fully featured Pro version. The manual reflects the Pro feature set.

TargetFrame is an automatic, zero-configuration runtime scalability management system for Unreal Engine 5.6+. Stop guessing what settings your players need: TargetFrame automatically benchmarks hardware, sets a stable baseline, and dynamically steps down resolution scale and overall quality during gameplay to defend your target frame rate.

Designed to eliminate "stuttering" reviews on launch day, this plugin handles the dirty work of performance scaling so you can focus on building your game.

Key Features

🛡️ Runtime Governor

Never drop below your target frame rate during a boss fight again. The Runtime Governor constantly monitors the smoothed FPS. If the frame rate drops below your configured threshold for a sustained period, the Governor steps in to automatically lower the ResolutionScale and OverallQuality step-by-step until the target FPS is restored. When the action cools down, it smoothly scales back up to maximize visual fidelity.

⚡ Auto-Benchmarking & Tiering

On boot, TargetFrame Core runs a fast, non-intrusive hardware scan. It assigns the machine to a hardware tier (Entry, Mainstream, Performance) based on CPU cores, RAM, and GPU capabilities. It automatically applies the recommended settings for that tier without the player ever having to open an Options menu.

📦 Fire-and-Forget Shipping Capsule

Hate writing custom save-game logic for graphics settings? The Fire-and-Forget Shipping feature completely abstracts scalability. The plugin automatically locks in the optimal settings after an initial "stabilization period," giving players a consistently smooth experience out-of-the-box.

🔲 Upscaler-Safe UI

Upscaling a 1080p render to 4K is great for performance, but it can make your UI text look like a blurry mess. TargetFrame Core automatically separates your UI rendering from your 3D scene rendering. The 3D scene scales dynamically, while your Slate/UMG UI remains locked at crisp, native resolution.

  • Dynamic Nanite Budgeting: Instead of brutally dropping the global scalability level, the Pro version surgically relaxes Nanite's MaxPixelsPerEdge and time budgets during heavy scenes, keeping your shadows and post-processing intact while slightly reducing distant geometric density.

  • Hardware Ray Tracing Guards: Lumen Hardware Ray Tracing is gorgeous but demands massive VRAM. The Pro version automatically intercepts the boot sequence, checks the physical VRAM and GPU capabilities, and gracefully falls back to Software Ray Tracing if the player's hardware would crash or stutter.

  • VRAM Exhaustion Protection: Automatically clamps Texture Pool sizes and disables memory-hungry features like Nanite Tessellation on hardware with 8GB of VRAM or less to prevent catastrophic Out of Video Memory crashes.

  • Vendor-Specific Profiles: Detects Intel ARC, AMD, and NVIDIA GPUs, applying specific capability maximums and dynamic resolution preferences to avoid known driver performance cliffs.

  • CSV Telemetry Export: Automatically writes detailed frame-time data, intervention logs, and hardware specs to CSV files during playtests, making it incredibly easy for your QA team to identify performance bottlenecks.

Update 0.2.0 — 2026-03-21


Fixes

  • FSR version orderingDeterminePreferredUpscaler now evaluates FSR3 > FSR2 > FSR in both vendor-specific and generic fallback paths. Previously FSR (1.0) could be selected over FSR3 when all three were available. (TargetFrameSubsystem.cpp)

  • DLSS excluded from runtime quality adjustmentTryAdjustUpscalerQuality guarded against all modes except FSR variants, silently skipping DLSS and XeSS. Changed to a blacklist of Native/TSR so every vendor upscaler participates in the runtime ladder. (TargetFrameSubsystem.cpp)

  • Widget "Skip Onboarding" opened control panelHandleSkipOnboarding called SetControlPanelVisible(true) and RefreshPresentation() after dismissing the wizard, unexpectedly showing the control panel. Removed both calls so "Skip" truly dismisses. (TargetFrameUserExperienceWidget.cpp)

  • GPU vendor detection false positivesDetectGPUVendor matched the substring "arc" (hitting "search", "march", etc.) and "uhd" (hitting "Thunderbolt"). Tightened to "intel arc" and "uhd graphics". (TargetFrameSubsystem.cpp)

  • Asymmetric quality step ladderStepQualityUp applied knobs in the same order as StepQualityDown. Reversed to overall quality > Nanite > resolution > triangle cull > upscaler, so the cheapest-to-restore knob is raised first. (TargetFrameSubsystem.cpp)

  • Redundant hardware snapshot refreshesApplyCurrentPolicy and EvaluateRuntimeBudget each called RefreshHardwareSnapshot() despite Initialize already doing so. Removed the duplicate calls. (TargetFrameSubsystem.cpp)

  • OverallQualityLevel exposed raw -1 to BlueprintGetOverallScalabilityLevel() returns -1 for "Custom". LoadStateFromGameUserSettings now maps -1 to FallbackOverallQualityLevelWhenCustom before writing Status.OverallQualityLevel, so Blueprint consumers never see a sentinel value. (TargetFrameSubsystem.cpp)

  • CanReduceCostFurther / CanIncreaseQualityFurther ignored activatable upscalers — Both functions checked IsVendorUpscalerActive(), missing upscalers that were available but not yet activated. Changed to DeterminePreferredUpscaler() != Native/TSR so an available vendor upscaler is correctly treated as a quality knob. (TargetFrameSubsystem.cpp)

Performance

  • Debounced SaveCurrentSettings disk writes — Runtime governor adjustments (TryAdjustResolutionScale, TryAdjustOverallQuality) now call MarkSettingsDirty() which updates local state immediately but defers ApplySettings + SaveSettings to disk. FlushDirtySettings() fires every 5 seconds when dirty, and is guaranteed to flush in Deinitialize(). One-shot operations (ApplyCurrentPolicy) still save immediately. (TargetFrameSubsystem.h, TargetFrameSubsystem.cpp)

  • Reduced hardware benchmark work scaleRunHardwareBenchmark work scale lowered from 10 to 5, cutting the synchronous hitch roughly in half. Added a UE_LOG Warning advising callers to run the benchmark during a loading screen. (TargetFrameSubsystem.cpp)

  • Hitch rejection for EMA — Tick frames longer than HitchThresholdSeconds (default 0.1 s) are excluded from the SmoothedFPS exponential moving average, preventing load spikes or hitches from triggering false quality step-downs. (TargetFrameSubsystem.cpp)

  • Telemetry snapshot throttleRecordTelemetrySnapshot was called every tick. Now gated behind TelemetrySnapshotIntervalSeconds (default 1.0 s) to reduce CSV profiler overhead. (TargetFrameSubsystem.cpp)

  • Capability probe cachedProbeProjectCapabilities now sets bCapabilitiesProbed on first run and early-exits on subsequent calls, avoiding repeated CVar lookups. (TargetFrameSubsystem.cpp)

New Features

  • XeSS upscaler support — Added ETargetFrameUpscalerMode::XeSS and full integration: capability probing (r.XeSS.Enabled / r.XeSS.Quality), preferred-on-Intel selection in DeterminePreferredUpscaler, ApplyXeSSState / GetXeSSQualityModeValue implementations, runtime status refresh, and vendor-active checks. Controlled by bPreferXeSSOnIntel in DeveloperSettings. (TargetFrameTypes.h, TargetFrameDeveloperSettings.h, TargetFrameSubsystem.h, TargetFrameSubsystem.cpp, DefaultTargetFrame.ini)

  • Runtime governor pause/resumeSetRuntimeGovernorPaused(bool) BlueprintCallable on the subsystem, plus PauseTargetFrameGovernor / ResumeTargetFrameGovernor static wrappers in the Blueprint library. Consecutive-sample counters reset on resume to prevent stale readings from triggering immediate adjustments. (TargetFrameSubsystem.h, TargetFrameSubsystem.cpp, TargetFrameBlueprintLibrary.h, TargetFrameBlueprintLibrary.cpp)

  • ResetToDefaults — BlueprintCallable that restores managed triangle-cull states, clears all runtime overrides, resets Status, and re-probes capabilities. Wrapped as ResetTargetFrameToDefaults in the Blueprint library. (TargetFrameSubsystem.h, TargetFrameSubsystem.cpp, TargetFrameBlueprintLibrary.h, TargetFrameBlueprintLibrary.cpp)

  • Policy-changed delegateOnPolicyChanged (FTargetFramePolicyChangedDelegate) BlueprintAssignable multicast delegate fires on every RecordPolicyAction call with the action string and reason, enabling Blueprint-side reactions to policy changes. (TargetFrameSubsystem.h, TargetFrameSubsystem.cpp)

  • Frame-rate clamping — When bClampFrameRateToTarget is enabled, SetTargetFPS and ApplyCurrentPolicy set t.MaxFPS to match the target, preventing the engine from rendering frames above the budget target. (TargetFrameDeveloperSettings.h, TargetFrameSubsystem.cpp, DefaultTargetFrame.ini)

Build & Packaging

  • UMG dependency scope — Moved "UMG" from PublicDependencyModuleNames to PrivateDependencyModuleNames since only the widget implementation uses it. (TargetFrame.Build.cs)