| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- using Ryujinx.Common;
- using System;
- namespace Ryujinx.Graphics.Texture
- {
- class BlockLinearSwizzle : ISwizzle
- {
- private const int GobWidth = 64;
- private const int GobHeight = 8;
- private const int GobSize = GobWidth * GobHeight;
- private int TexWidth;
- private int TexHeight;
- private int TexDepth;
- private int TexGobBlockHeight;
- private int TexGobBlockDepth;
- private int TexBpp;
- private int BhMask;
- private int BdMask;
- private int BhShift;
- private int BdShift;
- private int BppShift;
- private int XShift;
- private int RobSize;
- private int SliceSize;
- private int BaseOffset;
- public BlockLinearSwizzle(
- int Width,
- int Height,
- int Depth,
- int GobBlockHeight,
- int GobBlockDepth,
- int Bpp)
- {
- TexWidth = Width;
- TexHeight = Height;
- TexDepth = Depth;
- TexGobBlockHeight = GobBlockHeight;
- TexGobBlockDepth = GobBlockDepth;
- TexBpp = Bpp;
- BppShift = BitUtils.CountTrailingZeros32(Bpp);
- SetMipLevel(0);
- }
- public void SetMipLevel(int Level)
- {
- BaseOffset = GetMipOffset(Level);
- int Width = Math.Max(1, TexWidth >> Level);
- int Height = Math.Max(1, TexHeight >> Level);
- int Depth = Math.Max(1, TexDepth >> Level);
- GobBlockSizes GbSizes = AdjustGobBlockSizes(Height, Depth);
- BhMask = GbSizes.Height - 1;
- BdMask = GbSizes.Depth - 1;
- BhShift = BitUtils.CountTrailingZeros32(GbSizes.Height);
- BdShift = BitUtils.CountTrailingZeros32(GbSizes.Depth);
- XShift = BitUtils.CountTrailingZeros32(GobSize * GbSizes.Height * GbSizes.Depth);
- RobAndSliceSizes GsSizes = GetRobAndSliceSizes(Width, Height, GbSizes);
- RobSize = GsSizes.RobSize;
- SliceSize = GsSizes.SliceSize;
- }
- public int GetImageSize(int MipsCount)
- {
- int Size = GetMipOffset(MipsCount);
- Size = (Size + 0x1fff) & ~0x1fff;
- return Size;
- }
- public int GetMipOffset(int Level)
- {
- int TotalSize = 0;
- for (int Index = 0; Index < Level; Index++)
- {
- int Width = Math.Max(1, TexWidth >> Index);
- int Height = Math.Max(1, TexHeight >> Index);
- int Depth = Math.Max(1, TexDepth >> Index);
- GobBlockSizes GbSizes = AdjustGobBlockSizes(Height, Depth);
- RobAndSliceSizes RsSizes = GetRobAndSliceSizes(Width, Height, GbSizes);
- TotalSize += BitUtils.DivRoundUp(Depth, GbSizes.Depth) * RsSizes.SliceSize;
- }
- return TotalSize;
- }
- private struct GobBlockSizes
- {
- public int Height;
- public int Depth;
- public GobBlockSizes(int GobBlockHeight, int GobBlockDepth)
- {
- this.Height = GobBlockHeight;
- this.Depth = GobBlockDepth;
- }
- }
- private GobBlockSizes AdjustGobBlockSizes(int Height, int Depth)
- {
- int GobBlockHeight = TexGobBlockHeight;
- int GobBlockDepth = TexGobBlockDepth;
- int Pow2Height = BitUtils.Pow2RoundUp(Height);
- int Pow2Depth = BitUtils.Pow2RoundUp(Depth);
- while (GobBlockHeight * GobHeight > Pow2Height && GobBlockHeight > 1)
- {
- GobBlockHeight >>= 1;
- }
- while (GobBlockDepth > Pow2Depth && GobBlockDepth > 1)
- {
- GobBlockDepth >>= 1;
- }
- return new GobBlockSizes(GobBlockHeight, GobBlockDepth);
- }
- private struct RobAndSliceSizes
- {
- public int RobSize;
- public int SliceSize;
- public RobAndSliceSizes(int RobSize, int SliceSize)
- {
- this.RobSize = RobSize;
- this.SliceSize = SliceSize;
- }
- }
- private RobAndSliceSizes GetRobAndSliceSizes(int Width, int Height, GobBlockSizes GbSizes)
- {
- int WidthInGobs = BitUtils.DivRoundUp(Width * TexBpp, GobWidth);
- int RobSize = GobSize * GbSizes.Height * GbSizes.Depth * WidthInGobs;
- int SliceSize = BitUtils.DivRoundUp(Height, GbSizes.Height * GobHeight) * RobSize;
- return new RobAndSliceSizes(RobSize, SliceSize);
- }
- public int GetSwizzleOffset(int X, int Y, int Z)
- {
- X <<= BppShift;
- int YH = Y / GobHeight;
- int Position = (Z >> BdShift) * SliceSize + (YH >> BhShift) * RobSize;
- Position += (X / GobWidth) << XShift;
- Position += (YH & BhMask) * GobSize;
- Position += ((Z & BdMask) * GobSize) << BhShift;
- Position += ((X & 0x3f) >> 5) << 8;
- Position += ((Y & 0x07) >> 1) << 6;
- Position += ((X & 0x1f) >> 4) << 5;
- Position += ((Y & 0x01) >> 0) << 4;
- Position += ((X & 0x0f) >> 0) << 0;
- return BaseOffset + Position;
- }
- }
- }
|