diff --git a/README.md b/README.md index 702fc725c..d8ce04df1 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 1444. +This is the source code for early-access 1452. ## Legal Notice diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index a7a2b8c95..f65d0769c 100755 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -147,7 +147,7 @@ add_library(core STATIC hle/kernel/client_session.h hle/kernel/code_set.cpp hle/kernel/code_set.h - hle/kernel/errors.h + hle/kernel/svc_results.h hle/kernel/global_scheduler_context.cpp hle/kernel/global_scheduler_context.h hle/kernel/handle_table.cpp @@ -223,7 +223,6 @@ add_library(core STATIC hle/kernel/svc.cpp hle/kernel/svc.h hle/kernel/svc_common.h - hle/kernel/svc_results.h hle/kernel/svc_types.h hle/kernel/svc_wrap.h hle/kernel/time_manager.cpp diff --git a/src/core/hle/kernel/client_port.cpp b/src/core/hle/kernel/client_port.cpp index f8f005f15..0b6957e31 100755 --- a/src/core/hle/kernel/client_port.cpp +++ b/src/core/hle/kernel/client_port.cpp @@ -4,11 +4,11 @@ #include "core/hle/kernel/client_port.h" #include "core/hle/kernel/client_session.h" -#include "core/hle/kernel/errors.h" #include "core/hle/kernel/hle_ipc.h" #include "core/hle/kernel/object.h" #include "core/hle/kernel/server_port.h" #include "core/hle/kernel/session.h" +#include "core/hle/kernel/svc_results.h" namespace Kernel { @@ -21,7 +21,7 @@ std::shared_ptr ClientPort::GetServerPort() const { ResultVal> ClientPort::Connect() { if (active_sessions >= max_sessions) { - return ERR_MAX_CONNECTIONS_REACHED; + return ResultMaxConnectionsReached; } active_sessions++; diff --git a/src/core/hle/kernel/client_session.cpp b/src/core/hle/kernel/client_session.cpp index a2be1a8f6..e230f365a 100755 --- a/src/core/hle/kernel/client_session.cpp +++ b/src/core/hle/kernel/client_session.cpp @@ -3,11 +3,11 @@ // Refer to the license.txt file included. #include "core/hle/kernel/client_session.h" -#include "core/hle/kernel/errors.h" #include "core/hle/kernel/hle_ipc.h" #include "core/hle/kernel/k_thread.h" #include "core/hle/kernel/server_session.h" #include "core/hle/kernel/session.h" +#include "core/hle/kernel/svc_results.h" #include "core/hle/result.h" namespace Kernel { @@ -43,7 +43,7 @@ ResultCode ClientSession::SendSyncRequest(std::shared_ptr thread, Core::Timing::CoreTiming& core_timing) { // Keep ServerSession alive until we're done working with it. if (!parent->Server()) { - return ERR_SESSION_CLOSED_BY_REMOTE; + return ResultSessionClosedByRemote; } // Signal the server session that new data is available diff --git a/src/core/hle/kernel/handle_table.cpp b/src/core/hle/kernel/handle_table.cpp index 1a2fa9cd8..f96d34078 100755 --- a/src/core/hle/kernel/handle_table.cpp +++ b/src/core/hle/kernel/handle_table.cpp @@ -6,12 +6,12 @@ #include "common/assert.h" #include "common/logging/log.h" #include "core/core.h" -#include "core/hle/kernel/errors.h" #include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/k_scheduler.h" #include "core/hle/kernel/k_thread.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/process.h" +#include "core/hle/kernel/svc_results.h" namespace Kernel { namespace { @@ -33,7 +33,7 @@ HandleTable::~HandleTable() = default; ResultCode HandleTable::SetSize(s32 handle_table_size) { if (static_cast(handle_table_size) > MAX_COUNT) { LOG_ERROR(Kernel, "Handle table size {} is greater than {}", handle_table_size, MAX_COUNT); - return ERR_OUT_OF_MEMORY; + return ResultOutOfMemory; } // Values less than or equal to zero indicate to use the maximum allowable @@ -53,7 +53,7 @@ ResultVal HandleTable::Create(std::shared_ptr obj) { const u16 slot = next_free_slot; if (slot >= table_size) { LOG_ERROR(Kernel, "Unable to allocate Handle, too many slots in use."); - return ERR_HANDLE_TABLE_FULL; + return ResultHandleTableFull; } next_free_slot = generations[slot]; @@ -76,7 +76,7 @@ ResultVal HandleTable::Duplicate(Handle handle) { std::shared_ptr object = GetGeneric(handle); if (object == nullptr) { LOG_ERROR(Kernel, "Tried to duplicate invalid handle: {:08X}", handle); - return ERR_INVALID_HANDLE; + return ResultInvalidHandle; } return Create(std::move(object)); } @@ -84,7 +84,7 @@ ResultVal HandleTable::Duplicate(Handle handle) { ResultCode HandleTable::Close(Handle handle) { if (!IsValid(handle)) { LOG_ERROR(Kernel, "Handle is not valid! handle={:08X}", handle); - return ERR_INVALID_HANDLE; + return ResultInvalidHandle; } const u16 slot = GetSlot(handle); diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index 7ec62cf18..161d9f782 100755 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp @@ -14,7 +14,6 @@ #include "common/common_types.h" #include "common/logging/log.h" #include "core/hle/ipc_helpers.h" -#include "core/hle/kernel/errors.h" #include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/hle_ipc.h" #include "core/hle/kernel/k_readable_event.h" @@ -26,6 +25,7 @@ #include "core/hle/kernel/object.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/server_session.h" +#include "core/hle/kernel/svc_results.h" #include "core/hle/kernel/time_manager.h" #include "core/memory.h" diff --git a/src/core/hle/kernel/k_address_arbiter.cpp b/src/core/hle/kernel/k_address_arbiter.cpp index d0e90fd60..7018f56da 100755 --- a/src/core/hle/kernel/k_address_arbiter.cpp +++ b/src/core/hle/kernel/k_address_arbiter.cpp @@ -120,10 +120,10 @@ ResultCode KAddressArbiter::SignalAndIncrementIfEqual(VAddr addr, s32 value, s32 s32 user_value{}; if (!UpdateIfEqual(system, &user_value, addr, value, value + 1)) { LOG_ERROR(Kernel, "Invalid current memory!"); - return Svc::ResultInvalidCurrentMemory; + return ResultInvalidCurrentMemory; } if (user_value != value) { - return Svc::ResultInvalidState; + return ResultInvalidState; } auto it = thread_tree.nfind_light({addr, -1}); @@ -189,10 +189,10 @@ ResultCode KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32 if (!succeeded) { LOG_ERROR(Kernel, "Invalid current memory!"); - return Svc::ResultInvalidCurrentMemory; + return ResultInvalidCurrentMemory; } if (user_value != value) { - return Svc::ResultInvalidState; + return ResultInvalidState; } while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) && @@ -221,11 +221,11 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement // Check that the thread isn't terminating. if (cur_thread->IsTerminationRequested()) { slp.CancelSleep(); - return Svc::ResultTerminationRequested; + return ResultTerminationRequested; } // Set the synced object. - cur_thread->SetSyncedObject(nullptr, Svc::ResultTimedOut); + cur_thread->SetSyncedObject(nullptr, ResultTimedOut); // Read the value from userspace. s32 user_value{}; @@ -238,19 +238,19 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement if (!succeeded) { slp.CancelSleep(); - return Svc::ResultInvalidCurrentMemory; + return ResultInvalidCurrentMemory; } // Check that the value is less than the specified one. if (user_value >= value) { slp.CancelSleep(); - return Svc::ResultInvalidState; + return ResultInvalidState; } // Check that the timeout is non-zero. if (timeout == 0) { slp.CancelSleep(); - return Svc::ResultTimedOut; + return ResultTimedOut; } // Set the arbiter. @@ -288,29 +288,29 @@ ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) { // Check that the thread isn't terminating. if (cur_thread->IsTerminationRequested()) { slp.CancelSleep(); - return Svc::ResultTerminationRequested; + return ResultTerminationRequested; } // Set the synced object. - cur_thread->SetSyncedObject(nullptr, Svc::ResultTimedOut); + cur_thread->SetSyncedObject(nullptr, ResultTimedOut); // Read the value from userspace. s32 user_value{}; if (!ReadFromUser(system, &user_value, addr)) { slp.CancelSleep(); - return Svc::ResultInvalidCurrentMemory; + return ResultInvalidCurrentMemory; } // Check that the value is equal. if (value != user_value) { slp.CancelSleep(); - return Svc::ResultInvalidState; + return ResultInvalidState; } // Check that the timeout is non-zero. if (timeout == 0) { slp.CancelSleep(); - return Svc::ResultTimedOut; + return ResultTimedOut; } // Set the arbiter. diff --git a/src/core/hle/kernel/k_condition_variable.cpp b/src/core/hle/kernel/k_condition_variable.cpp index f0ad8b390..170d8fa0d 100755 --- a/src/core/hle/kernel/k_condition_variable.cpp +++ b/src/core/hle/kernel/k_condition_variable.cpp @@ -92,10 +92,10 @@ ResultCode KConditionVariable::SignalToAddress(VAddr addr) { // Write the value to userspace. if (!WriteToUser(system, addr, std::addressof(next_value))) { if (next_owner_thread) { - next_owner_thread->SetSyncedObject(nullptr, Svc::ResultInvalidCurrentMemory); + next_owner_thread->SetSyncedObject(nullptr, ResultInvalidCurrentMemory); } - return Svc::ResultInvalidCurrentMemory; + return ResultInvalidCurrentMemory; } } @@ -114,20 +114,20 @@ ResultCode KConditionVariable::WaitForAddress(Handle handle, VAddr addr, u32 val cur_thread->SetSyncedObject(nullptr, RESULT_SUCCESS); // Check if the thread should terminate. - R_UNLESS(!cur_thread->IsTerminationRequested(), Svc::ResultTerminationRequested); + R_UNLESS(!cur_thread->IsTerminationRequested(), ResultTerminationRequested); { // Read the tag from userspace. u32 test_tag{}; R_UNLESS(ReadFromUser(system, std::addressof(test_tag), addr), - Svc::ResultInvalidCurrentMemory); + ResultInvalidCurrentMemory); // If the tag isn't the handle (with wait mask), we're done. R_UNLESS(test_tag == (handle | Svc::HandleWaitMask), RESULT_SUCCESS); // Get the lock owner thread. owner_thread = kernel.CurrentProcess()->GetHandleTable().Get(handle); - R_UNLESS(owner_thread, Svc::ResultInvalidHandle); + R_UNLESS(owner_thread, ResultInvalidHandle); // Update the lock. cur_thread->SetAddressKey(addr, value); @@ -191,13 +191,13 @@ KThread* KConditionVariable::SignalImpl(KThread* thread) { thread_to_close = owner_thread.get(); } else { // The lock was tagged with a thread that doesn't exist. - thread->SetSyncedObject(nullptr, Svc::ResultInvalidState); + thread->SetSyncedObject(nullptr, ResultInvalidState); thread->Wakeup(); } } } else { // If the address wasn't accessible, note so. - thread->SetSyncedObject(nullptr, Svc::ResultInvalidCurrentMemory); + thread->SetSyncedObject(nullptr, ResultInvalidCurrentMemory); thread->Wakeup(); } @@ -263,12 +263,12 @@ ResultCode KConditionVariable::Wait(VAddr addr, u64 key, u32 value, s64 timeout) KScopedSchedulerLockAndSleep slp{kernel, cur_thread, timeout}; // Set the synced object. - cur_thread->SetSyncedObject(nullptr, Svc::ResultTimedOut); + cur_thread->SetSyncedObject(nullptr, ResultTimedOut); // Check that the thread isn't terminating. if (cur_thread->IsTerminationRequested()) { slp.CancelSleep(); - return Svc::ResultTerminationRequested; + return ResultTerminationRequested; } // Update the value and process for the next owner. @@ -302,7 +302,7 @@ ResultCode KConditionVariable::Wait(VAddr addr, u64 key, u32 value, s64 timeout) // Write the value to userspace. if (!WriteToUser(system, addr, std::addressof(next_value))) { slp.CancelSleep(); - return Svc::ResultInvalidCurrentMemory; + return ResultInvalidCurrentMemory; } } diff --git a/src/core/hle/kernel/k_readable_event.cpp b/src/core/hle/kernel/k_readable_event.cpp index d8a42dbaf..4b4d34857 100755 --- a/src/core/hle/kernel/k_readable_event.cpp +++ b/src/core/hle/kernel/k_readable_event.cpp @@ -6,7 +6,6 @@ #include "common/assert.h" #include "common/common_funcs.h" #include "common/logging/log.h" -#include "core/hle/kernel/errors.h" #include "core/hle/kernel/k_readable_event.h" #include "core/hle/kernel/k_scheduler.h" #include "core/hle/kernel/k_thread.h" @@ -47,7 +46,7 @@ ResultCode KReadableEvent::Reset() { KScopedSchedulerLock lk{kernel}; if (!is_signaled) { - return Svc::ResultInvalidState; + return ResultInvalidState; } is_signaled = false; diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp index ab2ab683f..d7a4a38e6 100755 --- a/src/core/hle/kernel/k_resource_limit.cpp +++ b/src/core/hle/kernel/k_resource_limit.cpp @@ -75,7 +75,7 @@ s64 KResourceLimit::GetFreeValue(LimitableResource which) const { ResultCode KResourceLimit::SetLimitValue(LimitableResource which, s64 value) { const auto index = static_cast(which); KScopedLightLock lk(lock); - R_UNLESS(current_values[index] <= value, Svc::ResultInvalidState); + R_UNLESS(current_values[index] <= value, ResultInvalidState); limit_values[index] = value; diff --git a/src/core/hle/kernel/k_synchronization_object.cpp b/src/core/hle/kernel/k_synchronization_object.cpp index 140cc46a7..82f72a0fe 100755 --- a/src/core/hle/kernel/k_synchronization_object.cpp +++ b/src/core/hle/kernel/k_synchronization_object.cpp @@ -40,20 +40,20 @@ ResultCode KSynchronizationObject::Wait(KernelCore& kernel, s32* out_index, // Check if the timeout is zero. if (timeout == 0) { slp.CancelSleep(); - return Svc::ResultTimedOut; + return ResultTimedOut; } // Check if the thread should terminate. if (thread->IsTerminationRequested()) { slp.CancelSleep(); - return Svc::ResultTerminationRequested; + return ResultTerminationRequested; } // Check if waiting was canceled. if (thread->IsWaitCancelled()) { slp.CancelSleep(); thread->ClearWaitCancelled(); - return Svc::ResultCancelled; + return ResultCancelled; } // Add the waiters. @@ -75,7 +75,7 @@ ResultCode KSynchronizationObject::Wait(KernelCore& kernel, s32* out_index, // Mark the thread as waiting. thread->SetCancellable(); - thread->SetSyncedObject(nullptr, Svc::ResultTimedOut); + thread->SetSyncedObject(nullptr, ResultTimedOut); thread->SetState(ThreadState::Waiting); thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Synchronization); } diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index b59259c4f..e5620da5a 100755 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -18,7 +18,6 @@ #include "core/core.h" #include "core/cpu_manager.h" #include "core/hardware_properties.h" -#include "core/hle/kernel/errors.h" #include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/k_condition_variable.h" #include "core/hle/kernel/k_resource_limit.h" @@ -127,7 +126,7 @@ ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_s // Set core ID and wait result. core_id = phys_core; - wait_result = Svc::ResultNoSynchronizationObject; + wait_result = ResultNoSynchronizationObject; // Set priorities. priority = prio; @@ -238,7 +237,7 @@ void KThread::Finalize() { while (it != waiter_list.end()) { // The thread shouldn't be a kernel waiter. it->SetLockOwner(nullptr); - it->SetSyncedObject(nullptr, Svc::ResultInvalidState); + it->SetSyncedObject(nullptr, ResultInvalidState); it->Wakeup(); it = waiter_list.erase(it); } @@ -447,7 +446,7 @@ ResultCode KThread::SetCoreMask(s32 core_id, u64 v_affinity_mask) { // If the core id is no-update magic, preserve the ideal core id. if (core_id == Svc::IdealCoreNoUpdate) { core_id = virtual_ideal_core_id; - R_UNLESS(((1ULL << core_id) & v_affinity_mask) != 0, Svc::ResultInvalidCombination); + R_UNLESS(((1ULL << core_id) & v_affinity_mask) != 0, ResultInvalidCombination); } // Set the virtual core/affinity mask. @@ -526,7 +525,7 @@ ResultCode KThread::SetCoreMask(s32 core_id, u64 v_affinity_mask) { if (GetStackParameters().is_pinned) { // Verify that the current thread isn't terminating. R_UNLESS(!GetCurrentThread(kernel).IsTerminationRequested(), - Svc::ResultTerminationRequested); + ResultTerminationRequested); // Note that the thread was pinned. thread_is_pinned = true; @@ -604,7 +603,7 @@ void KThread::WaitCancel() { sleeping_queue->WakeupThread(this); wait_cancelled = true; } else { - SetSyncedObject(nullptr, Svc::ResultCancelled); + SetSyncedObject(nullptr, ResultCancelled); SetState(ThreadState::Runnable); wait_cancelled = false; } @@ -663,12 +662,12 @@ ResultCode KThread::SetActivity(Svc::ThreadActivity activity) { // Verify our state. const auto cur_state = GetState(); R_UNLESS((cur_state == ThreadState::Waiting || cur_state == ThreadState::Runnable), - Svc::ResultInvalidState); + ResultInvalidState); // Either pause or resume. if (activity == Svc::ThreadActivity::Paused) { // Verify that we're not suspended. - R_UNLESS(!IsSuspendRequested(SuspendType::Thread), Svc::ResultInvalidState); + R_UNLESS(!IsSuspendRequested(SuspendType::Thread), ResultInvalidState); // Suspend. RequestSuspend(SuspendType::Thread); @@ -676,7 +675,7 @@ ResultCode KThread::SetActivity(Svc::ThreadActivity activity) { ASSERT(activity == Svc::ThreadActivity::Runnable); // Verify that we're suspended. - R_UNLESS(IsSuspendRequested(SuspendType::Thread), Svc::ResultInvalidState); + R_UNLESS(IsSuspendRequested(SuspendType::Thread), ResultInvalidState); // Resume. Resume(SuspendType::Thread); @@ -698,7 +697,7 @@ ResultCode KThread::SetActivity(Svc::ThreadActivity activity) { if (GetStackParameters().is_pinned) { // Verify that the current thread isn't terminating. R_UNLESS(!GetCurrentThread(kernel).IsTerminationRequested(), - Svc::ResultTerminationRequested); + ResultTerminationRequested); // Note that the thread was pinned and not current. thread_is_pinned = true; @@ -745,7 +744,7 @@ ResultCode KThread::GetThreadContext3(std::vector& out) { KScopedSchedulerLock sl{kernel}; // Verify that we're suspended. - R_UNLESS(IsSuspendRequested(SuspendType::Thread), Svc::ResultInvalidState); + R_UNLESS(IsSuspendRequested(SuspendType::Thread), ResultInvalidState); // If we're not terminating, get the thread's user context. if (!IsTerminationRequested()) { @@ -905,12 +904,11 @@ ResultCode KThread::Run() { KScopedSchedulerLock lk{kernel}; // If either this thread or the current thread are requesting termination, note it. - R_UNLESS(!IsTerminationRequested(), Svc::ResultTerminationRequested); - R_UNLESS(!GetCurrentThread(kernel).IsTerminationRequested(), - Svc::ResultTerminationRequested); + R_UNLESS(!IsTerminationRequested(), ResultTerminationRequested); + R_UNLESS(!GetCurrentThread(kernel).IsTerminationRequested(), ResultTerminationRequested); // Ensure our thread state is correct. - R_UNLESS(GetState() == ThreadState::Initialized, Svc::ResultInvalidState); + R_UNLESS(GetState() == ThreadState::Initialized, ResultInvalidState); // If the current thread has been asked to suspend, suspend it and retry. if (GetCurrentThread(kernel).IsSuspended()) { @@ -962,7 +960,7 @@ ResultCode KThread::Sleep(s64 timeout) { // Check if the thread should terminate. if (IsTerminationRequested()) { slp.CancelSleep(); - return Svc::ResultTerminationRequested; + return ResultTerminationRequested; } // Mark the thread as waiting. diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index ba65bb022..b6e6f115e 100755 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -26,7 +26,6 @@ #include "core/device_memory.h" #include "core/hardware_properties.h" #include "core/hle/kernel/client_port.h" -#include "core/hle/kernel/errors.h" #include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/k_resource_limit.h" #include "core/hle/kernel/k_scheduler.h" @@ -39,6 +38,7 @@ #include "core/hle/kernel/process.h" #include "core/hle/kernel/service_thread.h" #include "core/hle/kernel/shared_memory.h" +#include "core/hle/kernel/svc_results.h" #include "core/hle/kernel/time_manager.h" #include "core/hle/lock.h" #include "core/hle/result.h" diff --git a/src/core/hle/kernel/memory/memory_manager.cpp b/src/core/hle/kernel/memory/memory_manager.cpp index acf13585c..77f135cdc 100755 --- a/src/core/hle/kernel/memory/memory_manager.cpp +++ b/src/core/hle/kernel/memory/memory_manager.cpp @@ -8,9 +8,9 @@ #include "common/assert.h" #include "common/common_types.h" #include "common/scope_exit.h" -#include "core/hle/kernel/errors.h" #include "core/hle/kernel/memory/memory_manager.h" #include "core/hle/kernel/memory/page_linked_list.h" +#include "core/hle/kernel/svc_results.h" namespace Kernel::Memory { @@ -95,7 +95,7 @@ ResultCode MemoryManager::Allocate(PageLinkedList& page_list, std::size_t num_pa // Choose a heap based on our page size request const s32 heap_index{PageHeap::GetBlockIndex(num_pages)}; if (heap_index < 0) { - return ERR_OUT_OF_MEMORY; + return ResultOutOfMemory; } // TODO (bunnei): Support multiple managers @@ -140,7 +140,7 @@ ResultCode MemoryManager::Allocate(PageLinkedList& page_list, std::size_t num_pa // Only succeed if we allocated as many pages as we wanted if (num_pages) { - return ERR_OUT_OF_MEMORY; + return ResultOutOfMemory; } // We succeeded! diff --git a/src/core/hle/kernel/memory/page_table.cpp b/src/core/hle/kernel/memory/page_table.cpp index 769748047..00ed9b881 100755 --- a/src/core/hle/kernel/memory/page_table.cpp +++ b/src/core/hle/kernel/memory/page_table.cpp @@ -6,7 +6,6 @@ #include "common/assert.h" #include "common/scope_exit.h" #include "core/core.h" -#include "core/hle/kernel/errors.h" #include "core/hle/kernel/k_scoped_resource_reservation.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/memory/address_space_info.h" @@ -16,6 +15,7 @@ #include "core/hle/kernel/memory/page_table.h" #include "core/hle/kernel/memory/system_control.h" #include "core/hle/kernel/process.h" +#include "core/hle/kernel/svc_results.h" #include "core/memory.h" namespace Kernel::Memory { @@ -141,7 +141,7 @@ ResultCode PageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_t (alias_region_size + heap_region_size + stack_region_size + kernel_map_region_size)}; if (alloc_size < needed_size) { UNREACHABLE(); - return ERR_OUT_OF_MEMORY; + return ResultOutOfMemory; } const std::size_t remaining_size{alloc_size - needed_size}; @@ -277,11 +277,11 @@ ResultCode PageTable::MapProcessCode(VAddr addr, std::size_t num_pages, MemorySt const u64 size{num_pages * PageSize}; if (!CanContain(addr, size, state)) { - return ERR_INVALID_ADDRESS_STATE; + return ResultInvalidCurrentMemory; } if (IsRegionMapped(addr, size)) { - return ERR_INVALID_ADDRESS_STATE; + return ResultInvalidCurrentMemory; } PageLinkedList page_linked_list; @@ -307,7 +307,7 @@ ResultCode PageTable::MapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std:: MemoryAttribute::None, MemoryAttribute::IpcAndDeviceMapped)); if (IsRegionMapped(dst_addr, size)) { - return ERR_INVALID_ADDRESS_STATE; + return ResultInvalidCurrentMemory; } PageLinkedList page_linked_list; @@ -418,7 +418,7 @@ ResultCode PageTable::MapPhysicalMemory(VAddr addr, std::size_t size) { remaining_size); if (!memory_reservation.Succeeded()) { LOG_ERROR(Kernel, "Could not reserve remaining {:X} bytes", remaining_size); - return ERR_RESOURCE_LIMIT_EXCEEDED; + return ResultResourceLimitedExceeded; } PageLinkedList page_linked_list; @@ -452,12 +452,12 @@ ResultCode PageTable::UnmapPhysicalMemory(VAddr addr, std::size_t size) { block_manager->IterateForRange(addr, end_addr, [&](const MemoryInfo& info) { if (info.state == MemoryState::Normal) { if (info.attribute != MemoryAttribute::None) { - result = ERR_INVALID_ADDRESS_STATE; + result = ResultInvalidCurrentMemory; return; } mapped_size += GetSizeInRange(info, addr, end_addr); } else if (info.state != MemoryState::Free) { - result = ERR_INVALID_ADDRESS_STATE; + result = ResultInvalidCurrentMemory; } }); @@ -524,7 +524,7 @@ ResultCode PageTable::Map(VAddr dst_addr, VAddr src_addr, std::size_t size) { MemoryAttribute::Mask, MemoryAttribute::None, MemoryAttribute::IpcAndDeviceMapped)); if (IsRegionMapped(dst_addr, size)) { - return ERR_INVALID_ADDRESS_STATE; + return ResultInvalidCurrentMemory; } PageLinkedList page_linked_list; @@ -575,7 +575,7 @@ ResultCode PageTable::Unmap(VAddr dst_addr, VAddr src_addr, std::size_t size) { AddRegionToPages(dst_addr, num_pages, dst_pages); if (!dst_pages.IsEqual(src_pages)) { - return ERR_INVALID_MEMORY_RANGE; + return ResultInvalidMemoryRange; } { @@ -624,11 +624,11 @@ ResultCode PageTable::MapPages(VAddr addr, PageLinkedList& page_linked_list, Mem const std::size_t size{num_pages * PageSize}; if (!CanContain(addr, size, state)) { - return ERR_INVALID_ADDRESS_STATE; + return ResultInvalidCurrentMemory; } if (IsRegionMapped(addr, num_pages * PageSize)) { - return ERR_INVALID_ADDRESS_STATE; + return ResultInvalidCurrentMemory; } CASCADE_CODE(MapPages(addr, page_linked_list, perm)); @@ -766,7 +766,7 @@ ResultCode PageTable::SetHeapCapacity(std::size_t new_heap_capacity) { ResultVal PageTable::SetHeapSize(std::size_t size) { if (size > heap_region_end - heap_region_start) { - return ERR_OUT_OF_MEMORY; + return ResultOutOfMemory; } const u64 previous_heap_size{GetHeapSize()}; @@ -786,7 +786,7 @@ ResultVal PageTable::SetHeapSize(std::size_t size) { if (!memory_reservation.Succeeded()) { LOG_ERROR(Kernel, "Could not reserve heap extension of size {:X} bytes", delta); - return ERR_RESOURCE_LIMIT_EXCEEDED; + return ResultResourceLimitedExceeded; } PageLinkedList page_linked_list; @@ -796,7 +796,7 @@ ResultVal PageTable::SetHeapSize(std::size_t size) { system.Kernel().MemoryManager().Allocate(page_linked_list, num_pages, memory_pool)); if (IsRegionMapped(current_heap_addr, delta)) { - return ERR_INVALID_ADDRESS_STATE; + return ResultInvalidCurrentMemory; } CASCADE_CODE( @@ -821,17 +821,17 @@ ResultVal PageTable::AllocateAndMapMemory(std::size_t needed_num_pages, s std::lock_guard lock{page_table_lock}; if (!CanContain(region_start, region_num_pages * PageSize, state)) { - return ERR_INVALID_ADDRESS_STATE; + return ResultInvalidCurrentMemory; } if (region_num_pages <= needed_num_pages) { - return ERR_OUT_OF_MEMORY; + return ResultOutOfMemory; } const VAddr addr{ AllocateVirtualMemory(region_start, region_num_pages, needed_num_pages, align)}; if (!addr) { - return ERR_OUT_OF_MEMORY; + return ResultOutOfMemory; } if (is_map_only) { @@ -1110,13 +1110,13 @@ constexpr ResultCode PageTable::CheckMemoryState(const MemoryInfo& info, MemoryS MemoryAttribute attr) const { // Validate the states match expectation if ((info.state & state_mask) != state) { - return ERR_INVALID_ADDRESS_STATE; + return ResultInvalidCurrentMemory; } if ((info.perm & perm_mask) != perm) { - return ERR_INVALID_ADDRESS_STATE; + return ResultInvalidCurrentMemory; } if ((info.attribute & attr_mask) != attr) { - return ERR_INVALID_ADDRESS_STATE; + return ResultInvalidCurrentMemory; } return RESULT_SUCCESS; @@ -1143,14 +1143,14 @@ ResultCode PageTable::CheckMemoryState(MemoryState* out_state, MemoryPermission* while (true) { // Validate the current block if (!(info.state == first_state)) { - return ERR_INVALID_ADDRESS_STATE; + return ResultInvalidCurrentMemory; } if (!(info.perm == first_perm)) { - return ERR_INVALID_ADDRESS_STATE; + return ResultInvalidCurrentMemory; } if (!((info.attribute | static_cast(ignore_attr)) == (first_attr | static_cast(ignore_attr)))) { - return ERR_INVALID_ADDRESS_STATE; + return ResultInvalidCurrentMemory; } // Validate against the provided masks diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 0de46cf06..47b3ac57b 100755 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -14,7 +14,6 @@ #include "core/device_memory.h" #include "core/file_sys/program_metadata.h" #include "core/hle/kernel/code_set.h" -#include "core/hle/kernel/errors.h" #include "core/hle/kernel/k_resource_limit.h" #include "core/hle/kernel/k_scheduler.h" #include "core/hle/kernel/k_scoped_resource_reservation.h" @@ -256,8 +255,8 @@ ResultCode Process::Reset() { KScopedSchedulerLock sl{kernel}; // Validate that we're in a state that we can reset. - R_UNLESS(status != ProcessStatus::Exited, Svc::ResultInvalidState); - R_UNLESS(is_signaled, Svc::ResultInvalidState); + R_UNLESS(status != ProcessStatus::Exited, ResultInvalidState); + R_UNLESS(is_signaled, ResultInvalidState); // Clear signaled. is_signaled = false; @@ -281,7 +280,7 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, if (!memory_reservation.Succeeded()) { LOG_ERROR(Kernel, "Could not reserve process memory requirements of size {:X} bytes", code_size + system_resource_size); - return ERR_RESOURCE_LIMIT_EXCEEDED; + return ResultResourceLimitedExceeded; } // Initialize proces address space if (const ResultCode result{ diff --git a/src/core/hle/kernel/process_capability.cpp b/src/core/hle/kernel/process_capability.cpp index 0566311b6..7c567049e 100755 --- a/src/core/hle/kernel/process_capability.cpp +++ b/src/core/hle/kernel/process_capability.cpp @@ -6,10 +6,10 @@ #include "common/bit_util.h" #include "common/logging/log.h" -#include "core/hle/kernel/errors.h" #include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/memory/page_table.h" #include "core/hle/kernel/process_capability.h" +#include "core/hle/kernel/svc_results.h" namespace Kernel { namespace { @@ -123,13 +123,13 @@ ResultCode ProcessCapabilities::ParseCapabilities(const u32* capabilities, // If there's only one, then there's a problem. if (i >= num_capabilities) { LOG_ERROR(Kernel, "Invalid combination! i={}", i); - return ERR_INVALID_COMBINATION; + return ResultInvalidCombination; } const auto size_flags = capabilities[i]; if (GetCapabilityType(size_flags) != CapabilityType::MapPhysical) { LOG_ERROR(Kernel, "Invalid capability type! size_flags={}", size_flags); - return ERR_INVALID_COMBINATION; + return ResultInvalidCombination; } const auto result = HandleMapPhysicalFlags(descriptor, size_flags, page_table); @@ -159,7 +159,7 @@ ResultCode ProcessCapabilities::ParseSingleFlagCapability(u32& set_flags, u32& s const auto type = GetCapabilityType(flag); if (type == CapabilityType::Unset) { - return ERR_INVALID_CAPABILITY_DESCRIPTOR; + return ResultInvalidCapabilityDescriptor; } // Bail early on ignorable entries, as one would expect, @@ -176,7 +176,7 @@ ResultCode ProcessCapabilities::ParseSingleFlagCapability(u32& set_flags, u32& s LOG_ERROR(Kernel, "Attempted to initialize flags that may only be initialized once. set_flags={}", set_flags); - return ERR_INVALID_COMBINATION; + return ResultInvalidCombination; } set_flags |= set_flag; @@ -202,7 +202,7 @@ ResultCode ProcessCapabilities::ParseSingleFlagCapability(u32& set_flags, u32& s } LOG_ERROR(Kernel, "Invalid capability type! type={}", type); - return ERR_INVALID_CAPABILITY_DESCRIPTOR; + return ResultInvalidCapabilityDescriptor; } void ProcessCapabilities::Clear() { @@ -225,7 +225,7 @@ ResultCode ProcessCapabilities::HandlePriorityCoreNumFlags(u32 flags) { if (priority_mask != 0 || core_mask != 0) { LOG_ERROR(Kernel, "Core or priority mask are not zero! priority_mask={}, core_mask={}", priority_mask, core_mask); - return ERR_INVALID_CAPABILITY_DESCRIPTOR; + return ResultInvalidCapabilityDescriptor; } const u32 core_num_min = (flags >> 16) & 0xFF; @@ -233,7 +233,7 @@ ResultCode ProcessCapabilities::HandlePriorityCoreNumFlags(u32 flags) { if (core_num_min > core_num_max) { LOG_ERROR(Kernel, "Core min is greater than core max! core_num_min={}, core_num_max={}", core_num_min, core_num_max); - return ERR_INVALID_COMBINATION; + return ResultInvalidCombination; } const u32 priority_min = (flags >> 10) & 0x3F; @@ -242,13 +242,13 @@ ResultCode ProcessCapabilities::HandlePriorityCoreNumFlags(u32 flags) { LOG_ERROR(Kernel, "Priority min is greater than priority max! priority_min={}, priority_max={}", core_num_min, priority_max); - return ERR_INVALID_COMBINATION; + return ResultInvalidCombination; } // The switch only has 4 usable cores. if (core_num_max >= 4) { LOG_ERROR(Kernel, "Invalid max cores specified! core_num_max={}", core_num_max); - return ERR_INVALID_PROCESSOR_ID; + return ResultInvalidCoreId; } const auto make_mask = [](u64 min, u64 max) { @@ -269,7 +269,7 @@ ResultCode ProcessCapabilities::HandleSyscallFlags(u32& set_svc_bits, u32 flags) // If we've already set this svc before, bail. if ((set_svc_bits & svc_bit) != 0) { - return ERR_INVALID_COMBINATION; + return ResultInvalidCombination; } set_svc_bits |= svc_bit; @@ -283,7 +283,7 @@ ResultCode ProcessCapabilities::HandleSyscallFlags(u32& set_svc_bits, u32 flags) if (svc_number >= svc_capabilities.size()) { LOG_ERROR(Kernel, "Process svc capability is out of range! svc_number={}", svc_number); - return ERR_OUT_OF_RANGE; + return ResultOutOfRange; } svc_capabilities[svc_number] = true; @@ -321,7 +321,7 @@ ResultCode ProcessCapabilities::HandleInterruptFlags(u32 flags) { if (interrupt >= interrupt_capabilities.size()) { LOG_ERROR(Kernel, "Process interrupt capability is out of range! svc_number={}", interrupt); - return ERR_OUT_OF_RANGE; + return ResultOutOfRange; } interrupt_capabilities[interrupt] = true; @@ -334,7 +334,7 @@ ResultCode ProcessCapabilities::HandleProgramTypeFlags(u32 flags) { const u32 reserved = flags >> 17; if (reserved != 0) { LOG_ERROR(Kernel, "Reserved value is non-zero! reserved={}", reserved); - return ERR_RESERVED_VALUE; + return ResultReservedValue; } program_type = static_cast((flags >> 14) & 0b111); @@ -354,7 +354,7 @@ ResultCode ProcessCapabilities::HandleKernelVersionFlags(u32 flags) { LOG_ERROR(Kernel, "Kernel version is non zero or flags are too small! major_version={}, flags={}", major_version, flags); - return ERR_INVALID_CAPABILITY_DESCRIPTOR; + return ResultInvalidCapabilityDescriptor; } kernel_version = flags; @@ -365,7 +365,7 @@ ResultCode ProcessCapabilities::HandleHandleTableFlags(u32 flags) { const u32 reserved = flags >> 26; if (reserved != 0) { LOG_ERROR(Kernel, "Reserved value is non-zero! reserved={}", reserved); - return ERR_RESERVED_VALUE; + return ResultReservedValue; } handle_table_size = static_cast((flags >> 16) & 0x3FF); @@ -376,7 +376,7 @@ ResultCode ProcessCapabilities::HandleDebugFlags(u32 flags) { const u32 reserved = flags >> 19; if (reserved != 0) { LOG_ERROR(Kernel, "Reserved value is non-zero! reserved={}", reserved); - return ERR_RESERVED_VALUE; + return ResultReservedValue; } is_debuggable = (flags & 0x20000) != 0; diff --git a/src/core/hle/kernel/server_port.cpp b/src/core/hle/kernel/server_port.cpp index fe7a483c4..5d17346ad 100755 --- a/src/core/hle/kernel/server_port.cpp +++ b/src/core/hle/kernel/server_port.cpp @@ -5,11 +5,11 @@ #include #include "common/assert.h" #include "core/hle/kernel/client_port.h" -#include "core/hle/kernel/errors.h" #include "core/hle/kernel/k_thread.h" #include "core/hle/kernel/object.h" #include "core/hle/kernel/server_port.h" #include "core/hle/kernel/server_session.h" +#include "core/hle/kernel/svc_results.h" namespace Kernel { @@ -18,7 +18,7 @@ ServerPort::~ServerPort() = default; ResultVal> ServerPort::Accept() { if (pending_sessions.empty()) { - return ERR_NOT_FOUND; + return ResultNotFound; } auto session = std::move(pending_sessions.back()); diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index e67e534b3..31d899e06 100755 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -23,7 +23,6 @@ #include "core/cpu_manager.h" #include "core/hle/kernel/client_port.h" #include "core/hle/kernel/client_session.h" -#include "core/hle/kernel/errors.h" #include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/k_address_arbiter.h" #include "core/hle/kernel/k_condition_variable.h" @@ -72,49 +71,49 @@ ResultCode MapUnmapMemorySanityChecks(const Memory::PageTable& manager, VAddr ds VAddr src_addr, u64 size) { if (!Common::Is4KBAligned(dst_addr)) { LOG_ERROR(Kernel_SVC, "Destination address is not aligned to 4KB, 0x{:016X}", dst_addr); - return ERR_INVALID_ADDRESS; + return ResultInvalidAddress; } if (!Common::Is4KBAligned(src_addr)) { LOG_ERROR(Kernel_SVC, "Source address is not aligned to 4KB, 0x{:016X}", src_addr); - return ERR_INVALID_SIZE; + return ResultInvalidSize; } if (size == 0) { LOG_ERROR(Kernel_SVC, "Size is 0"); - return ERR_INVALID_SIZE; + return ResultInvalidSize; } if (!Common::Is4KBAligned(size)) { LOG_ERROR(Kernel_SVC, "Size is not aligned to 4KB, 0x{:016X}", size); - return ERR_INVALID_SIZE; + return ResultInvalidSize; } if (!IsValidAddressRange(dst_addr, size)) { LOG_ERROR(Kernel_SVC, "Destination is not a valid address range, addr=0x{:016X}, size=0x{:016X}", dst_addr, size); - return ERR_INVALID_ADDRESS_STATE; + return ResultInvalidCurrentMemory; } if (!IsValidAddressRange(src_addr, size)) { LOG_ERROR(Kernel_SVC, "Source is not a valid address range, addr=0x{:016X}, size=0x{:016X}", src_addr, size); - return ERR_INVALID_ADDRESS_STATE; + return ResultInvalidCurrentMemory; } if (!manager.IsInsideAddressSpace(src_addr, size)) { LOG_ERROR(Kernel_SVC, "Source is not within the address space, addr=0x{:016X}, size=0x{:016X}", src_addr, size); - return ERR_INVALID_ADDRESS_STATE; + return ResultInvalidCurrentMemory; } if (manager.IsOutsideStackRegion(dst_addr, size)) { LOG_ERROR(Kernel_SVC, "Destination is not within the stack region, addr=0x{:016X}, size=0x{:016X}", dst_addr, size); - return ERR_INVALID_MEMORY_RANGE; + return ResultInvalidMemoryRange; } if (manager.IsInsideHeapRegion(dst_addr, size)) { @@ -122,7 +121,7 @@ ResultCode MapUnmapMemorySanityChecks(const Memory::PageTable& manager, VAddr ds "Destination does not fit within the heap region, addr=0x{:016X}, " "size=0x{:016X}", dst_addr, size); - return ERR_INVALID_MEMORY_RANGE; + return ResultInvalidMemoryRange; } if (manager.IsInsideAliasRegion(dst_addr, size)) { @@ -130,7 +129,7 @@ ResultCode MapUnmapMemorySanityChecks(const Memory::PageTable& manager, VAddr ds "Destination does not fit within the map region, addr=0x{:016X}, " "size=0x{:016X}", dst_addr, size); - return ERR_INVALID_MEMORY_RANGE; + return ResultInvalidMemoryRange; } return RESULT_SUCCESS; @@ -148,7 +147,7 @@ ResultVal RetrieveResourceLimitValue(Core::System& system, Handle resource_ const auto type = static_cast(resource_type); if (!IsValidResourceType(type)) { LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type); - return ERR_INVALID_ENUM_VALUE; + return ResultInvalidEnumValue; } const auto* const current_process = system.Kernel().CurrentProcess(); @@ -159,7 +158,7 @@ ResultVal RetrieveResourceLimitValue(Core::System& system, Handle resource_ if (!resource_limit_object) { LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}", resource_limit); - return ERR_INVALID_HANDLE; + return ResultInvalidHandle; } switch (value_type) { @@ -171,7 +170,7 @@ ResultVal RetrieveResourceLimitValue(Core::System& system, Handle resource_ return MakeResult(resource_limit_object->GetPeakValue(type)); default: LOG_ERROR(Kernel_SVC, "Invalid resource value_type: '{}'", value_type); - return ERR_INVALID_ENUM_VALUE; + return ResultInvalidEnumValue; } } } // Anonymous namespace @@ -185,12 +184,12 @@ static ResultCode SetHeapSize(Core::System& system, VAddr* heap_addr, u64 heap_s if ((heap_size % 0x200000) != 0) { LOG_ERROR(Kernel_SVC, "The heap size is not a multiple of 2MB, heap_size=0x{:016X}", heap_size); - return ERR_INVALID_SIZE; + return ResultInvalidSize; } if (heap_size >= 0x200000000) { LOG_ERROR(Kernel_SVC, "The heap size is not less than 8GB, heap_size=0x{:016X}", heap_size); - return ERR_INVALID_SIZE; + return ResultInvalidSize; } auto& page_table{system.Kernel().CurrentProcess()->PageTable()}; @@ -216,19 +215,19 @@ static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 si if (!Common::Is4KBAligned(address)) { LOG_ERROR(Kernel_SVC, "Address not page aligned (0x{:016X})", address); - return ERR_INVALID_ADDRESS; + return ResultInvalidAddress; } if (size == 0 || !Common::Is4KBAligned(size)) { LOG_ERROR(Kernel_SVC, "Invalid size (0x{:X}). Size must be non-zero and page aligned.", size); - return ERR_INVALID_ADDRESS; + return ResultInvalidAddress; } if (!IsValidAddressRange(address, size)) { LOG_ERROR(Kernel_SVC, "Address range overflowed (Address: 0x{:016X}, Size: 0x{:016X})", address, size); - return ERR_INVALID_ADDRESS_STATE; + return ResultInvalidCurrentMemory; } const auto attributes{static_cast(mask | attribute)}; @@ -237,7 +236,7 @@ static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 si LOG_ERROR(Kernel_SVC, "Memory attribute doesn't match the given mask (Attribute: 0x{:X}, Mask: {:X}", attribute, mask); - return ERR_INVALID_COMBINATION; + return ResultInvalidCombination; } auto& page_table{system.Kernel().CurrentProcess()->PageTable()}; @@ -301,7 +300,7 @@ static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle, LOG_ERROR(Kernel_SVC, "Port Name Address is not a valid virtual address, port_name_address=0x{:016X}", port_name_address); - return ERR_NOT_FOUND; + return ResultNotFound; } static constexpr std::size_t PortNameMaxLength = 11; @@ -310,7 +309,7 @@ static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle, if (port_name.size() > PortNameMaxLength) { LOG_ERROR(Kernel_SVC, "Port name is too long, expected {} but got {}", PortNameMaxLength, port_name.size()); - return ERR_OUT_OF_RANGE; + return ResultOutOfRange; } LOG_TRACE(Kernel_SVC, "called port_name={}", port_name); @@ -319,7 +318,7 @@ static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle, const auto it = kernel.FindNamedPort(port_name); if (!kernel.IsValidNamedPort(it)) { LOG_WARNING(Kernel_SVC, "tried to connect to unknown port: {}", port_name); - return ERR_NOT_FOUND; + return ResultNotFound; } auto client_port = it->second; @@ -346,7 +345,7 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) { std::shared_ptr session = handle_table.Get(handle); if (!session) { LOG_ERROR(Kernel_SVC, "called with invalid handle=0x{:08X}", handle); - return ERR_INVALID_HANDLE; + return ResultInvalidHandle; } LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName()); @@ -411,7 +410,7 @@ static ResultCode GetProcessId(Core::System& system, u64* process_id, Handle han const Process* const owner_process = thread->GetOwnerProcess(); if (!owner_process) { LOG_ERROR(Kernel_SVC, "Non-existent owning process encountered."); - return ERR_INVALID_HANDLE; + return ResultInvalidHandle; } *process_id = owner_process->GetProcessID(); @@ -421,7 +420,7 @@ static ResultCode GetProcessId(Core::System& system, u64* process_id, Handle han // NOTE: This should also handle debug objects before returning. LOG_ERROR(Kernel_SVC, "Handle does not exist, handle=0x{:08X}", handle); - return ERR_INVALID_HANDLE; + return ResultInvalidHandle; } static ResultCode GetProcessId32(Core::System& system, u32* process_id_low, u32* process_id_high, @@ -444,7 +443,7 @@ static ResultCode WaitSynchronization(Core::System& system, s32* index, VAddr ha LOG_ERROR(Kernel_SVC, "Handle address is not a valid virtual address, handle_address=0x{:016X}", handles_address); - return ERR_INVALID_POINTER; + return ResultInvalidPointer; } static constexpr u64 MaxHandles = 0x40; @@ -452,7 +451,7 @@ static ResultCode WaitSynchronization(Core::System& system, s32* index, VAddr ha if (handle_count > MaxHandles) { LOG_ERROR(Kernel_SVC, "Handle count specified is too large, expected {} but got {}", MaxHandles, handle_count); - return ERR_OUT_OF_RANGE; + return ResultOutOfRange; } auto& kernel = system.Kernel(); @@ -465,7 +464,7 @@ static ResultCode WaitSynchronization(Core::System& system, s32* index, VAddr ha if (object == nullptr) { LOG_ERROR(Kernel_SVC, "Object is a nullptr"); - return ERR_INVALID_HANDLE; + return ResultInvalidHandle; } objects[i] = object.get(); @@ -487,6 +486,7 @@ static ResultCode CancelSynchronization(Core::System& system, Handle thread_hand // Get the thread from its handle. const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); std::shared_ptr thread = handle_table.Get(thread_handle); + if (!thread) { LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle); return ResultInvalidHandle; @@ -531,6 +531,7 @@ static ResultCode ArbitrateUnlock(Core::System& system, VAddr address) { LOG_TRACE(Kernel_SVC, "called address=0x{:X}", address); // Validate the input address. + if (Memory::IsKernelAddress(address)) { LOG_ERROR(Kernel_SVC, "Attempting to arbitrate an unlock on a kernel address (address={:08X})", @@ -741,7 +742,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha if (info_sub_id != 0) { LOG_ERROR(Kernel_SVC, "Info sub id is non zero! info_id={}, info_sub_id={}", info_id, info_sub_id); - return ERR_INVALID_ENUM_VALUE; + return ResultInvalidEnumValue; } const auto& current_process_handle_table = @@ -750,7 +751,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha if (!process) { LOG_ERROR(Kernel_SVC, "Process is not valid! info_id={}, info_sub_id={}, handle={:08X}", info_id, info_sub_id, handle); - return ERR_INVALID_HANDLE; + return ResultInvalidHandle; } switch (info_id_type) { @@ -832,7 +833,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha } LOG_ERROR(Kernel_SVC, "Unimplemented svcGetInfo id=0x{:016X}", info_id); - return ERR_INVALID_ENUM_VALUE; + return ResultInvalidEnumValue; } case GetInfoType::IsCurrentProcessBeingDebugged: @@ -842,13 +843,13 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha case GetInfoType::RegisterResourceLimit: { if (handle != 0) { LOG_ERROR(Kernel, "Handle is non zero! handle={:08X}", handle); - return ERR_INVALID_HANDLE; + return ResultInvalidHandle; } if (info_sub_id != 0) { LOG_ERROR(Kernel, "Info sub id is non zero! info_id={}, info_sub_id={}", info_id, info_sub_id); - return ERR_INVALID_COMBINATION; + return ResultInvalidCombination; } Process* const current_process = system.Kernel().CurrentProcess(); @@ -873,13 +874,13 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha if (handle != 0) { LOG_ERROR(Kernel_SVC, "Process Handle is non zero, expected 0 result but got {:016X}", handle); - return ERR_INVALID_HANDLE; + return ResultInvalidHandle; } if (info_sub_id >= Process::RANDOM_ENTROPY_SIZE) { LOG_ERROR(Kernel_SVC, "Entropy size is out of range, expected {} but got {}", Process::RANDOM_ENTROPY_SIZE, info_sub_id); - return ERR_INVALID_COMBINATION; + return ResultInvalidCombination; } *result = system.Kernel().CurrentProcess()->GetRandomEntropy(info_sub_id); @@ -896,7 +897,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha if (info_sub_id != 0xFFFFFFFFFFFFFFFF && info_sub_id >= num_cpus) { LOG_ERROR(Kernel_SVC, "Core count is out of range, expected {} but got {}", num_cpus, info_sub_id); - return ERR_INVALID_COMBINATION; + return ResultInvalidCombination; } const auto thread = system.Kernel().CurrentProcess()->GetHandleTable().Get( @@ -904,7 +905,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha if (!thread) { LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", static_cast(handle)); - return ERR_INVALID_HANDLE; + return ResultInvalidHandle; } const auto& core_timing = system.CoreTiming(); @@ -928,7 +929,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha default: LOG_ERROR(Kernel_SVC, "Unimplemented svcGetInfo id=0x{:016X}", info_id); - return ERR_INVALID_ENUM_VALUE; + return ResultInvalidEnumValue; } } @@ -951,22 +952,22 @@ static ResultCode MapPhysicalMemory(Core::System& system, VAddr addr, u64 size) if (!Common::Is4KBAligned(addr)) { LOG_ERROR(Kernel_SVC, "Address is not aligned to 4KB, 0x{:016X}", addr); - return ERR_INVALID_ADDRESS; + return ResultInvalidAddress; } if (!Common::Is4KBAligned(size)) { LOG_ERROR(Kernel_SVC, "Size is not aligned to 4KB, 0x{:X}", size); - return ERR_INVALID_SIZE; + return ResultInvalidSize; } if (size == 0) { LOG_ERROR(Kernel_SVC, "Size is zero"); - return ERR_INVALID_SIZE; + return ResultInvalidSize; } if (!(addr < addr + size)) { LOG_ERROR(Kernel_SVC, "Size causes 64-bit overflow of address"); - return ERR_INVALID_MEMORY_RANGE; + return ResultInvalidMemoryRange; } Process* const current_process{system.Kernel().CurrentProcess()}; @@ -974,21 +975,21 @@ static ResultCode MapPhysicalMemory(Core::System& system, VAddr addr, u64 size) if (current_process->GetSystemResourceSize() == 0) { LOG_ERROR(Kernel_SVC, "System Resource Size is zero"); - return ERR_INVALID_STATE; + return ResultInvalidState; } if (!page_table.IsInsideAddressSpace(addr, size)) { LOG_ERROR(Kernel_SVC, "Address is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr, size); - return ERR_INVALID_MEMORY_RANGE; + return ResultInvalidMemoryRange; } if (page_table.IsOutsideAliasRegion(addr, size)) { LOG_ERROR(Kernel_SVC, "Address is not within the alias region, addr=0x{:016X}, size=0x{:016X}", addr, size); - return ERR_INVALID_MEMORY_RANGE; + return ResultInvalidMemoryRange; } return page_table.MapPhysicalMemory(addr, size); @@ -1005,22 +1006,22 @@ static ResultCode UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size if (!Common::Is4KBAligned(addr)) { LOG_ERROR(Kernel_SVC, "Address is not aligned to 4KB, 0x{:016X}", addr); - return ERR_INVALID_ADDRESS; + return ResultInvalidAddress; } if (!Common::Is4KBAligned(size)) { LOG_ERROR(Kernel_SVC, "Size is not aligned to 4KB, 0x{:X}", size); - return ERR_INVALID_SIZE; + return ResultInvalidSize; } if (size == 0) { LOG_ERROR(Kernel_SVC, "Size is zero"); - return ERR_INVALID_SIZE; + return ResultInvalidSize; } if (!(addr < addr + size)) { LOG_ERROR(Kernel_SVC, "Size causes 64-bit overflow of address"); - return ERR_INVALID_MEMORY_RANGE; + return ResultInvalidMemoryRange; } Process* const current_process{system.Kernel().CurrentProcess()}; @@ -1028,21 +1029,21 @@ static ResultCode UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size if (current_process->GetSystemResourceSize() == 0) { LOG_ERROR(Kernel_SVC, "System Resource Size is zero"); - return ERR_INVALID_STATE; + return ResultInvalidState; } if (!page_table.IsInsideAddressSpace(addr, size)) { LOG_ERROR(Kernel_SVC, "Address is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr, size); - return ERR_INVALID_MEMORY_RANGE; + return ResultInvalidMemoryRange; } if (page_table.IsOutsideAliasRegion(addr, size)) { LOG_ERROR(Kernel_SVC, "Address is not within the alias region, addr=0x{:016X}, size=0x{:016X}", addr, size); - return ERR_INVALID_MEMORY_RANGE; + return ResultInvalidMemoryRange; } return page_table.UnmapPhysicalMemory(addr, size); @@ -1212,23 +1213,23 @@ static ResultCode MapSharedMemory(Core::System& system, Handle shared_memory_han if (!Common::Is4KBAligned(addr)) { LOG_ERROR(Kernel_SVC, "Address is not aligned to 4KB, addr=0x{:016X}", addr); - return ERR_INVALID_ADDRESS; + return ResultInvalidAddress; } if (size == 0) { LOG_ERROR(Kernel_SVC, "Size is 0"); - return ERR_INVALID_SIZE; + return ResultInvalidSize; } if (!Common::Is4KBAligned(size)) { LOG_ERROR(Kernel_SVC, "Size is not aligned to 4KB, size=0x{:016X}", size); - return ERR_INVALID_SIZE; + return ResultInvalidSize; } if (!IsValidAddressRange(addr, size)) { LOG_ERROR(Kernel_SVC, "Region is not a valid address range, addr=0x{:016X}, size=0x{:016X}", addr, size); - return ERR_INVALID_ADDRESS_STATE; + return ResultInvalidCurrentMemory; } const auto permission_type = static_cast(permissions); @@ -1236,7 +1237,7 @@ static ResultCode MapSharedMemory(Core::System& system, Handle shared_memory_han Memory::MemoryPermission::ReadAndWrite) { LOG_ERROR(Kernel_SVC, "Expected Read or ReadWrite permission but got permissions=0x{:08X}", permissions); - return ERR_INVALID_MEMORY_PERMISSIONS; + return ResultInvalidMemoryPermissions; } auto* const current_process{system.Kernel().CurrentProcess()}; @@ -1247,7 +1248,7 @@ static ResultCode MapSharedMemory(Core::System& system, Handle shared_memory_han "Addr does not fit within the valid region, addr=0x{:016X}, " "size=0x{:016X}", addr, size); - return ERR_INVALID_MEMORY_RANGE; + return ResultInvalidMemoryRange; } if (page_table.IsInsideHeapRegion(addr, size)) { @@ -1255,7 +1256,7 @@ static ResultCode MapSharedMemory(Core::System& system, Handle shared_memory_han "Addr does not fit within the heap region, addr=0x{:016X}, " "size=0x{:016X}", addr, size); - return ERR_INVALID_MEMORY_RANGE; + return ResultInvalidMemoryRange; } if (page_table.IsInsideAliasRegion(addr, size)) { @@ -1263,14 +1264,14 @@ static ResultCode MapSharedMemory(Core::System& system, Handle shared_memory_han "Address does not fit within the map region, addr=0x{:016X}, " "size=0x{:016X}", addr, size); - return ERR_INVALID_MEMORY_RANGE; + return ResultInvalidMemoryRange; } auto shared_memory{current_process->GetHandleTable().Get(shared_memory_handle)}; if (!shared_memory) { LOG_ERROR(Kernel_SVC, "Shared memory does not exist, shared_memory_handle=0x{:08X}", shared_memory_handle); - return ERR_INVALID_HANDLE; + return ResultInvalidHandle; } return shared_memory->Map(*current_process, addr, size, permission_type); @@ -1291,7 +1292,7 @@ static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_add if (!process) { LOG_ERROR(Kernel_SVC, "Process handle does not exist, process_handle=0x{:08X}", process_handle); - return ERR_INVALID_HANDLE; + return ResultInvalidHandle; } auto& memory{system.Memory()}; @@ -1338,18 +1339,18 @@ static ResultCode MapProcessCodeMemory(Core::System& system, Handle process_hand if (!Common::Is4KBAligned(src_address)) { LOG_ERROR(Kernel_SVC, "src_address is not page-aligned (src_address=0x{:016X}).", src_address); - return ERR_INVALID_ADDRESS; + return ResultInvalidAddress; } if (!Common::Is4KBAligned(dst_address)) { LOG_ERROR(Kernel_SVC, "dst_address is not page-aligned (dst_address=0x{:016X}).", dst_address); - return ERR_INVALID_ADDRESS; + return ResultInvalidAddress; } if (size == 0 || !Common::Is4KBAligned(size)) { LOG_ERROR(Kernel_SVC, "Size is zero or not page-aligned (size=0x{:016X})", size); - return ERR_INVALID_SIZE; + return ResultInvalidSize; } if (!IsValidAddressRange(dst_address, size)) { @@ -1357,7 +1358,7 @@ static ResultCode MapProcessCodeMemory(Core::System& system, Handle process_hand "Destination address range overflows the address space (dst_address=0x{:016X}, " "size=0x{:016X}).", dst_address, size); - return ERR_INVALID_ADDRESS_STATE; + return ResultInvalidCurrentMemory; } if (!IsValidAddressRange(src_address, size)) { @@ -1365,7 +1366,7 @@ static ResultCode MapProcessCodeMemory(Core::System& system, Handle process_hand "Source address range overflows the address space (src_address=0x{:016X}, " "size=0x{:016X}).", src_address, size); - return ERR_INVALID_ADDRESS_STATE; + return ResultInvalidCurrentMemory; } const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); @@ -1373,7 +1374,7 @@ static ResultCode MapProcessCodeMemory(Core::System& system, Handle process_hand if (!process) { LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).", process_handle); - return ERR_INVALID_HANDLE; + return ResultInvalidHandle; } auto& page_table = process->PageTable(); @@ -1382,7 +1383,7 @@ static ResultCode MapProcessCodeMemory(Core::System& system, Handle process_hand "Source address range is not within the address space (src_address=0x{:016X}, " "size=0x{:016X}).", src_address, size); - return ERR_INVALID_ADDRESS_STATE; + return ResultInvalidCurrentMemory; } if (!page_table.IsInsideASLRRegion(dst_address, size)) { @@ -1390,7 +1391,7 @@ static ResultCode MapProcessCodeMemory(Core::System& system, Handle process_hand "Destination address range is not within the ASLR region (dst_address=0x{:016X}, " "size=0x{:016X}).", dst_address, size); - return ERR_INVALID_MEMORY_RANGE; + return ResultInvalidMemoryRange; } return page_table.MapProcessCodeMemory(dst_address, src_address, size); @@ -1406,18 +1407,18 @@ static ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_ha if (!Common::Is4KBAligned(dst_address)) { LOG_ERROR(Kernel_SVC, "dst_address is not page-aligned (dst_address=0x{:016X}).", dst_address); - return ERR_INVALID_ADDRESS; + return ResultInvalidAddress; } if (!Common::Is4KBAligned(src_address)) { LOG_ERROR(Kernel_SVC, "src_address is not page-aligned (src_address=0x{:016X}).", src_address); - return ERR_INVALID_ADDRESS; + return ResultInvalidAddress; } if (size == 0 || Common::Is4KBAligned(size)) { LOG_ERROR(Kernel_SVC, "Size is zero or not page-aligned (size=0x{:016X}).", size); - return ERR_INVALID_SIZE; + return ResultInvalidSize; } if (!IsValidAddressRange(dst_address, size)) { @@ -1425,7 +1426,7 @@ static ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_ha "Destination address range overflows the address space (dst_address=0x{:016X}, " "size=0x{:016X}).", dst_address, size); - return ERR_INVALID_ADDRESS_STATE; + return ResultInvalidCurrentMemory; } if (!IsValidAddressRange(src_address, size)) { @@ -1433,7 +1434,7 @@ static ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_ha "Source address range overflows the address space (src_address=0x{:016X}, " "size=0x{:016X}).", src_address, size); - return ERR_INVALID_ADDRESS_STATE; + return ResultInvalidCurrentMemory; } const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); @@ -1441,7 +1442,7 @@ static ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_ha if (!process) { LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).", process_handle); - return ERR_INVALID_HANDLE; + return ResultInvalidHandle; } auto& page_table = process->PageTable(); @@ -1450,7 +1451,7 @@ static ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_ha "Source address range is not within the address space (src_address=0x{:016X}, " "size=0x{:016X}).", src_address, size); - return ERR_INVALID_ADDRESS_STATE; + return ResultInvalidCurrentMemory; } if (!page_table.IsInsideASLRRegion(dst_address, size)) { @@ -1458,7 +1459,7 @@ static ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_ha "Destination address range is not within the ASLR region (dst_address=0x{:016X}, " "size=0x{:016X}).", dst_address, size); - return ERR_INVALID_MEMORY_RANGE; + return ResultInvalidMemoryRange; } return page_table.UnmapProcessCodeMemory(dst_address, src_address, size); @@ -1526,7 +1527,7 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e system.CoreTiming().GetGlobalTimeNs().count() + 100000000); if (!thread_reservation.Succeeded()) { LOG_ERROR(Kernel_SVC, "Could not reserve a new thread"); - return ERR_RESOURCE_LIMIT_EXCEEDED; + return ResultResourceLimitedExceeded; } std::shared_ptr thread; @@ -1856,7 +1857,7 @@ static ResultCode ResetSignal(Core::System& system, Handle handle) { LOG_ERROR(Kernel_SVC, "invalid handle (0x{:08X})", handle); - return Svc::ResultInvalidHandle; + return ResultInvalidHandle; } static ResultCode ResetSignal32(Core::System& system, Handle handle) { @@ -1872,18 +1873,18 @@ static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAd if (!Common::Is4KBAligned(addr)) { LOG_ERROR(Kernel_SVC, "Address ({:016X}) is not page aligned!", addr); - return ERR_INVALID_ADDRESS; + return ResultInvalidAddress; } if (!Common::Is4KBAligned(size) || size == 0) { LOG_ERROR(Kernel_SVC, "Size ({:016X}) is not page aligned or equal to zero!", size); - return ERR_INVALID_ADDRESS; + return ResultInvalidAddress; } if (!IsValidAddressRange(addr, size)) { LOG_ERROR(Kernel_SVC, "Address and size cause overflow! (address={:016X}, size={:016X})", addr, size); - return ERR_INVALID_ADDRESS_STATE; + return ResultInvalidCurrentMemory; } const auto perms{static_cast(permissions)}; @@ -1891,7 +1892,7 @@ static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAd perms == Memory::MemoryPermission::Write) { LOG_ERROR(Kernel_SVC, "Invalid memory permissions for transfer memory! (perms={:08X})", permissions); - return ERR_INVALID_MEMORY_PERMISSIONS; + return ResultInvalidMemoryPermissions; } auto& kernel = system.Kernel(); @@ -1900,7 +1901,7 @@ static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAd LimitableResource::TransferMemory); if (!trmem_reservation.Succeeded()) { LOG_ERROR(Kernel_SVC, "Could not reserve a new transfer memory"); - return ERR_RESOURCE_LIMIT_EXCEEDED; + return ResultResourceLimitedExceeded; } auto transfer_mem_handle = TransferMemory::Create(kernel, system.Memory(), addr, size, perms); @@ -2009,7 +2010,6 @@ static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle, LOG_ERROR(Kernel_SVC, "Unable to successfully set core mask (result={})", set_result.raw); return set_result; } - return RESULT_SUCCESS; } @@ -2031,7 +2031,7 @@ static ResultCode SignalEvent(Core::System& system, Handle event_handle) { LimitableResource::Events); if (!event_reservation.Succeeded()) { LOG_ERROR(Kernel, "Could not reserve a new event"); - return ERR_RESOURCE_LIMIT_EXCEEDED; + return ResultResourceLimitedExceeded; } // Get the writable event. @@ -2075,7 +2075,7 @@ static ResultCode ClearEvent(Core::System& system, Handle event_handle) { LOG_ERROR(Kernel_SVC, "Event handle does not exist, event_handle=0x{:08X}", event_handle); - return Svc::ResultInvalidHandle; + return ResultInvalidHandle; } static ResultCode ClearEvent32(Core::System& system, Handle event_handle) { @@ -2138,13 +2138,13 @@ static ResultCode GetProcessInfo(Core::System& system, u64* out, Handle process_ if (!process) { LOG_ERROR(Kernel_SVC, "Process handle does not exist, process_handle=0x{:08X}", process_handle); - return ERR_INVALID_HANDLE; + return ResultInvalidHandle; } const auto info_type = static_cast(type); if (info_type != InfoType::Status) { LOG_ERROR(Kernel_SVC, "Expected info_type to be Status but got {} instead", type); - return ERR_INVALID_ENUM_VALUE; + return ResultInvalidEnumValue; } *out = static_cast(process->GetStatus()); @@ -2206,7 +2206,7 @@ static ResultCode SetResourceLimitLimitValue(Core::System& system, Handle resour const auto type = static_cast(resource_type); if (!IsValidResourceType(type)) { LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type); - return ERR_INVALID_ENUM_VALUE; + return ResultInvalidEnumValue; } auto* const current_process = system.Kernel().CurrentProcess(); @@ -2217,16 +2217,16 @@ static ResultCode SetResourceLimitLimitValue(Core::System& system, Handle resour if (!resource_limit_object) { LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}", resource_limit); - return ERR_INVALID_HANDLE; + return ResultInvalidHandle; } const auto set_result = resource_limit_object->SetLimitValue(type, static_cast(value)); if (set_result.IsError()) { - LOG_ERROR( - Kernel_SVC, - "Attempted to lower resource limit ({}) for category '{}' below its current value ({})", - resource_limit_object->GetLimitValue(type), resource_type, - resource_limit_object->GetCurrentValue(type)); + LOG_ERROR(Kernel_SVC, + "Attempted to lower resource limit ({}) for category '{}' below its current " + "value ({})", + resource_limit_object->GetLimitValue(type), resource_type, + resource_limit_object->GetCurrentValue(type)); return set_result; } @@ -2243,7 +2243,7 @@ static ResultCode GetProcessList(Core::System& system, u32* out_num_processes, LOG_ERROR(Kernel_SVC, "Supplied size outside [0, 0x0FFFFFFF] range. out_process_ids_size={}", out_process_ids_size); - return ERR_OUT_OF_RANGE; + return ResultOutOfRange; } const auto& kernel = system.Kernel(); @@ -2253,7 +2253,7 @@ static ResultCode GetProcessList(Core::System& system, u32* out_num_processes, out_process_ids, total_copy_size)) { LOG_ERROR(Kernel_SVC, "Address range outside address space. begin=0x{:016X}, end=0x{:016X}", out_process_ids, out_process_ids + total_copy_size); - return ERR_INVALID_ADDRESS_STATE; + return ResultInvalidCurrentMemory; } auto& memory = system.Memory(); @@ -2282,7 +2282,7 @@ static ResultCode GetThreadList(Core::System& system, u32* out_num_threads, VAdd if ((out_thread_ids_size & 0xF0000000) != 0) { LOG_ERROR(Kernel_SVC, "Supplied size outside [0, 0x0FFFFFFF] range. size={}", out_thread_ids_size); - return ERR_OUT_OF_RANGE; + return ResultOutOfRange; } const auto* const current_process = system.Kernel().CurrentProcess(); @@ -2292,7 +2292,7 @@ static ResultCode GetThreadList(Core::System& system, u32* out_num_threads, VAdd !current_process->PageTable().IsInsideAddressSpace(out_thread_ids, total_copy_size)) { LOG_ERROR(Kernel_SVC, "Address range outside address space. begin=0x{:016X}, end=0x{:016X}", out_thread_ids, out_thread_ids + total_copy_size); - return ERR_INVALID_ADDRESS_STATE; + return ResultInvalidCurrentMemory; } auto& memory = system.Memory(); diff --git a/src/core/hle/kernel/svc_results.h b/src/core/hle/kernel/svc_results.h index 204cd989d..a26d9f2c9 100755 --- a/src/core/hle/kernel/svc_results.h +++ b/src/core/hle/kernel/svc_results.h @@ -1,4 +1,4 @@ -// Copyright 2020 yuzu emulator team +// Copyright 2018 yuzu emulator team // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -6,21 +6,36 @@ #include "core/hle/result.h" -namespace Kernel::Svc { +namespace Kernel { +// Confirmed Switch kernel error codes + +constexpr ResultCode ResultMaxConnectionsReached{ErrorModule::Kernel, 7}; +constexpr ResultCode ResultInvalidCapabilityDescriptor{ErrorModule::Kernel, 14}; constexpr ResultCode ResultNoSynchronizationObject{ErrorModule::Kernel, 57}; constexpr ResultCode ResultTerminationRequested{ErrorModule::Kernel, 59}; +constexpr ResultCode ResultInvalidSize{ErrorModule::Kernel, 101}; constexpr ResultCode ResultInvalidAddress{ErrorModule::Kernel, 102}; constexpr ResultCode ResultOutOfResource{ErrorModule::Kernel, 103}; +constexpr ResultCode ResultOutOfMemory{ErrorModule::Kernel, 104}; +constexpr ResultCode ResultHandleTableFull{ErrorModule::Kernel, 105}; constexpr ResultCode ResultInvalidCurrentMemory{ErrorModule::Kernel, 106}; +constexpr ResultCode ResultInvalidMemoryPermissions{ErrorModule::Kernel, 108}; +constexpr ResultCode ResultInvalidMemoryRange{ErrorModule::Kernel, 110}; constexpr ResultCode ResultInvalidPriority{ErrorModule::Kernel, 112}; constexpr ResultCode ResultInvalidCoreId{ErrorModule::Kernel, 113}; constexpr ResultCode ResultInvalidHandle{ErrorModule::Kernel, 114}; +constexpr ResultCode ResultInvalidPointer{ErrorModule::Kernel, 115}; constexpr ResultCode ResultInvalidCombination{ErrorModule::Kernel, 116}; constexpr ResultCode ResultTimedOut{ErrorModule::Kernel, 117}; constexpr ResultCode ResultCancelled{ErrorModule::Kernel, 118}; +constexpr ResultCode ResultOutOfRange{ErrorModule::Kernel, 119}; constexpr ResultCode ResultInvalidEnumValue{ErrorModule::Kernel, 120}; +constexpr ResultCode ResultNotFound{ErrorModule::Kernel, 121}; constexpr ResultCode ResultBusy{ErrorModule::Kernel, 122}; +constexpr ResultCode ResultSessionClosedByRemote{ErrorModule::Kernel, 123}; constexpr ResultCode ResultInvalidState{ErrorModule::Kernel, 125}; +constexpr ResultCode ResultReservedValue{ErrorModule::Kernel, 126}; +constexpr ResultCode ResultResourceLimitedExceeded{ErrorModule::Kernel, 132}; -} // namespace Kernel::Svc +} // namespace Kernel diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp index 9da786b4e..c724d2554 100755 --- a/src/core/hle/service/ldr/ldr.cpp +++ b/src/core/hle/service/ldr/ldr.cpp @@ -11,10 +11,10 @@ #include "common/scope_exit.h" #include "core/core.h" #include "core/hle/ipc_helpers.h" -#include "core/hle/kernel/errors.h" #include "core/hle/kernel/memory/page_table.h" #include "core/hle/kernel/memory/system_control.h" #include "core/hle/kernel/process.h" +#include "core/hle/kernel/svc_results.h" #include "core/hle/service/ldr/ldr.h" #include "core/hle/service/service.h" #include "core/loader/nro.h" @@ -330,7 +330,7 @@ public: const VAddr addr{GetRandomMapRegion(page_table, size)}; const ResultCode result{page_table.MapProcessCodeMemory(addr, baseAddress, size)}; - if (result == Kernel::ERR_INVALID_ADDRESS_STATE) { + if (result == Kernel::ResultInvalidCurrentMemory) { continue; } @@ -361,7 +361,7 @@ public: const ResultCode result{ page_table.MapProcessCodeMemory(addr + nro_size, bss_addr, bss_size)}; - if (result == Kernel::ERR_INVALID_ADDRESS_STATE) { + if (result == Kernel::ResultInvalidCurrentMemory) { continue; } diff --git a/src/video_core/compatible_formats.cpp b/src/video_core/compatible_formats.cpp index acf2668dc..873fcd1a7 100755 --- a/src/video_core/compatible_formats.cpp +++ b/src/video_core/compatible_formats.cpp @@ -39,13 +39,12 @@ constexpr std::array VIEW_CLASS_64_BITS{ // TODO: How should we handle 48 bits? constexpr std::array VIEW_CLASS_32_BITS{ - PixelFormat::R16G16_FLOAT, PixelFormat::B10G11R11_FLOAT, PixelFormat::R32_FLOAT, - PixelFormat::A2B10G10R10_UNORM, PixelFormat::R16G16_UINT, PixelFormat::R32_UINT, - PixelFormat::R16G16_SINT, PixelFormat::R32_SINT, PixelFormat::A8B8G8R8_UNORM, - PixelFormat::R16G16_UNORM, PixelFormat::A8B8G8R8_SNORM, PixelFormat::R16G16_SNORM, - PixelFormat::A8B8G8R8_SRGB, PixelFormat::E5B9G9R9_FLOAT, PixelFormat::B8G8R8A8_UNORM, - PixelFormat::B8G8R8A8_SRGB, PixelFormat::A8B8G8R8_UINT, PixelFormat::A8B8G8R8_SINT, - PixelFormat::A2B10G10R10_UINT, + PixelFormat::R16G16_FLOAT, PixelFormat::B10G11R11_FLOAT, PixelFormat::R32_FLOAT, + PixelFormat::A2B10G10R10_UNORM, PixelFormat::R16G16_UINT, PixelFormat::R32_UINT, + PixelFormat::R16G16_SINT, PixelFormat::R32_SINT, PixelFormat::A8B8G8R8_UNORM, + PixelFormat::R16G16_UNORM, PixelFormat::A8B8G8R8_SNORM, PixelFormat::R16G16_SNORM, + PixelFormat::A8B8G8R8_SRGB, PixelFormat::E5B9G9R9_FLOAT, PixelFormat::A8B8G8R8_UINT, + PixelFormat::A8B8G8R8_SINT, PixelFormat::A2B10G10R10_UINT, }; // TODO: How should we handle 24 bits? diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt index 970120acc..f5062a5a9 100755 --- a/src/video_core/host_shaders/CMakeLists.txt +++ b/src/video_core/host_shaders/CMakeLists.txt @@ -5,6 +5,8 @@ set(SHADER_FILES convert_float_to_depth.frag full_screen_triangle.vert opengl_copy_bc4.comp + opengl_copy_bgr16.comp + opengl_copy_bgra.comp opengl_present.frag opengl_present.vert pitch_unswizzle.comp diff --git a/src/video_core/host_shaders/opengl_copy_bgr16.comp b/src/video_core/host_shaders/opengl_copy_bgr16.comp new file mode 100755 index 000000000..fd4d01fb7 --- /dev/null +++ b/src/video_core/host_shaders/opengl_copy_bgr16.comp @@ -0,0 +1,14 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#version 430 core + +layout (local_size_x = 4, local_size_y = 4) in; + +layout(binding = 0, r16ui) readonly uniform uimage2D bgr_input; +layout(binding = 1, r16ui) writeonly uniform uimage2D bgr_output; + +void main() { + imageStore(bgr_output, ivec2(gl_GlobalInvocationID.xy), imageLoad(bgr_input, ivec2(gl_GlobalInvocationID.xy))); +} diff --git a/src/video_core/host_shaders/opengl_copy_bgra.comp b/src/video_core/host_shaders/opengl_copy_bgra.comp new file mode 100755 index 000000000..83b831eb1 --- /dev/null +++ b/src/video_core/host_shaders/opengl_copy_bgra.comp @@ -0,0 +1,15 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#version 430 core + +layout (local_size_x = 4, local_size_y = 4) in; + +layout(binding = 0, rgba8) readonly uniform image2D bgr_input; +layout(binding = 1, rgba8) writeonly uniform image2D bgr_output; + +void main() { + vec4 color = imageLoad(bgr_input, ivec2(gl_GlobalInvocationID.xy)); + imageStore(bgr_output, ivec2(gl_GlobalInvocationID.xy), color.bgra); +} diff --git a/src/video_core/memory_manager.h b/src/video_core/memory_manager.h index b8357bd46..5d6c196fa 100755 --- a/src/video_core/memory_manager.h +++ b/src/video_core/memory_manager.h @@ -162,10 +162,11 @@ private: VideoCore::RasterizerInterface* rasterizer = nullptr; std::vector page_table; - std::vector> cache_invalidate_queue; using MapRange = std::pair; std::vector map_ranges; + + std::vector> cache_invalidate_queue; }; } // namespace Tegra diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp index b9e9f20d6..48d5c4a5e 100755 --- a/src/video_core/renderer_opengl/gl_device.cpp +++ b/src/video_core/renderer_opengl/gl_device.cpp @@ -198,8 +198,8 @@ bool IsASTCSupported() { } // Anonymous namespace Device::Device() { - if (!GLAD_GL_VERSION_4_3) { - LOG_ERROR(Render_OpenGL, "OpenGL 4.3 is not available"); + if (!GLAD_GL_VERSION_4_6) { + LOG_ERROR(Render_OpenGL, "OpenGL 4.6 is not available"); throw std::runtime_error{"Insufficient version"}; } const std::string_view vendor = reinterpret_cast(glGetString(GL_VENDOR)); diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index a85b3d439..3a0ebd759 100755 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -38,6 +38,7 @@ namespace OpenGL { using Maxwell = Tegra::Engines::Maxwell3D::Regs; +using GLvec4 = std::array; using Tegra::Engines::ShaderType; using VideoCore::Surface::PixelFormat; @@ -51,14 +52,7 @@ MICROPROFILE_DEFINE(OpenGL_CacheManagement, "OpenGL", "Cache Management", MP_RGB namespace { -constexpr size_t NUM_CONST_BUFFERS_PER_STAGE = 18; -constexpr size_t NUM_CONST_BUFFERS_BYTES_PER_STAGE = - NUM_CONST_BUFFERS_PER_STAGE * Maxwell::MaxConstBufferSize; -constexpr size_t TOTAL_CONST_BUFFER_BYTES = - NUM_CONST_BUFFERS_BYTES_PER_STAGE * Maxwell::MaxShaderStage; - constexpr size_t NUM_SUPPORTED_VERTEX_ATTRIBUTES = 16; -constexpr size_t NUM_SUPPORTED_VERTEX_BINDINGS = 16; struct TextureHandle { constexpr TextureHandle(u32 data, bool via_header_index) { diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 93a1a52e0..ff5ec70dd 100755 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp @@ -398,7 +398,9 @@ void AttachTexture(GLuint fbo, GLenum attachment, const ImageView* image_view) { [[nodiscard]] bool IsPixelFormatBGR(PixelFormat format) { switch (format) { - case PixelFormat::B5G6R5_UNORM: + // TODO: B5G6R5 is currently not rendering after the compute copy. + // uncomment when this is resolved. + // case PixelFormat::B5G6R5_UNORM: case PixelFormat::B8G8R8A8_UNORM: case PixelFormat::B8G8R8A8_SRGB: return true; @@ -407,6 +409,16 @@ void AttachTexture(GLuint fbo, GLenum attachment, const ImageView* image_view) { } } +[[nodiscard]] GLenum GetStorageInternalFormat(PixelFormat format) { + switch (format) { + case PixelFormat::R5G6B5_UNORM: + case PixelFormat::B5G6R5_UNORM: + return GL_RGB565; + default: + return GL_RGBA8; + } +} + } // Anonymous namespace ImageBufferMap::~ImageBufferMap() { @@ -523,6 +535,9 @@ bool TextureCacheRuntime::CanImageBeCopied(const Image& dst, const Image& src) { if (dst.info.type == ImageType::e3D && dst.info.format == PixelFormat::BC4_UNORM) { return false; } + if (IsPixelFormatBGR(dst.info.format) || IsPixelFormatBGR(src.info.format)) { + return false; + } return true; } @@ -531,6 +546,8 @@ void TextureCacheRuntime::EmulateCopyImage(Image& dst, Image& src, if (dst.info.type == ImageType::e3D && dst.info.format == PixelFormat::BC4_UNORM) { ASSERT(src.info.type == ImageType::e3D); util_shaders.CopyBC4(dst, src, copies); + } else if (IsPixelFormatBGR(dst.info.format) || IsPixelFormatBGR(src.info.format)) { + util_shaders.CopyBGR(dst, src, copies); } else { UNREACHABLE(); } @@ -774,6 +791,39 @@ void Image::DownloadMemory(ImageBufferMap& map, } } +GLuint Image::StorageHandle() noexcept { + switch (info.format) { + case PixelFormat::A8B8G8R8_SRGB: + case PixelFormat::B8G8R8A8_SRGB: + case PixelFormat::R5G6B5_UNORM: + case PixelFormat::B5G6R5_UNORM: + case PixelFormat::BC1_RGBA_SRGB: + case PixelFormat::BC2_SRGB: + case PixelFormat::BC3_SRGB: + case PixelFormat::BC7_SRGB: + case PixelFormat::ASTC_2D_4X4_SRGB: + case PixelFormat::ASTC_2D_8X8_SRGB: + case PixelFormat::ASTC_2D_8X5_SRGB: + case PixelFormat::ASTC_2D_5X4_SRGB: + case PixelFormat::ASTC_2D_5X5_SRGB: + case PixelFormat::ASTC_2D_10X8_SRGB: + case PixelFormat::ASTC_2D_6X6_SRGB: + case PixelFormat::ASTC_2D_10X10_SRGB: + case PixelFormat::ASTC_2D_12X12_SRGB: + case PixelFormat::ASTC_2D_8X6_SRGB: + case PixelFormat::ASTC_2D_6X5_SRGB: + if (store_view.handle != 0) { + return store_view.handle; + } + store_view.Create(); + glTextureView(store_view.handle, ImageTarget(info), texture.handle, + GetStorageInternalFormat(info.format), 0, info.resources.levels, 0, + info.resources.layers); + return store_view.handle; + default: + return texture.handle; + } +} void Image::CopyBufferToImage(const VideoCommon::BufferImageCopy& copy, size_t buffer_offset) { // Compressed formats don't have a pixel format or type const bool is_compressed = gl_format == GL_NONE; @@ -955,13 +1005,7 @@ void ImageView::SetupView(const Device& device, Image& image, ImageViewType view glTextureView(handle, target, parent, internal_format, view_range.base.level, view_range.extent.levels, view_range.base.layer, view_range.extent.layers); if (!info.IsRenderTarget()) { - auto swizzle = info.Swizzle(); - if (IsPixelFormatBGR(image.info.format) || IsPixelFormatBGR(info.format)) { - // Explicitly swap the R and B channels of the swizzle. - swizzle[0] = SwizzleSource::R; - swizzle[2] = SwizzleSource::B; - } - ApplySwizzle(handle, format, swizzle); + ApplySwizzle(handle, format, info.Swizzle()); } } if (device.HasDebuggingToolAttached()) { diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index 874cf54f4..a6172f009 100755 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h @@ -145,6 +145,8 @@ public: void DownloadMemory(ImageBufferMap& map, std::span copies); + GLuint StorageHandle() noexcept; + GLuint Handle() const noexcept { return texture.handle; } @@ -155,8 +157,8 @@ private: void CopyImageToBuffer(const VideoCommon::BufferImageCopy& copy, size_t buffer_offset); OGLTexture texture; - OGLTextureView store_view; OGLBuffer buffer; + OGLTextureView store_view; GLenum gl_internal_format = GL_NONE; GLenum gl_format = GL_NONE; GLenum gl_type = GL_NONE; diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h index cbccfdeb4..f7ad8f370 100755 --- a/src/video_core/renderer_opengl/maxwell_to_gl.h +++ b/src/video_core/renderer_opengl/maxwell_to_gl.h @@ -4,23 +4,10 @@ #pragma once -#include #include -#include "common/common_types.h" -#include "common/logging/log.h" #include "video_core/engines/maxwell_3d.h" -namespace OpenGL { - -using GLvec2 = std::array; -using GLvec3 = std::array; -using GLvec4 = std::array; - -using GLuvec2 = std::array; -using GLuvec3 = std::array; -using GLuvec4 = std::array; - -namespace MaxwellToGL { +namespace OpenGL::MaxwellToGL { using Maxwell = Tegra::Engines::Maxwell3D::Regs; @@ -317,26 +304,6 @@ inline GLenum BlendFunc(Maxwell::Blend::Factor factor) { return GL_ZERO; } -inline GLenum SwizzleSource(Tegra::Texture::SwizzleSource source) { - switch (source) { - case Tegra::Texture::SwizzleSource::Zero: - return GL_ZERO; - case Tegra::Texture::SwizzleSource::R: - return GL_RED; - case Tegra::Texture::SwizzleSource::G: - return GL_GREEN; - case Tegra::Texture::SwizzleSource::B: - return GL_BLUE; - case Tegra::Texture::SwizzleSource::A: - return GL_ALPHA; - case Tegra::Texture::SwizzleSource::OneInt: - case Tegra::Texture::SwizzleSource::OneFloat: - return GL_ONE; - } - UNIMPLEMENTED_MSG("Unimplemented swizzle source={}", source); - return GL_ZERO; -} - inline GLenum ComparisonOp(Maxwell::ComparisonOp comparison) { switch (comparison) { case Maxwell::ComparisonOp::Never: @@ -493,5 +460,4 @@ inline GLenum ViewportSwizzle(Maxwell::ViewportSwizzle swizzle) { return GL_VIEWPORT_SWIZZLE_POSITIVE_X_NV + static_cast(swizzle); } -} // namespace MaxwellToGL -} // namespace OpenGL +} // namespace OpenGL::MaxwellToGL diff --git a/src/video_core/renderer_opengl/util_shaders.cpp b/src/video_core/renderer_opengl/util_shaders.cpp index 1b58e8617..03252e646 100755 --- a/src/video_core/renderer_opengl/util_shaders.cpp +++ b/src/video_core/renderer_opengl/util_shaders.cpp @@ -14,6 +14,8 @@ #include "video_core/host_shaders/block_linear_unswizzle_2d_comp.h" #include "video_core/host_shaders/block_linear_unswizzle_3d_comp.h" #include "video_core/host_shaders/opengl_copy_bc4_comp.h" +#include "video_core/host_shaders/opengl_copy_bgr16_comp.h" +#include "video_core/host_shaders/opengl_copy_bgra_comp.h" #include "video_core/host_shaders/pitch_unswizzle_comp.h" #include "video_core/renderer_opengl/gl_resource_manager.h" #include "video_core/renderer_opengl/gl_shader_manager.h" @@ -36,6 +38,7 @@ using VideoCommon::SwizzleParameters; using VideoCommon::Accelerated::MakeBlockLinearSwizzle2DParams; using VideoCommon::Accelerated::MakeBlockLinearSwizzle3DParams; using VideoCore::Surface::BytesPerBlock; +using VideoCore::Surface::PixelFormat; namespace { @@ -55,7 +58,9 @@ UtilShaders::UtilShaders(ProgramManager& program_manager_) block_linear_unswizzle_2d_program(MakeProgram(BLOCK_LINEAR_UNSWIZZLE_2D_COMP)), block_linear_unswizzle_3d_program(MakeProgram(BLOCK_LINEAR_UNSWIZZLE_3D_COMP)), pitch_unswizzle_program(MakeProgram(PITCH_UNSWIZZLE_COMP)), - copy_bc4_program(MakeProgram(OPENGL_COPY_BC4_COMP)) { + copy_bc4_program(MakeProgram(OPENGL_COPY_BC4_COMP)), + copy_bgr16_program(MakeProgram(OPENGL_COPY_BGR16_COMP)), + copy_bgra_program(MakeProgram(OPENGL_COPY_BGRA_COMP)) { const auto swizzle_table = Tegra::Texture::MakeSwizzleTable(); swizzle_table_buffer.Create(); glNamedBufferStorage(swizzle_table_buffer.handle, sizeof(swizzle_table), &swizzle_table, 0); @@ -93,7 +98,7 @@ void UtilShaders::BlockLinearUpload2D(Image& image, const ImageBufferMap& map, glUniform1ui(7, params.block_height_mask); glBindBufferRange(GL_SHADER_STORAGE_BUFFER, BINDING_INPUT_BUFFER, map.buffer, input_offset, image.guest_size_bytes - swizzle.buffer_offset); - glBindImageTexture(BINDING_OUTPUT_IMAGE, image.Handle(), swizzle.level, GL_TRUE, 0, + glBindImageTexture(BINDING_OUTPUT_IMAGE, image.StorageHandle(), swizzle.level, GL_TRUE, 0, GL_WRITE_ONLY, store_format); glDispatchCompute(num_dispatches_x, num_dispatches_y, image.info.resources.layers); } @@ -134,7 +139,7 @@ void UtilShaders::BlockLinearUpload3D(Image& image, const ImageBufferMap& map, glUniform1ui(9, params.block_depth_mask); glBindBufferRange(GL_SHADER_STORAGE_BUFFER, BINDING_INPUT_BUFFER, map.buffer, input_offset, image.guest_size_bytes - swizzle.buffer_offset); - glBindImageTexture(BINDING_OUTPUT_IMAGE, image.Handle(), swizzle.level, GL_TRUE, 0, + glBindImageTexture(BINDING_OUTPUT_IMAGE, image.StorageHandle(), swizzle.level, GL_TRUE, 0, GL_WRITE_ONLY, store_format); glDispatchCompute(num_dispatches_x, num_dispatches_y, num_dispatches_z); } @@ -164,7 +169,8 @@ void UtilShaders::PitchUpload(Image& image, const ImageBufferMap& map, glUniform2i(LOC_DESTINATION, 0, 0); glUniform1ui(LOC_BYTES_PER_BLOCK, bytes_per_block); glUniform1ui(LOC_PITCH, pitch); - glBindImageTexture(BINDING_OUTPUT_IMAGE, image.Handle(), 0, GL_FALSE, 0, GL_WRITE_ONLY, format); + glBindImageTexture(BINDING_OUTPUT_IMAGE, image.StorageHandle(), 0, GL_FALSE, 0, GL_WRITE_ONLY, + format); for (const SwizzleParameters& swizzle : swizzles) { const Extent3D num_tiles = swizzle.num_tiles; const size_t input_offset = swizzle.buffer_offset + map.offset; @@ -195,15 +201,41 @@ void UtilShaders::CopyBC4(Image& dst_image, Image& src_image, std::span copies) { + static constexpr GLuint BINDING_INPUT_IMAGE = 0; + static constexpr GLuint BINDING_OUTPUT_IMAGE = 1; + + GLenum format{}; + const u32 bytes_per_block = BytesPerBlock(dst_image.info.format); + if (bytes_per_block == 2) { + // BGR565 Copy + program_manager.BindHostCompute(copy_bgr16_program.handle); + format = GL_R16UI; + } else if (bytes_per_block == 4) { + // BGRA8 Copy + program_manager.BindHostCompute(copy_bgra_program.handle); + format = GL_RGBA8; + } + for (const ImageCopy& copy : copies) { + glBindImageTexture(BINDING_INPUT_IMAGE, src_image.StorageHandle(), + copy.src_subresource.base_level, GL_FALSE, 0, GL_READ_ONLY, format); + glBindImageTexture(BINDING_OUTPUT_IMAGE, dst_image.StorageHandle(), + copy.dst_subresource.base_level, GL_FALSE, 0, GL_WRITE_ONLY, format); + glDispatchCompute(copy.extent.width, copy.extent.height, copy.extent.depth); + } + program_manager.RestoreGuestCompute(); +} + GLenum StoreFormat(u32 bytes_per_block) { switch (bytes_per_block) { case 1: diff --git a/src/video_core/renderer_opengl/util_shaders.h b/src/video_core/renderer_opengl/util_shaders.h index 7b1d16b09..3a17424c9 100755 --- a/src/video_core/renderer_opengl/util_shaders.h +++ b/src/video_core/renderer_opengl/util_shaders.h @@ -36,6 +36,9 @@ public: void CopyBC4(Image& dst_image, Image& src_image, std::span copies); + void CopyBGR(Image& dst_image, Image& src_image, + std::span copies); + private: ProgramManager& program_manager; @@ -45,6 +48,8 @@ private: OGLProgram block_linear_unswizzle_3d_program; OGLProgram pitch_unswizzle_program; OGLProgram copy_bc4_program; + OGLProgram copy_bgr16_program; + OGLProgram copy_bgra_program; }; GLenum StoreFormat(u32 bytes_per_block); diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp index 294a09bc4..bd45d366e 100755 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp @@ -3161,7 +3161,11 @@ ShaderEntries GenerateShaderEntries(const VideoCommon::Shader::ShaderIR& ir) { entries.const_buffers.emplace_back(cbuf.second, cbuf.first); } for (const auto& [base, usage] : ir.GetGlobalMemory()) { - entries.global_buffers.emplace_back(base.cbuf_index, base.cbuf_offset, usage.is_written); + entries.global_buffers.emplace_back(GlobalBufferEntry{ + .cbuf_index = base.cbuf_index, + .cbuf_offset = base.cbuf_offset, + .is_written = usage.is_written, + }); } for (const auto& sampler : ir.GetSamplers()) { if (sampler.is_buffer) { diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index f9bc73f84..34d396434 100755 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -46,6 +46,7 @@ constexpr std::array REQUIRED_EXTENSIONS{ VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME, VK_EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME, VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME, + VK_EXT_ROBUSTNESS_2_EXTENSION_NAME, VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME, #ifdef _WIN32 VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME, @@ -379,20 +380,6 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR LOG_INFO(Render_Vulkan, "Device doesn't support extended dynamic state"); } - VkPhysicalDeviceRobustness2FeaturesEXT robustness2; - if (ext_robustness2) { - robustness2 = { - .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT, - .pNext = nullptr, - .robustBufferAccess2 = true, - .robustImageAccess2 = true, - .nullDescriptor = true, - }; - SetNext(next, robustness2); - } else { - LOG_INFO(Render_Vulkan, "Device doesn't support robustness2"); - } - if (!ext_depth_range_unrestricted) { LOG_INFO(Render_Vulkan, "Device doesn't support depth range unrestricted"); } @@ -579,7 +566,16 @@ void Device::CheckSuitability(bool requires_swapchain) const { throw vk::Exception(VK_ERROR_FEATURE_NOT_PRESENT); } } - const VkPhysicalDeviceFeatures features{physical.GetFeatures()}; + VkPhysicalDeviceRobustness2FeaturesEXT robustness2{}; + robustness2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT; + + VkPhysicalDeviceFeatures2 features2{}; + features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; + features2.pNext = &robustness2; + + physical.GetFeatures2KHR(features2); + + const VkPhysicalDeviceFeatures& features{features2.features}; const std::array feature_report{ std::make_pair(features.robustBufferAccess, "robustBufferAccess"), std::make_pair(features.vertexPipelineStoresAndAtomics, "vertexPipelineStoresAndAtomics"), @@ -598,6 +594,9 @@ void Device::CheckSuitability(bool requires_swapchain) const { std::make_pair(features.shaderImageGatherExtended, "shaderImageGatherExtended"), std::make_pair(features.shaderStorageImageWriteWithoutFormat, "shaderStorageImageWriteWithoutFormat"), + std::make_pair(robustness2.robustBufferAccess2, "robustBufferAccess2"), + std::make_pair(robustness2.robustImageAccess2, "robustImageAccess2"), + std::make_pair(robustness2.nullDescriptor, "nullDescriptor"), }; for (const auto& [is_supported, name] : feature_report) { if (is_supported) { @@ -621,7 +620,6 @@ std::vector Device::LoadExtensions(bool requires_surface) { bool has_ext_transform_feedback{}; bool has_ext_custom_border_color{}; bool has_ext_extended_dynamic_state{}; - bool has_ext_robustness2{}; for (const VkExtensionProperties& extension : physical.EnumerateDeviceExtensionProperties()) { const auto test = [&](std::optional> status, const char* name, bool push) { @@ -649,14 +647,12 @@ std::vector Device::LoadExtensions(bool requires_surface) { test(has_ext_transform_feedback, VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME, false); test(has_ext_custom_border_color, VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME, false); test(has_ext_extended_dynamic_state, VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME, false); - test(has_ext_robustness2, VK_EXT_ROBUSTNESS_2_EXTENSION_NAME, false); test(has_ext_subgroup_size_control, VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME, false); if (Settings::values.renderer_debug) { test(nv_device_diagnostics_config, VK_NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME, true); } } - VkPhysicalDeviceFeatures2KHR features; features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR; @@ -673,7 +669,6 @@ std::vector Device::LoadExtensions(bool requires_surface) { is_float16_supported = float16_int8_features.shaderFloat16; extensions.push_back(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME); } - if (has_ext_subgroup_size_control) { VkPhysicalDeviceSubgroupSizeControlFeaturesEXT subgroup_features; subgroup_features.sType = @@ -700,7 +695,6 @@ std::vector Device::LoadExtensions(bool requires_surface) { } else { is_warp_potentially_bigger = true; } - if (has_ext_transform_feedback) { VkPhysicalDeviceTransformFeedbackFeaturesEXT tfb_features; tfb_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT; @@ -722,7 +716,6 @@ std::vector Device::LoadExtensions(bool requires_surface) { ext_transform_feedback = true; } } - if (has_ext_custom_border_color) { VkPhysicalDeviceCustomBorderColorFeaturesEXT border_features; border_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT; @@ -735,7 +728,6 @@ std::vector Device::LoadExtensions(bool requires_surface) { ext_custom_border_color = true; } } - if (has_ext_extended_dynamic_state) { VkPhysicalDeviceExtendedDynamicStateFeaturesEXT dynamic_state; dynamic_state.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT; @@ -748,20 +740,6 @@ std::vector Device::LoadExtensions(bool requires_surface) { ext_extended_dynamic_state = true; } } - - if (has_ext_robustness2) { - VkPhysicalDeviceRobustness2FeaturesEXT robustness2; - robustness2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT; - robustness2.pNext = nullptr; - features.pNext = &robustness2; - physical.GetFeatures2KHR(features); - if (robustness2.nullDescriptor && robustness2.robustBufferAccess2 && - robustness2.robustImageAccess2) { - extensions.push_back(VK_EXT_ROBUSTNESS_2_EXTENSION_NAME); - ext_robustness2 = true; - } - } - return extensions; } diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index e0711f733..67d70cd22 100755 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -285,7 +285,6 @@ private: bool ext_transform_feedback{}; ///< Support for VK_EXT_transform_feedback. bool ext_custom_border_color{}; ///< Support for VK_EXT_custom_border_color. bool ext_extended_dynamic_state{}; ///< Support for VK_EXT_extended_dynamic_state. - bool ext_robustness2{}; ///< Support for VK_EXT_robustness2. bool ext_shader_stencil_export{}; ///< Support for VK_EXT_shader_stencil_export. bool nv_device_diagnostics_config{}; ///< Support for VK_NV_device_diagnostics_config. bool has_renderdoc{}; ///< Has RenderDoc attached diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index d592c82c0..0635d13d0 100755 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -782,7 +782,7 @@ void Config::ReadRendererValues() { ReadSettingGlobal(Settings::values.frame_limit, QStringLiteral("frame_limit"), 100); ReadSettingGlobal(Settings::values.use_disk_shader_cache, QStringLiteral("use_disk_shader_cache"), true); - ReadSettingGlobal(Settings::values.gpu_accuracy, QStringLiteral("gpu_accuracy"), 0); + ReadSettingGlobal(Settings::values.gpu_accuracy, QStringLiteral("gpu_accuracy"), 1); ReadSettingGlobal(Settings::values.use_asynchronous_gpu_emulation, QStringLiteral("use_asynchronous_gpu_emulation"), true); ReadSettingGlobal(Settings::values.use_nvdec_emulation, QStringLiteral("use_nvdec_emulation"), @@ -1351,7 +1351,7 @@ void Config::SaveRendererValues() { Settings::values.use_disk_shader_cache, true); WriteSettingGlobal(QStringLiteral("gpu_accuracy"), static_cast(Settings::values.gpu_accuracy.GetValue(global)), - Settings::values.gpu_accuracy.UsingGlobal(), 0); + Settings::values.gpu_accuracy.UsingGlobal(), 1); WriteSettingGlobal(QStringLiteral("use_asynchronous_gpu_emulation"), Settings::values.use_asynchronous_gpu_emulation, true); WriteSettingGlobal(QStringLiteral("use_nvdec_emulation"), Settings::values.use_nvdec_emulation, diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 52218eb70..28a52a56c 100755 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -2490,6 +2490,11 @@ void GMainWindow::OnCaptureScreenshot() { .arg(title_id, 16, 16, QLatin1Char{'0'}) .arg(date); + if (!Common::FS::CreateDir(screenshot_path.toStdString())) { + OnStartGame(); + return; + } + #ifdef _WIN32 if (UISettings::values.enable_screenshot_save_as) { filename = QFileDialog::getSaveFileName(this, tr("Capture Screenshot"), filename, diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index f76102459..aa0a9f288 100755 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp @@ -388,7 +388,7 @@ void Config::ReadValues() { static_cast(sdl2_config->GetInteger("Renderer", "frame_limit", 100))); Settings::values.use_disk_shader_cache.SetValue( sdl2_config->GetBoolean("Renderer", "use_disk_shader_cache", false)); - const int gpu_accuracy_level = sdl2_config->GetInteger("Renderer", "gpu_accuracy", 0); + const int gpu_accuracy_level = sdl2_config->GetInteger("Renderer", "gpu_accuracy", 1); Settings::values.gpu_accuracy.SetValue(static_cast(gpu_accuracy_level)); Settings::values.use_asynchronous_gpu_emulation.SetValue( sdl2_config->GetBoolean("Renderer", "use_asynchronous_gpu_emulation", true));