diff options
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Image/Texture.cs')
-rw-r--r-- | Ryujinx.Graphics.Gpu/Image/Texture.cs | 82 |
1 files changed, 66 insertions, 16 deletions
diff --git a/Ryujinx.Graphics.Gpu/Image/Texture.cs b/Ryujinx.Graphics.Gpu/Image/Texture.cs index 6c0de536..363f0f73 100644 --- a/Ryujinx.Graphics.Gpu/Image/Texture.cs +++ b/Ryujinx.Graphics.Gpu/Image/Texture.cs @@ -36,6 +36,7 @@ namespace Ryujinx.Graphics.Gpu.Image { public TexturePool Pool; public int ID; + public ulong GpuAddress; } private GpuContext _context; @@ -162,6 +163,11 @@ namespace Ryujinx.Graphics.Gpu.Image /// </summary> public bool IsView => _viewStorage != this; + /// <summary> + /// Whether or not this texture has views. + /// </summary> + public bool HasViews => _views.Count > 0; + private int _referenceCount; private List<TexturePoolOwner> _poolOwners; @@ -384,6 +390,17 @@ namespace Ryujinx.Graphics.Gpu.Image } /// <summary> + /// Replaces the texture's physical memory range. This forces tracking to regenerate. + /// </summary> + /// <param name="range">New physical memory range backing the texture</param> + public void ReplaceRange(MultiRange range) + { + Range = range; + + Group.RangeChanged(); + } + + /// <summary> /// Create a copy dependency to a texture that is view compatible with this one. /// When either texture is modified, the texture data will be copied to the other to keep them in sync. /// This is essentially an emulated view, useful for handling multiple view parents or format incompatibility. @@ -715,6 +732,8 @@ namespace Ryujinx.Graphics.Gpu.Image height = Math.Max(height >> level, 1); depth = Math.Max(depth >> level, 1); + int sliceDepth = single ? 1 : depth; + SpanOrArray<byte> result; if (Info.IsLinear) @@ -735,7 +754,7 @@ namespace Ryujinx.Graphics.Gpu.Image width, height, depth, - single ? 1 : depth, + sliceDepth, levels, layers, Info.FormatInfo.BlockWidth, @@ -759,7 +778,7 @@ namespace Ryujinx.Graphics.Gpu.Image Info.FormatInfo.BlockHeight, width, height, - depth, + sliceDepth, levels, layers, out byte[] decoded)) @@ -771,7 +790,7 @@ namespace Ryujinx.Graphics.Gpu.Image if (GraphicsConfig.EnableTextureRecompression) { - decoded = BCnEncoder.EncodeBC7(decoded, width, height, depth, levels, layers); + decoded = BCnEncoder.EncodeBC7(decoded, width, height, sliceDepth, levels, layers); } result = decoded; @@ -782,15 +801,15 @@ namespace Ryujinx.Graphics.Gpu.Image { case Format.Etc2RgbaSrgb: case Format.Etc2RgbaUnorm: - result = ETC2Decoder.DecodeRgba(result, width, height, depth, levels, layers); + result = ETC2Decoder.DecodeRgba(result, width, height, sliceDepth, levels, layers); break; case Format.Etc2RgbPtaSrgb: case Format.Etc2RgbPtaUnorm: - result = ETC2Decoder.DecodePta(result, width, height, depth, levels, layers); + result = ETC2Decoder.DecodePta(result, width, height, sliceDepth, levels, layers); break; case Format.Etc2RgbSrgb: case Format.Etc2RgbUnorm: - result = ETC2Decoder.DecodeRgb(result, width, height, depth, levels, layers); + result = ETC2Decoder.DecodeRgb(result, width, height, sliceDepth, levels, layers); break; } } @@ -800,31 +819,31 @@ namespace Ryujinx.Graphics.Gpu.Image { case Format.Bc1RgbaSrgb: case Format.Bc1RgbaUnorm: - result = BCnDecoder.DecodeBC1(result, width, height, depth, levels, layers); + result = BCnDecoder.DecodeBC1(result, width, height, sliceDepth, levels, layers); break; case Format.Bc2Srgb: case Format.Bc2Unorm: - result = BCnDecoder.DecodeBC2(result, width, height, depth, levels, layers); + result = BCnDecoder.DecodeBC2(result, width, height, sliceDepth, levels, layers); break; case Format.Bc3Srgb: case Format.Bc3Unorm: - result = BCnDecoder.DecodeBC3(result, width, height, depth, levels, layers); + result = BCnDecoder.DecodeBC3(result, width, height, sliceDepth, levels, layers); break; case Format.Bc4Snorm: case Format.Bc4Unorm: - result = BCnDecoder.DecodeBC4(result, width, height, depth, levels, layers, Format == Format.Bc4Snorm); + result = BCnDecoder.DecodeBC4(result, width, height, sliceDepth, levels, layers, Format == Format.Bc4Snorm); break; case Format.Bc5Snorm: case Format.Bc5Unorm: - result = BCnDecoder.DecodeBC5(result, width, height, depth, levels, layers, Format == Format.Bc5Snorm); + result = BCnDecoder.DecodeBC5(result, width, height, sliceDepth, levels, layers, Format == Format.Bc5Snorm); break; case Format.Bc6HSfloat: case Format.Bc6HUfloat: - result = BCnDecoder.DecodeBC6(result, width, height, depth, levels, layers, Format == Format.Bc6HSfloat); + result = BCnDecoder.DecodeBC6(result, width, height, sliceDepth, levels, layers, Format == Format.Bc6HSfloat); break; case Format.Bc7Srgb: case Format.Bc7Unorm: - result = BCnDecoder.DecodeBC7(result, width, height, depth, levels, layers); + result = BCnDecoder.DecodeBC7(result, width, height, sliceDepth, levels, layers); break; } } @@ -1484,11 +1503,12 @@ namespace Ryujinx.Graphics.Gpu.Image /// </summary> /// <param name="pool">The texture pool this texture has been added to</param> /// <param name="id">The ID of the reference to this texture in the pool</param> - public void IncrementReferenceCount(TexturePool pool, int id) + /// <param name="gpuVa">GPU VA of the pool reference</param> + public void IncrementReferenceCount(TexturePool pool, int id, ulong gpuVa) { lock (_poolOwners) { - _poolOwners.Add(new TexturePoolOwner { Pool = pool, ID = id }); + _poolOwners.Add(new TexturePoolOwner { Pool = pool, ID = id, GpuAddress = gpuVa }); } _referenceCount++; @@ -1586,6 +1606,36 @@ namespace Ryujinx.Graphics.Gpu.Image } /// <summary> + /// Queue updating texture mappings on the pool. Happens from another thread. + /// </summary> + public void UpdatePoolMappings() + { + lock (_poolOwners) + { + ulong address = 0; + + foreach (var owner in _poolOwners) + { + if (address == 0 || address == owner.GpuAddress) + { + address = owner.GpuAddress; + + owner.Pool.QueueUpdateMapping(this, owner.ID); + } + else + { + // If there is a different GPU VA mapping, prefer the first and delete the others. + owner.Pool.ForceRemove(this, owner.ID, true); + } + } + + _poolOwners.Clear(); + } + + InvalidatedSequence++; + } + + /// <summary> /// Delete the texture if it is not used anymore. /// The texture is considered unused when the reference count is zero, /// and it has no child views. @@ -1636,7 +1686,7 @@ namespace Ryujinx.Graphics.Gpu.Image Group.ClearModified(unmapRange); } - RemoveFromPools(true); + UpdatePoolMappings(); } /// <summary> |