aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Gpu/Image/TexturePool.cs
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2021-01-15 15:14:00 -0300
committerGitHub <noreply@github.com>2021-01-15 19:14:00 +0100
commit3bad321d2b0994cd19129bc18ed98bb3ab81c3b0 (patch)
tree0c1c3610b7b0b42a2be3f797baf46ce42986a98b /Ryujinx.Graphics.Gpu/Image/TexturePool.cs
parent1e5b37c94f870dc3faa94fb2d095cfa39fecb2a3 (diff)
Fix mipmap base level being ignored for sampled textures and images (#1911)
* Fix mipmap base level being ignored for sampled textures and images * Fix layer size and max level for textures * Missing XML doc + reorder comments
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Image/TexturePool.cs')
-rw-r--r--Ryujinx.Graphics.Gpu/Image/TexturePool.cs61
1 files changed, 56 insertions, 5 deletions
diff --git a/Ryujinx.Graphics.Gpu/Image/TexturePool.cs b/Ryujinx.Graphics.Gpu/Image/TexturePool.cs
index 9c7e849b..333ebaed 100644
--- a/Ryujinx.Graphics.Gpu/Image/TexturePool.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TexturePool.cs
@@ -1,6 +1,8 @@
using Ryujinx.Common.Logging;
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Gpu.Memory;
+using Ryujinx.Graphics.Texture;
+using System;
using System.Collections.Generic;
namespace Ryujinx.Graphics.Gpu.Image
@@ -50,7 +52,7 @@ namespace Ryujinx.Graphics.Gpu.Image
{
TextureDescriptor descriptor = GetDescriptor(id);
- TextureInfo info = GetInfo(descriptor);
+ TextureInfo info = GetInfo(descriptor, out int layerSize);
// Bad address. We can't add a texture with a invalid address
// to the cache.
@@ -59,7 +61,7 @@ namespace Ryujinx.Graphics.Gpu.Image
return null;
}
- texture = Context.Methods.TextureManager.FindOrCreateTexture(info, TextureSearchFlags.ForSampler);
+ texture = Context.Methods.TextureManager.FindOrCreateTexture(info, TextureSearchFlags.ForSampler, layerSize);
texture.IncrementReferenceCount();
@@ -121,7 +123,7 @@ namespace Ryujinx.Graphics.Gpu.Image
// If the descriptors are the same, the texture is the same,
// we don't need to remove as it was not modified. Just continue.
- if (texture.IsExactMatch(GetInfo(descriptor), TextureSearchFlags.Strict) != TextureMatchQuality.NoMatch)
+ if (texture.IsExactMatch(GetInfo(descriptor, out _), TextureSearchFlags.Strict) != TextureMatchQuality.NoMatch)
{
continue;
}
@@ -137,10 +139,12 @@ namespace Ryujinx.Graphics.Gpu.Image
/// Gets texture information from a texture descriptor.
/// </summary>
/// <param name="descriptor">The texture descriptor</param>
+ /// <param name="layerSize">Layer size for textures using a sub-range of mipmap levels, otherwise 0</param>
/// <returns>The texture information</returns>
- private TextureInfo GetInfo(TextureDescriptor descriptor)
+ private TextureInfo GetInfo(TextureDescriptor descriptor, out int layerSize)
{
ulong address = Context.MemoryManager.Translate(descriptor.UnpackAddress());
+ bool addressIsValid = address != MemoryManager.PteUnmapped;
int width = descriptor.UnpackWidth();
int height = descriptor.UnpackHeight();
@@ -181,7 +185,7 @@ namespace Ryujinx.Graphics.Gpu.Image
if (!FormatTable.TryGetTextureFormat(format, srgb, out FormatInfo formatInfo))
{
- if ((long)address > 0L && (int)format > 0)
+ if (addressIsValid && (int)format > 0)
{
Logger.Error?.Print(LogClass.Gpu, $"Invalid texture format 0x{format:X} (sRGB: {srgb}).");
}
@@ -194,6 +198,53 @@ namespace Ryujinx.Graphics.Gpu.Image
int gobBlocksInTileX = descriptor.UnpackGobBlocksInTileX();
+ layerSize = 0;
+
+ int minLod = descriptor.UnpackBaseLevel();
+ int maxLod = descriptor.UnpackMaxLevelInclusive();
+
+ // Linear textures don't support mipmaps, so we don't handle this case here.
+ if ((minLod != 0 || maxLod + 1 != levels) && target != Target.TextureBuffer && !isLinear && addressIsValid)
+ {
+ int depth = TextureInfo.GetDepth(target, depthOrLayers);
+ int layers = TextureInfo.GetLayers(target, depthOrLayers);
+
+ SizeInfo sizeInfo = SizeCalculator.GetBlockLinearTextureSize(
+ width,
+ height,
+ depth,
+ levels,
+ layers,
+ formatInfo.BlockWidth,
+ formatInfo.BlockHeight,
+ formatInfo.BytesPerPixel,
+ gobBlocksInY,
+ gobBlocksInZ,
+ gobBlocksInTileX);
+
+ layerSize = sizeInfo.LayerSize;
+
+ if (minLod != 0)
+ {
+ // If the base level is not zero, we additionally add the mip level offset
+ // to the address, this allows the texture manager to find the base level from the
+ // address if there is a overlapping texture on the cache that can contain the new texture.
+ address += (ulong)sizeInfo.GetMipOffset(minLod);
+
+ width = Math.Max(1, width >> minLod);
+ height = Math.Max(1, height >> minLod);
+
+ if (target == Target.Texture3D)
+ {
+ depthOrLayers = Math.Max(1, depthOrLayers >> minLod);
+ }
+
+ (gobBlocksInY, gobBlocksInZ) = SizeCalculator.GetMipGobBlockSizes(height, depth, formatInfo.BlockHeight, gobBlocksInY, gobBlocksInZ);
+ }
+
+ levels = (maxLod - minLod) + 1;
+ }
+
SwizzleComponent swizzleR = descriptor.UnpackSwizzleR().Convert();
SwizzleComponent swizzleG = descriptor.UnpackSwizzleG().Convert();
SwizzleComponent swizzleB = descriptor.UnpackSwizzleB().Convert();