| 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)
- {
- Height = gobBlockHeight;
- 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)
- {
- RobSize = robSize;
- 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;
- }
- }
- }
|