Compare commits
22 Commits
__refs_pul
...
__refs_pul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b5bcd8c71b | ||
|
|
090bc588e5 | ||
|
|
8f3e2a1b48 | ||
|
|
d482ec32a4 | ||
|
|
11f6bb1532 | ||
|
|
ba05301e1b | ||
|
|
5a657488e1 | ||
|
|
c9678bda24 | ||
|
|
83afc12475 | ||
|
|
d746cfc018 | ||
|
|
89221ca7d5 | ||
|
|
165ebbb63c | ||
|
|
898c5d35a5 | ||
|
|
a4d0663158 | ||
|
|
e531d1fae9 | ||
|
|
41183b622f | ||
|
|
1773a1039f | ||
|
|
17207939e5 | ||
|
|
57aaf00a0c | ||
|
|
5e746da981 | ||
|
|
505923f0f3 | ||
|
|
57a4388e2d |
@@ -241,7 +241,7 @@ endif()
|
||||
|
||||
if (ENABLE_WEB_SERVICE)
|
||||
find_package(cpp-jwt 1.4 CONFIG)
|
||||
find_package(httplib 0.11 MODULE)
|
||||
find_package(httplib 0.12 MODULE)
|
||||
endif()
|
||||
|
||||
if (YUZU_TESTS)
|
||||
|
||||
2
externals/cpp-httplib
vendored
2
externals/cpp-httplib
vendored
Submodule externals/cpp-httplib updated: 305a7abcb9...6d963fbe8d
@@ -23,6 +23,7 @@ public:
|
||||
buffer{Common::make_unique_for_overwrite<T[]>(initial_capacity)} {}
|
||||
|
||||
~ScratchBuffer() = default;
|
||||
ScratchBuffer(ScratchBuffer&&) = default;
|
||||
|
||||
/// This will only grow the buffer's capacity if size is greater than the current capacity.
|
||||
/// The previously held data will remain intact.
|
||||
|
||||
@@ -59,6 +59,7 @@ void LogSettings() {
|
||||
values.use_asynchronous_gpu_emulation.GetValue());
|
||||
log_setting("Renderer_NvdecEmulation", values.nvdec_emulation.GetValue());
|
||||
log_setting("Renderer_AccelerateASTC", values.accelerate_astc.GetValue());
|
||||
log_setting("Renderer_AsyncASTC", values.async_astc.GetValue());
|
||||
log_setting("Renderer_UseVsync", values.use_vsync.GetValue());
|
||||
log_setting("Renderer_ShaderBackend", values.shader_backend.GetValue());
|
||||
log_setting("Renderer_UseAsynchronousShaders", values.use_asynchronous_shaders.GetValue());
|
||||
@@ -212,6 +213,7 @@ void RestoreGlobalState(bool is_powered_on) {
|
||||
values.use_asynchronous_gpu_emulation.SetGlobal(true);
|
||||
values.nvdec_emulation.SetGlobal(true);
|
||||
values.accelerate_astc.SetGlobal(true);
|
||||
values.async_astc.SetGlobal(true);
|
||||
values.use_vsync.SetGlobal(true);
|
||||
values.shader_backend.SetGlobal(true);
|
||||
values.use_asynchronous_shaders.SetGlobal(true);
|
||||
|
||||
@@ -453,6 +453,7 @@ struct Values {
|
||||
SwitchableSetting<bool> use_asynchronous_gpu_emulation{true, "use_asynchronous_gpu_emulation"};
|
||||
SwitchableSetting<NvdecEmulation> nvdec_emulation{NvdecEmulation::GPU, "nvdec_emulation"};
|
||||
SwitchableSetting<bool> accelerate_astc{true, "accelerate_astc"};
|
||||
SwitchableSetting<bool> async_astc{false, "async_astc"};
|
||||
SwitchableSetting<bool> use_vsync{true, "use_vsync"};
|
||||
SwitchableSetting<ShaderBackend, true> shader_backend{ShaderBackend::GLSL, ShaderBackend::GLSL,
|
||||
ShaderBackend::SPIRV, "shader_backend"};
|
||||
|
||||
@@ -225,6 +225,8 @@ add_library(core STATIC
|
||||
hle/kernel/k_memory_manager.h
|
||||
hle/kernel/k_memory_region.h
|
||||
hle/kernel/k_memory_region_type.h
|
||||
hle/kernel/k_object_name.cpp
|
||||
hle/kernel/k_object_name.h
|
||||
hle/kernel/k_page_bitmap.h
|
||||
hle/kernel/k_page_buffer.cpp
|
||||
hle/kernel/k_page_buffer.h
|
||||
|
||||
@@ -23,7 +23,8 @@ void EmulatedConsole::SetTouchParams() {
|
||||
|
||||
// We can't use mouse as touch if native mouse is enabled
|
||||
if (!Settings::values.mouse_enabled) {
|
||||
touch_params[index++] = Common::ParamPackage{"engine:mouse,axis_x:10,axis_y:11,button:0"};
|
||||
touch_params[index++] =
|
||||
Common::ParamPackage{"engine:mouse,axis_x:0,axis_y:1,button:0,port:2"};
|
||||
}
|
||||
|
||||
touch_params[index++] =
|
||||
|
||||
@@ -34,9 +34,12 @@ void EmulatedDevices::ReloadInput() {
|
||||
// First two axis are reserved for mouse position
|
||||
key_index = 2;
|
||||
for (auto& mouse_device : mouse_analog_devices) {
|
||||
// Mouse axis are only mapped on port 1, pad 0
|
||||
Common::ParamPackage mouse_params;
|
||||
mouse_params.Set("engine", "mouse");
|
||||
mouse_params.Set("axis", static_cast<int>(key_index));
|
||||
mouse_params.Set("port", 1);
|
||||
mouse_params.Set("pad", 0);
|
||||
mouse_device = Common::Input::CreateInputDevice(mouse_params);
|
||||
key_index++;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "core/hle/kernel/k_event_info.h"
|
||||
#include "core/hle/kernel/k_memory_layout.h"
|
||||
#include "core/hle/kernel/k_memory_manager.h"
|
||||
#include "core/hle/kernel/k_object_name.h"
|
||||
#include "core/hle/kernel/k_page_buffer.h"
|
||||
#include "core/hle/kernel/k_port.h"
|
||||
#include "core/hle/kernel/k_process.h"
|
||||
@@ -49,6 +50,7 @@ namespace Kernel::Init {
|
||||
HANDLER(KThreadLocalPage, \
|
||||
(SLAB_COUNT(KProcess) + (SLAB_COUNT(KProcess) + SLAB_COUNT(KThread)) / 8), \
|
||||
##__VA_ARGS__) \
|
||||
HANDLER(KObjectName, (SLAB_COUNT(KObjectName)), ##__VA_ARGS__) \
|
||||
HANDLER(KResourceLimit, (SLAB_COUNT(KResourceLimit)), ##__VA_ARGS__) \
|
||||
HANDLER(KEventInfo, (SLAB_COUNT(KThread) + SLAB_COUNT(KDebug)), ##__VA_ARGS__) \
|
||||
HANDLER(KDebug, (SLAB_COUNT(KDebug)), ##__VA_ARGS__) \
|
||||
|
||||
102
src/core/hle/kernel/k_object_name.cpp
Normal file
102
src/core/hle/kernel/k_object_name.cpp
Normal file
@@ -0,0 +1,102 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/hle/kernel/k_object_name.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
KObjectNameGlobalData::KObjectNameGlobalData(KernelCore& kernel) : m_object_list_lock{kernel} {}
|
||||
KObjectNameGlobalData::~KObjectNameGlobalData() = default;
|
||||
|
||||
void KObjectName::Initialize(KAutoObject* obj, const char* name) {
|
||||
// Set member variables.
|
||||
m_object = obj;
|
||||
std::strncpy(m_name.data(), name, sizeof(m_name) - 1);
|
||||
m_name[sizeof(m_name) - 1] = '\x00';
|
||||
|
||||
// Open a reference to the object we hold.
|
||||
m_object->Open();
|
||||
}
|
||||
|
||||
bool KObjectName::MatchesName(const char* name) const {
|
||||
return std::strncmp(m_name.data(), name, sizeof(m_name)) == 0;
|
||||
}
|
||||
|
||||
Result KObjectName::NewFromName(KernelCore& kernel, KAutoObject* obj, const char* name) {
|
||||
// Create a new object name.
|
||||
KObjectName* new_name = KObjectName::Allocate(kernel);
|
||||
R_UNLESS(new_name != nullptr, ResultOutOfResource);
|
||||
|
||||
// Initialize the new name.
|
||||
new_name->Initialize(obj, name);
|
||||
|
||||
// Check if there's an existing name.
|
||||
{
|
||||
// Get the global data.
|
||||
KObjectNameGlobalData& gd{kernel.ObjectNameGlobalData()};
|
||||
|
||||
// Ensure we have exclusive access to the global list.
|
||||
KScopedLightLock lk{gd.GetObjectListLock()};
|
||||
|
||||
// If the object doesn't exist, put it into the list.
|
||||
KScopedAutoObject existing_object = FindImpl(kernel, name);
|
||||
if (existing_object.IsNull()) {
|
||||
gd.GetObjectList().push_back(*new_name);
|
||||
R_SUCCEED();
|
||||
}
|
||||
}
|
||||
|
||||
// The object already exists, which is an error condition. Perform cleanup.
|
||||
obj->Close();
|
||||
KObjectName::Free(kernel, new_name);
|
||||
R_THROW(ResultInvalidState);
|
||||
}
|
||||
|
||||
Result KObjectName::Delete(KernelCore& kernel, KAutoObject* obj, const char* compare_name) {
|
||||
// Get the global data.
|
||||
KObjectNameGlobalData& gd{kernel.ObjectNameGlobalData()};
|
||||
|
||||
// Ensure we have exclusive access to the global list.
|
||||
KScopedLightLock lk{gd.GetObjectListLock()};
|
||||
|
||||
// Find a matching entry in the list, and delete it.
|
||||
for (auto& name : gd.GetObjectList()) {
|
||||
if (name.MatchesName(compare_name) && obj == name.GetObject()) {
|
||||
// We found a match, clean up its resources.
|
||||
obj->Close();
|
||||
gd.GetObjectList().erase(gd.GetObjectList().iterator_to(name));
|
||||
KObjectName::Free(kernel, std::addressof(name));
|
||||
R_SUCCEED();
|
||||
}
|
||||
}
|
||||
|
||||
// We didn't find the object in the list.
|
||||
R_THROW(ResultNotFound);
|
||||
}
|
||||
|
||||
KScopedAutoObject<KAutoObject> KObjectName::Find(KernelCore& kernel, const char* name) {
|
||||
// Get the global data.
|
||||
KObjectNameGlobalData& gd{kernel.ObjectNameGlobalData()};
|
||||
|
||||
// Ensure we have exclusive access to the global list.
|
||||
KScopedLightLock lk{gd.GetObjectListLock()};
|
||||
|
||||
return FindImpl(kernel, name);
|
||||
}
|
||||
|
||||
KScopedAutoObject<KAutoObject> KObjectName::FindImpl(KernelCore& kernel, const char* compare_name) {
|
||||
// Get the global data.
|
||||
KObjectNameGlobalData& gd{kernel.ObjectNameGlobalData()};
|
||||
|
||||
// Try to find a matching object in the global list.
|
||||
for (const auto& name : gd.GetObjectList()) {
|
||||
if (name.MatchesName(compare_name)) {
|
||||
return name.GetObject();
|
||||
}
|
||||
}
|
||||
|
||||
// There's no matching entry in the list.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace Kernel
|
||||
86
src/core/hle/kernel/k_object_name.h
Normal file
86
src/core/hle/kernel/k_object_name.h
Normal file
@@ -0,0 +1,86 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <boost/intrusive/list.hpp>
|
||||
|
||||
#include "core/hle/kernel/k_light_lock.h"
|
||||
#include "core/hle/kernel/slab_helpers.h"
|
||||
#include "core/hle/kernel/svc_results.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class KObjectNameGlobalData;
|
||||
|
||||
class KObjectName : public KSlabAllocated<KObjectName>, public boost::intrusive::list_base_hook<> {
|
||||
public:
|
||||
explicit KObjectName(KernelCore&) {}
|
||||
virtual ~KObjectName() = default;
|
||||
|
||||
static constexpr size_t NameLengthMax = 12;
|
||||
using List = boost::intrusive::list<KObjectName>;
|
||||
|
||||
static Result NewFromName(KernelCore& kernel, KAutoObject* obj, const char* name);
|
||||
static Result Delete(KernelCore& kernel, KAutoObject* obj, const char* name);
|
||||
|
||||
static KScopedAutoObject<KAutoObject> Find(KernelCore& kernel, const char* name);
|
||||
|
||||
template <typename Derived>
|
||||
static Result Delete(KernelCore& kernel, const char* name) {
|
||||
// Find the object.
|
||||
KScopedAutoObject obj = Find(kernel, name);
|
||||
R_UNLESS(obj.IsNotNull(), ResultNotFound);
|
||||
|
||||
// Cast the object to the desired type.
|
||||
Derived* derived = obj->DynamicCast<Derived*>();
|
||||
R_UNLESS(derived != nullptr, ResultNotFound);
|
||||
|
||||
// Check that the object is closed.
|
||||
R_UNLESS(derived->IsServerClosed(), ResultInvalidState);
|
||||
|
||||
return Delete(kernel, obj.GetPointerUnsafe(), name);
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
requires(std::derived_from<Derived, KAutoObject>)
|
||||
static KScopedAutoObject<Derived> Find(KernelCore& kernel, const char* name) {
|
||||
return Find(kernel, name);
|
||||
}
|
||||
|
||||
private:
|
||||
static KScopedAutoObject<KAutoObject> FindImpl(KernelCore& kernel, const char* name);
|
||||
|
||||
void Initialize(KAutoObject* obj, const char* name);
|
||||
|
||||
bool MatchesName(const char* name) const;
|
||||
KAutoObject* GetObject() const {
|
||||
return m_object;
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<char, NameLengthMax> m_name{};
|
||||
KAutoObject* m_object{};
|
||||
};
|
||||
|
||||
class KObjectNameGlobalData {
|
||||
public:
|
||||
explicit KObjectNameGlobalData(KernelCore& kernel);
|
||||
~KObjectNameGlobalData();
|
||||
|
||||
KLightLock& GetObjectListLock() {
|
||||
return m_object_list_lock;
|
||||
}
|
||||
|
||||
KObjectName::List& GetObjectList() {
|
||||
return m_object_list;
|
||||
}
|
||||
|
||||
private:
|
||||
KLightLock m_object_list_lock;
|
||||
KObjectName::List m_object_list;
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "core/hle/kernel/k_hardware_timer.h"
|
||||
#include "core/hle/kernel/k_memory_layout.h"
|
||||
#include "core/hle/kernel/k_memory_manager.h"
|
||||
#include "core/hle/kernel/k_object_name.h"
|
||||
#include "core/hle/kernel/k_page_buffer.h"
|
||||
#include "core/hle/kernel/k_process.h"
|
||||
#include "core/hle/kernel/k_resource_limit.h"
|
||||
@@ -84,6 +85,7 @@ struct KernelCore::Impl {
|
||||
InitializeShutdownThreads();
|
||||
InitializePhysicalCores();
|
||||
InitializePreemption(kernel);
|
||||
InitializeGlobalData(kernel);
|
||||
|
||||
// Initialize the Dynamic Slab Heaps.
|
||||
{
|
||||
@@ -194,6 +196,8 @@ struct KernelCore::Impl {
|
||||
}
|
||||
}
|
||||
|
||||
object_name_global_data.reset();
|
||||
|
||||
// Ensure that the object list container is finalized and properly shutdown.
|
||||
global_object_list_container->Finalize();
|
||||
global_object_list_container.reset();
|
||||
@@ -363,27 +367,29 @@ struct KernelCore::Impl {
|
||||
}
|
||||
}
|
||||
|
||||
void InitializeGlobalData(KernelCore& kernel) {
|
||||
object_name_global_data = std::make_unique<KObjectNameGlobalData>(kernel);
|
||||
}
|
||||
|
||||
void MakeApplicationProcess(KProcess* process) {
|
||||
application_process = process;
|
||||
}
|
||||
|
||||
static inline thread_local u32 host_thread_id = UINT32_MAX;
|
||||
static inline thread_local u8 host_thread_id = UINT8_MAX;
|
||||
|
||||
/// Gets the host thread ID for the caller, allocating a new one if this is the first time
|
||||
u32 GetHostThreadId(std::size_t core_id) {
|
||||
if (host_thread_id == UINT32_MAX) {
|
||||
// The first four slots are reserved for CPU core threads
|
||||
ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
|
||||
host_thread_id = static_cast<u32>(core_id);
|
||||
}
|
||||
/// Sets the host thread ID for the caller.
|
||||
u32 SetHostThreadId(std::size_t core_id) {
|
||||
// This should only be called during core init.
|
||||
ASSERT(host_thread_id == UINT8_MAX);
|
||||
|
||||
// The first four slots are reserved for CPU core threads
|
||||
ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
|
||||
host_thread_id = static_cast<u8>(core_id);
|
||||
return host_thread_id;
|
||||
}
|
||||
|
||||
/// Gets the host thread ID for the caller, allocating a new one if this is the first time
|
||||
u32 GetHostThreadId() {
|
||||
if (host_thread_id == UINT32_MAX) {
|
||||
host_thread_id = next_host_thread_id++;
|
||||
}
|
||||
/// Gets the host thread ID for the caller
|
||||
u32 GetHostThreadId() const {
|
||||
return host_thread_id;
|
||||
}
|
||||
|
||||
@@ -391,23 +397,19 @@ struct KernelCore::Impl {
|
||||
KThread* GetHostDummyThread(KThread* existing_thread) {
|
||||
auto initialize = [this](KThread* thread) {
|
||||
ASSERT(KThread::InitializeDummyThread(thread, nullptr).IsSuccess());
|
||||
thread->SetName(fmt::format("DummyThread:{}", GetHostThreadId()));
|
||||
thread->SetName(fmt::format("DummyThread:{}", next_host_thread_id++));
|
||||
return thread;
|
||||
};
|
||||
|
||||
thread_local KThread raw_thread{system.Kernel()};
|
||||
thread_local KThread* thread = nullptr;
|
||||
if (thread == nullptr) {
|
||||
thread = (existing_thread == nullptr) ? initialize(&raw_thread) : existing_thread;
|
||||
}
|
||||
|
||||
thread_local KThread* thread = existing_thread ? existing_thread : initialize(&raw_thread);
|
||||
return thread;
|
||||
}
|
||||
|
||||
/// Registers a CPU core thread by allocating a host thread ID for it
|
||||
void RegisterCoreThread(std::size_t core_id) {
|
||||
ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
|
||||
const auto this_id = GetHostThreadId(core_id);
|
||||
const auto this_id = SetHostThreadId(core_id);
|
||||
if (!is_multicore) {
|
||||
single_core_thread_id = this_id;
|
||||
}
|
||||
@@ -415,7 +417,6 @@ struct KernelCore::Impl {
|
||||
|
||||
/// Registers a new host thread by allocating a host thread ID for it
|
||||
void RegisterHostThread(KThread* existing_thread) {
|
||||
[[maybe_unused]] const auto this_id = GetHostThreadId();
|
||||
[[maybe_unused]] const auto dummy_thread = GetHostDummyThread(existing_thread);
|
||||
}
|
||||
|
||||
@@ -445,11 +446,9 @@ struct KernelCore::Impl {
|
||||
static inline thread_local KThread* current_thread{nullptr};
|
||||
|
||||
KThread* GetCurrentEmuThread() {
|
||||
const auto thread_id = GetCurrentHostThreadID();
|
||||
if (thread_id >= Core::Hardware::NUM_CPU_CORES) {
|
||||
return GetHostDummyThread(nullptr);
|
||||
if (!current_thread) {
|
||||
current_thread = GetHostDummyThread(nullptr);
|
||||
}
|
||||
|
||||
return current_thread;
|
||||
}
|
||||
|
||||
@@ -838,6 +837,8 @@ struct KernelCore::Impl {
|
||||
|
||||
std::unique_ptr<KAutoObjectWithListContainer> global_object_list_container;
|
||||
|
||||
std::unique_ptr<KObjectNameGlobalData> object_name_global_data;
|
||||
|
||||
/// Map of named ports managed by the kernel, which can be retrieved using
|
||||
/// the ConnectToPort SVC.
|
||||
std::unordered_map<std::string, ServiceInterfaceFactory> service_interface_factory;
|
||||
@@ -1002,7 +1003,7 @@ const Kernel::PhysicalCore& KernelCore::CurrentPhysicalCore() const {
|
||||
}
|
||||
|
||||
Kernel::KScheduler* KernelCore::CurrentScheduler() {
|
||||
u32 core_id = impl->GetCurrentHostThreadID();
|
||||
const u32 core_id = impl->GetCurrentHostThreadID();
|
||||
if (core_id >= Core::Hardware::NUM_CPU_CORES) {
|
||||
// This is expected when called from not a guest thread
|
||||
return {};
|
||||
@@ -1138,6 +1139,10 @@ void KernelCore::SetCurrentEmuThread(KThread* thread) {
|
||||
impl->SetCurrentEmuThread(thread);
|
||||
}
|
||||
|
||||
KObjectNameGlobalData& KernelCore::ObjectNameGlobalData() {
|
||||
return *impl->object_name_global_data;
|
||||
}
|
||||
|
||||
KMemoryManager& KernelCore::MemoryManager() {
|
||||
return *impl->memory_manager;
|
||||
}
|
||||
|
||||
@@ -44,6 +44,8 @@ class KHardwareTimer;
|
||||
class KLinkedListNode;
|
||||
class KMemoryLayout;
|
||||
class KMemoryManager;
|
||||
class KObjectName;
|
||||
class KObjectNameGlobalData;
|
||||
class KPageBuffer;
|
||||
class KPageBufferSlabHeap;
|
||||
class KPort;
|
||||
@@ -240,6 +242,9 @@ public:
|
||||
/// Register the current thread as a non CPU core thread.
|
||||
void RegisterHostThread(KThread* existing_thread = nullptr);
|
||||
|
||||
/// Gets global data for KObjectName.
|
||||
KObjectNameGlobalData& ObjectNameGlobalData();
|
||||
|
||||
/// Gets the virtual memory manager for the kernel.
|
||||
KMemoryManager& MemoryManager();
|
||||
|
||||
@@ -372,6 +377,8 @@ public:
|
||||
return slab_heap_container->page_buffer;
|
||||
} else if constexpr (std::is_same_v<T, KThreadLocalPage>) {
|
||||
return slab_heap_container->thread_local_page;
|
||||
} else if constexpr (std::is_same_v<T, KObjectName>) {
|
||||
return slab_heap_container->object_name;
|
||||
} else if constexpr (std::is_same_v<T, KSessionRequest>) {
|
||||
return slab_heap_container->session_request;
|
||||
} else if constexpr (std::is_same_v<T, KSecureSystemResource>) {
|
||||
@@ -443,6 +450,7 @@ private:
|
||||
KSlabHeap<KDeviceAddressSpace> device_address_space;
|
||||
KSlabHeap<KPageBuffer> page_buffer;
|
||||
KSlabHeap<KThreadLocalPage> thread_local_page;
|
||||
KSlabHeap<KObjectName> object_name;
|
||||
KSlabHeap<KSessionRequest> session_request;
|
||||
KSlabHeap<KSecureSystemResource> secure_system_resource;
|
||||
KSlabHeap<KEventInfo> event_info;
|
||||
|
||||
@@ -82,7 +82,7 @@ static_assert(sizeof(uint64_t) == 8);
|
||||
static void SvcWrap_SetHeapSize64From32(Core::System& system) {
|
||||
Result ret{};
|
||||
|
||||
uintptr_t out_address{};
|
||||
uint64_t out_address{};
|
||||
uint32_t size{};
|
||||
|
||||
size = Convert<uint32_t>(GetReg32(system, 1));
|
||||
@@ -729,7 +729,7 @@ static void SvcWrap_GetLastThreadInfo64From32(Core::System& system) {
|
||||
Result ret{};
|
||||
|
||||
ilp32::LastThreadContext out_context{};
|
||||
uintptr_t out_tls_address{};
|
||||
uint64_t out_tls_address{};
|
||||
uint32_t out_flags{};
|
||||
|
||||
ret = GetLastThreadInfo64From32(system, &out_context, &out_tls_address, &out_flags);
|
||||
@@ -1278,8 +1278,8 @@ static void SvcWrap_QueryPhysicalAddress64From32(Core::System& system) {
|
||||
static void SvcWrap_QueryIoMapping64From32(Core::System& system) {
|
||||
Result ret{};
|
||||
|
||||
uintptr_t out_address{};
|
||||
uintptr_t out_size{};
|
||||
uint64_t out_address{};
|
||||
uint64_t out_size{};
|
||||
uint64_t physical_address{};
|
||||
uint32_t size{};
|
||||
|
||||
@@ -2088,7 +2088,7 @@ static void SvcWrap_UnmapInsecureMemory64From32(Core::System& system) {
|
||||
static void SvcWrap_SetHeapSize64(Core::System& system) {
|
||||
Result ret{};
|
||||
|
||||
uintptr_t out_address{};
|
||||
uint64_t out_address{};
|
||||
uint64_t size{};
|
||||
|
||||
size = Convert<uint64_t>(GetReg64(system, 1));
|
||||
@@ -2705,7 +2705,7 @@ static void SvcWrap_GetLastThreadInfo64(Core::System& system) {
|
||||
Result ret{};
|
||||
|
||||
lp64::LastThreadContext out_context{};
|
||||
uintptr_t out_tls_address{};
|
||||
uint64_t out_tls_address{};
|
||||
uint32_t out_flags{};
|
||||
|
||||
ret = GetLastThreadInfo64(system, &out_context, &out_tls_address, &out_flags);
|
||||
@@ -3217,8 +3217,8 @@ static void SvcWrap_QueryPhysicalAddress64(Core::System& system) {
|
||||
static void SvcWrap_QueryIoMapping64(Core::System& system) {
|
||||
Result ret{};
|
||||
|
||||
uintptr_t out_address{};
|
||||
uintptr_t out_size{};
|
||||
uint64_t out_address{};
|
||||
uint64_t out_size{};
|
||||
uint64_t physical_address{};
|
||||
uint64_t size{};
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ class System;
|
||||
namespace Kernel::Svc {
|
||||
|
||||
// clang-format off
|
||||
Result SetHeapSize(Core::System& system, uintptr_t* out_address, uint64_t size);
|
||||
Result SetHeapSize(Core::System& system, uint64_t* out_address, uint64_t size);
|
||||
Result SetMemoryPermission(Core::System& system, uint64_t address, uint64_t size, MemoryPermission perm);
|
||||
Result SetMemoryAttribute(Core::System& system, uint64_t address, uint64_t size, uint32_t mask, uint32_t attr);
|
||||
Result MapMemory(Core::System& system, uint64_t dst_address, uint64_t src_address, uint64_t size);
|
||||
@@ -61,7 +61,7 @@ Result FlushDataCache(Core::System& system, uint64_t address, uint64_t size);
|
||||
Result MapPhysicalMemory(Core::System& system, uint64_t address, uint64_t size);
|
||||
Result UnmapPhysicalMemory(Core::System& system, uint64_t address, uint64_t size);
|
||||
Result GetDebugFutureThreadInfo(Core::System& system, lp64::LastThreadContext* out_context, uint64_t* out_thread_id, Handle debug_handle, int64_t ns);
|
||||
Result GetLastThreadInfo(Core::System& system, lp64::LastThreadContext* out_context, uintptr_t* out_tls_address, uint32_t* out_flags);
|
||||
Result GetLastThreadInfo(Core::System& system, lp64::LastThreadContext* out_context, uint64_t* out_tls_address, uint32_t* out_flags);
|
||||
Result GetResourceLimitLimitValue(Core::System& system, int64_t* out_limit_value, Handle resource_limit_handle, LimitableResource which);
|
||||
Result GetResourceLimitCurrentValue(Core::System& system, int64_t* out_current_value, Handle resource_limit_handle, LimitableResource which);
|
||||
Result SetThreadActivity(Core::System& system, Handle thread_handle, ThreadActivity thread_activity);
|
||||
@@ -94,7 +94,7 @@ Result MapTransferMemory(Core::System& system, Handle trmem_handle, uint64_t add
|
||||
Result UnmapTransferMemory(Core::System& system, Handle trmem_handle, uint64_t address, uint64_t size);
|
||||
Result CreateInterruptEvent(Core::System& system, Handle* out_read_handle, int32_t interrupt_id, InterruptType interrupt_type);
|
||||
Result QueryPhysicalAddress(Core::System& system, lp64::PhysicalMemoryInfo* out_info, uint64_t address);
|
||||
Result QueryIoMapping(Core::System& system, uintptr_t* out_address, uintptr_t* out_size, uint64_t physical_address, uint64_t size);
|
||||
Result QueryIoMapping(Core::System& system, uint64_t* out_address, uint64_t* out_size, uint64_t physical_address, uint64_t size);
|
||||
Result CreateDeviceAddressSpace(Core::System& system, Handle* out_handle, uint64_t das_address, uint64_t das_size);
|
||||
Result AttachDeviceAddressSpace(Core::System& system, DeviceName device_name, Handle das_handle);
|
||||
Result DetachDeviceAddressSpace(Core::System& system, DeviceName device_name, Handle das_handle);
|
||||
@@ -137,7 +137,7 @@ Result SetResourceLimitLimitValue(Core::System& system, Handle resource_limit_ha
|
||||
Result MapInsecureMemory(Core::System& system, uint64_t address, uint64_t size);
|
||||
Result UnmapInsecureMemory(Core::System& system, uint64_t address, uint64_t size);
|
||||
|
||||
Result SetHeapSize64From32(Core::System& system, uintptr_t* out_address, uint32_t size);
|
||||
Result SetHeapSize64From32(Core::System& system, uint64_t* out_address, uint32_t size);
|
||||
Result SetMemoryPermission64From32(Core::System& system, uint32_t address, uint32_t size, MemoryPermission perm);
|
||||
Result SetMemoryAttribute64From32(Core::System& system, uint32_t address, uint32_t size, uint32_t mask, uint32_t attr);
|
||||
Result MapMemory64From32(Core::System& system, uint32_t dst_address, uint32_t src_address, uint32_t size);
|
||||
@@ -182,7 +182,7 @@ Result FlushDataCache64From32(Core::System& system, uint32_t address, uint32_t s
|
||||
Result MapPhysicalMemory64From32(Core::System& system, uint32_t address, uint32_t size);
|
||||
Result UnmapPhysicalMemory64From32(Core::System& system, uint32_t address, uint32_t size);
|
||||
Result GetDebugFutureThreadInfo64From32(Core::System& system, ilp32::LastThreadContext* out_context, uint64_t* out_thread_id, Handle debug_handle, int64_t ns);
|
||||
Result GetLastThreadInfo64From32(Core::System& system, ilp32::LastThreadContext* out_context, uintptr_t* out_tls_address, uint32_t* out_flags);
|
||||
Result GetLastThreadInfo64From32(Core::System& system, ilp32::LastThreadContext* out_context, uint64_t* out_tls_address, uint32_t* out_flags);
|
||||
Result GetResourceLimitLimitValue64From32(Core::System& system, int64_t* out_limit_value, Handle resource_limit_handle, LimitableResource which);
|
||||
Result GetResourceLimitCurrentValue64From32(Core::System& system, int64_t* out_current_value, Handle resource_limit_handle, LimitableResource which);
|
||||
Result SetThreadActivity64From32(Core::System& system, Handle thread_handle, ThreadActivity thread_activity);
|
||||
@@ -215,7 +215,7 @@ Result MapTransferMemory64From32(Core::System& system, Handle trmem_handle, uint
|
||||
Result UnmapTransferMemory64From32(Core::System& system, Handle trmem_handle, uint32_t address, uint32_t size);
|
||||
Result CreateInterruptEvent64From32(Core::System& system, Handle* out_read_handle, int32_t interrupt_id, InterruptType interrupt_type);
|
||||
Result QueryPhysicalAddress64From32(Core::System& system, ilp32::PhysicalMemoryInfo* out_info, uint32_t address);
|
||||
Result QueryIoMapping64From32(Core::System& system, uintptr_t* out_address, uintptr_t* out_size, uint64_t physical_address, uint32_t size);
|
||||
Result QueryIoMapping64From32(Core::System& system, uint64_t* out_address, uint64_t* out_size, uint64_t physical_address, uint32_t size);
|
||||
Result CreateDeviceAddressSpace64From32(Core::System& system, Handle* out_handle, uint64_t das_address, uint64_t das_size);
|
||||
Result AttachDeviceAddressSpace64From32(Core::System& system, DeviceName device_name, Handle das_handle);
|
||||
Result DetachDeviceAddressSpace64From32(Core::System& system, DeviceName device_name, Handle das_handle);
|
||||
@@ -258,7 +258,7 @@ Result SetResourceLimitLimitValue64From32(Core::System& system, Handle resource_
|
||||
Result MapInsecureMemory64From32(Core::System& system, uint32_t address, uint32_t size);
|
||||
Result UnmapInsecureMemory64From32(Core::System& system, uint32_t address, uint32_t size);
|
||||
|
||||
Result SetHeapSize64(Core::System& system, uintptr_t* out_address, uint64_t size);
|
||||
Result SetHeapSize64(Core::System& system, uint64_t* out_address, uint64_t size);
|
||||
Result SetMemoryPermission64(Core::System& system, uint64_t address, uint64_t size, MemoryPermission perm);
|
||||
Result SetMemoryAttribute64(Core::System& system, uint64_t address, uint64_t size, uint32_t mask, uint32_t attr);
|
||||
Result MapMemory64(Core::System& system, uint64_t dst_address, uint64_t src_address, uint64_t size);
|
||||
@@ -303,7 +303,7 @@ Result FlushDataCache64(Core::System& system, uint64_t address, uint64_t size);
|
||||
Result MapPhysicalMemory64(Core::System& system, uint64_t address, uint64_t size);
|
||||
Result UnmapPhysicalMemory64(Core::System& system, uint64_t address, uint64_t size);
|
||||
Result GetDebugFutureThreadInfo64(Core::System& system, lp64::LastThreadContext* out_context, uint64_t* out_thread_id, Handle debug_handle, int64_t ns);
|
||||
Result GetLastThreadInfo64(Core::System& system, lp64::LastThreadContext* out_context, uintptr_t* out_tls_address, uint32_t* out_flags);
|
||||
Result GetLastThreadInfo64(Core::System& system, lp64::LastThreadContext* out_context, uint64_t* out_tls_address, uint32_t* out_flags);
|
||||
Result GetResourceLimitLimitValue64(Core::System& system, int64_t* out_limit_value, Handle resource_limit_handle, LimitableResource which);
|
||||
Result GetResourceLimitCurrentValue64(Core::System& system, int64_t* out_current_value, Handle resource_limit_handle, LimitableResource which);
|
||||
Result SetThreadActivity64(Core::System& system, Handle thread_handle, ThreadActivity thread_activity);
|
||||
@@ -336,7 +336,7 @@ Result MapTransferMemory64(Core::System& system, Handle trmem_handle, uint64_t a
|
||||
Result UnmapTransferMemory64(Core::System& system, Handle trmem_handle, uint64_t address, uint64_t size);
|
||||
Result CreateInterruptEvent64(Core::System& system, Handle* out_read_handle, int32_t interrupt_id, InterruptType interrupt_type);
|
||||
Result QueryPhysicalAddress64(Core::System& system, lp64::PhysicalMemoryInfo* out_info, uint64_t address);
|
||||
Result QueryIoMapping64(Core::System& system, uintptr_t* out_address, uintptr_t* out_size, uint64_t physical_address, uint64_t size);
|
||||
Result QueryIoMapping64(Core::System& system, uint64_t* out_address, uint64_t* out_size, uint64_t physical_address, uint64_t size);
|
||||
Result CreateDeviceAddressSpace64(Core::System& system, Handle* out_handle, uint64_t das_address, uint64_t das_size);
|
||||
Result AttachDeviceAddressSpace64(Core::System& system, DeviceName device_name, Handle das_handle);
|
||||
Result DetachDeviceAddressSpace64(Core::System& system, DeviceName device_name, Handle das_handle);
|
||||
|
||||
@@ -12,7 +12,7 @@ Result QueryPhysicalAddress(Core::System& system, lp64::PhysicalMemoryInfo* out_
|
||||
R_THROW(ResultNotImplemented);
|
||||
}
|
||||
|
||||
Result QueryIoMapping(Core::System& system, uintptr_t* out_address, uintptr_t* out_size,
|
||||
Result QueryIoMapping(Core::System& system, uint64_t* out_address, uint64_t* out_size,
|
||||
uint64_t physical_address, uint64_t size) {
|
||||
UNIMPLEMENTED();
|
||||
R_THROW(ResultNotImplemented);
|
||||
@@ -23,7 +23,7 @@ Result QueryPhysicalAddress64(Core::System& system, lp64::PhysicalMemoryInfo* ou
|
||||
R_RETURN(QueryPhysicalAddress(system, out_info, address));
|
||||
}
|
||||
|
||||
Result QueryIoMapping64(Core::System& system, uintptr_t* out_address, uintptr_t* out_size,
|
||||
Result QueryIoMapping64(Core::System& system, uint64_t* out_address, uint64_t* out_size,
|
||||
uint64_t physical_address, uint64_t size) {
|
||||
R_RETURN(QueryIoMapping(system, out_address, out_size, physical_address, size));
|
||||
}
|
||||
@@ -41,10 +41,10 @@ Result QueryPhysicalAddress64From32(Core::System& system, ilp32::PhysicalMemoryI
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result QueryIoMapping64From32(Core::System& system, uintptr_t* out_address, uintptr_t* out_size,
|
||||
Result QueryIoMapping64From32(Core::System& system, uint64_t* out_address, uint64_t* out_size,
|
||||
uint64_t physical_address, uint32_t size) {
|
||||
R_RETURN(QueryIoMapping(system, reinterpret_cast<uintptr_t*>(out_address),
|
||||
reinterpret_cast<uintptr_t*>(out_size), physical_address, size));
|
||||
R_RETURN(QueryIoMapping(system, reinterpret_cast<uint64_t*>(out_address),
|
||||
reinterpret_cast<uint64_t*>(out_size), physical_address, size));
|
||||
}
|
||||
|
||||
} // namespace Kernel::Svc
|
||||
|
||||
@@ -13,7 +13,7 @@ void FlushEntireDataCache(Core::System& system) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
Result FlushDataCache(Core::System& system, VAddr address, size_t size) {
|
||||
Result FlushDataCache(Core::System& system, uint64_t address, uint64_t size) {
|
||||
UNIMPLEMENTED();
|
||||
R_THROW(ResultNotImplemented);
|
||||
}
|
||||
@@ -33,8 +33,8 @@ Result StoreProcessDataCache(Core::System& system, Handle process_handle, uint64
|
||||
Result FlushProcessDataCache(Core::System& system, Handle process_handle, u64 address, u64 size) {
|
||||
// Validate address/size.
|
||||
R_UNLESS(size > 0, ResultInvalidSize);
|
||||
R_UNLESS(address == static_cast<uintptr_t>(address), ResultInvalidCurrentMemory);
|
||||
R_UNLESS(size == static_cast<size_t>(size), ResultInvalidCurrentMemory);
|
||||
R_UNLESS(address == static_cast<uint64_t>(address), ResultInvalidCurrentMemory);
|
||||
R_UNLESS(size == static_cast<uint64_t>(size), ResultInvalidCurrentMemory);
|
||||
|
||||
// Get the process from its handle.
|
||||
KScopedAutoObject process =
|
||||
@@ -53,7 +53,7 @@ void FlushEntireDataCache64(Core::System& system) {
|
||||
FlushEntireDataCache(system);
|
||||
}
|
||||
|
||||
Result FlushDataCache64(Core::System& system, VAddr address, size_t size) {
|
||||
Result FlushDataCache64(Core::System& system, uint64_t address, uint64_t size) {
|
||||
R_RETURN(FlushDataCache(system, address, size));
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ constexpr bool IsValidUnmapFromOwnerCodeMemoryPermission(MemoryPermission perm)
|
||||
|
||||
} // namespace
|
||||
|
||||
Result CreateCodeMemory(Core::System& system, Handle* out, VAddr address, size_t size) {
|
||||
Result CreateCodeMemory(Core::System& system, Handle* out, VAddr address, uint64_t size) {
|
||||
LOG_TRACE(Kernel_SVC, "called, address=0x{:X}, size=0x{:X}", address, size);
|
||||
|
||||
// Get kernel instance.
|
||||
@@ -64,7 +64,7 @@ Result CreateCodeMemory(Core::System& system, Handle* out, VAddr address, size_t
|
||||
}
|
||||
|
||||
Result ControlCodeMemory(Core::System& system, Handle code_memory_handle,
|
||||
CodeMemoryOperation operation, VAddr address, size_t size,
|
||||
CodeMemoryOperation operation, VAddr address, uint64_t size,
|
||||
MemoryPermission perm) {
|
||||
|
||||
LOG_TRACE(Kernel_SVC,
|
||||
|
||||
@@ -45,19 +45,19 @@ Result SetDebugThreadContext(Core::System& system, Handle debug_handle, uint64_t
|
||||
}
|
||||
|
||||
Result QueryDebugProcessMemory(Core::System& system, uint64_t out_memory_info,
|
||||
PageInfo* out_page_info, Handle debug_handle, uintptr_t address) {
|
||||
PageInfo* out_page_info, Handle process_handle, uint64_t address) {
|
||||
UNIMPLEMENTED();
|
||||
R_THROW(ResultNotImplemented);
|
||||
}
|
||||
|
||||
Result ReadDebugProcessMemory(Core::System& system, uintptr_t buffer, Handle debug_handle,
|
||||
uintptr_t address, size_t size) {
|
||||
Result ReadDebugProcessMemory(Core::System& system, uint64_t buffer, Handle debug_handle,
|
||||
uint64_t address, uint64_t size) {
|
||||
UNIMPLEMENTED();
|
||||
R_THROW(ResultNotImplemented);
|
||||
}
|
||||
|
||||
Result WriteDebugProcessMemory(Core::System& system, Handle debug_handle, uintptr_t buffer,
|
||||
uintptr_t address, size_t size) {
|
||||
Result WriteDebugProcessMemory(Core::System& system, Handle debug_handle, uint64_t buffer,
|
||||
uint64_t address, uint64_t size) {
|
||||
UNIMPLEMENTED();
|
||||
R_THROW(ResultNotImplemented);
|
||||
}
|
||||
|
||||
@@ -76,8 +76,8 @@ constexpr bool IsValidDeviceMemoryPermission(MemoryPermission device_perm) {
|
||||
}
|
||||
|
||||
Result MapDeviceAddressSpaceByForce(Core::System& system, Handle das_handle, Handle process_handle,
|
||||
uint64_t process_address, size_t size, uint64_t device_address,
|
||||
u32 option) {
|
||||
uint64_t process_address, uint64_t size,
|
||||
uint64_t device_address, u32 option) {
|
||||
// Decode the option.
|
||||
const MapDeviceAddressSpaceOption option_pack{option};
|
||||
const auto device_perm = option_pack.permission;
|
||||
@@ -90,7 +90,7 @@ Result MapDeviceAddressSpaceByForce(Core::System& system, Handle das_handle, Han
|
||||
R_UNLESS(size > 0, ResultInvalidSize);
|
||||
R_UNLESS((process_address < process_address + size), ResultInvalidCurrentMemory);
|
||||
R_UNLESS((device_address < device_address + size), ResultInvalidMemoryRegion);
|
||||
R_UNLESS((process_address == static_cast<uintptr_t>(process_address)),
|
||||
R_UNLESS((process_address == static_cast<uint64_t>(process_address)),
|
||||
ResultInvalidCurrentMemory);
|
||||
R_UNLESS(IsValidDeviceMemoryPermission(device_perm), ResultInvalidNewMemoryPermission);
|
||||
R_UNLESS(reserved == 0, ResultInvalidEnumValue);
|
||||
@@ -116,8 +116,8 @@ Result MapDeviceAddressSpaceByForce(Core::System& system, Handle das_handle, Han
|
||||
}
|
||||
|
||||
Result MapDeviceAddressSpaceAligned(Core::System& system, Handle das_handle, Handle process_handle,
|
||||
uint64_t process_address, size_t size, uint64_t device_address,
|
||||
u32 option) {
|
||||
uint64_t process_address, uint64_t size,
|
||||
uint64_t device_address, u32 option) {
|
||||
// Decode the option.
|
||||
const MapDeviceAddressSpaceOption option_pack{option};
|
||||
const auto device_perm = option_pack.permission;
|
||||
@@ -131,7 +131,7 @@ Result MapDeviceAddressSpaceAligned(Core::System& system, Handle das_handle, Han
|
||||
R_UNLESS(size > 0, ResultInvalidSize);
|
||||
R_UNLESS((process_address < process_address + size), ResultInvalidCurrentMemory);
|
||||
R_UNLESS((device_address < device_address + size), ResultInvalidMemoryRegion);
|
||||
R_UNLESS((process_address == static_cast<uintptr_t>(process_address)),
|
||||
R_UNLESS((process_address == static_cast<uint64_t>(process_address)),
|
||||
ResultInvalidCurrentMemory);
|
||||
R_UNLESS(IsValidDeviceMemoryPermission(device_perm), ResultInvalidNewMemoryPermission);
|
||||
R_UNLESS(reserved == 0, ResultInvalidEnumValue);
|
||||
@@ -157,7 +157,7 @@ Result MapDeviceAddressSpaceAligned(Core::System& system, Handle das_handle, Han
|
||||
}
|
||||
|
||||
Result UnmapDeviceAddressSpace(Core::System& system, Handle das_handle, Handle process_handle,
|
||||
uint64_t process_address, size_t size, uint64_t device_address) {
|
||||
uint64_t process_address, uint64_t size, uint64_t device_address) {
|
||||
// Validate input.
|
||||
R_UNLESS(Common::IsAligned(process_address, PageSize), ResultInvalidAddress);
|
||||
R_UNLESS(Common::IsAligned(device_address, PageSize), ResultInvalidAddress);
|
||||
@@ -165,7 +165,7 @@ Result UnmapDeviceAddressSpace(Core::System& system, Handle das_handle, Handle p
|
||||
R_UNLESS(size > 0, ResultInvalidSize);
|
||||
R_UNLESS((process_address < process_address + size), ResultInvalidCurrentMemory);
|
||||
R_UNLESS((device_address < device_address + size), ResultInvalidMemoryRegion);
|
||||
R_UNLESS((process_address == static_cast<uintptr_t>(process_address)),
|
||||
R_UNLESS((process_address == static_cast<uint64_t>(process_address)),
|
||||
ResultInvalidCurrentMemory);
|
||||
|
||||
// Get the device address space.
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
|
||||
namespace Kernel::Svc {
|
||||
|
||||
Result MapInsecureMemory(Core::System& system, uintptr_t address, size_t size) {
|
||||
Result MapInsecureMemory(Core::System& system, uint64_t address, uint64_t size) {
|
||||
UNIMPLEMENTED();
|
||||
R_THROW(ResultNotImplemented);
|
||||
}
|
||||
|
||||
Result UnmapInsecureMemory(Core::System& system, uintptr_t address, size_t size) {
|
||||
Result UnmapInsecureMemory(Core::System& system, uint64_t address, uint64_t size) {
|
||||
UNIMPLEMENTED();
|
||||
R_THROW(ResultNotImplemented);
|
||||
}
|
||||
|
||||
@@ -12,19 +12,19 @@ Result CreateIoPool(Core::System& system, Handle* out, IoPoolType pool_type) {
|
||||
}
|
||||
|
||||
Result CreateIoRegion(Core::System& system, Handle* out, Handle io_pool_handle, uint64_t phys_addr,
|
||||
size_t size, MemoryMapping mapping, MemoryPermission perm) {
|
||||
uint64_t size, MemoryMapping mapping, MemoryPermission perm) {
|
||||
UNIMPLEMENTED();
|
||||
R_THROW(ResultNotImplemented);
|
||||
}
|
||||
|
||||
Result MapIoRegion(Core::System& system, Handle io_region_handle, uintptr_t address, size_t size,
|
||||
Result MapIoRegion(Core::System& system, Handle io_region_handle, uint64_t address, uint64_t size,
|
||||
MemoryPermission map_perm) {
|
||||
UNIMPLEMENTED();
|
||||
R_THROW(ResultNotImplemented);
|
||||
}
|
||||
|
||||
Result UnmapIoRegion(Core::System& system, Handle io_region_handle, uintptr_t address,
|
||||
size_t size) {
|
||||
Result UnmapIoRegion(Core::System& system, Handle io_region_handle, uint64_t address,
|
||||
uint64_t size) {
|
||||
UNIMPLEMENTED();
|
||||
R_THROW(ResultNotImplemented);
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ Result SetUnsafeLimit64(Core::System& system, uint64_t limit) {
|
||||
R_RETURN(SetUnsafeLimit(system, limit));
|
||||
}
|
||||
|
||||
Result SetHeapSize64From32(Core::System& system, uintptr_t* out_address, uint32_t size) {
|
||||
Result SetHeapSize64From32(Core::System& system, uint64_t* out_address, uint32_t size) {
|
||||
R_RETURN(SetHeapSize(system, out_address, size));
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "core/core.h"
|
||||
#include "core/hle/kernel/k_client_port.h"
|
||||
#include "core/hle/kernel/k_client_session.h"
|
||||
#include "core/hle/kernel/k_object_name.h"
|
||||
#include "core/hle/kernel/k_port.h"
|
||||
#include "core/hle/kernel/k_process.h"
|
||||
#include "core/hle/kernel/svc.h"
|
||||
@@ -64,7 +65,7 @@ Result ConnectToNamedPort(Core::System& system, Handle* out, VAddr port_name_add
|
||||
}
|
||||
|
||||
Result CreatePort(Core::System& system, Handle* out_server, Handle* out_client,
|
||||
int32_t max_sessions, bool is_light, uintptr_t name) {
|
||||
int32_t max_sessions, bool is_light, uint64_t name) {
|
||||
UNIMPLEMENTED();
|
||||
R_THROW(ResultNotImplemented);
|
||||
}
|
||||
@@ -74,10 +75,57 @@ Result ConnectToPort(Core::System& system, Handle* out_handle, Handle port) {
|
||||
R_THROW(ResultNotImplemented);
|
||||
}
|
||||
|
||||
Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t name,
|
||||
Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t user_name,
|
||||
int32_t max_sessions) {
|
||||
UNIMPLEMENTED();
|
||||
R_THROW(ResultNotImplemented);
|
||||
// Copy the provided name from user memory to kernel memory.
|
||||
std::array<char, KObjectName::NameLengthMax> name{};
|
||||
system.Memory().ReadBlock(user_name, name.data(), sizeof(name));
|
||||
|
||||
// Validate that sessions and name are valid.
|
||||
R_UNLESS(max_sessions >= 0, ResultOutOfRange);
|
||||
R_UNLESS(name[sizeof(name) - 1] == '\x00', ResultOutOfRange);
|
||||
|
||||
if (max_sessions > 0) {
|
||||
// Get the current handle table.
|
||||
auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
|
||||
|
||||
// Create a new port.
|
||||
KPort* port = KPort::Create(system.Kernel());
|
||||
R_UNLESS(port != nullptr, ResultOutOfResource);
|
||||
|
||||
// Initialize the new port.
|
||||
port->Initialize(max_sessions, false, "");
|
||||
|
||||
// Register the port.
|
||||
KPort::Register(system.Kernel(), port);
|
||||
|
||||
// Ensure that our only reference to the port is in the handle table when we're done.
|
||||
SCOPE_EXIT({
|
||||
port->GetClientPort().Close();
|
||||
port->GetServerPort().Close();
|
||||
});
|
||||
|
||||
// Register the handle in the table.
|
||||
R_TRY(handle_table.Add(out_server_handle, std::addressof(port->GetServerPort())));
|
||||
ON_RESULT_FAILURE {
|
||||
handle_table.Remove(*out_server_handle);
|
||||
};
|
||||
|
||||
// Create a new object name.
|
||||
R_TRY(KObjectName::NewFromName(system.Kernel(), std::addressof(port->GetClientPort()),
|
||||
name.data()));
|
||||
} else /* if (max_sessions == 0) */ {
|
||||
// Ensure that this else case is correct.
|
||||
ASSERT(max_sessions == 0);
|
||||
|
||||
// If we're closing, there's no server handle.
|
||||
*out_server_handle = InvalidHandle;
|
||||
|
||||
// Delete the object.
|
||||
R_TRY(KObjectName::Delete<KClientPort>(system.Kernel(), name.data()));
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ConnectToNamedPort64(Core::System& system, Handle* out_handle, uint64_t name) {
|
||||
|
||||
@@ -37,8 +37,8 @@ Result SetProcessMemoryPermission(Core::System& system, Handle process_handle, V
|
||||
R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize);
|
||||
R_UNLESS(size > 0, ResultInvalidSize);
|
||||
R_UNLESS((address < address + size), ResultInvalidCurrentMemory);
|
||||
R_UNLESS(address == static_cast<uintptr_t>(address), ResultInvalidCurrentMemory);
|
||||
R_UNLESS(size == static_cast<size_t>(size), ResultInvalidCurrentMemory);
|
||||
R_UNLESS(address == static_cast<uint64_t>(address), ResultInvalidCurrentMemory);
|
||||
R_UNLESS(size == static_cast<uint64_t>(size), ResultInvalidCurrentMemory);
|
||||
|
||||
// Validate the memory permission.
|
||||
R_UNLESS(IsValidProcessMemoryPermission(perm), ResultInvalidNewMemoryPermission);
|
||||
|
||||
@@ -443,7 +443,7 @@ def emit_wrapper(wrapped_fn, suffix, register_info, arguments, byte_size):
|
||||
lines.append("")
|
||||
|
||||
for output_type, var_name, _, is_address in output_writes:
|
||||
output_type = "uintptr_t" if is_address else output_type
|
||||
output_type = "uint64_t" if is_address else output_type
|
||||
lines.append(f"{output_type} {var_name}{{}};")
|
||||
for input_type, var_name, _ in input_reads:
|
||||
lines.append(f"{input_type} {var_name}{{}};")
|
||||
@@ -630,7 +630,7 @@ def emit_call(bitness, names, suffix):
|
||||
def build_fn_declaration(return_type, name, arguments):
|
||||
arg_list = ["Core::System& system"]
|
||||
for arg in arguments:
|
||||
type_name = "uintptr_t" if arg.is_address else arg.type_name
|
||||
type_name = "uint64_t" if arg.is_address else arg.type_name
|
||||
pointer = "*" if arg.is_output and not arg.is_outptr else ""
|
||||
arg_list.append(f"{type_name}{pointer} {arg.var_name}")
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ enum class Errno : u32 {
|
||||
INVAL = 22,
|
||||
MFILE = 24,
|
||||
MSGSIZE = 90,
|
||||
CONNRESET = 104,
|
||||
NOTCONN = 107,
|
||||
TIMEDOUT = 110,
|
||||
};
|
||||
|
||||
@@ -27,6 +27,8 @@ Errno Translate(Network::Errno value) {
|
||||
return Errno::NOTCONN;
|
||||
case Network::Errno::TIMEDOUT:
|
||||
return Errno::TIMEDOUT;
|
||||
case Network::Errno::CONNRESET:
|
||||
return Errno::CONNRESET;
|
||||
default:
|
||||
UNIMPLEMENTED_MSG("Unimplemented errno={}", value);
|
||||
return Errno::SUCCESS;
|
||||
|
||||
@@ -109,6 +109,8 @@ Errno TranslateNativeError(int e) {
|
||||
return Errno::AGAIN;
|
||||
case WSAECONNREFUSED:
|
||||
return Errno::CONNREFUSED;
|
||||
case WSAECONNRESET:
|
||||
return Errno::CONNRESET;
|
||||
case WSAEHOSTUNREACH:
|
||||
return Errno::HOSTUNREACH;
|
||||
case WSAENETDOWN:
|
||||
@@ -205,6 +207,8 @@ Errno TranslateNativeError(int e) {
|
||||
return Errno::AGAIN;
|
||||
case ECONNREFUSED:
|
||||
return Errno::CONNREFUSED;
|
||||
case ECONNRESET:
|
||||
return Errno::CONNRESET;
|
||||
case EHOSTUNREACH:
|
||||
return Errno::HOSTUNREACH;
|
||||
case ENETDOWN:
|
||||
|
||||
@@ -30,6 +30,7 @@ enum class Errno {
|
||||
NOTCONN,
|
||||
AGAIN,
|
||||
CONNREFUSED,
|
||||
CONNRESET,
|
||||
HOSTUNREACH,
|
||||
NETDOWN,
|
||||
NETUNREACH,
|
||||
|
||||
@@ -15,23 +15,39 @@ constexpr int mouse_axis_y = 1;
|
||||
constexpr int wheel_axis_x = 2;
|
||||
constexpr int wheel_axis_y = 3;
|
||||
constexpr int motion_wheel_y = 4;
|
||||
constexpr int touch_axis_x = 10;
|
||||
constexpr int touch_axis_y = 11;
|
||||
constexpr PadIdentifier identifier = {
|
||||
.guid = Common::UUID{},
|
||||
.port = 0,
|
||||
.pad = 0,
|
||||
};
|
||||
|
||||
constexpr PadIdentifier real_mouse_identifier = {
|
||||
.guid = Common::UUID{},
|
||||
.port = 1,
|
||||
.pad = 0,
|
||||
};
|
||||
|
||||
constexpr PadIdentifier touch_identifier = {
|
||||
.guid = Common::UUID{},
|
||||
.port = 2,
|
||||
.pad = 0,
|
||||
};
|
||||
|
||||
Mouse::Mouse(std::string input_engine_) : InputEngine(std::move(input_engine_)) {
|
||||
PreSetController(identifier);
|
||||
PreSetController(real_mouse_identifier);
|
||||
PreSetController(touch_identifier);
|
||||
|
||||
// Initialize all mouse axis
|
||||
PreSetAxis(identifier, mouse_axis_x);
|
||||
PreSetAxis(identifier, mouse_axis_y);
|
||||
PreSetAxis(identifier, wheel_axis_x);
|
||||
PreSetAxis(identifier, wheel_axis_y);
|
||||
PreSetAxis(identifier, motion_wheel_y);
|
||||
PreSetAxis(identifier, touch_axis_x);
|
||||
PreSetAxis(identifier, touch_axis_y);
|
||||
PreSetAxis(real_mouse_identifier, mouse_axis_x);
|
||||
PreSetAxis(real_mouse_identifier, mouse_axis_y);
|
||||
PreSetAxis(touch_identifier, mouse_axis_x);
|
||||
PreSetAxis(touch_identifier, mouse_axis_y);
|
||||
update_thread = std::jthread([this](std::stop_token stop_token) { UpdateThread(stop_token); });
|
||||
}
|
||||
|
||||
@@ -39,7 +55,7 @@ void Mouse::UpdateThread(std::stop_token stop_token) {
|
||||
Common::SetCurrentThreadName("Mouse");
|
||||
constexpr int update_time = 10;
|
||||
while (!stop_token.stop_requested()) {
|
||||
if (Settings::values.mouse_panning && !Settings::values.mouse_enabled) {
|
||||
if (Settings::values.mouse_panning) {
|
||||
// Slow movement by 4%
|
||||
last_mouse_change *= 0.96f;
|
||||
const float sensitivity =
|
||||
@@ -57,17 +73,7 @@ void Mouse::UpdateThread(std::stop_token stop_token) {
|
||||
}
|
||||
}
|
||||
|
||||
void Mouse::MouseMove(int x, int y, f32 touch_x, f32 touch_y, int center_x, int center_y) {
|
||||
// If native mouse is enabled just set the screen coordinates
|
||||
if (Settings::values.mouse_enabled) {
|
||||
SetAxis(identifier, mouse_axis_x, touch_x);
|
||||
SetAxis(identifier, mouse_axis_y, touch_y);
|
||||
return;
|
||||
}
|
||||
|
||||
SetAxis(identifier, touch_axis_x, touch_x);
|
||||
SetAxis(identifier, touch_axis_y, touch_y);
|
||||
|
||||
void Mouse::Move(int x, int y, int center_x, int center_y) {
|
||||
if (Settings::values.mouse_panning) {
|
||||
auto mouse_change =
|
||||
(Common::MakeVec(x, y) - Common::MakeVec(center_x, center_y)).Cast<float>();
|
||||
@@ -113,20 +119,41 @@ void Mouse::MouseMove(int x, int y, f32 touch_x, f32 touch_y, int center_x, int
|
||||
}
|
||||
}
|
||||
|
||||
void Mouse::PressButton(int x, int y, f32 touch_x, f32 touch_y, MouseButton button) {
|
||||
SetAxis(identifier, touch_axis_x, touch_x);
|
||||
SetAxis(identifier, touch_axis_y, touch_y);
|
||||
void Mouse::MouseMove(f32 touch_x, f32 touch_y) {
|
||||
SetAxis(real_mouse_identifier, mouse_axis_x, touch_x);
|
||||
SetAxis(real_mouse_identifier, mouse_axis_y, touch_y);
|
||||
}
|
||||
|
||||
void Mouse::TouchMove(f32 touch_x, f32 touch_y) {
|
||||
SetAxis(touch_identifier, mouse_axis_x, touch_x);
|
||||
SetAxis(touch_identifier, mouse_axis_y, touch_y);
|
||||
}
|
||||
|
||||
void Mouse::PressButton(int x, int y, MouseButton button) {
|
||||
SetButton(identifier, static_cast<int>(button), true);
|
||||
|
||||
// Set initial analog parameters
|
||||
mouse_origin = {x, y};
|
||||
last_mouse_position = {x, y};
|
||||
button_pressed = true;
|
||||
}
|
||||
|
||||
void Mouse::PressMouseButton(MouseButton button) {
|
||||
SetButton(real_mouse_identifier, static_cast<int>(button), true);
|
||||
}
|
||||
|
||||
void Mouse::PressTouchButton(f32 touch_x, f32 touch_y, MouseButton button) {
|
||||
SetAxis(touch_identifier, mouse_axis_x, touch_x);
|
||||
SetAxis(touch_identifier, mouse_axis_y, touch_y);
|
||||
SetButton(touch_identifier, static_cast<int>(button), true);
|
||||
}
|
||||
|
||||
void Mouse::ReleaseButton(MouseButton button) {
|
||||
SetButton(identifier, static_cast<int>(button), false);
|
||||
SetButton(real_mouse_identifier, static_cast<int>(button), false);
|
||||
SetButton(touch_identifier, static_cast<int>(button), false);
|
||||
|
||||
if (!Settings::values.mouse_panning && !Settings::values.mouse_enabled) {
|
||||
if (!Settings::values.mouse_panning) {
|
||||
SetAxis(identifier, mouse_axis_x, 0);
|
||||
SetAxis(identifier, mouse_axis_y, 0);
|
||||
}
|
||||
|
||||
@@ -37,13 +37,43 @@ public:
|
||||
* @param center_x the x-coordinate of the middle of the screen
|
||||
* @param center_y the y-coordinate of the middle of the screen
|
||||
*/
|
||||
void MouseMove(int x, int y, f32 touch_x, f32 touch_y, int center_x, int center_y);
|
||||
void Move(int x, int y, int center_x, int center_y);
|
||||
|
||||
/**
|
||||
* Sets the status of all buttons bound with the key to pressed
|
||||
* @param key_code the code of the key to press
|
||||
* Signals that real mouse has moved.
|
||||
* @param x the absolute position on the touchscreen of the cursor
|
||||
* @param y the absolute position on the touchscreen of the cursor
|
||||
*/
|
||||
void PressButton(int x, int y, f32 touch_x, f32 touch_y, MouseButton button);
|
||||
void MouseMove(f32 touch_x, f32 touch_y);
|
||||
|
||||
/**
|
||||
* Signals that touch finger has moved.
|
||||
* @param x the absolute position on the touchscreen of the cursor
|
||||
* @param y the absolute position on the touchscreen of the cursor
|
||||
*/
|
||||
void TouchMove(f32 touch_x, f32 touch_y);
|
||||
|
||||
/**
|
||||
* Sets the status of a button to pressed
|
||||
* @param x the x-coordinate of the cursor
|
||||
* @param y the y-coordinate of the cursor
|
||||
* @param button the id of the button to press
|
||||
*/
|
||||
void PressButton(int x, int y, MouseButton button);
|
||||
|
||||
/**
|
||||
* Sets the status of a mouse button to pressed
|
||||
* @param button the id of the button to press
|
||||
*/
|
||||
void PressMouseButton(MouseButton button);
|
||||
|
||||
/**
|
||||
* Sets the status of touch finger to pressed
|
||||
* @param x the absolute position on the touchscreen of the cursor
|
||||
* @param y the absolute position on the touchscreen of the cursor
|
||||
* @param button the id of the button to press
|
||||
*/
|
||||
void PressTouchButton(f32 touch_x, f32 touch_y, MouseButton button);
|
||||
|
||||
/**
|
||||
* Sets the status of all buttons bound with the key to released
|
||||
|
||||
@@ -194,6 +194,10 @@ bool MappingFactory::IsDriverValid(const MappingData& data) const {
|
||||
if (data.engine == "keyboard" && data.pad.port != 0) {
|
||||
return false;
|
||||
}
|
||||
// Only port 0 can be mapped on the mouse
|
||||
if (data.engine == "mouse" && data.pad.port != 0) {
|
||||
return false;
|
||||
}
|
||||
// To prevent mapping with two devices we disable any UDP except motion
|
||||
if (!Settings::values.enable_udp_controller && data.engine == "cemuhookudp" &&
|
||||
data.type != EngineInputType::Motion) {
|
||||
|
||||
@@ -292,7 +292,7 @@ IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::Blo
|
||||
|
||||
Optimization::PositionPass(env, program);
|
||||
|
||||
Optimization::GlobalMemoryToStorageBufferPass(program, host_info);
|
||||
Optimization::GlobalMemoryToStorageBufferPass(program);
|
||||
Optimization::TexturePass(env, program, host_info);
|
||||
|
||||
if (Settings::values.resolution_info.active) {
|
||||
|
||||
@@ -15,7 +15,6 @@ struct HostTranslateInfo {
|
||||
bool needs_demote_reorder{}; ///< True when the device needs DemoteToHelperInvocation reordered
|
||||
bool support_snorm_render_buffer{}; ///< True when the device supports SNORM render buffers
|
||||
bool support_viewport_index_layer{}; ///< True when the device supports gl_Layer in VS
|
||||
u32 min_ssbo_alignment{}; ///< Minimum alignment supported by the device for SSBOs
|
||||
bool support_geometry_shader_passthrough{}; ///< True when the device supports geometry
|
||||
///< passthrough shaders
|
||||
};
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include "shader_recompiler/frontend/ir/breadth_first_search.h"
|
||||
#include "shader_recompiler/frontend/ir/ir_emitter.h"
|
||||
#include "shader_recompiler/frontend/ir/value.h"
|
||||
#include "shader_recompiler/host_translate_info.h"
|
||||
#include "shader_recompiler/ir_opt/passes.h"
|
||||
|
||||
namespace Shader::Optimization {
|
||||
@@ -403,7 +402,7 @@ void CollectStorageBuffers(IR::Block& block, IR::Inst& inst, StorageInfo& info)
|
||||
}
|
||||
|
||||
/// Returns the offset in indices (not bytes) for an equivalent storage instruction
|
||||
IR::U32 StorageOffset(IR::Block& block, IR::Inst& inst, StorageBufferAddr buffer, u32 alignment) {
|
||||
IR::U32 StorageOffset(IR::Block& block, IR::Inst& inst, StorageBufferAddr buffer) {
|
||||
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
|
||||
IR::U32 offset;
|
||||
if (const std::optional<LowAddrInfo> low_addr{TrackLowAddress(&inst)}) {
|
||||
@@ -416,10 +415,7 @@ IR::U32 StorageOffset(IR::Block& block, IR::Inst& inst, StorageBufferAddr buffer
|
||||
}
|
||||
// Subtract the least significant 32 bits from the guest offset. The result is the storage
|
||||
// buffer offset in bytes.
|
||||
IR::U32 low_cbuf{ir.GetCbuf(ir.Imm32(buffer.index), ir.Imm32(buffer.offset))};
|
||||
|
||||
// Align the offset base to match the host alignment requirements
|
||||
low_cbuf = ir.BitwiseAnd(low_cbuf, ir.Imm32(~(alignment - 1U)));
|
||||
const IR::U32 low_cbuf{ir.GetCbuf(ir.Imm32(buffer.index), ir.Imm32(buffer.offset))};
|
||||
return ir.ISub(offset, low_cbuf);
|
||||
}
|
||||
|
||||
@@ -514,7 +510,7 @@ void Replace(IR::Block& block, IR::Inst& inst, const IR::U32& storage_index,
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
void GlobalMemoryToStorageBufferPass(IR::Program& program, const HostTranslateInfo& host_info) {
|
||||
void GlobalMemoryToStorageBufferPass(IR::Program& program) {
|
||||
StorageInfo info;
|
||||
for (IR::Block* const block : program.post_order_blocks) {
|
||||
for (IR::Inst& inst : block->Instructions()) {
|
||||
@@ -538,8 +534,7 @@ void GlobalMemoryToStorageBufferPass(IR::Program& program, const HostTranslateIn
|
||||
const IR::U32 index{IR::Value{static_cast<u32>(info.set.index_of(it))}};
|
||||
IR::Block* const block{storage_inst.block};
|
||||
IR::Inst* const inst{storage_inst.inst};
|
||||
const IR::U32 offset{
|
||||
StorageOffset(*block, *inst, storage_buffer, host_info.min_ssbo_alignment)};
|
||||
const IR::U32 offset{StorageOffset(*block, *inst, storage_buffer)};
|
||||
Replace(*block, *inst, index, offset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Shader::Optimization {
|
||||
void CollectShaderInfoPass(Environment& env, IR::Program& program);
|
||||
void ConstantPropagationPass(Environment& env, IR::Program& program);
|
||||
void DeadCodeEliminationPass(IR::Program& program);
|
||||
void GlobalMemoryToStorageBufferPass(IR::Program& program, const HostTranslateInfo& host_info);
|
||||
void GlobalMemoryToStorageBufferPass(IR::Program& program);
|
||||
void IdentityRemovalPass(IR::Program& program);
|
||||
void LowerFp16ToFp32(IR::Program& program);
|
||||
void LowerInt64ToInt32(IR::Program& program);
|
||||
|
||||
@@ -568,7 +568,7 @@ private:
|
||||
const u64* const state_words = Array<type>();
|
||||
const u64 num_query_words = size / BYTES_PER_WORD + 1;
|
||||
const u64 word_begin = offset / BYTES_PER_WORD;
|
||||
const u64 word_end = std::min(word_begin + num_query_words, NumWords());
|
||||
const u64 word_end = std::min<u64>(word_begin + num_query_words, NumWords());
|
||||
const u64 page_base = offset / BYTES_PER_PAGE;
|
||||
const u64 page_limit = Common::DivCeil(offset + size, BYTES_PER_PAGE);
|
||||
u64 begin = std::numeric_limits<u64>::max();
|
||||
|
||||
@@ -1938,21 +1938,14 @@ typename BufferCache<P>::Binding BufferCache<P>::StorageBufferBinding(GPUVAddr s
|
||||
bool is_written) const {
|
||||
const GPUVAddr gpu_addr = gpu_memory->Read<u64>(ssbo_addr);
|
||||
const u32 size = gpu_memory->Read<u32>(ssbo_addr + 8);
|
||||
const u32 alignment = runtime.GetStorageBufferAlignment();
|
||||
|
||||
const GPUVAddr aligned_gpu_addr = Common::AlignDown(gpu_addr, alignment);
|
||||
const u32 aligned_size =
|
||||
Common::AlignUp(static_cast<u32>(gpu_addr - aligned_gpu_addr) + size, alignment);
|
||||
|
||||
const std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(aligned_gpu_addr);
|
||||
const std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr);
|
||||
if (!cpu_addr || size == 0) {
|
||||
return NULL_BINDING;
|
||||
}
|
||||
|
||||
const VAddr cpu_end = Common::AlignUp(*cpu_addr + aligned_size, Core::Memory::YUZU_PAGESIZE);
|
||||
const VAddr cpu_end = Common::AlignUp(*cpu_addr + size, Core::Memory::YUZU_PAGESIZE);
|
||||
const Binding binding{
|
||||
.cpu_addr = *cpu_addr,
|
||||
.size = is_written ? aligned_size : static_cast<u32>(cpu_end - *cpu_addr),
|
||||
.size = is_written ? size : static_cast<u32>(cpu_end - *cpu_addr),
|
||||
.buffer_id = BufferId{},
|
||||
};
|
||||
return binding;
|
||||
|
||||
@@ -160,10 +160,6 @@ public:
|
||||
return device.CanReportMemoryUsage();
|
||||
}
|
||||
|
||||
u32 GetStorageBufferAlignment() const {
|
||||
return static_cast<u32>(device.GetShaderStorageBufferAlignment());
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr std::array PABO_LUT{
|
||||
GL_VERTEX_PROGRAM_PARAMETER_BUFFER_NV, GL_TESS_CONTROL_PROGRAM_PARAMETER_BUFFER_NV,
|
||||
|
||||
@@ -236,7 +236,6 @@ ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindo
|
||||
.needs_demote_reorder = device.IsAmd(),
|
||||
.support_snorm_render_buffer = false,
|
||||
.support_viewport_index_layer = device.HasVertexViewportLayer(),
|
||||
.min_ssbo_alignment = static_cast<u32>(device.GetShaderStorageBufferAlignment()),
|
||||
.support_geometry_shader_passthrough = device.HasGeometryShaderPassthrough(),
|
||||
} {
|
||||
if (use_asynchronous_shaders) {
|
||||
|
||||
@@ -228,8 +228,9 @@ void ApplySwizzle(GLuint handle, PixelFormat format, std::array<SwizzleSource, 4
|
||||
|
||||
[[nodiscard]] bool CanBeAccelerated(const TextureCacheRuntime& runtime,
|
||||
const VideoCommon::ImageInfo& info) {
|
||||
if (IsPixelFormatASTC(info.format)) {
|
||||
return !runtime.HasNativeASTC() && Settings::values.accelerate_astc.GetValue();
|
||||
if (IsPixelFormatASTC(info.format) && !runtime.HasNativeASTC()) {
|
||||
return Settings::values.accelerate_astc.GetValue() &&
|
||||
!Settings::values.async_astc.GetValue();
|
||||
}
|
||||
// Disable other accelerated uploads for now as they don't implement swizzled uploads
|
||||
return false;
|
||||
@@ -258,6 +259,14 @@ void ApplySwizzle(GLuint handle, PixelFormat format, std::array<SwizzleSource, 4
|
||||
return format_info.compatibility_class == store_class;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool CanBeDecodedAsync(const TextureCacheRuntime& runtime,
|
||||
const VideoCommon::ImageInfo& info) {
|
||||
if (IsPixelFormatASTC(info.format) && !runtime.HasNativeASTC()) {
|
||||
return Settings::values.async_astc.GetValue();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
[[nodiscard]] CopyOrigin MakeCopyOrigin(VideoCommon::Offset3D offset,
|
||||
VideoCommon::SubresourceLayers subresource, GLenum target) {
|
||||
switch (target) {
|
||||
@@ -721,7 +730,9 @@ std::optional<size_t> TextureCacheRuntime::StagingBuffers::FindBuffer(size_t req
|
||||
Image::Image(TextureCacheRuntime& runtime_, const VideoCommon::ImageInfo& info_, GPUVAddr gpu_addr_,
|
||||
VAddr cpu_addr_)
|
||||
: VideoCommon::ImageBase(info_, gpu_addr_, cpu_addr_), runtime{&runtime_} {
|
||||
if (CanBeAccelerated(*runtime, info)) {
|
||||
if (CanBeDecodedAsync(*runtime, info)) {
|
||||
flags |= ImageFlagBits::AsynchronousDecode;
|
||||
} else if (CanBeAccelerated(*runtime, info)) {
|
||||
flags |= ImageFlagBits::AcceleratedUpload;
|
||||
}
|
||||
if (IsConverted(runtime->device, info.format, info.type)) {
|
||||
|
||||
@@ -330,10 +330,6 @@ bool BufferCacheRuntime::CanReportMemoryUsage() const {
|
||||
return device.CanReportMemoryUsage();
|
||||
}
|
||||
|
||||
u32 BufferCacheRuntime::GetStorageBufferAlignment() const {
|
||||
return static_cast<u32>(device.GetStorageBufferAlignment());
|
||||
}
|
||||
|
||||
void BufferCacheRuntime::Finish() {
|
||||
scheduler.Finish();
|
||||
}
|
||||
|
||||
@@ -73,8 +73,6 @@ public:
|
||||
|
||||
bool CanReportMemoryUsage() const;
|
||||
|
||||
u32 GetStorageBufferAlignment() const;
|
||||
|
||||
[[nodiscard]] StagingBufferRef UploadStagingBuffer(size_t size);
|
||||
|
||||
[[nodiscard]] StagingBufferRef DownloadStagingBuffer(size_t size);
|
||||
|
||||
@@ -344,7 +344,6 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device
|
||||
driver_id == VK_DRIVER_ID_AMD_PROPRIETARY || driver_id == VK_DRIVER_ID_AMD_OPEN_SOURCE,
|
||||
.support_snorm_render_buffer = true,
|
||||
.support_viewport_index_layer = device.IsExtShaderViewportIndexLayerSupported(),
|
||||
.min_ssbo_alignment = static_cast<u32>(device.GetStorageBufferAlignment()),
|
||||
.support_geometry_shader_passthrough = device.IsNvGeometryShaderPassthroughSupported(),
|
||||
};
|
||||
|
||||
|
||||
@@ -36,23 +36,18 @@ VkSurfaceFormatKHR ChooseSwapSurfaceFormat(vk::Span<VkSurfaceFormatKHR> formats)
|
||||
VkPresentModeKHR ChooseSwapPresentMode(vk::Span<VkPresentModeKHR> modes) {
|
||||
// Mailbox (triple buffering) doesn't lock the application like fifo (vsync),
|
||||
// prefer it if vsync option is not selected
|
||||
// AMD proprietary drivers can't render past the screen's refresh rate
|
||||
const auto found_mailbox = std::find(modes.begin(), modes.end(), VK_PRESENT_MODE_MAILBOX_KHR);
|
||||
const auto found_imm = std::find(modes.begin(), modes.end(), VK_PRESENT_MODE_IMMEDIATE_KHR);
|
||||
if (!Settings::values.use_speed_limit.GetValue() && found_imm != modes.end()) {
|
||||
return VK_PRESENT_MODE_IMMEDIATE_KHR;
|
||||
if (Settings::values.fullscreen_mode.GetValue() == Settings::FullscreenMode::Borderless &&
|
||||
found_mailbox != modes.end() && !Settings::values.use_vsync.GetValue()) {
|
||||
return VK_PRESENT_MODE_MAILBOX_KHR;
|
||||
}
|
||||
if (Settings::values.use_vsync.GetValue()) {
|
||||
if (found_mailbox != modes.end()) {
|
||||
return VK_PRESENT_MODE_MAILBOX_KHR;
|
||||
}
|
||||
} else {
|
||||
if (!Settings::values.use_speed_limit.GetValue()) {
|
||||
// FIFO present mode locks the framerate to the monitor's refresh rate,
|
||||
// Find an alternative to surpass this limitation if FPS is unlocked.
|
||||
const auto found_imm = std::find(modes.begin(), modes.end(), VK_PRESENT_MODE_IMMEDIATE_KHR);
|
||||
if (found_imm != modes.end()) {
|
||||
return VK_PRESENT_MODE_IMMEDIATE_KHR;
|
||||
}
|
||||
if (found_mailbox != modes.end()) {
|
||||
return VK_PRESENT_MODE_MAILBOX_KHR;
|
||||
}
|
||||
}
|
||||
return VK_PRESENT_MODE_FIFO_KHR;
|
||||
}
|
||||
|
||||
@@ -1256,11 +1256,12 @@ Image::Image(TextureCacheRuntime& runtime_, const ImageInfo& info_, GPUVAddr gpu
|
||||
commit(runtime_.memory_allocator.Commit(original_image, MemoryUsage::DeviceLocal)),
|
||||
aspect_mask(ImageAspectMask(info.format)) {
|
||||
if (IsPixelFormatASTC(info.format) && !runtime->device.IsOptimalAstcSupported()) {
|
||||
if (Settings::values.accelerate_astc.GetValue()) {
|
||||
if (Settings::values.async_astc.GetValue()) {
|
||||
flags |= VideoCommon::ImageFlagBits::AsynchronousDecode;
|
||||
} else if (Settings::values.accelerate_astc.GetValue()) {
|
||||
flags |= VideoCommon::ImageFlagBits::AcceleratedUpload;
|
||||
} else {
|
||||
flags |= VideoCommon::ImageFlagBits::Converted;
|
||||
}
|
||||
flags |= VideoCommon::ImageFlagBits::Converted;
|
||||
flags |= VideoCommon::ImageFlagBits::CostlyLoad;
|
||||
}
|
||||
if (runtime->device.HasDebuggingToolAttached()) {
|
||||
|
||||
@@ -38,6 +38,9 @@ enum class ImageFlagBits : u32 {
|
||||
Rescaled = 1 << 13,
|
||||
CheckingRescalable = 1 << 14,
|
||||
IsRescalable = 1 << 15,
|
||||
|
||||
AsynchronousDecode = 1 << 16,
|
||||
IsDecoding = 1 << 17, ///< Is currently being decoded asynchornously.
|
||||
};
|
||||
DECLARE_ENUM_FLAG_OPERATORS(ImageFlagBits)
|
||||
|
||||
|
||||
@@ -85,6 +85,11 @@ void TextureCache<P>::RunGarbageCollector() {
|
||||
}
|
||||
--num_iterations;
|
||||
auto& image = slot_images[image_id];
|
||||
if (True(image.flags & ImageFlagBits::IsDecoding)) {
|
||||
// This image is still being decoded, deleting it will invalidate the slot
|
||||
// used by the async decoder thread.
|
||||
return false;
|
||||
}
|
||||
const bool must_download =
|
||||
image.IsSafeDownload() && False(image.flags & ImageFlagBits::BadOverlap);
|
||||
if (!high_priority_mode &&
|
||||
@@ -133,6 +138,8 @@ void TextureCache<P>::TickFrame() {
|
||||
sentenced_images.Tick();
|
||||
sentenced_framebuffers.Tick();
|
||||
sentenced_image_view.Tick();
|
||||
TickAsyncDecode();
|
||||
|
||||
runtime.TickFrame();
|
||||
critical_gc = 0;
|
||||
++frame_tick;
|
||||
@@ -777,6 +784,10 @@ void TextureCache<P>::RefreshContents(Image& image, ImageId image_id) {
|
||||
LOG_WARNING(HW_GPU, "MSAA image uploads are not implemented");
|
||||
return;
|
||||
}
|
||||
if (True(image.flags & ImageFlagBits::AsynchronousDecode)) {
|
||||
QueueAsyncDecode(image, image_id);
|
||||
return;
|
||||
}
|
||||
auto staging = runtime.UploadStagingBuffer(MapSizeBytes(image));
|
||||
UploadImageContents(image, staging);
|
||||
runtime.InsertUploadMemoryBarrier();
|
||||
@@ -989,6 +1000,65 @@ u64 TextureCache<P>::GetScaledImageSizeBytes(const ImageBase& image) {
|
||||
return fitted_size;
|
||||
}
|
||||
|
||||
template <class P>
|
||||
void TextureCache<P>::QueueAsyncDecode(Image& image, ImageId image_id) {
|
||||
UNIMPLEMENTED_IF(False(image.flags & ImageFlagBits::Converted));
|
||||
LOG_INFO(HW_GPU, "Queuing async texture decode");
|
||||
|
||||
image.flags |= ImageFlagBits::IsDecoding;
|
||||
auto decode = std::make_unique<AsyncDecodeContext>();
|
||||
auto* decode_ptr = decode.get();
|
||||
decode->image_id = image_id;
|
||||
async_decodes.push_back(std::move(decode));
|
||||
|
||||
Common::ScratchBuffer<u8> local_unswizzle_data_buffer(image.unswizzled_size_bytes);
|
||||
const size_t guest_size_bytes = image.guest_size_bytes;
|
||||
swizzle_data_buffer.resize_destructive(guest_size_bytes);
|
||||
gpu_memory->ReadBlockUnsafe(image.gpu_addr, swizzle_data_buffer.data(), guest_size_bytes);
|
||||
auto copies = UnswizzleImage(*gpu_memory, image.gpu_addr, image.info, swizzle_data_buffer,
|
||||
local_unswizzle_data_buffer);
|
||||
const size_t out_size = MapSizeBytes(image);
|
||||
|
||||
auto func = [out_size, copies, info = image.info,
|
||||
input = std::move(local_unswizzle_data_buffer),
|
||||
async_decode = decode_ptr]() mutable {
|
||||
async_decode->decoded_data.resize_destructive(out_size);
|
||||
std::span copies_span{copies.data(), copies.size()};
|
||||
ConvertImage(input, info, async_decode->decoded_data, copies_span);
|
||||
|
||||
// TODO: Do we need this lock?
|
||||
std::unique_lock lock{async_decode->mutex};
|
||||
async_decode->copies = std::move(copies);
|
||||
async_decode->complete = true;
|
||||
};
|
||||
texture_decode_worker.QueueWork(std::move(func));
|
||||
}
|
||||
|
||||
template <class P>
|
||||
void TextureCache<P>::TickAsyncDecode() {
|
||||
bool has_uploads{};
|
||||
auto i = async_decodes.begin();
|
||||
while (i != async_decodes.end()) {
|
||||
auto* async_decode = i->get();
|
||||
std::unique_lock lock{async_decode->mutex};
|
||||
if (!async_decode->complete) {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
Image& image = slot_images[async_decode->image_id];
|
||||
auto staging = runtime.UploadStagingBuffer(MapSizeBytes(image));
|
||||
std::memcpy(staging.mapped_span.data(), async_decode->decoded_data.data(),
|
||||
async_decode->decoded_data.size());
|
||||
image.UploadMemory(staging, async_decode->copies);
|
||||
image.flags &= ~ImageFlagBits::IsDecoding;
|
||||
has_uploads = true;
|
||||
i = async_decodes.erase(i);
|
||||
}
|
||||
if (has_uploads) {
|
||||
runtime.InsertUploadMemoryBarrier();
|
||||
}
|
||||
}
|
||||
|
||||
template <class P>
|
||||
bool TextureCache<P>::ScaleUp(Image& image) {
|
||||
const bool has_copy = image.HasScaled();
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <deque>
|
||||
#include <limits>
|
||||
#include <mutex>
|
||||
@@ -18,6 +19,7 @@
|
||||
#include "common/lru_cache.h"
|
||||
#include "common/polyfill_ranges.h"
|
||||
#include "common/scratch_buffer.h"
|
||||
#include "common/thread_worker.h"
|
||||
#include "video_core/compatible_formats.h"
|
||||
#include "video_core/control/channel_state_cache.h"
|
||||
#include "video_core/delayed_destruction_ring.h"
|
||||
@@ -54,6 +56,14 @@ struct ImageViewInOut {
|
||||
ImageViewId id{};
|
||||
};
|
||||
|
||||
struct AsyncDecodeContext {
|
||||
ImageId image_id;
|
||||
Common::ScratchBuffer<u8> decoded_data;
|
||||
std::vector<BufferImageCopy> copies;
|
||||
std::mutex mutex;
|
||||
std::atomic_bool complete;
|
||||
};
|
||||
|
||||
using TextureCacheGPUMap = std::unordered_map<u64, std::vector<ImageId>, Common::IdentityHash<u64>>;
|
||||
|
||||
class TextureCacheChannelInfo : public ChannelInfo {
|
||||
@@ -377,6 +387,9 @@ private:
|
||||
bool ScaleDown(Image& image);
|
||||
u64 GetScaledImageSizeBytes(const ImageBase& image);
|
||||
|
||||
void QueueAsyncDecode(Image& image, ImageId image_id);
|
||||
void TickAsyncDecode();
|
||||
|
||||
Runtime& runtime;
|
||||
|
||||
VideoCore::RasterizerInterface& rasterizer;
|
||||
@@ -430,6 +443,9 @@ private:
|
||||
|
||||
u64 modification_tick = 0;
|
||||
u64 frame_tick = 0;
|
||||
|
||||
Common::ThreadWorker texture_decode_worker{1, "TextureDecoder"};
|
||||
std::vector<std::unique_ptr<AsyncDecodeContext>> async_decodes;
|
||||
};
|
||||
|
||||
} // namespace VideoCommon
|
||||
|
||||
@@ -1656,8 +1656,8 @@ void Decompress(std::span<const uint8_t> data, uint32_t width, uint32_t height,
|
||||
const u32 rows = Common::DivideUp(height, block_height);
|
||||
const u32 cols = Common::DivideUp(width, block_width);
|
||||
|
||||
Common::ThreadWorker workers{std::max(std::thread::hardware_concurrency(), 2U) / 2,
|
||||
"ASTCDecompress"};
|
||||
static Common::ThreadWorker workers{std::max(std::thread::hardware_concurrency(), 2U) / 2,
|
||||
"ASTCDecompress"};
|
||||
|
||||
for (u32 z = 0; z < depth; ++z) {
|
||||
const u32 depth_offset = z * height * width * 4;
|
||||
|
||||
@@ -71,7 +71,7 @@ struct Client::Impl {
|
||||
const std::string& jwt_ = "", const std::string& username_ = "",
|
||||
const std::string& token_ = "") {
|
||||
if (cli == nullptr) {
|
||||
cli = std::make_unique<httplib::Client>(host.c_str());
|
||||
cli = std::make_unique<httplib::Client>(host);
|
||||
}
|
||||
|
||||
if (!cli->is_valid()) {
|
||||
|
||||
@@ -652,7 +652,10 @@ void GRenderWindow::mousePressEvent(QMouseEvent* event) {
|
||||
const auto [x, y] = ScaleTouch(pos);
|
||||
const auto [touch_x, touch_y] = MapToTouchScreen(x, y);
|
||||
const auto button = QtButtonToMouseButton(event->button());
|
||||
input_subsystem->GetMouse()->PressButton(x, y, touch_x, touch_y, button);
|
||||
|
||||
input_subsystem->GetMouse()->PressMouseButton(button);
|
||||
input_subsystem->GetMouse()->PressButton(pos.x(), pos.y(), button);
|
||||
input_subsystem->GetMouse()->PressTouchButton(touch_x, touch_y, button);
|
||||
|
||||
emit MouseActivity();
|
||||
}
|
||||
@@ -669,7 +672,10 @@ void GRenderWindow::mouseMoveEvent(QMouseEvent* event) {
|
||||
const auto [touch_x, touch_y] = MapToTouchScreen(x, y);
|
||||
const int center_x = width() / 2;
|
||||
const int center_y = height() / 2;
|
||||
input_subsystem->GetMouse()->MouseMove(x, y, touch_x, touch_y, center_x, center_y);
|
||||
|
||||
input_subsystem->GetMouse()->MouseMove(touch_x, touch_y);
|
||||
input_subsystem->GetMouse()->TouchMove(touch_x, touch_y);
|
||||
input_subsystem->GetMouse()->Move(pos.x(), pos.y(), center_x, center_y);
|
||||
|
||||
if (Settings::values.mouse_panning && !Settings::values.mouse_enabled) {
|
||||
QCursor::setPos(mapToGlobal(QPoint{center_x, center_y}));
|
||||
|
||||
@@ -147,6 +147,8 @@ public:
|
||||
|
||||
qreal windowPixelRatio() const;
|
||||
|
||||
std::pair<u32, u32> ScaleTouch(const QPointF& pos) const;
|
||||
|
||||
void closeEvent(QCloseEvent* event) override;
|
||||
|
||||
void resizeEvent(QResizeEvent* event) override;
|
||||
@@ -184,8 +186,6 @@ public:
|
||||
|
||||
void CaptureScreenshot(const QString& screenshot_path);
|
||||
|
||||
std::pair<u32, u32> ScaleTouch(const QPointF& pos) const;
|
||||
|
||||
/**
|
||||
* Instructs the window to re-launch the application using the specified program_index.
|
||||
* @param program_index Specifies the index within the application of the program to launch.
|
||||
|
||||
@@ -707,6 +707,7 @@ void Config::ReadRendererValues() {
|
||||
ReadGlobalSetting(Settings::values.use_asynchronous_gpu_emulation);
|
||||
ReadGlobalSetting(Settings::values.nvdec_emulation);
|
||||
ReadGlobalSetting(Settings::values.accelerate_astc);
|
||||
ReadGlobalSetting(Settings::values.async_astc);
|
||||
ReadGlobalSetting(Settings::values.use_vsync);
|
||||
ReadGlobalSetting(Settings::values.shader_backend);
|
||||
ReadGlobalSetting(Settings::values.use_asynchronous_shaders);
|
||||
@@ -1350,6 +1351,7 @@ void Config::SaveRendererValues() {
|
||||
static_cast<u32>(Settings::values.nvdec_emulation.GetDefault()),
|
||||
Settings::values.nvdec_emulation.UsingGlobal());
|
||||
WriteGlobalSetting(Settings::values.accelerate_astc);
|
||||
WriteGlobalSetting(Settings::values.async_astc);
|
||||
WriteGlobalSetting(Settings::values.use_vsync);
|
||||
WriteSetting(QString::fromStdString(Settings::values.shader_backend.GetLabel()),
|
||||
static_cast<u32>(Settings::values.shader_backend.GetValue(global)),
|
||||
|
||||
@@ -23,11 +23,13 @@ void ConfigureGraphicsAdvanced::SetConfiguration() {
|
||||
const bool runtime_lock = !system.IsPoweredOn();
|
||||
ui->use_vsync->setEnabled(runtime_lock);
|
||||
ui->renderer_force_max_clock->setEnabled(runtime_lock);
|
||||
ui->async_astc->setEnabled(runtime_lock);
|
||||
ui->use_asynchronous_shaders->setEnabled(runtime_lock);
|
||||
ui->anisotropic_filtering_combobox->setEnabled(runtime_lock);
|
||||
|
||||
ui->renderer_force_max_clock->setChecked(Settings::values.renderer_force_max_clock.GetValue());
|
||||
ui->use_vsync->setChecked(Settings::values.use_vsync.GetValue());
|
||||
ui->async_astc->setChecked(Settings::values.async_astc.GetValue());
|
||||
ui->use_asynchronous_shaders->setChecked(Settings::values.use_asynchronous_shaders.GetValue());
|
||||
ui->use_fast_gpu_time->setChecked(Settings::values.use_fast_gpu_time.GetValue());
|
||||
ui->use_pessimistic_flushes->setChecked(Settings::values.use_pessimistic_flushes.GetValue());
|
||||
@@ -60,6 +62,8 @@ void ConfigureGraphicsAdvanced::ApplyConfiguration() {
|
||||
ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy,
|
||||
ui->anisotropic_filtering_combobox);
|
||||
ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vsync, ui->use_vsync, use_vsync);
|
||||
ConfigurationShared::ApplyPerGameSetting(&Settings::values.async_astc, ui->async_astc,
|
||||
async_astc);
|
||||
ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_shaders,
|
||||
ui->use_asynchronous_shaders,
|
||||
use_asynchronous_shaders);
|
||||
@@ -91,6 +95,7 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() {
|
||||
ui->renderer_force_max_clock->setEnabled(
|
||||
Settings::values.renderer_force_max_clock.UsingGlobal());
|
||||
ui->use_vsync->setEnabled(Settings::values.use_vsync.UsingGlobal());
|
||||
ui->async_astc->setEnabled(Settings::values.async_astc.UsingGlobal());
|
||||
ui->use_asynchronous_shaders->setEnabled(
|
||||
Settings::values.use_asynchronous_shaders.UsingGlobal());
|
||||
ui->use_fast_gpu_time->setEnabled(Settings::values.use_fast_gpu_time.UsingGlobal());
|
||||
@@ -108,6 +113,8 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() {
|
||||
Settings::values.renderer_force_max_clock,
|
||||
renderer_force_max_clock);
|
||||
ConfigurationShared::SetColoredTristate(ui->use_vsync, Settings::values.use_vsync, use_vsync);
|
||||
ConfigurationShared::SetColoredTristate(ui->async_astc, Settings::values.async_astc,
|
||||
async_astc);
|
||||
ConfigurationShared::SetColoredTristate(ui->use_asynchronous_shaders,
|
||||
Settings::values.use_asynchronous_shaders,
|
||||
use_asynchronous_shaders);
|
||||
|
||||
@@ -38,6 +38,7 @@ private:
|
||||
|
||||
ConfigurationShared::CheckState renderer_force_max_clock;
|
||||
ConfigurationShared::CheckState use_vsync;
|
||||
ConfigurationShared::CheckState async_astc;
|
||||
ConfigurationShared::CheckState use_asynchronous_shaders;
|
||||
ConfigurationShared::CheckState use_fast_gpu_time;
|
||||
ConfigurationShared::CheckState use_pessimistic_flushes;
|
||||
|
||||
@@ -89,6 +89,16 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="async_astc">
|
||||
<property name="toolTip">
|
||||
<string>Enables asynchronous ASTC texture decoding, which may reduce load time stutter. This feature is experimental.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Decode ASTC textures asynchronously (Hack)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="use_asynchronous_shaders">
|
||||
<property name="toolTip">
|
||||
|
||||
@@ -1490,7 +1490,7 @@ void ConfigureInputPlayer::mousePressEvent(QMouseEvent* event) {
|
||||
}
|
||||
|
||||
const auto button = GRenderWindow::QtButtonToMouseButton(event->button());
|
||||
input_subsystem->GetMouse()->PressButton(0, 0, 0, 0, button);
|
||||
input_subsystem->GetMouse()->PressButton(0, 0, button);
|
||||
}
|
||||
|
||||
void ConfigureInputPlayer::wheelEvent(QWheelEvent* event) {
|
||||
|
||||
@@ -371,7 +371,7 @@ void ConfigureRingController::mousePressEvent(QMouseEvent* event) {
|
||||
}
|
||||
|
||||
const auto button = GRenderWindow::QtButtonToMouseButton(event->button());
|
||||
input_subsystem->GetMouse()->PressButton(0, 0, 0, 0, button);
|
||||
input_subsystem->GetMouse()->PressButton(0, 0, button);
|
||||
}
|
||||
|
||||
void ConfigureRingController::keyPressEvent(QKeyEvent* event) {
|
||||
|
||||
@@ -75,8 +75,10 @@ void DiscordImpl::Update() {
|
||||
|
||||
// New Check for game cover
|
||||
httplib::Client cli(game_cover_url);
|
||||
cli.set_connection_timeout(std::chrono::seconds(3));
|
||||
cli.set_read_timeout(std::chrono::seconds(3));
|
||||
|
||||
if (auto res = cli.Head(fmt::format("/images/game/boxart/{}.png", icon_name).c_str())) {
|
||||
if (auto res = cli.Head(fmt::format("/images/game/boxart/{}.png", icon_name))) {
|
||||
if (res->status == 200) {
|
||||
game_cover_url += fmt::format("/images/game/boxart/{}.png", icon_name);
|
||||
} else {
|
||||
|
||||
@@ -1165,6 +1165,14 @@ void GMainWindow::InitializeHotkeys() {
|
||||
Settings::values.use_speed_limit.SetValue(!Settings::values.use_speed_limit.GetValue());
|
||||
});
|
||||
connect_shortcut(QStringLiteral("Toggle Mouse Panning"), [&] {
|
||||
if (Settings::values.mouse_enabled) {
|
||||
Settings::values.mouse_panning = false;
|
||||
QMessageBox::warning(
|
||||
this, tr("Emulated mouse is enabled"),
|
||||
tr("Real mouse input and mouse panning are incompatible. Please disable the "
|
||||
"emulated mouse in input advanced settings to allow mouse panning."));
|
||||
return;
|
||||
}
|
||||
Settings::values.mouse_panning = !Settings::values.mouse_panning;
|
||||
if (Settings::values.mouse_panning) {
|
||||
render_window->installEventFilter(render_window);
|
||||
|
||||
@@ -324,6 +324,7 @@ void Config::ReadValues() {
|
||||
ReadSetting("Renderer", Settings::values.use_asynchronous_shaders);
|
||||
ReadSetting("Renderer", Settings::values.nvdec_emulation);
|
||||
ReadSetting("Renderer", Settings::values.accelerate_astc);
|
||||
ReadSetting("Renderer", Settings::values.async_astc);
|
||||
ReadSetting("Renderer", Settings::values.use_fast_gpu_time);
|
||||
ReadSetting("Renderer", Settings::values.use_pessimistic_flushes);
|
||||
ReadSetting("Renderer", Settings::values.use_vulkan_driver_pipeline_cache);
|
||||
|
||||
@@ -342,6 +342,10 @@ nvdec_emulation =
|
||||
# 0: Off, 1 (default): On
|
||||
accelerate_astc =
|
||||
|
||||
# Decode ASTC textures asynchronously.
|
||||
# 0 (default): Off, 1: On
|
||||
async_astc =
|
||||
|
||||
# Turns on the speed limiter, which will limit the emulation speed to the desired speed limit value
|
||||
# 0: Off, 1: On (default)
|
||||
use_speed_limit =
|
||||
|
||||
@@ -62,7 +62,9 @@ void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) {
|
||||
const auto mouse_button = SDLButtonToMouseButton(button);
|
||||
if (state == SDL_PRESSED) {
|
||||
const auto [touch_x, touch_y] = MouseToTouchPos(x, y);
|
||||
input_subsystem->GetMouse()->PressButton(x, y, touch_x, touch_y, mouse_button);
|
||||
input_subsystem->GetMouse()->PressButton(x, y, mouse_button);
|
||||
input_subsystem->GetMouse()->PressMouseButton(mouse_button);
|
||||
input_subsystem->GetMouse()->PressTouchButton(touch_x, touch_y, mouse_button);
|
||||
} else {
|
||||
input_subsystem->GetMouse()->ReleaseButton(mouse_button);
|
||||
}
|
||||
@@ -70,7 +72,9 @@ void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) {
|
||||
|
||||
void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) {
|
||||
const auto [touch_x, touch_y] = MouseToTouchPos(x, y);
|
||||
input_subsystem->GetMouse()->MouseMove(x, y, touch_x, touch_y, 0, 0);
|
||||
input_subsystem->GetMouse()->Move(x, y, 0, 0);
|
||||
input_subsystem->GetMouse()->MouseMove(touch_x, touch_y);
|
||||
input_subsystem->GetMouse()->TouchMove(touch_x, touch_y);
|
||||
}
|
||||
|
||||
void EmuWindow_SDL2::OnFingerDown(float x, float y, std::size_t id) {
|
||||
|
||||
Reference in New Issue
Block a user