2019-02-28 01:12:24 +00:00
|
|
|
using Ryujinx.Common;
|
2018-05-12 00:20:44 +01:00
|
|
|
using System;
|
|
|
|
|
2018-09-08 18:51:50 +01:00
|
|
|
namespace Ryujinx.Graphics.Texture
|
2018-04-08 20:17:35 +01:00
|
|
|
{
|
|
|
|
class BlockLinearSwizzle : ISwizzle
|
|
|
|
{
|
2019-02-28 01:12:24 +00:00
|
|
|
private const int GobWidth = 64;
|
|
|
|
private const int GobHeight = 8;
|
|
|
|
|
|
|
|
private const int GobSize = GobWidth * GobHeight;
|
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
private int _texWidth;
|
|
|
|
private int _texHeight;
|
|
|
|
private int _texDepth;
|
|
|
|
private int _texGobBlockHeight;
|
|
|
|
private int _texGobBlockDepth;
|
|
|
|
private int _texBpp;
|
2019-02-28 01:12:24 +00:00
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
private int _bhMask;
|
|
|
|
private int _bdMask;
|
2019-02-28 01:12:24 +00:00
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
private int _bhShift;
|
|
|
|
private int _bdShift;
|
|
|
|
private int _bppShift;
|
2018-04-08 20:17:35 +01:00
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
private int _xShift;
|
2018-04-08 20:17:35 +01:00
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
private int _robSize;
|
|
|
|
private int _sliceSize;
|
2019-02-28 01:12:24 +00:00
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
private int _baseOffset;
|
2019-02-28 01:12:24 +00:00
|
|
|
|
|
|
|
public BlockLinearSwizzle(
|
2019-03-04 01:45:25 +00:00
|
|
|
int width,
|
|
|
|
int height,
|
|
|
|
int depth,
|
|
|
|
int gobBlockHeight,
|
|
|
|
int gobBlockDepth,
|
|
|
|
int bpp)
|
2018-04-08 20:17:35 +01:00
|
|
|
{
|
2019-03-04 01:45:25 +00:00
|
|
|
_texWidth = width;
|
|
|
|
_texHeight = height;
|
|
|
|
_texDepth = depth;
|
|
|
|
_texGobBlockHeight = gobBlockHeight;
|
|
|
|
_texGobBlockDepth = gobBlockDepth;
|
|
|
|
_texBpp = bpp;
|
2019-02-28 01:12:24 +00:00
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
_bppShift = BitUtils.CountTrailingZeros32(bpp);
|
2019-02-28 01:12:24 +00:00
|
|
|
|
|
|
|
SetMipLevel(0);
|
|
|
|
}
|
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
public void SetMipLevel(int level)
|
2019-02-28 01:12:24 +00:00
|
|
|
{
|
2019-03-04 01:45:25 +00:00
|
|
|
_baseOffset = GetMipOffset(level);
|
2019-02-28 01:12:24 +00:00
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
int width = Math.Max(1, _texWidth >> level);
|
|
|
|
int height = Math.Max(1, _texHeight >> level);
|
|
|
|
int depth = Math.Max(1, _texDepth >> level);
|
2018-04-08 20:17:35 +01:00
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
GobBlockSizes gbSizes = AdjustGobBlockSizes(height, depth);
|
2018-04-08 20:17:35 +01:00
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
_bhMask = gbSizes.Height - 1;
|
|
|
|
_bdMask = gbSizes.Depth - 1;
|
2018-04-08 20:17:35 +01:00
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
_bhShift = BitUtils.CountTrailingZeros32(gbSizes.Height);
|
|
|
|
_bdShift = BitUtils.CountTrailingZeros32(gbSizes.Depth);
|
2018-04-08 20:17:35 +01:00
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
_xShift = BitUtils.CountTrailingZeros32(GobSize * gbSizes.Height * gbSizes.Depth);
|
2019-02-28 01:12:24 +00:00
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
RobAndSliceSizes gsSizes = GetRobAndSliceSizes(width, height, gbSizes);
|
2019-02-28 01:12:24 +00:00
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
_robSize = gsSizes.RobSize;
|
|
|
|
_sliceSize = gsSizes.SliceSize;
|
2019-02-28 01:12:24 +00:00
|
|
|
}
|
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
public int GetImageSize(int mipsCount)
|
2019-02-28 01:12:24 +00:00
|
|
|
{
|
2019-03-04 01:45:25 +00:00
|
|
|
int size = GetMipOffset(mipsCount);
|
2019-02-28 01:12:24 +00:00
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
size = (size + 0x1fff) & ~0x1fff;
|
2019-02-28 01:12:24 +00:00
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
return size;
|
2018-04-08 20:17:35 +01:00
|
|
|
}
|
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
public int GetMipOffset(int level)
|
2018-04-08 20:17:35 +01:00
|
|
|
{
|
2019-03-04 01:45:25 +00:00
|
|
|
int totalSize = 0;
|
2018-04-08 20:17:35 +01:00
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
for (int index = 0; index < level; index++)
|
2018-04-08 20:17:35 +01:00
|
|
|
{
|
2019-03-04 01:45:25 +00:00
|
|
|
int width = Math.Max(1, _texWidth >> index);
|
|
|
|
int height = Math.Max(1, _texHeight >> index);
|
|
|
|
int depth = Math.Max(1, _texDepth >> index);
|
2019-02-28 01:12:24 +00:00
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
GobBlockSizes gbSizes = AdjustGobBlockSizes(height, depth);
|
2019-02-28 01:12:24 +00:00
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
RobAndSliceSizes rsSizes = GetRobAndSliceSizes(width, height, gbSizes);
|
2019-02-28 01:12:24 +00:00
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
totalSize += BitUtils.DivRoundUp(depth, gbSizes.Depth) * rsSizes.SliceSize;
|
2018-04-08 20:17:35 +01:00
|
|
|
}
|
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
return totalSize;
|
2018-04-08 20:17:35 +01:00
|
|
|
}
|
|
|
|
|
2019-02-28 01:12:24 +00:00
|
|
|
private struct GobBlockSizes
|
|
|
|
{
|
|
|
|
public int Height;
|
|
|
|
public int Depth;
|
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
public GobBlockSizes(int gobBlockHeight, int gobBlockDepth)
|
2019-02-28 01:12:24 +00:00
|
|
|
{
|
2019-03-04 01:45:25 +00:00
|
|
|
Height = gobBlockHeight;
|
|
|
|
Depth = gobBlockDepth;
|
2019-02-28 01:12:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
private GobBlockSizes AdjustGobBlockSizes(int height, int depth)
|
2019-02-28 01:12:24 +00:00
|
|
|
{
|
2019-03-04 01:45:25 +00:00
|
|
|
int gobBlockHeight = _texGobBlockHeight;
|
|
|
|
int gobBlockDepth = _texGobBlockDepth;
|
2019-02-28 01:12:24 +00:00
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
int pow2Height = BitUtils.Pow2RoundUp(height);
|
|
|
|
int pow2Depth = BitUtils.Pow2RoundUp(depth);
|
2019-02-28 01:12:24 +00:00
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
while (gobBlockHeight * GobHeight > pow2Height && gobBlockHeight > 1)
|
2019-02-28 01:12:24 +00:00
|
|
|
{
|
2019-03-04 01:45:25 +00:00
|
|
|
gobBlockHeight >>= 1;
|
2019-02-28 01:12:24 +00:00
|
|
|
}
|
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
while (gobBlockDepth > pow2Depth && gobBlockDepth > 1)
|
2019-02-28 01:12:24 +00:00
|
|
|
{
|
2019-03-04 01:45:25 +00:00
|
|
|
gobBlockDepth >>= 1;
|
2019-02-28 01:12:24 +00:00
|
|
|
}
|
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
return new GobBlockSizes(gobBlockHeight, gobBlockDepth);
|
2019-02-28 01:12:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private struct RobAndSliceSizes
|
|
|
|
{
|
|
|
|
public int RobSize;
|
|
|
|
public int SliceSize;
|
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
public RobAndSliceSizes(int robSize, int sliceSize)
|
2019-02-28 01:12:24 +00:00
|
|
|
{
|
2019-03-04 01:45:25 +00:00
|
|
|
RobSize = robSize;
|
|
|
|
SliceSize = sliceSize;
|
2019-02-28 01:12:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
private RobAndSliceSizes GetRobAndSliceSizes(int width, int height, GobBlockSizes gbSizes)
|
2019-02-28 01:12:24 +00:00
|
|
|
{
|
2019-03-04 01:45:25 +00:00
|
|
|
int widthInGobs = BitUtils.DivRoundUp(width * _texBpp, GobWidth);
|
2019-02-28 01:12:24 +00:00
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
int robSize = GobSize * gbSizes.Height * gbSizes.Depth * widthInGobs;
|
2019-02-28 01:12:24 +00:00
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
int sliceSize = BitUtils.DivRoundUp(height, gbSizes.Height * GobHeight) * robSize;
|
2019-02-28 01:12:24 +00:00
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
return new RobAndSliceSizes(robSize, sliceSize);
|
2019-02-28 01:12:24 +00:00
|
|
|
}
|
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
public int GetSwizzleOffset(int x, int y, int z)
|
2018-04-08 20:17:35 +01:00
|
|
|
{
|
2019-03-04 01:45:25 +00:00
|
|
|
x <<= _bppShift;
|
2018-04-08 20:17:35 +01:00
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
int yh = y / GobHeight;
|
2019-02-28 01:12:24 +00:00
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
int position = (z >> _bdShift) * _sliceSize + (yh >> _bhShift) * _robSize;
|
2019-02-28 01:12:24 +00:00
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
position += (x / GobWidth) << _xShift;
|
2018-04-08 20:17:35 +01:00
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
position += (yh & _bhMask) * GobSize;
|
2018-04-08 20:17:35 +01:00
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
position += ((z & _bdMask) * GobSize) << _bhShift;
|
2018-04-08 20:17:35 +01:00
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
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;
|
2018-04-08 20:17:35 +01:00
|
|
|
|
2019-03-04 01:45:25 +00:00
|
|
|
return _baseOffset + position;
|
2018-04-08 20:17:35 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|