diff options
author | gdkchan <gab.dark.100@gmail.com> | 2021-01-17 15:44:34 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-17 19:44:34 +0100 |
commit | c4f56c570494a6186792439e3c0e74458cc82b5c (patch) | |
tree | 40be96f5f3f24b711e088bf2ca681d94aac68c15 /Ryujinx.Graphics.Gpu/Image/Texture.cs | |
parent | 3bad321d2b0994cd19129bc18ed98bb3ab81c3b0 (diff) |
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
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Image/Texture.cs')
-rw-r--r-- | Ryujinx.Graphics.Gpu/Image/Texture.cs | 84 |
1 files changed, 37 insertions, 47 deletions
diff --git a/Ryujinx.Graphics.Gpu/Image/Texture.cs b/Ryujinx.Graphics.Gpu/Image/Texture.cs index ae7fa6cf..1c558f56 100644 --- a/Ryujinx.Graphics.Gpu/Image/Texture.cs +++ b/Ryujinx.Graphics.Gpu/Image/Texture.cs @@ -1,7 +1,7 @@ using Ryujinx.Common; using Ryujinx.Common.Logging; -using Ryujinx.Cpu.Tracking; using Ryujinx.Graphics.GAL; +using Ryujinx.Graphics.Gpu.Memory; using Ryujinx.Graphics.Texture; using Ryujinx.Graphics.Texture.Astc; using Ryujinx.Memory.Range; @@ -14,7 +14,7 @@ namespace Ryujinx.Graphics.Gpu.Image /// <summary> /// Represents a cached GPU texture. /// </summary> - class Texture : IRange, IDisposable + class Texture : IMultiRangeItem, IDisposable { // How many updates we need before switching to the byte-by-byte comparison // modification check method. @@ -95,21 +95,16 @@ namespace Ryujinx.Graphics.Gpu.Image public event Action<Texture> Disposed; /// <summary> - /// Start address of the texture in guest memory. + /// Physical memory ranges where the texture data is located. /// </summary> - public ulong Address => Info.Address; - - /// <summary> - /// End address of the texture in guest memory. - /// </summary> - public ulong EndAddress => Info.Address + Size; + public MultiRange Range { get; private set; } /// <summary> /// Texture size in bytes. /// </summary> public ulong Size => (ulong)_sizeInfo.TotalSize; - private CpuRegionHandle _memoryTracking; + private GpuRegionHandle _memoryTracking; private int _referenceCount; @@ -119,6 +114,7 @@ namespace Ryujinx.Graphics.Gpu.Image /// <param name="context">GPU context that the texture belongs to</param> /// <param name="info">Texture information</param> /// <param name="sizeInfo">Size information of the texture</param> + /// <param name="range">Physical memory ranges where the texture data is located</param> /// <param name="firstLayer">The first layer of the texture, or 0 if the texture has no parent</param> /// <param name="firstLevel">The first mipmap level of the texture, or 0 if the texture has no parent</param> /// <param name="scaleFactor">The floating point scale factor to initialize with</param> @@ -127,12 +123,13 @@ namespace Ryujinx.Graphics.Gpu.Image GpuContext context, TextureInfo info, SizeInfo sizeInfo, + MultiRange range, int firstLayer, int firstLevel, float scaleFactor, TextureScaleMode scaleMode) { - InitializeTexture(context, info, sizeInfo); + InitializeTexture(context, info, sizeInfo, range); _firstLayer = firstLayer; _firstLevel = firstLevel; @@ -149,13 +146,14 @@ namespace Ryujinx.Graphics.Gpu.Image /// <param name="context">GPU context that the texture belongs to</param> /// <param name="info">Texture information</param> /// <param name="sizeInfo">Size information of the texture</param> + /// <param name="range">Physical memory ranges where the texture data is located</param> /// <param name="scaleMode">The scale mode to initialize with. If scaled, the texture's data is loaded immediately and scaled up</param> - public Texture(GpuContext context, TextureInfo info, SizeInfo sizeInfo, TextureScaleMode scaleMode) + public Texture(GpuContext context, TextureInfo info, SizeInfo sizeInfo, MultiRange range, TextureScaleMode scaleMode) { ScaleFactor = 1f; // Texture is first loaded at scale 1x. ScaleMode = scaleMode; - InitializeTexture(context, info, sizeInfo); + InitializeTexture(context, info, sizeInfo, range); } /// <summary> @@ -166,10 +164,12 @@ namespace Ryujinx.Graphics.Gpu.Image /// <param name="context">GPU context that the texture belongs to</param> /// <param name="info">Texture information</param> /// <param name="sizeInfo">Size information of the texture</param> - private void InitializeTexture(GpuContext context, TextureInfo info, SizeInfo sizeInfo) + /// <param name="range">Physical memory ranges where the texture data is located</param> + private void InitializeTexture(GpuContext context, TextureInfo info, SizeInfo sizeInfo, MultiRange range) { _context = context; _sizeInfo = sizeInfo; + Range = range; SetInfo(info); @@ -186,7 +186,7 @@ namespace Ryujinx.Graphics.Gpu.Image /// <param name="withData">True if the texture is to be initialized with data</param> public void InitializeData(bool isView, bool withData = false) { - _memoryTracking = _context.PhysicalMemory.BeginTracking(Address, Size); + _memoryTracking = _context.PhysicalMemory.BeginTracking(Range); if (withData) { @@ -229,15 +229,17 @@ namespace Ryujinx.Graphics.Gpu.Image /// </summary> /// <param name="info">Child texture information</param> /// <param name="sizeInfo">Child texture size information</param> + /// <param name="range">Physical memory ranges where the texture data is located</param> /// <param name="firstLayer">Start layer of the child texture on the parent texture</param> /// <param name="firstLevel">Start mipmap level of the child texture on the parent texture</param> /// <returns>The child texture</returns> - public Texture CreateView(TextureInfo info, SizeInfo sizeInfo, int firstLayer, int firstLevel) + public Texture CreateView(TextureInfo info, SizeInfo sizeInfo, MultiRange range, int firstLayer, int firstLevel) { Texture texture = new Texture( _context, info, sizeInfo, + range, _firstLayer + firstLayer, _firstLevel + firstLevel, ScaleFactor, @@ -367,7 +369,7 @@ namespace Ryujinx.Graphics.Gpu.Image ChangedSize = true; SetInfo(new TextureInfo( - Info.Address, + Info.GpuAddress, width, height, depthOrLayers, @@ -554,7 +556,7 @@ namespace Ryujinx.Graphics.Gpu.Image _memoryTracking?.Reprotect(); - ReadOnlySpan<byte> data = _context.PhysicalMemory.GetSpan(Address, (int)Size); + ReadOnlySpan<byte> data = _context.PhysicalMemory.GetSpan(Range); IsModified = false; @@ -586,6 +588,10 @@ namespace Ryujinx.Graphics.Gpu.Image _hasData = true; } + /// <summary> + /// Uploads new texture data to the host GPU. + /// </summary> + /// <param name="data">New data</param> public void SetData(ReadOnlySpan<byte> data) { BlacklistScale(); @@ -653,7 +659,7 @@ namespace Ryujinx.Graphics.Gpu.Image { string texInfo = $"{Info.Target} {Info.FormatInfo.Format} {Info.Width}x{Info.Height}x{Info.DepthOrLayers} levels {Info.Levels}"; - Logger.Debug?.Print(LogClass.Gpu, $"Invalid ASTC texture at 0x{Info.Address:X} ({texInfo})."); + Logger.Debug?.Print(LogClass.Gpu, $"Invalid ASTC texture at 0x{Info.GpuAddress:X} ({texInfo})."); } data = decoded; @@ -689,15 +695,14 @@ namespace Ryujinx.Graphics.Gpu.Image if (tracked) { - _context.PhysicalMemory.Write(Address, GetTextureDataFromGpu(tracked)); + _context.PhysicalMemory.Write(Range, GetTextureDataFromGpu(tracked)); } else { - _context.PhysicalMemory.WriteUntracked(Address, GetTextureDataFromGpu(tracked)); + _context.PhysicalMemory.WriteUntracked(Range, GetTextureDataFromGpu(tracked)); } } - /// <summary> /// Flushes the texture data, to be called from an external thread. /// The host backend must ensure that we have shared access to the resource from this thread. @@ -725,7 +730,7 @@ namespace Ryujinx.Graphics.Gpu.Image texture = _flushHostTexture = GetScaledHostTexture(1f, _flushHostTexture); } - _context.PhysicalMemory.WriteUntracked(Address, GetTextureDataFromGpu(false, texture)); + _context.PhysicalMemory.WriteUntracked(Range, GetTextureDataFromGpu(false, texture)); }); } @@ -847,25 +852,23 @@ namespace Ryujinx.Graphics.Gpu.Image return TextureMatchQuality.NoMatch; } - return Info.Address == info.Address && Info.Levels == info.Levels ? matchQuality : TextureMatchQuality.NoMatch; + return Info.Levels == info.Levels ? matchQuality : TextureMatchQuality.NoMatch; } /// <summary> /// Check if it's possible to create a view, with the given parameters, from this texture. /// </summary> /// <param name="info">Texture view information</param> - /// <param name="size">Texture view size</param> + /// <param name="range">Texture view physical memory ranges</param> /// <param name="firstLayer">Texture view initial layer on this texture</param> /// <param name="firstLevel">Texture view first mipmap level on this texture</param> /// <returns>The level of compatiblilty a view with the given parameters created from this texture has</returns> - public TextureViewCompatibility IsViewCompatible( - TextureInfo info, - ulong size, - out int firstLayer, - out int firstLevel) + public TextureViewCompatibility IsViewCompatible(TextureInfo info, MultiRange range, out int firstLayer, out int firstLevel) { + int offset = Range.FindOffset(range); + // Out of range. - if (info.Address < Address || info.Address + size > EndAddress) + if (offset < 0) { firstLayer = 0; firstLevel = 0; @@ -873,9 +876,7 @@ namespace Ryujinx.Graphics.Gpu.Image return TextureViewCompatibility.Incompatible; } - int offset = (int)(info.Address - Address); - - if (!_sizeInfo.FindView(offset, (int)size, out firstLayer, out firstLevel)) + if (!_sizeInfo.FindView(offset, out firstLayer, out firstLevel)) { return TextureViewCompatibility.Incompatible; } @@ -1046,17 +1047,6 @@ namespace Ryujinx.Graphics.Gpu.Image } /// <summary> - /// Checks if the texture overlaps with a memory range. - /// </summary> - /// <param name="address">Start address of the range</param> - /// <param name="size">Size of the range</param> - /// <returns>True if the texture overlaps with the range, false otherwise</returns> - public bool OverlapsWith(ulong address, ulong size) - { - return Address < address + size && address < EndAddress; - } - - /// <summary> /// Determine if any of our child textures are compaible as views of the given texture. /// </summary> /// <param name="texture">The texture to check against</param> @@ -1070,7 +1060,7 @@ namespace Ryujinx.Graphics.Gpu.Image foreach (Texture view in _views) { - if (texture.IsViewCompatible(view.Info, view.Size, out int _, out int _) != TextureViewCompatibility.Incompatible) + if (texture.IsViewCompatible(view.Info, view.Range, out _, out _) != TextureViewCompatibility.Incompatible) { return true; } @@ -1153,7 +1143,7 @@ namespace Ryujinx.Graphics.Gpu.Image { IsModified = false; // We shouldn't flush this texture, as its memory is no longer mapped. - CpuRegionHandle tracking = _memoryTracking; + var tracking = _memoryTracking; tracking?.Reprotect(); tracking?.RegisterAction(null); } |