summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/host_shaders/astc_decoder.comp50
-rw-r--r--src/video_core/renderer_opengl/util_shaders.cpp13
-rw-r--r--src/video_core/renderer_opengl/util_shaders.h1
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pass.cpp42
-rw-r--r--src/video_core/textures/astc.cpp70
-rw-r--r--src/video_core/textures/astc.h70
6 files changed, 108 insertions, 138 deletions
diff --git a/src/video_core/host_shaders/astc_decoder.comp b/src/video_core/host_shaders/astc_decoder.comp
index c37f15bfd..7f4efa31a 100644
--- a/src/video_core/host_shaders/astc_decoder.comp
+++ b/src/video_core/host_shaders/astc_decoder.comp
@@ -10,18 +10,16 @@
10#define END_PUSH_CONSTANTS }; 10#define END_PUSH_CONSTANTS };
11#define UNIFORM(n) 11#define UNIFORM(n)
12#define BINDING_INPUT_BUFFER 0 12#define BINDING_INPUT_BUFFER 0
13#define BINDING_ENC_BUFFER 1 13#define BINDING_SWIZZLE_BUFFER 1
14#define BINDING_SWIZZLE_BUFFER 2 14#define BINDING_OUTPUT_IMAGE 2
15#define BINDING_OUTPUT_IMAGE 3
16 15
17#else // ^^^ Vulkan ^^^ // vvv OpenGL vvv 16#else // ^^^ Vulkan ^^^ // vvv OpenGL vvv
18 17
19#define BEGIN_PUSH_CONSTANTS 18#define BEGIN_PUSH_CONSTANTS
20#define END_PUSH_CONSTANTS 19#define END_PUSH_CONSTANTS
21#define UNIFORM(n) layout(location = n) uniform 20#define UNIFORM(n) layout(location = n) uniform
22#define BINDING_SWIZZLE_BUFFER 0 21#define BINDING_INPUT_BUFFER 0
23#define BINDING_INPUT_BUFFER 1 22#define BINDING_SWIZZLE_BUFFER 1
24#define BINDING_ENC_BUFFER 2
25#define BINDING_OUTPUT_IMAGE 0 23#define BINDING_OUTPUT_IMAGE 0
26 24
27#endif 25#endif
@@ -64,11 +62,6 @@ layout(binding = BINDING_INPUT_BUFFER, std430) readonly buffer InputBufferU32 {
64 uint astc_data[]; 62 uint astc_data[];
65}; 63};
66 64
67// ASTC Encodings data
68layout(binding = BINDING_ENC_BUFFER, std430) readonly buffer EncodingsValues {
69 EncodingData encoding_values[];
70};
71
72layout(binding = BINDING_OUTPUT_IMAGE, rgba8) uniform writeonly image2DArray dest_image; 65layout(binding = BINDING_OUTPUT_IMAGE, rgba8) uniform writeonly image2DArray dest_image;
73 66
74const uint GOB_SIZE_X = 64; 67const uint GOB_SIZE_X = 64;
@@ -94,6 +87,19 @@ const int JUST_BITS = 0;
94const int QUINT = 1; 87const int QUINT = 1;
95const int TRIT = 2; 88const int TRIT = 2;
96 89
90// ASTC Encodings data, sorted in ascending order based on their BitLength value
91// (see GetBitLength() function)
92EncodingData encoding_values[22] = EncodingData[](
93 EncodingData(JUST_BITS, 0, 0, 0), EncodingData(JUST_BITS, 1, 0, 0), EncodingData(TRIT, 0, 0, 0),
94 EncodingData(JUST_BITS, 2, 0, 0), EncodingData(QUINT, 0, 0, 0), EncodingData(TRIT, 1, 0, 0),
95 EncodingData(JUST_BITS, 3, 0, 0), EncodingData(QUINT, 1, 0, 0), EncodingData(TRIT, 2, 0, 0),
96 EncodingData(JUST_BITS, 4, 0, 0), EncodingData(QUINT, 2, 0, 0), EncodingData(TRIT, 3, 0, 0),
97 EncodingData(JUST_BITS, 5, 0, 0), EncodingData(QUINT, 3, 0, 0), EncodingData(TRIT, 4, 0, 0),
98 EncodingData(JUST_BITS, 6, 0, 0), EncodingData(QUINT, 4, 0, 0), EncodingData(TRIT, 5, 0, 0),
99 EncodingData(JUST_BITS, 7, 0, 0), EncodingData(QUINT, 5, 0, 0), EncodingData(TRIT, 6, 0, 0),
100 EncodingData(JUST_BITS, 8, 0, 0)
101);
102
97// The following constants are expanded variants of the Replicate() 103// The following constants are expanded variants of the Replicate()
98// function calls corresponding to the following arguments: 104// function calls corresponding to the following arguments:
99// value: index into the generated table 105// value: index into the generated table
@@ -596,22 +602,16 @@ void DecodeColorValues(uvec4 modes, uint num_partitions, uint color_data_bits) {
596 for (uint i = 0; i < num_partitions; i++) { 602 for (uint i = 0; i < num_partitions; i++) {
597 num_values += ((modes[i] >> 2) + 1) << 1; 603 num_values += ((modes[i] >> 2) + 1) << 1;
598 } 604 }
599 int range = 256; 605 // Find the largest encoding that's within color_data_bits
600 while (--range > 0) { 606 // TODO(ameerj): profile with binary search
601 EncodingData val = encoding_values[range]; 607 int range = 0;
608 while (++range < encoding_values.length()) {
602 uint bit_length = GetBitLength(num_values, range); 609 uint bit_length = GetBitLength(num_values, range);
603 if (bit_length <= color_data_bits) { 610 if (bit_length > color_data_bits) {
604 while (--range > 0) {
605 EncodingData newval = encoding_values[range];
606 if (newval.encoding != val.encoding && newval.num_bits != val.num_bits) {
607 break;
608 }
609 }
610 ++range;
611 break; 611 break;
612 } 612 }
613 } 613 }
614 DecodeIntegerSequence(range, num_values); 614 DecodeIntegerSequence(range - 1, num_values);
615 uint out_index = 0; 615 uint out_index = 0;
616 for (int itr = 0; itr < result_index; ++itr) { 616 for (int itr = 0; itr < result_index; ++itr) {
617 if (out_index >= num_values) { 617 if (out_index >= num_values) {
@@ -1110,10 +1110,10 @@ TexelWeightParams DecodeBlockInfo(uint block_index) {
1110 } 1110 }
1111 weight_index -= 2; 1111 weight_index -= 2;
1112 if ((mode_layout != 9) && ((mode & 0x200) != 0)) { 1112 if ((mode_layout != 9) && ((mode & 0x200) != 0)) {
1113 const int max_weights[6] = int[6](9, 11, 15, 19, 23, 31); 1113 const int max_weights[6] = int[6](7, 8, 9, 10, 11, 12);
1114 params.max_weight = max_weights[weight_index]; 1114 params.max_weight = max_weights[weight_index];
1115 } else { 1115 } else {
1116 const int max_weights[6] = int[6](1, 2, 3, 4, 5, 7); 1116 const int max_weights[6] = int[6](1, 2, 3, 4, 5, 6);
1117 params.max_weight = max_weights[weight_index]; 1117 params.max_weight = max_weights[weight_index];
1118 } 1118 }
1119 return params; 1119 return params;
diff --git a/src/video_core/renderer_opengl/util_shaders.cpp b/src/video_core/renderer_opengl/util_shaders.cpp
index 37a4d1d9d..a2b264700 100644
--- a/src/video_core/renderer_opengl/util_shaders.cpp
+++ b/src/video_core/renderer_opengl/util_shaders.cpp
@@ -60,19 +60,15 @@ UtilShaders::UtilShaders(ProgramManager& program_manager_)
60 copy_bc4_program(MakeProgram(OPENGL_COPY_BC4_COMP)) { 60 copy_bc4_program(MakeProgram(OPENGL_COPY_BC4_COMP)) {
61 const auto swizzle_table = Tegra::Texture::MakeSwizzleTable(); 61 const auto swizzle_table = Tegra::Texture::MakeSwizzleTable();
62 swizzle_table_buffer.Create(); 62 swizzle_table_buffer.Create();
63 astc_buffer.Create();
64 glNamedBufferStorage(swizzle_table_buffer.handle, sizeof(swizzle_table), &swizzle_table, 0); 63 glNamedBufferStorage(swizzle_table_buffer.handle, sizeof(swizzle_table), &swizzle_table, 0);
65 glNamedBufferStorage(astc_buffer.handle, sizeof(ASTC_ENCODINGS_VALUES), &ASTC_ENCODINGS_VALUES,
66 0);
67} 64}
68 65
69UtilShaders::~UtilShaders() = default; 66UtilShaders::~UtilShaders() = default;
70 67
71void UtilShaders::ASTCDecode(Image& image, const ImageBufferMap& map, 68void UtilShaders::ASTCDecode(Image& image, const ImageBufferMap& map,
72 std::span<const VideoCommon::SwizzleParameters> swizzles) { 69 std::span<const VideoCommon::SwizzleParameters> swizzles) {
73 static constexpr GLuint BINDING_SWIZZLE_BUFFER = 0; 70 static constexpr GLuint BINDING_INPUT_BUFFER = 0;
74 static constexpr GLuint BINDING_INPUT_BUFFER = 1; 71 static constexpr GLuint BINDING_SWIZZLE_BUFFER = 1;
75 static constexpr GLuint BINDING_ENC_BUFFER = 2;
76 static constexpr GLuint BINDING_OUTPUT_IMAGE = 0; 72 static constexpr GLuint BINDING_OUTPUT_IMAGE = 0;
77 73
78 const Extent2D tile_size{ 74 const Extent2D tile_size{
@@ -81,7 +77,6 @@ void UtilShaders::ASTCDecode(Image& image, const ImageBufferMap& map,
81 }; 77 };
82 program_manager.BindComputeProgram(astc_decoder_program.handle); 78 program_manager.BindComputeProgram(astc_decoder_program.handle);
83 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, BINDING_SWIZZLE_BUFFER, swizzle_table_buffer.handle); 79 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, BINDING_SWIZZLE_BUFFER, swizzle_table_buffer.handle);
84 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, BINDING_ENC_BUFFER, astc_buffer.handle);
85 80
86 glFlushMappedNamedBufferRange(map.buffer, map.offset, image.guest_size_bytes); 81 glFlushMappedNamedBufferRange(map.buffer, map.offset, image.guest_size_bytes);
87 glUniform2ui(1, tile_size.width, tile_size.height); 82 glUniform2ui(1, tile_size.width, tile_size.height);
@@ -103,11 +98,11 @@ void UtilShaders::ASTCDecode(Image& image, const ImageBufferMap& map,
103 glUniform1ui(6, params.block_height); 98 glUniform1ui(6, params.block_height);
104 glUniform1ui(7, params.block_height_mask); 99 glUniform1ui(7, params.block_height_mask);
105 100
106 glBindImageTexture(BINDING_OUTPUT_IMAGE, image.StorageHandle(), swizzle.level, GL_TRUE, 0,
107 GL_WRITE_ONLY, GL_RGBA8);
108 // ASTC texture data 101 // ASTC texture data
109 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, BINDING_INPUT_BUFFER, map.buffer, input_offset, 102 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, BINDING_INPUT_BUFFER, map.buffer, input_offset,
110 image.guest_size_bytes - swizzle.buffer_offset); 103 image.guest_size_bytes - swizzle.buffer_offset);
104 glBindImageTexture(BINDING_OUTPUT_IMAGE, image.StorageHandle(), swizzle.level, GL_TRUE, 0,
105 GL_WRITE_ONLY, GL_RGBA8);
111 106
112 glDispatchCompute(num_dispatches_x, num_dispatches_y, image.info.resources.layers); 107 glDispatchCompute(num_dispatches_x, num_dispatches_y, image.info.resources.layers);
113 } 108 }
diff --git a/src/video_core/renderer_opengl/util_shaders.h b/src/video_core/renderer_opengl/util_shaders.h
index 53d65f368..ef881e35f 100644
--- a/src/video_core/renderer_opengl/util_shaders.h
+++ b/src/video_core/renderer_opengl/util_shaders.h
@@ -62,7 +62,6 @@ private:
62 ProgramManager& program_manager; 62 ProgramManager& program_manager;
63 63
64 OGLBuffer swizzle_table_buffer; 64 OGLBuffer swizzle_table_buffer;
65 OGLBuffer astc_buffer;
66 65
67 OGLProgram astc_decoder_program; 66 OGLProgram astc_decoder_program;
68 OGLProgram block_linear_unswizzle_2d_program; 67 OGLProgram block_linear_unswizzle_2d_program;
diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.cpp b/src/video_core/renderer_vulkan/vk_compute_pass.cpp
index 561cf5e11..328813a57 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pass.cpp
+++ b/src/video_core/renderer_vulkan/vk_compute_pass.cpp
@@ -30,16 +30,13 @@
30namespace Vulkan { 30namespace Vulkan {
31 31
32using Tegra::Texture::SWIZZLE_TABLE; 32using Tegra::Texture::SWIZZLE_TABLE;
33using Tegra::Texture::ASTC::ASTC_ENCODINGS_VALUES;
34using namespace Tegra::Texture::ASTC;
35 33
36namespace { 34namespace {
37 35
38constexpr u32 ASTC_BINDING_INPUT_BUFFER = 0; 36constexpr u32 ASTC_BINDING_INPUT_BUFFER = 0;
39constexpr u32 ASTC_BINDING_ENC_BUFFER = 1; 37constexpr u32 ASTC_BINDING_SWIZZLE_BUFFER = 1;
40constexpr u32 ASTC_BINDING_SWIZZLE_BUFFER = 2; 38constexpr u32 ASTC_BINDING_OUTPUT_IMAGE = 2;
41constexpr u32 ASTC_BINDING_OUTPUT_IMAGE = 3; 39constexpr size_t ASTC_NUM_BINDINGS = 3;
42constexpr size_t ASTC_NUM_BINDINGS = 4;
43 40
44template <size_t size> 41template <size_t size>
45inline constexpr VkPushConstantRange COMPUTE_PUSH_CONSTANT_RANGE{ 42inline constexpr VkPushConstantRange COMPUTE_PUSH_CONSTANT_RANGE{
@@ -75,7 +72,7 @@ constexpr DescriptorBankInfo INPUT_OUTPUT_BANK_INFO{
75 .score = 2, 72 .score = 2,
76}; 73};
77 74
78constexpr std::array<VkDescriptorSetLayoutBinding, 4> ASTC_DESCRIPTOR_SET_BINDINGS{{ 75constexpr std::array<VkDescriptorSetLayoutBinding, ASTC_NUM_BINDINGS> ASTC_DESCRIPTOR_SET_BINDINGS{{
79 { 76 {
80 .binding = ASTC_BINDING_INPUT_BUFFER, 77 .binding = ASTC_BINDING_INPUT_BUFFER,
81 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 78 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
@@ -84,13 +81,6 @@ constexpr std::array<VkDescriptorSetLayoutBinding, 4> ASTC_DESCRIPTOR_SET_BINDIN
84 .pImmutableSamplers = nullptr, 81 .pImmutableSamplers = nullptr,
85 }, 82 },
86 { 83 {
87 .binding = ASTC_BINDING_ENC_BUFFER,
88 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
89 .descriptorCount = 1,
90 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
91 .pImmutableSamplers = nullptr,
92 },
93 {
94 .binding = ASTC_BINDING_SWIZZLE_BUFFER, 84 .binding = ASTC_BINDING_SWIZZLE_BUFFER,
95 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 85 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
96 .descriptorCount = 1, 86 .descriptorCount = 1,
@@ -108,12 +98,12 @@ constexpr std::array<VkDescriptorSetLayoutBinding, 4> ASTC_DESCRIPTOR_SET_BINDIN
108 98
109constexpr DescriptorBankInfo ASTC_BANK_INFO{ 99constexpr DescriptorBankInfo ASTC_BANK_INFO{
110 .uniform_buffers = 0, 100 .uniform_buffers = 0,
111 .storage_buffers = 3, 101 .storage_buffers = 2,
112 .texture_buffers = 0, 102 .texture_buffers = 0,
113 .image_buffers = 0, 103 .image_buffers = 0,
114 .textures = 0, 104 .textures = 0,
115 .images = 1, 105 .images = 1,
116 .score = 4, 106 .score = 3,
117}; 107};
118 108
119constexpr VkDescriptorUpdateTemplateEntryKHR INPUT_OUTPUT_DESCRIPTOR_UPDATE_TEMPLATE{ 109constexpr VkDescriptorUpdateTemplateEntryKHR INPUT_OUTPUT_DESCRIPTOR_UPDATE_TEMPLATE{
@@ -136,14 +126,6 @@ constexpr std::array<VkDescriptorUpdateTemplateEntryKHR, ASTC_NUM_BINDINGS>
136 .stride = sizeof(DescriptorUpdateEntry), 126 .stride = sizeof(DescriptorUpdateEntry),
137 }, 127 },
138 { 128 {
139 .dstBinding = ASTC_BINDING_ENC_BUFFER,
140 .dstArrayElement = 0,
141 .descriptorCount = 1,
142 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
143 .offset = ASTC_BINDING_ENC_BUFFER * sizeof(DescriptorUpdateEntry),
144 .stride = sizeof(DescriptorUpdateEntry),
145 },
146 {
147 .dstBinding = ASTC_BINDING_SWIZZLE_BUFFER, 129 .dstBinding = ASTC_BINDING_SWIZZLE_BUFFER,
148 .dstArrayElement = 0, 130 .dstArrayElement = 0,
149 .descriptorCount = 1, 131 .descriptorCount = 1,
@@ -355,7 +337,7 @@ ASTCDecoderPass::ASTCDecoderPass(const Device& device_, VKScheduler& scheduler_,
355ASTCDecoderPass::~ASTCDecoderPass() = default; 337ASTCDecoderPass::~ASTCDecoderPass() = default;
356 338
357void ASTCDecoderPass::MakeDataBuffer() { 339void ASTCDecoderPass::MakeDataBuffer() {
358 constexpr size_t TOTAL_BUFFER_SIZE = sizeof(ASTC_ENCODINGS_VALUES) + sizeof(SWIZZLE_TABLE); 340 constexpr size_t TOTAL_BUFFER_SIZE = sizeof(SWIZZLE_TABLE);
359 data_buffer = device.GetLogical().CreateBuffer(VkBufferCreateInfo{ 341 data_buffer = device.GetLogical().CreateBuffer(VkBufferCreateInfo{
360 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 342 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
361 .pNext = nullptr, 343 .pNext = nullptr,
@@ -369,11 +351,7 @@ void ASTCDecoderPass::MakeDataBuffer() {
369 data_buffer_commit = memory_allocator.Commit(data_buffer, MemoryUsage::Upload); 351 data_buffer_commit = memory_allocator.Commit(data_buffer, MemoryUsage::Upload);
370 352
371 const auto staging_ref = staging_buffer_pool.Request(TOTAL_BUFFER_SIZE, MemoryUsage::Upload); 353 const auto staging_ref = staging_buffer_pool.Request(TOTAL_BUFFER_SIZE, MemoryUsage::Upload);
372 std::memcpy(staging_ref.mapped_span.data(), &ASTC_ENCODINGS_VALUES, 354 std::memcpy(staging_ref.mapped_span.data(), &SWIZZLE_TABLE, sizeof(SWIZZLE_TABLE));
373 sizeof(ASTC_ENCODINGS_VALUES));
374 // Tack on the swizzle table at the end of the buffer
375 std::memcpy(staging_ref.mapped_span.data() + sizeof(ASTC_ENCODINGS_VALUES), &SWIZZLE_TABLE,
376 sizeof(SWIZZLE_TABLE));
377 355
378 scheduler.Record([src = staging_ref.buffer, offset = staging_ref.offset, dst = *data_buffer, 356 scheduler.Record([src = staging_ref.buffer, offset = staging_ref.offset, dst = *data_buffer,
379 TOTAL_BUFFER_SIZE](vk::CommandBuffer cmdbuf) { 357 TOTAL_BUFFER_SIZE](vk::CommandBuffer cmdbuf) {
@@ -443,9 +421,7 @@ void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map,
443 update_descriptor_queue.Acquire(); 421 update_descriptor_queue.Acquire();
444 update_descriptor_queue.AddBuffer(map.buffer, input_offset, 422 update_descriptor_queue.AddBuffer(map.buffer, input_offset,
445 image.guest_size_bytes - swizzle.buffer_offset); 423 image.guest_size_bytes - swizzle.buffer_offset);
446 update_descriptor_queue.AddBuffer(*data_buffer, 0, sizeof(ASTC_ENCODINGS_VALUES)); 424 update_descriptor_queue.AddBuffer(*data_buffer, 0, sizeof(SWIZZLE_TABLE));
447 update_descriptor_queue.AddBuffer(*data_buffer, sizeof(ASTC_ENCODINGS_VALUES),
448 sizeof(SWIZZLE_TABLE));
449 update_descriptor_queue.AddImage(image.StorageImageView(swizzle.level)); 425 update_descriptor_queue.AddImage(image.StorageImageView(swizzle.level));
450 const void* const descriptor_data{update_descriptor_queue.UpdateData()}; 426 const void* const descriptor_data{update_descriptor_queue.UpdateData()};
451 427
diff --git a/src/video_core/textures/astc.cpp b/src/video_core/textures/astc.cpp
index 26c19d75b..25161df1f 100644
--- a/src/video_core/textures/astc.cpp
+++ b/src/video_core/textures/astc.cpp
@@ -151,6 +151,76 @@ private:
151 const IntType& m_Bits; 151 const IntType& m_Bits;
152}; 152};
153 153
154enum class IntegerEncoding { JustBits, Quint, Trit };
155
156struct IntegerEncodedValue {
157 constexpr IntegerEncodedValue() = default;
158
159 constexpr IntegerEncodedValue(IntegerEncoding encoding_, u32 num_bits_)
160 : encoding{encoding_}, num_bits{num_bits_} {}
161
162 constexpr bool MatchesEncoding(const IntegerEncodedValue& other) const {
163 return encoding == other.encoding && num_bits == other.num_bits;
164 }
165
166 // Returns the number of bits required to encode num_vals values.
167 u32 GetBitLength(u32 num_vals) const {
168 u32 total_bits = num_bits * num_vals;
169 if (encoding == IntegerEncoding::Trit) {
170 total_bits += (num_vals * 8 + 4) / 5;
171 } else if (encoding == IntegerEncoding::Quint) {
172 total_bits += (num_vals * 7 + 2) / 3;
173 }
174 return total_bits;
175 }
176
177 IntegerEncoding encoding{};
178 u32 num_bits = 0;
179 u32 bit_value = 0;
180 union {
181 u32 quint_value = 0;
182 u32 trit_value;
183 };
184};
185
186// Returns a new instance of this struct that corresponds to the
187// can take no more than mav_value values
188static constexpr IntegerEncodedValue CreateEncoding(u32 mav_value) {
189 while (mav_value > 0) {
190 u32 check = mav_value + 1;
191
192 // Is mav_value a power of two?
193 if (!(check & (check - 1))) {
194 return IntegerEncodedValue(IntegerEncoding::JustBits, std::popcount(mav_value));
195 }
196
197 // Is mav_value of the type 3*2^n - 1?
198 if ((check % 3 == 0) && !((check / 3) & ((check / 3) - 1))) {
199 return IntegerEncodedValue(IntegerEncoding::Trit, std::popcount(check / 3 - 1));
200 }
201
202 // Is mav_value of the type 5*2^n - 1?
203 if ((check % 5 == 0) && !((check / 5) & ((check / 5) - 1))) {
204 return IntegerEncodedValue(IntegerEncoding::Quint, std::popcount(check / 5 - 1));
205 }
206
207 // Apparently it can't be represented with a bounded integer sequence...
208 // just iterate.
209 mav_value--;
210 }
211 return IntegerEncodedValue(IntegerEncoding::JustBits, 0);
212}
213
214static constexpr std::array<IntegerEncodedValue, 256> MakeEncodedValues() {
215 std::array<IntegerEncodedValue, 256> encodings{};
216 for (std::size_t i = 0; i < encodings.size(); ++i) {
217 encodings[i] = CreateEncoding(static_cast<u32>(i));
218 }
219 return encodings;
220}
221
222static constexpr std::array<IntegerEncodedValue, 256> ASTC_ENCODINGS_VALUES = MakeEncodedValues();
223
154namespace Tegra::Texture::ASTC { 224namespace Tegra::Texture::ASTC {
155using IntegerEncodedVector = boost::container::static_vector< 225using IntegerEncodedVector = boost::container::static_vector<
156 IntegerEncodedValue, 256, 226 IntegerEncodedValue, 256,
diff --git a/src/video_core/textures/astc.h b/src/video_core/textures/astc.h
index 9e148afc4..14d2beec0 100644
--- a/src/video_core/textures/astc.h
+++ b/src/video_core/textures/astc.h
@@ -9,76 +9,6 @@
9 9
10namespace Tegra::Texture::ASTC { 10namespace Tegra::Texture::ASTC {
11 11
12enum class IntegerEncoding { JustBits, Quint, Trit };
13
14struct IntegerEncodedValue {
15 constexpr IntegerEncodedValue() = default;
16
17 constexpr IntegerEncodedValue(IntegerEncoding encoding_, u32 num_bits_)
18 : encoding{encoding_}, num_bits{num_bits_} {}
19
20 constexpr bool MatchesEncoding(const IntegerEncodedValue& other) const {
21 return encoding == other.encoding && num_bits == other.num_bits;
22 }
23
24 // Returns the number of bits required to encode num_vals values.
25 u32 GetBitLength(u32 num_vals) const {
26 u32 total_bits = num_bits * num_vals;
27 if (encoding == IntegerEncoding::Trit) {
28 total_bits += (num_vals * 8 + 4) / 5;
29 } else if (encoding == IntegerEncoding::Quint) {
30 total_bits += (num_vals * 7 + 2) / 3;
31 }
32 return total_bits;
33 }
34
35 IntegerEncoding encoding{};
36 u32 num_bits = 0;
37 u32 bit_value = 0;
38 union {
39 u32 quint_value = 0;
40 u32 trit_value;
41 };
42};
43
44// Returns a new instance of this struct that corresponds to the
45// can take no more than mav_value values
46constexpr IntegerEncodedValue CreateEncoding(u32 mav_value) {
47 while (mav_value > 0) {
48 u32 check = mav_value + 1;
49
50 // Is mav_value a power of two?
51 if (!(check & (check - 1))) {
52 return IntegerEncodedValue(IntegerEncoding::JustBits, std::popcount(mav_value));
53 }
54
55 // Is mav_value of the type 3*2^n - 1?
56 if ((check % 3 == 0) && !((check / 3) & ((check / 3) - 1))) {
57 return IntegerEncodedValue(IntegerEncoding::Trit, std::popcount(check / 3 - 1));
58 }
59
60 // Is mav_value of the type 5*2^n - 1?
61 if ((check % 5 == 0) && !((check / 5) & ((check / 5) - 1))) {
62 return IntegerEncodedValue(IntegerEncoding::Quint, std::popcount(check / 5 - 1));
63 }
64
65 // Apparently it can't be represented with a bounded integer sequence...
66 // just iterate.
67 mav_value--;
68 }
69 return IntegerEncodedValue(IntegerEncoding::JustBits, 0);
70}
71
72constexpr std::array<IntegerEncodedValue, 256> MakeEncodedValues() {
73 std::array<IntegerEncodedValue, 256> encodings{};
74 for (std::size_t i = 0; i < encodings.size(); ++i) {
75 encodings[i] = CreateEncoding(static_cast<u32>(i));
76 }
77 return encodings;
78}
79
80constexpr std::array<IntegerEncodedValue, 256> ASTC_ENCODINGS_VALUES = MakeEncodedValues();
81
82void Decompress(std::span<const uint8_t> data, uint32_t width, uint32_t height, uint32_t depth, 12void Decompress(std::span<const uint8_t> data, uint32_t width, uint32_t height, uint32_t depth,
83 uint32_t block_width, uint32_t block_height, std::span<uint8_t> output); 13 uint32_t block_width, uint32_t block_height, std::span<uint8_t> output);
84 14