summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/core.cpp27
-rw-r--r--src/core/hle/service/apm/controller.cpp50
-rw-r--r--src/core/hle/service/apm/controller.h2
-rw-r--r--src/core/memory/cheat_engine.cpp7
-rw-r--r--src/core/memory/dmnt_cheat_vm.cpp4
-rw-r--r--src/video_core/engines/maxwell_3d.cpp2
-rw-r--r--src/video_core/macro_interpreter.cpp71
-rw-r--r--src/video_core/macro_interpreter.h80
-rw-r--r--src/video_core/morton.cpp22
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp3
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.cpp13
-rw-r--r--src/video_core/renderer_vulkan/vk_shader_decompiler.cpp47
-rw-r--r--src/video_core/shader/ast.cpp85
-rw-r--r--src/video_core/shader/ast.h6
-rw-r--r--src/video_core/shader/decode/memory.cpp39
-rw-r--r--src/video_core/shader/shader_ir.h5
-rw-r--r--src/video_core/surface.cpp33
-rw-r--r--src/video_core/surface.h222
18 files changed, 453 insertions, 265 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp
index ddc767e30..b7b9259ec 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -112,8 +112,8 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
112} 112}
113struct System::Impl { 113struct System::Impl {
114 explicit Impl(System& system) 114 explicit Impl(System& system)
115 : kernel{system}, fs_controller{system}, cpu_core_manager{system}, 115 : kernel{system}, fs_controller{system}, cpu_core_manager{system}, reporter{system},
116 applet_manager{system}, reporter{system} {} 116 applet_manager{system} {}
117 117
118 Cpu& CurrentCpuCore() { 118 Cpu& CurrentCpuCore() {
119 return cpu_core_manager.GetCurrentCore(); 119 return cpu_core_manager.GetCurrentCore();
@@ -240,16 +240,19 @@ struct System::Impl {
240 } 240 }
241 241
242 void Shutdown() { 242 void Shutdown() {
243 // Log last frame performance stats 243 // Log last frame performance stats if game was loded
244 const auto perf_results = GetAndResetPerfStats(); 244 if (perf_stats) {
245 telemetry_session->AddField(Telemetry::FieldType::Performance, "Shutdown_EmulationSpeed", 245 const auto perf_results = GetAndResetPerfStats();
246 perf_results.emulation_speed * 100.0); 246 telemetry_session->AddField(Telemetry::FieldType::Performance,
247 telemetry_session->AddField(Telemetry::FieldType::Performance, "Shutdown_Framerate", 247 "Shutdown_EmulationSpeed",
248 perf_results.game_fps); 248 perf_results.emulation_speed * 100.0);
249 telemetry_session->AddField(Telemetry::FieldType::Performance, "Shutdown_Frametime", 249 telemetry_session->AddField(Telemetry::FieldType::Performance, "Shutdown_Framerate",
250 perf_results.frametime * 1000.0); 250 perf_results.game_fps);
251 telemetry_session->AddField(Telemetry::FieldType::Performance, "Mean_Frametime_MS", 251 telemetry_session->AddField(Telemetry::FieldType::Performance, "Shutdown_Frametime",
252 perf_stats->GetMeanFrametime()); 252 perf_results.frametime * 1000.0);
253 telemetry_session->AddField(Telemetry::FieldType::Performance, "Mean_Frametime_MS",
254 perf_stats->GetMeanFrametime());
255 }
253 256
254 lm_manager.Flush(); 257 lm_manager.Flush();
255 258
diff --git a/src/core/hle/service/apm/controller.cpp b/src/core/hle/service/apm/controller.cpp
index 073d0f6fa..25a886238 100644
--- a/src/core/hle/service/apm/controller.cpp
+++ b/src/core/hle/service/apm/controller.cpp
@@ -2,6 +2,10 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm>
6#include <array>
7#include <utility>
8
5#include "common/logging/log.h" 9#include "common/logging/log.h"
6#include "core/core_timing.h" 10#include "core/core_timing.h"
7#include "core/hle/service/apm/controller.h" 11#include "core/hle/service/apm/controller.h"
@@ -9,8 +13,7 @@
9 13
10namespace Service::APM { 14namespace Service::APM {
11 15
12constexpr PerformanceConfiguration DEFAULT_PERFORMANCE_CONFIGURATION = 16constexpr auto DEFAULT_PERFORMANCE_CONFIGURATION = PerformanceConfiguration::Config7;
13 PerformanceConfiguration::Config7;
14 17
15Controller::Controller(Core::Timing::CoreTiming& core_timing) 18Controller::Controller(Core::Timing::CoreTiming& core_timing)
16 : core_timing{core_timing}, configs{ 19 : core_timing{core_timing}, configs{
@@ -22,18 +25,35 @@ Controller::~Controller() = default;
22 25
23void Controller::SetPerformanceConfiguration(PerformanceMode mode, 26void Controller::SetPerformanceConfiguration(PerformanceMode mode,
24 PerformanceConfiguration config) { 27 PerformanceConfiguration config) {
25 static const std::map<PerformanceConfiguration, u32> PCONFIG_TO_SPEED_MAP{ 28 static constexpr std::array<std::pair<PerformanceConfiguration, u32>, 16> config_to_speed{{
26 {PerformanceConfiguration::Config1, 1020}, {PerformanceConfiguration::Config2, 1020}, 29 {PerformanceConfiguration::Config1, 1020},
27 {PerformanceConfiguration::Config3, 1224}, {PerformanceConfiguration::Config4, 1020}, 30 {PerformanceConfiguration::Config2, 1020},
28 {PerformanceConfiguration::Config5, 1020}, {PerformanceConfiguration::Config6, 1224}, 31 {PerformanceConfiguration::Config3, 1224},
29 {PerformanceConfiguration::Config7, 1020}, {PerformanceConfiguration::Config8, 1020}, 32 {PerformanceConfiguration::Config4, 1020},
30 {PerformanceConfiguration::Config9, 1020}, {PerformanceConfiguration::Config10, 1020}, 33 {PerformanceConfiguration::Config5, 1020},
31 {PerformanceConfiguration::Config11, 1020}, {PerformanceConfiguration::Config12, 1020}, 34 {PerformanceConfiguration::Config6, 1224},
32 {PerformanceConfiguration::Config13, 1785}, {PerformanceConfiguration::Config14, 1785}, 35 {PerformanceConfiguration::Config7, 1020},
33 {PerformanceConfiguration::Config15, 1020}, {PerformanceConfiguration::Config16, 1020}, 36 {PerformanceConfiguration::Config8, 1020},
34 }; 37 {PerformanceConfiguration::Config9, 1020},
35 38 {PerformanceConfiguration::Config10, 1020},
36 SetClockSpeed(PCONFIG_TO_SPEED_MAP.find(config)->second); 39 {PerformanceConfiguration::Config11, 1020},
40 {PerformanceConfiguration::Config12, 1020},
41 {PerformanceConfiguration::Config13, 1785},
42 {PerformanceConfiguration::Config14, 1785},
43 {PerformanceConfiguration::Config15, 1020},
44 {PerformanceConfiguration::Config16, 1020},
45 }};
46
47 const auto iter = std::find_if(config_to_speed.cbegin(), config_to_speed.cend(),
48 [config](const auto& entry) { return entry.first == config; });
49
50 if (iter == config_to_speed.cend()) {
51 LOG_ERROR(Service_APM, "Invalid performance configuration value provided: {}",
52 static_cast<u32>(config));
53 return;
54 }
55
56 SetClockSpeed(iter->second);
37 configs.insert_or_assign(mode, config); 57 configs.insert_or_assign(mode, config);
38} 58}
39 59
@@ -48,7 +68,7 @@ void Controller::SetFromCpuBoostMode(CpuBoostMode mode) {
48 BOOST_MODE_TO_CONFIG_MAP.at(static_cast<u32>(mode))); 68 BOOST_MODE_TO_CONFIG_MAP.at(static_cast<u32>(mode)));
49} 69}
50 70
51PerformanceMode Controller::GetCurrentPerformanceMode() { 71PerformanceMode Controller::GetCurrentPerformanceMode() const {
52 return Settings::values.use_docked_mode ? PerformanceMode::Docked : PerformanceMode::Handheld; 72 return Settings::values.use_docked_mode ? PerformanceMode::Docked : PerformanceMode::Handheld;
53} 73}
54 74
diff --git a/src/core/hle/service/apm/controller.h b/src/core/hle/service/apm/controller.h
index 454caa6eb..af0c4cd34 100644
--- a/src/core/hle/service/apm/controller.h
+++ b/src/core/hle/service/apm/controller.h
@@ -56,7 +56,7 @@ public:
56 void SetPerformanceConfiguration(PerformanceMode mode, PerformanceConfiguration config); 56 void SetPerformanceConfiguration(PerformanceMode mode, PerformanceConfiguration config);
57 void SetFromCpuBoostMode(CpuBoostMode mode); 57 void SetFromCpuBoostMode(CpuBoostMode mode);
58 58
59 PerformanceMode GetCurrentPerformanceMode(); 59 PerformanceMode GetCurrentPerformanceMode() const;
60 PerformanceConfiguration GetCurrentPerformanceConfiguration(PerformanceMode mode); 60 PerformanceConfiguration GetCurrentPerformanceConfiguration(PerformanceMode mode);
61 61
62private: 62private:
diff --git a/src/core/memory/cheat_engine.cpp b/src/core/memory/cheat_engine.cpp
index b56cb0627..10821d452 100644
--- a/src/core/memory/cheat_engine.cpp
+++ b/src/core/memory/cheat_engine.cpp
@@ -22,7 +22,7 @@ constexpr u32 KEYPAD_BITMASK = 0x3FFFFFF;
22 22
23StandardVmCallbacks::StandardVmCallbacks(const Core::System& system, 23StandardVmCallbacks::StandardVmCallbacks(const Core::System& system,
24 const CheatProcessMetadata& metadata) 24 const CheatProcessMetadata& metadata)
25 : system(system), metadata(metadata) {} 25 : metadata(metadata), system(system) {}
26 26
27StandardVmCallbacks::~StandardVmCallbacks() = default; 27StandardVmCallbacks::~StandardVmCallbacks() = default;
28 28
@@ -176,9 +176,8 @@ std::vector<CheatEntry> TextCheatParser::Parse(const Core::System& system,
176 176
177CheatEngine::CheatEngine(Core::System& system, std::vector<CheatEntry> cheats, 177CheatEngine::CheatEngine(Core::System& system, std::vector<CheatEntry> cheats,
178 const std::array<u8, 0x20>& build_id) 178 const std::array<u8, 0x20>& build_id)
179 : system{system}, core_timing{system.CoreTiming()}, vm{std::make_unique<StandardVmCallbacks>( 179 : vm{std::make_unique<StandardVmCallbacks>(system, metadata)},
180 system, metadata)}, 180 cheats(std::move(cheats)), core_timing{system.CoreTiming()}, system{system} {
181 cheats(std::move(cheats)) {
182 metadata.main_nso_build_id = build_id; 181 metadata.main_nso_build_id = build_id;
183} 182}
184 183
diff --git a/src/core/memory/dmnt_cheat_vm.cpp b/src/core/memory/dmnt_cheat_vm.cpp
index cc16d15a4..4f4fa5099 100644
--- a/src/core/memory/dmnt_cheat_vm.cpp
+++ b/src/core/memory/dmnt_cheat_vm.cpp
@@ -1133,8 +1133,8 @@ void DmntCheatVm::Execute(const CheatProcessMetadata& metadata) {
1133 case SaveRestoreRegisterOpType::ClearRegs: 1133 case SaveRestoreRegisterOpType::ClearRegs:
1134 case SaveRestoreRegisterOpType::Restore: 1134 case SaveRestoreRegisterOpType::Restore:
1135 default: 1135 default:
1136 src = registers.data(); 1136 src = saved_values.data();
1137 dst = saved_values.data(); 1137 dst = registers.data();
1138 break; 1138 break;
1139 } 1139 }
1140 for (std::size_t i = 0; i < NumRegisters; i++) { 1140 for (std::size_t i = 0; i < NumRegisters; i++) {
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index c5ec7d9f1..59976943a 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -479,7 +479,7 @@ void Maxwell3D::CallMethodFromMME(const GPU::MethodCall& method_call) {
479} 479}
480 480
481void Maxwell3D::FlushMMEInlineDraw() { 481void Maxwell3D::FlushMMEInlineDraw() {
482 LOG_DEBUG(HW_GPU, "called, topology={}, count={}", static_cast<u32>(regs.draw.topology.Value()), 482 LOG_TRACE(HW_GPU, "called, topology={}, count={}", static_cast<u32>(regs.draw.topology.Value()),
483 regs.vertex_buffer.count); 483 regs.vertex_buffer.count);
484 ASSERT_MSG(!(regs.index_array.count && regs.vertex_buffer.count), "Both indexed and direct?"); 484 ASSERT_MSG(!(regs.index_array.count && regs.vertex_buffer.count), "Both indexed and direct?");
485 ASSERT(mme_draw.instance_count == mme_draw.gl_end_count); 485 ASSERT(mme_draw.instance_count == mme_draw.gl_end_count);
diff --git a/src/video_core/macro_interpreter.cpp b/src/video_core/macro_interpreter.cpp
index dbaeac6db..42031d80a 100644
--- a/src/video_core/macro_interpreter.cpp
+++ b/src/video_core/macro_interpreter.cpp
@@ -11,6 +11,77 @@
11MICROPROFILE_DEFINE(MacroInterp, "GPU", "Execute macro interpreter", MP_RGB(128, 128, 192)); 11MICROPROFILE_DEFINE(MacroInterp, "GPU", "Execute macro interpreter", MP_RGB(128, 128, 192));
12 12
13namespace Tegra { 13namespace Tegra {
14namespace {
15enum class Operation : u32 {
16 ALU = 0,
17 AddImmediate = 1,
18 ExtractInsert = 2,
19 ExtractShiftLeftImmediate = 3,
20 ExtractShiftLeftRegister = 4,
21 Read = 5,
22 Unused = 6, // This operation doesn't seem to be a valid encoding.
23 Branch = 7,
24};
25} // Anonymous namespace
26
27enum class MacroInterpreter::ALUOperation : u32 {
28 Add = 0,
29 AddWithCarry = 1,
30 Subtract = 2,
31 SubtractWithBorrow = 3,
32 // Operations 4-7 don't seem to be valid encodings.
33 Xor = 8,
34 Or = 9,
35 And = 10,
36 AndNot = 11,
37 Nand = 12
38};
39
40enum class MacroInterpreter::ResultOperation : u32 {
41 IgnoreAndFetch = 0,
42 Move = 1,
43 MoveAndSetMethod = 2,
44 FetchAndSend = 3,
45 MoveAndSend = 4,
46 FetchAndSetMethod = 5,
47 MoveAndSetMethodFetchAndSend = 6,
48 MoveAndSetMethodSend = 7
49};
50
51enum class MacroInterpreter::BranchCondition : u32 {
52 Zero = 0,
53 NotZero = 1,
54};
55
56union MacroInterpreter::Opcode {
57 u32 raw;
58 BitField<0, 3, Operation> operation;
59 BitField<4, 3, ResultOperation> result_operation;
60 BitField<4, 1, BranchCondition> branch_condition;
61 // If set on a branch, then the branch doesn't have a delay slot.
62 BitField<5, 1, u32> branch_annul;
63 BitField<7, 1, u32> is_exit;
64 BitField<8, 3, u32> dst;
65 BitField<11, 3, u32> src_a;
66 BitField<14, 3, u32> src_b;
67 // The signed immediate overlaps the second source operand and the alu operation.
68 BitField<14, 18, s32> immediate;
69
70 BitField<17, 5, ALUOperation> alu_operation;
71
72 // Bitfield instructions data
73 BitField<17, 5, u32> bf_src_bit;
74 BitField<22, 5, u32> bf_size;
75 BitField<27, 5, u32> bf_dst_bit;
76
77 u32 GetBitfieldMask() const {
78 return (1 << bf_size) - 1;
79 }
80
81 s32 GetBranchTarget() const {
82 return static_cast<s32>(immediate * sizeof(u32));
83 }
84};
14 85
15MacroInterpreter::MacroInterpreter(Engines::Maxwell3D& maxwell3d) : maxwell3d(maxwell3d) {} 86MacroInterpreter::MacroInterpreter(Engines::Maxwell3D& maxwell3d) : maxwell3d(maxwell3d) {}
16 87
diff --git a/src/video_core/macro_interpreter.h b/src/video_core/macro_interpreter.h
index 76b6a895b..631146d89 100644
--- a/src/video_core/macro_interpreter.h
+++ b/src/video_core/macro_interpreter.h
@@ -6,7 +6,6 @@
6 6
7#include <array> 7#include <array>
8#include <optional> 8#include <optional>
9#include <vector>
10 9
11#include "common/bit_field.h" 10#include "common/bit_field.h"
12#include "common/common_types.h" 11#include "common/common_types.h"
@@ -28,75 +27,11 @@ public:
28 void Execute(u32 offset, std::size_t num_parameters, const u32* parameters); 27 void Execute(u32 offset, std::size_t num_parameters, const u32* parameters);
29 28
30private: 29private:
31 enum class Operation : u32 { 30 enum class ALUOperation : u32;
32 ALU = 0, 31 enum class BranchCondition : u32;
33 AddImmediate = 1, 32 enum class ResultOperation : u32;
34 ExtractInsert = 2,
35 ExtractShiftLeftImmediate = 3,
36 ExtractShiftLeftRegister = 4,
37 Read = 5,
38 Unused = 6, // This operation doesn't seem to be a valid encoding.
39 Branch = 7,
40 };
41
42 enum class ALUOperation : u32 {
43 Add = 0,
44 AddWithCarry = 1,
45 Subtract = 2,
46 SubtractWithBorrow = 3,
47 // Operations 4-7 don't seem to be valid encodings.
48 Xor = 8,
49 Or = 9,
50 And = 10,
51 AndNot = 11,
52 Nand = 12
53 };
54
55 enum class ResultOperation : u32 {
56 IgnoreAndFetch = 0,
57 Move = 1,
58 MoveAndSetMethod = 2,
59 FetchAndSend = 3,
60 MoveAndSend = 4,
61 FetchAndSetMethod = 5,
62 MoveAndSetMethodFetchAndSend = 6,
63 MoveAndSetMethodSend = 7
64 };
65 33
66 enum class BranchCondition : u32 { 34 union Opcode;
67 Zero = 0,
68 NotZero = 1,
69 };
70
71 union Opcode {
72 u32 raw;
73 BitField<0, 3, Operation> operation;
74 BitField<4, 3, ResultOperation> result_operation;
75 BitField<4, 1, BranchCondition> branch_condition;
76 BitField<5, 1, u32>
77 branch_annul; // If set on a branch, then the branch doesn't have a delay slot.
78 BitField<7, 1, u32> is_exit;
79 BitField<8, 3, u32> dst;
80 BitField<11, 3, u32> src_a;
81 BitField<14, 3, u32> src_b;
82 // The signed immediate overlaps the second source operand and the alu operation.
83 BitField<14, 18, s32> immediate;
84
85 BitField<17, 5, ALUOperation> alu_operation;
86
87 // Bitfield instructions data
88 BitField<17, 5, u32> bf_src_bit;
89 BitField<22, 5, u32> bf_size;
90 BitField<27, 5, u32> bf_dst_bit;
91
92 u32 GetBitfieldMask() const {
93 return (1 << bf_size) - 1;
94 }
95
96 s32 GetBranchTarget() const {
97 return static_cast<s32>(immediate * sizeof(u32));
98 }
99 };
100 35
101 union MethodAddress { 36 union MethodAddress {
102 u32 raw; 37 u32 raw;
@@ -149,9 +84,10 @@ private:
149 84
150 Engines::Maxwell3D& maxwell3d; 85 Engines::Maxwell3D& maxwell3d;
151 86
152 u32 pc; ///< Current program counter 87 /// Current program counter
153 std::optional<u32> 88 u32 pc;
154 delayed_pc; ///< Program counter to execute at after the delay slot is executed. 89 /// Program counter to execute at after the delay slot is executed.
90 std::optional<u32> delayed_pc;
155 91
156 static constexpr std::size_t NumMacroRegisters = 8; 92 static constexpr std::size_t NumMacroRegisters = 8;
157 93
diff --git a/src/video_core/morton.cpp b/src/video_core/morton.cpp
index ab71870ab..fe5f08ace 100644
--- a/src/video_core/morton.cpp
+++ b/src/video_core/morton.cpp
@@ -93,6 +93,7 @@ static constexpr ConversionArray morton_to_linear_fns = {
93 MortonCopy<true, PixelFormat::DXT23_SRGB>, 93 MortonCopy<true, PixelFormat::DXT23_SRGB>,
94 MortonCopy<true, PixelFormat::DXT45_SRGB>, 94 MortonCopy<true, PixelFormat::DXT45_SRGB>,
95 MortonCopy<true, PixelFormat::BC7U_SRGB>, 95 MortonCopy<true, PixelFormat::BC7U_SRGB>,
96 MortonCopy<true, PixelFormat::R4G4B4A4U>,
96 MortonCopy<true, PixelFormat::ASTC_2D_4X4_SRGB>, 97 MortonCopy<true, PixelFormat::ASTC_2D_4X4_SRGB>,
97 MortonCopy<true, PixelFormat::ASTC_2D_8X8_SRGB>, 98 MortonCopy<true, PixelFormat::ASTC_2D_8X8_SRGB>,
98 MortonCopy<true, PixelFormat::ASTC_2D_8X5_SRGB>, 99 MortonCopy<true, PixelFormat::ASTC_2D_8X5_SRGB>,
@@ -101,6 +102,16 @@ static constexpr ConversionArray morton_to_linear_fns = {
101 MortonCopy<true, PixelFormat::ASTC_2D_5X5_SRGB>, 102 MortonCopy<true, PixelFormat::ASTC_2D_5X5_SRGB>,
102 MortonCopy<true, PixelFormat::ASTC_2D_10X8>, 103 MortonCopy<true, PixelFormat::ASTC_2D_10X8>,
103 MortonCopy<true, PixelFormat::ASTC_2D_10X8_SRGB>, 104 MortonCopy<true, PixelFormat::ASTC_2D_10X8_SRGB>,
105 MortonCopy<true, PixelFormat::ASTC_2D_6X6>,
106 MortonCopy<true, PixelFormat::ASTC_2D_6X6_SRGB>,
107 MortonCopy<true, PixelFormat::ASTC_2D_10X10>,
108 MortonCopy<true, PixelFormat::ASTC_2D_10X10_SRGB>,
109 MortonCopy<true, PixelFormat::ASTC_2D_12X12>,
110 MortonCopy<true, PixelFormat::ASTC_2D_12X12_SRGB>,
111 MortonCopy<true, PixelFormat::ASTC_2D_8X6>,
112 MortonCopy<true, PixelFormat::ASTC_2D_8X6_SRGB>,
113 MortonCopy<true, PixelFormat::ASTC_2D_6X5>,
114 MortonCopy<true, PixelFormat::ASTC_2D_6X5_SRGB>,
104 MortonCopy<true, PixelFormat::Z32F>, 115 MortonCopy<true, PixelFormat::Z32F>,
105 MortonCopy<true, PixelFormat::Z16>, 116 MortonCopy<true, PixelFormat::Z16>,
106 MortonCopy<true, PixelFormat::Z24S8>, 117 MortonCopy<true, PixelFormat::Z24S8>,
@@ -162,6 +173,17 @@ static constexpr ConversionArray linear_to_morton_fns = {
162 MortonCopy<false, PixelFormat::DXT23_SRGB>, 173 MortonCopy<false, PixelFormat::DXT23_SRGB>,
163 MortonCopy<false, PixelFormat::DXT45_SRGB>, 174 MortonCopy<false, PixelFormat::DXT45_SRGB>,
164 MortonCopy<false, PixelFormat::BC7U_SRGB>, 175 MortonCopy<false, PixelFormat::BC7U_SRGB>,
176 MortonCopy<false, PixelFormat::R4G4B4A4U>,
177 nullptr,
178 nullptr,
179 nullptr,
180 nullptr,
181 nullptr,
182 nullptr,
183 nullptr,
184 nullptr,
185 nullptr,
186 nullptr,
165 nullptr, 187 nullptr,
166 nullptr, 188 nullptr,
167 nullptr, 189 nullptr,
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index a3524a6a9..baec66ff0 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -2314,10 +2314,13 @@ public:
2314 switch (index) { 2314 switch (index) {
2315 case Tegra::Shader::Pred::NeverExecute: 2315 case Tegra::Shader::Pred::NeverExecute:
2316 target = "false"; 2316 target = "false";
2317 break;
2317 case Tegra::Shader::Pred::UnusedIndex: 2318 case Tegra::Shader::Pred::UnusedIndex:
2318 target = "true"; 2319 target = "true";
2320 break;
2319 default: 2321 default:
2320 target = decomp.GetPredicate(index); 2322 target = decomp.GetPredicate(index);
2323 break;
2321 } 2324 }
2322 } else if (const auto flag = std::get_if<InternalFlagNode>(&*cc)) { 2325 } else if (const auto flag = std::get_if<InternalFlagNode>(&*cc)) {
2323 target = decomp.GetInternalFlag(flag->GetFlag()); 2326 target = decomp.GetInternalFlag(flag->GetFlag());
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp
index 173b76c4e..2f9bfd7e4 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp
@@ -111,7 +111,8 @@ constexpr std::array<FormatTuple, VideoCore::Surface::MaxPixelFormat> tex_format
111 {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, ComponentType::UNorm, 111 {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, ComponentType::UNorm,
112 true}, // DXT45_SRGB 112 true}, // DXT45_SRGB
113 {GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, ComponentType::UNorm, 113 {GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, ComponentType::UNorm,
114 true}, // BC7U_SRGB 114 true}, // BC7U_SRGB
115 {GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4_REV, ComponentType::UNorm, false}, // R4G4B4A4U
115 {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_4X4_SRGB 116 {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_4X4_SRGB
116 {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X8_SRGB 117 {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X8_SRGB
117 {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X5_SRGB 118 {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X5_SRGB
@@ -120,6 +121,16 @@ constexpr std::array<FormatTuple, VideoCore::Surface::MaxPixelFormat> tex_format
120 {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_5X5_SRGB 121 {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_5X5_SRGB
121 {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_10X8 122 {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_10X8
122 {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_10X8_SRGB 123 {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_10X8_SRGB
124 {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_6X6
125 {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_6X6_SRGB
126 {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_10X10
127 {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_10X10_SRGB
128 {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_12X12
129 {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_12X12_SRGB
130 {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X6
131 {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X6_SRGB
132 {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_6X5
133 {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_6X5_SRGB
123 134
124 // Depth formats 135 // Depth formats
125 {GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, ComponentType::Float, false}, // Z32F 136 {GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, ComponentType::Float, false}, // Z32F
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
index 8bcd04221..0d943a826 100644
--- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
+++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
@@ -1648,32 +1648,32 @@ class ExprDecompiler {
1648public: 1648public:
1649 explicit ExprDecompiler(SPIRVDecompiler& decomp) : decomp{decomp} {} 1649 explicit ExprDecompiler(SPIRVDecompiler& decomp) : decomp{decomp} {}
1650 1650
1651 Id operator()(VideoCommon::Shader::ExprAnd& expr) { 1651 Id operator()(const ExprAnd& expr) {
1652 const Id type_def = decomp.GetTypeDefinition(Type::Bool); 1652 const Id type_def = decomp.GetTypeDefinition(Type::Bool);
1653 const Id op1 = Visit(expr.operand1); 1653 const Id op1 = Visit(expr.operand1);
1654 const Id op2 = Visit(expr.operand2); 1654 const Id op2 = Visit(expr.operand2);
1655 return decomp.Emit(decomp.OpLogicalAnd(type_def, op1, op2)); 1655 return decomp.Emit(decomp.OpLogicalAnd(type_def, op1, op2));
1656 } 1656 }
1657 1657
1658 Id operator()(VideoCommon::Shader::ExprOr& expr) { 1658 Id operator()(const ExprOr& expr) {
1659 const Id type_def = decomp.GetTypeDefinition(Type::Bool); 1659 const Id type_def = decomp.GetTypeDefinition(Type::Bool);
1660 const Id op1 = Visit(expr.operand1); 1660 const Id op1 = Visit(expr.operand1);
1661 const Id op2 = Visit(expr.operand2); 1661 const Id op2 = Visit(expr.operand2);
1662 return decomp.Emit(decomp.OpLogicalOr(type_def, op1, op2)); 1662 return decomp.Emit(decomp.OpLogicalOr(type_def, op1, op2));
1663 } 1663 }
1664 1664
1665 Id operator()(VideoCommon::Shader::ExprNot& expr) { 1665 Id operator()(const ExprNot& expr) {
1666 const Id type_def = decomp.GetTypeDefinition(Type::Bool); 1666 const Id type_def = decomp.GetTypeDefinition(Type::Bool);
1667 const Id op1 = Visit(expr.operand1); 1667 const Id op1 = Visit(expr.operand1);
1668 return decomp.Emit(decomp.OpLogicalNot(type_def, op1)); 1668 return decomp.Emit(decomp.OpLogicalNot(type_def, op1));
1669 } 1669 }
1670 1670
1671 Id operator()(VideoCommon::Shader::ExprPredicate& expr) { 1671 Id operator()(const ExprPredicate& expr) {
1672 const auto pred = static_cast<Tegra::Shader::Pred>(expr.predicate); 1672 const auto pred = static_cast<Tegra::Shader::Pred>(expr.predicate);
1673 return decomp.Emit(decomp.OpLoad(decomp.t_bool, decomp.predicates.at(pred))); 1673 return decomp.Emit(decomp.OpLoad(decomp.t_bool, decomp.predicates.at(pred)));
1674 } 1674 }
1675 1675
1676 Id operator()(VideoCommon::Shader::ExprCondCode& expr) { 1676 Id operator()(const ExprCondCode& expr) {
1677 const Node cc = decomp.ir.GetConditionCode(expr.cc); 1677 const Node cc = decomp.ir.GetConditionCode(expr.cc);
1678 Id target; 1678 Id target;
1679 1679
@@ -1682,10 +1682,13 @@ public:
1682 switch (index) { 1682 switch (index) {
1683 case Tegra::Shader::Pred::NeverExecute: 1683 case Tegra::Shader::Pred::NeverExecute:
1684 target = decomp.v_false; 1684 target = decomp.v_false;
1685 break;
1685 case Tegra::Shader::Pred::UnusedIndex: 1686 case Tegra::Shader::Pred::UnusedIndex:
1686 target = decomp.v_true; 1687 target = decomp.v_true;
1688 break;
1687 default: 1689 default:
1688 target = decomp.predicates.at(index); 1690 target = decomp.predicates.at(index);
1691 break;
1689 } 1692 }
1690 } else if (const auto flag = std::get_if<InternalFlagNode>(&*cc)) { 1693 } else if (const auto flag = std::get_if<InternalFlagNode>(&*cc)) {
1691 target = decomp.internal_flags.at(static_cast<u32>(flag->GetFlag())); 1694 target = decomp.internal_flags.at(static_cast<u32>(flag->GetFlag()));
@@ -1693,15 +1696,15 @@ public:
1693 return decomp.Emit(decomp.OpLoad(decomp.t_bool, target)); 1696 return decomp.Emit(decomp.OpLoad(decomp.t_bool, target));
1694 } 1697 }
1695 1698
1696 Id operator()(VideoCommon::Shader::ExprVar& expr) { 1699 Id operator()(const ExprVar& expr) {
1697 return decomp.Emit(decomp.OpLoad(decomp.t_bool, decomp.flow_variables.at(expr.var_index))); 1700 return decomp.Emit(decomp.OpLoad(decomp.t_bool, decomp.flow_variables.at(expr.var_index)));
1698 } 1701 }
1699 1702
1700 Id operator()(VideoCommon::Shader::ExprBoolean& expr) { 1703 Id operator()(const ExprBoolean& expr) {
1701 return expr.value ? decomp.v_true : decomp.v_false; 1704 return expr.value ? decomp.v_true : decomp.v_false;
1702 } 1705 }
1703 1706
1704 Id Visit(VideoCommon::Shader::Expr& node) { 1707 Id Visit(const Expr& node) {
1705 return std::visit(*this, *node); 1708 return std::visit(*this, *node);
1706 } 1709 }
1707 1710
@@ -1713,7 +1716,7 @@ class ASTDecompiler {
1713public: 1716public:
1714 explicit ASTDecompiler(SPIRVDecompiler& decomp) : decomp{decomp} {} 1717 explicit ASTDecompiler(SPIRVDecompiler& decomp) : decomp{decomp} {}
1715 1718
1716 void operator()(VideoCommon::Shader::ASTProgram& ast) { 1719 void operator()(const ASTProgram& ast) {
1717 ASTNode current = ast.nodes.GetFirst(); 1720 ASTNode current = ast.nodes.GetFirst();
1718 while (current) { 1721 while (current) {
1719 Visit(current); 1722 Visit(current);
@@ -1721,7 +1724,7 @@ public:
1721 } 1724 }
1722 } 1725 }
1723 1726
1724 void operator()(VideoCommon::Shader::ASTIfThen& ast) { 1727 void operator()(const ASTIfThen& ast) {
1725 ExprDecompiler expr_parser{decomp}; 1728 ExprDecompiler expr_parser{decomp};
1726 const Id condition = expr_parser.Visit(ast.condition); 1729 const Id condition = expr_parser.Visit(ast.condition);
1727 const Id then_label = decomp.OpLabel(); 1730 const Id then_label = decomp.OpLabel();
@@ -1738,33 +1741,33 @@ public:
1738 decomp.Emit(endif_label); 1741 decomp.Emit(endif_label);
1739 } 1742 }
1740 1743
1741 void operator()(VideoCommon::Shader::ASTIfElse& ast) { 1744 void operator()([[maybe_unused]] const ASTIfElse& ast) {
1742 UNREACHABLE(); 1745 UNREACHABLE();
1743 } 1746 }
1744 1747
1745 void operator()(VideoCommon::Shader::ASTBlockEncoded& ast) { 1748 void operator()([[maybe_unused]] const ASTBlockEncoded& ast) {
1746 UNREACHABLE(); 1749 UNREACHABLE();
1747 } 1750 }
1748 1751
1749 void operator()(VideoCommon::Shader::ASTBlockDecoded& ast) { 1752 void operator()(const ASTBlockDecoded& ast) {
1750 decomp.VisitBasicBlock(ast.nodes); 1753 decomp.VisitBasicBlock(ast.nodes);
1751 } 1754 }
1752 1755
1753 void operator()(VideoCommon::Shader::ASTVarSet& ast) { 1756 void operator()(const ASTVarSet& ast) {
1754 ExprDecompiler expr_parser{decomp}; 1757 ExprDecompiler expr_parser{decomp};
1755 const Id condition = expr_parser.Visit(ast.condition); 1758 const Id condition = expr_parser.Visit(ast.condition);
1756 decomp.Emit(decomp.OpStore(decomp.flow_variables.at(ast.index), condition)); 1759 decomp.Emit(decomp.OpStore(decomp.flow_variables.at(ast.index), condition));
1757 } 1760 }
1758 1761
1759 void operator()(VideoCommon::Shader::ASTLabel& ast) { 1762 void operator()([[maybe_unused]] const ASTLabel& ast) {
1760 // Do nothing 1763 // Do nothing
1761 } 1764 }
1762 1765
1763 void operator()(VideoCommon::Shader::ASTGoto& ast) { 1766 void operator()([[maybe_unused]] const ASTGoto& ast) {
1764 UNREACHABLE(); 1767 UNREACHABLE();
1765 } 1768 }
1766 1769
1767 void operator()(VideoCommon::Shader::ASTDoWhile& ast) { 1770 void operator()(const ASTDoWhile& ast) {
1768 const Id loop_label = decomp.OpLabel(); 1771 const Id loop_label = decomp.OpLabel();
1769 const Id endloop_label = decomp.OpLabel(); 1772 const Id endloop_label = decomp.OpLabel();
1770 const Id loop_start_block = decomp.OpLabel(); 1773 const Id loop_start_block = decomp.OpLabel();
@@ -1787,7 +1790,7 @@ public:
1787 decomp.Emit(endloop_label); 1790 decomp.Emit(endloop_label);
1788 } 1791 }
1789 1792
1790 void operator()(VideoCommon::Shader::ASTReturn& ast) { 1793 void operator()(const ASTReturn& ast) {
1791 if (!VideoCommon::Shader::ExprIsTrue(ast.condition)) { 1794 if (!VideoCommon::Shader::ExprIsTrue(ast.condition)) {
1792 ExprDecompiler expr_parser{decomp}; 1795 ExprDecompiler expr_parser{decomp};
1793 const Id condition = expr_parser.Visit(ast.condition); 1796 const Id condition = expr_parser.Visit(ast.condition);
@@ -1817,7 +1820,7 @@ public:
1817 } 1820 }
1818 } 1821 }
1819 1822
1820 void operator()(VideoCommon::Shader::ASTBreak& ast) { 1823 void operator()(const ASTBreak& ast) {
1821 if (!VideoCommon::Shader::ExprIsTrue(ast.condition)) { 1824 if (!VideoCommon::Shader::ExprIsTrue(ast.condition)) {
1822 ExprDecompiler expr_parser{decomp}; 1825 ExprDecompiler expr_parser{decomp};
1823 const Id condition = expr_parser.Visit(ast.condition); 1826 const Id condition = expr_parser.Visit(ast.condition);
@@ -1837,7 +1840,7 @@ public:
1837 } 1840 }
1838 } 1841 }
1839 1842
1840 void Visit(VideoCommon::Shader::ASTNode& node) { 1843 void Visit(const ASTNode& node) {
1841 std::visit(*this, *node->GetInnerData()); 1844 std::visit(*this, *node->GetInnerData());
1842 } 1845 }
1843 1846
@@ -1853,9 +1856,11 @@ void SPIRVDecompiler::DecompileAST() {
1853 Name(id, fmt::format("flow_var_{}", i)); 1856 Name(id, fmt::format("flow_var_{}", i));
1854 flow_variables.emplace(i, AddGlobalVariable(id)); 1857 flow_variables.emplace(i, AddGlobalVariable(id));
1855 } 1858 }
1859
1860 const ASTNode program = ir.GetASTProgram();
1856 ASTDecompiler decompiler{*this}; 1861 ASTDecompiler decompiler{*this};
1857 VideoCommon::Shader::ASTNode program = ir.GetASTProgram();
1858 decompiler.Visit(program); 1862 decompiler.Visit(program);
1863
1859 const Id next_block = OpLabel(); 1864 const Id next_block = OpLabel();
1860 Emit(OpBranch(next_block)); 1865 Emit(OpBranch(next_block));
1861 Emit(next_block); 1866 Emit(next_block);
diff --git a/src/video_core/shader/ast.cpp b/src/video_core/shader/ast.cpp
index 436d45f4b..e43aecc18 100644
--- a/src/video_core/shader/ast.cpp
+++ b/src/video_core/shader/ast.cpp
@@ -3,6 +3,9 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <string> 5#include <string>
6#include <string_view>
7
8#include <fmt/format.h>
6 9
7#include "common/assert.h" 10#include "common/assert.h"
8#include "common/common_types.h" 11#include "common/common_types.h"
@@ -229,7 +232,8 @@ public:
229 return inner; 232 return inner;
230 } 233 }
231 234
232 std::string inner{}; 235private:
236 std::string inner;
233}; 237};
234 238
235class ASTPrinter { 239class ASTPrinter {
@@ -249,7 +253,7 @@ public:
249 void operator()(const ASTIfThen& ast) { 253 void operator()(const ASTIfThen& ast) {
250 ExprPrinter expr_parser{}; 254 ExprPrinter expr_parser{};
251 std::visit(expr_parser, *ast.condition); 255 std::visit(expr_parser, *ast.condition);
252 inner += Ident() + "if (" + expr_parser.GetResult() + ") {\n"; 256 inner += fmt::format("{}if ({}) {{\n", Indent(), expr_parser.GetResult());
253 scope++; 257 scope++;
254 ASTNode current = ast.nodes.GetFirst(); 258 ASTNode current = ast.nodes.GetFirst();
255 while (current) { 259 while (current) {
@@ -257,11 +261,13 @@ public:
257 current = current->GetNext(); 261 current = current->GetNext();
258 } 262 }
259 scope--; 263 scope--;
260 inner += Ident() + "}\n"; 264 inner += fmt::format("{}}}\n", Indent());
261 } 265 }
262 266
263 void operator()(const ASTIfElse& ast) { 267 void operator()(const ASTIfElse& ast) {
264 inner += Ident() + "else {\n"; 268 inner += Indent();
269 inner += "else {\n";
270
265 scope++; 271 scope++;
266 ASTNode current = ast.nodes.GetFirst(); 272 ASTNode current = ast.nodes.GetFirst();
267 while (current) { 273 while (current) {
@@ -269,40 +275,41 @@ public:
269 current = current->GetNext(); 275 current = current->GetNext();
270 } 276 }
271 scope--; 277 scope--;
272 inner += Ident() + "}\n"; 278
279 inner += Indent();
280 inner += "}\n";
273 } 281 }
274 282
275 void operator()(const ASTBlockEncoded& ast) { 283 void operator()(const ASTBlockEncoded& ast) {
276 inner += Ident() + "Block(" + std::to_string(ast.start) + ", " + std::to_string(ast.end) + 284 inner += fmt::format("{}Block({}, {});\n", Indent(), ast.start, ast.end);
277 ");\n";
278 } 285 }
279 286
280 void operator()(const ASTBlockDecoded& ast) { 287 void operator()([[maybe_unused]] const ASTBlockDecoded& ast) {
281 inner += Ident() + "Block;\n"; 288 inner += Indent();
289 inner += "Block;\n";
282 } 290 }
283 291
284 void operator()(const ASTVarSet& ast) { 292 void operator()(const ASTVarSet& ast) {
285 ExprPrinter expr_parser{}; 293 ExprPrinter expr_parser{};
286 std::visit(expr_parser, *ast.condition); 294 std::visit(expr_parser, *ast.condition);
287 inner += 295 inner += fmt::format("{}V{} := {};\n", Indent(), ast.index, expr_parser.GetResult());
288 Ident() + "V" + std::to_string(ast.index) + " := " + expr_parser.GetResult() + ";\n";
289 } 296 }
290 297
291 void operator()(const ASTLabel& ast) { 298 void operator()(const ASTLabel& ast) {
292 inner += "Label_" + std::to_string(ast.index) + ":\n"; 299 inner += fmt::format("Label_{}:\n", ast.index);
293 } 300 }
294 301
295 void operator()(const ASTGoto& ast) { 302 void operator()(const ASTGoto& ast) {
296 ExprPrinter expr_parser{}; 303 ExprPrinter expr_parser{};
297 std::visit(expr_parser, *ast.condition); 304 std::visit(expr_parser, *ast.condition);
298 inner += Ident() + "(" + expr_parser.GetResult() + ") -> goto Label_" + 305 inner +=
299 std::to_string(ast.label) + ";\n"; 306 fmt::format("{}({}) -> goto Label_{};\n", Indent(), expr_parser.GetResult(), ast.label);
300 } 307 }
301 308
302 void operator()(const ASTDoWhile& ast) { 309 void operator()(const ASTDoWhile& ast) {
303 ExprPrinter expr_parser{}; 310 ExprPrinter expr_parser{};
304 std::visit(expr_parser, *ast.condition); 311 std::visit(expr_parser, *ast.condition);
305 inner += Ident() + "do {\n"; 312 inner += fmt::format("{}do {{\n", Indent());
306 scope++; 313 scope++;
307 ASTNode current = ast.nodes.GetFirst(); 314 ASTNode current = ast.nodes.GetFirst();
308 while (current) { 315 while (current) {
@@ -310,32 +317,23 @@ public:
310 current = current->GetNext(); 317 current = current->GetNext();
311 } 318 }
312 scope--; 319 scope--;
313 inner += Ident() + "} while (" + expr_parser.GetResult() + ");\n"; 320 inner += fmt::format("{}}} while ({});\n", Indent(), expr_parser.GetResult());
314 } 321 }
315 322
316 void operator()(const ASTReturn& ast) { 323 void operator()(const ASTReturn& ast) {
317 ExprPrinter expr_parser{}; 324 ExprPrinter expr_parser{};
318 std::visit(expr_parser, *ast.condition); 325 std::visit(expr_parser, *ast.condition);
319 inner += Ident() + "(" + expr_parser.GetResult() + ") -> " + 326 inner += fmt::format("{}({}) -> {};\n", Indent(), expr_parser.GetResult(),
320 (ast.kills ? "discard" : "exit") + ";\n"; 327 ast.kills ? "discard" : "exit");
321 } 328 }
322 329
323 void operator()(const ASTBreak& ast) { 330 void operator()(const ASTBreak& ast) {
324 ExprPrinter expr_parser{}; 331 ExprPrinter expr_parser{};
325 std::visit(expr_parser, *ast.condition); 332 std::visit(expr_parser, *ast.condition);
326 inner += Ident() + "(" + expr_parser.GetResult() + ") -> break;\n"; 333 inner += fmt::format("{}({}) -> break;\n", Indent(), expr_parser.GetResult());
327 } 334 }
328 335
329 std::string& Ident() { 336 void Visit(const ASTNode& node) {
330 if (memo_scope == scope) {
331 return tabs_memo;
332 }
333 tabs_memo = tabs.substr(0, scope * 2);
334 memo_scope = scope;
335 return tabs_memo;
336 }
337
338 void Visit(ASTNode& node) {
339 std::visit(*this, *node->GetInnerData()); 337 std::visit(*this, *node->GetInnerData());
340 } 338 }
341 339
@@ -344,16 +342,29 @@ public:
344 } 342 }
345 343
346private: 344private:
345 std::string_view Indent() {
346 if (space_segment_scope == scope) {
347 return space_segment;
348 }
349
350 // Ensure that we don't exceed our view.
351 ASSERT(scope * 2 < spaces.size());
352
353 space_segment = spaces.substr(0, scope * 2);
354 space_segment_scope = scope;
355 return space_segment;
356 }
357
347 std::string inner{}; 358 std::string inner{};
348 u32 scope{}; 359 std::string_view space_segment;
349 360
350 std::string tabs_memo{}; 361 u32 scope{};
351 u32 memo_scope{}; 362 u32 space_segment_scope{};
352 363
353 static constexpr std::string_view tabs{" "}; 364 static constexpr std::string_view spaces{" "};
354}; 365};
355 366
356std::string ASTManager::Print() { 367std::string ASTManager::Print() const {
357 ASTPrinter printer{}; 368 ASTPrinter printer{};
358 printer.Visit(main_node); 369 printer.Visit(main_node);
359 return printer.GetResult(); 370 return printer.GetResult();
@@ -549,13 +560,13 @@ bool ASTManager::DirectlyRelated(const ASTNode& first, const ASTNode& second) co
549 return min->GetParent() == max->GetParent(); 560 return min->GetParent() == max->GetParent();
550} 561}
551 562
552void ASTManager::ShowCurrentState(std::string_view state) { 563void ASTManager::ShowCurrentState(std::string_view state) const {
553 LOG_CRITICAL(HW_GPU, "\nState {}:\n\n{}\n", state, Print()); 564 LOG_CRITICAL(HW_GPU, "\nState {}:\n\n{}\n", state, Print());
554 SanityCheck(); 565 SanityCheck();
555} 566}
556 567
557void ASTManager::SanityCheck() { 568void ASTManager::SanityCheck() const {
558 for (auto& label : labels) { 569 for (const auto& label : labels) {
559 if (!label->GetParent()) { 570 if (!label->GetParent()) {
560 LOG_CRITICAL(HW_GPU, "Sanity Check Failed"); 571 LOG_CRITICAL(HW_GPU, "Sanity Check Failed");
561 } 572 }
diff --git a/src/video_core/shader/ast.h b/src/video_core/shader/ast.h
index d7bf11821..a2f0044ba 100644
--- a/src/video_core/shader/ast.h
+++ b/src/video_core/shader/ast.h
@@ -328,13 +328,13 @@ public:
328 328
329 void InsertReturn(Expr condition, bool kills); 329 void InsertReturn(Expr condition, bool kills);
330 330
331 std::string Print(); 331 std::string Print() const;
332 332
333 void Decompile(); 333 void Decompile();
334 334
335 void ShowCurrentState(std::string_view state); 335 void ShowCurrentState(std::string_view state) const;
336 336
337 void SanityCheck(); 337 void SanityCheck() const;
338 338
339 void Clear(); 339 void Clear();
340 340
diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp
index 7923d4d69..335d78146 100644
--- a/src/video_core/shader/decode/memory.cpp
+++ b/src/video_core/shader/decode/memory.cpp
@@ -166,9 +166,17 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
166 }(); 166 }();
167 167
168 const auto [real_address_base, base_address, descriptor] = 168 const auto [real_address_base, base_address, descriptor] =
169 TrackAndGetGlobalMemory(bb, instr, false); 169 TrackGlobalMemory(bb, instr, false);
170 170
171 const u32 count = GetUniformTypeElementsCount(type); 171 const u32 count = GetUniformTypeElementsCount(type);
172 if (!real_address_base || !base_address) {
173 // Tracking failed, load zeroes.
174 for (u32 i = 0; i < count; ++i) {
175 SetRegister(bb, instr.gpr0.Value() + i, Immediate(0.0f));
176 }
177 break;
178 }
179
172 for (u32 i = 0; i < count; ++i) { 180 for (u32 i = 0; i < count; ++i) {
173 const Node it_offset = Immediate(i * 4); 181 const Node it_offset = Immediate(i * 4);
174 const Node real_address = 182 const Node real_address =
@@ -260,22 +268,19 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
260 }(); 268 }();
261 269
262 const auto [real_address_base, base_address, descriptor] = 270 const auto [real_address_base, base_address, descriptor] =
263 TrackAndGetGlobalMemory(bb, instr, true); 271 TrackGlobalMemory(bb, instr, true);
264 272 if (!real_address_base || !base_address) {
265 // Encode in temporary registers like this: real_base_address, {registers_to_be_written...} 273 // Tracking failed, skip the store.
266 SetTemporary(bb, 0, real_address_base); 274 break;
275 }
267 276
268 const u32 count = GetUniformTypeElementsCount(type); 277 const u32 count = GetUniformTypeElementsCount(type);
269 for (u32 i = 0; i < count; ++i) { 278 for (u32 i = 0; i < count; ++i) {
270 SetTemporary(bb, i + 1, GetRegister(instr.gpr0.Value() + i));
271 }
272 for (u32 i = 0; i < count; ++i) {
273 const Node it_offset = Immediate(i * 4); 279 const Node it_offset = Immediate(i * 4);
274 const Node real_address = 280 const Node real_address = Operation(OperationCode::UAdd, real_address_base, it_offset);
275 Operation(OperationCode::UAdd, NO_PRECISE, real_address_base, it_offset);
276 const Node gmem = MakeNode<GmemNode>(real_address, base_address, descriptor); 281 const Node gmem = MakeNode<GmemNode>(real_address, base_address, descriptor);
277 282 const Node value = GetRegister(instr.gpr0.Value() + i);
278 bb.push_back(Operation(OperationCode::Assign, gmem, GetTemporary(i + 1))); 283 bb.push_back(Operation(OperationCode::Assign, gmem, value));
279 } 284 }
280 break; 285 break;
281 } 286 }
@@ -301,15 +306,17 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
301 return pc; 306 return pc;
302} 307}
303 308
304std::tuple<Node, Node, GlobalMemoryBase> ShaderIR::TrackAndGetGlobalMemory(NodeBlock& bb, 309std::tuple<Node, Node, GlobalMemoryBase> ShaderIR::TrackGlobalMemory(NodeBlock& bb,
305 Instruction instr, 310 Instruction instr,
306 bool is_write) { 311 bool is_write) {
307 const auto addr_register{GetRegister(instr.gmem.gpr)}; 312 const auto addr_register{GetRegister(instr.gmem.gpr)};
308 const auto immediate_offset{static_cast<u32>(instr.gmem.offset)}; 313 const auto immediate_offset{static_cast<u32>(instr.gmem.offset)};
309 314
310 const auto [base_address, index, offset] = 315 const auto [base_address, index, offset] =
311 TrackCbuf(addr_register, global_code, static_cast<s64>(global_code.size())); 316 TrackCbuf(addr_register, global_code, static_cast<s64>(global_code.size()));
312 ASSERT(base_address != nullptr); 317 ASSERT_OR_EXECUTE_MSG(base_address != nullptr,
318 { return std::make_tuple(nullptr, nullptr, GlobalMemoryBase{}); },
319 "Global memory tracking failed");
313 320
314 bb.push_back(Comment(fmt::format("Base address is c[0x{:x}][0x{:x}]", index, offset))); 321 bb.push_back(Comment(fmt::format("Base address is c[0x{:x}][0x{:x}]", index, offset)));
315 322
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h
index 105981d67..91cd0a534 100644
--- a/src/video_core/shader/shader_ir.h
+++ b/src/video_core/shader/shader_ir.h
@@ -371,8 +371,9 @@ private:
371 std::pair<Node, s64> TrackRegister(const GprNode* tracked, const NodeBlock& code, 371 std::pair<Node, s64> TrackRegister(const GprNode* tracked, const NodeBlock& code,
372 s64 cursor) const; 372 s64 cursor) const;
373 373
374 std::tuple<Node, Node, GlobalMemoryBase> TrackAndGetGlobalMemory( 374 std::tuple<Node, Node, GlobalMemoryBase> TrackGlobalMemory(NodeBlock& bb,
375 NodeBlock& bb, Tegra::Shader::Instruction instr, bool is_write); 375 Tegra::Shader::Instruction instr,
376 bool is_write);
376 377
377 const ProgramCode& program_code; 378 const ProgramCode& program_code;
378 const u32 main_offset; 379 const u32 main_offset;
diff --git a/src/video_core/surface.cpp b/src/video_core/surface.cpp
index ef6b3592e..9a3c05288 100644
--- a/src/video_core/surface.cpp
+++ b/src/video_core/surface.cpp
@@ -212,6 +212,14 @@ PixelFormat PixelFormatFromTextureFormat(Tegra::Texture::TextureFormat format,
212 break; 212 break;
213 } 213 }
214 break; 214 break;
215 case Tegra::Texture::TextureFormat::A4B4G4R4:
216 switch (component_type) {
217 case Tegra::Texture::ComponentType::UNORM:
218 return PixelFormat::R4G4B4A4U;
219 default:
220 break;
221 }
222 break;
215 case Tegra::Texture::TextureFormat::R8: 223 case Tegra::Texture::TextureFormat::R8:
216 switch (component_type) { 224 switch (component_type) {
217 case Tegra::Texture::ComponentType::UNORM: 225 case Tegra::Texture::ComponentType::UNORM:
@@ -351,6 +359,16 @@ PixelFormat PixelFormatFromTextureFormat(Tegra::Texture::TextureFormat format,
351 return is_srgb ? PixelFormat::ASTC_2D_8X5_SRGB : PixelFormat::ASTC_2D_8X5; 359 return is_srgb ? PixelFormat::ASTC_2D_8X5_SRGB : PixelFormat::ASTC_2D_8X5;
352 case Tegra::Texture::TextureFormat::ASTC_2D_10X8: 360 case Tegra::Texture::TextureFormat::ASTC_2D_10X8:
353 return is_srgb ? PixelFormat::ASTC_2D_10X8_SRGB : PixelFormat::ASTC_2D_10X8; 361 return is_srgb ? PixelFormat::ASTC_2D_10X8_SRGB : PixelFormat::ASTC_2D_10X8;
362 case Tegra::Texture::TextureFormat::ASTC_2D_6X6:
363 return is_srgb ? PixelFormat::ASTC_2D_6X6_SRGB : PixelFormat::ASTC_2D_6X6;
364 case Tegra::Texture::TextureFormat::ASTC_2D_10X10:
365 return is_srgb ? PixelFormat::ASTC_2D_10X10_SRGB : PixelFormat::ASTC_2D_10X10;
366 case Tegra::Texture::TextureFormat::ASTC_2D_12X12:
367 return is_srgb ? PixelFormat::ASTC_2D_12X12_SRGB : PixelFormat::ASTC_2D_12X12;
368 case Tegra::Texture::TextureFormat::ASTC_2D_8X6:
369 return is_srgb ? PixelFormat::ASTC_2D_8X6_SRGB : PixelFormat::ASTC_2D_8X6;
370 case Tegra::Texture::TextureFormat::ASTC_2D_6X5:
371 return is_srgb ? PixelFormat::ASTC_2D_6X5_SRGB : PixelFormat::ASTC_2D_6X5;
354 case Tegra::Texture::TextureFormat::R16_G16: 372 case Tegra::Texture::TextureFormat::R16_G16:
355 switch (component_type) { 373 switch (component_type) {
356 case Tegra::Texture::ComponentType::FLOAT: 374 case Tegra::Texture::ComponentType::FLOAT:
@@ -511,6 +529,16 @@ bool IsPixelFormatASTC(PixelFormat format) {
511 case PixelFormat::ASTC_2D_8X5_SRGB: 529 case PixelFormat::ASTC_2D_8X5_SRGB:
512 case PixelFormat::ASTC_2D_10X8: 530 case PixelFormat::ASTC_2D_10X8:
513 case PixelFormat::ASTC_2D_10X8_SRGB: 531 case PixelFormat::ASTC_2D_10X8_SRGB:
532 case PixelFormat::ASTC_2D_6X6:
533 case PixelFormat::ASTC_2D_6X6_SRGB:
534 case PixelFormat::ASTC_2D_10X10:
535 case PixelFormat::ASTC_2D_10X10_SRGB:
536 case PixelFormat::ASTC_2D_12X12:
537 case PixelFormat::ASTC_2D_12X12_SRGB:
538 case PixelFormat::ASTC_2D_8X6:
539 case PixelFormat::ASTC_2D_8X6_SRGB:
540 case PixelFormat::ASTC_2D_6X5:
541 case PixelFormat::ASTC_2D_6X5_SRGB:
514 return true; 542 return true;
515 default: 543 default:
516 return false; 544 return false;
@@ -531,6 +559,11 @@ bool IsPixelFormatSRGB(PixelFormat format) {
531 case PixelFormat::ASTC_2D_5X4_SRGB: 559 case PixelFormat::ASTC_2D_5X4_SRGB:
532 case PixelFormat::ASTC_2D_5X5_SRGB: 560 case PixelFormat::ASTC_2D_5X5_SRGB:
533 case PixelFormat::ASTC_2D_10X8_SRGB: 561 case PixelFormat::ASTC_2D_10X8_SRGB:
562 case PixelFormat::ASTC_2D_6X6_SRGB:
563 case PixelFormat::ASTC_2D_10X10_SRGB:
564 case PixelFormat::ASTC_2D_12X12_SRGB:
565 case PixelFormat::ASTC_2D_8X6_SRGB:
566 case PixelFormat::ASTC_2D_6X5_SRGB:
534 return true; 567 return true;
535 default: 568 default:
536 return false; 569 return false;
diff --git a/src/video_core/surface.h b/src/video_core/surface.h
index 1e1c432a5..97668f802 100644
--- a/src/video_core/surface.h
+++ b/src/video_core/surface.h
@@ -67,27 +67,38 @@ enum class PixelFormat {
67 DXT23_SRGB = 49, 67 DXT23_SRGB = 49,
68 DXT45_SRGB = 50, 68 DXT45_SRGB = 50,
69 BC7U_SRGB = 51, 69 BC7U_SRGB = 51,
70 ASTC_2D_4X4_SRGB = 52, 70 R4G4B4A4U = 52,
71 ASTC_2D_8X8_SRGB = 53, 71 ASTC_2D_4X4_SRGB = 53,
72 ASTC_2D_8X5_SRGB = 54, 72 ASTC_2D_8X8_SRGB = 54,
73 ASTC_2D_5X4_SRGB = 55, 73 ASTC_2D_8X5_SRGB = 55,
74 ASTC_2D_5X5 = 56, 74 ASTC_2D_5X4_SRGB = 56,
75 ASTC_2D_5X5_SRGB = 57, 75 ASTC_2D_5X5 = 57,
76 ASTC_2D_10X8 = 58, 76 ASTC_2D_5X5_SRGB = 58,
77 ASTC_2D_10X8_SRGB = 59, 77 ASTC_2D_10X8 = 59,
78 ASTC_2D_10X8_SRGB = 60,
79 ASTC_2D_6X6 = 61,
80 ASTC_2D_6X6_SRGB = 62,
81 ASTC_2D_10X10 = 63,
82 ASTC_2D_10X10_SRGB = 64,
83 ASTC_2D_12X12 = 65,
84 ASTC_2D_12X12_SRGB = 66,
85 ASTC_2D_8X6 = 67,
86 ASTC_2D_8X6_SRGB = 68,
87 ASTC_2D_6X5 = 69,
88 ASTC_2D_6X5_SRGB = 70,
78 89
79 MaxColorFormat, 90 MaxColorFormat,
80 91
81 // Depth formats 92 // Depth formats
82 Z32F = 60, 93 Z32F = 71,
83 Z16 = 61, 94 Z16 = 72,
84 95
85 MaxDepthFormat, 96 MaxDepthFormat,
86 97
87 // DepthStencil formats 98 // DepthStencil formats
88 Z24S8 = 62, 99 Z24S8 = 73,
89 S8Z24 = 63, 100 S8Z24 = 74,
90 Z32FS8 = 64, 101 Z32FS8 = 75,
91 102
92 MaxDepthStencilFormat, 103 MaxDepthStencilFormat,
93 104
@@ -177,6 +188,7 @@ constexpr std::array<u32, MaxPixelFormat> compression_factor_shift_table = {{
177 2, // DXT23_SRGB 188 2, // DXT23_SRGB
178 2, // DXT45_SRGB 189 2, // DXT45_SRGB
179 2, // BC7U_SRGB 190 2, // BC7U_SRGB
191 0, // R4G4B4A4U
180 2, // ASTC_2D_4X4_SRGB 192 2, // ASTC_2D_4X4_SRGB
181 2, // ASTC_2D_8X8_SRGB 193 2, // ASTC_2D_8X8_SRGB
182 2, // ASTC_2D_8X5_SRGB 194 2, // ASTC_2D_8X5_SRGB
@@ -185,6 +197,16 @@ constexpr std::array<u32, MaxPixelFormat> compression_factor_shift_table = {{
185 2, // ASTC_2D_5X5_SRGB 197 2, // ASTC_2D_5X5_SRGB
186 2, // ASTC_2D_10X8 198 2, // ASTC_2D_10X8
187 2, // ASTC_2D_10X8_SRGB 199 2, // ASTC_2D_10X8_SRGB
200 2, // ASTC_2D_6X6
201 2, // ASTC_2D_6X6_SRGB
202 2, // ASTC_2D_10X10
203 2, // ASTC_2D_10X10_SRGB
204 2, // ASTC_2D_12X12
205 2, // ASTC_2D_12X12_SRGB
206 2, // ASTC_2D_8X6
207 2, // ASTC_2D_8X6_SRGB
208 2, // ASTC_2D_6X5
209 2, // ASTC_2D_6X5_SRGB
188 0, // Z32F 210 0, // Z32F
189 0, // Z16 211 0, // Z16
190 0, // Z24S8 212 0, // Z24S8
@@ -261,6 +283,7 @@ constexpr std::array<u32, MaxPixelFormat> block_width_table = {{
261 4, // DXT23_SRGB 283 4, // DXT23_SRGB
262 4, // DXT45_SRGB 284 4, // DXT45_SRGB
263 4, // BC7U_SRGB 285 4, // BC7U_SRGB
286 1, // R4G4B4A4U
264 4, // ASTC_2D_4X4_SRGB 287 4, // ASTC_2D_4X4_SRGB
265 8, // ASTC_2D_8X8_SRGB 288 8, // ASTC_2D_8X8_SRGB
266 8, // ASTC_2D_8X5_SRGB 289 8, // ASTC_2D_8X5_SRGB
@@ -269,6 +292,16 @@ constexpr std::array<u32, MaxPixelFormat> block_width_table = {{
269 5, // ASTC_2D_5X5_SRGB 292 5, // ASTC_2D_5X5_SRGB
270 10, // ASTC_2D_10X8 293 10, // ASTC_2D_10X8
271 10, // ASTC_2D_10X8_SRGB 294 10, // ASTC_2D_10X8_SRGB
295 6, // ASTC_2D_6X6
296 6, // ASTC_2D_6X6_SRGB
297 10, // ASTC_2D_10X10
298 10, // ASTC_2D_10X10_SRGB
299 12, // ASTC_2D_12X12
300 12, // ASTC_2D_12X12_SRGB
301 8, // ASTC_2D_8X6
302 8, // ASTC_2D_8X6_SRGB
303 6, // ASTC_2D_6X5
304 6, // ASTC_2D_6X5_SRGB
272 1, // Z32F 305 1, // Z32F
273 1, // Z16 306 1, // Z16
274 1, // Z24S8 307 1, // Z24S8
@@ -285,71 +318,82 @@ static constexpr u32 GetDefaultBlockWidth(PixelFormat format) {
285} 318}
286 319
287constexpr std::array<u32, MaxPixelFormat> block_height_table = {{ 320constexpr std::array<u32, MaxPixelFormat> block_height_table = {{
288 1, // ABGR8U 321 1, // ABGR8U
289 1, // ABGR8S 322 1, // ABGR8S
290 1, // ABGR8UI 323 1, // ABGR8UI
291 1, // B5G6R5U 324 1, // B5G6R5U
292 1, // A2B10G10R10U 325 1, // A2B10G10R10U
293 1, // A1B5G5R5U 326 1, // A1B5G5R5U
294 1, // R8U 327 1, // R8U
295 1, // R8UI 328 1, // R8UI
296 1, // RGBA16F 329 1, // RGBA16F
297 1, // RGBA16U 330 1, // RGBA16U
298 1, // RGBA16UI 331 1, // RGBA16UI
299 1, // R11FG11FB10F 332 1, // R11FG11FB10F
300 1, // RGBA32UI 333 1, // RGBA32UI
301 4, // DXT1 334 4, // DXT1
302 4, // DXT23 335 4, // DXT23
303 4, // DXT45 336 4, // DXT45
304 4, // DXN1 337 4, // DXN1
305 4, // DXN2UNORM 338 4, // DXN2UNORM
306 4, // DXN2SNORM 339 4, // DXN2SNORM
307 4, // BC7U 340 4, // BC7U
308 4, // BC6H_UF16 341 4, // BC6H_UF16
309 4, // BC6H_SF16 342 4, // BC6H_SF16
310 4, // ASTC_2D_4X4 343 4, // ASTC_2D_4X4
311 1, // BGRA8 344 1, // BGRA8
312 1, // RGBA32F 345 1, // RGBA32F
313 1, // RG32F 346 1, // RG32F
314 1, // R32F 347 1, // R32F
315 1, // R16F 348 1, // R16F
316 1, // R16U 349 1, // R16U
317 1, // R16S 350 1, // R16S
318 1, // R16UI 351 1, // R16UI
319 1, // R16I 352 1, // R16I
320 1, // RG16 353 1, // RG16
321 1, // RG16F 354 1, // RG16F
322 1, // RG16UI 355 1, // RG16UI
323 1, // RG16I 356 1, // RG16I
324 1, // RG16S 357 1, // RG16S
325 1, // RGB32F 358 1, // RGB32F
326 1, // RGBA8_SRGB 359 1, // RGBA8_SRGB
327 1, // RG8U 360 1, // RG8U
328 1, // RG8S 361 1, // RG8S
329 1, // RG32UI 362 1, // RG32UI
330 1, // RGBX16F 363 1, // RGBX16F
331 1, // R32UI 364 1, // R32UI
332 8, // ASTC_2D_8X8 365 8, // ASTC_2D_8X8
333 5, // ASTC_2D_8X5 366 5, // ASTC_2D_8X5
334 4, // ASTC_2D_5X4 367 4, // ASTC_2D_5X4
335 1, // BGRA8_SRGB 368 1, // BGRA8_SRGB
336 4, // DXT1_SRGB 369 4, // DXT1_SRGB
337 4, // DXT23_SRGB 370 4, // DXT23_SRGB
338 4, // DXT45_SRGB 371 4, // DXT45_SRGB
339 4, // BC7U_SRGB 372 4, // BC7U_SRGB
340 4, // ASTC_2D_4X4_SRGB 373 1, // R4G4B4A4U
341 8, // ASTC_2D_8X8_SRGB 374 4, // ASTC_2D_4X4_SRGB
342 5, // ASTC_2D_8X5_SRGB 375 8, // ASTC_2D_8X8_SRGB
343 4, // ASTC_2D_5X4_SRGB 376 5, // ASTC_2D_8X5_SRGB
344 5, // ASTC_2D_5X5 377 4, // ASTC_2D_5X4_SRGB
345 5, // ASTC_2D_5X5_SRGB 378 5, // ASTC_2D_5X5
346 8, // ASTC_2D_10X8 379 5, // ASTC_2D_5X5_SRGB
347 8, // ASTC_2D_10X8_SRGB 380 8, // ASTC_2D_10X8
348 1, // Z32F 381 8, // ASTC_2D_10X8_SRGB
349 1, // Z16 382 6, // ASTC_2D_6X6
350 1, // Z24S8 383 6, // ASTC_2D_6X6_SRGB
351 1, // S8Z24 384 10, // ASTC_2D_10X10
352 1, // Z32FS8 385 10, // ASTC_2D_10X10_SRGB
386 12, // ASTC_2D_12X12
387 12, // ASTC_2D_12X12_SRGB
388 6, // ASTC_2D_8X6
389 6, // ASTC_2D_8X6_SRGB
390 5, // ASTC_2D_6X5
391 5, // ASTC_2D_6X5_SRGB
392 1, // Z32F
393 1, // Z16
394 1, // Z24S8
395 1, // S8Z24
396 1, // Z32FS8
353}}; 397}};
354 398
355static constexpr u32 GetDefaultBlockHeight(PixelFormat format) { 399static constexpr u32 GetDefaultBlockHeight(PixelFormat format) {
@@ -413,6 +457,7 @@ constexpr std::array<u32, MaxPixelFormat> bpp_table = {{
413 128, // DXT23_SRGB 457 128, // DXT23_SRGB
414 128, // DXT45_SRGB 458 128, // DXT45_SRGB
415 128, // BC7U 459 128, // BC7U
460 16, // R4G4B4A4U
416 128, // ASTC_2D_4X4_SRGB 461 128, // ASTC_2D_4X4_SRGB
417 128, // ASTC_2D_8X8_SRGB 462 128, // ASTC_2D_8X8_SRGB
418 128, // ASTC_2D_8X5_SRGB 463 128, // ASTC_2D_8X5_SRGB
@@ -421,6 +466,16 @@ constexpr std::array<u32, MaxPixelFormat> bpp_table = {{
421 128, // ASTC_2D_5X5_SRGB 466 128, // ASTC_2D_5X5_SRGB
422 128, // ASTC_2D_10X8 467 128, // ASTC_2D_10X8
423 128, // ASTC_2D_10X8_SRGB 468 128, // ASTC_2D_10X8_SRGB
469 128, // ASTC_2D_6X6
470 128, // ASTC_2D_6X6_SRGB
471 128, // ASTC_2D_10X10
472 128, // ASTC_2D_10X10_SRGB
473 128, // ASTC_2D_12X12
474 128, // ASTC_2D_12X12_SRGB
475 128, // ASTC_2D_8X6
476 128, // ASTC_2D_8X6_SRGB
477 128, // ASTC_2D_6X5
478 128, // ASTC_2D_6X5_SRGB
424 32, // Z32F 479 32, // Z32F
425 16, // Z16 480 16, // Z16
426 32, // Z24S8 481 32, // Z24S8
@@ -504,6 +559,7 @@ constexpr std::array<SurfaceCompression, MaxPixelFormat> compression_type_table
504 SurfaceCompression::Compressed, // DXT23_SRGB 559 SurfaceCompression::Compressed, // DXT23_SRGB
505 SurfaceCompression::Compressed, // DXT45_SRGB 560 SurfaceCompression::Compressed, // DXT45_SRGB
506 SurfaceCompression::Compressed, // BC7U_SRGB 561 SurfaceCompression::Compressed, // BC7U_SRGB
562 SurfaceCompression::None, // R4G4B4A4U
507 SurfaceCompression::Converted, // ASTC_2D_4X4_SRGB 563 SurfaceCompression::Converted, // ASTC_2D_4X4_SRGB
508 SurfaceCompression::Converted, // ASTC_2D_8X8_SRGB 564 SurfaceCompression::Converted, // ASTC_2D_8X8_SRGB
509 SurfaceCompression::Converted, // ASTC_2D_8X5_SRGB 565 SurfaceCompression::Converted, // ASTC_2D_8X5_SRGB
@@ -512,6 +568,16 @@ constexpr std::array<SurfaceCompression, MaxPixelFormat> compression_type_table
512 SurfaceCompression::Converted, // ASTC_2D_5X5_SRGB 568 SurfaceCompression::Converted, // ASTC_2D_5X5_SRGB
513 SurfaceCompression::Converted, // ASTC_2D_10X8 569 SurfaceCompression::Converted, // ASTC_2D_10X8
514 SurfaceCompression::Converted, // ASTC_2D_10X8_SRGB 570 SurfaceCompression::Converted, // ASTC_2D_10X8_SRGB
571 SurfaceCompression::Converted, // ASTC_2D_6X6
572 SurfaceCompression::Converted, // ASTC_2D_6X6_SRGB
573 SurfaceCompression::Converted, // ASTC_2D_10X10
574 SurfaceCompression::Converted, // ASTC_2D_10X10_SRGB
575 SurfaceCompression::Converted, // ASTC_2D_12X12
576 SurfaceCompression::Converted, // ASTC_2D_12X12_SRGB
577 SurfaceCompression::Converted, // ASTC_2D_8X6
578 SurfaceCompression::Converted, // ASTC_2D_8X6_SRGB
579 SurfaceCompression::Converted, // ASTC_2D_6X5
580 SurfaceCompression::Converted, // ASTC_2D_6X5_SRGB
515 SurfaceCompression::None, // Z32F 581 SurfaceCompression::None, // Z32F
516 SurfaceCompression::None, // Z16 582 SurfaceCompression::None, // Z16
517 SurfaceCompression::None, // Z24S8 583 SurfaceCompression::None, // Z24S8