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/TextureManager.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/TextureManager.cs')
-rw-r--r-- | Ryujinx.Graphics.Gpu/Image/TextureManager.cs | 100 |
1 files changed, 52 insertions, 48 deletions
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs index 5bad3952..30137d06 100644 --- a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs +++ b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs @@ -37,14 +37,11 @@ namespace Ryujinx.Graphics.Gpu.Image private readonly TextureBindingsManager _gpBindingsManager; private readonly Texture[] _rtColors; - - private Texture _rtDepthStencil; - private readonly ITexture[] _rtHostColors; - + private Texture _rtDepthStencil; private ITexture _rtHostDs; - private readonly RangeList<Texture> _textures; + private readonly MultiRangeList<Texture> _textures; private Texture[] _textureOverlaps; private OverlapInfo[] _overlapInfo; @@ -70,10 +67,9 @@ namespace Ryujinx.Graphics.Gpu.Image _gpBindingsManager = new TextureBindingsManager(context, texturePoolCache, isCompute: false); _rtColors = new Texture[Constants.TotalRenderTargets]; - _rtHostColors = new ITexture[Constants.TotalRenderTargets]; - _textures = new RangeList<Texture>(); + _textures = new MultiRangeList<Texture>(); _textureOverlaps = new Texture[OverlapsBufferInitialCapacity]; _overlapInfo = new OverlapInfo[OverlapsBufferInitialCapacity]; @@ -470,13 +466,6 @@ namespace Ryujinx.Graphics.Gpu.Image /// <returns>The texture</returns> public Texture FindOrCreateTexture(CopyTexture copyTexture, FormatInfo formatInfo, bool preferScaling = true, Size? sizeHint = null) { - ulong address = _context.MemoryManager.Translate(copyTexture.Address.Pack()); - - if (address == MemoryManager.PteUnmapped) - { - return null; - } - int gobBlocksInY = copyTexture.MemoryLayout.UnpackGobBlocksInY(); int gobBlocksInZ = copyTexture.MemoryLayout.UnpackGobBlocksInZ(); @@ -492,7 +481,7 @@ namespace Ryujinx.Graphics.Gpu.Image } TextureInfo info = new TextureInfo( - address, + copyTexture.Address.Pack(), width, copyTexture.Height, copyTexture.Depth, @@ -514,9 +503,9 @@ namespace Ryujinx.Graphics.Gpu.Image flags |= TextureSearchFlags.WithUpscale; } - Texture texture = FindOrCreateTexture(info, flags, 0, sizeHint); + Texture texture = FindOrCreateTexture(flags, info, 0, sizeHint); - texture.SynchronizeMemory(); + texture?.SynchronizeMemory(); return texture; } @@ -531,13 +520,6 @@ namespace Ryujinx.Graphics.Gpu.Image /// <returns>The texture</returns> public Texture FindOrCreateTexture(RtColorState colorState, int samplesInX, int samplesInY, Size sizeHint) { - ulong address = _context.MemoryManager.Translate(colorState.Address.Pack()); - - if (address == MemoryManager.PteUnmapped) - { - return null; - } - bool isLinear = colorState.MemoryLayout.UnpackIsLinear(); int gobBlocksInY = colorState.MemoryLayout.UnpackGobBlocksInY(); @@ -583,7 +565,7 @@ namespace Ryujinx.Graphics.Gpu.Image } TextureInfo info = new TextureInfo( - address, + colorState.Address.Pack(), width, colorState.Height, colorState.Depth, @@ -600,9 +582,9 @@ namespace Ryujinx.Graphics.Gpu.Image int layerSize = !isLinear ? colorState.LayerSize * 4 : 0; - Texture texture = FindOrCreateTexture(info, TextureSearchFlags.WithUpscale, layerSize, sizeHint); + Texture texture = FindOrCreateTexture(TextureSearchFlags.WithUpscale, info, layerSize, sizeHint); - texture.SynchronizeMemory(); + texture?.SynchronizeMemory(); return texture; } @@ -618,13 +600,6 @@ namespace Ryujinx.Graphics.Gpu.Image /// <returns>The texture</returns> public Texture FindOrCreateTexture(RtDepthStencilState dsState, Size3D size, int samplesInX, int samplesInY, Size sizeHint) { - ulong address = _context.MemoryManager.Translate(dsState.Address.Pack()); - - if (address == MemoryManager.PteUnmapped) - { - return null; - } - int gobBlocksInY = dsState.MemoryLayout.UnpackGobBlocksInY(); int gobBlocksInZ = dsState.MemoryLayout.UnpackGobBlocksInZ(); @@ -635,7 +610,7 @@ namespace Ryujinx.Graphics.Gpu.Image FormatInfo formatInfo = dsState.Format.Convert(); TextureInfo info = new TextureInfo( - address, + dsState.Address.Pack(), size.Width, size.Height, size.Depth, @@ -650,9 +625,9 @@ namespace Ryujinx.Graphics.Gpu.Image target, formatInfo); - Texture texture = FindOrCreateTexture(info, TextureSearchFlags.WithUpscale, dsState.LayerSize * 4, sizeHint); + Texture texture = FindOrCreateTexture(TextureSearchFlags.WithUpscale, info, dsState.LayerSize * 4, sizeHint); - texture.SynchronizeMemory(); + texture?.SynchronizeMemory(); return texture; } @@ -660,12 +635,13 @@ namespace Ryujinx.Graphics.Gpu.Image /// <summary> /// Tries to find an existing texture, or create a new one if not found. /// </summary> - /// <param name="info">Texture information of the texture to be found or created</param> /// <param name="flags">The texture search flags, defines texture comparison rules</param> + /// <param name="info">Texture information of the texture to be found or created</param> /// <param name="layerSize">Size in bytes of a single texture layer</param> /// <param name="sizeHint">A hint indicating the minimum used size for the texture</param> + /// <param name="range">Optional ranges of physical memory where the texture data is located</param> /// <returns>The texture</returns> - public Texture FindOrCreateTexture(TextureInfo info, TextureSearchFlags flags = TextureSearchFlags.None, int layerSize = 0, Size? sizeHint = null) + public Texture FindOrCreateTexture(TextureSearchFlags flags, TextureInfo info, int layerSize = 0, Size? sizeHint = null, MultiRange? range = null) { bool isSamplerTexture = (flags & TextureSearchFlags.ForSampler) != 0; @@ -677,12 +653,28 @@ namespace Ryujinx.Graphics.Gpu.Image scaleMode = (flags & TextureSearchFlags.WithUpscale) != 0 ? TextureScaleMode.Scaled : TextureScaleMode.Eligible; } + ulong address; + + if (range != null) + { + address = range.Value.GetSubRange(0).Address; + } + else + { + address = _context.MemoryManager.Translate(info.GpuAddress); + + if (address == MemoryManager.PteUnmapped) + { + return null; + } + } + int sameAddressOverlapsCount; lock (_textures) { // Try to find a perfect texture match, with the same address and parameters. - sameAddressOverlapsCount = _textures.FindOverlaps(info.Address, ref _textureOverlaps); + sameAddressOverlapsCount = _textures.FindOverlaps(address, ref _textureOverlaps); } Texture texture = null; @@ -693,6 +685,12 @@ namespace Ryujinx.Graphics.Gpu.Image { Texture overlap = _textureOverlaps[index]; + bool rangeMatches = range != null ? overlap.Range.Equals(range.Value) : overlap.Info.GpuAddress == info.GpuAddress; + if (!rangeMatches) + { + continue; + } + TextureMatchQuality matchQuality = overlap.IsExactMatch(info, flags); if (matchQuality == TextureMatchQuality.Perfect) @@ -727,19 +725,25 @@ namespace Ryujinx.Graphics.Gpu.Image // Calculate texture sizes, used to find all overlapping textures. SizeInfo sizeInfo = info.CalculateSizeInfo(layerSize); - // Find view compatible matches. ulong size = (ulong)sizeInfo.TotalSize; + + if (range == null) + { + range = _context.MemoryManager.GetPhysicalRegions(info.GpuAddress, size); + } + + // Find view compatible matches. int overlapsCount; lock (_textures) { - overlapsCount = _textures.FindOverlaps(info.Address, size, ref _textureOverlaps); + overlapsCount = _textures.FindOverlaps(range.Value, ref _textureOverlaps); } for (int index = 0; index < overlapsCount; index++) { Texture overlap = _textureOverlaps[index]; - TextureViewCompatibility overlapCompatibility = overlap.IsViewCompatible(info, size, out int firstLayer, out int firstLevel); + TextureViewCompatibility overlapCompatibility = overlap.IsViewCompatible(info, range.Value, out int firstLayer, out int firstLevel); if (overlapCompatibility == TextureViewCompatibility.Full) { @@ -750,7 +754,7 @@ namespace Ryujinx.Graphics.Gpu.Image info = oInfo; } - texture = overlap.CreateView(oInfo, sizeInfo, firstLayer, firstLevel); + texture = overlap.CreateView(oInfo, sizeInfo, range.Value, firstLayer, firstLevel); if (overlap.IsModified) { @@ -771,7 +775,7 @@ namespace Ryujinx.Graphics.Gpu.Image // No match, create a new texture. if (texture == null) { - texture = new Texture(_context, info, sizeInfo, scaleMode); + texture = new Texture(_context, info, sizeInfo, range.Value, scaleMode); // Step 1: Find textures that are view compatible with the new texture. // Any textures that are incompatible will contain garbage data, so they should be removed where possible. @@ -784,7 +788,7 @@ namespace Ryujinx.Graphics.Gpu.Image Texture overlap = _textureOverlaps[index]; bool overlapInCache = overlap.CacheNode != null; - TextureViewCompatibility compatibility = texture.IsViewCompatible(overlap.Info, overlap.Size, out int firstLayer, out int firstLevel); + TextureViewCompatibility compatibility = texture.IsViewCompatible(overlap.Info, overlap.Range, out int firstLayer, out int firstLevel); if (compatibility != TextureViewCompatibility.Incompatible) { @@ -812,7 +816,7 @@ namespace Ryujinx.Graphics.Gpu.Image // If the data has been modified by the CPU, then it also shouldn't be flushed. bool modified = overlap.ConsumeModified(); - bool flush = overlapInCache && !modified && (overlap.Address < texture.Address || overlap.EndAddress > texture.EndAddress) && overlap.HasViewCompatibleChild(texture); + bool flush = overlapInCache && !modified && !texture.Range.Contains(overlap.Range) && overlap.HasViewCompatibleChild(texture); setData |= modified || flush; @@ -1070,7 +1074,7 @@ namespace Ryujinx.Graphics.Gpu.Image } return new TextureInfo( - info.Address, + info.GpuAddress, width, height, depthOrLayers, |