diff options
author | gdkchan <gab.dark.100@gmail.com> | 2021-01-15 15:14:00 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-15 19:14:00 +0100 |
commit | 3bad321d2b0994cd19129bc18ed98bb3ab81c3b0 (patch) | |
tree | 0c1c3610b7b0b42a2be3f797baf46ce42986a98b /Ryujinx.Graphics.Gpu/Image/TexturePool.cs | |
parent | 1e5b37c94f870dc3faa94fb2d095cfa39fecb2a3 (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.cs | 61 |
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(); |