summaryrefslogtreecommitdiff
path: root/src/video_core/textures/astc.h
diff options
context:
space:
mode:
authorGravatar ameerj2021-03-25 16:53:51 -0400
committerGravatar ameerj2021-03-25 16:53:51 -0400
commit2f83d9a61bca42d9ef24074beb2b11b19bd4cecd (patch)
tree514e40eb750280c2e3025f9301befb6f8c9b46e9 /src/video_core/textures/astc.h
parentastc_decoder: Reimplement Layers (diff)
downloadyuzu-2f83d9a61bca42d9ef24074beb2b11b19bd4cecd.tar.gz
yuzu-2f83d9a61bca42d9ef24074beb2b11b19bd4cecd.tar.xz
yuzu-2f83d9a61bca42d9ef24074beb2b11b19bd4cecd.zip
astc_decoder: Refactor for style and more efficient memory use
Diffstat (limited to 'src/video_core/textures/astc.h')
-rw-r--r--src/video_core/textures/astc.h174
1 files changed, 51 insertions, 123 deletions
diff --git a/src/video_core/textures/astc.h b/src/video_core/textures/astc.h
index bc8bddaec..c1c73fda5 100644
--- a/src/video_core/textures/astc.h
+++ b/src/video_core/textures/astc.h
@@ -4,20 +4,12 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <cstdint> 7#include <bit>
8#include "common/common_types.h"
8 9
9namespace Tegra::Texture::ASTC { 10namespace Tegra::Texture::ASTC {
10 11
11/// Count the number of bits set in a number. 12enum class IntegerEncoding { JustBits, Quint, Trit };
12constexpr u32 Popcnt(u32 n) {
13 u32 c = 0;
14 for (; n; c++) {
15 n &= n - 1;
16 }
17 return c;
18}
19
20enum class IntegerEncoding { JustBits, Qus32, Trit };
21 13
22struct IntegerEncodedValue { 14struct IntegerEncodedValue {
23 constexpr IntegerEncodedValue() = default; 15 constexpr IntegerEncodedValue() = default;
@@ -29,55 +21,55 @@ struct IntegerEncodedValue {
29 return encoding == other.encoding && num_bits == other.num_bits; 21 return encoding == other.encoding && num_bits == other.num_bits;
30 } 22 }
31 23
32 // Returns the number of bits required to encode nVals values. 24 // Returns the number of bits required to encode num_vals values.
33 u32 GetBitLength(u32 nVals) const { 25 u32 GetBitLength(u32 num_vals) const {
34 u32 totalBits = num_bits * nVals; 26 u32 total_bits = num_bits * num_vals;
35 if (encoding == IntegerEncoding::Trit) { 27 if (encoding == IntegerEncoding::Trit) {
36 totalBits += (nVals * 8 + 4) / 5; 28 total_bits += (num_vals * 8 + 4) / 5;
37 } else if (encoding == IntegerEncoding::Qus32) { 29 } else if (encoding == IntegerEncoding::Quint) {
38 totalBits += (nVals * 7 + 2) / 3; 30 total_bits += (num_vals * 7 + 2) / 3;
39 } 31 }
40 return totalBits; 32 return total_bits;
41 } 33 }
42 34
43 IntegerEncoding encoding{}; 35 IntegerEncoding encoding{};
44 u32 num_bits = 0; 36 u32 num_bits = 0;
45 u32 bit_value = 0; 37 u32 bit_value = 0;
46 union { 38 union {
47 u32 qus32_value = 0; 39 u32 quint_value = 0;
48 u32 trit_value; 40 u32 trit_value;
49 }; 41 };
50}; 42};
51 43
52// Returns a new instance of this struct that corresponds to the 44// Returns a new instance of this struct that corresponds to the
53// can take no more than maxval values 45// can take no more than mav_value values
54static constexpr IntegerEncodedValue CreateEncoding(u32 maxVal) { 46constexpr IntegerEncodedValue CreateEncoding(u32 mav_value) {
55 while (maxVal > 0) { 47 while (mav_value > 0) {
56 u32 check = maxVal + 1; 48 u32 check = mav_value + 1;
57 49
58 // Is maxVal a power of two? 50 // Is mav_value a power of two?
59 if (!(check & (check - 1))) { 51 if (!(check & (check - 1))) {
60 return IntegerEncodedValue(IntegerEncoding::JustBits, Popcnt(maxVal)); 52 return IntegerEncodedValue(IntegerEncoding::JustBits, std::popcount(mav_value));
61 } 53 }
62 54
63 // Is maxVal of the type 3*2^n - 1? 55 // Is mav_value of the type 3*2^n - 1?
64 if ((check % 3 == 0) && !((check / 3) & ((check / 3) - 1))) { 56 if ((check % 3 == 0) && !((check / 3) & ((check / 3) - 1))) {
65 return IntegerEncodedValue(IntegerEncoding::Trit, Popcnt(check / 3 - 1)); 57 return IntegerEncodedValue(IntegerEncoding::Trit, std::popcount(check / 3 - 1));
66 } 58 }
67 59
68 // Is maxVal of the type 5*2^n - 1? 60 // Is mav_value of the type 5*2^n - 1?
69 if ((check % 5 == 0) && !((check / 5) & ((check / 5) - 1))) { 61 if ((check % 5 == 0) && !((check / 5) & ((check / 5) - 1))) {
70 return IntegerEncodedValue(IntegerEncoding::Qus32, Popcnt(check / 5 - 1)); 62 return IntegerEncodedValue(IntegerEncoding::Quint, std::popcount(check / 5 - 1));
71 } 63 }
72 64
73 // Apparently it can't be represented with a bounded integer sequence... 65 // Apparently it can't be represented with a bounded integer sequence...
74 // just iterate. 66 // just iterate.
75 maxVal--; 67 mav_value--;
76 } 68 }
77 return IntegerEncodedValue(IntegerEncoding::JustBits, 0); 69 return IntegerEncodedValue(IntegerEncoding::JustBits, 0);
78} 70}
79 71
80static constexpr std::array<IntegerEncodedValue, 256> MakeEncodedValues() { 72constexpr std::array<IntegerEncodedValue, 256> MakeEncodedValues() {
81 std::array<IntegerEncodedValue, 256> encodings{}; 73 std::array<IntegerEncodedValue, 256> encodings{};
82 for (std::size_t i = 0; i < encodings.size(); ++i) { 74 for (std::size_t i = 0; i < encodings.size(); ++i) {
83 encodings[i] = CreateEncoding(static_cast<u32>(i)); 75 encodings[i] = CreateEncoding(static_cast<u32>(i));
@@ -85,41 +77,38 @@ static constexpr std::array<IntegerEncodedValue, 256> MakeEncodedValues() {
85 return encodings; 77 return encodings;
86} 78}
87 79
88static constexpr std::array<IntegerEncodedValue, 256> EncodingsValues = MakeEncodedValues(); 80constexpr std::array<IntegerEncodedValue, 256> EncodingsValues = MakeEncodedValues();
89 81
90// Replicates low numBits such that [(toBit - 1):(toBit - 1 - fromBit)] 82// Replicates low num_bits such that [(to_bit - 1):(to_bit - 1 - from_bit)]
91// is the same as [(numBits - 1):0] and repeats all the way down. 83// is the same as [(num_bits - 1):0] and repeats all the way down.
92template <typename IntType> 84template <typename IntType>
93static constexpr IntType Replicate(IntType val, u32 numBits, u32 toBit) { 85constexpr IntType Replicate(IntType val, u32 num_bits, u32 to_bit) {
94 if (numBits == 0) { 86 if (num_bits == 0 || to_bit == 0) {
95 return 0;
96 }
97 if (toBit == 0) {
98 return 0; 87 return 0;
99 } 88 }
100 const IntType v = val & static_cast<IntType>((1 << numBits) - 1); 89 const IntType v = val & static_cast<IntType>((1 << num_bits) - 1);
101 IntType res = v; 90 IntType res = v;
102 u32 reslen = numBits; 91 u32 reslen = num_bits;
103 while (reslen < toBit) { 92 while (reslen < to_bit) {
104 u32 comp = 0; 93 u32 comp = 0;
105 if (numBits > toBit - reslen) { 94 if (num_bits > to_bit - reslen) {
106 u32 newshift = toBit - reslen; 95 u32 newshift = to_bit - reslen;
107 comp = numBits - newshift; 96 comp = num_bits - newshift;
108 numBits = newshift; 97 num_bits = newshift;
109 } 98 }
110 res = static_cast<IntType>(res << numBits); 99 res = static_cast<IntType>(res << num_bits);
111 res = static_cast<IntType>(res | (v >> comp)); 100 res = static_cast<IntType>(res | (v >> comp));
112 reslen += numBits; 101 reslen += num_bits;
113 } 102 }
114 return res; 103 return res;
115} 104}
116 105
117static constexpr std::size_t NumReplicateEntries(u32 num_bits) { 106constexpr std::size_t NumReplicateEntries(u32 num_bits) {
118 return std::size_t(1) << num_bits; 107 return std::size_t(1) << num_bits;
119} 108}
120 109
121template <typename IntType, u32 num_bits, u32 to_bit> 110template <typename IntType, u32 num_bits, u32 to_bit>
122static constexpr auto MakeReplicateTable() { 111constexpr auto MakeReplicateTable() {
123 std::array<IntType, NumReplicateEntries(num_bits)> table{}; 112 std::array<IntType, NumReplicateEntries(num_bits)> table{};
124 for (IntType value = 0; value < static_cast<IntType>(std::size(table)); ++value) { 113 for (IntType value = 0; value < static_cast<IntType>(std::size(table)); ++value) {
125 table[value] = Replicate(value, num_bits, to_bit); 114 table[value] = Replicate(value, num_bits, to_bit);
@@ -127,78 +116,17 @@ static constexpr auto MakeReplicateTable() {
127 return table; 116 return table;
128} 117}
129 118
130static constexpr auto REPLICATE_BYTE_TO_16_TABLE = MakeReplicateTable<u32, 8, 16>(); 119constexpr auto REPLICATE_BYTE_TO_16_TABLE = MakeReplicateTable<u32, 8, 16>();
131static constexpr u32 ReplicateByteTo16(std::size_t value) { 120constexpr auto REPLICATE_6_BIT_TO_8_TABLE = MakeReplicateTable<u32, 6, 8>();
132 return REPLICATE_BYTE_TO_16_TABLE[value]; 121constexpr auto REPLICATE_7_BIT_TO_8_TABLE = MakeReplicateTable<u32, 7, 8>();
133} 122constexpr auto REPLICATE_8_BIT_TO_8_TABLE = MakeReplicateTable<u32, 8, 8>();
134 123
135static constexpr auto REPLICATE_BIT_TO_7_TABLE = MakeReplicateTable<u32, 1, 7>(); 124struct AstcBufferData {
136static constexpr u32 ReplicateBitTo7(std::size_t value) { 125 decltype(EncodingsValues) encoding_values = EncodingsValues;
137 return REPLICATE_BIT_TO_7_TABLE[value]; 126 decltype(REPLICATE_6_BIT_TO_8_TABLE) replicate_6_to_8 = REPLICATE_6_BIT_TO_8_TABLE;
138} 127 decltype(REPLICATE_7_BIT_TO_8_TABLE) replicate_7_to_8 = REPLICATE_7_BIT_TO_8_TABLE;
139 128 decltype(REPLICATE_8_BIT_TO_8_TABLE) replicate_8_to_8 = REPLICATE_8_BIT_TO_8_TABLE;
140static constexpr auto REPLICATE_BIT_TO_9_TABLE = MakeReplicateTable<u32, 1, 9>(); 129 decltype(REPLICATE_BYTE_TO_16_TABLE) replicate_byte_to_16 = REPLICATE_BYTE_TO_16_TABLE;
141static constexpr u32 ReplicateBitTo9(std::size_t value) { 130} constexpr ASTC_BUFFER_DATA;
142 return REPLICATE_BIT_TO_9_TABLE[value];
143}
144
145static constexpr auto REPLICATE_1_BIT_TO_8_TABLE = MakeReplicateTable<u32, 1, 8>();
146static constexpr auto REPLICATE_2_BIT_TO_8_TABLE = MakeReplicateTable<u32, 2, 8>();
147static constexpr auto REPLICATE_3_BIT_TO_8_TABLE = MakeReplicateTable<u32, 3, 8>();
148static constexpr auto REPLICATE_4_BIT_TO_8_TABLE = MakeReplicateTable<u32, 4, 8>();
149static constexpr auto REPLICATE_5_BIT_TO_8_TABLE = MakeReplicateTable<u32, 5, 8>();
150static constexpr auto REPLICATE_6_BIT_TO_8_TABLE = MakeReplicateTable<u32, 6, 8>();
151static constexpr auto REPLICATE_7_BIT_TO_8_TABLE = MakeReplicateTable<u32, 7, 8>();
152static constexpr auto REPLICATE_8_BIT_TO_8_TABLE = MakeReplicateTable<u32, 8, 8>();
153/// Use a precompiled table with the most common usages, if it's not in the expected range, fallback
154/// to the runtime implementation
155static constexpr u32 FastReplicateTo8(u32 value, u32 num_bits) {
156 switch (num_bits) {
157 case 1:
158 return REPLICATE_1_BIT_TO_8_TABLE[value];
159 case 2:
160 return REPLICATE_2_BIT_TO_8_TABLE[value];
161 case 3:
162 return REPLICATE_3_BIT_TO_8_TABLE[value];
163 case 4:
164 return REPLICATE_4_BIT_TO_8_TABLE[value];
165 case 5:
166 return REPLICATE_5_BIT_TO_8_TABLE[value];
167 case 6:
168 return REPLICATE_6_BIT_TO_8_TABLE[value];
169 case 7:
170 return REPLICATE_7_BIT_TO_8_TABLE[value];
171 case 8:
172 return REPLICATE_8_BIT_TO_8_TABLE[value];
173 default:
174 return Replicate(value, num_bits, 8);
175 }
176}
177
178static constexpr auto REPLICATE_1_BIT_TO_6_TABLE = MakeReplicateTable<u32, 1, 6>();
179static constexpr auto REPLICATE_2_BIT_TO_6_TABLE = MakeReplicateTable<u32, 2, 6>();
180static constexpr auto REPLICATE_3_BIT_TO_6_TABLE = MakeReplicateTable<u32, 3, 6>();
181static constexpr auto REPLICATE_4_BIT_TO_6_TABLE = MakeReplicateTable<u32, 4, 6>();
182static constexpr auto REPLICATE_5_BIT_TO_6_TABLE = MakeReplicateTable<u32, 5, 6>();
183
184static constexpr u32 FastReplicateTo6(u32 value, u32 num_bits) {
185 switch (num_bits) {
186 case 1:
187 return REPLICATE_1_BIT_TO_6_TABLE[value];
188 case 2:
189 return REPLICATE_2_BIT_TO_6_TABLE[value];
190 case 3:
191 return REPLICATE_3_BIT_TO_6_TABLE[value];
192 case 4:
193 return REPLICATE_4_BIT_TO_6_TABLE[value];
194 case 5:
195 return REPLICATE_5_BIT_TO_6_TABLE[value];
196 default:
197 return Replicate(value, num_bits, 6);
198 }
199}
200
201void Decompress(std::span<const uint8_t> data, uint32_t width, uint32_t height, uint32_t depth,
202 uint32_t block_width, uint32_t block_height, std::span<uint8_t> output);
203 131
204} // namespace Tegra::Texture::ASTC 132} // namespace Tegra::Texture::ASTC