diff options
Diffstat (limited to 'src')
79 files changed, 732 insertions, 403 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3ad2c0950..9182dbfd4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt | |||
| @@ -65,12 +65,14 @@ if (MSVC) | |||
| 65 | /we4305 # 'context': truncation from 'type1' to 'type2' | 65 | /we4305 # 'context': truncation from 'type1' to 'type2' |
| 66 | /we4388 # 'expression': signed/unsigned mismatch | 66 | /we4388 # 'expression': signed/unsigned mismatch |
| 67 | /we4389 # 'operator': signed/unsigned mismatch | 67 | /we4389 # 'operator': signed/unsigned mismatch |
| 68 | /we4505 # 'function': unreferenced local function has been removed | ||
| 68 | /we4547 # 'operator': operator before comma has no effect; expected operator with side-effect | 69 | /we4547 # 'operator': operator before comma has no effect; expected operator with side-effect |
| 69 | /we4549 # 'operator1': operator before comma has no effect; did you intend 'operator2'? | 70 | /we4549 # 'operator1': operator before comma has no effect; did you intend 'operator2'? |
| 70 | /we4555 # Expression has no effect; expected expression with side-effect | 71 | /we4555 # Expression has no effect; expected expression with side-effect |
| 71 | /we4715 # 'function': not all control paths return a value | 72 | /we4715 # 'function': not all control paths return a value |
| 72 | /we4834 # Discarding return value of function with 'nodiscard' attribute | 73 | /we4834 # Discarding return value of function with 'nodiscard' attribute |
| 73 | /we5038 # data member 'member1' will be initialized after data member 'member2' | 74 | /we5038 # data member 'member1' will be initialized after data member 'member2' |
| 75 | /we5245 # 'function': unreferenced function with internal linkage has been removed | ||
| 74 | ) | 76 | ) |
| 75 | 77 | ||
| 76 | if (ARCHITECTURE_x86_64) | 78 | if (ARCHITECTURE_x86_64) |
diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp index e829af1ac..802943eb7 100644 --- a/src/common/host_memory.cpp +++ b/src/common/host_memory.cpp | |||
| @@ -149,7 +149,7 @@ public: | |||
| 149 | } | 149 | } |
| 150 | 150 | ||
| 151 | void Unmap(size_t virtual_offset, size_t length) { | 151 | void Unmap(size_t virtual_offset, size_t length) { |
| 152 | std::lock_guard lock{placeholder_mutex}; | 152 | std::scoped_lock lock{placeholder_mutex}; |
| 153 | 153 | ||
| 154 | // Unmap until there are no more placeholders | 154 | // Unmap until there are no more placeholders |
| 155 | while (UnmapOnePlaceholder(virtual_offset, length)) { | 155 | while (UnmapOnePlaceholder(virtual_offset, length)) { |
| @@ -169,7 +169,7 @@ public: | |||
| 169 | } | 169 | } |
| 170 | const size_t virtual_end = virtual_offset + length; | 170 | const size_t virtual_end = virtual_offset + length; |
| 171 | 171 | ||
| 172 | std::lock_guard lock{placeholder_mutex}; | 172 | std::scoped_lock lock{placeholder_mutex}; |
| 173 | auto [it, end] = placeholders.equal_range({virtual_offset, virtual_end}); | 173 | auto [it, end] = placeholders.equal_range({virtual_offset, virtual_end}); |
| 174 | while (it != end) { | 174 | while (it != end) { |
| 175 | const size_t offset = std::max(it->lower(), virtual_offset); | 175 | const size_t offset = std::max(it->lower(), virtual_offset); |
diff --git a/src/common/logging/filter.cpp b/src/common/logging/filter.cpp index 9120cc178..4acbff649 100644 --- a/src/common/logging/filter.cpp +++ b/src/common/logging/filter.cpp | |||
| @@ -101,6 +101,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) { | |||
| 101 | SUB(Service, GRC) \ | 101 | SUB(Service, GRC) \ |
| 102 | SUB(Service, HID) \ | 102 | SUB(Service, HID) \ |
| 103 | SUB(Service, IRS) \ | 103 | SUB(Service, IRS) \ |
| 104 | SUB(Service, JIT) \ | ||
| 104 | SUB(Service, LBL) \ | 105 | SUB(Service, LBL) \ |
| 105 | SUB(Service, LDN) \ | 106 | SUB(Service, LDN) \ |
| 106 | SUB(Service, LDR) \ | 107 | SUB(Service, LDR) \ |
diff --git a/src/common/logging/types.h b/src/common/logging/types.h index f803ab796..99c15fa96 100644 --- a/src/common/logging/types.h +++ b/src/common/logging/types.h | |||
| @@ -69,6 +69,7 @@ enum class Class : u8 { | |||
| 69 | Service_GRC, ///< The game recording service | 69 | Service_GRC, ///< The game recording service |
| 70 | Service_HID, ///< The HID (Human interface device) service | 70 | Service_HID, ///< The HID (Human interface device) service |
| 71 | Service_IRS, ///< The IRS service | 71 | Service_IRS, ///< The IRS service |
| 72 | Service_JIT, ///< The JIT service | ||
| 72 | Service_LBL, ///< The LBL (LCD backlight) service | 73 | Service_LBL, ///< The LBL (LCD backlight) service |
| 73 | Service_LDN, ///< The LDN (Local domain network) service | 74 | Service_LDN, ///< The LDN (Local domain network) service |
| 74 | Service_LDR, ///< The loader service | 75 | Service_LDR, ///< The loader service |
diff --git a/src/common/thread.h b/src/common/thread.h index a8c17c71a..626609372 100644 --- a/src/common/thread.h +++ b/src/common/thread.h | |||
| @@ -17,7 +17,7 @@ namespace Common { | |||
| 17 | class Event { | 17 | class Event { |
| 18 | public: | 18 | public: |
| 19 | void Set() { | 19 | void Set() { |
| 20 | std::lock_guard lk{mutex}; | 20 | std::scoped_lock lk{mutex}; |
| 21 | if (!is_set) { | 21 | if (!is_set) { |
| 22 | is_set = true; | 22 | is_set = true; |
| 23 | condvar.notify_one(); | 23 | condvar.notify_one(); |
diff --git a/src/common/threadsafe_queue.h b/src/common/threadsafe_queue.h index 2c8c2b90e..7272ac6e8 100644 --- a/src/common/threadsafe_queue.h +++ b/src/common/threadsafe_queue.h | |||
| @@ -52,7 +52,7 @@ public: | |||
| 52 | // line before cv.wait | 52 | // line before cv.wait |
| 53 | // TODO(bunnei): This can be replaced with C++20 waitable atomics when properly supported. | 53 | // TODO(bunnei): This can be replaced with C++20 waitable atomics when properly supported. |
| 54 | // See discussion on https://github.com/yuzu-emu/yuzu/pull/3173 for details. | 54 | // See discussion on https://github.com/yuzu-emu/yuzu/pull/3173 for details. |
| 55 | std::lock_guard lock{cv_mutex}; | 55 | std::scoped_lock lock{cv_mutex}; |
| 56 | cv.notify_one(); | 56 | cv.notify_one(); |
| 57 | } | 57 | } |
| 58 | 58 | ||
| @@ -159,7 +159,7 @@ public: | |||
| 159 | 159 | ||
| 160 | template <typename Arg> | 160 | template <typename Arg> |
| 161 | void Push(Arg&& t) { | 161 | void Push(Arg&& t) { |
| 162 | std::lock_guard lock{write_lock}; | 162 | std::scoped_lock lock{write_lock}; |
| 163 | spsc_queue.Push(t); | 163 | spsc_queue.Push(t); |
| 164 | } | 164 | } |
| 165 | 165 | ||
diff --git a/src/common/x64/native_clock.cpp b/src/common/x64/native_clock.cpp index 7a3f21dcf..7fd9d22f8 100644 --- a/src/common/x64/native_clock.cpp +++ b/src/common/x64/native_clock.cpp | |||
| @@ -10,25 +10,49 @@ | |||
| 10 | #include "common/uint128.h" | 10 | #include "common/uint128.h" |
| 11 | #include "common/x64/native_clock.h" | 11 | #include "common/x64/native_clock.h" |
| 12 | 12 | ||
| 13 | #ifdef _MSC_VER | ||
| 14 | #include <intrin.h> | ||
| 15 | #endif | ||
| 16 | |||
| 13 | namespace Common { | 17 | namespace Common { |
| 14 | 18 | ||
| 19 | #ifdef _MSC_VER | ||
| 20 | __forceinline static u64 FencedRDTSC() { | ||
| 21 | _mm_lfence(); | ||
| 22 | _ReadWriteBarrier(); | ||
| 23 | const u64 result = __rdtsc(); | ||
| 24 | _mm_lfence(); | ||
| 25 | _ReadWriteBarrier(); | ||
| 26 | return result; | ||
| 27 | } | ||
| 28 | #else | ||
| 29 | static u64 FencedRDTSC() { | ||
| 30 | u64 result; | ||
| 31 | asm volatile("lfence\n\t" | ||
| 32 | "rdtsc\n\t" | ||
| 33 | "shl $32, %%rdx\n\t" | ||
| 34 | "or %%rdx, %0\n\t" | ||
| 35 | "lfence" | ||
| 36 | : "=a"(result) | ||
| 37 | : | ||
| 38 | : "rdx", "memory", "cc"); | ||
| 39 | return result; | ||
| 40 | } | ||
| 41 | #endif | ||
| 42 | |||
| 15 | u64 EstimateRDTSCFrequency() { | 43 | u64 EstimateRDTSCFrequency() { |
| 16 | // Discard the first result measuring the rdtsc. | 44 | // Discard the first result measuring the rdtsc. |
| 17 | _mm_mfence(); | 45 | FencedRDTSC(); |
| 18 | __rdtsc(); | ||
| 19 | std::this_thread::sleep_for(std::chrono::milliseconds{1}); | 46 | std::this_thread::sleep_for(std::chrono::milliseconds{1}); |
| 20 | _mm_mfence(); | 47 | FencedRDTSC(); |
| 21 | __rdtsc(); | ||
| 22 | 48 | ||
| 23 | // Get the current time. | 49 | // Get the current time. |
| 24 | const auto start_time = std::chrono::steady_clock::now(); | 50 | const auto start_time = std::chrono::steady_clock::now(); |
| 25 | _mm_mfence(); | 51 | const u64 tsc_start = FencedRDTSC(); |
| 26 | const u64 tsc_start = __rdtsc(); | ||
| 27 | // Wait for 200 milliseconds. | 52 | // Wait for 200 milliseconds. |
| 28 | std::this_thread::sleep_for(std::chrono::milliseconds{200}); | 53 | std::this_thread::sleep_for(std::chrono::milliseconds{200}); |
| 29 | const auto end_time = std::chrono::steady_clock::now(); | 54 | const auto end_time = std::chrono::steady_clock::now(); |
| 30 | _mm_mfence(); | 55 | const u64 tsc_end = FencedRDTSC(); |
| 31 | const u64 tsc_end = __rdtsc(); | ||
| 32 | // Calculate differences. | 56 | // Calculate differences. |
| 33 | const u64 timer_diff = static_cast<u64>( | 57 | const u64 timer_diff = static_cast<u64>( |
| 34 | std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - start_time).count()); | 58 | std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - start_time).count()); |
| @@ -42,8 +66,7 @@ NativeClock::NativeClock(u64 emulated_cpu_frequency_, u64 emulated_clock_frequen | |||
| 42 | u64 rtsc_frequency_) | 66 | u64 rtsc_frequency_) |
| 43 | : WallClock(emulated_cpu_frequency_, emulated_clock_frequency_, true), rtsc_frequency{ | 67 | : WallClock(emulated_cpu_frequency_, emulated_clock_frequency_, true), rtsc_frequency{ |
| 44 | rtsc_frequency_} { | 68 | rtsc_frequency_} { |
| 45 | _mm_mfence(); | 69 | time_point.inner.last_measure = FencedRDTSC(); |
| 46 | time_point.inner.last_measure = __rdtsc(); | ||
| 47 | time_point.inner.accumulated_ticks = 0U; | 70 | time_point.inner.accumulated_ticks = 0U; |
| 48 | ns_rtsc_factor = GetFixedPoint64Factor(NS_RATIO, rtsc_frequency); | 71 | ns_rtsc_factor = GetFixedPoint64Factor(NS_RATIO, rtsc_frequency); |
| 49 | us_rtsc_factor = GetFixedPoint64Factor(US_RATIO, rtsc_frequency); | 72 | us_rtsc_factor = GetFixedPoint64Factor(US_RATIO, rtsc_frequency); |
| @@ -58,8 +81,7 @@ u64 NativeClock::GetRTSC() { | |||
| 58 | 81 | ||
| 59 | current_time_point.pack = Common::AtomicLoad128(time_point.pack.data()); | 82 | current_time_point.pack = Common::AtomicLoad128(time_point.pack.data()); |
| 60 | do { | 83 | do { |
| 61 | _mm_mfence(); | 84 | const u64 current_measure = FencedRDTSC(); |
| 62 | const u64 current_measure = __rdtsc(); | ||
| 63 | u64 diff = current_measure - current_time_point.inner.last_measure; | 85 | u64 diff = current_measure - current_time_point.inner.last_measure; |
| 64 | diff = diff & ~static_cast<u64>(static_cast<s64>(diff) >> 63); // max(diff, 0) | 86 | diff = diff & ~static_cast<u64>(static_cast<s64>(diff) >> 63); // max(diff, 0) |
| 65 | new_time_point.inner.last_measure = current_measure > current_time_point.inner.last_measure | 87 | new_time_point.inner.last_measure = current_measure > current_time_point.inner.last_measure |
| @@ -80,8 +102,7 @@ void NativeClock::Pause(bool is_paused) { | |||
| 80 | current_time_point.pack = Common::AtomicLoad128(time_point.pack.data()); | 102 | current_time_point.pack = Common::AtomicLoad128(time_point.pack.data()); |
| 81 | do { | 103 | do { |
| 82 | new_time_point.pack = current_time_point.pack; | 104 | new_time_point.pack = current_time_point.pack; |
| 83 | _mm_mfence(); | 105 | new_time_point.inner.last_measure = FencedRDTSC(); |
| 84 | new_time_point.inner.last_measure = __rdtsc(); | ||
| 85 | } while (!Common::AtomicCompareAndSwap(time_point.pack.data(), new_time_point.pack, | 106 | } while (!Common::AtomicCompareAndSwap(time_point.pack.data(), new_time_point.pack, |
| 86 | current_time_point.pack, current_time_point.pack)); | 107 | current_time_point.pack, current_time_point.pack)); |
| 87 | } | 108 | } |
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 6536d0544..81eaf0942 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -458,6 +458,8 @@ add_library(core STATIC | |||
| 458 | hle/service/hid/controllers/touchscreen.h | 458 | hle/service/hid/controllers/touchscreen.h |
| 459 | hle/service/hid/controllers/xpad.cpp | 459 | hle/service/hid/controllers/xpad.cpp |
| 460 | hle/service/hid/controllers/xpad.h | 460 | hle/service/hid/controllers/xpad.h |
| 461 | hle/service/jit/jit.cpp | ||
| 462 | hle/service/jit/jit.h | ||
| 461 | hle/service/lbl/lbl.cpp | 463 | hle/service/lbl/lbl.cpp |
| 462 | hle/service/lbl/lbl.h | 464 | hle/service/lbl/lbl.h |
| 463 | hle/service/ldn/errors.h | 465 | hle/service/ldn/errors.h |
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h index c60322442..dce2f4195 100644 --- a/src/core/arm/arm_interface.h +++ b/src/core/arm/arm_interface.h | |||
| @@ -171,6 +171,9 @@ public: | |||
| 171 | /// Prepare core for thread reschedule (if needed to correctly handle state) | 171 | /// Prepare core for thread reschedule (if needed to correctly handle state) |
| 172 | virtual void PrepareReschedule() = 0; | 172 | virtual void PrepareReschedule() = 0; |
| 173 | 173 | ||
| 174 | /// Signal an interrupt and ask the core to halt as soon as possible. | ||
| 175 | virtual void SignalInterrupt() = 0; | ||
| 176 | |||
| 174 | struct BacktraceEntry { | 177 | struct BacktraceEntry { |
| 175 | std::string module; | 178 | std::string module; |
| 176 | u64 address; | 179 | u64 address; |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index 054572445..ab3210d84 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp | |||
| @@ -25,6 +25,9 @@ namespace Core { | |||
| 25 | 25 | ||
| 26 | using namespace Common::Literals; | 26 | using namespace Common::Literals; |
| 27 | 27 | ||
| 28 | constexpr Dynarmic::HaltReason break_loop = Dynarmic::HaltReason::UserDefined2; | ||
| 29 | constexpr Dynarmic::HaltReason svc_call = Dynarmic::HaltReason::UserDefined3; | ||
| 30 | |||
| 28 | class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks { | 31 | class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks { |
| 29 | public: | 32 | public: |
| 30 | explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent_) | 33 | explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent_) |
| @@ -84,15 +87,13 @@ public: | |||
| 84 | } | 87 | } |
| 85 | 88 | ||
| 86 | void CallSVC(u32 swi) override { | 89 | void CallSVC(u32 swi) override { |
| 87 | parent.svc_called = true; | ||
| 88 | parent.svc_swi = swi; | 90 | parent.svc_swi = swi; |
| 89 | parent.jit->HaltExecution(); | 91 | parent.jit->HaltExecution(svc_call); |
| 90 | } | 92 | } |
| 91 | 93 | ||
| 92 | void AddTicks(u64 ticks) override { | 94 | void AddTicks(u64 ticks) override { |
| 93 | if (parent.uses_wall_clock) { | 95 | ASSERT_MSG(!parent.uses_wall_clock, "This should never happen - dynarmic ticking disabled"); |
| 94 | return; | 96 | |
| 95 | } | ||
| 96 | // Divide the number of ticks by the amount of CPU cores. TODO(Subv): This yields only a | 97 | // Divide the number of ticks by the amount of CPU cores. TODO(Subv): This yields only a |
| 97 | // rough approximation of the amount of executed ticks in the system, it may be thrown off | 98 | // rough approximation of the amount of executed ticks in the system, it may be thrown off |
| 98 | // if not all cores are doing a similar amount of work. Instead of doing this, we should | 99 | // if not all cores are doing a similar amount of work. Instead of doing this, we should |
| @@ -108,12 +109,8 @@ public: | |||
| 108 | } | 109 | } |
| 109 | 110 | ||
| 110 | u64 GetTicksRemaining() override { | 111 | u64 GetTicksRemaining() override { |
| 111 | if (parent.uses_wall_clock) { | 112 | ASSERT_MSG(!parent.uses_wall_clock, "This should never happen - dynarmic ticking disabled"); |
| 112 | if (!parent.interrupt_handlers[parent.core_index].IsInterrupted()) { | 113 | |
| 113 | return minimum_run_cycles; | ||
| 114 | } | ||
| 115 | return 0U; | ||
| 116 | } | ||
| 117 | return std::max<s64>(parent.system.CoreTiming().GetDowncount(), 0); | 114 | return std::max<s64>(parent.system.CoreTiming().GetDowncount(), 0); |
| 118 | } | 115 | } |
| 119 | 116 | ||
| @@ -148,6 +145,7 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable* | |||
| 148 | 145 | ||
| 149 | // Timing | 146 | // Timing |
| 150 | config.wall_clock_cntpct = uses_wall_clock; | 147 | config.wall_clock_cntpct = uses_wall_clock; |
| 148 | config.enable_cycle_counting = !uses_wall_clock; | ||
| 151 | 149 | ||
| 152 | // Code cache size | 150 | // Code cache size |
| 153 | config.code_cache_size = 512_MiB; | 151 | config.code_cache_size = 512_MiB; |
| @@ -230,13 +228,11 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable* | |||
| 230 | 228 | ||
| 231 | void ARM_Dynarmic_32::Run() { | 229 | void ARM_Dynarmic_32::Run() { |
| 232 | while (true) { | 230 | while (true) { |
| 233 | jit->Run(); | 231 | const auto hr = jit->Run(); |
| 234 | if (!svc_called) { | 232 | if (Has(hr, svc_call)) { |
| 235 | break; | 233 | Kernel::Svc::Call(system, svc_swi); |
| 236 | } | 234 | } |
| 237 | svc_called = false; | 235 | if (Has(hr, break_loop)) { |
| 238 | Kernel::Svc::Call(system, svc_swi); | ||
| 239 | if (shutdown) { | ||
| 240 | break; | 236 | break; |
| 241 | } | 237 | } |
| 242 | } | 238 | } |
| @@ -322,8 +318,11 @@ void ARM_Dynarmic_32::LoadContext(const ThreadContext32& ctx) { | |||
| 322 | } | 318 | } |
| 323 | 319 | ||
| 324 | void ARM_Dynarmic_32::PrepareReschedule() { | 320 | void ARM_Dynarmic_32::PrepareReschedule() { |
| 325 | jit->HaltExecution(); | 321 | jit->HaltExecution(break_loop); |
| 326 | shutdown = true; | 322 | } |
| 323 | |||
| 324 | void ARM_Dynarmic_32::SignalInterrupt() { | ||
| 325 | jit->HaltExecution(break_loop); | ||
| 327 | } | 326 | } |
| 328 | 327 | ||
| 329 | void ARM_Dynarmic_32::ClearInstructionCache() { | 328 | void ARM_Dynarmic_32::ClearInstructionCache() { |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.h b/src/core/arm/dynarmic/arm_dynarmic_32.h index 5d47b600d..3f68a4ff1 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.h +++ b/src/core/arm/dynarmic/arm_dynarmic_32.h | |||
| @@ -57,6 +57,7 @@ public: | |||
| 57 | void LoadContext(const ThreadContext64& ctx) override {} | 57 | void LoadContext(const ThreadContext64& ctx) override {} |
| 58 | 58 | ||
| 59 | void PrepareReschedule() override; | 59 | void PrepareReschedule() override; |
| 60 | void SignalInterrupt() override; | ||
| 60 | void ClearExclusiveState() override; | 61 | void ClearExclusiveState() override; |
| 61 | 62 | ||
| 62 | void ClearInstructionCache() override; | 63 | void ClearInstructionCache() override; |
| @@ -83,9 +84,6 @@ private: | |||
| 83 | 84 | ||
| 84 | // SVC callback | 85 | // SVC callback |
| 85 | u32 svc_swi{}; | 86 | u32 svc_swi{}; |
| 86 | bool svc_called{}; | ||
| 87 | |||
| 88 | bool shutdown{}; | ||
| 89 | }; | 87 | }; |
| 90 | 88 | ||
| 91 | } // namespace Core | 89 | } // namespace Core |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 7ff8f9495..68822a1fc 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp | |||
| @@ -26,6 +26,9 @@ namespace Core { | |||
| 26 | using Vector = Dynarmic::A64::Vector; | 26 | using Vector = Dynarmic::A64::Vector; |
| 27 | using namespace Common::Literals; | 27 | using namespace Common::Literals; |
| 28 | 28 | ||
| 29 | constexpr Dynarmic::HaltReason break_loop = Dynarmic::HaltReason::UserDefined2; | ||
| 30 | constexpr Dynarmic::HaltReason svc_call = Dynarmic::HaltReason::UserDefined3; | ||
| 31 | |||
| 29 | class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks { | 32 | class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks { |
| 30 | public: | 33 | public: |
| 31 | explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent_) | 34 | explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent_) |
| @@ -106,7 +109,7 @@ public: | |||
| 106 | break; | 109 | break; |
| 107 | } | 110 | } |
| 108 | 111 | ||
| 109 | parent.jit->HaltExecution(); | 112 | parent.jit->HaltExecution(Dynarmic::HaltReason::CacheInvalidation); |
| 110 | } | 113 | } |
| 111 | 114 | ||
| 112 | void ExceptionRaised(u64 pc, Dynarmic::A64::Exception exception) override { | 115 | void ExceptionRaised(u64 pc, Dynarmic::A64::Exception exception) override { |
| @@ -126,15 +129,12 @@ public: | |||
| 126 | } | 129 | } |
| 127 | 130 | ||
| 128 | void CallSVC(u32 swi) override { | 131 | void CallSVC(u32 swi) override { |
| 129 | parent.svc_called = true; | ||
| 130 | parent.svc_swi = swi; | 132 | parent.svc_swi = swi; |
| 131 | parent.jit->HaltExecution(); | 133 | parent.jit->HaltExecution(svc_call); |
| 132 | } | 134 | } |
| 133 | 135 | ||
| 134 | void AddTicks(u64 ticks) override { | 136 | void AddTicks(u64 ticks) override { |
| 135 | if (parent.uses_wall_clock) { | 137 | ASSERT_MSG(!parent.uses_wall_clock, "This should never happen - dynarmic ticking disabled"); |
| 136 | return; | ||
| 137 | } | ||
| 138 | 138 | ||
| 139 | // Divide the number of ticks by the amount of CPU cores. TODO(Subv): This yields only a | 139 | // Divide the number of ticks by the amount of CPU cores. TODO(Subv): This yields only a |
| 140 | // rough approximation of the amount of executed ticks in the system, it may be thrown off | 140 | // rough approximation of the amount of executed ticks in the system, it may be thrown off |
| @@ -149,12 +149,8 @@ public: | |||
| 149 | } | 149 | } |
| 150 | 150 | ||
| 151 | u64 GetTicksRemaining() override { | 151 | u64 GetTicksRemaining() override { |
| 152 | if (parent.uses_wall_clock) { | 152 | ASSERT_MSG(!parent.uses_wall_clock, "This should never happen - dynarmic ticking disabled"); |
| 153 | if (!parent.interrupt_handlers[parent.core_index].IsInterrupted()) { | 153 | |
| 154 | return minimum_run_cycles; | ||
| 155 | } | ||
| 156 | return 0U; | ||
| 157 | } | ||
| 158 | return std::max<s64>(parent.system.CoreTiming().GetDowncount(), 0); | 154 | return std::max<s64>(parent.system.CoreTiming().GetDowncount(), 0); |
| 159 | } | 155 | } |
| 160 | 156 | ||
| @@ -210,6 +206,7 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable* | |||
| 210 | 206 | ||
| 211 | // Timing | 207 | // Timing |
| 212 | config.wall_clock_cntpct = uses_wall_clock; | 208 | config.wall_clock_cntpct = uses_wall_clock; |
| 209 | config.enable_cycle_counting = !uses_wall_clock; | ||
| 213 | 210 | ||
| 214 | // Code cache size | 211 | // Code cache size |
| 215 | config.code_cache_size = 512_MiB; | 212 | config.code_cache_size = 512_MiB; |
| @@ -292,13 +289,11 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable* | |||
| 292 | 289 | ||
| 293 | void ARM_Dynarmic_64::Run() { | 290 | void ARM_Dynarmic_64::Run() { |
| 294 | while (true) { | 291 | while (true) { |
| 295 | jit->Run(); | 292 | const auto hr = jit->Run(); |
| 296 | if (!svc_called) { | 293 | if (Has(hr, svc_call)) { |
| 297 | break; | 294 | Kernel::Svc::Call(system, svc_swi); |
| 298 | } | 295 | } |
| 299 | svc_called = false; | 296 | if (Has(hr, break_loop)) { |
| 300 | Kernel::Svc::Call(system, svc_swi); | ||
| 301 | if (shutdown) { | ||
| 302 | break; | 297 | break; |
| 303 | } | 298 | } |
| 304 | } | 299 | } |
| @@ -389,8 +384,11 @@ void ARM_Dynarmic_64::LoadContext(const ThreadContext64& ctx) { | |||
| 389 | } | 384 | } |
| 390 | 385 | ||
| 391 | void ARM_Dynarmic_64::PrepareReschedule() { | 386 | void ARM_Dynarmic_64::PrepareReschedule() { |
| 392 | jit->HaltExecution(); | 387 | jit->HaltExecution(break_loop); |
| 393 | shutdown = true; | 388 | } |
| 389 | |||
| 390 | void ARM_Dynarmic_64::SignalInterrupt() { | ||
| 391 | jit->HaltExecution(break_loop); | ||
| 394 | } | 392 | } |
| 395 | 393 | ||
| 396 | void ARM_Dynarmic_64::ClearInstructionCache() { | 394 | void ARM_Dynarmic_64::ClearInstructionCache() { |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.h b/src/core/arm/dynarmic/arm_dynarmic_64.h index 0c4e46c64..58bc7fbec 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.h +++ b/src/core/arm/dynarmic/arm_dynarmic_64.h | |||
| @@ -51,6 +51,7 @@ public: | |||
| 51 | void LoadContext(const ThreadContext64& ctx) override; | 51 | void LoadContext(const ThreadContext64& ctx) override; |
| 52 | 52 | ||
| 53 | void PrepareReschedule() override; | 53 | void PrepareReschedule() override; |
| 54 | void SignalInterrupt() override; | ||
| 54 | void ClearExclusiveState() override; | 55 | void ClearExclusiveState() override; |
| 55 | 56 | ||
| 56 | void ClearInstructionCache() override; | 57 | void ClearInstructionCache() override; |
| @@ -77,9 +78,6 @@ private: | |||
| 77 | 78 | ||
| 78 | // SVC callback | 79 | // SVC callback |
| 79 | u32 svc_swi{}; | 80 | u32 svc_swi{}; |
| 80 | bool svc_called{}; | ||
| 81 | |||
| 82 | bool shutdown{}; | ||
| 83 | }; | 81 | }; |
| 84 | 82 | ||
| 85 | } // namespace Core | 83 | } // namespace Core |
diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp index eef0ff493..de565048b 100644 --- a/src/core/hid/emulated_console.cpp +++ b/src/core/hid/emulated_console.cpp | |||
| @@ -132,7 +132,7 @@ void EmulatedConsole::SetMotionParam(Common::ParamPackage param) { | |||
| 132 | } | 132 | } |
| 133 | 133 | ||
| 134 | void EmulatedConsole::SetMotion(const Common::Input::CallbackStatus& callback) { | 134 | void EmulatedConsole::SetMotion(const Common::Input::CallbackStatus& callback) { |
| 135 | std::lock_guard lock{mutex}; | 135 | std::unique_lock lock{mutex}; |
| 136 | auto& raw_status = console.motion_values.raw_status; | 136 | auto& raw_status = console.motion_values.raw_status; |
| 137 | auto& emulated = console.motion_values.emulated; | 137 | auto& emulated = console.motion_values.emulated; |
| 138 | 138 | ||
| @@ -151,6 +151,7 @@ void EmulatedConsole::SetMotion(const Common::Input::CallbackStatus& callback) { | |||
| 151 | emulated.UpdateOrientation(raw_status.delta_timestamp); | 151 | emulated.UpdateOrientation(raw_status.delta_timestamp); |
| 152 | 152 | ||
| 153 | if (is_configuring) { | 153 | if (is_configuring) { |
| 154 | lock.unlock(); | ||
| 154 | TriggerOnChange(ConsoleTriggerType::Motion); | 155 | TriggerOnChange(ConsoleTriggerType::Motion); |
| 155 | return; | 156 | return; |
| 156 | } | 157 | } |
| @@ -166,6 +167,7 @@ void EmulatedConsole::SetMotion(const Common::Input::CallbackStatus& callback) { | |||
| 166 | // Find what is this value | 167 | // Find what is this value |
| 167 | motion.verticalization_error = 0.0f; | 168 | motion.verticalization_error = 0.0f; |
| 168 | 169 | ||
| 170 | lock.unlock(); | ||
| 169 | TriggerOnChange(ConsoleTriggerType::Motion); | 171 | TriggerOnChange(ConsoleTriggerType::Motion); |
| 170 | } | 172 | } |
| 171 | 173 | ||
| @@ -173,11 +175,12 @@ void EmulatedConsole::SetTouch(const Common::Input::CallbackStatus& callback, st | |||
| 173 | if (index >= console.touch_values.size()) { | 175 | if (index >= console.touch_values.size()) { |
| 174 | return; | 176 | return; |
| 175 | } | 177 | } |
| 176 | std::lock_guard lock{mutex}; | 178 | std::unique_lock lock{mutex}; |
| 177 | 179 | ||
| 178 | console.touch_values[index] = TransformToTouch(callback); | 180 | console.touch_values[index] = TransformToTouch(callback); |
| 179 | 181 | ||
| 180 | if (is_configuring) { | 182 | if (is_configuring) { |
| 183 | lock.unlock(); | ||
| 181 | TriggerOnChange(ConsoleTriggerType::Touch); | 184 | TriggerOnChange(ConsoleTriggerType::Touch); |
| 182 | return; | 185 | return; |
| 183 | } | 186 | } |
| @@ -189,26 +192,32 @@ void EmulatedConsole::SetTouch(const Common::Input::CallbackStatus& callback, st | |||
| 189 | .pressed = console.touch_values[index].pressed.value, | 192 | .pressed = console.touch_values[index].pressed.value, |
| 190 | }; | 193 | }; |
| 191 | 194 | ||
| 195 | lock.unlock(); | ||
| 192 | TriggerOnChange(ConsoleTriggerType::Touch); | 196 | TriggerOnChange(ConsoleTriggerType::Touch); |
| 193 | } | 197 | } |
| 194 | 198 | ||
| 195 | ConsoleMotionValues EmulatedConsole::GetMotionValues() const { | 199 | ConsoleMotionValues EmulatedConsole::GetMotionValues() const { |
| 200 | std::scoped_lock lock{mutex}; | ||
| 196 | return console.motion_values; | 201 | return console.motion_values; |
| 197 | } | 202 | } |
| 198 | 203 | ||
| 199 | TouchValues EmulatedConsole::GetTouchValues() const { | 204 | TouchValues EmulatedConsole::GetTouchValues() const { |
| 205 | std::scoped_lock lock{mutex}; | ||
| 200 | return console.touch_values; | 206 | return console.touch_values; |
| 201 | } | 207 | } |
| 202 | 208 | ||
| 203 | ConsoleMotion EmulatedConsole::GetMotion() const { | 209 | ConsoleMotion EmulatedConsole::GetMotion() const { |
| 210 | std::scoped_lock lock{mutex}; | ||
| 204 | return console.motion_state; | 211 | return console.motion_state; |
| 205 | } | 212 | } |
| 206 | 213 | ||
| 207 | TouchFingerState EmulatedConsole::GetTouch() const { | 214 | TouchFingerState EmulatedConsole::GetTouch() const { |
| 215 | std::scoped_lock lock{mutex}; | ||
| 208 | return console.touch_state; | 216 | return console.touch_state; |
| 209 | } | 217 | } |
| 210 | 218 | ||
| 211 | void EmulatedConsole::TriggerOnChange(ConsoleTriggerType type) { | 219 | void EmulatedConsole::TriggerOnChange(ConsoleTriggerType type) { |
| 220 | std::scoped_lock lock{callback_mutex}; | ||
| 212 | for (const auto& poller_pair : callback_list) { | 221 | for (const auto& poller_pair : callback_list) { |
| 213 | const ConsoleUpdateCallback& poller = poller_pair.second; | 222 | const ConsoleUpdateCallback& poller = poller_pair.second; |
| 214 | if (poller.on_change) { | 223 | if (poller.on_change) { |
| @@ -218,13 +227,13 @@ void EmulatedConsole::TriggerOnChange(ConsoleTriggerType type) { | |||
| 218 | } | 227 | } |
| 219 | 228 | ||
| 220 | int EmulatedConsole::SetCallback(ConsoleUpdateCallback update_callback) { | 229 | int EmulatedConsole::SetCallback(ConsoleUpdateCallback update_callback) { |
| 221 | std::lock_guard lock{mutex}; | 230 | std::scoped_lock lock{callback_mutex}; |
| 222 | callback_list.insert_or_assign(last_callback_key, update_callback); | 231 | callback_list.insert_or_assign(last_callback_key, update_callback); |
| 223 | return last_callback_key++; | 232 | return last_callback_key++; |
| 224 | } | 233 | } |
| 225 | 234 | ||
| 226 | void EmulatedConsole::DeleteCallback(int key) { | 235 | void EmulatedConsole::DeleteCallback(int key) { |
| 227 | std::lock_guard lock{mutex}; | 236 | std::scoped_lock lock{callback_mutex}; |
| 228 | const auto& iterator = callback_list.find(key); | 237 | const auto& iterator = callback_list.find(key); |
| 229 | if (iterator == callback_list.end()) { | 238 | if (iterator == callback_list.end()) { |
| 230 | LOG_ERROR(Input, "Tried to delete non-existent callback {}", key); | 239 | LOG_ERROR(Input, "Tried to delete non-existent callback {}", key); |
diff --git a/src/core/hid/emulated_console.h b/src/core/hid/emulated_console.h index 5eb170823..53677bdc5 100644 --- a/src/core/hid/emulated_console.h +++ b/src/core/hid/emulated_console.h | |||
| @@ -183,6 +183,7 @@ private: | |||
| 183 | TouchDevices touch_devices; | 183 | TouchDevices touch_devices; |
| 184 | 184 | ||
| 185 | mutable std::mutex mutex; | 185 | mutable std::mutex mutex; |
| 186 | mutable std::mutex callback_mutex; | ||
| 186 | std::unordered_map<int, ConsoleUpdateCallback> callback_list; | 187 | std::unordered_map<int, ConsoleUpdateCallback> callback_list; |
| 187 | int last_callback_key = 0; | 188 | int last_callback_key = 0; |
| 188 | 189 | ||
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 7e05666d6..c3f21066c 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp | |||
| @@ -353,14 +353,17 @@ void EmulatedController::DisableConfiguration() { | |||
| 353 | } | 353 | } |
| 354 | 354 | ||
| 355 | void EmulatedController::EnableSystemButtons() { | 355 | void EmulatedController::EnableSystemButtons() { |
| 356 | std::scoped_lock lock{mutex}; | ||
| 356 | system_buttons_enabled = true; | 357 | system_buttons_enabled = true; |
| 357 | } | 358 | } |
| 358 | 359 | ||
| 359 | void EmulatedController::DisableSystemButtons() { | 360 | void EmulatedController::DisableSystemButtons() { |
| 361 | std::scoped_lock lock{mutex}; | ||
| 360 | system_buttons_enabled = false; | 362 | system_buttons_enabled = false; |
| 361 | } | 363 | } |
| 362 | 364 | ||
| 363 | void EmulatedController::ResetSystemButtons() { | 365 | void EmulatedController::ResetSystemButtons() { |
| 366 | std::scoped_lock lock{mutex}; | ||
| 364 | controller.home_button_state.home.Assign(false); | 367 | controller.home_button_state.home.Assign(false); |
| 365 | controller.capture_button_state.capture.Assign(false); | 368 | controller.capture_button_state.capture.Assign(false); |
| 366 | } | 369 | } |
| @@ -494,139 +497,141 @@ void EmulatedController::SetButton(const Common::Input::CallbackStatus& callback | |||
| 494 | if (index >= controller.button_values.size()) { | 497 | if (index >= controller.button_values.size()) { |
| 495 | return; | 498 | return; |
| 496 | } | 499 | } |
| 497 | { | 500 | std::unique_lock lock{mutex}; |
| 498 | std::lock_guard lock{mutex}; | 501 | bool value_changed = false; |
| 499 | bool value_changed = false; | 502 | const auto new_status = TransformToButton(callback); |
| 500 | const auto new_status = TransformToButton(callback); | 503 | auto& current_status = controller.button_values[index]; |
| 501 | auto& current_status = controller.button_values[index]; | ||
| 502 | 504 | ||
| 503 | // Only read button values that have the same uuid or are pressed once | 505 | // Only read button values that have the same uuid or are pressed once |
| 504 | if (current_status.uuid != uuid) { | 506 | if (current_status.uuid != uuid) { |
| 505 | if (!new_status.value) { | 507 | if (!new_status.value) { |
| 506 | return; | 508 | return; |
| 507 | } | ||
| 508 | } | 509 | } |
| 510 | } | ||
| 509 | 511 | ||
| 510 | current_status.toggle = new_status.toggle; | 512 | current_status.toggle = new_status.toggle; |
| 511 | current_status.uuid = uuid; | 513 | current_status.uuid = uuid; |
| 512 | |||
| 513 | // Update button status with current | ||
| 514 | if (!current_status.toggle) { | ||
| 515 | current_status.locked = false; | ||
| 516 | if (current_status.value != new_status.value) { | ||
| 517 | current_status.value = new_status.value; | ||
| 518 | value_changed = true; | ||
| 519 | } | ||
| 520 | } else { | ||
| 521 | // Toggle button and lock status | ||
| 522 | if (new_status.value && !current_status.locked) { | ||
| 523 | current_status.locked = true; | ||
| 524 | current_status.value = !current_status.value; | ||
| 525 | value_changed = true; | ||
| 526 | } | ||
| 527 | 514 | ||
| 528 | // Unlock button ready for next press | 515 | // Update button status with current |
| 529 | if (!new_status.value && current_status.locked) { | 516 | if (!current_status.toggle) { |
| 530 | current_status.locked = false; | 517 | current_status.locked = false; |
| 531 | } | 518 | if (current_status.value != new_status.value) { |
| 519 | current_status.value = new_status.value; | ||
| 520 | value_changed = true; | ||
| 532 | } | 521 | } |
| 533 | 522 | } else { | |
| 534 | if (!value_changed) { | 523 | // Toggle button and lock status |
| 535 | return; | 524 | if (new_status.value && !current_status.locked) { |
| 525 | current_status.locked = true; | ||
| 526 | current_status.value = !current_status.value; | ||
| 527 | value_changed = true; | ||
| 536 | } | 528 | } |
| 537 | 529 | ||
| 538 | if (is_configuring) { | 530 | // Unlock button ready for next press |
| 539 | controller.npad_button_state.raw = NpadButton::None; | 531 | if (!new_status.value && current_status.locked) { |
| 540 | controller.debug_pad_button_state.raw = 0; | 532 | current_status.locked = false; |
| 541 | TriggerOnChange(ControllerTriggerType::Button, false); | ||
| 542 | return; | ||
| 543 | } | 533 | } |
| 534 | } | ||
| 544 | 535 | ||
| 545 | switch (index) { | 536 | if (!value_changed) { |
| 546 | case Settings::NativeButton::A: | 537 | return; |
| 547 | controller.npad_button_state.a.Assign(current_status.value); | 538 | } |
| 548 | controller.debug_pad_button_state.a.Assign(current_status.value); | 539 | |
| 549 | break; | 540 | if (is_configuring) { |
| 550 | case Settings::NativeButton::B: | 541 | controller.npad_button_state.raw = NpadButton::None; |
| 551 | controller.npad_button_state.b.Assign(current_status.value); | 542 | controller.debug_pad_button_state.raw = 0; |
| 552 | controller.debug_pad_button_state.b.Assign(current_status.value); | 543 | lock.unlock(); |
| 553 | break; | 544 | TriggerOnChange(ControllerTriggerType::Button, false); |
| 554 | case Settings::NativeButton::X: | 545 | return; |
| 555 | controller.npad_button_state.x.Assign(current_status.value); | 546 | } |
| 556 | controller.debug_pad_button_state.x.Assign(current_status.value); | 547 | |
| 557 | break; | 548 | switch (index) { |
| 558 | case Settings::NativeButton::Y: | 549 | case Settings::NativeButton::A: |
| 559 | controller.npad_button_state.y.Assign(current_status.value); | 550 | controller.npad_button_state.a.Assign(current_status.value); |
| 560 | controller.debug_pad_button_state.y.Assign(current_status.value); | 551 | controller.debug_pad_button_state.a.Assign(current_status.value); |
| 561 | break; | 552 | break; |
| 562 | case Settings::NativeButton::LStick: | 553 | case Settings::NativeButton::B: |
| 563 | controller.npad_button_state.stick_l.Assign(current_status.value); | 554 | controller.npad_button_state.b.Assign(current_status.value); |
| 564 | break; | 555 | controller.debug_pad_button_state.b.Assign(current_status.value); |
| 565 | case Settings::NativeButton::RStick: | 556 | break; |
| 566 | controller.npad_button_state.stick_r.Assign(current_status.value); | 557 | case Settings::NativeButton::X: |
| 567 | break; | 558 | controller.npad_button_state.x.Assign(current_status.value); |
| 568 | case Settings::NativeButton::L: | 559 | controller.debug_pad_button_state.x.Assign(current_status.value); |
| 569 | controller.npad_button_state.l.Assign(current_status.value); | 560 | break; |
| 570 | controller.debug_pad_button_state.l.Assign(current_status.value); | 561 | case Settings::NativeButton::Y: |
| 571 | break; | 562 | controller.npad_button_state.y.Assign(current_status.value); |
| 572 | case Settings::NativeButton::R: | 563 | controller.debug_pad_button_state.y.Assign(current_status.value); |
| 573 | controller.npad_button_state.r.Assign(current_status.value); | 564 | break; |
| 574 | controller.debug_pad_button_state.r.Assign(current_status.value); | 565 | case Settings::NativeButton::LStick: |
| 575 | break; | 566 | controller.npad_button_state.stick_l.Assign(current_status.value); |
| 576 | case Settings::NativeButton::ZL: | 567 | break; |
| 577 | controller.npad_button_state.zl.Assign(current_status.value); | 568 | case Settings::NativeButton::RStick: |
| 578 | controller.debug_pad_button_state.zl.Assign(current_status.value); | 569 | controller.npad_button_state.stick_r.Assign(current_status.value); |
| 579 | break; | 570 | break; |
| 580 | case Settings::NativeButton::ZR: | 571 | case Settings::NativeButton::L: |
| 581 | controller.npad_button_state.zr.Assign(current_status.value); | 572 | controller.npad_button_state.l.Assign(current_status.value); |
| 582 | controller.debug_pad_button_state.zr.Assign(current_status.value); | 573 | controller.debug_pad_button_state.l.Assign(current_status.value); |
| 583 | break; | 574 | break; |
| 584 | case Settings::NativeButton::Plus: | 575 | case Settings::NativeButton::R: |
| 585 | controller.npad_button_state.plus.Assign(current_status.value); | 576 | controller.npad_button_state.r.Assign(current_status.value); |
| 586 | controller.debug_pad_button_state.plus.Assign(current_status.value); | 577 | controller.debug_pad_button_state.r.Assign(current_status.value); |
| 587 | break; | 578 | break; |
| 588 | case Settings::NativeButton::Minus: | 579 | case Settings::NativeButton::ZL: |
| 589 | controller.npad_button_state.minus.Assign(current_status.value); | 580 | controller.npad_button_state.zl.Assign(current_status.value); |
| 590 | controller.debug_pad_button_state.minus.Assign(current_status.value); | 581 | controller.debug_pad_button_state.zl.Assign(current_status.value); |
| 591 | break; | 582 | break; |
| 592 | case Settings::NativeButton::DLeft: | 583 | case Settings::NativeButton::ZR: |
| 593 | controller.npad_button_state.left.Assign(current_status.value); | 584 | controller.npad_button_state.zr.Assign(current_status.value); |
| 594 | controller.debug_pad_button_state.d_left.Assign(current_status.value); | 585 | controller.debug_pad_button_state.zr.Assign(current_status.value); |
| 595 | break; | 586 | break; |
| 596 | case Settings::NativeButton::DUp: | 587 | case Settings::NativeButton::Plus: |
| 597 | controller.npad_button_state.up.Assign(current_status.value); | 588 | controller.npad_button_state.plus.Assign(current_status.value); |
| 598 | controller.debug_pad_button_state.d_up.Assign(current_status.value); | 589 | controller.debug_pad_button_state.plus.Assign(current_status.value); |
| 599 | break; | 590 | break; |
| 600 | case Settings::NativeButton::DRight: | 591 | case Settings::NativeButton::Minus: |
| 601 | controller.npad_button_state.right.Assign(current_status.value); | 592 | controller.npad_button_state.minus.Assign(current_status.value); |
| 602 | controller.debug_pad_button_state.d_right.Assign(current_status.value); | 593 | controller.debug_pad_button_state.minus.Assign(current_status.value); |
| 603 | break; | 594 | break; |
| 604 | case Settings::NativeButton::DDown: | 595 | case Settings::NativeButton::DLeft: |
| 605 | controller.npad_button_state.down.Assign(current_status.value); | 596 | controller.npad_button_state.left.Assign(current_status.value); |
| 606 | controller.debug_pad_button_state.d_down.Assign(current_status.value); | 597 | controller.debug_pad_button_state.d_left.Assign(current_status.value); |
| 607 | break; | 598 | break; |
| 608 | case Settings::NativeButton::SL: | 599 | case Settings::NativeButton::DUp: |
| 609 | controller.npad_button_state.left_sl.Assign(current_status.value); | 600 | controller.npad_button_state.up.Assign(current_status.value); |
| 610 | controller.npad_button_state.right_sl.Assign(current_status.value); | 601 | controller.debug_pad_button_state.d_up.Assign(current_status.value); |
| 611 | break; | 602 | break; |
| 612 | case Settings::NativeButton::SR: | 603 | case Settings::NativeButton::DRight: |
| 613 | controller.npad_button_state.left_sr.Assign(current_status.value); | 604 | controller.npad_button_state.right.Assign(current_status.value); |
| 614 | controller.npad_button_state.right_sr.Assign(current_status.value); | 605 | controller.debug_pad_button_state.d_right.Assign(current_status.value); |
| 615 | break; | 606 | break; |
| 616 | case Settings::NativeButton::Home: | 607 | case Settings::NativeButton::DDown: |
| 617 | if (!system_buttons_enabled) { | 608 | controller.npad_button_state.down.Assign(current_status.value); |
| 618 | break; | 609 | controller.debug_pad_button_state.d_down.Assign(current_status.value); |
| 619 | } | 610 | break; |
| 620 | controller.home_button_state.home.Assign(current_status.value); | 611 | case Settings::NativeButton::SL: |
| 612 | controller.npad_button_state.left_sl.Assign(current_status.value); | ||
| 613 | controller.npad_button_state.right_sl.Assign(current_status.value); | ||
| 614 | break; | ||
| 615 | case Settings::NativeButton::SR: | ||
| 616 | controller.npad_button_state.left_sr.Assign(current_status.value); | ||
| 617 | controller.npad_button_state.right_sr.Assign(current_status.value); | ||
| 618 | break; | ||
| 619 | case Settings::NativeButton::Home: | ||
| 620 | if (!system_buttons_enabled) { | ||
| 621 | break; | 621 | break; |
| 622 | case Settings::NativeButton::Screenshot: | 622 | } |
| 623 | if (!system_buttons_enabled) { | 623 | controller.home_button_state.home.Assign(current_status.value); |
| 624 | break; | 624 | break; |
| 625 | } | 625 | case Settings::NativeButton::Screenshot: |
| 626 | controller.capture_button_state.capture.Assign(current_status.value); | 626 | if (!system_buttons_enabled) { |
| 627 | break; | 627 | break; |
| 628 | } | 628 | } |
| 629 | controller.capture_button_state.capture.Assign(current_status.value); | ||
| 630 | break; | ||
| 629 | } | 631 | } |
| 632 | |||
| 633 | lock.unlock(); | ||
| 634 | |||
| 630 | if (!is_connected) { | 635 | if (!is_connected) { |
| 631 | if (npad_id_type == NpadIdType::Player1 && npad_type != NpadStyleIndex::Handheld) { | 636 | if (npad_id_type == NpadIdType::Player1 && npad_type != NpadStyleIndex::Handheld) { |
| 632 | Connect(); | 637 | Connect(); |
| @@ -643,7 +648,7 @@ void EmulatedController::SetStick(const Common::Input::CallbackStatus& callback, | |||
| 643 | if (index >= controller.stick_values.size()) { | 648 | if (index >= controller.stick_values.size()) { |
| 644 | return; | 649 | return; |
| 645 | } | 650 | } |
| 646 | std::lock_guard lock{mutex}; | 651 | std::unique_lock lock{mutex}; |
| 647 | const auto stick_value = TransformToStick(callback); | 652 | const auto stick_value = TransformToStick(callback); |
| 648 | 653 | ||
| 649 | // Only read stick values that have the same uuid or are over the threshold to avoid flapping | 654 | // Only read stick values that have the same uuid or are over the threshold to avoid flapping |
| @@ -659,6 +664,7 @@ void EmulatedController::SetStick(const Common::Input::CallbackStatus& callback, | |||
| 659 | if (is_configuring) { | 664 | if (is_configuring) { |
| 660 | controller.analog_stick_state.left = {}; | 665 | controller.analog_stick_state.left = {}; |
| 661 | controller.analog_stick_state.right = {}; | 666 | controller.analog_stick_state.right = {}; |
| 667 | lock.unlock(); | ||
| 662 | TriggerOnChange(ControllerTriggerType::Stick, false); | 668 | TriggerOnChange(ControllerTriggerType::Stick, false); |
| 663 | return; | 669 | return; |
| 664 | } | 670 | } |
| @@ -685,6 +691,7 @@ void EmulatedController::SetStick(const Common::Input::CallbackStatus& callback, | |||
| 685 | break; | 691 | break; |
| 686 | } | 692 | } |
| 687 | 693 | ||
| 694 | lock.unlock(); | ||
| 688 | TriggerOnChange(ControllerTriggerType::Stick, true); | 695 | TriggerOnChange(ControllerTriggerType::Stick, true); |
| 689 | } | 696 | } |
| 690 | 697 | ||
| @@ -693,7 +700,7 @@ void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callbac | |||
| 693 | if (index >= controller.trigger_values.size()) { | 700 | if (index >= controller.trigger_values.size()) { |
| 694 | return; | 701 | return; |
| 695 | } | 702 | } |
| 696 | std::lock_guard lock{mutex}; | 703 | std::unique_lock lock{mutex}; |
| 697 | const auto trigger_value = TransformToTrigger(callback); | 704 | const auto trigger_value = TransformToTrigger(callback); |
| 698 | 705 | ||
| 699 | // Only read trigger values that have the same uuid or are pressed once | 706 | // Only read trigger values that have the same uuid or are pressed once |
| @@ -709,6 +716,7 @@ void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callbac | |||
| 709 | if (is_configuring) { | 716 | if (is_configuring) { |
| 710 | controller.gc_trigger_state.left = 0; | 717 | controller.gc_trigger_state.left = 0; |
| 711 | controller.gc_trigger_state.right = 0; | 718 | controller.gc_trigger_state.right = 0; |
| 719 | lock.unlock(); | ||
| 712 | TriggerOnChange(ControllerTriggerType::Trigger, false); | 720 | TriggerOnChange(ControllerTriggerType::Trigger, false); |
| 713 | return; | 721 | return; |
| 714 | } | 722 | } |
| @@ -727,6 +735,7 @@ void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callbac | |||
| 727 | break; | 735 | break; |
| 728 | } | 736 | } |
| 729 | 737 | ||
| 738 | lock.unlock(); | ||
| 730 | TriggerOnChange(ControllerTriggerType::Trigger, true); | 739 | TriggerOnChange(ControllerTriggerType::Trigger, true); |
| 731 | } | 740 | } |
| 732 | 741 | ||
| @@ -735,7 +744,7 @@ void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback | |||
| 735 | if (index >= controller.motion_values.size()) { | 744 | if (index >= controller.motion_values.size()) { |
| 736 | return; | 745 | return; |
| 737 | } | 746 | } |
| 738 | std::lock_guard lock{mutex}; | 747 | std::unique_lock lock{mutex}; |
| 739 | auto& raw_status = controller.motion_values[index].raw_status; | 748 | auto& raw_status = controller.motion_values[index].raw_status; |
| 740 | auto& emulated = controller.motion_values[index].emulated; | 749 | auto& emulated = controller.motion_values[index].emulated; |
| 741 | 750 | ||
| @@ -756,6 +765,7 @@ void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback | |||
| 756 | force_update_motion = raw_status.force_update; | 765 | force_update_motion = raw_status.force_update; |
| 757 | 766 | ||
| 758 | if (is_configuring) { | 767 | if (is_configuring) { |
| 768 | lock.unlock(); | ||
| 759 | TriggerOnChange(ControllerTriggerType::Motion, false); | 769 | TriggerOnChange(ControllerTriggerType::Motion, false); |
| 760 | return; | 770 | return; |
| 761 | } | 771 | } |
| @@ -767,6 +777,7 @@ void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback | |||
| 767 | motion.orientation = emulated.GetOrientation(); | 777 | motion.orientation = emulated.GetOrientation(); |
| 768 | motion.is_at_rest = !emulated.IsMoving(motion_sensitivity); | 778 | motion.is_at_rest = !emulated.IsMoving(motion_sensitivity); |
| 769 | 779 | ||
| 780 | lock.unlock(); | ||
| 770 | TriggerOnChange(ControllerTriggerType::Motion, true); | 781 | TriggerOnChange(ControllerTriggerType::Motion, true); |
| 771 | } | 782 | } |
| 772 | 783 | ||
| @@ -775,10 +786,11 @@ void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callbac | |||
| 775 | if (index >= controller.battery_values.size()) { | 786 | if (index >= controller.battery_values.size()) { |
| 776 | return; | 787 | return; |
| 777 | } | 788 | } |
| 778 | std::lock_guard lock{mutex}; | 789 | std::unique_lock lock{mutex}; |
| 779 | controller.battery_values[index] = TransformToBattery(callback); | 790 | controller.battery_values[index] = TransformToBattery(callback); |
| 780 | 791 | ||
| 781 | if (is_configuring) { | 792 | if (is_configuring) { |
| 793 | lock.unlock(); | ||
| 782 | TriggerOnChange(ControllerTriggerType::Battery, false); | 794 | TriggerOnChange(ControllerTriggerType::Battery, false); |
| 783 | return; | 795 | return; |
| 784 | } | 796 | } |
| @@ -835,6 +847,8 @@ void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callbac | |||
| 835 | }; | 847 | }; |
| 836 | break; | 848 | break; |
| 837 | } | 849 | } |
| 850 | |||
| 851 | lock.unlock(); | ||
| 838 | TriggerOnChange(ControllerTriggerType::Battery, true); | 852 | TriggerOnChange(ControllerTriggerType::Battery, true); |
| 839 | } | 853 | } |
| 840 | 854 | ||
| @@ -932,6 +946,7 @@ void EmulatedController::SetSupportedNpadStyleTag(NpadStyleTag supported_styles) | |||
| 932 | } | 946 | } |
| 933 | 947 | ||
| 934 | bool EmulatedController::IsControllerFullkey(bool use_temporary_value) const { | 948 | bool EmulatedController::IsControllerFullkey(bool use_temporary_value) const { |
| 949 | std::scoped_lock lock{mutex}; | ||
| 935 | const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type; | 950 | const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type; |
| 936 | switch (type) { | 951 | switch (type) { |
| 937 | case NpadStyleIndex::ProController: | 952 | case NpadStyleIndex::ProController: |
| @@ -947,6 +962,7 @@ bool EmulatedController::IsControllerFullkey(bool use_temporary_value) const { | |||
| 947 | } | 962 | } |
| 948 | 963 | ||
| 949 | bool EmulatedController::IsControllerSupported(bool use_temporary_value) const { | 964 | bool EmulatedController::IsControllerSupported(bool use_temporary_value) const { |
| 965 | std::scoped_lock lock{mutex}; | ||
| 950 | const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type; | 966 | const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type; |
| 951 | switch (type) { | 967 | switch (type) { |
| 952 | case NpadStyleIndex::ProController: | 968 | case NpadStyleIndex::ProController: |
| @@ -982,40 +998,44 @@ void EmulatedController::Connect(bool use_temporary_value) { | |||
| 982 | LOG_ERROR(Service_HID, "Controller type {} is not supported", type); | 998 | LOG_ERROR(Service_HID, "Controller type {} is not supported", type); |
| 983 | return; | 999 | return; |
| 984 | } | 1000 | } |
| 985 | { | ||
| 986 | std::lock_guard lock{mutex}; | ||
| 987 | if (is_configuring) { | ||
| 988 | tmp_is_connected = true; | ||
| 989 | TriggerOnChange(ControllerTriggerType::Connected, false); | ||
| 990 | return; | ||
| 991 | } | ||
| 992 | 1001 | ||
| 993 | if (is_connected) { | 1002 | std::unique_lock lock{mutex}; |
| 994 | return; | 1003 | if (is_configuring) { |
| 995 | } | 1004 | tmp_is_connected = true; |
| 996 | is_connected = true; | 1005 | lock.unlock(); |
| 1006 | TriggerOnChange(ControllerTriggerType::Connected, false); | ||
| 1007 | return; | ||
| 1008 | } | ||
| 1009 | |||
| 1010 | if (is_connected) { | ||
| 1011 | return; | ||
| 997 | } | 1012 | } |
| 1013 | is_connected = true; | ||
| 1014 | |||
| 1015 | lock.unlock(); | ||
| 998 | TriggerOnChange(ControllerTriggerType::Connected, true); | 1016 | TriggerOnChange(ControllerTriggerType::Connected, true); |
| 999 | } | 1017 | } |
| 1000 | 1018 | ||
| 1001 | void EmulatedController::Disconnect() { | 1019 | void EmulatedController::Disconnect() { |
| 1002 | { | 1020 | std::unique_lock lock{mutex}; |
| 1003 | std::lock_guard lock{mutex}; | 1021 | if (is_configuring) { |
| 1004 | if (is_configuring) { | 1022 | tmp_is_connected = false; |
| 1005 | tmp_is_connected = false; | 1023 | lock.unlock(); |
| 1006 | TriggerOnChange(ControllerTriggerType::Disconnected, false); | 1024 | TriggerOnChange(ControllerTriggerType::Disconnected, false); |
| 1007 | return; | 1025 | return; |
| 1008 | } | 1026 | } |
| 1009 | 1027 | ||
| 1010 | if (!is_connected) { | 1028 | if (!is_connected) { |
| 1011 | return; | 1029 | return; |
| 1012 | } | ||
| 1013 | is_connected = false; | ||
| 1014 | } | 1030 | } |
| 1031 | is_connected = false; | ||
| 1032 | |||
| 1033 | lock.unlock(); | ||
| 1015 | TriggerOnChange(ControllerTriggerType::Disconnected, true); | 1034 | TriggerOnChange(ControllerTriggerType::Disconnected, true); |
| 1016 | } | 1035 | } |
| 1017 | 1036 | ||
| 1018 | bool EmulatedController::IsConnected(bool get_temporary_value) const { | 1037 | bool EmulatedController::IsConnected(bool get_temporary_value) const { |
| 1038 | std::scoped_lock lock{mutex}; | ||
| 1019 | if (get_temporary_value && is_configuring) { | 1039 | if (get_temporary_value && is_configuring) { |
| 1020 | return tmp_is_connected; | 1040 | return tmp_is_connected; |
| 1021 | } | 1041 | } |
| @@ -1029,10 +1049,12 @@ bool EmulatedController::IsVibrationEnabled() const { | |||
| 1029 | } | 1049 | } |
| 1030 | 1050 | ||
| 1031 | NpadIdType EmulatedController::GetNpadIdType() const { | 1051 | NpadIdType EmulatedController::GetNpadIdType() const { |
| 1052 | std::scoped_lock lock{mutex}; | ||
| 1032 | return npad_id_type; | 1053 | return npad_id_type; |
| 1033 | } | 1054 | } |
| 1034 | 1055 | ||
| 1035 | NpadStyleIndex EmulatedController::GetNpadStyleIndex(bool get_temporary_value) const { | 1056 | NpadStyleIndex EmulatedController::GetNpadStyleIndex(bool get_temporary_value) const { |
| 1057 | std::scoped_lock lock{mutex}; | ||
| 1036 | if (get_temporary_value && is_configuring) { | 1058 | if (get_temporary_value && is_configuring) { |
| 1037 | return tmp_npad_type; | 1059 | return tmp_npad_type; |
| 1038 | } | 1060 | } |
| @@ -1040,27 +1062,28 @@ NpadStyleIndex EmulatedController::GetNpadStyleIndex(bool get_temporary_value) c | |||
| 1040 | } | 1062 | } |
| 1041 | 1063 | ||
| 1042 | void EmulatedController::SetNpadStyleIndex(NpadStyleIndex npad_type_) { | 1064 | void EmulatedController::SetNpadStyleIndex(NpadStyleIndex npad_type_) { |
| 1043 | { | 1065 | std::unique_lock lock{mutex}; |
| 1044 | std::lock_guard lock{mutex}; | ||
| 1045 | 1066 | ||
| 1046 | if (is_configuring) { | 1067 | if (is_configuring) { |
| 1047 | if (tmp_npad_type == npad_type_) { | 1068 | if (tmp_npad_type == npad_type_) { |
| 1048 | return; | ||
| 1049 | } | ||
| 1050 | tmp_npad_type = npad_type_; | ||
| 1051 | TriggerOnChange(ControllerTriggerType::Type, false); | ||
| 1052 | return; | 1069 | return; |
| 1053 | } | 1070 | } |
| 1071 | tmp_npad_type = npad_type_; | ||
| 1072 | lock.unlock(); | ||
| 1073 | TriggerOnChange(ControllerTriggerType::Type, false); | ||
| 1074 | return; | ||
| 1075 | } | ||
| 1054 | 1076 | ||
| 1055 | if (npad_type == npad_type_) { | 1077 | if (npad_type == npad_type_) { |
| 1056 | return; | 1078 | return; |
| 1057 | } | 1079 | } |
| 1058 | if (is_connected) { | 1080 | if (is_connected) { |
| 1059 | LOG_WARNING(Service_HID, "Controller {} type changed while it's connected", | 1081 | LOG_WARNING(Service_HID, "Controller {} type changed while it's connected", |
| 1060 | NpadIdTypeToIndex(npad_id_type)); | 1082 | NpadIdTypeToIndex(npad_id_type)); |
| 1061 | } | ||
| 1062 | npad_type = npad_type_; | ||
| 1063 | } | 1083 | } |
| 1084 | npad_type = npad_type_; | ||
| 1085 | |||
| 1086 | lock.unlock(); | ||
| 1064 | TriggerOnChange(ControllerTriggerType::Type, true); | 1087 | TriggerOnChange(ControllerTriggerType::Type, true); |
| 1065 | } | 1088 | } |
| 1066 | 1089 | ||
| @@ -1088,30 +1111,37 @@ LedPattern EmulatedController::GetLedPattern() const { | |||
| 1088 | } | 1111 | } |
| 1089 | 1112 | ||
| 1090 | ButtonValues EmulatedController::GetButtonsValues() const { | 1113 | ButtonValues EmulatedController::GetButtonsValues() const { |
| 1114 | std::scoped_lock lock{mutex}; | ||
| 1091 | return controller.button_values; | 1115 | return controller.button_values; |
| 1092 | } | 1116 | } |
| 1093 | 1117 | ||
| 1094 | SticksValues EmulatedController::GetSticksValues() const { | 1118 | SticksValues EmulatedController::GetSticksValues() const { |
| 1119 | std::scoped_lock lock{mutex}; | ||
| 1095 | return controller.stick_values; | 1120 | return controller.stick_values; |
| 1096 | } | 1121 | } |
| 1097 | 1122 | ||
| 1098 | TriggerValues EmulatedController::GetTriggersValues() const { | 1123 | TriggerValues EmulatedController::GetTriggersValues() const { |
| 1124 | std::scoped_lock lock{mutex}; | ||
| 1099 | return controller.trigger_values; | 1125 | return controller.trigger_values; |
| 1100 | } | 1126 | } |
| 1101 | 1127 | ||
| 1102 | ControllerMotionValues EmulatedController::GetMotionValues() const { | 1128 | ControllerMotionValues EmulatedController::GetMotionValues() const { |
| 1129 | std::scoped_lock lock{mutex}; | ||
| 1103 | return controller.motion_values; | 1130 | return controller.motion_values; |
| 1104 | } | 1131 | } |
| 1105 | 1132 | ||
| 1106 | ColorValues EmulatedController::GetColorsValues() const { | 1133 | ColorValues EmulatedController::GetColorsValues() const { |
| 1134 | std::scoped_lock lock{mutex}; | ||
| 1107 | return controller.color_values; | 1135 | return controller.color_values; |
| 1108 | } | 1136 | } |
| 1109 | 1137 | ||
| 1110 | BatteryValues EmulatedController::GetBatteryValues() const { | 1138 | BatteryValues EmulatedController::GetBatteryValues() const { |
| 1139 | std::scoped_lock lock{mutex}; | ||
| 1111 | return controller.battery_values; | 1140 | return controller.battery_values; |
| 1112 | } | 1141 | } |
| 1113 | 1142 | ||
| 1114 | HomeButtonState EmulatedController::GetHomeButtons() const { | 1143 | HomeButtonState EmulatedController::GetHomeButtons() const { |
| 1144 | std::scoped_lock lock{mutex}; | ||
| 1115 | if (is_configuring) { | 1145 | if (is_configuring) { |
| 1116 | return {}; | 1146 | return {}; |
| 1117 | } | 1147 | } |
| @@ -1119,6 +1149,7 @@ HomeButtonState EmulatedController::GetHomeButtons() const { | |||
| 1119 | } | 1149 | } |
| 1120 | 1150 | ||
| 1121 | CaptureButtonState EmulatedController::GetCaptureButtons() const { | 1151 | CaptureButtonState EmulatedController::GetCaptureButtons() const { |
| 1152 | std::scoped_lock lock{mutex}; | ||
| 1122 | if (is_configuring) { | 1153 | if (is_configuring) { |
| 1123 | return {}; | 1154 | return {}; |
| 1124 | } | 1155 | } |
| @@ -1126,6 +1157,7 @@ CaptureButtonState EmulatedController::GetCaptureButtons() const { | |||
| 1126 | } | 1157 | } |
| 1127 | 1158 | ||
| 1128 | NpadButtonState EmulatedController::GetNpadButtons() const { | 1159 | NpadButtonState EmulatedController::GetNpadButtons() const { |
| 1160 | std::scoped_lock lock{mutex}; | ||
| 1129 | if (is_configuring) { | 1161 | if (is_configuring) { |
| 1130 | return {}; | 1162 | return {}; |
| 1131 | } | 1163 | } |
| @@ -1133,6 +1165,7 @@ NpadButtonState EmulatedController::GetNpadButtons() const { | |||
| 1133 | } | 1165 | } |
| 1134 | 1166 | ||
| 1135 | DebugPadButton EmulatedController::GetDebugPadButtons() const { | 1167 | DebugPadButton EmulatedController::GetDebugPadButtons() const { |
| 1168 | std::scoped_lock lock{mutex}; | ||
| 1136 | if (is_configuring) { | 1169 | if (is_configuring) { |
| 1137 | return {}; | 1170 | return {}; |
| 1138 | } | 1171 | } |
| @@ -1140,20 +1173,27 @@ DebugPadButton EmulatedController::GetDebugPadButtons() const { | |||
| 1140 | } | 1173 | } |
| 1141 | 1174 | ||
| 1142 | AnalogSticks EmulatedController::GetSticks() const { | 1175 | AnalogSticks EmulatedController::GetSticks() const { |
| 1176 | std::unique_lock lock{mutex}; | ||
| 1177 | |||
| 1143 | if (is_configuring) { | 1178 | if (is_configuring) { |
| 1144 | return {}; | 1179 | return {}; |
| 1145 | } | 1180 | } |
| 1181 | |||
| 1146 | // Some drivers like stick from buttons need constant refreshing | 1182 | // Some drivers like stick from buttons need constant refreshing |
| 1147 | for (auto& device : stick_devices) { | 1183 | for (auto& device : stick_devices) { |
| 1148 | if (!device) { | 1184 | if (!device) { |
| 1149 | continue; | 1185 | continue; |
| 1150 | } | 1186 | } |
| 1187 | lock.unlock(); | ||
| 1151 | device->SoftUpdate(); | 1188 | device->SoftUpdate(); |
| 1189 | lock.lock(); | ||
| 1152 | } | 1190 | } |
| 1191 | |||
| 1153 | return controller.analog_stick_state; | 1192 | return controller.analog_stick_state; |
| 1154 | } | 1193 | } |
| 1155 | 1194 | ||
| 1156 | NpadGcTriggerState EmulatedController::GetTriggers() const { | 1195 | NpadGcTriggerState EmulatedController::GetTriggers() const { |
| 1196 | std::scoped_lock lock{mutex}; | ||
| 1157 | if (is_configuring) { | 1197 | if (is_configuring) { |
| 1158 | return {}; | 1198 | return {}; |
| 1159 | } | 1199 | } |
| @@ -1161,26 +1201,35 @@ NpadGcTriggerState EmulatedController::GetTriggers() const { | |||
| 1161 | } | 1201 | } |
| 1162 | 1202 | ||
| 1163 | MotionState EmulatedController::GetMotions() const { | 1203 | MotionState EmulatedController::GetMotions() const { |
| 1204 | std::unique_lock lock{mutex}; | ||
| 1205 | |||
| 1206 | // Some drivers like mouse motion need constant refreshing | ||
| 1164 | if (force_update_motion) { | 1207 | if (force_update_motion) { |
| 1165 | for (auto& device : motion_devices) { | 1208 | for (auto& device : motion_devices) { |
| 1166 | if (!device) { | 1209 | if (!device) { |
| 1167 | continue; | 1210 | continue; |
| 1168 | } | 1211 | } |
| 1212 | lock.unlock(); | ||
| 1169 | device->ForceUpdate(); | 1213 | device->ForceUpdate(); |
| 1214 | lock.lock(); | ||
| 1170 | } | 1215 | } |
| 1171 | } | 1216 | } |
| 1217 | |||
| 1172 | return controller.motion_state; | 1218 | return controller.motion_state; |
| 1173 | } | 1219 | } |
| 1174 | 1220 | ||
| 1175 | ControllerColors EmulatedController::GetColors() const { | 1221 | ControllerColors EmulatedController::GetColors() const { |
| 1222 | std::scoped_lock lock{mutex}; | ||
| 1176 | return controller.colors_state; | 1223 | return controller.colors_state; |
| 1177 | } | 1224 | } |
| 1178 | 1225 | ||
| 1179 | BatteryLevelState EmulatedController::GetBattery() const { | 1226 | BatteryLevelState EmulatedController::GetBattery() const { |
| 1227 | std::scoped_lock lock{mutex}; | ||
| 1180 | return controller.battery_state; | 1228 | return controller.battery_state; |
| 1181 | } | 1229 | } |
| 1182 | 1230 | ||
| 1183 | void EmulatedController::TriggerOnChange(ControllerTriggerType type, bool is_npad_service_update) { | 1231 | void EmulatedController::TriggerOnChange(ControllerTriggerType type, bool is_npad_service_update) { |
| 1232 | std::scoped_lock lock{callback_mutex}; | ||
| 1184 | for (const auto& poller_pair : callback_list) { | 1233 | for (const auto& poller_pair : callback_list) { |
| 1185 | const ControllerUpdateCallback& poller = poller_pair.second; | 1234 | const ControllerUpdateCallback& poller = poller_pair.second; |
| 1186 | if (!is_npad_service_update && poller.is_npad_service) { | 1235 | if (!is_npad_service_update && poller.is_npad_service) { |
| @@ -1193,13 +1242,13 @@ void EmulatedController::TriggerOnChange(ControllerTriggerType type, bool is_npa | |||
| 1193 | } | 1242 | } |
| 1194 | 1243 | ||
| 1195 | int EmulatedController::SetCallback(ControllerUpdateCallback update_callback) { | 1244 | int EmulatedController::SetCallback(ControllerUpdateCallback update_callback) { |
| 1196 | std::lock_guard lock{mutex}; | 1245 | std::scoped_lock lock{callback_mutex}; |
| 1197 | callback_list.insert_or_assign(last_callback_key, std::move(update_callback)); | 1246 | callback_list.insert_or_assign(last_callback_key, std::move(update_callback)); |
| 1198 | return last_callback_key++; | 1247 | return last_callback_key++; |
| 1199 | } | 1248 | } |
| 1200 | 1249 | ||
| 1201 | void EmulatedController::DeleteCallback(int key) { | 1250 | void EmulatedController::DeleteCallback(int key) { |
| 1202 | std::lock_guard lock{mutex}; | 1251 | std::scoped_lock lock{callback_mutex}; |
| 1203 | const auto& iterator = callback_list.find(key); | 1252 | const auto& iterator = callback_list.find(key); |
| 1204 | if (iterator == callback_list.end()) { | 1253 | if (iterator == callback_list.end()) { |
| 1205 | LOG_ERROR(Input, "Tried to delete non-existent callback {}", key); | 1254 | LOG_ERROR(Input, "Tried to delete non-existent callback {}", key); |
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index aa52f9572..1e224685d 100644 --- a/src/core/hid/emulated_controller.h +++ b/src/core/hid/emulated_controller.h | |||
| @@ -400,7 +400,7 @@ private: | |||
| 400 | */ | 400 | */ |
| 401 | void TriggerOnChange(ControllerTriggerType type, bool is_service_update); | 401 | void TriggerOnChange(ControllerTriggerType type, bool is_service_update); |
| 402 | 402 | ||
| 403 | NpadIdType npad_id_type; | 403 | const NpadIdType npad_id_type; |
| 404 | NpadStyleIndex npad_type{NpadStyleIndex::None}; | 404 | NpadStyleIndex npad_type{NpadStyleIndex::None}; |
| 405 | NpadStyleTag supported_style_tag{NpadStyleSet::All}; | 405 | NpadStyleTag supported_style_tag{NpadStyleSet::All}; |
| 406 | bool is_connected{false}; | 406 | bool is_connected{false}; |
| @@ -434,6 +434,7 @@ private: | |||
| 434 | StickDevices tas_stick_devices; | 434 | StickDevices tas_stick_devices; |
| 435 | 435 | ||
| 436 | mutable std::mutex mutex; | 436 | mutable std::mutex mutex; |
| 437 | mutable std::mutex callback_mutex; | ||
| 437 | std::unordered_map<int, ControllerUpdateCallback> callback_list; | 438 | std::unordered_map<int, ControllerUpdateCallback> callback_list; |
| 438 | int last_callback_key = 0; | 439 | int last_callback_key = 0; |
| 439 | 440 | ||
diff --git a/src/core/hid/emulated_devices.cpp b/src/core/hid/emulated_devices.cpp index 708480f2d..cc0dcd931 100644 --- a/src/core/hid/emulated_devices.cpp +++ b/src/core/hid/emulated_devices.cpp | |||
| @@ -169,7 +169,7 @@ void EmulatedDevices::SetKeyboardButton(const Common::Input::CallbackStatus& cal | |||
| 169 | if (index >= device_status.keyboard_values.size()) { | 169 | if (index >= device_status.keyboard_values.size()) { |
| 170 | return; | 170 | return; |
| 171 | } | 171 | } |
| 172 | std::lock_guard lock{mutex}; | 172 | std::unique_lock lock{mutex}; |
| 173 | bool value_changed = false; | 173 | bool value_changed = false; |
| 174 | const auto new_status = TransformToButton(callback); | 174 | const auto new_status = TransformToButton(callback); |
| 175 | auto& current_status = device_status.keyboard_values[index]; | 175 | auto& current_status = device_status.keyboard_values[index]; |
| @@ -201,6 +201,7 @@ void EmulatedDevices::SetKeyboardButton(const Common::Input::CallbackStatus& cal | |||
| 201 | } | 201 | } |
| 202 | 202 | ||
| 203 | if (is_configuring) { | 203 | if (is_configuring) { |
| 204 | lock.unlock(); | ||
| 204 | TriggerOnChange(DeviceTriggerType::Keyboard); | 205 | TriggerOnChange(DeviceTriggerType::Keyboard); |
| 205 | return; | 206 | return; |
| 206 | } | 207 | } |
| @@ -208,6 +209,7 @@ void EmulatedDevices::SetKeyboardButton(const Common::Input::CallbackStatus& cal | |||
| 208 | // Index should be converted from NativeKeyboard to KeyboardKeyIndex | 209 | // Index should be converted from NativeKeyboard to KeyboardKeyIndex |
| 209 | UpdateKey(index, current_status.value); | 210 | UpdateKey(index, current_status.value); |
| 210 | 211 | ||
| 212 | lock.unlock(); | ||
| 211 | TriggerOnChange(DeviceTriggerType::Keyboard); | 213 | TriggerOnChange(DeviceTriggerType::Keyboard); |
| 212 | } | 214 | } |
| 213 | 215 | ||
| @@ -227,7 +229,7 @@ void EmulatedDevices::SetKeyboardModifier(const Common::Input::CallbackStatus& c | |||
| 227 | if (index >= device_status.keyboard_moddifier_values.size()) { | 229 | if (index >= device_status.keyboard_moddifier_values.size()) { |
| 228 | return; | 230 | return; |
| 229 | } | 231 | } |
| 230 | std::lock_guard lock{mutex}; | 232 | std::unique_lock lock{mutex}; |
| 231 | bool value_changed = false; | 233 | bool value_changed = false; |
| 232 | const auto new_status = TransformToButton(callback); | 234 | const auto new_status = TransformToButton(callback); |
| 233 | auto& current_status = device_status.keyboard_moddifier_values[index]; | 235 | auto& current_status = device_status.keyboard_moddifier_values[index]; |
| @@ -259,6 +261,7 @@ void EmulatedDevices::SetKeyboardModifier(const Common::Input::CallbackStatus& c | |||
| 259 | } | 261 | } |
| 260 | 262 | ||
| 261 | if (is_configuring) { | 263 | if (is_configuring) { |
| 264 | lock.unlock(); | ||
| 262 | TriggerOnChange(DeviceTriggerType::KeyboardModdifier); | 265 | TriggerOnChange(DeviceTriggerType::KeyboardModdifier); |
| 263 | return; | 266 | return; |
| 264 | } | 267 | } |
| @@ -289,6 +292,7 @@ void EmulatedDevices::SetKeyboardModifier(const Common::Input::CallbackStatus& c | |||
| 289 | break; | 292 | break; |
| 290 | } | 293 | } |
| 291 | 294 | ||
| 295 | lock.unlock(); | ||
| 292 | TriggerOnChange(DeviceTriggerType::KeyboardModdifier); | 296 | TriggerOnChange(DeviceTriggerType::KeyboardModdifier); |
| 293 | } | 297 | } |
| 294 | 298 | ||
| @@ -297,7 +301,7 @@ void EmulatedDevices::SetMouseButton(const Common::Input::CallbackStatus& callba | |||
| 297 | if (index >= device_status.mouse_button_values.size()) { | 301 | if (index >= device_status.mouse_button_values.size()) { |
| 298 | return; | 302 | return; |
| 299 | } | 303 | } |
| 300 | std::lock_guard lock{mutex}; | 304 | std::unique_lock lock{mutex}; |
| 301 | bool value_changed = false; | 305 | bool value_changed = false; |
| 302 | const auto new_status = TransformToButton(callback); | 306 | const auto new_status = TransformToButton(callback); |
| 303 | auto& current_status = device_status.mouse_button_values[index]; | 307 | auto& current_status = device_status.mouse_button_values[index]; |
| @@ -329,6 +333,7 @@ void EmulatedDevices::SetMouseButton(const Common::Input::CallbackStatus& callba | |||
| 329 | } | 333 | } |
| 330 | 334 | ||
| 331 | if (is_configuring) { | 335 | if (is_configuring) { |
| 336 | lock.unlock(); | ||
| 332 | TriggerOnChange(DeviceTriggerType::Mouse); | 337 | TriggerOnChange(DeviceTriggerType::Mouse); |
| 333 | return; | 338 | return; |
| 334 | } | 339 | } |
| @@ -351,6 +356,7 @@ void EmulatedDevices::SetMouseButton(const Common::Input::CallbackStatus& callba | |||
| 351 | break; | 356 | break; |
| 352 | } | 357 | } |
| 353 | 358 | ||
| 359 | lock.unlock(); | ||
| 354 | TriggerOnChange(DeviceTriggerType::Mouse); | 360 | TriggerOnChange(DeviceTriggerType::Mouse); |
| 355 | } | 361 | } |
| 356 | 362 | ||
| @@ -359,13 +365,14 @@ void EmulatedDevices::SetMouseAnalog(const Common::Input::CallbackStatus& callba | |||
| 359 | if (index >= device_status.mouse_analog_values.size()) { | 365 | if (index >= device_status.mouse_analog_values.size()) { |
| 360 | return; | 366 | return; |
| 361 | } | 367 | } |
| 362 | std::lock_guard lock{mutex}; | 368 | std::unique_lock lock{mutex}; |
| 363 | const auto analog_value = TransformToAnalog(callback); | 369 | const auto analog_value = TransformToAnalog(callback); |
| 364 | 370 | ||
| 365 | device_status.mouse_analog_values[index] = analog_value; | 371 | device_status.mouse_analog_values[index] = analog_value; |
| 366 | 372 | ||
| 367 | if (is_configuring) { | 373 | if (is_configuring) { |
| 368 | device_status.mouse_position_state = {}; | 374 | device_status.mouse_position_state = {}; |
| 375 | lock.unlock(); | ||
| 369 | TriggerOnChange(DeviceTriggerType::Mouse); | 376 | TriggerOnChange(DeviceTriggerType::Mouse); |
| 370 | return; | 377 | return; |
| 371 | } | 378 | } |
| @@ -379,17 +386,19 @@ void EmulatedDevices::SetMouseAnalog(const Common::Input::CallbackStatus& callba | |||
| 379 | break; | 386 | break; |
| 380 | } | 387 | } |
| 381 | 388 | ||
| 389 | lock.unlock(); | ||
| 382 | TriggerOnChange(DeviceTriggerType::Mouse); | 390 | TriggerOnChange(DeviceTriggerType::Mouse); |
| 383 | } | 391 | } |
| 384 | 392 | ||
| 385 | void EmulatedDevices::SetMouseStick(const Common::Input::CallbackStatus& callback) { | 393 | void EmulatedDevices::SetMouseStick(const Common::Input::CallbackStatus& callback) { |
| 386 | std::lock_guard lock{mutex}; | 394 | std::unique_lock lock{mutex}; |
| 387 | const auto touch_value = TransformToTouch(callback); | 395 | const auto touch_value = TransformToTouch(callback); |
| 388 | 396 | ||
| 389 | device_status.mouse_stick_value = touch_value; | 397 | device_status.mouse_stick_value = touch_value; |
| 390 | 398 | ||
| 391 | if (is_configuring) { | 399 | if (is_configuring) { |
| 392 | device_status.mouse_position_state = {}; | 400 | device_status.mouse_position_state = {}; |
| 401 | lock.unlock(); | ||
| 393 | TriggerOnChange(DeviceTriggerType::Mouse); | 402 | TriggerOnChange(DeviceTriggerType::Mouse); |
| 394 | return; | 403 | return; |
| 395 | } | 404 | } |
| @@ -397,42 +406,52 @@ void EmulatedDevices::SetMouseStick(const Common::Input::CallbackStatus& callbac | |||
| 397 | device_status.mouse_position_state.x = touch_value.x.value; | 406 | device_status.mouse_position_state.x = touch_value.x.value; |
| 398 | device_status.mouse_position_state.y = touch_value.y.value; | 407 | device_status.mouse_position_state.y = touch_value.y.value; |
| 399 | 408 | ||
| 409 | lock.unlock(); | ||
| 400 | TriggerOnChange(DeviceTriggerType::Mouse); | 410 | TriggerOnChange(DeviceTriggerType::Mouse); |
| 401 | } | 411 | } |
| 402 | 412 | ||
| 403 | KeyboardValues EmulatedDevices::GetKeyboardValues() const { | 413 | KeyboardValues EmulatedDevices::GetKeyboardValues() const { |
| 414 | std::scoped_lock lock{mutex}; | ||
| 404 | return device_status.keyboard_values; | 415 | return device_status.keyboard_values; |
| 405 | } | 416 | } |
| 406 | 417 | ||
| 407 | KeyboardModifierValues EmulatedDevices::GetKeyboardModdifierValues() const { | 418 | KeyboardModifierValues EmulatedDevices::GetKeyboardModdifierValues() const { |
| 419 | std::scoped_lock lock{mutex}; | ||
| 408 | return device_status.keyboard_moddifier_values; | 420 | return device_status.keyboard_moddifier_values; |
| 409 | } | 421 | } |
| 410 | 422 | ||
| 411 | MouseButtonValues EmulatedDevices::GetMouseButtonsValues() const { | 423 | MouseButtonValues EmulatedDevices::GetMouseButtonsValues() const { |
| 424 | std::scoped_lock lock{mutex}; | ||
| 412 | return device_status.mouse_button_values; | 425 | return device_status.mouse_button_values; |
| 413 | } | 426 | } |
| 414 | 427 | ||
| 415 | KeyboardKey EmulatedDevices::GetKeyboard() const { | 428 | KeyboardKey EmulatedDevices::GetKeyboard() const { |
| 429 | std::scoped_lock lock{mutex}; | ||
| 416 | return device_status.keyboard_state; | 430 | return device_status.keyboard_state; |
| 417 | } | 431 | } |
| 418 | 432 | ||
| 419 | KeyboardModifier EmulatedDevices::GetKeyboardModifier() const { | 433 | KeyboardModifier EmulatedDevices::GetKeyboardModifier() const { |
| 434 | std::scoped_lock lock{mutex}; | ||
| 420 | return device_status.keyboard_moddifier_state; | 435 | return device_status.keyboard_moddifier_state; |
| 421 | } | 436 | } |
| 422 | 437 | ||
| 423 | MouseButton EmulatedDevices::GetMouseButtons() const { | 438 | MouseButton EmulatedDevices::GetMouseButtons() const { |
| 439 | std::scoped_lock lock{mutex}; | ||
| 424 | return device_status.mouse_button_state; | 440 | return device_status.mouse_button_state; |
| 425 | } | 441 | } |
| 426 | 442 | ||
| 427 | MousePosition EmulatedDevices::GetMousePosition() const { | 443 | MousePosition EmulatedDevices::GetMousePosition() const { |
| 444 | std::scoped_lock lock{mutex}; | ||
| 428 | return device_status.mouse_position_state; | 445 | return device_status.mouse_position_state; |
| 429 | } | 446 | } |
| 430 | 447 | ||
| 431 | AnalogStickState EmulatedDevices::GetMouseWheel() const { | 448 | AnalogStickState EmulatedDevices::GetMouseWheel() const { |
| 449 | std::scoped_lock lock{mutex}; | ||
| 432 | return device_status.mouse_wheel_state; | 450 | return device_status.mouse_wheel_state; |
| 433 | } | 451 | } |
| 434 | 452 | ||
| 435 | void EmulatedDevices::TriggerOnChange(DeviceTriggerType type) { | 453 | void EmulatedDevices::TriggerOnChange(DeviceTriggerType type) { |
| 454 | std::scoped_lock lock{callback_mutex}; | ||
| 436 | for (const auto& poller_pair : callback_list) { | 455 | for (const auto& poller_pair : callback_list) { |
| 437 | const InterfaceUpdateCallback& poller = poller_pair.second; | 456 | const InterfaceUpdateCallback& poller = poller_pair.second; |
| 438 | if (poller.on_change) { | 457 | if (poller.on_change) { |
| @@ -442,13 +461,13 @@ void EmulatedDevices::TriggerOnChange(DeviceTriggerType type) { | |||
| 442 | } | 461 | } |
| 443 | 462 | ||
| 444 | int EmulatedDevices::SetCallback(InterfaceUpdateCallback update_callback) { | 463 | int EmulatedDevices::SetCallback(InterfaceUpdateCallback update_callback) { |
| 445 | std::lock_guard lock{mutex}; | 464 | std::scoped_lock lock{callback_mutex}; |
| 446 | callback_list.insert_or_assign(last_callback_key, std::move(update_callback)); | 465 | callback_list.insert_or_assign(last_callback_key, std::move(update_callback)); |
| 447 | return last_callback_key++; | 466 | return last_callback_key++; |
| 448 | } | 467 | } |
| 449 | 468 | ||
| 450 | void EmulatedDevices::DeleteCallback(int key) { | 469 | void EmulatedDevices::DeleteCallback(int key) { |
| 451 | std::lock_guard lock{mutex}; | 470 | std::scoped_lock lock{callback_mutex}; |
| 452 | const auto& iterator = callback_list.find(key); | 471 | const auto& iterator = callback_list.find(key); |
| 453 | if (iterator == callback_list.end()) { | 472 | if (iterator == callback_list.end()) { |
| 454 | LOG_ERROR(Input, "Tried to delete non-existent callback {}", key); | 473 | LOG_ERROR(Input, "Tried to delete non-existent callback {}", key); |
diff --git a/src/core/hid/emulated_devices.h b/src/core/hid/emulated_devices.h index 790d3b411..73e9f0293 100644 --- a/src/core/hid/emulated_devices.h +++ b/src/core/hid/emulated_devices.h | |||
| @@ -200,6 +200,7 @@ private: | |||
| 200 | MouseStickDevice mouse_stick_device; | 200 | MouseStickDevice mouse_stick_device; |
| 201 | 201 | ||
| 202 | mutable std::mutex mutex; | 202 | mutable std::mutex mutex; |
| 203 | mutable std::mutex callback_mutex; | ||
| 203 | std::unordered_map<int, InterfaceUpdateCallback> callback_list; | 204 | std::unordered_map<int, InterfaceUpdateCallback> callback_list; |
| 204 | int last_callback_key = 0; | 205 | int last_callback_key = 0; |
| 205 | 206 | ||
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index 42d1b0e31..b547a3463 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp | |||
| @@ -24,8 +24,15 @@ | |||
| 24 | 24 | ||
| 25 | namespace Kernel { | 25 | namespace Kernel { |
| 26 | 26 | ||
| 27 | SessionRequestHandler::SessionRequestHandler(KernelCore& kernel_, const char* service_name_) | 27 | SessionRequestHandler::SessionRequestHandler(KernelCore& kernel_, const char* service_name_, |
| 28 | : kernel{kernel_}, service_thread{kernel.CreateServiceThread(service_name_)} {} | 28 | ServiceThreadType thread_type) |
| 29 | : kernel{kernel_} { | ||
| 30 | if (thread_type == ServiceThreadType::CreateNew) { | ||
| 31 | service_thread = kernel.CreateServiceThread(service_name_); | ||
| 32 | } else { | ||
| 33 | service_thread = kernel.GetDefaultServiceThread(); | ||
| 34 | } | ||
| 35 | } | ||
| 29 | 36 | ||
| 30 | SessionRequestHandler::~SessionRequestHandler() { | 37 | SessionRequestHandler::~SessionRequestHandler() { |
| 31 | kernel.ReleaseServiceThread(service_thread); | 38 | kernel.ReleaseServiceThread(service_thread); |
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index 670cc741c..640146137 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h | |||
| @@ -33,6 +33,11 @@ namespace Service { | |||
| 33 | class ServiceFrameworkBase; | 33 | class ServiceFrameworkBase; |
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | enum class ServiceThreadType { | ||
| 37 | Default, | ||
| 38 | CreateNew, | ||
| 39 | }; | ||
| 40 | |||
| 36 | namespace Kernel { | 41 | namespace Kernel { |
| 37 | 42 | ||
| 38 | class Domain; | 43 | class Domain; |
| @@ -57,7 +62,8 @@ enum class ThreadWakeupReason; | |||
| 57 | */ | 62 | */ |
| 58 | class SessionRequestHandler : public std::enable_shared_from_this<SessionRequestHandler> { | 63 | class SessionRequestHandler : public std::enable_shared_from_this<SessionRequestHandler> { |
| 59 | public: | 64 | public: |
| 60 | SessionRequestHandler(KernelCore& kernel, const char* service_name_); | 65 | SessionRequestHandler(KernelCore& kernel_, const char* service_name_, |
| 66 | ServiceThreadType thread_type); | ||
| 61 | virtual ~SessionRequestHandler(); | 67 | virtual ~SessionRequestHandler(); |
| 62 | 68 | ||
| 63 | /** | 69 | /** |
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 34da7c23b..134a0b8e9 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -61,6 +61,7 @@ struct KernelCore::Impl { | |||
| 61 | global_scheduler_context = std::make_unique<Kernel::GlobalSchedulerContext>(kernel); | 61 | global_scheduler_context = std::make_unique<Kernel::GlobalSchedulerContext>(kernel); |
| 62 | global_handle_table = std::make_unique<Kernel::KHandleTable>(kernel); | 62 | global_handle_table = std::make_unique<Kernel::KHandleTable>(kernel); |
| 63 | global_handle_table->Initialize(KHandleTable::MaxTableSize); | 63 | global_handle_table->Initialize(KHandleTable::MaxTableSize); |
| 64 | default_service_thread = CreateServiceThread(kernel, "DefaultServiceThread"); | ||
| 64 | 65 | ||
| 65 | is_phantom_mode_for_singlecore = false; | 66 | is_phantom_mode_for_singlecore = false; |
| 66 | 67 | ||
| @@ -98,7 +99,7 @@ struct KernelCore::Impl { | |||
| 98 | // Close all open server ports. | 99 | // Close all open server ports. |
| 99 | std::unordered_set<KServerPort*> server_ports_; | 100 | std::unordered_set<KServerPort*> server_ports_; |
| 100 | { | 101 | { |
| 101 | std::lock_guard lk(server_ports_lock); | 102 | std::scoped_lock lk{server_ports_lock}; |
| 102 | server_ports_ = server_ports; | 103 | server_ports_ = server_ports; |
| 103 | server_ports.clear(); | 104 | server_ports.clear(); |
| 104 | } | 105 | } |
| @@ -156,7 +157,7 @@ struct KernelCore::Impl { | |||
| 156 | 157 | ||
| 157 | // Close kernel objects that were not freed on shutdown | 158 | // Close kernel objects that were not freed on shutdown |
| 158 | { | 159 | { |
| 159 | std::lock_guard lk(registered_in_use_objects_lock); | 160 | std::scoped_lock lk{registered_in_use_objects_lock}; |
| 160 | if (registered_in_use_objects.size()) { | 161 | if (registered_in_use_objects.size()) { |
| 161 | for (auto& object : registered_in_use_objects) { | 162 | for (auto& object : registered_in_use_objects) { |
| 162 | object->Close(); | 163 | object->Close(); |
| @@ -177,7 +178,7 @@ struct KernelCore::Impl { | |||
| 177 | 178 | ||
| 178 | // Track kernel objects that were not freed on shutdown | 179 | // Track kernel objects that were not freed on shutdown |
| 179 | { | 180 | { |
| 180 | std::lock_guard lk(registered_objects_lock); | 181 | std::scoped_lock lk{registered_objects_lock}; |
| 181 | if (registered_objects.size()) { | 182 | if (registered_objects.size()) { |
| 182 | LOG_DEBUG(Kernel, "{} kernel objects were dangling on shutdown!", | 183 | LOG_DEBUG(Kernel, "{} kernel objects were dangling on shutdown!", |
| 183 | registered_objects.size()); | 184 | registered_objects.size()); |
| @@ -659,7 +660,7 @@ struct KernelCore::Impl { | |||
| 659 | 660 | ||
| 660 | KClientPort* port = &search->second(system.ServiceManager(), system); | 661 | KClientPort* port = &search->second(system.ServiceManager(), system); |
| 661 | { | 662 | { |
| 662 | std::lock_guard lk(server_ports_lock); | 663 | std::scoped_lock lk{server_ports_lock}; |
| 663 | server_ports.insert(&port->GetParent()->GetServerPort()); | 664 | server_ports.insert(&port->GetParent()->GetServerPort()); |
| 664 | } | 665 | } |
| 665 | return port; | 666 | return port; |
| @@ -677,6 +678,12 @@ struct KernelCore::Impl { | |||
| 677 | 678 | ||
| 678 | void ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread) { | 679 | void ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread) { |
| 679 | if (auto strong_ptr = service_thread.lock()) { | 680 | if (auto strong_ptr = service_thread.lock()) { |
| 681 | if (strong_ptr == default_service_thread.lock()) { | ||
| 682 | // Nothing to do here, the service is using default_service_thread, which will be | ||
| 683 | // released on shutdown. | ||
| 684 | return; | ||
| 685 | } | ||
| 686 | |||
| 680 | service_threads_manager.QueueWork( | 687 | service_threads_manager.QueueWork( |
| 681 | [this, strong_ptr{std::move(strong_ptr)}]() { service_threads.erase(strong_ptr); }); | 688 | [this, strong_ptr{std::move(strong_ptr)}]() { service_threads.erase(strong_ptr); }); |
| 682 | } | 689 | } |
| @@ -739,7 +746,8 @@ struct KernelCore::Impl { | |||
| 739 | std::unique_ptr<KMemoryLayout> memory_layout; | 746 | std::unique_ptr<KMemoryLayout> memory_layout; |
| 740 | 747 | ||
| 741 | // Threads used for services | 748 | // Threads used for services |
| 742 | std::unordered_set<std::shared_ptr<Kernel::ServiceThread>> service_threads; | 749 | std::unordered_set<std::shared_ptr<ServiceThread>> service_threads; |
| 750 | std::weak_ptr<ServiceThread> default_service_thread; | ||
| 743 | Common::ThreadWorker service_threads_manager; | 751 | Common::ThreadWorker service_threads_manager; |
| 744 | 752 | ||
| 745 | std::array<KThread*, Core::Hardware::NUM_CPU_CORES> suspend_threads; | 753 | std::array<KThread*, Core::Hardware::NUM_CPU_CORES> suspend_threads; |
| @@ -921,22 +929,22 @@ KClientPort* KernelCore::CreateNamedServicePort(std::string name) { | |||
| 921 | } | 929 | } |
| 922 | 930 | ||
| 923 | void KernelCore::RegisterKernelObject(KAutoObject* object) { | 931 | void KernelCore::RegisterKernelObject(KAutoObject* object) { |
| 924 | std::lock_guard lk(impl->registered_objects_lock); | 932 | std::scoped_lock lk{impl->registered_objects_lock}; |
| 925 | impl->registered_objects.insert(object); | 933 | impl->registered_objects.insert(object); |
| 926 | } | 934 | } |
| 927 | 935 | ||
| 928 | void KernelCore::UnregisterKernelObject(KAutoObject* object) { | 936 | void KernelCore::UnregisterKernelObject(KAutoObject* object) { |
| 929 | std::lock_guard lk(impl->registered_objects_lock); | 937 | std::scoped_lock lk{impl->registered_objects_lock}; |
| 930 | impl->registered_objects.erase(object); | 938 | impl->registered_objects.erase(object); |
| 931 | } | 939 | } |
| 932 | 940 | ||
| 933 | void KernelCore::RegisterInUseObject(KAutoObject* object) { | 941 | void KernelCore::RegisterInUseObject(KAutoObject* object) { |
| 934 | std::lock_guard lk(impl->registered_in_use_objects_lock); | 942 | std::scoped_lock lk{impl->registered_in_use_objects_lock}; |
| 935 | impl->registered_in_use_objects.insert(object); | 943 | impl->registered_in_use_objects.insert(object); |
| 936 | } | 944 | } |
| 937 | 945 | ||
| 938 | void KernelCore::UnregisterInUseObject(KAutoObject* object) { | 946 | void KernelCore::UnregisterInUseObject(KAutoObject* object) { |
| 939 | std::lock_guard lk(impl->registered_in_use_objects_lock); | 947 | std::scoped_lock lk{impl->registered_in_use_objects_lock}; |
| 940 | impl->registered_in_use_objects.erase(object); | 948 | impl->registered_in_use_objects.erase(object); |
| 941 | } | 949 | } |
| 942 | 950 | ||
| @@ -1065,6 +1073,10 @@ std::weak_ptr<Kernel::ServiceThread> KernelCore::CreateServiceThread(const std:: | |||
| 1065 | return impl->CreateServiceThread(*this, name); | 1073 | return impl->CreateServiceThread(*this, name); |
| 1066 | } | 1074 | } |
| 1067 | 1075 | ||
| 1076 | std::weak_ptr<Kernel::ServiceThread> KernelCore::GetDefaultServiceThread() const { | ||
| 1077 | return impl->default_service_thread; | ||
| 1078 | } | ||
| 1079 | |||
| 1068 | void KernelCore::ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread) { | 1080 | void KernelCore::ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread) { |
| 1069 | impl->ReleaseServiceThread(service_thread); | 1081 | impl->ReleaseServiceThread(service_thread); |
| 1070 | } | 1082 | } |
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 4c68e96df..24e26fa44 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -271,9 +271,11 @@ public: | |||
| 271 | void ExitSVCProfile(); | 271 | void ExitSVCProfile(); |
| 272 | 272 | ||
| 273 | /** | 273 | /** |
| 274 | * Creates an HLE service thread, which are used to execute service routines asynchronously. | 274 | * Creates a host thread to execute HLE service requests, which are used to execute service |
| 275 | * While these are allocated per ServerSession, these need to be owned and managed outside | 275 | * routines asynchronously. While these are allocated per ServerSession, these need to be owned |
| 276 | * of ServerSession to avoid a circular dependency. | 276 | * and managed outside of ServerSession to avoid a circular dependency. In general, most |
| 277 | * services can just use the default service thread, and not need their own host service thread. | ||
| 278 | * See GetDefaultServiceThread. | ||
| 277 | * @param name String name for the ServerSession creating this thread, used for debug | 279 | * @param name String name for the ServerSession creating this thread, used for debug |
| 278 | * purposes. | 280 | * purposes. |
| 279 | * @returns The a weak pointer newly created service thread. | 281 | * @returns The a weak pointer newly created service thread. |
| @@ -281,6 +283,14 @@ public: | |||
| 281 | std::weak_ptr<Kernel::ServiceThread> CreateServiceThread(const std::string& name); | 283 | std::weak_ptr<Kernel::ServiceThread> CreateServiceThread(const std::string& name); |
| 282 | 284 | ||
| 283 | /** | 285 | /** |
| 286 | * Gets the default host service thread, which executes HLE service requests. Unless service | ||
| 287 | * requests need to block on the host, the default service thread should be used in favor of | ||
| 288 | * creating a new service thread. | ||
| 289 | * @returns The a weak pointer for the default service thread. | ||
| 290 | */ | ||
| 291 | std::weak_ptr<Kernel::ServiceThread> GetDefaultServiceThread() const; | ||
| 292 | |||
| 293 | /** | ||
| 284 | * Releases a HLE service thread, instructing KernelCore to free it. This should be called when | 294 | * Releases a HLE service thread, instructing KernelCore to free it. This should be called when |
| 285 | * the ServerSession associated with the thread is destroyed. | 295 | * the ServerSession associated with the thread is destroyed. |
| 286 | * @param service_thread Service thread to release. | 296 | * @param service_thread Service thread to release. |
diff --git a/src/core/hle/kernel/physical_core.cpp b/src/core/hle/kernel/physical_core.cpp index 7477668e4..18a5f40f8 100644 --- a/src/core/hle/kernel/physical_core.cpp +++ b/src/core/hle/kernel/physical_core.cpp | |||
| @@ -58,6 +58,7 @@ bool PhysicalCore::IsInterrupted() const { | |||
| 58 | void PhysicalCore::Interrupt() { | 58 | void PhysicalCore::Interrupt() { |
| 59 | guard->lock(); | 59 | guard->lock(); |
| 60 | interrupts[core_index].SetInterrupt(true); | 60 | interrupts[core_index].SetInterrupt(true); |
| 61 | arm_interface->SignalInterrupt(); | ||
| 61 | guard->unlock(); | 62 | guard->unlock(); |
| 62 | } | 63 | } |
| 63 | 64 | ||
diff --git a/src/core/hle/kernel/time_manager.cpp b/src/core/hle/kernel/time_manager.cpp index aa985d820..5b8fe8eae 100644 --- a/src/core/hle/kernel/time_manager.cpp +++ b/src/core/hle/kernel/time_manager.cpp | |||
| @@ -24,7 +24,7 @@ TimeManager::TimeManager(Core::System& system_) : system{system_} { | |||
| 24 | } | 24 | } |
| 25 | 25 | ||
| 26 | void TimeManager::ScheduleTimeEvent(KThread* thread, s64 nanoseconds) { | 26 | void TimeManager::ScheduleTimeEvent(KThread* thread, s64 nanoseconds) { |
| 27 | std::lock_guard lock{mutex}; | 27 | std::scoped_lock lock{mutex}; |
| 28 | if (nanoseconds > 0) { | 28 | if (nanoseconds > 0) { |
| 29 | ASSERT(thread); | 29 | ASSERT(thread); |
| 30 | ASSERT(thread->GetState() != ThreadState::Runnable); | 30 | ASSERT(thread->GetState() != ThreadState::Runnable); |
| @@ -35,7 +35,7 @@ void TimeManager::ScheduleTimeEvent(KThread* thread, s64 nanoseconds) { | |||
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | void TimeManager::UnscheduleTimeEvent(KThread* thread) { | 37 | void TimeManager::UnscheduleTimeEvent(KThread* thread) { |
| 38 | std::lock_guard lock{mutex}; | 38 | std::scoped_lock lock{mutex}; |
| 39 | system.CoreTiming().UnscheduleEvent(time_manager_event_type, | 39 | system.CoreTiming().UnscheduleEvent(time_manager_event_type, |
| 40 | reinterpret_cast<uintptr_t>(thread)); | 40 | reinterpret_cast<uintptr_t>(thread)); |
| 41 | } | 41 | } |
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 420de3c54..4d7e5ecd3 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -1337,7 +1337,7 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_) | |||
| 1337 | {200, nullptr, "GetLastApplicationExitReason"}, | 1337 | {200, nullptr, "GetLastApplicationExitReason"}, |
| 1338 | {500, nullptr, "StartContinuousRecordingFlushForDebug"}, | 1338 | {500, nullptr, "StartContinuousRecordingFlushForDebug"}, |
| 1339 | {1000, nullptr, "CreateMovieMaker"}, | 1339 | {1000, nullptr, "CreateMovieMaker"}, |
| 1340 | {1001, nullptr, "PrepareForJit"}, | 1340 | {1001, &IApplicationFunctions::PrepareForJit, "PrepareForJit"}, |
| 1341 | }; | 1341 | }; |
| 1342 | // clang-format on | 1342 | // clang-format on |
| 1343 | 1343 | ||
| @@ -1787,6 +1787,13 @@ void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(Kernel::HLERe | |||
| 1787 | rb.PushCopyObjects(health_warning_disappeared_system_event->GetReadableEvent()); | 1787 | rb.PushCopyObjects(health_warning_disappeared_system_event->GetReadableEvent()); |
| 1788 | } | 1788 | } |
| 1789 | 1789 | ||
| 1790 | void IApplicationFunctions::PrepareForJit(Kernel::HLERequestContext& ctx) { | ||
| 1791 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 1792 | |||
| 1793 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1794 | rb.Push(ResultSuccess); | ||
| 1795 | } | ||
| 1796 | |||
| 1790 | void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger, | 1797 | void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger, |
| 1791 | Core::System& system) { | 1798 | Core::System& system) { |
| 1792 | auto message_queue = std::make_shared<AppletMessageQueue>(system); | 1799 | auto message_queue = std::make_shared<AppletMessageQueue>(system); |
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index fdd937b82..11a3c0459 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h | |||
| @@ -336,6 +336,7 @@ private: | |||
| 336 | void TryPopFromFriendInvitationStorageChannel(Kernel::HLERequestContext& ctx); | 336 | void TryPopFromFriendInvitationStorageChannel(Kernel::HLERequestContext& ctx); |
| 337 | void GetNotificationStorageChannelEvent(Kernel::HLERequestContext& ctx); | 337 | void GetNotificationStorageChannelEvent(Kernel::HLERequestContext& ctx); |
| 338 | void GetHealthWarningDisappearedSystemEvent(Kernel::HLERequestContext& ctx); | 338 | void GetHealthWarningDisappearedSystemEvent(Kernel::HLERequestContext& ctx); |
| 339 | void PrepareForJit(Kernel::HLERequestContext& ctx); | ||
| 339 | 340 | ||
| 340 | KernelHelpers::ServiceContext service_context; | 341 | KernelHelpers::ServiceContext service_context; |
| 341 | 342 | ||
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp index affa7971c..a72956a28 100644 --- a/src/core/hle/service/audio/audout_u.cpp +++ b/src/core/hle/service/audio/audout_u.cpp | |||
| @@ -41,9 +41,10 @@ public: | |||
| 41 | explicit IAudioOut(Core::System& system_, AudoutParams audio_params_, | 41 | explicit IAudioOut(Core::System& system_, AudoutParams audio_params_, |
| 42 | AudioCore::AudioOut& audio_core_, std::string&& device_name_, | 42 | AudioCore::AudioOut& audio_core_, std::string&& device_name_, |
| 43 | std::string&& unique_name) | 43 | std::string&& unique_name) |
| 44 | : ServiceFramework{system_, "IAudioOut"}, audio_core{audio_core_}, | 44 | : ServiceFramework{system_, "IAudioOut", ServiceThreadType::CreateNew}, |
| 45 | device_name{std::move(device_name_)}, audio_params{audio_params_}, | 45 | audio_core{audio_core_}, device_name{std::move(device_name_)}, |
| 46 | main_memory{system.Memory()}, service_context{system_, "IAudioOut"} { | 46 | audio_params{audio_params_}, main_memory{system.Memory()}, service_context{system_, |
| 47 | "IAudioOut"} { | ||
| 47 | // clang-format off | 48 | // clang-format off |
| 48 | static const FunctionInfo functions[] = { | 49 | static const FunctionInfo functions[] = { |
| 49 | {0, &IAudioOut::GetAudioOutState, "GetAudioOutState"}, | 50 | {0, &IAudioOut::GetAudioOutState, "GetAudioOutState"}, |
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index f45e5cecc..d4ffeb21d 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp | |||
| @@ -24,7 +24,8 @@ public: | |||
| 24 | explicit IAudioRenderer(Core::System& system_, | 24 | explicit IAudioRenderer(Core::System& system_, |
| 25 | const AudioCommon::AudioRendererParameter& audren_params, | 25 | const AudioCommon::AudioRendererParameter& audren_params, |
| 26 | const std::size_t instance_number) | 26 | const std::size_t instance_number) |
| 27 | : ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"} { | 27 | : ServiceFramework{system_, "IAudioRenderer", ServiceThreadType::CreateNew}, |
| 28 | service_context{system_, "IAudioRenderer"} { | ||
| 28 | // clang-format off | 29 | // clang-format off |
| 29 | static const FunctionInfo functions[] = { | 30 | static const FunctionInfo functions[] = { |
| 30 | {0, &IAudioRenderer::GetSampleRate, "GetSampleRate"}, | 31 | {0, &IAudioRenderer::GetSampleRate, "GetSampleRate"}, |
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index b087e7bba..c07929ab8 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp | |||
| @@ -58,7 +58,8 @@ enum class FileSystemType : u8 { | |||
| 58 | class IStorage final : public ServiceFramework<IStorage> { | 58 | class IStorage final : public ServiceFramework<IStorage> { |
| 59 | public: | 59 | public: |
| 60 | explicit IStorage(Core::System& system_, FileSys::VirtualFile backend_) | 60 | explicit IStorage(Core::System& system_, FileSys::VirtualFile backend_) |
| 61 | : ServiceFramework{system_, "IStorage"}, backend(std::move(backend_)) { | 61 | : ServiceFramework{system_, "IStorage", ServiceThreadType::CreateNew}, |
| 62 | backend(std::move(backend_)) { | ||
| 62 | static const FunctionInfo functions[] = { | 63 | static const FunctionInfo functions[] = { |
| 63 | {0, &IStorage::Read, "Read"}, | 64 | {0, &IStorage::Read, "Read"}, |
| 64 | {1, nullptr, "Write"}, | 65 | {1, nullptr, "Write"}, |
| @@ -116,7 +117,8 @@ private: | |||
| 116 | class IFile final : public ServiceFramework<IFile> { | 117 | class IFile final : public ServiceFramework<IFile> { |
| 117 | public: | 118 | public: |
| 118 | explicit IFile(Core::System& system_, FileSys::VirtualFile backend_) | 119 | explicit IFile(Core::System& system_, FileSys::VirtualFile backend_) |
| 119 | : ServiceFramework{system_, "IFile"}, backend(std::move(backend_)) { | 120 | : ServiceFramework{system_, "IFile", ServiceThreadType::CreateNew}, |
| 121 | backend(std::move(backend_)) { | ||
| 120 | static const FunctionInfo functions[] = { | 122 | static const FunctionInfo functions[] = { |
| 121 | {0, &IFile::Read, "Read"}, | 123 | {0, &IFile::Read, "Read"}, |
| 122 | {1, &IFile::Write, "Write"}, | 124 | {1, &IFile::Write, "Write"}, |
| @@ -252,7 +254,8 @@ static void BuildEntryIndex(std::vector<FileSys::Entry>& entries, const std::vec | |||
| 252 | class IDirectory final : public ServiceFramework<IDirectory> { | 254 | class IDirectory final : public ServiceFramework<IDirectory> { |
| 253 | public: | 255 | public: |
| 254 | explicit IDirectory(Core::System& system_, FileSys::VirtualDir backend_) | 256 | explicit IDirectory(Core::System& system_, FileSys::VirtualDir backend_) |
| 255 | : ServiceFramework{system_, "IDirectory"}, backend(std::move(backend_)) { | 257 | : ServiceFramework{system_, "IDirectory", ServiceThreadType::CreateNew}, |
| 258 | backend(std::move(backend_)) { | ||
| 256 | static const FunctionInfo functions[] = { | 259 | static const FunctionInfo functions[] = { |
| 257 | {0, &IDirectory::Read, "Read"}, | 260 | {0, &IDirectory::Read, "Read"}, |
| 258 | {1, &IDirectory::GetEntryCount, "GetEntryCount"}, | 261 | {1, &IDirectory::GetEntryCount, "GetEntryCount"}, |
| @@ -308,8 +311,8 @@ private: | |||
| 308 | class IFileSystem final : public ServiceFramework<IFileSystem> { | 311 | class IFileSystem final : public ServiceFramework<IFileSystem> { |
| 309 | public: | 312 | public: |
| 310 | explicit IFileSystem(Core::System& system_, FileSys::VirtualDir backend_, SizeGetter size_) | 313 | explicit IFileSystem(Core::System& system_, FileSys::VirtualDir backend_, SizeGetter size_) |
| 311 | : ServiceFramework{system_, "IFileSystem"}, backend{std::move(backend_)}, size{std::move( | 314 | : ServiceFramework{system_, "IFileSystem", ServiceThreadType::CreateNew}, |
| 312 | size_)} { | 315 | backend{std::move(backend_)}, size{std::move(size_)} { |
| 313 | static const FunctionInfo functions[] = { | 316 | static const FunctionInfo functions[] = { |
| 314 | {0, &IFileSystem::CreateFile, "CreateFile"}, | 317 | {0, &IFileSystem::CreateFile, "CreateFile"}, |
| 315 | {1, &IFileSystem::DeleteFile, "DeleteFile"}, | 318 | {1, &IFileSystem::DeleteFile, "DeleteFile"}, |
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index aa6cb34b7..4e17a952e 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp | |||
| @@ -318,7 +318,7 @@ void Controller_NPad::OnRelease() { | |||
| 318 | } | 318 | } |
| 319 | 319 | ||
| 320 | void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) { | 320 | void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) { |
| 321 | std::lock_guard lock{mutex}; | 321 | std::scoped_lock lock{mutex}; |
| 322 | auto& controller = GetControllerFromNpadIdType(npad_id); | 322 | auto& controller = GetControllerFromNpadIdType(npad_id); |
| 323 | const auto controller_type = controller.device->GetNpadStyleIndex(); | 323 | const auto controller_type = controller.device->GetNpadStyleIndex(); |
| 324 | if (!controller.device->IsConnected()) { | 324 | if (!controller.device->IsConnected()) { |
diff --git a/src/core/hle/service/jit/jit.cpp b/src/core/hle/service/jit/jit.cpp new file mode 100644 index 000000000..c8ebd2e3f --- /dev/null +++ b/src/core/hle/service/jit/jit.cpp | |||
| @@ -0,0 +1,53 @@ | |||
| 1 | // Copyright 2022 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "core/hle/ipc_helpers.h" | ||
| 6 | #include "core/hle/result.h" | ||
| 7 | #include "core/hle/service/jit/jit.h" | ||
| 8 | #include "core/hle/service/service.h" | ||
| 9 | |||
| 10 | namespace Service::JIT { | ||
| 11 | |||
| 12 | class IJitEnvironment final : public ServiceFramework<IJitEnvironment> { | ||
| 13 | public: | ||
| 14 | explicit IJitEnvironment(Core::System& system_) : ServiceFramework{system_, "IJitEnvironment"} { | ||
| 15 | // clang-format off | ||
| 16 | static const FunctionInfo functions[] = { | ||
| 17 | {0, nullptr, "GenerateCode"}, | ||
| 18 | {1, nullptr, "Control"}, | ||
| 19 | {1000, nullptr, "LoadPlugin"}, | ||
| 20 | {1001, nullptr, "GetCodeAddress"}, | ||
| 21 | }; | ||
| 22 | // clang-format on | ||
| 23 | |||
| 24 | RegisterHandlers(functions); | ||
| 25 | } | ||
| 26 | }; | ||
| 27 | |||
| 28 | class JITU final : public ServiceFramework<JITU> { | ||
| 29 | public: | ||
| 30 | explicit JITU(Core::System& system_) : ServiceFramework{system_, "jit:u"} { | ||
| 31 | // clang-format off | ||
| 32 | static const FunctionInfo functions[] = { | ||
| 33 | {0, &JITU::CreateJitEnvironment, "CreateJitEnvironment"}, | ||
| 34 | }; | ||
| 35 | // clang-format on | ||
| 36 | |||
| 37 | RegisterHandlers(functions); | ||
| 38 | } | ||
| 39 | |||
| 40 | void CreateJitEnvironment(Kernel::HLERequestContext& ctx) { | ||
| 41 | LOG_DEBUG(Service_JIT, "called"); | ||
| 42 | |||
| 43 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 44 | rb.Push(ResultSuccess); | ||
| 45 | rb.PushIpcInterface<IJitEnvironment>(system); | ||
| 46 | } | ||
| 47 | }; | ||
| 48 | |||
| 49 | void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { | ||
| 50 | std::make_shared<JITU>(system)->InstallAsService(sm); | ||
| 51 | } | ||
| 52 | |||
| 53 | } // namespace Service::JIT | ||
diff --git a/src/core/hle/service/jit/jit.h b/src/core/hle/service/jit/jit.h new file mode 100644 index 000000000..8fbf504a1 --- /dev/null +++ b/src/core/hle/service/jit/jit.h | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | // Copyright 2022 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | namespace Core { | ||
| 8 | class System; | ||
| 9 | } | ||
| 10 | |||
| 11 | namespace Service::SM { | ||
| 12 | class ServiceManager; | ||
| 13 | } | ||
| 14 | |||
| 15 | namespace Service::JIT { | ||
| 16 | |||
| 17 | /// Registers all JIT services with the specified service manager. | ||
| 18 | void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); | ||
| 19 | |||
| 20 | } // namespace Service::JIT | ||
diff --git a/src/core/hle/service/nvdrv/nvdrv_interface.cpp b/src/core/hle/service/nvdrv/nvdrv_interface.cpp index 1ce2a856b..8467b50e4 100644 --- a/src/core/hle/service/nvdrv/nvdrv_interface.cpp +++ b/src/core/hle/service/nvdrv/nvdrv_interface.cpp | |||
| @@ -230,7 +230,7 @@ void NVDRV::DumpGraphicsMemoryInfo(Kernel::HLERequestContext& ctx) { | |||
| 230 | } | 230 | } |
| 231 | 231 | ||
| 232 | NVDRV::NVDRV(Core::System& system_, std::shared_ptr<Module> nvdrv_, const char* name) | 232 | NVDRV::NVDRV(Core::System& system_, std::shared_ptr<Module> nvdrv_, const char* name) |
| 233 | : ServiceFramework{system_, name}, nvdrv{std::move(nvdrv_)} { | 233 | : ServiceFramework{system_, name, ServiceThreadType::CreateNew}, nvdrv{std::move(nvdrv_)} { |
| 234 | static const FunctionInfo functions[] = { | 234 | static const FunctionInfo functions[] = { |
| 235 | {0, &NVDRV::Open, "Open"}, | 235 | {0, &NVDRV::Open, "Open"}, |
| 236 | {1, &NVDRV::Ioctl1, "Ioctl"}, | 236 | {1, &NVDRV::Ioctl1, "Ioctl"}, |
diff --git a/src/core/hle/service/nvflinger/buffer_item_consumer.cpp b/src/core/hle/service/nvflinger/buffer_item_consumer.cpp index 93fa1ec10..d7ee5362b 100644 --- a/src/core/hle/service/nvflinger/buffer_item_consumer.cpp +++ b/src/core/hle/service/nvflinger/buffer_item_consumer.cpp | |||
| @@ -21,7 +21,7 @@ Status BufferItemConsumer::AcquireBuffer(BufferItem* item, std::chrono::nanoseco | |||
| 21 | return Status::BadValue; | 21 | return Status::BadValue; |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | std::scoped_lock lock(mutex); | 24 | std::scoped_lock lock{mutex}; |
| 25 | 25 | ||
| 26 | if (const auto status = AcquireBufferLocked(item, present_when); status != Status::NoError) { | 26 | if (const auto status = AcquireBufferLocked(item, present_when); status != Status::NoError) { |
| 27 | if (status != Status::NoBufferAvailable) { | 27 | if (status != Status::NoBufferAvailable) { |
| @@ -40,7 +40,7 @@ Status BufferItemConsumer::AcquireBuffer(BufferItem* item, std::chrono::nanoseco | |||
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | Status BufferItemConsumer::ReleaseBuffer(const BufferItem& item, Fence& release_fence) { | 42 | Status BufferItemConsumer::ReleaseBuffer(const BufferItem& item, Fence& release_fence) { |
| 43 | std::scoped_lock lock(mutex); | 43 | std::scoped_lock lock{mutex}; |
| 44 | 44 | ||
| 45 | if (const auto status = AddReleaseFenceLocked(item.buf, item.graphic_buffer, release_fence); | 45 | if (const auto status = AddReleaseFenceLocked(item.buf, item.graphic_buffer, release_fence); |
| 46 | status != Status::NoError) { | 46 | status != Status::NoError) { |
diff --git a/src/core/hle/service/nvflinger/buffer_queue_consumer.cpp b/src/core/hle/service/nvflinger/buffer_queue_consumer.cpp index c527c577e..3ab9a8c05 100644 --- a/src/core/hle/service/nvflinger/buffer_queue_consumer.cpp +++ b/src/core/hle/service/nvflinger/buffer_queue_consumer.cpp | |||
| @@ -19,7 +19,7 @@ BufferQueueConsumer::~BufferQueueConsumer() = default; | |||
| 19 | 19 | ||
| 20 | Status BufferQueueConsumer::AcquireBuffer(BufferItem* out_buffer, | 20 | Status BufferQueueConsumer::AcquireBuffer(BufferItem* out_buffer, |
| 21 | std::chrono::nanoseconds expected_present) { | 21 | std::chrono::nanoseconds expected_present) { |
| 22 | std::scoped_lock lock(core->mutex); | 22 | std::scoped_lock lock{core->mutex}; |
| 23 | 23 | ||
| 24 | // Check that the consumer doesn't currently have the maximum number of buffers acquired. | 24 | // Check that the consumer doesn't currently have the maximum number of buffers acquired. |
| 25 | const s32 num_acquired_buffers{ | 25 | const s32 num_acquired_buffers{ |
| @@ -120,7 +120,7 @@ Status BufferQueueConsumer::ReleaseBuffer(s32 slot, u64 frame_number, const Fenc | |||
| 120 | 120 | ||
| 121 | std::shared_ptr<IProducerListener> listener; | 121 | std::shared_ptr<IProducerListener> listener; |
| 122 | { | 122 | { |
| 123 | std::scoped_lock lock(core->mutex); | 123 | std::scoped_lock lock{core->mutex}; |
| 124 | 124 | ||
| 125 | // If the frame number has changed because the buffer has been reallocated, we can ignore | 125 | // If the frame number has changed because the buffer has been reallocated, we can ignore |
| 126 | // this ReleaseBuffer for the old buffer. | 126 | // this ReleaseBuffer for the old buffer. |
| @@ -180,7 +180,7 @@ Status BufferQueueConsumer::Connect(std::shared_ptr<IConsumerListener> consumer_ | |||
| 180 | 180 | ||
| 181 | LOG_DEBUG(Service_NVFlinger, "controlled_by_app={}", controlled_by_app); | 181 | LOG_DEBUG(Service_NVFlinger, "controlled_by_app={}", controlled_by_app); |
| 182 | 182 | ||
| 183 | std::scoped_lock lock(core->mutex); | 183 | std::scoped_lock lock{core->mutex}; |
| 184 | 184 | ||
| 185 | if (core->is_abandoned) { | 185 | if (core->is_abandoned) { |
| 186 | LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); | 186 | LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); |
| @@ -199,7 +199,7 @@ Status BufferQueueConsumer::GetReleasedBuffers(u64* out_slot_mask) { | |||
| 199 | return Status::BadValue; | 199 | return Status::BadValue; |
| 200 | } | 200 | } |
| 201 | 201 | ||
| 202 | std::scoped_lock lock(core->mutex); | 202 | std::scoped_lock lock{core->mutex}; |
| 203 | 203 | ||
| 204 | if (core->is_abandoned) { | 204 | if (core->is_abandoned) { |
| 205 | LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); | 205 | LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); |
diff --git a/src/core/hle/service/nvflinger/buffer_queue_core.cpp b/src/core/hle/service/nvflinger/buffer_queue_core.cpp index 3a0481786..ec5aabaeb 100644 --- a/src/core/hle/service/nvflinger/buffer_queue_core.cpp +++ b/src/core/hle/service/nvflinger/buffer_queue_core.cpp | |||
| @@ -15,7 +15,7 @@ BufferQueueCore::BufferQueueCore() = default; | |||
| 15 | BufferQueueCore::~BufferQueueCore() = default; | 15 | BufferQueueCore::~BufferQueueCore() = default; |
| 16 | 16 | ||
| 17 | void BufferQueueCore::NotifyShutdown() { | 17 | void BufferQueueCore::NotifyShutdown() { |
| 18 | std::scoped_lock lock(mutex); | 18 | std::scoped_lock lock{mutex}; |
| 19 | 19 | ||
| 20 | is_shutting_down = true; | 20 | is_shutting_down = true; |
| 21 | 21 | ||
diff --git a/src/core/hle/service/nvflinger/buffer_queue_producer.cpp b/src/core/hle/service/nvflinger/buffer_queue_producer.cpp index 3d6e990c3..6f604a88e 100644 --- a/src/core/hle/service/nvflinger/buffer_queue_producer.cpp +++ b/src/core/hle/service/nvflinger/buffer_queue_producer.cpp | |||
| @@ -38,7 +38,7 @@ BufferQueueProducer::~BufferQueueProducer() { | |||
| 38 | Status BufferQueueProducer::RequestBuffer(s32 slot, std::shared_ptr<GraphicBuffer>* buf) { | 38 | Status BufferQueueProducer::RequestBuffer(s32 slot, std::shared_ptr<GraphicBuffer>* buf) { |
| 39 | LOG_DEBUG(Service_NVFlinger, "slot {}", slot); | 39 | LOG_DEBUG(Service_NVFlinger, "slot {}", slot); |
| 40 | 40 | ||
| 41 | std::scoped_lock lock(core->mutex); | 41 | std::scoped_lock lock{core->mutex}; |
| 42 | 42 | ||
| 43 | if (core->is_abandoned) { | 43 | if (core->is_abandoned) { |
| 44 | LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); | 44 | LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); |
| @@ -65,7 +65,7 @@ Status BufferQueueProducer::SetBufferCount(s32 buffer_count) { | |||
| 65 | 65 | ||
| 66 | std::shared_ptr<IConsumerListener> listener; | 66 | std::shared_ptr<IConsumerListener> listener; |
| 67 | { | 67 | { |
| 68 | std::scoped_lock lock(core->mutex); | 68 | std::scoped_lock lock{core->mutex}; |
| 69 | core->WaitWhileAllocatingLocked(); | 69 | core->WaitWhileAllocatingLocked(); |
| 70 | 70 | ||
| 71 | if (core->is_abandoned) { | 71 | if (core->is_abandoned) { |
| @@ -236,7 +236,7 @@ Status BufferQueueProducer::DequeueBuffer(s32* out_slot, Fence* out_fence, bool | |||
| 236 | Status return_flags = Status::NoError; | 236 | Status return_flags = Status::NoError; |
| 237 | bool attached_by_consumer = false; | 237 | bool attached_by_consumer = false; |
| 238 | { | 238 | { |
| 239 | std::scoped_lock lock(core->mutex); | 239 | std::scoped_lock lock{core->mutex}; |
| 240 | core->WaitWhileAllocatingLocked(); | 240 | core->WaitWhileAllocatingLocked(); |
| 241 | 241 | ||
| 242 | if (format == PixelFormat::NoFormat) { | 242 | if (format == PixelFormat::NoFormat) { |
| @@ -295,7 +295,7 @@ Status BufferQueueProducer::DequeueBuffer(s32* out_slot, Fence* out_fence, bool | |||
| 295 | } | 295 | } |
| 296 | 296 | ||
| 297 | { | 297 | { |
| 298 | std::scoped_lock lock(core->mutex); | 298 | std::scoped_lock lock{core->mutex}; |
| 299 | 299 | ||
| 300 | if (core->is_abandoned) { | 300 | if (core->is_abandoned) { |
| 301 | LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); | 301 | LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); |
| @@ -320,7 +320,7 @@ Status BufferQueueProducer::DequeueBuffer(s32* out_slot, Fence* out_fence, bool | |||
| 320 | Status BufferQueueProducer::DetachBuffer(s32 slot) { | 320 | Status BufferQueueProducer::DetachBuffer(s32 slot) { |
| 321 | LOG_DEBUG(Service_NVFlinger, "slot {}", slot); | 321 | LOG_DEBUG(Service_NVFlinger, "slot {}", slot); |
| 322 | 322 | ||
| 323 | std::scoped_lock lock(core->mutex); | 323 | std::scoped_lock lock{core->mutex}; |
| 324 | 324 | ||
| 325 | if (core->is_abandoned) { | 325 | if (core->is_abandoned) { |
| 326 | LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); | 326 | LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); |
| @@ -356,7 +356,7 @@ Status BufferQueueProducer::DetachNextBuffer(std::shared_ptr<GraphicBuffer>* out | |||
| 356 | return Status::BadValue; | 356 | return Status::BadValue; |
| 357 | } | 357 | } |
| 358 | 358 | ||
| 359 | std::scoped_lock lock(core->mutex); | 359 | std::scoped_lock lock{core->mutex}; |
| 360 | core->WaitWhileAllocatingLocked(); | 360 | core->WaitWhileAllocatingLocked(); |
| 361 | 361 | ||
| 362 | if (core->is_abandoned) { | 362 | if (core->is_abandoned) { |
| @@ -399,7 +399,7 @@ Status BufferQueueProducer::AttachBuffer(s32* out_slot, | |||
| 399 | return Status::BadValue; | 399 | return Status::BadValue; |
| 400 | } | 400 | } |
| 401 | 401 | ||
| 402 | std::scoped_lock lock(core->mutex); | 402 | std::scoped_lock lock{core->mutex}; |
| 403 | core->WaitWhileAllocatingLocked(); | 403 | core->WaitWhileAllocatingLocked(); |
| 404 | 404 | ||
| 405 | Status return_flags = Status::NoError; | 405 | Status return_flags = Status::NoError; |
| @@ -460,7 +460,7 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input, | |||
| 460 | BufferItem item; | 460 | BufferItem item; |
| 461 | 461 | ||
| 462 | { | 462 | { |
| 463 | std::scoped_lock lock(core->mutex); | 463 | std::scoped_lock lock{core->mutex}; |
| 464 | 464 | ||
| 465 | if (core->is_abandoned) { | 465 | if (core->is_abandoned) { |
| 466 | LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); | 466 | LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); |
| @@ -576,7 +576,7 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input, | |||
| 576 | // Call back without the main BufferQueue lock held, but with the callback lock held so we can | 576 | // Call back without the main BufferQueue lock held, but with the callback lock held so we can |
| 577 | // ensure that callbacks occur in order | 577 | // ensure that callbacks occur in order |
| 578 | { | 578 | { |
| 579 | std::scoped_lock lock(callback_mutex); | 579 | std::scoped_lock lock{callback_mutex}; |
| 580 | while (callback_ticket != current_callback_ticket) { | 580 | while (callback_ticket != current_callback_ticket) { |
| 581 | callback_condition.wait(callback_mutex); | 581 | callback_condition.wait(callback_mutex); |
| 582 | } | 582 | } |
| @@ -597,7 +597,7 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input, | |||
| 597 | void BufferQueueProducer::CancelBuffer(s32 slot, const Fence& fence) { | 597 | void BufferQueueProducer::CancelBuffer(s32 slot, const Fence& fence) { |
| 598 | LOG_DEBUG(Service_NVFlinger, "slot {}", slot); | 598 | LOG_DEBUG(Service_NVFlinger, "slot {}", slot); |
| 599 | 599 | ||
| 600 | std::scoped_lock lock(core->mutex); | 600 | std::scoped_lock lock{core->mutex}; |
| 601 | 601 | ||
| 602 | if (core->is_abandoned) { | 602 | if (core->is_abandoned) { |
| 603 | LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); | 603 | LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); |
| @@ -623,7 +623,7 @@ void BufferQueueProducer::CancelBuffer(s32 slot, const Fence& fence) { | |||
| 623 | } | 623 | } |
| 624 | 624 | ||
| 625 | Status BufferQueueProducer::Query(NativeWindow what, s32* out_value) { | 625 | Status BufferQueueProducer::Query(NativeWindow what, s32* out_value) { |
| 626 | std::scoped_lock lock(core->mutex); | 626 | std::scoped_lock lock{core->mutex}; |
| 627 | 627 | ||
| 628 | if (out_value == nullptr) { | 628 | if (out_value == nullptr) { |
| 629 | LOG_ERROR(Service_NVFlinger, "outValue was nullptr"); | 629 | LOG_ERROR(Service_NVFlinger, "outValue was nullptr"); |
| @@ -673,7 +673,7 @@ Status BufferQueueProducer::Query(NativeWindow what, s32* out_value) { | |||
| 673 | Status BufferQueueProducer::Connect(const std::shared_ptr<IProducerListener>& listener, | 673 | Status BufferQueueProducer::Connect(const std::shared_ptr<IProducerListener>& listener, |
| 674 | NativeWindowApi api, bool producer_controlled_by_app, | 674 | NativeWindowApi api, bool producer_controlled_by_app, |
| 675 | QueueBufferOutput* output) { | 675 | QueueBufferOutput* output) { |
| 676 | std::scoped_lock lock(core->mutex); | 676 | std::scoped_lock lock{core->mutex}; |
| 677 | 677 | ||
| 678 | LOG_DEBUG(Service_NVFlinger, "api = {} producer_controlled_by_app = {}", api, | 678 | LOG_DEBUG(Service_NVFlinger, "api = {} producer_controlled_by_app = {}", api, |
| 679 | producer_controlled_by_app); | 679 | producer_controlled_by_app); |
| @@ -730,7 +730,7 @@ Status BufferQueueProducer::Disconnect(NativeWindowApi api) { | |||
| 730 | std::shared_ptr<IConsumerListener> listener; | 730 | std::shared_ptr<IConsumerListener> listener; |
| 731 | 731 | ||
| 732 | { | 732 | { |
| 733 | std::scoped_lock lock(core->mutex); | 733 | std::scoped_lock lock{core->mutex}; |
| 734 | 734 | ||
| 735 | core->WaitWhileAllocatingLocked(); | 735 | core->WaitWhileAllocatingLocked(); |
| 736 | 736 | ||
| @@ -780,7 +780,7 @@ Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot, | |||
| 780 | return Status::BadValue; | 780 | return Status::BadValue; |
| 781 | } | 781 | } |
| 782 | 782 | ||
| 783 | std::scoped_lock lock(core->mutex); | 783 | std::scoped_lock lock{core->mutex}; |
| 784 | 784 | ||
| 785 | slots[slot] = {}; | 785 | slots[slot] = {}; |
| 786 | slots[slot].graphic_buffer = buffer; | 786 | slots[slot].graphic_buffer = buffer; |
diff --git a/src/core/hle/service/nvflinger/consumer_base.cpp b/src/core/hle/service/nvflinger/consumer_base.cpp index c2c80832c..30fc21acc 100644 --- a/src/core/hle/service/nvflinger/consumer_base.cpp +++ b/src/core/hle/service/nvflinger/consumer_base.cpp | |||
| @@ -18,7 +18,7 @@ ConsumerBase::ConsumerBase(std::unique_ptr<BufferQueueConsumer> consumer_) | |||
| 18 | : consumer{std::move(consumer_)} {} | 18 | : consumer{std::move(consumer_)} {} |
| 19 | 19 | ||
| 20 | ConsumerBase::~ConsumerBase() { | 20 | ConsumerBase::~ConsumerBase() { |
| 21 | std::scoped_lock lock(mutex); | 21 | std::scoped_lock lock{mutex}; |
| 22 | 22 | ||
| 23 | ASSERT_MSG(is_abandoned, "consumer is not abandoned!"); | 23 | ASSERT_MSG(is_abandoned, "consumer is not abandoned!"); |
| 24 | } | 24 | } |
| @@ -44,7 +44,7 @@ void ConsumerBase::OnFrameReplaced(const BufferItem& item) { | |||
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | void ConsumerBase::OnBuffersReleased() { | 46 | void ConsumerBase::OnBuffersReleased() { |
| 47 | std::scoped_lock lock(mutex); | 47 | std::scoped_lock lock{mutex}; |
| 48 | 48 | ||
| 49 | LOG_DEBUG(Service_NVFlinger, "called"); | 49 | LOG_DEBUG(Service_NVFlinger, "called"); |
| 50 | 50 | ||
diff --git a/src/core/hle/service/nvflinger/graphic_buffer_producer.cpp b/src/core/hle/service/nvflinger/graphic_buffer_producer.cpp index d4da98ddb..04068827e 100644 --- a/src/core/hle/service/nvflinger/graphic_buffer_producer.cpp +++ b/src/core/hle/service/nvflinger/graphic_buffer_producer.cpp | |||
| @@ -4,8 +4,6 @@ | |||
| 4 | // Parts of this implementation were base on: | 4 | // Parts of this implementation were base on: |
| 5 | // https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/IGraphicBufferProducer.cpp | 5 | // https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/IGraphicBufferProducer.cpp |
| 6 | 6 | ||
| 7 | #pragma once | ||
| 8 | |||
| 9 | #include "core/hle/service/nvflinger/graphic_buffer_producer.h" | 7 | #include "core/hle/service/nvflinger/graphic_buffer_producer.h" |
| 10 | #include "core/hle/service/nvflinger/parcel.h" | 8 | #include "core/hle/service/nvflinger/parcel.h" |
| 11 | 9 | ||
diff --git a/src/core/hle/service/nvflinger/hos_binder_driver_server.cpp b/src/core/hle/service/nvflinger/hos_binder_driver_server.cpp index 0c937d682..094ba2542 100644 --- a/src/core/hle/service/nvflinger/hos_binder_driver_server.cpp +++ b/src/core/hle/service/nvflinger/hos_binder_driver_server.cpp | |||
| @@ -14,7 +14,7 @@ HosBinderDriverServer::HosBinderDriverServer(Core::System& system_) | |||
| 14 | HosBinderDriverServer::~HosBinderDriverServer() {} | 14 | HosBinderDriverServer::~HosBinderDriverServer() {} |
| 15 | 15 | ||
| 16 | u64 HosBinderDriverServer::RegisterProducer(std::unique_ptr<android::IBinder>&& binder) { | 16 | u64 HosBinderDriverServer::RegisterProducer(std::unique_ptr<android::IBinder>&& binder) { |
| 17 | std::lock_guard lk{lock}; | 17 | std::scoped_lock lk{lock}; |
| 18 | 18 | ||
| 19 | last_id++; | 19 | last_id++; |
| 20 | 20 | ||
| @@ -24,7 +24,7 @@ u64 HosBinderDriverServer::RegisterProducer(std::unique_ptr<android::IBinder>&& | |||
| 24 | } | 24 | } |
| 25 | 25 | ||
| 26 | android::IBinder* HosBinderDriverServer::TryGetProducer(u64 id) { | 26 | android::IBinder* HosBinderDriverServer::TryGetProducer(u64 id) { |
| 27 | std::lock_guard lk{lock}; | 27 | std::scoped_lock lk{lock}; |
| 28 | 28 | ||
| 29 | if (auto search = producers.find(id); search != producers.end()) { | 29 | if (auto search = producers.find(id); search != producers.end()) { |
| 30 | return search->second.get(); | 30 | return search->second.get(); |
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index ab3286db9..0f59a03c5 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include "core/hle/service/glue/glue.h" | 32 | #include "core/hle/service/glue/glue.h" |
| 33 | #include "core/hle/service/grc/grc.h" | 33 | #include "core/hle/service/grc/grc.h" |
| 34 | #include "core/hle/service/hid/hid.h" | 34 | #include "core/hle/service/hid/hid.h" |
| 35 | #include "core/hle/service/jit/jit.h" | ||
| 35 | #include "core/hle/service/lbl/lbl.h" | 36 | #include "core/hle/service/lbl/lbl.h" |
| 36 | #include "core/hle/service/ldn/ldn.h" | 37 | #include "core/hle/service/ldn/ldn.h" |
| 37 | #include "core/hle/service/ldr/ldr.h" | 38 | #include "core/hle/service/ldr/ldr.h" |
| @@ -91,8 +92,9 @@ namespace Service { | |||
| 91 | } | 92 | } |
| 92 | 93 | ||
| 93 | ServiceFrameworkBase::ServiceFrameworkBase(Core::System& system_, const char* service_name_, | 94 | ServiceFrameworkBase::ServiceFrameworkBase(Core::System& system_, const char* service_name_, |
| 94 | u32 max_sessions_, InvokerFn* handler_invoker_) | 95 | ServiceThreadType thread_type, u32 max_sessions_, |
| 95 | : SessionRequestHandler(system_.Kernel(), service_name_), system{system_}, | 96 | InvokerFn* handler_invoker_) |
| 97 | : SessionRequestHandler(system_.Kernel(), service_name_, thread_type), system{system_}, | ||
| 96 | service_name{service_name_}, max_sessions{max_sessions_}, handler_invoker{handler_invoker_} {} | 98 | service_name{service_name_}, max_sessions{max_sessions_}, handler_invoker{handler_invoker_} {} |
| 97 | 99 | ||
| 98 | ServiceFrameworkBase::~ServiceFrameworkBase() { | 100 | ServiceFrameworkBase::~ServiceFrameworkBase() { |
| @@ -261,6 +263,7 @@ Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system | |||
| 261 | Glue::InstallInterfaces(system); | 263 | Glue::InstallInterfaces(system); |
| 262 | GRC::InstallInterfaces(*sm, system); | 264 | GRC::InstallInterfaces(*sm, system); |
| 263 | HID::InstallInterfaces(*sm, system); | 265 | HID::InstallInterfaces(*sm, system); |
| 266 | JIT::InstallInterfaces(*sm, system); | ||
| 264 | LBL::InstallInterfaces(*sm, system); | 267 | LBL::InstallInterfaces(*sm, system); |
| 265 | LDN::InstallInterfaces(*sm, system); | 268 | LDN::InstallInterfaces(*sm, system); |
| 266 | LDR::InstallInterfaces(*sm, system); | 269 | LDR::InstallInterfaces(*sm, system); |
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index b9ab2c465..c78b2baeb 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h | |||
| @@ -114,7 +114,8 @@ private: | |||
| 114 | Kernel::HLERequestContext& ctx); | 114 | Kernel::HLERequestContext& ctx); |
| 115 | 115 | ||
| 116 | explicit ServiceFrameworkBase(Core::System& system_, const char* service_name_, | 116 | explicit ServiceFrameworkBase(Core::System& system_, const char* service_name_, |
| 117 | u32 max_sessions_, InvokerFn* handler_invoker_); | 117 | ServiceThreadType thread_type, u32 max_sessions_, |
| 118 | InvokerFn* handler_invoker_); | ||
| 118 | ~ServiceFrameworkBase() override; | 119 | ~ServiceFrameworkBase() override; |
| 119 | 120 | ||
| 120 | void RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n); | 121 | void RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n); |
| @@ -176,14 +177,17 @@ protected: | |||
| 176 | /** | 177 | /** |
| 177 | * Initializes the handler with no functions installed. | 178 | * Initializes the handler with no functions installed. |
| 178 | * | 179 | * |
| 179 | * @param system_ The system context to construct this service under. | 180 | * @param system_ The system context to construct this service under. |
| 180 | * @param service_name_ Name of the service. | 181 | * @param service_name_ Name of the service. |
| 181 | * @param max_sessions_ Maximum number of sessions that can be | 182 | * @param thread_type Specifies the thread type for this service. If this is set to CreateNew, |
| 182 | * connected to this service at the same time. | 183 | * it creates a new thread for it, otherwise this uses the default thread. |
| 184 | * @param max_sessions_ Maximum number of sessions that can be connected to this service at the | ||
| 185 | * same time. | ||
| 183 | */ | 186 | */ |
| 184 | explicit ServiceFramework(Core::System& system_, const char* service_name_, | 187 | explicit ServiceFramework(Core::System& system_, const char* service_name_, |
| 188 | ServiceThreadType thread_type = ServiceThreadType::Default, | ||
| 185 | u32 max_sessions_ = ServerSessionCountMax) | 189 | u32 max_sessions_ = ServerSessionCountMax) |
| 186 | : ServiceFrameworkBase(system_, service_name_, max_sessions_, Invoker) {} | 190 | : ServiceFrameworkBase(system_, service_name_, thread_type, max_sessions_, Invoker) {} |
| 187 | 191 | ||
| 188 | /// Registers handlers in the service. | 192 | /// Registers handlers in the service. |
| 189 | template <std::size_t N> | 193 | template <std::size_t N> |
diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp index 695a1faa6..97f895852 100644 --- a/src/core/hle/service/sm/sm.cpp +++ b/src/core/hle/service/sm/sm.cpp | |||
| @@ -206,7 +206,7 @@ void SM::UnregisterService(Kernel::HLERequestContext& ctx) { | |||
| 206 | } | 206 | } |
| 207 | 207 | ||
| 208 | SM::SM(ServiceManager& service_manager_, Core::System& system_) | 208 | SM::SM(ServiceManager& service_manager_, Core::System& system_) |
| 209 | : ServiceFramework{system_, "sm:", 4}, | 209 | : ServiceFramework{system_, "sm:", ServiceThreadType::Default, 4}, |
| 210 | service_manager{service_manager_}, kernel{system_.Kernel()} { | 210 | service_manager{service_manager_}, kernel{system_.Kernel()} { |
| 211 | RegisterHandlers({ | 211 | RegisterHandlers({ |
| 212 | {0, &SM::Initialize, "Initialize"}, | 212 | {0, &SM::Initialize, "Initialize"}, |
diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp index e5631c27e..d25b050e2 100644 --- a/src/core/hle/service/sockets/bsd.cpp +++ b/src/core/hle/service/sockets/bsd.cpp | |||
| @@ -840,7 +840,8 @@ void BSD::BuildErrnoResponse(Kernel::HLERequestContext& ctx, Errno bsd_errno) co | |||
| 840 | rb.PushEnum(bsd_errno); | 840 | rb.PushEnum(bsd_errno); |
| 841 | } | 841 | } |
| 842 | 842 | ||
| 843 | BSD::BSD(Core::System& system_, const char* name) : ServiceFramework{system_, name} { | 843 | BSD::BSD(Core::System& system_, const char* name) |
| 844 | : ServiceFramework{system_, name, ServiceThreadType::CreateNew} { | ||
| 844 | // clang-format off | 845 | // clang-format off |
| 845 | static const FunctionInfo functions[] = { | 846 | static const FunctionInfo functions[] = { |
| 846 | {0, &BSD::RegisterClient, "RegisterClient"}, | 847 | {0, &BSD::RegisterClient, "RegisterClient"}, |
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 430cbc546..a3436c8ea 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp | |||
| @@ -77,7 +77,8 @@ static_assert(sizeof(NativeWindow) == 0x28, "NativeWindow has wrong size"); | |||
| 77 | class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> { | 77 | class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> { |
| 78 | public: | 78 | public: |
| 79 | explicit IHOSBinderDriver(Core::System& system_, NVFlinger::HosBinderDriverServer& server_) | 79 | explicit IHOSBinderDriver(Core::System& system_, NVFlinger::HosBinderDriverServer& server_) |
| 80 | : ServiceFramework{system_, "IHOSBinderDriver"}, server(server_) { | 80 | : ServiceFramework{system_, "IHOSBinderDriver", ServiceThreadType::CreateNew}, |
| 81 | server(server_) { | ||
| 81 | static const FunctionInfo functions[] = { | 82 | static const FunctionInfo functions[] = { |
| 82 | {0, &IHOSBinderDriver::TransactParcel, "TransactParcel"}, | 83 | {0, &IHOSBinderDriver::TransactParcel, "TransactParcel"}, |
| 83 | {1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"}, | 84 | {1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"}, |
diff --git a/src/core/perf_stats.cpp b/src/core/perf_stats.cpp index 52c43c857..6ef459b7a 100644 --- a/src/core/perf_stats.cpp +++ b/src/core/perf_stats.cpp | |||
| @@ -53,13 +53,13 @@ PerfStats::~PerfStats() { | |||
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | void PerfStats::BeginSystemFrame() { | 55 | void PerfStats::BeginSystemFrame() { |
| 56 | std::lock_guard lock{object_mutex}; | 56 | std::scoped_lock lock{object_mutex}; |
| 57 | 57 | ||
| 58 | frame_begin = Clock::now(); | 58 | frame_begin = Clock::now(); |
| 59 | } | 59 | } |
| 60 | 60 | ||
| 61 | void PerfStats::EndSystemFrame() { | 61 | void PerfStats::EndSystemFrame() { |
| 62 | std::lock_guard lock{object_mutex}; | 62 | std::scoped_lock lock{object_mutex}; |
| 63 | 63 | ||
| 64 | auto frame_end = Clock::now(); | 64 | auto frame_end = Clock::now(); |
| 65 | const auto frame_time = frame_end - frame_begin; | 65 | const auto frame_time = frame_end - frame_begin; |
| @@ -79,7 +79,7 @@ void PerfStats::EndGameFrame() { | |||
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | double PerfStats::GetMeanFrametime() const { | 81 | double PerfStats::GetMeanFrametime() const { |
| 82 | std::lock_guard lock{object_mutex}; | 82 | std::scoped_lock lock{object_mutex}; |
| 83 | 83 | ||
| 84 | if (current_index <= IgnoreFrames) { | 84 | if (current_index <= IgnoreFrames) { |
| 85 | return 0; | 85 | return 0; |
| @@ -91,7 +91,7 @@ double PerfStats::GetMeanFrametime() const { | |||
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | PerfStatsResults PerfStats::GetAndResetStats(microseconds current_system_time_us) { | 93 | PerfStatsResults PerfStats::GetAndResetStats(microseconds current_system_time_us) { |
| 94 | std::lock_guard lock{object_mutex}; | 94 | std::scoped_lock lock{object_mutex}; |
| 95 | 95 | ||
| 96 | const auto now = Clock::now(); | 96 | const auto now = Clock::now(); |
| 97 | // Walltime elapsed since stats were reset | 97 | // Walltime elapsed since stats were reset |
| @@ -120,7 +120,7 @@ PerfStatsResults PerfStats::GetAndResetStats(microseconds current_system_time_us | |||
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | double PerfStats::GetLastFrameTimeScale() const { | 122 | double PerfStats::GetLastFrameTimeScale() const { |
| 123 | std::lock_guard lock{object_mutex}; | 123 | std::scoped_lock lock{object_mutex}; |
| 124 | 124 | ||
| 125 | constexpr double FRAME_LENGTH = 1.0 / 60; | 125 | constexpr double FRAME_LENGTH = 1.0 / 60; |
| 126 | return duration_cast<DoubleSecs>(previous_frame_length).count() / FRAME_LENGTH; | 126 | return duration_cast<DoubleSecs>(previous_frame_length).count() / FRAME_LENGTH; |
diff --git a/src/core/tools/freezer.cpp b/src/core/tools/freezer.cpp index 032c71aff..c81dc0e52 100644 --- a/src/core/tools/freezer.cpp +++ b/src/core/tools/freezer.cpp | |||
| @@ -80,7 +80,7 @@ bool Freezer::IsActive() const { | |||
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | void Freezer::Clear() { | 82 | void Freezer::Clear() { |
| 83 | std::lock_guard lock{entries_mutex}; | 83 | std::scoped_lock lock{entries_mutex}; |
| 84 | 84 | ||
| 85 | LOG_DEBUG(Common_Memory, "Clearing all frozen memory values."); | 85 | LOG_DEBUG(Common_Memory, "Clearing all frozen memory values."); |
| 86 | 86 | ||
| @@ -88,7 +88,7 @@ void Freezer::Clear() { | |||
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | u64 Freezer::Freeze(VAddr address, u32 width) { | 90 | u64 Freezer::Freeze(VAddr address, u32 width) { |
| 91 | std::lock_guard lock{entries_mutex}; | 91 | std::scoped_lock lock{entries_mutex}; |
| 92 | 92 | ||
| 93 | const auto current_value = MemoryReadWidth(memory, width, address); | 93 | const auto current_value = MemoryReadWidth(memory, width, address); |
| 94 | entries.push_back({address, width, current_value}); | 94 | entries.push_back({address, width, current_value}); |
| @@ -101,7 +101,7 @@ u64 Freezer::Freeze(VAddr address, u32 width) { | |||
| 101 | } | 101 | } |
| 102 | 102 | ||
| 103 | void Freezer::Unfreeze(VAddr address) { | 103 | void Freezer::Unfreeze(VAddr address) { |
| 104 | std::lock_guard lock{entries_mutex}; | 104 | std::scoped_lock lock{entries_mutex}; |
| 105 | 105 | ||
| 106 | LOG_DEBUG(Common_Memory, "Unfreezing memory for address={:016X}", address); | 106 | LOG_DEBUG(Common_Memory, "Unfreezing memory for address={:016X}", address); |
| 107 | 107 | ||
| @@ -109,13 +109,13 @@ void Freezer::Unfreeze(VAddr address) { | |||
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | bool Freezer::IsFrozen(VAddr address) const { | 111 | bool Freezer::IsFrozen(VAddr address) const { |
| 112 | std::lock_guard lock{entries_mutex}; | 112 | std::scoped_lock lock{entries_mutex}; |
| 113 | 113 | ||
| 114 | return FindEntry(address) != entries.cend(); | 114 | return FindEntry(address) != entries.cend(); |
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | void Freezer::SetFrozenValue(VAddr address, u64 value) { | 117 | void Freezer::SetFrozenValue(VAddr address, u64 value) { |
| 118 | std::lock_guard lock{entries_mutex}; | 118 | std::scoped_lock lock{entries_mutex}; |
| 119 | 119 | ||
| 120 | const auto iter = FindEntry(address); | 120 | const auto iter = FindEntry(address); |
| 121 | 121 | ||
| @@ -132,7 +132,7 @@ void Freezer::SetFrozenValue(VAddr address, u64 value) { | |||
| 132 | } | 132 | } |
| 133 | 133 | ||
| 134 | std::optional<Freezer::Entry> Freezer::GetEntry(VAddr address) const { | 134 | std::optional<Freezer::Entry> Freezer::GetEntry(VAddr address) const { |
| 135 | std::lock_guard lock{entries_mutex}; | 135 | std::scoped_lock lock{entries_mutex}; |
| 136 | 136 | ||
| 137 | const auto iter = FindEntry(address); | 137 | const auto iter = FindEntry(address); |
| 138 | 138 | ||
| @@ -144,7 +144,7 @@ std::optional<Freezer::Entry> Freezer::GetEntry(VAddr address) const { | |||
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | std::vector<Freezer::Entry> Freezer::GetEntries() const { | 146 | std::vector<Freezer::Entry> Freezer::GetEntries() const { |
| 147 | std::lock_guard lock{entries_mutex}; | 147 | std::scoped_lock lock{entries_mutex}; |
| 148 | 148 | ||
| 149 | return entries; | 149 | return entries; |
| 150 | } | 150 | } |
| @@ -165,7 +165,7 @@ void Freezer::FrameCallback(std::uintptr_t, std::chrono::nanoseconds ns_late) { | |||
| 165 | return; | 165 | return; |
| 166 | } | 166 | } |
| 167 | 167 | ||
| 168 | std::lock_guard lock{entries_mutex}; | 168 | std::scoped_lock lock{entries_mutex}; |
| 169 | 169 | ||
| 170 | for (const auto& entry : entries) { | 170 | for (const auto& entry : entries) { |
| 171 | LOG_DEBUG(Common_Memory, | 171 | LOG_DEBUG(Common_Memory, |
| @@ -178,7 +178,7 @@ void Freezer::FrameCallback(std::uintptr_t, std::chrono::nanoseconds ns_late) { | |||
| 178 | } | 178 | } |
| 179 | 179 | ||
| 180 | void Freezer::FillEntryReads() { | 180 | void Freezer::FillEntryReads() { |
| 181 | std::lock_guard lock{entries_mutex}; | 181 | std::scoped_lock lock{entries_mutex}; |
| 182 | 182 | ||
| 183 | LOG_DEBUG(Common_Memory, "Updating memory freeze entries to current values."); | 183 | LOG_DEBUG(Common_Memory, "Updating memory freeze entries to current values."); |
| 184 | 184 | ||
diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp index c17ea305e..b3e4c3f64 100644 --- a/src/input_common/drivers/sdl_driver.cpp +++ b/src/input_common/drivers/sdl_driver.cpp | |||
| @@ -62,7 +62,7 @@ public: | |||
| 62 | 62 | ||
| 63 | bool UpdateMotion(SDL_ControllerSensorEvent event) { | 63 | bool UpdateMotion(SDL_ControllerSensorEvent event) { |
| 64 | constexpr float gravity_constant = 9.80665f; | 64 | constexpr float gravity_constant = 9.80665f; |
| 65 | std::lock_guard lock{mutex}; | 65 | std::scoped_lock lock{mutex}; |
| 66 | const u64 time_difference = event.timestamp - last_motion_update; | 66 | const u64 time_difference = event.timestamp - last_motion_update; |
| 67 | last_motion_update = event.timestamp; | 67 | last_motion_update = event.timestamp; |
| 68 | switch (event.sensor) { | 68 | switch (event.sensor) { |
| @@ -241,7 +241,7 @@ private: | |||
| 241 | }; | 241 | }; |
| 242 | 242 | ||
| 243 | std::shared_ptr<SDLJoystick> SDLDriver::GetSDLJoystickByGUID(const std::string& guid, int port) { | 243 | std::shared_ptr<SDLJoystick> SDLDriver::GetSDLJoystickByGUID(const std::string& guid, int port) { |
| 244 | std::lock_guard lock{joystick_map_mutex}; | 244 | std::scoped_lock lock{joystick_map_mutex}; |
| 245 | const auto it = joystick_map.find(guid); | 245 | const auto it = joystick_map.find(guid); |
| 246 | 246 | ||
| 247 | if (it != joystick_map.end()) { | 247 | if (it != joystick_map.end()) { |
| @@ -263,7 +263,7 @@ std::shared_ptr<SDLJoystick> SDLDriver::GetSDLJoystickBySDLID(SDL_JoystickID sdl | |||
| 263 | auto sdl_joystick = SDL_JoystickFromInstanceID(sdl_id); | 263 | auto sdl_joystick = SDL_JoystickFromInstanceID(sdl_id); |
| 264 | const std::string guid = GetGUID(sdl_joystick); | 264 | const std::string guid = GetGUID(sdl_joystick); |
| 265 | 265 | ||
| 266 | std::lock_guard lock{joystick_map_mutex}; | 266 | std::scoped_lock lock{joystick_map_mutex}; |
| 267 | const auto map_it = joystick_map.find(guid); | 267 | const auto map_it = joystick_map.find(guid); |
| 268 | 268 | ||
| 269 | if (map_it == joystick_map.end()) { | 269 | if (map_it == joystick_map.end()) { |
| @@ -297,7 +297,7 @@ void SDLDriver::InitJoystick(int joystick_index) { | |||
| 297 | 297 | ||
| 298 | const std::string guid = GetGUID(sdl_joystick); | 298 | const std::string guid = GetGUID(sdl_joystick); |
| 299 | 299 | ||
| 300 | std::lock_guard lock{joystick_map_mutex}; | 300 | std::scoped_lock lock{joystick_map_mutex}; |
| 301 | if (joystick_map.find(guid) == joystick_map.end()) { | 301 | if (joystick_map.find(guid) == joystick_map.end()) { |
| 302 | auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick, sdl_gamecontroller); | 302 | auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick, sdl_gamecontroller); |
| 303 | PreSetController(joystick->GetPadIdentifier()); | 303 | PreSetController(joystick->GetPadIdentifier()); |
| @@ -326,7 +326,7 @@ void SDLDriver::InitJoystick(int joystick_index) { | |||
| 326 | void SDLDriver::CloseJoystick(SDL_Joystick* sdl_joystick) { | 326 | void SDLDriver::CloseJoystick(SDL_Joystick* sdl_joystick) { |
| 327 | const std::string guid = GetGUID(sdl_joystick); | 327 | const std::string guid = GetGUID(sdl_joystick); |
| 328 | 328 | ||
| 329 | std::lock_guard lock{joystick_map_mutex}; | 329 | std::scoped_lock lock{joystick_map_mutex}; |
| 330 | // This call to guid is safe since the joystick is guaranteed to be in the map | 330 | // This call to guid is safe since the joystick is guaranteed to be in the map |
| 331 | const auto& joystick_guid_list = joystick_map[guid]; | 331 | const auto& joystick_guid_list = joystick_map[guid]; |
| 332 | const auto joystick_it = std::find_if(joystick_guid_list.begin(), joystick_guid_list.end(), | 332 | const auto joystick_it = std::find_if(joystick_guid_list.begin(), joystick_guid_list.end(), |
| @@ -392,7 +392,7 @@ void SDLDriver::HandleGameControllerEvent(const SDL_Event& event) { | |||
| 392 | } | 392 | } |
| 393 | 393 | ||
| 394 | void SDLDriver::CloseJoysticks() { | 394 | void SDLDriver::CloseJoysticks() { |
| 395 | std::lock_guard lock{joystick_map_mutex}; | 395 | std::scoped_lock lock{joystick_map_mutex}; |
| 396 | joystick_map.clear(); | 396 | joystick_map.clear(); |
| 397 | } | 397 | } |
| 398 | 398 | ||
diff --git a/src/input_common/input_engine.cpp b/src/input_common/input_engine.cpp index 738022ece..a16cca33d 100644 --- a/src/input_common/input_engine.cpp +++ b/src/input_common/input_engine.cpp | |||
| @@ -8,37 +8,37 @@ | |||
| 8 | namespace InputCommon { | 8 | namespace InputCommon { |
| 9 | 9 | ||
| 10 | void InputEngine::PreSetController(const PadIdentifier& identifier) { | 10 | void InputEngine::PreSetController(const PadIdentifier& identifier) { |
| 11 | std::lock_guard lock{mutex}; | 11 | std::scoped_lock lock{mutex}; |
| 12 | controller_list.try_emplace(identifier); | 12 | controller_list.try_emplace(identifier); |
| 13 | } | 13 | } |
| 14 | 14 | ||
| 15 | void InputEngine::PreSetButton(const PadIdentifier& identifier, int button) { | 15 | void InputEngine::PreSetButton(const PadIdentifier& identifier, int button) { |
| 16 | std::lock_guard lock{mutex}; | 16 | std::scoped_lock lock{mutex}; |
| 17 | ControllerData& controller = controller_list.at(identifier); | 17 | ControllerData& controller = controller_list.at(identifier); |
| 18 | controller.buttons.try_emplace(button, false); | 18 | controller.buttons.try_emplace(button, false); |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | void InputEngine::PreSetHatButton(const PadIdentifier& identifier, int button) { | 21 | void InputEngine::PreSetHatButton(const PadIdentifier& identifier, int button) { |
| 22 | std::lock_guard lock{mutex}; | 22 | std::scoped_lock lock{mutex}; |
| 23 | ControllerData& controller = controller_list.at(identifier); | 23 | ControllerData& controller = controller_list.at(identifier); |
| 24 | controller.hat_buttons.try_emplace(button, u8{0}); | 24 | controller.hat_buttons.try_emplace(button, u8{0}); |
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | void InputEngine::PreSetAxis(const PadIdentifier& identifier, int axis) { | 27 | void InputEngine::PreSetAxis(const PadIdentifier& identifier, int axis) { |
| 28 | std::lock_guard lock{mutex}; | 28 | std::scoped_lock lock{mutex}; |
| 29 | ControllerData& controller = controller_list.at(identifier); | 29 | ControllerData& controller = controller_list.at(identifier); |
| 30 | controller.axes.try_emplace(axis, 0.0f); | 30 | controller.axes.try_emplace(axis, 0.0f); |
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | void InputEngine::PreSetMotion(const PadIdentifier& identifier, int motion) { | 33 | void InputEngine::PreSetMotion(const PadIdentifier& identifier, int motion) { |
| 34 | std::lock_guard lock{mutex}; | 34 | std::scoped_lock lock{mutex}; |
| 35 | ControllerData& controller = controller_list.at(identifier); | 35 | ControllerData& controller = controller_list.at(identifier); |
| 36 | controller.motions.try_emplace(motion); | 36 | controller.motions.try_emplace(motion); |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | void InputEngine::SetButton(const PadIdentifier& identifier, int button, bool value) { | 39 | void InputEngine::SetButton(const PadIdentifier& identifier, int button, bool value) { |
| 40 | { | 40 | { |
| 41 | std::lock_guard lock{mutex}; | 41 | std::scoped_lock lock{mutex}; |
| 42 | ControllerData& controller = controller_list.at(identifier); | 42 | ControllerData& controller = controller_list.at(identifier); |
| 43 | if (!configuring) { | 43 | if (!configuring) { |
| 44 | controller.buttons.insert_or_assign(button, value); | 44 | controller.buttons.insert_or_assign(button, value); |
| @@ -49,7 +49,7 @@ void InputEngine::SetButton(const PadIdentifier& identifier, int button, bool va | |||
| 49 | 49 | ||
| 50 | void InputEngine::SetHatButton(const PadIdentifier& identifier, int button, u8 value) { | 50 | void InputEngine::SetHatButton(const PadIdentifier& identifier, int button, u8 value) { |
| 51 | { | 51 | { |
| 52 | std::lock_guard lock{mutex}; | 52 | std::scoped_lock lock{mutex}; |
| 53 | ControllerData& controller = controller_list.at(identifier); | 53 | ControllerData& controller = controller_list.at(identifier); |
| 54 | if (!configuring) { | 54 | if (!configuring) { |
| 55 | controller.hat_buttons.insert_or_assign(button, value); | 55 | controller.hat_buttons.insert_or_assign(button, value); |
| @@ -60,7 +60,7 @@ void InputEngine::SetHatButton(const PadIdentifier& identifier, int button, u8 v | |||
| 60 | 60 | ||
| 61 | void InputEngine::SetAxis(const PadIdentifier& identifier, int axis, f32 value) { | 61 | void InputEngine::SetAxis(const PadIdentifier& identifier, int axis, f32 value) { |
| 62 | { | 62 | { |
| 63 | std::lock_guard lock{mutex}; | 63 | std::scoped_lock lock{mutex}; |
| 64 | ControllerData& controller = controller_list.at(identifier); | 64 | ControllerData& controller = controller_list.at(identifier); |
| 65 | if (!configuring) { | 65 | if (!configuring) { |
| 66 | controller.axes.insert_or_assign(axis, value); | 66 | controller.axes.insert_or_assign(axis, value); |
| @@ -71,7 +71,7 @@ void InputEngine::SetAxis(const PadIdentifier& identifier, int axis, f32 value) | |||
| 71 | 71 | ||
| 72 | void InputEngine::SetBattery(const PadIdentifier& identifier, Common::Input::BatteryLevel value) { | 72 | void InputEngine::SetBattery(const PadIdentifier& identifier, Common::Input::BatteryLevel value) { |
| 73 | { | 73 | { |
| 74 | std::lock_guard lock{mutex}; | 74 | std::scoped_lock lock{mutex}; |
| 75 | ControllerData& controller = controller_list.at(identifier); | 75 | ControllerData& controller = controller_list.at(identifier); |
| 76 | if (!configuring) { | 76 | if (!configuring) { |
| 77 | controller.battery = value; | 77 | controller.battery = value; |
| @@ -82,7 +82,7 @@ void InputEngine::SetBattery(const PadIdentifier& identifier, Common::Input::Bat | |||
| 82 | 82 | ||
| 83 | void InputEngine::SetMotion(const PadIdentifier& identifier, int motion, const BasicMotion& value) { | 83 | void InputEngine::SetMotion(const PadIdentifier& identifier, int motion, const BasicMotion& value) { |
| 84 | { | 84 | { |
| 85 | std::lock_guard lock{mutex}; | 85 | std::scoped_lock lock{mutex}; |
| 86 | ControllerData& controller = controller_list.at(identifier); | 86 | ControllerData& controller = controller_list.at(identifier); |
| 87 | if (!configuring) { | 87 | if (!configuring) { |
| 88 | controller.motions.insert_or_assign(motion, value); | 88 | controller.motions.insert_or_assign(motion, value); |
| @@ -92,7 +92,7 @@ void InputEngine::SetMotion(const PadIdentifier& identifier, int motion, const B | |||
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | bool InputEngine::GetButton(const PadIdentifier& identifier, int button) const { | 94 | bool InputEngine::GetButton(const PadIdentifier& identifier, int button) const { |
| 95 | std::lock_guard lock{mutex}; | 95 | std::scoped_lock lock{mutex}; |
| 96 | const auto controller_iter = controller_list.find(identifier); | 96 | const auto controller_iter = controller_list.find(identifier); |
| 97 | if (controller_iter == controller_list.cend()) { | 97 | if (controller_iter == controller_list.cend()) { |
| 98 | LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(), | 98 | LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(), |
| @@ -109,7 +109,7 @@ bool InputEngine::GetButton(const PadIdentifier& identifier, int button) const { | |||
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | bool InputEngine::GetHatButton(const PadIdentifier& identifier, int button, u8 direction) const { | 111 | bool InputEngine::GetHatButton(const PadIdentifier& identifier, int button, u8 direction) const { |
| 112 | std::lock_guard lock{mutex}; | 112 | std::scoped_lock lock{mutex}; |
| 113 | const auto controller_iter = controller_list.find(identifier); | 113 | const auto controller_iter = controller_list.find(identifier); |
| 114 | if (controller_iter == controller_list.cend()) { | 114 | if (controller_iter == controller_list.cend()) { |
| 115 | LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(), | 115 | LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(), |
| @@ -126,7 +126,7 @@ bool InputEngine::GetHatButton(const PadIdentifier& identifier, int button, u8 d | |||
| 126 | } | 126 | } |
| 127 | 127 | ||
| 128 | f32 InputEngine::GetAxis(const PadIdentifier& identifier, int axis) const { | 128 | f32 InputEngine::GetAxis(const PadIdentifier& identifier, int axis) const { |
| 129 | std::lock_guard lock{mutex}; | 129 | std::scoped_lock lock{mutex}; |
| 130 | const auto controller_iter = controller_list.find(identifier); | 130 | const auto controller_iter = controller_list.find(identifier); |
| 131 | if (controller_iter == controller_list.cend()) { | 131 | if (controller_iter == controller_list.cend()) { |
| 132 | LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(), | 132 | LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(), |
| @@ -143,7 +143,7 @@ f32 InputEngine::GetAxis(const PadIdentifier& identifier, int axis) const { | |||
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | Common::Input::BatteryLevel InputEngine::GetBattery(const PadIdentifier& identifier) const { | 145 | Common::Input::BatteryLevel InputEngine::GetBattery(const PadIdentifier& identifier) const { |
| 146 | std::lock_guard lock{mutex}; | 146 | std::scoped_lock lock{mutex}; |
| 147 | const auto controller_iter = controller_list.find(identifier); | 147 | const auto controller_iter = controller_list.find(identifier); |
| 148 | if (controller_iter == controller_list.cend()) { | 148 | if (controller_iter == controller_list.cend()) { |
| 149 | LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(), | 149 | LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(), |
| @@ -155,7 +155,7 @@ Common::Input::BatteryLevel InputEngine::GetBattery(const PadIdentifier& identif | |||
| 155 | } | 155 | } |
| 156 | 156 | ||
| 157 | BasicMotion InputEngine::GetMotion(const PadIdentifier& identifier, int motion) const { | 157 | BasicMotion InputEngine::GetMotion(const PadIdentifier& identifier, int motion) const { |
| 158 | std::lock_guard lock{mutex}; | 158 | std::scoped_lock lock{mutex}; |
| 159 | const auto controller_iter = controller_list.find(identifier); | 159 | const auto controller_iter = controller_list.find(identifier); |
| 160 | if (controller_iter == controller_list.cend()) { | 160 | if (controller_iter == controller_list.cend()) { |
| 161 | LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(), | 161 | LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(), |
| @@ -186,7 +186,7 @@ void InputEngine::ResetAnalogState() { | |||
| 186 | } | 186 | } |
| 187 | 187 | ||
| 188 | void InputEngine::TriggerOnButtonChange(const PadIdentifier& identifier, int button, bool value) { | 188 | void InputEngine::TriggerOnButtonChange(const PadIdentifier& identifier, int button, bool value) { |
| 189 | std::lock_guard lock{mutex_callback}; | 189 | std::scoped_lock lock{mutex_callback}; |
| 190 | for (const auto& poller_pair : callback_list) { | 190 | for (const auto& poller_pair : callback_list) { |
| 191 | const InputIdentifier& poller = poller_pair.second; | 191 | const InputIdentifier& poller = poller_pair.second; |
| 192 | if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Button, button)) { | 192 | if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Button, button)) { |
| @@ -214,7 +214,7 @@ void InputEngine::TriggerOnButtonChange(const PadIdentifier& identifier, int but | |||
| 214 | } | 214 | } |
| 215 | 215 | ||
| 216 | void InputEngine::TriggerOnHatButtonChange(const PadIdentifier& identifier, int button, u8 value) { | 216 | void InputEngine::TriggerOnHatButtonChange(const PadIdentifier& identifier, int button, u8 value) { |
| 217 | std::lock_guard lock{mutex_callback}; | 217 | std::scoped_lock lock{mutex_callback}; |
| 218 | for (const auto& poller_pair : callback_list) { | 218 | for (const auto& poller_pair : callback_list) { |
| 219 | const InputIdentifier& poller = poller_pair.second; | 219 | const InputIdentifier& poller = poller_pair.second; |
| 220 | if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::HatButton, button)) { | 220 | if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::HatButton, button)) { |
| @@ -243,7 +243,7 @@ void InputEngine::TriggerOnHatButtonChange(const PadIdentifier& identifier, int | |||
| 243 | } | 243 | } |
| 244 | 244 | ||
| 245 | void InputEngine::TriggerOnAxisChange(const PadIdentifier& identifier, int axis, f32 value) { | 245 | void InputEngine::TriggerOnAxisChange(const PadIdentifier& identifier, int axis, f32 value) { |
| 246 | std::lock_guard lock{mutex_callback}; | 246 | std::scoped_lock lock{mutex_callback}; |
| 247 | for (const auto& poller_pair : callback_list) { | 247 | for (const auto& poller_pair : callback_list) { |
| 248 | const InputIdentifier& poller = poller_pair.second; | 248 | const InputIdentifier& poller = poller_pair.second; |
| 249 | if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Analog, axis)) { | 249 | if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Analog, axis)) { |
| @@ -270,7 +270,7 @@ void InputEngine::TriggerOnAxisChange(const PadIdentifier& identifier, int axis, | |||
| 270 | 270 | ||
| 271 | void InputEngine::TriggerOnBatteryChange(const PadIdentifier& identifier, | 271 | void InputEngine::TriggerOnBatteryChange(const PadIdentifier& identifier, |
| 272 | [[maybe_unused]] Common::Input::BatteryLevel value) { | 272 | [[maybe_unused]] Common::Input::BatteryLevel value) { |
| 273 | std::lock_guard lock{mutex_callback}; | 273 | std::scoped_lock lock{mutex_callback}; |
| 274 | for (const auto& poller_pair : callback_list) { | 274 | for (const auto& poller_pair : callback_list) { |
| 275 | const InputIdentifier& poller = poller_pair.second; | 275 | const InputIdentifier& poller = poller_pair.second; |
| 276 | if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Battery, 0)) { | 276 | if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Battery, 0)) { |
| @@ -284,7 +284,7 @@ void InputEngine::TriggerOnBatteryChange(const PadIdentifier& identifier, | |||
| 284 | 284 | ||
| 285 | void InputEngine::TriggerOnMotionChange(const PadIdentifier& identifier, int motion, | 285 | void InputEngine::TriggerOnMotionChange(const PadIdentifier& identifier, int motion, |
| 286 | const BasicMotion& value) { | 286 | const BasicMotion& value) { |
| 287 | std::lock_guard lock{mutex_callback}; | 287 | std::scoped_lock lock{mutex_callback}; |
| 288 | for (const auto& poller_pair : callback_list) { | 288 | for (const auto& poller_pair : callback_list) { |
| 289 | const InputIdentifier& poller = poller_pair.second; | 289 | const InputIdentifier& poller = poller_pair.second; |
| 290 | if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Motion, motion)) { | 290 | if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Motion, motion)) { |
| @@ -346,18 +346,18 @@ const std::string& InputEngine::GetEngineName() const { | |||
| 346 | } | 346 | } |
| 347 | 347 | ||
| 348 | int InputEngine::SetCallback(InputIdentifier input_identifier) { | 348 | int InputEngine::SetCallback(InputIdentifier input_identifier) { |
| 349 | std::lock_guard lock{mutex_callback}; | 349 | std::scoped_lock lock{mutex_callback}; |
| 350 | callback_list.insert_or_assign(last_callback_key, std::move(input_identifier)); | 350 | callback_list.insert_or_assign(last_callback_key, std::move(input_identifier)); |
| 351 | return last_callback_key++; | 351 | return last_callback_key++; |
| 352 | } | 352 | } |
| 353 | 353 | ||
| 354 | void InputEngine::SetMappingCallback(MappingCallback callback) { | 354 | void InputEngine::SetMappingCallback(MappingCallback callback) { |
| 355 | std::lock_guard lock{mutex_callback}; | 355 | std::scoped_lock lock{mutex_callback}; |
| 356 | mapping_callback = std::move(callback); | 356 | mapping_callback = std::move(callback); |
| 357 | } | 357 | } |
| 358 | 358 | ||
| 359 | void InputEngine::DeleteCallback(int key) { | 359 | void InputEngine::DeleteCallback(int key) { |
| 360 | std::lock_guard lock{mutex_callback}; | 360 | std::scoped_lock lock{mutex_callback}; |
| 361 | const auto& iterator = callback_list.find(key); | 361 | const auto& iterator = callback_list.find(key); |
| 362 | if (iterator == callback_list.end()) { | 362 | if (iterator == callback_list.end()) { |
| 363 | LOG_ERROR(Input, "Tried to delete non-existent callback {}", key); | 363 | LOG_ERROR(Input, "Tried to delete non-existent callback {}", key); |
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 0c1fbc7b1..282668b36 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 | |||
| @@ -35,6 +35,15 @@ std::string_view OutputVertexIndex(EmitContext& ctx) { | |||
| 35 | return ctx.stage == Stage::TessellationControl ? "[gl_InvocationID]" : ""; | 35 | return ctx.stage == Stage::TessellationControl ? "[gl_InvocationID]" : ""; |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | std::string ChooseCbuf(EmitContext& ctx, const IR::Value& binding, std::string_view index) { | ||
| 39 | if (binding.IsImmediate()) { | ||
| 40 | return fmt::format("{}_cbuf{}[{}]", ctx.stage_name, binding.U32(), index); | ||
| 41 | } else { | ||
| 42 | const auto binding_var{ctx.var_alloc.Consume(binding)}; | ||
| 43 | return fmt::format("GetCbufIndirect({},{})", binding_var, index); | ||
| 44 | } | ||
| 45 | } | ||
| 46 | |||
| 38 | void GetCbuf(EmitContext& ctx, std::string_view ret, const IR::Value& binding, | 47 | void GetCbuf(EmitContext& ctx, std::string_view ret, const IR::Value& binding, |
| 39 | const IR::Value& offset, u32 num_bits, std::string_view cast = {}, | 48 | const IR::Value& offset, u32 num_bits, std::string_view cast = {}, |
| 40 | std::string_view bit_offset = {}) { | 49 | std::string_view bit_offset = {}) { |
| @@ -55,8 +64,8 @@ void GetCbuf(EmitContext& ctx, std::string_view ret, const IR::Value& binding, | |||
| 55 | const auto swizzle{is_immediate ? fmt::format(".{}", OffsetSwizzle(offset.U32())) | 64 | const auto swizzle{is_immediate ? fmt::format(".{}", OffsetSwizzle(offset.U32())) |
| 56 | : fmt::format("[({}>>2)%4]", offset_var)}; | 65 | : fmt::format("[({}>>2)%4]", offset_var)}; |
| 57 | 66 | ||
| 58 | const auto cbuf{fmt::format("{}_cbuf{}", ctx.stage_name, binding.U32())}; | 67 | const auto cbuf{ChooseCbuf(ctx, binding, index)}; |
| 59 | const auto cbuf_cast{fmt::format("{}({}[{}]{{}})", cast, cbuf, index)}; | 68 | const auto cbuf_cast{fmt::format("{}({}{{}})", cast, cbuf)}; |
| 60 | const auto extraction{num_bits == 32 ? cbuf_cast | 69 | const auto extraction{num_bits == 32 ? cbuf_cast |
| 61 | : fmt::format("bitfieldExtract({},int({}),{})", cbuf_cast, | 70 | : fmt::format("bitfieldExtract({},int({}),{})", cbuf_cast, |
| 62 | bit_offset, num_bits)}; | 71 | bit_offset, num_bits)}; |
| @@ -140,9 +149,9 @@ void EmitGetCbufF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, | |||
| 140 | 149 | ||
| 141 | void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, | 150 | void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, |
| 142 | const IR::Value& offset) { | 151 | const IR::Value& offset) { |
| 143 | const auto cbuf{fmt::format("{}_cbuf{}", ctx.stage_name, binding.U32())}; | ||
| 144 | const auto cast{ctx.profile.has_gl_cbuf_ftou_bug ? "" : "ftou"}; | 152 | const auto cast{ctx.profile.has_gl_cbuf_ftou_bug ? "" : "ftou"}; |
| 145 | if (offset.IsImmediate()) { | 153 | if (offset.IsImmediate()) { |
| 154 | const auto cbuf{fmt::format("{}_cbuf{}", ctx.stage_name, binding.U32())}; | ||
| 146 | static constexpr u32 cbuf_size{0x10000}; | 155 | static constexpr u32 cbuf_size{0x10000}; |
| 147 | const u32 u32_offset{offset.U32()}; | 156 | const u32 u32_offset{offset.U32()}; |
| 148 | const s32 signed_offset{static_cast<s32>(offset.U32())}; | 157 | const s32 signed_offset{static_cast<s32>(offset.U32())}; |
| @@ -162,17 +171,17 @@ void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding | |||
| 162 | return; | 171 | return; |
| 163 | } | 172 | } |
| 164 | const auto offset_var{ctx.var_alloc.Consume(offset)}; | 173 | const auto offset_var{ctx.var_alloc.Consume(offset)}; |
| 174 | const auto cbuf{ChooseCbuf(ctx, binding, fmt::format("{}>>4", offset_var))}; | ||
| 165 | if (!ctx.profile.has_gl_component_indexing_bug) { | 175 | if (!ctx.profile.has_gl_component_indexing_bug) { |
| 166 | ctx.AddU32x2("{}=uvec2({}({}[{}>>4][({}>>2)%4]),{}({}[({}+4)>>4][(({}+4)>>2)%4]));", inst, | 176 | ctx.AddU32x2("{}=uvec2({}({}[({}>>2)%4]),{}({}[(({}+4)>>2)%4]));", inst, cast, cbuf, |
| 167 | cast, cbuf, offset_var, offset_var, cast, cbuf, offset_var, offset_var); | 177 | offset_var, cast, cbuf, offset_var); |
| 168 | return; | 178 | return; |
| 169 | } | 179 | } |
| 170 | const auto ret{ctx.var_alloc.Define(inst, GlslVarType::U32x2)}; | 180 | const auto ret{ctx.var_alloc.Define(inst, GlslVarType::U32x2)}; |
| 171 | const auto cbuf_offset{fmt::format("{}>>2", offset_var)}; | 181 | const auto cbuf_offset{fmt::format("{}>>2", offset_var)}; |
| 172 | for (u32 swizzle = 0; swizzle < 4; ++swizzle) { | 182 | for (u32 swizzle = 0; swizzle < 4; ++swizzle) { |
| 173 | ctx.Add("if(({}&3)=={}){}=uvec2({}({}[{}>>4].{}),{}({}[({}+4)>>4].{}));", cbuf_offset, | 183 | ctx.Add("if(({}&3)=={}){}=uvec2({}({}.{}),{}({}.{}));", cbuf_offset, swizzle, ret, cast, |
| 174 | swizzle, ret, cast, cbuf, offset_var, "xyzw"[swizzle], cast, cbuf, offset_var, | 184 | cbuf, "xyzw"[swizzle], cast, cbuf, "xyzw"[(swizzle + 1) % 4]); |
| 175 | "xyzw"[(swizzle + 1) % 4]); | ||
| 176 | } | 185 | } |
| 177 | } | 186 | } |
| 178 | 187 | ||
diff --git a/src/shader_recompiler/backend/glsl/glsl_emit_context.cpp b/src/shader_recompiler/backend/glsl/glsl_emit_context.cpp index e816a93ec..17266f40d 100644 --- a/src/shader_recompiler/backend/glsl/glsl_emit_context.cpp +++ b/src/shader_recompiler/backend/glsl/glsl_emit_context.cpp | |||
| @@ -359,6 +359,7 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile | |||
| 359 | header += "layout(location=0) uniform vec4 scaling;"; | 359 | header += "layout(location=0) uniform vec4 scaling;"; |
| 360 | } | 360 | } |
| 361 | DefineConstantBuffers(bindings); | 361 | DefineConstantBuffers(bindings); |
| 362 | DefineConstantBufferIndirect(); | ||
| 362 | DefineStorageBuffers(bindings); | 363 | DefineStorageBuffers(bindings); |
| 363 | SetupImages(bindings); | 364 | SetupImages(bindings); |
| 364 | SetupTextures(bindings); | 365 | SetupTextures(bindings); |
| @@ -436,6 +437,24 @@ void EmitContext::DefineConstantBuffers(Bindings& bindings) { | |||
| 436 | } | 437 | } |
| 437 | } | 438 | } |
| 438 | 439 | ||
| 440 | void EmitContext::DefineConstantBufferIndirect() { | ||
| 441 | if (!info.uses_cbuf_indirect) { | ||
| 442 | return; | ||
| 443 | } | ||
| 444 | |||
| 445 | header += profile.has_gl_cbuf_ftou_bug ? "uvec4 " : "vec4 "; | ||
| 446 | header += "GetCbufIndirect(uint binding, uint offset){" | ||
| 447 | "switch(binding){" | ||
| 448 | "default:"; | ||
| 449 | |||
| 450 | for (const auto& desc : info.constant_buffer_descriptors) { | ||
| 451 | header += | ||
| 452 | fmt::format("case {}:return {}_cbuf{}[offset];", desc.index, stage_name, desc.index); | ||
| 453 | } | ||
| 454 | |||
| 455 | header += "}}"; | ||
| 456 | } | ||
| 457 | |||
| 439 | void EmitContext::DefineStorageBuffers(Bindings& bindings) { | 458 | void EmitContext::DefineStorageBuffers(Bindings& bindings) { |
| 440 | if (info.storage_buffers_descriptors.empty()) { | 459 | if (info.storage_buffers_descriptors.empty()) { |
| 441 | return; | 460 | return; |
diff --git a/src/shader_recompiler/backend/glsl/glsl_emit_context.h b/src/shader_recompiler/backend/glsl/glsl_emit_context.h index d9b639d29..2b13db6e6 100644 --- a/src/shader_recompiler/backend/glsl/glsl_emit_context.h +++ b/src/shader_recompiler/backend/glsl/glsl_emit_context.h | |||
| @@ -162,6 +162,7 @@ public: | |||
| 162 | private: | 162 | private: |
| 163 | void SetupExtensions(); | 163 | void SetupExtensions(); |
| 164 | void DefineConstantBuffers(Bindings& bindings); | 164 | void DefineConstantBuffers(Bindings& bindings); |
| 165 | void DefineConstantBufferIndirect(); | ||
| 165 | void DefineStorageBuffers(Bindings& bindings); | 166 | void DefineStorageBuffers(Bindings& bindings); |
| 166 | void DefineGenericOutput(size_t index, u32 invocations); | 167 | void DefineGenericOutput(size_t index, u32 invocations); |
| 167 | void DefineHelperFunctions(); | 168 | void DefineHelperFunctions(); |
diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index 28f6a6184..9c83cd2e4 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp | |||
| @@ -1043,15 +1043,15 @@ void EmitContext::DefineConstantBufferIndirectFunctions(const Info& info) { | |||
| 1043 | const Id merge_label{OpLabel()}; | 1043 | const Id merge_label{OpLabel()}; |
| 1044 | const Id uniform_type{uniform_types.*member_ptr}; | 1044 | const Id uniform_type{uniform_types.*member_ptr}; |
| 1045 | 1045 | ||
| 1046 | std::array<Id, Info::MAX_CBUFS> buf_labels; | 1046 | std::array<Id, Info::MAX_INDIRECT_CBUFS> buf_labels; |
| 1047 | std::array<Sirit::Literal, Info::MAX_CBUFS> buf_literals; | 1047 | std::array<Sirit::Literal, Info::MAX_INDIRECT_CBUFS> buf_literals; |
| 1048 | for (u32 i = 0; i < Info::MAX_CBUFS; i++) { | 1048 | for (u32 i = 0; i < Info::MAX_INDIRECT_CBUFS; i++) { |
| 1049 | buf_labels[i] = OpLabel(); | 1049 | buf_labels[i] = OpLabel(); |
| 1050 | buf_literals[i] = Sirit::Literal{i}; | 1050 | buf_literals[i] = Sirit::Literal{i}; |
| 1051 | } | 1051 | } |
| 1052 | OpSelectionMerge(merge_label, spv::SelectionControlMask::MaskNone); | 1052 | OpSelectionMerge(merge_label, spv::SelectionControlMask::MaskNone); |
| 1053 | OpSwitch(binding, buf_labels[0], buf_literals, buf_labels); | 1053 | OpSwitch(binding, buf_labels[0], buf_literals, buf_labels); |
| 1054 | for (u32 i = 0; i < Info::MAX_CBUFS; i++) { | 1054 | for (u32 i = 0; i < Info::MAX_INDIRECT_CBUFS; i++) { |
| 1055 | AddLabel(buf_labels[i]); | 1055 | AddLabel(buf_labels[i]); |
| 1056 | const Id cbuf{cbufs[i].*member_ptr}; | 1056 | const Id cbuf{cbufs[i].*member_ptr}; |
| 1057 | const Id access_chain{OpAccessChain(uniform_type, cbuf, u32_zero_value, offset)}; | 1057 | const Id access_chain{OpAccessChain(uniform_type, cbuf, u32_zero_value, offset)}; |
| @@ -1064,22 +1064,23 @@ void EmitContext::DefineConstantBufferIndirectFunctions(const Info& info) { | |||
| 1064 | return func; | 1064 | return func; |
| 1065 | }}; | 1065 | }}; |
| 1066 | IR::Type types{info.used_indirect_cbuf_types}; | 1066 | IR::Type types{info.used_indirect_cbuf_types}; |
| 1067 | if (True(types & IR::Type::U8)) { | 1067 | bool supports_aliasing = profile.support_descriptor_aliasing; |
| 1068 | if (supports_aliasing && True(types & IR::Type::U8)) { | ||
| 1068 | load_const_func_u8 = make_accessor(U8, &UniformDefinitions::U8); | 1069 | load_const_func_u8 = make_accessor(U8, &UniformDefinitions::U8); |
| 1069 | } | 1070 | } |
| 1070 | if (True(types & IR::Type::U16)) { | 1071 | if (supports_aliasing && True(types & IR::Type::U16)) { |
| 1071 | load_const_func_u16 = make_accessor(U16, &UniformDefinitions::U16); | 1072 | load_const_func_u16 = make_accessor(U16, &UniformDefinitions::U16); |
| 1072 | } | 1073 | } |
| 1073 | if (True(types & IR::Type::F32)) { | 1074 | if (supports_aliasing && True(types & IR::Type::F32)) { |
| 1074 | load_const_func_f32 = make_accessor(F32[1], &UniformDefinitions::F32); | 1075 | load_const_func_f32 = make_accessor(F32[1], &UniformDefinitions::F32); |
| 1075 | } | 1076 | } |
| 1076 | if (True(types & IR::Type::U32)) { | 1077 | if (supports_aliasing && True(types & IR::Type::U32)) { |
| 1077 | load_const_func_u32 = make_accessor(U32[1], &UniformDefinitions::U32); | 1078 | load_const_func_u32 = make_accessor(U32[1], &UniformDefinitions::U32); |
| 1078 | } | 1079 | } |
| 1079 | if (True(types & IR::Type::U32x2)) { | 1080 | if (supports_aliasing && True(types & IR::Type::U32x2)) { |
| 1080 | load_const_func_u32x2 = make_accessor(U32[2], &UniformDefinitions::U32x2); | 1081 | load_const_func_u32x2 = make_accessor(U32[2], &UniformDefinitions::U32x2); |
| 1081 | } | 1082 | } |
| 1082 | if (True(types & IR::Type::U32x4)) { | 1083 | if (!supports_aliasing || True(types & IR::Type::U32x4)) { |
| 1083 | load_const_func_u32x4 = make_accessor(U32[4], &UniformDefinitions::U32x4); | 1084 | load_const_func_u32x4 = make_accessor(U32[4], &UniformDefinitions::U32x4); |
| 1084 | } | 1085 | } |
| 1085 | } | 1086 | } |
diff --git a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp index 0b2c60842..16278faab 100644 --- a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp +++ b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp | |||
| @@ -32,13 +32,8 @@ void AddConstantBufferDescriptor(Info& info, u32 index, u32 count) { | |||
| 32 | void AddRegisterIndexedLdc(Info& info) { | 32 | void AddRegisterIndexedLdc(Info& info) { |
| 33 | info.uses_cbuf_indirect = true; | 33 | info.uses_cbuf_indirect = true; |
| 34 | 34 | ||
| 35 | // The shader can use any possible constant buffer | 35 | for (u32 i = 0; i < Info::MAX_INDIRECT_CBUFS; i++) { |
| 36 | info.constant_buffer_mask = (1 << Info::MAX_CBUFS) - 1; | 36 | AddConstantBufferDescriptor(info, i, 1); |
| 37 | |||
| 38 | auto& cbufs{info.constant_buffer_descriptors}; | ||
| 39 | cbufs.clear(); | ||
| 40 | for (u32 i = 0; i < Info::MAX_CBUFS; i++) { | ||
| 41 | cbufs.push_back(ConstantBufferDescriptor{.index = i, .count = 1}); | ||
| 42 | 37 | ||
| 43 | // The shader can use any possible access size | 38 | // The shader can use any possible access size |
| 44 | info.constant_buffer_used_sizes[i] = 0x10'000; | 39 | info.constant_buffer_used_sizes[i] = 0x10'000; |
diff --git a/src/shader_recompiler/shader_info.h b/src/shader_recompiler/shader_info.h index 9d36bd9eb..a3a09c71c 100644 --- a/src/shader_recompiler/shader_info.h +++ b/src/shader_recompiler/shader_info.h | |||
| @@ -105,6 +105,7 @@ struct ImageDescriptor { | |||
| 105 | using ImageDescriptors = boost::container::small_vector<ImageDescriptor, 4>; | 105 | using ImageDescriptors = boost::container::small_vector<ImageDescriptor, 4>; |
| 106 | 106 | ||
| 107 | struct Info { | 107 | struct Info { |
| 108 | static constexpr size_t MAX_INDIRECT_CBUFS{14}; | ||
| 108 | static constexpr size_t MAX_CBUFS{18}; | 109 | static constexpr size_t MAX_CBUFS{18}; |
| 109 | static constexpr size_t MAX_SSBOS{32}; | 110 | static constexpr size_t MAX_SSBOS{32}; |
| 110 | 111 | ||
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index ba9ba082f..789af452d 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp | |||
| @@ -230,7 +230,7 @@ struct GPU::Impl { | |||
| 230 | void IncrementSyncPoint(u32 syncpoint_id) { | 230 | void IncrementSyncPoint(u32 syncpoint_id) { |
| 231 | auto& syncpoint = syncpoints.at(syncpoint_id); | 231 | auto& syncpoint = syncpoints.at(syncpoint_id); |
| 232 | syncpoint++; | 232 | syncpoint++; |
| 233 | std::lock_guard lock{sync_mutex}; | 233 | std::scoped_lock lock{sync_mutex}; |
| 234 | sync_cv.notify_all(); | 234 | sync_cv.notify_all(); |
| 235 | auto& interrupt = syncpt_interrupts.at(syncpoint_id); | 235 | auto& interrupt = syncpt_interrupts.at(syncpoint_id); |
| 236 | if (!interrupt.empty()) { | 236 | if (!interrupt.empty()) { |
| @@ -252,7 +252,7 @@ struct GPU::Impl { | |||
| 252 | } | 252 | } |
| 253 | 253 | ||
| 254 | void RegisterSyncptInterrupt(u32 syncpoint_id, u32 value) { | 254 | void RegisterSyncptInterrupt(u32 syncpoint_id, u32 value) { |
| 255 | std::lock_guard lock{sync_mutex}; | 255 | std::scoped_lock lock{sync_mutex}; |
| 256 | auto& interrupt = syncpt_interrupts.at(syncpoint_id); | 256 | auto& interrupt = syncpt_interrupts.at(syncpoint_id); |
| 257 | bool contains = std::any_of(interrupt.begin(), interrupt.end(), | 257 | bool contains = std::any_of(interrupt.begin(), interrupt.end(), |
| 258 | [value](u32 in_value) { return in_value == value; }); | 258 | [value](u32 in_value) { return in_value == value; }); |
| @@ -263,7 +263,7 @@ struct GPU::Impl { | |||
| 263 | } | 263 | } |
| 264 | 264 | ||
| 265 | [[nodiscard]] bool CancelSyncptInterrupt(u32 syncpoint_id, u32 value) { | 265 | [[nodiscard]] bool CancelSyncptInterrupt(u32 syncpoint_id, u32 value) { |
| 266 | std::lock_guard lock{sync_mutex}; | 266 | std::scoped_lock lock{sync_mutex}; |
| 267 | auto& interrupt = syncpt_interrupts.at(syncpoint_id); | 267 | auto& interrupt = syncpt_interrupts.at(syncpoint_id); |
| 268 | const auto iter = | 268 | const auto iter = |
| 269 | std::find_if(interrupt.begin(), interrupt.end(), | 269 | std::find_if(interrupt.begin(), interrupt.end(), |
diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp index 9547f277a..4e8999915 100644 --- a/src/video_core/gpu_thread.cpp +++ b/src/video_core/gpu_thread.cpp | |||
| @@ -56,7 +56,7 @@ static void RunThread(std::stop_token stop_token, Core::System& system, | |||
| 56 | if (next.block) { | 56 | if (next.block) { |
| 57 | // We have to lock the write_lock to ensure that the condition_variable wait not get a | 57 | // We have to lock the write_lock to ensure that the condition_variable wait not get a |
| 58 | // race between the check and the lock itself. | 58 | // race between the check and the lock itself. |
| 59 | std::lock_guard lk(state.write_lock); | 59 | std::scoped_lock lk{state.write_lock}; |
| 60 | state.cv.notify_all(); | 60 | state.cv.notify_all(); |
| 61 | } | 61 | } |
| 62 | } | 62 | } |
diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt index af05d47d1..190fc6aea 100644 --- a/src/video_core/host_shaders/CMakeLists.txt +++ b/src/video_core/host_shaders/CMakeLists.txt | |||
| @@ -18,6 +18,7 @@ set(SHADER_FILES | |||
| 18 | full_screen_triangle.vert | 18 | full_screen_triangle.vert |
| 19 | fxaa.frag | 19 | fxaa.frag |
| 20 | fxaa.vert | 20 | fxaa.vert |
| 21 | opengl_convert_s8d24.comp | ||
| 21 | opengl_copy_bc4.comp | 22 | opengl_copy_bc4.comp |
| 22 | opengl_present.frag | 23 | opengl_present.frag |
| 23 | opengl_present.vert | 24 | opengl_present.vert |
diff --git a/src/video_core/host_shaders/opengl_convert_s8d24.comp b/src/video_core/host_shaders/opengl_convert_s8d24.comp new file mode 100644 index 000000000..83e1ab176 --- /dev/null +++ b/src/video_core/host_shaders/opengl_convert_s8d24.comp | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | // Copyright 2022 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #version 430 core | ||
| 6 | |||
| 7 | layout(local_size_x = 16, local_size_y = 8) in; | ||
| 8 | |||
| 9 | layout(binding = 0, rgba8ui) restrict uniform uimage2D destination; | ||
| 10 | layout(location = 0) uniform uvec3 size; | ||
| 11 | |||
| 12 | void main() { | ||
| 13 | if (any(greaterThanEqual(gl_GlobalInvocationID, size))) { | ||
| 14 | return; | ||
| 15 | } | ||
| 16 | uvec4 components = imageLoad(destination, ivec2(gl_GlobalInvocationID.xy)); | ||
| 17 | imageStore(destination, ivec2(gl_GlobalInvocationID.xy), components.wxyz); | ||
| 18 | } | ||
diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp index 9e6732abd..fd40966d5 100644 --- a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp +++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp | |||
| @@ -253,7 +253,7 @@ GraphicsPipeline::GraphicsPipeline( | |||
| 253 | } | 253 | } |
| 254 | } | 254 | } |
| 255 | if (in_parallel) { | 255 | if (in_parallel) { |
| 256 | std::lock_guard lock{built_mutex}; | 256 | std::scoped_lock lock{built_mutex}; |
| 257 | built_fence.Create(); | 257 | built_fence.Create(); |
| 258 | // Flush this context to ensure compilation commands and fence are in the GPU pipe. | 258 | // Flush this context to ensure compilation commands and fence are in the GPU pipe. |
| 259 | glFlush(); | 259 | glFlush(); |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index e6f9ece8b..8ef79753f 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -520,6 +520,8 @@ bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config, | |||
| 520 | // ASSERT_MSG(image_view->size.width == config.width, "Framebuffer width is different"); | 520 | // ASSERT_MSG(image_view->size.width == config.width, "Framebuffer width is different"); |
| 521 | // ASSERT_MSG(image_view->size.height == config.height, "Framebuffer height is different"); | 521 | // ASSERT_MSG(image_view->size.height == config.height, "Framebuffer height is different"); |
| 522 | 522 | ||
| 523 | screen_info.texture.width = image_view->size.width; | ||
| 524 | screen_info.texture.height = image_view->size.height; | ||
| 523 | screen_info.display_texture = image_view->Handle(Shader::TextureType::Color2D); | 525 | screen_info.display_texture = image_view->Handle(Shader::TextureType::Color2D); |
| 524 | screen_info.display_srgb = VideoCore::Surface::IsPixelFormatSRGB(image_view->format); | 526 | screen_info.display_srgb = VideoCore::Surface::IsPixelFormatSRGB(image_view->format); |
| 525 | return true; | 527 | return true; |
| @@ -557,12 +559,19 @@ void RasterizerOpenGL::SyncViewport() { | |||
| 557 | const bool dirty_viewport = flags[Dirty::Viewports] || rescale_viewports; | 559 | const bool dirty_viewport = flags[Dirty::Viewports] || rescale_viewports; |
| 558 | const bool dirty_clip_control = flags[Dirty::ClipControl]; | 560 | const bool dirty_clip_control = flags[Dirty::ClipControl]; |
| 559 | 561 | ||
| 560 | if (dirty_clip_control || flags[Dirty::FrontFace]) { | 562 | if (dirty_viewport || dirty_clip_control || flags[Dirty::FrontFace]) { |
| 561 | flags[Dirty::FrontFace] = false; | 563 | flags[Dirty::FrontFace] = false; |
| 562 | 564 | ||
| 563 | GLenum mode = MaxwellToGL::FrontFace(regs.front_face); | 565 | GLenum mode = MaxwellToGL::FrontFace(regs.front_face); |
| 566 | bool flip_faces = false; | ||
| 564 | if (regs.screen_y_control.triangle_rast_flip != 0 && | 567 | if (regs.screen_y_control.triangle_rast_flip != 0 && |
| 565 | regs.viewport_transform[0].scale_y < 0.0f) { | 568 | regs.viewport_transform[0].scale_y < 0.0f) { |
| 569 | flip_faces = !flip_faces; | ||
| 570 | } | ||
| 571 | if (regs.viewport_transform[0].scale_z < 0.0f) { | ||
| 572 | flip_faces = !flip_faces; | ||
| 573 | } | ||
| 574 | if (flip_faces) { | ||
| 566 | switch (mode) { | 575 | switch (mode) { |
| 567 | case GL_CW: | 576 | case GL_CW: |
| 568 | mode = GL_CCW; | 577 | mode = GL_CCW; |
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 6423992c3..05c5e702c 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp | |||
| @@ -258,7 +258,7 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading, | |||
| 258 | [this, key, env = std::move(env), &state, &callback](Context* ctx) mutable { | 258 | [this, key, env = std::move(env), &state, &callback](Context* ctx) mutable { |
| 259 | ctx->pools.ReleaseContents(); | 259 | ctx->pools.ReleaseContents(); |
| 260 | auto pipeline{CreateComputePipeline(ctx->pools, key, env)}; | 260 | auto pipeline{CreateComputePipeline(ctx->pools, key, env)}; |
| 261 | std::lock_guard lock{state.mutex}; | 261 | std::scoped_lock lock{state.mutex}; |
| 262 | if (pipeline) { | 262 | if (pipeline) { |
| 263 | compute_cache.emplace(key, std::move(pipeline)); | 263 | compute_cache.emplace(key, std::move(pipeline)); |
| 264 | } | 264 | } |
| @@ -280,7 +280,7 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading, | |||
| 280 | } | 280 | } |
| 281 | ctx->pools.ReleaseContents(); | 281 | ctx->pools.ReleaseContents(); |
| 282 | auto pipeline{CreateGraphicsPipeline(ctx->pools, key, MakeSpan(env_ptrs), false)}; | 282 | auto pipeline{CreateGraphicsPipeline(ctx->pools, key, MakeSpan(env_ptrs), false)}; |
| 283 | std::lock_guard lock{state.mutex}; | 283 | std::scoped_lock lock{state.mutex}; |
| 284 | if (pipeline) { | 284 | if (pipeline) { |
| 285 | graphics_cache.emplace(key, std::move(pipeline)); | 285 | graphics_cache.emplace(key, std::move(pipeline)); |
| 286 | } | 286 | } |
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 8f9a65beb..d12076358 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp | |||
| @@ -409,8 +409,8 @@ ImageBufferMap::~ImageBufferMap() { | |||
| 409 | 409 | ||
| 410 | TextureCacheRuntime::TextureCacheRuntime(const Device& device_, ProgramManager& program_manager, | 410 | TextureCacheRuntime::TextureCacheRuntime(const Device& device_, ProgramManager& program_manager, |
| 411 | StateTracker& state_tracker_) | 411 | StateTracker& state_tracker_) |
| 412 | : device{device_}, state_tracker{state_tracker_}, | 412 | : device{device_}, state_tracker{state_tracker_}, util_shaders(program_manager), |
| 413 | util_shaders(program_manager), resolution{Settings::values.resolution_info} { | 413 | format_conversion_pass{util_shaders}, resolution{Settings::values.resolution_info} { |
| 414 | static constexpr std::array TARGETS{GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_ARRAY, GL_TEXTURE_3D}; | 414 | static constexpr std::array TARGETS{GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_ARRAY, GL_TEXTURE_3D}; |
| 415 | for (size_t i = 0; i < TARGETS.size(); ++i) { | 415 | for (size_t i = 0; i < TARGETS.size(); ++i) { |
| 416 | const GLenum target = TARGETS[i]; | 416 | const GLenum target = TARGETS[i]; |
| @@ -1325,6 +1325,9 @@ Framebuffer::Framebuffer(TextureCacheRuntime& runtime, std::span<ImageView*, NUM | |||
| 1325 | 1325 | ||
| 1326 | Framebuffer::~Framebuffer() = default; | 1326 | Framebuffer::~Framebuffer() = default; |
| 1327 | 1327 | ||
| 1328 | FormatConversionPass::FormatConversionPass(UtilShaders& util_shaders_) | ||
| 1329 | : util_shaders{util_shaders_} {} | ||
| 1330 | |||
| 1328 | void FormatConversionPass::ConvertImage(Image& dst_image, Image& src_image, | 1331 | void FormatConversionPass::ConvertImage(Image& dst_image, Image& src_image, |
| 1329 | std::span<const VideoCommon::ImageCopy> copies) { | 1332 | std::span<const VideoCommon::ImageCopy> copies) { |
| 1330 | const GLenum dst_target = ImageTarget(dst_image.info); | 1333 | const GLenum dst_target = ImageTarget(dst_image.info); |
| @@ -1357,6 +1360,12 @@ void FormatConversionPass::ConvertImage(Image& dst_image, Image& src_image, | |||
| 1357 | dst_origin.z, region.width, region.height, region.depth, | 1360 | dst_origin.z, region.width, region.height, region.depth, |
| 1358 | dst_image.GlFormat(), dst_image.GlType(), nullptr); | 1361 | dst_image.GlFormat(), dst_image.GlType(), nullptr); |
| 1359 | } | 1362 | } |
| 1363 | |||
| 1364 | // Swap component order of S8D24 to ABGR8 reinterprets | ||
| 1365 | if (src_image.info.format == PixelFormat::D24_UNORM_S8_UINT && | ||
| 1366 | dst_image.info.format == PixelFormat::A8B8G8R8_UNORM) { | ||
| 1367 | util_shaders.ConvertS8D24(dst_image, copies); | ||
| 1368 | } | ||
| 1360 | } | 1369 | } |
| 1361 | 1370 | ||
| 1362 | } // namespace OpenGL | 1371 | } // namespace OpenGL |
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index 53088b66e..672fa8dde 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h | |||
| @@ -55,13 +55,14 @@ struct FormatProperties { | |||
| 55 | 55 | ||
| 56 | class FormatConversionPass { | 56 | class FormatConversionPass { |
| 57 | public: | 57 | public: |
| 58 | FormatConversionPass() = default; | 58 | explicit FormatConversionPass(UtilShaders& util_shaders); |
| 59 | ~FormatConversionPass() = default; | 59 | ~FormatConversionPass() = default; |
| 60 | 60 | ||
| 61 | void ConvertImage(Image& dst_image, Image& src_image, | 61 | void ConvertImage(Image& dst_image, Image& src_image, |
| 62 | std::span<const VideoCommon::ImageCopy> copies); | 62 | std::span<const VideoCommon::ImageCopy> copies); |
| 63 | 63 | ||
| 64 | private: | 64 | private: |
| 65 | UtilShaders& util_shaders; | ||
| 65 | OGLBuffer intermediate_pbo; | 66 | OGLBuffer intermediate_pbo; |
| 66 | size_t pbo_size{}; | 67 | size_t pbo_size{}; |
| 67 | }; | 68 | }; |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index f8f29013a..3a3c213bb 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -208,6 +208,8 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf | |||
| 208 | // Framebuffer orientation handling | 208 | // Framebuffer orientation handling |
| 209 | framebuffer_transform_flags = framebuffer.transform_flags; | 209 | framebuffer_transform_flags = framebuffer.transform_flags; |
| 210 | framebuffer_crop_rect = framebuffer.crop_rect; | 210 | framebuffer_crop_rect = framebuffer.crop_rect; |
| 211 | framebuffer_width = framebuffer.width; | ||
| 212 | framebuffer_height = framebuffer.height; | ||
| 211 | 213 | ||
| 212 | const VAddr framebuffer_addr{framebuffer.address + framebuffer.offset}; | 214 | const VAddr framebuffer_addr{framebuffer.address + framebuffer.offset}; |
| 213 | screen_info.was_accelerated = | 215 | screen_info.was_accelerated = |
| @@ -480,9 +482,12 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { | |||
| 480 | ASSERT_MSG(framebuffer_crop_rect.top == 0, "Unimplemented"); | 482 | ASSERT_MSG(framebuffer_crop_rect.top == 0, "Unimplemented"); |
| 481 | ASSERT_MSG(framebuffer_crop_rect.left == 0, "Unimplemented"); | 483 | ASSERT_MSG(framebuffer_crop_rect.left == 0, "Unimplemented"); |
| 482 | 484 | ||
| 485 | f32 scale_u = static_cast<f32>(framebuffer_width) / static_cast<f32>(screen_info.texture.width); | ||
| 486 | f32 scale_v = | ||
| 487 | static_cast<f32>(framebuffer_height) / static_cast<f32>(screen_info.texture.height); | ||
| 488 | |||
| 483 | // Scale the output by the crop width/height. This is commonly used with 1280x720 rendering | 489 | // Scale the output by the crop width/height. This is commonly used with 1280x720 rendering |
| 484 | // (e.g. handheld mode) on a 1920x1080 framebuffer. | 490 | // (e.g. handheld mode) on a 1920x1080 framebuffer. |
| 485 | f32 scale_u = 1.f, scale_v = 1.f; | ||
| 486 | if (framebuffer_crop_rect.GetWidth() > 0) { | 491 | if (framebuffer_crop_rect.GetWidth() > 0) { |
| 487 | scale_u = static_cast<f32>(framebuffer_crop_rect.GetWidth()) / | 492 | scale_u = static_cast<f32>(framebuffer_crop_rect.GetWidth()) / |
| 488 | static_cast<f32>(screen_info.texture.width); | 493 | static_cast<f32>(screen_info.texture.width); |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index aa206878b..ae9558a33 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h | |||
| @@ -137,6 +137,8 @@ private: | |||
| 137 | /// Used for transforming the framebuffer orientation | 137 | /// Used for transforming the framebuffer orientation |
| 138 | Service::android::BufferTransformFlags framebuffer_transform_flags{}; | 138 | Service::android::BufferTransformFlags framebuffer_transform_flags{}; |
| 139 | Common::Rectangle<int> framebuffer_crop_rect; | 139 | Common::Rectangle<int> framebuffer_crop_rect; |
| 140 | u32 framebuffer_width; | ||
| 141 | u32 framebuffer_height; | ||
| 140 | }; | 142 | }; |
| 141 | 143 | ||
| 142 | } // namespace OpenGL | 144 | } // namespace OpenGL |
diff --git a/src/video_core/renderer_opengl/util_shaders.cpp b/src/video_core/renderer_opengl/util_shaders.cpp index 897c380b3..04c482a09 100644 --- a/src/video_core/renderer_opengl/util_shaders.cpp +++ b/src/video_core/renderer_opengl/util_shaders.cpp | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include "video_core/host_shaders/astc_decoder_comp.h" | 13 | #include "video_core/host_shaders/astc_decoder_comp.h" |
| 14 | #include "video_core/host_shaders/block_linear_unswizzle_2d_comp.h" | 14 | #include "video_core/host_shaders/block_linear_unswizzle_2d_comp.h" |
| 15 | #include "video_core/host_shaders/block_linear_unswizzle_3d_comp.h" | 15 | #include "video_core/host_shaders/block_linear_unswizzle_3d_comp.h" |
| 16 | #include "video_core/host_shaders/opengl_convert_s8d24_comp.h" | ||
| 16 | #include "video_core/host_shaders/opengl_copy_bc4_comp.h" | 17 | #include "video_core/host_shaders/opengl_copy_bc4_comp.h" |
| 17 | #include "video_core/host_shaders/pitch_unswizzle_comp.h" | 18 | #include "video_core/host_shaders/pitch_unswizzle_comp.h" |
| 18 | #include "video_core/renderer_opengl/gl_shader_manager.h" | 19 | #include "video_core/renderer_opengl/gl_shader_manager.h" |
| @@ -50,7 +51,8 @@ UtilShaders::UtilShaders(ProgramManager& program_manager_) | |||
| 50 | block_linear_unswizzle_2d_program(MakeProgram(BLOCK_LINEAR_UNSWIZZLE_2D_COMP)), | 51 | block_linear_unswizzle_2d_program(MakeProgram(BLOCK_LINEAR_UNSWIZZLE_2D_COMP)), |
| 51 | block_linear_unswizzle_3d_program(MakeProgram(BLOCK_LINEAR_UNSWIZZLE_3D_COMP)), | 52 | block_linear_unswizzle_3d_program(MakeProgram(BLOCK_LINEAR_UNSWIZZLE_3D_COMP)), |
| 52 | pitch_unswizzle_program(MakeProgram(PITCH_UNSWIZZLE_COMP)), | 53 | pitch_unswizzle_program(MakeProgram(PITCH_UNSWIZZLE_COMP)), |
| 53 | copy_bc4_program(MakeProgram(OPENGL_COPY_BC4_COMP)) { | 54 | copy_bc4_program(MakeProgram(OPENGL_COPY_BC4_COMP)), |
| 55 | convert_s8d24_program(MakeProgram(OPENGL_CONVERT_S8D24_COMP)) { | ||
| 54 | const auto swizzle_table = Tegra::Texture::MakeSwizzleTable(); | 56 | const auto swizzle_table = Tegra::Texture::MakeSwizzleTable(); |
| 55 | swizzle_table_buffer.Create(); | 57 | swizzle_table_buffer.Create(); |
| 56 | glNamedBufferStorage(swizzle_table_buffer.handle, sizeof(swizzle_table), &swizzle_table, 0); | 58 | glNamedBufferStorage(swizzle_table_buffer.handle, sizeof(swizzle_table), &swizzle_table, 0); |
| @@ -248,6 +250,26 @@ void UtilShaders::CopyBC4(Image& dst_image, Image& src_image, std::span<const Im | |||
| 248 | program_manager.RestoreGuestCompute(); | 250 | program_manager.RestoreGuestCompute(); |
| 249 | } | 251 | } |
| 250 | 252 | ||
| 253 | void UtilShaders::ConvertS8D24(Image& dst_image, std::span<const ImageCopy> copies) { | ||
| 254 | static constexpr GLuint BINDING_DESTINATION = 0; | ||
| 255 | static constexpr GLuint LOC_SIZE = 0; | ||
| 256 | |||
| 257 | program_manager.BindComputeProgram(convert_s8d24_program.handle); | ||
| 258 | for (const ImageCopy& copy : copies) { | ||
| 259 | ASSERT(copy.src_subresource.base_layer == 0); | ||
| 260 | ASSERT(copy.src_subresource.num_layers == 1); | ||
| 261 | ASSERT(copy.dst_subresource.base_layer == 0); | ||
| 262 | ASSERT(copy.dst_subresource.num_layers == 1); | ||
| 263 | |||
| 264 | glUniform3ui(LOC_SIZE, copy.extent.width, copy.extent.height, copy.extent.depth); | ||
| 265 | glBindImageTexture(BINDING_DESTINATION, dst_image.StorageHandle(), | ||
| 266 | copy.dst_subresource.base_level, GL_TRUE, 0, GL_READ_WRITE, GL_RGBA8UI); | ||
| 267 | glDispatchCompute(Common::DivCeil(copy.extent.width, 16u), | ||
| 268 | Common::DivCeil(copy.extent.height, 8u), copy.extent.depth); | ||
| 269 | } | ||
| 270 | program_manager.RestoreGuestCompute(); | ||
| 271 | } | ||
| 272 | |||
| 251 | GLenum StoreFormat(u32 bytes_per_block) { | 273 | GLenum StoreFormat(u32 bytes_per_block) { |
| 252 | switch (bytes_per_block) { | 274 | switch (bytes_per_block) { |
| 253 | case 1: | 275 | case 1: |
diff --git a/src/video_core/renderer_opengl/util_shaders.h b/src/video_core/renderer_opengl/util_shaders.h index 5de95ea7a..5c132e67f 100644 --- a/src/video_core/renderer_opengl/util_shaders.h +++ b/src/video_core/renderer_opengl/util_shaders.h | |||
| @@ -39,6 +39,8 @@ public: | |||
| 39 | void CopyBC4(Image& dst_image, Image& src_image, | 39 | void CopyBC4(Image& dst_image, Image& src_image, |
| 40 | std::span<const VideoCommon::ImageCopy> copies); | 40 | std::span<const VideoCommon::ImageCopy> copies); |
| 41 | 41 | ||
| 42 | void ConvertS8D24(Image& dst_image, std::span<const VideoCommon::ImageCopy> copies); | ||
| 43 | |||
| 42 | private: | 44 | private: |
| 43 | ProgramManager& program_manager; | 45 | ProgramManager& program_manager; |
| 44 | 46 | ||
| @@ -49,6 +51,7 @@ private: | |||
| 49 | OGLProgram block_linear_unswizzle_3d_program; | 51 | OGLProgram block_linear_unswizzle_3d_program; |
| 50 | OGLProgram pitch_unswizzle_program; | 52 | OGLProgram pitch_unswizzle_program; |
| 51 | OGLProgram copy_bc4_program; | 53 | OGLProgram copy_bc4_program; |
| 54 | OGLProgram convert_s8d24_program; | ||
| 52 | }; | 55 | }; |
| 53 | 56 | ||
| 54 | GLenum StoreFormat(u32 bytes_per_block); | 57 | GLenum StoreFormat(u32 bytes_per_block); |
diff --git a/src/video_core/renderer_vulkan/pipeline_statistics.cpp b/src/video_core/renderer_vulkan/pipeline_statistics.cpp index bfec931a6..7ccadf084 100644 --- a/src/video_core/renderer_vulkan/pipeline_statistics.cpp +++ b/src/video_core/renderer_vulkan/pipeline_statistics.cpp | |||
| @@ -57,7 +57,7 @@ void PipelineStatistics::Collect(VkPipeline pipeline) { | |||
| 57 | stage_stats.basic_block_count = GetUint64(statistic); | 57 | stage_stats.basic_block_count = GetUint64(statistic); |
| 58 | } | 58 | } |
| 59 | } | 59 | } |
| 60 | std::lock_guard lock{mutex}; | 60 | std::scoped_lock lock{mutex}; |
| 61 | collected_stats.push_back(stage_stats); | 61 | collected_stats.push_back(stage_stats); |
| 62 | } | 62 | } |
| 63 | } | 63 | } |
| @@ -66,7 +66,7 @@ void PipelineStatistics::Report() const { | |||
| 66 | double num{}; | 66 | double num{}; |
| 67 | Stats total; | 67 | Stats total; |
| 68 | { | 68 | { |
| 69 | std::lock_guard lock{mutex}; | 69 | std::scoped_lock lock{mutex}; |
| 70 | for (const Stats& stats : collected_stats) { | 70 | for (const Stats& stats : collected_stats) { |
| 71 | total.code_size += stats.code_size; | 71 | total.code_size += stats.code_size; |
| 72 | total.register_count += stats.register_count; | 72 | total.register_count += stats.register_count; |
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp index d893c1952..b866e9103 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp +++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp | |||
| @@ -1406,8 +1406,9 @@ void VKBlitScreen::SetVertexData(BufferData& data, const Tegra::FramebufferConfi | |||
| 1406 | UNIMPLEMENTED_IF(framebuffer_crop_rect.top != 0); | 1406 | UNIMPLEMENTED_IF(framebuffer_crop_rect.top != 0); |
| 1407 | UNIMPLEMENTED_IF(framebuffer_crop_rect.left != 0); | 1407 | UNIMPLEMENTED_IF(framebuffer_crop_rect.left != 0); |
| 1408 | 1408 | ||
| 1409 | f32 scale_u = 1.0f; | 1409 | f32 scale_u = static_cast<f32>(framebuffer.width) / static_cast<f32>(screen_info.width); |
| 1410 | f32 scale_v = 1.0f; | 1410 | f32 scale_v = static_cast<f32>(framebuffer.height) / static_cast<f32>(screen_info.height); |
| 1411 | |||
| 1411 | // Scale the output by the crop width/height. This is commonly used with 1280x720 rendering | 1412 | // Scale the output by the crop width/height. This is commonly used with 1280x720 rendering |
| 1412 | // (e.g. handheld mode) on a 1920x1080 framebuffer. | 1413 | // (e.g. handheld mode) on a 1920x1080 framebuffer. |
| 1413 | if (!fsr) { | 1414 | if (!fsr) { |
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp index de36bcdb7..97b3594c2 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp | |||
| @@ -77,7 +77,7 @@ ComputePipeline::ComputePipeline(const Device& device_, DescriptorPool& descript | |||
| 77 | if (pipeline_statistics) { | 77 | if (pipeline_statistics) { |
| 78 | pipeline_statistics->Collect(*pipeline); | 78 | pipeline_statistics->Collect(*pipeline); |
| 79 | } | 79 | } |
| 80 | std::lock_guard lock{build_mutex}; | 80 | std::scoped_lock lock{build_mutex}; |
| 81 | is_built = true; | 81 | is_built = true; |
| 82 | build_condvar.notify_one(); | 82 | build_condvar.notify_one(); |
| 83 | if (shader_notify) { | 83 | if (shader_notify) { |
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index d514b71d0..8959d6059 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp | |||
| @@ -258,7 +258,7 @@ GraphicsPipeline::GraphicsPipeline( | |||
| 258 | pipeline_statistics->Collect(*pipeline); | 258 | pipeline_statistics->Collect(*pipeline); |
| 259 | } | 259 | } |
| 260 | 260 | ||
| 261 | std::lock_guard lock{build_mutex}; | 261 | std::scoped_lock lock{build_mutex}; |
| 262 | is_built = true; | 262 | is_built = true; |
| 263 | build_condvar.notify_one(); | 263 | build_condvar.notify_one(); |
| 264 | if (shader_notify) { | 264 | if (shader_notify) { |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 27e59df73..336d1e9dc 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | |||
| @@ -404,7 +404,7 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading | |||
| 404 | workers.QueueWork([this, key, env = std::move(env), &state, &callback]() mutable { | 404 | workers.QueueWork([this, key, env = std::move(env), &state, &callback]() mutable { |
| 405 | ShaderPools pools; | 405 | ShaderPools pools; |
| 406 | auto pipeline{CreateComputePipeline(pools, key, env, state.statistics.get(), false)}; | 406 | auto pipeline{CreateComputePipeline(pools, key, env, state.statistics.get(), false)}; |
| 407 | std::lock_guard lock{state.mutex}; | 407 | std::scoped_lock lock{state.mutex}; |
| 408 | if (pipeline) { | 408 | if (pipeline) { |
| 409 | compute_cache.emplace(key, std::move(pipeline)); | 409 | compute_cache.emplace(key, std::move(pipeline)); |
| 410 | } | 410 | } |
| @@ -434,7 +434,7 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading | |||
| 434 | auto pipeline{CreateGraphicsPipeline(pools, key, MakeSpan(env_ptrs), | 434 | auto pipeline{CreateGraphicsPipeline(pools, key, MakeSpan(env_ptrs), |
| 435 | state.statistics.get(), false)}; | 435 | state.statistics.get(), false)}; |
| 436 | 436 | ||
| 437 | std::lock_guard lock{state.mutex}; | 437 | std::scoped_lock lock{state.mutex}; |
| 438 | graphics_cache.emplace(key, std::move(pipeline)); | 438 | graphics_cache.emplace(key, std::move(pipeline)); |
| 439 | ++state.built; | 439 | ++state.built; |
| 440 | if (state.has_loaded) { | 440 | if (state.has_loaded) { |
diff --git a/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp b/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp index 451ffe019..d22bb6694 100644 --- a/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp | |||
| @@ -36,7 +36,7 @@ VkAttachmentDescription AttachmentDescription(const Device& device, PixelFormat | |||
| 36 | RenderPassCache::RenderPassCache(const Device& device_) : device{&device_} {} | 36 | RenderPassCache::RenderPassCache(const Device& device_) : device{&device_} {} |
| 37 | 37 | ||
| 38 | VkRenderPass RenderPassCache::Get(const RenderPassKey& key) { | 38 | VkRenderPass RenderPassCache::Get(const RenderPassKey& key) { |
| 39 | std::lock_guard lock{mutex}; | 39 | std::scoped_lock lock{mutex}; |
| 40 | const auto [pair, is_new] = cache.try_emplace(key); | 40 | const auto [pair, is_new] = cache.try_emplace(key); |
| 41 | if (!is_new) { | 41 | if (!is_new) { |
| 42 | return *pair->second; | 42 | return *pair->second; |
diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp index ad320991b..6a9416457 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.cpp +++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp | |||
| @@ -73,7 +73,7 @@ void VKScheduler::DispatchWork() { | |||
| 73 | return; | 73 | return; |
| 74 | } | 74 | } |
| 75 | { | 75 | { |
| 76 | std::lock_guard lock{work_mutex}; | 76 | std::scoped_lock lock{work_mutex}; |
| 77 | work_queue.push(std::move(chunk)); | 77 | work_queue.push(std::move(chunk)); |
| 78 | } | 78 | } |
| 79 | work_cv.notify_one(); | 79 | work_cv.notify_one(); |
| @@ -157,7 +157,7 @@ void VKScheduler::WorkerThread(std::stop_token stop_token) { | |||
| 157 | if (has_submit) { | 157 | if (has_submit) { |
| 158 | AllocateWorkerCommandBuffer(); | 158 | AllocateWorkerCommandBuffer(); |
| 159 | } | 159 | } |
| 160 | std::lock_guard reserve_lock{reserve_mutex}; | 160 | std::scoped_lock reserve_lock{reserve_mutex}; |
| 161 | chunk_reserve.push_back(std::move(work)); | 161 | chunk_reserve.push_back(std::move(work)); |
| 162 | } while (!stop_token.stop_requested()); | 162 | } while (!stop_token.stop_requested()); |
| 163 | } | 163 | } |
| @@ -282,7 +282,7 @@ void VKScheduler::EndRenderPass() { | |||
| 282 | } | 282 | } |
| 283 | 283 | ||
| 284 | void VKScheduler::AcquireNewChunk() { | 284 | void VKScheduler::AcquireNewChunk() { |
| 285 | std::lock_guard lock{reserve_mutex}; | 285 | std::scoped_lock lock{reserve_mutex}; |
| 286 | if (chunk_reserve.empty()) { | 286 | if (chunk_reserve.empty()) { |
| 287 | chunk = std::make_unique<CommandChunk>(); | 287 | chunk = std::make_unique<CommandChunk>(); |
| 288 | return; | 288 | return; |
diff --git a/src/video_core/shader_cache.cpp b/src/video_core/shader_cache.cpp index 87636857d..75031767a 100644 --- a/src/video_core/shader_cache.cpp +++ b/src/video_core/shader_cache.cpp | |||
| @@ -25,7 +25,7 @@ void ShaderCache::InvalidateRegion(VAddr addr, size_t size) { | |||
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | void ShaderCache::OnCPUWrite(VAddr addr, size_t size) { | 27 | void ShaderCache::OnCPUWrite(VAddr addr, size_t size) { |
| 28 | std::lock_guard lock{invalidation_mutex}; | 28 | std::scoped_lock lock{invalidation_mutex}; |
| 29 | InvalidatePagesInRegion(addr, size); | 29 | InvalidatePagesInRegion(addr, size); |
| 30 | } | 30 | } |
| 31 | 31 | ||
diff --git a/src/web_service/web_backend.cpp b/src/web_service/web_backend.cpp index 4208bd044..58b0c2f10 100644 --- a/src/web_service/web_backend.cpp +++ b/src/web_service/web_backend.cpp | |||
| @@ -32,7 +32,7 @@ constexpr std::size_t TIMEOUT_SECONDS = 30; | |||
| 32 | struct Client::Impl { | 32 | struct Client::Impl { |
| 33 | Impl(std::string host, std::string username, std::string token) | 33 | Impl(std::string host, std::string username, std::string token) |
| 34 | : host{std::move(host)}, username{std::move(username)}, token{std::move(token)} { | 34 | : host{std::move(host)}, username{std::move(username)}, token{std::move(token)} { |
| 35 | std::lock_guard lock{jwt_cache.mutex}; | 35 | std::scoped_lock lock{jwt_cache.mutex}; |
| 36 | if (this->username == jwt_cache.username && this->token == jwt_cache.token) { | 36 | if (this->username == jwt_cache.username && this->token == jwt_cache.token) { |
| 37 | jwt = jwt_cache.jwt; | 37 | jwt = jwt_cache.jwt; |
| 38 | } | 38 | } |
| @@ -147,7 +147,7 @@ struct Client::Impl { | |||
| 147 | if (result.result_code != WebResult::Code::Success) { | 147 | if (result.result_code != WebResult::Code::Success) { |
| 148 | LOG_ERROR(WebService, "UpdateJWT failed"); | 148 | LOG_ERROR(WebService, "UpdateJWT failed"); |
| 149 | } else { | 149 | } else { |
| 150 | std::lock_guard lock{jwt_cache.mutex}; | 150 | std::scoped_lock lock{jwt_cache.mutex}; |
| 151 | jwt_cache.username = username; | 151 | jwt_cache.username = username; |
| 152 | jwt_cache.token = token; | 152 | jwt_cache.token = token; |
| 153 | jwt_cache.jwt = jwt = result.returned_data; | 153 | jwt_cache.jwt = jwt = result.returned_data; |
diff --git a/src/yuzu/util/controller_navigation.cpp b/src/yuzu/util/controller_navigation.cpp index c2b13123d..9a1868cae 100644 --- a/src/yuzu/util/controller_navigation.cpp +++ b/src/yuzu/util/controller_navigation.cpp | |||
| @@ -39,7 +39,7 @@ void ControllerNavigation::TriggerButton(Settings::NativeButton::Values native_b | |||
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | void ControllerNavigation::ControllerUpdateEvent(Core::HID::ControllerTriggerType type) { | 41 | void ControllerNavigation::ControllerUpdateEvent(Core::HID::ControllerTriggerType type) { |
| 42 | std::lock_guard lock{mutex}; | 42 | std::scoped_lock lock{mutex}; |
| 43 | if (!Settings::values.controller_navigation) { | 43 | if (!Settings::values.controller_navigation) { |
| 44 | return; | 44 | return; |
| 45 | } | 45 | } |