Skip to content

Commit f2da43b

Browse files
committed
BitStream optimizations
1 parent 128eb58 commit f2da43b

File tree

3 files changed

+76
-65
lines changed

3 files changed

+76
-65
lines changed

AssetRipper.TextureDecoder/Bc/BcHelpers.cs

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,9 @@ public static void DecompressBc5(ReadOnlySpan<byte> compressedBlock, Span<byte>
3434

3535
public static void DecompressBc6h(ReadOnlySpan<byte> compressedBlock, Span<byte> decompressedBlock, int destinationPitch, bool isSigned)
3636
{
37-
BitStream bstream = new()
38-
{
39-
low = BinaryPrimitives.ReadUInt64LittleEndian(compressedBlock),
40-
high = BinaryPrimitives.ReadUInt64LittleEndian(compressedBlock.Slice(sizeof(ulong)))
41-
};
37+
BitStream bstream = new(
38+
BinaryPrimitives.ReadUInt64LittleEndian(compressedBlock),
39+
BinaryPrimitives.ReadUInt64LittleEndian(compressedBlock.Slice(sizeof(ulong))));
4240
Span<uint> r = stackalloc uint[4]; // wxyz
4341
Span<uint> g = stackalloc uint[4];
4442
Span<uint> b = stackalloc uint[4];
@@ -559,11 +557,9 @@ static uint ReadBc6hModeBits(ref BitStream bstream)
559557

560558
public static void DecompressBc7(ReadOnlySpan<byte> compressedBlock, Span<byte> decompressedBlock, int destinationPitch)
561559
{
562-
BitStream bstream = new()
563-
{
564-
low = BinaryPrimitives.ReadUInt64LittleEndian(compressedBlock),
565-
high = BinaryPrimitives.ReadUInt64LittleEndian(compressedBlock.Slice(sizeof(ulong)))
566-
};
560+
BitStream bstream = new(
561+
BinaryPrimitives.ReadUInt64LittleEndian(compressedBlock),
562+
BinaryPrimitives.ReadUInt64LittleEndian(compressedBlock.Slice(sizeof(ulong))));
567563
Span2D<uint> endpoints = new(stackalloc uint[6 * 4], 6, 4);
568564
Span2D<int> indices = new(stackalloc int[4 * 4], 4, 4);
569565

@@ -1081,14 +1077,4 @@ public static void SwapValues(ref uint a, ref uint b)
10811077
{
10821078
(a, b) = (b, a);
10831079
}
1084-
1085-
private static uint ToUnsigned(this int value)
1086-
{
1087-
return unchecked((uint)value);
1088-
}
1089-
1090-
private static int ToSigned(this uint value)
1091-
{
1092-
return unchecked((int)value);
1093-
}
10941080
}
Lines changed: 46 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,46 @@
1-
namespace AssetRipper.TextureDecoder.Bc;
2-
3-
internal struct BitStream
4-
{
5-
public ulong low;
6-
public ulong high;
7-
8-
public uint ReadBits(int numBits)
9-
{
10-
uint mask = (1u << numBits) - 1u;
11-
// Read the low N bits
12-
uint bits = unchecked((uint)(this.low & mask));
13-
14-
this.low >>= numBits;
15-
// Put the low N bits of "high" into the high 64-N bits of "low".
16-
this.low |= (this.high & mask) << ((sizeof(ulong) * 8) - numBits);
17-
this.high >>= numBits;
18-
19-
return bits;
20-
}
21-
22-
public uint ReadBit()
23-
{
24-
return this.ReadBits(1);
25-
}
26-
27-
/// <summary>
28-
/// Reversed bits pulling, used in BC6H decoding
29-
/// </summary>
30-
/// <param name="numBits"></param>
31-
/// <returns></returns>
32-
public uint ReadBitsReversed(int numBits)
33-
{
34-
uint bits = this.ReadBits(numBits);
35-
// Reverse the bits.
36-
uint result = 0;
37-
while (numBits-- != 0)
38-
{
39-
result <<= 1;
40-
result |= bits & 1;
41-
bits >>= 1;
42-
}
43-
return result;
44-
}
45-
}
1+
namespace AssetRipper.TextureDecoder.Bc;
2+
3+
internal ref struct BitStream
4+
{
5+
private ulong low;
6+
private ulong high;
7+
8+
public BitStream(ulong low, ulong high)
9+
{
10+
this.low = low;
11+
this.high = high;
12+
}
13+
14+
public uint ReadBits(int numBits)
15+
{
16+
uint mask = (1u << numBits) - 1u;
17+
// Read the low N bits
18+
uint bits = unchecked((uint)(this.low & mask));
19+
20+
this.low >>= numBits;
21+
// Put the low N bits of "high" into the high 64-N bits of "low".
22+
this.low |= (this.high & mask) << ((sizeof(ulong) * 8) - numBits);
23+
this.high >>= numBits;
24+
25+
return bits;
26+
}
27+
28+
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
29+
public uint ReadBit()
30+
{
31+
return this.ReadBits(1);
32+
}
33+
34+
/// <summary>
35+
/// Reversed bits pulling, used in BC6H decoding
36+
/// </summary>
37+
/// <param name="numBits"></param>
38+
/// <returns></returns>
39+
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
40+
public uint ReadBitsReversed(int numBits)
41+
{
42+
uint bits = this.ReadBits(numBits);
43+
// Reverse the bits.
44+
return bits.ReverseBits() >> (32 - numBits);
45+
}
46+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
namespace AssetRipper.TextureDecoder.Bc;
2+
3+
internal static class NumericExtensions
4+
{
5+
public static uint ReverseBits(this uint n)
6+
{
7+
n = (n >> 1) & 0x55555555 | (n << 1) & 0xAAAAAAAA;
8+
n = (n >> 2) & 0x33333333 | (n << 2) & 0xCCCCCCCC;
9+
n = (n >> 4) & 0x0F0F0F0F | (n << 4) & 0xF0F0F0F0;
10+
n = (n >> 8) & 0x00FF00FF | (n << 8) & 0xFF00FF00;
11+
n = (n >> 16) & 0x0000FFFF | (n << 16) & 0xFFFF0000;
12+
return n;
13+
}
14+
15+
public static uint ToUnsigned(this int value)
16+
{
17+
return unchecked((uint)value);
18+
}
19+
20+
public static int ToSigned(this uint value)
21+
{
22+
return unchecked((int)value);
23+
}
24+
}

0 commit comments

Comments
 (0)