diff options
| author | riperiperi <rhy3756547@hotmail.com> | 2021-03-02 22:30:54 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-03-02 19:30:54 -0300 |
| commit | b530f0e1104723b894695b2860cf0f568f24cc9a (patch) | |
| tree | 04f6b7d76d334ddc5c0378f6aa00b98739bc793e /Ryujinx.Graphics.Texture | |
| parent | 7a90abc03555f41ba7589bc8e1f714839f9e2fed (diff) | |
Texture Cache: "Texture Groups" and "Texture Dependencies" (#2001)
* Initial implementation (3d tex mips broken)
This works rather well for most games, just need to fix 3d texture mips.
* Cleanup
* Address feedback
* Copy Dependencies and various other fixes
* Fix layer/level offset for copy from view<->view.
* Remove dirty flag from dependency
The dirty flag behaviour is not needed - DeferredCopy is all we need.
* Fix tracking mip slices.
* Propagate granularity (fix astral chain)
* Address Feedback pt 1
* Save slice sizes as part of SizeInfo
* Fix nits
* Fix disposing multiple dependencies causing a crash
This list is obviously modified when removing dependencies, so create a copy of it.
Diffstat (limited to 'Ryujinx.Graphics.Texture')
| -rw-r--r-- | Ryujinx.Graphics.Texture/SizeCalculator.cs | 29 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Texture/SizeInfo.cs | 43 |
2 files changed, 60 insertions, 12 deletions
diff --git a/Ryujinx.Graphics.Texture/SizeCalculator.cs b/Ryujinx.Graphics.Texture/SizeCalculator.cs index 2dc60869..7eee13c0 100644 --- a/Ryujinx.Graphics.Texture/SizeCalculator.cs +++ b/Ryujinx.Graphics.Texture/SizeCalculator.cs @@ -9,6 +9,19 @@ namespace Ryujinx.Graphics.Texture { private const int StrideAlignment = 32; + private static int Calculate3DOffsetCount(int levels, int depth) + { + int offsetCount = depth; + + while (--levels > 0) + { + depth = Math.Max(1, depth >> 1); + offsetCount += depth; + } + + return offsetCount; + } + public static SizeInfo GetBlockLinearTextureSize( int width, int height, @@ -27,8 +40,9 @@ namespace Ryujinx.Graphics.Texture int layerSize = 0; - int[] allOffsets = new int[levels * layers * depth]; + int[] allOffsets = new int[is3D ? Calculate3DOffsetCount(levels, depth) : levels * layers * depth]; int[] mipOffsets = new int[levels]; + int[] sliceSizes = new int[levels]; int mipGobBlocksInY = gobBlocksInY; int mipGobBlocksInZ = gobBlocksInZ; @@ -36,6 +50,8 @@ namespace Ryujinx.Graphics.Texture int gobWidth = (GobStride / bytesPerPixel) * gobBlocksInTileX; int gobHeight = gobBlocksInY * GobHeight; + int depthLevelOffset = 0; + for (int level = 0; level < levels; level++) { int w = Math.Max(1, width >> level); @@ -86,13 +102,16 @@ namespace Ryujinx.Graphics.Texture int zLow = z & mask; int zHigh = z & ~mask; - allOffsets[z * levels + level] = baseOffset + zLow * gobSize + zHigh * sliceSize; + allOffsets[z + depthLevelOffset] = baseOffset + zLow * gobSize + zHigh * sliceSize; } } mipOffsets[level] = layerSize; + sliceSizes[level] = totalBlocksOfGobsInY * robSize; + + layerSize += totalBlocksOfGobsInZ * sliceSizes[level]; - layerSize += totalBlocksOfGobsInZ * totalBlocksOfGobsInY * robSize; + depthLevelOffset += d; } if (layers > 1) @@ -133,7 +152,7 @@ namespace Ryujinx.Graphics.Texture } } - return new SizeInfo(mipOffsets, allOffsets, levels, layerSize, totalSize); + return new SizeInfo(mipOffsets, allOffsets, sliceSizes, depth, levels, layerSize, totalSize, is3D); } public static SizeInfo GetLinearTextureSize(int stride, int height, int blockHeight) @@ -142,7 +161,7 @@ namespace Ryujinx.Graphics.Texture // so we only need to handle a single case (2D textures without mipmaps). int totalSize = stride * BitUtils.DivRoundUp(height, blockHeight); - return new SizeInfo(new int[] { 0 }, new int[] { 0 }, 1, totalSize, totalSize); + return new SizeInfo(totalSize); } private static int AlignLayerSize( diff --git a/Ryujinx.Graphics.Texture/SizeInfo.cs b/Ryujinx.Graphics.Texture/SizeInfo.cs index 55b22e3a..f518ee4b 100644 --- a/Ryujinx.Graphics.Texture/SizeInfo.cs +++ b/Ryujinx.Graphics.Texture/SizeInfo.cs @@ -5,34 +5,46 @@ namespace Ryujinx.Graphics.Texture public struct SizeInfo { private readonly int[] _mipOffsets; - private readonly int[] _allOffsets; private readonly int _levels; + private readonly int _depth; + private readonly bool _is3D; + public readonly int[] AllOffsets; + public readonly int[] SliceSizes; public int LayerSize { get; } public int TotalSize { get; } public SizeInfo(int size) { _mipOffsets = new int[] { 0 }; - _allOffsets = new int[] { 0 }; + AllOffsets = new int[] { 0 }; + SliceSizes = new int[] { size }; + _depth = 1; _levels = 1; LayerSize = size; TotalSize = size; + _is3D = false; } internal SizeInfo( int[] mipOffsets, int[] allOffsets, + int[] sliceSizes, + int depth, int levels, int layerSize, - int totalSize) + int totalSize, + bool is3D) { _mipOffsets = mipOffsets; - _allOffsets = allOffsets; + AllOffsets = allOffsets; + SliceSizes = sliceSizes; + _depth = depth; _levels = levels; LayerSize = layerSize; TotalSize = totalSize; + _is3D = is3D; } public int GetMipOffset(int level) @@ -47,7 +59,7 @@ namespace Ryujinx.Graphics.Texture public bool FindView(int offset, out int firstLayer, out int firstLevel) { - int index = Array.BinarySearch(_allOffsets, offset); + int index = Array.BinarySearch(AllOffsets, offset); if (index < 0) { @@ -57,8 +69,25 @@ namespace Ryujinx.Graphics.Texture return false; } - firstLayer = index / _levels; - firstLevel = index - (firstLayer * _levels); + if (_is3D) + { + firstLayer = index; + firstLevel = 0; + + int levelDepth = _depth; + + while (firstLayer >= levelDepth) + { + firstLayer -= levelDepth; + firstLevel++; + levelDepth = Math.Max(levelDepth >> 1, 1); + } + } + else + { + firstLayer = index / _levels; + firstLevel = index - (firstLayer * _levels); + } return true; } |
