summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar ameerj2021-07-04 22:48:41 -0400
committerGravatar ameerj2021-07-31 21:36:26 -0400
commit5665d055476fa793192523c3cb6fe06369d58674 (patch)
tree45a3ed50774c2106dcbeee9d38415f057d64a6fe
parentastc.h: Move data to cpp implementation (diff)
downloadyuzu-5665d055476fa793192523c3cb6fe06369d58674.tar.gz
yuzu-5665d055476fa793192523c3cb6fe06369d58674.tar.xz
yuzu-5665d055476fa793192523c3cb6fe06369d58674.zip
astc_decoder: Optimize the use EncodingData
This buffer was a list of EncodingData structures sorted by their bit length, with some duplication from the cpu decoder implementation. We can take advantage of its sorted property to optimize its usage in the shader. Thanks to wwylele for the optimization idea.
Diffstat (limited to '')
-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