diff options
Diffstat (limited to 'src')
56 files changed, 432 insertions, 92 deletions
diff --git a/src/audio_core/renderer/performance/performance_manager.cpp b/src/audio_core/renderer/performance/performance_manager.cpp index fd5873e1e..8aa0f5ed0 100644 --- a/src/audio_core/renderer/performance/performance_manager.cpp +++ b/src/audio_core/renderer/performance/performance_manager.cpp | |||
| @@ -26,6 +26,7 @@ void PerformanceManager::CreateImpl(const size_t version) { | |||
| 26 | impl = std::make_unique< | 26 | impl = std::make_unique< |
| 27 | PerformanceManagerImpl<PerformanceVersion::Version1, PerformanceFrameHeaderVersion1, | 27 | PerformanceManagerImpl<PerformanceVersion::Version1, PerformanceFrameHeaderVersion1, |
| 28 | PerformanceEntryVersion1, PerformanceDetailVersion1>>(); | 28 | PerformanceEntryVersion1, PerformanceDetailVersion1>>(); |
| 29 | break; | ||
| 29 | } | 30 | } |
| 30 | } | 31 | } |
| 31 | 32 | ||
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index c0555f840..b7c15c191 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt | |||
| @@ -34,6 +34,8 @@ add_library(common STATIC | |||
| 34 | bit_util.h | 34 | bit_util.h |
| 35 | cityhash.cpp | 35 | cityhash.cpp |
| 36 | cityhash.h | 36 | cityhash.h |
| 37 | cache_management.cpp | ||
| 38 | cache_management.h | ||
| 37 | common_funcs.h | 39 | common_funcs.h |
| 38 | common_types.h | 40 | common_types.h |
| 39 | concepts.h | 41 | concepts.h |
diff --git a/src/common/atomic_helpers.h b/src/common/atomic_helpers.h index bef5015c1..aef3b66a4 100644 --- a/src/common/atomic_helpers.h +++ b/src/common/atomic_helpers.h | |||
| @@ -156,6 +156,7 @@ AE_FORCEINLINE void compiler_fence(memory_order order) AE_NO_TSAN { | |||
| 156 | break; | 156 | break; |
| 157 | default: | 157 | default: |
| 158 | assert(false); | 158 | assert(false); |
| 159 | break; | ||
| 159 | } | 160 | } |
| 160 | } | 161 | } |
| 161 | 162 | ||
diff --git a/src/common/cache_management.cpp b/src/common/cache_management.cpp new file mode 100644 index 000000000..57810b76a --- /dev/null +++ b/src/common/cache_management.cpp | |||
| @@ -0,0 +1,60 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include <cstring> | ||
| 5 | |||
| 6 | #include "alignment.h" | ||
| 7 | #include "cache_management.h" | ||
| 8 | #include "common_types.h" | ||
| 9 | |||
| 10 | namespace Common { | ||
| 11 | |||
| 12 | #if defined(ARCHITECTURE_x86_64) | ||
| 13 | |||
| 14 | // Most cache operations are no-ops on x86 | ||
| 15 | |||
| 16 | void DataCacheLineCleanByVAToPoU(void* start, size_t size) {} | ||
| 17 | void DataCacheLineCleanAndInvalidateByVAToPoC(void* start, size_t size) {} | ||
| 18 | void DataCacheLineCleanByVAToPoC(void* start, size_t size) {} | ||
| 19 | void DataCacheZeroByVA(void* start, size_t size) { | ||
| 20 | std::memset(start, 0, size); | ||
| 21 | } | ||
| 22 | |||
| 23 | #elif defined(ARCHITECTURE_arm64) | ||
| 24 | |||
| 25 | // BS/DminLine is log2(cache size in words), we want size in bytes | ||
| 26 | #define EXTRACT_DMINLINE(ctr_el0) (1 << ((((ctr_el0) >> 16) & 0xf) + 2)) | ||
| 27 | #define EXTRACT_BS(dczid_el0) (1 << (((dczid_el0)&0xf) + 2)) | ||
| 28 | |||
| 29 | #define DEFINE_DC_OP(op_name, function_name) \ | ||
| 30 | void function_name(void* start, size_t size) { \ | ||
| 31 | size_t ctr_el0; \ | ||
| 32 | asm volatile("mrs %[ctr_el0], ctr_el0\n\t" : [ctr_el0] "=r"(ctr_el0)); \ | ||
| 33 | size_t cacheline_size = EXTRACT_DMINLINE(ctr_el0); \ | ||
| 34 | uintptr_t va_start = reinterpret_cast<uintptr_t>(start); \ | ||
| 35 | uintptr_t va_end = va_start + size; \ | ||
| 36 | for (uintptr_t va = va_start; va < va_end; va += cacheline_size) { \ | ||
| 37 | asm volatile("dc " #op_name ", %[va]\n\t" : : [va] "r"(va) : "memory"); \ | ||
| 38 | } \ | ||
| 39 | } | ||
| 40 | |||
| 41 | #define DEFINE_DC_OP_DCZID(op_name, function_name) \ | ||
| 42 | void function_name(void* start, size_t size) { \ | ||
| 43 | size_t dczid_el0; \ | ||
| 44 | asm volatile("mrs %[dczid_el0], dczid_el0\n\t" : [dczid_el0] "=r"(dczid_el0)); \ | ||
| 45 | size_t cacheline_size = EXTRACT_BS(dczid_el0); \ | ||
| 46 | uintptr_t va_start = reinterpret_cast<uintptr_t>(start); \ | ||
| 47 | uintptr_t va_end = va_start + size; \ | ||
| 48 | for (uintptr_t va = va_start; va < va_end; va += cacheline_size) { \ | ||
| 49 | asm volatile("dc " #op_name ", %[va]\n\t" : : [va] "r"(va) : "memory"); \ | ||
| 50 | } \ | ||
| 51 | } | ||
| 52 | |||
| 53 | DEFINE_DC_OP(cvau, DataCacheLineCleanByVAToPoU); | ||
| 54 | DEFINE_DC_OP(civac, DataCacheLineCleanAndInvalidateByVAToPoC); | ||
| 55 | DEFINE_DC_OP(cvac, DataCacheLineCleanByVAToPoC); | ||
| 56 | DEFINE_DC_OP_DCZID(zva, DataCacheZeroByVA); | ||
| 57 | |||
| 58 | #endif | ||
| 59 | |||
| 60 | } // namespace Common | ||
diff --git a/src/common/cache_management.h b/src/common/cache_management.h new file mode 100644 index 000000000..e467b87e4 --- /dev/null +++ b/src/common/cache_management.h | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "stdlib.h" | ||
| 7 | |||
| 8 | namespace Common { | ||
| 9 | |||
| 10 | // Data cache instructions enabled at EL0 by SCTLR_EL1.UCI. | ||
| 11 | // VA = virtual address | ||
| 12 | // PoC = point of coherency | ||
| 13 | // PoU = point of unification | ||
| 14 | |||
| 15 | // dc cvau | ||
| 16 | void DataCacheLineCleanByVAToPoU(void* start, size_t size); | ||
| 17 | |||
| 18 | // dc civac | ||
| 19 | void DataCacheLineCleanAndInvalidateByVAToPoC(void* start, size_t size); | ||
| 20 | |||
| 21 | // dc cvac | ||
| 22 | void DataCacheLineCleanByVAToPoC(void* start, size_t size); | ||
| 23 | |||
| 24 | // dc zva | ||
| 25 | void DataCacheZeroByVA(void* start, size_t size); | ||
| 26 | |||
| 27 | } // namespace Common | ||
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index afb7fb3a0..cb53d64ba 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp | |||
| @@ -348,7 +348,6 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable* | |||
| 348 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Auto) { | 348 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Auto) { |
| 349 | config.unsafe_optimizations = true; | 349 | config.unsafe_optimizations = true; |
| 350 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; | 350 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; |
| 351 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_InaccurateNaN; | ||
| 352 | config.fastmem_address_space_bits = 64; | 351 | config.fastmem_address_space_bits = 64; |
| 353 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreGlobalMonitor; | 352 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreGlobalMonitor; |
| 354 | } | 353 | } |
diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp index aac45907d..fb7e5802a 100644 --- a/src/core/hid/emulated_console.cpp +++ b/src/core/hid/emulated_console.cpp | |||
| @@ -19,27 +19,26 @@ void EmulatedConsole::ReloadFromSettings() { | |||
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | void EmulatedConsole::SetTouchParams() { | 21 | void EmulatedConsole::SetTouchParams() { |
| 22 | // TODO(german77): Support any number of fingers | ||
| 23 | std::size_t index = 0; | 22 | std::size_t index = 0; |
| 24 | 23 | ||
| 25 | // Hardcode mouse, touchscreen and cemuhook parameters | 24 | // We can't use mouse as touch if native mouse is enabled |
| 26 | if (!Settings::values.mouse_enabled) { | 25 | if (!Settings::values.mouse_enabled) { |
| 27 | // We can't use mouse as touch if native mouse is enabled | ||
| 28 | touch_params[index++] = Common::ParamPackage{"engine:mouse,axis_x:10,axis_y:11,button:0"}; | 26 | touch_params[index++] = Common::ParamPackage{"engine:mouse,axis_x:10,axis_y:11,button:0"}; |
| 29 | } | 27 | } |
| 30 | 28 | ||
| 31 | touch_params[index++] = | 29 | touch_params[index++] = |
| 32 | Common::ParamPackage{"engine:touch,axis_x:0,axis_y:1,button:0,touch_id:0"}; | 30 | Common::ParamPackage{"engine:cemuhookudp,axis_x:17,axis_y:18,button:65536"}; |
| 33 | touch_params[index++] = | 31 | touch_params[index++] = |
| 34 | Common::ParamPackage{"engine:touch,axis_x:2,axis_y:3,button:1,touch_id:1"}; | 32 | Common::ParamPackage{"engine:cemuhookudp,axis_x:19,axis_y:20,button:131072"}; |
| 35 | touch_params[index++] = | 33 | |
| 36 | Common::ParamPackage{"engine:touch,axis_x:4,axis_y:5,button:2,touch_id:2"}; | 34 | for (int i = 0; i < static_cast<int>(MaxActiveTouchInputs); i++) { |
| 37 | touch_params[index++] = | 35 | Common::ParamPackage touchscreen_param{}; |
| 38 | Common::ParamPackage{"engine:touch,axis_x:6,axis_y:7,button:3,touch_id:3"}; | 36 | touchscreen_param.Set("engine", "touch"); |
| 39 | touch_params[index++] = | 37 | touchscreen_param.Set("axis_x", i * 2); |
| 40 | Common::ParamPackage{"engine:cemuhookudp,axis_x:17,axis_y:18,button:65536,touch_id:0"}; | 38 | touchscreen_param.Set("axis_y", (i * 2) + 1); |
| 41 | touch_params[index++] = | 39 | touchscreen_param.Set("button", i); |
| 42 | Common::ParamPackage{"engine:cemuhookudp,axis_x:19,axis_y:20,button:131072,touch_id:1"}; | 40 | touch_params[index++] = touchscreen_param; |
| 41 | } | ||
| 43 | 42 | ||
| 44 | const auto button_index = | 43 | const auto button_index = |
| 45 | static_cast<u64>(Settings::values.touch_from_button_map_index.GetValue()); | 44 | static_cast<u64>(Settings::values.touch_from_button_map_index.GetValue()); |
| @@ -47,7 +46,7 @@ void EmulatedConsole::SetTouchParams() { | |||
| 47 | 46 | ||
| 48 | // Map the rest of the fingers from touch from button configuration | 47 | // Map the rest of the fingers from touch from button configuration |
| 49 | for (const auto& config_entry : touch_buttons) { | 48 | for (const auto& config_entry : touch_buttons) { |
| 50 | if (index >= touch_params.size()) { | 49 | if (index >= MaxTouchDevices) { |
| 51 | continue; | 50 | continue; |
| 52 | } | 51 | } |
| 53 | Common::ParamPackage params{config_entry}; | 52 | Common::ParamPackage params{config_entry}; |
| @@ -60,7 +59,6 @@ void EmulatedConsole::SetTouchParams() { | |||
| 60 | touch_button_params.Set("button", params.Serialize()); | 59 | touch_button_params.Set("button", params.Serialize()); |
| 61 | touch_button_params.Set("x", x); | 60 | touch_button_params.Set("x", x); |
| 62 | touch_button_params.Set("y", y); | 61 | touch_button_params.Set("y", y); |
| 63 | touch_button_params.Set("touch_id", static_cast<int>(index)); | ||
| 64 | touch_params[index] = touch_button_params; | 62 | touch_params[index] = touch_button_params; |
| 65 | index++; | 63 | index++; |
| 66 | } | 64 | } |
| @@ -178,12 +176,38 @@ void EmulatedConsole::SetMotion(const Common::Input::CallbackStatus& callback) { | |||
| 178 | } | 176 | } |
| 179 | 177 | ||
| 180 | void EmulatedConsole::SetTouch(const Common::Input::CallbackStatus& callback, std::size_t index) { | 178 | void EmulatedConsole::SetTouch(const Common::Input::CallbackStatus& callback, std::size_t index) { |
| 181 | if (index >= console.touch_values.size()) { | 179 | if (index >= MaxTouchDevices) { |
| 182 | return; | 180 | return; |
| 183 | } | 181 | } |
| 184 | std::unique_lock lock{mutex}; | 182 | std::unique_lock lock{mutex}; |
| 185 | 183 | ||
| 186 | console.touch_values[index] = TransformToTouch(callback); | 184 | const auto touch_input = TransformToTouch(callback); |
| 185 | auto touch_index = GetIndexFromFingerId(index); | ||
| 186 | bool is_new_input = false; | ||
| 187 | |||
| 188 | if (!touch_index.has_value() && touch_input.pressed.value) { | ||
| 189 | touch_index = GetNextFreeIndex(); | ||
| 190 | is_new_input = true; | ||
| 191 | } | ||
| 192 | |||
| 193 | // No free entries or invalid state. Ignore input | ||
| 194 | if (!touch_index.has_value()) { | ||
| 195 | return; | ||
| 196 | } | ||
| 197 | |||
| 198 | auto& touch_value = console.touch_values[touch_index.value()]; | ||
| 199 | |||
| 200 | if (is_new_input) { | ||
| 201 | touch_value.pressed.value = true; | ||
| 202 | touch_value.id = static_cast<u32>(index); | ||
| 203 | } | ||
| 204 | |||
| 205 | touch_value.x = touch_input.x; | ||
| 206 | touch_value.y = touch_input.y; | ||
| 207 | |||
| 208 | if (!touch_input.pressed.value) { | ||
| 209 | touch_value.pressed.value = false; | ||
| 210 | } | ||
| 187 | 211 | ||
| 188 | if (is_configuring) { | 212 | if (is_configuring) { |
| 189 | lock.unlock(); | 213 | lock.unlock(); |
| @@ -191,11 +215,15 @@ void EmulatedConsole::SetTouch(const Common::Input::CallbackStatus& callback, st | |||
| 191 | return; | 215 | return; |
| 192 | } | 216 | } |
| 193 | 217 | ||
| 194 | // TODO(german77): Remap touch id in sequential order | 218 | // Touch outside allowed range. Ignore input |
| 195 | console.touch_state[index] = { | 219 | if (touch_index.value() >= MaxActiveTouchInputs) { |
| 196 | .position = {console.touch_values[index].x.value, console.touch_values[index].y.value}, | 220 | return; |
| 197 | .id = static_cast<u32>(console.touch_values[index].id), | 221 | } |
| 198 | .pressed = console.touch_values[index].pressed.value, | 222 | |
| 223 | console.touch_state[touch_index.value()] = { | ||
| 224 | .position = {touch_value.x.value, touch_value.y.value}, | ||
| 225 | .id = static_cast<u32>(touch_index.value()), | ||
| 226 | .pressed = touch_input.pressed.value, | ||
| 199 | }; | 227 | }; |
| 200 | 228 | ||
| 201 | lock.unlock(); | 229 | lock.unlock(); |
| @@ -222,6 +250,28 @@ TouchFingerState EmulatedConsole::GetTouch() const { | |||
| 222 | return console.touch_state; | 250 | return console.touch_state; |
| 223 | } | 251 | } |
| 224 | 252 | ||
| 253 | std::optional<std::size_t> EmulatedConsole::GetIndexFromFingerId(std::size_t finger_id) const { | ||
| 254 | for (std::size_t index = 0; index < MaxTouchDevices; ++index) { | ||
| 255 | const auto& finger = console.touch_values[index]; | ||
| 256 | if (!finger.pressed.value) { | ||
| 257 | continue; | ||
| 258 | } | ||
| 259 | if (finger.id == static_cast<int>(finger_id)) { | ||
| 260 | return index; | ||
| 261 | } | ||
| 262 | } | ||
| 263 | return std::nullopt; | ||
| 264 | } | ||
| 265 | |||
| 266 | std::optional<std::size_t> EmulatedConsole::GetNextFreeIndex() const { | ||
| 267 | for (std::size_t index = 0; index < MaxTouchDevices; ++index) { | ||
| 268 | if (!console.touch_values[index].pressed.value) { | ||
| 269 | return index; | ||
| 270 | } | ||
| 271 | } | ||
| 272 | return std::nullopt; | ||
| 273 | } | ||
| 274 | |||
| 225 | void EmulatedConsole::TriggerOnChange(ConsoleTriggerType type) { | 275 | void EmulatedConsole::TriggerOnChange(ConsoleTriggerType type) { |
| 226 | std::scoped_lock lock{callback_mutex}; | 276 | std::scoped_lock lock{callback_mutex}; |
| 227 | for (const auto& poller_pair : callback_list) { | 277 | for (const auto& poller_pair : callback_list) { |
diff --git a/src/core/hid/emulated_console.h b/src/core/hid/emulated_console.h index 1c510cd19..697ecd2d6 100644 --- a/src/core/hid/emulated_console.h +++ b/src/core/hid/emulated_console.h | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <functional> | 7 | #include <functional> |
| 8 | #include <memory> | 8 | #include <memory> |
| 9 | #include <mutex> | 9 | #include <mutex> |
| 10 | #include <optional> | ||
| 10 | #include <unordered_map> | 11 | #include <unordered_map> |
| 11 | 12 | ||
| 12 | #include "common/common_funcs.h" | 13 | #include "common/common_funcs.h" |
| @@ -20,6 +21,8 @@ | |||
| 20 | #include "core/hid/motion_input.h" | 21 | #include "core/hid/motion_input.h" |
| 21 | 22 | ||
| 22 | namespace Core::HID { | 23 | namespace Core::HID { |
| 24 | static constexpr std::size_t MaxTouchDevices = 32; | ||
| 25 | static constexpr std::size_t MaxActiveTouchInputs = 16; | ||
| 23 | 26 | ||
| 24 | struct ConsoleMotionInfo { | 27 | struct ConsoleMotionInfo { |
| 25 | Common::Input::MotionStatus raw_status{}; | 28 | Common::Input::MotionStatus raw_status{}; |
| @@ -27,13 +30,13 @@ struct ConsoleMotionInfo { | |||
| 27 | }; | 30 | }; |
| 28 | 31 | ||
| 29 | using ConsoleMotionDevices = std::unique_ptr<Common::Input::InputDevice>; | 32 | using ConsoleMotionDevices = std::unique_ptr<Common::Input::InputDevice>; |
| 30 | using TouchDevices = std::array<std::unique_ptr<Common::Input::InputDevice>, 16>; | 33 | using TouchDevices = std::array<std::unique_ptr<Common::Input::InputDevice>, MaxTouchDevices>; |
| 31 | 34 | ||
| 32 | using ConsoleMotionParams = Common::ParamPackage; | 35 | using ConsoleMotionParams = Common::ParamPackage; |
| 33 | using TouchParams = std::array<Common::ParamPackage, 16>; | 36 | using TouchParams = std::array<Common::ParamPackage, MaxTouchDevices>; |
| 34 | 37 | ||
| 35 | using ConsoleMotionValues = ConsoleMotionInfo; | 38 | using ConsoleMotionValues = ConsoleMotionInfo; |
| 36 | using TouchValues = std::array<Common::Input::TouchStatus, 16>; | 39 | using TouchValues = std::array<Common::Input::TouchStatus, MaxTouchDevices>; |
| 37 | 40 | ||
| 38 | struct TouchFinger { | 41 | struct TouchFinger { |
| 39 | u64 last_touch{}; | 42 | u64 last_touch{}; |
| @@ -55,7 +58,7 @@ struct ConsoleMotion { | |||
| 55 | bool is_at_rest{}; | 58 | bool is_at_rest{}; |
| 56 | }; | 59 | }; |
| 57 | 60 | ||
| 58 | using TouchFingerState = std::array<TouchFinger, 16>; | 61 | using TouchFingerState = std::array<TouchFinger, MaxActiveTouchInputs>; |
| 59 | 62 | ||
| 60 | struct ConsoleStatus { | 63 | struct ConsoleStatus { |
| 61 | // Data from input_common | 64 | // Data from input_common |
| @@ -166,6 +169,10 @@ private: | |||
| 166 | */ | 169 | */ |
| 167 | void SetTouch(const Common::Input::CallbackStatus& callback, std::size_t index); | 170 | void SetTouch(const Common::Input::CallbackStatus& callback, std::size_t index); |
| 168 | 171 | ||
| 172 | std::optional<std::size_t> GetIndexFromFingerId(std::size_t finger_id) const; | ||
| 173 | |||
| 174 | std::optional<std::size_t> GetNextFreeIndex() const; | ||
| 175 | |||
| 169 | /** | 176 | /** |
| 170 | * Triggers a callback that something has changed on the console status | 177 | * Triggers a callback that something has changed on the console status |
| 171 | * @param type Input type of the event to trigger | 178 | * @param type Input type of the event to trigger |
diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp index 5d8b75b50..502692875 100644 --- a/src/core/hid/input_converter.cpp +++ b/src/core/hid/input_converter.cpp | |||
| @@ -200,9 +200,6 @@ Common::Input::TouchStatus TransformToTouch(const Common::Input::CallbackStatus& | |||
| 200 | x = std::clamp(x, 0.0f, 1.0f); | 200 | x = std::clamp(x, 0.0f, 1.0f); |
| 201 | y = std::clamp(y, 0.0f, 1.0f); | 201 | y = std::clamp(y, 0.0f, 1.0f); |
| 202 | 202 | ||
| 203 | // Limit id to maximum number of fingers | ||
| 204 | status.id = std::clamp(status.id, 0, 16); | ||
| 205 | |||
| 206 | if (status.pressed.inverted) { | 203 | if (status.pressed.inverted) { |
| 207 | status.pressed.value = !status.pressed.value; | 204 | status.pressed.value = !status.pressed.value; |
| 208 | } | 205 | } |
diff --git a/src/core/hle/kernel/init/init_slab_setup.cpp b/src/core/hle/kernel/init/init_slab_setup.cpp index bda098511..7b363eb1e 100644 --- a/src/core/hle/kernel/init/init_slab_setup.cpp +++ b/src/core/hle/kernel/init/init_slab_setup.cpp | |||
| @@ -243,6 +243,7 @@ void InitializeSlabHeaps(Core::System& system, KMemoryLayout& memory_layout) { | |||
| 243 | // If we somehow get an invalid type, abort. | 243 | // If we somehow get an invalid type, abort. |
| 244 | default: | 244 | default: |
| 245 | ASSERT_MSG(false, "Unknown slab type: {}", slab_types[i]); | 245 | ASSERT_MSG(false, "Unknown slab type: {}", slab_types[i]); |
| 246 | break; | ||
| 246 | } | 247 | } |
| 247 | 248 | ||
| 248 | // If we've hit the end of a gap, free it. | 249 | // If we've hit the end of a gap, free it. |
diff --git a/src/core/hle/kernel/k_page_table.cpp b/src/core/hle/kernel/k_page_table.cpp index 5387bf5fe..612fc76fa 100644 --- a/src/core/hle/kernel/k_page_table.cpp +++ b/src/core/hle/kernel/k_page_table.cpp | |||
| @@ -2301,6 +2301,7 @@ Result KPageTable::SetProcessMemoryPermission(VAddr addr, size_t size, | |||
| 2301 | break; | 2301 | break; |
| 2302 | default: | 2302 | default: |
| 2303 | ASSERT(false); | 2303 | ASSERT(false); |
| 2304 | break; | ||
| 2304 | } | 2305 | } |
| 2305 | } | 2306 | } |
| 2306 | 2307 | ||
| @@ -2803,6 +2804,7 @@ Result KPageTable::Operate(VAddr addr, size_t num_pages, const KPageGroup& page_ | |||
| 2803 | break; | 2804 | break; |
| 2804 | default: | 2805 | default: |
| 2805 | ASSERT(false); | 2806 | ASSERT(false); |
| 2807 | break; | ||
| 2806 | } | 2808 | } |
| 2807 | 2809 | ||
| 2808 | addr += size; | 2810 | addr += size; |
| @@ -2838,6 +2840,7 @@ Result KPageTable::Operate(VAddr addr, size_t num_pages, KMemoryPermission perm, | |||
| 2838 | break; | 2840 | break; |
| 2839 | default: | 2841 | default: |
| 2840 | ASSERT(false); | 2842 | ASSERT(false); |
| 2843 | break; | ||
| 2841 | } | 2844 | } |
| 2842 | R_SUCCEED(); | 2845 | R_SUCCEED(); |
| 2843 | } | 2846 | } |
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index 55a9c5fae..d1dc62401 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp | |||
| @@ -395,6 +395,7 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std: | |||
| 395 | 395 | ||
| 396 | default: | 396 | default: |
| 397 | ASSERT(false); | 397 | ASSERT(false); |
| 398 | break; | ||
| 398 | } | 399 | } |
| 399 | 400 | ||
| 400 | // Create TLS region | 401 | // Create TLS region |
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 9962ad171..e520cab47 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -2701,14 +2701,24 @@ static Result GetThreadList(Core::System& system, u32* out_num_threads, VAddr ou | |||
| 2701 | return ResultSuccess; | 2701 | return ResultSuccess; |
| 2702 | } | 2702 | } |
| 2703 | 2703 | ||
| 2704 | static Result FlushProcessDataCache32([[maybe_unused]] Core::System& system, | 2704 | static Result FlushProcessDataCache32(Core::System& system, Handle process_handle, u64 address, |
| 2705 | [[maybe_unused]] Handle handle, [[maybe_unused]] u32 address, | 2705 | u64 size) { |
| 2706 | [[maybe_unused]] u32 size) { | 2706 | // Validate address/size. |
| 2707 | // Note(Blinkhawk): For emulation purposes of the data cache this is mostly a no-op, | 2707 | R_UNLESS(size > 0, ResultInvalidSize); |
| 2708 | // as all emulation is done in the same cache level in host architecture, thus data cache | 2708 | R_UNLESS(address == static_cast<uintptr_t>(address), ResultInvalidCurrentMemory); |
| 2709 | // does not need flushing. | 2709 | R_UNLESS(size == static_cast<size_t>(size), ResultInvalidCurrentMemory); |
| 2710 | LOG_DEBUG(Kernel_SVC, "called"); | 2710 | |
| 2711 | return ResultSuccess; | 2711 | // Get the process from its handle. |
| 2712 | KScopedAutoObject process = | ||
| 2713 | system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KProcess>(process_handle); | ||
| 2714 | R_UNLESS(process.IsNotNull(), ResultInvalidHandle); | ||
| 2715 | |||
| 2716 | // Verify the region is within range. | ||
| 2717 | auto& page_table = process->PageTable(); | ||
| 2718 | R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory); | ||
| 2719 | |||
| 2720 | // Perform the operation. | ||
| 2721 | R_RETURN(system.Memory().FlushDataCache(*process, address, size)); | ||
| 2712 | } | 2722 | } |
| 2713 | 2723 | ||
| 2714 | namespace { | 2724 | namespace { |
diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h index 272c54cf7..3730937fe 100644 --- a/src/core/hle/kernel/svc_wrap.h +++ b/src/core/hle/kernel/svc_wrap.h | |||
| @@ -722,4 +722,12 @@ void SvcWrap32(Core::System& system) { | |||
| 722 | FuncReturn(system, retval); | 722 | FuncReturn(system, retval); |
| 723 | } | 723 | } |
| 724 | 724 | ||
| 725 | // Used by Invalidate/Store/FlushProcessDataCache32 | ||
| 726 | template <Result func(Core::System&, Handle, u64, u64)> | ||
| 727 | void SvcWrap32(Core::System& system) { | ||
| 728 | const u64 address = (Param(system, 3) << 32) | Param(system, 2); | ||
| 729 | const u64 size = (Param(system, 4) << 32) | Param(system, 1); | ||
| 730 | FuncReturn32(system, func(system, Param32(system, 0), address, size).raw); | ||
| 731 | } | ||
| 732 | |||
| 725 | } // namespace Kernel | 733 | } // namespace Kernel |
diff --git a/src/core/hle/service/am/applets/applet_error.cpp b/src/core/hle/service/am/applets/applet_error.cpp index fcf34bf7e..bae0d99a6 100644 --- a/src/core/hle/service/am/applets/applet_error.cpp +++ b/src/core/hle/service/am/applets/applet_error.cpp | |||
| @@ -144,6 +144,7 @@ void Error::Initialize() { | |||
| 144 | break; | 144 | break; |
| 145 | default: | 145 | default: |
| 146 | UNIMPLEMENTED_MSG("Unimplemented LibAppletError mode={:02X}!", mode); | 146 | UNIMPLEMENTED_MSG("Unimplemented LibAppletError mode={:02X}!", mode); |
| 147 | break; | ||
| 147 | } | 148 | } |
| 148 | } | 149 | } |
| 149 | 150 | ||
diff --git a/src/core/hle/service/am/applets/applet_general_backend.cpp b/src/core/hle/service/am/applets/applet_general_backend.cpp index c34ef08b3..e50acdaf6 100644 --- a/src/core/hle/service/am/applets/applet_general_backend.cpp +++ b/src/core/hle/service/am/applets/applet_general_backend.cpp | |||
| @@ -129,6 +129,7 @@ void Auth::Execute() { | |||
| 129 | } | 129 | } |
| 130 | default: | 130 | default: |
| 131 | unimplemented_log(); | 131 | unimplemented_log(); |
| 132 | break; | ||
| 132 | } | 133 | } |
| 133 | } | 134 | } |
| 134 | 135 | ||
| @@ -192,6 +193,7 @@ void PhotoViewer::Execute() { | |||
| 192 | break; | 193 | break; |
| 193 | default: | 194 | default: |
| 194 | UNIMPLEMENTED_MSG("Unimplemented PhotoViewer applet mode={:02X}!", mode); | 195 | UNIMPLEMENTED_MSG("Unimplemented PhotoViewer applet mode={:02X}!", mode); |
| 196 | break; | ||
| 195 | } | 197 | } |
| 196 | } | 198 | } |
| 197 | 199 | ||
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 79375bd2f..bf28440c6 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp | |||
| @@ -36,8 +36,9 @@ namespace Service::HID { | |||
| 36 | 36 | ||
| 37 | // Updating period for each HID device. | 37 | // Updating period for each HID device. |
| 38 | // Period time is obtained by measuring the number of samples in a second on HW using a homebrew | 38 | // Period time is obtained by measuring the number of samples in a second on HW using a homebrew |
| 39 | // Correct pad_update_ns is 4ms this is overclocked to lower input lag | 39 | // Correct npad_update_ns is 4ms this is overclocked to lower input lag |
| 40 | constexpr auto pad_update_ns = std::chrono::nanoseconds{1 * 1000 * 1000}; // (1ms, 1000Hz) | 40 | constexpr auto npad_update_ns = std::chrono::nanoseconds{1 * 1000 * 1000}; // (1ms, 1000Hz) |
| 41 | constexpr auto default_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000}; // (4ms, 1000Hz) | ||
| 41 | constexpr auto mouse_keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz) | 42 | constexpr auto mouse_keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz) |
| 42 | constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz) | 43 | constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz) |
| 43 | 44 | ||
| @@ -75,11 +76,19 @@ IAppletResource::IAppletResource(Core::System& system_, | |||
| 75 | GetController<Controller_Stubbed>(HidController::UniquePad).SetCommonHeaderOffset(0x5A00); | 76 | GetController<Controller_Stubbed>(HidController::UniquePad).SetCommonHeaderOffset(0x5A00); |
| 76 | 77 | ||
| 77 | // Register update callbacks | 78 | // Register update callbacks |
| 78 | pad_update_event = Core::Timing::CreateEvent( | 79 | npad_update_event = Core::Timing::CreateEvent( |
| 79 | "HID::UpdatePadCallback", | 80 | "HID::UpdatePadCallback", |
| 80 | [this](std::uintptr_t user_data, s64 time, | 81 | [this](std::uintptr_t user_data, s64 time, |
| 81 | std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { | 82 | std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { |
| 82 | const auto guard = LockService(); | 83 | const auto guard = LockService(); |
| 84 | UpdateNpad(user_data, ns_late); | ||
| 85 | return std::nullopt; | ||
| 86 | }); | ||
| 87 | default_update_event = Core::Timing::CreateEvent( | ||
| 88 | "HID::UpdateDefaultCallback", | ||
| 89 | [this](std::uintptr_t user_data, s64 time, | ||
| 90 | std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { | ||
| 91 | const auto guard = LockService(); | ||
| 83 | UpdateControllers(user_data, ns_late); | 92 | UpdateControllers(user_data, ns_late); |
| 84 | return std::nullopt; | 93 | return std::nullopt; |
| 85 | }); | 94 | }); |
| @@ -100,7 +109,9 @@ IAppletResource::IAppletResource(Core::System& system_, | |||
| 100 | return std::nullopt; | 109 | return std::nullopt; |
| 101 | }); | 110 | }); |
| 102 | 111 | ||
| 103 | system.CoreTiming().ScheduleLoopingEvent(pad_update_ns, pad_update_ns, pad_update_event); | 112 | system.CoreTiming().ScheduleLoopingEvent(npad_update_ns, npad_update_ns, npad_update_event); |
| 113 | system.CoreTiming().ScheduleLoopingEvent(default_update_ns, default_update_ns, | ||
| 114 | default_update_event); | ||
| 104 | system.CoreTiming().ScheduleLoopingEvent(mouse_keyboard_update_ns, mouse_keyboard_update_ns, | 115 | system.CoreTiming().ScheduleLoopingEvent(mouse_keyboard_update_ns, mouse_keyboard_update_ns, |
| 105 | mouse_keyboard_update_event); | 116 | mouse_keyboard_update_event); |
| 106 | system.CoreTiming().ScheduleLoopingEvent(motion_update_ns, motion_update_ns, | 117 | system.CoreTiming().ScheduleLoopingEvent(motion_update_ns, motion_update_ns, |
| @@ -118,7 +129,8 @@ void IAppletResource::DeactivateController(HidController controller) { | |||
| 118 | } | 129 | } |
| 119 | 130 | ||
| 120 | IAppletResource::~IAppletResource() { | 131 | IAppletResource::~IAppletResource() { |
| 121 | system.CoreTiming().UnscheduleEvent(pad_update_event, 0); | 132 | system.CoreTiming().UnscheduleEvent(npad_update_event, 0); |
| 133 | system.CoreTiming().UnscheduleEvent(default_update_event, 0); | ||
| 122 | system.CoreTiming().UnscheduleEvent(mouse_keyboard_update_event, 0); | 134 | system.CoreTiming().UnscheduleEvent(mouse_keyboard_update_event, 0); |
| 123 | system.CoreTiming().UnscheduleEvent(motion_update_event, 0); | 135 | system.CoreTiming().UnscheduleEvent(motion_update_event, 0); |
| 124 | } | 136 | } |
| @@ -144,10 +156,20 @@ void IAppletResource::UpdateControllers(std::uintptr_t user_data, | |||
| 144 | if (controller == controllers[static_cast<size_t>(HidController::Mouse)]) { | 156 | if (controller == controllers[static_cast<size_t>(HidController::Mouse)]) { |
| 145 | continue; | 157 | continue; |
| 146 | } | 158 | } |
| 159 | // Npad has it's own update event | ||
| 160 | if (controller == controllers[static_cast<size_t>(HidController::NPad)]) { | ||
| 161 | continue; | ||
| 162 | } | ||
| 147 | controller->OnUpdate(core_timing); | 163 | controller->OnUpdate(core_timing); |
| 148 | } | 164 | } |
| 149 | } | 165 | } |
| 150 | 166 | ||
| 167 | void IAppletResource::UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { | ||
| 168 | auto& core_timing = system.CoreTiming(); | ||
| 169 | |||
| 170 | controllers[static_cast<size_t>(HidController::NPad)]->OnUpdate(core_timing); | ||
| 171 | } | ||
| 172 | |||
| 151 | void IAppletResource::UpdateMouseKeyboard(std::uintptr_t user_data, | 173 | void IAppletResource::UpdateMouseKeyboard(std::uintptr_t user_data, |
| 152 | std::chrono::nanoseconds ns_late) { | 174 | std::chrono::nanoseconds ns_late) { |
| 153 | auto& core_timing = system.CoreTiming(); | 175 | auto& core_timing = system.CoreTiming(); |
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index 340d26fdc..b7c2a23ef 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h | |||
| @@ -71,12 +71,14 @@ private: | |||
| 71 | 71 | ||
| 72 | void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx); | 72 | void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx); |
| 73 | void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); | 73 | void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); |
| 74 | void UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); | ||
| 74 | void UpdateMouseKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); | 75 | void UpdateMouseKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); |
| 75 | void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); | 76 | void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); |
| 76 | 77 | ||
| 77 | KernelHelpers::ServiceContext& service_context; | 78 | KernelHelpers::ServiceContext& service_context; |
| 78 | 79 | ||
| 79 | std::shared_ptr<Core::Timing::EventType> pad_update_event; | 80 | std::shared_ptr<Core::Timing::EventType> npad_update_event; |
| 81 | std::shared_ptr<Core::Timing::EventType> default_update_event; | ||
| 80 | std::shared_ptr<Core::Timing::EventType> mouse_keyboard_update_event; | 82 | std::shared_ptr<Core::Timing::EventType> mouse_keyboard_update_event; |
| 81 | std::shared_ptr<Core::Timing::EventType> motion_update_event; | 83 | std::shared_ptr<Core::Timing::EventType> motion_update_event; |
| 82 | 84 | ||
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp index ced57dfe6..b97813fbc 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp | |||
| @@ -300,11 +300,10 @@ Kernel::KEvent* nvhost_ctrl_gpu::QueryEvent(u32 event_id) { | |||
| 300 | return error_notifier_event; | 300 | return error_notifier_event; |
| 301 | case 2: | 301 | case 2: |
| 302 | return unknown_event; | 302 | return unknown_event; |
| 303 | default: { | 303 | default: |
| 304 | LOG_CRITICAL(Service_NVDRV, "Unknown Ctrl GPU Event {}", event_id); | 304 | LOG_CRITICAL(Service_NVDRV, "Unknown Ctrl GPU Event {}", event_id); |
| 305 | return nullptr; | ||
| 305 | } | 306 | } |
| 306 | } | ||
| 307 | return nullptr; | ||
| 308 | } | 307 | } |
| 309 | 308 | ||
| 310 | } // namespace Service::Nvidia::Devices | 309 | } // namespace Service::Nvidia::Devices |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp index 45a759fa8..e123564c6 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp | |||
| @@ -364,11 +364,10 @@ Kernel::KEvent* nvhost_gpu::QueryEvent(u32 event_id) { | |||
| 364 | return sm_exception_breakpoint_pause_report_event; | 364 | return sm_exception_breakpoint_pause_report_event; |
| 365 | case 3: | 365 | case 3: |
| 366 | return error_notifier_event; | 366 | return error_notifier_event; |
| 367 | default: { | 367 | default: |
| 368 | LOG_CRITICAL(Service_NVDRV, "Unknown Ctrl GPU Event {}", event_id); | 368 | LOG_CRITICAL(Service_NVDRV, "Unknown Ctrl GPU Event {}", event_id); |
| 369 | return nullptr; | ||
| 369 | } | 370 | } |
| 370 | } | ||
| 371 | return nullptr; | ||
| 372 | } | 371 | } |
| 373 | 372 | ||
| 374 | } // namespace Service::Nvidia::Devices | 373 | } // namespace Service::Nvidia::Devices |
diff --git a/src/core/hle/service/nvflinger/buffer_queue_core.cpp b/src/core/hle/service/nvflinger/buffer_queue_core.cpp index ea4a14ea4..3d1338e66 100644 --- a/src/core/hle/service/nvflinger/buffer_queue_core.cpp +++ b/src/core/hle/service/nvflinger/buffer_queue_core.cpp | |||
| @@ -23,15 +23,17 @@ void BufferQueueCore::NotifyShutdown() { | |||
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | void BufferQueueCore::SignalDequeueCondition() { | 25 | void BufferQueueCore::SignalDequeueCondition() { |
| 26 | dequeue_possible.store(true); | ||
| 26 | dequeue_condition.notify_all(); | 27 | dequeue_condition.notify_all(); |
| 27 | } | 28 | } |
| 28 | 29 | ||
| 29 | bool BufferQueueCore::WaitForDequeueCondition() { | 30 | bool BufferQueueCore::WaitForDequeueCondition(std::unique_lock<std::mutex>& lk) { |
| 30 | if (is_shutting_down) { | 31 | if (is_shutting_down) { |
| 31 | return false; | 32 | return false; |
| 32 | } | 33 | } |
| 33 | 34 | ||
| 34 | dequeue_condition.wait(mutex); | 35 | dequeue_condition.wait(lk, [&] { return dequeue_possible.load(); }); |
| 36 | dequeue_possible.store(false); | ||
| 35 | 37 | ||
| 36 | return true; | 38 | return true; |
| 37 | } | 39 | } |
diff --git a/src/core/hle/service/nvflinger/buffer_queue_core.h b/src/core/hle/service/nvflinger/buffer_queue_core.h index ca6baefaf..85b3bc4c1 100644 --- a/src/core/hle/service/nvflinger/buffer_queue_core.h +++ b/src/core/hle/service/nvflinger/buffer_queue_core.h | |||
| @@ -38,7 +38,7 @@ public: | |||
| 38 | 38 | ||
| 39 | private: | 39 | private: |
| 40 | void SignalDequeueCondition(); | 40 | void SignalDequeueCondition(); |
| 41 | bool WaitForDequeueCondition(); | 41 | bool WaitForDequeueCondition(std::unique_lock<std::mutex>& lk); |
| 42 | 42 | ||
| 43 | s32 GetMinUndequeuedBufferCountLocked(bool async) const; | 43 | s32 GetMinUndequeuedBufferCountLocked(bool async) const; |
| 44 | s32 GetMinMaxBufferCountLocked(bool async) const; | 44 | s32 GetMinMaxBufferCountLocked(bool async) const; |
| @@ -60,7 +60,8 @@ private: | |||
| 60 | BufferQueueDefs::SlotsType slots{}; | 60 | BufferQueueDefs::SlotsType slots{}; |
| 61 | std::vector<BufferItem> queue; | 61 | std::vector<BufferItem> queue; |
| 62 | s32 override_max_buffer_count{}; | 62 | s32 override_max_buffer_count{}; |
| 63 | mutable std::condition_variable_any dequeue_condition; | 63 | std::condition_variable dequeue_condition; |
| 64 | std::atomic<bool> dequeue_possible{}; | ||
| 64 | const bool use_async_buffer{}; // This is always disabled on HOS | 65 | const bool use_async_buffer{}; // This is always disabled on HOS |
| 65 | bool dequeue_buffer_cannot_block{}; | 66 | bool dequeue_buffer_cannot_block{}; |
| 66 | PixelFormat default_buffer_format{PixelFormat::Rgba8888}; | 67 | PixelFormat default_buffer_format{PixelFormat::Rgba8888}; |
diff --git a/src/core/hle/service/nvflinger/buffer_queue_producer.cpp b/src/core/hle/service/nvflinger/buffer_queue_producer.cpp index 41ba44b21..e601b5da1 100644 --- a/src/core/hle/service/nvflinger/buffer_queue_producer.cpp +++ b/src/core/hle/service/nvflinger/buffer_queue_producer.cpp | |||
| @@ -121,8 +121,8 @@ Status BufferQueueProducer::SetBufferCount(s32 buffer_count) { | |||
| 121 | return Status::NoError; | 121 | return Status::NoError; |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | Status BufferQueueProducer::WaitForFreeSlotThenRelock(bool async, s32* found, | 124 | Status BufferQueueProducer::WaitForFreeSlotThenRelock(bool async, s32* found, Status* return_flags, |
| 125 | Status* return_flags) const { | 125 | std::unique_lock<std::mutex>& lk) const { |
| 126 | bool try_again = true; | 126 | bool try_again = true; |
| 127 | 127 | ||
| 128 | while (try_again) { | 128 | while (try_again) { |
| @@ -214,7 +214,7 @@ Status BufferQueueProducer::WaitForFreeSlotThenRelock(bool async, s32* found, | |||
| 214 | return Status::WouldBlock; | 214 | return Status::WouldBlock; |
| 215 | } | 215 | } |
| 216 | 216 | ||
| 217 | if (!core->WaitForDequeueCondition()) { | 217 | if (!core->WaitForDequeueCondition(lk)) { |
| 218 | // We are no longer running | 218 | // We are no longer running |
| 219 | return Status::NoError; | 219 | return Status::NoError; |
| 220 | } | 220 | } |
| @@ -237,7 +237,7 @@ Status BufferQueueProducer::DequeueBuffer(s32* out_slot, Fence* out_fence, bool | |||
| 237 | Status return_flags = Status::NoError; | 237 | Status return_flags = Status::NoError; |
| 238 | bool attached_by_consumer = false; | 238 | bool attached_by_consumer = false; |
| 239 | { | 239 | { |
| 240 | std::scoped_lock lock{core->mutex}; | 240 | std::unique_lock lock{core->mutex}; |
| 241 | core->WaitWhileAllocatingLocked(); | 241 | core->WaitWhileAllocatingLocked(); |
| 242 | 242 | ||
| 243 | if (format == PixelFormat::NoFormat) { | 243 | if (format == PixelFormat::NoFormat) { |
| @@ -248,7 +248,7 @@ Status BufferQueueProducer::DequeueBuffer(s32* out_slot, Fence* out_fence, bool | |||
| 248 | usage |= core->consumer_usage_bit; | 248 | usage |= core->consumer_usage_bit; |
| 249 | 249 | ||
| 250 | s32 found{}; | 250 | s32 found{}; |
| 251 | Status status = WaitForFreeSlotThenRelock(async, &found, &return_flags); | 251 | Status status = WaitForFreeSlotThenRelock(async, &found, &return_flags, lock); |
| 252 | if (status != Status::NoError) { | 252 | if (status != Status::NoError) { |
| 253 | return status; | 253 | return status; |
| 254 | } | 254 | } |
| @@ -400,13 +400,13 @@ Status BufferQueueProducer::AttachBuffer(s32* out_slot, | |||
| 400 | return Status::BadValue; | 400 | return Status::BadValue; |
| 401 | } | 401 | } |
| 402 | 402 | ||
| 403 | std::scoped_lock lock{core->mutex}; | 403 | std::unique_lock lock{core->mutex}; |
| 404 | core->WaitWhileAllocatingLocked(); | 404 | core->WaitWhileAllocatingLocked(); |
| 405 | 405 | ||
| 406 | Status return_flags = Status::NoError; | 406 | Status return_flags = Status::NoError; |
| 407 | s32 found{}; | 407 | s32 found{}; |
| 408 | 408 | ||
| 409 | const auto status = WaitForFreeSlotThenRelock(false, &found, &return_flags); | 409 | const auto status = WaitForFreeSlotThenRelock(false, &found, &return_flags, lock); |
| 410 | if (status != Status::NoError) { | 410 | if (status != Status::NoError) { |
| 411 | return status; | 411 | return status; |
| 412 | } | 412 | } |
diff --git a/src/core/hle/service/nvflinger/buffer_queue_producer.h b/src/core/hle/service/nvflinger/buffer_queue_producer.h index 7526bf8ec..1d380480f 100644 --- a/src/core/hle/service/nvflinger/buffer_queue_producer.h +++ b/src/core/hle/service/nvflinger/buffer_queue_producer.h | |||
| @@ -70,7 +70,8 @@ public: | |||
| 70 | private: | 70 | private: |
| 71 | BufferQueueProducer(const BufferQueueProducer&) = delete; | 71 | BufferQueueProducer(const BufferQueueProducer&) = delete; |
| 72 | 72 | ||
| 73 | Status WaitForFreeSlotThenRelock(bool async, s32* found, Status* return_flags) const; | 73 | Status WaitForFreeSlotThenRelock(bool async, s32* found, Status* return_flags, |
| 74 | std::unique_lock<std::mutex>& lk) const; | ||
| 74 | 75 | ||
| 75 | Kernel::KEvent* buffer_wait_event{}; | 76 | Kernel::KEvent* buffer_wait_event{}; |
| 76 | Service::KernelHelpers::ServiceContext& service_context; | 77 | Service::KernelHelpers::ServiceContext& service_context; |
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 5ab41c0c4..0de67f1e1 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp | |||
| @@ -228,6 +228,7 @@ Result ServiceFrameworkBase::HandleSyncRequest(Kernel::KServerSession& session, | |||
| 228 | } | 228 | } |
| 229 | 229 | ||
| 230 | UNIMPLEMENTED_MSG("command_type={}", ctx.GetCommandType()); | 230 | UNIMPLEMENTED_MSG("command_type={}", ctx.GetCommandType()); |
| 231 | break; | ||
| 231 | } | 232 | } |
| 232 | 233 | ||
| 233 | // If emulation was shutdown, we are closing service threads, do not write the response back to | 234 | // If emulation was shutdown, we are closing service threads, do not write the response back to |
diff --git a/src/core/hle/service/time/time_zone_manager.cpp b/src/core/hle/service/time/time_zone_manager.cpp index 2aa675df9..f9ada7c93 100644 --- a/src/core/hle/service/time/time_zone_manager.cpp +++ b/src/core/hle/service/time/time_zone_manager.cpp | |||
| @@ -280,6 +280,7 @@ static constexpr int TransitionTime(int year, Rule rule, int offset) { | |||
| 280 | } | 280 | } |
| 281 | default: | 281 | default: |
| 282 | ASSERT(false); | 282 | ASSERT(false); |
| 283 | break; | ||
| 283 | } | 284 | } |
| 284 | return value + rule.transition_time + offset; | 285 | return value + rule.transition_time + offset; |
| 285 | } | 286 | } |
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 3ca80c8ff..3141122f1 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include "common/assert.h" | 7 | #include "common/assert.h" |
| 8 | #include "common/atomic_ops.h" | 8 | #include "common/atomic_ops.h" |
| 9 | #include "common/cache_management.h" | ||
| 9 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 10 | #include "common/logging/log.h" | 11 | #include "common/logging/log.h" |
| 11 | #include "common/page_table.h" | 12 | #include "common/page_table.h" |
| @@ -329,6 +330,55 @@ struct Memory::Impl { | |||
| 329 | }); | 330 | }); |
| 330 | } | 331 | } |
| 331 | 332 | ||
| 333 | template <typename Callback> | ||
| 334 | Result PerformCacheOperation(const Kernel::KProcess& process, VAddr dest_addr, std::size_t size, | ||
| 335 | Callback&& cb) { | ||
| 336 | class InvalidMemoryException : public std::exception {}; | ||
| 337 | |||
| 338 | try { | ||
| 339 | WalkBlock( | ||
| 340 | process, dest_addr, size, | ||
| 341 | [&](const std::size_t block_size, const VAddr current_vaddr) { | ||
| 342 | LOG_ERROR(HW_Memory, "Unmapped cache maintenance @ {:#018X}", current_vaddr); | ||
| 343 | throw InvalidMemoryException(); | ||
| 344 | }, | ||
| 345 | [&](const std::size_t block_size, u8* const host_ptr) { cb(block_size, host_ptr); }, | ||
| 346 | [&](const VAddr current_vaddr, const std::size_t block_size, u8* const host_ptr) { | ||
| 347 | system.GPU().FlushRegion(current_vaddr, block_size); | ||
| 348 | cb(block_size, host_ptr); | ||
| 349 | }, | ||
| 350 | [](const std::size_t block_size) {}); | ||
| 351 | } catch (InvalidMemoryException&) { | ||
| 352 | return Kernel::ResultInvalidCurrentMemory; | ||
| 353 | } | ||
| 354 | |||
| 355 | return ResultSuccess; | ||
| 356 | } | ||
| 357 | |||
| 358 | Result InvalidateDataCache(const Kernel::KProcess& process, VAddr dest_addr, std::size_t size) { | ||
| 359 | auto perform = [&](const std::size_t block_size, u8* const host_ptr) { | ||
| 360 | // Do nothing; this operation (dc ivac) cannot be supported | ||
| 361 | // from EL0 | ||
| 362 | }; | ||
| 363 | return PerformCacheOperation(process, dest_addr, size, perform); | ||
| 364 | } | ||
| 365 | |||
| 366 | Result StoreDataCache(const Kernel::KProcess& process, VAddr dest_addr, std::size_t size) { | ||
| 367 | auto perform = [&](const std::size_t block_size, u8* const host_ptr) { | ||
| 368 | // dc cvac: Store to point of coherency | ||
| 369 | Common::DataCacheLineCleanByVAToPoC(host_ptr, block_size); | ||
| 370 | }; | ||
| 371 | return PerformCacheOperation(process, dest_addr, size, perform); | ||
| 372 | } | ||
| 373 | |||
| 374 | Result FlushDataCache(const Kernel::KProcess& process, VAddr dest_addr, std::size_t size) { | ||
| 375 | auto perform = [&](const std::size_t block_size, u8* const host_ptr) { | ||
| 376 | // dc civac: Store to point of coherency, and invalidate from cache | ||
| 377 | Common::DataCacheLineCleanAndInvalidateByVAToPoC(host_ptr, block_size); | ||
| 378 | }; | ||
| 379 | return PerformCacheOperation(process, dest_addr, size, perform); | ||
| 380 | } | ||
| 381 | |||
| 332 | void MarkRegionDebug(VAddr vaddr, u64 size, bool debug) { | 382 | void MarkRegionDebug(VAddr vaddr, u64 size, bool debug) { |
| 333 | if (vaddr == 0) { | 383 | if (vaddr == 0) { |
| 334 | return; | 384 | return; |
| @@ -786,6 +836,21 @@ void Memory::ZeroBlock(const Kernel::KProcess& process, VAddr dest_addr, const s | |||
| 786 | impl->ZeroBlock(process, dest_addr, size); | 836 | impl->ZeroBlock(process, dest_addr, size); |
| 787 | } | 837 | } |
| 788 | 838 | ||
| 839 | Result Memory::InvalidateDataCache(const Kernel::KProcess& process, VAddr dest_addr, | ||
| 840 | const std::size_t size) { | ||
| 841 | return impl->InvalidateDataCache(process, dest_addr, size); | ||
| 842 | } | ||
| 843 | |||
| 844 | Result Memory::StoreDataCache(const Kernel::KProcess& process, VAddr dest_addr, | ||
| 845 | const std::size_t size) { | ||
| 846 | return impl->StoreDataCache(process, dest_addr, size); | ||
| 847 | } | ||
| 848 | |||
| 849 | Result Memory::FlushDataCache(const Kernel::KProcess& process, VAddr dest_addr, | ||
| 850 | const std::size_t size) { | ||
| 851 | return impl->FlushDataCache(process, dest_addr, size); | ||
| 852 | } | ||
| 853 | |||
| 789 | void Memory::RasterizerMarkRegionCached(VAddr vaddr, u64 size, bool cached) { | 854 | void Memory::RasterizerMarkRegionCached(VAddr vaddr, u64 size, bool cached) { |
| 790 | impl->RasterizerMarkRegionCached(vaddr, size, cached); | 855 | impl->RasterizerMarkRegionCached(vaddr, size, cached); |
| 791 | } | 856 | } |
diff --git a/src/core/memory.h b/src/core/memory.h index 81eac448b..31fe699d8 100644 --- a/src/core/memory.h +++ b/src/core/memory.h | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <string> | 8 | #include <string> |
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "core/hle/result.h" | ||
| 10 | 11 | ||
| 11 | namespace Common { | 12 | namespace Common { |
| 12 | struct PageTable; | 13 | struct PageTable; |
| @@ -450,6 +451,39 @@ public: | |||
| 450 | void ZeroBlock(const Kernel::KProcess& process, VAddr dest_addr, std::size_t size); | 451 | void ZeroBlock(const Kernel::KProcess& process, VAddr dest_addr, std::size_t size); |
| 451 | 452 | ||
| 452 | /** | 453 | /** |
| 454 | * Invalidates a range of bytes within the current process' address space at the specified | ||
| 455 | * virtual address. | ||
| 456 | * | ||
| 457 | * @param process The process that will have data invalidated within its address space. | ||
| 458 | * @param dest_addr The destination virtual address to invalidate the data from. | ||
| 459 | * @param size The size of the range to invalidate, in bytes. | ||
| 460 | * | ||
| 461 | */ | ||
| 462 | Result InvalidateDataCache(const Kernel::KProcess& process, VAddr dest_addr, std::size_t size); | ||
| 463 | |||
| 464 | /** | ||
| 465 | * Stores a range of bytes within the current process' address space at the specified | ||
| 466 | * virtual address. | ||
| 467 | * | ||
| 468 | * @param process The process that will have data stored within its address space. | ||
| 469 | * @param dest_addr The destination virtual address to store the data from. | ||
| 470 | * @param size The size of the range to store, in bytes. | ||
| 471 | * | ||
| 472 | */ | ||
| 473 | Result StoreDataCache(const Kernel::KProcess& process, VAddr dest_addr, std::size_t size); | ||
| 474 | |||
| 475 | /** | ||
| 476 | * Flushes a range of bytes within the current process' address space at the specified | ||
| 477 | * virtual address. | ||
| 478 | * | ||
| 479 | * @param process The process that will have data flushed within its address space. | ||
| 480 | * @param dest_addr The destination virtual address to flush the data from. | ||
| 481 | * @param size The size of the range to flush, in bytes. | ||
| 482 | * | ||
| 483 | */ | ||
| 484 | Result FlushDataCache(const Kernel::KProcess& process, VAddr dest_addr, std::size_t size); | ||
| 485 | |||
| 486 | /** | ||
| 453 | * Marks each page within the specified address range as cached or uncached. | 487 | * Marks each page within the specified address range as cached or uncached. |
| 454 | * | 488 | * |
| 455 | * @param vaddr The virtual address indicating the start of the address range. | 489 | * @param vaddr The virtual address indicating the start of the address range. |
diff --git a/src/input_common/helpers/touch_from_buttons.cpp b/src/input_common/helpers/touch_from_buttons.cpp index da4a3dca5..003a38da5 100644 --- a/src/input_common/helpers/touch_from_buttons.cpp +++ b/src/input_common/helpers/touch_from_buttons.cpp | |||
| @@ -10,8 +10,8 @@ namespace InputCommon { | |||
| 10 | class TouchFromButtonDevice final : public Common::Input::InputDevice { | 10 | class TouchFromButtonDevice final : public Common::Input::InputDevice { |
| 11 | public: | 11 | public: |
| 12 | using Button = std::unique_ptr<Common::Input::InputDevice>; | 12 | using Button = std::unique_ptr<Common::Input::InputDevice>; |
| 13 | TouchFromButtonDevice(Button button_, int touch_id_, float x_, float y_) | 13 | TouchFromButtonDevice(Button button_, float x_, float y_) |
| 14 | : button(std::move(button_)), touch_id(touch_id_), x(x_), y(y_) { | 14 | : button(std::move(button_)), x(x_), y(y_) { |
| 15 | last_button_value = false; | 15 | last_button_value = false; |
| 16 | button->SetCallback({ | 16 | button->SetCallback({ |
| 17 | .on_change = | 17 | .on_change = |
| @@ -34,7 +34,6 @@ public: | |||
| 34 | .pressed = button_status, | 34 | .pressed = button_status, |
| 35 | .x = {}, | 35 | .x = {}, |
| 36 | .y = {}, | 36 | .y = {}, |
| 37 | .id = touch_id, | ||
| 38 | }; | 37 | }; |
| 39 | status.x.properties = properties; | 38 | status.x.properties = properties; |
| 40 | status.y.properties = properties; | 39 | status.y.properties = properties; |
| @@ -62,7 +61,6 @@ public: | |||
| 62 | private: | 61 | private: |
| 63 | Button button; | 62 | Button button; |
| 64 | bool last_button_value; | 63 | bool last_button_value; |
| 65 | const int touch_id; | ||
| 66 | const float x; | 64 | const float x; |
| 67 | const float y; | 65 | const float y; |
| 68 | const Common::Input::AnalogProperties properties{0.0f, 1.0f, 0.5f, 0.0f, false}; | 66 | const Common::Input::AnalogProperties properties{0.0f, 1.0f, 0.5f, 0.0f, false}; |
| @@ -73,10 +71,9 @@ std::unique_ptr<Common::Input::InputDevice> TouchFromButton::Create( | |||
| 73 | const std::string null_engine = Common::ParamPackage{{"engine", "null"}}.Serialize(); | 71 | const std::string null_engine = Common::ParamPackage{{"engine", "null"}}.Serialize(); |
| 74 | auto button = Common::Input::CreateDeviceFromString<Common::Input::InputDevice>( | 72 | auto button = Common::Input::CreateDeviceFromString<Common::Input::InputDevice>( |
| 75 | params.Get("button", null_engine)); | 73 | params.Get("button", null_engine)); |
| 76 | const auto touch_id = params.Get("touch_id", 0); | ||
| 77 | const float x = params.Get("x", 0.0f) / 1280.0f; | 74 | const float x = params.Get("x", 0.0f) / 1280.0f; |
| 78 | const float y = params.Get("y", 0.0f) / 720.0f; | 75 | const float y = params.Get("y", 0.0f) / 720.0f; |
| 79 | return std::make_unique<TouchFromButtonDevice>(std::move(button), touch_id, x, y); | 76 | return std::make_unique<TouchFromButtonDevice>(std::move(button), x, y); |
| 80 | } | 77 | } |
| 81 | 78 | ||
| 82 | } // namespace InputCommon | 79 | } // namespace InputCommon |
diff --git a/src/input_common/input_poller.cpp b/src/input_common/input_poller.cpp index 4ac182147..fb8be42e2 100644 --- a/src/input_common/input_poller.cpp +++ b/src/input_common/input_poller.cpp | |||
| @@ -229,13 +229,12 @@ private: | |||
| 229 | 229 | ||
| 230 | class InputFromTouch final : public Common::Input::InputDevice { | 230 | class InputFromTouch final : public Common::Input::InputDevice { |
| 231 | public: | 231 | public: |
| 232 | explicit InputFromTouch(PadIdentifier identifier_, int touch_id_, int button_, bool toggle_, | 232 | explicit InputFromTouch(PadIdentifier identifier_, int button_, bool toggle_, bool inverted_, |
| 233 | bool inverted_, int axis_x_, int axis_y_, | 233 | int axis_x_, int axis_y_, Common::Input::AnalogProperties properties_x_, |
| 234 | Common::Input::AnalogProperties properties_x_, | ||
| 235 | Common::Input::AnalogProperties properties_y_, | 234 | Common::Input::AnalogProperties properties_y_, |
| 236 | InputEngine* input_engine_) | 235 | InputEngine* input_engine_) |
| 237 | : identifier(identifier_), touch_id(touch_id_), button(button_), toggle(toggle_), | 236 | : identifier(identifier_), button(button_), toggle(toggle_), inverted(inverted_), |
| 238 | inverted(inverted_), axis_x(axis_x_), axis_y(axis_y_), properties_x(properties_x_), | 237 | axis_x(axis_x_), axis_y(axis_y_), properties_x(properties_x_), |
| 239 | properties_y(properties_y_), input_engine(input_engine_) { | 238 | properties_y(properties_y_), input_engine(input_engine_) { |
| 240 | UpdateCallback engine_callback{[this]() { OnChange(); }}; | 239 | UpdateCallback engine_callback{[this]() { OnChange(); }}; |
| 241 | const InputIdentifier button_input_identifier{ | 240 | const InputIdentifier button_input_identifier{ |
| @@ -271,8 +270,7 @@ public: | |||
| 271 | } | 270 | } |
| 272 | 271 | ||
| 273 | Common::Input::TouchStatus GetStatus() const { | 272 | Common::Input::TouchStatus GetStatus() const { |
| 274 | Common::Input::TouchStatus status; | 273 | Common::Input::TouchStatus status{}; |
| 275 | status.id = touch_id; | ||
| 276 | status.pressed = { | 274 | status.pressed = { |
| 277 | .value = input_engine->GetButton(identifier, button), | 275 | .value = input_engine->GetButton(identifier, button), |
| 278 | .inverted = inverted, | 276 | .inverted = inverted, |
| @@ -307,7 +305,6 @@ public: | |||
| 307 | 305 | ||
| 308 | private: | 306 | private: |
| 309 | const PadIdentifier identifier; | 307 | const PadIdentifier identifier; |
| 310 | const int touch_id; | ||
| 311 | const int button; | 308 | const int button; |
| 312 | const bool toggle; | 309 | const bool toggle; |
| 313 | const bool inverted; | 310 | const bool inverted; |
| @@ -919,7 +916,6 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateTriggerDevice( | |||
| 919 | 916 | ||
| 920 | std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateTouchDevice( | 917 | std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateTouchDevice( |
| 921 | const Common::ParamPackage& params) { | 918 | const Common::ParamPackage& params) { |
| 922 | const auto touch_id = params.Get("touch_id", 0); | ||
| 923 | const auto deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f); | 919 | const auto deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f); |
| 924 | const auto range = std::clamp(params.Get("range", 1.0f), 0.25f, 1.50f); | 920 | const auto range = std::clamp(params.Get("range", 1.0f), 0.25f, 1.50f); |
| 925 | const auto threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f); | 921 | const auto threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f); |
| @@ -954,8 +950,8 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateTouchDevice( | |||
| 954 | input_engine->PreSetAxis(identifier, axis_x); | 950 | input_engine->PreSetAxis(identifier, axis_x); |
| 955 | input_engine->PreSetAxis(identifier, axis_y); | 951 | input_engine->PreSetAxis(identifier, axis_y); |
| 956 | input_engine->PreSetButton(identifier, button); | 952 | input_engine->PreSetButton(identifier, button); |
| 957 | return std::make_unique<InputFromTouch>(identifier, touch_id, button, toggle, inverted, axis_x, | 953 | return std::make_unique<InputFromTouch>(identifier, button, toggle, inverted, axis_x, axis_y, |
| 958 | axis_y, properties_x, properties_y, input_engine.get()); | 954 | properties_x, properties_y, input_engine.get()); |
| 959 | } | 955 | } |
| 960 | 956 | ||
| 961 | std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateBatteryDevice( | 957 | std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateBatteryDevice( |
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 3b0176bf6..0cb1e193e 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp | |||
| @@ -320,6 +320,7 @@ void SetupOptions(const IR::Program& program, const Profile& profile, | |||
| 320 | } | 320 | } |
| 321 | if (stage == Stage::Fragment) { | 321 | if (stage == Stage::Fragment) { |
| 322 | header += "OPTION ARB_draw_buffers;"; | 322 | header += "OPTION ARB_draw_buffers;"; |
| 323 | header += "OPTION ARB_fragment_layer_viewport;"; | ||
| 323 | } | 324 | } |
| 324 | } | 325 | } |
| 325 | 326 | ||
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp index d6562c842..f0bd84ab2 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp | |||
| @@ -104,6 +104,9 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, Scal | |||
| 104 | case IR::Attribute::PrimitiveId: | 104 | case IR::Attribute::PrimitiveId: |
| 105 | ctx.Add("MOV.F {}.x,primitive.id;", inst); | 105 | ctx.Add("MOV.F {}.x,primitive.id;", inst); |
| 106 | break; | 106 | break; |
| 107 | case IR::Attribute::Layer: | ||
| 108 | ctx.Add("MOV.F {}.x,fragment.layer;", inst); | ||
| 109 | break; | ||
| 107 | case IR::Attribute::PositionX: | 110 | case IR::Attribute::PositionX: |
| 108 | case IR::Attribute::PositionY: | 111 | case IR::Attribute::PositionY: |
| 109 | case IR::Attribute::PositionZ: | 112 | case IR::Attribute::PositionZ: |
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp index c1671c37b..39579cf5d 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp | |||
| @@ -205,6 +205,9 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, | |||
| 205 | case IR::Attribute::PrimitiveId: | 205 | case IR::Attribute::PrimitiveId: |
| 206 | ctx.AddF32("{}=itof(gl_PrimitiveID);", inst); | 206 | ctx.AddF32("{}=itof(gl_PrimitiveID);", inst); |
| 207 | break; | 207 | break; |
| 208 | case IR::Attribute::Layer: | ||
| 209 | ctx.AddF32("{}=itof(gl_Layer);", inst); | ||
| 210 | break; | ||
| 208 | case IR::Attribute::PositionX: | 211 | case IR::Attribute::PositionX: |
| 209 | case IR::Attribute::PositionY: | 212 | case IR::Attribute::PositionY: |
| 210 | case IR::Attribute::PositionZ: | 213 | case IR::Attribute::PositionZ: |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp index 5b3b5d1f3..01f6ec9b5 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp | |||
| @@ -315,6 +315,8 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, Id vertex) { | |||
| 315 | switch (attr) { | 315 | switch (attr) { |
| 316 | case IR::Attribute::PrimitiveId: | 316 | case IR::Attribute::PrimitiveId: |
| 317 | return ctx.OpBitcast(ctx.F32[1], ctx.OpLoad(ctx.U32[1], ctx.primitive_id)); | 317 | return ctx.OpBitcast(ctx.F32[1], ctx.OpLoad(ctx.U32[1], ctx.primitive_id)); |
| 318 | case IR::Attribute::Layer: | ||
| 319 | return ctx.OpBitcast(ctx.F32[1], ctx.OpLoad(ctx.U32[1], ctx.layer)); | ||
| 318 | case IR::Attribute::PositionX: | 320 | case IR::Attribute::PositionX: |
| 319 | case IR::Attribute::PositionY: | 321 | case IR::Attribute::PositionY: |
| 320 | case IR::Attribute::PositionZ: | 322 | case IR::Attribute::PositionZ: |
diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index 0bfc2dd89..8e3e40cd5 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp | |||
| @@ -1359,6 +1359,11 @@ void EmitContext::DefineInputs(const IR::Program& program) { | |||
| 1359 | if (loads[IR::Attribute::PrimitiveId]) { | 1359 | if (loads[IR::Attribute::PrimitiveId]) { |
| 1360 | primitive_id = DefineInput(*this, U32[1], false, spv::BuiltIn::PrimitiveId); | 1360 | primitive_id = DefineInput(*this, U32[1], false, spv::BuiltIn::PrimitiveId); |
| 1361 | } | 1361 | } |
| 1362 | if (loads[IR::Attribute::Layer]) { | ||
| 1363 | AddCapability(spv::Capability::Geometry); | ||
| 1364 | layer = DefineInput(*this, U32[1], false, spv::BuiltIn::Layer); | ||
| 1365 | Decorate(layer, spv::Decoration::Flat); | ||
| 1366 | } | ||
| 1362 | if (loads.AnyComponent(IR::Attribute::PositionX)) { | 1367 | if (loads.AnyComponent(IR::Attribute::PositionX)) { |
| 1363 | const bool is_fragment{stage != Stage::Fragment}; | 1368 | const bool is_fragment{stage != Stage::Fragment}; |
| 1364 | const spv::BuiltIn built_in{is_fragment ? spv::BuiltIn::Position : spv::BuiltIn::FragCoord}; | 1369 | const spv::BuiltIn built_in{is_fragment ? spv::BuiltIn::Position : spv::BuiltIn::FragCoord}; |
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index d502d181c..5bb1427c1 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp | |||
| @@ -232,7 +232,7 @@ void Maxwell3D::ProcessMethodCall(u32 method, u32 argument, u32 nonshadow_argume | |||
| 232 | use_topology_override = true; | 232 | use_topology_override = true; |
| 233 | return; | 233 | return; |
| 234 | case MAXWELL3D_REG_INDEX(clear_surface): | 234 | case MAXWELL3D_REG_INDEX(clear_surface): |
| 235 | return ProcessClearBuffers(); | 235 | return ProcessClearBuffers(1); |
| 236 | case MAXWELL3D_REG_INDEX(report_semaphore.query): | 236 | case MAXWELL3D_REG_INDEX(report_semaphore.query): |
| 237 | return ProcessQueryGet(); | 237 | return ProcessQueryGet(); |
| 238 | case MAXWELL3D_REG_INDEX(render_enable.mode): | 238 | case MAXWELL3D_REG_INDEX(render_enable.mode): |
| @@ -596,8 +596,8 @@ u32 Maxwell3D::GetRegisterValue(u32 method) const { | |||
| 596 | return regs.reg_array[method]; | 596 | return regs.reg_array[method]; |
| 597 | } | 597 | } |
| 598 | 598 | ||
| 599 | void Maxwell3D::ProcessClearBuffers() { | 599 | void Maxwell3D::ProcessClearBuffers(u32 layer_count) { |
| 600 | rasterizer->Clear(); | 600 | rasterizer->Clear(layer_count); |
| 601 | } | 601 | } |
| 602 | 602 | ||
| 603 | void Maxwell3D::ProcessDraw(u32 instance_count) { | 603 | void Maxwell3D::ProcessDraw(u32 instance_count) { |
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 34b085388..c3099f9a6 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h | |||
| @@ -3086,6 +3086,9 @@ public: | |||
| 3086 | 3086 | ||
| 3087 | std::vector<u8> inline_index_draw_indexes; | 3087 | std::vector<u8> inline_index_draw_indexes; |
| 3088 | 3088 | ||
| 3089 | /// Handles a write to the CLEAR_BUFFERS register. | ||
| 3090 | void ProcessClearBuffers(u32 layer_count); | ||
| 3091 | |||
| 3089 | private: | 3092 | private: |
| 3090 | void InitializeRegisterDefaults(); | 3093 | void InitializeRegisterDefaults(); |
| 3091 | 3094 | ||
| @@ -3120,9 +3123,6 @@ private: | |||
| 3120 | /// Handles firmware blob 4 | 3123 | /// Handles firmware blob 4 |
| 3121 | void ProcessFirmwareCall4(); | 3124 | void ProcessFirmwareCall4(); |
| 3122 | 3125 | ||
| 3123 | /// Handles a write to the CLEAR_BUFFERS register. | ||
| 3124 | void ProcessClearBuffers(); | ||
| 3125 | |||
| 3126 | /// Handles a write to the QUERY_GET register. | 3126 | /// Handles a write to the QUERY_GET register. |
| 3127 | void ProcessQueryGet(); | 3127 | void ProcessQueryGet(); |
| 3128 | 3128 | ||
diff --git a/src/video_core/engines/maxwell_dma.cpp b/src/video_core/engines/maxwell_dma.cpp index 54523a4b2..1bf6ca2dd 100644 --- a/src/video_core/engines/maxwell_dma.cpp +++ b/src/video_core/engines/maxwell_dma.cpp | |||
| @@ -314,6 +314,7 @@ void MaxwellDMA::ReleaseSemaphore() { | |||
| 314 | } | 314 | } |
| 315 | default: | 315 | default: |
| 316 | ASSERT_MSG(false, "Unknown semaphore type: {}", static_cast<u32>(type.Value())); | 316 | ASSERT_MSG(false, "Unknown semaphore type: {}", static_cast<u32>(type.Value())); |
| 317 | break; | ||
| 317 | } | 318 | } |
| 318 | } | 319 | } |
| 319 | 320 | ||
diff --git a/src/video_core/engines/puller.cpp b/src/video_core/engines/puller.cpp index 3977bb0fb..4d2278811 100644 --- a/src/video_core/engines/puller.cpp +++ b/src/video_core/engines/puller.cpp | |||
| @@ -50,6 +50,7 @@ void Puller::ProcessBindMethod(const MethodCall& method_call) { | |||
| 50 | break; | 50 | break; |
| 51 | default: | 51 | default: |
| 52 | UNIMPLEMENTED_MSG("Unimplemented engine {:04X}", engine_id); | 52 | UNIMPLEMENTED_MSG("Unimplemented engine {:04X}", engine_id); |
| 53 | break; | ||
| 53 | } | 54 | } |
| 54 | } | 55 | } |
| 55 | 56 | ||
| @@ -65,6 +66,7 @@ void Puller::ProcessFenceActionMethod() { | |||
| 65 | break; | 66 | break; |
| 66 | default: | 67 | default: |
| 67 | UNIMPLEMENTED_MSG("Unimplemented operation {}", regs.fence_action.op.Value()); | 68 | UNIMPLEMENTED_MSG("Unimplemented operation {}", regs.fence_action.op.Value()); |
| 69 | break; | ||
| 68 | } | 70 | } |
| 69 | } | 71 | } |
| 70 | 72 | ||
| @@ -228,6 +230,7 @@ void Puller::CallEngineMethod(const MethodCall& method_call) { | |||
| 228 | break; | 230 | break; |
| 229 | default: | 231 | default: |
| 230 | UNIMPLEMENTED_MSG("Unimplemented engine"); | 232 | UNIMPLEMENTED_MSG("Unimplemented engine"); |
| 233 | break; | ||
| 231 | } | 234 | } |
| 232 | } | 235 | } |
| 233 | 236 | ||
| @@ -254,6 +257,7 @@ void Puller::CallEngineMultiMethod(u32 method, u32 subchannel, const u32* base_s | |||
| 254 | break; | 257 | break; |
| 255 | default: | 258 | default: |
| 256 | UNIMPLEMENTED_MSG("Unimplemented engine"); | 259 | UNIMPLEMENTED_MSG("Unimplemented engine"); |
| 260 | break; | ||
| 257 | } | 261 | } |
| 258 | } | 262 | } |
| 259 | 263 | ||
diff --git a/src/video_core/macro/macro_hle.cpp b/src/video_core/macro/macro_hle.cpp index f896591bf..0f3262edb 100644 --- a/src/video_core/macro/macro_hle.cpp +++ b/src/video_core/macro/macro_hle.cpp | |||
| @@ -126,11 +126,25 @@ void HLE_3F5E74B9C9A50164(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& | |||
| 126 | } | 126 | } |
| 127 | } | 127 | } |
| 128 | 128 | ||
| 129 | constexpr std::array<std::pair<u64, HLEFunction>, 4> hle_funcs{{ | 129 | // Multi-layer Clear |
| 130 | void HLE_EAD26C3E2109B06B(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters) { | ||
| 131 | ASSERT(parameters.size() == 1); | ||
| 132 | |||
| 133 | const Engines::Maxwell3D::Regs::ClearSurface clear_params{parameters[0]}; | ||
| 134 | const u32 rt_index = clear_params.RT; | ||
| 135 | const u32 num_layers = maxwell3d.regs.rt[rt_index].depth; | ||
| 136 | ASSERT(clear_params.layer == 0); | ||
| 137 | |||
| 138 | maxwell3d.regs.clear_surface.raw = clear_params.raw; | ||
| 139 | maxwell3d.ProcessClearBuffers(num_layers); | ||
| 140 | } | ||
| 141 | |||
| 142 | constexpr std::array<std::pair<u64, HLEFunction>, 5> hle_funcs{{ | ||
| 130 | {0x771BB18C62444DA0, &HLE_771BB18C62444DA0}, | 143 | {0x771BB18C62444DA0, &HLE_771BB18C62444DA0}, |
| 131 | {0x0D61FC9FAAC9FCAD, &HLE_0D61FC9FAAC9FCAD}, | 144 | {0x0D61FC9FAAC9FCAD, &HLE_0D61FC9FAAC9FCAD}, |
| 132 | {0x0217920100488FF7, &HLE_0217920100488FF7}, | 145 | {0x0217920100488FF7, &HLE_0217920100488FF7}, |
| 133 | {0x3F5E74B9C9A50164, &HLE_3F5E74B9C9A50164}, | 146 | {0x3F5E74B9C9A50164, &HLE_3F5E74B9C9A50164}, |
| 147 | {0xEAD26C3E2109B06B, &HLE_EAD26C3E2109B06B}, | ||
| 134 | }}; | 148 | }}; |
| 135 | 149 | ||
| 136 | class HLEMacroImpl final : public CachedMacro { | 150 | class HLEMacroImpl final : public CachedMacro { |
diff --git a/src/video_core/macro/macro_interpreter.cpp b/src/video_core/macro/macro_interpreter.cpp index c0d32c112..0d63495a9 100644 --- a/src/video_core/macro/macro_interpreter.cpp +++ b/src/video_core/macro/macro_interpreter.cpp | |||
| @@ -201,6 +201,7 @@ bool MacroInterpreterImpl::Step(bool is_delay_slot) { | |||
| 201 | } | 201 | } |
| 202 | default: | 202 | default: |
| 203 | UNIMPLEMENTED_MSG("Unimplemented macro operation {}", opcode.operation.Value()); | 203 | UNIMPLEMENTED_MSG("Unimplemented macro operation {}", opcode.operation.Value()); |
| 204 | break; | ||
| 204 | } | 205 | } |
| 205 | 206 | ||
| 206 | // An instruction with the Exit flag will not actually | 207 | // An instruction with the Exit flag will not actually |
| @@ -297,6 +298,7 @@ void MacroInterpreterImpl::ProcessResult(Macro::ResultOperation operation, u32 r | |||
| 297 | break; | 298 | break; |
| 298 | default: | 299 | default: |
| 299 | UNIMPLEMENTED_MSG("Unimplemented result operation {}", operation); | 300 | UNIMPLEMENTED_MSG("Unimplemented result operation {}", operation); |
| 301 | break; | ||
| 300 | } | 302 | } |
| 301 | } | 303 | } |
| 302 | 304 | ||
diff --git a/src/video_core/macro/macro_jit_x64.cpp b/src/video_core/macro/macro_jit_x64.cpp index 25c1ce798..7347cbd88 100644 --- a/src/video_core/macro/macro_jit_x64.cpp +++ b/src/video_core/macro/macro_jit_x64.cpp | |||
| @@ -652,6 +652,7 @@ void MacroJITx64Impl::Compile_ProcessResult(Macro::ResultOperation operation, u3 | |||
| 652 | break; | 652 | break; |
| 653 | default: | 653 | default: |
| 654 | UNIMPLEMENTED_MSG("Unimplemented macro operation {}", operation); | 654 | UNIMPLEMENTED_MSG("Unimplemented macro operation {}", operation); |
| 655 | break; | ||
| 655 | } | 656 | } |
| 656 | } | 657 | } |
| 657 | 658 | ||
diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h index 1cbfef090..cfd872a40 100644 --- a/src/video_core/rasterizer_interface.h +++ b/src/video_core/rasterizer_interface.h | |||
| @@ -43,7 +43,7 @@ public: | |||
| 43 | virtual void Draw(bool is_indexed, u32 instance_count) = 0; | 43 | virtual void Draw(bool is_indexed, u32 instance_count) = 0; |
| 44 | 44 | ||
| 45 | /// Clear the current framebuffer | 45 | /// Clear the current framebuffer |
| 46 | virtual void Clear() = 0; | 46 | virtual void Clear(u32 layer_count) = 0; |
| 47 | 47 | ||
| 48 | /// Dispatches a compute shader invocation | 48 | /// Dispatches a compute shader invocation |
| 49 | virtual void DispatchCompute() = 0; | 49 | virtual void DispatchCompute() = 0; |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index d05a5f60b..115a5e010 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -136,7 +136,7 @@ void RasterizerOpenGL::LoadDiskResources(u64 title_id, std::stop_token stop_load | |||
| 136 | shader_cache.LoadDiskResources(title_id, stop_loading, callback); | 136 | shader_cache.LoadDiskResources(title_id, stop_loading, callback); |
| 137 | } | 137 | } |
| 138 | 138 | ||
| 139 | void RasterizerOpenGL::Clear() { | 139 | void RasterizerOpenGL::Clear(u32 layer_count) { |
| 140 | MICROPROFILE_SCOPE(OpenGL_Clears); | 140 | MICROPROFILE_SCOPE(OpenGL_Clears); |
| 141 | if (!maxwell3d->ShouldExecute()) { | 141 | if (!maxwell3d->ShouldExecute()) { |
| 142 | return; | 142 | return; |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 793e0d608..449a14f12 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -69,7 +69,7 @@ public: | |||
| 69 | ~RasterizerOpenGL() override; | 69 | ~RasterizerOpenGL() override; |
| 70 | 70 | ||
| 71 | void Draw(bool is_indexed, u32 instance_count) override; | 71 | void Draw(bool is_indexed, u32 instance_count) override; |
| 72 | void Clear() override; | 72 | void Clear(u32 layer_count) override; |
| 73 | void DispatchCompute() override; | 73 | void DispatchCompute() override; |
| 74 | void ResetCounter(VideoCore::QueryType type) override; | 74 | void ResetCounter(VideoCore::QueryType type) override; |
| 75 | void Query(GPUVAddr gpu_addr, VideoCore::QueryType type, std::optional<u64> timestamp) override; | 75 | void Query(GPUVAddr gpu_addr, VideoCore::QueryType type, std::optional<u64> timestamp) override; |
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 99cd11d1e..9f7ce7414 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp | |||
| @@ -891,6 +891,7 @@ void Image::CopyBufferToImage(const VideoCommon::BufferImageCopy& copy, size_t b | |||
| 891 | break; | 891 | break; |
| 892 | default: | 892 | default: |
| 893 | ASSERT(false); | 893 | ASSERT(false); |
| 894 | break; | ||
| 894 | } | 895 | } |
| 895 | } | 896 | } |
| 896 | 897 | ||
| @@ -927,6 +928,7 @@ void Image::CopyImageToBuffer(const VideoCommon::BufferImageCopy& copy, size_t b | |||
| 927 | break; | 928 | break; |
| 928 | default: | 929 | default: |
| 929 | ASSERT(false); | 930 | ASSERT(false); |
| 931 | break; | ||
| 930 | } | 932 | } |
| 931 | // Compressed formats don't have a pixel format or type | 933 | // Compressed formats don't have a pixel format or type |
| 932 | const bool is_compressed = gl_format == GL_NONE; | 934 | const bool is_compressed = gl_format == GL_NONE; |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 8bd5eba7e..f29462f7c 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -340,6 +340,7 @@ void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, | |||
| 340 | texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV; | 340 | texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV; |
| 341 | // UNIMPLEMENTED_MSG("Unknown framebuffer pixel format: {}", | 341 | // UNIMPLEMENTED_MSG("Unknown framebuffer pixel format: {}", |
| 342 | // static_cast<u32>(framebuffer.pixel_format)); | 342 | // static_cast<u32>(framebuffer.pixel_format)); |
| 343 | break; | ||
| 343 | } | 344 | } |
| 344 | 345 | ||
| 345 | texture.resource.Release(); | 346 | texture.resource.Release(); |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index f69c0c50f..67b88621a 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -213,7 +213,7 @@ void RasterizerVulkan::Draw(bool is_indexed, u32 instance_count) { | |||
| 213 | EndTransformFeedback(); | 213 | EndTransformFeedback(); |
| 214 | } | 214 | } |
| 215 | 215 | ||
| 216 | void RasterizerVulkan::Clear() { | 216 | void RasterizerVulkan::Clear(u32 layer_count) { |
| 217 | MICROPROFILE_SCOPE(Vulkan_Clearing); | 217 | MICROPROFILE_SCOPE(Vulkan_Clearing); |
| 218 | 218 | ||
| 219 | if (!maxwell3d->ShouldExecute()) { | 219 | if (!maxwell3d->ShouldExecute()) { |
| @@ -256,7 +256,7 @@ void RasterizerVulkan::Clear() { | |||
| 256 | .rect = regs.clear_control.use_scissor ? GetScissorState(regs, 0, up_scale, down_shift) | 256 | .rect = regs.clear_control.use_scissor ? GetScissorState(regs, 0, up_scale, down_shift) |
| 257 | : default_scissor, | 257 | : default_scissor, |
| 258 | .baseArrayLayer = regs.clear_surface.layer, | 258 | .baseArrayLayer = regs.clear_surface.layer, |
| 259 | .layerCount = 1, | 259 | .layerCount = layer_count, |
| 260 | }; | 260 | }; |
| 261 | if (clear_rect.rect.extent.width == 0 || clear_rect.rect.extent.height == 0) { | 261 | if (clear_rect.rect.extent.width == 0 || clear_rect.rect.extent.height == 0) { |
| 262 | return; | 262 | return; |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index b0bc306f5..70f36d58a 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h | |||
| @@ -65,7 +65,7 @@ public: | |||
| 65 | ~RasterizerVulkan() override; | 65 | ~RasterizerVulkan() override; |
| 66 | 66 | ||
| 67 | void Draw(bool is_indexed, u32 instance_count) override; | 67 | void Draw(bool is_indexed, u32 instance_count) override; |
| 68 | void Clear() override; | 68 | void Clear(u32 layer_count) override; |
| 69 | void DispatchCompute() override; | 69 | void DispatchCompute() override; |
| 70 | void ResetCounter(VideoCore::QueryType type) override; | 70 | void ResetCounter(VideoCore::QueryType type) override; |
| 71 | void Query(GPUVAddr gpu_addr, VideoCore::QueryType type, std::optional<u64> timestamp) override; | 71 | void Query(GPUVAddr gpu_addr, VideoCore::QueryType type, std::optional<u64> timestamp) override; |
diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp index 7934f2a51..4a7b633b7 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.cpp +++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp | |||
| @@ -221,6 +221,7 @@ void Scheduler::SubmitExecution(VkSemaphore signal_semaphore, VkSemaphore wait_s | |||
| 221 | [[fallthrough]]; | 221 | [[fallthrough]]; |
| 222 | default: | 222 | default: |
| 223 | vk::Check(result); | 223 | vk::Check(result); |
| 224 | break; | ||
| 224 | } | 225 | } |
| 225 | }); | 226 | }); |
| 226 | chunk->MarkSubmit(); | 227 | chunk->MarkSubmit(); |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 853b80d8a..a65bbeb1c 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp | |||
| @@ -108,6 +108,7 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) { | |||
| 108 | break; | 108 | break; |
| 109 | default: | 109 | default: |
| 110 | ASSERT_MSG(false, "Invalid surface type"); | 110 | ASSERT_MSG(false, "Invalid surface type"); |
| 111 | break; | ||
| 111 | } | 112 | } |
| 112 | } | 113 | } |
| 113 | if (info.storage) { | 114 | if (info.storage) { |
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp index fd1a4b987..59120cd09 100644 --- a/src/video_core/textures/decoders.cpp +++ b/src/video_core/textures/decoders.cpp | |||
| @@ -170,6 +170,7 @@ void Swizzle(std::span<u8> output, std::span<const u8> input, u32 bytes_per_pixe | |||
| 170 | #undef BPP_CASE | 170 | #undef BPP_CASE |
| 171 | default: | 171 | default: |
| 172 | ASSERT_MSG(false, "Invalid bytes_per_pixel={}", bytes_per_pixel); | 172 | ASSERT_MSG(false, "Invalid bytes_per_pixel={}", bytes_per_pixel); |
| 173 | break; | ||
| 173 | } | 174 | } |
| 174 | } | 175 | } |
| 175 | 176 | ||
| @@ -217,6 +218,7 @@ void SwizzleSubrect(std::span<u8> output, std::span<const u8> input, u32 bytes_p | |||
| 217 | #undef BPP_CASE | 218 | #undef BPP_CASE |
| 218 | default: | 219 | default: |
| 219 | ASSERT_MSG(false, "Invalid bytes_per_pixel={}", bytes_per_pixel); | 220 | ASSERT_MSG(false, "Invalid bytes_per_pixel={}", bytes_per_pixel); |
| 221 | break; | ||
| 220 | } | 222 | } |
| 221 | } | 223 | } |
| 222 | 224 | ||
| @@ -240,6 +242,7 @@ void UnswizzleSubrect(std::span<u8> output, std::span<const u8> input, u32 bytes | |||
| 240 | #undef BPP_CASE | 242 | #undef BPP_CASE |
| 241 | default: | 243 | default: |
| 242 | ASSERT_MSG(false, "Invalid bytes_per_pixel={}", bytes_per_pixel); | 244 | ASSERT_MSG(false, "Invalid bytes_per_pixel={}", bytes_per_pixel); |
| 245 | break; | ||
| 243 | } | 246 | } |
| 244 | } | 247 | } |
| 245 | 248 | ||
diff --git a/src/yuzu/compatdb.cpp b/src/yuzu/compatdb.cpp index b03e71248..05f49c0d2 100644 --- a/src/yuzu/compatdb.cpp +++ b/src/yuzu/compatdb.cpp | |||
| @@ -126,6 +126,7 @@ void CompatDB::Submit() { | |||
| 126 | break; | 126 | break; |
| 127 | default: | 127 | default: |
| 128 | LOG_ERROR(Frontend, "Unexpected page: {}", currentId()); | 128 | LOG_ERROR(Frontend, "Unexpected page: {}", currentId()); |
| 129 | break; | ||
| 129 | } | 130 | } |
| 130 | } | 131 | } |
| 131 | 132 | ||
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 72498f52a..7ee2302cc 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -1956,6 +1956,7 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target | |||
| 1956 | } | 1956 | } |
| 1957 | default: | 1957 | default: |
| 1958 | UNIMPLEMENTED(); | 1958 | UNIMPLEMENTED(); |
| 1959 | break; | ||
| 1959 | } | 1960 | } |
| 1960 | 1961 | ||
| 1961 | const QString qpath = QString::fromStdString(Common::FS::PathToUTF8String(path)); | 1962 | const QString qpath = QString::fromStdString(Common::FS::PathToUTF8String(path)); |
| @@ -3199,6 +3200,7 @@ void GMainWindow::OnToggleGpuAccuracy() { | |||
| 3199 | case Settings::GPUAccuracy::Extreme: | 3200 | case Settings::GPUAccuracy::Extreme: |
| 3200 | default: { | 3201 | default: { |
| 3201 | Settings::values.gpu_accuracy.SetValue(Settings::GPUAccuracy::High); | 3202 | Settings::values.gpu_accuracy.SetValue(Settings::GPUAccuracy::High); |
| 3203 | break; | ||
| 3202 | } | 3204 | } |
| 3203 | } | 3205 | } |
| 3204 | 3206 | ||
| @@ -3531,6 +3533,7 @@ void GMainWindow::UpdateGPUAccuracyButton() { | |||
| 3531 | default: { | 3533 | default: { |
| 3532 | gpu_accuracy_button->setText(tr("GPU ERROR")); | 3534 | gpu_accuracy_button->setText(tr("GPU ERROR")); |
| 3533 | gpu_accuracy_button->setChecked(true); | 3535 | gpu_accuracy_button->setChecked(true); |
| 3536 | break; | ||
| 3534 | } | 3537 | } |
| 3535 | } | 3538 | } |
| 3536 | } | 3539 | } |
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp index 65455c86e..25948328c 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp | |||
| @@ -84,6 +84,7 @@ EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsyste | |||
| 84 | default: | 84 | default: |
| 85 | LOG_CRITICAL(Frontend, "Window manager subsystem not implemented"); | 85 | LOG_CRITICAL(Frontend, "Window manager subsystem not implemented"); |
| 86 | std::exit(EXIT_FAILURE); | 86 | std::exit(EXIT_FAILURE); |
| 87 | break; | ||
| 87 | } | 88 | } |
| 88 | 89 | ||
| 89 | OnResize(); | 90 | OnResize(); |
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp index e16f79eb4..dfe5a30ea 100644 --- a/src/yuzu_cmd/yuzu.cpp +++ b/src/yuzu_cmd/yuzu.cpp | |||
| @@ -351,6 +351,7 @@ int main(int argc, char** argv) { | |||
| 351 | "additional help.\n\nError Code: {:04X}-{:04X}\nError Description: {}", | 351 | "additional help.\n\nError Code: {:04X}-{:04X}\nError Description: {}", |
| 352 | loader_id, error_id, static_cast<Loader::ResultStatus>(error_id)); | 352 | loader_id, error_id, static_cast<Loader::ResultStatus>(error_id)); |
| 353 | } | 353 | } |
| 354 | break; | ||
| 354 | } | 355 | } |
| 355 | 356 | ||
| 356 | system.TelemetrySession().AddField(Common::Telemetry::FieldType::App, "Frontend", "SDL"); | 357 | system.TelemetrySession().AddField(Common::Telemetry::FieldType::App, "Frontend", "SDL"); |