Support for resources on non-contiguous GPU memory regions (#1905)

* Support for resources on non-contiguous GPU memory regions

* Implement MultiRange physical addresses, only used with a single range for now

* Actually use non-contiguous ranges

* GetPhysicalRegions fixes

* Documentation and remove Address property from TextureInfo

* Finish implementing GetWritableRegion

* Fix typo
This commit is contained in:
gdkchan 2021-01-17 15:44:34 -03:00 committed by GitHub
parent 3bad321d2b
commit c4f56c5704
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 1141 additions and 167 deletions

View file

@ -54,15 +54,14 @@ namespace Ryujinx.Graphics.Gpu.Image
TextureInfo info = GetInfo(descriptor, out int layerSize);
// Bad address. We can't add a texture with a invalid address
// to the cache.
if (info.Address == MemoryManager.PteUnmapped)
texture = Context.Methods.TextureManager.FindOrCreateTexture(TextureSearchFlags.ForSampler, info, layerSize);
// If this happens, then the texture address is invalid, we can't add it to the cache.
if (texture == null)
{
return null;
}
texture = Context.Methods.TextureManager.FindOrCreateTexture(info, TextureSearchFlags.ForSampler, layerSize);
texture.IncrementReferenceCount();
Items[id] = texture;
@ -123,7 +122,8 @@ 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, out _), TextureSearchFlags.Strict) != TextureMatchQuality.NoMatch)
if (texture.Info.GpuAddress == descriptor.UnpackAddress() &&
texture.IsExactMatch(GetInfo(descriptor, out _), TextureSearchFlags.Strict) != TextureMatchQuality.NoMatch)
{
continue;
}
@ -143,9 +143,6 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <returns>The texture information</returns>
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();
int depthOrLayers = descriptor.UnpackDepth();
@ -183,9 +180,11 @@ namespace Ryujinx.Graphics.Gpu.Image
uint format = descriptor.UnpackFormat();
bool srgb = descriptor.UnpackSrgb();
ulong gpuVa = descriptor.UnpackAddress();
if (!FormatTable.TryGetTextureFormat(format, srgb, out FormatInfo formatInfo))
{
if (addressIsValid && (int)format > 0)
if (Context.MemoryManager.IsMapped(gpuVa) && (int)format > 0)
{
Logger.Error?.Print(LogClass.Gpu, $"Invalid texture format 0x{format:X} (sRGB: {srgb}).");
}
@ -204,7 +203,7 @@ namespace Ryujinx.Graphics.Gpu.Image
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)
if ((minLod != 0 || maxLod + 1 != levels) && target != Target.TextureBuffer && !isLinear)
{
int depth = TextureInfo.GetDepth(target, depthOrLayers);
int layers = TextureInfo.GetLayers(target, depthOrLayers);
@ -229,7 +228,7 @@ namespace Ryujinx.Graphics.Gpu.Image
// 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);
gpuVa += (ulong)sizeInfo.GetMipOffset(minLod);
width = Math.Max(1, width >> minLod);
height = Math.Max(1, height >> minLod);
@ -274,7 +273,7 @@ namespace Ryujinx.Graphics.Gpu.Image
}
return new TextureInfo(
address,
gpuVa,
width,
height,
depthOrLayers,