summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/bit_util.h6
-rw-r--r--src/common/fiber.cpp5
-rw-r--r--src/common/input.h7
-rw-r--r--src/core/CMakeLists.txt3
-rw-r--r--src/core/hid/emulated_console.cpp2
-rw-r--r--src/core/hid/emulated_controller.cpp2
-rw-r--r--src/core/hid/input_converter.cpp2
-rw-r--r--src/core/hle/kernel/k_memory_manager.cpp15
-rw-r--r--src/core/hle/kernel/k_memory_manager.h15
-rw-r--r--src/core/hle/kernel/k_page_table.cpp17
-rw-r--r--src/core/hle/kernel/k_page_table.h1
-rw-r--r--src/core/hle/kernel/k_process.cpp6
-rw-r--r--src/core/hle/kernel/k_process.h6
-rw-r--r--src/core/hle/kernel/k_scheduler.cpp2
-rw-r--r--src/core/hle/kernel/k_thread.cpp78
-rw-r--r--src/core/hle/kernel/k_thread.h11
-rw-r--r--src/core/hle/kernel/k_worker_task.h18
-rw-r--r--src/core/hle/kernel/k_worker_task_manager.cpp42
-rw-r--r--src/core/hle/kernel/k_worker_task_manager.h33
-rw-r--r--src/core/hle/kernel/kernel.cpp13
-rw-r--r--src/core/hle/kernel/kernel.h7
-rw-r--r--src/core/hle/service/hid/hid.cpp3
-rw-r--r--src/input_common/drivers/mouse.cpp35
-rw-r--r--src/input_common/drivers/mouse.h2
-rw-r--r--src/input_common/drivers/sdl_driver.cpp4
-rw-r--r--src/input_common/input_engine.cpp2
-rw-r--r--src/input_common/input_mapping.cpp13
-rw-r--r--src/video_core/command_classes/codecs/codec.h2
-rw-r--r--src/video_core/host_shaders/astc_decoder.comp80
-rw-r--r--src/video_core/vulkan_common/vulkan_device.cpp2
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp10
31 files changed, 342 insertions, 102 deletions
diff --git a/src/common/bit_util.h b/src/common/bit_util.h
index eef8c1c5a..f50d3308a 100644
--- a/src/common/bit_util.h
+++ b/src/common/bit_util.h
@@ -46,6 +46,12 @@ template <typename T>
46} 46}
47 47
48template <typename T> 48template <typename T>
49requires std::is_unsigned_v<T>
50[[nodiscard]] constexpr bool IsPow2(T value) {
51 return std::has_single_bit(value);
52}
53
54template <typename T>
49requires std::is_integral_v<T> 55requires std::is_integral_v<T>
50[[nodiscard]] T NextPow2(T value) { 56[[nodiscard]] T NextPow2(T value) {
51 return static_cast<T>(1ULL << ((8U * sizeof(T)) - std::countl_zero(value - 1U))); 57 return static_cast<T>(1ULL << ((8U * sizeof(T)) - std::countl_zero(value - 1U)));
diff --git a/src/common/fiber.cpp b/src/common/fiber.cpp
index 62010d762..81b212e4b 100644
--- a/src/common/fiber.cpp
+++ b/src/common/fiber.cpp
@@ -124,7 +124,10 @@ void Fiber::YieldTo(std::weak_ptr<Fiber> weak_from, Fiber& to) {
124 124
125 // "from" might no longer be valid if the thread was killed 125 // "from" might no longer be valid if the thread was killed
126 if (auto from = weak_from.lock()) { 126 if (auto from = weak_from.lock()) {
127 ASSERT(from->impl->previous_fiber != nullptr); 127 if (from->impl->previous_fiber == nullptr) {
128 ASSERT_MSG(false, "previous_fiber is nullptr!");
129 return;
130 }
128 from->impl->previous_fiber->impl->context = transfer.fctx; 131 from->impl->previous_fiber->impl->context = transfer.fctx;
129 from->impl->previous_fiber->impl->guard.unlock(); 132 from->impl->previous_fiber->impl->guard.unlock();
130 from->impl->previous_fiber.reset(); 133 from->impl->previous_fiber.reset();
diff --git a/src/common/input.h b/src/common/input.h
index f775a4c01..f4f9eb30a 100644
--- a/src/common/input.h
+++ b/src/common/input.h
@@ -209,6 +209,13 @@ enum class ButtonNames {
209 Triangle, 209 Triangle,
210 Share, 210 Share,
211 Options, 211 Options,
212
213 // Mouse buttons
214 ButtonMouseWheel,
215 ButtonBackward,
216 ButtonForward,
217 ButtonTask,
218 ButtonExtra,
212}; 219};
213 220
214// Callback data consisting of an input type and the equivalent data status 221// Callback data consisting of an input type and the equivalent data status
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index b1a746727..6e8d11919 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -247,6 +247,9 @@ add_library(core STATIC
247 hle/kernel/k_trace.h 247 hle/kernel/k_trace.h
248 hle/kernel/k_transfer_memory.cpp 248 hle/kernel/k_transfer_memory.cpp
249 hle/kernel/k_transfer_memory.h 249 hle/kernel/k_transfer_memory.h
250 hle/kernel/k_worker_task.h
251 hle/kernel/k_worker_task_manager.cpp
252 hle/kernel/k_worker_task_manager.h
250 hle/kernel/k_writable_event.cpp 253 hle/kernel/k_writable_event.cpp
251 hle/kernel/k_writable_event.h 254 hle/kernel/k_writable_event.h
252 hle/kernel/kernel.cpp 255 hle/kernel/kernel.cpp
diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp
index 08f8af551..eef0ff493 100644
--- a/src/core/hid/emulated_console.cpp
+++ b/src/core/hid/emulated_console.cpp
@@ -158,7 +158,7 @@ void EmulatedConsole::SetMotion(const Common::Input::CallbackStatus& callback) {
158 auto& motion = console.motion_state; 158 auto& motion = console.motion_state;
159 motion.accel = emulated.GetAcceleration(); 159 motion.accel = emulated.GetAcceleration();
160 motion.gyro = emulated.GetGyroscope(); 160 motion.gyro = emulated.GetGyroscope();
161 motion.rotation = emulated.GetGyroscope(); 161 motion.rotation = emulated.GetRotations();
162 motion.orientation = emulated.GetOrientation(); 162 motion.orientation = emulated.GetOrientation();
163 motion.quaternion = emulated.GetQuaternion(); 163 motion.quaternion = emulated.GetQuaternion();
164 motion.gyro_bias = emulated.GetGyroBias(); 164 motion.gyro_bias = emulated.GetGyroBias();
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index 13edb7332..d12037b11 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -145,7 +145,7 @@ void EmulatedController::LoadDevices() {
145 motion_devices.begin(), Common::Input::CreateDevice<Common::Input::InputDevice>); 145 motion_devices.begin(), Common::Input::CreateDevice<Common::Input::InputDevice>);
146 std::transform(trigger_params.begin(), trigger_params.end(), trigger_devices.begin(), 146 std::transform(trigger_params.begin(), trigger_params.end(), trigger_devices.begin(),
147 Common::Input::CreateDevice<Common::Input::InputDevice>); 147 Common::Input::CreateDevice<Common::Input::InputDevice>);
148 std::transform(battery_params.begin(), battery_params.begin(), battery_devices.end(), 148 std::transform(battery_params.begin(), battery_params.end(), battery_devices.begin(),
149 Common::Input::CreateDevice<Common::Input::InputDevice>); 149 Common::Input::CreateDevice<Common::Input::InputDevice>);
150 std::transform(output_params.begin(), output_params.end(), output_devices.begin(), 150 std::transform(output_params.begin(), output_params.end(), output_devices.begin(),
151 Common::Input::CreateDevice<Common::Input::OutputDevice>); 151 Common::Input::CreateDevice<Common::Input::OutputDevice>);
diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp
index f5acff6e0..860aab400 100644
--- a/src/core/hid/input_converter.cpp
+++ b/src/core/hid/input_converter.cpp
@@ -114,7 +114,7 @@ Common::Input::MotionStatus TransformToMotion(const Common::Input::CallbackStatu
114 if (TransformToButton(callback).value) { 114 if (TransformToButton(callback).value) {
115 std::random_device device; 115 std::random_device device;
116 std::mt19937 gen(device()); 116 std::mt19937 gen(device());
117 std::uniform_int_distribution<s16> distribution(-1000, 1000); 117 std::uniform_int_distribution<s16> distribution(-5000, 5000);
118 status.accel.x.raw_value = static_cast<f32>(distribution(gen)) * 0.001f; 118 status.accel.x.raw_value = static_cast<f32>(distribution(gen)) * 0.001f;
119 status.accel.y.raw_value = static_cast<f32>(distribution(gen)) * 0.001f; 119 status.accel.y.raw_value = static_cast<f32>(distribution(gen)) * 0.001f;
120 status.accel.z.raw_value = static_cast<f32>(distribution(gen)) * 0.001f; 120 status.accel.z.raw_value = static_cast<f32>(distribution(gen)) * 0.001f;
diff --git a/src/core/hle/kernel/k_memory_manager.cpp b/src/core/hle/kernel/k_memory_manager.cpp
index 0166df0a5..1b44541b1 100644
--- a/src/core/hle/kernel/k_memory_manager.cpp
+++ b/src/core/hle/kernel/k_memory_manager.cpp
@@ -8,12 +8,16 @@
8#include "common/assert.h" 8#include "common/assert.h"
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "common/scope_exit.h" 10#include "common/scope_exit.h"
11#include "core/core.h"
12#include "core/device_memory.h"
11#include "core/hle/kernel/k_memory_manager.h" 13#include "core/hle/kernel/k_memory_manager.h"
12#include "core/hle/kernel/k_page_linked_list.h" 14#include "core/hle/kernel/k_page_linked_list.h"
13#include "core/hle/kernel/svc_results.h" 15#include "core/hle/kernel/svc_results.h"
14 16
15namespace Kernel { 17namespace Kernel {
16 18
19KMemoryManager::KMemoryManager(Core::System& system_) : system{system_} {}
20
17std::size_t KMemoryManager::Impl::Initialize(Pool new_pool, u64 start_address, u64 end_address) { 21std::size_t KMemoryManager::Impl::Initialize(Pool new_pool, u64 start_address, u64 end_address) {
18 const auto size{end_address - start_address}; 22 const auto size{end_address - start_address};
19 23
@@ -81,7 +85,7 @@ VAddr KMemoryManager::AllocateAndOpenContinuous(std::size_t num_pages, std::size
81} 85}
82 86
83ResultCode KMemoryManager::Allocate(KPageLinkedList& page_list, std::size_t num_pages, Pool pool, 87ResultCode KMemoryManager::Allocate(KPageLinkedList& page_list, std::size_t num_pages, Pool pool,
84 Direction dir) { 88 Direction dir, u32 heap_fill_value) {
85 ASSERT(page_list.GetNumPages() == 0); 89 ASSERT(page_list.GetNumPages() == 0);
86 90
87 // Early return if we're allocating no pages 91 // Early return if we're allocating no pages
@@ -139,6 +143,12 @@ ResultCode KMemoryManager::Allocate(KPageLinkedList& page_list, std::size_t num_
139 } 143 }
140 } 144 }
141 145
146 // Clear allocated memory.
147 for (const auto& it : page_list.Nodes()) {
148 std::memset(system.DeviceMemory().GetPointer(it.GetAddress()), heap_fill_value,
149 it.GetSize());
150 }
151
142 // Only succeed if we allocated as many pages as we wanted 152 // Only succeed if we allocated as many pages as we wanted
143 if (num_pages) { 153 if (num_pages) {
144 return ResultOutOfMemory; 154 return ResultOutOfMemory;
@@ -146,11 +156,12 @@ ResultCode KMemoryManager::Allocate(KPageLinkedList& page_list, std::size_t num_
146 156
147 // We succeeded! 157 // We succeeded!
148 group_guard.Cancel(); 158 group_guard.Cancel();
159
149 return ResultSuccess; 160 return ResultSuccess;
150} 161}
151 162
152ResultCode KMemoryManager::Free(KPageLinkedList& page_list, std::size_t num_pages, Pool pool, 163ResultCode KMemoryManager::Free(KPageLinkedList& page_list, std::size_t num_pages, Pool pool,
153 Direction dir) { 164 Direction dir, u32 heap_fill_value) {
154 // Early return if we're freeing no pages 165 // Early return if we're freeing no pages
155 if (!num_pages) { 166 if (!num_pages) {
156 return ResultSuccess; 167 return ResultSuccess;
diff --git a/src/core/hle/kernel/k_memory_manager.h b/src/core/hle/kernel/k_memory_manager.h
index 39badc5f1..abd6c8ace 100644
--- a/src/core/hle/kernel/k_memory_manager.h
+++ b/src/core/hle/kernel/k_memory_manager.h
@@ -12,6 +12,10 @@
12#include "core/hle/kernel/k_page_heap.h" 12#include "core/hle/kernel/k_page_heap.h"
13#include "core/hle/result.h" 13#include "core/hle/result.h"
14 14
15namespace Core {
16class System;
17}
18
15namespace Kernel { 19namespace Kernel {
16 20
17class KPageLinkedList; 21class KPageLinkedList;
@@ -42,7 +46,7 @@ public:
42 Mask = (0xF << Shift), 46 Mask = (0xF << Shift),
43 }; 47 };
44 48
45 KMemoryManager() = default; 49 explicit KMemoryManager(Core::System& system_);
46 50
47 constexpr std::size_t GetSize(Pool pool) const { 51 constexpr std::size_t GetSize(Pool pool) const {
48 return managers[static_cast<std::size_t>(pool)].GetSize(); 52 return managers[static_cast<std::size_t>(pool)].GetSize();
@@ -51,10 +55,10 @@ public:
51 void InitializeManager(Pool pool, u64 start_address, u64 end_address); 55 void InitializeManager(Pool pool, u64 start_address, u64 end_address);
52 56
53 VAddr AllocateAndOpenContinuous(size_t num_pages, size_t align_pages, u32 option); 57 VAddr AllocateAndOpenContinuous(size_t num_pages, size_t align_pages, u32 option);
54 ResultCode Allocate(KPageLinkedList& page_list, std::size_t num_pages, Pool pool, 58 ResultCode Allocate(KPageLinkedList& page_list, std::size_t num_pages, Pool pool, Direction dir,
55 Direction dir = Direction::FromFront); 59 u32 heap_fill_value = 0);
56 ResultCode Free(KPageLinkedList& page_list, std::size_t num_pages, Pool pool, 60 ResultCode Free(KPageLinkedList& page_list, std::size_t num_pages, Pool pool, Direction dir,
57 Direction dir = Direction::FromFront); 61 u32 heap_fill_value = 0);
58 62
59 static constexpr std::size_t MaxManagerCount = 10; 63 static constexpr std::size_t MaxManagerCount = 10;
60 64
@@ -129,6 +133,7 @@ private:
129 }; 133 };
130 134
131private: 135private:
136 Core::System& system;
132 std::array<std::mutex, static_cast<std::size_t>(Pool::Count)> pool_locks; 137 std::array<std::mutex, static_cast<std::size_t>(Pool::Count)> pool_locks;
133 std::array<Impl, MaxManagerCount> managers; 138 std::array<Impl, MaxManagerCount> managers;
134}; 139};
diff --git a/src/core/hle/kernel/k_page_table.cpp b/src/core/hle/kernel/k_page_table.cpp
index 27d86c9a4..b650ea31d 100644
--- a/src/core/hle/kernel/k_page_table.cpp
+++ b/src/core/hle/kernel/k_page_table.cpp
@@ -289,8 +289,8 @@ ResultCode KPageTable::MapProcessCode(VAddr addr, std::size_t num_pages, KMemory
289 } 289 }
290 290
291 KPageLinkedList page_linked_list; 291 KPageLinkedList page_linked_list;
292 CASCADE_CODE( 292 CASCADE_CODE(system.Kernel().MemoryManager().Allocate(page_linked_list, num_pages, memory_pool,
293 system.Kernel().MemoryManager().Allocate(page_linked_list, num_pages, memory_pool)); 293 allocation_option));
294 CASCADE_CODE(Operate(addr, num_pages, page_linked_list, OperationType::MapGroup)); 294 CASCADE_CODE(Operate(addr, num_pages, page_linked_list, OperationType::MapGroup));
295 295
296 block_manager->Update(addr, num_pages, state, perm); 296 block_manager->Update(addr, num_pages, state, perm);
@@ -457,8 +457,8 @@ ResultCode KPageTable::MapPhysicalMemory(VAddr addr, std::size_t size) {
457 457
458 KPageLinkedList page_linked_list; 458 KPageLinkedList page_linked_list;
459 459
460 CASCADE_CODE( 460 CASCADE_CODE(system.Kernel().MemoryManager().Allocate(page_linked_list, remaining_pages,
461 system.Kernel().MemoryManager().Allocate(page_linked_list, remaining_pages, memory_pool)); 461 memory_pool, allocation_option));
462 462
463 // We succeeded, so commit the memory reservation. 463 // We succeeded, so commit the memory reservation.
464 memory_reservation.Commit(); 464 memory_reservation.Commit();
@@ -541,7 +541,8 @@ ResultCode KPageTable::UnmapMemory(VAddr addr, std::size_t size) {
541 } 541 }
542 542
543 const std::size_t num_pages{size / PageSize}; 543 const std::size_t num_pages{size / PageSize};
544 system.Kernel().MemoryManager().Free(page_linked_list, num_pages, memory_pool); 544 system.Kernel().MemoryManager().Free(page_linked_list, num_pages, memory_pool,
545 allocation_option);
545 546
546 block_manager->Update(addr, num_pages, KMemoryState::Free); 547 block_manager->Update(addr, num_pages, KMemoryState::Free);
547 548
@@ -960,7 +961,7 @@ ResultCode KPageTable::SetHeapSize(VAddr* out, std::size_t size) {
960 // Allocate pages for the heap extension. 961 // Allocate pages for the heap extension.
961 KPageLinkedList page_linked_list; 962 KPageLinkedList page_linked_list;
962 R_TRY(system.Kernel().MemoryManager().Allocate(page_linked_list, allocation_size / PageSize, 963 R_TRY(system.Kernel().MemoryManager().Allocate(page_linked_list, allocation_size / PageSize,
963 memory_pool)); 964 memory_pool, allocation_option));
964 965
965 // Map the pages. 966 // Map the pages.
966 { 967 {
@@ -1027,8 +1028,8 @@ ResultVal<VAddr> KPageTable::AllocateAndMapMemory(std::size_t needed_num_pages,
1027 CASCADE_CODE(Operate(addr, needed_num_pages, perm, OperationType::Map, map_addr)); 1028 CASCADE_CODE(Operate(addr, needed_num_pages, perm, OperationType::Map, map_addr));
1028 } else { 1029 } else {
1029 KPageLinkedList page_group; 1030 KPageLinkedList page_group;
1030 CASCADE_CODE( 1031 CASCADE_CODE(system.Kernel().MemoryManager().Allocate(page_group, needed_num_pages,
1031 system.Kernel().MemoryManager().Allocate(page_group, needed_num_pages, memory_pool)); 1032 memory_pool, allocation_option));
1032 CASCADE_CODE(Operate(addr, needed_num_pages, page_group, OperationType::MapGroup)); 1033 CASCADE_CODE(Operate(addr, needed_num_pages, page_group, OperationType::MapGroup));
1033 } 1034 }
1034 1035
diff --git a/src/core/hle/kernel/k_page_table.h b/src/core/hle/kernel/k_page_table.h
index 274644181..f67986e91 100644
--- a/src/core/hle/kernel/k_page_table.h
+++ b/src/core/hle/kernel/k_page_table.h
@@ -303,6 +303,7 @@ private:
303 bool is_aslr_enabled{}; 303 bool is_aslr_enabled{};
304 304
305 KMemoryManager::Pool memory_pool{KMemoryManager::Pool::Application}; 305 KMemoryManager::Pool memory_pool{KMemoryManager::Pool::Application};
306 KMemoryManager::Direction allocation_option{KMemoryManager::Direction::FromFront};
306 307
307 Common::PageTable page_table_impl; 308 Common::PageTable page_table_impl;
308 309
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp
index cca405fed..265ac6fa1 100644
--- a/src/core/hle/kernel/k_process.cpp
+++ b/src/core/hle/kernel/k_process.cpp
@@ -149,6 +149,10 @@ ResultCode KProcess::Initialize(KProcess* process, Core::System& system, std::st
149 return ResultSuccess; 149 return ResultSuccess;
150} 150}
151 151
152void KProcess::DoWorkerTaskImpl() {
153 UNIMPLEMENTED();
154}
155
152KResourceLimit* KProcess::GetResourceLimit() const { 156KResourceLimit* KProcess::GetResourceLimit() const {
153 return resource_limit; 157 return resource_limit;
154} 158}
@@ -477,7 +481,7 @@ void KProcess::Finalize() {
477 } 481 }
478 482
479 // Perform inherited finalization. 483 // Perform inherited finalization.
480 KAutoObjectWithSlabHeapAndContainer<KProcess, KSynchronizationObject>::Finalize(); 484 KAutoObjectWithSlabHeapAndContainer<KProcess, KWorkerTask>::Finalize();
481} 485}
482 486
483/** 487/**
diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h
index e7c8b5838..c2a672021 100644
--- a/src/core/hle/kernel/k_process.h
+++ b/src/core/hle/kernel/k_process.h
@@ -15,6 +15,7 @@
15#include "core/hle/kernel/k_condition_variable.h" 15#include "core/hle/kernel/k_condition_variable.h"
16#include "core/hle/kernel/k_handle_table.h" 16#include "core/hle/kernel/k_handle_table.h"
17#include "core/hle/kernel/k_synchronization_object.h" 17#include "core/hle/kernel/k_synchronization_object.h"
18#include "core/hle/kernel/k_worker_task.h"
18#include "core/hle/kernel/process_capability.h" 19#include "core/hle/kernel/process_capability.h"
19#include "core/hle/kernel/slab_helpers.h" 20#include "core/hle/kernel/slab_helpers.h"
20#include "core/hle/result.h" 21#include "core/hle/result.h"
@@ -62,8 +63,7 @@ enum class ProcessStatus {
62 DebugBreak, 63 DebugBreak,
63}; 64};
64 65
65class KProcess final 66class KProcess final : public KAutoObjectWithSlabHeapAndContainer<KProcess, KWorkerTask> {
66 : public KAutoObjectWithSlabHeapAndContainer<KProcess, KSynchronizationObject> {
67 KERNEL_AUTOOBJECT_TRAITS(KProcess, KSynchronizationObject); 67 KERNEL_AUTOOBJECT_TRAITS(KProcess, KSynchronizationObject);
68 68
69public: 69public:
@@ -345,6 +345,8 @@ public:
345 345
346 bool IsSignaled() const override; 346 bool IsSignaled() const override;
347 347
348 void DoWorkerTaskImpl();
349
348 void PinCurrentThread(s32 core_id); 350 void PinCurrentThread(s32 core_id);
349 void UnpinCurrentThread(s32 core_id); 351 void UnpinCurrentThread(s32 core_id);
350 void UnpinThread(KThread* thread); 352 void UnpinThread(KThread* thread);
diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp
index 31cec990e..f900b2e7a 100644
--- a/src/core/hle/kernel/k_scheduler.cpp
+++ b/src/core/hle/kernel/k_scheduler.cpp
@@ -49,8 +49,6 @@ void KScheduler::RescheduleCores(KernelCore& kernel, u64 cores_pending_reschedul
49 if (!must_context_switch || core != current_core) { 49 if (!must_context_switch || core != current_core) {
50 auto& phys_core = kernel.PhysicalCore(core); 50 auto& phys_core = kernel.PhysicalCore(core);
51 phys_core.Interrupt(); 51 phys_core.Interrupt();
52 } else {
53 must_context_switch = true;
54 } 52 }
55 cores_pending_reschedule &= ~(1ULL << core); 53 cores_pending_reschedule &= ~(1ULL << core);
56 } 54 }
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp
index 71e029a3f..7a5e6fc08 100644
--- a/src/core/hle/kernel/k_thread.cpp
+++ b/src/core/hle/kernel/k_thread.cpp
@@ -30,6 +30,7 @@
30#include "core/hle/kernel/k_system_control.h" 30#include "core/hle/kernel/k_system_control.h"
31#include "core/hle/kernel/k_thread.h" 31#include "core/hle/kernel/k_thread.h"
32#include "core/hle/kernel/k_thread_queue.h" 32#include "core/hle/kernel/k_thread_queue.h"
33#include "core/hle/kernel/k_worker_task_manager.h"
33#include "core/hle/kernel/kernel.h" 34#include "core/hle/kernel/kernel.h"
34#include "core/hle/kernel/svc_results.h" 35#include "core/hle/kernel/svc_results.h"
35#include "core/hle/kernel/time_manager.h" 36#include "core/hle/kernel/time_manager.h"
@@ -332,7 +333,7 @@ void KThread::Finalize() {
332 } 333 }
333 334
334 // Perform inherited finalization. 335 // Perform inherited finalization.
335 KAutoObjectWithSlabHeapAndContainer<KThread, KSynchronizationObject>::Finalize(); 336 KSynchronizationObject::Finalize();
336} 337}
337 338
338bool KThread::IsSignaled() const { 339bool KThread::IsSignaled() const {
@@ -376,11 +377,28 @@ void KThread::StartTermination() {
376 377
377 // Register terminated dpc flag. 378 // Register terminated dpc flag.
378 RegisterDpc(DpcFlag::Terminated); 379 RegisterDpc(DpcFlag::Terminated);
380}
381
382void KThread::FinishTermination() {
383 // Ensure that the thread is not executing on any core.
384 if (parent != nullptr) {
385 for (std::size_t i = 0; i < static_cast<std::size_t>(Core::Hardware::NUM_CPU_CORES); ++i) {
386 KThread* core_thread{};
387 do {
388 core_thread = kernel.Scheduler(i).GetCurrentThread();
389 } while (core_thread == this);
390 }
391 }
379 392
380 // Close the thread. 393 // Close the thread.
381 this->Close(); 394 this->Close();
382} 395}
383 396
397void KThread::DoWorkerTaskImpl() {
398 // Finish the termination that was begun by Exit().
399 this->FinishTermination();
400}
401
384void KThread::Pin(s32 current_core) { 402void KThread::Pin(s32 current_core) {
385 ASSERT(kernel.GlobalSchedulerContext().IsLocked()); 403 ASSERT(kernel.GlobalSchedulerContext().IsLocked());
386 404
@@ -417,12 +435,7 @@ void KThread::Pin(s32 current_core) {
417 static_cast<u32>(ThreadState::SuspendShift))); 435 static_cast<u32>(ThreadState::SuspendShift)));
418 436
419 // Update our state. 437 // Update our state.
420 const ThreadState old_state = thread_state; 438 UpdateState();
421 thread_state = static_cast<ThreadState>(GetSuspendFlags() |
422 static_cast<u32>(old_state & ThreadState::Mask));
423 if (thread_state != old_state) {
424 KScheduler::OnThreadStateChanged(kernel, this, old_state);
425 }
426 } 439 }
427 440
428 // TODO(bunnei): Update our SVC access permissions. 441 // TODO(bunnei): Update our SVC access permissions.
@@ -463,20 +476,13 @@ void KThread::Unpin() {
463 } 476 }
464 477
465 // Allow performing thread suspension (if termination hasn't been requested). 478 // Allow performing thread suspension (if termination hasn't been requested).
466 { 479 if (!IsTerminationRequested()) {
467 // Update our allow flags. 480 // Update our allow flags.
468 if (!IsTerminationRequested()) { 481 suspend_allowed_flags |= (1 << (static_cast<u32>(SuspendType::Thread) +
469 suspend_allowed_flags |= (1 << (static_cast<u32>(SuspendType::Thread) + 482 static_cast<u32>(ThreadState::SuspendShift)));
470 static_cast<u32>(ThreadState::SuspendShift)));
471 }
472 483
473 // Update our state. 484 // Update our state.
474 const ThreadState old_state = thread_state; 485 UpdateState();
475 thread_state = static_cast<ThreadState>(GetSuspendFlags() |
476 static_cast<u32>(old_state & ThreadState::Mask));
477 if (thread_state != old_state) {
478 KScheduler::OnThreadStateChanged(kernel, this, old_state);
479 }
480 } 486 }
481 487
482 // TODO(bunnei): Update our SVC access permissions. 488 // TODO(bunnei): Update our SVC access permissions.
@@ -689,12 +695,7 @@ void KThread::Resume(SuspendType type) {
689 ~(1u << (static_cast<u32>(ThreadState::SuspendShift) + static_cast<u32>(type))); 695 ~(1u << (static_cast<u32>(ThreadState::SuspendShift) + static_cast<u32>(type)));
690 696
691 // Update our state. 697 // Update our state.
692 const ThreadState old_state = thread_state; 698 this->UpdateState();
693 thread_state = static_cast<ThreadState>(GetSuspendFlags() |
694 static_cast<u32>(old_state & ThreadState::Mask));
695 if (thread_state != old_state) {
696 KScheduler::OnThreadStateChanged(kernel, this, old_state);
697 }
698} 699}
699 700
700void KThread::WaitCancel() { 701void KThread::WaitCancel() {
@@ -721,19 +722,22 @@ void KThread::TrySuspend() {
721 ASSERT(GetNumKernelWaiters() == 0); 722 ASSERT(GetNumKernelWaiters() == 0);
722 723
723 // Perform the suspend. 724 // Perform the suspend.
724 Suspend(); 725 this->UpdateState();
725} 726}
726 727
727void KThread::Suspend() { 728void KThread::UpdateState() {
728 ASSERT(kernel.GlobalSchedulerContext().IsLocked()); 729 ASSERT(kernel.GlobalSchedulerContext().IsLocked());
729 ASSERT(IsSuspendRequested());
730 730
731 // Set our suspend flags in state. 731 // Set our suspend flags in state.
732 const auto old_state = thread_state; 732 const auto old_state = thread_state;
733 thread_state = static_cast<ThreadState>(GetSuspendFlags()) | (old_state & ThreadState::Mask); 733 const auto new_state =
734 static_cast<ThreadState>(this->GetSuspendFlags()) | (old_state & ThreadState::Mask);
735 thread_state = new_state;
734 736
735 // Note the state change in scheduler. 737 // Note the state change in scheduler.
736 KScheduler::OnThreadStateChanged(kernel, this, old_state); 738 if (new_state != old_state) {
739 KScheduler::OnThreadStateChanged(kernel, this, old_state);
740 }
737} 741}
738 742
739void KThread::Continue() { 743void KThread::Continue() {
@@ -998,13 +1002,16 @@ ResultCode KThread::Run() {
998 1002
999 // If the current thread has been asked to suspend, suspend it and retry. 1003 // If the current thread has been asked to suspend, suspend it and retry.
1000 if (GetCurrentThread(kernel).IsSuspended()) { 1004 if (GetCurrentThread(kernel).IsSuspended()) {
1001 GetCurrentThread(kernel).Suspend(); 1005 GetCurrentThread(kernel).UpdateState();
1002 continue; 1006 continue;
1003 } 1007 }
1004 1008
1005 // If we're not a kernel thread and we've been asked to suspend, suspend ourselves. 1009 // If we're not a kernel thread and we've been asked to suspend, suspend ourselves.
1006 if (IsUserThread() && IsSuspended()) { 1010 if (KProcess* owner = this->GetOwnerProcess(); owner != nullptr) {
1007 Suspend(); 1011 if (IsUserThread() && IsSuspended()) {
1012 this->UpdateState();
1013 }
1014 owner->IncrementThreadCount();
1008 } 1015 }
1009 1016
1010 // Set our state and finish. 1017 // Set our state and finish.
@@ -1031,9 +1038,16 @@ void KThread::Exit() {
1031 1038
1032 // Disallow all suspension. 1039 // Disallow all suspension.
1033 suspend_allowed_flags = 0; 1040 suspend_allowed_flags = 0;
1041 this->UpdateState();
1042
1043 // Disallow all suspension.
1044 suspend_allowed_flags = 0;
1034 1045
1035 // Start termination. 1046 // Start termination.
1036 StartTermination(); 1047 StartTermination();
1048
1049 // Register the thread as a work task.
1050 KWorkerTaskManager::AddTask(kernel, KWorkerTaskManager::WorkerType::Exit, this);
1037 } 1051 }
1038} 1052}
1039 1053
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h
index 83dfde69b..cc427f6cf 100644
--- a/src/core/hle/kernel/k_thread.h
+++ b/src/core/hle/kernel/k_thread.h
@@ -19,6 +19,7 @@
19#include "core/hle/kernel/k_light_lock.h" 19#include "core/hle/kernel/k_light_lock.h"
20#include "core/hle/kernel/k_spin_lock.h" 20#include "core/hle/kernel/k_spin_lock.h"
21#include "core/hle/kernel/k_synchronization_object.h" 21#include "core/hle/kernel/k_synchronization_object.h"
22#include "core/hle/kernel/k_worker_task.h"
22#include "core/hle/kernel/slab_helpers.h" 23#include "core/hle/kernel/slab_helpers.h"
23#include "core/hle/kernel/svc_common.h" 24#include "core/hle/kernel/svc_common.h"
24#include "core/hle/kernel/svc_types.h" 25#include "core/hle/kernel/svc_types.h"
@@ -100,7 +101,7 @@ enum class ThreadWaitReasonForDebugging : u32 {
100[[nodiscard]] KThread& GetCurrentThread(KernelCore& kernel); 101[[nodiscard]] KThread& GetCurrentThread(KernelCore& kernel);
101[[nodiscard]] s32 GetCurrentCoreId(KernelCore& kernel); 102[[nodiscard]] s32 GetCurrentCoreId(KernelCore& kernel);
102 103
103class KThread final : public KAutoObjectWithSlabHeapAndContainer<KThread, KSynchronizationObject>, 104class KThread final : public KAutoObjectWithSlabHeapAndContainer<KThread, KWorkerTask>,
104 public boost::intrusive::list_base_hook<> { 105 public boost::intrusive::list_base_hook<> {
105 KERNEL_AUTOOBJECT_TRAITS(KThread, KSynchronizationObject); 106 KERNEL_AUTOOBJECT_TRAITS(KThread, KSynchronizationObject);
106 107
@@ -192,9 +193,9 @@ public:
192 193
193 void TrySuspend(); 194 void TrySuspend();
194 195
195 void Continue(); 196 void UpdateState();
196 197
197 void Suspend(); 198 void Continue();
198 199
199 constexpr void SetSyncedIndex(s32 index) { 200 constexpr void SetSyncedIndex(s32 index) {
200 synced_index = index; 201 synced_index = index;
@@ -385,6 +386,8 @@ public:
385 386
386 void OnTimer(); 387 void OnTimer();
387 388
389 void DoWorkerTaskImpl();
390
388 static void PostDestroy(uintptr_t arg); 391 static void PostDestroy(uintptr_t arg);
389 392
390 [[nodiscard]] static ResultCode InitializeDummyThread(KThread* thread); 393 [[nodiscard]] static ResultCode InitializeDummyThread(KThread* thread);
@@ -679,6 +682,8 @@ private:
679 682
680 void StartTermination(); 683 void StartTermination();
681 684
685 void FinishTermination();
686
682 [[nodiscard]] ResultCode Initialize(KThreadFunction func, uintptr_t arg, VAddr user_stack_top, 687 [[nodiscard]] ResultCode Initialize(KThreadFunction func, uintptr_t arg, VAddr user_stack_top,
683 s32 prio, s32 virt_core, KProcess* owner, ThreadType type); 688 s32 prio, s32 virt_core, KProcess* owner, ThreadType type);
684 689
diff --git a/src/core/hle/kernel/k_worker_task.h b/src/core/hle/kernel/k_worker_task.h
new file mode 100644
index 000000000..b7794c6a8
--- /dev/null
+++ b/src/core/hle/kernel/k_worker_task.h
@@ -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#pragma once
6
7#include "core/hle/kernel/k_synchronization_object.h"
8
9namespace Kernel {
10
11class KWorkerTask : public KSynchronizationObject {
12public:
13 explicit KWorkerTask(KernelCore& kernel_);
14
15 void DoWorkerTask();
16};
17
18} // namespace Kernel
diff --git a/src/core/hle/kernel/k_worker_task_manager.cpp b/src/core/hle/kernel/k_worker_task_manager.cpp
new file mode 100644
index 000000000..785e08111
--- /dev/null
+++ b/src/core/hle/kernel/k_worker_task_manager.cpp
@@ -0,0 +1,42 @@
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 "common/assert.h"
6#include "core/hle/kernel/k_process.h"
7#include "core/hle/kernel/k_thread.h"
8#include "core/hle/kernel/k_worker_task.h"
9#include "core/hle/kernel/k_worker_task_manager.h"
10#include "core/hle/kernel/kernel.h"
11
12namespace Kernel {
13
14KWorkerTask::KWorkerTask(KernelCore& kernel_) : KSynchronizationObject{kernel_} {}
15
16void KWorkerTask::DoWorkerTask() {
17 if (auto* const thread = this->DynamicCast<KThread*>(); thread != nullptr) {
18 return thread->DoWorkerTaskImpl();
19 } else {
20 auto* const process = this->DynamicCast<KProcess*>();
21 ASSERT(process != nullptr);
22
23 return process->DoWorkerTaskImpl();
24 }
25}
26
27KWorkerTaskManager::KWorkerTaskManager() : m_waiting_thread(1, "yuzu:KWorkerTaskManager") {}
28
29void KWorkerTaskManager::AddTask(KernelCore& kernel, WorkerType type, KWorkerTask* task) {
30 ASSERT(type <= WorkerType::Count);
31 kernel.WorkerTaskManager().AddTask(kernel, task);
32}
33
34void KWorkerTaskManager::AddTask(KernelCore& kernel, KWorkerTask* task) {
35 KScopedSchedulerLock sl(kernel);
36 m_waiting_thread.QueueWork([task]() {
37 // Do the task.
38 task->DoWorkerTask();
39 });
40}
41
42} // namespace Kernel
diff --git a/src/core/hle/kernel/k_worker_task_manager.h b/src/core/hle/kernel/k_worker_task_manager.h
new file mode 100644
index 000000000..43d1bfcec
--- /dev/null
+++ b/src/core/hle/kernel/k_worker_task_manager.h
@@ -0,0 +1,33 @@
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#include "common/common_types.h"
8#include "common/thread_worker.h"
9
10namespace Kernel {
11
12class KernelCore;
13class KWorkerTask;
14
15class KWorkerTaskManager final {
16public:
17 enum class WorkerType : u32 {
18 Exit,
19 Count,
20 };
21
22 KWorkerTaskManager();
23
24 static void AddTask(KernelCore& kernel_, WorkerType type, KWorkerTask* task);
25
26private:
27 void AddTask(KernelCore& kernel, KWorkerTask* task);
28
29private:
30 Common::ThreadWorker m_waiting_thread;
31};
32
33} // namespace Kernel
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 0b618fb46..887c1fd27 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -37,6 +37,7 @@
37#include "core/hle/kernel/k_shared_memory.h" 37#include "core/hle/kernel/k_shared_memory.h"
38#include "core/hle/kernel/k_slab_heap.h" 38#include "core/hle/kernel/k_slab_heap.h"
39#include "core/hle/kernel/k_thread.h" 39#include "core/hle/kernel/k_thread.h"
40#include "core/hle/kernel/k_worker_task_manager.h"
40#include "core/hle/kernel/kernel.h" 41#include "core/hle/kernel/kernel.h"
41#include "core/hle/kernel/physical_core.h" 42#include "core/hle/kernel/physical_core.h"
42#include "core/hle/kernel/service_thread.h" 43#include "core/hle/kernel/service_thread.h"
@@ -630,7 +631,7 @@ struct KernelCore::Impl {
630 const auto application_pool = memory_layout.GetKernelApplicationPoolRegionPhysicalExtents(); 631 const auto application_pool = memory_layout.GetKernelApplicationPoolRegionPhysicalExtents();
631 632
632 // Initialize memory managers 633 // Initialize memory managers
633 memory_manager = std::make_unique<KMemoryManager>(); 634 memory_manager = std::make_unique<KMemoryManager>(system);
634 memory_manager->InitializeManager(KMemoryManager::Pool::Application, 635 memory_manager->InitializeManager(KMemoryManager::Pool::Application,
635 application_pool.GetAddress(), 636 application_pool.GetAddress(),
636 application_pool.GetEndAddress()); 637 application_pool.GetEndAddress());
@@ -797,6 +798,8 @@ struct KernelCore::Impl {
797 798
798 std::array<u64, Core::Hardware::NUM_CPU_CORES> svc_ticks{}; 799 std::array<u64, Core::Hardware::NUM_CPU_CORES> svc_ticks{};
799 800
801 KWorkerTaskManager worker_task_manager;
802
800 // System context 803 // System context
801 Core::System& system; 804 Core::System& system;
802}; 805};
@@ -1137,6 +1140,14 @@ const Init::KSlabResourceCounts& KernelCore::SlabResourceCounts() const {
1137 return impl->slab_resource_counts; 1140 return impl->slab_resource_counts;
1138} 1141}
1139 1142
1143KWorkerTaskManager& KernelCore::WorkerTaskManager() {
1144 return impl->worker_task_manager;
1145}
1146
1147const KWorkerTaskManager& KernelCore::WorkerTaskManager() const {
1148 return impl->worker_task_manager;
1149}
1150
1140bool KernelCore::IsPhantomModeForSingleCore() const { 1151bool KernelCore::IsPhantomModeForSingleCore() const {
1141 return impl->IsPhantomModeForSingleCore(); 1152 return impl->IsPhantomModeForSingleCore();
1142} 1153}
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index b9b423908..0e04fc3bb 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -52,6 +52,7 @@ class KSharedMemory;
52class KSharedMemoryInfo; 52class KSharedMemoryInfo;
53class KThread; 53class KThread;
54class KTransferMemory; 54class KTransferMemory;
55class KWorkerTaskManager;
55class KWritableEvent; 56class KWritableEvent;
56class KCodeMemory; 57class KCodeMemory;
57class PhysicalCore; 58class PhysicalCore;
@@ -343,6 +344,12 @@ public:
343 /// Gets the current slab resource counts. 344 /// Gets the current slab resource counts.
344 const Init::KSlabResourceCounts& SlabResourceCounts() const; 345 const Init::KSlabResourceCounts& SlabResourceCounts() const;
345 346
347 /// Gets the current worker task manager, used for dispatching KThread/KProcess tasks.
348 KWorkerTaskManager& WorkerTaskManager();
349
350 /// Gets the current worker task manager, used for dispatching KThread/KProcess tasks.
351 const KWorkerTaskManager& WorkerTaskManager() const;
352
346private: 353private:
347 friend class KProcess; 354 friend class KProcess;
348 friend class KThread; 355 friend class KThread;
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 84da38b3b..a2bf7defb 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -1176,7 +1176,8 @@ void Hid::SetNpadAnalogStickUseCenterClamp(Kernel::HLERequestContext& ctx) {
1176 1176
1177 const auto parameters{rp.PopRaw<Parameters>()}; 1177 const auto parameters{rp.PopRaw<Parameters>()};
1178 1178
1179 applet_resource->GetController<Controller_NPad>(HidController::NPad) 1179 GetAppletResource()
1180 ->GetController<Controller_NPad>(HidController::NPad)
1180 .SetAnalogStickUseCenterClamp(parameters.analog_stick_use_center_clamp); 1181 .SetAnalogStickUseCenterClamp(parameters.analog_stick_use_center_clamp);
1181 1182
1182 LOG_WARNING(Service_HID, 1183 LOG_WARNING(Service_HID,
diff --git a/src/input_common/drivers/mouse.cpp b/src/input_common/drivers/mouse.cpp
index aa69216c8..d8ae7f0c1 100644
--- a/src/input_common/drivers/mouse.cpp
+++ b/src/input_common/drivers/mouse.cpp
@@ -16,6 +16,7 @@ constexpr int mouse_axis_x = 0;
16constexpr int mouse_axis_y = 1; 16constexpr int mouse_axis_y = 1;
17constexpr int wheel_axis_x = 2; 17constexpr int wheel_axis_x = 2;
18constexpr int wheel_axis_y = 3; 18constexpr int wheel_axis_y = 3;
19constexpr int motion_wheel_y = 4;
19constexpr int touch_axis_x = 10; 20constexpr int touch_axis_x = 10;
20constexpr int touch_axis_y = 11; 21constexpr int touch_axis_y = 11;
21constexpr PadIdentifier identifier = { 22constexpr PadIdentifier identifier = {
@@ -30,8 +31,9 @@ Mouse::Mouse(std::string input_engine_) : InputEngine(std::move(input_engine_))
30 PreSetAxis(identifier, mouse_axis_y); 31 PreSetAxis(identifier, mouse_axis_y);
31 PreSetAxis(identifier, wheel_axis_x); 32 PreSetAxis(identifier, wheel_axis_x);
32 PreSetAxis(identifier, wheel_axis_y); 33 PreSetAxis(identifier, wheel_axis_y);
34 PreSetAxis(identifier, motion_wheel_y);
33 PreSetAxis(identifier, touch_axis_x); 35 PreSetAxis(identifier, touch_axis_x);
34 PreSetAxis(identifier, touch_axis_x); 36 PreSetAxis(identifier, touch_axis_y);
35 update_thread = std::jthread([this](std::stop_token stop_token) { UpdateThread(stop_token); }); 37 update_thread = std::jthread([this](std::stop_token stop_token) { UpdateThread(stop_token); });
36} 38}
37 39
@@ -48,6 +50,8 @@ void Mouse::UpdateThread(std::stop_token stop_token) {
48 SetAxis(identifier, mouse_axis_y, -last_mouse_change.y * sensitivity); 50 SetAxis(identifier, mouse_axis_y, -last_mouse_change.y * sensitivity);
49 } 51 }
50 52
53 SetAxis(identifier, motion_wheel_y, 0.0f);
54
51 if (mouse_panning_timout++ > 20) { 55 if (mouse_panning_timout++ > 20) {
52 StopPanning(); 56 StopPanning();
53 } 57 }
@@ -136,6 +140,7 @@ void Mouse::MouseWheelChange(int x, int y) {
136 wheel_position.y += y; 140 wheel_position.y += y;
137 SetAxis(identifier, wheel_axis_x, static_cast<f32>(wheel_position.x)); 141 SetAxis(identifier, wheel_axis_x, static_cast<f32>(wheel_position.x));
138 SetAxis(identifier, wheel_axis_y, static_cast<f32>(wheel_position.y)); 142 SetAxis(identifier, wheel_axis_y, static_cast<f32>(wheel_position.y));
143 SetAxis(identifier, motion_wheel_y, static_cast<f32>(y) / 100.0f);
139} 144}
140 145
141void Mouse::ReleaseAllButtons() { 146void Mouse::ReleaseAllButtons() {
@@ -171,13 +176,39 @@ AnalogMapping Mouse::GetAnalogMappingForDevice(
171 return mapping; 176 return mapping;
172} 177}
173 178
179Common::Input::ButtonNames Mouse::GetUIButtonName(const Common::ParamPackage& params) const {
180 const auto button = static_cast<MouseButton>(params.Get("button", 0));
181 switch (button) {
182 case MouseButton::Left:
183 return Common::Input::ButtonNames::ButtonLeft;
184 case MouseButton::Right:
185 return Common::Input::ButtonNames::ButtonRight;
186 case MouseButton::Wheel:
187 return Common::Input::ButtonNames::ButtonMouseWheel;
188 case MouseButton::Backward:
189 return Common::Input::ButtonNames::ButtonBackward;
190 case MouseButton::Forward:
191 return Common::Input::ButtonNames::ButtonForward;
192 case MouseButton::Task:
193 return Common::Input::ButtonNames::ButtonTask;
194 case MouseButton::Extra:
195 return Common::Input::ButtonNames::ButtonExtra;
196 case MouseButton::Undefined:
197 default:
198 return Common::Input::ButtonNames::Undefined;
199 }
200}
201
174Common::Input::ButtonNames Mouse::GetUIName(const Common::ParamPackage& params) const { 202Common::Input::ButtonNames Mouse::GetUIName(const Common::ParamPackage& params) const {
175 if (params.Has("button")) { 203 if (params.Has("button")) {
176 return Common::Input::ButtonNames::Value; 204 return GetUIButtonName(params);
177 } 205 }
178 if (params.Has("axis")) { 206 if (params.Has("axis")) {
179 return Common::Input::ButtonNames::Value; 207 return Common::Input::ButtonNames::Value;
180 } 208 }
209 if (params.Has("axis_x") && params.Has("axis_y") && params.Has("axis_z")) {
210 return Common::Input::ButtonNames::Engine;
211 }
181 212
182 return Common::Input::ButtonNames::Invalid; 213 return Common::Input::ButtonNames::Invalid;
183} 214}
diff --git a/src/input_common/drivers/mouse.h b/src/input_common/drivers/mouse.h
index 040446178..c5833b8ed 100644
--- a/src/input_common/drivers/mouse.h
+++ b/src/input_common/drivers/mouse.h
@@ -69,6 +69,8 @@ private:
69 void UpdateThread(std::stop_token stop_token); 69 void UpdateThread(std::stop_token stop_token);
70 void StopPanning(); 70 void StopPanning();
71 71
72 Common::Input::ButtonNames GetUIButtonName(const Common::ParamPackage& params) const;
73
72 Common::Vec2<int> mouse_origin; 74 Common::Vec2<int> mouse_origin;
73 Common::Vec2<int> last_mouse_position; 75 Common::Vec2<int> last_mouse_position;
74 Common::Vec2<float> last_mouse_change; 76 Common::Vec2<float> last_mouse_change;
diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp
index 41701e24d..ed6281772 100644
--- a/src/input_common/drivers/sdl_driver.cpp
+++ b/src/input_common/drivers/sdl_driver.cpp
@@ -198,9 +198,9 @@ public:
198 if (sdl_controller) { 198 if (sdl_controller) {
199 switch (SDL_GameControllerGetType(sdl_controller.get())) { 199 switch (SDL_GameControllerGetType(sdl_controller.get())) {
200 case SDL_CONTROLLER_TYPE_XBOX360: 200 case SDL_CONTROLLER_TYPE_XBOX360:
201 return "XBox 360 Controller"; 201 return "Xbox 360 Controller";
202 case SDL_CONTROLLER_TYPE_XBOXONE: 202 case SDL_CONTROLLER_TYPE_XBOXONE:
203 return "XBox One Controller"; 203 return "Xbox One Controller";
204 case SDL_CONTROLLER_TYPE_PS3: 204 case SDL_CONTROLLER_TYPE_PS3:
205 return "DualShock 3 Controller"; 205 return "DualShock 3 Controller";
206 case SDL_CONTROLLER_TYPE_PS4: 206 case SDL_CONTROLLER_TYPE_PS4:
diff --git a/src/input_common/input_engine.cpp b/src/input_common/input_engine.cpp
index b57330e51..0508b408d 100644
--- a/src/input_common/input_engine.cpp
+++ b/src/input_common/input_engine.cpp
@@ -173,7 +173,7 @@ void InputEngine::ResetButtonState() {
173 SetButton(controller.first, button.first, false); 173 SetButton(controller.first, button.first, false);
174 } 174 }
175 for (const auto& button : controller.second.hat_buttons) { 175 for (const auto& button : controller.second.hat_buttons) {
176 SetHatButton(controller.first, button.first, false); 176 SetHatButton(controller.first, button.first, 0);
177 } 177 }
178 } 178 }
179} 179}
diff --git a/src/input_common/input_mapping.cpp b/src/input_common/input_mapping.cpp
index 6e0024b2d..475257f42 100644
--- a/src/input_common/input_mapping.cpp
+++ b/src/input_common/input_mapping.cpp
@@ -143,6 +143,19 @@ void MappingFactory::RegisterMotion(const MappingData& data) {
143 } 143 }
144 new_input.Set("port", static_cast<int>(data.pad.port)); 144 new_input.Set("port", static_cast<int>(data.pad.port));
145 new_input.Set("pad", static_cast<int>(data.pad.pad)); 145 new_input.Set("pad", static_cast<int>(data.pad.pad));
146
147 // If engine is mouse map the mouse position as 3 axis motion
148 if (data.engine == "mouse") {
149 new_input.Set("axis_x", 1);
150 new_input.Set("invert_x", "-");
151 new_input.Set("axis_y", 0);
152 new_input.Set("axis_z", 4);
153 new_input.Set("range", 1.0f);
154 new_input.Set("deadzone", 0.0f);
155 input_queue.Push(new_input);
156 return;
157 }
158
146 switch (data.type) { 159 switch (data.type) {
147 case EngineInputType::Button: 160 case EngineInputType::Button:
148 case EngineInputType::HatButton: 161 case EngineInputType::HatButton:
diff --git a/src/video_core/command_classes/codecs/codec.h b/src/video_core/command_classes/codecs/codec.h
index 13ed88382..de5672155 100644
--- a/src/video_core/command_classes/codecs/codec.h
+++ b/src/video_core/command_classes/codecs/codec.h
@@ -66,7 +66,7 @@ private:
66 bool initialized{}; 66 bool initialized{};
67 NvdecCommon::VideoCodec current_codec{NvdecCommon::VideoCodec::None}; 67 NvdecCommon::VideoCodec current_codec{NvdecCommon::VideoCodec::None};
68 68
69 AVCodec* av_codec{nullptr}; 69 const AVCodec* av_codec{nullptr};
70 AVCodecContext* av_codec_ctx{nullptr}; 70 AVCodecContext* av_codec_ctx{nullptr};
71 AVBufferRef* av_gpu_decoder{nullptr}; 71 AVBufferRef* av_gpu_decoder{nullptr};
72 72
diff --git a/src/video_core/host_shaders/astc_decoder.comp b/src/video_core/host_shaders/astc_decoder.comp
index f34c5f5d9..3a10578cb 100644
--- a/src/video_core/host_shaders/astc_decoder.comp
+++ b/src/video_core/host_shaders/astc_decoder.comp
@@ -155,9 +155,6 @@ uint SwizzleOffset(uvec2 pos) {
155// Replicates low num_bits such that [(to_bit - 1):(to_bit - 1 - from_bit)] 155// Replicates low num_bits such that [(to_bit - 1):(to_bit - 1 - from_bit)]
156// is the same as [(num_bits - 1):0] and repeats all the way down. 156// is the same as [(num_bits - 1):0] and repeats all the way down.
157uint Replicate(uint val, uint num_bits, uint to_bit) { 157uint Replicate(uint val, uint num_bits, uint to_bit) {
158 if (num_bits == 0 || to_bit == 0) {
159 return 0;
160 }
161 const uint v = val & uint((1 << num_bits) - 1); 158 const uint v = val & uint((1 << num_bits) - 1);
162 uint res = v; 159 uint res = v;
163 uint reslen = num_bits; 160 uint reslen = num_bits;
@@ -187,42 +184,57 @@ uint ReplicateBitTo9(uint value) {
187 return REPLICATE_1_BIT_TO_9_TABLE[value]; 184 return REPLICATE_1_BIT_TO_9_TABLE[value];
188} 185}
189 186
190uint FastReplicateTo8(uint value, uint num_bits) { 187uint FastReplicate(uint value, uint num_bits, uint to_bit) {
191 switch (num_bits) { 188 if (num_bits == 0) {
192 case 1: 189 return 0;
193 return REPLICATE_1_BIT_TO_8_TABLE[value]; 190 }
194 case 2: 191 if (num_bits == to_bit) {
195 return REPLICATE_2_BIT_TO_8_TABLE[value];
196 case 3:
197 return REPLICATE_3_BIT_TO_8_TABLE[value];
198 case 4:
199 return REPLICATE_4_BIT_TO_8_TABLE[value];
200 case 5:
201 return REPLICATE_5_BIT_TO_8_TABLE[value];
202 case 6:
203 return REPLICATE_6_BIT_TO_8_TABLE[value];
204 case 7:
205 return REPLICATE_7_BIT_TO_8_TABLE[value];
206 case 8:
207 return value; 192 return value;
208 } 193 }
209 return Replicate(value, num_bits, 8); 194 if (to_bit == 6) {
195 switch (num_bits) {
196 case 1:
197 return REPLICATE_1_BIT_TO_6_TABLE[value];
198 case 2:
199 return REPLICATE_2_BIT_TO_6_TABLE[value];
200 case 3:
201 return REPLICATE_3_BIT_TO_6_TABLE[value];
202 case 4:
203 return REPLICATE_4_BIT_TO_6_TABLE[value];
204 case 5:
205 return REPLICATE_5_BIT_TO_6_TABLE[value];
206 default:
207 break;
208 }
209 } else { /* if (to_bit == 8) */
210 switch (num_bits) {
211 case 1:
212 return REPLICATE_1_BIT_TO_8_TABLE[value];
213 case 2:
214 return REPLICATE_2_BIT_TO_8_TABLE[value];
215 case 3:
216 return REPLICATE_3_BIT_TO_8_TABLE[value];
217 case 4:
218 return REPLICATE_4_BIT_TO_8_TABLE[value];
219 case 5:
220 return REPLICATE_5_BIT_TO_8_TABLE[value];
221 case 6:
222 return REPLICATE_6_BIT_TO_8_TABLE[value];
223 case 7:
224 return REPLICATE_7_BIT_TO_8_TABLE[value];
225 default:
226 break;
227 }
228 }
229 return Replicate(value, num_bits, to_bit);
230}
231
232uint FastReplicateTo8(uint value, uint num_bits) {
233 return FastReplicate(value, num_bits, 8);
210} 234}
211 235
212uint FastReplicateTo6(uint value, uint num_bits) { 236uint FastReplicateTo6(uint value, uint num_bits) {
213 switch (num_bits) { 237 return FastReplicate(value, num_bits, 6);
214 case 1:
215 return REPLICATE_1_BIT_TO_6_TABLE[value];
216 case 2:
217 return REPLICATE_2_BIT_TO_6_TABLE[value];
218 case 3:
219 return REPLICATE_3_BIT_TO_6_TABLE[value];
220 case 4:
221 return REPLICATE_4_BIT_TO_6_TABLE[value];
222 case 5:
223 return REPLICATE_5_BIT_TO_6_TABLE[value];
224 }
225 return Replicate(value, num_bits, 6);
226} 238}
227 239
228uint Div3Floor(uint v) { 240uint Div3Floor(uint v) {
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp
index 3d78efddc..153702c0b 100644
--- a/src/video_core/vulkan_common/vulkan_device.cpp
+++ b/src/video_core/vulkan_common/vulkan_device.cpp
@@ -1038,7 +1038,7 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) {
1038 } 1038 }
1039 if (has_ext_shader_atomic_int64) { 1039 if (has_ext_shader_atomic_int64) {
1040 VkPhysicalDeviceShaderAtomicInt64Features atomic_int64; 1040 VkPhysicalDeviceShaderAtomicInt64Features atomic_int64;
1041 atomic_int64.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT; 1041 atomic_int64.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES;
1042 atomic_int64.pNext = nullptr; 1042 atomic_int64.pNext = nullptr;
1043 features.pNext = &atomic_int64; 1043 features.pNext = &atomic_int64;
1044 physical.GetFeatures2KHR(features); 1044 physical.GetFeatures2KHR(features);
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index b9342466e..d2132b408 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -102,6 +102,16 @@ QString GetButtonName(Common::Input::ButtonNames button_name) {
102 return QObject::tr("Share"); 102 return QObject::tr("Share");
103 case Common::Input::ButtonNames::Options: 103 case Common::Input::ButtonNames::Options:
104 return QObject::tr("Options"); 104 return QObject::tr("Options");
105 case Common::Input::ButtonNames::ButtonMouseWheel:
106 return QObject::tr("Wheel", "Indicates the mouse wheel");
107 case Common::Input::ButtonNames::ButtonBackward:
108 return QObject::tr("Backward");
109 case Common::Input::ButtonNames::ButtonForward:
110 return QObject::tr("Forward");
111 case Common::Input::ButtonNames::ButtonTask:
112 return QObject::tr("Task");
113 case Common::Input::ButtonNames::ButtonExtra:
114 return QObject::tr("Extra");
105 default: 115 default:
106 return QObject::tr("[undefined]"); 116 return QObject::tr("[undefined]");
107 } 117 }