From ebd748d55f458bc0c23dc63759e7ad7e73dea03f Mon Sep 17 00:00:00 2001 From: pineappleEA Date: Sun, 29 Jan 2023 15:48:11 +0100 Subject: [PATCH] early-access version 3347 --- README.md | 2 +- dist/yuzu.ico | Bin 23159 -> 25355 bytes dist/yuzu.svg | 2 +- src/common/input.h | 2 + src/common/polyfill_thread.h | 87 +++-- src/common/string_util.cpp | 2 +- src/common/string_util.h | 3 +- src/core/CMakeLists.txt | 2 + src/core/hardware_properties.h | 20 + src/core/hid/emulated_controller.cpp | 73 +++- src/core/hid/emulated_controller.h | 6 + src/core/hle/kernel/hle_ipc.cpp | 30 +- src/core/hle/kernel/hle_ipc.h | 8 +- src/core/hle/kernel/k_capabilities.cpp | 358 ++++++++++++++++++ src/core/hle/kernel/k_capabilities.h | 295 +++++++++++++++ src/core/hle/kernel/svc_types.h | 5 + src/core/hle/kernel/svc_version.h | 58 +++ src/core/hle/service/am/am.cpp | 2 +- src/core/hle/service/audio/audren_u.cpp | 2 +- src/core/hle/service/audio/hwopus.cpp | 2 +- src/core/hle/service/es/es.cpp | 2 +- src/core/hle/service/filesystem/fsp_srv.cpp | 9 +- src/core/hle/service/glue/arp.cpp | 3 +- src/core/hle/service/hid/controllers/npad.cpp | 8 +- src/core/hle/service/hid/controllers/npad.h | 3 +- src/core/hle/service/hid/hid.cpp | 4 +- src/core/hle/service/hid/hidbus/hidbus_base.h | 3 +- src/core/hle/service/hid/hidbus/ringcon.cpp | 2 +- src/core/hle/service/hid/hidbus/ringcon.h | 3 +- src/core/hle/service/hid/hidbus/starlink.cpp | 2 +- src/core/hle/service/hid/hidbus/starlink.h | 2 +- src/core/hle/service/hid/hidbus/stubbed.cpp | 2 +- src/core/hle/service/hid/hidbus/stubbed.h | 2 +- src/core/hle/service/jit/jit.cpp | 4 +- src/core/hle/service/ldn/ldn.cpp | 4 +- src/core/hle/service/nvdrv/devices/nvdevice.h | 10 +- .../service/nvdrv/devices/nvdisp_disp0.cpp | 8 +- .../hle/service/nvdrv/devices/nvdisp_disp0.h | 10 +- .../service/nvdrv/devices/nvhost_as_gpu.cpp | 26 +- .../hle/service/nvdrv/devices/nvhost_as_gpu.h | 28 +- .../hle/service/nvdrv/devices/nvhost_ctrl.cpp | 21 +- .../hle/service/nvdrv/devices/nvhost_ctrl.h | 22 +- .../service/nvdrv/devices/nvhost_ctrl_gpu.cpp | 31 +- .../service/nvdrv/devices/nvhost_ctrl_gpu.h | 32 +- .../hle/service/nvdrv/devices/nvhost_gpu.cpp | 35 +- .../hle/service/nvdrv/devices/nvhost_gpu.h | 36 +- .../service/nvdrv/devices/nvhost_nvdec.cpp | 8 +- .../hle/service/nvdrv/devices/nvhost_nvdec.h | 10 +- .../nvdrv/devices/nvhost_nvdec_common.cpp | 17 +- .../nvdrv/devices/nvhost_nvdec_common.h | 14 +- .../service/nvdrv/devices/nvhost_nvjpg.cpp | 10 +- .../hle/service/nvdrv/devices/nvhost_nvjpg.h | 12 +- .../hle/service/nvdrv/devices/nvhost_vic.cpp | 8 +- .../hle/service/nvdrv/devices/nvhost_vic.h | 10 +- src/core/hle/service/nvdrv/devices/nvmap.cpp | 20 +- src/core/hle/service/nvdrv/devices/nvmap.h | 22 +- src/core/hle/service/nvdrv/nvdrv.cpp | 8 +- src/core/hle/service/nvdrv/nvdrv.h | 12 +- .../nvflinger/buffer_queue_producer.cpp | 4 +- .../nvflinger/graphic_buffer_producer.cpp | 2 +- .../nvflinger/graphic_buffer_producer.h | 4 +- src/core/hle/service/nvflinger/parcel.h | 87 +++-- src/core/hle/service/prepo/prepo.cpp | 8 +- src/core/hle/service/sockets/bsd.cpp | 15 +- src/core/hle/service/sockets/bsd.h | 23 +- src/core/hle/service/sockets/sfdnsres.cpp | 2 +- src/core/hle/service/ssl/ssl.cpp | 8 +- src/core/hle/service/vi/vi.cpp | 4 +- src/core/internal_network/network.cpp | 4 +- src/core/internal_network/socket_proxy.cpp | 4 +- src/core/internal_network/socket_proxy.h | 5 +- src/core/internal_network/sockets.h | 9 +- src/core/reporter.cpp | 2 +- src/core/reporter.h | 4 +- .../helpers/joycon_protocol/calibration.cpp | 212 ++++++----- .../helpers/joycon_protocol/calibration.h | 18 + .../joycon_protocol/common_protocol.cpp | 18 +- .../helpers/joycon_protocol/common_protocol.h | 23 +- .../joycon_protocol/generic_functions.cpp | 8 +- .../helpers/joycon_protocol/joycon_types.h | 52 ++- src/input_common/input_poller.cpp | 30 +- .../backend/glasm/emit_glasm_image.cpp | 2 +- .../backend/glasm/emit_glasm_instructions.h | 2 +- .../backend/glsl/emit_glsl_image.cpp | 20 +- .../backend/glsl/emit_glsl_instructions.h | 2 +- .../backend/spirv/emit_spirv_image.cpp | 6 +- .../backend/spirv/emit_spirv_instructions.h | 3 +- .../frontend/ir/ir_emitter.cpp | 9 +- .../frontend/ir/ir_emitter.h | 5 +- src/shader_recompiler/frontend/ir/opcodes.inc | 6 +- .../maxwell/translate/impl/texture_query.cpp | 8 +- src/shader_recompiler/ir_opt/texture_pass.cpp | 28 +- src/video_core/host_shaders/CMakeLists.txt | 2 + src/video_core/renderer_vulkan/blit_image.cpp | 126 +++++- src/video_core/renderer_vulkan/blit_image.h | 10 + .../renderer_vulkan/vk_rasterizer.cpp | 10 +- src/yuzu/applets/qt_software_keyboard.cpp | 2 +- .../configuration/configure_input_player.cpp | 17 +- src/yuzu/discord_impl.cpp | 2 +- src/yuzu/main.cpp | 69 +++- src/yuzu/util/overlay_dialog.cpp | 2 +- 101 files changed, 1732 insertions(+), 567 deletions(-) create mode 100755 src/core/hle/kernel/k_capabilities.cpp create mode 100755 src/core/hle/kernel/k_capabilities.h create mode 100755 src/core/hle/kernel/svc_version.h diff --git a/README.md b/README.md index 76bd93dae..244df25c1 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 3345. +This is the source code for early-access 3347. ## Legal Notice diff --git a/dist/yuzu.ico b/dist/yuzu.ico index df3be8464fcb3c0fb10308472ed527dbcdc10d61..7c998a5c53a3b079b67c526586c269f2efd25447 100755 GIT binary patch literal 25355 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 s8oRK@Tvf05pF literal 23159 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 diff --git a/dist/yuzu.svg b/dist/yuzu.svg index 93171d1bf..98ded2d8f 100755 --- a/dist/yuzu.svg +++ b/dist/yuzu.svg @@ -1 +1 @@ -Artboard 1 \ No newline at end of file +newAsset 7 \ No newline at end of file diff --git a/src/common/input.h b/src/common/input.h index 1f9db5af2..5cfacc307 100755 --- a/src/common/input.h +++ b/src/common/input.h @@ -130,6 +130,8 @@ struct ButtonStatus { bool inverted{}; // Press once to activate, press again to release bool toggle{}; + // Spams the button when active + bool turbo{}; // Internal lock for the toggle status bool locked{}; }; diff --git a/src/common/polyfill_thread.h b/src/common/polyfill_thread.h index b2c929d2f..b4c94a5fc 100755 --- a/src/common/polyfill_thread.h +++ b/src/common/polyfill_thread.h @@ -41,17 +41,18 @@ bool StoppableTimedWait(std::stop_token token, const std::chrono::duration #include #include -#include +#include #include #include #include #include #include +#include namespace std { namespace polyfill { -using stop_state_callbacks = list>; +using stop_state_callback = size_t; class stop_state { public: @@ -59,61 +60,69 @@ public: ~stop_state() = default; bool request_stop() { - stop_state_callbacks callbacks; + unique_lock lk{m_lock}; - { - scoped_lock lk{m_lock}; - - if (m_stop_requested.load()) { - // Already set, nothing to do - return false; - } - - // Set as requested - m_stop_requested = true; - - // Copy callback list - callbacks = m_callbacks; + if (m_stop_requested) { + // Already set, nothing to do. + return false; } - for (auto callback : callbacks) { - callback(); + // Mark stop requested. + m_stop_requested = true; + + while (!m_callbacks.empty()) { + // Get an iterator to the first element. + const auto it = m_callbacks.begin(); + + // Move the callback function out of the map. + function f; + swap(it->second, f); + + // Erase the now-empty map element. + m_callbacks.erase(it); + + // Run the callback. + if (f) { + f(); + } } return true; } bool stop_requested() const { - return m_stop_requested.load(); + unique_lock lk{m_lock}; + return m_stop_requested; } - stop_state_callbacks::const_iterator insert_callback(function f) { - stop_state_callbacks::const_iterator ret{}; - bool should_run{}; + stop_state_callback insert_callback(function f) { + unique_lock lk{m_lock}; - { - scoped_lock lk{m_lock}; - should_run = m_stop_requested.load(); - m_callbacks.push_front(f); - ret = m_callbacks.begin(); - } - - if (should_run) { - f(); + if (m_stop_requested) { + // Stop already requested. Don't insert anything, + // just run the callback synchronously. + if (f) { + f(); + } + return 0; } + // Insert the callback. + stop_state_callback ret = ++m_next_callback; + m_callbacks.emplace(ret, move(f)); return ret; } - void remove_callback(stop_state_callbacks::const_iterator it) { - scoped_lock lk{m_lock}; - m_callbacks.erase(it); + void remove_callback(stop_state_callback cb) { + unique_lock lk{m_lock}; + m_callbacks.erase(cb); } private: - mutex m_lock; - atomic m_stop_requested; - stop_state_callbacks m_callbacks; + mutable recursive_mutex m_lock; + map> m_callbacks; + stop_state_callback m_next_callback{0}; + bool m_stop_requested{false}; }; } // namespace polyfill @@ -223,7 +232,7 @@ public: } ~stop_callback() { if (m_stop_state && m_callback) { - m_stop_state->remove_callback(*m_callback); + m_stop_state->remove_callback(m_callback); } } @@ -234,7 +243,7 @@ public: private: shared_ptr m_stop_state; - optional m_callback; + polyfill::stop_state_callback m_callback; }; template diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp index b847fd4d9..b9e897f3b 100755 --- a/src/common/string_util.cpp +++ b/src/common/string_util.cpp @@ -30,7 +30,7 @@ std::string ToUpper(std::string str) { return str; } -std::string StringFromBuffer(const std::vector& data) { +std::string StringFromBuffer(std::span data) { return std::string(data.begin(), std::find(data.begin(), data.end(), '\0')); } diff --git a/src/common/string_util.h b/src/common/string_util.h index 2ba7cadb9..e03bde0a5 100755 --- a/src/common/string_util.h +++ b/src/common/string_util.h @@ -5,6 +5,7 @@ #pragma once #include +#include #include #include #include "common/common_types.h" @@ -17,7 +18,7 @@ namespace Common { /// Make a string uppercase [[nodiscard]] std::string ToUpper(std::string str); -[[nodiscard]] std::string StringFromBuffer(const std::vector& data); +[[nodiscard]] std::string StringFromBuffer(std::span data); [[nodiscard]] std::string StripSpaces(const std::string& s); [[nodiscard]] std::string StripQuotes(const std::string& s); diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 2269a9edd..ec95e3ca0 100755 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -182,6 +182,8 @@ add_library(core STATIC hle/kernel/k_auto_object_container.cpp hle/kernel/k_auto_object_container.h hle/kernel/k_affinity_mask.h + hle/kernel/k_capabilities.cpp + hle/kernel/k_capabilities.h hle/kernel/k_class_token.cpp hle/kernel/k_class_token.h hle/kernel/k_client_port.cpp diff --git a/src/core/hardware_properties.h b/src/core/hardware_properties.h index 23e20c2cc..c0d8d267e 100755 --- a/src/core/hardware_properties.h +++ b/src/core/hardware_properties.h @@ -25,6 +25,26 @@ constexpr std::array()> VirtualToPhysicalCoreMap{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, }; +static constexpr inline size_t NumVirtualCores = Common::BitSize(); + +static constexpr inline u64 VirtualCoreMask = [] { + u64 mask = 0; + for (size_t i = 0; i < NumVirtualCores; ++i) { + mask |= (UINT64_C(1) << i); + } + return mask; +}(); + +static constexpr inline u64 ConvertVirtualCoreMaskToPhysical(u64 v_core_mask) { + u64 p_core_mask = 0; + while (v_core_mask != 0) { + const u64 next = std::countr_zero(v_core_mask); + v_core_mask &= ~(static_cast(1) << next); + p_core_mask |= (static_cast(1) << VirtualToPhysicalCoreMap[next]); + } + return p_core_mask; +} + // Cortex-A57 supports 4 memory watchpoints constexpr u64 NUM_WATCHPOINTS = 4; diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 3d43145a1..08932ac77 100755 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -687,6 +687,7 @@ void EmulatedController::SetButton(const Common::Input::CallbackStatus& callback } current_status.toggle = new_status.toggle; + current_status.turbo = new_status.turbo; current_status.uuid = uuid; // Update button status with current @@ -1548,7 +1549,7 @@ NpadButtonState EmulatedController::GetNpadButtons() const { if (is_configuring) { return {}; } - return controller.npad_button_state; + return {controller.npad_button_state.raw & GetTurboButtonMask()}; } DebugPadButton EmulatedController::GetDebugPadButtons() const { @@ -1656,4 +1657,74 @@ void EmulatedController::DeleteCallback(int key) { } callback_list.erase(iterator); } + +void EmulatedController::TurboButtonUpdate() { + turbo_button_state = !turbo_button_state; +} + +NpadButton EmulatedController::GetTurboButtonMask() const { + // Apply no mask when disabled + if (!turbo_button_state) { + return {NpadButton::All}; + } + + NpadButtonState button_mask{}; + for (std::size_t index = 0; index < controller.button_values.size(); ++index) { + if (!controller.button_values[index].turbo) { + continue; + } + + switch (index) { + case Settings::NativeButton::A: + button_mask.a.Assign(1); + break; + case Settings::NativeButton::B: + button_mask.b.Assign(1); + break; + case Settings::NativeButton::X: + button_mask.x.Assign(1); + break; + case Settings::NativeButton::Y: + button_mask.y.Assign(1); + break; + case Settings::NativeButton::L: + button_mask.l.Assign(1); + break; + case Settings::NativeButton::R: + button_mask.r.Assign(1); + break; + case Settings::NativeButton::ZL: + button_mask.zl.Assign(1); + break; + case Settings::NativeButton::ZR: + button_mask.zr.Assign(1); + break; + case Settings::NativeButton::DLeft: + button_mask.left.Assign(1); + break; + case Settings::NativeButton::DUp: + button_mask.up.Assign(1); + break; + case Settings::NativeButton::DRight: + button_mask.right.Assign(1); + break; + case Settings::NativeButton::DDown: + button_mask.down.Assign(1); + break; + case Settings::NativeButton::SL: + button_mask.left_sl.Assign(1); + button_mask.right_sl.Assign(1); + break; + case Settings::NativeButton::SR: + button_mask.left_sr.Assign(1); + button_mask.right_sr.Assign(1); + break; + default: + break; + } + } + + return static_cast(~button_mask.raw); +} + } // namespace Core::HID diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index dd97bb817..77963e32d 100755 --- a/src/core/hid/emulated_controller.h +++ b/src/core/hid/emulated_controller.h @@ -411,6 +411,9 @@ public: */ void DeleteCallback(int key); + /// Swaps the state of the turbo buttons + void TurboButtonUpdate(); + private: /// creates input devices from params void LoadDevices(); @@ -511,6 +514,8 @@ private: */ void TriggerOnChange(ControllerTriggerType type, bool is_service_update); + NpadButton GetTurboButtonMask() const; + const NpadIdType npad_id_type; NpadStyleIndex npad_type{NpadStyleIndex::None}; NpadStyleIndex original_npad_type{NpadStyleIndex::None}; @@ -520,6 +525,7 @@ private: bool system_buttons_enabled{true}; f32 motion_sensitivity{0.01f}; bool force_update_motion{false}; + bool turbo_button_state{false}; // Temporary values to avoid doing changes while the controller is in configuring mode NpadStyleIndex tmp_npad_type{NpadStyleIndex::None}; diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index b2879a24d..20c051364 100755 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp @@ -11,6 +11,7 @@ #include "common/common_funcs.h" #include "common/common_types.h" #include "common/logging/log.h" +#include "common/scratch_buffer.h" #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/hle_ipc.h" #include "core/hle/kernel/k_auto_object.h" @@ -325,7 +326,7 @@ Result HLERequestContext::WriteToOutgoingCommandBuffer(KThread& requesting_threa return ResultSuccess; } -std::vector HLERequestContext::ReadBuffer(std::size_t buffer_index) const { +std::vector HLERequestContext::ReadBufferCopy(std::size_t buffer_index) const { const bool is_buffer_a{BufferDescriptorA().size() > buffer_index && BufferDescriptorA()[buffer_index].Size()}; if (is_buffer_a) { @@ -345,6 +346,33 @@ std::vector HLERequestContext::ReadBuffer(std::size_t buffer_index) const { } } +std::span HLERequestContext::ReadBuffer(std::size_t buffer_index) const { + static thread_local std::array, 2> read_buffer_a; + static thread_local std::array, 2> read_buffer_x; + + const bool is_buffer_a{BufferDescriptorA().size() > buffer_index && + BufferDescriptorA()[buffer_index].Size()}; + if (is_buffer_a) { + ASSERT_OR_EXECUTE_MSG( + BufferDescriptorA().size() > buffer_index, { return {}; }, + "BufferDescriptorA invalid buffer_index {}", buffer_index); + auto& read_buffer = read_buffer_a[buffer_index]; + read_buffer.resize_destructive(BufferDescriptorA()[buffer_index].Size()); + memory.ReadBlock(BufferDescriptorA()[buffer_index].Address(), read_buffer.data(), + read_buffer.size()); + return read_buffer; + } else { + ASSERT_OR_EXECUTE_MSG( + BufferDescriptorX().size() > buffer_index, { return {}; }, + "BufferDescriptorX invalid buffer_index {}", buffer_index); + auto& read_buffer = read_buffer_x[buffer_index]; + read_buffer.resize_destructive(BufferDescriptorX()[buffer_index].Size()); + memory.ReadBlock(BufferDescriptorX()[buffer_index].Address(), read_buffer.data(), + read_buffer.size()); + return read_buffer; + } +} + std::size_t HLERequestContext::WriteBuffer(const void* buffer, std::size_t size, std::size_t buffer_index) const { if (size == 0) { diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index 1715c0924..8eeeee4e1 100755 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -270,8 +271,11 @@ public: return domain_message_header.has_value(); } - /// Helper function to read a buffer using the appropriate buffer descriptor - [[nodiscard]] std::vector ReadBuffer(std::size_t buffer_index = 0) const; + /// Helper function to get a span of a buffer using the appropriate buffer descriptor + [[nodiscard]] std::span ReadBuffer(std::size_t buffer_index = 0) const; + + /// Helper function to read a copy of a buffer using the appropriate buffer descriptor + [[nodiscard]] std::vector ReadBufferCopy(std::size_t buffer_index = 0) const; /// Helper function to write a buffer using the appropriate buffer descriptor std::size_t WriteBuffer(const void* buffer, std::size_t size, diff --git a/src/core/hle/kernel/k_capabilities.cpp b/src/core/hle/kernel/k_capabilities.cpp new file mode 100755 index 000000000..60afdc8f1 --- /dev/null +++ b/src/core/hle/kernel/k_capabilities.cpp @@ -0,0 +1,358 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hardware_properties.h" +#include "core/hle/kernel/k_capabilities.h" +#include "core/hle/kernel/k_memory_layout.h" +#include "core/hle/kernel/k_page_table.h" +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/svc_results.h" +#include "core/hle/kernel/svc_version.h" + +namespace Kernel { + +Result KCapabilities::InitializeForKIP(std::span kern_caps, KPageTable* page_table) { + // We're initializing an initial process. + m_svc_access_flags.reset(); + m_irq_access_flags.reset(); + m_debug_capabilities = 0; + m_handle_table_size = 0; + m_intended_kernel_version = 0; + m_program_type = 0; + + // Initial processes may run on all cores. + constexpr u64 VirtMask = Core::Hardware::VirtualCoreMask; + constexpr u64 PhysMask = Core::Hardware::ConvertVirtualCoreMaskToPhysical(VirtMask); + + m_core_mask = VirtMask; + m_phys_core_mask = PhysMask; + + // Initial processes may use any user priority they like. + m_priority_mask = ~0xFULL; + + // Here, Nintendo sets the kernel version to the current kernel version. + // We will follow suit and set the version to the highest supported kernel version. + KernelVersion intended_kernel_version{}; + intended_kernel_version.major_version.Assign(Svc::SupportedKernelMajorVersion); + intended_kernel_version.minor_version.Assign(Svc::SupportedKernelMinorVersion); + m_intended_kernel_version = intended_kernel_version.raw; + + // Parse the capabilities array. + R_RETURN(this->SetCapabilities(kern_caps, page_table)); +} + +Result KCapabilities::InitializeForUser(std::span user_caps, KPageTable* page_table) { + // We're initializing a user process. + m_svc_access_flags.reset(); + m_irq_access_flags.reset(); + m_debug_capabilities = 0; + m_handle_table_size = 0; + m_intended_kernel_version = 0; + m_program_type = 0; + + // User processes must specify what cores/priorities they can use. + m_core_mask = 0; + m_priority_mask = 0; + + // Parse the user capabilities array. + R_RETURN(this->SetCapabilities(user_caps, page_table)); +} + +Result KCapabilities::SetCorePriorityCapability(const u32 cap) { + // We can't set core/priority if we've already set them. + R_UNLESS(m_core_mask == 0, ResultInvalidArgument); + R_UNLESS(m_priority_mask == 0, ResultInvalidArgument); + + // Validate the core/priority. + CorePriority pack{cap}; + const u32 min_core = pack.minimum_core_id; + const u32 max_core = pack.maximum_core_id; + const u32 max_prio = pack.lowest_thread_priority; + const u32 min_prio = pack.highest_thread_priority; + + R_UNLESS(min_core <= max_core, ResultInvalidCombination); + R_UNLESS(min_prio <= max_prio, ResultInvalidCombination); + R_UNLESS(max_core < Core::Hardware::NumVirtualCores, ResultInvalidCoreId); + + ASSERT(max_prio < Common::BitSize()); + + // Set core mask. + for (auto core_id = min_core; core_id <= max_core; core_id++) { + m_core_mask |= (1ULL << core_id); + } + ASSERT((m_core_mask & Core::Hardware::VirtualCoreMask) == m_core_mask); + + // Set physical core mask. + m_phys_core_mask = Core::Hardware::ConvertVirtualCoreMaskToPhysical(m_core_mask); + + // Set priority mask. + for (auto prio = min_prio; prio <= max_prio; prio++) { + m_priority_mask |= (1ULL << prio); + } + + // We must have some core/priority we can use. + R_UNLESS(m_core_mask != 0, ResultInvalidArgument); + R_UNLESS(m_priority_mask != 0, ResultInvalidArgument); + + // Processes must not have access to kernel thread priorities. + R_UNLESS((m_priority_mask & 0xF) == 0, ResultInvalidArgument); + + R_SUCCEED(); +} + +Result KCapabilities::SetSyscallMaskCapability(const u32 cap, u32& set_svc) { + // Validate the index. + SyscallMask pack{cap}; + const u32 mask = pack.mask; + const u32 index = pack.index; + + const u32 index_flag = (1U << index); + R_UNLESS((set_svc & index_flag) == 0, ResultInvalidCombination); + set_svc |= index_flag; + + // Set SVCs. + for (size_t i = 0; i < decltype(SyscallMask::mask)::bits; i++) { + const u32 svc_id = static_cast(decltype(SyscallMask::mask)::bits* index + i); + if (mask & (1U << i)) { + R_UNLESS(this->SetSvcAllowed(svc_id), ResultOutOfRange); + } + } + + R_SUCCEED(); +} + +Result KCapabilities::MapRange_(const u32 cap, const u32 size_cap, KPageTable* page_table) { + const auto range_pack = MapRange{cap}; + const auto size_pack = MapRangeSize{size_cap}; + + // Get/validate address/size + const u64 phys_addr = range_pack.address.Value() * PageSize; + + // Validate reserved bits are unused. + R_UNLESS(size_pack.reserved.Value() == 0, ResultOutOfRange); + + const size_t num_pages = size_pack.pages; + const size_t size = num_pages * PageSize; + R_UNLESS(num_pages != 0, ResultInvalidSize); + R_UNLESS(phys_addr < phys_addr + size, ResultInvalidAddress); + R_UNLESS(((phys_addr + size - 1) & ~PhysicalMapAllowedMask) == 0, ResultInvalidAddress); + + // Do the mapping. + [[maybe_unused]] const KMemoryPermission perm = range_pack.read_only.Value() + ? KMemoryPermission::UserRead + : KMemoryPermission::UserReadWrite; + if (MapRangeSize{size_cap}.normal) { + // R_RETURN(page_table->MapStatic(phys_addr, size, perm)); + } else { + // R_RETURN(page_table->MapIo(phys_addr, size, perm)); + } + + UNIMPLEMENTED(); + R_SUCCEED(); +} + +Result KCapabilities::MapIoPage_(const u32 cap, KPageTable* page_table) { + // Get/validate address/size + const u64 phys_addr = MapIoPage{cap}.address.Value() * PageSize; + const size_t num_pages = 1; + const size_t size = num_pages * PageSize; + R_UNLESS(num_pages != 0, ResultInvalidSize); + R_UNLESS(phys_addr < phys_addr + size, ResultInvalidAddress); + R_UNLESS(((phys_addr + size - 1) & ~PhysicalMapAllowedMask) == 0, ResultInvalidAddress); + + // Do the mapping. + // R_RETURN(page_table->MapIo(phys_addr, size, KMemoryPermission_UserReadWrite)); + + UNIMPLEMENTED(); + R_SUCCEED(); +} + +template +Result KCapabilities::ProcessMapRegionCapability(const u32 cap, F f) { + // Define the allowed memory regions. + constexpr std::array MemoryRegions{ + KMemoryRegionType_None, + KMemoryRegionType_KernelTraceBuffer, + KMemoryRegionType_OnMemoryBootImage, + KMemoryRegionType_DTB, + }; + + // Extract regions/read only. + const MapRegion pack{cap}; + const std::array types{pack.region0, pack.region1, pack.region2}; + const std::array ro{pack.read_only0, pack.read_only1, pack.read_only2}; + + for (size_t i = 0; i < types.size(); i++) { + const auto type = types[i]; + const auto perm = ro[i] ? KMemoryPermission::UserRead : KMemoryPermission::UserReadWrite; + switch (type) { + case RegionType::NoMapping: + break; + case RegionType::KernelTraceBuffer: + case RegionType::OnMemoryBootImage: + case RegionType::DTB: + R_TRY(f(MemoryRegions[static_cast(type)], perm)); + break; + default: + R_THROW(ResultNotFound); + } + } + + R_SUCCEED(); +} + +Result KCapabilities::MapRegion_(const u32 cap, KPageTable* page_table) { + // Map each region into the process's page table. + R_RETURN(ProcessMapRegionCapability( + cap, [](KMemoryRegionType region_type, KMemoryPermission perm) -> Result { + // R_RETURN(page_table->MapRegion(region_type, perm)); + UNIMPLEMENTED(); + R_SUCCEED(); + })); +} + +Result KCapabilities::CheckMapRegion(KernelCore& kernel, const u32 cap) { + // Check that each region has a physical backing store. + R_RETURN(ProcessMapRegionCapability( + cap, [&](KMemoryRegionType region_type, KMemoryPermission perm) -> Result { + R_UNLESS(kernel.MemoryLayout().GetPhysicalMemoryRegionTree().FindFirstDerived( + region_type) != nullptr, + ResultOutOfRange); + R_SUCCEED(); + })); +} + +Result KCapabilities::SetInterruptPairCapability(const u32 cap) { + // Extract interrupts. + const InterruptPair pack{cap}; + const std::array ids{pack.interrupt_id0, pack.interrupt_id1}; + + for (size_t i = 0; i < ids.size(); i++) { + if (ids[i] != PaddingInterruptId) { + UNIMPLEMENTED(); + // R_UNLESS(Kernel::GetInterruptManager().IsInterruptDefined(ids[i]), ResultOutOfRange); + // R_UNLESS(this->SetInterruptPermitted(ids[i]), ResultOutOfRange); + } + } + + R_SUCCEED(); +} + +Result KCapabilities::SetProgramTypeCapability(const u32 cap) { + // Validate. + const ProgramType pack{cap}; + R_UNLESS(pack.reserved == 0, ResultReservedUsed); + + m_program_type = pack.type; + R_SUCCEED(); +} + +Result KCapabilities::SetKernelVersionCapability(const u32 cap) { + // Ensure we haven't set our version before. + R_UNLESS(KernelVersion{m_intended_kernel_version}.major_version == 0, ResultInvalidArgument); + + // Set, ensure that we set a valid version. + m_intended_kernel_version = cap; + R_UNLESS(KernelVersion{m_intended_kernel_version}.major_version != 0, ResultInvalidArgument); + + R_SUCCEED(); +} + +Result KCapabilities::SetHandleTableCapability(const u32 cap) { + // Validate. + const HandleTable pack{cap}; + R_UNLESS(pack.reserved == 0, ResultReservedUsed); + + m_handle_table_size = pack.size; + R_SUCCEED(); +} + +Result KCapabilities::SetDebugFlagsCapability(const u32 cap) { + // Validate. + const DebugFlags pack{cap}; + R_UNLESS(pack.reserved == 0, ResultReservedUsed); + + DebugFlags debug_capabilities{m_debug_capabilities}; + debug_capabilities.allow_debug.Assign(pack.allow_debug); + debug_capabilities.force_debug.Assign(pack.force_debug); + m_debug_capabilities = debug_capabilities.raw; + + R_SUCCEED(); +} + +Result KCapabilities::SetCapability(const u32 cap, u32& set_flags, u32& set_svc, + KPageTable* page_table) { + // Validate this is a capability we can act on. + const auto type = GetCapabilityType(cap); + R_UNLESS(type != CapabilityType::Invalid, ResultInvalidArgument); + + // If the type is padding, we have no work to do. + R_SUCCEED_IF(type == CapabilityType::Padding); + + // Check that we haven't already processed this capability. + const auto flag = GetCapabilityFlag(type); + R_UNLESS(((set_flags & InitializeOnceFlags) & flag) == 0, ResultInvalidCombination); + set_flags |= flag; + + // Process the capability. + switch (type) { + case CapabilityType::CorePriority: + R_RETURN(this->SetCorePriorityCapability(cap)); + case CapabilityType::SyscallMask: + R_RETURN(this->SetSyscallMaskCapability(cap, set_svc)); + case CapabilityType::MapIoPage: + R_RETURN(this->MapIoPage_(cap, page_table)); + case CapabilityType::MapRegion: + R_RETURN(this->MapRegion_(cap, page_table)); + case CapabilityType::InterruptPair: + R_RETURN(this->SetInterruptPairCapability(cap)); + case CapabilityType::ProgramType: + R_RETURN(this->SetProgramTypeCapability(cap)); + case CapabilityType::KernelVersion: + R_RETURN(this->SetKernelVersionCapability(cap)); + case CapabilityType::HandleTable: + R_RETURN(this->SetHandleTableCapability(cap)); + case CapabilityType::DebugFlags: + R_RETURN(this->SetDebugFlagsCapability(cap)); + default: + R_THROW(ResultInvalidArgument); + } +} + +Result KCapabilities::SetCapabilities(std::span caps, KPageTable* page_table) { + u32 set_flags = 0, set_svc = 0; + + for (size_t i = 0; i < caps.size(); i++) { + const u32 cap{caps[i]}; + + if (GetCapabilityType(cap) == CapabilityType::MapRange) { + // Check that the pair cap exists. + R_UNLESS((++i) < caps.size(), ResultInvalidCombination); + + // Check the pair cap is a map range cap. + const u32 size_cap{caps[i]}; + R_UNLESS(GetCapabilityType(size_cap) == CapabilityType::MapRange, + ResultInvalidCombination); + + // Map the range. + R_TRY(this->MapRange_(cap, size_cap, page_table)); + } else { + R_TRY(this->SetCapability(cap, set_flags, set_svc, page_table)); + } + } + + R_SUCCEED(); +} + +Result KCapabilities::CheckCapabilities(KernelCore& kernel, std::span caps) { + for (auto cap : caps) { + // Check the capability refers to a valid region. + if (GetCapabilityType(cap) == CapabilityType::MapRegion) { + R_TRY(CheckMapRegion(kernel, cap)); + } + } + + R_SUCCEED(); +} + +} // namespace Kernel diff --git a/src/core/hle/kernel/k_capabilities.h b/src/core/hle/kernel/k_capabilities.h new file mode 100755 index 000000000..cd96f8d23 --- /dev/null +++ b/src/core/hle/kernel/k_capabilities.h @@ -0,0 +1,295 @@ + +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +#include "common/bit_field.h" +#include "common/common_types.h" + +#include "core/hle/kernel/svc_types.h" +#include "core/hle/result.h" + +namespace Kernel { + +class KPageTable; +class KernelCore; + +class KCapabilities { +public: + constexpr explicit KCapabilities() = default; + + Result InitializeForKIP(std::span kern_caps, KPageTable* page_table); + Result InitializeForUser(std::span user_caps, KPageTable* page_table); + + static Result CheckCapabilities(KernelCore& kernel, std::span user_caps); + + constexpr u64 GetCoreMask() const { + return m_core_mask; + } + + constexpr u64 GetPhysicalCoreMask() const { + return m_phys_core_mask; + } + + constexpr u64 GetPriorityMask() const { + return m_priority_mask; + } + + constexpr s32 GetHandleTableSize() const { + return m_handle_table_size; + } + + constexpr const Svc::SvcAccessFlagSet& GetSvcPermissions() const { + return m_svc_access_flags; + } + + constexpr bool IsPermittedSvc(u32 id) const { + return (id < m_svc_access_flags.size()) && m_svc_access_flags[id]; + } + + constexpr bool IsPermittedInterrupt(u32 id) const { + return (id < m_irq_access_flags.size()) && m_irq_access_flags[id]; + } + + constexpr bool IsPermittedDebug() const { + return DebugFlags{m_debug_capabilities}.allow_debug.Value() != 0; + } + + constexpr bool CanForceDebug() const { + return DebugFlags{m_debug_capabilities}.force_debug.Value() != 0; + } + + constexpr u32 GetIntendedKernelMajorVersion() const { + return KernelVersion{m_intended_kernel_version}.major_version; + } + + constexpr u32 GetIntendedKernelMinorVersion() const { + return KernelVersion{m_intended_kernel_version}.minor_version; + } + +private: + static constexpr size_t InterruptIdCount = 0x400; + using InterruptFlagSet = std::bitset; + + enum class CapabilityType : u32 { + CorePriority = (1U << 3) - 1, + SyscallMask = (1U << 4) - 1, + MapRange = (1U << 6) - 1, + MapIoPage = (1U << 7) - 1, + MapRegion = (1U << 10) - 1, + InterruptPair = (1U << 11) - 1, + ProgramType = (1U << 13) - 1, + KernelVersion = (1U << 14) - 1, + HandleTable = (1U << 15) - 1, + DebugFlags = (1U << 16) - 1, + + Invalid = 0U, + Padding = ~0U, + }; + + using RawCapabilityValue = u32; + + static constexpr CapabilityType GetCapabilityType(const RawCapabilityValue value) { + return static_cast((~value & (value + 1)) - 1); + } + + static constexpr u32 GetCapabilityFlag(CapabilityType type) { + return static_cast(type) + 1; + } + + template + static constexpr inline u32 CapabilityFlag = static_cast(Type) + 1; + + template + static constexpr inline u32 CapabilityId = std::countr_zero(CapabilityFlag); + + union CorePriority { + static_assert(CapabilityId + 1 == 4); + + RawCapabilityValue raw; + BitField<0, 4, CapabilityType> id; + BitField<4, 6, u32> lowest_thread_priority; + BitField<10, 6, u32> highest_thread_priority; + BitField<16, 8, u32> minimum_core_id; + BitField<24, 8, u32> maximum_core_id; + }; + + union SyscallMask { + static_assert(CapabilityId + 1 == 5); + + RawCapabilityValue raw; + BitField<0, 5, CapabilityType> id; + BitField<5, 24, u32> mask; + BitField<29, 3, u32> index; + }; + + // #undef MESOSPHERE_ENABLE_LARGE_PHYSICAL_ADDRESS_CAPABILITIES + static constexpr u64 PhysicalMapAllowedMask = (1ULL << 36) - 1; + + union MapRange { + static_assert(CapabilityId + 1 == 7); + + RawCapabilityValue raw; + BitField<0, 7, CapabilityType> id; + BitField<7, 24, u32> address; + BitField<31, 1, u32> read_only; + }; + + union MapRangeSize { + static_assert(CapabilityId + 1 == 7); + + RawCapabilityValue raw; + BitField<0, 7, CapabilityType> id; + BitField<7, 20, u32> pages; + BitField<27, 4, u32> reserved; + BitField<31, 1, u32> normal; + }; + + union MapIoPage { + static_assert(CapabilityId + 1 == 8); + + RawCapabilityValue raw; + BitField<0, 8, CapabilityType> id; + BitField<8, 24, u32> address; + }; + + enum class RegionType : u32 { + NoMapping = 0, + KernelTraceBuffer = 1, + OnMemoryBootImage = 2, + DTB = 3, + }; + + union MapRegion { + static_assert(CapabilityId + 1 == 11); + + RawCapabilityValue raw; + BitField<0, 11, CapabilityType> id; + BitField<11, 6, RegionType> region0; + BitField<17, 1, u32> read_only0; + BitField<18, 6, RegionType> region1; + BitField<24, 1, u32> read_only1; + BitField<25, 6, RegionType> region2; + BitField<31, 1, u32> read_only2; + }; + + union InterruptPair { + static_assert(CapabilityId + 1 == 12); + + RawCapabilityValue raw; + BitField<0, 12, CapabilityType> id; + BitField<12, 10, u32> interrupt_id0; + BitField<22, 10, u32> interrupt_id1; + }; + + union ProgramType { + static_assert(CapabilityId + 1 == 14); + + RawCapabilityValue raw; + BitField<0, 14, CapabilityType> id; + BitField<14, 3, u32> type; + BitField<17, 15, u32> reserved; + }; + + union KernelVersion { + static_assert(CapabilityId + 1 == 15); + + RawCapabilityValue raw; + BitField<0, 15, CapabilityType> id; + BitField<15, 4, u32> major_version; + BitField<19, 13, u32> minor_version; + }; + + union HandleTable { + static_assert(CapabilityId + 1 == 16); + + RawCapabilityValue raw; + BitField<0, 16, CapabilityType> id; + BitField<16, 10, u32> size; + BitField<26, 6, u32> reserved; + }; + + union DebugFlags { + static_assert(CapabilityId + 1 == 17); + + RawCapabilityValue raw; + BitField<0, 17, CapabilityType> id; + BitField<17, 1, u32> allow_debug; + BitField<18, 1, u32> force_debug; + BitField<19, 13, u32> reserved; + }; + + static_assert(sizeof(CorePriority) == 4); + static_assert(sizeof(SyscallMask) == 4); + static_assert(sizeof(MapRange) == 4); + static_assert(sizeof(MapRangeSize) == 4); + static_assert(sizeof(MapIoPage) == 4); + static_assert(sizeof(MapRegion) == 4); + static_assert(sizeof(InterruptPair) == 4); + static_assert(sizeof(ProgramType) == 4); + static_assert(sizeof(KernelVersion) == 4); + static_assert(sizeof(HandleTable) == 4); + static_assert(sizeof(DebugFlags) == 4); + + static constexpr u32 InitializeOnceFlags = + CapabilityFlag | CapabilityFlag | + CapabilityFlag | + CapabilityFlag | CapabilityFlag; + + static const u32 PaddingInterruptId = 0x3FF; + static_assert(PaddingInterruptId < InterruptIdCount); + +private: + constexpr bool SetSvcAllowed(u32 id) { + if (id < m_svc_access_flags.size()) [[likely]] { + m_svc_access_flags[id] = true; + return true; + } else { + return false; + } + } + + constexpr bool SetInterruptPermitted(u32 id) { + if (id < m_irq_access_flags.size()) [[likely]] { + m_irq_access_flags[id] = true; + return true; + } else { + return false; + } + } + + Result SetCorePriorityCapability(const u32 cap); + Result SetSyscallMaskCapability(const u32 cap, u32& set_svc); + Result MapRange_(const u32 cap, const u32 size_cap, KPageTable* page_table); + Result MapIoPage_(const u32 cap, KPageTable* page_table); + Result MapRegion_(const u32 cap, KPageTable* page_table); + Result SetInterruptPairCapability(const u32 cap); + Result SetProgramTypeCapability(const u32 cap); + Result SetKernelVersionCapability(const u32 cap); + Result SetHandleTableCapability(const u32 cap); + Result SetDebugFlagsCapability(const u32 cap); + + template + static Result ProcessMapRegionCapability(const u32 cap, F f); + static Result CheckMapRegion(KernelCore& kernel, const u32 cap); + + Result SetCapability(const u32 cap, u32& set_flags, u32& set_svc, KPageTable* page_table); + Result SetCapabilities(std::span caps, KPageTable* page_table); + +private: + Svc::SvcAccessFlagSet m_svc_access_flags{}; + InterruptFlagSet m_irq_access_flags{}; + u64 m_core_mask{}; + u64 m_phys_core_mask{}; + u64 m_priority_mask{}; + u32 m_debug_capabilities{}; + s32 m_handle_table_size{}; + u32 m_intended_kernel_version{}; + u32 m_program_type{}; +}; + +} // namespace Kernel diff --git a/src/core/hle/kernel/svc_types.h b/src/core/hle/kernel/svc_types.h index 06f1d219b..44a7a7014 100755 --- a/src/core/hle/kernel/svc_types.h +++ b/src/core/hle/kernel/svc_types.h @@ -3,6 +3,8 @@ #pragma once +#include + #include "common/common_funcs.h" #include "common/common_types.h" @@ -592,4 +594,7 @@ struct CreateProcessParameter { }; static_assert(sizeof(CreateProcessParameter) == 0x30); +constexpr size_t NumSupervisorCalls = 0xC0; +using SvcAccessFlagSet = std::bitset; + } // namespace Kernel::Svc diff --git a/src/core/hle/kernel/svc_version.h b/src/core/hle/kernel/svc_version.h new file mode 100755 index 000000000..e4f47b34b --- /dev/null +++ b/src/core/hle/kernel/svc_version.h @@ -0,0 +1,58 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/bit_field.h" +#include "common/common_types.h" +#include "common/literals.h" + +namespace Kernel::Svc { + +constexpr inline u32 ConvertToSvcMajorVersion(u32 sdk) { + return sdk + 4; +} +constexpr inline u32 ConvertToSdkMajorVersion(u32 svc) { + return svc - 4; +} + +constexpr inline u32 ConvertToSvcMinorVersion(u32 sdk) { + return sdk; +} +constexpr inline u32 ConvertToSdkMinorVersion(u32 svc) { + return svc; +} + +union KernelVersion { + u32 value; + BitField<0, 4, u32> minor_version; + BitField<4, 13, u32> major_version; +}; + +constexpr inline u32 EncodeKernelVersion(u32 major, u32 minor) { + return decltype(KernelVersion::minor_version)::FormatValue(minor) | + decltype(KernelVersion::major_version)::FormatValue(major); +} + +constexpr inline u32 GetKernelMajorVersion(u32 encoded) { + return std::bit_cast(encoded).Value(); +} + +constexpr inline u32 GetKernelMinorVersion(u32 encoded) { + return std::bit_cast(encoded).Value(); +} + +// Nintendo doesn't support programs targeting SVC versions < 3.0. +constexpr inline u32 RequiredKernelMajorVersion = 3; +constexpr inline u32 RequiredKernelMinorVersion = 0; +constexpr inline u32 RequiredKernelVersion = + EncodeKernelVersion(RequiredKernelMajorVersion, RequiredKernelMinorVersion); + +// This is the highest SVC version supported, to be updated on new kernel releases. +// NOTE: Official kernel versions have SVC major = SDK major + 4, SVC minor = SDK minor. +constexpr inline u32 SupportedKernelMajorVersion = ConvertToSvcMajorVersion(15); +constexpr inline u32 SupportedKernelMinorVersion = ConvertToSvcMinorVersion(3); +constexpr inline u32 SupportedKernelVersion = + EncodeKernelVersion(SupportedKernelMajorVersion, SupportedKernelMinorVersion); + +} // namespace Kernel::Svc diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 294e7692b..d6f46e3c5 100755 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -1124,7 +1124,7 @@ void IStorageAccessor::Write(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u64 offset{rp.Pop()}; - const std::vector data{ctx.ReadBuffer()}; + const auto data{ctx.ReadBuffer()}; const std::size_t size{std::min(data.size(), backing.GetSize() - offset)}; LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, size); diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index 539240842..a0d67412e 100755 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp @@ -112,7 +112,7 @@ private: void RequestUpdate(Kernel::HLERequestContext& ctx) { LOG_TRACE(Service_Audio, "called"); - std::vector input{ctx.ReadBuffer(0)}; + const auto input{ctx.ReadBuffer(0)}; // These buffers are written manually to avoid an issue with WriteBuffer throwing errors for // checking size 0. Performance size is 0 for most games. diff --git a/src/core/hle/service/audio/hwopus.cpp b/src/core/hle/service/audio/hwopus.cpp index 4508ea821..5953f1c4a 100755 --- a/src/core/hle/service/audio/hwopus.cpp +++ b/src/core/hle/service/audio/hwopus.cpp @@ -93,7 +93,7 @@ private: ctx.WriteBuffer(samples); } - bool DecodeOpusData(u32& consumed, u32& sample_count, const std::vector& input, + bool DecodeOpusData(u32& consumed, u32& sample_count, std::span input, std::vector& output, u64* out_performance_time) const { const auto start_time = std::chrono::steady_clock::now(); const std::size_t raw_output_sz = output.size() * sizeof(opus_int16); diff --git a/src/core/hle/service/es/es.cpp b/src/core/hle/service/es/es.cpp index c62f53b3d..1447688b4 100755 --- a/src/core/hle/service/es/es.cpp +++ b/src/core/hle/service/es/es.cpp @@ -122,7 +122,7 @@ private: void ImportTicket(Kernel::HLERequestContext& ctx) { const auto ticket = ctx.ReadBuffer(); - const auto cert = ctx.ReadBuffer(1); + [[maybe_unused]] const auto cert = ctx.ReadBuffer(1); if (ticket.size() < sizeof(Core::Crypto::Ticket)) { LOG_ERROR(Service_ETicket, "The input buffer is not large enough!"); diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index 779072def..34af9fd94 100755 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp @@ -190,7 +190,7 @@ private: return; } - const std::vector data = ctx.ReadBuffer(); + const auto data = ctx.ReadBuffer(); ASSERT_MSG( static_cast(data.size()) <= length, @@ -401,11 +401,8 @@ public: } void RenameFile(Kernel::HLERequestContext& ctx) { - std::vector buffer = ctx.ReadBuffer(0); - const std::string src_name = Common::StringFromBuffer(buffer); - - buffer = ctx.ReadBuffer(1); - const std::string dst_name = Common::StringFromBuffer(buffer); + const std::string src_name = Common::StringFromBuffer(ctx.ReadBuffer(0)); + const std::string dst_name = Common::StringFromBuffer(ctx.ReadBuffer(1)); LOG_DEBUG(Service_FS, "called. file '{}' to file '{}'", src_name, dst_name); diff --git a/src/core/hle/service/glue/arp.cpp b/src/core/hle/service/glue/arp.cpp index 03bd04f1a..a33de8166 100755 --- a/src/core/hle/service/glue/arp.cpp +++ b/src/core/hle/service/glue/arp.cpp @@ -228,7 +228,8 @@ private: return; } - control = ctx.ReadBuffer(); + // TODO: Can this be a span? + control = ctx.ReadBufferCopy(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 6b09bbf25..d2ac820a6 100755 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -428,6 +428,9 @@ void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) { return; } + // This function is unique to yuzu for the turbo buttons to work properly + controller.device->TurboButtonUpdate(); + auto& pad_entry = controller.npad_pad_state; auto& trigger_entry = controller.npad_trigger_state; const auto button_state = controller.device->GetNpadButtons(); @@ -755,11 +758,12 @@ Core::HID::NpadStyleTag Controller_NPad::GetSupportedStyleSet() const { return hid_core.GetSupportedStyleTag(); } -void Controller_NPad::SetSupportedNpadIdTypes(u8* data, std::size_t length) { +void Controller_NPad::SetSupportedNpadIdTypes(std::span data) { + const auto length = data.size(); ASSERT(length > 0 && (length % sizeof(u32)) == 0); supported_npad_id_types.clear(); supported_npad_id_types.resize(length / sizeof(u32)); - std::memcpy(supported_npad_id_types.data(), data, length); + std::memcpy(supported_npad_id_types.data(), data.data(), length); } void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) { diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index cfcc27222..968d671ac 100755 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -6,6 +6,7 @@ #include #include #include +#include #include "common/bit_field.h" #include "common/common_types.h" @@ -95,7 +96,7 @@ public: void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set); Core::HID::NpadStyleTag GetSupportedStyleSet() const; - void SetSupportedNpadIdTypes(u8* data, std::size_t length); + void SetSupportedNpadIdTypes(std::span data); void GetSupportedNpadIdTypes(u32* data, std::size_t max_length); std::size_t GetSupportedNpadIdTypesSize() const; diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 224d9f86a..1944ae64f 100755 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -1026,7 +1026,7 @@ void Hid::SetSupportedNpadIdType(Kernel::HLERequestContext& ctx) { const auto applet_resource_user_id{rp.Pop()}; applet_resource->GetController(HidController::NPad) - .SetSupportedNpadIdTypes(ctx.ReadBuffer().data(), ctx.GetReadBufferSize()); + .SetSupportedNpadIdTypes(ctx.ReadBuffer()); LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); @@ -2104,7 +2104,7 @@ void Hid::WritePalmaRgbLedPatternEntry(Kernel::HLERequestContext& ctx) { const auto connection_handle{rp.PopRaw()}; const auto unknown{rp.Pop()}; - const auto buffer = ctx.ReadBuffer(); + [[maybe_unused]] const auto buffer = ctx.ReadBuffer(); LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, unknown={}", connection_handle.npad_id, unknown); diff --git a/src/core/hle/service/hid/hidbus/hidbus_base.h b/src/core/hle/service/hid/hidbus/hidbus_base.h index ff5c56c9a..9258b73d6 100755 --- a/src/core/hle/service/hid/hidbus/hidbus_base.h +++ b/src/core/hle/service/hid/hidbus/hidbus_base.h @@ -4,6 +4,7 @@ #pragma once #include +#include #include "common/common_types.h" #include "core/hle/result.h" @@ -150,7 +151,7 @@ public: } // Assigns a command from data - virtual bool SetCommand(const std::vector& data) { + virtual bool SetCommand(std::span data) { return {}; } diff --git a/src/core/hle/service/hid/hidbus/ringcon.cpp b/src/core/hle/service/hid/hidbus/ringcon.cpp index 2b8615ecc..8181531d7 100755 --- a/src/core/hle/service/hid/hidbus/ringcon.cpp +++ b/src/core/hle/service/hid/hidbus/ringcon.cpp @@ -116,7 +116,7 @@ std::vector RingController::GetReply() const { } } -bool RingController::SetCommand(const std::vector& data) { +bool RingController::SetCommand(std::span data) { if (data.size() < 4) { LOG_ERROR(Service_HID, "Command size not supported {}", data.size()); command = RingConCommands::Error; diff --git a/src/core/hle/service/hid/hidbus/ringcon.h b/src/core/hle/service/hid/hidbus/ringcon.h index e6e3b6572..1a7b477af 100755 --- a/src/core/hle/service/hid/hidbus/ringcon.h +++ b/src/core/hle/service/hid/hidbus/ringcon.h @@ -4,6 +4,7 @@ #pragma once #include +#include #include "common/common_types.h" #include "core/hle/service/hid/hidbus/hidbus_base.h" @@ -31,7 +32,7 @@ public: u8 GetDeviceId() const override; // Assigns a command from data - bool SetCommand(const std::vector& data) override; + bool SetCommand(std::span data) override; // Returns a reply from a command std::vector GetReply() const override; diff --git a/src/core/hle/service/hid/hidbus/starlink.cpp b/src/core/hle/service/hid/hidbus/starlink.cpp index 6d1d01629..3d74eaafd 100755 --- a/src/core/hle/service/hid/hidbus/starlink.cpp +++ b/src/core/hle/service/hid/hidbus/starlink.cpp @@ -42,7 +42,7 @@ std::vector Starlink::GetReply() const { return {}; } -bool Starlink::SetCommand(const std::vector& data) { +bool Starlink::SetCommand(std::span data) { LOG_ERROR(Service_HID, "Command not implemented"); return false; } diff --git a/src/core/hle/service/hid/hidbus/starlink.h b/src/core/hle/service/hid/hidbus/starlink.h index 9be7d54c1..bbde84384 100755 --- a/src/core/hle/service/hid/hidbus/starlink.h +++ b/src/core/hle/service/hid/hidbus/starlink.h @@ -29,7 +29,7 @@ public: u8 GetDeviceId() const override; // Assigns a command from data - bool SetCommand(const std::vector& data) override; + bool SetCommand(std::span data) override; // Returns a reply from a command std::vector GetReply() const override; diff --git a/src/core/hle/service/hid/hidbus/stubbed.cpp b/src/core/hle/service/hid/hidbus/stubbed.cpp index 7489d50cb..c4215443c 100755 --- a/src/core/hle/service/hid/hidbus/stubbed.cpp +++ b/src/core/hle/service/hid/hidbus/stubbed.cpp @@ -43,7 +43,7 @@ std::vector HidbusStubbed::GetReply() const { return {}; } -bool HidbusStubbed::SetCommand(const std::vector& data) { +bool HidbusStubbed::SetCommand(std::span data) { LOG_ERROR(Service_HID, "Command not implemented"); return false; } diff --git a/src/core/hle/service/hid/hidbus/stubbed.h b/src/core/hle/service/hid/hidbus/stubbed.h index 0130707a9..0772bc6ee 100755 --- a/src/core/hle/service/hid/hidbus/stubbed.h +++ b/src/core/hle/service/hid/hidbus/stubbed.h @@ -29,7 +29,7 @@ public: u8 GetDeviceId() const override; // Assigns a command from data - bool SetCommand(const std::vector& data) override; + bool SetCommand(std::span data) override; // Returns a reply from a command std::vector GetReply() const override; diff --git a/src/core/hle/service/jit/jit.cpp b/src/core/hle/service/jit/jit.cpp index a6369d52a..ec162fd31 100755 --- a/src/core/hle/service/jit/jit.cpp +++ b/src/core/hle/service/jit/jit.cpp @@ -62,7 +62,7 @@ public: const auto parameters{rp.PopRaw()}; // Optional input/output buffers - std::vector input_buffer{ctx.CanReadBuffer() ? ctx.ReadBuffer() : std::vector()}; + const auto input_buffer{ctx.CanReadBuffer() ? ctx.ReadBuffer() : std::span()}; std::vector output_buffer(ctx.CanWriteBuffer() ? ctx.GetWriteBufferSize() : 0); // Function call prototype: @@ -132,7 +132,7 @@ public: const auto command{rp.PopRaw()}; // Optional input/output buffers - std::vector input_buffer{ctx.CanReadBuffer() ? ctx.ReadBuffer() : std::vector()}; + const auto input_buffer{ctx.CanReadBuffer() ? ctx.ReadBuffer() : std::span()}; std::vector output_buffer(ctx.CanWriteBuffer() ? ctx.GetWriteBufferSize() : 0); // Function call prototype: diff --git a/src/core/hle/service/ldn/ldn.cpp b/src/core/hle/service/ldn/ldn.cpp index a5ff82944..edd170132 100755 --- a/src/core/hle/service/ldn/ldn.cpp +++ b/src/core/hle/service/ldn/ldn.cpp @@ -427,7 +427,7 @@ public: } void SetAdvertiseData(Kernel::HLERequestContext& ctx) { - std::vector read_buffer = ctx.ReadBuffer(); + const auto read_buffer = ctx.ReadBuffer(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(lan_discovery.SetAdvertiseData(read_buffer)); @@ -479,7 +479,7 @@ public: parameters.security_config.passphrase_size, parameters.security_config.security_mode, parameters.local_communication_version); - const std::vector read_buffer = ctx.ReadBuffer(); + const auto read_buffer = ctx.ReadBuffer(); if (read_buffer.size() != sizeof(NetworkInfo)) { LOG_ERROR(Frontend, "NetworkInfo doesn't match read_buffer size!"); IPC::ResponseBuilder rb{ctx, 2}; diff --git a/src/core/hle/service/nvdrv/devices/nvdevice.h b/src/core/hle/service/nvdrv/devices/nvdevice.h index 4020821b3..607d303d7 100755 --- a/src/core/hle/service/nvdrv/devices/nvdevice.h +++ b/src/core/hle/service/nvdrv/devices/nvdevice.h @@ -3,7 +3,9 @@ #pragma once +#include #include + #include "common/common_types.h" #include "core/hle/service/nvdrv/nvdata.h" @@ -31,7 +33,7 @@ public: * @param output A buffer where the output data will be written to. * @returns The result code of the ioctl. */ - virtual NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector& input, + virtual NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span input, std::vector& output) = 0; /** @@ -42,8 +44,8 @@ public: * @param output A buffer where the output data will be written to. * @returns The result code of the ioctl. */ - virtual NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector& input, - const std::vector& inline_input, std::vector& output) = 0; + virtual NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span input, + std::span inline_input, std::vector& output) = 0; /** * Handles an ioctl3 request. @@ -53,7 +55,7 @@ public: * @param inline_output A buffer where the inlined output data will be written to. * @returns The result code of the ioctl. */ - virtual NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector& input, + virtual NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span input, std::vector& output, std::vector& inline_output) = 0; /** diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp index 6ddd40e85..0b4bb7bcb 100755 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp @@ -17,19 +17,19 @@ nvdisp_disp0::nvdisp_disp0(Core::System& system_, NvCore::Container& core) : nvdevice{system_}, container{core}, nvmap{core.GetNvMapFile()} {} nvdisp_disp0::~nvdisp_disp0() = default; -NvResult nvdisp_disp0::Ioctl1(DeviceFD fd, Ioctl command, const std::vector& input, +NvResult nvdisp_disp0::Ioctl1(DeviceFD fd, Ioctl command, std::span input, std::vector& output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; } -NvResult nvdisp_disp0::Ioctl2(DeviceFD fd, Ioctl command, const std::vector& input, - const std::vector& inline_input, std::vector& output) { +NvResult nvdisp_disp0::Ioctl2(DeviceFD fd, Ioctl command, std::span input, + std::span inline_input, std::vector& output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; } -NvResult nvdisp_disp0::Ioctl3(DeviceFD fd, Ioctl command, const std::vector& input, +NvResult nvdisp_disp0::Ioctl3(DeviceFD fd, Ioctl command, std::span input, std::vector& output, std::vector& inline_output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h index e420efb4f..7e09e3331 100755 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h @@ -25,12 +25,12 @@ public: explicit nvdisp_disp0(Core::System& system_, NvCore::Container& core); ~nvdisp_disp0() override; - NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector& input, + NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span input, std::vector& output) override; - NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector& input, - const std::vector& inline_input, std::vector& output) override; - NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector& input, - std::vector& output, std::vector& inline_output) override; + NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span input, + std::span inline_input, std::vector& output) override; + NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span input, std::vector& output, + std::vector& inline_output) override; void OnOpen(DeviceFD fd) override; void OnClose(DeviceFD fd) override; 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 72a4d18eb..ad4fab423 100755 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp @@ -27,7 +27,7 @@ nvhost_as_gpu::nvhost_as_gpu(Core::System& system_, Module& module_, NvCore::Con nvhost_as_gpu::~nvhost_as_gpu() = default; -NvResult nvhost_as_gpu::Ioctl1(DeviceFD fd, Ioctl command, const std::vector& input, +NvResult nvhost_as_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span input, std::vector& output) { switch (command.group) { case 'A': @@ -60,13 +60,13 @@ NvResult nvhost_as_gpu::Ioctl1(DeviceFD fd, Ioctl command, const std::vector return NvResult::NotImplemented; } -NvResult nvhost_as_gpu::Ioctl2(DeviceFD fd, Ioctl command, const std::vector& input, - const std::vector& inline_input, std::vector& output) { +NvResult nvhost_as_gpu::Ioctl2(DeviceFD fd, Ioctl command, std::span input, + std::span inline_input, std::vector& output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; } -NvResult nvhost_as_gpu::Ioctl3(DeviceFD fd, Ioctl command, const std::vector& input, +NvResult nvhost_as_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span input, std::vector& output, std::vector& inline_output) { switch (command.group) { case 'A': @@ -87,7 +87,7 @@ NvResult nvhost_as_gpu::Ioctl3(DeviceFD fd, Ioctl command, const std::vector void nvhost_as_gpu::OnOpen(DeviceFD fd) {} void nvhost_as_gpu::OnClose(DeviceFD fd) {} -NvResult nvhost_as_gpu::AllocAsEx(const std::vector& input, std::vector& output) { +NvResult nvhost_as_gpu::AllocAsEx(std::span input, std::vector& output) { IoctlAllocAsEx params{}; std::memcpy(¶ms, input.data(), input.size()); @@ -141,7 +141,7 @@ NvResult nvhost_as_gpu::AllocAsEx(const std::vector& input, std::vector& return NvResult::Success; } -NvResult nvhost_as_gpu::AllocateSpace(const std::vector& input, std::vector& output) { +NvResult nvhost_as_gpu::AllocateSpace(std::span input, std::vector& output) { IoctlAllocSpace params{}; std::memcpy(¶ms, input.data(), input.size()); @@ -220,7 +220,7 @@ void nvhost_as_gpu::FreeMappingLocked(u64 offset) { mapping_map.erase(offset); } -NvResult nvhost_as_gpu::FreeSpace(const std::vector& input, std::vector& output) { +NvResult nvhost_as_gpu::FreeSpace(std::span input, std::vector& output) { IoctlFreeSpace params{}; std::memcpy(¶ms, input.data(), input.size()); @@ -266,7 +266,7 @@ NvResult nvhost_as_gpu::FreeSpace(const std::vector& input, std::vector& return NvResult::Success; } -NvResult nvhost_as_gpu::Remap(const std::vector& input, std::vector& output) { +NvResult nvhost_as_gpu::Remap(std::span input, std::vector& output) { const auto num_entries = input.size() / sizeof(IoctlRemapEntry); LOG_DEBUG(Service_NVDRV, "called, num_entries=0x{:X}", num_entries); @@ -320,7 +320,7 @@ NvResult nvhost_as_gpu::Remap(const std::vector& input, std::vector& out return NvResult::Success; } -NvResult nvhost_as_gpu::MapBufferEx(const std::vector& input, std::vector& output) { +NvResult nvhost_as_gpu::MapBufferEx(std::span input, std::vector& output) { IoctlMapBufferEx params{}; std::memcpy(¶ms, input.data(), input.size()); @@ -424,7 +424,7 @@ NvResult nvhost_as_gpu::MapBufferEx(const std::vector& input, std::vector& input, std::vector& output) { +NvResult nvhost_as_gpu::UnmapBuffer(std::span input, std::vector& output) { IoctlUnmapBuffer params{}; std::memcpy(¶ms, input.data(), input.size()); @@ -463,7 +463,7 @@ NvResult nvhost_as_gpu::UnmapBuffer(const std::vector& input, std::vector& input, std::vector& output) { +NvResult nvhost_as_gpu::BindChannel(std::span input, std::vector& output) { IoctlBindChannel params{}; std::memcpy(¶ms, input.data(), input.size()); LOG_DEBUG(Service_NVDRV, "called, fd={:X}", params.fd); @@ -492,7 +492,7 @@ void nvhost_as_gpu::GetVARegionsImpl(IoctlGetVaRegions& params) { }; } -NvResult nvhost_as_gpu::GetVARegions(const std::vector& input, std::vector& output) { +NvResult nvhost_as_gpu::GetVARegions(std::span input, std::vector& output) { IoctlGetVaRegions params{}; std::memcpy(¶ms, input.data(), input.size()); @@ -511,7 +511,7 @@ NvResult nvhost_as_gpu::GetVARegions(const std::vector& input, std::vector& input, std::vector& output, +NvResult nvhost_as_gpu::GetVARegions(std::span input, std::vector& output, std::vector& inline_output) { IoctlGetVaRegions params{}; std::memcpy(¶ms, input.data(), input.size()); 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 57b6a1f76..dcfc02419 100755 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h @@ -47,12 +47,12 @@ public: explicit nvhost_as_gpu(Core::System& system_, Module& module, NvCore::Container& core); ~nvhost_as_gpu() override; - NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector& input, + NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span input, std::vector& output) override; - NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector& input, - const std::vector& inline_input, std::vector& output) override; - NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector& input, - std::vector& output, std::vector& inline_output) override; + NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span input, + std::span inline_input, std::vector& output) override; + NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span input, std::vector& output, + std::vector& inline_output) override; void OnOpen(DeviceFD fd) override; void OnClose(DeviceFD fd) override; @@ -138,17 +138,17 @@ private: static_assert(sizeof(IoctlGetVaRegions) == 16 + sizeof(VaRegion) * 2, "IoctlGetVaRegions is incorrect size"); - NvResult AllocAsEx(const std::vector& input, std::vector& output); - NvResult AllocateSpace(const std::vector& input, std::vector& output); - NvResult Remap(const std::vector& input, std::vector& output); - NvResult MapBufferEx(const std::vector& input, std::vector& output); - NvResult UnmapBuffer(const std::vector& input, std::vector& output); - NvResult FreeSpace(const std::vector& input, std::vector& output); - NvResult BindChannel(const std::vector& input, std::vector& output); + NvResult AllocAsEx(std::span input, std::vector& output); + NvResult AllocateSpace(std::span input, std::vector& output); + NvResult Remap(std::span input, std::vector& output); + NvResult MapBufferEx(std::span input, std::vector& output); + NvResult UnmapBuffer(std::span input, std::vector& output); + NvResult FreeSpace(std::span input, std::vector& output); + NvResult BindChannel(std::span input, std::vector& output); void GetVARegionsImpl(IoctlGetVaRegions& params); - NvResult GetVARegions(const std::vector& input, std::vector& output); - NvResult GetVARegions(const std::vector& input, std::vector& output, + NvResult GetVARegions(std::span input, std::vector& output); + NvResult GetVARegions(std::span input, std::vector& output, std::vector& inline_output); void FreeMappingLocked(u64 offset); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index c6ab1447c..c2091af86 100755 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp @@ -34,7 +34,7 @@ nvhost_ctrl::~nvhost_ctrl() { } } -NvResult nvhost_ctrl::Ioctl1(DeviceFD fd, Ioctl command, const std::vector& input, +NvResult nvhost_ctrl::Ioctl1(DeviceFD fd, Ioctl command, std::span input, std::vector& output) { switch (command.group) { case 0x0: @@ -63,13 +63,13 @@ NvResult nvhost_ctrl::Ioctl1(DeviceFD fd, Ioctl command, const std::vector& return NvResult::NotImplemented; } -NvResult nvhost_ctrl::Ioctl2(DeviceFD fd, Ioctl command, const std::vector& input, - const std::vector& inline_input, std::vector& output) { +NvResult nvhost_ctrl::Ioctl2(DeviceFD fd, Ioctl command, std::span input, + std::span inline_input, std::vector& output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; } -NvResult nvhost_ctrl::Ioctl3(DeviceFD fd, Ioctl command, const std::vector& input, +NvResult nvhost_ctrl::Ioctl3(DeviceFD fd, Ioctl command, std::span input, std::vector& output, std::vector& inline_outpu) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; @@ -79,7 +79,7 @@ void nvhost_ctrl::OnOpen(DeviceFD fd) {} void nvhost_ctrl::OnClose(DeviceFD fd) {} -NvResult nvhost_ctrl::NvOsGetConfigU32(const std::vector& input, std::vector& output) { +NvResult nvhost_ctrl::NvOsGetConfigU32(std::span input, std::vector& output) { IocGetConfigParams params{}; std::memcpy(¶ms, input.data(), sizeof(params)); LOG_TRACE(Service_NVDRV, "called, setting={}!{}", params.domain_str.data(), @@ -87,7 +87,7 @@ NvResult nvhost_ctrl::NvOsGetConfigU32(const std::vector& input, std::vector return NvResult::ConfigVarNotFound; // Returns error on production mode } -NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector& input, std::vector& output, +NvResult nvhost_ctrl::IocCtrlEventWait(std::span input, std::vector& output, bool is_allocation) { IocCtrlEventWaitParams params{}; std::memcpy(¶ms, input.data(), sizeof(params)); @@ -231,7 +231,7 @@ NvResult nvhost_ctrl::FreeEvent(u32 slot) { return NvResult::Success; } -NvResult nvhost_ctrl::IocCtrlEventRegister(const std::vector& input, std::vector& output) { +NvResult nvhost_ctrl::IocCtrlEventRegister(std::span input, std::vector& output) { IocCtrlEventRegisterParams params{}; std::memcpy(¶ms, input.data(), sizeof(params)); const u32 event_id = params.user_event_id; @@ -252,8 +252,7 @@ NvResult nvhost_ctrl::IocCtrlEventRegister(const std::vector& input, std::ve return NvResult::Success; } -NvResult nvhost_ctrl::IocCtrlEventUnregister(const std::vector& input, - std::vector& output) { +NvResult nvhost_ctrl::IocCtrlEventUnregister(std::span input, std::vector& output) { IocCtrlEventUnregisterParams params{}; std::memcpy(¶ms, input.data(), sizeof(params)); const u32 event_id = params.user_event_id & 0x00FF; @@ -263,7 +262,7 @@ NvResult nvhost_ctrl::IocCtrlEventUnregister(const std::vector& input, return FreeEvent(event_id); } -NvResult nvhost_ctrl::IocCtrlEventUnregisterBatch(const std::vector& input, +NvResult nvhost_ctrl::IocCtrlEventUnregisterBatch(std::span input, std::vector& output) { IocCtrlEventUnregisterBatchParams params{}; std::memcpy(¶ms, input.data(), sizeof(params)); @@ -282,7 +281,7 @@ NvResult nvhost_ctrl::IocCtrlEventUnregisterBatch(const std::vector& input, return NvResult::Success; } -NvResult nvhost_ctrl::IocCtrlClearEventWait(const std::vector& input, std::vector& output) { +NvResult nvhost_ctrl::IocCtrlClearEventWait(std::span input, std::vector& output) { IocCtrlEventClearParams params{}; std::memcpy(¶ms, input.data(), sizeof(params)); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h index 48a670384..f96466030 100755 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h @@ -25,12 +25,12 @@ public: NvCore::Container& core); ~nvhost_ctrl() override; - NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector& input, + NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span input, std::vector& output) override; - NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector& input, - const std::vector& inline_input, std::vector& output) override; - NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector& input, - std::vector& output, std::vector& inline_output) override; + NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span input, + std::span inline_input, std::vector& output) override; + NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span input, std::vector& output, + std::vector& inline_output) override; void OnOpen(DeviceFD fd) override; void OnClose(DeviceFD fd) override; @@ -186,13 +186,13 @@ private: static_assert(sizeof(IocCtrlEventUnregisterBatchParams) == 8, "IocCtrlEventKill is incorrect size"); - NvResult NvOsGetConfigU32(const std::vector& input, std::vector& output); - NvResult IocCtrlEventWait(const std::vector& input, std::vector& output, + NvResult NvOsGetConfigU32(std::span input, std::vector& output); + NvResult IocCtrlEventWait(std::span input, std::vector& output, bool is_allocation); - NvResult IocCtrlEventRegister(const std::vector& input, std::vector& output); - NvResult IocCtrlEventUnregister(const std::vector& input, std::vector& output); - NvResult IocCtrlEventUnregisterBatch(const std::vector& input, std::vector& output); - NvResult IocCtrlClearEventWait(const std::vector& input, std::vector& output); + NvResult IocCtrlEventRegister(std::span input, std::vector& output); + NvResult IocCtrlEventUnregister(std::span input, std::vector& output); + NvResult IocCtrlEventUnregisterBatch(std::span input, std::vector& output); + NvResult IocCtrlClearEventWait(std::span input, std::vector& output); NvResult FreeEvent(u32 slot); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp index 0e5721a9b..8784d091f 100755 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp @@ -21,7 +21,7 @@ nvhost_ctrl_gpu::~nvhost_ctrl_gpu() { events_interface.FreeEvent(unknown_event); } -NvResult nvhost_ctrl_gpu::Ioctl1(DeviceFD fd, Ioctl command, const std::vector& input, +NvResult nvhost_ctrl_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span input, std::vector& output) { switch (command.group) { case 'G': @@ -53,13 +53,13 @@ NvResult nvhost_ctrl_gpu::Ioctl1(DeviceFD fd, Ioctl command, const std::vector& input, - const std::vector& inline_input, std::vector& output) { +NvResult nvhost_ctrl_gpu::Ioctl2(DeviceFD fd, Ioctl command, std::span input, + std::span inline_input, std::vector& output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; } -NvResult nvhost_ctrl_gpu::Ioctl3(DeviceFD fd, Ioctl command, const std::vector& input, +NvResult nvhost_ctrl_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span input, std::vector& output, std::vector& inline_output) { switch (command.group) { case 'G': @@ -82,8 +82,7 @@ NvResult nvhost_ctrl_gpu::Ioctl3(DeviceFD fd, Ioctl command, const std::vector& input, - std::vector& output) { +NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span input, std::vector& output) { LOG_DEBUG(Service_NVDRV, "called"); IoctlCharacteristics params{}; std::memcpy(¶ms, input.data(), input.size()); @@ -128,7 +127,7 @@ NvResult nvhost_ctrl_gpu::GetCharacteristics(const std::vector& input, return NvResult::Success; } -NvResult nvhost_ctrl_gpu::GetCharacteristics(const std::vector& input, std::vector& output, +NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span input, std::vector& output, std::vector& inline_output) { LOG_DEBUG(Service_NVDRV, "called"); IoctlCharacteristics params{}; @@ -176,7 +175,7 @@ NvResult nvhost_ctrl_gpu::GetCharacteristics(const std::vector& input, std:: return NvResult::Success; } -NvResult nvhost_ctrl_gpu::GetTPCMasks(const std::vector& input, std::vector& output) { +NvResult nvhost_ctrl_gpu::GetTPCMasks(std::span input, std::vector& output) { IoctlGpuGetTpcMasksArgs params{}; std::memcpy(¶ms, input.data(), input.size()); LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size=0x{:X}", params.mask_buffer_size); @@ -187,7 +186,7 @@ NvResult nvhost_ctrl_gpu::GetTPCMasks(const std::vector& input, std::vector< return NvResult::Success; } -NvResult nvhost_ctrl_gpu::GetTPCMasks(const std::vector& input, std::vector& output, +NvResult nvhost_ctrl_gpu::GetTPCMasks(std::span input, std::vector& output, std::vector& inline_output) { IoctlGpuGetTpcMasksArgs params{}; std::memcpy(¶ms, input.data(), input.size()); @@ -200,7 +199,7 @@ NvResult nvhost_ctrl_gpu::GetTPCMasks(const std::vector& input, std::vector< return NvResult::Success; } -NvResult nvhost_ctrl_gpu::GetActiveSlotMask(const std::vector& input, std::vector& output) { +NvResult nvhost_ctrl_gpu::GetActiveSlotMask(std::span input, std::vector& output) { LOG_DEBUG(Service_NVDRV, "called"); IoctlActiveSlotMask params{}; @@ -213,7 +212,7 @@ NvResult nvhost_ctrl_gpu::GetActiveSlotMask(const std::vector& input, std::v return NvResult::Success; } -NvResult nvhost_ctrl_gpu::ZCullGetCtxSize(const std::vector& input, std::vector& output) { +NvResult nvhost_ctrl_gpu::ZCullGetCtxSize(std::span input, std::vector& output) { LOG_DEBUG(Service_NVDRV, "called"); IoctlZcullGetCtxSize params{}; @@ -225,7 +224,7 @@ NvResult nvhost_ctrl_gpu::ZCullGetCtxSize(const std::vector& input, std::vec return NvResult::Success; } -NvResult nvhost_ctrl_gpu::ZCullGetInfo(const std::vector& input, std::vector& output) { +NvResult nvhost_ctrl_gpu::ZCullGetInfo(std::span input, std::vector& output) { LOG_DEBUG(Service_NVDRV, "called"); IoctlNvgpuGpuZcullGetInfoArgs params{}; @@ -248,7 +247,7 @@ NvResult nvhost_ctrl_gpu::ZCullGetInfo(const std::vector& input, std::vector return NvResult::Success; } -NvResult nvhost_ctrl_gpu::ZBCSetTable(const std::vector& input, std::vector& output) { +NvResult nvhost_ctrl_gpu::ZBCSetTable(std::span input, std::vector& output) { LOG_WARNING(Service_NVDRV, "(STUBBED) called"); IoctlZbcSetTable params{}; @@ -264,7 +263,7 @@ NvResult nvhost_ctrl_gpu::ZBCSetTable(const std::vector& input, std::vector< return NvResult::Success; } -NvResult nvhost_ctrl_gpu::ZBCQueryTable(const std::vector& input, std::vector& output) { +NvResult nvhost_ctrl_gpu::ZBCQueryTable(std::span input, std::vector& output) { LOG_WARNING(Service_NVDRV, "(STUBBED) called"); IoctlZbcQueryTable params{}; @@ -274,7 +273,7 @@ NvResult nvhost_ctrl_gpu::ZBCQueryTable(const std::vector& input, std::vecto return NvResult::Success; } -NvResult nvhost_ctrl_gpu::FlushL2(const std::vector& input, std::vector& output) { +NvResult nvhost_ctrl_gpu::FlushL2(std::span input, std::vector& output) { LOG_WARNING(Service_NVDRV, "(STUBBED) called"); IoctlFlushL2 params{}; @@ -284,7 +283,7 @@ NvResult nvhost_ctrl_gpu::FlushL2(const std::vector& input, std::vector& return NvResult::Success; } -NvResult nvhost_ctrl_gpu::GetGpuTime(const std::vector& input, std::vector& output) { +NvResult nvhost_ctrl_gpu::GetGpuTime(std::span input, std::vector& output) { LOG_DEBUG(Service_NVDRV, "called"); IoctlGetGpuTime params{}; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h index a7641bd05..225ce57c2 100755 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h @@ -21,12 +21,12 @@ public: explicit nvhost_ctrl_gpu(Core::System& system_, EventInterface& events_interface_); ~nvhost_ctrl_gpu() override; - NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector& input, + NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span input, std::vector& output) override; - NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector& input, - const std::vector& inline_input, std::vector& output) override; - NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector& input, - std::vector& output, std::vector& inline_output) override; + NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span input, + std::span inline_input, std::vector& output) override; + NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span input, std::vector& output, + std::vector& inline_output) override; void OnOpen(DeviceFD fd) override; void OnClose(DeviceFD fd) override; @@ -151,21 +151,21 @@ private: }; static_assert(sizeof(IoctlGetGpuTime) == 0x10, "IoctlGetGpuTime is incorrect size"); - NvResult GetCharacteristics(const std::vector& input, std::vector& output); - NvResult GetCharacteristics(const std::vector& input, std::vector& output, + NvResult GetCharacteristics(std::span input, std::vector& output); + NvResult GetCharacteristics(std::span input, std::vector& output, std::vector& inline_output); - NvResult GetTPCMasks(const std::vector& input, std::vector& output); - NvResult GetTPCMasks(const std::vector& input, std::vector& output, + NvResult GetTPCMasks(std::span input, std::vector& output); + NvResult GetTPCMasks(std::span input, std::vector& output, std::vector& inline_output); - NvResult GetActiveSlotMask(const std::vector& input, std::vector& output); - NvResult ZCullGetCtxSize(const std::vector& input, std::vector& output); - NvResult ZCullGetInfo(const std::vector& input, std::vector& output); - NvResult ZBCSetTable(const std::vector& input, std::vector& output); - NvResult ZBCQueryTable(const std::vector& input, std::vector& output); - NvResult FlushL2(const std::vector& input, std::vector& output); - NvResult GetGpuTime(const std::vector& input, std::vector& output); + NvResult GetActiveSlotMask(std::span input, std::vector& output); + NvResult ZCullGetCtxSize(std::span input, std::vector& output); + NvResult ZCullGetInfo(std::span input, std::vector& output); + NvResult ZBCSetTable(std::span input, std::vector& output); + NvResult ZBCQueryTable(std::span input, std::vector& output); + NvResult FlushL2(std::span input, std::vector& output); + NvResult GetGpuTime(std::span input, std::vector& output); EventInterface& events_interface; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp index 1873c40f2..1cfba5819 100755 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp @@ -46,7 +46,7 @@ nvhost_gpu::~nvhost_gpu() { syncpoint_manager.FreeSyncpoint(channel_syncpoint); } -NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, const std::vector& input, +NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span input, std::vector& output) { switch (command.group) { case 0x0: @@ -98,8 +98,8 @@ NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, const std::vector& i return NvResult::NotImplemented; }; -NvResult nvhost_gpu::Ioctl2(DeviceFD fd, Ioctl command, const std::vector& input, - const std::vector& inline_input, std::vector& output) { +NvResult nvhost_gpu::Ioctl2(DeviceFD fd, Ioctl command, std::span input, + std::span inline_input, std::vector& output) { switch (command.group) { case 'H': switch (command.cmd) { @@ -112,7 +112,7 @@ NvResult nvhost_gpu::Ioctl2(DeviceFD fd, Ioctl command, const std::vector& i return NvResult::NotImplemented; } -NvResult nvhost_gpu::Ioctl3(DeviceFD fd, Ioctl command, const std::vector& input, +NvResult nvhost_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span input, std::vector& output, std::vector& inline_output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; @@ -121,7 +121,7 @@ NvResult nvhost_gpu::Ioctl3(DeviceFD fd, Ioctl command, const std::vector& i void nvhost_gpu::OnOpen(DeviceFD fd) {} void nvhost_gpu::OnClose(DeviceFD fd) {} -NvResult nvhost_gpu::SetNVMAPfd(const std::vector& input, std::vector& output) { +NvResult nvhost_gpu::SetNVMAPfd(std::span input, std::vector& output) { IoctlSetNvmapFD params{}; std::memcpy(¶ms, input.data(), input.size()); LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); @@ -130,7 +130,7 @@ NvResult nvhost_gpu::SetNVMAPfd(const std::vector& input, std::vector& o return NvResult::Success; } -NvResult nvhost_gpu::SetClientData(const std::vector& input, std::vector& output) { +NvResult nvhost_gpu::SetClientData(std::span input, std::vector& output) { LOG_DEBUG(Service_NVDRV, "called"); IoctlClientData params{}; @@ -139,7 +139,7 @@ NvResult nvhost_gpu::SetClientData(const std::vector& input, std::vector return NvResult::Success; } -NvResult nvhost_gpu::GetClientData(const std::vector& input, std::vector& output) { +NvResult nvhost_gpu::GetClientData(std::span input, std::vector& output) { LOG_DEBUG(Service_NVDRV, "called"); IoctlClientData params{}; @@ -149,7 +149,7 @@ NvResult nvhost_gpu::GetClientData(const std::vector& input, std::vector return NvResult::Success; } -NvResult nvhost_gpu::ZCullBind(const std::vector& input, std::vector& output) { +NvResult nvhost_gpu::ZCullBind(std::span input, std::vector& output) { std::memcpy(&zcull_params, input.data(), input.size()); LOG_DEBUG(Service_NVDRV, "called, gpu_va={:X}, mode={:X}", zcull_params.gpu_va, zcull_params.mode); @@ -158,7 +158,7 @@ NvResult nvhost_gpu::ZCullBind(const std::vector& input, std::vector& ou return NvResult::Success; } -NvResult nvhost_gpu::SetErrorNotifier(const std::vector& input, std::vector& output) { +NvResult nvhost_gpu::SetErrorNotifier(std::span input, std::vector& output) { IoctlSetErrorNotifier params{}; std::memcpy(¶ms, input.data(), input.size()); LOG_WARNING(Service_NVDRV, "(STUBBED) called, offset={:X}, size={:X}, mem={:X}", params.offset, @@ -168,14 +168,14 @@ NvResult nvhost_gpu::SetErrorNotifier(const std::vector& input, std::vector< return NvResult::Success; } -NvResult nvhost_gpu::SetChannelPriority(const std::vector& input, std::vector& output) { +NvResult nvhost_gpu::SetChannelPriority(std::span input, std::vector& output) { std::memcpy(&channel_priority, input.data(), input.size()); LOG_DEBUG(Service_NVDRV, "(STUBBED) called, priority={:X}", channel_priority); return NvResult::Success; } -NvResult nvhost_gpu::AllocGPFIFOEx2(const std::vector& input, std::vector& output) { +NvResult nvhost_gpu::AllocGPFIFOEx2(std::span input, std::vector& output) { IoctlAllocGpfifoEx2 params{}; std::memcpy(¶ms, input.data(), input.size()); LOG_WARNING(Service_NVDRV, @@ -197,7 +197,7 @@ NvResult nvhost_gpu::AllocGPFIFOEx2(const std::vector& input, std::vector& input, std::vector& output) { +NvResult nvhost_gpu::AllocateObjectContext(std::span input, std::vector& output) { IoctlAllocObjCtx params{}; std::memcpy(¶ms, input.data(), input.size()); LOG_WARNING(Service_NVDRV, "(STUBBED) called, class_num={:X}, flags={:X}", params.class_num, @@ -293,7 +293,7 @@ NvResult nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::vector return NvResult::Success; } -NvResult nvhost_gpu::SubmitGPFIFOBase(const std::vector& input, std::vector& output, +NvResult nvhost_gpu::SubmitGPFIFOBase(std::span input, std::vector& output, bool kickoff) { if (input.size() < sizeof(IoctlSubmitGpfifo)) { UNIMPLEMENTED(); @@ -314,8 +314,7 @@ NvResult nvhost_gpu::SubmitGPFIFOBase(const std::vector& input, std::vector< return SubmitGPFIFOImpl(params, output, std::move(entries)); } -NvResult nvhost_gpu::SubmitGPFIFOBase(const std::vector& input, - const std::vector& input_inline, +NvResult nvhost_gpu::SubmitGPFIFOBase(std::span input, std::span input_inline, std::vector& output) { if (input.size() < sizeof(IoctlSubmitGpfifo)) { UNIMPLEMENTED(); @@ -328,7 +327,7 @@ NvResult nvhost_gpu::SubmitGPFIFOBase(const std::vector& input, return SubmitGPFIFOImpl(params, output, std::move(entries)); } -NvResult nvhost_gpu::GetWaitbase(const std::vector& input, std::vector& output) { +NvResult nvhost_gpu::GetWaitbase(std::span input, std::vector& output) { IoctlGetWaitbase params{}; std::memcpy(¶ms, input.data(), sizeof(IoctlGetWaitbase)); LOG_INFO(Service_NVDRV, "called, unknown=0x{:X}", params.unknown); @@ -338,7 +337,7 @@ NvResult nvhost_gpu::GetWaitbase(const std::vector& input, std::vector& return NvResult::Success; } -NvResult nvhost_gpu::ChannelSetTimeout(const std::vector& input, std::vector& output) { +NvResult nvhost_gpu::ChannelSetTimeout(std::span input, std::vector& output) { IoctlChannelSetTimeout params{}; std::memcpy(¶ms, input.data(), sizeof(IoctlChannelSetTimeout)); LOG_INFO(Service_NVDRV, "called, timeout=0x{:X}", params.timeout); @@ -346,7 +345,7 @@ NvResult nvhost_gpu::ChannelSetTimeout(const std::vector& input, std::vector return NvResult::Success; } -NvResult nvhost_gpu::ChannelSetTimeslice(const std::vector& input, std::vector& output) { +NvResult nvhost_gpu::ChannelSetTimeslice(std::span input, std::vector& output) { IoctlSetTimeslice params{}; std::memcpy(¶ms, input.data(), sizeof(IoctlSetTimeslice)); LOG_INFO(Service_NVDRV, "called, timeslice=0x{:X}", params.timeslice); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h index 93265560c..294b661e5 100755 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h @@ -40,12 +40,12 @@ public: NvCore::Container& core); ~nvhost_gpu() override; - NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector& input, + NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span input, std::vector& output) override; - NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector& input, - const std::vector& inline_input, std::vector& output) override; - NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector& input, - std::vector& output, std::vector& inline_output) override; + NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span input, + std::span inline_input, std::vector& output) override; + NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span input, std::vector& output, + std::vector& inline_output) override; void OnOpen(DeviceFD fd) override; void OnClose(DeviceFD fd) override; @@ -186,23 +186,23 @@ private: u32_le channel_priority{}; u32_le channel_timeslice{}; - NvResult SetNVMAPfd(const std::vector& input, std::vector& output); - NvResult SetClientData(const std::vector& input, std::vector& output); - NvResult GetClientData(const std::vector& input, std::vector& output); - NvResult ZCullBind(const std::vector& input, std::vector& output); - NvResult SetErrorNotifier(const std::vector& input, std::vector& output); - NvResult SetChannelPriority(const std::vector& input, std::vector& output); - NvResult AllocGPFIFOEx2(const std::vector& input, std::vector& output); - NvResult AllocateObjectContext(const std::vector& input, std::vector& output); + NvResult SetNVMAPfd(std::span input, std::vector& output); + NvResult SetClientData(std::span input, std::vector& output); + NvResult GetClientData(std::span input, std::vector& output); + NvResult ZCullBind(std::span input, std::vector& output); + NvResult SetErrorNotifier(std::span input, std::vector& output); + NvResult SetChannelPriority(std::span input, std::vector& output); + NvResult AllocGPFIFOEx2(std::span input, std::vector& output); + NvResult AllocateObjectContext(std::span input, std::vector& output); NvResult SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::vector& output, Tegra::CommandList&& entries); - NvResult SubmitGPFIFOBase(const std::vector& input, std::vector& output, + NvResult SubmitGPFIFOBase(std::span input, std::vector& output, bool kickoff = false); - NvResult SubmitGPFIFOBase(const std::vector& input, const std::vector& input_inline, + NvResult SubmitGPFIFOBase(std::span input, std::span input_inline, std::vector& output); - NvResult GetWaitbase(const std::vector& input, std::vector& output); - NvResult ChannelSetTimeout(const std::vector& input, std::vector& output); - NvResult ChannelSetTimeslice(const std::vector& input, std::vector& output); + NvResult GetWaitbase(std::span input, std::vector& output); + NvResult ChannelSetTimeout(std::span input, std::vector& output); + NvResult ChannelSetTimeslice(std::span input, std::vector& output); EventInterface& events_interface; NvCore::Container& core; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp index 8422d5bad..a2de66cdc 100755 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp @@ -15,7 +15,7 @@ nvhost_nvdec::nvhost_nvdec(Core::System& system_, NvCore::Container& core_) : nvhost_nvdec_common{system_, core_, NvCore::ChannelType::NvDec} {} nvhost_nvdec::~nvhost_nvdec() = default; -NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, const std::vector& input, +NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, std::span input, std::vector& output) { switch (command.group) { case 0x0: @@ -55,13 +55,13 @@ NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, const std::vector& return NvResult::NotImplemented; } -NvResult nvhost_nvdec::Ioctl2(DeviceFD fd, Ioctl command, const std::vector& input, - const std::vector& inline_input, std::vector& output) { +NvResult nvhost_nvdec::Ioctl2(DeviceFD fd, Ioctl command, std::span input, + std::span inline_input, std::vector& output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; } -NvResult nvhost_nvdec::Ioctl3(DeviceFD fd, Ioctl command, const std::vector& input, +NvResult nvhost_nvdec::Ioctl3(DeviceFD fd, Ioctl command, std::span input, std::vector& output, std::vector& inline_output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h index 398a03557..3ec682337 100755 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h @@ -13,12 +13,12 @@ public: explicit nvhost_nvdec(Core::System& system_, NvCore::Container& core); ~nvhost_nvdec() override; - NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector& input, + NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span input, std::vector& output) override; - NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector& input, - const std::vector& inline_input, std::vector& output) override; - NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector& input, - std::vector& output, std::vector& inline_output) override; + NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span input, + std::span inline_input, std::vector& output) override; + NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span input, std::vector& output, + std::vector& inline_output) override; void OnOpen(DeviceFD fd) override; void OnClose(DeviceFD fd) override; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp index 3bb92c834..62c803838 100755 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp @@ -23,7 +23,7 @@ namespace { // Copies count amount of type T from the input vector into the dst vector. // Returns the number of bytes written into dst. template -std::size_t SliceVectors(const std::vector& input, std::vector& dst, std::size_t count, +std::size_t SliceVectors(std::span input, std::vector& dst, std::size_t count, std::size_t offset) { if (dst.empty()) { return 0; @@ -63,7 +63,7 @@ nvhost_nvdec_common::~nvhost_nvdec_common() { core.Host1xDeviceFile().syncpts_accumulated.push_back(channel_syncpoint); } -NvResult nvhost_nvdec_common::SetNVMAPfd(const std::vector& input) { +NvResult nvhost_nvdec_common::SetNVMAPfd(std::span input) { IoctlSetNvmapFD params{}; std::memcpy(¶ms, input.data(), sizeof(IoctlSetNvmapFD)); LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); @@ -72,7 +72,7 @@ NvResult nvhost_nvdec_common::SetNVMAPfd(const std::vector& input) { return NvResult::Success; } -NvResult nvhost_nvdec_common::Submit(DeviceFD fd, const std::vector& input, +NvResult nvhost_nvdec_common::Submit(DeviceFD fd, std::span input, std::vector& output) { IoctlSubmit params{}; std::memcpy(¶ms, input.data(), sizeof(IoctlSubmit)); @@ -121,7 +121,7 @@ NvResult nvhost_nvdec_common::Submit(DeviceFD fd, const std::vector& input, return NvResult::Success; } -NvResult nvhost_nvdec_common::GetSyncpoint(const std::vector& input, std::vector& output) { +NvResult nvhost_nvdec_common::GetSyncpoint(std::span input, std::vector& output) { IoctlGetSyncpoint params{}; std::memcpy(¶ms, input.data(), sizeof(IoctlGetSyncpoint)); LOG_DEBUG(Service_NVDRV, "called GetSyncpoint, id={}", params.param); @@ -133,7 +133,7 @@ NvResult nvhost_nvdec_common::GetSyncpoint(const std::vector& input, std::ve return NvResult::Success; } -NvResult nvhost_nvdec_common::GetWaitbase(const std::vector& input, std::vector& output) { +NvResult nvhost_nvdec_common::GetWaitbase(std::span input, std::vector& output) { IoctlGetWaitbase params{}; LOG_CRITICAL(Service_NVDRV, "called WAITBASE"); std::memcpy(¶ms, input.data(), sizeof(IoctlGetWaitbase)); @@ -142,7 +142,7 @@ NvResult nvhost_nvdec_common::GetWaitbase(const std::vector& input, std::vec return NvResult::Success; } -NvResult nvhost_nvdec_common::MapBuffer(const std::vector& input, std::vector& output) { +NvResult nvhost_nvdec_common::MapBuffer(std::span input, std::vector& output) { IoctlMapBuffer params{}; std::memcpy(¶ms, input.data(), sizeof(IoctlMapBuffer)); std::vector cmd_buffer_handles(params.num_entries); @@ -159,7 +159,7 @@ NvResult nvhost_nvdec_common::MapBuffer(const std::vector& input, std::vecto return NvResult::Success; } -NvResult nvhost_nvdec_common::UnmapBuffer(const std::vector& input, std::vector& output) { +NvResult nvhost_nvdec_common::UnmapBuffer(std::span input, std::vector& output) { IoctlMapBuffer params{}; std::memcpy(¶ms, input.data(), sizeof(IoctlMapBuffer)); std::vector cmd_buffer_handles(params.num_entries); @@ -173,8 +173,7 @@ NvResult nvhost_nvdec_common::UnmapBuffer(const std::vector& input, std::vec return NvResult::Success; } -NvResult nvhost_nvdec_common::SetSubmitTimeout(const std::vector& input, - std::vector& output) { +NvResult nvhost_nvdec_common::SetSubmitTimeout(std::span input, std::vector& output) { std::memcpy(&submit_timeout, input.data(), input.size()); LOG_WARNING(Service_NVDRV, "(STUBBED) called"); return NvResult::Success; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h index 083f9fdcf..d614ecf9b 100755 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h @@ -107,13 +107,13 @@ protected: static_assert(sizeof(IoctlMapBuffer) == 0x0C, "IoctlMapBuffer is incorrect size"); /// Ioctl command implementations - NvResult SetNVMAPfd(const std::vector& input); - NvResult Submit(DeviceFD fd, const std::vector& input, std::vector& output); - NvResult GetSyncpoint(const std::vector& input, std::vector& output); - NvResult GetWaitbase(const std::vector& input, std::vector& output); - NvResult MapBuffer(const std::vector& input, std::vector& output); - NvResult UnmapBuffer(const std::vector& input, std::vector& output); - NvResult SetSubmitTimeout(const std::vector& input, std::vector& output); + NvResult SetNVMAPfd(std::span input); + NvResult Submit(DeviceFD fd, std::span input, std::vector& output); + NvResult GetSyncpoint(std::span input, std::vector& output); + NvResult GetWaitbase(std::span input, std::vector& output); + NvResult MapBuffer(std::span input, std::vector& output); + NvResult UnmapBuffer(std::span input, std::vector& output); + NvResult SetSubmitTimeout(std::span input, std::vector& output); Kernel::KEvent* QueryEvent(u32 event_id) override; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp index 0b267bb9d..59a9f6143 100755 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp @@ -12,7 +12,7 @@ namespace Service::Nvidia::Devices { nvhost_nvjpg::nvhost_nvjpg(Core::System& system_) : nvdevice{system_} {} nvhost_nvjpg::~nvhost_nvjpg() = default; -NvResult nvhost_nvjpg::Ioctl1(DeviceFD fd, Ioctl command, const std::vector& input, +NvResult nvhost_nvjpg::Ioctl1(DeviceFD fd, Ioctl command, std::span input, std::vector& output) { switch (command.group) { case 'H': @@ -31,13 +31,13 @@ NvResult nvhost_nvjpg::Ioctl1(DeviceFD fd, Ioctl command, const std::vector& return NvResult::NotImplemented; } -NvResult nvhost_nvjpg::Ioctl2(DeviceFD fd, Ioctl command, const std::vector& input, - const std::vector& inline_input, std::vector& output) { +NvResult nvhost_nvjpg::Ioctl2(DeviceFD fd, Ioctl command, std::span input, + std::span inline_input, std::vector& output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; } -NvResult nvhost_nvjpg::Ioctl3(DeviceFD fd, Ioctl command, const std::vector& input, +NvResult nvhost_nvjpg::Ioctl3(DeviceFD fd, Ioctl command, std::span input, std::vector& output, std::vector& inline_output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; @@ -46,7 +46,7 @@ NvResult nvhost_nvjpg::Ioctl3(DeviceFD fd, Ioctl command, const std::vector& void nvhost_nvjpg::OnOpen(DeviceFD fd) {} void nvhost_nvjpg::OnClose(DeviceFD fd) {} -NvResult nvhost_nvjpg::SetNVMAPfd(const std::vector& input, std::vector& output) { +NvResult nvhost_nvjpg::SetNVMAPfd(std::span input, std::vector& output) { IoctlSetNvmapFD params{}; std::memcpy(¶ms, input.data(), input.size()); LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h index a2e5dab1a..1b0b119a6 100755 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h @@ -15,12 +15,12 @@ public: explicit nvhost_nvjpg(Core::System& system_); ~nvhost_nvjpg() override; - NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector& input, + NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span input, std::vector& output) override; - NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector& input, - const std::vector& inline_input, std::vector& output) override; - NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector& input, - std::vector& output, std::vector& inline_output) override; + NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span input, + std::span inline_input, std::vector& output) override; + NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span input, std::vector& output, + std::vector& inline_output) override; void OnOpen(DeviceFD fd) override; void OnClose(DeviceFD fd) override; @@ -33,7 +33,7 @@ private: s32_le nvmap_fd{}; - NvResult SetNVMAPfd(const std::vector& input, std::vector& output); + NvResult SetNVMAPfd(std::span input, std::vector& output); }; } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp index 0b5e2a123..d0238c1e3 100755 --- a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp @@ -15,7 +15,7 @@ nvhost_vic::nvhost_vic(Core::System& system_, NvCore::Container& core_) nvhost_vic::~nvhost_vic() = default; -NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, const std::vector& input, +NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, std::span input, std::vector& output) { switch (command.group) { case 0x0: @@ -55,13 +55,13 @@ NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, const std::vector& i return NvResult::NotImplemented; } -NvResult nvhost_vic::Ioctl2(DeviceFD fd, Ioctl command, const std::vector& input, - const std::vector& inline_input, std::vector& output) { +NvResult nvhost_vic::Ioctl2(DeviceFD fd, Ioctl command, std::span input, + std::span inline_input, std::vector& output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; } -NvResult nvhost_vic::Ioctl3(DeviceFD fd, Ioctl command, const std::vector& input, +NvResult nvhost_vic::Ioctl3(DeviceFD fd, Ioctl command, std::span input, std::vector& output, std::vector& inline_output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.h b/src/core/hle/service/nvdrv/devices/nvhost_vic.h index 714df8562..a590d104f 100755 --- a/src/core/hle/service/nvdrv/devices/nvhost_vic.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.h @@ -12,12 +12,12 @@ public: explicit nvhost_vic(Core::System& system_, NvCore::Container& core); ~nvhost_vic(); - NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector& input, + NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span input, std::vector& output) override; - NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector& input, - const std::vector& inline_input, std::vector& output) override; - NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector& input, - std::vector& output, std::vector& inline_output) override; + NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span input, + std::span inline_input, std::vector& output) override; + NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span input, std::vector& output, + std::vector& inline_output) override; void OnOpen(DeviceFD fd) override; void OnClose(DeviceFD fd) override; diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp index d81813f57..375428f02 100755 --- a/src/core/hle/service/nvdrv/devices/nvmap.cpp +++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp @@ -25,7 +25,7 @@ nvmap::nvmap(Core::System& system_, NvCore::Container& container_) nvmap::~nvmap() = default; -NvResult nvmap::Ioctl1(DeviceFD fd, Ioctl command, const std::vector& input, +NvResult nvmap::Ioctl1(DeviceFD fd, Ioctl command, std::span input, std::vector& output) { switch (command.group) { case 0x1: @@ -54,13 +54,13 @@ NvResult nvmap::Ioctl1(DeviceFD fd, Ioctl command, const std::vector& input, return NvResult::NotImplemented; } -NvResult nvmap::Ioctl2(DeviceFD fd, Ioctl command, const std::vector& input, - const std::vector& inline_input, std::vector& output) { +NvResult nvmap::Ioctl2(DeviceFD fd, Ioctl command, std::span input, + std::span inline_input, std::vector& output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; } -NvResult nvmap::Ioctl3(DeviceFD fd, Ioctl command, const std::vector& input, +NvResult nvmap::Ioctl3(DeviceFD fd, Ioctl command, std::span input, std::vector& output, std::vector& inline_output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; @@ -69,7 +69,7 @@ NvResult nvmap::Ioctl3(DeviceFD fd, Ioctl command, const std::vector& input, void nvmap::OnOpen(DeviceFD fd) {} void nvmap::OnClose(DeviceFD fd) {} -NvResult nvmap::IocCreate(const std::vector& input, std::vector& output) { +NvResult nvmap::IocCreate(std::span input, std::vector& output) { IocCreateParams params; std::memcpy(¶ms, input.data(), sizeof(params)); LOG_DEBUG(Service_NVDRV, "called, size=0x{:08X}", params.size); @@ -89,7 +89,7 @@ NvResult nvmap::IocCreate(const std::vector& input, std::vector& output) return NvResult::Success; } -NvResult nvmap::IocAlloc(const std::vector& input, std::vector& output) { +NvResult nvmap::IocAlloc(std::span input, std::vector& output) { IocAllocParams params; std::memcpy(¶ms, input.data(), sizeof(params)); LOG_DEBUG(Service_NVDRV, "called, addr={:X}", params.address); @@ -137,7 +137,7 @@ NvResult nvmap::IocAlloc(const std::vector& input, std::vector& output) return result; } -NvResult nvmap::IocGetId(const std::vector& input, std::vector& output) { +NvResult nvmap::IocGetId(std::span input, std::vector& output) { IocGetIdParams params; std::memcpy(¶ms, input.data(), sizeof(params)); @@ -161,7 +161,7 @@ NvResult nvmap::IocGetId(const std::vector& input, std::vector& output) return NvResult::Success; } -NvResult nvmap::IocFromId(const std::vector& input, std::vector& output) { +NvResult nvmap::IocFromId(std::span input, std::vector& output) { IocFromIdParams params; std::memcpy(¶ms, input.data(), sizeof(params)); @@ -192,7 +192,7 @@ NvResult nvmap::IocFromId(const std::vector& input, std::vector& output) return NvResult::Success; } -NvResult nvmap::IocParam(const std::vector& input, std::vector& output) { +NvResult nvmap::IocParam(std::span input, std::vector& output) { enum class ParamTypes { Size = 1, Alignment = 2, Base = 3, Heap = 4, Kind = 5, Compr = 6 }; IocParamParams params; @@ -241,7 +241,7 @@ NvResult nvmap::IocParam(const std::vector& input, std::vector& output) return NvResult::Success; } -NvResult nvmap::IocFree(const std::vector& input, std::vector& output) { +NvResult nvmap::IocFree(std::span input, std::vector& output) { IocFreeParams params; std::memcpy(¶ms, input.data(), sizeof(params)); diff --git a/src/core/hle/service/nvdrv/devices/nvmap.h b/src/core/hle/service/nvdrv/devices/nvmap.h index ebd8f372d..59b2350e3 100755 --- a/src/core/hle/service/nvdrv/devices/nvmap.h +++ b/src/core/hle/service/nvdrv/devices/nvmap.h @@ -26,12 +26,12 @@ public: nvmap(const nvmap&) = delete; nvmap& operator=(const nvmap&) = delete; - NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector& input, + NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span input, std::vector& output) override; - NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector& input, - const std::vector& inline_input, std::vector& output) override; - NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector& input, - std::vector& output, std::vector& inline_output) override; + NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span input, + std::span inline_input, std::vector& output) override; + NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span input, std::vector& output, + std::vector& inline_output) override; void OnOpen(DeviceFD fd) override; void OnClose(DeviceFD fd) override; @@ -106,12 +106,12 @@ private: }; static_assert(sizeof(IocGetIdParams) == 8, "IocGetIdParams has wrong size"); - NvResult IocCreate(const std::vector& input, std::vector& output); - NvResult IocAlloc(const std::vector& input, std::vector& output); - NvResult IocGetId(const std::vector& input, std::vector& output); - NvResult IocFromId(const std::vector& input, std::vector& output); - NvResult IocParam(const std::vector& input, std::vector& output); - NvResult IocFree(const std::vector& input, std::vector& output); + NvResult IocCreate(std::span input, std::vector& output); + NvResult IocAlloc(std::span input, std::vector& output); + NvResult IocGetId(std::span input, std::vector& output); + NvResult IocFromId(std::span input, std::vector& output); + NvResult IocParam(std::span input, std::vector& output); + NvResult IocFree(std::span input, std::vector& output); NvCore::Container& container; NvCore::NvMap& file; diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp index f577913ff..975f6a865 100755 --- a/src/core/hle/service/nvdrv/nvdrv.cpp +++ b/src/core/hle/service/nvdrv/nvdrv.cpp @@ -124,7 +124,7 @@ DeviceFD Module::Open(const std::string& device_name) { return fd; } -NvResult Module::Ioctl1(DeviceFD fd, Ioctl command, const std::vector& input, +NvResult Module::Ioctl1(DeviceFD fd, Ioctl command, std::span input, std::vector& output) { if (fd < 0) { LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd); @@ -141,8 +141,8 @@ NvResult Module::Ioctl1(DeviceFD fd, Ioctl command, const std::vector& input return itr->second->Ioctl1(fd, command, input, output); } -NvResult Module::Ioctl2(DeviceFD fd, Ioctl command, const std::vector& input, - const std::vector& inline_input, std::vector& output) { +NvResult Module::Ioctl2(DeviceFD fd, Ioctl command, std::span input, + std::span inline_input, std::vector& output) { if (fd < 0) { LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd); return NvResult::InvalidState; @@ -158,7 +158,7 @@ NvResult Module::Ioctl2(DeviceFD fd, Ioctl command, const std::vector& input return itr->second->Ioctl2(fd, command, input, inline_input, output); } -NvResult Module::Ioctl3(DeviceFD fd, Ioctl command, const std::vector& input, +NvResult Module::Ioctl3(DeviceFD fd, Ioctl command, std::span input, std::vector& output, std::vector& inline_output) { if (fd < 0) { LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd); diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h index 2135881c1..60f9720c0 100755 --- a/src/core/hle/service/nvdrv/nvdrv.h +++ b/src/core/hle/service/nvdrv/nvdrv.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -79,14 +80,13 @@ public: DeviceFD Open(const std::string& device_name); /// Sends an ioctl command to the specified file descriptor. - NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector& input, - std::vector& output); + NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span input, std::vector& output); - NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector& input, - const std::vector& inline_input, std::vector& output); + NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span input, + std::span inline_input, std::vector& output); - NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector& input, - std::vector& output, std::vector& inline_output); + NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span input, std::vector& output, + std::vector& inline_output); /// Closes a device file descriptor and returns operation success. NvResult Close(DeviceFD fd); diff --git a/src/core/hle/service/nvflinger/buffer_queue_producer.cpp b/src/core/hle/service/nvflinger/buffer_queue_producer.cpp index 48ea91247..9ae0553bc 100755 --- a/src/core/hle/service/nvflinger/buffer_queue_producer.cpp +++ b/src/core/hle/service/nvflinger/buffer_queue_producer.cpp @@ -815,8 +815,8 @@ Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot, void BufferQueueProducer::Transact(Kernel::HLERequestContext& ctx, TransactionId code, u32 flags) { Status status{Status::NoError}; - Parcel parcel_in{ctx.ReadBuffer()}; - Parcel parcel_out{}; + InputParcel parcel_in{ctx.ReadBuffer()}; + OutputParcel parcel_out{}; switch (code) { case TransactionId::Connect: { diff --git a/src/core/hle/service/nvflinger/graphic_buffer_producer.cpp b/src/core/hle/service/nvflinger/graphic_buffer_producer.cpp index bc47c08b9..9a9f7ec2b 100755 --- a/src/core/hle/service/nvflinger/graphic_buffer_producer.cpp +++ b/src/core/hle/service/nvflinger/graphic_buffer_producer.cpp @@ -9,7 +9,7 @@ namespace Service::android { -QueueBufferInput::QueueBufferInput(Parcel& parcel) { +QueueBufferInput::QueueBufferInput(InputParcel& parcel) { parcel.ReadFlattened(*this); } diff --git a/src/core/hle/service/nvflinger/graphic_buffer_producer.h b/src/core/hle/service/nvflinger/graphic_buffer_producer.h index 95ad3eb4e..6ea8cb971 100755 --- a/src/core/hle/service/nvflinger/graphic_buffer_producer.h +++ b/src/core/hle/service/nvflinger/graphic_buffer_producer.h @@ -14,11 +14,11 @@ namespace Service::android { -class Parcel; +class InputParcel; #pragma pack(push, 1) struct QueueBufferInput final { - explicit QueueBufferInput(Parcel& parcel); + explicit QueueBufferInput(InputParcel& parcel); void Deflate(s64* timestamp_, bool* is_auto_timestamp_, Common::Rectangle* crop_, NativeWindowScalingMode* scaling_mode_, NativeWindowTransform* transform_, diff --git a/src/core/hle/service/nvflinger/parcel.h b/src/core/hle/service/nvflinger/parcel.h index 60582340b..82cae203d 100755 --- a/src/core/hle/service/nvflinger/parcel.h +++ b/src/core/hle/service/nvflinger/parcel.h @@ -4,6 +4,7 @@ #pragma once #include +#include #include #include "common/alignment.h" @@ -12,18 +13,17 @@ namespace Service::android { -class Parcel final { +struct ParcelHeader { + u32 data_size; + u32 data_offset; + u32 objects_size; + u32 objects_offset; +}; +static_assert(sizeof(ParcelHeader) == 16, "ParcelHeader has wrong size"); + +class InputParcel final { public: - static constexpr std::size_t DefaultBufferSize = 0x40; - - Parcel() : buffer(DefaultBufferSize) {} - - template - explicit Parcel(const T& out_data) : buffer(DefaultBufferSize) { - Write(out_data); - } - - explicit Parcel(std::vector in_data) : buffer(std::move(in_data)) { + explicit InputParcel(std::span in_data) : read_buffer(std::move(in_data)) { DeserializeHeader(); [[maybe_unused]] const std::u16string token = ReadInterfaceToken(); } @@ -31,9 +31,9 @@ public: template void Read(T& val) { static_assert(std::is_trivially_copyable_v, "T must be trivially copyable."); - ASSERT(read_index + sizeof(T) <= buffer.size()); + ASSERT(read_index + sizeof(T) <= read_buffer.size()); - std::memcpy(&val, buffer.data() + read_index, sizeof(T)); + std::memcpy(&val, read_buffer.data() + read_index, sizeof(T)); read_index += sizeof(T); read_index = Common::AlignUp(read_index, 4); } @@ -62,10 +62,10 @@ public: template T ReadUnaligned() { static_assert(std::is_trivially_copyable_v, "T must be trivially copyable."); - ASSERT(read_index + sizeof(T) <= buffer.size()); + ASSERT(read_index + sizeof(T) <= read_buffer.size()); T val; - std::memcpy(&val, buffer.data() + read_index, sizeof(T)); + std::memcpy(&val, read_buffer.data() + read_index, sizeof(T)); read_index += sizeof(T); return val; } @@ -101,6 +101,31 @@ public: return token; } + void DeserializeHeader() { + ASSERT(read_buffer.size() > sizeof(ParcelHeader)); + + ParcelHeader header{}; + std::memcpy(&header, read_buffer.data(), sizeof(ParcelHeader)); + + read_index = header.data_offset; + } + +private: + std::span read_buffer; + std::size_t read_index = 0; +}; + +class OutputParcel final { +public: + static constexpr std::size_t DefaultBufferSize = 0x40; + + OutputParcel() : buffer(DefaultBufferSize) {} + + template + explicit OutputParcel(const T& out_data) : buffer(DefaultBufferSize) { + Write(out_data); + } + template void Write(const T& val) { static_assert(std::is_trivially_copyable_v, "T must be trivially copyable."); @@ -133,40 +158,20 @@ public: WriteObject(ptr.get()); } - void DeserializeHeader() { - ASSERT(buffer.size() > sizeof(Header)); - - Header header{}; - std::memcpy(&header, buffer.data(), sizeof(Header)); - - read_index = header.data_offset; - } - std::vector Serialize() const { - ASSERT(read_index == 0); - - Header header{}; - header.data_size = static_cast(write_index - sizeof(Header)); - header.data_offset = sizeof(Header); + ParcelHeader header{}; + header.data_size = static_cast(write_index - sizeof(ParcelHeader)); + header.data_offset = sizeof(ParcelHeader); header.objects_size = 4; - header.objects_offset = static_cast(sizeof(Header) + header.data_size); - std::memcpy(buffer.data(), &header, sizeof(Header)); + header.objects_offset = static_cast(sizeof(ParcelHeader) + header.data_size); + std::memcpy(buffer.data(), &header, sizeof(ParcelHeader)); return buffer; } private: - struct Header { - u32 data_size; - u32 data_offset; - u32 objects_size; - u32 objects_offset; - }; - static_assert(sizeof(Header) == 16, "ParcelHeader has wrong size"); - mutable std::vector buffer; - std::size_t read_index = 0; - std::size_t write_index = sizeof(Header); + std::size_t write_index = sizeof(ParcelHeader); }; } // namespace Service::android diff --git a/src/core/hle/service/prepo/prepo.cpp b/src/core/hle/service/prepo/prepo.cpp index 5a5bd3f88..94c2414e0 100755 --- a/src/core/hle/service/prepo/prepo.cpp +++ b/src/core/hle/service/prepo/prepo.cpp @@ -63,7 +63,7 @@ private: return ctx.ReadBuffer(1); } - return std::vector{}; + return std::span{}; }(); LOG_DEBUG(Service_PREPO, @@ -90,7 +90,7 @@ private: return ctx.ReadBuffer(1); } - return std::vector{}; + return std::span{}; }(); LOG_DEBUG(Service_PREPO, @@ -142,7 +142,7 @@ private: return ctx.ReadBuffer(1); } - return std::vector{}; + return std::span{}; }(); LOG_DEBUG(Service_PREPO, "called, title_id={:016X}, data1_size={:016X}, data2_size={:016X}", @@ -166,7 +166,7 @@ private: return ctx.ReadBuffer(1); } - return std::vector{}; + return std::span{}; }(); LOG_DEBUG(Service_PREPO, diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp index 6be7d33b8..761da854f 100755 --- a/src/core/hle/service/sockets/bsd.cpp +++ b/src/core/hle/service/sockets/bsd.cpp @@ -208,7 +208,6 @@ void BSD::Bind(Kernel::HLERequestContext& ctx) { const s32 fd = rp.Pop(); LOG_DEBUG(Service, "called. fd={} addrlen={}", fd, ctx.GetReadBufferSize()); - BuildErrnoResponse(ctx, BindImpl(fd, ctx.ReadBuffer())); } @@ -312,7 +311,7 @@ void BSD::SetSockOpt(Kernel::HLERequestContext& ctx) { const u32 level = rp.Pop(); const OptName optname = static_cast(rp.Pop()); - const std::vector buffer = ctx.ReadBuffer(); + const auto buffer = ctx.ReadBuffer(); const u8* optval = buffer.empty() ? nullptr : buffer.data(); size_t optlen = buffer.size(); @@ -489,7 +488,7 @@ std::pair BSD::SocketImpl(Domain domain, Type type, Protocol protoco return {fd, Errno::SUCCESS}; } -std::pair BSD::PollImpl(std::vector& write_buffer, std::vector read_buffer, +std::pair BSD::PollImpl(std::vector& write_buffer, std::span read_buffer, s32 nfds, s32 timeout) { if (write_buffer.size() < nfds * sizeof(PollFD)) { return {-1, Errno::INVAL}; @@ -584,7 +583,7 @@ std::pair BSD::AcceptImpl(s32 fd, std::vector& write_buffer) { return {new_fd, Errno::SUCCESS}; } -Errno BSD::BindImpl(s32 fd, const std::vector& addr) { +Errno BSD::BindImpl(s32 fd, std::span addr) { if (!IsFileDescriptorValid(fd)) { return Errno::BADF; } @@ -595,7 +594,7 @@ Errno BSD::BindImpl(s32 fd, const std::vector& addr) { return Translate(file_descriptors[fd]->socket->Bind(Translate(addr_in))); } -Errno BSD::ConnectImpl(s32 fd, const std::vector& addr) { +Errno BSD::ConnectImpl(s32 fd, std::span addr) { if (!IsFileDescriptorValid(fd)) { return Errno::BADF; } @@ -800,15 +799,15 @@ std::pair BSD::RecvFromImpl(s32 fd, u32 flags, std::vector& mess return {ret, bsd_errno}; } -std::pair BSD::SendImpl(s32 fd, u32 flags, const std::vector& message) { +std::pair BSD::SendImpl(s32 fd, u32 flags, std::span message) { if (!IsFileDescriptorValid(fd)) { return {-1, Errno::BADF}; } return Translate(file_descriptors[fd]->socket->Send(message, flags)); } -std::pair BSD::SendToImpl(s32 fd, u32 flags, const std::vector& message, - const std::vector& addr) { +std::pair BSD::SendToImpl(s32 fd, u32 flags, std::span message, + std::span addr) { if (!IsFileDescriptorValid(fd)) { return {-1, Errno::BADF}; } diff --git a/src/core/hle/service/sockets/bsd.h b/src/core/hle/service/sockets/bsd.h index 329881776..35cd92b69 100755 --- a/src/core/hle/service/sockets/bsd.h +++ b/src/core/hle/service/sockets/bsd.h @@ -4,6 +4,7 @@ #pragma once #include +#include #include #include "common/common_types.h" @@ -44,7 +45,7 @@ private: s32 nfds; s32 timeout; - std::vector read_buffer; + std::span read_buffer; std::vector write_buffer; s32 ret{}; Errno bsd_errno{}; @@ -65,7 +66,7 @@ private: void Response(Kernel::HLERequestContext& ctx); s32 fd; - std::vector addr; + std::span addr; Errno bsd_errno{}; }; @@ -98,7 +99,7 @@ private: s32 fd; u32 flags; - std::vector message; + std::span message; s32 ret{}; Errno bsd_errno{}; }; @@ -109,8 +110,8 @@ private: s32 fd; u32 flags; - std::vector message; - std::vector addr; + std::span message; + std::span addr; s32 ret{}; Errno bsd_errno{}; }; @@ -143,11 +144,11 @@ private: void ExecuteWork(Kernel::HLERequestContext& ctx, Work work); std::pair SocketImpl(Domain domain, Type type, Protocol protocol); - std::pair PollImpl(std::vector& write_buffer, std::vector read_buffer, + std::pair PollImpl(std::vector& write_buffer, std::span read_buffer, s32 nfds, s32 timeout); std::pair AcceptImpl(s32 fd, std::vector& write_buffer); - Errno BindImpl(s32 fd, const std::vector& addr); - Errno ConnectImpl(s32 fd, const std::vector& addr); + Errno BindImpl(s32 fd, std::span addr); + Errno ConnectImpl(s32 fd, std::span addr); Errno GetPeerNameImpl(s32 fd, std::vector& write_buffer); Errno GetSockNameImpl(s32 fd, std::vector& write_buffer); Errno ListenImpl(s32 fd, s32 backlog); @@ -157,9 +158,9 @@ private: std::pair RecvImpl(s32 fd, u32 flags, std::vector& message); std::pair RecvFromImpl(s32 fd, u32 flags, std::vector& message, std::vector& addr); - std::pair SendImpl(s32 fd, u32 flags, const std::vector& message); - std::pair SendToImpl(s32 fd, u32 flags, const std::vector& message, - const std::vector& addr); + std::pair SendImpl(s32 fd, u32 flags, std::span message); + std::pair SendToImpl(s32 fd, u32 flags, std::span message, + std::span addr); Errno CloseImpl(s32 fd); s32 FindFreeFileDescriptorHandle() noexcept; diff --git a/src/core/hle/service/sockets/sfdnsres.cpp b/src/core/hle/service/sockets/sfdnsres.cpp index f756fa232..db338c642 100755 --- a/src/core/hle/service/sockets/sfdnsres.cpp +++ b/src/core/hle/service/sockets/sfdnsres.cpp @@ -243,4 +243,4 @@ void SFDNSRES::GetAddrInfoRequestWithOptions(Kernel::HLERequestContext& ctx) { rb.Push(0); } -} // namespace Service::Sockets \ No newline at end of file +} // namespace Service::Sockets diff --git a/src/core/hle/service/ssl/ssl.cpp b/src/core/hle/service/ssl/ssl.cpp index ebadc2da5..d05187c8e 100755 --- a/src/core/hle/service/ssl/ssl.cpp +++ b/src/core/hle/service/ssl/ssl.cpp @@ -101,7 +101,7 @@ private: void ImportServerPki(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto certificate_format = rp.PopEnum(); - const auto pkcs_12_certificates = ctx.ReadBuffer(0); + [[maybe_unused]] const auto pkcs_12_certificates = ctx.ReadBuffer(0); constexpr u64 server_id = 0; @@ -113,13 +113,13 @@ private: } void ImportClientPki(Kernel::HLERequestContext& ctx) { - const auto pkcs_12_certificate = ctx.ReadBuffer(0); - const auto ascii_password = [&ctx] { + [[maybe_unused]] const auto pkcs_12_certificate = ctx.ReadBuffer(0); + [[maybe_unused]] const auto ascii_password = [&ctx] { if (ctx.CanReadBuffer(1)) { return ctx.ReadBuffer(1); } - return std::vector{}; + return std::span{}; }(); constexpr u64 client_id = 0; diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index ce23309a7..d36621162 100755 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -603,7 +603,7 @@ private: return; } - const auto parcel = android::Parcel{NativeWindow{*buffer_queue_id}}; + const auto parcel = android::OutputParcel{NativeWindow{*buffer_queue_id}}; const auto buffer_size = ctx.WriteBuffer(parcel.Serialize()); IPC::ResponseBuilder rb{ctx, 4}; @@ -649,7 +649,7 @@ private: return; } - const auto parcel = android::Parcel{NativeWindow{*buffer_queue_id}}; + const auto parcel = android::OutputParcel{NativeWindow{*buffer_queue_id}}; const auto buffer_size = ctx.WriteBuffer(parcel.Serialize()); IPC::ResponseBuilder rb{ctx, 6}; diff --git a/src/core/internal_network/network.cpp b/src/core/internal_network/network.cpp index 0ef1706b6..e6a1ec7c1 100755 --- a/src/core/internal_network/network.cpp +++ b/src/core/internal_network/network.cpp @@ -550,7 +550,7 @@ std::pair Socket::RecvFrom(int flags, std::vector& message, Sock return {-1, GetAndLogLastError()}; } -std::pair Socket::Send(const std::vector& message, int flags) { +std::pair Socket::Send(std::span message, int flags) { ASSERT(message.size() < static_cast(std::numeric_limits::max())); ASSERT(flags == 0); @@ -563,7 +563,7 @@ std::pair Socket::Send(const std::vector& message, int flags) { return {-1, GetAndLogLastError()}; } -std::pair Socket::SendTo(u32 flags, const std::vector& message, +std::pair Socket::SendTo(u32 flags, std::span message, const SockAddrIn* addr) { ASSERT(flags == 0); diff --git a/src/core/internal_network/socket_proxy.cpp b/src/core/internal_network/socket_proxy.cpp index 589bbfa8a..cc4afe13f 100755 --- a/src/core/internal_network/socket_proxy.cpp +++ b/src/core/internal_network/socket_proxy.cpp @@ -182,7 +182,7 @@ std::pair ProxySocket::ReceivePacket(int flags, std::vector& mes return {static_cast(read_bytes), Errno::SUCCESS}; } -std::pair ProxySocket::Send(const std::vector& message, int flags) { +std::pair ProxySocket::Send(std::span message, int flags) { LOG_WARNING(Network, "(STUBBED) called"); ASSERT(message.size() < static_cast(std::numeric_limits::max())); ASSERT(flags == 0); @@ -200,7 +200,7 @@ void ProxySocket::SendPacket(ProxyPacket& packet) { } } -std::pair ProxySocket::SendTo(u32 flags, const std::vector& message, +std::pair ProxySocket::SendTo(u32 flags, std::span message, const SockAddrIn* addr) { ASSERT(flags == 0); diff --git a/src/core/internal_network/socket_proxy.h b/src/core/internal_network/socket_proxy.h index e561cb961..a09a2d5af 100755 --- a/src/core/internal_network/socket_proxy.h +++ b/src/core/internal_network/socket_proxy.h @@ -4,6 +4,7 @@ #pragma once #include +#include #include #include @@ -48,11 +49,11 @@ public: std::pair ReceivePacket(int flags, std::vector& message, SockAddrIn* addr, std::size_t max_length); - std::pair Send(const std::vector& message, int flags) override; + std::pair Send(std::span message, int flags) override; void SendPacket(ProxyPacket& packet); - std::pair SendTo(u32 flags, const std::vector& message, + std::pair SendTo(u32 flags, std::span message, const SockAddrIn* addr) override; Errno SetLinger(bool enable, u32 linger) override; diff --git a/src/core/internal_network/sockets.h b/src/core/internal_network/sockets.h index 9aa289678..d999f27dd 100755 --- a/src/core/internal_network/sockets.h +++ b/src/core/internal_network/sockets.h @@ -5,6 +5,7 @@ #include #include +#include #include #if defined(_WIN32) @@ -66,9 +67,9 @@ public: virtual std::pair RecvFrom(int flags, std::vector& message, SockAddrIn* addr) = 0; - virtual std::pair Send(const std::vector& message, int flags) = 0; + virtual std::pair Send(std::span message, int flags) = 0; - virtual std::pair SendTo(u32 flags, const std::vector& message, + virtual std::pair SendTo(u32 flags, std::span message, const SockAddrIn* addr) = 0; virtual Errno SetLinger(bool enable, u32 linger) = 0; @@ -138,9 +139,9 @@ public: std::pair RecvFrom(int flags, std::vector& message, SockAddrIn* addr) override; - std::pair Send(const std::vector& message, int flags) override; + std::pair Send(std::span message, int flags) override; - std::pair SendTo(u32 flags, const std::vector& message, + std::pair SendTo(u32 flags, std::span message, const SockAddrIn* addr) override; Errno SetLinger(bool enable, u32 linger) override; diff --git a/src/core/reporter.cpp b/src/core/reporter.cpp index 9d0923920..f81ed76ef 100755 --- a/src/core/reporter.cpp +++ b/src/core/reporter.cpp @@ -312,7 +312,7 @@ void Reporter::SaveUnimplementedAppletReport( } void Reporter::SavePlayReport(PlayReportType type, u64 title_id, - const std::vector>& data, + const std::vector>& data, std::optional process_id, std::optional user_id) const { if (!IsReportingEnabled()) { return; diff --git a/src/core/reporter.h b/src/core/reporter.h index 36b6a598b..51596c183 100755 --- a/src/core/reporter.h +++ b/src/core/reporter.h @@ -5,6 +5,7 @@ #include #include +#include #include #include #include "common/common_types.h" @@ -56,7 +57,8 @@ public: System, }; - void SavePlayReport(PlayReportType type, u64 title_id, const std::vector>& data, + void SavePlayReport(PlayReportType type, u64 title_id, + const std::vector>& data, std::optional process_id = {}, std::optional user_id = {}) const; // Used by error applet diff --git a/src/input_common/helpers/joycon_protocol/calibration.cpp b/src/input_common/helpers/joycon_protocol/calibration.cpp index f6e7e97d5..d8f040f75 100755 --- a/src/input_common/helpers/joycon_protocol/calibration.cpp +++ b/src/input_common/helpers/joycon_protocol/calibration.cpp @@ -13,34 +13,34 @@ CalibrationProtocol::CalibrationProtocol(std::shared_ptr handle) DriverResult CalibrationProtocol::GetLeftJoyStickCalibration(JoyStickCalibration& calibration) { ScopedSetBlocking sb(this); - std::vector buffer; DriverResult result{DriverResult::Success}; + JoystickLeftSpiCalibration spi_calibration{}; + bool has_user_calibration = false; calibration = {}; - result = ReadSPI(CalAddr::USER_LEFT_MAGIC, sizeof(u16), buffer); - if (result == DriverResult::Success) { - const bool has_user_calibration = buffer[0] == 0xB2 && buffer[1] == 0xA1; - if (has_user_calibration) { - result = ReadSPI(CalAddr::USER_LEFT_DATA, 9, buffer); - } else { - result = ReadSPI(CalAddr::FACT_LEFT_DATA, 9, buffer); - } + result = HasUserCalibration(SpiAddress::USER_LEFT_MAGIC, has_user_calibration); + } + + // Read User defined calibration + if (result == DriverResult::Success && has_user_calibration) { + result = ReadSPI(SpiAddress::USER_LEFT_DATA, spi_calibration); + } + + // Read Factory calibration + if (result == DriverResult::Success && !has_user_calibration) { + result = ReadSPI(SpiAddress::FACT_LEFT_DATA, spi_calibration); } if (result == DriverResult::Success) { - calibration.x.max = static_cast(((buffer[1] & 0x0F) << 8) | buffer[0]); - calibration.y.max = static_cast((buffer[2] << 4) | (buffer[1] >> 4)); - calibration.x.center = static_cast(((buffer[4] & 0x0F) << 8) | buffer[3]); - calibration.y.center = static_cast((buffer[5] << 4) | (buffer[4] >> 4)); - calibration.x.min = static_cast(((buffer[7] & 0x0F) << 8) | buffer[6]); - calibration.y.min = static_cast((buffer[8] << 4) | (buffer[7] >> 4)); + calibration.x.center = GetXAxisCalibrationValue(spi_calibration.center); + calibration.y.center = GetYAxisCalibrationValue(spi_calibration.center); + calibration.x.min = GetXAxisCalibrationValue(spi_calibration.min); + calibration.y.min = GetYAxisCalibrationValue(spi_calibration.min); + calibration.x.max = GetXAxisCalibrationValue(spi_calibration.max); + calibration.y.max = GetYAxisCalibrationValue(spi_calibration.max); } - // Nintendo fix for drifting stick - // result = ReadSPI(0x60, 0x86 ,buffer, 16); - // calibration.deadzone = (u16)((buffer[4] << 8) & 0xF00 | buffer[3]); - // Set a valid default calibration if data is missing ValidateCalibration(calibration); @@ -49,34 +49,34 @@ DriverResult CalibrationProtocol::GetLeftJoyStickCalibration(JoyStickCalibration DriverResult CalibrationProtocol::GetRightJoyStickCalibration(JoyStickCalibration& calibration) { ScopedSetBlocking sb(this); - std::vector buffer; DriverResult result{DriverResult::Success}; + JoystickRightSpiCalibration spi_calibration{}; + bool has_user_calibration = false; calibration = {}; - result = ReadSPI(CalAddr::USER_RIGHT_MAGIC, sizeof(u16), buffer); - if (result == DriverResult::Success) { - const bool has_user_calibration = buffer[0] == 0xB2 && buffer[1] == 0xA1; - if (has_user_calibration) { - result = ReadSPI(CalAddr::USER_RIGHT_DATA, 9, buffer); - } else { - result = ReadSPI(CalAddr::FACT_RIGHT_DATA, 9, buffer); - } + result = HasUserCalibration(SpiAddress::USER_RIGHT_MAGIC, has_user_calibration); + } + + // Read User defined calibration + if (result == DriverResult::Success && has_user_calibration) { + result = ReadSPI(SpiAddress::USER_RIGHT_DATA, spi_calibration); + } + + // Read Factory calibration + if (result == DriverResult::Success && !has_user_calibration) { + result = ReadSPI(SpiAddress::FACT_RIGHT_DATA, spi_calibration); } if (result == DriverResult::Success) { - calibration.x.center = static_cast(((buffer[1] & 0x0F) << 8) | buffer[0]); - calibration.y.center = static_cast((buffer[2] << 4) | (buffer[1] >> 4)); - calibration.x.min = static_cast(((buffer[4] & 0x0F) << 8) | buffer[3]); - calibration.y.min = static_cast((buffer[5] << 4) | (buffer[4] >> 4)); - calibration.x.max = static_cast(((buffer[7] & 0x0F) << 8) | buffer[6]); - calibration.y.max = static_cast((buffer[8] << 4) | (buffer[7] >> 4)); + calibration.x.center = GetXAxisCalibrationValue(spi_calibration.center); + calibration.y.center = GetYAxisCalibrationValue(spi_calibration.center); + calibration.x.min = GetXAxisCalibrationValue(spi_calibration.min); + calibration.y.min = GetYAxisCalibrationValue(spi_calibration.min); + calibration.x.max = GetXAxisCalibrationValue(spi_calibration.max); + calibration.y.max = GetYAxisCalibrationValue(spi_calibration.max); } - // Nintendo fix for drifting stick - // buffer = ReadSPI(0x60, 0x98 , 16); - // joystick.deadzone = (u16)((buffer[4] << 8) & 0xF00 | buffer[3]); - // Set a valid default calibration if data is missing ValidateCalibration(calibration); @@ -85,39 +85,41 @@ DriverResult CalibrationProtocol::GetRightJoyStickCalibration(JoyStickCalibratio DriverResult CalibrationProtocol::GetImuCalibration(MotionCalibration& calibration) { ScopedSetBlocking sb(this); - std::vector buffer; DriverResult result{DriverResult::Success}; + ImuSpiCalibration spi_calibration{}; + bool has_user_calibration = false; calibration = {}; - result = ReadSPI(CalAddr::USER_IMU_MAGIC, sizeof(u16), buffer); - if (result == DriverResult::Success) { - const bool has_user_calibration = buffer[0] == 0xB2 && buffer[1] == 0xA1; - if (has_user_calibration) { - result = ReadSPI(CalAddr::USER_IMU_DATA, sizeof(IMUCalibration), buffer); - } else { - result = ReadSPI(CalAddr::FACT_IMU_DATA, sizeof(IMUCalibration), buffer); - } + result = HasUserCalibration(SpiAddress::USER_IMU_MAGIC, has_user_calibration); + } + + // Read User defined calibration + if (result == DriverResult::Success && has_user_calibration) { + result = ReadSPI(SpiAddress::USER_IMU_DATA, spi_calibration); + } + + // Read Factory calibration + if (result == DriverResult::Success && !has_user_calibration) { + result = ReadSPI(SpiAddress::FACT_IMU_DATA, spi_calibration); } if (result == DriverResult::Success) { - IMUCalibration device_calibration{}; - memcpy(&device_calibration, buffer.data(), sizeof(IMUCalibration)); - calibration.accelerometer[0].offset = device_calibration.accelerometer_offset[0]; - calibration.accelerometer[1].offset = device_calibration.accelerometer_offset[1]; - calibration.accelerometer[2].offset = device_calibration.accelerometer_offset[2]; + calibration.accelerometer[0].offset = spi_calibration.accelerometer_offset[0]; + calibration.accelerometer[1].offset = spi_calibration.accelerometer_offset[1]; + calibration.accelerometer[2].offset = spi_calibration.accelerometer_offset[2]; - calibration.accelerometer[0].scale = device_calibration.accelerometer_scale[0]; - calibration.accelerometer[1].scale = device_calibration.accelerometer_scale[1]; - calibration.accelerometer[2].scale = device_calibration.accelerometer_scale[2]; + calibration.accelerometer[0].scale = spi_calibration.accelerometer_scale[0]; + calibration.accelerometer[1].scale = spi_calibration.accelerometer_scale[1]; + calibration.accelerometer[2].scale = spi_calibration.accelerometer_scale[2]; - calibration.gyro[0].offset = device_calibration.gyroscope_offset[0]; - calibration.gyro[1].offset = device_calibration.gyroscope_offset[1]; - calibration.gyro[2].offset = device_calibration.gyroscope_offset[2]; + calibration.gyro[0].offset = spi_calibration.gyroscope_offset[0]; + calibration.gyro[1].offset = spi_calibration.gyroscope_offset[1]; + calibration.gyro[2].offset = spi_calibration.gyroscope_offset[2]; - calibration.gyro[0].scale = device_calibration.gyroscope_scale[0]; - calibration.gyro[1].scale = device_calibration.gyroscope_scale[1]; - calibration.gyro[2].scale = device_calibration.gyroscope_scale[2]; + calibration.gyro[0].scale = spi_calibration.gyroscope_scale[0]; + calibration.gyro[1].scale = spi_calibration.gyroscope_scale[1]; + calibration.gyro[2].scale = spi_calibration.gyroscope_scale[2]; } ValidateCalibration(calibration); @@ -127,10 +129,12 @@ DriverResult CalibrationProtocol::GetImuCalibration(MotionCalibration& calibrati DriverResult CalibrationProtocol::GetRingCalibration(RingCalibration& calibration, s16 current_value) { + constexpr s16 DefaultRingRange{800}; + // TODO: Get default calibration form ring itself if (ring_data_max == 0 && ring_data_min == 0) { - ring_data_max = current_value + 800; - ring_data_min = current_value - 800; + ring_data_max = current_value + DefaultRingRange; + ring_data_min = current_value - DefaultRingRange; ring_data_default = current_value; } ring_data_max = std::max(ring_data_max, current_value); @@ -143,42 +147,72 @@ DriverResult CalibrationProtocol::GetRingCalibration(RingCalibration& calibratio return DriverResult::Success; } +DriverResult CalibrationProtocol::HasUserCalibration(SpiAddress address, + bool& has_user_calibration) { + MagicSpiCalibration spi_magic{}; + const DriverResult result{ReadSPI(address, spi_magic)}; + has_user_calibration = false; + if (result == DriverResult::Success) { + has_user_calibration = spi_magic.first == CalibrationMagic::USR_MAGIC_0 && + spi_magic.second == CalibrationMagic::USR_MAGIC_1; + } + return result; +} + +u16 CalibrationProtocol::GetXAxisCalibrationValue(std::span block) const { + return static_cast(((block[1] & 0x0F) << 8) | block[0]); +} + +u16 CalibrationProtocol::GetYAxisCalibrationValue(std::span block) const { + return static_cast((block[2] << 4) | (block[1] >> 4)); +} + void CalibrationProtocol::ValidateCalibration(JoyStickCalibration& calibration) { - constexpr u16 DefaultStickCenter{2048}; - constexpr u16 DefaultStickRange{1740}; + constexpr u16 DefaultStickCenter{0x800}; + constexpr u16 DefaultStickRange{0x6cc}; - if (calibration.x.center == 0xFFF || calibration.x.center == 0) { - calibration.x.center = DefaultStickCenter; - } - if (calibration.x.max == 0xFFF || calibration.x.max == 0) { - calibration.x.max = DefaultStickRange; - } - if (calibration.x.min == 0xFFF || calibration.x.min == 0) { - calibration.x.min = DefaultStickRange; - } + calibration.x.center = ValidateValue(calibration.x.center, DefaultStickCenter); + calibration.x.max = ValidateValue(calibration.x.max, DefaultStickRange); + calibration.x.min = ValidateValue(calibration.x.min, DefaultStickRange); - if (calibration.y.center == 0xFFF || calibration.y.center == 0) { - calibration.y.center = DefaultStickCenter; - } - if (calibration.y.max == 0xFFF || calibration.y.max == 0) { - calibration.y.max = DefaultStickRange; - } - if (calibration.y.min == 0xFFF || calibration.y.min == 0) { - calibration.y.min = DefaultStickRange; - } + calibration.y.center = ValidateValue(calibration.y.center, DefaultStickCenter); + calibration.y.max = ValidateValue(calibration.y.max, DefaultStickRange); + calibration.y.min = ValidateValue(calibration.y.min, DefaultStickRange); } void CalibrationProtocol::ValidateCalibration(MotionCalibration& calibration) { + constexpr s16 DefaultAccelerometerScale{0x4000}; + constexpr s16 DefaultGyroScale{0x3be7}; + constexpr s16 DefaultOffset{0}; + for (auto& sensor : calibration.accelerometer) { - if (sensor.scale == 0) { - sensor.scale = 0x4000; - } + sensor.scale = ValidateValue(sensor.scale, DefaultAccelerometerScale); + sensor.offset = ValidateValue(sensor.offset, DefaultOffset); } for (auto& sensor : calibration.gyro) { - if (sensor.scale == 0) { - sensor.scale = 0x3be7; - } + sensor.scale = ValidateValue(sensor.scale, DefaultGyroScale); + sensor.offset = ValidateValue(sensor.offset, DefaultOffset); } } +u16 CalibrationProtocol::ValidateValue(u16 value, u16 default_value) const { + if (value == 0) { + return default_value; + } + if (value == 0xFFF) { + return default_value; + } + return value; +} + +s16 CalibrationProtocol::ValidateValue(s16 value, s16 default_value) const { + if (value == 0) { + return default_value; + } + if (value == 0xFFF) { + return default_value; + } + return value; +} + } // namespace InputCommon::Joycon diff --git a/src/input_common/helpers/joycon_protocol/calibration.h b/src/input_common/helpers/joycon_protocol/calibration.h index afb52a36a..c6fd0f729 100755 --- a/src/input_common/helpers/joycon_protocol/calibration.h +++ b/src/input_common/helpers/joycon_protocol/calibration.h @@ -53,9 +53,27 @@ public: DriverResult GetRingCalibration(RingCalibration& calibration, s16 current_value); private: + /// Returns true if the specified address corresponds to the magic value of user calibration + DriverResult HasUserCalibration(SpiAddress address, bool& has_user_calibration); + + /// Converts a raw calibration block to an u16 value containing the x axis value + u16 GetXAxisCalibrationValue(std::span block) const; + + /// Converts a raw calibration block to an u16 value containing the y axis value + u16 GetYAxisCalibrationValue(std::span block) const; + + /// Ensures that all joystick calibration values are set void ValidateCalibration(JoyStickCalibration& calibration); + + /// Ensures that all motion calibration values are set void ValidateCalibration(MotionCalibration& calibration); + /// Returns the default value if the value is either zero or 0xFFF + u16 ValidateValue(u16 value, u16 default_value) const; + + /// Returns the default value if the value is either zero or 0xFFF + s16 ValidateValue(s16 value, s16 default_value) const; + s16 ring_data_max = 0; s16 ring_data_default = 0; s16 ring_data_min = 0; diff --git a/src/input_common/helpers/joycon_protocol/common_protocol.cpp b/src/input_common/helpers/joycon_protocol/common_protocol.cpp index 417d0dcc5..0ef240344 100755 --- a/src/input_common/helpers/joycon_protocol/common_protocol.cpp +++ b/src/input_common/helpers/joycon_protocol/common_protocol.cpp @@ -22,8 +22,8 @@ void JoyconCommonProtocol::SetNonBlocking() { } DriverResult JoyconCommonProtocol::GetDeviceType(ControllerType& controller_type) { - std::vector buffer; - const auto result = ReadSPI(CalAddr::DEVICE_TYPE, 1, buffer); + std::array buffer{}; + const auto result = ReadRawSPI(SpiAddress::DEVICE_TYPE, buffer); controller_type = ControllerType::None; if (result == DriverResult::Success) { @@ -148,11 +148,13 @@ DriverResult JoyconCommonProtocol::SendVibrationReport(std::span buffe return SendData(local_buffer); } -DriverResult JoyconCommonProtocol::ReadSPI(CalAddr addr, u8 size, std::vector& output) { +DriverResult JoyconCommonProtocol::ReadRawSPI(SpiAddress addr, std::span output) { + constexpr std::size_t HeaderSize = 20; constexpr std::size_t MaxTries = 10; + const auto size = output.size(); std::size_t tries = 0; - std::array buffer = {0x00, 0x00, 0x00, 0x00, size}; - std::vector local_buffer(size + 20); + std::array buffer = {0x00, 0x00, 0x00, 0x00, static_cast(size)}; + std::vector local_buffer{}; buffer[0] = static_cast(static_cast(addr) & 0x00FF); buffer[1] = static_cast((static_cast(addr) & 0xFF00) >> 8); @@ -167,8 +169,12 @@ DriverResult JoyconCommonProtocol::ReadSPI(CalAddr addr, u8 size, std::vector(local_buffer.begin() + 20, local_buffer.begin() + 20 + size); + memcpy(output.data(), local_buffer.data() + HeaderSize, size); return DriverResult::Success; } diff --git a/src/input_common/helpers/joycon_protocol/common_protocol.h b/src/input_common/helpers/joycon_protocol/common_protocol.h index 903bcf402..75d3f20a4 100755 --- a/src/input_common/helpers/joycon_protocol/common_protocol.h +++ b/src/input_common/helpers/joycon_protocol/common_protocol.h @@ -97,10 +97,29 @@ public: /** * Reads the SPI memory stored on the joycon * @param Initial address location - * @param size in bytes to be read * @returns output buffer containing the responce */ - DriverResult ReadSPI(CalAddr addr, u8 size, std::vector& output); + DriverResult ReadRawSPI(SpiAddress addr, std::span output); + + /** + * Reads the SPI memory stored on the joycon + * @param Initial address location + * @returns output object containing the responce + */ + template + requires std::is_trivially_copyable_v DriverResult ReadSPI(SpiAddress addr, + Output& output) { + std::array buffer; + output = {}; + + const auto result = ReadRawSPI(addr, buffer); + if (result != DriverResult::Success) { + return result; + } + + std::memcpy(&output, buffer.data(), sizeof(Output)); + return DriverResult::Success; + } /** * Enables MCU chip on the joycon diff --git a/src/input_common/helpers/joycon_protocol/generic_functions.cpp b/src/input_common/helpers/joycon_protocol/generic_functions.cpp index 63cfb1369..484c208e6 100755 --- a/src/input_common/helpers/joycon_protocol/generic_functions.cpp +++ b/src/input_common/helpers/joycon_protocol/generic_functions.cpp @@ -71,8 +71,8 @@ DriverResult GenericProtocol::GetBattery(u32& battery_level) { DriverResult GenericProtocol::GetColor(Color& color) { ScopedSetBlocking sb(this); - std::vector buffer; - const auto result = ReadSPI(CalAddr::COLOR_DATA, 12, buffer); + std::array buffer{}; + const auto result = ReadRawSPI(SpiAddress::COLOR_DATA, buffer); color = {}; if (result == DriverResult::Success) { @@ -87,8 +87,8 @@ DriverResult GenericProtocol::GetColor(Color& color) { DriverResult GenericProtocol::GetSerialNumber(SerialNumber& serial_number) { ScopedSetBlocking sb(this); - std::vector buffer; - const auto result = ReadSPI(CalAddr::SERIAL_NUMBER, 16, buffer); + std::array buffer{}; + const auto result = ReadRawSPI(SpiAddress::SERIAL_NUMBER, buffer); serial_number = {}; if (result == DriverResult::Success) { diff --git a/src/input_common/helpers/joycon_protocol/joycon_types.h b/src/input_common/helpers/joycon_protocol/joycon_types.h index 182d2c15b..14b07bfb5 100755 --- a/src/input_common/helpers/joycon_protocol/joycon_types.h +++ b/src/input_common/helpers/joycon_protocol/joycon_types.h @@ -159,13 +159,12 @@ enum class UsbSubCommand : u8 { SEND_UART = 0x92, }; -enum class CalMagic : u8 { +enum class CalibrationMagic : u8 { USR_MAGIC_0 = 0xB2, USR_MAGIC_1 = 0xA1, - USRR_MAGI_SIZE = 2, }; -enum class CalAddr { +enum class SpiAddress { SERIAL_NUMBER = 0X6000, DEVICE_TYPE = 0X6012, COLOR_EXIST = 0X601B, @@ -396,10 +395,35 @@ struct MotionData { u64 delta_timestamp{}; }; +// Output from SPI read command containing user calibration magic +struct MagicSpiCalibration { + CalibrationMagic first; + CalibrationMagic second; +}; +static_assert(sizeof(MagicSpiCalibration) == 0x2, "MagicSpiCalibration is an invalid size"); + +// Output from SPI read command containing left joystick calibration +struct JoystickLeftSpiCalibration { + std::array max; + std::array center; + std::array min; +}; +static_assert(sizeof(JoystickLeftSpiCalibration) == 0x9, + "JoystickLeftSpiCalibration is an invalid size"); + +// Output from SPI read command containing right joystick calibration +struct JoystickRightSpiCalibration { + std::array center; + std::array min; + std::array max; +}; +static_assert(sizeof(JoystickRightSpiCalibration) == 0x9, + "JoystickRightSpiCalibration is an invalid size"); + struct JoyStickAxisCalibration { - u16 max{1}; - u16 min{1}; - u16 center{0}; + u16 max; + u16 min; + u16 center; }; struct JoyStickCalibration { @@ -407,6 +431,14 @@ struct JoyStickCalibration { JoyStickAxisCalibration y; }; +struct ImuSpiCalibration { + std::array accelerometer_offset; + std::array accelerometer_scale; + std::array gyroscope_offset; + std::array gyroscope_scale; +}; +static_assert(sizeof(ImuSpiCalibration) == 0x18, "ImuSpiCalibration is an invalid size"); + struct RingCalibration { s16 default_value; s16 max_value; @@ -488,14 +520,6 @@ struct InputReportNfcIr { static_assert(sizeof(InputReportNfcIr) == 0x29, "InputReportNfcIr is an invalid size"); #pragma pack(pop) -struct IMUCalibration { - std::array accelerometer_offset; - std::array accelerometer_scale; - std::array gyroscope_offset; - std::array gyroscope_scale; -}; -static_assert(sizeof(IMUCalibration) == 0x18, "IMUCalibration is an invalid size"); - struct NFCReadBlock { u8 start; u8 end; diff --git a/src/input_common/input_poller.cpp b/src/input_common/input_poller.cpp index 6daa96eeb..1f880e2ce 100755 --- a/src/input_common/input_poller.cpp +++ b/src/input_common/input_poller.cpp @@ -16,10 +16,10 @@ public: class InputFromButton final : public Common::Input::InputDevice { public: - explicit InputFromButton(PadIdentifier identifier_, int button_, bool toggle_, bool inverted_, - InputEngine* input_engine_) - : identifier(identifier_), button(button_), toggle(toggle_), inverted(inverted_), - input_engine(input_engine_) { + explicit InputFromButton(PadIdentifier identifier_, int button_, bool turbo_, bool toggle_, + bool inverted_, InputEngine* input_engine_) + : identifier(identifier_), button(button_), turbo(turbo_), toggle(toggle_), + inverted(inverted_), input_engine(input_engine_) { UpdateCallback engine_callback{[this]() { OnChange(); }}; const InputIdentifier input_identifier{ .identifier = identifier, @@ -40,6 +40,7 @@ public: .value = input_engine->GetButton(identifier, button), .inverted = inverted, .toggle = toggle, + .turbo = turbo, }; } @@ -68,6 +69,7 @@ public: private: const PadIdentifier identifier; const int button; + const bool turbo; const bool toggle; const bool inverted; int callback_key; @@ -77,10 +79,10 @@ private: class InputFromHatButton final : public Common::Input::InputDevice { public: - explicit InputFromHatButton(PadIdentifier identifier_, int button_, u8 direction_, bool toggle_, - bool inverted_, InputEngine* input_engine_) - : identifier(identifier_), button(button_), direction(direction_), toggle(toggle_), - inverted(inverted_), input_engine(input_engine_) { + explicit InputFromHatButton(PadIdentifier identifier_, int button_, u8 direction_, bool turbo_, + bool toggle_, bool inverted_, InputEngine* input_engine_) + : identifier(identifier_), button(button_), direction(direction_), turbo(turbo_), + toggle(toggle_), inverted(inverted_), input_engine(input_engine_) { UpdateCallback engine_callback{[this]() { OnChange(); }}; const InputIdentifier input_identifier{ .identifier = identifier, @@ -101,6 +103,7 @@ public: .value = input_engine->GetHatButton(identifier, button, direction), .inverted = inverted, .toggle = toggle, + .turbo = turbo, }; } @@ -130,6 +133,7 @@ private: const PadIdentifier identifier; const int button; const u8 direction; + const bool turbo; const bool toggle; const bool inverted; int callback_key; @@ -853,14 +857,15 @@ std::unique_ptr InputFactory::CreateButtonDevice( const auto keyboard_key = params.Get("code", 0); const auto toggle = params.Get("toggle", false) != 0; const auto inverted = params.Get("inverted", false) != 0; + const auto turbo = params.Get("turbo", false) != 0; input_engine->PreSetController(identifier); input_engine->PreSetButton(identifier, button_id); input_engine->PreSetButton(identifier, keyboard_key); if (keyboard_key != 0) { - return std::make_unique(identifier, keyboard_key, toggle, inverted, + return std::make_unique(identifier, keyboard_key, turbo, toggle, inverted, input_engine.get()); } - return std::make_unique(identifier, button_id, toggle, inverted, + return std::make_unique(identifier, button_id, turbo, toggle, inverted, input_engine.get()); } @@ -876,11 +881,12 @@ std::unique_ptr InputFactory::CreateHatButtonDevice( const auto direction = input_engine->GetHatButtonId(params.Get("direction", "")); const auto toggle = params.Get("toggle", false) != 0; const auto inverted = params.Get("inverted", false) != 0; + const auto turbo = params.Get("turbo", false) != 0; input_engine->PreSetController(identifier); input_engine->PreSetHatButton(identifier, button_id); - return std::make_unique(identifier, button_id, direction, toggle, inverted, - input_engine.get()); + return std::make_unique(identifier, button_id, direction, turbo, toggle, + inverted, input_engine.get()); } std::unique_ptr InputFactory::CreateStickDevice( diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp index db16d81f0..e59c2d64e 100755 --- a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp @@ -532,7 +532,7 @@ void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, } void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - ScalarS32 lod) { + ScalarS32 lod, [[maybe_unused]] const IR::Value& skip_mips) { const auto info{inst.Flags()}; const std::string texture{Texture(ctx, info, index)}; const std::string_view type{TextureType(info)}; diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index e91314b76..af551d0e8 100755 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h @@ -581,7 +581,7 @@ void EmitImageGatherDref(EmitContext& ctx, IR::Inst& inst, const IR::Value& inde void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, const IR::Value& coord, const IR::Value& offset, ScalarS32 lod, ScalarS32 ms); void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - ScalarS32 lod); + ScalarS32 lod, const IR::Value& skip_mips); void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord); void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, const IR::Value& coord, const IR::Value& derivatives, diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp index de2c3e903..18b39b956 100755 --- a/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp @@ -460,27 +460,27 @@ void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, } void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view lod) { + std::string_view lod, const IR::Value& skip_mips_val) { const auto info{inst.Flags()}; const auto texture{Texture(ctx, info, index)}; + const bool skip_mips{skip_mips_val.U1()}; + const auto mips{ + [&] { return skip_mips ? "0u" : fmt::format("uint(textureQueryLevels({}))", texture); }}; switch (info.type) { case TextureType::Color1D: - return ctx.AddU32x4( - "{}=uvec4(uint(textureSize({},int({}))),0u,0u,uint(textureQueryLevels({})));", inst, - texture, lod, texture); + return ctx.AddU32x4("{}=uvec4(uint(textureSize({},int({}))),0u,0u,{});", inst, texture, lod, + mips()); case TextureType::ColorArray1D: case TextureType::Color2D: case TextureType::ColorCube: case TextureType::Color2DRect: - return ctx.AddU32x4( - "{}=uvec4(uvec2(textureSize({},int({}))),0u,uint(textureQueryLevels({})));", inst, - texture, lod, texture); + return ctx.AddU32x4("{}=uvec4(uvec2(textureSize({},int({}))),0u,{});", inst, texture, lod, + mips()); case TextureType::ColorArray2D: case TextureType::Color3D: case TextureType::ColorArrayCube: - return ctx.AddU32x4( - "{}=uvec4(uvec3(textureSize({},int({}))),uint(textureQueryLevels({})));", inst, texture, - lod, texture); + return ctx.AddU32x4("{}=uvec4(uvec3(textureSize({},int({}))),{});", inst, texture, lod, + mips()); case TextureType::Buffer: throw NotImplementedException("EmitImageQueryDimensions Texture buffers"); } diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h b/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h index ebef278cc..f8c862a32 100755 --- a/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h +++ b/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h @@ -654,7 +654,7 @@ void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords, std::string_view offset, std::string_view lod, std::string_view ms); void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, - std::string_view lod); + std::string_view lod, const IR::Value& skip_mips); void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, std::string_view coords); void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp index 2167536c3..e68a6169e 100755 --- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp @@ -445,11 +445,13 @@ Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id c TextureImage(ctx, info, index), coords, operands.MaskOptional(), operands.Span()); } -Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod) { +Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod, + const IR::Value& skip_mips_val) { const auto info{inst->Flags()}; const Id image{TextureImage(ctx, info, index)}; const Id zero{ctx.u32_zero_value}; - const auto mips{[&] { return ctx.OpImageQueryLevels(ctx.U32[1], image); }}; + const bool skip_mips{skip_mips_val.U1()}; + const auto mips{[&] { return skip_mips ? zero : ctx.OpImageQueryLevels(ctx.U32[1], image); }}; switch (info.type) { case TextureType::Color1D: return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[1], image, lod), diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h index 44e78ad5c..e30e0c459 100755 --- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h @@ -539,7 +539,8 @@ Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, const IR::Value& offset, const IR::Value& offset2, Id dref); Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset, Id lod, Id ms); -Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod); +Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod, + const IR::Value& skip_mips); Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords); Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id derivates, Id offset, Id lod_clamp); diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp index aa3be4b6d..5a2791309 100755 --- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp +++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp @@ -1846,15 +1846,16 @@ Value IREmitter::ImageFetch(const Value& handle, const Value& coords, const Valu return Inst(op, Flags{info}, handle, coords, offset, lod, multisampling); } -Value IREmitter::ImageQueryDimension(const Value& handle, const IR::U32& lod) { +Value IREmitter::ImageQueryDimension(const Value& handle, const IR::U32& lod, + const IR::U1& skip_mips) { const Opcode op{handle.IsImmediate() ? Opcode::BoundImageQueryDimensions : Opcode::BindlessImageQueryDimensions}; - return Inst(op, handle, lod); + return Inst(op, handle, lod, skip_mips); } Value IREmitter::ImageQueryDimension(const Value& handle, const IR::U32& lod, - TextureInstInfo info) { - return Inst(Opcode::ImageQueryDimensions, Flags{info}, handle, lod); + const IR::U1& skip_mips, TextureInstInfo info) { + return Inst(Opcode::ImageQueryDimensions, Flags{info}, handle, lod, skip_mips); } Value IREmitter::ImageQueryLod(const Value& handle, const Value& coords, TextureInstInfo info) { diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h index 4ea1457a0..c94eef89b 100755 --- a/src/shader_recompiler/frontend/ir/ir_emitter.h +++ b/src/shader_recompiler/frontend/ir/ir_emitter.h @@ -320,9 +320,10 @@ public: [[nodiscard]] F32 ImageSampleDrefExplicitLod(const Value& handle, const Value& coords, const F32& dref, const F32& lod, const Value& offset, TextureInstInfo info); - [[nodiscard]] Value ImageQueryDimension(const Value& handle, const IR::U32& lod); [[nodiscard]] Value ImageQueryDimension(const Value& handle, const IR::U32& lod, - TextureInstInfo info); + const IR::U1& skip_mips); + [[nodiscard]] Value ImageQueryDimension(const Value& handle, const IR::U32& lod, + const IR::U1& skip_mips, TextureInstInfo info); [[nodiscard]] Value ImageQueryLod(const Value& handle, const Value& coords, TextureInstInfo info); diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc index ca9065a8c..3ae9196bf 100755 --- a/src/shader_recompiler/frontend/ir/opcodes.inc +++ b/src/shader_recompiler/frontend/ir/opcodes.inc @@ -482,7 +482,7 @@ OPCODE(BindlessImageSampleDrefExplicitLod, F32, U32, OPCODE(BindlessImageGather, F32x4, U32, Opaque, Opaque, Opaque, ) OPCODE(BindlessImageGatherDref, F32x4, U32, Opaque, Opaque, Opaque, F32, ) OPCODE(BindlessImageFetch, F32x4, U32, Opaque, Opaque, U32, Opaque, ) -OPCODE(BindlessImageQueryDimensions, U32x4, U32, U32, ) +OPCODE(BindlessImageQueryDimensions, U32x4, U32, U32, U1, ) OPCODE(BindlessImageQueryLod, F32x4, U32, Opaque, ) OPCODE(BindlessImageGradient, F32x4, U32, Opaque, Opaque, Opaque, Opaque, ) OPCODE(BindlessImageRead, U32x4, U32, Opaque, ) @@ -495,7 +495,7 @@ OPCODE(BoundImageSampleDrefExplicitLod, F32, U32, OPCODE(BoundImageGather, F32x4, U32, Opaque, Opaque, Opaque, ) OPCODE(BoundImageGatherDref, F32x4, U32, Opaque, Opaque, Opaque, F32, ) OPCODE(BoundImageFetch, F32x4, U32, Opaque, Opaque, U32, Opaque, ) -OPCODE(BoundImageQueryDimensions, U32x4, U32, U32, ) +OPCODE(BoundImageQueryDimensions, U32x4, U32, U32, U1, ) OPCODE(BoundImageQueryLod, F32x4, U32, Opaque, ) OPCODE(BoundImageGradient, F32x4, U32, Opaque, Opaque, Opaque, Opaque, ) OPCODE(BoundImageRead, U32x4, U32, Opaque, ) @@ -508,7 +508,7 @@ OPCODE(ImageSampleDrefExplicitLod, F32, Opaq OPCODE(ImageGather, F32x4, Opaque, Opaque, Opaque, Opaque, ) OPCODE(ImageGatherDref, F32x4, Opaque, Opaque, Opaque, Opaque, F32, ) OPCODE(ImageFetch, F32x4, Opaque, Opaque, Opaque, U32, Opaque, ) -OPCODE(ImageQueryDimensions, U32x4, Opaque, U32, ) +OPCODE(ImageQueryDimensions, U32x4, Opaque, U32, U1, ) OPCODE(ImageQueryLod, F32x4, Opaque, Opaque, ) OPCODE(ImageGradient, F32x4, Opaque, Opaque, Opaque, Opaque, Opaque, ) OPCODE(ImageRead, U32x4, Opaque, Opaque, ) diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_query.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_query.cpp index b7250a8a3..193ef1dde 100755 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_query.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_query.cpp @@ -15,11 +15,13 @@ enum class Mode : u64 { SamplePos = 5, }; -IR::Value Query(TranslatorVisitor& v, const IR::U32& handle, Mode mode, IR::Reg src_reg) { +IR::Value Query(TranslatorVisitor& v, const IR::U32& handle, Mode mode, IR::Reg src_reg, u64 mask) { switch (mode) { case Mode::Dimension: { + const bool needs_num_mips{((mask >> 3) & 1) != 0}; + const IR::U1 skip_mips{v.ir.Imm1(!needs_num_mips)}; const IR::U32 lod{v.X(src_reg)}; - return v.ir.ImageQueryDimension(handle, lod); + return v.ir.ImageQueryDimension(handle, lod, skip_mips); } case Mode::TextureType: case Mode::SamplePos: @@ -46,7 +48,7 @@ void Impl(TranslatorVisitor& v, u64 insn, std::optional cbuf_offset) { handle = v.X(src_reg); ++src_reg; } - const IR::Value query{Query(v, handle, txq.mode, src_reg)}; + const IR::Value query{Query(v, handle, txq.mode, src_reg, txq.mask)}; IR::Reg dest_reg{txq.dest_reg}; for (int element = 0; element < 4; ++element) { if (((txq.mask >> element) & 1) == 0) { diff --git a/src/shader_recompiler/ir_opt/texture_pass.cpp b/src/shader_recompiler/ir_opt/texture_pass.cpp index 55a8bc764..9ce917c62 100755 --- a/src/shader_recompiler/ir_opt/texture_pass.cpp +++ b/src/shader_recompiler/ir_opt/texture_pass.cpp @@ -355,21 +355,21 @@ TextureInst MakeInst(Environment& env, IR::Block* block, IR::Inst& inst) { }; } -TextureType ReadTextureType(Environment& env, const ConstBufferAddr& cbuf) { +u32 GetTextureHandle(Environment& env, const ConstBufferAddr& cbuf) { const u32 secondary_index{cbuf.has_secondary ? cbuf.secondary_index : cbuf.index}; const u32 secondary_offset{cbuf.has_secondary ? cbuf.secondary_offset : cbuf.offset}; const u32 lhs_raw{env.ReadCbufValue(cbuf.index, cbuf.offset) << cbuf.shift_left}; const u32 rhs_raw{env.ReadCbufValue(secondary_index, secondary_offset) << cbuf.secondary_shift_left}; - return env.ReadTextureType(lhs_raw | rhs_raw); + return lhs_raw | rhs_raw; +} + +TextureType ReadTextureType(Environment& env, const ConstBufferAddr& cbuf) { + return env.ReadTextureType(GetTextureHandle(env, cbuf)); } TexturePixelFormat ReadTexturePixelFormat(Environment& env, const ConstBufferAddr& cbuf) { - const u32 secondary_index{cbuf.has_secondary ? cbuf.secondary_index : cbuf.index}; - const u32 secondary_offset{cbuf.has_secondary ? cbuf.secondary_offset : cbuf.offset}; - const u32 lhs_raw{env.ReadCbufValue(cbuf.index, cbuf.offset)}; - const u32 rhs_raw{env.ReadCbufValue(secondary_index, secondary_offset)}; - return env.ReadTexturePixelFormat(lhs_raw | rhs_raw); + return env.ReadTexturePixelFormat(GetTextureHandle(env, cbuf)); } class Descriptors { @@ -386,8 +386,10 @@ public: return Add(texture_buffer_descriptors, desc, [&desc](const auto& existing) { return desc.cbuf_index == existing.cbuf_index && desc.cbuf_offset == existing.cbuf_offset && + desc.shift_left == existing.shift_left && desc.secondary_cbuf_index == existing.secondary_cbuf_index && desc.secondary_cbuf_offset == existing.secondary_cbuf_offset && + desc.secondary_shift_left == existing.secondary_shift_left && desc.count == existing.count && desc.size_shift == existing.size_shift && desc.has_secondary == existing.has_secondary; }); @@ -405,15 +407,20 @@ public: } u32 Add(const TextureDescriptor& desc) { - return Add(texture_descriptors, desc, [&desc](const auto& existing) { + const u32 index{Add(texture_descriptors, desc, [&desc](const auto& existing) { return desc.type == existing.type && desc.is_depth == existing.is_depth && desc.has_secondary == existing.has_secondary && desc.cbuf_index == existing.cbuf_index && desc.cbuf_offset == existing.cbuf_offset && + desc.shift_left == existing.shift_left && desc.secondary_cbuf_index == existing.secondary_cbuf_index && desc.secondary_cbuf_offset == existing.secondary_cbuf_offset && + desc.secondary_shift_left == existing.secondary_shift_left && desc.count == existing.count && desc.size_shift == existing.size_shift; - }); + })}; + // TODO: Read this from TIC + texture_descriptors[index].is_multisample |= desc.is_multisample; + return index; } u32 Add(const ImageDescriptor& desc) { @@ -452,7 +459,8 @@ void PatchImageSampleImplicitLod(IR::Block& block, IR::Inst& inst) { const IR::Value coord(inst.Arg(1)); const IR::Value handle(ir.Imm32(0)); const IR::U32 lod{ir.Imm32(0)}; - const IR::Value texture_size = ir.ImageQueryDimension(handle, lod, info); + const IR::U1 skip_mips{ir.Imm1(true)}; + const IR::Value texture_size = ir.ImageQueryDimension(handle, lod, skip_mips, info); inst.SetArg( 1, ir.CompositeConstruct( ir.FPMul(IR::F32(ir.CompositeExtract(coord, 0)), diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt index e8cef450f..99e846fb5 100755 --- a/src/video_core/host_shaders/CMakeLists.txt +++ b/src/video_core/host_shaders/CMakeLists.txt @@ -45,6 +45,8 @@ set(SHADER_FILES smaa_neighborhood_blending.vert smaa_neighborhood_blending.frag vulkan_blit_depth_stencil.frag + vulkan_color_clear.frag + vulkan_color_clear.vert vulkan_fidelityfx_fsr_easu_fp16.comp vulkan_fidelityfx_fsr_easu_fp32.comp vulkan_fidelityfx_fsr_rcas_fp16.comp diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp index 3b219408f..dc996049d 100755 --- a/src/video_core/renderer_vulkan/blit_image.cpp +++ b/src/video_core/renderer_vulkan/blit_image.cpp @@ -12,6 +12,8 @@ #include "video_core/host_shaders/convert_s8d24_to_abgr8_frag_spv.h" #include "video_core/host_shaders/full_screen_triangle_vert_spv.h" #include "video_core/host_shaders/vulkan_blit_depth_stencil_frag_spv.h" +#include "video_core/host_shaders/vulkan_color_clear_frag_spv.h" +#include "video_core/host_shaders/vulkan_color_clear_vert_spv.h" #include "video_core/renderer_vulkan/blit_image.h" #include "video_core/renderer_vulkan/maxwell_to_vk.h" #include "video_core/renderer_vulkan/vk_scheduler.h" @@ -69,10 +71,11 @@ constexpr VkDescriptorSetLayoutCreateInfo TWO_TEXTURES_DESCRIPTOR_SET_LAYOUT_CRE .bindingCount = static_cast(TWO_TEXTURES_DESCRIPTOR_SET_LAYOUT_BINDINGS.size()), .pBindings = TWO_TEXTURES_DESCRIPTOR_SET_LAYOUT_BINDINGS.data(), }; -constexpr VkPushConstantRange PUSH_CONSTANT_RANGE{ - .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, +template +inline constexpr VkPushConstantRange PUSH_CONSTANT_RANGE{ + .stageFlags = stageFlags, .offset = 0, - .size = sizeof(PushConstants), + .size = static_cast(size), }; constexpr VkPipelineVertexInputStateCreateInfo PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO{ .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, @@ -125,10 +128,8 @@ constexpr VkPipelineMultisampleStateCreateInfo PIPELINE_MULTISAMPLE_STATE_CREATE .alphaToCoverageEnable = VK_FALSE, .alphaToOneEnable = VK_FALSE, }; -constexpr std::array DYNAMIC_STATES{ - VK_DYNAMIC_STATE_VIEWPORT, - VK_DYNAMIC_STATE_SCISSOR, -}; +constexpr std::array DYNAMIC_STATES{VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR, + VK_DYNAMIC_STATE_BLEND_CONSTANTS}; constexpr VkPipelineDynamicStateCreateInfo PIPELINE_DYNAMIC_STATE_CREATE_INFO{ .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, .pNext = nullptr, @@ -205,15 +206,15 @@ inline constexpr VkSamplerCreateInfo SAMPLER_CREATE_INFO{ }; constexpr VkPipelineLayoutCreateInfo PipelineLayoutCreateInfo( - const VkDescriptorSetLayout* set_layout) { + const VkDescriptorSetLayout* set_layout, vk::Span push_constants) { return VkPipelineLayoutCreateInfo{ .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, .pNext = nullptr, .flags = 0, - .setLayoutCount = 1, + .setLayoutCount = (set_layout != nullptr ? 1u : 0u), .pSetLayouts = set_layout, - .pushConstantRangeCount = 1, - .pPushConstantRanges = &PUSH_CONSTANT_RANGE, + .pushConstantRangeCount = push_constants.size(), + .pPushConstantRanges = push_constants.data(), }; } @@ -302,8 +303,7 @@ void UpdateTwoTexturesDescriptorSet(const Device& device, VkDescriptorSet descri device.GetLogical().UpdateDescriptorSets(write_descriptor_sets, nullptr); } -void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout, const Region2D& dst_region, - const Region2D& src_region, const Extent3D& src_size = {1, 1, 1}) { +void BindBlitState(vk::CommandBuffer cmdbuf, const Region2D& dst_region) { const VkOffset2D offset{ .x = std::min(dst_region.start.x, dst_region.end.x), .y = std::min(dst_region.start.y, dst_region.end.y), @@ -325,6 +325,13 @@ void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout, const Regi .offset = offset, .extent = extent, }; + cmdbuf.SetViewport(0, viewport); + cmdbuf.SetScissor(0, scissor); +} + +void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout, const Region2D& dst_region, + const Region2D& src_region, const Extent3D& src_size = {1, 1, 1}) { + BindBlitState(cmdbuf, dst_region); const float scale_x = static_cast(src_region.end.x - src_region.start.x) / static_cast(src_size.width); const float scale_y = static_cast(src_region.end.y - src_region.start.y) / @@ -335,8 +342,6 @@ void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout, const Regi static_cast(src_region.start.y) / static_cast(src_size.height)}, }; - cmdbuf.SetViewport(0, viewport); - cmdbuf.SetScissor(0, scissor); cmdbuf.PushConstants(layout, VK_SHADER_STAGE_VERTEX_BIT, push_constants); } @@ -408,13 +413,20 @@ BlitImageHelper::BlitImageHelper(const Device& device_, Scheduler& scheduler_, descriptor_pool.Allocator(*one_texture_set_layout, TEXTURE_DESCRIPTOR_BANK_INFO<1>)}, two_textures_descriptor_allocator{ descriptor_pool.Allocator(*two_textures_set_layout, TEXTURE_DESCRIPTOR_BANK_INFO<2>)}, - one_texture_pipeline_layout(device.GetLogical().CreatePipelineLayout( - PipelineLayoutCreateInfo(one_texture_set_layout.address()))), - two_textures_pipeline_layout(device.GetLogical().CreatePipelineLayout( - PipelineLayoutCreateInfo(two_textures_set_layout.address()))), + one_texture_pipeline_layout(device.GetLogical().CreatePipelineLayout(PipelineLayoutCreateInfo( + one_texture_set_layout.address(), + PUSH_CONSTANT_RANGE))), + two_textures_pipeline_layout( + device.GetLogical().CreatePipelineLayout(PipelineLayoutCreateInfo( + two_textures_set_layout.address(), + PUSH_CONSTANT_RANGE))), + clear_color_pipeline_layout(device.GetLogical().CreatePipelineLayout(PipelineLayoutCreateInfo( + nullptr, PUSH_CONSTANT_RANGE))), full_screen_vert(BuildShader(device, FULL_SCREEN_TRIANGLE_VERT_SPV)), blit_color_to_color_frag(BuildShader(device, BLIT_COLOR_FLOAT_FRAG_SPV)), blit_depth_stencil_frag(BuildShader(device, VULKAN_BLIT_DEPTH_STENCIL_FRAG_SPV)), + clear_color_vert(BuildShader(device, VULKAN_COLOR_CLEAR_VERT_SPV)), + clear_color_frag(BuildShader(device, VULKAN_COLOR_CLEAR_FRAG_SPV)), convert_depth_to_float_frag(BuildShader(device, CONVERT_DEPTH_TO_FLOAT_FRAG_SPV)), convert_float_to_depth_frag(BuildShader(device, CONVERT_FLOAT_TO_DEPTH_FRAG_SPV)), convert_abgr8_to_d24s8_frag(BuildShader(device, CONVERT_ABGR8_TO_D24S8_FRAG_SPV)), @@ -553,6 +565,30 @@ void BlitImageHelper::ConvertS8D24ToABGR8(const Framebuffer* dst_framebuffer, ConvertDepthStencil(*convert_s8d24_to_abgr8_pipeline, dst_framebuffer, src_image_view); } +void BlitImageHelper::ClearColor(const Framebuffer* dst_framebuffer, u8 color_mask, + const std::array& clear_color, + const Region2D& dst_region) { + const BlitImagePipelineKey key{ + .renderpass = dst_framebuffer->RenderPass(), + .operation = Tegra::Engines::Fermi2D::Operation::BlendPremult, + }; + const VkPipeline pipeline = FindOrEmplaceClearColorPipeline(key); + const VkPipelineLayout layout = *clear_color_pipeline_layout; + scheduler.RequestRenderpass(dst_framebuffer); + scheduler.Record( + [pipeline, layout, color_mask, clear_color, dst_region](vk::CommandBuffer cmdbuf) { + cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); + const std::array blend_color = { + (color_mask & 0x1) ? 1.0f : 0.0f, (color_mask & 0x2) ? 1.0f : 0.0f, + (color_mask & 0x4) ? 1.0f : 0.0f, (color_mask & 0x8) ? 1.0f : 0.0f}; + cmdbuf.SetBlendConstants(blend_color.data()); + BindBlitState(cmdbuf, dst_region); + cmdbuf.PushConstants(layout, VK_SHADER_STAGE_FRAGMENT_BIT, clear_color); + cmdbuf.Draw(3, 1, 0, 0); + }); + scheduler.InvalidateState(); +} + void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer, const ImageView& src_image_view) { const VkPipelineLayout layout = *one_texture_pipeline_layout; @@ -728,6 +764,58 @@ VkPipeline BlitImageHelper::FindOrEmplaceDepthStencilPipeline(const BlitImagePip return *blit_depth_stencil_pipelines.back(); } +VkPipeline BlitImageHelper::FindOrEmplaceClearColorPipeline(const BlitImagePipelineKey& key) { + const auto it = std::ranges::find(clear_color_keys, key); + if (it != clear_color_keys.end()) { + return *clear_color_pipelines[std::distance(clear_color_keys.begin(), it)]; + } + clear_color_keys.push_back(key); + const std::array stages = MakeStages(*clear_color_vert, *clear_color_frag); + const VkPipelineColorBlendAttachmentState color_blend_attachment_state{ + .blendEnable = VK_TRUE, + .srcColorBlendFactor = VK_BLEND_FACTOR_CONSTANT_COLOR, + .dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR, + .colorBlendOp = VK_BLEND_OP_ADD, + .srcAlphaBlendFactor = VK_BLEND_FACTOR_CONSTANT_ALPHA, + .dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA, + .alphaBlendOp = VK_BLEND_OP_ADD, + .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | + VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, + }; + const VkPipelineColorBlendStateCreateInfo color_blend_state_generic_create_info{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .logicOpEnable = VK_FALSE, + .logicOp = VK_LOGIC_OP_CLEAR, + .attachmentCount = 1, + .pAttachments = &color_blend_attachment_state, + .blendConstants = {0.0f, 0.0f, 0.0f, 0.0f}, + }; + clear_color_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ + .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .stageCount = static_cast(stages.size()), + .pStages = stages.data(), + .pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, + .pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, + .pTessellationState = nullptr, + .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, + .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, + .pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, + .pDepthStencilState = &PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, + .pColorBlendState = &color_blend_state_generic_create_info, + .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO, + .layout = *clear_color_pipeline_layout, + .renderPass = key.renderpass, + .subpass = 0, + .basePipelineHandle = VK_NULL_HANDLE, + .basePipelineIndex = 0, + })); + return *clear_color_pipelines.back(); +} + void BlitImageHelper::ConvertPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass, bool is_target_depth) { if (pipeline) { diff --git a/src/video_core/renderer_vulkan/blit_image.h b/src/video_core/renderer_vulkan/blit_image.h index 089cf92d2..4aed7f1af 100755 --- a/src/video_core/renderer_vulkan/blit_image.h +++ b/src/video_core/renderer_vulkan/blit_image.h @@ -61,6 +61,9 @@ public: void ConvertS8D24ToABGR8(const Framebuffer* dst_framebuffer, ImageView& src_image_view); + void ClearColor(const Framebuffer* dst_framebuffer, u8 color_mask, + const std::array& clear_color, const Region2D& dst_region); + private: void Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer, const ImageView& src_image_view); @@ -72,6 +75,8 @@ private: [[nodiscard]] VkPipeline FindOrEmplaceDepthStencilPipeline(const BlitImagePipelineKey& key); + [[nodiscard]] VkPipeline FindOrEmplaceClearColorPipeline(const BlitImagePipelineKey& key); + void ConvertPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass, bool is_target_depth); void ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass); @@ -97,9 +102,12 @@ private: DescriptorAllocator two_textures_descriptor_allocator; vk::PipelineLayout one_texture_pipeline_layout; vk::PipelineLayout two_textures_pipeline_layout; + vk::PipelineLayout clear_color_pipeline_layout; vk::ShaderModule full_screen_vert; vk::ShaderModule blit_color_to_color_frag; vk::ShaderModule blit_depth_stencil_frag; + vk::ShaderModule clear_color_vert; + vk::ShaderModule clear_color_frag; vk::ShaderModule convert_depth_to_float_frag; vk::ShaderModule convert_float_to_depth_frag; vk::ShaderModule convert_abgr8_to_d24s8_frag; @@ -112,6 +120,8 @@ private: std::vector blit_color_pipelines; std::vector blit_depth_stencil_keys; std::vector blit_depth_stencil_pipelines; + std::vector clear_color_keys; + std::vector clear_color_pipelines; vk::Pipeline convert_d32_to_r32_pipeline; vk::Pipeline convert_r32_to_d32_pipeline; vk::Pipeline convert_d16_to_r16_pipeline; diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 073cb1271..4d64a62f8 100755 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -394,7 +394,15 @@ void RasterizerVulkan::Clear(u32 layer_count) { cmdbuf.ClearAttachments(attachment, clear_rect); }); } else { - UNIMPLEMENTED_MSG("Unimplemented Clear only the specified channel"); + u8 color_mask = static_cast(regs.clear_surface.R | regs.clear_surface.G << 1 | + regs.clear_surface.B << 2 | regs.clear_surface.A << 3); + Region2D dst_region = { + Offset2D{.x = clear_rect.rect.offset.x, .y = clear_rect.rect.offset.y}, + Offset2D{.x = clear_rect.rect.offset.x + + static_cast(clear_rect.rect.extent.width), + .y = clear_rect.rect.offset.y + + static_cast(clear_rect.rect.extent.height)}}; + blit_image.ClearColor(framebuffer, color_mask, regs.clear_color, dst_region); } } diff --git a/src/yuzu/applets/qt_software_keyboard.cpp b/src/yuzu/applets/qt_software_keyboard.cpp index 06ccaa108..d4a144376 100755 --- a/src/yuzu/applets/qt_software_keyboard.cpp +++ b/src/yuzu/applets/qt_software_keyboard.cpp @@ -575,7 +575,7 @@ void QtSoftwareKeyboardDialog::MoveAndResizeWindow(QPoint pos, QSize size) { QDialog::resize(size); // High DPI - const float dpi_scale = qApp->screenAt(pos)->logicalDotsPerInch() / 96.0f; + const float dpi_scale = screen()->logicalDotsPerInch() / 96.0f; RescaleKeyboardElements(size.width(), size.height(), dpi_scale); } diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index 9bfc6ea88..b6f086be3 100755 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -182,12 +182,13 @@ QString ConfigureInputPlayer::ButtonToText(const Common::ParamPackage& param) { const QString toggle = QString::fromStdString(param.Get("toggle", false) ? "~" : ""); const QString inverted = QString::fromStdString(param.Get("inverted", false) ? "!" : ""); const QString invert = QString::fromStdString(param.Get("invert", "+") == "-" ? "-" : ""); + const QString turbo = QString::fromStdString(param.Get("turbo", false) ? "$" : ""); const auto common_button_name = input_subsystem->GetButtonName(param); // Retrieve the names from Qt if (param.Get("engine", "") == "keyboard") { const QString button_str = GetKeyName(param.Get("code", 0)); - return QObject::tr("%1%2%3").arg(toggle, inverted, button_str); + return QObject::tr("%1%2%3%4").arg(turbo, toggle, inverted, button_str); } if (common_button_name == Common::Input::ButtonNames::Invalid) { @@ -201,7 +202,7 @@ QString ConfigureInputPlayer::ButtonToText(const Common::ParamPackage& param) { if (common_button_name == Common::Input::ButtonNames::Value) { if (param.Has("hat")) { const QString hat = GetDirectionName(param.Get("direction", "")); - return QObject::tr("%1%2Hat %3").arg(toggle, inverted, hat); + return QObject::tr("%1%2%3Hat %4").arg(turbo, toggle, inverted, hat); } if (param.Has("axis")) { const QString axis = QString::fromStdString(param.Get("axis", "")); @@ -219,13 +220,13 @@ QString ConfigureInputPlayer::ButtonToText(const Common::ParamPackage& param) { } if (param.Has("button")) { const QString button = QString::fromStdString(param.Get("button", "")); - return QObject::tr("%1%2Button %3").arg(toggle, inverted, button); + return QObject::tr("%1%2%3Button %4").arg(turbo, toggle, inverted, button); } } QString button_name = GetButtonName(common_button_name); if (param.Has("hat")) { - return QObject::tr("%1%2Hat %3").arg(toggle, inverted, button_name); + return QObject::tr("%1%2%3Hat %4").arg(turbo, toggle, inverted, button_name); } if (param.Has("axis")) { return QObject::tr("%1%2Axis %3").arg(toggle, inverted, button_name); @@ -234,7 +235,7 @@ QString ConfigureInputPlayer::ButtonToText(const Common::ParamPackage& param) { return QObject::tr("%1%2Axis %3").arg(toggle, inverted, button_name); } if (param.Has("button")) { - return QObject::tr("%1%2Button %3").arg(toggle, inverted, button_name); + return QObject::tr("%1%2%3Button %4").arg(turbo, toggle, inverted, button_name); } return QObject::tr("[unknown]"); @@ -395,6 +396,12 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i button_map[button_id]->setText(ButtonToText(param)); emulated_controller->SetButtonParam(button_id, param); }); + context_menu.addAction(tr("Turbo button"), [&] { + const bool turbo_value = !param.Get("turbo", false); + param.Set("turbo", turbo_value); + button_map[button_id]->setText(ButtonToText(param)); + emulated_controller->SetButtonParam(button_id, param); + }); } if (param.Has("axis")) { context_menu.addAction(tr("Invert axis"), [&] { diff --git a/src/yuzu/discord_impl.cpp b/src/yuzu/discord_impl.cpp index 020b8ae2c..567a89345 100755 --- a/src/yuzu/discord_impl.cpp +++ b/src/yuzu/discord_impl.cpp @@ -38,7 +38,7 @@ void DiscordImpl::Update() { system.GetAppLoader().ReadTitle(title); } DiscordRichPresence presence{}; - presence.largeImageKey = "yuzu_logo"; + presence.largeImageKey = "yuzu_logo_ea"; presence.largeImageText = "yuzu is an emulator for the Nintendo Switch"; if (system.IsPoweredOn()) { presence.state = title.c_str(); diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 8154e2da5..fe0415019 100755 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -680,8 +680,10 @@ void GMainWindow::SoftwareKeyboardShowNormal() { const auto y = layout.screen.top; const auto w = layout.screen.GetWidth(); const auto h = layout.screen.GetHeight(); + const auto scale_ratio = devicePixelRatioF(); - software_keyboard->ShowNormalKeyboard(render_window->mapToGlobal(QPoint(x, y)), QSize(w, h)); + software_keyboard->ShowNormalKeyboard(render_window->mapToGlobal(QPoint(x, y) / scale_ratio), + QSize(w, h) / scale_ratio); } void GMainWindow::SoftwareKeyboardShowTextCheck( @@ -714,9 +716,11 @@ void GMainWindow::SoftwareKeyboardShowInline( (1.0f - appear_parameters.key_top_scale_y)))); const auto w = static_cast(layout.screen.GetWidth() * appear_parameters.key_top_scale_x); const auto h = static_cast(layout.screen.GetHeight() * appear_parameters.key_top_scale_y); + const auto scale_ratio = devicePixelRatioF(); software_keyboard->ShowInlineKeyboard(std::move(appear_parameters), - render_window->mapToGlobal(QPoint(x, y)), QSize(w, h)); + render_window->mapToGlobal(QPoint(x, y) / scale_ratio), + QSize(w, h) / scale_ratio); } void GMainWindow::SoftwareKeyboardHideInline() { @@ -796,10 +800,11 @@ void GMainWindow::WebBrowserOpenWebPage(const std::string& main_url, } const auto& layout = render_window->GetFramebufferLayout(); - web_browser_view.resize(layout.screen.GetWidth(), layout.screen.GetHeight()); - web_browser_view.move(layout.screen.left, layout.screen.top + menuBar()->height()); - web_browser_view.setZoomFactor(static_cast(layout.screen.GetWidth()) / - static_cast(Layout::ScreenUndocked::Width)); + const auto scale_ratio = devicePixelRatioF(); + web_browser_view.resize(layout.screen.GetWidth() / scale_ratio, + layout.screen.GetHeight() / scale_ratio); + web_browser_view.move(layout.screen.left / scale_ratio, + (layout.screen.top / scale_ratio) + menuBar()->height()); web_browser_view.setFocus(); web_browser_view.show(); @@ -4390,6 +4395,55 @@ void GMainWindow::changeEvent(QEvent* event) { #undef main #endif +static void SetHighDPIAttributes() { +#ifdef _WIN32 + // For Windows, we want to avoid scaling artifacts on fractional scaling ratios. + // This is done by setting the optimal scaling policy for the primary screen. + + // Create a temporary QApplication. + int temp_argc = 0; + char** temp_argv = nullptr; + QApplication temp{temp_argc, temp_argv}; + + // Get the current screen geometry. + const QScreen* primary_screen = QGuiApplication::primaryScreen(); + if (primary_screen == nullptr) { + return; + } + + const QRect screen_rect = primary_screen->geometry(); + const int real_width = screen_rect.width(); + const int real_height = screen_rect.height(); + const float real_ratio = primary_screen->logicalDotsPerInch() / 96.0f; + + // Recommended minimum width and height for proper window fit. + // Any screen with a lower resolution than this will still have a scale of 1. + constexpr float minimum_width = 1350.0f; + constexpr float minimum_height = 900.0f; + + const float width_ratio = std::max(1.0f, real_width / minimum_width); + const float height_ratio = std::max(1.0f, real_height / minimum_height); + + // Get the lower of the 2 ratios and truncate, this is the maximum integer scale. + const float max_ratio = std::trunc(std::min(width_ratio, height_ratio)); + + if (max_ratio > real_ratio) { + QApplication::setHighDpiScaleFactorRoundingPolicy( + Qt::HighDpiScaleFactorRoundingPolicy::Round); + } else { + QApplication::setHighDpiScaleFactorRoundingPolicy( + Qt::HighDpiScaleFactorRoundingPolicy::Floor); + } +#else + // Other OSes should be better than Windows at fractional scaling. + QApplication::setHighDpiScaleFactorRoundingPolicy( + Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); +#endif + + QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); +} + int main(int argc, char* argv[]) { std::unique_ptr config = std::make_unique(); bool has_broken_vulkan = false; @@ -4445,6 +4499,8 @@ int main(int argc, char* argv[]) { } #endif + SetHighDPIAttributes(); + #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) // Disables the "?" button on all dialogs. Disabled by default on Qt6. QCoreApplication::setAttribute(Qt::AA_DisableWindowContextHelpButton); @@ -4452,6 +4508,7 @@ int main(int argc, char* argv[]) { // Enables the core to make the qt created contexts current on std::threads QCoreApplication::setAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity); + QApplication app(argc, argv); #ifdef _WIN32 diff --git a/src/yuzu/util/overlay_dialog.cpp b/src/yuzu/util/overlay_dialog.cpp index 42dde9e68..f3d55668e 100755 --- a/src/yuzu/util/overlay_dialog.cpp +++ b/src/yuzu/util/overlay_dialog.cpp @@ -163,7 +163,7 @@ void OverlayDialog::MoveAndResizeWindow() { const auto height = static_cast(parentWidget()->height()); // High DPI - const float dpi_scale = parentWidget()->windowHandle()->screen()->logicalDotsPerInch() / 96.0f; + const float dpi_scale = screen()->logicalDotsPerInch() / 96.0f; const auto title_text_font_size = BASE_TITLE_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale; const auto body_text_font_size =