summaryrefslogtreecommitdiffstats
path: root/src/video_core/textures/astc.cpp
diff options
context:
space:
mode:
authorReinUsesLisp <reinuseslisp@airmail.cc>2020-03-14 02:49:28 +0100
committerReinUsesLisp <reinuseslisp@airmail.cc>2020-03-14 02:49:28 +0100
commite183820956b528f64bb5d6e05052752bf437d3a1 (patch)
treee03afbae2cb53e1bcbb843998056a13bbf9dcd0e /src/video_core/textures/astc.cpp
parentastc: Make IntegerEncodedValue constructor constexpr (diff)
downloadyuzu-e183820956b528f64bb5d6e05052752bf437d3a1.tar
yuzu-e183820956b528f64bb5d6e05052752bf437d3a1.tar.gz
yuzu-e183820956b528f64bb5d6e05052752bf437d3a1.tar.bz2
yuzu-e183820956b528f64bb5d6e05052752bf437d3a1.tar.lz
yuzu-e183820956b528f64bb5d6e05052752bf437d3a1.tar.xz
yuzu-e183820956b528f64bb5d6e05052752bf437d3a1.tar.zst
yuzu-e183820956b528f64bb5d6e05052752bf437d3a1.zip
Diffstat (limited to 'src/video_core/textures/astc.cpp')
-rw-r--r--src/video_core/textures/astc.cpp389
1 files changed, 177 insertions, 212 deletions
diff --git a/src/video_core/textures/astc.cpp b/src/video_core/textures/astc.cpp
index f4513998c..2d948ee62 100644
--- a/src/video_core/textures/astc.cpp
+++ b/src/video_core/textures/astc.cpp
@@ -160,232 +160,198 @@ private:
enum class IntegerEncoding { JustBits, Qus32, Trit };
-class IntegerEncodedValue {
-private:
- IntegerEncoding m_Encoding{};
- u32 m_NumBits = 0;
- u32 m_BitValue = 0;
- union {
- u32 m_Qus32Value = 0;
- u32 m_TritValue;
- };
-
-public:
- constexpr IntegerEncodedValue() = default;
- constexpr IntegerEncodedValue(IntegerEncoding encoding, u32 numBits)
- : m_Encoding(encoding), m_NumBits(numBits) {}
-
- IntegerEncoding GetEncoding() const {
- return m_Encoding;
- }
- u32 BaseBitLength() const {
- return m_NumBits;
- }
-
- u32 GetBitValue() const {
- return m_BitValue;
- }
- void SetBitValue(u32 val) {
- m_BitValue = val;
- }
-
- u32 GetTritValue() const {
- return m_TritValue;
- }
- void SetTritValue(u32 val) {
- m_TritValue = val;
- }
-
- u32 GetQus32Value() const {
- return m_Qus32Value;
- }
- void SetQus32Value(u32 val) {
- m_Qus32Value = val;
- }
+struct IntegerEncodedValue {
+ constexpr IntegerEncodedValue(IntegerEncoding encoding_, u32 num_bits_)
+ : encoding{encoding_}, num_bits{num_bits_} {}
- bool MatchesEncoding(const IntegerEncodedValue& other) const {
- return m_Encoding == other.m_Encoding && m_NumBits == other.m_NumBits;
+ constexpr bool MatchesEncoding(const IntegerEncodedValue& other) const {
+ return encoding == other.encoding && num_bits == other.num_bits;
}
// Returns the number of bits required to encode nVals values.
u32 GetBitLength(u32 nVals) const {
- u32 totalBits = m_NumBits * nVals;
- if (m_Encoding == IntegerEncoding::Trit) {
+ u32 totalBits = num_bits * nVals;
+ if (encoding == IntegerEncoding::Trit) {
totalBits += (nVals * 8 + 4) / 5;
- } else if (m_Encoding == IntegerEncoding::Qus32) {
+ } else if (encoding == IntegerEncoding::Qus32) {
totalBits += (nVals * 7 + 2) / 3;
}
return totalBits;
}
- // Returns a new instance of this struct that corresponds to the
- // can take no more than maxval values
- static IntegerEncodedValue CreateEncoding(u32 maxVal) {
- while (maxVal > 0) {
- u32 check = maxVal + 1;
+ IntegerEncoding encoding;
+ u32 num_bits;
+ u32 bit_value = 0;
+ union {
+ u32 qus32_value = 0;
+ u32 trit_value;
+ };
+};
- // Is maxVal a power of two?
- if (!(check & (check - 1))) {
- return IntegerEncodedValue(IntegerEncoding::JustBits, Popcnt(maxVal));
- }
+static void DecodeTritBlock(InputBitStream& bits, std::vector<IntegerEncodedValue>& result,
+ u32 nBitsPerValue) {
+ // Implement the algorithm in section C.2.12
+ u32 m[5];
+ u32 t[5];
+ u32 T;
+
+ // Read the trit encoded block according to
+ // table C.2.14
+ m[0] = bits.ReadBits(nBitsPerValue);
+ T = bits.ReadBits(2);
+ m[1] = bits.ReadBits(nBitsPerValue);
+ T |= bits.ReadBits(2) << 2;
+ m[2] = bits.ReadBits(nBitsPerValue);
+ T |= bits.ReadBit() << 4;
+ m[3] = bits.ReadBits(nBitsPerValue);
+ T |= bits.ReadBits(2) << 5;
+ m[4] = bits.ReadBits(nBitsPerValue);
+ T |= bits.ReadBit() << 7;
+
+ u32 C = 0;
+
+ Bits<u32> Tb(T);
+ if (Tb(2, 4) == 7) {
+ C = (Tb(5, 7) << 2) | Tb(0, 1);
+ t[4] = t[3] = 2;
+ } else {
+ C = Tb(0, 4);
+ if (Tb(5, 6) == 3) {
+ t[4] = 2;
+ t[3] = Tb[7];
+ } else {
+ t[4] = Tb[7];
+ t[3] = Tb(5, 6);
+ }
+ }
- // Is maxVal of the type 3*2^n - 1?
- if ((check % 3 == 0) && !((check / 3) & ((check / 3) - 1))) {
- return IntegerEncodedValue(IntegerEncoding::Trit, Popcnt(check / 3 - 1));
- }
+ Bits<u32> Cb(C);
+ if (Cb(0, 1) == 3) {
+ t[2] = 2;
+ t[1] = Cb[4];
+ t[0] = (Cb[3] << 1) | (Cb[2] & ~Cb[3]);
+ } else if (Cb(2, 3) == 3) {
+ t[2] = 2;
+ t[1] = 2;
+ t[0] = Cb(0, 1);
+ } else {
+ t[2] = Cb[4];
+ t[1] = Cb(2, 3);
+ t[0] = (Cb[1] << 1) | (Cb[0] & ~Cb[1]);
+ }
- // Is maxVal of the type 5*2^n - 1?
- if ((check % 5 == 0) && !((check / 5) & ((check / 5) - 1))) {
- return IntegerEncodedValue(IntegerEncoding::Qus32, Popcnt(check / 5 - 1));
- }
+ for (std::size_t i = 0; i < 5; ++i) {
+ IntegerEncodedValue& val = result.emplace_back(IntegerEncoding::Trit, nBitsPerValue);
+ val.bit_value = m[i];
+ val.trit_value = t[i];
+ }
+}
- // Apparently it can't be represented with a bounded s32eger sequence...
- // just iterate.
- maxVal--;
+static void DecodeQus32Block(InputBitStream& bits, std::vector<IntegerEncodedValue>& result,
+ u32 nBitsPerValue) {
+ // Implement the algorithm in section C.2.12
+ u32 m[3];
+ u32 q[3];
+ u32 Q;
+
+ // Read the trit encoded block according to
+ // table C.2.15
+ m[0] = bits.ReadBits(nBitsPerValue);
+ Q = bits.ReadBits(3);
+ m[1] = bits.ReadBits(nBitsPerValue);
+ Q |= bits.ReadBits(2) << 3;
+ m[2] = bits.ReadBits(nBitsPerValue);
+ Q |= bits.ReadBits(2) << 5;
+
+ Bits<u32> Qb(Q);
+ if (Qb(1, 2) == 3 && Qb(5, 6) == 0) {
+ q[0] = q[1] = 4;
+ q[2] = (Qb[0] << 2) | ((Qb[4] & ~Qb[0]) << 1) | (Qb[3] & ~Qb[0]);
+ } else {
+ u32 C = 0;
+ if (Qb(1, 2) == 3) {
+ q[2] = 4;
+ C = (Qb(3, 4) << 3) | ((~Qb(5, 6) & 3) << 1) | Qb[0];
+ } else {
+ q[2] = Qb(5, 6);
+ C = Qb(0, 4);
}
- return IntegerEncodedValue(IntegerEncoding::JustBits, 0);
- }
-
- // Fills result with the values that are encoded in the given
- // bitstream. We must know beforehand what the maximum possible
- // value is, and how many values we're decoding.
- static void DecodeIntegerSequence(std::vector<IntegerEncodedValue>& result,
- InputBitStream& bits, u32 maxRange, u32 nValues) {
- // Determine encoding parameters
- IntegerEncodedValue val = IntegerEncodedValue::CreateEncoding(maxRange);
-
- // Start decoding
- u32 nValsDecoded = 0;
- while (nValsDecoded < nValues) {
- switch (val.GetEncoding()) {
- case IntegerEncoding::Qus32:
- DecodeQus32Block(bits, result, val.BaseBitLength());
- nValsDecoded += 3;
- break;
-
- case IntegerEncoding::Trit:
- DecodeTritBlock(bits, result, val.BaseBitLength());
- nValsDecoded += 5;
- break;
- case IntegerEncoding::JustBits:
- val.SetBitValue(bits.ReadBits(val.BaseBitLength()));
- result.push_back(val);
- nValsDecoded++;
- break;
- }
+ Bits<u32> Cb(C);
+ if (Cb(0, 2) == 5) {
+ q[1] = 4;
+ q[0] = Cb(3, 4);
+ } else {
+ q[1] = Cb(3, 4);
+ q[0] = Cb(0, 2);
}
}
-private:
- static void DecodeTritBlock(InputBitStream& bits, std::vector<IntegerEncodedValue>& result,
- u32 nBitsPerValue) {
- // Implement the algorithm in section C.2.12
- u32 m[5];
- u32 t[5];
- u32 T;
-
- // Read the trit encoded block according to
- // table C.2.14
- m[0] = bits.ReadBits(nBitsPerValue);
- T = bits.ReadBits(2);
- m[1] = bits.ReadBits(nBitsPerValue);
- T |= bits.ReadBits(2) << 2;
- m[2] = bits.ReadBits(nBitsPerValue);
- T |= bits.ReadBit() << 4;
- m[3] = bits.ReadBits(nBitsPerValue);
- T |= bits.ReadBits(2) << 5;
- m[4] = bits.ReadBits(nBitsPerValue);
- T |= bits.ReadBit() << 7;
+ for (std::size_t i = 0; i < 3; ++i) {
+ IntegerEncodedValue& val = result.emplace_back(IntegerEncoding::Qus32, nBitsPerValue);
+ val.bit_value = m[i];
+ val.qus32_value = q[i];
+ }
+}
- u32 C = 0;
+// Returns a new instance of this struct that corresponds to the
+// can take no more than maxval values
+static IntegerEncodedValue CreateEncoding(u32 maxVal) {
+ while (maxVal > 0) {
+ u32 check = maxVal + 1;
- Bits<u32> Tb(T);
- if (Tb(2, 4) == 7) {
- C = (Tb(5, 7) << 2) | Tb(0, 1);
- t[4] = t[3] = 2;
- } else {
- C = Tb(0, 4);
- if (Tb(5, 6) == 3) {
- t[4] = 2;
- t[3] = Tb[7];
- } else {
- t[4] = Tb[7];
- t[3] = Tb(5, 6);
- }
+ // Is maxVal a power of two?
+ if (!(check & (check - 1))) {
+ return IntegerEncodedValue(IntegerEncoding::JustBits, Popcnt(maxVal));
}
- Bits<u32> Cb(C);
- if (Cb(0, 1) == 3) {
- t[2] = 2;
- t[1] = Cb[4];
- t[0] = (Cb[3] << 1) | (Cb[2] & ~Cb[3]);
- } else if (Cb(2, 3) == 3) {
- t[2] = 2;
- t[1] = 2;
- t[0] = Cb(0, 1);
- } else {
- t[2] = Cb[4];
- t[1] = Cb(2, 3);
- t[0] = (Cb[1] << 1) | (Cb[0] & ~Cb[1]);
+ // Is maxVal of the type 3*2^n - 1?
+ if ((check % 3 == 0) && !((check / 3) & ((check / 3) - 1))) {
+ return IntegerEncodedValue(IntegerEncoding::Trit, Popcnt(check / 3 - 1));
}
- for (u32 i = 0; i < 5; i++) {
- IntegerEncodedValue val(IntegerEncoding::Trit, nBitsPerValue);
- val.SetBitValue(m[i]);
- val.SetTritValue(t[i]);
- result.push_back(val);
+ // Is maxVal of the type 5*2^n - 1?
+ if ((check % 5 == 0) && !((check / 5) & ((check / 5) - 1))) {
+ return IntegerEncodedValue(IntegerEncoding::Qus32, Popcnt(check / 5 - 1));
}
+
+ // Apparently it can't be represented with a bounded s32eger sequence...
+ // just iterate.
+ maxVal--;
}
+ return IntegerEncodedValue(IntegerEncoding::JustBits, 0);
+}
- static void DecodeQus32Block(InputBitStream& bits, std::vector<IntegerEncodedValue>& result,
- u32 nBitsPerValue) {
- // Implement the algorithm in section C.2.12
- u32 m[3];
- u32 q[3];
- u32 Q;
-
- // Read the trit encoded block according to
- // table C.2.15
- m[0] = bits.ReadBits(nBitsPerValue);
- Q = bits.ReadBits(3);
- m[1] = bits.ReadBits(nBitsPerValue);
- Q |= bits.ReadBits(2) << 3;
- m[2] = bits.ReadBits(nBitsPerValue);
- Q |= bits.ReadBits(2) << 5;
-
- Bits<u32> Qb(Q);
- if (Qb(1, 2) == 3 && Qb(5, 6) == 0) {
- q[0] = q[1] = 4;
- q[2] = (Qb[0] << 2) | ((Qb[4] & ~Qb[0]) << 1) | (Qb[3] & ~Qb[0]);
- } else {
- u32 C = 0;
- if (Qb(1, 2) == 3) {
- q[2] = 4;
- C = (Qb(3, 4) << 3) | ((~Qb(5, 6) & 3) << 1) | Qb[0];
- } else {
- q[2] = Qb(5, 6);
- C = Qb(0, 4);
- }
+// Fills result with the values that are encoded in the given
+// bitstream. We must know beforehand what the maximum possible
+// value is, and how many values we're decoding.
+static void DecodeIntegerSequence(std::vector<IntegerEncodedValue>& result, InputBitStream& bits,
+ u32 maxRange, u32 nValues) {
+ // Determine encoding parameters
+ IntegerEncodedValue val = CreateEncoding(maxRange);
+
+ // Start decoding
+ u32 nValsDecoded = 0;
+ while (nValsDecoded < nValues) {
+ switch (val.encoding) {
+ case IntegerEncoding::Qus32:
+ DecodeQus32Block(bits, result, val.num_bits);
+ nValsDecoded += 3;
+ break;
- Bits<u32> Cb(C);
- if (Cb(0, 2) == 5) {
- q[1] = 4;
- q[0] = Cb(3, 4);
- } else {
- q[1] = Cb(3, 4);
- q[0] = Cb(0, 2);
- }
- }
+ case IntegerEncoding::Trit:
+ DecodeTritBlock(bits, result, val.num_bits);
+ nValsDecoded += 5;
+ break;
- for (u32 i = 0; i < 3; i++) {
- IntegerEncodedValue val(IntegerEncoding::Qus32, nBitsPerValue);
- val.m_BitValue = m[i];
- val.m_Qus32Value = q[i];
+ case IntegerEncoding::JustBits:
+ val.bit_value = bits.ReadBits(val.num_bits);
result.push_back(val);
+ nValsDecoded++;
+ break;
}
}
-};
+}
namespace ASTCC {
@@ -405,7 +371,7 @@ struct TexelWeightParams {
nIdxs *= 2;
}
- return IntegerEncodedValue::CreateEncoding(m_MaxWeight).GetBitLength(nIdxs);
+ return CreateEncoding(m_MaxWeight).GetBitLength(nIdxs);
}
u32 GetNumWeightValues() const {
@@ -814,12 +780,12 @@ static void DecodeColorValues(u32* out, u8* data, const u32* modes, const u32 nP
// figure out the max value for each of them...
u32 range = 256;
while (--range > 0) {
- IntegerEncodedValue val = IntegerEncodedValue::CreateEncoding(range);
+ IntegerEncodedValue val = CreateEncoding(range);
u32 bitLength = val.GetBitLength(nValues);
if (bitLength <= nBitsForColorData) {
// Find the smallest possible range that matches the given encoding
while (--range > 0) {
- IntegerEncodedValue newval = IntegerEncodedValue::CreateEncoding(range);
+ IntegerEncodedValue newval = CreateEncoding(range);
if (!newval.MatchesEncoding(val)) {
break;
}
@@ -834,7 +800,7 @@ static void DecodeColorValues(u32* out, u8* data, const u32* modes, const u32 nP
// We now have enough to decode our s32eger sequence.
std::vector<IntegerEncodedValue> decodedColorValues;
InputBitStream colorStream(data);
- IntegerEncodedValue::DecodeIntegerSequence(decodedColorValues, colorStream, range, nValues);
+ DecodeIntegerSequence(decodedColorValues, colorStream, range, nValues);
// Once we have the decoded values, we need to dequantize them to the 0-255 range
// This procedure is outlined in ASTC spec C.2.13
@@ -846,8 +812,8 @@ static void DecodeColorValues(u32* out, u8* data, const u32* modes, const u32 nP
}
const IntegerEncodedValue& val = *itr;
- u32 bitlen = val.BaseBitLength();
- u32 bitval = val.GetBitValue();
+ u32 bitlen = val.num_bits;
+ u32 bitval = val.bit_value;
assert(bitlen >= 1);
@@ -855,7 +821,7 @@ static void DecodeColorValues(u32* out, u8* data, const u32* modes, const u32 nP
// A is just the lsb replicated 9 times.
A = Replicate(bitval & 1, 1, 9);
- switch (val.GetEncoding()) {
+ switch (val.encoding) {
// Replicate bits
case IntegerEncoding::JustBits:
out[outIdx++] = Replicate(bitval, bitlen, 8);
@@ -864,7 +830,7 @@ static void DecodeColorValues(u32* out, u8* data, const u32* modes, const u32 nP
// Use algorithm in C.2.13
case IntegerEncoding::Trit: {
- D = val.GetTritValue();
+ D = val.trit_value;
switch (bitlen) {
case 1: {
@@ -915,7 +881,7 @@ static void DecodeColorValues(u32* out, u8* data, const u32* modes, const u32 nP
case IntegerEncoding::Qus32: {
- D = val.GetQus32Value();
+ D = val.qus32_value;
switch (bitlen) {
case 1: {
@@ -956,9 +922,9 @@ static void DecodeColorValues(u32* out, u8* data, const u32* modes, const u32 nP
} // switch(bitlen)
} // case IntegerEncoding::Qus32
break;
- } // switch(val.GetEncoding())
+ } // switch(val.encoding)
- if (val.GetEncoding() != IntegerEncoding::JustBits) {
+ if (val.encoding != IntegerEncoding::JustBits) {
u32 T = D * C + B;
T ^= A;
T = (A & 0x80) | (T >> 2);
@@ -973,20 +939,20 @@ static void DecodeColorValues(u32* out, u8* data, const u32* modes, const u32 nP
}
static u32 UnquantizeTexelWeight(const IntegerEncodedValue& val) {
- u32 bitval = val.GetBitValue();
- u32 bitlen = val.BaseBitLength();
+ u32 bitval = val.bit_value;
+ u32 bitlen = val.num_bits;
u32 A = Replicate(bitval & 1, 1, 7);
u32 B = 0, C = 0, D = 0;
u32 result = 0;
- switch (val.GetEncoding()) {
+ switch (val.encoding) {
case IntegerEncoding::JustBits:
result = Replicate(bitval, bitlen, 6);
break;
case IntegerEncoding::Trit: {
- D = val.GetTritValue();
+ D = val.trit_value;
assert(D < 3);
switch (bitlen) {
@@ -1018,7 +984,7 @@ static u32 UnquantizeTexelWeight(const IntegerEncodedValue& val) {
} break;
case IntegerEncoding::Qus32: {
- D = val.GetQus32Value();
+ D = val.qus32_value;
assert(D < 5);
switch (bitlen) {
@@ -1044,7 +1010,7 @@ static u32 UnquantizeTexelWeight(const IntegerEncodedValue& val) {
} break;
}
- if (val.GetEncoding() != IntegerEncoding::JustBits && bitlen > 0) {
+ if (val.encoding != IntegerEncoding::JustBits && bitlen > 0) {
// Decode the value...
result = D * C + B;
result ^= A;
@@ -1562,9 +1528,8 @@ static void DecompressBlock(const u8 inBuf[16], const u32 blockWidth, const u32
std::vector<IntegerEncodedValue> texelWeightValues;
InputBitStream weightStream(texelWeightData);
- IntegerEncodedValue::DecodeIntegerSequence(texelWeightValues, weightStream,
- weightParams.m_MaxWeight,
- weightParams.GetNumWeightValues());
+ DecodeIntegerSequence(texelWeightValues, weightStream, weightParams.m_MaxWeight,
+ weightParams.GetNumWeightValues());
// Blocks can be at most 12x12, so we can have as many as 144 weights
u32 weights[2][144];