diff options
Diffstat (limited to 'src/Ryujinx.Graphics.Texture/Astc/IntegerEncoded.cs')
-rw-r--r-- | src/Ryujinx.Graphics.Texture/Astc/IntegerEncoded.cs | 345 |
1 files changed, 345 insertions, 0 deletions
diff --git a/src/Ryujinx.Graphics.Texture/Astc/IntegerEncoded.cs b/src/Ryujinx.Graphics.Texture/Astc/IntegerEncoded.cs new file mode 100644 index 00000000..065de46b --- /dev/null +++ b/src/Ryujinx.Graphics.Texture/Astc/IntegerEncoded.cs @@ -0,0 +1,345 @@ +using System; +using System.Numerics; + +namespace Ryujinx.Graphics.Texture.Astc +{ + internal struct IntegerEncoded + { + internal const int StructSize = 8; + private static readonly IntegerEncoded[] Encodings; + + public enum EIntegerEncoding : byte + { + JustBits, + Quint, + Trit + } + + EIntegerEncoding _encoding; + public byte NumberBits { get; private set; } + public byte TritValue { get; private set; } + public byte QuintValue { get; private set; } + public int BitValue { get; private set; } + + static IntegerEncoded() + { + Encodings = new IntegerEncoded[0x100]; + + for (int i = 0; i < Encodings.Length; i++) + { + Encodings[i] = CreateEncodingCalc(i); + } + } + + public IntegerEncoded(EIntegerEncoding encoding, int numBits) + { + _encoding = encoding; + NumberBits = (byte)numBits; + BitValue = 0; + TritValue = 0; + QuintValue = 0; + } + + public bool MatchesEncoding(IntegerEncoded other) + { + return _encoding == other._encoding && NumberBits == other.NumberBits; + } + + public EIntegerEncoding GetEncoding() + { + return _encoding; + } + + public int GetBitLength(int numberVals) + { + int totalBits = NumberBits * numberVals; + if (_encoding == EIntegerEncoding.Trit) + { + totalBits += (numberVals * 8 + 4) / 5; + } + else if (_encoding == EIntegerEncoding.Quint) + { + totalBits += (numberVals * 7 + 2) / 3; + } + return totalBits; + } + + public static IntegerEncoded CreateEncoding(int maxVal) + { + return Encodings[maxVal]; + } + + private static IntegerEncoded CreateEncodingCalc(int maxVal) + { + while (maxVal > 0) + { + int check = maxVal + 1; + + // Is maxVal a power of two? + if ((check & (check - 1)) == 0) + { + return new IntegerEncoded(EIntegerEncoding.JustBits, BitOperations.PopCount((uint)maxVal)); + } + + // Is maxVal of the type 3*2^n - 1? + if ((check % 3 == 0) && ((check / 3) & ((check / 3) - 1)) == 0) + { + return new IntegerEncoded(EIntegerEncoding.Trit, BitOperations.PopCount((uint)(check / 3 - 1))); + } + + // Is maxVal of the type 5*2^n - 1? + if ((check % 5 == 0) && ((check / 5) & ((check / 5) - 1)) == 0) + { + return new IntegerEncoded(EIntegerEncoding.Quint, BitOperations.PopCount((uint)(check / 5 - 1))); + } + + // Apparently it can't be represented with a bounded integer sequence... + // just iterate. + maxVal--; + } + + return new IntegerEncoded(EIntegerEncoding.JustBits, 0); + } + + public static void DecodeTritBlock( + ref BitStream128 bitStream, + ref IntegerSequence listIntegerEncoded, + int numberBitsPerValue) + { + // Implement the algorithm in section C.2.12 + Span<int> m = stackalloc int[5]; + + m[0] = bitStream.ReadBits(numberBitsPerValue); + int encoded = bitStream.ReadBits(2); + m[1] = bitStream.ReadBits(numberBitsPerValue); + encoded |= bitStream.ReadBits(2) << 2; + m[2] = bitStream.ReadBits(numberBitsPerValue); + encoded |= bitStream.ReadBits(1) << 4; + m[3] = bitStream.ReadBits(numberBitsPerValue); + encoded |= bitStream.ReadBits(2) << 5; + m[4] = bitStream.ReadBits(numberBitsPerValue); + encoded |= bitStream.ReadBits(1) << 7; + + ReadOnlySpan<byte> encodings = GetTritEncoding(encoded); + + IntegerEncoded intEncoded = new IntegerEncoded(EIntegerEncoding.Trit, numberBitsPerValue); + + for (int i = 0; i < 5; i++) + { + intEncoded.BitValue = m[i]; + intEncoded.TritValue = encodings[i]; + + listIntegerEncoded.Add(ref intEncoded); + } + } + + public static void DecodeQuintBlock( + ref BitStream128 bitStream, + ref IntegerSequence listIntegerEncoded, + int numberBitsPerValue) + { + ReadOnlySpan<byte> interleavedBits = new byte[] { 3, 2, 2 }; + + // Implement the algorithm in section C.2.12 + Span<int> m = stackalloc int[3]; + ulong encoded = 0; + int encodedBitsRead = 0; + + for (int i = 0; i < m.Length; i++) + { + m[i] = bitStream.ReadBits(numberBitsPerValue); + + uint encodedBits = (uint)bitStream.ReadBits(interleavedBits[i]); + + encoded |= encodedBits << encodedBitsRead; + encodedBitsRead += interleavedBits[i]; + } + + ReadOnlySpan<byte> encodings = GetQuintEncoding((int)encoded); + + for (int i = 0; i < 3; i++) + { + IntegerEncoded intEncoded = new IntegerEncoded(EIntegerEncoding.Quint, numberBitsPerValue) + { + BitValue = m[i], + QuintValue = encodings[i] + }; + + listIntegerEncoded.Add(ref intEncoded); + } + } + + public static void DecodeIntegerSequence( + ref IntegerSequence decodeIntegerSequence, + ref BitStream128 bitStream, + int maxRange, + int numberValues) + { + // Determine encoding parameters + IntegerEncoded intEncoded = CreateEncoding(maxRange); + + // Start decoding + int numberValuesDecoded = 0; + while (numberValuesDecoded < numberValues) + { + switch (intEncoded.GetEncoding()) + { + case EIntegerEncoding.Quint: + { + DecodeQuintBlock(ref bitStream, ref decodeIntegerSequence, intEncoded.NumberBits); + numberValuesDecoded += 3; + + break; + } + + case EIntegerEncoding.Trit: + { + DecodeTritBlock(ref bitStream, ref decodeIntegerSequence, intEncoded.NumberBits); + numberValuesDecoded += 5; + + break; + } + + case EIntegerEncoding.JustBits: + { + intEncoded.BitValue = bitStream.ReadBits(intEncoded.NumberBits); + decodeIntegerSequence.Add(ref intEncoded); + numberValuesDecoded++; + + break; + } + } + } + } + + private static ReadOnlySpan<byte> GetTritEncoding(int index) + { + return TritEncodings.Slice(index * 5, 5); + } + + private static ReadOnlySpan<byte> GetQuintEncoding(int index) + { + return QuintEncodings.Slice(index * 3, 3); + } + + private static ReadOnlySpan<byte> TritEncodings => new byte[] + { + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, + 2, 1, 0, 0, 0, 1, 0, 2, 0, 0, 0, 2, 0, 0, 0, + 1, 2, 0, 0, 0, 2, 2, 0, 0, 0, 2, 0, 2, 0, 0, + 0, 2, 2, 0, 0, 1, 2, 2, 0, 0, 2, 2, 2, 0, 0, + 2, 0, 2, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, + 2, 0, 1, 0, 0, 0, 1, 2, 0, 0, 0, 1, 1, 0, 0, + 1, 1, 1, 0, 0, 2, 1, 1, 0, 0, 1, 1, 2, 0, 0, + 0, 2, 1, 0, 0, 1, 2, 1, 0, 0, 2, 2, 1, 0, 0, + 2, 1, 2, 0, 0, 0, 0, 0, 2, 2, 1, 0, 0, 2, 2, + 2, 0, 0, 2, 2, 0, 0, 2, 2, 2, 0, 0, 0, 1, 0, + 1, 0, 0, 1, 0, 2, 0, 0, 1, 0, 0, 0, 2, 1, 0, + 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 2, 1, 0, 1, 0, + 1, 0, 2, 1, 0, 0, 2, 0, 1, 0, 1, 2, 0, 1, 0, + 2, 2, 0, 1, 0, 2, 0, 2, 1, 0, 0, 2, 2, 1, 0, + 1, 2, 2, 1, 0, 2, 2, 2, 1, 0, 2, 0, 2, 1, 0, + 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 2, 0, 1, 1, 0, + 0, 1, 2, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, + 2, 1, 1, 1, 0, 1, 1, 2, 1, 0, 0, 2, 1, 1, 0, + 1, 2, 1, 1, 0, 2, 2, 1, 1, 0, 2, 1, 2, 1, 0, + 0, 1, 0, 2, 2, 1, 1, 0, 2, 2, 2, 1, 0, 2, 2, + 1, 0, 2, 2, 2, 0, 0, 0, 2, 0, 1, 0, 0, 2, 0, + 2, 0, 0, 2, 0, 0, 0, 2, 2, 0, 0, 1, 0, 2, 0, + 1, 1, 0, 2, 0, 2, 1, 0, 2, 0, 1, 0, 2, 2, 0, + 0, 2, 0, 2, 0, 1, 2, 0, 2, 0, 2, 2, 0, 2, 0, + 2, 0, 2, 2, 0, 0, 2, 2, 2, 0, 1, 2, 2, 2, 0, + 2, 2, 2, 2, 0, 2, 0, 2, 2, 0, 0, 0, 1, 2, 0, + 1, 0, 1, 2, 0, 2, 0, 1, 2, 0, 0, 1, 2, 2, 0, + 0, 1, 1, 2, 0, 1, 1, 1, 2, 0, 2, 1, 1, 2, 0, + 1, 1, 2, 2, 0, 0, 2, 1, 2, 0, 1, 2, 1, 2, 0, + 2, 2, 1, 2, 0, 2, 1, 2, 2, 0, 0, 2, 0, 2, 2, + 1, 2, 0, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, + 0, 0, 0, 0, 2, 1, 0, 0, 0, 2, 2, 0, 0, 0, 2, + 0, 0, 2, 0, 2, 0, 1, 0, 0, 2, 1, 1, 0, 0, 2, + 2, 1, 0, 0, 2, 1, 0, 2, 0, 2, 0, 2, 0, 0, 2, + 1, 2, 0, 0, 2, 2, 2, 0, 0, 2, 2, 0, 2, 0, 2, + 0, 2, 2, 0, 2, 1, 2, 2, 0, 2, 2, 2, 2, 0, 2, + 2, 0, 2, 0, 2, 0, 0, 1, 0, 2, 1, 0, 1, 0, 2, + 2, 0, 1, 0, 2, 0, 1, 2, 0, 2, 0, 1, 1, 0, 2, + 1, 1, 1, 0, 2, 2, 1, 1, 0, 2, 1, 1, 2, 0, 2, + 0, 2, 1, 0, 2, 1, 2, 1, 0, 2, 2, 2, 1, 0, 2, + 2, 1, 2, 0, 2, 0, 2, 2, 2, 2, 1, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 1, + 1, 0, 0, 0, 1, 2, 0, 0, 0, 1, 0, 0, 2, 0, 1, + 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 2, 1, 0, 0, 1, + 1, 0, 2, 0, 1, 0, 2, 0, 0, 1, 1, 2, 0, 0, 1, + 2, 2, 0, 0, 1, 2, 0, 2, 0, 1, 0, 2, 2, 0, 1, + 1, 2, 2, 0, 1, 2, 2, 2, 0, 1, 2, 0, 2, 0, 1, + 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 2, 0, 1, 0, 1, + 0, 1, 2, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, + 2, 1, 1, 0, 1, 1, 1, 2, 0, 1, 0, 2, 1, 0, 1, + 1, 2, 1, 0, 1, 2, 2, 1, 0, 1, 2, 1, 2, 0, 1, + 0, 0, 1, 2, 2, 1, 0, 1, 2, 2, 2, 0, 1, 2, 2, + 0, 1, 2, 2, 2, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, + 2, 0, 0, 1, 1, 0, 0, 2, 1, 1, 0, 1, 0, 1, 1, + 1, 1, 0, 1, 1, 2, 1, 0, 1, 1, 1, 0, 2, 1, 1, + 0, 2, 0, 1, 1, 1, 2, 0, 1, 1, 2, 2, 0, 1, 1, + 2, 0, 2, 1, 1, 0, 2, 2, 1, 1, 1, 2, 2, 1, 1, + 2, 2, 2, 1, 1, 2, 0, 2, 1, 1, 0, 0, 1, 1, 1, + 1, 0, 1, 1, 1, 2, 0, 1, 1, 1, 0, 1, 2, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, + 1, 1, 2, 1, 1, 0, 2, 1, 1, 1, 1, 2, 1, 1, 1, + 2, 2, 1, 1, 1, 2, 1, 2, 1, 1, 0, 1, 1, 2, 2, + 1, 1, 1, 2, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 2, + 0, 0, 0, 2, 1, 1, 0, 0, 2, 1, 2, 0, 0, 2, 1, + 0, 0, 2, 2, 1, 0, 1, 0, 2, 1, 1, 1, 0, 2, 1, + 2, 1, 0, 2, 1, 1, 0, 2, 2, 1, 0, 2, 0, 2, 1, + 1, 2, 0, 2, 1, 2, 2, 0, 2, 1, 2, 0, 2, 2, 1, + 0, 2, 2, 2, 1, 1, 2, 2, 2, 1, 2, 2, 2, 2, 1, + 2, 0, 2, 2, 1, 0, 0, 1, 2, 1, 1, 0, 1, 2, 1, + 2, 0, 1, 2, 1, 0, 1, 2, 2, 1, 0, 1, 1, 2, 1, + 1, 1, 1, 2, 1, 2, 1, 1, 2, 1, 1, 1, 2, 2, 1, + 0, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, + 2, 1, 2, 2, 1, 0, 2, 1, 2, 2, 1, 2, 1, 2, 2, + 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 0, 0, 0, 1, 2, + 1, 0, 0, 1, 2, 2, 0, 0, 1, 2, 0, 0, 2, 1, 2, + 0, 1, 0, 1, 2, 1, 1, 0, 1, 2, 2, 1, 0, 1, 2, + 1, 0, 2, 1, 2, 0, 2, 0, 1, 2, 1, 2, 0, 1, 2, + 2, 2, 0, 1, 2, 2, 0, 2, 1, 2, 0, 2, 2, 1, 2, + 1, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 0, 2, 1, 2, + 0, 0, 1, 1, 2, 1, 0, 1, 1, 2, 2, 0, 1, 1, 2, + 0, 1, 2, 1, 2, 0, 1, 1, 1, 2, 1, 1, 1, 1, 2, + 2, 1, 1, 1, 2, 1, 1, 2, 1, 2, 0, 2, 1, 1, 2, + 1, 2, 1, 1, 2, 2, 2, 1, 1, 2, 2, 1, 2, 1, 2, + 0, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 1, 2, 2, 2 + }; + + private static ReadOnlySpan<byte> QuintEncodings => new byte[] + { + 0, 0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0, 4, 0, 0, + 0, 4, 0, 4, 4, 0, 4, 4, 4, 0, 1, 0, 1, 1, 0, + 2, 1, 0, 3, 1, 0, 4, 1, 0, 1, 4, 0, 4, 4, 1, + 4, 4, 4, 0, 2, 0, 1, 2, 0, 2, 2, 0, 3, 2, 0, + 4, 2, 0, 2, 4, 0, 4, 4, 2, 4, 4, 4, 0, 3, 0, + 1, 3, 0, 2, 3, 0, 3, 3, 0, 4, 3, 0, 3, 4, 0, + 4, 4, 3, 4, 4, 4, 0, 0, 1, 1, 0, 1, 2, 0, 1, + 3, 0, 1, 4, 0, 1, 0, 4, 1, 4, 0, 4, 0, 4, 4, + 0, 1, 1, 1, 1, 1, 2, 1, 1, 3, 1, 1, 4, 1, 1, + 1, 4, 1, 4, 1, 4, 1, 4, 4, 0, 2, 1, 1, 2, 1, + 2, 2, 1, 3, 2, 1, 4, 2, 1, 2, 4, 1, 4, 2, 4, + 2, 4, 4, 0, 3, 1, 1, 3, 1, 2, 3, 1, 3, 3, 1, + 4, 3, 1, 3, 4, 1, 4, 3, 4, 3, 4, 4, 0, 0, 2, + 1, 0, 2, 2, 0, 2, 3, 0, 2, 4, 0, 2, 0, 4, 2, + 2, 0, 4, 3, 0, 4, 0, 1, 2, 1, 1, 2, 2, 1, 2, + 3, 1, 2, 4, 1, 2, 1, 4, 2, 2, 1, 4, 3, 1, 4, + 0, 2, 2, 1, 2, 2, 2, 2, 2, 3, 2, 2, 4, 2, 2, + 2, 4, 2, 2, 2, 4, 3, 2, 4, 0, 3, 2, 1, 3, 2, + 2, 3, 2, 3, 3, 2, 4, 3, 2, 3, 4, 2, 2, 3, 4, + 3, 3, 4, 0, 0, 3, 1, 0, 3, 2, 0, 3, 3, 0, 3, + 4, 0, 3, 0, 4, 3, 0, 0, 4, 1, 0, 4, 0, 1, 3, + 1, 1, 3, 2, 1, 3, 3, 1, 3, 4, 1, 3, 1, 4, 3, + 0, 1, 4, 1, 1, 4, 0, 2, 3, 1, 2, 3, 2, 2, 3, + 3, 2, 3, 4, 2, 3, 2, 4, 3, 0, 2, 4, 1, 2, 4, + 0, 3, 3, 1, 3, 3, 2, 3, 3, 3, 3, 3, 4, 3, 3, + 3, 4, 3, 0, 3, 4, 1, 3, 4 + }; + } +} |