diff --git a/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs b/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs
index fb4ab007..da412bdf 100644
--- a/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs
@@ -380,11 +380,16 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
if (changedScale)
{
+ float oldScale = _channel.TextureManager.RenderTargetScale;
_channel.TextureManager.UpdateRenderTargetScale(singleUse);
- _context.Renderer.Pipeline.SetRenderTargetScale(_channel.TextureManager.RenderTargetScale);
- UpdateViewportTransform();
- UpdateScissorState();
+ if (oldScale != _channel.TextureManager.RenderTargetScale)
+ {
+ _context.Renderer.Pipeline.SetRenderTargetScale(_channel.TextureManager.RenderTargetScale);
+
+ UpdateViewportTransform();
+ UpdateScissorState();
+ }
}
}
diff --git a/Ryujinx.Graphics.Gpu/Image/Texture.cs b/Ryujinx.Graphics.Gpu/Image/Texture.cs
index a3105cf2..e156ff5e 100644
--- a/Ryujinx.Graphics.Gpu/Image/Texture.cs
+++ b/Ryujinx.Graphics.Gpu/Image/Texture.cs
@@ -549,7 +549,8 @@ namespace Ryujinx.Graphics.Gpu.Image
/// The new scale factor for this texture
public void SetScale(float scale)
{
- TextureScaleMode newScaleMode = ScaleMode == TextureScaleMode.Blacklisted ? ScaleMode : TextureScaleMode.Scaled;
+ bool unscaled = ScaleMode == TextureScaleMode.Blacklisted || (ScaleMode == TextureScaleMode.Undesired && scale == 1);
+ TextureScaleMode newScaleMode = unscaled ? ScaleMode : TextureScaleMode.Scaled;
if (_viewStorage != this)
{
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureCache.cs b/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
index d9920f97..58cd3a2f 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
@@ -87,10 +87,16 @@ namespace Ryujinx.Graphics.Gpu.Image
/// Determines if a given texture is eligible for upscaling from its info.
///
/// The texture info to check
+ /// True if the user of the texture would prefer it to be upscaled immediately
/// True if eligible
- private static bool IsUpscaleCompatible(TextureInfo info)
+ private static TextureScaleMode IsUpscaleCompatible(TextureInfo info, bool withUpscale)
{
- return (info.Target == Target.Texture2D || info.Target == Target.Texture2DArray) && !info.FormatInfo.IsCompressed && UpscaleSafeMode(info);
+ if ((info.Target == Target.Texture2D || info.Target == Target.Texture2DArray) && !info.FormatInfo.IsCompressed)
+ {
+ return UpscaleSafeMode(info) ? (withUpscale ? TextureScaleMode.Scaled : TextureScaleMode.Eligible) : TextureScaleMode.Undesired;
+ }
+
+ return TextureScaleMode.Blacklisted;
}
///
@@ -117,13 +123,13 @@ namespace Ryujinx.Graphics.Gpu.Image
return false;
}
+ int widthAlignment = (info.IsLinear ? Constants.StrideAlignment : Constants.GobAlignment) / info.FormatInfo.BytesPerPixel;
+
if (!(info.FormatInfo.Format.IsDepthOrStencil() || info.FormatInfo.Components == 1))
{
// Discount square textures that aren't depth-stencil like. (excludes game textures, cubemap faces, most 3D texture LUT, texture atlas)
// Detect if the texture is possibly square. Widths may be aligned, so to remove the uncertainty we align both the width and height.
- int widthAlignment = (info.IsLinear ? Constants.StrideAlignment : Constants.GobAlignment) / info.FormatInfo.BytesPerPixel;
-
bool possiblySquare = BitUtils.AlignUp(info.Width, widthAlignment) == BitUtils.AlignUp(info.Height, widthAlignment);
if (possiblySquare)
@@ -132,11 +138,17 @@ namespace Ryujinx.Graphics.Gpu.Image
}
}
- int aspect = (int)Math.Round((info.Width / (float)info.Height) * 9);
- if (aspect == 16 && info.Height < 360)
+ if (info.Height < 360)
{
- // Targets that are roughly 16:9 can only be rescaled if they're equal to or above 360p. (excludes blur and bloom textures)
- return false;
+ int aspectWidth = (int)MathF.Ceiling((info.Height / 9f) * 16f);
+ int aspectMaxWidth = BitUtils.AlignUp(aspectWidth, widthAlignment);
+ int aspectMinWidth = BitUtils.AlignDown(aspectWidth, widthAlignment);
+
+ if (info.Width >= aspectMinWidth && info.Width <= aspectMaxWidth && info.Height < 360)
+ {
+ // Targets that are roughly 16:9 can only be rescaled if they're equal to or above 360p. (excludes blur and bloom textures)
+ return false;
+ }
}
return true;
@@ -354,13 +366,7 @@ namespace Ryujinx.Graphics.Gpu.Image
{
bool isSamplerTexture = (flags & TextureSearchFlags.ForSampler) != 0;
- bool isScalable = IsUpscaleCompatible(info);
-
- TextureScaleMode scaleMode = TextureScaleMode.Blacklisted;
- if (isScalable)
- {
- scaleMode = (flags & TextureSearchFlags.WithUpscale) != 0 ? TextureScaleMode.Scaled : TextureScaleMode.Eligible;
- }
+ TextureScaleMode scaleMode = IsUpscaleCompatible(info, (flags & TextureSearchFlags.WithUpscale) != 0);
ulong address;
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs
index 157b7c17..4db6532b 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs
@@ -140,6 +140,16 @@ namespace Ryujinx.Graphics.Gpu.Image
_gpBindingsManager.SetTexturePool(gpuVa, maximumId);
}
+ ///
+ /// Check if a texture's scale must be updated to match the configured resolution scale.
+ ///
+ /// The texture to check
+ /// True if the scale needs updating, false if the scale is up to date
+ private bool ScaleNeedsUpdated(Texture texture)
+ {
+ return texture != null && !(texture.ScaleMode == TextureScaleMode.Blacklisted || texture.ScaleMode == TextureScaleMode.Undesired) && texture.ScaleFactor != GraphicsConfig.ResScale;
+ }
+
///
/// Sets the render target color buffer.
///
@@ -164,7 +174,7 @@ namespace Ryujinx.Graphics.Gpu.Image
_rtColors[index] = color;
}
- return changesScale || (hasValue && color.ScaleMode != TextureScaleMode.Blacklisted && color.ScaleFactor != GraphicsConfig.ResScale);
+ return changesScale || ScaleNeedsUpdated(color);
}
///
@@ -190,7 +200,7 @@ namespace Ryujinx.Graphics.Gpu.Image
_rtDepthStencil = depthStencil;
}
- return changesScale || (hasValue && depthStencil.ScaleMode != TextureScaleMode.Blacklisted && depthStencil.ScaleFactor != GraphicsConfig.ResScale);
+ return changesScale || ScaleNeedsUpdated(depthStencil);
}
///
@@ -214,6 +224,7 @@ namespace Ryujinx.Graphics.Gpu.Image
bool mismatch = false;
bool blacklisted = false;
bool hasUpscaled = false;
+ bool hasUndesired = false;
float targetScale = GraphicsConfig.ResScale;
void ConsiderTarget(Texture target)
@@ -230,9 +241,13 @@ namespace Ryujinx.Graphics.Gpu.Image
case TextureScaleMode.Eligible:
mismatch = true; // We must make a decision.
break;
+ case TextureScaleMode.Undesired:
+ hasUndesired = true;
+ mismatch |= scale != 1f || hasUpscaled; // If another target is upscaled, scale this one up too.
+ break;
case TextureScaleMode.Scaled:
hasUpscaled = true;
- mismatch |= scale != targetScale; // If the target scale has changed, reset the scale for all targets.
+ mismatch |= hasUndesired || scale != targetScale; // If the target scale has changed, reset the scale for all targets.
break;
}
}
@@ -254,7 +269,7 @@ namespace Ryujinx.Graphics.Gpu.Image
mismatch |= blacklisted && hasUpscaled;
- if (blacklisted)
+ if (blacklisted || (hasUndesired && !hasUpscaled))
{
targetScale = 1f;
}
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureScaleMode.cs b/Ryujinx.Graphics.Gpu/Image/TextureScaleMode.cs
index 2c9e431d..b937f577 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureScaleMode.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureScaleMode.cs
@@ -4,11 +4,13 @@
/// The scale mode for a given texture.
/// Blacklisted textures cannot be scaled, Eligible textures have not been scaled yet,
/// and Scaled textures have been scaled already.
+ /// Undesired textures will stay at 1x until a situation where they must match a scaled texture.
///
enum TextureScaleMode
{
Eligible = 0,
Scaled = 1,
- Blacklisted = 2
+ Blacklisted = 2,
+ Undesired = 3
}
}