TAA Phase 5: expose native TAA in the UI (Anti-Aliasing dropdown)

Adds AntiAliasing.Taa and a 'TAA' entry to Settings > Graphics > Anti-Aliasing,
so the native temporal AA is a normal user-selectable option alongside FXAA/SMAA
(it is a post-process effect, not a scaling filter). Selecting it instantiates
TemporalFilter as the active IPostProcessingEffect; applies live, no restart.
RYUJINX_TAA=1 still force-enables it as a dev override. On the OpenGL backend TAA
falls back to no AA (Vulkan-only feature). Validated in game via the UI.

Bakes the in-game-validated defaults so UI users get the tuned look with no env
vars: history blend 0.80, variance clamp 1.25 (RYUJINX_TAA_* still override).
This commit is contained in:
2026-06-28 21:41:25 -04:00
parent df3240c17f
commit caea82cbb4
5 changed files with 21 additions and 17 deletions
@@ -11,5 +11,6 @@ namespace Ryujinx.Common.Configuration
SmaaMedium, SmaaMedium,
SmaaHigh, SmaaHigh,
SmaaUltra, SmaaUltra,
Taa,
} }
} }
+1
View File
@@ -324,6 +324,7 @@ namespace Ryujinx.Graphics.OpenGL
_antiAliasing = new FxaaPostProcessingEffect(_renderer); _antiAliasing = new FxaaPostProcessingEffect(_renderer);
break; break;
case AntiAliasing.None: case AntiAliasing.None:
case AntiAliasing.Taa: // TAA is a Vulkan-only effect; on the GL backend it falls back to no AA.
_antiAliasing?.Dispose(); _antiAliasing?.Dispose();
_antiAliasing = null; _antiAliasing = null;
break; break;
@@ -20,10 +20,10 @@ namespace Ryujinx.Graphics.Vulkan.Effects
/// the dominant cost), then the field is bilinear-upscaled and scaled by N when the blend reprojects the /// the dominant cost), then the field is bilinear-upscaled and scaled by N when the blend reprojects the
/// history. Motion estimation is self-contained (reuses the DLSS shaders) so TAA works with DLSS off. /// history. Motion estimation is self-contained (reuses the DLSS shaders) so TAA works with DLSS off.
/// ///
/// Gated entirely on RYUJINX_TAA=1: when unset the present path never constructs or runs this, so the /// Selected from the UI as an Anti-Aliasing option (AntiAliasing.Taa); RYUJINX_TAA=1 also force-enables it
/// default render is byte-identical. Tunables (no rebuild): RYUJINX_TAA_BLEND (history weight, default /// (dev override). Tunables (no rebuild): RYUJINX_TAA_BLEND (history weight, default 0.80), RYUJINX_TAA_MV_SIGN
/// 0.90), RYUJINX_TAA_MV_SIGN (reprojection direction, default +1), RYUJINX_TAA_CLAMP (variance-box /// (reprojection direction, default +1), RYUJINX_TAA_CLAMP (variance-box half-width in std-devs, default 1.25),
/// half-width in std-devs, default 1.0), RYUJINX_TAA_MV_DOWNSCALE (flow resolution divisor 1/2/4, default 2). /// RYUJINX_TAA_MV_DOWNSCALE (flow resolution divisor 1/2/4, default 2).
/// </summary> /// </summary>
internal class TemporalFilter : IPostProcessingEffect internal class TemporalFilter : IPostProcessingEffect
{ {
@@ -91,7 +91,7 @@ namespace Ryujinx.Graphics.Vulkan.Effects
return blend; return blend;
} }
return 0.90f; return 0.80f; // validated in-game default (sharp + steady); RYUJINX_TAA_BLEND overrides.
} }
private static float ParseSign() private static float ParseSign()
@@ -113,7 +113,7 @@ namespace Ryujinx.Graphics.Vulkan.Effects
return gamma; return gamma;
} }
return 1.0f; return 1.25f; // validated in-game default (lets native texture detail through); RYUJINX_TAA_CLAMP overrides.
} }
private static int ParseDownscale() private static int ParseDownscale()
+11 -11
View File
@@ -37,7 +37,6 @@ namespace Ryujinx.Graphics.Vulkan
private bool _updateEffect; private bool _updateEffect;
private IPostProcessingEffect _effect; private IPostProcessingEffect _effect;
private IScalingFilter _scalingFilter; private IScalingFilter _scalingFilter;
private Effects.TemporalFilter _taa;
private Dlss.DlssUpscaler _dlss; private Dlss.DlssUpscaler _dlss;
private bool _isLinear; private bool _isLinear;
private float _scalingFilterLevel; private float _scalingFilterLevel;
@@ -395,14 +394,6 @@ namespace Ryujinx.Graphics.Vulkan
view = _effect.Run(view, cbs, _width, _height); view = _effect.Run(view, cbs, _width, _height);
} }
// Native temporal anti-aliasing (clean-room), gated on RYUJINX_TAA=1. Runs at render resolution
// before the spatial upscale/blit, like a post-processing effect. Phase 0 is a pass-through.
if (Effects.TemporalFilter.IsEnabled)
{
_taa ??= new Effects.TemporalFilter(_gd, _device);
view = _taa.Run(view, cbs, _width, _height);
}
int srcX0, srcX1, srcY0, srcY1; int srcX0, srcX1, srcY0, srcY1;
if (crop.Left == 0 && crop.Right == 0) if (crop.Left == 0 && crop.Right == 0)
@@ -615,12 +606,22 @@ namespace Ryujinx.Graphics.Vulkan
{ {
_updateEffect = false; _updateEffect = false;
switch (_currentAntiAliasing) // RYUJINX_TAA=1 forces the native temporal filter regardless of the UI selection (dev override).
AntiAliasing antiAliasing = Effects.TemporalFilter.IsEnabled ? AntiAliasing.Taa : _currentAntiAliasing;
switch (antiAliasing)
{ {
case AntiAliasing.Fxaa: case AntiAliasing.Fxaa:
_effect?.Dispose(); _effect?.Dispose();
_effect = new FxaaPostProcessingEffect(_gd, _device); _effect = new FxaaPostProcessingEffect(_gd, _device);
break; break;
case AntiAliasing.Taa:
if (_effect is not Effects.TemporalFilter)
{
_effect?.Dispose();
_effect = new Effects.TemporalFilter(_gd, _device);
}
break;
case AntiAliasing.None: case AntiAliasing.None:
_effect?.Dispose(); _effect?.Dispose();
_effect = null; _effect = null;
@@ -791,7 +792,6 @@ namespace Ryujinx.Graphics.Vulkan
_effect?.Dispose(); _effect?.Dispose();
_scalingFilter?.Dispose(); _scalingFilter?.Dispose();
_taa?.Dispose();
_dlss?.Dispose(); _dlss?.Dispose();
} }
} }
@@ -290,6 +290,8 @@
Content="{ext:Locale SmaaHigh}" /> Content="{ext:Locale SmaaHigh}" />
<ComboBoxItem <ComboBoxItem
Content="{ext:Locale SmaaUltra}" /> Content="{ext:Locale SmaaUltra}" />
<ComboBoxItem
Content="TAA" />
</ComboBox> </ComboBox>
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>