summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/service/time/time_zone_content_manager.cpp2
-rw-r--r--src/core/settings.h1
-rw-r--r--src/input_common/udp/udp.cpp3
-rw-r--r--src/video_core/dirty_flags.cpp8
-rw-r--r--src/video_core/dirty_flags.h2
-rw-r--r--src/video_core/engines/kepler_compute.cpp8
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp9
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp34
-rw-r--r--src/video_core/renderer_opengl/gl_state_tracker.cpp1
-rw-r--r--src/video_core/renderer_vulkan/maxwell_to_vk.cpp6
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.cpp6
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.h6
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp88
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.h1
-rw-r--r--src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp2
-rw-r--r--src/video_core/renderer_vulkan/vk_state_tracker.cpp2
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp6
-rw-r--r--src/video_core/shader/decode/xmad.cpp63
-rw-r--r--src/video_core/textures/astc.cpp1074
-rw-r--r--src/yuzu/configuration/config.cpp4
-rw-r--r--src/yuzu/configuration/configure_system.cpp2
21 files changed, 668 insertions, 660 deletions
diff --git a/src/core/hle/service/time/time_zone_content_manager.cpp b/src/core/hle/service/time/time_zone_content_manager.cpp
index 57b1a2bca..78d4acd95 100644
--- a/src/core/hle/service/time/time_zone_content_manager.cpp
+++ b/src/core/hle/service/time/time_zone_content_manager.cpp
@@ -53,7 +53,7 @@ static std::vector<std::string> BuildLocationNameCache(Core::System& system) {
53 return {}; 53 return {};
54 } 54 }
55 55
56 std::vector<char> raw_data(binary_list->GetSize()); 56 std::vector<char> raw_data(binary_list->GetSize() + 1);
57 binary_list->ReadBytes<char>(raw_data.data(), binary_list->GetSize()); 57 binary_list->ReadBytes<char>(raw_data.data(), binary_list->GetSize());
58 58
59 std::stringstream data_stream{raw_data.data()}; 59 std::stringstream data_stream{raw_data.data()};
diff --git a/src/core/settings.h b/src/core/settings.h
index cb5979e6f..12e2cc9e7 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -387,6 +387,7 @@ struct Values {
387 387
388 s32 current_user; 388 s32 current_user;
389 s32 language_index; 389 s32 language_index;
390 s32 sound_index;
390 391
391 // Controls 392 // Controls
392 std::array<PlayerInput, 10> players; 393 std::array<PlayerInput, 10> players;
diff --git a/src/input_common/udp/udp.cpp b/src/input_common/udp/udp.cpp
index ca99cc22f..8c6ef1394 100644
--- a/src/input_common/udp/udp.cpp
+++ b/src/input_common/udp/udp.cpp
@@ -3,6 +3,7 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <mutex> 5#include <mutex>
6#include <optional>
6#include <tuple> 7#include <tuple>
7 8
8#include "common/param_package.h" 9#include "common/param_package.h"
@@ -44,7 +45,7 @@ public:
44 std::unique_ptr<Input::TouchDevice> Create(const Common::ParamPackage& params) override { 45 std::unique_ptr<Input::TouchDevice> Create(const Common::ParamPackage& params) override {
45 { 46 {
46 std::lock_guard guard(status->update_mutex); 47 std::lock_guard guard(status->update_mutex);
47 status->touch_calibration.emplace(); 48 status->touch_calibration = DeviceStatus::CalibrationData{};
48 // These default values work well for DS4 but probably not other touch inputs 49 // These default values work well for DS4 but probably not other touch inputs
49 status->touch_calibration->min_x = params.Get("min_x", 100); 50 status->touch_calibration->min_x = params.Get("min_x", 100);
50 status->touch_calibration->min_y = params.Get("min_y", 50); 51 status->touch_calibration->min_y = params.Get("min_y", 50);
diff --git a/src/video_core/dirty_flags.cpp b/src/video_core/dirty_flags.cpp
index 4429f3405..e16075993 100644
--- a/src/video_core/dirty_flags.cpp
+++ b/src/video_core/dirty_flags.cpp
@@ -15,14 +15,6 @@ namespace VideoCommon::Dirty {
15 15
16using Tegra::Engines::Maxwell3D; 16using Tegra::Engines::Maxwell3D;
17 17
18void SetupCommonOnWriteStores(Tegra::Engines::Maxwell3D::DirtyState::Flags& store) {
19 store[RenderTargets] = true;
20 store[ZetaBuffer] = true;
21 for (std::size_t i = 0; i < Maxwell3D::Regs::NumRenderTargets; ++i) {
22 store[ColorBuffer0 + i] = true;
23 }
24}
25
26void SetupDirtyRenderTargets(Tegra::Engines::Maxwell3D::DirtyState::Tables& tables) { 18void SetupDirtyRenderTargets(Tegra::Engines::Maxwell3D::DirtyState::Tables& tables) {
27 static constexpr std::size_t num_per_rt = NUM(rt[0]); 19 static constexpr std::size_t num_per_rt = NUM(rt[0]);
28 static constexpr std::size_t begin = OFF(rt); 20 static constexpr std::size_t begin = OFF(rt);
diff --git a/src/video_core/dirty_flags.h b/src/video_core/dirty_flags.h
index 0dbafd3ef..3f6c1d83a 100644
--- a/src/video_core/dirty_flags.h
+++ b/src/video_core/dirty_flags.h
@@ -44,8 +44,6 @@ void FillBlock(Tegra::Engines::Maxwell3D::DirtyState::Tables& tables, std::size_
44 FillBlock(tables[1], begin, num, index_b); 44 FillBlock(tables[1], begin, num, index_b);
45} 45}
46 46
47void SetupCommonOnWriteStores(Tegra::Engines::Maxwell3D::DirtyState::Flags& store);
48
49void SetupDirtyRenderTargets(Tegra::Engines::Maxwell3D::DirtyState::Tables& tables); 47void SetupDirtyRenderTargets(Tegra::Engines::Maxwell3D::DirtyState::Tables& tables);
50 48
51} // namespace VideoCommon::Dirty 49} // namespace VideoCommon::Dirty
diff --git a/src/video_core/engines/kepler_compute.cpp b/src/video_core/engines/kepler_compute.cpp
index 1ecd65925..368c75a66 100644
--- a/src/video_core/engines/kepler_compute.cpp
+++ b/src/video_core/engines/kepler_compute.cpp
@@ -119,14 +119,6 @@ Texture::TICEntry KeplerCompute::GetTICEntry(u32 tic_index) const {
119 Texture::TICEntry tic_entry; 119 Texture::TICEntry tic_entry;
120 memory_manager.ReadBlockUnsafe(tic_address_gpu, &tic_entry, sizeof(Texture::TICEntry)); 120 memory_manager.ReadBlockUnsafe(tic_address_gpu, &tic_entry, sizeof(Texture::TICEntry));
121 121
122 const auto r_type{tic_entry.r_type.Value()};
123 const auto g_type{tic_entry.g_type.Value()};
124 const auto b_type{tic_entry.b_type.Value()};
125 const auto a_type{tic_entry.a_type.Value()};
126
127 // TODO(Subv): Different data types for separate components are not supported
128 DEBUG_ASSERT(r_type == g_type && r_type == b_type && r_type == a_type);
129
130 return tic_entry; 122 return tic_entry;
131} 123}
132 124
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 1af4268a4..063f41327 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -93,10 +93,6 @@ void oglEnable(GLenum cap, bool state) {
93 (state ? glEnable : glDisable)(cap); 93 (state ? glEnable : glDisable)(cap);
94} 94}
95 95
96void oglEnablei(GLenum cap, bool state, GLuint index) {
97 (state ? glEnablei : glDisablei)(cap, index);
98}
99
100} // Anonymous namespace 96} // Anonymous namespace
101 97
102RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window, 98RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window,
@@ -478,7 +474,6 @@ void RasterizerOpenGL::Clear() {
478void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) { 474void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) {
479 MICROPROFILE_SCOPE(OpenGL_Drawing); 475 MICROPROFILE_SCOPE(OpenGL_Drawing);
480 auto& gpu = system.GPU().Maxwell3D(); 476 auto& gpu = system.GPU().Maxwell3D();
481 const auto& regs = gpu.regs;
482 477
483 query_cache.UpdateCounters(); 478 query_cache.UpdateCounters();
484 479
@@ -529,7 +524,7 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) {
529 // Upload vertex and index data. 524 // Upload vertex and index data.
530 SetupVertexBuffer(); 525 SetupVertexBuffer();
531 SetupVertexInstances(); 526 SetupVertexInstances();
532 GLintptr index_buffer_offset; 527 GLintptr index_buffer_offset = 0;
533 if (is_indexed) { 528 if (is_indexed) {
534 index_buffer_offset = SetupIndexBuffer(); 529 index_buffer_offset = SetupIndexBuffer();
535 } 530 }
@@ -555,7 +550,7 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) {
555 ConfigureFramebuffers(); 550 ConfigureFramebuffers();
556 551
557 // Signal the buffer cache that we are not going to upload more things. 552 // Signal the buffer cache that we are not going to upload more things.
558 const bool invalidate = buffer_cache.Unmap(); 553 buffer_cache.Unmap();
559 554
560 // Now that we are no longer uploading data, we can safely bind the buffers to OpenGL. 555 // Now that we are no longer uploading data, we can safely bind the buffers to OpenGL.
561 vertex_array_pushbuffer.Bind(); 556 vertex_array_pushbuffer.Bind();
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 3adf7f0cb..2c38f57fd 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -393,10 +393,6 @@ std::string FlowStackTopName(MetaStackClass stack) {
393 return fmt::format("{}_flow_stack_top", GetFlowStackPrefix(stack)); 393 return fmt::format("{}_flow_stack_top", GetFlowStackPrefix(stack));
394} 394}
395 395
396[[deprecated]] constexpr bool IsVertexShader(ShaderType stage) {
397 return stage == ShaderType::Vertex;
398}
399
400struct GenericVaryingDescription { 396struct GenericVaryingDescription {
401 std::string name; 397 std::string name;
402 u8 first_element = 0; 398 u8 first_element = 0;
@@ -529,8 +525,9 @@ private:
529 } 525 }
530 526
531 void DeclareVertex() { 527 void DeclareVertex() {
532 if (!IsVertexShader(stage)) 528 if (stage != ShaderType::Vertex) {
533 return; 529 return;
530 }
534 531
535 DeclareVertexRedeclarations(); 532 DeclareVertexRedeclarations();
536 } 533 }
@@ -602,14 +599,14 @@ private:
602 break; 599 break;
603 } 600 }
604 } 601 }
605 if (!IsVertexShader(stage) || device.HasVertexViewportLayer()) { 602 if (stage != ShaderType::Vertex || device.HasVertexViewportLayer()) {
606 if (ir.UsesLayer()) { 603 if (ir.UsesLayer()) {
607 code.AddLine("int gl_Layer;"); 604 code.AddLine("int gl_Layer;");
608 } 605 }
609 if (ir.UsesViewportIndex()) { 606 if (ir.UsesViewportIndex()) {
610 code.AddLine("int gl_ViewportIndex;"); 607 code.AddLine("int gl_ViewportIndex;");
611 } 608 }
612 } else if ((ir.UsesLayer() || ir.UsesViewportIndex()) && IsVertexShader(stage) && 609 } else if ((ir.UsesLayer() || ir.UsesViewportIndex()) && stage == ShaderType::Vertex &&
613 !device.HasVertexViewportLayer()) { 610 !device.HasVertexViewportLayer()) {
614 LOG_ERROR( 611 LOG_ERROR(
615 Render_OpenGL, 612 Render_OpenGL,
@@ -1147,7 +1144,7 @@ private:
1147 // TODO(Subv): Find out what the values are for the first two elements when inside a 1144 // TODO(Subv): Find out what the values are for the first two elements when inside a
1148 // vertex shader, and what's the value of the fourth element when inside a Tess Eval 1145 // vertex shader, and what's the value of the fourth element when inside a Tess Eval
1149 // shader. 1146 // shader.
1150 ASSERT(IsVertexShader(stage)); 1147 ASSERT(stage == ShaderType::Vertex);
1151 switch (element) { 1148 switch (element) {
1152 case 2: 1149 case 2:
1153 // Config pack's first value is instance_id. 1150 // Config pack's first value is instance_id.
@@ -1218,12 +1215,12 @@ private:
1218 UNIMPLEMENTED(); 1215 UNIMPLEMENTED();
1219 return {}; 1216 return {};
1220 case 1: 1217 case 1:
1221 if (IsVertexShader(stage) && !device.HasVertexViewportLayer()) { 1218 if (stage == ShaderType::Vertex && !device.HasVertexViewportLayer()) {
1222 return {}; 1219 return {};
1223 } 1220 }
1224 return {{"gl_Layer", Type::Int}}; 1221 return {{"gl_Layer", Type::Int}};
1225 case 2: 1222 case 2:
1226 if (IsVertexShader(stage) && !device.HasVertexViewportLayer()) { 1223 if (stage == ShaderType::Vertex && !device.HasVertexViewportLayer()) {
1227 return {}; 1224 return {};
1228 } 1225 }
1229 return {{"gl_ViewportIndex", Type::Int}}; 1226 return {{"gl_ViewportIndex", Type::Int}};
@@ -2009,16 +2006,19 @@ private:
2009 expr += GetSampler(meta->sampler); 2006 expr += GetSampler(meta->sampler);
2010 expr += ", "; 2007 expr += ", ";
2011 2008
2012 expr += constructors.at(operation.GetOperandsCount() - 1); 2009 expr += constructors.at(operation.GetOperandsCount() + (meta->array ? 1 : 0) - 1);
2013 expr += '('; 2010 expr += '(';
2014 for (std::size_t i = 0; i < count; ++i) { 2011 for (std::size_t i = 0; i < count; ++i) {
2015 expr += VisitOperand(operation, i).AsInt(); 2012 if (i > 0) {
2016 const std::size_t next = i + 1;
2017 if (next == count)
2018 expr += ')';
2019 else if (next < count)
2020 expr += ", "; 2013 expr += ", ";
2014 }
2015 expr += VisitOperand(operation, i).AsInt();
2021 } 2016 }
2017 if (meta->array) {
2018 expr += ", ";
2019 expr += Visit(meta->array).AsInt();
2020 }
2021 expr += ')';
2022 2022
2023 if (meta->lod && !meta->sampler.IsBuffer()) { 2023 if (meta->lod && !meta->sampler.IsBuffer()) {
2024 expr += ", "; 2024 expr += ", ";
@@ -2529,7 +2529,7 @@ private:
2529 } 2529 }
2530 2530
2531 u32 GetNumPhysicalInputAttributes() const { 2531 u32 GetNumPhysicalInputAttributes() const {
2532 return IsVertexShader(stage) ? GetNumPhysicalAttributes() : GetNumPhysicalVaryings(); 2532 return stage == ShaderType::Vertex ? GetNumPhysicalAttributes() : GetNumPhysicalVaryings();
2533 } 2533 }
2534 2534
2535 u32 GetNumPhysicalAttributes() const { 2535 u32 GetNumPhysicalAttributes() const {
diff --git a/src/video_core/renderer_opengl/gl_state_tracker.cpp b/src/video_core/renderer_opengl/gl_state_tracker.cpp
index 3f3bdf812..255ac3147 100644
--- a/src/video_core/renderer_opengl/gl_state_tracker.cpp
+++ b/src/video_core/renderer_opengl/gl_state_tracker.cpp
@@ -238,7 +238,6 @@ void StateTracker::Initialize() {
238 SetupDirtyMisc(tables); 238 SetupDirtyMisc(tables);
239 239
240 auto& store = dirty.on_write_stores; 240 auto& store = dirty.on_write_stores;
241 SetupCommonOnWriteStores(store);
242 store[VertexBuffers] = true; 241 store[VertexBuffers] = true;
243 for (std::size_t i = 0; i < Regs::NumVertexArrays; ++i) { 242 for (std::size_t i = 0; i < Regs::NumVertexArrays; ++i) {
244 store[VertexBuffer0 + i] = true; 243 store[VertexBuffer0 + i] = true;
diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
index 59e963263..f93447610 100644
--- a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
+++ b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
@@ -257,6 +257,8 @@ vk::ShaderStageFlagBits ShaderStage(Tegra::Engines::ShaderType stage) {
257 return vk::ShaderStageFlagBits::eGeometry; 257 return vk::ShaderStageFlagBits::eGeometry;
258 case Tegra::Engines::ShaderType::Fragment: 258 case Tegra::Engines::ShaderType::Fragment:
259 return vk::ShaderStageFlagBits::eFragment; 259 return vk::ShaderStageFlagBits::eFragment;
260 case Tegra::Engines::ShaderType::Compute:
261 return vk::ShaderStageFlagBits::eCompute;
260 } 262 }
261 UNIMPLEMENTED_MSG("Unimplemented shader stage={}", static_cast<u32>(stage)); 263 UNIMPLEMENTED_MSG("Unimplemented shader stage={}", static_cast<u32>(stage));
262 return {}; 264 return {};
@@ -367,6 +369,10 @@ vk::Format VertexFormat(Maxwell::VertexAttribute::Type type, Maxwell::VertexAttr
367 return vk::Format::eR8G8B8A8Uint; 369 return vk::Format::eR8G8B8A8Uint;
368 case Maxwell::VertexAttribute::Size::Size_32: 370 case Maxwell::VertexAttribute::Size::Size_32:
369 return vk::Format::eR32Uint; 371 return vk::Format::eR32Uint;
372 case Maxwell::VertexAttribute::Size::Size_32_32:
373 return vk::Format::eR32G32Uint;
374 case Maxwell::VertexAttribute::Size::Size_32_32_32:
375 return vk::Format::eR32G32B32Uint;
370 case Maxwell::VertexAttribute::Size::Size_32_32_32_32: 376 case Maxwell::VertexAttribute::Size::Size_32_32_32_32:
371 return vk::Format::eR32G32B32A32Uint; 377 return vk::Format::eR32G32B32A32Uint;
372 default: 378 default:
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
index 056ef495c..557b9d662 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -179,10 +179,11 @@ Tegra::Engines::ConstBufferEngineInterface& CachedShader::GetEngine(
179VKPipelineCache::VKPipelineCache(Core::System& system, RasterizerVulkan& rasterizer, 179VKPipelineCache::VKPipelineCache(Core::System& system, RasterizerVulkan& rasterizer,
180 const VKDevice& device, VKScheduler& scheduler, 180 const VKDevice& device, VKScheduler& scheduler,
181 VKDescriptorPool& descriptor_pool, 181 VKDescriptorPool& descriptor_pool,
182 VKUpdateDescriptorQueue& update_descriptor_queue) 182 VKUpdateDescriptorQueue& update_descriptor_queue,
183 VKRenderPassCache& renderpass_cache)
183 : RasterizerCache{rasterizer}, system{system}, device{device}, scheduler{scheduler}, 184 : RasterizerCache{rasterizer}, system{system}, device{device}, scheduler{scheduler},
184 descriptor_pool{descriptor_pool}, update_descriptor_queue{update_descriptor_queue}, 185 descriptor_pool{descriptor_pool}, update_descriptor_queue{update_descriptor_queue},
185 renderpass_cache(device) {} 186 renderpass_cache{renderpass_cache} {}
186 187
187VKPipelineCache::~VKPipelineCache() = default; 188VKPipelineCache::~VKPipelineCache() = default;
188 189
@@ -191,7 +192,6 @@ std::array<Shader, Maxwell::MaxShaderProgram> VKPipelineCache::GetShaders() {
191 192
192 std::array<Shader, Maxwell::MaxShaderProgram> shaders; 193 std::array<Shader, Maxwell::MaxShaderProgram> shaders;
193 for (std::size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) { 194 for (std::size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) {
194 const auto& shader_config = gpu.regs.shader_config[index];
195 const auto program{static_cast<Maxwell::ShaderProgram>(index)}; 195 const auto program{static_cast<Maxwell::ShaderProgram>(index)};
196 196
197 // Skip stages that are not enabled 197 // Skip stages that are not enabled
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h
index 21340c9a4..c4c112290 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h
@@ -161,7 +161,8 @@ public:
161 explicit VKPipelineCache(Core::System& system, RasterizerVulkan& rasterizer, 161 explicit VKPipelineCache(Core::System& system, RasterizerVulkan& rasterizer,
162 const VKDevice& device, VKScheduler& scheduler, 162 const VKDevice& device, VKScheduler& scheduler,
163 VKDescriptorPool& descriptor_pool, 163 VKDescriptorPool& descriptor_pool,
164 VKUpdateDescriptorQueue& update_descriptor_queue); 164 VKUpdateDescriptorQueue& update_descriptor_queue,
165 VKRenderPassCache& renderpass_cache);
165 ~VKPipelineCache(); 166 ~VKPipelineCache();
166 167
167 std::array<Shader, Maxwell::MaxShaderProgram> GetShaders(); 168 std::array<Shader, Maxwell::MaxShaderProgram> GetShaders();
@@ -184,8 +185,7 @@ private:
184 VKScheduler& scheduler; 185 VKScheduler& scheduler;
185 VKDescriptorPool& descriptor_pool; 186 VKDescriptorPool& descriptor_pool;
186 VKUpdateDescriptorQueue& update_descriptor_queue; 187 VKUpdateDescriptorQueue& update_descriptor_queue;
187 188 VKRenderPassCache& renderpass_cache;
188 VKRenderPassCache renderpass_cache;
189 189
190 std::array<Shader, Maxwell::MaxShaderProgram> last_shaders; 190 std::array<Shader, Maxwell::MaxShaderProgram> last_shaders;
191 191
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index c9886cc16..58c69b786 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -287,12 +287,13 @@ RasterizerVulkan::RasterizerVulkan(Core::System& system, Core::Frontend::EmuWind
287 screen_info{screen_info}, device{device}, resource_manager{resource_manager}, 287 screen_info{screen_info}, device{device}, resource_manager{resource_manager},
288 memory_manager{memory_manager}, state_tracker{state_tracker}, scheduler{scheduler}, 288 memory_manager{memory_manager}, state_tracker{state_tracker}, scheduler{scheduler},
289 staging_pool(device, memory_manager, scheduler), descriptor_pool(device), 289 staging_pool(device, memory_manager, scheduler), descriptor_pool(device),
290 update_descriptor_queue(device, scheduler), 290 update_descriptor_queue(device, scheduler), renderpass_cache(device),
291 quad_array_pass(device, scheduler, descriptor_pool, staging_pool, update_descriptor_queue), 291 quad_array_pass(device, scheduler, descriptor_pool, staging_pool, update_descriptor_queue),
292 uint8_pass(device, scheduler, descriptor_pool, staging_pool, update_descriptor_queue), 292 uint8_pass(device, scheduler, descriptor_pool, staging_pool, update_descriptor_queue),
293 texture_cache(system, *this, device, resource_manager, memory_manager, scheduler, 293 texture_cache(system, *this, device, resource_manager, memory_manager, scheduler,
294 staging_pool), 294 staging_pool),
295 pipeline_cache(system, *this, device, scheduler, descriptor_pool, update_descriptor_queue), 295 pipeline_cache(system, *this, device, scheduler, descriptor_pool, update_descriptor_queue,
296 renderpass_cache),
296 buffer_cache(*this, system, device, memory_manager, scheduler, staging_pool), 297 buffer_cache(*this, system, device, memory_manager, scheduler, staging_pool),
297 sampler_cache(device), query_cache(system, *this, device, scheduler) { 298 sampler_cache(device), query_cache(system, *this, device, scheduler) {
298 scheduler.SetQueryCache(query_cache); 299 scheduler.SetQueryCache(query_cache);
@@ -365,13 +366,16 @@ void RasterizerVulkan::Draw(bool is_indexed, bool is_instanced) {
365void RasterizerVulkan::Clear() { 366void RasterizerVulkan::Clear() {
366 MICROPROFILE_SCOPE(Vulkan_Clearing); 367 MICROPROFILE_SCOPE(Vulkan_Clearing);
367 368
368 query_cache.UpdateCounters();
369
370 const auto& gpu = system.GPU().Maxwell3D(); 369 const auto& gpu = system.GPU().Maxwell3D();
371 if (!system.GPU().Maxwell3D().ShouldExecute()) { 370 if (!system.GPU().Maxwell3D().ShouldExecute()) {
372 return; 371 return;
373 } 372 }
374 373
374 sampled_views.clear();
375 image_views.clear();
376
377 query_cache.UpdateCounters();
378
375 const auto& regs = gpu.regs; 379 const auto& regs = gpu.regs;
376 const bool use_color = regs.clear_buffers.R || regs.clear_buffers.G || regs.clear_buffers.B || 380 const bool use_color = regs.clear_buffers.R || regs.clear_buffers.G || regs.clear_buffers.B ||
377 regs.clear_buffers.A; 381 regs.clear_buffers.A;
@@ -380,52 +384,54 @@ void RasterizerVulkan::Clear() {
380 if (!use_color && !use_depth && !use_stencil) { 384 if (!use_color && !use_depth && !use_stencil) {
381 return; 385 return;
382 } 386 }
383 // Clearing images requires to be out of a renderpass
384 scheduler.RequestOutsideRenderPassOperationContext();
385 387
386 // TODO(Rodrigo): Implement clears rendering a quad or using beginning a renderpass. 388 [[maybe_unused]] const auto texceptions = UpdateAttachments();
389 DEBUG_ASSERT(texceptions.none());
390 SetupImageTransitions(0, color_attachments, zeta_attachment);
387 391
388 if (use_color) { 392 const vk::RenderPass renderpass = renderpass_cache.GetRenderPass(GetRenderPassParams(0));
389 View color_view; 393 const auto [framebuffer, render_area] = ConfigureFramebuffers(renderpass);
390 { 394 scheduler.RequestRenderpass({renderpass, framebuffer, {{0, 0}, render_area}, 0, nullptr});
391 MICROPROFILE_SCOPE(Vulkan_RenderTargets); 395
392 color_view = texture_cache.GetColorBufferSurface(regs.clear_buffers.RT.Value(), false); 396 const auto& scissor = regs.scissor_test[0];
393 } 397 const vk::Offset2D scissor_offset(scissor.min_x, scissor.min_y);
398 vk::Extent2D scissor_extent{scissor.max_x - scissor.min_x, scissor.max_y - scissor.min_y};
399 scissor_extent.width = std::min(scissor_extent.width, render_area.width);
400 scissor_extent.height = std::min(scissor_extent.height, render_area.height);
394 401
395 color_view->Transition(vk::ImageLayout::eTransferDstOptimal, 402 const u32 layer = regs.clear_buffers.layer;
396 vk::PipelineStageFlagBits::eTransfer, 403 const vk::ClearRect clear_rect({scissor_offset, scissor_extent}, layer, 1);
397 vk::AccessFlagBits::eTransferWrite);
398 404
405 if (use_color) {
399 const std::array clear_color = {regs.clear_color[0], regs.clear_color[1], 406 const std::array clear_color = {regs.clear_color[0], regs.clear_color[1],
400 regs.clear_color[2], regs.clear_color[3]}; 407 regs.clear_color[2], regs.clear_color[3]};
401 const vk::ClearColorValue clear(clear_color); 408 const vk::ClearValue clear_value{clear_color};
402 scheduler.Record([image = color_view->GetImage(), 409 const u32 color_attachment = regs.clear_buffers.RT;
403 subresource = color_view->GetImageSubresourceRange(), 410 scheduler.Record([color_attachment, clear_value, clear_rect](auto cmdbuf, auto& dld) {
404 clear](auto cmdbuf, auto& dld) { 411 const vk::ClearAttachment attachment(vk::ImageAspectFlagBits::eColor, color_attachment,
405 cmdbuf.clearColorImage(image, vk::ImageLayout::eTransferDstOptimal, clear, subresource, 412 clear_value);
406 dld); 413 cmdbuf.clearAttachments(1, &attachment, 1, &clear_rect, dld);
407 }); 414 });
408 } 415 }
409 if (use_depth || use_stencil) {
410 View zeta_surface;
411 {
412 MICROPROFILE_SCOPE(Vulkan_RenderTargets);
413 zeta_surface = texture_cache.GetDepthBufferSurface(false);
414 }
415 416
416 zeta_surface->Transition(vk::ImageLayout::eTransferDstOptimal, 417 if (!use_depth && !use_stencil) {
417 vk::PipelineStageFlagBits::eTransfer, 418 return;
418 vk::AccessFlagBits::eTransferWrite); 419 }
419 420 vk::ImageAspectFlags aspect_flags;
420 const vk::ClearDepthStencilValue clear(regs.clear_depth, 421 if (use_depth) {
421 static_cast<u32>(regs.clear_stencil)); 422 aspect_flags |= vk::ImageAspectFlagBits::eDepth;
422 scheduler.Record([image = zeta_surface->GetImage(), 423 }
423 subresource = zeta_surface->GetImageSubresourceRange(), 424 if (use_stencil) {
424 clear](auto cmdbuf, auto& dld) { 425 aspect_flags |= vk::ImageAspectFlagBits::eStencil;
425 cmdbuf.clearDepthStencilImage(image, vk::ImageLayout::eTransferDstOptimal, clear,
426 subresource, dld);
427 });
428 } 426 }
427
428 scheduler.Record([clear_depth = regs.clear_depth, clear_stencil = regs.clear_stencil,
429 clear_rect, aspect_flags](auto cmdbuf, auto& dld) {
430 const vk::ClearDepthStencilValue clear_zeta(clear_depth, clear_stencil);
431 const vk::ClearValue clear_value{clear_zeta};
432 const vk::ClearAttachment attachment(aspect_flags, 0, clear_value);
433 cmdbuf.clearAttachments(1, &attachment, 1, &clear_rect, dld);
434 });
429} 435}
430 436
431void RasterizerVulkan::DispatchCompute(GPUVAddr code_addr) { 437void RasterizerVulkan::DispatchCompute(GPUVAddr code_addr) {
@@ -542,8 +548,6 @@ bool RasterizerVulkan::AccelerateDisplay(const Tegra::FramebufferConfig& config,
542 548
543 // Verify that the cached surface is the same size and format as the requested framebuffer 549 // Verify that the cached surface is the same size and format as the requested framebuffer
544 const auto& params{surface->GetSurfaceParams()}; 550 const auto& params{surface->GetSurfaceParams()};
545 const auto& pixel_format{
546 VideoCore::Surface::PixelFormatFromGPUPixelFormat(config.pixel_format)};
547 ASSERT_MSG(params.width == config.width, "Framebuffer width is different"); 551 ASSERT_MSG(params.width == config.width, "Framebuffer width is different");
548 ASSERT_MSG(params.height == config.height, "Framebuffer height is different"); 552 ASSERT_MSG(params.height == config.height, "Framebuffer height is different");
549 553
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h
index b2e73d98d..3185868e9 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.h
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.h
@@ -253,6 +253,7 @@ private:
253 VKStagingBufferPool staging_pool; 253 VKStagingBufferPool staging_pool;
254 VKDescriptorPool descriptor_pool; 254 VKDescriptorPool descriptor_pool;
255 VKUpdateDescriptorQueue update_descriptor_queue; 255 VKUpdateDescriptorQueue update_descriptor_queue;
256 VKRenderPassCache renderpass_cache;
256 QuadArrayPass quad_array_pass; 257 QuadArrayPass quad_array_pass;
257 Uint8Pass uint8_pass; 258 Uint8Pass uint8_pass;
258 259
diff --git a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp
index d9ea3cc21..374959f82 100644
--- a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp
+++ b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp
@@ -100,7 +100,6 @@ void VKStagingBufferPool::ReleaseCache(bool host_visible) {
100} 100}
101 101
102u64 VKStagingBufferPool::ReleaseLevel(StagingBuffersCache& cache, std::size_t log2) { 102u64 VKStagingBufferPool::ReleaseLevel(StagingBuffersCache& cache, std::size_t log2) {
103 static constexpr u64 epochs_to_destroy = 180;
104 static constexpr std::size_t deletions_per_tick = 16; 103 static constexpr std::size_t deletions_per_tick = 16;
105 104
106 auto& staging = cache[log2]; 105 auto& staging = cache[log2];
@@ -108,6 +107,7 @@ u64 VKStagingBufferPool::ReleaseLevel(StagingBuffersCache& cache, std::size_t lo
108 const std::size_t old_size = entries.size(); 107 const std::size_t old_size = entries.size();
109 108
110 const auto is_deleteable = [this](const auto& entry) { 109 const auto is_deleteable = [this](const auto& entry) {
110 static constexpr u64 epochs_to_destroy = 180;
111 return entry.last_epoch + epochs_to_destroy < epoch && !entry.watch.IsUsed(); 111 return entry.last_epoch + epochs_to_destroy < epoch && !entry.watch.IsUsed();
112 }; 112 };
113 const std::size_t begin_offset = staging.delete_index; 113 const std::size_t begin_offset = staging.delete_index;
diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.cpp b/src/video_core/renderer_vulkan/vk_state_tracker.cpp
index d74e68b63..94a89e388 100644
--- a/src/video_core/renderer_vulkan/vk_state_tracker.cpp
+++ b/src/video_core/renderer_vulkan/vk_state_tracker.cpp
@@ -90,8 +90,6 @@ void StateTracker::Initialize() {
90 SetupDirtyBlendConstants(tables); 90 SetupDirtyBlendConstants(tables);
91 SetupDirtyDepthBounds(tables); 91 SetupDirtyDepthBounds(tables);
92 SetupDirtyStencilProperties(tables); 92 SetupDirtyStencilProperties(tables);
93
94 SetupCommonOnWriteStores(dirty.on_write_stores);
95} 93}
96 94
97void StateTracker::InvalidateCommandBufferState() { 95void StateTracker::InvalidateCommandBufferState() {
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index 73d92a5ae..26175921b 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -52,6 +52,9 @@ vk::ImageType SurfaceTargetToImage(SurfaceTarget target) {
52 return vk::ImageType::e2D; 52 return vk::ImageType::e2D;
53 case SurfaceTarget::Texture3D: 53 case SurfaceTarget::Texture3D:
54 return vk::ImageType::e3D; 54 return vk::ImageType::e3D;
55 case SurfaceTarget::TextureBuffer:
56 UNREACHABLE();
57 return {};
55 } 58 }
56 UNREACHABLE_MSG("Unknown texture target={}", static_cast<u32>(target)); 59 UNREACHABLE_MSG("Unknown texture target={}", static_cast<u32>(target));
57 return {}; 60 return {};
@@ -273,7 +276,6 @@ void CachedSurface::UploadImage(const std::vector<u8>& staging_buffer) {
273 276
274 for (u32 level = 0; level < params.num_levels; ++level) { 277 for (u32 level = 0; level < params.num_levels; ++level) {
275 vk::BufferImageCopy copy = GetBufferImageCopy(level); 278 vk::BufferImageCopy copy = GetBufferImageCopy(level);
276 const auto& dld = device.GetDispatchLoader();
277 if (image->GetAspectMask() == 279 if (image->GetAspectMask() ==
278 (vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil)) { 280 (vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil)) {
279 vk::BufferImageCopy depth = copy; 281 vk::BufferImageCopy depth = copy;
@@ -422,7 +424,6 @@ void VKTextureCache::ImageCopy(Surface& src_surface, Surface& dst_surface,
422 dst_base_layer, num_layers, copy_params.dest_level, 1, vk::PipelineStageFlagBits::eTransfer, 424 dst_base_layer, num_layers, copy_params.dest_level, 1, vk::PipelineStageFlagBits::eTransfer,
423 vk::AccessFlagBits::eTransferWrite, vk::ImageLayout::eTransferDstOptimal); 425 vk::AccessFlagBits::eTransferWrite, vk::ImageLayout::eTransferDstOptimal);
424 426
425 const auto& dld{device.GetDispatchLoader()};
426 const vk::ImageSubresourceLayers src_subresource( 427 const vk::ImageSubresourceLayers src_subresource(
427 src_surface->GetAspectMask(), copy_params.source_level, copy_params.source_z, num_layers); 428 src_surface->GetAspectMask(), copy_params.source_level, copy_params.source_z, num_layers);
428 const vk::ImageSubresourceLayers dst_subresource( 429 const vk::ImageSubresourceLayers dst_subresource(
@@ -458,7 +459,6 @@ void VKTextureCache::ImageBlit(View& src_view, View& dst_view,
458 dst_view->GetImageSubresourceLayers(), {dst_top_left, dst_bot_right}); 459 dst_view->GetImageSubresourceLayers(), {dst_top_left, dst_bot_right});
459 const bool is_linear = copy_config.filter == Tegra::Engines::Fermi2D::Filter::Linear; 460 const bool is_linear = copy_config.filter == Tegra::Engines::Fermi2D::Filter::Linear;
460 461
461 const auto& dld{device.GetDispatchLoader()};
462 scheduler.Record([src_image = src_view->GetImage(), dst_image = dst_view->GetImage(), blit, 462 scheduler.Record([src_image = src_view->GetImage(), dst_image = dst_view->GetImage(), blit,
463 is_linear](auto cmdbuf, auto& dld) { 463 is_linear](auto cmdbuf, auto& dld) {
464 cmdbuf.blitImage(src_image, vk::ImageLayout::eTransferSrcOptimal, dst_image, 464 cmdbuf.blitImage(src_image, vk::ImageLayout::eTransferSrcOptimal, dst_image,
diff --git a/src/video_core/shader/decode/xmad.cpp b/src/video_core/shader/decode/xmad.cpp
index 206961909..fbd7e9a17 100644
--- a/src/video_core/shader/decode/xmad.cpp
+++ b/src/video_core/shader/decode/xmad.cpp
@@ -12,6 +12,7 @@ namespace VideoCommon::Shader {
12 12
13using Tegra::Shader::Instruction; 13using Tegra::Shader::Instruction;
14using Tegra::Shader::OpCode; 14using Tegra::Shader::OpCode;
15using Tegra::Shader::PredCondition;
15 16
16u32 ShaderIR::DecodeXmad(NodeBlock& bb, u32 pc) { 17u32 ShaderIR::DecodeXmad(NodeBlock& bb, u32 pc) {
17 const Instruction instr = {program_code[pc]}; 18 const Instruction instr = {program_code[pc]};
@@ -63,15 +64,18 @@ u32 ShaderIR::DecodeXmad(NodeBlock& bb, u32 pc) {
63 } 64 }
64 }(); 65 }();
65 66
66 op_a = BitfieldExtract(op_a, instr.xmad.high_a ? 16 : 0, 16); 67 op_a = SignedOperation(OperationCode::IBitfieldExtract, is_signed_a, std::move(op_a),
68 instr.xmad.high_a ? Immediate(16) : Immediate(0), Immediate(16));
67 69
68 const Node original_b = op_b; 70 const Node original_b = op_b;
69 op_b = BitfieldExtract(op_b, is_high_b ? 16 : 0, 16); 71 op_b = SignedOperation(OperationCode::IBitfieldExtract, is_signed_b, std::move(op_b),
72 is_high_b ? Immediate(16) : Immediate(0), Immediate(16));
70 73
71 // TODO(Rodrigo): Use an appropiate sign for this operation 74 // we already check sign_a and sign_b is difference or not before so just use one in here.
72 Node product = Operation(OperationCode::IMul, NO_PRECISE, op_a, op_b); 75 Node product = SignedOperation(OperationCode::IMul, is_signed_a, op_a, op_b);
73 if (is_psl) { 76 if (is_psl) {
74 product = Operation(OperationCode::ILogicalShiftLeft, NO_PRECISE, product, Immediate(16)); 77 product =
78 SignedOperation(OperationCode::ILogicalShiftLeft, is_signed_a, product, Immediate(16));
75 } 79 }
76 SetTemporary(bb, 0, product); 80 SetTemporary(bb, 0, product);
77 product = GetTemporary(0); 81 product = GetTemporary(0);
@@ -88,12 +92,40 @@ u32 ShaderIR::DecodeXmad(NodeBlock& bb, u32 pc) {
88 return BitfieldExtract(original_c, 16, 16); 92 return BitfieldExtract(original_c, 16, 16);
89 case Tegra::Shader::XmadMode::CBcc: { 93 case Tegra::Shader::XmadMode::CBcc: {
90 const Node shifted_b = SignedOperation(OperationCode::ILogicalShiftLeft, is_signed_b, 94 const Node shifted_b = SignedOperation(OperationCode::ILogicalShiftLeft, is_signed_b,
91 NO_PRECISE, original_b, Immediate(16)); 95 original_b, Immediate(16));
92 return SignedOperation(OperationCode::IAdd, is_signed_c, NO_PRECISE, original_c, 96 return SignedOperation(OperationCode::IAdd, is_signed_c, original_c, shifted_b);
93 shifted_b); 97 }
98 case Tegra::Shader::XmadMode::CSfu: {
99 const Node comp_a = GetPredicateComparisonInteger(PredCondition::Equal, is_signed_a,
100 op_a, Immediate(0));
101 const Node comp_b = GetPredicateComparisonInteger(PredCondition::Equal, is_signed_b,
102 op_b, Immediate(0));
103 const Node comp = Operation(OperationCode::LogicalOr, comp_a, comp_b);
104
105 const Node comp_minus_a = GetPredicateComparisonInteger(
106 PredCondition::NotEqual, is_signed_a,
107 SignedOperation(OperationCode::IBitwiseAnd, is_signed_a, op_a,
108 Immediate(0x80000000)),
109 Immediate(0));
110 const Node comp_minus_b = GetPredicateComparisonInteger(
111 PredCondition::NotEqual, is_signed_b,
112 SignedOperation(OperationCode::IBitwiseAnd, is_signed_b, op_b,
113 Immediate(0x80000000)),
114 Immediate(0));
115
116 Node new_c = Operation(
117 OperationCode::Select, comp_minus_a,
118 SignedOperation(OperationCode::IAdd, is_signed_c, original_c, Immediate(-65536)),
119 original_c);
120 new_c = Operation(
121 OperationCode::Select, comp_minus_b,
122 SignedOperation(OperationCode::IAdd, is_signed_c, new_c, Immediate(-65536)),
123 std::move(new_c));
124
125 return Operation(OperationCode::Select, comp, original_c, std::move(new_c));
94 } 126 }
95 default: 127 default:
96 UNIMPLEMENTED_MSG("Unhandled XMAD mode: {}", static_cast<u32>(instr.xmad.mode.Value())); 128 UNREACHABLE();
97 return Immediate(0); 129 return Immediate(0);
98 } 130 }
99 }(); 131 }();
@@ -102,18 +134,19 @@ u32 ShaderIR::DecodeXmad(NodeBlock& bb, u32 pc) {
102 op_c = GetTemporary(1); 134 op_c = GetTemporary(1);
103 135
104 // TODO(Rodrigo): Use an appropiate sign for this operation 136 // TODO(Rodrigo): Use an appropiate sign for this operation
105 Node sum = Operation(OperationCode::IAdd, product, op_c); 137 Node sum = SignedOperation(OperationCode::IAdd, is_signed_a, product, std::move(op_c));
106 SetTemporary(bb, 2, sum); 138 SetTemporary(bb, 2, sum);
107 sum = GetTemporary(2); 139 sum = GetTemporary(2);
108 if (is_merge) { 140 if (is_merge) {
109 const Node a = BitfieldExtract(sum, 0, 16); 141 const Node a = SignedOperation(OperationCode::IBitfieldExtract, is_signed_a, std::move(sum),
110 const Node b = 142 Immediate(0), Immediate(16));
111 Operation(OperationCode::ILogicalShiftLeft, NO_PRECISE, original_b, Immediate(16)); 143 const Node b = SignedOperation(OperationCode::ILogicalShiftLeft, is_signed_b, original_b,
112 sum = Operation(OperationCode::IBitwiseOr, NO_PRECISE, a, b); 144 Immediate(16));
145 sum = SignedOperation(OperationCode::IBitwiseOr, is_signed_a, a, b);
113 } 146 }
114 147
115 SetInternalFlagsFromInteger(bb, sum, instr.generates_cc); 148 SetInternalFlagsFromInteger(bb, sum, instr.generates_cc);
116 SetRegister(bb, instr.gpr0, sum); 149 SetRegister(bb, instr.gpr0, std::move(sum));
117 150
118 return pc; 151 return pc;
119} 152}
diff --git a/src/video_core/textures/astc.cpp b/src/video_core/textures/astc.cpp
index 33bd31865..062b4f252 100644
--- a/src/video_core/textures/astc.cpp
+++ b/src/video_core/textures/astc.cpp
@@ -17,26 +17,37 @@
17 17
18#include <algorithm> 18#include <algorithm>
19#include <cassert> 19#include <cassert>
20#include <cstdint>
21#include <cstring> 20#include <cstring>
22#include <vector> 21#include <vector>
23 22
23#include "common/common_types.h"
24
24#include "video_core/textures/astc.h" 25#include "video_core/textures/astc.h"
25 26
27namespace {
28
29/// Count the number of bits set in a number.
30constexpr u32 Popcnt(u32 n) {
31 u32 c = 0;
32 for (; n; c++) {
33 n &= n - 1;
34 }
35 return c;
36}
37
38} // Anonymous namespace
39
26class InputBitStream { 40class InputBitStream {
27public: 41public:
28 explicit InputBitStream(const unsigned char* ptr, int start_offset = 0) 42 explicit InputBitStream(const u8* ptr, std::size_t start_offset = 0)
29 : m_CurByte(ptr), m_NextBit(start_offset % 8) {} 43 : m_CurByte(ptr), m_NextBit(start_offset % 8) {}
30 44
31 ~InputBitStream() = default; 45 std::size_t GetBitsRead() const {
32
33 int GetBitsRead() const {
34 return m_BitsRead; 46 return m_BitsRead;
35 } 47 }
36 48
37 int ReadBit() { 49 u32 ReadBit() {
38 50 u32 bit = *m_CurByte >> m_NextBit++;
39 int bit = *m_CurByte >> m_NextBit++;
40 while (m_NextBit >= 8) { 51 while (m_NextBit >= 8) {
41 m_NextBit -= 8; 52 m_NextBit -= 8;
42 m_CurByte++; 53 m_CurByte++;
@@ -46,57 +57,66 @@ public:
46 return bit & 1; 57 return bit & 1;
47 } 58 }
48 59
49 unsigned int ReadBits(unsigned int nBits) { 60 u32 ReadBits(std::size_t nBits) {
50 unsigned int ret = 0; 61 u32 ret = 0;
51 for (unsigned int i = 0; i < nBits; i++) { 62 for (std::size_t i = 0; i < nBits; ++i) {
63 ret |= (ReadBit() & 1) << i;
64 }
65 return ret;
66 }
67
68 template <std::size_t nBits>
69 u32 ReadBits() {
70 u32 ret = 0;
71 for (std::size_t i = 0; i < nBits; ++i) {
52 ret |= (ReadBit() & 1) << i; 72 ret |= (ReadBit() & 1) << i;
53 } 73 }
54 return ret; 74 return ret;
55 } 75 }
56 76
57private: 77private:
58 const unsigned char* m_CurByte; 78 const u8* m_CurByte;
59 int m_NextBit = 0; 79 std::size_t m_NextBit = 0;
60 int m_BitsRead = 0; 80 std::size_t m_BitsRead = 0;
61}; 81};
62 82
63class OutputBitStream { 83class OutputBitStream {
64public: 84public:
65 explicit OutputBitStream(unsigned char* ptr, int nBits = 0, int start_offset = 0) 85 explicit OutputBitStream(u8* ptr, s32 nBits = 0, s32 start_offset = 0)
66 : m_NumBits(nBits), m_CurByte(ptr), m_NextBit(start_offset % 8) {} 86 : m_NumBits(nBits), m_CurByte(ptr), m_NextBit(start_offset % 8) {}
67 87
68 ~OutputBitStream() = default; 88 ~OutputBitStream() = default;
69 89
70 int GetBitsWritten() const { 90 s32 GetBitsWritten() const {
71 return m_BitsWritten; 91 return m_BitsWritten;
72 } 92 }
73 93
74 void WriteBitsR(unsigned int val, unsigned int nBits) { 94 void WriteBitsR(u32 val, u32 nBits) {
75 for (unsigned int i = 0; i < nBits; i++) { 95 for (u32 i = 0; i < nBits; i++) {
76 WriteBit((val >> (nBits - i - 1)) & 1); 96 WriteBit((val >> (nBits - i - 1)) & 1);
77 } 97 }
78 } 98 }
79 99
80 void WriteBits(unsigned int val, unsigned int nBits) { 100 void WriteBits(u32 val, u32 nBits) {
81 for (unsigned int i = 0; i < nBits; i++) { 101 for (u32 i = 0; i < nBits; i++) {
82 WriteBit((val >> i) & 1); 102 WriteBit((val >> i) & 1);
83 } 103 }
84 } 104 }
85 105
86private: 106private:
87 void WriteBit(int b) { 107 void WriteBit(s32 b) {
88 108
89 if (done) 109 if (done)
90 return; 110 return;
91 111
92 const unsigned int mask = 1 << m_NextBit++; 112 const u32 mask = 1 << m_NextBit++;
93 113
94 // clear the bit 114 // clear the bit
95 *m_CurByte &= static_cast<unsigned char>(~mask); 115 *m_CurByte &= static_cast<u8>(~mask);
96 116
97 // Write the bit, if necessary 117 // Write the bit, if necessary
98 if (b) 118 if (b)
99 *m_CurByte |= static_cast<unsigned char>(mask); 119 *m_CurByte |= static_cast<u8>(mask);
100 120
101 // Next byte? 121 // Next byte?
102 if (m_NextBit >= 8) { 122 if (m_NextBit >= 8) {
@@ -107,10 +127,10 @@ private:
107 done = done || ++m_BitsWritten >= m_NumBits; 127 done = done || ++m_BitsWritten >= m_NumBits;
108 } 128 }
109 129
110 int m_BitsWritten = 0; 130 s32 m_BitsWritten = 0;
111 const int m_NumBits; 131 const s32 m_NumBits;
112 unsigned char* m_CurByte; 132 u8* m_CurByte;
113 int m_NextBit = 0; 133 s32 m_NextBit = 0;
114 134
115 bool done = false; 135 bool done = false;
116}; 136};
@@ -123,20 +143,20 @@ public:
123 Bits(const Bits&) = delete; 143 Bits(const Bits&) = delete;
124 Bits& operator=(const Bits&) = delete; 144 Bits& operator=(const Bits&) = delete;
125 145
126 uint8_t operator[](uint32_t bitPos) const { 146 u8 operator[](u32 bitPos) const {
127 return static_cast<uint8_t>((m_Bits >> bitPos) & 1); 147 return static_cast<u8>((m_Bits >> bitPos) & 1);
128 } 148 }
129 149
130 IntType operator()(uint32_t start, uint32_t end) const { 150 IntType operator()(u32 start, u32 end) const {
131 if (start == end) { 151 if (start == end) {
132 return (*this)[start]; 152 return (*this)[start];
133 } else if (start > end) { 153 } else if (start > end) {
134 uint32_t t = start; 154 u32 t = start;
135 start = end; 155 start = end;
136 end = t; 156 end = t;
137 } 157 }
138 158
139 uint64_t mask = (1 << (end - start + 1)) - 1; 159 u64 mask = (1 << (end - start + 1)) - 1;
140 return (m_Bits >> start) & static_cast<IntType>(mask); 160 return (m_Bits >> start) & static_cast<IntType>(mask);
141 } 161 }
142 162
@@ -144,273 +164,236 @@ private:
144 const IntType& m_Bits; 164 const IntType& m_Bits;
145}; 165};
146 166
147enum EIntegerEncoding { eIntegerEncoding_JustBits, eIntegerEncoding_Quint, eIntegerEncoding_Trit }; 167enum class IntegerEncoding { JustBits, Qus32, Trit };
148
149class IntegerEncodedValue {
150private:
151 const EIntegerEncoding m_Encoding;
152 const uint32_t m_NumBits;
153 uint32_t m_BitValue;
154 union {
155 uint32_t m_QuintValue;
156 uint32_t m_TritValue;
157 };
158 168
159public: 169struct IntegerEncodedValue {
160 // Jank, but we're not doing any heavy lifting in this class, so it's 170 constexpr IntegerEncodedValue() = default;
161 // probably OK. It allows us to use these in std::vectors...
162 IntegerEncodedValue& operator=(const IntegerEncodedValue& other) {
163 new (this) IntegerEncodedValue(other);
164 return *this;
165 }
166 171
167 IntegerEncodedValue(EIntegerEncoding encoding, uint32_t numBits) 172 constexpr IntegerEncodedValue(IntegerEncoding encoding_, u32 num_bits_)
168 : m_Encoding(encoding), m_NumBits(numBits) {} 173 : encoding{encoding_}, num_bits{num_bits_} {}
169 174
170 EIntegerEncoding GetEncoding() const { 175 constexpr bool MatchesEncoding(const IntegerEncodedValue& other) const {
171 return m_Encoding; 176 return encoding == other.encoding && num_bits == other.num_bits;
172 }
173 uint32_t BaseBitLength() const {
174 return m_NumBits;
175 }
176
177 uint32_t GetBitValue() const {
178 return m_BitValue;
179 }
180 void SetBitValue(uint32_t val) {
181 m_BitValue = val;
182 }
183
184 uint32_t GetTritValue() const {
185 return m_TritValue;
186 }
187 void SetTritValue(uint32_t val) {
188 m_TritValue = val;
189 }
190
191 uint32_t GetQuintValue() const {
192 return m_QuintValue;
193 }
194 void SetQuintValue(uint32_t val) {
195 m_QuintValue = val;
196 }
197
198 bool MatchesEncoding(const IntegerEncodedValue& other) const {
199 return m_Encoding == other.m_Encoding && m_NumBits == other.m_NumBits;
200 } 177 }
201 178
202 // Returns the number of bits required to encode nVals values. 179 // Returns the number of bits required to encode nVals values.
203 uint32_t GetBitLength(uint32_t nVals) const { 180 u32 GetBitLength(u32 nVals) const {
204 uint32_t totalBits = m_NumBits * nVals; 181 u32 totalBits = num_bits * nVals;
205 if (m_Encoding == eIntegerEncoding_Trit) { 182 if (encoding == IntegerEncoding::Trit) {
206 totalBits += (nVals * 8 + 4) / 5; 183 totalBits += (nVals * 8 + 4) / 5;
207 } else if (m_Encoding == eIntegerEncoding_Quint) { 184 } else if (encoding == IntegerEncoding::Qus32) {
208 totalBits += (nVals * 7 + 2) / 3; 185 totalBits += (nVals * 7 + 2) / 3;
209 } 186 }
210 return totalBits; 187 return totalBits;
211 } 188 }
212 189
213 // Count the number of bits set in a number. 190 IntegerEncoding encoding{};
214 static inline uint32_t Popcnt(uint32_t n) { 191 u32 num_bits = 0;
215 uint32_t c; 192 u32 bit_value = 0;
216 for (c = 0; n; c++) { 193 union {
217 n &= n - 1; 194 u32 qus32_value = 0;
195 u32 trit_value;
196 };
197};
198
199static void DecodeTritBlock(InputBitStream& bits, std::vector<IntegerEncodedValue>& result,
200 u32 nBitsPerValue) {
201 // Implement the algorithm in section C.2.12
202 u32 m[5];
203 u32 t[5];
204 u32 T;
205
206 // Read the trit encoded block according to
207 // table C.2.14
208 m[0] = bits.ReadBits(nBitsPerValue);
209 T = bits.ReadBits<2>();
210 m[1] = bits.ReadBits(nBitsPerValue);
211 T |= bits.ReadBits<2>() << 2;
212 m[2] = bits.ReadBits(nBitsPerValue);
213 T |= bits.ReadBit() << 4;
214 m[3] = bits.ReadBits(nBitsPerValue);
215 T |= bits.ReadBits<2>() << 5;
216 m[4] = bits.ReadBits(nBitsPerValue);
217 T |= bits.ReadBit() << 7;
218
219 u32 C = 0;
220
221 Bits<u32> Tb(T);
222 if (Tb(2, 4) == 7) {
223 C = (Tb(5, 7) << 2) | Tb(0, 1);
224 t[4] = t[3] = 2;
225 } else {
226 C = Tb(0, 4);
227 if (Tb(5, 6) == 3) {
228 t[4] = 2;
229 t[3] = Tb[7];
230 } else {
231 t[4] = Tb[7];
232 t[3] = Tb(5, 6);
218 } 233 }
219 return c;
220 } 234 }
221 235
222 // Returns a new instance of this struct that corresponds to the 236 Bits<u32> Cb(C);
223 // can take no more than maxval values 237 if (Cb(0, 1) == 3) {
224 static IntegerEncodedValue CreateEncoding(uint32_t maxVal) { 238 t[2] = 2;
225 while (maxVal > 0) { 239 t[1] = Cb[4];
226 uint32_t check = maxVal + 1; 240 t[0] = (Cb[3] << 1) | (Cb[2] & ~Cb[3]);
227 241 } else if (Cb(2, 3) == 3) {
228 // Is maxVal a power of two? 242 t[2] = 2;
229 if (!(check & (check - 1))) { 243 t[1] = 2;
230 return IntegerEncodedValue(eIntegerEncoding_JustBits, Popcnt(maxVal)); 244 t[0] = Cb(0, 1);
231 } 245 } else {
232 246 t[2] = Cb[4];
233 // Is maxVal of the type 3*2^n - 1? 247 t[1] = Cb(2, 3);
234 if ((check % 3 == 0) && !((check / 3) & ((check / 3) - 1))) { 248 t[0] = (Cb[1] << 1) | (Cb[0] & ~Cb[1]);
235 return IntegerEncodedValue(eIntegerEncoding_Trit, Popcnt(check / 3 - 1)); 249 }
236 }
237 250
238 // Is maxVal of the type 5*2^n - 1? 251 for (std::size_t i = 0; i < 5; ++i) {
239 if ((check % 5 == 0) && !((check / 5) & ((check / 5) - 1))) { 252 IntegerEncodedValue& val = result.emplace_back(IntegerEncoding::Trit, nBitsPerValue);
240 return IntegerEncodedValue(eIntegerEncoding_Quint, Popcnt(check / 5 - 1)); 253 val.bit_value = m[i];
241 } 254 val.trit_value = t[i];
255 }
256}
242 257
243 // Apparently it can't be represented with a bounded integer sequence... 258static void DecodeQus32Block(InputBitStream& bits, std::vector<IntegerEncodedValue>& result,
244 // just iterate. 259 u32 nBitsPerValue) {
245 maxVal--; 260 // Implement the algorithm in section C.2.12
261 u32 m[3];
262 u32 q[3];
263 u32 Q;
264
265 // Read the trit encoded block according to
266 // table C.2.15
267 m[0] = bits.ReadBits(nBitsPerValue);
268 Q = bits.ReadBits<3>();
269 m[1] = bits.ReadBits(nBitsPerValue);
270 Q |= bits.ReadBits<2>() << 3;
271 m[2] = bits.ReadBits(nBitsPerValue);
272 Q |= bits.ReadBits<2>() << 5;
273
274 Bits<u32> Qb(Q);
275 if (Qb(1, 2) == 3 && Qb(5, 6) == 0) {
276 q[0] = q[1] = 4;
277 q[2] = (Qb[0] << 2) | ((Qb[4] & ~Qb[0]) << 1) | (Qb[3] & ~Qb[0]);
278 } else {
279 u32 C = 0;
280 if (Qb(1, 2) == 3) {
281 q[2] = 4;
282 C = (Qb(3, 4) << 3) | ((~Qb(5, 6) & 3) << 1) | Qb[0];
283 } else {
284 q[2] = Qb(5, 6);
285 C = Qb(0, 4);
246 } 286 }
247 return IntegerEncodedValue(eIntegerEncoding_JustBits, 0);
248 }
249
250 // Fills result with the values that are encoded in the given
251 // bitstream. We must know beforehand what the maximum possible
252 // value is, and how many values we're decoding.
253 static void DecodeIntegerSequence(std::vector<IntegerEncodedValue>& result,
254 InputBitStream& bits, uint32_t maxRange, uint32_t nValues) {
255 // Determine encoding parameters
256 IntegerEncodedValue val = IntegerEncodedValue::CreateEncoding(maxRange);
257
258 // Start decoding
259 uint32_t nValsDecoded = 0;
260 while (nValsDecoded < nValues) {
261 switch (val.GetEncoding()) {
262 case eIntegerEncoding_Quint:
263 DecodeQuintBlock(bits, result, val.BaseBitLength());
264 nValsDecoded += 3;
265 break;
266 287
267 case eIntegerEncoding_Trit: 288 Bits<u32> Cb(C);
268 DecodeTritBlock(bits, result, val.BaseBitLength()); 289 if (Cb(0, 2) == 5) {
269 nValsDecoded += 5; 290 q[1] = 4;
270 break; 291 q[0] = Cb(3, 4);
271 292 } else {
272 case eIntegerEncoding_JustBits: 293 q[1] = Cb(3, 4);
273 val.SetBitValue(bits.ReadBits(val.BaseBitLength())); 294 q[0] = Cb(0, 2);
274 result.push_back(val);
275 nValsDecoded++;
276 break;
277 }
278 } 295 }
279 } 296 }
280 297
281private: 298 for (std::size_t i = 0; i < 3; ++i) {
282 static void DecodeTritBlock(InputBitStream& bits, std::vector<IntegerEncodedValue>& result, 299 IntegerEncodedValue& val = result.emplace_back(IntegerEncoding::Qus32, nBitsPerValue);
283 uint32_t nBitsPerValue) { 300 val.bit_value = m[i];
284 // Implement the algorithm in section C.2.12 301 val.qus32_value = q[i];
285 uint32_t m[5]; 302 }
286 uint32_t t[5]; 303}
287 uint32_t T; 304
288 305// Returns a new instance of this struct that corresponds to the
289 // Read the trit encoded block according to 306// can take no more than maxval values
290 // table C.2.14 307static constexpr IntegerEncodedValue CreateEncoding(u32 maxVal) {
291 m[0] = bits.ReadBits(nBitsPerValue); 308 while (maxVal > 0) {
292 T = bits.ReadBits(2); 309 u32 check = maxVal + 1;
293 m[1] = bits.ReadBits(nBitsPerValue); 310
294 T |= bits.ReadBits(2) << 2; 311 // Is maxVal a power of two?
295 m[2] = bits.ReadBits(nBitsPerValue); 312 if (!(check & (check - 1))) {
296 T |= bits.ReadBit() << 4; 313 return IntegerEncodedValue(IntegerEncoding::JustBits, Popcnt(maxVal));
297 m[3] = bits.ReadBits(nBitsPerValue);
298 T |= bits.ReadBits(2) << 5;
299 m[4] = bits.ReadBits(nBitsPerValue);
300 T |= bits.ReadBit() << 7;
301
302 uint32_t C = 0;
303
304 Bits<uint32_t> Tb(T);
305 if (Tb(2, 4) == 7) {
306 C = (Tb(5, 7) << 2) | Tb(0, 1);
307 t[4] = t[3] = 2;
308 } else {
309 C = Tb(0, 4);
310 if (Tb(5, 6) == 3) {
311 t[4] = 2;
312 t[3] = Tb[7];
313 } else {
314 t[4] = Tb[7];
315 t[3] = Tb(5, 6);
316 }
317 } 314 }
318 315
319 Bits<uint32_t> Cb(C); 316 // Is maxVal of the type 3*2^n - 1?
320 if (Cb(0, 1) == 3) { 317 if ((check % 3 == 0) && !((check / 3) & ((check / 3) - 1))) {
321 t[2] = 2; 318 return IntegerEncodedValue(IntegerEncoding::Trit, Popcnt(check / 3 - 1));
322 t[1] = Cb[4];
323 t[0] = (Cb[3] << 1) | (Cb[2] & ~Cb[3]);
324 } else if (Cb(2, 3) == 3) {
325 t[2] = 2;
326 t[1] = 2;
327 t[0] = Cb(0, 1);
328 } else {
329 t[2] = Cb[4];
330 t[1] = Cb(2, 3);
331 t[0] = (Cb[1] << 1) | (Cb[0] & ~Cb[1]);
332 } 319 }
333 320
334 for (uint32_t i = 0; i < 5; i++) { 321 // Is maxVal of the type 5*2^n - 1?
335 IntegerEncodedValue val(eIntegerEncoding_Trit, nBitsPerValue); 322 if ((check % 5 == 0) && !((check / 5) & ((check / 5) - 1))) {
336 val.SetBitValue(m[i]); 323 return IntegerEncodedValue(IntegerEncoding::Qus32, Popcnt(check / 5 - 1));
337 val.SetTritValue(t[i]);
338 result.push_back(val);
339 } 324 }
325
326 // Apparently it can't be represented with a bounded integer sequence...
327 // just iterate.
328 maxVal--;
340 } 329 }
330 return IntegerEncodedValue(IntegerEncoding::JustBits, 0);
331}
341 332
342 static void DecodeQuintBlock(InputBitStream& bits, std::vector<IntegerEncodedValue>& result, 333static constexpr std::array<IntegerEncodedValue, 256> MakeEncodedValues() {
343 uint32_t nBitsPerValue) { 334 std::array<IntegerEncodedValue, 256> encodings{};
344 // Implement the algorithm in section C.2.12 335 for (std::size_t i = 0; i < encodings.size(); ++i) {
345 uint32_t m[3]; 336 encodings[i] = CreateEncoding(static_cast<u32>(i));
346 uint32_t q[3]; 337 }
347 uint32_t Q; 338 return encodings;
348 339}
349 // Read the trit encoded block according to
350 // table C.2.15
351 m[0] = bits.ReadBits(nBitsPerValue);
352 Q = bits.ReadBits(3);
353 m[1] = bits.ReadBits(nBitsPerValue);
354 Q |= bits.ReadBits(2) << 3;
355 m[2] = bits.ReadBits(nBitsPerValue);
356 Q |= bits.ReadBits(2) << 5;
357
358 Bits<uint32_t> Qb(Q);
359 if (Qb(1, 2) == 3 && Qb(5, 6) == 0) {
360 q[0] = q[1] = 4;
361 q[2] = (Qb[0] << 2) | ((Qb[4] & ~Qb[0]) << 1) | (Qb[3] & ~Qb[0]);
362 } else {
363 uint32_t C = 0;
364 if (Qb(1, 2) == 3) {
365 q[2] = 4;
366 C = (Qb(3, 4) << 3) | ((~Qb(5, 6) & 3) << 1) | Qb[0];
367 } else {
368 q[2] = Qb(5, 6);
369 C = Qb(0, 4);
370 }
371 340
372 Bits<uint32_t> Cb(C); 341static constexpr std::array EncodingsValues = MakeEncodedValues();
373 if (Cb(0, 2) == 5) { 342
374 q[1] = 4; 343// Fills result with the values that are encoded in the given
375 q[0] = Cb(3, 4); 344// bitstream. We must know beforehand what the maximum possible
376 } else { 345// value is, and how many values we're decoding.
377 q[1] = Cb(3, 4); 346static void DecodeIntegerSequence(std::vector<IntegerEncodedValue>& result, InputBitStream& bits,
378 q[0] = Cb(0, 2); 347 u32 maxRange, u32 nValues) {
379 } 348 // Determine encoding parameters
380 } 349 IntegerEncodedValue val = EncodingsValues[maxRange];
350
351 // Start decoding
352 u32 nValsDecoded = 0;
353 while (nValsDecoded < nValues) {
354 switch (val.encoding) {
355 case IntegerEncoding::Qus32:
356 DecodeQus32Block(bits, result, val.num_bits);
357 nValsDecoded += 3;
358 break;
359
360 case IntegerEncoding::Trit:
361 DecodeTritBlock(bits, result, val.num_bits);
362 nValsDecoded += 5;
363 break;
381 364
382 for (uint32_t i = 0; i < 3; i++) { 365 case IntegerEncoding::JustBits:
383 IntegerEncodedValue val(eIntegerEncoding_Quint, nBitsPerValue); 366 val.bit_value = bits.ReadBits(val.num_bits);
384 val.m_BitValue = m[i];
385 val.m_QuintValue = q[i];
386 result.push_back(val); 367 result.push_back(val);
368 nValsDecoded++;
369 break;
387 } 370 }
388 } 371 }
389}; 372}
390 373
391namespace ASTCC { 374namespace ASTCC {
392 375
393struct TexelWeightParams { 376struct TexelWeightParams {
394 uint32_t m_Width = 0; 377 u32 m_Width = 0;
395 uint32_t m_Height = 0; 378 u32 m_Height = 0;
396 bool m_bDualPlane = false; 379 bool m_bDualPlane = false;
397 uint32_t m_MaxWeight = 0; 380 u32 m_MaxWeight = 0;
398 bool m_bError = false; 381 bool m_bError = false;
399 bool m_bVoidExtentLDR = false; 382 bool m_bVoidExtentLDR = false;
400 bool m_bVoidExtentHDR = false; 383 bool m_bVoidExtentHDR = false;
401 384
402 uint32_t GetPackedBitSize() const { 385 u32 GetPackedBitSize() const {
403 // How many indices do we have? 386 // How many indices do we have?
404 uint32_t nIdxs = m_Height * m_Width; 387 u32 nIdxs = m_Height * m_Width;
405 if (m_bDualPlane) { 388 if (m_bDualPlane) {
406 nIdxs *= 2; 389 nIdxs *= 2;
407 } 390 }
408 391
409 return IntegerEncodedValue::CreateEncoding(m_MaxWeight).GetBitLength(nIdxs); 392 return EncodingsValues[m_MaxWeight].GetBitLength(nIdxs);
410 } 393 }
411 394
412 uint32_t GetNumWeightValues() const { 395 u32 GetNumWeightValues() const {
413 uint32_t ret = m_Width * m_Height; 396 u32 ret = m_Width * m_Height;
414 if (m_bDualPlane) { 397 if (m_bDualPlane) {
415 ret *= 2; 398 ret *= 2;
416 } 399 }
@@ -422,7 +405,7 @@ static TexelWeightParams DecodeBlockInfo(InputBitStream& strm) {
422 TexelWeightParams params; 405 TexelWeightParams params;
423 406
424 // Read the entire block mode all at once 407 // Read the entire block mode all at once
425 uint16_t modeBits = static_cast<uint16_t>(strm.ReadBits(11)); 408 u16 modeBits = static_cast<u16>(strm.ReadBits<11>());
426 409
427 // Does this match the void extent block mode? 410 // Does this match the void extent block mode?
428 if ((modeBits & 0x01FF) == 0x1FC) { 411 if ((modeBits & 0x01FF) == 0x1FC) {
@@ -457,7 +440,7 @@ static TexelWeightParams DecodeBlockInfo(InputBitStream& strm) {
457 // of the block mode. Layout is determined by a number 440 // of the block mode. Layout is determined by a number
458 // between 0 and 9 corresponding to table C.2.8 of the 441 // between 0 and 9 corresponding to table C.2.8 of the
459 // ASTC spec. 442 // ASTC spec.
460 uint32_t layout = 0; 443 u32 layout = 0;
461 444
462 if ((modeBits & 0x1) || (modeBits & 0x2)) { 445 if ((modeBits & 0x1) || (modeBits & 0x2)) {
463 // layout is in [0-4] 446 // layout is in [0-4]
@@ -509,7 +492,7 @@ static TexelWeightParams DecodeBlockInfo(InputBitStream& strm) {
509 assert(layout < 10); 492 assert(layout < 10);
510 493
511 // Determine R 494 // Determine R
512 uint32_t R = !!(modeBits & 0x10); 495 u32 R = !!(modeBits & 0x10);
513 if (layout < 5) { 496 if (layout < 5) {
514 R |= (modeBits & 0x3) << 1; 497 R |= (modeBits & 0x3) << 1;
515 } else { 498 } else {
@@ -520,54 +503,54 @@ static TexelWeightParams DecodeBlockInfo(InputBitStream& strm) {
520 // Determine width & height 503 // Determine width & height
521 switch (layout) { 504 switch (layout) {
522 case 0: { 505 case 0: {
523 uint32_t A = (modeBits >> 5) & 0x3; 506 u32 A = (modeBits >> 5) & 0x3;
524 uint32_t B = (modeBits >> 7) & 0x3; 507 u32 B = (modeBits >> 7) & 0x3;
525 params.m_Width = B + 4; 508 params.m_Width = B + 4;
526 params.m_Height = A + 2; 509 params.m_Height = A + 2;
527 break; 510 break;
528 } 511 }
529 512
530 case 1: { 513 case 1: {
531 uint32_t A = (modeBits >> 5) & 0x3; 514 u32 A = (modeBits >> 5) & 0x3;
532 uint32_t B = (modeBits >> 7) & 0x3; 515 u32 B = (modeBits >> 7) & 0x3;
533 params.m_Width = B + 8; 516 params.m_Width = B + 8;
534 params.m_Height = A + 2; 517 params.m_Height = A + 2;
535 break; 518 break;
536 } 519 }
537 520
538 case 2: { 521 case 2: {
539 uint32_t A = (modeBits >> 5) & 0x3; 522 u32 A = (modeBits >> 5) & 0x3;
540 uint32_t B = (modeBits >> 7) & 0x3; 523 u32 B = (modeBits >> 7) & 0x3;
541 params.m_Width = A + 2; 524 params.m_Width = A + 2;
542 params.m_Height = B + 8; 525 params.m_Height = B + 8;
543 break; 526 break;
544 } 527 }
545 528
546 case 3: { 529 case 3: {
547 uint32_t A = (modeBits >> 5) & 0x3; 530 u32 A = (modeBits >> 5) & 0x3;
548 uint32_t B = (modeBits >> 7) & 0x1; 531 u32 B = (modeBits >> 7) & 0x1;
549 params.m_Width = A + 2; 532 params.m_Width = A + 2;
550 params.m_Height = B + 6; 533 params.m_Height = B + 6;
551 break; 534 break;
552 } 535 }
553 536
554 case 4: { 537 case 4: {
555 uint32_t A = (modeBits >> 5) & 0x3; 538 u32 A = (modeBits >> 5) & 0x3;
556 uint32_t B = (modeBits >> 7) & 0x1; 539 u32 B = (modeBits >> 7) & 0x1;
557 params.m_Width = B + 2; 540 params.m_Width = B + 2;
558 params.m_Height = A + 2; 541 params.m_Height = A + 2;
559 break; 542 break;
560 } 543 }
561 544
562 case 5: { 545 case 5: {
563 uint32_t A = (modeBits >> 5) & 0x3; 546 u32 A = (modeBits >> 5) & 0x3;
564 params.m_Width = 12; 547 params.m_Width = 12;
565 params.m_Height = A + 2; 548 params.m_Height = A + 2;
566 break; 549 break;
567 } 550 }
568 551
569 case 6: { 552 case 6: {
570 uint32_t A = (modeBits >> 5) & 0x3; 553 u32 A = (modeBits >> 5) & 0x3;
571 params.m_Width = A + 2; 554 params.m_Width = A + 2;
572 params.m_Height = 12; 555 params.m_Height = 12;
573 break; 556 break;
@@ -586,15 +569,15 @@ static TexelWeightParams DecodeBlockInfo(InputBitStream& strm) {
586 } 569 }
587 570
588 case 9: { 571 case 9: {
589 uint32_t A = (modeBits >> 5) & 0x3; 572 u32 A = (modeBits >> 5) & 0x3;
590 uint32_t B = (modeBits >> 9) & 0x3; 573 u32 B = (modeBits >> 9) & 0x3;
591 params.m_Width = A + 6; 574 params.m_Width = A + 6;
592 params.m_Height = B + 6; 575 params.m_Height = B + 6;
593 break; 576 break;
594 } 577 }
595 578
596 default: 579 default:
597 assert(!"Don't know this layout..."); 580 assert(false && "Don't know this layout...");
598 params.m_bError = true; 581 params.m_bError = true;
599 break; 582 break;
600 } 583 }
@@ -605,10 +588,10 @@ static TexelWeightParams DecodeBlockInfo(InputBitStream& strm) {
605 bool H = (layout != 9) && (modeBits & 0x200); 588 bool H = (layout != 9) && (modeBits & 0x200);
606 589
607 if (H) { 590 if (H) {
608 const uint32_t maxWeights[6] = {9, 11, 15, 19, 23, 31}; 591 const u32 maxWeights[6] = {9, 11, 15, 19, 23, 31};
609 params.m_MaxWeight = maxWeights[R - 2]; 592 params.m_MaxWeight = maxWeights[R - 2];
610 } else { 593 } else {
611 const uint32_t maxWeights[6] = {1, 2, 3, 4, 5, 7}; 594 const u32 maxWeights[6] = {1, 2, 3, 4, 5, 7};
612 params.m_MaxWeight = maxWeights[R - 2]; 595 params.m_MaxWeight = maxWeights[R - 2];
613 } 596 }
614 597
@@ -617,32 +600,32 @@ static TexelWeightParams DecodeBlockInfo(InputBitStream& strm) {
617 return params; 600 return params;
618} 601}
619 602
620static void FillVoidExtentLDR(InputBitStream& strm, uint32_t* const outBuf, uint32_t blockWidth, 603static void FillVoidExtentLDR(InputBitStream& strm, u32* const outBuf, u32 blockWidth,
621 uint32_t blockHeight) { 604 u32 blockHeight) {
622 // Don't actually care about the void extent, just read the bits... 605 // Don't actually care about the void extent, just read the bits...
623 for (int i = 0; i < 4; ++i) { 606 for (s32 i = 0; i < 4; ++i) {
624 strm.ReadBits(13); 607 strm.ReadBits<13>();
625 } 608 }
626 609
627 // Decode the RGBA components and renormalize them to the range [0, 255] 610 // Decode the RGBA components and renormalize them to the range [0, 255]
628 uint16_t r = static_cast<uint16_t>(strm.ReadBits(16)); 611 u16 r = static_cast<u16>(strm.ReadBits<16>());
629 uint16_t g = static_cast<uint16_t>(strm.ReadBits(16)); 612 u16 g = static_cast<u16>(strm.ReadBits<16>());
630 uint16_t b = static_cast<uint16_t>(strm.ReadBits(16)); 613 u16 b = static_cast<u16>(strm.ReadBits<16>());
631 uint16_t a = static_cast<uint16_t>(strm.ReadBits(16)); 614 u16 a = static_cast<u16>(strm.ReadBits<16>());
632 615
633 uint32_t rgba = (r >> 8) | (g & 0xFF00) | (static_cast<uint32_t>(b) & 0xFF00) << 8 | 616 u32 rgba = (r >> 8) | (g & 0xFF00) | (static_cast<u32>(b) & 0xFF00) << 8 |
634 (static_cast<uint32_t>(a) & 0xFF00) << 16; 617 (static_cast<u32>(a) & 0xFF00) << 16;
635 618
636 for (uint32_t j = 0; j < blockHeight; j++) { 619 for (u32 j = 0; j < blockHeight; j++) {
637 for (uint32_t i = 0; i < blockWidth; i++) { 620 for (u32 i = 0; i < blockWidth; i++) {
638 outBuf[j * blockWidth + i] = rgba; 621 outBuf[j * blockWidth + i] = rgba;
639 } 622 }
640 } 623 }
641} 624}
642 625
643static void FillError(uint32_t* outBuf, uint32_t blockWidth, uint32_t blockHeight) { 626static void FillError(u32* outBuf, u32 blockWidth, u32 blockHeight) {
644 for (uint32_t j = 0; j < blockHeight; j++) { 627 for (u32 j = 0; j < blockHeight; j++) {
645 for (uint32_t i = 0; i < blockWidth; i++) { 628 for (u32 i = 0; i < blockWidth; i++) {
646 outBuf[j * blockWidth + i] = 0xFFFF00FF; 629 outBuf[j * blockWidth + i] = 0xFFFF00FF;
647 } 630 }
648 } 631 }
@@ -651,18 +634,18 @@ static void FillError(uint32_t* outBuf, uint32_t blockWidth, uint32_t blockHeigh
651// Replicates low numBits such that [(toBit - 1):(toBit - 1 - fromBit)] 634// Replicates low numBits such that [(toBit - 1):(toBit - 1 - fromBit)]
652// is the same as [(numBits - 1):0] and repeats all the way down. 635// is the same as [(numBits - 1):0] and repeats all the way down.
653template <typename IntType> 636template <typename IntType>
654static IntType Replicate(const IntType& val, uint32_t numBits, uint32_t toBit) { 637static IntType Replicate(IntType val, u32 numBits, u32 toBit) {
655 if (numBits == 0) 638 if (numBits == 0)
656 return 0; 639 return 0;
657 if (toBit == 0) 640 if (toBit == 0)
658 return 0; 641 return 0;
659 IntType v = val & static_cast<IntType>((1 << numBits) - 1); 642 IntType v = val & static_cast<IntType>((1 << numBits) - 1);
660 IntType res = v; 643 IntType res = v;
661 uint32_t reslen = numBits; 644 u32 reslen = numBits;
662 while (reslen < toBit) { 645 while (reslen < toBit) {
663 uint32_t comp = 0; 646 u32 comp = 0;
664 if (numBits > toBit - reslen) { 647 if (numBits > toBit - reslen) {
665 uint32_t newshift = toBit - reslen; 648 u32 newshift = toBit - reslen;
666 comp = numBits - newshift; 649 comp = numBits - newshift;
667 numBits = newshift; 650 numBits = newshift;
668 } 651 }
@@ -675,14 +658,14 @@ static IntType Replicate(const IntType& val, uint32_t numBits, uint32_t toBit) {
675 658
676class Pixel { 659class Pixel {
677protected: 660protected:
678 using ChannelType = int16_t; 661 using ChannelType = s16;
679 uint8_t m_BitDepth[4] = {8, 8, 8, 8}; 662 u8 m_BitDepth[4] = {8, 8, 8, 8};
680 int16_t color[4] = {}; 663 s16 color[4] = {};
681 664
682public: 665public:
683 Pixel() = default; 666 Pixel() = default;
684 Pixel(uint32_t a, uint32_t r, uint32_t g, uint32_t b, unsigned bitDepth = 8) 667 Pixel(u32 a, u32 r, u32 g, u32 b, u32 bitDepth = 8)
685 : m_BitDepth{uint8_t(bitDepth), uint8_t(bitDepth), uint8_t(bitDepth), uint8_t(bitDepth)}, 668 : m_BitDepth{u8(bitDepth), u8(bitDepth), u8(bitDepth), u8(bitDepth)},
686 color{static_cast<ChannelType>(a), static_cast<ChannelType>(r), 669 color{static_cast<ChannelType>(a), static_cast<ChannelType>(r),
687 static_cast<ChannelType>(g), static_cast<ChannelType>(b)} {} 670 static_cast<ChannelType>(g), static_cast<ChannelType>(b)} {}
688 671
@@ -691,22 +674,22 @@ public:
691 // significant bits when going from larger to smaller bit depth 674 // significant bits when going from larger to smaller bit depth
692 // or by repeating the most significant bits when going from 675 // or by repeating the most significant bits when going from
693 // smaller to larger bit depths. 676 // smaller to larger bit depths.
694 void ChangeBitDepth(const uint8_t (&depth)[4]) { 677 void ChangeBitDepth(const u8 (&depth)[4]) {
695 for (uint32_t i = 0; i < 4; i++) { 678 for (u32 i = 0; i < 4; i++) {
696 Component(i) = ChangeBitDepth(Component(i), m_BitDepth[i], depth[i]); 679 Component(i) = ChangeBitDepth(Component(i), m_BitDepth[i], depth[i]);
697 m_BitDepth[i] = depth[i]; 680 m_BitDepth[i] = depth[i];
698 } 681 }
699 } 682 }
700 683
701 template <typename IntType> 684 template <typename IntType>
702 static float ConvertChannelToFloat(IntType channel, uint8_t bitDepth) { 685 static float ConvertChannelToFloat(IntType channel, u8 bitDepth) {
703 float denominator = static_cast<float>((1 << bitDepth) - 1); 686 float denominator = static_cast<float>((1 << bitDepth) - 1);
704 return static_cast<float>(channel) / denominator; 687 return static_cast<float>(channel) / denominator;
705 } 688 }
706 689
707 // Changes the bit depth of a single component. See the comment 690 // Changes the bit depth of a single component. See the comment
708 // above for how we do this. 691 // above for how we do this.
709 static ChannelType ChangeBitDepth(Pixel::ChannelType val, uint8_t oldDepth, uint8_t newDepth) { 692 static ChannelType ChangeBitDepth(Pixel::ChannelType val, u8 oldDepth, u8 newDepth) {
710 assert(newDepth <= 8); 693 assert(newDepth <= 8);
711 assert(oldDepth <= 8); 694 assert(oldDepth <= 8);
712 695
@@ -722,16 +705,15 @@ public:
722 if (newDepth == 0) { 705 if (newDepth == 0) {
723 return 0xFF; 706 return 0xFF;
724 } else { 707 } else {
725 uint8_t bitsWasted = static_cast<uint8_t>(oldDepth - newDepth); 708 u8 bitsWasted = static_cast<u8>(oldDepth - newDepth);
726 uint16_t v = static_cast<uint16_t>(val); 709 u16 v = static_cast<u16>(val);
727 v = static_cast<uint16_t>((v + (1 << (bitsWasted - 1))) >> bitsWasted); 710 v = static_cast<u16>((v + (1 << (bitsWasted - 1))) >> bitsWasted);
728 v = ::std::min<uint16_t>(::std::max<uint16_t>(0, v), 711 v = ::std::min<u16>(::std::max<u16>(0, v), static_cast<u16>((1 << newDepth) - 1));
729 static_cast<uint16_t>((1 << newDepth) - 1)); 712 return static_cast<u8>(v);
730 return static_cast<uint8_t>(v);
731 } 713 }
732 } 714 }
733 715
734 assert(!"We shouldn't get here."); 716 assert(false && "We shouldn't get here.");
735 return 0; 717 return 0;
736 } 718 }
737 719
@@ -759,15 +741,15 @@ public:
759 ChannelType& B() { 741 ChannelType& B() {
760 return color[3]; 742 return color[3];
761 } 743 }
762 const ChannelType& Component(uint32_t idx) const { 744 const ChannelType& Component(u32 idx) const {
763 return color[idx]; 745 return color[idx];
764 } 746 }
765 ChannelType& Component(uint32_t idx) { 747 ChannelType& Component(u32 idx) {
766 return color[idx]; 748 return color[idx];
767 } 749 }
768 750
769 void GetBitDepth(uint8_t (&outDepth)[4]) const { 751 void GetBitDepth(u8 (&outDepth)[4]) const {
770 for (int i = 0; i < 4; i++) { 752 for (s32 i = 0; i < 4; i++) {
771 outDepth[i] = m_BitDepth[i]; 753 outDepth[i] = m_BitDepth[i];
772 } 754 }
773 } 755 }
@@ -776,12 +758,12 @@ public:
776 // and then pack each channel into an R8G8B8A8 32-bit integer. We assume 758 // and then pack each channel into an R8G8B8A8 32-bit integer. We assume
777 // that the architecture is little-endian, so the alpha channel will end 759 // that the architecture is little-endian, so the alpha channel will end
778 // up in the most-significant byte. 760 // up in the most-significant byte.
779 uint32_t Pack() const { 761 u32 Pack() const {
780 Pixel eightBit(*this); 762 Pixel eightBit(*this);
781 const uint8_t eightBitDepth[4] = {8, 8, 8, 8}; 763 const u8 eightBitDepth[4] = {8, 8, 8, 8};
782 eightBit.ChangeBitDepth(eightBitDepth); 764 eightBit.ChangeBitDepth(eightBitDepth);
783 765
784 uint32_t r = 0; 766 u32 r = 0;
785 r |= eightBit.A(); 767 r |= eightBit.A();
786 r <<= 8; 768 r <<= 8;
787 r |= eightBit.B(); 769 r |= eightBit.B();
@@ -794,7 +776,7 @@ public:
794 776
795 // Clamps the pixel to the range [0,255] 777 // Clamps the pixel to the range [0,255]
796 void ClampByte() { 778 void ClampByte() {
797 for (uint32_t i = 0; i < 4; i++) { 779 for (u32 i = 0; i < 4; i++) {
798 color[i] = (color[i] < 0) ? 0 : ((color[i] > 255) ? 255 : color[i]); 780 color[i] = (color[i] < 0) ? 0 : ((color[i] > 255) ? 255 : color[i]);
799 } 781 }
800 } 782 }
@@ -804,24 +786,24 @@ public:
804 } 786 }
805}; 787};
806 788
807static void DecodeColorValues(uint32_t* out, uint8_t* data, const uint32_t* modes, 789static void DecodeColorValues(u32* out, u8* data, const u32* modes, const u32 nPartitions,
808 const uint32_t nPartitions, const uint32_t nBitsForColorData) { 790 const u32 nBitsForColorData) {
809 // First figure out how many color values we have 791 // First figure out how many color values we have
810 uint32_t nValues = 0; 792 u32 nValues = 0;
811 for (uint32_t i = 0; i < nPartitions; i++) { 793 for (u32 i = 0; i < nPartitions; i++) {
812 nValues += ((modes[i] >> 2) + 1) << 1; 794 nValues += ((modes[i] >> 2) + 1) << 1;
813 } 795 }
814 796
815 // Then based on the number of values and the remaining number of bits, 797 // Then based on the number of values and the remaining number of bits,
816 // figure out the max value for each of them... 798 // figure out the max value for each of them...
817 uint32_t range = 256; 799 u32 range = 256;
818 while (--range > 0) { 800 while (--range > 0) {
819 IntegerEncodedValue val = IntegerEncodedValue::CreateEncoding(range); 801 IntegerEncodedValue val = EncodingsValues[range];
820 uint32_t bitLength = val.GetBitLength(nValues); 802 u32 bitLength = val.GetBitLength(nValues);
821 if (bitLength <= nBitsForColorData) { 803 if (bitLength <= nBitsForColorData) {
822 // Find the smallest possible range that matches the given encoding 804 // Find the smallest possible range that matches the given encoding
823 while (--range > 0) { 805 while (--range > 0) {
824 IntegerEncodedValue newval = IntegerEncodedValue::CreateEncoding(range); 806 IntegerEncodedValue newval = EncodingsValues[range];
825 if (!newval.MatchesEncoding(val)) { 807 if (!newval.MatchesEncoding(val)) {
826 break; 808 break;
827 } 809 }
@@ -835,12 +817,14 @@ static void DecodeColorValues(uint32_t* out, uint8_t* data, const uint32_t* mode
835 817
836 // We now have enough to decode our integer sequence. 818 // We now have enough to decode our integer sequence.
837 std::vector<IntegerEncodedValue> decodedColorValues; 819 std::vector<IntegerEncodedValue> decodedColorValues;
820 decodedColorValues.reserve(32);
821
838 InputBitStream colorStream(data); 822 InputBitStream colorStream(data);
839 IntegerEncodedValue::DecodeIntegerSequence(decodedColorValues, colorStream, range, nValues); 823 DecodeIntegerSequence(decodedColorValues, colorStream, range, nValues);
840 824
841 // Once we have the decoded values, we need to dequantize them to the 0-255 range 825 // Once we have the decoded values, we need to dequantize them to the 0-255 range
842 // This procedure is outlined in ASTC spec C.2.13 826 // This procedure is outlined in ASTC spec C.2.13
843 uint32_t outIdx = 0; 827 u32 outIdx = 0;
844 for (auto itr = decodedColorValues.begin(); itr != decodedColorValues.end(); ++itr) { 828 for (auto itr = decodedColorValues.begin(); itr != decodedColorValues.end(); ++itr) {
845 // Have we already decoded all that we need? 829 // Have we already decoded all that we need?
846 if (outIdx >= nValues) { 830 if (outIdx >= nValues) {
@@ -848,25 +832,25 @@ static void DecodeColorValues(uint32_t* out, uint8_t* data, const uint32_t* mode
848 } 832 }
849 833
850 const IntegerEncodedValue& val = *itr; 834 const IntegerEncodedValue& val = *itr;
851 uint32_t bitlen = val.BaseBitLength(); 835 u32 bitlen = val.num_bits;
852 uint32_t bitval = val.GetBitValue(); 836 u32 bitval = val.bit_value;
853 837
854 assert(bitlen >= 1); 838 assert(bitlen >= 1);
855 839
856 uint32_t A = 0, B = 0, C = 0, D = 0; 840 u32 A = 0, B = 0, C = 0, D = 0;
857 // A is just the lsb replicated 9 times. 841 // A is just the lsb replicated 9 times.
858 A = Replicate(bitval & 1, 1, 9); 842 A = Replicate(bitval & 1, 1, 9);
859 843
860 switch (val.GetEncoding()) { 844 switch (val.encoding) {
861 // Replicate bits 845 // Replicate bits
862 case eIntegerEncoding_JustBits: 846 case IntegerEncoding::JustBits:
863 out[outIdx++] = Replicate(bitval, bitlen, 8); 847 out[outIdx++] = Replicate(bitval, bitlen, 8);
864 break; 848 break;
865 849
866 // Use algorithm in C.2.13 850 // Use algorithm in C.2.13
867 case eIntegerEncoding_Trit: { 851 case IntegerEncoding::Trit: {
868 852
869 D = val.GetTritValue(); 853 D = val.trit_value;
870 854
871 switch (bitlen) { 855 switch (bitlen) {
872 case 1: { 856 case 1: {
@@ -876,48 +860,48 @@ static void DecodeColorValues(uint32_t* out, uint8_t* data, const uint32_t* mode
876 case 2: { 860 case 2: {
877 C = 93; 861 C = 93;
878 // B = b000b0bb0 862 // B = b000b0bb0
879 uint32_t b = (bitval >> 1) & 1; 863 u32 b = (bitval >> 1) & 1;
880 B = (b << 8) | (b << 4) | (b << 2) | (b << 1); 864 B = (b << 8) | (b << 4) | (b << 2) | (b << 1);
881 } break; 865 } break;
882 866
883 case 3: { 867 case 3: {
884 C = 44; 868 C = 44;
885 // B = cb000cbcb 869 // B = cb000cbcb
886 uint32_t cb = (bitval >> 1) & 3; 870 u32 cb = (bitval >> 1) & 3;
887 B = (cb << 7) | (cb << 2) | cb; 871 B = (cb << 7) | (cb << 2) | cb;
888 } break; 872 } break;
889 873
890 case 4: { 874 case 4: {
891 C = 22; 875 C = 22;
892 // B = dcb000dcb 876 // B = dcb000dcb
893 uint32_t dcb = (bitval >> 1) & 7; 877 u32 dcb = (bitval >> 1) & 7;
894 B = (dcb << 6) | dcb; 878 B = (dcb << 6) | dcb;
895 } break; 879 } break;
896 880
897 case 5: { 881 case 5: {
898 C = 11; 882 C = 11;
899 // B = edcb000ed 883 // B = edcb000ed
900 uint32_t edcb = (bitval >> 1) & 0xF; 884 u32 edcb = (bitval >> 1) & 0xF;
901 B = (edcb << 5) | (edcb >> 2); 885 B = (edcb << 5) | (edcb >> 2);
902 } break; 886 } break;
903 887
904 case 6: { 888 case 6: {
905 C = 5; 889 C = 5;
906 // B = fedcb000f 890 // B = fedcb000f
907 uint32_t fedcb = (bitval >> 1) & 0x1F; 891 u32 fedcb = (bitval >> 1) & 0x1F;
908 B = (fedcb << 4) | (fedcb >> 4); 892 B = (fedcb << 4) | (fedcb >> 4);
909 } break; 893 } break;
910 894
911 default: 895 default:
912 assert(!"Unsupported trit encoding for color values!"); 896 assert(false && "Unsupported trit encoding for color values!");
913 break; 897 break;
914 } // switch(bitlen) 898 } // switch(bitlen)
915 } // case eIntegerEncoding_Trit 899 } // case IntegerEncoding::Trit
916 break; 900 break;
917 901
918 case eIntegerEncoding_Quint: { 902 case IntegerEncoding::Qus32: {
919 903
920 D = val.GetQuintValue(); 904 D = val.qus32_value;
921 905
922 switch (bitlen) { 906 switch (bitlen) {
923 case 1: { 907 case 1: {
@@ -927,41 +911,41 @@ static void DecodeColorValues(uint32_t* out, uint8_t* data, const uint32_t* mode
927 case 2: { 911 case 2: {
928 C = 54; 912 C = 54;
929 // B = b0000bb00 913 // B = b0000bb00
930 uint32_t b = (bitval >> 1) & 1; 914 u32 b = (bitval >> 1) & 1;
931 B = (b << 8) | (b << 3) | (b << 2); 915 B = (b << 8) | (b << 3) | (b << 2);
932 } break; 916 } break;
933 917
934 case 3: { 918 case 3: {
935 C = 26; 919 C = 26;
936 // B = cb0000cbc 920 // B = cb0000cbc
937 uint32_t cb = (bitval >> 1) & 3; 921 u32 cb = (bitval >> 1) & 3;
938 B = (cb << 7) | (cb << 1) | (cb >> 1); 922 B = (cb << 7) | (cb << 1) | (cb >> 1);
939 } break; 923 } break;
940 924
941 case 4: { 925 case 4: {
942 C = 13; 926 C = 13;
943 // B = dcb0000dc 927 // B = dcb0000dc
944 uint32_t dcb = (bitval >> 1) & 7; 928 u32 dcb = (bitval >> 1) & 7;
945 B = (dcb << 6) | (dcb >> 1); 929 B = (dcb << 6) | (dcb >> 1);
946 } break; 930 } break;
947 931
948 case 5: { 932 case 5: {
949 C = 6; 933 C = 6;
950 // B = edcb0000e 934 // B = edcb0000e
951 uint32_t edcb = (bitval >> 1) & 0xF; 935 u32 edcb = (bitval >> 1) & 0xF;
952 B = (edcb << 5) | (edcb >> 3); 936 B = (edcb << 5) | (edcb >> 3);
953 } break; 937 } break;
954 938
955 default: 939 default:
956 assert(!"Unsupported quint encoding for color values!"); 940 assert(false && "Unsupported quint encoding for color values!");
957 break; 941 break;
958 } // switch(bitlen) 942 } // switch(bitlen)
959 } // case eIntegerEncoding_Quint 943 } // case IntegerEncoding::Qus32
960 break; 944 break;
961 } // switch(val.GetEncoding()) 945 } // switch(val.encoding)
962 946
963 if (val.GetEncoding() != eIntegerEncoding_JustBits) { 947 if (val.encoding != IntegerEncoding::JustBits) {
964 uint32_t T = D * C + B; 948 u32 T = D * C + B;
965 T ^= A; 949 T ^= A;
966 T = (A & 0x80) | (T >> 2); 950 T = (A & 0x80) | (T >> 2);
967 out[outIdx++] = T; 951 out[outIdx++] = T;
@@ -969,31 +953,31 @@ static void DecodeColorValues(uint32_t* out, uint8_t* data, const uint32_t* mode
969 } 953 }
970 954
971 // Make sure that each of our values is in the proper range... 955 // Make sure that each of our values is in the proper range...
972 for (uint32_t i = 0; i < nValues; i++) { 956 for (u32 i = 0; i < nValues; i++) {
973 assert(out[i] <= 255); 957 assert(out[i] <= 255);
974 } 958 }
975} 959}
976 960
977static uint32_t UnquantizeTexelWeight(const IntegerEncodedValue& val) { 961static u32 UnquantizeTexelWeight(const IntegerEncodedValue& val) {
978 uint32_t bitval = val.GetBitValue(); 962 u32 bitval = val.bit_value;
979 uint32_t bitlen = val.BaseBitLength(); 963 u32 bitlen = val.num_bits;
980 964
981 uint32_t A = Replicate(bitval & 1, 1, 7); 965 u32 A = Replicate(bitval & 1, 1, 7);
982 uint32_t B = 0, C = 0, D = 0; 966 u32 B = 0, C = 0, D = 0;
983 967
984 uint32_t result = 0; 968 u32 result = 0;
985 switch (val.GetEncoding()) { 969 switch (val.encoding) {
986 case eIntegerEncoding_JustBits: 970 case IntegerEncoding::JustBits:
987 result = Replicate(bitval, bitlen, 6); 971 result = Replicate(bitval, bitlen, 6);
988 break; 972 break;
989 973
990 case eIntegerEncoding_Trit: { 974 case IntegerEncoding::Trit: {
991 D = val.GetTritValue(); 975 D = val.trit_value;
992 assert(D < 3); 976 assert(D < 3);
993 977
994 switch (bitlen) { 978 switch (bitlen) {
995 case 0: { 979 case 0: {
996 uint32_t results[3] = {0, 32, 63}; 980 u32 results[3] = {0, 32, 63};
997 result = results[D]; 981 result = results[D];
998 } break; 982 } break;
999 983
@@ -1003,29 +987,29 @@ static uint32_t UnquantizeTexelWeight(const IntegerEncodedValue& val) {
1003 987
1004 case 2: { 988 case 2: {
1005 C = 23; 989 C = 23;
1006 uint32_t b = (bitval >> 1) & 1; 990 u32 b = (bitval >> 1) & 1;
1007 B = (b << 6) | (b << 2) | b; 991 B = (b << 6) | (b << 2) | b;
1008 } break; 992 } break;
1009 993
1010 case 3: { 994 case 3: {
1011 C = 11; 995 C = 11;
1012 uint32_t cb = (bitval >> 1) & 3; 996 u32 cb = (bitval >> 1) & 3;
1013 B = (cb << 5) | cb; 997 B = (cb << 5) | cb;
1014 } break; 998 } break;
1015 999
1016 default: 1000 default:
1017 assert(!"Invalid trit encoding for texel weight"); 1001 assert(false && "Invalid trit encoding for texel weight");
1018 break; 1002 break;
1019 } 1003 }
1020 } break; 1004 } break;
1021 1005
1022 case eIntegerEncoding_Quint: { 1006 case IntegerEncoding::Qus32: {
1023 D = val.GetQuintValue(); 1007 D = val.qus32_value;
1024 assert(D < 5); 1008 assert(D < 5);
1025 1009
1026 switch (bitlen) { 1010 switch (bitlen) {
1027 case 0: { 1011 case 0: {
1028 uint32_t results[5] = {0, 16, 32, 47, 63}; 1012 u32 results[5] = {0, 16, 32, 47, 63};
1029 result = results[D]; 1013 result = results[D];
1030 } break; 1014 } break;
1031 1015
@@ -1035,18 +1019,18 @@ static uint32_t UnquantizeTexelWeight(const IntegerEncodedValue& val) {
1035 1019
1036 case 2: { 1020 case 2: {
1037 C = 13; 1021 C = 13;
1038 uint32_t b = (bitval >> 1) & 1; 1022 u32 b = (bitval >> 1) & 1;
1039 B = (b << 6) | (b << 1); 1023 B = (b << 6) | (b << 1);
1040 } break; 1024 } break;
1041 1025
1042 default: 1026 default:
1043 assert(!"Invalid quint encoding for texel weight"); 1027 assert(false && "Invalid quint encoding for texel weight");
1044 break; 1028 break;
1045 } 1029 }
1046 } break; 1030 } break;
1047 } 1031 }
1048 1032
1049 if (val.GetEncoding() != eIntegerEncoding_JustBits && bitlen > 0) { 1033 if (val.encoding != IntegerEncoding::JustBits && bitlen > 0) {
1050 // Decode the value... 1034 // Decode the value...
1051 result = D * C + B; 1035 result = D * C + B;
1052 result ^= A; 1036 result ^= A;
@@ -1063,12 +1047,11 @@ static uint32_t UnquantizeTexelWeight(const IntegerEncodedValue& val) {
1063 return result; 1047 return result;
1064} 1048}
1065 1049
1066static void UnquantizeTexelWeights(uint32_t out[2][144], 1050static void UnquantizeTexelWeights(u32 out[2][144], const std::vector<IntegerEncodedValue>& weights,
1067 const std::vector<IntegerEncodedValue>& weights, 1051 const TexelWeightParams& params, const u32 blockWidth,
1068 const TexelWeightParams& params, const uint32_t blockWidth, 1052 const u32 blockHeight) {
1069 const uint32_t blockHeight) { 1053 u32 weightIdx = 0;
1070 uint32_t weightIdx = 0; 1054 u32 unquantized[2][144];
1071 uint32_t unquantized[2][144];
1072 1055
1073 for (auto itr = weights.begin(); itr != weights.end(); ++itr) { 1056 for (auto itr = weights.begin(); itr != weights.end(); ++itr) {
1074 unquantized[0][weightIdx] = UnquantizeTexelWeight(*itr); 1057 unquantized[0][weightIdx] = UnquantizeTexelWeight(*itr);
@@ -1086,34 +1069,34 @@ static void UnquantizeTexelWeights(uint32_t out[2][144],
1086 } 1069 }
1087 1070
1088 // Do infill if necessary (Section C.2.18) ... 1071 // Do infill if necessary (Section C.2.18) ...
1089 uint32_t Ds = (1024 + (blockWidth / 2)) / (blockWidth - 1); 1072 u32 Ds = (1024 + (blockWidth / 2)) / (blockWidth - 1);
1090 uint32_t Dt = (1024 + (blockHeight / 2)) / (blockHeight - 1); 1073 u32 Dt = (1024 + (blockHeight / 2)) / (blockHeight - 1);
1091 1074
1092 const uint32_t kPlaneScale = params.m_bDualPlane ? 2U : 1U; 1075 const u32 kPlaneScale = params.m_bDualPlane ? 2U : 1U;
1093 for (uint32_t plane = 0; plane < kPlaneScale; plane++) 1076 for (u32 plane = 0; plane < kPlaneScale; plane++)
1094 for (uint32_t t = 0; t < blockHeight; t++) 1077 for (u32 t = 0; t < blockHeight; t++)
1095 for (uint32_t s = 0; s < blockWidth; s++) { 1078 for (u32 s = 0; s < blockWidth; s++) {
1096 uint32_t cs = Ds * s; 1079 u32 cs = Ds * s;
1097 uint32_t ct = Dt * t; 1080 u32 ct = Dt * t;
1098 1081
1099 uint32_t gs = (cs * (params.m_Width - 1) + 32) >> 6; 1082 u32 gs = (cs * (params.m_Width - 1) + 32) >> 6;
1100 uint32_t gt = (ct * (params.m_Height - 1) + 32) >> 6; 1083 u32 gt = (ct * (params.m_Height - 1) + 32) >> 6;
1101 1084
1102 uint32_t js = gs >> 4; 1085 u32 js = gs >> 4;
1103 uint32_t fs = gs & 0xF; 1086 u32 fs = gs & 0xF;
1104 1087
1105 uint32_t jt = gt >> 4; 1088 u32 jt = gt >> 4;
1106 uint32_t ft = gt & 0x0F; 1089 u32 ft = gt & 0x0F;
1107 1090
1108 uint32_t w11 = (fs * ft + 8) >> 4; 1091 u32 w11 = (fs * ft + 8) >> 4;
1109 uint32_t w10 = ft - w11; 1092 u32 w10 = ft - w11;
1110 uint32_t w01 = fs - w11; 1093 u32 w01 = fs - w11;
1111 uint32_t w00 = 16 - fs - ft + w11; 1094 u32 w00 = 16 - fs - ft + w11;
1112 1095
1113 uint32_t v0 = js + jt * params.m_Width; 1096 u32 v0 = js + jt * params.m_Width;
1114 1097
1115#define FIND_TEXEL(tidx, bidx) \ 1098#define FIND_TEXEL(tidx, bidx) \
1116 uint32_t p##bidx = 0; \ 1099 u32 p##bidx = 0; \
1117 do { \ 1100 do { \
1118 if ((tidx) < (params.m_Width * params.m_Height)) { \ 1101 if ((tidx) < (params.m_Width * params.m_Height)) { \
1119 p##bidx = unquantized[plane][(tidx)]; \ 1102 p##bidx = unquantized[plane][(tidx)]; \
@@ -1133,7 +1116,7 @@ static void UnquantizeTexelWeights(uint32_t out[2][144],
1133} 1116}
1134 1117
1135// Transfers a bit as described in C.2.14 1118// Transfers a bit as described in C.2.14
1136static inline void BitTransferSigned(int32_t& a, int32_t& b) { 1119static inline void BitTransferSigned(s32& a, s32& b) {
1137 b >>= 1; 1120 b >>= 1;
1138 b |= a & 0x80; 1121 b |= a & 0x80;
1139 a >>= 1; 1122 a >>= 1;
@@ -1144,14 +1127,14 @@ static inline void BitTransferSigned(int32_t& a, int32_t& b) {
1144 1127
1145// Adds more precision to the blue channel as described 1128// Adds more precision to the blue channel as described
1146// in C.2.14 1129// in C.2.14
1147static inline Pixel BlueContract(int32_t a, int32_t r, int32_t g, int32_t b) { 1130static inline Pixel BlueContract(s32 a, s32 r, s32 g, s32 b) {
1148 return Pixel(static_cast<int16_t>(a), static_cast<int16_t>((r + b) >> 1), 1131 return Pixel(static_cast<s16>(a), static_cast<s16>((r + b) >> 1),
1149 static_cast<int16_t>((g + b) >> 1), static_cast<int16_t>(b)); 1132 static_cast<s16>((g + b) >> 1), static_cast<s16>(b));
1150} 1133}
1151 1134
1152// Partition selection functions as specified in 1135// Partition selection functions as specified in
1153// C.2.21 1136// C.2.21
1154static inline uint32_t hash52(uint32_t p) { 1137static inline u32 hash52(u32 p) {
1155 p ^= p >> 15; 1138 p ^= p >> 15;
1156 p -= p << 17; 1139 p -= p << 17;
1157 p += p << 7; 1140 p += p << 7;
@@ -1165,8 +1148,7 @@ static inline uint32_t hash52(uint32_t p) {
1165 return p; 1148 return p;
1166} 1149}
1167 1150
1168static uint32_t SelectPartition(int32_t seed, int32_t x, int32_t y, int32_t z, 1151static u32 SelectPartition(s32 seed, s32 x, s32 y, s32 z, s32 partitionCount, s32 smallBlock) {
1169 int32_t partitionCount, int32_t smallBlock) {
1170 if (1 == partitionCount) 1152 if (1 == partitionCount)
1171 return 0; 1153 return 0;
1172 1154
@@ -1178,34 +1160,34 @@ static uint32_t SelectPartition(int32_t seed, int32_t x, int32_t y, int32_t z,
1178 1160
1179 seed += (partitionCount - 1) * 1024; 1161 seed += (partitionCount - 1) * 1024;
1180 1162
1181 uint32_t rnum = hash52(static_cast<uint32_t>(seed)); 1163 u32 rnum = hash52(static_cast<u32>(seed));
1182 uint8_t seed1 = static_cast<uint8_t>(rnum & 0xF); 1164 u8 seed1 = static_cast<u8>(rnum & 0xF);
1183 uint8_t seed2 = static_cast<uint8_t>((rnum >> 4) & 0xF); 1165 u8 seed2 = static_cast<u8>((rnum >> 4) & 0xF);
1184 uint8_t seed3 = static_cast<uint8_t>((rnum >> 8) & 0xF); 1166 u8 seed3 = static_cast<u8>((rnum >> 8) & 0xF);
1185 uint8_t seed4 = static_cast<uint8_t>((rnum >> 12) & 0xF); 1167 u8 seed4 = static_cast<u8>((rnum >> 12) & 0xF);
1186 uint8_t seed5 = static_cast<uint8_t>((rnum >> 16) & 0xF); 1168 u8 seed5 = static_cast<u8>((rnum >> 16) & 0xF);
1187 uint8_t seed6 = static_cast<uint8_t>((rnum >> 20) & 0xF); 1169 u8 seed6 = static_cast<u8>((rnum >> 20) & 0xF);
1188 uint8_t seed7 = static_cast<uint8_t>((rnum >> 24) & 0xF); 1170 u8 seed7 = static_cast<u8>((rnum >> 24) & 0xF);
1189 uint8_t seed8 = static_cast<uint8_t>((rnum >> 28) & 0xF); 1171 u8 seed8 = static_cast<u8>((rnum >> 28) & 0xF);
1190 uint8_t seed9 = static_cast<uint8_t>((rnum >> 18) & 0xF); 1172 u8 seed9 = static_cast<u8>((rnum >> 18) & 0xF);
1191 uint8_t seed10 = static_cast<uint8_t>((rnum >> 22) & 0xF); 1173 u8 seed10 = static_cast<u8>((rnum >> 22) & 0xF);
1192 uint8_t seed11 = static_cast<uint8_t>((rnum >> 26) & 0xF); 1174 u8 seed11 = static_cast<u8>((rnum >> 26) & 0xF);
1193 uint8_t seed12 = static_cast<uint8_t>(((rnum >> 30) | (rnum << 2)) & 0xF); 1175 u8 seed12 = static_cast<u8>(((rnum >> 30) | (rnum << 2)) & 0xF);
1194 1176
1195 seed1 = static_cast<uint8_t>(seed1 * seed1); 1177 seed1 = static_cast<u8>(seed1 * seed1);
1196 seed2 = static_cast<uint8_t>(seed2 * seed2); 1178 seed2 = static_cast<u8>(seed2 * seed2);
1197 seed3 = static_cast<uint8_t>(seed3 * seed3); 1179 seed3 = static_cast<u8>(seed3 * seed3);
1198 seed4 = static_cast<uint8_t>(seed4 * seed4); 1180 seed4 = static_cast<u8>(seed4 * seed4);
1199 seed5 = static_cast<uint8_t>(seed5 * seed5); 1181 seed5 = static_cast<u8>(seed5 * seed5);
1200 seed6 = static_cast<uint8_t>(seed6 * seed6); 1182 seed6 = static_cast<u8>(seed6 * seed6);
1201 seed7 = static_cast<uint8_t>(seed7 * seed7); 1183 seed7 = static_cast<u8>(seed7 * seed7);
1202 seed8 = static_cast<uint8_t>(seed8 * seed8); 1184 seed8 = static_cast<u8>(seed8 * seed8);
1203 seed9 = static_cast<uint8_t>(seed9 * seed9); 1185 seed9 = static_cast<u8>(seed9 * seed9);
1204 seed10 = static_cast<uint8_t>(seed10 * seed10); 1186 seed10 = static_cast<u8>(seed10 * seed10);
1205 seed11 = static_cast<uint8_t>(seed11 * seed11); 1187 seed11 = static_cast<u8>(seed11 * seed11);
1206 seed12 = static_cast<uint8_t>(seed12 * seed12); 1188 seed12 = static_cast<u8>(seed12 * seed12);
1207 1189
1208 int32_t sh1, sh2, sh3; 1190 s32 sh1, sh2, sh3;
1209 if (seed & 1) { 1191 if (seed & 1) {
1210 sh1 = (seed & 2) ? 4 : 5; 1192 sh1 = (seed & 2) ? 4 : 5;
1211 sh2 = (partitionCount == 3) ? 6 : 5; 1193 sh2 = (partitionCount == 3) ? 6 : 5;
@@ -1215,23 +1197,23 @@ static uint32_t SelectPartition(int32_t seed, int32_t x, int32_t y, int32_t z,
1215 } 1197 }
1216 sh3 = (seed & 0x10) ? sh1 : sh2; 1198 sh3 = (seed & 0x10) ? sh1 : sh2;
1217 1199
1218 seed1 = static_cast<uint8_t>(seed1 >> sh1); 1200 seed1 = static_cast<u8>(seed1 >> sh1);
1219 seed2 = static_cast<uint8_t>(seed2 >> sh2); 1201 seed2 = static_cast<u8>(seed2 >> sh2);
1220 seed3 = static_cast<uint8_t>(seed3 >> sh1); 1202 seed3 = static_cast<u8>(seed3 >> sh1);
1221 seed4 = static_cast<uint8_t>(seed4 >> sh2); 1203 seed4 = static_cast<u8>(seed4 >> sh2);
1222 seed5 = static_cast<uint8_t>(seed5 >> sh1); 1204 seed5 = static_cast<u8>(seed5 >> sh1);
1223 seed6 = static_cast<uint8_t>(seed6 >> sh2); 1205 seed6 = static_cast<u8>(seed6 >> sh2);
1224 seed7 = static_cast<uint8_t>(seed7 >> sh1); 1206 seed7 = static_cast<u8>(seed7 >> sh1);
1225 seed8 = static_cast<uint8_t>(seed8 >> sh2); 1207 seed8 = static_cast<u8>(seed8 >> sh2);
1226 seed9 = static_cast<uint8_t>(seed9 >> sh3); 1208 seed9 = static_cast<u8>(seed9 >> sh3);
1227 seed10 = static_cast<uint8_t>(seed10 >> sh3); 1209 seed10 = static_cast<u8>(seed10 >> sh3);
1228 seed11 = static_cast<uint8_t>(seed11 >> sh3); 1210 seed11 = static_cast<u8>(seed11 >> sh3);
1229 seed12 = static_cast<uint8_t>(seed12 >> sh3); 1211 seed12 = static_cast<u8>(seed12 >> sh3);
1230 1212
1231 int32_t a = seed1 * x + seed2 * y + seed11 * z + (rnum >> 14); 1213 s32 a = seed1 * x + seed2 * y + seed11 * z + (rnum >> 14);
1232 int32_t b = seed3 * x + seed4 * y + seed12 * z + (rnum >> 10); 1214 s32 b = seed3 * x + seed4 * y + seed12 * z + (rnum >> 10);
1233 int32_t c = seed5 * x + seed6 * y + seed9 * z + (rnum >> 6); 1215 s32 c = seed5 * x + seed6 * y + seed9 * z + (rnum >> 6);
1234 int32_t d = seed7 * x + seed8 * y + seed10 * z + (rnum >> 2); 1216 s32 d = seed7 * x + seed8 * y + seed10 * z + (rnum >> 2);
1235 1217
1236 a &= 0x3F; 1218 a &= 0x3F;
1237 b &= 0x3F; 1219 b &= 0x3F;
@@ -1252,27 +1234,26 @@ static uint32_t SelectPartition(int32_t seed, int32_t x, int32_t y, int32_t z,
1252 return 3; 1234 return 3;
1253} 1235}
1254 1236
1255static inline uint32_t Select2DPartition(int32_t seed, int32_t x, int32_t y, int32_t partitionCount, 1237static inline u32 Select2DPartition(s32 seed, s32 x, s32 y, s32 partitionCount, s32 smallBlock) {
1256 int32_t smallBlock) {
1257 return SelectPartition(seed, x, y, 0, partitionCount, smallBlock); 1238 return SelectPartition(seed, x, y, 0, partitionCount, smallBlock);
1258} 1239}
1259 1240
1260// Section C.2.14 1241// Section C.2.14
1261static void ComputeEndpoints(Pixel& ep1, Pixel& ep2, const uint32_t*& colorValues, 1242static void ComputeEndpos32s(Pixel& ep1, Pixel& ep2, const u32*& colorValues,
1262 uint32_t colorEndpointMode) { 1243 u32 colorEndpos32Mode) {
1263#define READ_UINT_VALUES(N) \ 1244#define READ_UINT_VALUES(N) \
1264 uint32_t v[N]; \ 1245 u32 v[N]; \
1265 for (uint32_t i = 0; i < N; i++) { \ 1246 for (u32 i = 0; i < N; i++) { \
1266 v[i] = *(colorValues++); \ 1247 v[i] = *(colorValues++); \
1267 } 1248 }
1268 1249
1269#define READ_INT_VALUES(N) \ 1250#define READ_INT_VALUES(N) \
1270 int32_t v[N]; \ 1251 s32 v[N]; \
1271 for (uint32_t i = 0; i < N; i++) { \ 1252 for (u32 i = 0; i < N; i++) { \
1272 v[i] = static_cast<int32_t>(*(colorValues++)); \ 1253 v[i] = static_cast<s32>(*(colorValues++)); \
1273 } 1254 }
1274 1255
1275 switch (colorEndpointMode) { 1256 switch (colorEndpos32Mode) {
1276 case 0: { 1257 case 0: {
1277 READ_UINT_VALUES(2) 1258 READ_UINT_VALUES(2)
1278 ep1 = Pixel(0xFF, v[0], v[0], v[0]); 1259 ep1 = Pixel(0xFF, v[0], v[0], v[0]);
@@ -1281,8 +1262,8 @@ static void ComputeEndpoints(Pixel& ep1, Pixel& ep2, const uint32_t*& colorValue
1281 1262
1282 case 1: { 1263 case 1: {
1283 READ_UINT_VALUES(2) 1264 READ_UINT_VALUES(2)
1284 uint32_t L0 = (v[0] >> 2) | (v[1] & 0xC0); 1265 u32 L0 = (v[0] >> 2) | (v[1] & 0xC0);
1285 uint32_t L1 = std::max(L0 + (v[1] & 0x3F), 0xFFU); 1266 u32 L1 = std::max(L0 + (v[1] & 0x3F), 0xFFU);
1286 ep1 = Pixel(0xFF, L0, L0, L0); 1267 ep1 = Pixel(0xFF, L0, L0, L0);
1287 ep2 = Pixel(0xFF, L1, L1, L1); 1268 ep2 = Pixel(0xFF, L1, L1, L1);
1288 } break; 1269 } break;
@@ -1371,7 +1352,7 @@ static void ComputeEndpoints(Pixel& ep1, Pixel& ep2, const uint32_t*& colorValue
1371 } break; 1352 } break;
1372 1353
1373 default: 1354 default:
1374 assert(!"Unsupported color endpoint mode (is it HDR?)"); 1355 assert(false && "Unsupported color endpoint mode (is it HDR?)");
1375 break; 1356 break;
1376 } 1357 }
1377 1358
@@ -1379,14 +1360,14 @@ static void ComputeEndpoints(Pixel& ep1, Pixel& ep2, const uint32_t*& colorValue
1379#undef READ_INT_VALUES 1360#undef READ_INT_VALUES
1380} 1361}
1381 1362
1382static void DecompressBlock(const uint8_t inBuf[16], const uint32_t blockWidth, 1363static void DecompressBlock(const u8 inBuf[16], const u32 blockWidth, const u32 blockHeight,
1383 const uint32_t blockHeight, uint32_t* outBuf) { 1364 u32* outBuf) {
1384 InputBitStream strm(inBuf); 1365 InputBitStream strm(inBuf);
1385 TexelWeightParams weightParams = DecodeBlockInfo(strm); 1366 TexelWeightParams weightParams = DecodeBlockInfo(strm);
1386 1367
1387 // Was there an error? 1368 // Was there an error?
1388 if (weightParams.m_bError) { 1369 if (weightParams.m_bError) {
1389 assert(!"Invalid block mode"); 1370 assert(false && "Invalid block mode");
1390 FillError(outBuf, blockWidth, blockHeight); 1371 FillError(outBuf, blockWidth, blockHeight);
1391 return; 1372 return;
1392 } 1373 }
@@ -1397,63 +1378,63 @@ static void DecompressBlock(const uint8_t inBuf[16], const uint32_t blockWidth,
1397 } 1378 }
1398 1379
1399 if (weightParams.m_bVoidExtentHDR) { 1380 if (weightParams.m_bVoidExtentHDR) {
1400 assert(!"HDR void extent blocks are unsupported!"); 1381 assert(false && "HDR void extent blocks are unsupported!");
1401 FillError(outBuf, blockWidth, blockHeight); 1382 FillError(outBuf, blockWidth, blockHeight);
1402 return; 1383 return;
1403 } 1384 }
1404 1385
1405 if (weightParams.m_Width > blockWidth) { 1386 if (weightParams.m_Width > blockWidth) {
1406 assert(!"Texel weight grid width should be smaller than block width"); 1387 assert(false && "Texel weight grid width should be smaller than block width");
1407 FillError(outBuf, blockWidth, blockHeight); 1388 FillError(outBuf, blockWidth, blockHeight);
1408 return; 1389 return;
1409 } 1390 }
1410 1391
1411 if (weightParams.m_Height > blockHeight) { 1392 if (weightParams.m_Height > blockHeight) {
1412 assert(!"Texel weight grid height should be smaller than block height"); 1393 assert(false && "Texel weight grid height should be smaller than block height");
1413 FillError(outBuf, blockWidth, blockHeight); 1394 FillError(outBuf, blockWidth, blockHeight);
1414 return; 1395 return;
1415 } 1396 }
1416 1397
1417 // Read num partitions 1398 // Read num partitions
1418 uint32_t nPartitions = strm.ReadBits(2) + 1; 1399 u32 nPartitions = strm.ReadBits<2>() + 1;
1419 assert(nPartitions <= 4); 1400 assert(nPartitions <= 4);
1420 1401
1421 if (nPartitions == 4 && weightParams.m_bDualPlane) { 1402 if (nPartitions == 4 && weightParams.m_bDualPlane) {
1422 assert(!"Dual plane mode is incompatible with four partition blocks"); 1403 assert(false && "Dual plane mode is incompatible with four partition blocks");
1423 FillError(outBuf, blockWidth, blockHeight); 1404 FillError(outBuf, blockWidth, blockHeight);
1424 return; 1405 return;
1425 } 1406 }
1426 1407
1427 // Based on the number of partitions, read the color endpoint mode for 1408 // Based on the number of partitions, read the color endpos32 mode for
1428 // each partition. 1409 // each partition.
1429 1410
1430 // Determine partitions, partition index, and color endpoint modes 1411 // Determine partitions, partition index, and color endpos32 modes
1431 int32_t planeIdx = -1; 1412 s32 planeIdx = -1;
1432 uint32_t partitionIndex; 1413 u32 partitionIndex;
1433 uint32_t colorEndpointMode[4] = {0, 0, 0, 0}; 1414 u32 colorEndpos32Mode[4] = {0, 0, 0, 0};
1434 1415
1435 // Define color data. 1416 // Define color data.
1436 uint8_t colorEndpointData[16]; 1417 u8 colorEndpos32Data[16];
1437 memset(colorEndpointData, 0, sizeof(colorEndpointData)); 1418 memset(colorEndpos32Data, 0, sizeof(colorEndpos32Data));
1438 OutputBitStream colorEndpointStream(colorEndpointData, 16 * 8, 0); 1419 OutputBitStream colorEndpos32Stream(colorEndpos32Data, 16 * 8, 0);
1439 1420
1440 // Read extra config data... 1421 // Read extra config data...
1441 uint32_t baseCEM = 0; 1422 u32 baseCEM = 0;
1442 if (nPartitions == 1) { 1423 if (nPartitions == 1) {
1443 colorEndpointMode[0] = strm.ReadBits(4); 1424 colorEndpos32Mode[0] = strm.ReadBits<4>();
1444 partitionIndex = 0; 1425 partitionIndex = 0;
1445 } else { 1426 } else {
1446 partitionIndex = strm.ReadBits(10); 1427 partitionIndex = strm.ReadBits<10>();
1447 baseCEM = strm.ReadBits(6); 1428 baseCEM = strm.ReadBits<6>();
1448 } 1429 }
1449 uint32_t baseMode = (baseCEM & 3); 1430 u32 baseMode = (baseCEM & 3);
1450 1431
1451 // Remaining bits are color endpoint data... 1432 // Remaining bits are color endpos32 data...
1452 uint32_t nWeightBits = weightParams.GetPackedBitSize(); 1433 u32 nWeightBits = weightParams.GetPackedBitSize();
1453 int32_t remainingBits = 128 - nWeightBits - strm.GetBitsRead(); 1434 s32 remainingBits = 128 - nWeightBits - static_cast<s32>(strm.GetBitsRead());
1454 1435
1455 // Consider extra bits prior to texel data... 1436 // Consider extra bits prior to texel data...
1456 uint32_t extraCEMbits = 0; 1437 u32 extraCEMbits = 0;
1457 if (baseMode) { 1438 if (baseMode) {
1458 switch (nPartitions) { 1439 switch (nPartitions) {
1459 case 2: 1440 case 2:
@@ -1473,18 +1454,18 @@ static void DecompressBlock(const uint8_t inBuf[16], const uint32_t blockWidth,
1473 remainingBits -= extraCEMbits; 1454 remainingBits -= extraCEMbits;
1474 1455
1475 // Do we have a dual plane situation? 1456 // Do we have a dual plane situation?
1476 uint32_t planeSelectorBits = 0; 1457 u32 planeSelectorBits = 0;
1477 if (weightParams.m_bDualPlane) { 1458 if (weightParams.m_bDualPlane) {
1478 planeSelectorBits = 2; 1459 planeSelectorBits = 2;
1479 } 1460 }
1480 remainingBits -= planeSelectorBits; 1461 remainingBits -= planeSelectorBits;
1481 1462
1482 // Read color data... 1463 // Read color data...
1483 uint32_t colorDataBits = remainingBits; 1464 u32 colorDataBits = remainingBits;
1484 while (remainingBits > 0) { 1465 while (remainingBits > 0) {
1485 uint32_t nb = std::min(remainingBits, 8); 1466 u32 nb = std::min(remainingBits, 8);
1486 uint32_t b = strm.ReadBits(nb); 1467 u32 b = strm.ReadBits(nb);
1487 colorEndpointStream.WriteBits(b, nb); 1468 colorEndpos32Stream.WriteBits(b, nb);
1488 remainingBits -= 8; 1469 remainingBits -= 8;
1489 } 1470 }
1490 1471
@@ -1493,64 +1474,64 @@ static void DecompressBlock(const uint8_t inBuf[16], const uint32_t blockWidth,
1493 1474
1494 // Read the rest of the CEM 1475 // Read the rest of the CEM
1495 if (baseMode) { 1476 if (baseMode) {
1496 uint32_t extraCEM = strm.ReadBits(extraCEMbits); 1477 u32 extraCEM = strm.ReadBits(extraCEMbits);
1497 uint32_t CEM = (extraCEM << 6) | baseCEM; 1478 u32 CEM = (extraCEM << 6) | baseCEM;
1498 CEM >>= 2; 1479 CEM >>= 2;
1499 1480
1500 bool C[4] = {0}; 1481 bool C[4] = {0};
1501 for (uint32_t i = 0; i < nPartitions; i++) { 1482 for (u32 i = 0; i < nPartitions; i++) {
1502 C[i] = CEM & 1; 1483 C[i] = CEM & 1;
1503 CEM >>= 1; 1484 CEM >>= 1;
1504 } 1485 }
1505 1486
1506 uint8_t M[4] = {0}; 1487 u8 M[4] = {0};
1507 for (uint32_t i = 0; i < nPartitions; i++) { 1488 for (u32 i = 0; i < nPartitions; i++) {
1508 M[i] = CEM & 3; 1489 M[i] = CEM & 3;
1509 CEM >>= 2; 1490 CEM >>= 2;
1510 assert(M[i] <= 3); 1491 assert(M[i] <= 3);
1511 } 1492 }
1512 1493
1513 for (uint32_t i = 0; i < nPartitions; i++) { 1494 for (u32 i = 0; i < nPartitions; i++) {
1514 colorEndpointMode[i] = baseMode; 1495 colorEndpos32Mode[i] = baseMode;
1515 if (!(C[i])) 1496 if (!(C[i]))
1516 colorEndpointMode[i] -= 1; 1497 colorEndpos32Mode[i] -= 1;
1517 colorEndpointMode[i] <<= 2; 1498 colorEndpos32Mode[i] <<= 2;
1518 colorEndpointMode[i] |= M[i]; 1499 colorEndpos32Mode[i] |= M[i];
1519 } 1500 }
1520 } else if (nPartitions > 1) { 1501 } else if (nPartitions > 1) {
1521 uint32_t CEM = baseCEM >> 2; 1502 u32 CEM = baseCEM >> 2;
1522 for (uint32_t i = 0; i < nPartitions; i++) { 1503 for (u32 i = 0; i < nPartitions; i++) {
1523 colorEndpointMode[i] = CEM; 1504 colorEndpos32Mode[i] = CEM;
1524 } 1505 }
1525 } 1506 }
1526 1507
1527 // Make sure everything up till here is sane. 1508 // Make sure everything up till here is sane.
1528 for (uint32_t i = 0; i < nPartitions; i++) { 1509 for (u32 i = 0; i < nPartitions; i++) {
1529 assert(colorEndpointMode[i] < 16); 1510 assert(colorEndpos32Mode[i] < 16);
1530 } 1511 }
1531 assert(strm.GetBitsRead() + weightParams.GetPackedBitSize() == 128); 1512 assert(strm.GetBitsRead() + weightParams.GetPackedBitSize() == 128);
1532 1513
1533 // Decode both color data and texel weight data 1514 // Decode both color data and texel weight data
1534 uint32_t colorValues[32]; // Four values, two endpoints, four maximum paritions 1515 u32 colorValues[32]; // Four values, two endpos32s, four maximum paritions
1535 DecodeColorValues(colorValues, colorEndpointData, colorEndpointMode, nPartitions, 1516 DecodeColorValues(colorValues, colorEndpos32Data, colorEndpos32Mode, nPartitions,
1536 colorDataBits); 1517 colorDataBits);
1537 1518
1538 Pixel endpoints[4][2]; 1519 Pixel endpos32s[4][2];
1539 const uint32_t* colorValuesPtr = colorValues; 1520 const u32* colorValuesPtr = colorValues;
1540 for (uint32_t i = 0; i < nPartitions; i++) { 1521 for (u32 i = 0; i < nPartitions; i++) {
1541 ComputeEndpoints(endpoints[i][0], endpoints[i][1], colorValuesPtr, colorEndpointMode[i]); 1522 ComputeEndpos32s(endpos32s[i][0], endpos32s[i][1], colorValuesPtr, colorEndpos32Mode[i]);
1542 } 1523 }
1543 1524
1544 // Read the texel weight data.. 1525 // Read the texel weight data..
1545 uint8_t texelWeightData[16]; 1526 u8 texelWeightData[16];
1546 memcpy(texelWeightData, inBuf, sizeof(texelWeightData)); 1527 memcpy(texelWeightData, inBuf, sizeof(texelWeightData));
1547 1528
1548 // Reverse everything 1529 // Reverse everything
1549 for (uint32_t i = 0; i < 8; i++) { 1530 for (u32 i = 0; i < 8; i++) {
1550// Taken from http://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith64Bits 1531// Taken from http://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith64Bits
1551#define REVERSE_BYTE(b) (((b)*0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32 1532#define REVERSE_BYTE(b) (((b)*0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32
1552 unsigned char a = static_cast<unsigned char>(REVERSE_BYTE(texelWeightData[i])); 1533 u8 a = static_cast<u8>(REVERSE_BYTE(texelWeightData[i]));
1553 unsigned char b = static_cast<unsigned char>(REVERSE_BYTE(texelWeightData[15 - i])); 1534 u8 b = static_cast<u8>(REVERSE_BYTE(texelWeightData[15 - i]));
1554#undef REVERSE_BYTE 1535#undef REVERSE_BYTE
1555 1536
1556 texelWeightData[i] = b; 1537 texelWeightData[i] = b;
@@ -1558,50 +1539,51 @@ static void DecompressBlock(const uint8_t inBuf[16], const uint32_t blockWidth,
1558 } 1539 }
1559 1540
1560 // Make sure that higher non-texel bits are set to zero 1541 // Make sure that higher non-texel bits are set to zero
1561 const uint32_t clearByteStart = (weightParams.GetPackedBitSize() >> 3) + 1; 1542 const u32 clearByteStart = (weightParams.GetPackedBitSize() >> 3) + 1;
1562 texelWeightData[clearByteStart - 1] = 1543 texelWeightData[clearByteStart - 1] =
1563 texelWeightData[clearByteStart - 1] & 1544 texelWeightData[clearByteStart - 1] &
1564 static_cast<uint8_t>((1 << (weightParams.GetPackedBitSize() % 8)) - 1); 1545 static_cast<u8>((1 << (weightParams.GetPackedBitSize() % 8)) - 1);
1565 memset(texelWeightData + clearByteStart, 0, 16 - clearByteStart); 1546 memset(texelWeightData + clearByteStart, 0, 16 - clearByteStart);
1566 1547
1567 std::vector<IntegerEncodedValue> texelWeightValues; 1548 std::vector<IntegerEncodedValue> texelWeightValues;
1549 texelWeightValues.reserve(64);
1550
1568 InputBitStream weightStream(texelWeightData); 1551 InputBitStream weightStream(texelWeightData);
1569 1552
1570 IntegerEncodedValue::DecodeIntegerSequence(texelWeightValues, weightStream, 1553 DecodeIntegerSequence(texelWeightValues, weightStream, weightParams.m_MaxWeight,
1571 weightParams.m_MaxWeight, 1554 weightParams.GetNumWeightValues());
1572 weightParams.GetNumWeightValues());
1573 1555
1574 // Blocks can be at most 12x12, so we can have as many as 144 weights 1556 // Blocks can be at most 12x12, so we can have as many as 144 weights
1575 uint32_t weights[2][144]; 1557 u32 weights[2][144];
1576 UnquantizeTexelWeights(weights, texelWeightValues, weightParams, blockWidth, blockHeight); 1558 UnquantizeTexelWeights(weights, texelWeightValues, weightParams, blockWidth, blockHeight);
1577 1559
1578 // Now that we have endpoints and weights, we can interpolate and generate 1560 // Now that we have endpos32s and weights, we can s32erpolate and generate
1579 // the proper decoding... 1561 // the proper decoding...
1580 for (uint32_t j = 0; j < blockHeight; j++) 1562 for (u32 j = 0; j < blockHeight; j++)
1581 for (uint32_t i = 0; i < blockWidth; i++) { 1563 for (u32 i = 0; i < blockWidth; i++) {
1582 uint32_t partition = Select2DPartition(partitionIndex, i, j, nPartitions, 1564 u32 partition = Select2DPartition(partitionIndex, i, j, nPartitions,
1583 (blockHeight * blockWidth) < 32); 1565 (blockHeight * blockWidth) < 32);
1584 assert(partition < nPartitions); 1566 assert(partition < nPartitions);
1585 1567
1586 Pixel p; 1568 Pixel p;
1587 for (uint32_t c = 0; c < 4; c++) { 1569 for (u32 c = 0; c < 4; c++) {
1588 uint32_t C0 = endpoints[partition][0].Component(c); 1570 u32 C0 = endpos32s[partition][0].Component(c);
1589 C0 = Replicate(C0, 8, 16); 1571 C0 = Replicate(C0, 8, 16);
1590 uint32_t C1 = endpoints[partition][1].Component(c); 1572 u32 C1 = endpos32s[partition][1].Component(c);
1591 C1 = Replicate(C1, 8, 16); 1573 C1 = Replicate(C1, 8, 16);
1592 1574
1593 uint32_t plane = 0; 1575 u32 plane = 0;
1594 if (weightParams.m_bDualPlane && (((planeIdx + 1) & 3) == c)) { 1576 if (weightParams.m_bDualPlane && (((planeIdx + 1) & 3) == c)) {
1595 plane = 1; 1577 plane = 1;
1596 } 1578 }
1597 1579
1598 uint32_t weight = weights[plane][j * blockWidth + i]; 1580 u32 weight = weights[plane][j * blockWidth + i];
1599 uint32_t C = (C0 * (64 - weight) + C1 * weight + 32) / 64; 1581 u32 C = (C0 * (64 - weight) + C1 * weight + 32) / 64;
1600 if (C == 65535) { 1582 if (C == 65535) {
1601 p.Component(c) = 255; 1583 p.Component(c) = 255;
1602 } else { 1584 } else {
1603 double Cf = static_cast<double>(C); 1585 double Cf = static_cast<double>(C);
1604 p.Component(c) = static_cast<uint16_t>(255.0 * (Cf / 65536.0) + 0.5); 1586 p.Component(c) = static_cast<u16>(255.0 * (Cf / 65536.0) + 0.5);
1605 } 1587 }
1606 } 1588 }
1607 1589
@@ -1613,26 +1595,26 @@ static void DecompressBlock(const uint8_t inBuf[16], const uint32_t blockWidth,
1613 1595
1614namespace Tegra::Texture::ASTC { 1596namespace Tegra::Texture::ASTC {
1615 1597
1616std::vector<uint8_t> Decompress(const uint8_t* data, uint32_t width, uint32_t height, 1598std::vector<u8> Decompress(const u8* data, u32 width, u32 height, u32 depth, u32 block_width,
1617 uint32_t depth, uint32_t block_width, uint32_t block_height) { 1599 u32 block_height) {
1618 uint32_t blockIdx = 0; 1600 u32 blockIdx = 0;
1619 std::size_t depth_offset = 0; 1601 std::size_t depth_offset = 0;
1620 std::vector<uint8_t> outData(height * width * depth * 4); 1602 std::vector<u8> outData(height * width * depth * 4);
1621 for (uint32_t k = 0; k < depth; k++) { 1603 for (u32 k = 0; k < depth; k++) {
1622 for (uint32_t j = 0; j < height; j += block_height) { 1604 for (u32 j = 0; j < height; j += block_height) {
1623 for (uint32_t i = 0; i < width; i += block_width) { 1605 for (u32 i = 0; i < width; i += block_width) {
1624 1606
1625 const uint8_t* blockPtr = data + blockIdx * 16; 1607 const u8* blockPtr = data + blockIdx * 16;
1626 1608
1627 // Blocks can be at most 12x12 1609 // Blocks can be at most 12x12
1628 uint32_t uncompData[144]; 1610 u32 uncompData[144];
1629 ASTCC::DecompressBlock(blockPtr, block_width, block_height, uncompData); 1611 ASTCC::DecompressBlock(blockPtr, block_width, block_height, uncompData);
1630 1612
1631 uint32_t decompWidth = std::min(block_width, width - i); 1613 u32 decompWidth = std::min(block_width, width - i);
1632 uint32_t decompHeight = std::min(block_height, height - j); 1614 u32 decompHeight = std::min(block_height, height - j);
1633 1615
1634 uint8_t* outRow = depth_offset + outData.data() + (j * width + i) * 4; 1616 u8* outRow = depth_offset + outData.data() + (j * width + i) * 4;
1635 for (uint32_t jj = 0; jj < decompHeight; jj++) { 1617 for (u32 jj = 0; jj < decompHeight; jj++) {
1636 memcpy(outRow + jj * width * 4, uncompData + jj * block_width, decompWidth * 4); 1618 memcpy(outRow + jj * width * 4, uncompData + jj * block_width, decompWidth * 4);
1637 } 1619 }
1638 1620
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index acfe57e77..16e67cc0a 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -698,6 +698,8 @@ void Config::ReadSystemValues() {
698 Settings::values.custom_rtc = std::nullopt; 698 Settings::values.custom_rtc = std::nullopt;
699 } 699 }
700 700
701 Settings::values.sound_index = ReadSetting(QStringLiteral("sound_index"), 1).toInt();
702
701 qt_config->endGroup(); 703 qt_config->endGroup();
702} 704}
703 705
@@ -1125,6 +1127,8 @@ void Config::SaveSystemValues() {
1125 Settings::values.custom_rtc.value_or(std::chrono::seconds{}).count()), 1127 Settings::values.custom_rtc.value_or(std::chrono::seconds{}).count()),
1126 0); 1128 0);
1127 1129
1130 WriteSetting(QStringLiteral("sound_index"), Settings::values.sound_index, 1);
1131
1128 qt_config->endGroup(); 1132 qt_config->endGroup();
1129} 1133}
1130 1134
diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp
index e1b52f8d9..f9a5b4fbe 100644
--- a/src/yuzu/configuration/configure_system.cpp
+++ b/src/yuzu/configuration/configure_system.cpp
@@ -56,6 +56,7 @@ void ConfigureSystem::SetConfiguration() {
56 enabled = !Core::System::GetInstance().IsPoweredOn(); 56 enabled = !Core::System::GetInstance().IsPoweredOn();
57 57
58 ui->combo_language->setCurrentIndex(Settings::values.language_index); 58 ui->combo_language->setCurrentIndex(Settings::values.language_index);
59 ui->combo_sound->setCurrentIndex(Settings::values.sound_index);
59 60
60 ui->rng_seed_checkbox->setChecked(Settings::values.rng_seed.has_value()); 61 ui->rng_seed_checkbox->setChecked(Settings::values.rng_seed.has_value());
61 ui->rng_seed_edit->setEnabled(Settings::values.rng_seed.has_value()); 62 ui->rng_seed_edit->setEnabled(Settings::values.rng_seed.has_value());
@@ -81,6 +82,7 @@ void ConfigureSystem::ApplyConfiguration() {
81 } 82 }
82 83
83 Settings::values.language_index = ui->combo_language->currentIndex(); 84 Settings::values.language_index = ui->combo_language->currentIndex();
85 Settings::values.sound_index = ui->combo_sound->currentIndex();
84 86
85 if (ui->rng_seed_checkbox->isChecked()) { 87 if (ui->rng_seed_checkbox->isChecked()) {
86 Settings::values.rng_seed = ui->rng_seed_edit->text().toULongLong(nullptr, 16); 88 Settings::values.rng_seed = ui->rng_seed_edit->text().toULongLong(nullptr, 16);