summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/math_util.h4
-rw-r--r--src/common/vector_math.h75
-rw-r--r--src/core/CMakeLists.txt14
-rw-r--r--src/core/hle/kernel/kernel.cpp66
-rw-r--r--src/core/hle/service/acc/acc.cpp8
-rw-r--r--src/core/hle/service/bcat/backend/boxcat.cpp10
-rw-r--r--src/core/hle/service/filesystem/filesystem.cpp5
-rw-r--r--src/core/hle/service/mii/manager.cpp2
-rw-r--r--src/core/hle/service/nifm/nifm.cpp12
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp16
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h9
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.cpp14
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.h1
-rw-r--r--src/core/hle/service/vi/vi.cpp52
-rw-r--r--src/input_common/CMakeLists.txt29
-rwxr-xr-xsrc/input_common/analog_from_button.cpp18
-rw-r--r--src/input_common/gcadapter/gc_adapter.cpp35
-rw-r--r--src/input_common/gcadapter/gc_adapter.h6
-rw-r--r--src/input_common/gcadapter/gc_poller.cpp48
-rw-r--r--src/input_common/keyboard.cpp5
-rw-r--r--src/input_common/main.cpp4
-rw-r--r--src/input_common/motion_emu.cpp41
-rw-r--r--src/input_common/motion_from_button.cpp2
-rw-r--r--src/input_common/motion_input.cpp38
-rw-r--r--src/input_common/motion_input.h10
-rw-r--r--src/input_common/sdl/sdl_impl.cpp89
-rw-r--r--src/input_common/settings.h2
-rw-r--r--src/input_common/touch_from_button.cpp8
-rw-r--r--src/input_common/udp/client.cpp78
-rw-r--r--src/input_common/udp/client.h18
-rw-r--r--src/input_common/udp/udp.cpp28
-rw-r--r--src/video_core/renderer_vulkan/fixed_pipeline_state.cpp3
-rw-r--r--src/video_core/renderer_vulkan/fixed_pipeline_state.h10
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.cpp24
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.h2
-rw-r--r--src/video_core/renderer_vulkan/vk_device.cpp97
-rw-r--r--src/video_core/renderer_vulkan/vk_device.h12
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp5
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.cpp3
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp11
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.h1
-rw-r--r--src/video_core/renderer_vulkan/vk_shader_decompiler.cpp12
-rw-r--r--src/video_core/renderer_vulkan/wrapper.cpp23
-rw-r--r--src/video_core/renderer_vulkan/wrapper.h4
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp37
-rw-r--r--src/yuzu/configuration/configure_input_player.h9
-rw-r--r--src/yuzu/configuration/configure_motion_touch.cpp2
47 files changed, 622 insertions, 380 deletions
diff --git a/src/common/math_util.h b/src/common/math_util.h
index 661c056ca..4c38d8040 100644
--- a/src/common/math_util.h
+++ b/src/common/math_util.h
@@ -20,8 +20,8 @@ struct Rectangle {
constexpr Rectangle() = default;
- constexpr Rectangle(T left, T top, T right, T bottom)
- : left(left), top(top), right(right), bottom(bottom) {}
+ constexpr Rectangle(T left_, T top_, T right_, T bottom_)
+ : left(left_), top(top_), right(right_), bottom(bottom_) {}
[[nodiscard]] T GetWidth() const {
if constexpr (std::is_floating_point_v<T>) {
diff --git a/src/common/vector_math.h b/src/common/vector_math.h
index 2a0fcf541..22dba3c2d 100644
--- a/src/common/vector_math.h
+++ b/src/common/vector_math.h
@@ -87,7 +87,13 @@ public:
template <typename V>
[[nodiscard]] constexpr Vec2<decltype(T{} * V{})> operator*(const V& f) const {
- return {x * f, y * f};
+ using TV = decltype(T{} * V{});
+ using C = std::common_type_t<T, V>;
+
+ return {
+ static_cast<TV>(static_cast<C>(x) * static_cast<C>(f)),
+ static_cast<TV>(static_cast<C>(y) * static_cast<C>(f)),
+ };
}
template <typename V>
@@ -98,7 +104,13 @@ public:
template <typename V>
[[nodiscard]] constexpr Vec2<decltype(T{} / V{})> operator/(const V& f) const {
- return {x / f, y / f};
+ using TV = decltype(T{} / V{});
+ using C = std::common_type_t<T, V>;
+
+ return {
+ static_cast<TV>(static_cast<C>(x) / static_cast<C>(f)),
+ static_cast<TV>(static_cast<C>(y) / static_cast<C>(f)),
+ };
}
template <typename V>
@@ -168,7 +180,10 @@ public:
template <typename T, typename V>
[[nodiscard]] constexpr Vec2<T> operator*(const V& f, const Vec2<T>& vec) {
- return Vec2<T>(f * vec.x, f * vec.y);
+ using C = std::common_type_t<T, V>;
+
+ return Vec2<T>(static_cast<T>(static_cast<C>(f) * static_cast<C>(vec.x)),
+ static_cast<T>(static_cast<C>(f) * static_cast<C>(vec.y)));
}
using Vec2f = Vec2<float>;
@@ -237,7 +252,14 @@ public:
template <typename V>
[[nodiscard]] constexpr Vec3<decltype(T{} * V{})> operator*(const V& f) const {
- return {x * f, y * f, z * f};
+ using TV = decltype(T{} * V{});
+ using C = std::common_type_t<T, V>;
+
+ return {
+ static_cast<TV>(static_cast<C>(x) * static_cast<C>(f)),
+ static_cast<TV>(static_cast<C>(y) * static_cast<C>(f)),
+ static_cast<TV>(static_cast<C>(z) * static_cast<C>(f)),
+ };
}
template <typename V>
@@ -247,7 +269,14 @@ public:
}
template <typename V>
[[nodiscard]] constexpr Vec3<decltype(T{} / V{})> operator/(const V& f) const {
- return {x / f, y / f, z / f};
+ using TV = decltype(T{} / V{});
+ using C = std::common_type_t<T, V>;
+
+ return {
+ static_cast<TV>(static_cast<C>(x) / static_cast<C>(f)),
+ static_cast<TV>(static_cast<C>(y) / static_cast<C>(f)),
+ static_cast<TV>(static_cast<C>(z) / static_cast<C>(f)),
+ };
}
template <typename V>
@@ -367,7 +396,11 @@ public:
template <typename T, typename V>
[[nodiscard]] constexpr Vec3<T> operator*(const V& f, const Vec3<T>& vec) {
- return Vec3<T>(f * vec.x, f * vec.y, f * vec.z);
+ using C = std::common_type_t<T, V>;
+
+ return Vec3<T>(static_cast<T>(static_cast<C>(f) * static_cast<C>(vec.x)),
+ static_cast<T>(static_cast<C>(f) * static_cast<C>(vec.y)),
+ static_cast<T>(static_cast<C>(f) * static_cast<C>(vec.z)));
}
template <>
@@ -446,7 +479,15 @@ public:
template <typename V>
[[nodiscard]] constexpr Vec4<decltype(T{} * V{})> operator*(const V& f) const {
- return {x * f, y * f, z * f, w * f};
+ using TV = decltype(T{} * V{});
+ using C = std::common_type_t<T, V>;
+
+ return {
+ static_cast<TV>(static_cast<C>(x) * static_cast<C>(f)),
+ static_cast<TV>(static_cast<C>(y) * static_cast<C>(f)),
+ static_cast<TV>(static_cast<C>(z) * static_cast<C>(f)),
+ static_cast<TV>(static_cast<C>(w) * static_cast<C>(f)),
+ };
}
template <typename V>
@@ -457,7 +498,15 @@ public:
template <typename V>
[[nodiscard]] constexpr Vec4<decltype(T{} / V{})> operator/(const V& f) const {
- return {x / f, y / f, z / f, w / f};
+ using TV = decltype(T{} / V{});
+ using C = std::common_type_t<T, V>;
+
+ return {
+ static_cast<TV>(static_cast<C>(x) / static_cast<C>(f)),
+ static_cast<TV>(static_cast<C>(y) / static_cast<C>(f)),
+ static_cast<TV>(static_cast<C>(z) / static_cast<C>(f)),
+ static_cast<TV>(static_cast<C>(w) / static_cast<C>(f)),
+ };
}
template <typename V>
@@ -582,7 +631,15 @@ public:
template <typename T, typename V>
[[nodiscard]] constexpr Vec4<decltype(V{} * T{})> operator*(const V& f, const Vec4<T>& vec) {
- return {f * vec.x, f * vec.y, f * vec.z, f * vec.w};
+ using TV = decltype(V{} * T{});
+ using C = std::common_type_t<T, V>;
+
+ return {
+ static_cast<TV>(static_cast<C>(f) * static_cast<C>(vec.x)),
+ static_cast<TV>(static_cast<C>(f) * static_cast<C>(vec.y)),
+ static_cast<TV>(static_cast<C>(f) * static_cast<C>(vec.z)),
+ static_cast<TV>(static_cast<C>(f) * static_cast<C>(vec.w)),
+ };
}
using Vec4f = Vec4<float>;
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index f910e438f..9dc320f53 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -1,9 +1,3 @@
-if (YUZU_ENABLE_BOXCAT)
- set(BCAT_BOXCAT_ADDITIONAL_SOURCES hle/service/bcat/backend/boxcat.cpp hle/service/bcat/backend/boxcat.h)
-else()
- set(BCAT_BOXCAT_ADDITIONAL_SOURCES)
-endif()
-
add_library(core STATIC
arm/arm_interface.h
arm/arm_interface.cpp
@@ -303,7 +297,6 @@ add_library(core STATIC
hle/service/audio/hwopus.h
hle/service/bcat/backend/backend.cpp
hle/service/bcat/backend/backend.h
- ${BCAT_BOXCAT_ADDITIONAL_SOURCES}
hle/service/bcat/bcat.cpp
hle/service/bcat/bcat.h
hle/service/bcat/module.cpp
@@ -608,6 +601,13 @@ add_library(core STATIC
tools/freezer.h
)
+if (YUZU_ENABLE_BOXCAT)
+ target_sources(core PRIVATE
+ hle/service/bcat/backend/boxcat.cpp
+ hle/service/bcat/backend/boxcat.h
+ )
+endif()
+
if (MSVC)
target_compile_options(core PRIVATE
# 'expression' : signed/unsigned mismatch
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index c04b23eff..ed30854ee 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -7,7 +7,6 @@
#include <bitset>
#include <functional>
#include <memory>
-#include <mutex>
#include <thread>
#include <unordered_map>
#include <utility>
@@ -107,7 +106,11 @@ struct KernelCore::Impl {
cores.clear();
exclusive_monitor.reset();
- host_thread_ids.clear();
+
+ num_host_threads = 0;
+ std::fill(register_host_thread_keys.begin(), register_host_thread_keys.end(),
+ std::thread::id{});
+ std::fill(register_host_thread_values.begin(), register_host_thread_values.end(), 0);
}
void InitializePhysicalCores() {
@@ -177,54 +180,56 @@ struct KernelCore::Impl {
void MakeCurrentProcess(Process* process) {
current_process = process;
-
if (process == nullptr) {
return;
}
-
- u32 core_id = GetCurrentHostThreadID();
+ const u32 core_id = GetCurrentHostThreadID();
if (core_id < Core::Hardware::NUM_CPU_CORES) {
system.Memory().SetCurrentPageTable(*process, core_id);
}
}
void RegisterCoreThread(std::size_t core_id) {
- std::unique_lock lock{register_thread_mutex};
+ const std::thread::id this_id = std::this_thread::get_id();
if (!is_multicore) {
- single_core_thread_id = std::this_thread::get_id();
+ single_core_thread_id = this_id;
}
- const std::thread::id this_id = std::this_thread::get_id();
- const auto it = host_thread_ids.find(this_id);
+ const auto end = register_host_thread_keys.begin() + num_host_threads;
+ const auto it = std::find(register_host_thread_keys.begin(), end, this_id);
ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
- ASSERT(it == host_thread_ids.end());
+ ASSERT(it == end);
ASSERT(!registered_core_threads[core_id]);
- host_thread_ids[this_id] = static_cast<u32>(core_id);
+ InsertHostThread(static_cast<u32>(core_id));
registered_core_threads.set(core_id);
}
void RegisterHostThread() {
- std::unique_lock lock{register_thread_mutex};
const std::thread::id this_id = std::this_thread::get_id();
- const auto it = host_thread_ids.find(this_id);
- if (it != host_thread_ids.end()) {
- return;
+ const auto end = register_host_thread_keys.begin() + num_host_threads;
+ const auto it = std::find(register_host_thread_keys.begin(), end, this_id);
+ if (it == end) {
+ InsertHostThread(registered_thread_ids++);
}
- host_thread_ids[this_id] = registered_thread_ids++;
}
- u32 GetCurrentHostThreadID() const {
+ void InsertHostThread(u32 value) {
+ const size_t index = num_host_threads++;
+ ASSERT_MSG(index < NUM_REGISTRABLE_HOST_THREADS, "Too many host threads");
+ register_host_thread_values[index] = value;
+ register_host_thread_keys[index] = std::this_thread::get_id();
+ }
+
+ [[nodiscard]] u32 GetCurrentHostThreadID() const {
const std::thread::id this_id = std::this_thread::get_id();
- if (!is_multicore) {
- if (single_core_thread_id == this_id) {
- return static_cast<u32>(system.GetCpuManager().CurrentCore());
- }
+ if (!is_multicore && single_core_thread_id == this_id) {
+ return static_cast<u32>(system.GetCpuManager().CurrentCore());
}
- std::unique_lock lock{register_thread_mutex};
- const auto it = host_thread_ids.find(this_id);
- if (it == host_thread_ids.end()) {
+ const auto end = register_host_thread_keys.begin() + num_host_threads;
+ const auto it = std::find(register_host_thread_keys.begin(), end, this_id);
+ if (it == end) {
return Core::INVALID_HOST_THREAD_ID;
}
- return it->second;
+ return register_host_thread_values[std::distance(register_host_thread_keys.begin(), it)];
}
Core::EmuThreadHandle GetCurrentEmuThreadID() const {
@@ -322,10 +327,15 @@ struct KernelCore::Impl {
std::vector<Kernel::PhysicalCore> cores;
// 0-3 IDs represent core threads, >3 represent others
- std::unordered_map<std::thread::id, u32> host_thread_ids;
- u32 registered_thread_ids{Core::Hardware::NUM_CPU_CORES};
+ std::atomic<u32> registered_thread_ids{Core::Hardware::NUM_CPU_CORES};
std::bitset<Core::Hardware::NUM_CPU_CORES> registered_core_threads;
- mutable std::mutex register_thread_mutex;
+
+ // Number of host threads is a relatively high number to avoid overflowing
+ static constexpr size_t NUM_REGISTRABLE_HOST_THREADS = 64;
+ std::atomic<size_t> num_host_threads{0};
+ std::array<std::atomic<std::thread::id>, NUM_REGISTRABLE_HOST_THREADS>
+ register_host_thread_keys{};
+ std::array<std::atomic<u32>, NUM_REGISTRABLE_HOST_THREADS> register_host_thread_values{};
// Kernel memory management
std::unique_ptr<Memory::MemoryManager> memory_manager;
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp
index 6b1613510..2850dd805 100644
--- a/src/core/hle/service/acc/acc.cpp
+++ b/src/core/hle/service/acc/acc.cpp
@@ -496,7 +496,7 @@ public:
{3, nullptr, "LoadIdTokenCache"},
{130, nullptr, "GetNintendoAccountUserResourceCacheForApplication"},
{150, nullptr, "CreateAuthorizationRequest"},
- {160, nullptr, "StoreOpenContext"},
+ {160, &IManagerForApplication::StoreOpenContext, "StoreOpenContext"},
{170, nullptr, "LoadNetworkServiceLicenseKindAsync"},
};
// clang-format on
@@ -520,6 +520,12 @@ private:
rb.PushRaw<u64>(user_id.GetNintendoID());
}
+ void StoreOpenContext(Kernel::HLERequestContext& ctx) {
+ LOG_WARNING(Service_ACC, "(STUBBED) called");
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+ }
+
Common::UUID user_id;
};
diff --git a/src/core/hle/service/bcat/backend/boxcat.cpp b/src/core/hle/service/bcat/backend/boxcat.cpp
index bd7ea75c2..e6cadf491 100644
--- a/src/core/hle/service/bcat/backend/boxcat.cpp
+++ b/src/core/hle/service/bcat/backend/boxcat.cpp
@@ -463,6 +463,16 @@ Boxcat::StatusResult Boxcat::GetStatus(std::optional<std::string>& global,
{std::string("Boxcat-Client-Type"), std::string(BOXCAT_CLIENT_TYPE)},
};
+ if (!client.is_valid()) {
+ LOG_ERROR(Service_BCAT, "Client is invalid, going offline!");
+ return StatusResult::Offline;
+ }
+
+ if (!client.is_socket_open()) {
+ LOG_ERROR(Service_BCAT, "Failed to open socket, going offline!");
+ return StatusResult::Offline;
+ }
+
const auto response = client.Get(BOXCAT_PATHNAME_EVENTS, headers);
if (response == nullptr)
return StatusResult::Offline;
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index 54a5fb84b..3cdef4888 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -79,7 +79,7 @@ ResultCode VfsDirectoryServiceWrapper::DeleteFile(const std::string& path_) cons
}
auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path));
- if (dir->GetFile(Common::FS::GetFilename(path)) == nullptr) {
+ if (dir == nullptr || dir->GetFile(Common::FS::GetFilename(path)) == nullptr) {
return FileSys::ERROR_PATH_NOT_FOUND;
}
if (!dir->DeleteFile(Common::FS::GetFilename(path))) {
@@ -93,8 +93,9 @@ ResultCode VfsDirectoryServiceWrapper::DeleteFile(const std::string& path_) cons
ResultCode VfsDirectoryServiceWrapper::CreateDirectory(const std::string& path_) const {
std::string path(Common::FS::SanitizePath(path_));
auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path));
- if (dir == nullptr && Common::FS::GetFilename(Common::FS::GetParentPath(path)).empty())
+ if (dir == nullptr || Common::FS::GetFilename(Common::FS::GetParentPath(path)).empty()) {
dir = backing;
+ }
auto new_dir = dir->CreateSubdirectory(Common::FS::GetFilename(path));
if (new_dir == nullptr) {
// TODO(DarkLordZach): Find a better error code for this
diff --git a/src/core/hle/service/mii/manager.cpp b/src/core/hle/service/mii/manager.cpp
index 5930765bc..1b75c2ebe 100644
--- a/src/core/hle/service/mii/manager.cpp
+++ b/src/core/hle/service/mii/manager.cpp
@@ -131,7 +131,7 @@ template <typename T>
T GetRandomValue(T min, T max) {
std::random_device device;
std::mt19937 gen(device());
- std::uniform_int_distribution<u64> distribution(0, static_cast<u64>(max));
+ std::uniform_int_distribution<u64> distribution(static_cast<u64>(min), static_cast<u64>(max));
return static_cast<T>(distribution(gen));
}
diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp
index 2e9d95195..db7ec6d0e 100644
--- a/src/core/hle/service/nifm/nifm.cpp
+++ b/src/core/hle/service/nifm/nifm.cpp
@@ -62,7 +62,7 @@ public:
{18, nullptr, "SetRequirementByRevision"},
{19, nullptr, "GetRequirement"},
{20, nullptr, "GetRevision"},
- {21, nullptr, "GetAppletInfo"},
+ {21, &IRequest::GetAppletInfo, "GetAppletInfo"},
{22, nullptr, "GetAdditionalInfo"},
{23, nullptr, "SetKeptInSleep"},
{24, nullptr, "RegisterSocketDescriptor"},
@@ -125,6 +125,16 @@ private:
rb.Push(RESULT_SUCCESS);
}
+ void GetAppletInfo(Kernel::HLERequestContext& ctx) {
+ LOG_WARNING(Service_NIFM, "(STUBBED) called");
+
+ IPC::ResponseBuilder rb{ctx, 8};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push<u32>(0);
+ rb.Push<u32>(0);
+ rb.Push<u32>(0);
+ }
+
Kernel::EventPair event1, event2;
};
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
index 85e921ceb..3a5bebff3 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
@@ -46,6 +46,8 @@ u32 nvhost_as_gpu::ioctl(Ioctl command, const std::vector<u8>& input, const std:
return GetVARegions(input, output);
case IoctlCommand::IocUnmapBufferCommand:
return UnmapBuffer(input, output);
+ case IoctlCommand::IocFreeSpaceCommand:
+ return FreeSpace(input, output);
default:
break;
}
@@ -91,6 +93,20 @@ u32 nvhost_as_gpu::AllocateSpace(const std::vector<u8>& input, std::vector<u8>&
return result;
}
+u32 nvhost_as_gpu::FreeSpace(const std::vector<u8>& input, std::vector<u8>& output) {
+ IoctlFreeSpace params{};
+ std::memcpy(&params, input.data(), input.size());
+
+ LOG_DEBUG(Service_NVDRV, "called, offset={:X}, pages={:X}, page_size={:X}", params.offset,
+ params.pages, params.page_size);
+
+ system.GPU().MemoryManager().Unmap(params.offset,
+ static_cast<std::size_t>(params.pages) * params.page_size);
+
+ std::memcpy(output.data(), &params, output.size());
+ return NvErrCodes::Success;
+}
+
u32 nvhost_as_gpu::Remap(const std::vector<u8>& input, std::vector<u8>& output) {
const auto num_entries = input.size() / sizeof(IoctlRemapEntry);
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h
index 9a0cdff0c..fcdb40d93 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h
@@ -82,6 +82,7 @@ private:
IocBindChannelCommand = 0x40044101,
IocGetVaRegionsCommand = 0xC0404108,
IocUnmapBufferCommand = 0xC0084105,
+ IocFreeSpaceCommand = 0xC0104103,
};
struct IoctlInitalizeEx {
@@ -107,6 +108,13 @@ private:
};
static_assert(sizeof(IoctlAllocSpace) == 24, "IoctlInitalizeEx is incorrect size");
+ struct IoctlFreeSpace {
+ u64_le offset;
+ u32_le pages;
+ u32_le page_size;
+ };
+ static_assert(sizeof(IoctlFreeSpace) == 16, "IoctlFreeSpace is incorrect size");
+
struct IoctlRemapEntry {
u16_le flags;
u16_le kind;
@@ -162,6 +170,7 @@ private:
u32 Remap(const std::vector<u8>& input, std::vector<u8>& output);
u32 MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output);
u32 UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output);
+ u32 FreeSpace(const std::vector<u8>& input, std::vector<u8>& output);
u32 BindChannel(const std::vector<u8>& input, std::vector<u8>& output);
u32 GetVARegions(const std::vector<u8>& input, std::vector<u8>& output);
diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp
index 637b310d7..4f1e210b1 100644
--- a/src/core/hle/service/nvflinger/buffer_queue.cpp
+++ b/src/core/hle/service/nvflinger/buffer_queue.cpp
@@ -99,6 +99,20 @@ void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform,
queue_sequence.push_back(slot);
}
+void BufferQueue::CancelBuffer(u32 slot, const Service::Nvidia::MultiFence& multi_fence) {
+ const auto itr = std::find_if(queue.begin(), queue.end(),
+ [slot](const Buffer& buffer) { return buffer.slot == slot; });
+ ASSERT(itr != queue.end());
+ ASSERT(itr->status != Buffer::Status::Free);
+ itr->status = Buffer::Status::Free;
+ itr->multi_fence = multi_fence;
+ itr->swap_interval = 0;
+
+ free_buffers.push_back(slot);
+
+ buffer_wait_event.writable->Signal();
+}
+
std::optional<std::reference_wrapper<const BufferQueue::Buffer>> BufferQueue::AcquireBuffer() {
auto itr = queue.end();
// Iterate to find a queued buffer matching the requested slot.
diff --git a/src/core/hle/service/nvflinger/buffer_queue.h b/src/core/hle/service/nvflinger/buffer_queue.h
index 8a837e5aa..e7517c7e1 100644
--- a/src/core/hle/service/nvflinger/buffer_queue.h
+++ b/src/core/hle/service/nvflinger/buffer_queue.h
@@ -95,6 +95,7 @@ public:
void QueueBuffer(u32 slot, BufferTransformFlags transform,
const Common::Rectangle<int>& crop_rect, u32 swap_interval,
Service::Nvidia::MultiFence& multi_fence);
+ void CancelBuffer(u32 slot, const Service::Nvidia::MultiFence& multi_fence);
std::optional<std::reference_wrapper<const Buffer>> AcquireBuffer();
void ReleaseBuffer(u32 slot);
void Disconnect();
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index d380c60fb..5b0e371fe 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -215,10 +215,9 @@ public:
explicit IGBPConnectRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) {
Deserialize();
}
- ~IGBPConnectRequestParcel() override = default;
void DeserializeData() override {
- std::u16string token = ReadInterfaceToken();
+ [[maybe_unused]] const std::u16string token = ReadInterfaceToken();
data = Read<Data>();
}
@@ -279,10 +278,9 @@ public:
: Parcel(std::move(buffer)) {
Deserialize();
}
- ~IGBPSetPreallocatedBufferRequestParcel() override = default;
void DeserializeData() override {
- std::u16string token = ReadInterfaceToken();
+ [[maybe_unused]] const std::u16string token = ReadInterfaceToken();
data = Read<Data>();
buffer = Read<NVFlinger::IGBPBuffer>();
}
@@ -306,15 +304,40 @@ protected:
}
};
+class IGBPCancelBufferRequestParcel : public Parcel {
+public:
+ explicit IGBPCancelBufferRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) {
+ Deserialize();
+ }
+
+ void DeserializeData() override {
+ [[maybe_unused]] const std::u16string token = ReadInterfaceToken();
+ data = Read<Data>();
+ }
+
+ struct Data {
+ u32_le slot;
+ Service::Nvidia::MultiFence multi_fence;
+ };
+
+ Data data;
+};
+
+class IGBPCancelBufferResponseParcel : public Parcel {
+protected:
+ void SerializeData() override {
+ Write<u32>(0); // Success
+ }
+};
+
class IGBPDequeueBufferRequestParcel : public Parcel {
public:
explicit IGBPDequeueBufferRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) {
Deserialize();
}
- ~IGBPDequeueBufferRequestParcel() override = default;
void DeserializeData() override {
- std::u16string token = ReadInterfaceToken();
+ [[maybe_unused]] const std::u16string token = ReadInterfaceToken();
data = Read<Data>();
}
@@ -333,7 +356,6 @@ class IGBPDequeueBufferResponseParcel : public Parcel {
public:
explicit IGBPDequeueBufferResponseParcel(u32 slot, Service::Nvidia::MultiFence& multi_fence)
: slot(slot), multi_fence(multi_fence) {}
- ~IGBPDequeueBufferResponseParcel() override = default;
protected:
void SerializeData() override {
@@ -352,10 +374,9 @@ public:
explicit IGBPRequestBufferRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) {
Deserialize();
}
- ~IGBPRequestBufferRequestParcel() override = default;
void DeserializeData() override {
- std::u16string token = ReadInterfaceToken();
+ [[maybe_unused]] const std::u16string token = ReadInterfaceToken();
slot = Read<u32_le>();
}
@@ -384,10 +405,9 @@ public:
explicit IGBPQueueBufferRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) {
Deserialize();
}
- ~IGBPQueueBufferRequestParcel() override = default;
void DeserializeData() override {
- std::u16string token = ReadInterfaceToken();
+ [[maybe_unused]] const std::u16string token = ReadInterfaceToken();
data = Read<Data>();
}
@@ -447,10 +467,9 @@ public:
explicit IGBPQueryRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) {
Deserialize();
}
- ~IGBPQueryRequestParcel() override = default;
void DeserializeData() override {
- std::u16string token = ReadInterfaceToken();
+ [[maybe_unused]] const std::u16string token = ReadInterfaceToken();
type = Read<u32_le>();
}
@@ -596,7 +615,12 @@ private:
break;
}
case TransactionId::CancelBuffer: {
- LOG_CRITICAL(Service_VI, "(STUBBED) called, transaction=CancelBuffer");
+ IGBPCancelBufferRequestParcel request{ctx.ReadBuffer()};
+
+ buffer_queue.CancelBuffer(request.data.slot, request.data.multi_fence);
+
+ IGBPCancelBufferResponseParcel response{};
+ ctx.WriteBuffer(response.Serialize());
break;
}
case TransactionId::Disconnect: {
diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt
index c84685214..7b39a38c1 100644
--- a/src/input_common/CMakeLists.txt
+++ b/src/input_common/CMakeLists.txt
@@ -29,6 +29,35 @@ add_library(input_common STATIC
udp/udp.h
)
+if (MSVC)
+ target_compile_options(input_common PRIVATE
+ # 'expression' : signed/unsigned mismatch
+ /we4018
+ # 'argument' : conversion from 'type1' to 'type2', possible loss of data (floating-point)
+ /we4244
+ # 'conversion' : conversion from 'type1' to 'type2', signed/unsigned mismatch
+ /we4245
+ # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
+ /we4254
+ # 'var' : conversion from 'size_t' to 'type', possible loss of data
+ /we4267
+ # 'context' : truncation from 'type1' to 'type2'
+ /we4305
+ )
+else()
+ target_compile_options(input_common PRIVATE
+ -Werror=conversion
+ -Werror=ignored-qualifiers
+ -Werror=implicit-fallthrough
+ -Werror=reorder
+ -Werror=shadow
+ -Werror=sign-compare
+ -Werror=unused-but-set-parameter
+ -Werror=unused-but-set-variable
+ -Werror=unused-variable
+ )
+endif()
+
if(SDL2_FOUND)
target_sources(input_common PRIVATE
sdl/sdl_impl.cpp
diff --git a/src/input_common/analog_from_button.cpp b/src/input_common/analog_from_button.cpp
index 6cabdaa3c..74744d7f3 100755
--- a/src/input_common/analog_from_button.cpp
+++ b/src/input_common/analog_from_button.cpp
@@ -20,18 +20,22 @@ public:
constexpr float SQRT_HALF = 0.707106781f;
int x = 0, y = 0;
- if (right->GetStatus())
+ if (right->GetStatus()) {
++x;
- if (left->GetStatus())
+ }
+ if (left->GetStatus()) {
--x;
- if (up->GetStatus())
+ }
+ if (up->GetStatus()) {
++y;
- if (down->GetStatus())
+ }
+ if (down->GetStatus()) {
--y;
+ }
- float coef = modifier->GetStatus() ? modifier_scale : 1.0f;
- return std::make_tuple(x * coef * (y == 0 ? 1.0f : SQRT_HALF),
- y * coef * (x == 0 ? 1.0f : SQRT_HALF));
+ const float coef = modifier->GetStatus() ? modifier_scale : 1.0f;
+ return std::make_tuple(static_cast<float>(x) * coef * (y == 0 ? 1.0f : SQRT_HALF),
+ static_cast<float>(y) * coef * (x == 0 ? 1.0f : SQRT_HALF));
}
bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override {
diff --git a/src/input_common/gcadapter/gc_adapter.cpp b/src/input_common/gcadapter/gc_adapter.cpp
index 89c148aba..c95feb0d7 100644
--- a/src/input_common/gcadapter/gc_adapter.cpp
+++ b/src/input_common/gcadapter/gc_adapter.cpp
@@ -21,7 +21,7 @@
namespace GCAdapter {
-/// Used to loop through and assign button in poller
+// Used to loop through and assign button in poller
constexpr std::array<PadButton, 12> PadButtonArray{
PadButton::PAD_BUTTON_LEFT, PadButton::PAD_BUTTON_RIGHT, PadButton::PAD_BUTTON_DOWN,
PadButton::PAD_BUTTON_UP, PadButton::PAD_TRIGGER_Z, PadButton::PAD_TRIGGER_R,
@@ -29,6 +29,18 @@ constexpr std::array<PadButton, 12> PadButtonArray{
PadButton::PAD_BUTTON_X, PadButton::PAD_BUTTON_Y, PadButton::PAD_BUTTON_START,
};
+static void PadToState(const GCPadStatus& pad, GCState& out_state) {
+ for (const auto& button : PadButtonArray) {
+ const auto button_key = static_cast<u16>(button);
+ const auto button_value = (pad.button & button_key) != 0;
+ out_state.buttons.insert_or_assign(static_cast<s32>(button_key), button_value);
+ }
+
+ for (std::size_t i = 0; i < pad.axis_values.size(); ++i) {
+ out_state.axes.insert_or_assign(static_cast<u32>(i), pad.axis_values[i]);
+ }
+}
+
Adapter::Adapter() {
if (usb_adapter_handle != nullptr) {
return;
@@ -78,17 +90,17 @@ GCPadStatus Adapter::GetPadStatus(std::size_t port, const std::array<u8, 37>& ad
for (std::size_t i = 0; i < b1_buttons.size(); ++i) {
if ((b1 & (1U << i)) != 0) {
- pad.button |= static_cast<u16>(b1_buttons[i]);
+ pad.button = static_cast<u16>(pad.button | static_cast<u16>(b1_buttons[i]));
}
}
for (std::size_t j = 0; j < b2_buttons.size(); ++j) {
if ((b2 & (1U << j)) != 0) {
- pad.button |= static_cast<u16>(b2_buttons[j]);
+ pad.button = static_cast<u16>(pad.button | static_cast<u16>(b2_buttons[j]));
}
}
for (PadAxes axis : axes) {
- const std::size_t index = static_cast<std::size_t>(axis);
+ const auto index = static_cast<std::size_t>(axis);
pad.axis_values[index] = adapter_payload[offset + 3 + index];
}
@@ -100,17 +112,6 @@ GCPadStatus Adapter::GetPadStatus(std::size_t port, const std::array<u8, 37>& ad
return pad;
}
-void Adapter::PadToState(const GCPadStatus& pad, GCState& state) {
- for (const auto& button : PadButtonArray) {
- const u16 button_value = static_cast<u16>(button);
- state.buttons.insert_or_assign(button_value, pad.button & button_value);
- }
-
- for (size_t i = 0; i < pad.axis_values.size(); ++i) {
- state.axes.insert_or_assign(static_cast<u8>(i), pad.axis_values[i]);
- }
-}
-
void Adapter::Read() {
LOG_DEBUG(Input, "GC Adapter Read() thread started");
@@ -250,7 +251,7 @@ void Adapter::GetGCEndpoint(libusb_device* device) {
const libusb_interface_descriptor* interface = &interfaceContainer->altsetting[i];
for (u8 e = 0; e < interface->bNumEndpoints; e++) {
const libusb_endpoint_descriptor* endpoint = &interface->endpoint[e];
- if (endpoint->bEndpointAddress & LIBUSB_ENDPOINT_IN) {
+ if ((endpoint->bEndpointAddress & LIBUSB_ENDPOINT_IN) != 0) {
input_endpoint = endpoint->bEndpointAddress;
} else {
output_endpoint = endpoint->bEndpointAddress;
@@ -419,7 +420,7 @@ const std::array<GCState, 4>& Adapter::GetPadState() const {
return state;
}
-int Adapter::GetOriginValue(int port, int axis) const {
+int Adapter::GetOriginValue(u32 port, u32 axis) const {
return origin_status[port].axis_values[axis];
}
diff --git a/src/input_common/gcadapter/gc_adapter.h b/src/input_common/gcadapter/gc_adapter.h
index 75bf9fe74..4f5f3de8e 100644
--- a/src/input_common/gcadapter/gc_adapter.h
+++ b/src/input_common/gcadapter/gc_adapter.h
@@ -60,7 +60,7 @@ struct GCPadStatus {
struct GCState {
std::unordered_map<int, bool> buttons;
- std::unordered_map<int, u16> axes;
+ std::unordered_map<u32, u16> axes;
};
enum class ControllerTypes { None, Wired, Wireless };
@@ -89,13 +89,11 @@ public:
std::array<GCState, 4>& GetPadState();
const std::array<GCState, 4>& GetPadState() const;
- int GetOriginValue(int port, int axis) const;
+ int GetOriginValue(u32 port, u32 axis) const;
private:
GCPadStatus GetPadStatus(std::size_t port, const std::array<u8, 37>& adapter_payload);
- void PadToState(const GCPadStatus& pad, GCState& state);
-
void Read();
/// Resets status of device connected to port
diff --git a/src/input_common/gcadapter/gc_poller.cpp b/src/input_common/gcadapter/gc_poller.cpp
index 92e9e8e89..893556916 100644
--- a/src/input_common/gcadapter/gc_poller.cpp
+++ b/src/input_common/gcadapter/gc_poller.cpp
@@ -15,7 +15,7 @@ namespace InputCommon {
class GCButton final : public Input::ButtonDevice {
public:
- explicit GCButton(int port_, int button_, const GCAdapter::Adapter* adapter)
+ explicit GCButton(u32 port_, int button_, const GCAdapter::Adapter* adapter)
: port(port_), button(button_), gcadapter(adapter) {}
~GCButton() override;
@@ -28,14 +28,14 @@ public:
}
private:
- const int port;
+ const u32 port;
const int button;
const GCAdapter::Adapter* gcadapter;
};
class GCAxisButton final : public Input::ButtonDevice {
public:
- explicit GCAxisButton(int port_, int axis_, float threshold_, bool trigger_if_greater_,
+ explicit GCAxisButton(u32 port_, u32 axis_, float threshold_, bool trigger_if_greater_,
const GCAdapter::Adapter* adapter)
: port(port_), axis(axis_), threshold(threshold_), trigger_if_greater(trigger_if_greater_),
gcadapter(adapter),
@@ -56,8 +56,8 @@ public:
}
private:
- const int port;
- const int axis;
+ const u32 port;
+ const u32 axis;
float threshold;
bool trigger_if_greater;
const GCAdapter::Adapter* gcadapter;
@@ -70,8 +70,8 @@ GCButtonFactory::GCButtonFactory(std::shared_ptr<GCAdapter::Adapter> adapter_)
GCButton::~GCButton() = default;
std::unique_ptr<Input::ButtonDevice> GCButtonFactory::Create(const Common::ParamPackage& params) {
- const int button_id = params.Get("button", 0);
- const int port = params.Get("port", 0);
+ const auto button_id = params.Get("button", 0);
+ const auto port = static_cast<u32>(params.Get("port", 0));
constexpr int PAD_STICK_ID = static_cast<u16>(GCAdapter::PadButton::PAD_STICK);
@@ -149,25 +149,27 @@ void GCButtonFactory::EndConfiguration() {
class GCAnalog final : public Input::AnalogDevice {
public:
- GCAnalog(int port_, int axis_x_, int axis_y_, float deadzone_,
- const GCAdapter::Adapter* adapter, float range_)
+ explicit GCAnalog(u32 port_, u32 axis_x_, u32 axis_y_, float deadzone_,
+ const GCAdapter::Adapter* adapter, float range_)
: port(port_), axis_x(axis_x_), axis_y(axis_y_), deadzone(deadzone_), gcadapter(adapter),
origin_value_x(static_cast<float>(adapter->GetOriginValue(port_, axis_x_))),
origin_value_y(static_cast<float>(adapter->GetOriginValue(port_, axis_y_))),
range(range_) {}
- float GetAxis(int axis) const {
+ float GetAxis(u32 axis) const {
if (gcadapter->DeviceConnected(port)) {
std::lock_guard lock{mutex};
const auto origin_value = axis % 2 == 0 ? origin_value_x : origin_value_y;
- return (gcadapter->GetPadState()[port].axes.at(axis) - origin_value) / (100.0f * range);
+ const auto axis_value =
+ static_cast<float>(gcadapter->GetPadState()[port].axes.at(axis));
+ return (axis_value - origin_value) / (100.0f * range);
}
return 0.0f;
}
- std::pair<float, float> GetAnalog(int axis_x, int axis_y) const {
- float x = GetAxis(axis_x);
- float y = GetAxis(axis_y);
+ std::pair<float, float> GetAnalog(u32 analog_axis_x, u32 analog_axis_y) const {
+ float x = GetAxis(analog_axis_x);
+ float y = GetAxis(analog_axis_y);
// Make sure the coordinates are in the unit circle,
// otherwise normalize it.
@@ -208,9 +210,9 @@ public:
}
private:
- const int port;
- const int axis_x;
- const int axis_y;
+ const u32 port;
+ const u32 axis_x;
+ const u32 axis_y;
const float deadzone;
const GCAdapter::Adapter* gcadapter;
const float origin_value_x;
@@ -231,11 +233,11 @@ GCAnalogFactory::GCAnalogFactory(std::shared_ptr<GCAdapter::Adapter> adapter_)
* - "axis_y": the index of the axis to be bind as y-axis
*/
std::unique_ptr<Input::AnalogDevice> GCAnalogFactory::Create(const Common::ParamPackage& params) {
- const int port = params.Get("port", 0);
- const int axis_x = params.Get("axis_x", 0);
- const int axis_y = params.Get("axis_y", 1);
- const float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f);
- const float range = std::clamp(params.Get("range", 1.0f), 0.50f, 1.50f);
+ const auto port = static_cast<u32>(params.Get("port", 0));
+ const auto axis_x = static_cast<u32>(params.Get("axis_x", 0));
+ const auto axis_y = static_cast<u32>(params.Get("axis_y", 1));
+ const auto deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f);
+ const auto range = std::clamp(params.Get("range", 1.0f), 0.50f, 1.50f);
return std::make_unique<GCAnalog>(port, axis_x, axis_y, deadzone, adapter.get(), range);
}
@@ -256,7 +258,7 @@ Common::ParamPackage GCAnalogFactory::GetNextInput() {
for (std::size_t port = 0; port < queue.size(); ++port) {
while (queue[port].Pop(pad)) {
if (pad.axis == GCAdapter::PadAxes::Undefined ||
- std::abs((pad.axis_value - 128.0f) / 128.0f) < 0.1) {
+ std::abs((static_cast<float>(pad.axis_value) - 128.0f) / 128.0f) < 0.1f) {
continue;
}
// An analog device needs two axes, so we need to store the axis for later and wait for
diff --git a/src/input_common/keyboard.cpp b/src/input_common/keyboard.cpp
index afb8e6612..24a6f7a33 100644
--- a/src/input_common/keyboard.cpp
+++ b/src/input_common/keyboard.cpp
@@ -49,8 +49,9 @@ public:
void ChangeKeyStatus(int key_code, bool pressed) {
std::lock_guard guard{mutex};
for (const KeyButtonPair& pair : list) {
- if (pair.key_code == key_code)
+ if (pair.key_code == key_code) {
pair.key_button->status.store(pressed);
+ }
}
}
@@ -73,7 +74,7 @@ KeyButton::~KeyButton() {
}
std::unique_ptr<Input::ButtonDevice> Keyboard::Create(const Common::ParamPackage& params) {
- int key_code = params.Get("code", 0);
+ const int key_code = params.Get("code", 0);
std::unique_ptr<KeyButton> button = std::make_unique<KeyButton>(key_button_list);
key_button_list->AddKeyButton(key_code, button.get());
return button;
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp
index 3d97d95f7..d32fd8b81 100644
--- a/src/input_common/main.cpp
+++ b/src/input_common/main.cpp
@@ -196,6 +196,10 @@ ButtonMapping InputSubsystem::GetButtonMappingForDevice(const Common::ParamPacka
return impl->GetButtonMappingForDevice(device);
}
+MotionMapping InputSubsystem::GetMotionMappingForDevice(const Common::ParamPackage& device) const {
+ return impl->GetMotionMappingForDevice(device);
+}
+
GCAnalogFactory* InputSubsystem::GetGCAnalogs() {
return impl->gcanalog.get();
}
diff --git a/src/input_common/motion_emu.cpp b/src/input_common/motion_emu.cpp
index 69fd3c1d2..d4da5596b 100644
--- a/src/input_common/motion_emu.cpp
+++ b/src/input_common/motion_emu.cpp
@@ -18,11 +18,11 @@ namespace InputCommon {
// Implementation class of the motion emulation device
class MotionEmuDevice {
public:
- MotionEmuDevice(int update_millisecond, float sensitivity)
- : update_millisecond(update_millisecond),
+ explicit MotionEmuDevice(int update_millisecond_, float sensitivity_)
+ : update_millisecond(update_millisecond_),
update_duration(std::chrono::duration_cast<std::chrono::steady_clock::duration>(
std::chrono::milliseconds(update_millisecond))),
- sensitivity(sensitivity), motion_emu_thread(&MotionEmuDevice::MotionEmuThread, this) {}
+ sensitivity(sensitivity_), motion_emu_thread(&MotionEmuDevice::MotionEmuThread, this) {}
~MotionEmuDevice() {
if (motion_emu_thread.joinable()) {
@@ -37,16 +37,18 @@ public:
}
void Tilt(int x, int y) {
- auto mouse_move = Common::MakeVec(x, y) - mouse_origin;
- if (is_tilting) {
- std::lock_guard guard{tilt_mutex};
- if (mouse_move.x == 0 && mouse_move.y == 0) {
- tilt_angle = 0;
- } else {
- tilt_direction = mouse_move.Cast<float>();
- tilt_angle =
- std::clamp(tilt_direction.Normalize() * sensitivity, 0.0f, Common::PI * 0.5f);
- }
+ if (!is_tilting) {
+ return;
+ }
+
+ std::lock_guard guard{tilt_mutex};
+ const auto mouse_move = Common::MakeVec(x, y) - mouse_origin;
+ if (mouse_move.x == 0 && mouse_move.y == 0) {
+ tilt_angle = 0;
+ } else {
+ tilt_direction = mouse_move.Cast<float>();
+ tilt_angle =
+ std::clamp(tilt_direction.Normalize() * sensitivity, 0.0f, Common::PI * 0.5f);
}
}
@@ -86,11 +88,10 @@ private:
void MotionEmuThread() {
auto update_time = std::chrono::steady_clock::now();
Common::Quaternion<float> q = Common::MakeQuaternion(Common::Vec3<float>(), 0);
- Common::Quaternion<float> old_q;
while (!shutdown_event.WaitUntil(update_time)) {
update_time += update_duration;
- old_q = q;
+ const Common::Quaternion<float> old_q = q;
{
std::lock_guard guard{tilt_mutex};
@@ -100,14 +101,14 @@ private:
Common::MakeVec(-tilt_direction.y, 0.0f, tilt_direction.x), tilt_angle);
}
- auto inv_q = q.Inverse();
+ const auto inv_q = q.Inverse();
// Set the gravity vector in world space
auto gravity = Common::MakeVec(0.0f, -1.0f, 0.0f);
// Find the angular rate vector in world space
auto angular_rate = ((q - old_q) * inv_q).xyz * 2;
- angular_rate *= 1000 / update_millisecond / Common::PI * 180;
+ angular_rate *= static_cast<float>(1000 / update_millisecond) / Common::PI * 180.0f;
// Transform the two vectors from world space to 3DS space
gravity = QuaternionRotate(inv_q, gravity);
@@ -136,7 +137,7 @@ private:
// can forward all the inputs to the implementation only when it is valid.
class MotionEmuDeviceWrapper : public Input::MotionDevice {
public:
- MotionEmuDeviceWrapper(int update_millisecond, float sensitivity) {
+ explicit MotionEmuDeviceWrapper(int update_millisecond, float sensitivity) {
device = std::make_shared<MotionEmuDevice>(update_millisecond, sensitivity);
}
@@ -148,8 +149,8 @@ public:
};
std::unique_ptr<Input::MotionDevice> MotionEmu::Create(const Common::ParamPackage& params) {
- int update_period = params.Get("update_period", 100);
- float sensitivity = params.Get("sensitivity", 0.01f);
+ const int update_period = params.Get("update_period", 100);
+ const float sensitivity = params.Get("sensitivity", 0.01f);
auto device_wrapper = std::make_unique<MotionEmuDeviceWrapper>(update_period, sensitivity);
// Previously created device is disconnected here. Having two motion devices for 3DS is not
// expected.
diff --git a/src/input_common/motion_from_button.cpp b/src/input_common/motion_from_button.cpp
index 9d459f963..29045a673 100644
--- a/src/input_common/motion_from_button.cpp
+++ b/src/input_common/motion_from_button.cpp
@@ -11,7 +11,7 @@ class MotionKey final : public Input::MotionDevice {
public:
using Button = std::unique_ptr<Input::ButtonDevice>;
- MotionKey(Button key_) : key(std::move(key_)) {}
+ explicit MotionKey(Button key_) : key(std::move(key_)) {}
Input::MotionStatus GetStatus() const override {
diff --git a/src/input_common/motion_input.cpp b/src/input_common/motion_input.cpp
index e89019723..f77ba535d 100644
--- a/src/input_common/motion_input.cpp
+++ b/src/input_common/motion_input.cpp
@@ -8,8 +8,7 @@
namespace InputCommon {
-MotionInput::MotionInput(f32 new_kp, f32 new_ki, f32 new_kd)
- : kp(new_kp), ki(new_ki), kd(new_kd), quat{{0, 0, -1}, 0} {}
+MotionInput::MotionInput(f32 new_kp, f32 new_ki, f32 new_kd) : kp(new_kp), ki(new_ki), kd(new_kd) {}
void MotionInput::SetAcceleration(const Common::Vec3f& acceleration) {
accel = acceleration;
@@ -59,7 +58,7 @@ bool MotionInput::IsCalibrated(f32 sensitivity) const {
}
void MotionInput::UpdateRotation(u64 elapsed_time) {
- const f32 sample_period = elapsed_time / 1000000.0f;
+ const auto sample_period = static_cast<f32>(elapsed_time) / 1000000.0f;
if (sample_period > 0.1f) {
return;
}
@@ -75,7 +74,7 @@ void MotionInput::UpdateOrientation(u64 elapsed_time) {
f32 q2 = quat.xyz[0];
f32 q3 = quat.xyz[1];
f32 q4 = quat.xyz[2];
- const f32 sample_period = elapsed_time / 1000000.0f;
+ const auto sample_period = static_cast<f32>(elapsed_time) / 1000000.0f;
// Ignore invalid elapsed time
if (sample_period > 0.1f) {
@@ -203,21 +202,21 @@ Input::MotionStatus MotionInput::GetRandomMotion(int accel_magnitude, int gyro_m
std::random_device device;
std::mt19937 gen(device());
std::uniform_int_distribution<s16> distribution(-1000, 1000);
- const Common::Vec3f gyroscope = {
- distribution(gen) * 0.001f,
- distribution(gen) * 0.001f,
- distribution(gen) * 0.001f,
+ const Common::Vec3f gyroscope{
+ static_cast<f32>(distribution(gen)) * 0.001f,
+ static_cast<f32>(distribution(gen)) * 0.001f,
+ static_cast<f32>(distribution(gen)) * 0.001f,
};
- const Common::Vec3f accelerometer = {
- distribution(gen) * 0.001f,
- distribution(gen) * 0.001f,
- distribution(gen) * 0.001f,
+ const Common::Vec3f accelerometer{
+ static_cast<f32>(distribution(gen)) * 0.001f,
+ static_cast<f32>(distribution(gen)) * 0.001f,
+ static_cast<f32>(distribution(gen)) * 0.001f,
};
- const Common::Vec3f rotation = {};
- const std::array<Common::Vec3f, 3> orientation = {
- Common::Vec3f{1.0f, 0, 0},
- Common::Vec3f{0, 1.0f, 0},
- Common::Vec3f{0, 0, 1.0f},
+ constexpr Common::Vec3f rotation;
+ constexpr std::array orientation{
+ Common::Vec3f{1.0f, 0.0f, 0.0f},
+ Common::Vec3f{0.0f, 1.0f, 0.0f},
+ Common::Vec3f{0.0f, 0.0f, 1.0f},
};
return {accelerometer * accel_magnitude, gyroscope * gyro_magnitude, rotation, orientation};
}
@@ -247,9 +246,6 @@ void MotionInput::SetOrientationFromAccelerometer() {
const f32 sample_period = 0.015f;
const auto normal_accel = accel.Normalized();
- const f32 ax = -normal_accel.x;
- const f32 ay = normal_accel.y;
- const f32 az = -normal_accel.z;
while (!IsCalibrated(0.01f) && ++iterations < 100) {
// Short name local variable for readability
@@ -258,7 +254,7 @@ void MotionInput::SetOrientationFromAccelerometer() {
f32 q3 = quat.xyz[1];
f32 q4 = quat.xyz[2];
- Common::Vec3f rad_gyro = {};
+ Common::Vec3f rad_gyro;
const f32 ax = -normal_accel.x;
const f32 ay = normal_accel.y;
const f32 az = -normal_accel.z;
diff --git a/src/input_common/motion_input.h b/src/input_common/motion_input.h
index 6342d0318..abb957f04 100644
--- a/src/input_common/motion_input.h
+++ b/src/input_common/motion_input.h
@@ -22,7 +22,7 @@ public:
MotionInput& operator=(MotionInput&&) = default;
void SetAcceleration(const Common::Vec3f& acceleration);
- void SetGyroscope(const Common::Vec3f& acceleration);
+ void SetGyroscope(const Common::Vec3f& gyroscope);
void SetQuaternion(const Common::Quaternion<f32>& quaternion);
void SetGyroDrift(const Common::Vec3f& drift);
void SetGyroThreshold(f32 threshold);
@@ -49,16 +49,16 @@ private:
void SetOrientationFromAccelerometer();
// PID constants
- const f32 kp;
- const f32 ki;
- const f32 kd;
+ f32 kp;
+ f32 ki;
+ f32 kd;
// PID errors
Common::Vec3f real_error;
Common::Vec3f integral_error;
Common::Vec3f derivative_error;
- Common::Quaternion<f32> quat;
+ Common::Quaternion<f32> quat{{0.0f, 0.0f, -1.0f}, 0.0f};
Common::Vec3f rotations;
Common::Vec3f accel;
Common::Vec3f gyro;
diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp
index bd480570a..9c3035920 100644
--- a/src/input_common/sdl/sdl_impl.cpp
+++ b/src/input_common/sdl/sdl_impl.cpp
@@ -56,9 +56,9 @@ static int SDLEventWatcher(void* user_data, SDL_Event* event) {
class SDLJoystick {
public:
SDLJoystick(std::string guid_, int port_, SDL_Joystick* joystick,
- SDL_GameController* gamecontroller)
+ SDL_GameController* game_controller)
: guid{std::move(guid_)}, port{port_}, sdl_joystick{joystick, &SDL_JoystickClose},
- sdl_controller{gamecontroller, &SDL_GameControllerClose} {}
+ sdl_controller{game_controller, &SDL_GameControllerClose} {}
void SetButton(int button, bool value) {
std::lock_guard lock{mutex};
@@ -77,10 +77,10 @@ public:
float GetAxis(int axis, float range) const {
std::lock_guard lock{mutex};
- return state.axes.at(axis) / (32767.0f * range);
+ return static_cast<float>(state.axes.at(axis)) / (32767.0f * range);
}
- bool RumblePlay(f32 amp_low, f32 amp_high, int time) {
+ bool RumblePlay(f32 amp_low, f32 amp_high, u32 time) {
const u16 raw_amp_low = static_cast<u16>(amp_low * 0xFFFF);
const u16 raw_amp_high = static_cast<u16>(amp_high * 0xFFFF);
// Lower drastically the number of state changes
@@ -124,7 +124,7 @@ public:
return std::make_tuple(x, y);
}
- const InputCommon::MotionInput& GetMotion() const {
+ const MotionInput& GetMotion() const {
return motion;
}
@@ -172,15 +172,15 @@ private:
} state;
std::string guid;
int port;
- u16 last_state_rumble_high;
- u16 last_state_rumble_low;
+ u16 last_state_rumble_high = 0;
+ u16 last_state_rumble_low = 0;
std::chrono::time_point<std::chrono::system_clock> last_vibration;
std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick;
std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller;
mutable std::mutex mutex;
- // motion is initalized without PID values as motion input is not aviable for SDL2
- InputCommon::MotionInput motion{0.0f, 0.0f, 0.0f};
+ // Motion is initialized without PID values as motion input is not aviable for SDL2
+ MotionInput motion{0.0f, 0.0f, 0.0f};
};
std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickByGUID(const std::string& guid, int port) {
@@ -192,7 +192,7 @@ std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickByGUID(const std::string& g
nullptr, nullptr);
it->second.emplace_back(std::move(joystick));
}
- return it->second[port];
+ return it->second[static_cast<std::size_t>(port)];
}
auto joystick = std::make_shared<SDLJoystick>(guid, 0, nullptr, nullptr);
return joystick_map[guid].emplace_back(std::move(joystick));
@@ -212,7 +212,7 @@ std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickBySDLID(SDL_JoystickID sdl_
return sdl_joystick == joystick->GetSDLJoystick();
});
if (vec_it != map_it->second.end()) {
- // This is the common case: There is already an existing SDL_Joystick maped to a
+ // This is the common case: There is already an existing SDL_Joystick mapped to a
// SDLJoystick. return the SDLJoystick
return *vec_it;
}
@@ -220,7 +220,7 @@ std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickBySDLID(SDL_JoystickID sdl_
// Search for a SDLJoystick without a mapped SDL_Joystick...
const auto nullptr_it = std::find_if(map_it->second.begin(), map_it->second.end(),
[](const std::shared_ptr<SDLJoystick>& joystick) {
- return !joystick->GetSDLJoystick();
+ return joystick->GetSDLJoystick() == nullptr;
});
if (nullptr_it != map_it->second.end()) {
// ... and map it
@@ -273,22 +273,19 @@ void SDLState::InitJoystick(int joystick_index) {
void SDLState::CloseJoystick(SDL_Joystick* sdl_joystick) {
const std::string guid = GetGUID(sdl_joystick);
- std::shared_ptr<SDLJoystick> joystick;
- {
- std::lock_guard lock{joystick_map_mutex};
- // This call to guid is safe since the joystick is guaranteed to be in the map
- const auto& joystick_guid_list = joystick_map[guid];
- const auto joystick_it =
- std::find_if(joystick_guid_list.begin(), joystick_guid_list.end(),
- [&sdl_joystick](const std::shared_ptr<SDLJoystick>& joystick) {
- return joystick->GetSDLJoystick() == sdl_joystick;
- });
- joystick = *joystick_it;
- }
+ std::lock_guard lock{joystick_map_mutex};
+ auto& joystick_guid_list = joystick_map[guid];
+ auto joystick_it = std::find_if(
+ joystick_guid_list.begin(), joystick_guid_list.end(),
+ [&sdl_joystick](auto& joystick) { return joystick->GetSDLJoystick() == sdl_joystick; });
- // Destruct SDL_Joystick outside the lock guard because SDL can internally call the
- // event callback which locks the mutex again.
- joystick->SetSDLJoystick(nullptr, nullptr);
+ if (joystick_it != joystick_guid_list.end()) {
+ (*joystick_it)->SetSDLJoystick(nullptr, nullptr);
+ joystick_guid_list.erase(joystick_it);
+ if (joystick_guid_list.empty()) {
+ joystick_map.erase(guid);
+ }
+ }
}
void SDLState::HandleGameControllerEvent(const SDL_Event& event) {
@@ -392,8 +389,8 @@ private:
class SDLAnalog final : public Input::AnalogDevice {
public:
- SDLAnalog(std::shared_ptr<SDLJoystick> joystick_, int axis_x_, int axis_y_, float deadzone_,
- float range_)
+ explicit SDLAnalog(std::shared_ptr<SDLJoystick> joystick_, int axis_x_, int axis_y_,
+ float deadzone_, float range_)
: joystick(std::move(joystick_)), axis_x(axis_x_), axis_y(axis_y_), deadzone(deadzone_),
range(range_) {}
@@ -672,13 +669,13 @@ SDLState::SDLState() {
RegisterFactory<ButtonDevice>("sdl", button_factory);
RegisterFactory<MotionDevice>("sdl", motion_factory);
- // If the frontend is going to manage the event loop, then we dont start one here
- start_thread = !SDL_WasInit(SDL_INIT_JOYSTICK);
+ // If the frontend is going to manage the event loop, then we don't start one here
+ start_thread = SDL_WasInit(SDL_INIT_JOYSTICK) == 0;
if (start_thread && SDL_Init(SDL_INIT_JOYSTICK) < 0) {
LOG_CRITICAL(Input, "SDL_Init(SDL_INIT_JOYSTICK) failed with: {}", SDL_GetError());
return;
}
- has_gamecontroller = SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER);
+ has_gamecontroller = SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) != 0;
if (SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1") == SDL_FALSE) {
LOG_ERROR(Input, "Failed to set hint for background events with: {}", SDL_GetError());
}
@@ -723,8 +720,8 @@ std::vector<Common::ParamPackage> SDLState::GetInputDevices() {
std::vector<Common::ParamPackage> devices;
for (const auto& [key, value] : joystick_map) {
for (const auto& joystick : value) {
- auto joy = joystick->GetSDLJoystick();
- if (auto controller = joystick->GetSDLGameController()) {
+ auto* joy = joystick->GetSDLJoystick();
+ if (auto* controller = joystick->GetSDLGameController()) {
std::string name =
fmt::format("{} {}", SDL_GameControllerName(controller), joystick->GetPort());
devices.emplace_back(Common::ParamPackage{
@@ -748,7 +745,7 @@ std::vector<Common::ParamPackage> SDLState::GetInputDevices() {
}
namespace {
-Common::ParamPackage BuildAnalogParamPackageForButton(int port, std::string guid, u8 axis,
+Common::ParamPackage BuildAnalogParamPackageForButton(int port, std::string guid, s32 axis,
float value = 0.1f) {
Common::ParamPackage params({{"engine", "sdl"}});
params.Set("port", port);
@@ -764,7 +761,7 @@ Common::ParamPackage BuildAnalogParamPackageForButton(int port, std::string guid
return params;
}
-Common::ParamPackage BuildButtonParamPackageForButton(int port, std::string guid, u8 button) {
+Common::ParamPackage BuildButtonParamPackageForButton(int port, std::string guid, s32 button) {
Common::ParamPackage params({{"engine", "sdl"}});
params.Set("port", port);
params.Set("guid", std::move(guid));
@@ -772,7 +769,7 @@ Common::ParamPackage BuildButtonParamPackageForButton(int port, std::string guid
return params;
}
-Common::ParamPackage BuildHatParamPackageForButton(int port, std::string guid, u8 hat, u8 value) {
+Common::ParamPackage BuildHatParamPackageForButton(int port, std::string guid, s32 hat, s32 value) {
Common::ParamPackage params({{"engine", "sdl"}});
params.Set("port", port);
@@ -802,17 +799,19 @@ Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Eve
case SDL_JOYAXISMOTION: {
const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which);
return BuildAnalogParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
- event.jaxis.axis, event.jaxis.value);
+ static_cast<s32>(event.jaxis.axis),
+ event.jaxis.value);
}
case SDL_JOYBUTTONUP: {
const auto joystick = state.GetSDLJoystickBySDLID(event.jbutton.which);
return BuildButtonParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
- event.jbutton.button);
+ static_cast<s32>(event.jbutton.button));
}
case SDL_JOYHATMOTION: {
const auto joystick = state.GetSDLJoystickBySDLID(event.jhat.which);
return BuildHatParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
- event.jhat.hat, event.jhat.value);
+ static_cast<s32>(event.jhat.hat),
+ static_cast<s32>(event.jhat.value));
}
}
return {};
@@ -823,17 +822,19 @@ Common::ParamPackage SDLEventToMotionParamPackage(SDLState& state, const SDL_Eve
case SDL_JOYAXISMOTION: {
const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which);
return BuildAnalogParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
- event.jaxis.axis, event.jaxis.value);
+ static_cast<s32>(event.jaxis.axis),
+ event.jaxis.value);
}
case SDL_JOYBUTTONUP: {
const auto joystick = state.GetSDLJoystickBySDLID(event.jbutton.which);
return BuildButtonParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
- event.jbutton.button);
+ static_cast<s32>(event.jbutton.button));
}
case SDL_JOYHATMOTION: {
const auto joystick = state.GetSDLJoystickBySDLID(event.jhat.which);
return BuildHatParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
- event.jhat.hat, event.jhat.value);
+ static_cast<s32>(event.jhat.hat),
+ static_cast<s32>(event.jhat.value));
}
}
return {};
@@ -1062,7 +1063,7 @@ public:
if (event.type == SDL_JOYAXISMOTION) {
const auto axis = event.jaxis.axis;
const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which);
- const auto controller = joystick->GetSDLGameController();
+ auto* const controller = joystick->GetSDLGameController();
if (controller) {
const auto axis_left_x =
SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTX)
diff --git a/src/input_common/settings.h b/src/input_common/settings.h
index ab0b95cf1..f52d28540 100644
--- a/src/input_common/settings.h
+++ b/src/input_common/settings.h
@@ -331,8 +331,6 @@ struct PlayerInput {
ButtonsRaw buttons;
AnalogsRaw analogs;
MotionRaw motions;
- std::string lstick_mod;
- std::string rstick_mod;
u32 body_color_left;
u32 body_color_right;
diff --git a/src/input_common/touch_from_button.cpp b/src/input_common/touch_from_button.cpp
index 98da0ef1a..c37716aae 100644
--- a/src/input_common/touch_from_button.cpp
+++ b/src/input_common/touch_from_button.cpp
@@ -11,9 +11,11 @@ namespace InputCommon {
class TouchFromButtonDevice final : public Input::TouchDevice {
public:
TouchFromButtonDevice() {
- for (const auto& config_entry :
- Settings::values.touch_from_button_maps[Settings::values.touch_from_button_map_index]
- .buttons) {
+ const auto button_index =
+ static_cast<std::size_t>(Settings::values.touch_from_button_map_index);
+ const auto& buttons = Settings::values.touch_from_button_maps[button_index].buttons;
+
+ for (const auto& config_entry : buttons) {
const Common::ParamPackage package{config_entry};
map.emplace_back(
Input::CreateDevice<Input::ButtonDevice>(config_entry),
diff --git a/src/input_common/udp/client.cpp b/src/input_common/udp/client.cpp
index 9d0b9f31d..7039d6fc3 100644
--- a/src/input_common/udp/client.cpp
+++ b/src/input_common/udp/client.cpp
@@ -26,11 +26,11 @@ class Socket {
public:
using clock = std::chrono::system_clock;
- explicit Socket(const std::string& host, u16 port, u8 pad_index, u32 client_id,
- SocketCallback callback)
- : callback(std::move(callback)), timer(io_service),
- socket(io_service, udp::endpoint(udp::v4(), 0)), client_id(client_id),
- pad_index(pad_index) {
+ explicit Socket(const std::string& host, u16 port, std::size_t pad_index_, u32 client_id_,
+ SocketCallback callback_)
+ : callback(std::move(callback_)), timer(io_service),
+ socket(io_service, udp::endpoint(udp::v4(), 0)), client_id(client_id_),
+ pad_index(pad_index_) {
boost::system::error_code ec{};
auto ipv4 = boost::asio::ip::make_address_v4(host, ec);
if (ec.value() != boost::system::errc::success) {
@@ -93,13 +93,17 @@ private:
void HandleSend(const boost::system::error_code& error) {
boost::system::error_code _ignored{};
// Send a request for getting port info for the pad
- Request::PortInfo port_info{1, {pad_index, 0, 0, 0}};
+ const Request::PortInfo port_info{1, {static_cast<u8>(pad_index), 0, 0, 0}};
const auto port_message = Request::Create(port_info, client_id);
std::memcpy(&send_buffer1, &port_message, PORT_INFO_SIZE);
socket.send_to(boost::asio::buffer(send_buffer1), send_endpoint, {}, _ignored);
// Send a request for getting pad data for the pad
- Request::PadData pad_data{Request::PadData::Flags::Id, pad_index, EMPTY_MAC_ADDRESS};
+ const Request::PadData pad_data{
+ Request::PadData::Flags::Id,
+ static_cast<u8>(pad_index),
+ EMPTY_MAC_ADDRESS,
+ };
const auto pad_message = Request::Create(pad_data, client_id);
std::memcpy(send_buffer2.data(), &pad_message, PAD_DATA_SIZE);
socket.send_to(boost::asio::buffer(send_buffer2), send_endpoint, {}, _ignored);
@@ -112,7 +116,7 @@ private:
udp::socket socket;
u32 client_id{};
- u8 pad_index{};
+ std::size_t pad_index{};
static constexpr std::size_t PORT_INFO_SIZE = sizeof(Message<Request::PortInfo>);
static constexpr std::size_t PAD_DATA_SIZE = sizeof(Message<Request::PadData>);
@@ -133,7 +137,7 @@ static void SocketLoop(Socket* socket) {
Client::Client() {
LOG_INFO(Input, "Udp Initialization started");
for (std::size_t client = 0; client < clients.size(); client++) {
- u8 pad = client % 4;
+ const auto pad = client % 4;
StartCommunication(client, Settings::values.udp_input_address,
Settings::values.udp_input_port, pad, 24872);
// Set motion parameters
@@ -166,9 +170,9 @@ std::vector<Common::ParamPackage> Client::GetInputDevices() const {
bool Client::DeviceConnected(std::size_t pad) const {
// Use last timestamp to detect if the socket has stopped sending data
const auto now = std::chrono::system_clock::now();
- u64 time_difference =
+ const auto time_difference = static_cast<u64>(
std::chrono::duration_cast<std::chrono::milliseconds>(now - clients[pad].last_motion_update)
- .count();
+ .count());
return time_difference < 1000 && clients[pad].active == 1;
}
@@ -177,9 +181,9 @@ void Client::ReloadUDPClient() {
ReloadSocket(Settings::values.udp_input_address, Settings::values.udp_input_port, client);
}
}
-void Client::ReloadSocket(const std::string& host, u16 port, u8 pad_index, u32 client_id) {
+void Client::ReloadSocket(const std::string& host, u16 port, std::size_t pad_index, u32 client_id) {
// client number must be determined from host / port and pad index
- std::size_t client = pad_index;
+ const std::size_t client = pad_index;
clients[client].socket->Stop();
clients[client].thread.join();
StartCommunication(client, host, port, pad_index, client_id);
@@ -194,8 +198,8 @@ void Client::OnPortInfo(Response::PortInfo data) {
}
void Client::OnPadData(Response::PadData data) {
- // client number must be determined from host / port and pad index
- std::size_t client = data.info.id;
+ // Client number must be determined from host / port and pad index
+ const std::size_t client = data.info.id;
LOG_TRACE(Input, "PadData packet received");
if (data.packet_counter == clients[client].packet_sequence) {
LOG_WARNING(
@@ -207,11 +211,12 @@ void Client::OnPadData(Response::PadData data) {
clients[client].active = data.info.is_pad_active;
clients[client].packet_sequence = data.packet_counter;
const auto now = std::chrono::system_clock::now();
- u64 time_difference = std::chrono::duration_cast<std::chrono::microseconds>(
- now - clients[client].last_motion_update)
- .count();
+ const auto time_difference =
+ static_cast<u64>(std::chrono::duration_cast<std::chrono::microseconds>(
+ now - clients[client].last_motion_update)
+ .count());
clients[client].last_motion_update = now;
- Common::Vec3f raw_gyroscope = {data.gyro.pitch, data.gyro.roll, -data.gyro.yaw};
+ const Common::Vec3f raw_gyroscope = {data.gyro.pitch, data.gyro.roll, -data.gyro.yaw};
clients[client].motion.SetAcceleration({data.accel.x, -data.accel.z, data.accel.y});
// Gyroscope values are not it the correct scale from better joy.
// Dividing by 312 allows us to make one full turn = 1 turn
@@ -237,9 +242,11 @@ void Client::OnPadData(Response::PadData data) {
const u16 min_y = clients[client].status.touch_calibration->min_y;
const u16 max_y = clients[client].status.touch_calibration->max_y;
- x = (std::clamp(static_cast<u16>(data.touch_1.x), min_x, max_x) - min_x) /
+ x = static_cast<float>(std::clamp(static_cast<u16>(data.touch_1.x), min_x, max_x) -
+ min_x) /
static_cast<float>(max_x - min_x);
- y = (std::clamp(static_cast<u16>(data.touch_1.y), min_y, max_y) - min_y) /
+ y = static_cast<float>(std::clamp(static_cast<u16>(data.touch_1.y), min_y, max_y) -
+ min_y) /
static_cast<float>(max_y - min_y);
}
@@ -253,8 +260,8 @@ void Client::OnPadData(Response::PadData data) {
}
}
-void Client::StartCommunication(std::size_t client, const std::string& host, u16 port, u8 pad_index,
- u32 client_id) {
+void Client::StartCommunication(std::size_t client, const std::string& host, u16 port,
+ std::size_t pad_index, u32 client_id) {
SocketCallback callback{[this](Response::Version version) { OnVersion(version); },
[this](Response::PortInfo info) { OnPortInfo(info); },
[this](Response::PadData data) { OnPadData(data); }};
@@ -264,9 +271,9 @@ void Client::StartCommunication(std::size_t client, const std::string& host, u16
}
void Client::Reset() {
- for (std::size_t client = 0; client < clients.size(); client++) {
- clients[client].socket->Stop();
- clients[client].thread.join();
+ for (auto& client : clients) {
+ client.socket->Stop();
+ client.thread.join();
}
}
@@ -325,16 +332,19 @@ const std::array<Common::SPSCQueue<UDPPadStatus>, 4>& Client::GetPadQueue() cons
return pad_queue;
}
-void TestCommunication(const std::string& host, u16 port, u8 pad_index, u32 client_id,
- std::function<void()> success_callback,
- std::function<void()> failure_callback) {
+void TestCommunication(const std::string& host, u16 port, std::size_t pad_index, u32 client_id,
+ const std::function<void()>& success_callback,
+ const std::function<void()>& failure_callback) {
std::thread([=] {
Common::Event success_event;
- SocketCallback callback{[](Response::Version version) {}, [](Response::PortInfo info) {},
- [&](Response::PadData data) { success_event.Set(); }};
+ SocketCallback callback{
+ .version = [](Response::Version) {},
+ .port_info = [](Response::PortInfo) {},
+ .pad_data = [&](Response::PadData) { success_event.Set(); },
+ };
Socket socket{host, port, pad_index, client_id, std::move(callback)};
std::thread worker_thread{SocketLoop, &socket};
- bool result = success_event.WaitFor(std::chrono::seconds(8));
+ const bool result = success_event.WaitFor(std::chrono::seconds(8));
socket.Stop();
worker_thread.join();
if (result) {
@@ -346,7 +356,7 @@ void TestCommunication(const std::string& host, u16 port, u8 pad_index, u32 clie
}
CalibrationConfigurationJob::CalibrationConfigurationJob(
- const std::string& host, u16 port, u8 pad_index, u32 client_id,
+ const std::string& host, u16 port, std::size_t pad_index, u32 client_id,
std::function<void(Status)> status_callback,
std::function<void(u16, u16, u16, u16)> data_callback) {
@@ -366,7 +376,7 @@ CalibrationConfigurationJob::CalibrationConfigurationJob(
current_status = Status::Ready;
status_callback(current_status);
}
- if (!data.touch_1.is_active) {
+ if (data.touch_1.is_active == 0) {
return;
}
LOG_DEBUG(Input, "Current touch: {} {}", data.touch_1.x,
diff --git a/src/input_common/udp/client.h b/src/input_common/udp/client.h
index 523dc6a7a..747e0c0a2 100644
--- a/src/input_common/udp/client.h
+++ b/src/input_common/udp/client.h
@@ -84,8 +84,8 @@ public:
bool DeviceConnected(std::size_t pad) const;
void ReloadUDPClient();
- void ReloadSocket(const std::string& host = "127.0.0.1", u16 port = 26760, u8 pad_index = 0,
- u32 client_id = 24872);
+ void ReloadSocket(const std::string& host = "127.0.0.1", u16 port = 26760,
+ std::size_t pad_index = 0, u32 client_id = 24872);
std::array<Common::SPSCQueue<UDPPadStatus>, 4>& GetPadQueue();
const std::array<Common::SPSCQueue<UDPPadStatus>, 4>& GetPadQueue() const;
@@ -99,7 +99,7 @@ private:
DeviceStatus status;
std::thread thread;
u64 packet_sequence = 0;
- u8 active;
+ u8 active = 0;
// Realtime values
// motion is initalized with PID values for drift correction on joycons
@@ -113,8 +113,8 @@ private:
void OnVersion(Response::Version);
void OnPortInfo(Response::PortInfo);
void OnPadData(Response::PadData);
- void StartCommunication(std::size_t client, const std::string& host, u16 port, u8 pad_index,
- u32 client_id);
+ void StartCommunication(std::size_t client, const std::string& host, u16 port,
+ std::size_t pad_index, u32 client_id);
void UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& acc,
const Common::Vec3<float>& gyro, bool touch);
@@ -139,7 +139,7 @@ public:
* @param status_callback Callback for job status updates
* @param data_callback Called when calibration data is ready
*/
- explicit CalibrationConfigurationJob(const std::string& host, u16 port, u8 pad_index,
+ explicit CalibrationConfigurationJob(const std::string& host, u16 port, std::size_t pad_index,
u32 client_id, std::function<void(Status)> status_callback,
std::function<void(u16, u16, u16, u16)> data_callback);
~CalibrationConfigurationJob();
@@ -149,8 +149,8 @@ private:
Common::Event complete_event;
};
-void TestCommunication(const std::string& host, u16 port, u8 pad_index, u32 client_id,
- std::function<void()> success_callback,
- std::function<void()> failure_callback);
+void TestCommunication(const std::string& host, u16 port, std::size_t pad_index, u32 client_id,
+ const std::function<void()>& success_callback,
+ const std::function<void()>& failure_callback);
} // namespace InputCommon::CemuhookUDP
diff --git a/src/input_common/udp/udp.cpp b/src/input_common/udp/udp.cpp
index eba077a36..71a76a7aa 100644
--- a/src/input_common/udp/udp.cpp
+++ b/src/input_common/udp/udp.cpp
@@ -2,8 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include <atomic>
-#include <list>
#include <mutex>
#include <utility>
#include "common/assert.h"
@@ -15,8 +13,8 @@ namespace InputCommon {
class UDPMotion final : public Input::MotionDevice {
public:
- UDPMotion(std::string ip_, int port_, int pad_, CemuhookUDP::Client* client_)
- : ip(ip_), port(port_), pad(pad_), client(client_) {}
+ explicit UDPMotion(std::string ip_, int port_, u32 pad_, CemuhookUDP::Client* client_)
+ : ip(std::move(ip_)), port(port_), pad(pad_), client(client_) {}
Input::MotionStatus GetStatus() const override {
return client->GetPadState(pad).motion_status;
@@ -25,7 +23,7 @@ public:
private:
const std::string ip;
const int port;
- const int pad;
+ const u32 pad;
CemuhookUDP::Client* client;
mutable std::mutex mutex;
};
@@ -40,11 +38,11 @@ UDPMotionFactory::UDPMotionFactory(std::shared_ptr<CemuhookUDP::Client> client_)
* - "port": the nth jcpad on the adapter
*/
std::unique_ptr<Input::MotionDevice> UDPMotionFactory::Create(const Common::ParamPackage& params) {
- const std::string ip = params.Get("ip", "127.0.0.1");
- const int port = params.Get("port", 26760);
- const int pad = params.Get("pad_index", 0);
+ auto ip = params.Get("ip", "127.0.0.1");
+ const auto port = params.Get("port", 26760);
+ const auto pad = static_cast<u32>(params.Get("pad_index", 0));
- return std::make_unique<UDPMotion>(ip, port, pad, client.get());
+ return std::make_unique<UDPMotion>(std::move(ip), port, pad, client.get());
}
void UDPMotionFactory::BeginConfiguration() {
@@ -79,7 +77,7 @@ Common::ParamPackage UDPMotionFactory::GetNextInput() {
class UDPTouch final : public Input::TouchDevice {
public:
- UDPTouch(std::string ip_, int port_, int pad_, CemuhookUDP::Client* client_)
+ explicit UDPTouch(std::string ip_, int port_, u32 pad_, CemuhookUDP::Client* client_)
: ip(std::move(ip_)), port(port_), pad(pad_), client(client_) {}
std::tuple<float, float, bool> GetStatus() const override {
@@ -89,7 +87,7 @@ public:
private:
const std::string ip;
const int port;
- const int pad;
+ const u32 pad;
CemuhookUDP::Client* client;
mutable std::mutex mutex;
};
@@ -104,11 +102,11 @@ UDPTouchFactory::UDPTouchFactory(std::shared_ptr<CemuhookUDP::Client> client_)
* - "port": the nth jcpad on the adapter
*/
std::unique_ptr<Input::TouchDevice> UDPTouchFactory::Create(const Common::ParamPackage& params) {
- const std::string ip = params.Get("ip", "127.0.0.1");
- const int port = params.Get("port", 26760);
- const int pad = params.Get("pad_index", 0);
+ auto ip = params.Get("ip", "127.0.0.1");
+ const auto port = params.Get("port", 26760);
+ const auto pad = static_cast<u32>(params.Get("pad_index", 0));
- return std::make_unique<UDPTouch>(ip, port, pad, client.get());
+ return std::make_unique<UDPTouch>(std::move(ip), port, pad, client.get());
}
void UDPTouchFactory::BeginConfiguration() {
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
index 81a39a3b8..da5c550ea 100644
--- a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
+++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
@@ -58,6 +58,7 @@ void FixedPipelineState::Fill(const Maxwell& regs, bool has_extended_dynamic_sta
logic_op_enable.Assign(regs.logic_op.enable != 0 ? 1 : 0);
logic_op.Assign(PackLogicOp(regs.logic_op.operation));
rasterize_enable.Assign(regs.rasterize_enable != 0 ? 1 : 0);
+ topology.Assign(regs.draw.topology);
std::memcpy(&point_size, &regs.point_size, sizeof(point_size)); // TODO: C++20 std::bit_cast
@@ -131,7 +132,6 @@ void FixedPipelineState::BlendingAttachment::Fill(const Maxwell& regs, std::size
}
void FixedPipelineState::DynamicState::Fill(const Maxwell& regs) {
- const u32 topology_index = static_cast<u32>(regs.draw.topology.Value());
u32 packed_front_face = PackFrontFace(regs.front_face);
if (regs.screen_y_control.triangle_rast_flip != 0) {
// Flip front face
@@ -161,7 +161,6 @@ void FixedPipelineState::DynamicState::Fill(const Maxwell& regs) {
depth_test_enable.Assign(regs.depth_test_enable);
front_face.Assign(packed_front_face);
depth_test_func.Assign(PackComparisonOp(regs.depth_test_func));
- topology.Assign(topology_index);
cull_face.Assign(PackCullFace(regs.cull_face));
cull_enable.Assign(regs.cull_test_enabled != 0 ? 1 : 0);
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.h b/src/video_core/renderer_vulkan/fixed_pipeline_state.h
index cdcbb65f5..2c18eeaae 100644
--- a/src/video_core/renderer_vulkan/fixed_pipeline_state.h
+++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.h
@@ -150,9 +150,8 @@ struct FixedPipelineState {
};
union {
u32 raw2;
- BitField<0, 4, u32> topology;
- BitField<4, 2, u32> cull_face;
- BitField<6, 1, u32> cull_enable;
+ BitField<0, 2, u32> cull_face;
+ BitField<2, 1, u32> cull_enable;
};
std::array<VertexBinding, Maxwell::NumVertexArrays> vertex_bindings;
@@ -169,10 +168,6 @@ struct FixedPipelineState {
Maxwell::FrontFace FrontFace() const noexcept {
return UnpackFrontFace(front_face.Value());
}
-
- constexpr Maxwell::PrimitiveTopology Topology() const noexcept {
- return static_cast<Maxwell::PrimitiveTopology>(topology.Value());
- }
};
union {
@@ -190,6 +185,7 @@ struct FixedPipelineState {
BitField<18, 1, u32> logic_op_enable;
BitField<19, 4, u32> logic_op;
BitField<23, 1, u32> rasterize_enable;
+ BitField<24, 4, Maxwell::PrimitiveTopology> topology;
};
u32 point_size;
std::array<u32, Maxwell::NumVertexArrays> binding_divisors;
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
index 715182b3b..f2610868e 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
@@ -92,9 +92,9 @@ Common::DynamicLibrary OpenVulkanLibrary() {
return library;
}
-vk::Instance CreateInstance(Common::DynamicLibrary& library, vk::InstanceDispatch& dld,
- WindowSystemType window_type = WindowSystemType::Headless,
- bool enable_layers = false) {
+std::pair<vk::Instance, u32> CreateInstance(
+ Common::DynamicLibrary& library, vk::InstanceDispatch& dld,
+ WindowSystemType window_type = WindowSystemType::Headless, bool enable_layers = false) {
if (!library.IsOpen()) {
LOG_ERROR(Render_Vulkan, "Vulkan library not available");
return {};
@@ -180,7 +180,10 @@ vk::Instance CreateInstance(Common::DynamicLibrary& library, vk::InstanceDispatc
}
}
- vk::Instance instance = vk::Instance::Create(layers, extensions, dld);
+ // Limit the maximum version of Vulkan to avoid using untested version.
+ const u32 version = std::min(vk::AvailableVersion(dld), static_cast<u32>(VK_API_VERSION_1_1));
+
+ vk::Instance instance = vk::Instance::Create(version, layers, extensions, dld);
if (!instance) {
LOG_ERROR(Render_Vulkan, "Failed to create Vulkan instance");
return {};
@@ -188,7 +191,7 @@ vk::Instance CreateInstance(Common::DynamicLibrary& library, vk::InstanceDispatc
if (!vk::Load(*instance, dld)) {
LOG_ERROR(Render_Vulkan, "Failed to load Vulkan instance function pointers");
}
- return instance;
+ return std::make_pair(std::move(instance), version);
}
std::string GetReadableVersion(u32 version) {
@@ -285,8 +288,8 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
bool RendererVulkan::Init() {
library = OpenVulkanLibrary();
- instance = CreateInstance(library, dld, render_window.GetWindowInfo().type,
- Settings::values.renderer_debug);
+ std::tie(instance, instance_version) = CreateInstance(
+ library, dld, render_window.GetWindowInfo().type, Settings::values.renderer_debug);
if (!instance || !CreateDebugCallback() || !CreateSurface() || !PickDevices()) {
return false;
}
@@ -416,7 +419,8 @@ bool RendererVulkan::PickDevices() {
return false;
}
- device = std::make_unique<VKDevice>(*instance, physical_device, *surface, dld);
+ device =
+ std::make_unique<VKDevice>(*instance, instance_version, physical_device, *surface, dld);
return device->Create();
}
@@ -426,7 +430,7 @@ void RendererVulkan::Report() const {
const std::string driver_version = GetDriverVersion(*device);
const std::string driver_name = fmt::format("{} {}", vendor_name, driver_version);
- const std::string api_version = GetReadableVersion(device->GetApiVersion());
+ const std::string api_version = GetReadableVersion(device->ApiVersion());
const std::string extensions = BuildCommaSeparatedExtensions(device->GetAvailableExtensions());
@@ -445,7 +449,7 @@ void RendererVulkan::Report() const {
std::vector<std::string> RendererVulkan::EnumerateDevices() {
vk::InstanceDispatch dld;
Common::DynamicLibrary library = OpenVulkanLibrary();
- vk::Instance instance = CreateInstance(library, dld);
+ vk::Instance instance = CreateInstance(library, dld).first;
if (!instance) {
return {};
}
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h
index 49a4141ec..1044ca124 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.h
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.h
@@ -73,6 +73,8 @@ private:
vk::InstanceDispatch dld;
vk::Instance instance;
+ u32 instance_version{};
+
vk::SurfaceKHR surface;
VKScreenInfo screen_info;
diff --git a/src/video_core/renderer_vulkan/vk_device.cpp b/src/video_core/renderer_vulkan/vk_device.cpp
index 3d8d3213d..e1217ca83 100644
--- a/src/video_core/renderer_vulkan/vk_device.cpp
+++ b/src/video_core/renderer_vulkan/vk_device.cpp
@@ -38,6 +38,9 @@ constexpr std::array Depth16UnormS8_UINT{
constexpr std::array REQUIRED_EXTENSIONS{
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
+ VK_KHR_MAINTENANCE1_EXTENSION_NAME,
+ VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME,
+ VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME,
VK_KHR_16BIT_STORAGE_EXTENSION_NAME,
VK_KHR_8BIT_STORAGE_EXTENSION_NAME,
VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME,
@@ -79,6 +82,21 @@ VkFormatFeatureFlags GetFormatFeatures(VkFormatProperties properties, FormatType
}
}
+[[nodiscard]] bool IsRDNA(std::string_view device_name, VkDriverIdKHR driver_id) {
+ static constexpr std::array RDNA_DEVICES{
+ "5700",
+ "5600",
+ "5500",
+ "5300",
+ };
+ if (driver_id != VK_DRIVER_ID_AMD_PROPRIETARY_KHR) {
+ return false;
+ }
+ return std::any_of(RDNA_DEVICES.begin(), RDNA_DEVICES.end(), [device_name](const char* name) {
+ return device_name.find(name) != std::string_view::npos;
+ });
+}
+
std::unordered_map<VkFormat, VkFormatProperties> GetFormatProperties(
vk::PhysicalDevice physical, const vk::InstanceDispatch& dld) {
static constexpr std::array formats{
@@ -172,10 +190,10 @@ std::unordered_map<VkFormat, VkFormatProperties> GetFormatProperties(
} // Anonymous namespace
-VKDevice::VKDevice(VkInstance instance, vk::PhysicalDevice physical, VkSurfaceKHR surface,
- const vk::InstanceDispatch& dld)
- : dld{dld}, physical{physical}, properties{physical.GetProperties()},
- format_properties{GetFormatProperties(physical, dld)} {
+VKDevice::VKDevice(VkInstance instance_, u32 instance_version_, vk::PhysicalDevice physical_,
+ VkSurfaceKHR surface, const vk::InstanceDispatch& dld_)
+ : dld{dld_}, physical{physical_}, properties{physical.GetProperties()},
+ instance_version{instance_version_}, format_properties{GetFormatProperties(physical, dld)} {
SetupFamilies(surface);
SetupFeatures();
}
@@ -388,6 +406,15 @@ bool VKDevice::Create() {
CollectTelemetryParameters();
+ if (ext_extended_dynamic_state && IsRDNA(properties.deviceName, driver_id)) {
+ // AMD's proprietary driver supports VK_EXT_extended_dynamic_state but on RDNA devices it
+ // seems to cause stability issues
+ LOG_WARNING(
+ Render_Vulkan,
+ "Blacklisting AMD proprietary on RDNA devices from VK_EXT_extended_dynamic_state");
+ ext_extended_dynamic_state = false;
+ }
+
graphics_queue = logical.GetQueue(graphics_family);
present_queue = logical.GetQueue(present_family);
@@ -573,20 +600,6 @@ bool VKDevice::IsSuitable(vk::PhysicalDevice physical, VkSurfaceKHR surface) {
std::vector<const char*> VKDevice::LoadExtensions() {
std::vector<const char*> extensions;
- const auto Test = [&](const VkExtensionProperties& extension,
- std::optional<std::reference_wrapper<bool>> status, const char* name,
- bool push) {
- if (extension.extensionName != std::string_view(name)) {
- return;
- }
- if (push) {
- extensions.push_back(name);
- }
- if (status) {
- status->get() = true;
- }
- };
-
extensions.reserve(7 + REQUIRED_EXTENSIONS.size());
extensions.insert(extensions.begin(), REQUIRED_EXTENSIONS.begin(), REQUIRED_EXTENSIONS.end());
@@ -595,28 +608,36 @@ std::vector<const char*> VKDevice::LoadExtensions() {
bool has_ext_transform_feedback{};
bool has_ext_custom_border_color{};
bool has_ext_extended_dynamic_state{};
- for (const auto& extension : physical.EnumerateDeviceExtensionProperties()) {
- Test(extension, nv_viewport_swizzle, VK_NV_VIEWPORT_SWIZZLE_EXTENSION_NAME, true);
- Test(extension, khr_uniform_buffer_standard_layout,
+ for (const VkExtensionProperties& extension : physical.EnumerateDeviceExtensionProperties()) {
+ const auto test = [&](std::optional<std::reference_wrapper<bool>> status, const char* name,
+ bool push) {
+ if (extension.extensionName != std::string_view(name)) {
+ return;
+ }
+ if (push) {
+ extensions.push_back(name);
+ }
+ if (status) {
+ status->get() = true;
+ }
+ };
+ test(nv_viewport_swizzle, VK_NV_VIEWPORT_SWIZZLE_EXTENSION_NAME, true);
+ test(khr_uniform_buffer_standard_layout,
VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_EXTENSION_NAME, true);
- Test(extension, has_khr_shader_float16_int8, VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME,
- false);
- Test(extension, ext_depth_range_unrestricted,
- VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME, true);
- Test(extension, ext_index_type_uint8, VK_EXT_INDEX_TYPE_UINT8_EXTENSION_NAME, true);
- Test(extension, ext_shader_viewport_index_layer,
- VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME, true);
- Test(extension, has_ext_subgroup_size_control, VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME,
- false);
- Test(extension, has_ext_transform_feedback, VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME,
- false);
- Test(extension, has_ext_custom_border_color, VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME,
- false);
- Test(extension, has_ext_extended_dynamic_state,
- VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME, false);
+ test(has_khr_shader_float16_int8, VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME, false);
+ test(ext_depth_range_unrestricted, VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME, true);
+ test(ext_index_type_uint8, VK_EXT_INDEX_TYPE_UINT8_EXTENSION_NAME, true);
+ test(ext_shader_viewport_index_layer, VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME,
+ true);
+ 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);
+ if (instance_version >= VK_API_VERSION_1_1) {
+ test(has_ext_subgroup_size_control, VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME, false);
+ }
if (Settings::values.renderer_debug) {
- Test(extension, nv_device_diagnostics_config,
- VK_NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME, true);
+ test(nv_device_diagnostics_config, VK_NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME,
+ true);
}
}
diff --git a/src/video_core/renderer_vulkan/vk_device.h b/src/video_core/renderer_vulkan/vk_device.h
index 26a233db1..4286673d9 100644
--- a/src/video_core/renderer_vulkan/vk_device.h
+++ b/src/video_core/renderer_vulkan/vk_device.h
@@ -24,8 +24,8 @@ const u32 GuestWarpSize = 32;
/// Handles data specific to a physical device.
class VKDevice final {
public:
- explicit VKDevice(VkInstance instance, vk::PhysicalDevice physical, VkSurfaceKHR surface,
- const vk::InstanceDispatch& dld);
+ explicit VKDevice(VkInstance instance, u32 instance_version, vk::PhysicalDevice physical,
+ VkSurfaceKHR surface, const vk::InstanceDispatch& dld);
~VKDevice();
/// Initializes the device. Returns true on success.
@@ -82,8 +82,13 @@ public:
return present_family;
}
+ /// Returns the current instance Vulkan API version in Vulkan-formatted version numbers.
+ u32 InstanceApiVersion() const {
+ return instance_version;
+ }
+
/// Returns the current Vulkan API version provided in Vulkan-formatted version numbers.
- u32 GetApiVersion() const {
+ u32 ApiVersion() const {
return properties.apiVersion;
}
@@ -239,6 +244,7 @@ private:
vk::Device logical; ///< Logical device.
vk::Queue graphics_queue; ///< Main graphics queue.
vk::Queue present_queue; ///< Main present queue.
+ u32 instance_version{}; ///< Vulkan onstance version.
u32 graphics_family{}; ///< Main graphics queue family index.
u32 present_family{}; ///< Main present queue family index.
VkDriverIdKHR driver_id{}; ///< Driver ID.
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
index a4b9e7ef5..696eaeb5f 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
@@ -261,12 +261,12 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
vertex_input_ci.pNext = &input_divisor_ci;
}
- const auto input_assembly_topology = MaxwellToVK::PrimitiveTopology(device, dynamic.Topology());
+ const auto input_assembly_topology = MaxwellToVK::PrimitiveTopology(device, state.topology);
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci{
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
- .topology = MaxwellToVK::PrimitiveTopology(device, dynamic.Topology()),
+ .topology = MaxwellToVK::PrimitiveTopology(device, state.topology),
.primitiveRestartEnable = state.primitive_restart_enable != 0 &&
SupportsPrimitiveRestart(input_assembly_topology),
};
@@ -400,7 +400,6 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
static constexpr std::array extended{
VK_DYNAMIC_STATE_CULL_MODE_EXT,
VK_DYNAMIC_STATE_FRONT_FACE_EXT,
- VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT,
VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT,
VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT,
VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT,
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
index 5c038f4bc..dedc9c466 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -331,8 +331,7 @@ void VKPipelineCache::OnShaderRemoval(Shader* shader) {
std::pair<SPIRVProgram, std::vector<VkDescriptorSetLayoutBinding>>
VKPipelineCache::DecompileShaders(const FixedPipelineState& fixed_state) {
Specialization specialization;
- if (fixed_state.dynamic_state.Topology() == Maxwell::PrimitiveTopology::Points ||
- device.IsExtExtendedDynamicStateSupported()) {
+ if (fixed_state.topology == Maxwell::PrimitiveTopology::Points) {
float point_size;
std::memcpy(&point_size, &fixed_state.point_size, sizeof(float));
specialization.point_size = point_size;
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index f3c2483c8..e0fb8693f 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -948,7 +948,6 @@ void RasterizerVulkan::UpdateDynamicStates() {
UpdateDepthWriteEnable(regs);
UpdateDepthCompareOp(regs);
UpdateFrontFace(regs);
- UpdatePrimitiveTopology(regs);
UpdateStencilOp(regs);
UpdateStencilTestEnable(regs);
}
@@ -1418,16 +1417,6 @@ void RasterizerVulkan::UpdateFrontFace(Tegra::Engines::Maxwell3D::Regs& regs) {
[front_face](vk::CommandBuffer cmdbuf) { cmdbuf.SetFrontFaceEXT(front_face); });
}
-void RasterizerVulkan::UpdatePrimitiveTopology(Tegra::Engines::Maxwell3D::Regs& regs) {
- const Maxwell::PrimitiveTopology primitive_topology = regs.draw.topology.Value();
- if (!state_tracker.ChangePrimitiveTopology(primitive_topology)) {
- return;
- }
- scheduler.Record([this, primitive_topology](vk::CommandBuffer cmdbuf) {
- cmdbuf.SetPrimitiveTopologyEXT(MaxwellToVK::PrimitiveTopology(device, primitive_topology));
- });
-}
-
void RasterizerVulkan::UpdateStencilOp(Tegra::Engines::Maxwell3D::Regs& regs) {
if (!state_tracker.TouchStencilOp()) {
return;
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h
index b47c8fc13..237e51fa4 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.h
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.h
@@ -259,7 +259,6 @@ private:
void UpdateDepthWriteEnable(Tegra::Engines::Maxwell3D::Regs& regs);
void UpdateDepthCompareOp(Tegra::Engines::Maxwell3D::Regs& regs);
void UpdateFrontFace(Tegra::Engines::Maxwell3D::Regs& regs);
- void UpdatePrimitiveTopology(Tegra::Engines::Maxwell3D::Regs& regs);
void UpdateStencilOp(Tegra::Engines::Maxwell3D::Regs& regs);
void UpdateStencilTestEnable(Tegra::Engines::Maxwell3D::Regs& regs);
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
index cd7d7a4e4..a20452b87 100644
--- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
+++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
@@ -272,12 +272,19 @@ bool IsPrecise(Operation operand) {
return false;
}
+u32 ShaderVersion(const VKDevice& device) {
+ if (device.InstanceApiVersion() < VK_API_VERSION_1_1) {
+ return 0x00010000;
+ }
+ return 0x00010300;
+}
+
class SPIRVDecompiler final : public Sirit::Module {
public:
explicit SPIRVDecompiler(const VKDevice& device, const ShaderIR& ir, ShaderType stage,
const Registry& registry, const Specialization& specialization)
- : Module(0x00010300), device{device}, ir{ir}, stage{stage}, header{ir.GetHeader()},
- registry{registry}, specialization{specialization} {
+ : Module(ShaderVersion(device)), device{device}, ir{ir}, stage{stage},
+ header{ir.GetHeader()}, registry{registry}, specialization{specialization} {
if (stage != ShaderType::Compute) {
transform_feedback = BuildTransformFeedback(registry.GetGraphicsInfo());
}
@@ -293,6 +300,7 @@ public:
AddCapability(spv::Capability::DrawParameters);
AddCapability(spv::Capability::SubgroupBallotKHR);
AddCapability(spv::Capability::SubgroupVoteKHR);
+ AddExtension("SPV_KHR_16bit_storage");
AddExtension("SPV_KHR_shader_ballot");
AddExtension("SPV_KHR_subgroup_vote");
AddExtension("SPV_KHR_storage_buffer_storage_class");
diff --git a/src/video_core/renderer_vulkan/wrapper.cpp b/src/video_core/renderer_vulkan/wrapper.cpp
index 2598440fb..c034558a3 100644
--- a/src/video_core/renderer_vulkan/wrapper.cpp
+++ b/src/video_core/renderer_vulkan/wrapper.cpp
@@ -11,6 +11,7 @@
#include <vector>
#include "common/common_types.h"
+#include "common/logging/log.h"
#include "video_core/renderer_vulkan/wrapper.h"
@@ -415,18 +416,17 @@ VkResult Free(VkDevice device, VkCommandPool handle, Span<VkCommandBuffer> buffe
return VK_SUCCESS;
}
-Instance Instance::Create(Span<const char*> layers, Span<const char*> extensions,
+Instance Instance::Create(u32 version, Span<const char*> layers, Span<const char*> extensions,
InstanceDispatch& dld) noexcept {
- static constexpr VkApplicationInfo application_info{
+ const VkApplicationInfo application_info{
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
.pNext = nullptr,
.pApplicationName = "yuzu Emulator",
.applicationVersion = VK_MAKE_VERSION(0, 1, 0),
.pEngineName = "yuzu Emulator",
.engineVersion = VK_MAKE_VERSION(0, 1, 0),
- .apiVersion = VK_API_VERSION_1_1,
+ .apiVersion = version,
};
-
const VkInstanceCreateInfo ci{
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
.pNext = nullptr,
@@ -818,6 +818,21 @@ VkPhysicalDeviceMemoryProperties PhysicalDevice::GetMemoryProperties() const noe
return properties;
}
+u32 AvailableVersion(const InstanceDispatch& dld) noexcept {
+ PFN_vkEnumerateInstanceVersion vkEnumerateInstanceVersion;
+ if (!Proc(vkEnumerateInstanceVersion, dld, "vkEnumerateInstanceVersion")) {
+ // If the procedure is not found, Vulkan 1.0 is assumed
+ return VK_API_VERSION_1_0;
+ }
+ u32 version;
+ if (const VkResult result = vkEnumerateInstanceVersion(&version); result != VK_SUCCESS) {
+ LOG_ERROR(Render_Vulkan, "vkEnumerateInstanceVersion returned {}, assuming Vulkan 1.1",
+ ToString(result));
+ return VK_API_VERSION_1_1;
+ }
+ return version;
+}
+
std::optional<std::vector<VkExtensionProperties>> EnumerateInstanceExtensionProperties(
const InstanceDispatch& dld) {
u32 num;
diff --git a/src/video_core/renderer_vulkan/wrapper.h b/src/video_core/renderer_vulkan/wrapper.h
index 234e01693..f64919623 100644
--- a/src/video_core/renderer_vulkan/wrapper.h
+++ b/src/video_core/renderer_vulkan/wrapper.h
@@ -564,7 +564,7 @@ class Instance : public Handle<VkInstance, NoOwner, InstanceDispatch> {
public:
/// Creates a Vulkan instance. Use "operator bool" for error handling.
- static Instance Create(Span<const char*> layers, Span<const char*> extensions,
+ static Instance Create(u32 version, Span<const char*> layers, Span<const char*> extensions,
InstanceDispatch& dld) noexcept;
/// Enumerates physical devices.
@@ -1090,6 +1090,8 @@ private:
const DeviceDispatch* dld;
};
+u32 AvailableVersion(const InstanceDispatch& dld) noexcept;
+
std::optional<std::vector<VkExtensionProperties>> EnumerateInstanceExtensionProperties(
const InstanceDispatch& dld);
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index 698cb1940..f58ca29d7 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -256,11 +256,6 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
ui->buttonSL, ui->buttonSR, ui->buttonHome, ui->buttonScreenshot,
};
- mod_buttons = {
- ui->buttonLStickMod,
- ui->buttonRStickMod,
- };
-
analog_map_buttons = {{
{
ui->buttonLStickUp,
@@ -284,6 +279,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
analog_map_deadzone_label = {ui->labelLStickDeadzone, ui->labelRStickDeadzone};
analog_map_deadzone_slider = {ui->sliderLStickDeadzone, ui->sliderRStickDeadzone};
analog_map_modifier_groupbox = {ui->buttonLStickModGroup, ui->buttonRStickModGroup};
+ analog_map_modifier_button = {ui->buttonLStickMod, ui->buttonRStickMod};
analog_map_modifier_label = {ui->labelLStickModifierRange, ui->labelRStickModifierRange};
analog_map_modifier_slider = {ui->sliderLStickModifierRange, ui->sliderRStickModifierRange};
analog_map_range_groupbox = {ui->buttonLStickRangeGroup, ui->buttonRStickRangeGroup};
@@ -394,20 +390,26 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
}
// Handle clicks for the modifier buttons as well.
- ConfigureButtonClick(mod_buttons[analog_id], &stick_mod_param[analog_id],
- Config::default_stick_mod[analog_id],
- InputCommon::Polling::DeviceType::Button);
+ connect(analog_map_modifier_button[analog_id], &QPushButton::clicked, [=, this] {
+ HandleClick(
+ analog_map_modifier_button[analog_id],
+ [=, this](const Common::ParamPackage& params) {
+ analogs_param[analog_id].Set("modifier", params.Serialize());
+ },
+ InputCommon::Polling::DeviceType::Button);
+ });
- mod_buttons[analog_id]->setContextMenuPolicy(Qt::CustomContextMenu);
+ analog_map_modifier_button[analog_id]->setContextMenuPolicy(Qt::CustomContextMenu);
- connect(mod_buttons[analog_id], &QPushButton::customContextMenuRequested,
+ connect(analog_map_modifier_button[analog_id], &QPushButton::customContextMenuRequested,
[=, this](const QPoint& menu_location) {
QMenu context_menu;
context_menu.addAction(tr("Clear"), [&] {
- stick_mod_param[analog_id].Clear();
- mod_buttons[analog_id]->setText(tr("[not set]"));
+ analogs_param[analog_id].Set("modifier", "");
+ analog_map_modifier_button[analog_id]->setText(tr("[not set]"));
});
- context_menu.exec(mod_buttons[analog_id]->mapToGlobal(menu_location));
+ context_menu.exec(
+ analog_map_modifier_button[analog_id]->mapToGlobal(menu_location));
});
connect(analog_map_range_spinbox[analog_id], qOverload<int>(&QSpinBox::valueChanged),
@@ -636,8 +638,8 @@ void ConfigureInputPlayer::RestoreDefaults() {
SetAnalogParam(params, analogs_param[analog_id], analog_sub_buttons[sub_button_id]);
}
- stick_mod_param[analog_id] = Common::ParamPackage(
- InputCommon::GenerateKeyboardParam(Config::default_stick_mod[analog_id]));
+ analogs_param[analog_id].Set(
+ "modifier", InputCommon::GenerateKeyboardParam(Config::default_stick_mod[analog_id]));
}
for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) {
@@ -669,8 +671,6 @@ void ConfigureInputPlayer::ClearAll() {
analogs_param[analog_id].Clear();
}
-
- stick_mod_param[analog_id].Clear();
}
for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) {
@@ -707,7 +707,8 @@ void ConfigureInputPlayer::UpdateUI() {
AnalogToText(analogs_param[analog_id], analog_sub_buttons[sub_button_id]));
}
- mod_buttons[analog_id]->setText(ButtonToText(stick_mod_param[analog_id]));
+ analog_map_modifier_button[analog_id]->setText(
+ ButtonToText(Common::ParamPackage{analogs_param[analog_id].Get("modifier", "")}));
const auto deadzone_label = analog_map_deadzone_label[analog_id];
const auto deadzone_slider = analog_map_deadzone_slider[analog_id];
diff --git a/src/yuzu/configuration/configure_input_player.h b/src/yuzu/configuration/configure_input_player.h
index ce443dec5..c19aefffa 100644
--- a/src/yuzu/configuration/configure_input_player.h
+++ b/src/yuzu/configuration/configure_input_player.h
@@ -131,26 +131,25 @@ private:
std::array<Common::ParamPackage, Settings::NativeButton::NumButtons> buttons_param;
std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs> analogs_param;
- std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs> stick_mod_param;
std::array<Common::ParamPackage, Settings::NativeMotion::NumMotions> motions_param;
static constexpr int ANALOG_SUB_BUTTONS_NUM = 4;
/// Each button input is represented by a QPushButton.
std::array<QPushButton*, Settings::NativeButton::NumButtons> button_map;
- /// Each motion input is represented by a QPushButton.
- std::array<QPushButton*, Settings::NativeMotion::NumMotions> motion_map;
- /// Extra buttons for the modifiers.
- std::array<QPushButton*, Settings::NativeAnalog::NumAnalogs> mod_buttons;
/// A group of four QPushButtons represent one analog input. The buttons each represent up,
/// down, left, right, respectively.
std::array<std::array<QPushButton*, ANALOG_SUB_BUTTONS_NUM>, Settings::NativeAnalog::NumAnalogs>
analog_map_buttons;
+ /// Each motion input is represented by a QPushButton.
+ std::array<QPushButton*, Settings::NativeMotion::NumMotions> motion_map;
+
std::array<QLabel*, Settings::NativeAnalog::NumAnalogs> analog_map_deadzone_label;
std::array<QSlider*, Settings::NativeAnalog::NumAnalogs> analog_map_deadzone_slider;
std::array<QGroupBox*, Settings::NativeAnalog::NumAnalogs> analog_map_modifier_groupbox;
+ std::array<QPushButton*, Settings::NativeAnalog::NumAnalogs> analog_map_modifier_button;
std::array<QLabel*, Settings::NativeAnalog::NumAnalogs> analog_map_modifier_label;
std::array<QSlider*, Settings::NativeAnalog::NumAnalogs> analog_map_modifier_slider;
std::array<QGroupBox*, Settings::NativeAnalog::NumAnalogs> analog_map_range_groupbox;
diff --git a/src/yuzu/configuration/configure_motion_touch.cpp b/src/yuzu/configuration/configure_motion_touch.cpp
index c7d085151..170574d9b 100644
--- a/src/yuzu/configuration/configure_motion_touch.cpp
+++ b/src/yuzu/configuration/configure_motion_touch.cpp
@@ -193,7 +193,7 @@ void ConfigureMotionTouch::OnCemuhookUDPTest() {
udp_test_in_progress = true;
InputCommon::CemuhookUDP::TestCommunication(
ui->udp_server->text().toStdString(), static_cast<u16>(ui->udp_port->text().toInt()),
- static_cast<u8>(ui->udp_pad_index->currentIndex()), 24872,
+ static_cast<u32>(ui->udp_pad_index->currentIndex()), 24872,
[this] {
LOG_INFO(Frontend, "UDP input test success");
QMetaObject::invokeMethod(this, "ShowUDPTestResult", Q_ARG(bool, true));