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
This commit is contained in:
parent
1e5b37c94f
commit
3bad321d2b
4 changed files with 159 additions and 54 deletions
|
@ -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();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue