summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-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>
}
template <typename T>
+requires std::is_unsigned_v<T>
+[[nodiscard]] constexpr bool IsPow2(T value) {
+ return std::has_single_bit(value);
+}
+
+template <typename T>
requires std::is_integral_v<T>
[[nodiscard]] T NextPow2(T value) {
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) {
// "from" might no longer be valid if the thread was killed
if (auto from = weak_from.lock()) {
- ASSERT(from->impl->previous_fiber != nullptr);
+ if (from->impl->previous_fiber == nullptr) {
+ ASSERT_MSG(false, "previous_fiber is nullptr!");
+ return;
+ }
from->impl->previous_fiber->impl->context = transfer.fctx;
from->impl->previous_fiber->impl->guard.unlock();
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 {
Triangle,
Share,
Options,
+
+ // Mouse buttons
+ ButtonMouseWheel,
+ ButtonBackward,
+ ButtonForward,
+ ButtonTask,
+ ButtonExtra,
};
// 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
hle/kernel/k_trace.h
hle/kernel/k_transfer_memory.cpp
hle/kernel/k_transfer_memory.h
+ hle/kernel/k_worker_task.h
+ hle/kernel/k_worker_task_manager.cpp
+ hle/kernel/k_worker_task_manager.h
hle/kernel/k_writable_event.cpp
hle/kernel/k_writable_event.h
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) {
auto& motion = console.motion_state;
motion.accel = emulated.GetAcceleration();
motion.gyro = emulated.GetGyroscope();
- motion.rotation = emulated.GetGyroscope();
+ motion.rotation = emulated.GetRotations();
motion.orientation = emulated.GetOrientation();
motion.quaternion = emulated.GetQuaternion();
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() {
motion_devices.begin(), Common::Input::CreateDevice<Common::Input::InputDevice>);
std::transform(trigger_params.begin(), trigger_params.end(), trigger_devices.begin(),
Common::Input::CreateDevice<Common::Input::InputDevice>);
- std::transform(battery_params.begin(), battery_params.begin(), battery_devices.end(),
+ std::transform(battery_params.begin(), battery_params.end(), battery_devices.begin(),
Common::Input::CreateDevice<Common::Input::InputDevice>);
std::transform(output_params.begin(), output_params.end(), output_devices.begin(),
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
if (TransformToButton(callback).value) {
std::random_device device;
std::mt19937 gen(device());
- std::uniform_int_distribution<s16> distribution(-1000, 1000);
+ std::uniform_int_distribution<s16> distribution(-5000, 5000);
status.accel.x.raw_value = static_cast<f32>(distribution(gen)) * 0.001f;
status.accel.y.raw_value = static_cast<f32>(distribution(gen)) * 0.001f;
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 @@
#include "common/assert.h"
#include "common/common_types.h"
#include "common/scope_exit.h"
+#include "core/core.h"
+#include "core/device_memory.h"
#include "core/hle/kernel/k_memory_manager.h"
#include "core/hle/kernel/k_page_linked_list.h"
#include "core/hle/kernel/svc_results.h"
namespace Kernel {
+KMemoryManager::KMemoryManager(Core::System& system_) : system{system_} {}
+
std::size_t KMemoryManager::Impl::Initialize(Pool new_pool, u64 start_address, u64 end_address) {
const auto size{end_address - start_address};
@@ -81,7 +85,7 @@ VAddr KMemoryManager::AllocateAndOpenContinuous(std::size_t num_pages, std::size
}
ResultCode KMemoryManager::Allocate(KPageLinkedList& page_list, std::size_t num_pages, Pool pool,
- Direction dir) {
+ Direction dir, u32 heap_fill_value) {
ASSERT(page_list.GetNumPages() == 0);
// Early return if we're allocating no pages
@@ -139,6 +143,12 @@ ResultCode KMemoryManager::Allocate(KPageLinkedList& page_list, std::size_t num_
}
}
+ // Clear allocated memory.
+ for (const auto& it : page_list.Nodes()) {
+ std::memset(system.DeviceMemory().GetPointer(it.GetAddress()), heap_fill_value,
+ it.GetSize());
+ }
+
// Only succeed if we allocated as many pages as we wanted
if (num_pages) {
return ResultOutOfMemory;
@@ -146,11 +156,12 @@ ResultCode KMemoryManager::Allocate(KPageLinkedList& page_list, std::size_t num_
// We succeeded!
group_guard.Cancel();
+
return ResultSuccess;
}
ResultCode KMemoryManager::Free(KPageLinkedList& page_list, std::size_t num_pages, Pool pool,
- Direction dir) {
+ Direction dir, u32 heap_fill_value) {
// Early return if we're freeing no pages
if (!num_pages) {
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 @@
#include "core/hle/kernel/k_page_heap.h"
#include "core/hle/result.h"
+namespace Core {
+class System;
+}
+
namespace Kernel {
class KPageLinkedList;
@@ -42,7 +46,7 @@ public:
Mask = (0xF << Shift),
};
- KMemoryManager() = default;
+ explicit KMemoryManager(Core::System& system_);
constexpr std::size_t GetSize(Pool pool) const {
return managers[static_cast<std::size_t>(pool)].GetSize();
@@ -51,10 +55,10 @@ public:
void InitializeManager(Pool pool, u64 start_address, u64 end_address);
VAddr AllocateAndOpenContinuous(size_t num_pages, size_t align_pages, u32 option);
- ResultCode Allocate(KPageLinkedList& page_list, std::size_t num_pages, Pool pool,
- Direction dir = Direction::FromFront);
- ResultCode Free(KPageLinkedList& page_list, std::size_t num_pages, Pool pool,
- Direction dir = Direction::FromFront);
+ ResultCode Allocate(KPageLinkedList& page_list, std::size_t num_pages, Pool pool, Direction dir,
+ u32 heap_fill_value = 0);
+ ResultCode Free(KPageLinkedList& page_list, std::size_t num_pages, Pool pool, Direction dir,
+ u32 heap_fill_value = 0);
static constexpr std::size_t MaxManagerCount = 10;
@@ -129,6 +133,7 @@ private:
};
private:
+ Core::System& system;
std::array<std::mutex, static_cast<std::size_t>(Pool::Count)> pool_locks;
std::array<Impl, MaxManagerCount> managers;
};
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
}
KPageLinkedList page_linked_list;
- CASCADE_CODE(
- system.Kernel().MemoryManager().Allocate(page_linked_list, num_pages, memory_pool));
+ CASCADE_CODE(system.Kernel().MemoryManager().Allocate(page_linked_list, num_pages, memory_pool,
+ allocation_option));
CASCADE_CODE(Operate(addr, num_pages, page_linked_list, OperationType::MapGroup));
block_manager->Update(addr, num_pages, state, perm);
@@ -457,8 +457,8 @@ ResultCode KPageTable::MapPhysicalMemory(VAddr addr, std::size_t size) {
KPageLinkedList page_linked_list;
- CASCADE_CODE(
- system.Kernel().MemoryManager().Allocate(page_linked_list, remaining_pages, memory_pool));
+ CASCADE_CODE(system.Kernel().MemoryManager().Allocate(page_linked_list, remaining_pages,
+ memory_pool, allocation_option));
// We succeeded, so commit the memory reservation.
memory_reservation.Commit();
@@ -541,7 +541,8 @@ ResultCode KPageTable::UnmapMemory(VAddr addr, std::size_t size) {
}
const std::size_t num_pages{size / PageSize};
- system.Kernel().MemoryManager().Free(page_linked_list, num_pages, memory_pool);
+ system.Kernel().MemoryManager().Free(page_linked_list, num_pages, memory_pool,
+ allocation_option);
block_manager->Update(addr, num_pages, KMemoryState::Free);
@@ -960,7 +961,7 @@ ResultCode KPageTable::SetHeapSize(VAddr* out, std::size_t size) {
// Allocate pages for the heap extension.
KPageLinkedList page_linked_list;
R_TRY(system.Kernel().MemoryManager().Allocate(page_linked_list, allocation_size / PageSize,
- memory_pool));
+ memory_pool, allocation_option));
// Map the pages.
{
@@ -1027,8 +1028,8 @@ ResultVal<VAddr> KPageTable::AllocateAndMapMemory(std::size_t needed_num_pages,
CASCADE_CODE(Operate(addr, needed_num_pages, perm, OperationType::Map, map_addr));
} else {
KPageLinkedList page_group;
- CASCADE_CODE(
- system.Kernel().MemoryManager().Allocate(page_group, needed_num_pages, memory_pool));
+ CASCADE_CODE(system.Kernel().MemoryManager().Allocate(page_group, needed_num_pages,
+ memory_pool, allocation_option));
CASCADE_CODE(Operate(addr, needed_num_pages, page_group, OperationType::MapGroup));
}
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:
bool is_aslr_enabled{};
KMemoryManager::Pool memory_pool{KMemoryManager::Pool::Application};
+ KMemoryManager::Direction allocation_option{KMemoryManager::Direction::FromFront};
Common::PageTable page_table_impl;
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
return ResultSuccess;
}
+void KProcess::DoWorkerTaskImpl() {
+ UNIMPLEMENTED();
+}
+
KResourceLimit* KProcess::GetResourceLimit() const {
return resource_limit;
}
@@ -477,7 +481,7 @@ void KProcess::Finalize() {
}
// Perform inherited finalization.
- KAutoObjectWithSlabHeapAndContainer<KProcess, KSynchronizationObject>::Finalize();
+ KAutoObjectWithSlabHeapAndContainer<KProcess, KWorkerTask>::Finalize();
}
/**
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 @@
#include "core/hle/kernel/k_condition_variable.h"
#include "core/hle/kernel/k_handle_table.h"
#include "core/hle/kernel/k_synchronization_object.h"
+#include "core/hle/kernel/k_worker_task.h"
#include "core/hle/kernel/process_capability.h"
#include "core/hle/kernel/slab_helpers.h"
#include "core/hle/result.h"
@@ -62,8 +63,7 @@ enum class ProcessStatus {
DebugBreak,
};
-class KProcess final
- : public KAutoObjectWithSlabHeapAndContainer<KProcess, KSynchronizationObject> {
+class KProcess final : public KAutoObjectWithSlabHeapAndContainer<KProcess, KWorkerTask> {
KERNEL_AUTOOBJECT_TRAITS(KProcess, KSynchronizationObject);
public:
@@ -345,6 +345,8 @@ public:
bool IsSignaled() const override;
+ void DoWorkerTaskImpl();
+
void PinCurrentThread(s32 core_id);
void UnpinCurrentThread(s32 core_id);
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
if (!must_context_switch || core != current_core) {
auto& phys_core = kernel.PhysicalCore(core);
phys_core.Interrupt();
- } else {
- must_context_switch = true;
}
cores_pending_reschedule &= ~(1ULL << core);
}
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 @@
#include "core/hle/kernel/k_system_control.h"
#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/k_thread_queue.h"
+#include "core/hle/kernel/k_worker_task_manager.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/svc_results.h"
#include "core/hle/kernel/time_manager.h"
@@ -332,7 +333,7 @@ void KThread::Finalize() {
}
// Perform inherited finalization.
- KAutoObjectWithSlabHeapAndContainer<KThread, KSynchronizationObject>::Finalize();
+ KSynchronizationObject::Finalize();
}
bool KThread::IsSignaled() const {
@@ -376,11 +377,28 @@ void KThread::StartTermination() {
// Register terminated dpc flag.
RegisterDpc(DpcFlag::Terminated);
+}
+
+void KThread::FinishTermination() {
+ // Ensure that the thread is not executing on any core.
+ if (parent != nullptr) {
+ for (std::size_t i = 0; i < static_cast<std::size_t>(Core::Hardware::NUM_CPU_CORES); ++i) {
+ KThread* core_thread{};
+ do {
+ core_thread = kernel.Scheduler(i).GetCurrentThread();
+ } while (core_thread == this);
+ }
+ }
// Close the thread.
this->Close();
}
+void KThread::DoWorkerTaskImpl() {
+ // Finish the termination that was begun by Exit().
+ this->FinishTermination();
+}
+
void KThread::Pin(s32 current_core) {
ASSERT(kernel.GlobalSchedulerContext().IsLocked());
@@ -417,12 +435,7 @@ void KThread::Pin(s32 current_core) {
static_cast<u32>(ThreadState::SuspendShift)));
// Update our state.
- const ThreadState old_state = thread_state;
- thread_state = static_cast<ThreadState>(GetSuspendFlags() |
- static_cast<u32>(old_state & ThreadState::Mask));
- if (thread_state != old_state) {
- KScheduler::OnThreadStateChanged(kernel, this, old_state);
- }
+ UpdateState();
}
// TODO(bunnei): Update our SVC access permissions.
@@ -463,20 +476,13 @@ void KThread::Unpin() {
}
// Allow performing thread suspension (if termination hasn't been requested).
- {
+ if (!IsTerminationRequested()) {
// Update our allow flags.
- if (!IsTerminationRequested()) {
- suspend_allowed_flags |= (1 << (static_cast<u32>(SuspendType::Thread) +
- static_cast<u32>(ThreadState::SuspendShift)));
- }
+ suspend_allowed_flags |= (1 << (static_cast<u32>(SuspendType::Thread) +
+ static_cast<u32>(ThreadState::SuspendShift)));
// Update our state.
- const ThreadState old_state = thread_state;
- thread_state = static_cast<ThreadState>(GetSuspendFlags() |
- static_cast<u32>(old_state & ThreadState::Mask));
- if (thread_state != old_state) {
- KScheduler::OnThreadStateChanged(kernel, this, old_state);
- }
+ UpdateState();
}
// TODO(bunnei): Update our SVC access permissions.
@@ -689,12 +695,7 @@ void KThread::Resume(SuspendType type) {
~(1u << (static_cast<u32>(ThreadState::SuspendShift) + static_cast<u32>(type)));
// Update our state.
- const ThreadState old_state = thread_state;
- thread_state = static_cast<ThreadState>(GetSuspendFlags() |
- static_cast<u32>(old_state & ThreadState::Mask));
- if (thread_state != old_state) {
- KScheduler::OnThreadStateChanged(kernel, this, old_state);
- }
+ this->UpdateState();
}
void KThread::WaitCancel() {
@@ -721,19 +722,22 @@ void KThread::TrySuspend() {
ASSERT(GetNumKernelWaiters() == 0);
// Perform the suspend.
- Suspend();
+ this->UpdateState();
}
-void KThread::Suspend() {
+void KThread::UpdateState() {
ASSERT(kernel.GlobalSchedulerContext().IsLocked());
- ASSERT(IsSuspendRequested());
// Set our suspend flags in state.
const auto old_state = thread_state;
- thread_state = static_cast<ThreadState>(GetSuspendFlags()) | (old_state & ThreadState::Mask);
+ const auto new_state =
+ static_cast<ThreadState>(this->GetSuspendFlags()) | (old_state & ThreadState::Mask);
+ thread_state = new_state;
// Note the state change in scheduler.
- KScheduler::OnThreadStateChanged(kernel, this, old_state);
+ if (new_state != old_state) {
+ KScheduler::OnThreadStateChanged(kernel, this, old_state);
+ }
}
void KThread::Continue() {
@@ -998,13 +1002,16 @@ ResultCode KThread::Run() {
// If the current thread has been asked to suspend, suspend it and retry.
if (GetCurrentThread(kernel).IsSuspended()) {
- GetCurrentThread(kernel).Suspend();
+ GetCurrentThread(kernel).UpdateState();
continue;
}
// If we're not a kernel thread and we've been asked to suspend, suspend ourselves.
- if (IsUserThread() && IsSuspended()) {
- Suspend();
+ if (KProcess* owner = this->GetOwnerProcess(); owner != nullptr) {
+ if (IsUserThread() && IsSuspended()) {
+ this->UpdateState();
+ }
+ owner->IncrementThreadCount();
}
// Set our state and finish.
@@ -1031,9 +1038,16 @@ void KThread::Exit() {
// Disallow all suspension.
suspend_allowed_flags = 0;
+ this->UpdateState();
+
+ // Disallow all suspension.
+ suspend_allowed_flags = 0;
// Start termination.
StartTermination();
+
+ // Register the thread as a work task.
+ KWorkerTaskManager::AddTask(kernel, KWorkerTaskManager::WorkerType::Exit, this);
}
}
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 @@
#include "core/hle/kernel/k_light_lock.h"
#include "core/hle/kernel/k_spin_lock.h"
#include "core/hle/kernel/k_synchronization_object.h"
+#include "core/hle/kernel/k_worker_task.h"
#include "core/hle/kernel/slab_helpers.h"
#include "core/hle/kernel/svc_common.h"
#include "core/hle/kernel/svc_types.h"
@@ -100,7 +101,7 @@ enum class ThreadWaitReasonForDebugging : u32 {
[[nodiscard]] KThread& GetCurrentThread(KernelCore& kernel);
[[nodiscard]] s32 GetCurrentCoreId(KernelCore& kernel);
-class KThread final : public KAutoObjectWithSlabHeapAndContainer<KThread, KSynchronizationObject>,
+class KThread final : public KAutoObjectWithSlabHeapAndContainer<KThread, KWorkerTask>,
public boost::intrusive::list_base_hook<> {
KERNEL_AUTOOBJECT_TRAITS(KThread, KSynchronizationObject);
@@ -192,9 +193,9 @@ public:
void TrySuspend();
- void Continue();
+ void UpdateState();
- void Suspend();
+ void Continue();
constexpr void SetSyncedIndex(s32 index) {
synced_index = index;
@@ -385,6 +386,8 @@ public:
void OnTimer();
+ void DoWorkerTaskImpl();
+
static void PostDestroy(uintptr_t arg);
[[nodiscard]] static ResultCode InitializeDummyThread(KThread* thread);
@@ -679,6 +682,8 @@ private:
void StartTermination();
+ void FinishTermination();
+
[[nodiscard]] ResultCode Initialize(KThreadFunction func, uintptr_t arg, VAddr user_stack_top,
s32 prio, s32 virt_core, KProcess* owner, ThreadType type);
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 @@
+// Copyright 2022 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/kernel/k_synchronization_object.h"
+
+namespace Kernel {
+
+class KWorkerTask : public KSynchronizationObject {
+public:
+ explicit KWorkerTask(KernelCore& kernel_);
+
+ void DoWorkerTask();
+};
+
+} // 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 @@
+// Copyright 2022 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/assert.h"
+#include "core/hle/kernel/k_process.h"
+#include "core/hle/kernel/k_thread.h"
+#include "core/hle/kernel/k_worker_task.h"
+#include "core/hle/kernel/k_worker_task_manager.h"
+#include "core/hle/kernel/kernel.h"
+
+namespace Kernel {
+
+KWorkerTask::KWorkerTask(KernelCore& kernel_) : KSynchronizationObject{kernel_} {}
+
+void KWorkerTask::DoWorkerTask() {
+ if (auto* const thread = this->DynamicCast<KThread*>(); thread != nullptr) {
+ return thread->DoWorkerTaskImpl();
+ } else {
+ auto* const process = this->DynamicCast<KProcess*>();
+ ASSERT(process != nullptr);
+
+ return process->DoWorkerTaskImpl();
+ }
+}
+
+KWorkerTaskManager::KWorkerTaskManager() : m_waiting_thread(1, "yuzu:KWorkerTaskManager") {}
+
+void KWorkerTaskManager::AddTask(KernelCore& kernel, WorkerType type, KWorkerTask* task) {
+ ASSERT(type <= WorkerType::Count);
+ kernel.WorkerTaskManager().AddTask(kernel, task);
+}
+
+void KWorkerTaskManager::AddTask(KernelCore& kernel, KWorkerTask* task) {
+ KScopedSchedulerLock sl(kernel);
+ m_waiting_thread.QueueWork([task]() {
+ // Do the task.
+ task->DoWorkerTask();
+ });
+}
+
+} // 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 @@
+// Copyright 2022 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "common/common_types.h"
+#include "common/thread_worker.h"
+
+namespace Kernel {
+
+class KernelCore;
+class KWorkerTask;
+
+class KWorkerTaskManager final {
+public:
+ enum class WorkerType : u32 {
+ Exit,
+ Count,
+ };
+
+ KWorkerTaskManager();
+
+ static void AddTask(KernelCore& kernel_, WorkerType type, KWorkerTask* task);
+
+private:
+ void AddTask(KernelCore& kernel, KWorkerTask* task);
+
+private:
+ Common::ThreadWorker m_waiting_thread;
+};
+
+} // 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 @@
#include "core/hle/kernel/k_shared_memory.h"
#include "core/hle/kernel/k_slab_heap.h"
#include "core/hle/kernel/k_thread.h"
+#include "core/hle/kernel/k_worker_task_manager.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/physical_core.h"
#include "core/hle/kernel/service_thread.h"
@@ -630,7 +631,7 @@ struct KernelCore::Impl {
const auto application_pool = memory_layout.GetKernelApplicationPoolRegionPhysicalExtents();
// Initialize memory managers
- memory_manager = std::make_unique<KMemoryManager>();
+ memory_manager = std::make_unique<KMemoryManager>(system);
memory_manager->InitializeManager(KMemoryManager::Pool::Application,
application_pool.GetAddress(),
application_pool.GetEndAddress());
@@ -797,6 +798,8 @@ struct KernelCore::Impl {
std::array<u64, Core::Hardware::NUM_CPU_CORES> svc_ticks{};
+ KWorkerTaskManager worker_task_manager;
+
// System context
Core::System& system;
};
@@ -1137,6 +1140,14 @@ const Init::KSlabResourceCounts& KernelCore::SlabResourceCounts() const {
return impl->slab_resource_counts;
}
+KWorkerTaskManager& KernelCore::WorkerTaskManager() {
+ return impl->worker_task_manager;
+}
+
+const KWorkerTaskManager& KernelCore::WorkerTaskManager() const {
+ return impl->worker_task_manager;
+}
+
bool KernelCore::IsPhantomModeForSingleCore() const {
return impl->IsPhantomModeForSingleCore();
}
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;
class KSharedMemoryInfo;
class KThread;
class KTransferMemory;
+class KWorkerTaskManager;
class KWritableEvent;
class KCodeMemory;
class PhysicalCore;
@@ -343,6 +344,12 @@ public:
/// Gets the current slab resource counts.
const Init::KSlabResourceCounts& SlabResourceCounts() const;
+ /// Gets the current worker task manager, used for dispatching KThread/KProcess tasks.
+ KWorkerTaskManager& WorkerTaskManager();
+
+ /// Gets the current worker task manager, used for dispatching KThread/KProcess tasks.
+ const KWorkerTaskManager& WorkerTaskManager() const;
+
private:
friend class KProcess;
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) {
const auto parameters{rp.PopRaw<Parameters>()};
- applet_resource->GetController<Controller_NPad>(HidController::NPad)
+ GetAppletResource()
+ ->GetController<Controller_NPad>(HidController::NPad)
.SetAnalogStickUseCenterClamp(parameters.analog_stick_use_center_clamp);
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;
constexpr int mouse_axis_y = 1;
constexpr int wheel_axis_x = 2;
constexpr int wheel_axis_y = 3;
+constexpr int motion_wheel_y = 4;
constexpr int touch_axis_x = 10;
constexpr int touch_axis_y = 11;
constexpr PadIdentifier identifier = {
@@ -30,8 +31,9 @@ Mouse::Mouse(std::string input_engine_) : InputEngine(std::move(input_engine_))
PreSetAxis(identifier, mouse_axis_y);
PreSetAxis(identifier, wheel_axis_x);
PreSetAxis(identifier, wheel_axis_y);
+ PreSetAxis(identifier, motion_wheel_y);
PreSetAxis(identifier, touch_axis_x);
- PreSetAxis(identifier, touch_axis_x);
+ PreSetAxis(identifier, touch_axis_y);
update_thread = std::jthread([this](std::stop_token stop_token) { UpdateThread(stop_token); });
}
@@ -48,6 +50,8 @@ void Mouse::UpdateThread(std::stop_token stop_token) {
SetAxis(identifier, mouse_axis_y, -last_mouse_change.y * sensitivity);
}
+ SetAxis(identifier, motion_wheel_y, 0.0f);
+
if (mouse_panning_timout++ > 20) {
StopPanning();
}
@@ -136,6 +140,7 @@ void Mouse::MouseWheelChange(int x, int y) {
wheel_position.y += y;
SetAxis(identifier, wheel_axis_x, static_cast<f32>(wheel_position.x));
SetAxis(identifier, wheel_axis_y, static_cast<f32>(wheel_position.y));
+ SetAxis(identifier, motion_wheel_y, static_cast<f32>(y) / 100.0f);
}
void Mouse::ReleaseAllButtons() {
@@ -171,13 +176,39 @@ AnalogMapping Mouse::GetAnalogMappingForDevice(
return mapping;
}
+Common::Input::ButtonNames Mouse::GetUIButtonName(const Common::ParamPackage& params) const {
+ const auto button = static_cast<MouseButton>(params.Get("button", 0));
+ switch (button) {
+ case MouseButton::Left:
+ return Common::Input::ButtonNames::ButtonLeft;
+ case MouseButton::Right:
+ return Common::Input::ButtonNames::ButtonRight;
+ case MouseButton::Wheel:
+ return Common::Input::ButtonNames::ButtonMouseWheel;
+ case MouseButton::Backward:
+ return Common::Input::ButtonNames::ButtonBackward;
+ case MouseButton::Forward:
+ return Common::Input::ButtonNames::ButtonForward;
+ case MouseButton::Task:
+ return Common::Input::ButtonNames::ButtonTask;
+ case MouseButton::Extra:
+ return Common::Input::ButtonNames::ButtonExtra;
+ case MouseButton::Undefined:
+ default:
+ return Common::Input::ButtonNames::Undefined;
+ }
+}
+
Common::Input::ButtonNames Mouse::GetUIName(const Common::ParamPackage& params) const {
if (params.Has("button")) {
- return Common::Input::ButtonNames::Value;
+ return GetUIButtonName(params);
}
if (params.Has("axis")) {
return Common::Input::ButtonNames::Value;
}
+ if (params.Has("axis_x") && params.Has("axis_y") && params.Has("axis_z")) {
+ return Common::Input::ButtonNames::Engine;
+ }
return Common::Input::ButtonNames::Invalid;
}
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:
void UpdateThread(std::stop_token stop_token);
void StopPanning();
+ Common::Input::ButtonNames GetUIButtonName(const Common::ParamPackage& params) const;
+
Common::Vec2<int> mouse_origin;
Common::Vec2<int> last_mouse_position;
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:
if (sdl_controller) {
switch (SDL_GameControllerGetType(sdl_controller.get())) {
case SDL_CONTROLLER_TYPE_XBOX360:
- return "XBox 360 Controller";
+ return "Xbox 360 Controller";
case SDL_CONTROLLER_TYPE_XBOXONE:
- return "XBox One Controller";
+ return "Xbox One Controller";
case SDL_CONTROLLER_TYPE_PS3:
return "DualShock 3 Controller";
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() {
SetButton(controller.first, button.first, false);
}
for (const auto& button : controller.second.hat_buttons) {
- SetHatButton(controller.first, button.first, false);
+ SetHatButton(controller.first, button.first, 0);
}
}
}
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) {
}
new_input.Set("port", static_cast<int>(data.pad.port));
new_input.Set("pad", static_cast<int>(data.pad.pad));
+
+ // If engine is mouse map the mouse position as 3 axis motion
+ if (data.engine == "mouse") {
+ new_input.Set("axis_x", 1);
+ new_input.Set("invert_x", "-");
+ new_input.Set("axis_y", 0);
+ new_input.Set("axis_z", 4);
+ new_input.Set("range", 1.0f);
+ new_input.Set("deadzone", 0.0f);
+ input_queue.Push(new_input);
+ return;
+ }
+
switch (data.type) {
case EngineInputType::Button:
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:
bool initialized{};
NvdecCommon::VideoCodec current_codec{NvdecCommon::VideoCodec::None};
- AVCodec* av_codec{nullptr};
+ const AVCodec* av_codec{nullptr};
AVCodecContext* av_codec_ctx{nullptr};
AVBufferRef* av_gpu_decoder{nullptr};
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) {
// Replicates low num_bits such that [(to_bit - 1):(to_bit - 1 - from_bit)]
// is the same as [(num_bits - 1):0] and repeats all the way down.
uint Replicate(uint val, uint num_bits, uint to_bit) {
- if (num_bits == 0 || to_bit == 0) {
- return 0;
- }
const uint v = val & uint((1 << num_bits) - 1);
uint res = v;
uint reslen = num_bits;
@@ -187,42 +184,57 @@ uint ReplicateBitTo9(uint value) {
return REPLICATE_1_BIT_TO_9_TABLE[value];
}
-uint FastReplicateTo8(uint value, uint num_bits) {
- switch (num_bits) {
- case 1:
- return REPLICATE_1_BIT_TO_8_TABLE[value];
- case 2:
- return REPLICATE_2_BIT_TO_8_TABLE[value];
- case 3:
- return REPLICATE_3_BIT_TO_8_TABLE[value];
- case 4:
- return REPLICATE_4_BIT_TO_8_TABLE[value];
- case 5:
- return REPLICATE_5_BIT_TO_8_TABLE[value];
- case 6:
- return REPLICATE_6_BIT_TO_8_TABLE[value];
- case 7:
- return REPLICATE_7_BIT_TO_8_TABLE[value];
- case 8:
+uint FastReplicate(uint value, uint num_bits, uint to_bit) {
+ if (num_bits == 0) {
+ return 0;
+ }
+ if (num_bits == to_bit) {
return value;
}
- return Replicate(value, num_bits, 8);
+ if (to_bit == 6) {
+ switch (num_bits) {
+ case 1:
+ return REPLICATE_1_BIT_TO_6_TABLE[value];
+ case 2:
+ return REPLICATE_2_BIT_TO_6_TABLE[value];
+ case 3:
+ return REPLICATE_3_BIT_TO_6_TABLE[value];
+ case 4:
+ return REPLICATE_4_BIT_TO_6_TABLE[value];
+ case 5:
+ return REPLICATE_5_BIT_TO_6_TABLE[value];
+ default:
+ break;
+ }
+ } else { /* if (to_bit == 8) */
+ switch (num_bits) {
+ case 1:
+ return REPLICATE_1_BIT_TO_8_TABLE[value];
+ case 2:
+ return REPLICATE_2_BIT_TO_8_TABLE[value];
+ case 3:
+ return REPLICATE_3_BIT_TO_8_TABLE[value];
+ case 4:
+ return REPLICATE_4_BIT_TO_8_TABLE[value];
+ case 5:
+ return REPLICATE_5_BIT_TO_8_TABLE[value];
+ case 6:
+ return REPLICATE_6_BIT_TO_8_TABLE[value];
+ case 7:
+ return REPLICATE_7_BIT_TO_8_TABLE[value];
+ default:
+ break;
+ }
+ }
+ return Replicate(value, num_bits, to_bit);
+}
+
+uint FastReplicateTo8(uint value, uint num_bits) {
+ return FastReplicate(value, num_bits, 8);
}
uint FastReplicateTo6(uint value, uint num_bits) {
- switch (num_bits) {
- case 1:
- return REPLICATE_1_BIT_TO_6_TABLE[value];
- case 2:
- return REPLICATE_2_BIT_TO_6_TABLE[value];
- case 3:
- return REPLICATE_3_BIT_TO_6_TABLE[value];
- case 4:
- return REPLICATE_4_BIT_TO_6_TABLE[value];
- case 5:
- return REPLICATE_5_BIT_TO_6_TABLE[value];
- }
- return Replicate(value, num_bits, 6);
+ return FastReplicate(value, num_bits, 6);
}
uint 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) {
}
if (has_ext_shader_atomic_int64) {
VkPhysicalDeviceShaderAtomicInt64Features atomic_int64;
- atomic_int64.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT;
+ atomic_int64.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES;
atomic_int64.pNext = nullptr;
features.pNext = &atomic_int64;
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) {
return QObject::tr("Share");
case Common::Input::ButtonNames::Options:
return QObject::tr("Options");
+ case Common::Input::ButtonNames::ButtonMouseWheel:
+ return QObject::tr("Wheel", "Indicates the mouse wheel");
+ case Common::Input::ButtonNames::ButtonBackward:
+ return QObject::tr("Backward");
+ case Common::Input::ButtonNames::ButtonForward:
+ return QObject::tr("Forward");
+ case Common::Input::ButtonNames::ButtonTask:
+ return QObject::tr("Task");
+ case Common::Input::ButtonNames::ButtonExtra:
+ return QObject::tr("Extra");
default:
return QObject::tr("[undefined]");
}