SizeInfo.cs
1 using System; 2 using System.Collections.Generic; 3 4 namespace Ryujinx.Graphics.Texture 5 { 6 public readonly struct SizeInfo 7 { 8 private readonly int[] _mipOffsets; 9 10 private readonly int _levels; 11 private readonly int _depth; 12 private readonly bool _is3D; 13 14 public readonly int[] AllOffsets; 15 public readonly int[] SliceSizes; 16 public readonly int[] LevelSizes; 17 public int LayerSize { get; } 18 public int TotalSize { get; } 19 20 public SizeInfo(int size) 21 { 22 _mipOffsets = new int[] { 0 }; 23 AllOffsets = new int[] { 0 }; 24 SliceSizes = new int[] { size }; 25 LevelSizes = new int[] { size }; 26 _depth = 1; 27 _levels = 1; 28 LayerSize = size; 29 TotalSize = size; 30 _is3D = false; 31 } 32 33 internal SizeInfo( 34 int[] mipOffsets, 35 int[] allOffsets, 36 int[] sliceSizes, 37 int[] levelSizes, 38 int depth, 39 int levels, 40 int layerSize, 41 int totalSize, 42 bool is3D) 43 { 44 _mipOffsets = mipOffsets; 45 AllOffsets = allOffsets; 46 SliceSizes = sliceSizes; 47 LevelSizes = levelSizes; 48 _depth = depth; 49 _levels = levels; 50 LayerSize = layerSize; 51 TotalSize = totalSize; 52 _is3D = is3D; 53 } 54 55 public int GetMipOffset(int level) 56 { 57 if ((uint)level >= _mipOffsets.Length) 58 { 59 throw new ArgumentOutOfRangeException(nameof(level)); 60 } 61 62 return _mipOffsets[level]; 63 } 64 65 public bool FindView(int offset, out int firstLayer, out int firstLevel) 66 { 67 int index = Array.BinarySearch(AllOffsets, offset); 68 69 if (index < 0) 70 { 71 firstLayer = 0; 72 firstLevel = 0; 73 74 return false; 75 } 76 77 if (_is3D) 78 { 79 firstLayer = index; 80 firstLevel = 0; 81 82 int levelDepth = _depth; 83 84 while (firstLayer >= levelDepth) 85 { 86 firstLayer -= levelDepth; 87 firstLevel++; 88 levelDepth = Math.Max(levelDepth >> 1, 1); 89 } 90 } 91 else 92 { 93 firstLayer = index / _levels; 94 firstLevel = index - (firstLayer * _levels); 95 } 96 97 return true; 98 } 99 100 public IEnumerable<Region> AllRegions() 101 { 102 if (_is3D) 103 { 104 for (int i = 0; i < _mipOffsets.Length; i++) 105 { 106 int maxSize = TotalSize - _mipOffsets[i]; 107 yield return new Region(_mipOffsets[i], Math.Min(maxSize, LevelSizes[i])); 108 } 109 } 110 else 111 { 112 for (int i = 0; i < AllOffsets.Length; i++) 113 { 114 yield return new Region(AllOffsets[i], SliceSizes[i % _levels]); 115 } 116 } 117 } 118 } 119 }