diff options
Diffstat (limited to 'src')
121 files changed, 1901 insertions, 775 deletions
diff --git a/src/common/address_space.h b/src/common/address_space.h index 9222b2fdc..8683c23c3 100644 --- a/src/common/address_space.h +++ b/src/common/address_space.h @@ -12,7 +12,8 @@ namespace Common { template <typename VaType, size_t AddressSpaceBits> -concept AddressSpaceValid = std::is_unsigned_v<VaType> && sizeof(VaType) * 8 >= AddressSpaceBits; +concept AddressSpaceValid = std::is_unsigned_v<VaType> && sizeof(VaType) * 8 >= +AddressSpaceBits; struct EmptyStruct {}; @@ -21,7 +22,7 @@ struct EmptyStruct {}; */ template <typename VaType, VaType UnmappedVa, typename PaType, PaType UnmappedPa, bool PaContigSplit, size_t AddressSpaceBits, typename ExtraBlockInfo = EmptyStruct> -requires AddressSpaceValid<VaType, AddressSpaceBits> + requires AddressSpaceValid<VaType, AddressSpaceBits> class FlatAddressSpaceMap { public: /// The maximum VA that this AS can technically reach @@ -109,7 +110,7 @@ private: * initial, fast linear pass and a subsequent slower pass that iterates until it finds a free block */ template <typename VaType, VaType UnmappedVa, size_t AddressSpaceBits> -requires AddressSpaceValid<VaType, AddressSpaceBits> + requires AddressSpaceValid<VaType, AddressSpaceBits> class FlatAllocator : public FlatAddressSpaceMap<VaType, UnmappedVa, bool, false, false, AddressSpaceBits> { private: diff --git a/src/common/alignment.h b/src/common/alignment.h index 7e897334b..fa715d497 100644 --- a/src/common/alignment.h +++ b/src/common/alignment.h @@ -10,7 +10,7 @@ namespace Common { template <typename T> -requires std::is_unsigned_v<T> + requires std::is_unsigned_v<T> [[nodiscard]] constexpr T AlignUp(T value, size_t size) { auto mod{static_cast<T>(value % size)}; value -= mod; @@ -18,31 +18,31 @@ requires std::is_unsigned_v<T> } template <typename T> -requires std::is_unsigned_v<T> + requires std::is_unsigned_v<T> [[nodiscard]] constexpr T AlignUpLog2(T value, size_t align_log2) { return static_cast<T>((value + ((1ULL << align_log2) - 1)) >> align_log2 << align_log2); } template <typename T> -requires std::is_unsigned_v<T> + requires std::is_unsigned_v<T> [[nodiscard]] constexpr T AlignDown(T value, size_t size) { return static_cast<T>(value - value % size); } template <typename T> -requires std::is_unsigned_v<T> + requires std::is_unsigned_v<T> [[nodiscard]] constexpr bool Is4KBAligned(T value) { return (value & 0xFFF) == 0; } template <typename T> -requires std::is_unsigned_v<T> + requires std::is_unsigned_v<T> [[nodiscard]] constexpr bool IsWordAligned(T value) { return (value & 0b11) == 0; } template <typename T> -requires std::is_integral_v<T> + requires std::is_integral_v<T> [[nodiscard]] constexpr bool IsAligned(T value, size_t alignment) { using U = typename std::make_unsigned_t<T>; const U mask = static_cast<U>(alignment - 1); @@ -50,7 +50,7 @@ requires std::is_integral_v<T> } template <typename T, typename U> -requires std::is_integral_v<T> + requires std::is_integral_v<T> [[nodiscard]] constexpr T DivideUp(T x, U y) { return (x + (y - 1)) / y; } @@ -73,11 +73,11 @@ public: constexpr AlignmentAllocator(const AlignmentAllocator<T2, Align>&) noexcept {} [[nodiscard]] T* allocate(size_type n) { - return static_cast<T*>(::operator new (n * sizeof(T), std::align_val_t{Align})); + return static_cast<T*>(::operator new(n * sizeof(T), std::align_val_t{Align})); } void deallocate(T* p, size_type n) { - ::operator delete (p, n * sizeof(T), std::align_val_t{Align}); + ::operator delete(p, n * sizeof(T), std::align_val_t{Align}); } template <typename T2> diff --git a/src/common/atomic_helpers.h b/src/common/atomic_helpers.h index aef3b66a4..d997f10ba 100644 --- a/src/common/atomic_helpers.h +++ b/src/common/atomic_helpers.h @@ -75,7 +75,7 @@ extern "C" void AnnotateHappensAfter(const char*, int, void*); #if defined(AE_VCPP) || defined(AE_ICC) #define AE_FORCEINLINE __forceinline #elif defined(AE_GCC) -//#define AE_FORCEINLINE __attribute__((always_inline)) +// #define AE_FORCEINLINE __attribute__((always_inline)) #define AE_FORCEINLINE inline #else #define AE_FORCEINLINE inline diff --git a/src/common/bit_util.h b/src/common/bit_util.h index e4e6287f3..13368b439 100644 --- a/src/common/bit_util.h +++ b/src/common/bit_util.h @@ -45,19 +45,19 @@ template <typename T> } template <typename T> -requires std::is_unsigned_v<T> + requires std::is_unsigned_v<T> [[nodiscard]] constexpr bool IsPow2(T value) { return std::has_single_bit(value); } template <typename T> -requires std::is_integral_v<T> + requires std::is_integral_v<T> [[nodiscard]] T NextPow2(T value) { return static_cast<T>(1ULL << ((8U * sizeof(T)) - std::countl_zero(value - 1U))); } template <size_t bit_index, typename T> -requires std::is_integral_v<T> + requires std::is_integral_v<T> [[nodiscard]] constexpr bool Bit(const T value) { static_assert(bit_index < BitSize<T>(), "bit_index must be smaller than size of T"); return ((value >> bit_index) & T(1)) == T(1); diff --git a/src/common/concepts.h b/src/common/concepts.h index a9acff3e7..61df1d32a 100644 --- a/src/common/concepts.h +++ b/src/common/concepts.h @@ -16,9 +16,9 @@ concept IsContiguousContainer = std::contiguous_iterator<typename T::iterator>; // is available on all supported platforms. template <typename Derived, typename Base> concept DerivedFrom = requires { - std::is_base_of_v<Base, Derived>; - std::is_convertible_v<const volatile Derived*, const volatile Base*>; -}; + std::is_base_of_v<Base, Derived>; + std::is_convertible_v<const volatile Derived*, const volatile Base*>; + }; // TODO: Replace with std::convertible_to when libc++ implements it. template <typename From, typename To> diff --git a/src/common/div_ceil.h b/src/common/div_ceil.h index eebc279c2..c12477d42 100644 --- a/src/common/div_ceil.h +++ b/src/common/div_ceil.h @@ -10,14 +10,14 @@ namespace Common { /// Ceiled integer division. template <typename N, typename D> -requires std::is_integral_v<N> && std::is_unsigned_v<D> + requires std::is_integral_v<N> && std::is_unsigned_v<D> [[nodiscard]] constexpr N DivCeil(N number, D divisor) { return static_cast<N>((static_cast<D>(number) + divisor - 1) / divisor); } /// Ceiled integer division with logarithmic divisor in base 2 template <typename N, typename D> -requires std::is_integral_v<N> && std::is_unsigned_v<D> + requires std::is_integral_v<N> && std::is_unsigned_v<D> [[nodiscard]] constexpr N DivCeilLog2(N value, D alignment_log2) { return static_cast<N>((static_cast<D>(value) + (D(1) << alignment_log2) - 1) >> alignment_log2); } diff --git a/src/common/expected.h b/src/common/expected.h index 6e6c86ee7..5fccfbcbd 100644 --- a/src/common/expected.h +++ b/src/common/expected.h @@ -64,7 +64,7 @@ struct no_init_t { * Additionally, this requires E to be trivially destructible */ template <typename T, typename E, bool = std::is_trivially_destructible_v<T>> -requires std::is_trivially_destructible_v<E> + requires std::is_trivially_destructible_v<E> struct expected_storage_base { constexpr expected_storage_base() : m_val{T{}}, m_has_val{true} {} @@ -111,7 +111,7 @@ struct expected_storage_base { * Additionally, this requires E to be trivially destructible */ template <typename T, typename E> -requires std::is_trivially_destructible_v<E> + requires std::is_trivially_destructible_v<E> struct expected_storage_base<T, E, true> { constexpr expected_storage_base() : m_val{T{}}, m_has_val{true} {} @@ -251,7 +251,7 @@ struct expected_operations_base : expected_storage_base<T, E> { * Additionally, this requires E to be trivially copy constructible */ template <typename T, typename E, bool = std::is_trivially_copy_constructible_v<T>> -requires std::is_trivially_copy_constructible_v<E> + requires std::is_trivially_copy_constructible_v<E> struct expected_copy_base : expected_operations_base<T, E> { using expected_operations_base<T, E>::expected_operations_base; }; @@ -261,7 +261,7 @@ struct expected_copy_base : expected_operations_base<T, E> { * Additionally, this requires E to be trivially copy constructible */ template <typename T, typename E> -requires std::is_trivially_copy_constructible_v<E> + requires std::is_trivially_copy_constructible_v<E> struct expected_copy_base<T, E, false> : expected_operations_base<T, E> { using expected_operations_base<T, E>::expected_operations_base; @@ -289,7 +289,7 @@ struct expected_copy_base<T, E, false> : expected_operations_base<T, E> { * Additionally, this requires E to be trivially move constructible */ template <typename T, typename E, bool = std::is_trivially_move_constructible_v<T>> -requires std::is_trivially_move_constructible_v<E> + requires std::is_trivially_move_constructible_v<E> struct expected_move_base : expected_copy_base<T, E> { using expected_copy_base<T, E>::expected_copy_base; }; @@ -299,7 +299,7 @@ struct expected_move_base : expected_copy_base<T, E> { * Additionally, this requires E to be trivially move constructible */ template <typename T, typename E> -requires std::is_trivially_move_constructible_v<E> + requires std::is_trivially_move_constructible_v<E> struct expected_move_base<T, E, false> : expected_copy_base<T, E> { using expected_copy_base<T, E>::expected_copy_base; @@ -330,9 +330,9 @@ template <typename T, typename E, bool = std::conjunction_v<std::is_trivially_copy_assignable<T>, std::is_trivially_copy_constructible<T>, std::is_trivially_destructible<T>>> -requires std::conjunction_v<std::is_trivially_copy_assignable<E>, - std::is_trivially_copy_constructible<E>, - std::is_trivially_destructible<E>> + requires std::conjunction_v<std::is_trivially_copy_assignable<E>, + std::is_trivially_copy_constructible<E>, + std::is_trivially_destructible<E>> struct expected_copy_assign_base : expected_move_base<T, E> { using expected_move_base<T, E>::expected_move_base; }; @@ -342,9 +342,9 @@ struct expected_copy_assign_base : expected_move_base<T, E> { * Additionally, this requires E to be trivially copy assignable */ template <typename T, typename E> -requires std::conjunction_v<std::is_trivially_copy_assignable<E>, - std::is_trivially_copy_constructible<E>, - std::is_trivially_destructible<E>> + requires std::conjunction_v<std::is_trivially_copy_assignable<E>, + std::is_trivially_copy_constructible<E>, + std::is_trivially_destructible<E>> struct expected_copy_assign_base<T, E, false> : expected_move_base<T, E> { using expected_move_base<T, E>::expected_move_base; @@ -371,9 +371,9 @@ template <typename T, typename E, bool = std::conjunction_v<std::is_trivially_move_assignable<T>, std::is_trivially_move_constructible<T>, std::is_trivially_destructible<T>>> -requires std::conjunction_v<std::is_trivially_move_assignable<E>, - std::is_trivially_move_constructible<E>, - std::is_trivially_destructible<E>> + requires std::conjunction_v<std::is_trivially_move_assignable<E>, + std::is_trivially_move_constructible<E>, + std::is_trivially_destructible<E>> struct expected_move_assign_base : expected_copy_assign_base<T, E> { using expected_copy_assign_base<T, E>::expected_copy_assign_base; }; @@ -383,9 +383,9 @@ struct expected_move_assign_base : expected_copy_assign_base<T, E> { * Additionally, this requires E to be trivially move assignable */ template <typename T, typename E> -requires std::conjunction_v<std::is_trivially_move_assignable<E>, - std::is_trivially_move_constructible<E>, - std::is_trivially_destructible<E>> + requires std::conjunction_v<std::is_trivially_move_assignable<E>, + std::is_trivially_move_constructible<E>, + std::is_trivially_destructible<E>> struct expected_move_assign_base<T, E, false> : expected_copy_assign_base<T, E> { using expected_copy_assign_base<T, E>::expected_copy_assign_base; @@ -412,7 +412,7 @@ struct expected_move_assign_base<T, E, false> : expected_copy_assign_base<T, E> */ template <typename T, typename E, bool EnableCopy = std::is_copy_constructible_v<T>, bool EnableMove = std::is_move_constructible_v<T>> -requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>> + requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>> struct expected_delete_ctor_base { expected_delete_ctor_base() = default; expected_delete_ctor_base(const expected_delete_ctor_base&) = default; @@ -422,7 +422,7 @@ struct expected_delete_ctor_base { }; template <typename T, typename E> -requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>> + requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>> struct expected_delete_ctor_base<T, E, true, false> { expected_delete_ctor_base() = default; expected_delete_ctor_base(const expected_delete_ctor_base&) = default; @@ -432,7 +432,7 @@ struct expected_delete_ctor_base<T, E, true, false> { }; template <typename T, typename E> -requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>> + requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>> struct expected_delete_ctor_base<T, E, false, true> { expected_delete_ctor_base() = default; expected_delete_ctor_base(const expected_delete_ctor_base&) = delete; @@ -442,7 +442,7 @@ struct expected_delete_ctor_base<T, E, false, true> { }; template <typename T, typename E> -requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>> + requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>> struct expected_delete_ctor_base<T, E, false, false> { expected_delete_ctor_base() = default; expected_delete_ctor_base(const expected_delete_ctor_base&) = delete; @@ -460,8 +460,8 @@ template < typename T, typename E, bool EnableCopy = std::conjunction_v<std::is_copy_constructible<T>, std::is_copy_assignable<T>>, bool EnableMove = std::conjunction_v<std::is_move_constructible<T>, std::is_move_assignable<T>>> -requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>, - std::is_copy_assignable<E>, std::is_move_assignable<E>> + requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>, + std::is_copy_assignable<E>, std::is_move_assignable<E>> struct expected_delete_assign_base { expected_delete_assign_base() = default; expected_delete_assign_base(const expected_delete_assign_base&) = default; @@ -471,8 +471,8 @@ struct expected_delete_assign_base { }; template <typename T, typename E> -requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>, - std::is_copy_assignable<E>, std::is_move_assignable<E>> + requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>, + std::is_copy_assignable<E>, std::is_move_assignable<E>> struct expected_delete_assign_base<T, E, true, false> { expected_delete_assign_base() = default; expected_delete_assign_base(const expected_delete_assign_base&) = default; @@ -482,8 +482,8 @@ struct expected_delete_assign_base<T, E, true, false> { }; template <typename T, typename E> -requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>, - std::is_copy_assignable<E>, std::is_move_assignable<E>> + requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>, + std::is_copy_assignable<E>, std::is_move_assignable<E>> struct expected_delete_assign_base<T, E, false, true> { expected_delete_assign_base() = default; expected_delete_assign_base(const expected_delete_assign_base&) = default; @@ -493,8 +493,8 @@ struct expected_delete_assign_base<T, E, false, true> { }; template <typename T, typename E> -requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>, - std::is_copy_assignable<E>, std::is_move_assignable<E>> + requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>, + std::is_copy_assignable<E>, std::is_move_assignable<E>> struct expected_delete_assign_base<T, E, false, false> { expected_delete_assign_base() = default; expected_delete_assign_base(const expected_delete_assign_base&) = default; diff --git a/src/common/input.h b/src/common/input.h index d61cd7ca8..b5748a6c8 100644 --- 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/intrusive_red_black_tree.h b/src/common/intrusive_red_black_tree.h index 93046615e..5f6b34e82 100644 --- a/src/common/intrusive_red_black_tree.h +++ b/src/common/intrusive_red_black_tree.h @@ -242,19 +242,21 @@ public: template <typename T> concept HasRedBlackKeyType = requires { - { std::is_same<typename T::RedBlackKeyType, void>::value } -> std::convertible_to<bool>; -}; + { + std::is_same<typename T::RedBlackKeyType, void>::value + } -> std::convertible_to<bool>; + }; namespace impl { - template <typename T, typename Default> - consteval auto* GetRedBlackKeyType() { - if constexpr (HasRedBlackKeyType<T>) { - return static_cast<typename T::RedBlackKeyType*>(nullptr); - } else { - return static_cast<Default*>(nullptr); - } +template <typename T, typename Default> +consteval auto* GetRedBlackKeyType() { + if constexpr (HasRedBlackKeyType<T>) { + return static_cast<typename T::RedBlackKeyType*>(nullptr); + } else { + return static_cast<Default*>(nullptr); } +} } // namespace impl diff --git a/src/common/make_unique_for_overwrite.h b/src/common/make_unique_for_overwrite.h index c7413cf51..17f81bba4 100644 --- a/src/common/make_unique_for_overwrite.h +++ b/src/common/make_unique_for_overwrite.h @@ -9,17 +9,19 @@ namespace Common { template <class T> -requires(!std::is_array_v<T>) std::unique_ptr<T> make_unique_for_overwrite() { + requires(!std::is_array_v<T>) +std::unique_ptr<T> make_unique_for_overwrite() { return std::unique_ptr<T>(new T); } template <class T> -requires std::is_unbounded_array_v<T> std::unique_ptr<T> make_unique_for_overwrite(std::size_t n) { + requires std::is_unbounded_array_v<T> +std::unique_ptr<T> make_unique_for_overwrite(std::size_t n) { return std::unique_ptr<T>(new std::remove_extent_t<T>[n]); } template <class T, class... Args> -requires std::is_bounded_array_v<T> + requires std::is_bounded_array_v<T> void make_unique_for_overwrite(Args&&...) = delete; } // namespace Common diff --git a/src/common/polyfill_ranges.h b/src/common/polyfill_ranges.h index ca44bfaef..512dbcbcb 100644 --- a/src/common/polyfill_ranges.h +++ b/src/common/polyfill_ranges.h @@ -18,9 +18,9 @@ namespace ranges { template <typename T> concept range = requires(T& t) { - begin(t); - end(t); -}; + begin(t); + end(t); + }; template <typename T> concept input_range = range<T>; @@ -421,7 +421,7 @@ struct generate_fn { } template <typename R, std::copy_constructible F> - requires std::invocable<F&> && ranges::output_range<R> + requires std::invocable<F&> && ranges::output_range<R> constexpr ranges::iterator_t<R> operator()(R&& r, F gen) const { return operator()(ranges::begin(r), ranges::end(r), std::move(gen)); } diff --git a/src/common/polyfill_thread.h b/src/common/polyfill_thread.h index b4c94a5fc..b5ef055db 100644 --- a/src/common/polyfill_thread.h +++ b/src/common/polyfill_thread.h @@ -213,7 +213,7 @@ public: using callback_type = Callback; template <typename C> - requires constructible_from<Callback, C> + requires constructible_from<Callback, C> explicit stop_callback(const stop_token& st, C&& cb) noexcept(is_nothrow_constructible_v<Callback, C>) : m_stop_state(st.m_stop_state) { @@ -222,7 +222,7 @@ public: } } template <typename C> - requires constructible_from<Callback, C> + requires constructible_from<Callback, C> explicit stop_callback(stop_token&& st, C&& cb) noexcept(is_nothrow_constructible_v<Callback, C>) : m_stop_state(move(st.m_stop_state)) { diff --git a/src/common/settings.h b/src/common/settings.h index 4b4da4da2..64db66f37 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -131,7 +131,8 @@ public: * @param default_val Intial value of the setting, and default value of the setting * @param name Label for the setting */ - explicit Setting(const Type& default_val, const std::string& name) requires(!ranged) + explicit Setting(const Type& default_val, const std::string& name) + requires(!ranged) : value{default_val}, default_value{default_val}, label{name} {} virtual ~Setting() = default; @@ -144,7 +145,8 @@ public: * @param name Label for the setting */ explicit Setting(const Type& default_val, const Type& min_val, const Type& max_val, - const std::string& name) requires(ranged) + const std::string& name) + requires(ranged) : value{default_val}, default_value{default_val}, maximum{max_val}, minimum{min_val}, label{name} {} @@ -232,7 +234,8 @@ public: * @param default_val Intial value of the setting, and default value of the setting * @param name Label for the setting */ - explicit SwitchableSetting(const Type& default_val, const std::string& name) requires(!ranged) + explicit SwitchableSetting(const Type& default_val, const std::string& name) + requires(!ranged) : Setting<Type>{default_val, name} {} virtual ~SwitchableSetting() = default; @@ -245,7 +248,8 @@ public: * @param name Label for the setting */ explicit SwitchableSetting(const Type& default_val, const Type& min_val, const Type& max_val, - const std::string& name) requires(ranged) + const std::string& name) + requires(ranged) : Setting<Type, true>{default_val, min_val, max_val, name} {} /** diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp index b26db4796..e0b6180c5 100644 --- 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<u8>& data) { +std::string StringFromBuffer(std::span<const u8> 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 ce18a33cf..f8aecc875 100644 --- a/src/common/string_util.h +++ b/src/common/string_util.h @@ -5,6 +5,7 @@ #pragma once #include <cstddef> +#include <span> #include <string> #include <vector> #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<u8>& data); +[[nodiscard]] std::string StringFromBuffer(std::span<const u8> data); [[nodiscard]] std::string StripSpaces(const std::string& s); [[nodiscard]] std::string StripQuotes(const std::string& s); diff --git a/src/common/tree.h b/src/common/tree.h index f77859209..f4fc43de3 100644 --- a/src/common/tree.h +++ b/src/common/tree.h @@ -103,12 +103,12 @@ concept IsRBEntry = CheckRBEntry<T>::value; template <typename T> concept HasRBEntry = requires(T& t, const T& ct) { - { t.GetRBEntry() } -> std::same_as<RBEntry<T>&>; - { ct.GetRBEntry() } -> std::same_as<const RBEntry<T>&>; -}; + { t.GetRBEntry() } -> std::same_as<RBEntry<T>&>; + { ct.GetRBEntry() } -> std::same_as<const RBEntry<T>&>; + }; template <typename T> -requires HasRBEntry<T> + requires HasRBEntry<T> class RBHead { private: T* m_rbh_root = nullptr; @@ -130,90 +130,90 @@ public: }; template <typename T> -requires HasRBEntry<T> + requires HasRBEntry<T> [[nodiscard]] constexpr RBEntry<T>& RB_ENTRY(T* t) { return t->GetRBEntry(); } template <typename T> -requires HasRBEntry<T> + requires HasRBEntry<T> [[nodiscard]] constexpr const RBEntry<T>& RB_ENTRY(const T* t) { return t->GetRBEntry(); } template <typename T> -requires HasRBEntry<T> + requires HasRBEntry<T> [[nodiscard]] constexpr T* RB_LEFT(T* t) { return RB_ENTRY(t).Left(); } template <typename T> -requires HasRBEntry<T> + requires HasRBEntry<T> [[nodiscard]] constexpr const T* RB_LEFT(const T* t) { return RB_ENTRY(t).Left(); } template <typename T> -requires HasRBEntry<T> + requires HasRBEntry<T> [[nodiscard]] constexpr T* RB_RIGHT(T* t) { return RB_ENTRY(t).Right(); } template <typename T> -requires HasRBEntry<T> + requires HasRBEntry<T> [[nodiscard]] constexpr const T* RB_RIGHT(const T* t) { return RB_ENTRY(t).Right(); } template <typename T> -requires HasRBEntry<T> + requires HasRBEntry<T> [[nodiscard]] constexpr T* RB_PARENT(T* t) { return RB_ENTRY(t).Parent(); } template <typename T> -requires HasRBEntry<T> + requires HasRBEntry<T> [[nodiscard]] constexpr const T* RB_PARENT(const T* t) { return RB_ENTRY(t).Parent(); } template <typename T> -requires HasRBEntry<T> + requires HasRBEntry<T> constexpr void RB_SET_LEFT(T* t, T* e) { RB_ENTRY(t).SetLeft(e); } template <typename T> -requires HasRBEntry<T> + requires HasRBEntry<T> constexpr void RB_SET_RIGHT(T* t, T* e) { RB_ENTRY(t).SetRight(e); } template <typename T> -requires HasRBEntry<T> + requires HasRBEntry<T> constexpr void RB_SET_PARENT(T* t, T* e) { RB_ENTRY(t).SetParent(e); } template <typename T> -requires HasRBEntry<T> + requires HasRBEntry<T> [[nodiscard]] constexpr bool RB_IS_BLACK(const T* t) { return RB_ENTRY(t).IsBlack(); } template <typename T> -requires HasRBEntry<T> + requires HasRBEntry<T> [[nodiscard]] constexpr bool RB_IS_RED(const T* t) { return RB_ENTRY(t).IsRed(); } template <typename T> -requires HasRBEntry<T> + requires HasRBEntry<T> [[nodiscard]] constexpr RBColor RB_COLOR(const T* t) { return RB_ENTRY(t).Color(); } template <typename T> -requires HasRBEntry<T> + requires HasRBEntry<T> constexpr void RB_SET_COLOR(T* t, RBColor c) { RB_ENTRY(t).SetColor(c); } template <typename T> -requires HasRBEntry<T> + requires HasRBEntry<T> constexpr void RB_SET(T* elm, T* parent) { auto& rb_entry = RB_ENTRY(elm); rb_entry.SetParent(parent); @@ -223,14 +223,14 @@ constexpr void RB_SET(T* elm, T* parent) { } template <typename T> -requires HasRBEntry<T> + requires HasRBEntry<T> constexpr void RB_SET_BLACKRED(T* black, T* red) { RB_SET_COLOR(black, RBColor::RB_BLACK); RB_SET_COLOR(red, RBColor::RB_RED); } template <typename T> -requires HasRBEntry<T> + requires HasRBEntry<T> constexpr void RB_ROTATE_LEFT(RBHead<T>& head, T* elm, T*& tmp) { tmp = RB_RIGHT(elm); if (RB_SET_RIGHT(elm, RB_LEFT(tmp)); RB_RIGHT(elm) != nullptr) { @@ -252,7 +252,7 @@ constexpr void RB_ROTATE_LEFT(RBHead<T>& head, T* elm, T*& tmp) { } template <typename T> -requires HasRBEntry<T> + requires HasRBEntry<T> constexpr void RB_ROTATE_RIGHT(RBHead<T>& head, T* elm, T*& tmp) { tmp = RB_LEFT(elm); if (RB_SET_LEFT(elm, RB_RIGHT(tmp)); RB_LEFT(elm) != nullptr) { @@ -274,7 +274,7 @@ constexpr void RB_ROTATE_RIGHT(RBHead<T>& head, T* elm, T*& tmp) { } template <typename T> -requires HasRBEntry<T> + requires HasRBEntry<T> constexpr void RB_REMOVE_COLOR(RBHead<T>& head, T* parent, T* elm) { T* tmp; while ((elm == nullptr || RB_IS_BLACK(elm)) && elm != head.Root()) { @@ -358,7 +358,7 @@ constexpr void RB_REMOVE_COLOR(RBHead<T>& head, T* parent, T* elm) { } template <typename T> -requires HasRBEntry<T> + requires HasRBEntry<T> constexpr T* RB_REMOVE(RBHead<T>& head, T* elm) { T* child = nullptr; T* parent = nullptr; @@ -451,7 +451,7 @@ constexpr T* RB_REMOVE(RBHead<T>& head, T* elm) { } template <typename T> -requires HasRBEntry<T> + requires HasRBEntry<T> constexpr void RB_INSERT_COLOR(RBHead<T>& head, T* elm) { T *parent = nullptr, *tmp = nullptr; while ((parent = RB_PARENT(elm)) != nullptr && RB_IS_RED(parent)) { @@ -499,7 +499,7 @@ constexpr void RB_INSERT_COLOR(RBHead<T>& head, T* elm) { } template <typename T, typename Compare> -requires HasRBEntry<T> + requires HasRBEntry<T> constexpr T* RB_INSERT(RBHead<T>& head, T* elm, Compare cmp) { T* parent = nullptr; T* tmp = head.Root(); @@ -534,7 +534,7 @@ constexpr T* RB_INSERT(RBHead<T>& head, T* elm, Compare cmp) { } template <typename T, typename Compare> -requires HasRBEntry<T> + requires HasRBEntry<T> constexpr T* RB_FIND(RBHead<T>& head, T* elm, Compare cmp) { T* tmp = head.Root(); @@ -553,7 +553,7 @@ constexpr T* RB_FIND(RBHead<T>& head, T* elm, Compare cmp) { } template <typename T, typename Compare> -requires HasRBEntry<T> + requires HasRBEntry<T> constexpr T* RB_NFIND(RBHead<T>& head, T* elm, Compare cmp) { T* tmp = head.Root(); T* res = nullptr; @@ -574,7 +574,7 @@ constexpr T* RB_NFIND(RBHead<T>& head, T* elm, Compare cmp) { } template <typename T, typename U, typename Compare> -requires HasRBEntry<T> + requires HasRBEntry<T> constexpr T* RB_FIND_KEY(RBHead<T>& head, const U& key, Compare cmp) { T* tmp = head.Root(); @@ -593,7 +593,7 @@ constexpr T* RB_FIND_KEY(RBHead<T>& head, const U& key, Compare cmp) { } template <typename T, typename U, typename Compare> -requires HasRBEntry<T> + requires HasRBEntry<T> constexpr T* RB_NFIND_KEY(RBHead<T>& head, const U& key, Compare cmp) { T* tmp = head.Root(); T* res = nullptr; @@ -614,7 +614,7 @@ constexpr T* RB_NFIND_KEY(RBHead<T>& head, const U& key, Compare cmp) { } template <typename T, typename Compare> -requires HasRBEntry<T> + requires HasRBEntry<T> constexpr T* RB_FIND_EXISTING(RBHead<T>& head, T* elm, Compare cmp) { T* tmp = head.Root(); @@ -631,7 +631,7 @@ constexpr T* RB_FIND_EXISTING(RBHead<T>& head, T* elm, Compare cmp) { } template <typename T, typename U, typename Compare> -requires HasRBEntry<T> + requires HasRBEntry<T> constexpr T* RB_FIND_EXISTING_KEY(RBHead<T>& head, const U& key, Compare cmp) { T* tmp = head.Root(); @@ -648,7 +648,7 @@ constexpr T* RB_FIND_EXISTING_KEY(RBHead<T>& head, const U& key, Compare cmp) { } template <typename T> -requires HasRBEntry<T> + requires HasRBEntry<T> constexpr T* RB_NEXT(T* elm) { if (RB_RIGHT(elm)) { elm = RB_RIGHT(elm); @@ -669,7 +669,7 @@ constexpr T* RB_NEXT(T* elm) { } template <typename T> -requires HasRBEntry<T> + requires HasRBEntry<T> constexpr T* RB_PREV(T* elm) { if (RB_LEFT(elm)) { elm = RB_LEFT(elm); @@ -690,7 +690,7 @@ constexpr T* RB_PREV(T* elm) { } template <typename T> -requires HasRBEntry<T> + requires HasRBEntry<T> constexpr T* RB_MIN(RBHead<T>& head) { T* tmp = head.Root(); T* parent = nullptr; @@ -704,7 +704,7 @@ constexpr T* RB_MIN(RBHead<T>& head) { } template <typename T> -requires HasRBEntry<T> + requires HasRBEntry<T> constexpr T* RB_MAX(RBHead<T>& head) { T* tmp = head.Root(); T* parent = nullptr; diff --git a/src/common/vector_math.h b/src/common/vector_math.h index e62eeea2e..0e2095c45 100644 --- a/src/common/vector_math.h +++ b/src/common/vector_math.h @@ -348,9 +348,7 @@ public: // _DEFINE_SWIZZLER2 defines a single such function, DEFINE_SWIZZLER2 defines all of them for all // component names (x<->r) and permutations (xy<->yx) #define _DEFINE_SWIZZLER2(a, b, name) \ - [[nodiscard]] constexpr Vec2<T> name() const { \ - return Vec2<T>(a, b); \ - } + [[nodiscard]] constexpr Vec2<T> name() const { return Vec2<T>(a, b); } #define DEFINE_SWIZZLER2(a, b, a2, b2, a3, b3, a4, b4) \ _DEFINE_SWIZZLER2(a, b, a##b); \ _DEFINE_SWIZZLER2(a, b, a2##b2); \ @@ -543,9 +541,7 @@ public: // DEFINE_SWIZZLER2_COMP2 defines two component functions for all component names (x<->r) and // permutations (xy<->yx) #define _DEFINE_SWIZZLER2(a, b, name) \ - [[nodiscard]] constexpr Vec2<T> name() const { \ - return Vec2<T>(a, b); \ - } + [[nodiscard]] constexpr Vec2<T> name() const { return Vec2<T>(a, b); } #define DEFINE_SWIZZLER2_COMP1(a, a2) \ _DEFINE_SWIZZLER2(a, a, a##a); \ _DEFINE_SWIZZLER2(a, a, a2##a2) @@ -570,9 +566,7 @@ public: #undef _DEFINE_SWIZZLER2 #define _DEFINE_SWIZZLER3(a, b, c, name) \ - [[nodiscard]] constexpr Vec3<T> name() const { \ - return Vec3<T>(a, b, c); \ - } + [[nodiscard]] constexpr Vec3<T> name() const { return Vec3<T>(a, b, c); } #define DEFINE_SWIZZLER3_COMP1(a, a2) \ _DEFINE_SWIZZLER3(a, a, a, a##a##a); \ _DEFINE_SWIZZLER3(a, a, a, a2##a2##a2) @@ -641,8 +635,8 @@ template <typename T> // linear interpolation via float: 0.0=begin, 1.0=end template <typename X> -[[nodiscard]] constexpr decltype(X{} * float{} + X{} * float{}) - Lerp(const X& begin, const X& end, const float t) { +[[nodiscard]] constexpr decltype(X{} * float{} + X{} * float{}) Lerp(const X& begin, const X& end, + const float t) { return begin * (1.f - t) + end * t; } diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 5afdeb5ff..3eee1cfbe 100644 --- 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 13cbdb734..45567b840 100644 --- a/src/core/hardware_properties.h +++ b/src/core/hardware_properties.h @@ -25,6 +25,26 @@ constexpr std::array<s32, Common::BitSize<u64>()> 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<u64>(); + +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<u64>(1) << next); + p_core_mask |= (static_cast<u64>(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 0e06468da..631aa6ad2 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -12,6 +12,7 @@ namespace Core::HID { constexpr s32 HID_JOYSTICK_MAX = 0x7fff; constexpr s32 HID_TRIGGER_MAX = 0x7fff; +constexpr u32 TURBO_BUTTON_DELAY = 4; // Use a common UUID for TAS and Virtual Gamepad constexpr Common::UUID TAS_UUID = Common::UUID{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xA5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; @@ -447,6 +448,7 @@ void EmulatedController::ReloadInput() { }, }); } + turbo_button_state = 0; } void EmulatedController::UnloadInput() { @@ -687,6 +689,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 +1551,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 +1659,74 @@ void EmulatedController::DeleteCallback(int key) { } callback_list.erase(iterator); } + +void EmulatedController::TurboButtonUpdate() { + turbo_button_state = (turbo_button_state + 1) % (TURBO_BUTTON_DELAY * 2); +} + +NpadButton EmulatedController::GetTurboButtonMask() const { + // Apply no mask when disabled + if (turbo_button_state < TURBO_BUTTON_DELAY) { + 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<NpadButton>(~button_mask.raw); +} + } // namespace Core::HID diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index 3ac77b2b5..b02bf35c4 100644 --- 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}; + u32 turbo_button_state{0}; // 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 738b6d0f1..494151eef 100644 --- 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<u8> HLERequestContext::ReadBuffer(std::size_t buffer_index) const { +std::vector<u8> 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<u8> HLERequestContext::ReadBuffer(std::size_t buffer_index) const { } } +std::span<const u8> HLERequestContext::ReadBuffer(std::size_t buffer_index) const { + static thread_local std::array<Common::ScratchBuffer<u8>, 2> read_buffer_a; + static thread_local std::array<Common::ScratchBuffer<u8>, 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 e252b5f4b..5bf4f171b 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h @@ -7,6 +7,7 @@ #include <functional> #include <memory> #include <optional> +#include <span> #include <string> #include <type_traits> #include <vector> @@ -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<u8> 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<const u8> 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<u8> 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_auto_object.h b/src/core/hle/kernel/k_auto_object.h index 2827763d5..e8118c2b8 100644 --- a/src/core/hle/kernel/k_auto_object.h +++ b/src/core/hle/kernel/k_auto_object.h @@ -24,9 +24,7 @@ private: friend class ::Kernel::KClassTokenGenerator; \ static constexpr inline auto ObjectType = ::Kernel::KClassTokenGenerator::ObjectType::CLASS; \ static constexpr inline const char* const TypeName = #CLASS; \ - static constexpr inline ClassTokenType ClassToken() { \ - return ::Kernel::ClassToken<CLASS>; \ - } \ + static constexpr inline ClassTokenType ClassToken() { return ::Kernel::ClassToken<CLASS>; } \ \ public: \ YUZU_NON_COPYABLE(CLASS); \ @@ -37,15 +35,9 @@ public: constexpr ClassTokenType Token = ClassToken(); \ return TypeObj(TypeName, Token); \ } \ - static constexpr const char* GetStaticTypeName() { \ - return TypeName; \ - } \ - virtual TypeObj GetTypeObj() ATTRIBUTE { \ - return GetStaticTypeObj(); \ - } \ - virtual const char* GetTypeName() ATTRIBUTE { \ - return GetStaticTypeName(); \ - } \ + static constexpr const char* GetStaticTypeName() { return TypeName; } \ + virtual TypeObj GetTypeObj() ATTRIBUTE { return GetStaticTypeObj(); } \ + virtual const char* GetTypeName() ATTRIBUTE { return GetStaticTypeName(); } \ \ private: \ constexpr bool operator!=(const TypeObj& rhs) @@ -245,8 +237,8 @@ public: } template <typename U> - requires(std::derived_from<T, U> || - std::derived_from<U, T>) constexpr KScopedAutoObject(KScopedAutoObject<U>&& rhs) { + requires(std::derived_from<T, U> || std::derived_from<U, T>) + constexpr KScopedAutoObject(KScopedAutoObject<U>&& rhs) { if constexpr (std::derived_from<U, T>) { // Upcast. m_obj = rhs.m_obj; diff --git a/src/core/hle/kernel/k_capabilities.cpp b/src/core/hle/kernel/k_capabilities.cpp new file mode 100644 index 000000000..64f1d7371 --- /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<const u32> 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<const u32> 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<u64>()); + + // 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<u32>(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 <typename F> +Result KCapabilities::ProcessMapRegionCapability(const u32 cap, F f) { + // Define the allowed memory regions. + constexpr std::array<KMemoryRegionType, 4> MemoryRegions{ + KMemoryRegionType_None, + KMemoryRegionType_KernelTraceBuffer, + KMemoryRegionType_OnMemoryBootImage, + KMemoryRegionType_DTB, + }; + + // Extract regions/read only. + const MapRegion pack{cap}; + const std::array<RegionType, 3> types{pack.region0, pack.region1, pack.region2}; + const std::array<u32, 3> 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<u32>(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<u32, 2> 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<const u32> 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<const u32> 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 100644 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 <bitset> +#include <span> + +#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<const u32> kern_caps, KPageTable* page_table); + Result InitializeForUser(std::span<const u32> user_caps, KPageTable* page_table); + + static Result CheckCapabilities(KernelCore& kernel, std::span<const u32> 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<InterruptIdCount>; + + 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<CapabilityType>((~value & (value + 1)) - 1); + } + + static constexpr u32 GetCapabilityFlag(CapabilityType type) { + return static_cast<u32>(type) + 1; + } + + template <CapabilityType Type> + static constexpr inline u32 CapabilityFlag = static_cast<u32>(Type) + 1; + + template <CapabilityType Type> + static constexpr inline u32 CapabilityId = std::countr_zero(CapabilityFlag<Type>); + + union CorePriority { + static_assert(CapabilityId<CapabilityType::CorePriority> + 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<CapabilityType::SyscallMask> + 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<CapabilityType::MapRange> + 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<CapabilityType::MapRange> + 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<CapabilityType::MapIoPage> + 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<CapabilityType::MapRegion> + 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<CapabilityType::InterruptPair> + 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<CapabilityType::ProgramType> + 1 == 14); + + RawCapabilityValue raw; + BitField<0, 14, CapabilityType> id; + BitField<14, 3, u32> type; + BitField<17, 15, u32> reserved; + }; + + union KernelVersion { + static_assert(CapabilityId<CapabilityType::KernelVersion> + 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<CapabilityType::HandleTable> + 1 == 16); + + RawCapabilityValue raw; + BitField<0, 16, CapabilityType> id; + BitField<16, 10, u32> size; + BitField<26, 6, u32> reserved; + }; + + union DebugFlags { + static_assert(CapabilityId<CapabilityType::DebugFlags> + 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<CapabilityType::CorePriority> | CapabilityFlag<CapabilityType::ProgramType> | + CapabilityFlag<CapabilityType::KernelVersion> | + CapabilityFlag<CapabilityType::HandleTable> | CapabilityFlag<CapabilityType::DebugFlags>; + + 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 <typename F> + 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<const u32> 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/k_priority_queue.h b/src/core/hle/kernel/k_priority_queue.h index cb2512b0b..645c5b531 100644 --- a/src/core/hle/kernel/k_priority_queue.h +++ b/src/core/hle/kernel/k_priority_queue.h @@ -17,35 +17,41 @@ namespace Kernel { class KThread; template <typename T> -concept KPriorityQueueAffinityMask = !std::is_reference_v<T> && requires(T & t) { - { t.GetAffinityMask() } -> Common::ConvertibleTo<u64>; - {t.SetAffinityMask(0)}; +concept KPriorityQueueAffinityMask = ! +std::is_reference_v<T>&& requires(T& t) { + { t.GetAffinityMask() } -> Common::ConvertibleTo<u64>; + { t.SetAffinityMask(0) }; - { t.GetAffinity(0) } -> std::same_as<bool>; - {t.SetAffinity(0, false)}; - {t.SetAll()}; -}; + { t.GetAffinity(0) } -> std::same_as<bool>; + { t.SetAffinity(0, false) }; + { t.SetAll() }; + }; template <typename T> -concept KPriorityQueueMember = !std::is_reference_v<T> && requires(T & t) { - {typename T::QueueEntry()}; - {(typename T::QueueEntry()).Initialize()}; - {(typename T::QueueEntry()).SetPrev(std::addressof(t))}; - {(typename T::QueueEntry()).SetNext(std::addressof(t))}; - { (typename T::QueueEntry()).GetNext() } -> std::same_as<T*>; - { (typename T::QueueEntry()).GetPrev() } -> std::same_as<T*>; - { t.GetPriorityQueueEntry(0) } -> std::same_as<typename T::QueueEntry&>; - - {t.GetAffinityMask()}; - { std::remove_cvref_t<decltype(t.GetAffinityMask())>() } -> KPriorityQueueAffinityMask; - - { t.GetActiveCore() } -> Common::ConvertibleTo<s32>; - { t.GetPriority() } -> Common::ConvertibleTo<s32>; - { t.IsDummyThread() } -> Common::ConvertibleTo<bool>; -}; +concept KPriorityQueueMember = ! +std::is_reference_v<T>&& requires(T& t) { + { typename T::QueueEntry() }; + { (typename T::QueueEntry()).Initialize() }; + { (typename T::QueueEntry()).SetPrev(std::addressof(t)) }; + { (typename T::QueueEntry()).SetNext(std::addressof(t)) }; + { (typename T::QueueEntry()).GetNext() } -> std::same_as<T*>; + { (typename T::QueueEntry()).GetPrev() } -> std::same_as<T*>; + { + t.GetPriorityQueueEntry(0) + } -> std::same_as<typename T::QueueEntry&>; + + { t.GetAffinityMask() }; + { + std::remove_cvref_t<decltype(t.GetAffinityMask())>() + } -> KPriorityQueueAffinityMask; + + { t.GetActiveCore() } -> Common::ConvertibleTo<s32>; + { t.GetPriority() } -> Common::ConvertibleTo<s32>; + { t.IsDummyThread() } -> Common::ConvertibleTo<bool>; + }; template <typename Member, size_t NumCores_, int LowestPriority, int HighestPriority> -requires KPriorityQueueMember<Member> + requires KPriorityQueueMember<Member> class KPriorityQueue { public: using AffinityMaskType = std::remove_cv_t< diff --git a/src/core/hle/kernel/k_scoped_lock.h b/src/core/hle/kernel/k_scoped_lock.h index 857e21156..59b3e32ae 100644 --- a/src/core/hle/kernel/k_scoped_lock.h +++ b/src/core/hle/kernel/k_scoped_lock.h @@ -9,13 +9,14 @@ namespace Kernel { template <typename T> -concept KLockable = !std::is_reference_v<T> && requires(T & t) { - { t.Lock() } -> std::same_as<void>; - { t.Unlock() } -> std::same_as<void>; -}; +concept KLockable = ! +std::is_reference_v<T>&& requires(T& t) { + { t.Lock() } -> std::same_as<void>; + { t.Unlock() } -> std::same_as<void>; + }; template <typename T> -requires KLockable<T> + requires KLockable<T> class [[nodiscard]] KScopedLock { public: explicit KScopedLock(T* l) : lock_ptr(l) { diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index 9d771de0e..8b8dc51be 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h @@ -677,7 +677,7 @@ private: union SyncObjectBuffer { std::array<KSynchronizationObject*, Svc::ArgumentHandleCountMax> sync_objects{}; std::array<Handle, - Svc::ArgumentHandleCountMax*(sizeof(KSynchronizationObject*) / sizeof(Handle))> + Svc::ArgumentHandleCountMax * (sizeof(KSynchronizationObject*) / sizeof(Handle))> handles; constexpr SyncObjectBuffer() {} }; @@ -698,10 +698,8 @@ private: }; template <typename T> - requires( - std::same_as<T, KThread> || - std::same_as<T, RedBlackKeyType>) static constexpr int Compare(const T& lhs, - const KThread& rhs) { + requires(std::same_as<T, KThread> || std::same_as<T, RedBlackKeyType>) + static constexpr int Compare(const T& lhs, const KThread& rhs) { const u64 l_key = lhs.GetConditionVariableKey(); const u64 r_key = rhs.GetConditionVariableKey(); diff --git a/src/core/hle/kernel/k_thread_local_page.h b/src/core/hle/kernel/k_thread_local_page.h index fe0cff084..71254eb55 100644 --- a/src/core/hle/kernel/k_thread_local_page.h +++ b/src/core/hle/kernel/k_thread_local_page.h @@ -70,10 +70,8 @@ public: } template <typename T> - requires(std::same_as<T, KThreadLocalPage> || - std::same_as<T, RedBlackKeyType>) static constexpr int Compare(const T& lhs, - const KThreadLocalPage& - rhs) { + requires(std::same_as<T, KThreadLocalPage> || std::same_as<T, RedBlackKeyType>) + static constexpr int Compare(const T& lhs, const KThreadLocalPage& rhs) { const VAddr lval = GetRedBlackKey(lhs); const VAddr rval = GetRedBlackKey(rhs); diff --git a/src/core/hle/kernel/svc_types.h b/src/core/hle/kernel/svc_types.h index 33eebcef6..9c2f9998a 100644 --- a/src/core/hle/kernel/svc_types.h +++ b/src/core/hle/kernel/svc_types.h @@ -3,6 +3,8 @@ #pragma once +#include <bitset> + #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<NumSupervisorCalls>; + } // namespace Kernel::Svc diff --git a/src/core/hle/kernel/svc_version.h b/src/core/hle/kernel/svc_version.h new file mode 100644 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<decltype(KernelVersion::major_version)>(encoded).Value(); +} + +constexpr inline u32 GetKernelMinorVersion(u32 encoded) { + return std::bit_cast<decltype(KernelVersion::minor_version)>(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 22999c942..ebcf6e164 100644 --- 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<u64>()}; - const std::vector<u8> data{ctx.ReadBuffer()}; + const auto data{ctx.ReadBuffer()}; const std::size_t size{std::min<u64>(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 3a1c231b6..0ee28752c 100644 --- 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<u8> 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 825fb8bcc..e01f87356 100644 --- 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<u8>& input, + bool DecodeOpusData(u32& consumed, u32& sample_count, std::span<const u8> input, std::vector<opus_int16>& 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 d183e5829..fb8686859 100644 --- 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 fbb16a7da..cab44bf9c 100644 --- 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<u8> data = ctx.ReadBuffer(); + const auto data = ctx.ReadBuffer(); ASSERT_MSG( static_cast<s64>(data.size()) <= length, @@ -401,11 +401,8 @@ public: } void RenameFile(Kernel::HLERequestContext& ctx) { - std::vector<u8> 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 49b6d45fe..ce21b69e3 100644 --- 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 5713f1288..513ea485a 100644 --- 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<const u8> 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 1a589cca2..1f7d33459 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -6,6 +6,7 @@ #include <array> #include <atomic> #include <mutex> +#include <span> #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<const u8> 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 bf28440c6..f15f1a6bb 100644 --- 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<u64>()}; applet_resource->GetController<Controller_NPad>(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<Controller_Palma::PalmaConnectionHandle>()}; const auto unknown{rp.Pop<u64>()}; - 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 d3960f506..65e301137 100644 --- 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 <array> +#include <span> #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<u8>& data) { + virtual bool SetCommand(std::span<const u8> data) { return {}; } diff --git a/src/core/hle/service/hid/hidbus/ringcon.cpp b/src/core/hle/service/hid/hidbus/ringcon.cpp index 78ed47014..35847cbdd 100644 --- a/src/core/hle/service/hid/hidbus/ringcon.cpp +++ b/src/core/hle/service/hid/hidbus/ringcon.cpp @@ -116,7 +116,7 @@ std::vector<u8> RingController::GetReply() const { } } -bool RingController::SetCommand(const std::vector<u8>& data) { +bool RingController::SetCommand(std::span<const u8> 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 845ce85a5..c2fb386b1 100644 --- 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 <array> +#include <span> #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<u8>& data) override; + bool SetCommand(std::span<const u8> data) override; // Returns a reply from a command std::vector<u8> GetReply() const override; diff --git a/src/core/hle/service/hid/hidbus/starlink.cpp b/src/core/hle/service/hid/hidbus/starlink.cpp index dd439f60a..d0e760314 100644 --- a/src/core/hle/service/hid/hidbus/starlink.cpp +++ b/src/core/hle/service/hid/hidbus/starlink.cpp @@ -42,7 +42,7 @@ std::vector<u8> Starlink::GetReply() const { return {}; } -bool Starlink::SetCommand(const std::vector<u8>& data) { +bool Starlink::SetCommand(std::span<const u8> 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 0b1b7ba49..07c800e6e 100644 --- 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<u8>& data) override; + bool SetCommand(std::span<const u8> data) override; // Returns a reply from a command std::vector<u8> GetReply() const override; diff --git a/src/core/hle/service/hid/hidbus/stubbed.cpp b/src/core/hle/service/hid/hidbus/stubbed.cpp index e477443e3..07632c872 100644 --- a/src/core/hle/service/hid/hidbus/stubbed.cpp +++ b/src/core/hle/service/hid/hidbus/stubbed.cpp @@ -43,7 +43,7 @@ std::vector<u8> HidbusStubbed::GetReply() const { return {}; } -bool HidbusStubbed::SetCommand(const std::vector<u8>& data) { +bool HidbusStubbed::SetCommand(std::span<const u8> 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 91165ceff..38eaa0ecc 100644 --- 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<u8>& data) override; + bool SetCommand(std::span<const u8> data) override; // Returns a reply from a command std::vector<u8> GetReply() const override; diff --git a/src/core/hle/service/jit/jit.cpp b/src/core/hle/service/jit/jit.cpp index 8f2920c51..1295a44c7 100644 --- 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<InputParameters>()}; // Optional input/output buffers - std::vector<u8> input_buffer{ctx.CanReadBuffer() ? ctx.ReadBuffer() : std::vector<u8>()}; + const auto input_buffer{ctx.CanReadBuffer() ? ctx.ReadBuffer() : std::span<const u8>()}; std::vector<u8> output_buffer(ctx.CanWriteBuffer() ? ctx.GetWriteBufferSize() : 0); // Function call prototype: @@ -132,7 +132,7 @@ public: const auto command{rp.PopRaw<u64>()}; // Optional input/output buffers - std::vector<u8> input_buffer{ctx.CanReadBuffer() ? ctx.ReadBuffer() : std::vector<u8>()}; + const auto input_buffer{ctx.CanReadBuffer() ? ctx.ReadBuffer() : std::span<const u8>()}; std::vector<u8> 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 c49c61cff..e5099d61f 100644 --- a/src/core/hle/service/ldn/ldn.cpp +++ b/src/core/hle/service/ldn/ldn.cpp @@ -412,7 +412,7 @@ public: } void SetAdvertiseData(Kernel::HLERequestContext& ctx) { - std::vector<u8> read_buffer = ctx.ReadBuffer(); + const auto read_buffer = ctx.ReadBuffer(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(lan_discovery.SetAdvertiseData(read_buffer)); @@ -464,7 +464,7 @@ public: parameters.security_config.passphrase_size, parameters.security_config.security_mode, parameters.local_communication_version); - const std::vector<u8> 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 204b0e757..c562e04d2 100644 --- 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 <span> #include <vector> + #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<u8>& input, + virtual NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& 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<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) = 0; + virtual NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::vector<u8>& 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<u8>& input, + virtual NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output, std::vector<u8>& 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 4122fc98d..5a5b2e305 100644 --- 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<u8>& input, +NvResult nvdisp_disp0::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; } -NvResult nvdisp_disp0::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) { +NvResult nvdisp_disp0::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::vector<u8>& output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; } -NvResult nvdisp_disp0::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, +NvResult nvdisp_disp0::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output, std::vector<u8>& 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 04217ab12..81bd7960a 100644 --- 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<u8>& input, + NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output) override; - NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) override; - NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output, std::vector<u8>& inline_output) override; + NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::vector<u8>& output) override; + NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output, + std::vector<u8>& 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 b635e6ed1..681bd0867 100644 --- 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<u8>& input, +NvResult nvhost_as_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output) { switch (command.group) { case 'A': @@ -60,13 +60,13 @@ NvResult nvhost_as_gpu::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8> return NvResult::NotImplemented; } -NvResult nvhost_as_gpu::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) { +NvResult nvhost_as_gpu::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::vector<u8>& output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; } -NvResult nvhost_as_gpu::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, +NvResult nvhost_as_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output, std::vector<u8>& inline_output) { switch (command.group) { case 'A': @@ -87,7 +87,7 @@ NvResult nvhost_as_gpu::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8> void nvhost_as_gpu::OnOpen(DeviceFD fd) {} void nvhost_as_gpu::OnClose(DeviceFD fd) {} -NvResult nvhost_as_gpu::AllocAsEx(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_as_gpu::AllocAsEx(std::span<const u8> input, std::vector<u8>& output) { IoctlAllocAsEx params{}; std::memcpy(¶ms, input.data(), input.size()); @@ -141,7 +141,7 @@ NvResult nvhost_as_gpu::AllocAsEx(const std::vector<u8>& input, std::vector<u8>& return NvResult::Success; } -NvResult nvhost_as_gpu::AllocateSpace(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_as_gpu::AllocateSpace(std::span<const u8> input, std::vector<u8>& 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<u8>& input, std::vector<u8>& output) { +NvResult nvhost_as_gpu::FreeSpace(std::span<const u8> input, std::vector<u8>& output) { IoctlFreeSpace params{}; std::memcpy(¶ms, input.data(), input.size()); @@ -266,7 +266,7 @@ NvResult nvhost_as_gpu::FreeSpace(const std::vector<u8>& input, std::vector<u8>& return NvResult::Success; } -NvResult nvhost_as_gpu::Remap(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_as_gpu::Remap(std::span<const u8> input, std::vector<u8>& 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<u8>& input, std::vector<u8>& out return NvResult::Success; } -NvResult nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_as_gpu::MapBufferEx(std::span<const u8> input, std::vector<u8>& output) { IoctlMapBufferEx params{}; std::memcpy(¶ms, input.data(), input.size()); @@ -424,7 +424,7 @@ NvResult nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8 return NvResult::Success; } -NvResult nvhost_as_gpu::UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_as_gpu::UnmapBuffer(std::span<const u8> input, std::vector<u8>& output) { IoctlUnmapBuffer params{}; std::memcpy(¶ms, input.data(), input.size()); @@ -463,7 +463,7 @@ NvResult nvhost_as_gpu::UnmapBuffer(const std::vector<u8>& input, std::vector<u8 return NvResult::Success; } -NvResult nvhost_as_gpu::BindChannel(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_as_gpu::BindChannel(std::span<const u8> input, std::vector<u8>& 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<u8>& input, std::vector<u8>& output) { +NvResult nvhost_as_gpu::GetVARegions(std::span<const u8> input, std::vector<u8>& output) { IoctlGetVaRegions params{}; std::memcpy(¶ms, input.data(), input.size()); @@ -511,7 +511,7 @@ NvResult nvhost_as_gpu::GetVARegions(const std::vector<u8>& input, std::vector<u return NvResult::Success; } -NvResult nvhost_as_gpu::GetVARegions(const std::vector<u8>& input, std::vector<u8>& output, +NvResult nvhost_as_gpu::GetVARegions(std::span<const u8> input, std::vector<u8>& output, std::vector<u8>& 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 86fe71c75..1aba8d579 100644 --- 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<u8>& input, + NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output) override; - NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) override; - NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output, std::vector<u8>& inline_output) override; + NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::vector<u8>& output) override; + NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output, + std::vector<u8>& 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<u8>& input, std::vector<u8>& output); - NvResult AllocateSpace(const std::vector<u8>& input, std::vector<u8>& output); - NvResult Remap(const std::vector<u8>& input, std::vector<u8>& output); - NvResult MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output); - NvResult UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output); - NvResult FreeSpace(const std::vector<u8>& input, std::vector<u8>& output); - NvResult BindChannel(const std::vector<u8>& input, std::vector<u8>& output); + NvResult AllocAsEx(std::span<const u8> input, std::vector<u8>& output); + NvResult AllocateSpace(std::span<const u8> input, std::vector<u8>& output); + NvResult Remap(std::span<const u8> input, std::vector<u8>& output); + NvResult MapBufferEx(std::span<const u8> input, std::vector<u8>& output); + NvResult UnmapBuffer(std::span<const u8> input, std::vector<u8>& output); + NvResult FreeSpace(std::span<const u8> input, std::vector<u8>& output); + NvResult BindChannel(std::span<const u8> input, std::vector<u8>& output); void GetVARegionsImpl(IoctlGetVaRegions& params); - NvResult GetVARegions(const std::vector<u8>& input, std::vector<u8>& output); - NvResult GetVARegions(const std::vector<u8>& input, std::vector<u8>& output, + NvResult GetVARegions(std::span<const u8> input, std::vector<u8>& output); + NvResult GetVARegions(std::span<const u8> input, std::vector<u8>& output, std::vector<u8>& 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 eee11fab8..0cdde82a7 100644 --- 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<u8>& input, +NvResult nvhost_ctrl::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output) { switch (command.group) { case 0x0: @@ -63,13 +63,13 @@ NvResult nvhost_ctrl::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& return NvResult::NotImplemented; } -NvResult nvhost_ctrl::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) { +NvResult nvhost_ctrl::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::vector<u8>& output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; } -NvResult nvhost_ctrl::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, +NvResult nvhost_ctrl::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output, std::vector<u8>& 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<u8>& input, std::vector<u8>& output) { +NvResult nvhost_ctrl::NvOsGetConfigU32(std::span<const u8> input, std::vector<u8>& 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<u8>& input, std::vector return NvResult::ConfigVarNotFound; // Returns error on production mode } -NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output, +NvResult nvhost_ctrl::IocCtrlEventWait(std::span<const u8> input, std::vector<u8>& 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<u8>& input, std::vector<u8>& output) { +NvResult nvhost_ctrl::IocCtrlEventRegister(std::span<const u8> input, std::vector<u8>& 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<u8>& input, std::ve return NvResult::Success; } -NvResult nvhost_ctrl::IocCtrlEventUnregister(const std::vector<u8>& input, - std::vector<u8>& output) { +NvResult nvhost_ctrl::IocCtrlEventUnregister(std::span<const u8> input, std::vector<u8>& 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<u8>& input, return FreeEvent(event_id); } -NvResult nvhost_ctrl::IocCtrlEventUnregisterBatch(const std::vector<u8>& input, +NvResult nvhost_ctrl::IocCtrlEventUnregisterBatch(std::span<const u8> input, std::vector<u8>& output) { IocCtrlEventUnregisterBatchParams params{}; std::memcpy(¶ms, input.data(), sizeof(params)); @@ -282,7 +281,7 @@ NvResult nvhost_ctrl::IocCtrlEventUnregisterBatch(const std::vector<u8>& input, return NvResult::Success; } -NvResult nvhost_ctrl::IocCtrlClearEventWait(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_ctrl::IocCtrlClearEventWait(std::span<const u8> input, std::vector<u8>& 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 0b56d7070..dd2e7888a 100644 --- 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<u8>& input, + NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output) override; - NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) override; - NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output, std::vector<u8>& inline_output) override; + NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::vector<u8>& output) override; + NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output, + std::vector<u8>& 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<u8>& input, std::vector<u8>& output); - NvResult IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output, + NvResult NvOsGetConfigU32(std::span<const u8> input, std::vector<u8>& output); + NvResult IocCtrlEventWait(std::span<const u8> input, std::vector<u8>& output, bool is_allocation); - NvResult IocCtrlEventRegister(const std::vector<u8>& input, std::vector<u8>& output); - NvResult IocCtrlEventUnregister(const std::vector<u8>& input, std::vector<u8>& output); - NvResult IocCtrlEventUnregisterBatch(const std::vector<u8>& input, std::vector<u8>& output); - NvResult IocCtrlClearEventWait(const std::vector<u8>& input, std::vector<u8>& output); + NvResult IocCtrlEventRegister(std::span<const u8> input, std::vector<u8>& output); + NvResult IocCtrlEventUnregister(std::span<const u8> input, std::vector<u8>& output); + NvResult IocCtrlEventUnregisterBatch(std::span<const u8> input, std::vector<u8>& output); + NvResult IocCtrlClearEventWait(std::span<const u8> input, std::vector<u8>& 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 b97813fbc..be3c083db 100644 --- 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<u8>& input, +NvResult nvhost_ctrl_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output) { switch (command.group) { case 'G': @@ -53,13 +53,13 @@ NvResult nvhost_ctrl_gpu::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u return NvResult::NotImplemented; } -NvResult nvhost_ctrl_gpu::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::vector<u8>& output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; } -NvResult nvhost_ctrl_gpu::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, +NvResult nvhost_ctrl_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output, std::vector<u8>& inline_output) { switch (command.group) { case 'G': @@ -82,8 +82,7 @@ NvResult nvhost_ctrl_gpu::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u void nvhost_ctrl_gpu::OnOpen(DeviceFD fd) {} void nvhost_ctrl_gpu::OnClose(DeviceFD fd) {} -NvResult nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input, - std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::vector<u8>& 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<u8>& input, return NvResult::Success; } -NvResult nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output, +NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::vector<u8>& output, std::vector<u8>& inline_output) { LOG_DEBUG(Service_NVDRV, "called"); IoctlCharacteristics params{}; @@ -176,7 +175,7 @@ NvResult nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input, std:: return NvResult::Success; } -NvResult nvhost_ctrl_gpu::GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::GetTPCMasks(std::span<const u8> input, std::vector<u8>& 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<u8>& input, std::vector< return NvResult::Success; } -NvResult nvhost_ctrl_gpu::GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output, +NvResult nvhost_ctrl_gpu::GetTPCMasks(std::span<const u8> input, std::vector<u8>& output, std::vector<u8>& inline_output) { IoctlGpuGetTpcMasksArgs params{}; std::memcpy(¶ms, input.data(), input.size()); @@ -200,7 +199,7 @@ NvResult nvhost_ctrl_gpu::GetTPCMasks(const std::vector<u8>& input, std::vector< return NvResult::Success; } -NvResult nvhost_ctrl_gpu::GetActiveSlotMask(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::GetActiveSlotMask(std::span<const u8> input, std::vector<u8>& output) { LOG_DEBUG(Service_NVDRV, "called"); IoctlActiveSlotMask params{}; @@ -213,7 +212,7 @@ NvResult nvhost_ctrl_gpu::GetActiveSlotMask(const std::vector<u8>& input, std::v return NvResult::Success; } -NvResult nvhost_ctrl_gpu::ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::ZCullGetCtxSize(std::span<const u8> input, std::vector<u8>& output) { LOG_DEBUG(Service_NVDRV, "called"); IoctlZcullGetCtxSize params{}; @@ -225,7 +224,7 @@ NvResult nvhost_ctrl_gpu::ZCullGetCtxSize(const std::vector<u8>& input, std::vec return NvResult::Success; } -NvResult nvhost_ctrl_gpu::ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::ZCullGetInfo(std::span<const u8> input, std::vector<u8>& output) { LOG_DEBUG(Service_NVDRV, "called"); IoctlNvgpuGpuZcullGetInfoArgs params{}; @@ -248,7 +247,7 @@ NvResult nvhost_ctrl_gpu::ZCullGetInfo(const std::vector<u8>& input, std::vector return NvResult::Success; } -NvResult nvhost_ctrl_gpu::ZBCSetTable(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::ZBCSetTable(std::span<const u8> input, std::vector<u8>& output) { LOG_WARNING(Service_NVDRV, "(STUBBED) called"); IoctlZbcSetTable params{}; @@ -264,7 +263,7 @@ NvResult nvhost_ctrl_gpu::ZBCSetTable(const std::vector<u8>& input, std::vector< return NvResult::Success; } -NvResult nvhost_ctrl_gpu::ZBCQueryTable(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::ZBCQueryTable(std::span<const u8> input, std::vector<u8>& output) { LOG_WARNING(Service_NVDRV, "(STUBBED) called"); IoctlZbcQueryTable params{}; @@ -274,7 +273,7 @@ NvResult nvhost_ctrl_gpu::ZBCQueryTable(const std::vector<u8>& input, std::vecto return NvResult::Success; } -NvResult nvhost_ctrl_gpu::FlushL2(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::FlushL2(std::span<const u8> input, std::vector<u8>& output) { LOG_WARNING(Service_NVDRV, "(STUBBED) called"); IoctlFlushL2 params{}; @@ -284,7 +283,7 @@ NvResult nvhost_ctrl_gpu::FlushL2(const std::vector<u8>& input, std::vector<u8>& return NvResult::Success; } -NvResult nvhost_ctrl_gpu::GetGpuTime(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::GetGpuTime(std::span<const u8> input, std::vector<u8>& 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 1e8f254e2..b9333d9d3 100644 --- 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<u8>& input, + NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output) override; - NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) override; - NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output, std::vector<u8>& inline_output) override; + NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::vector<u8>& output) override; + NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output, + std::vector<u8>& 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<u8>& input, std::vector<u8>& output); - NvResult GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output, + NvResult GetCharacteristics(std::span<const u8> input, std::vector<u8>& output); + NvResult GetCharacteristics(std::span<const u8> input, std::vector<u8>& output, std::vector<u8>& inline_output); - NvResult GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output); - NvResult GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output, + NvResult GetTPCMasks(std::span<const u8> input, std::vector<u8>& output); + NvResult GetTPCMasks(std::span<const u8> input, std::vector<u8>& output, std::vector<u8>& inline_output); - NvResult GetActiveSlotMask(const std::vector<u8>& input, std::vector<u8>& output); - NvResult ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u8>& output); - NvResult ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>& output); - NvResult ZBCSetTable(const std::vector<u8>& input, std::vector<u8>& output); - NvResult ZBCQueryTable(const std::vector<u8>& input, std::vector<u8>& output); - NvResult FlushL2(const std::vector<u8>& input, std::vector<u8>& output); - NvResult GetGpuTime(const std::vector<u8>& input, std::vector<u8>& output); + NvResult GetActiveSlotMask(std::span<const u8> input, std::vector<u8>& output); + NvResult ZCullGetCtxSize(std::span<const u8> input, std::vector<u8>& output); + NvResult ZCullGetInfo(std::span<const u8> input, std::vector<u8>& output); + NvResult ZBCSetTable(std::span<const u8> input, std::vector<u8>& output); + NvResult ZBCQueryTable(std::span<const u8> input, std::vector<u8>& output); + NvResult FlushL2(std::span<const u8> input, std::vector<u8>& output); + NvResult GetGpuTime(std::span<const u8> input, std::vector<u8>& 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 e123564c6..d2308fffc 100644 --- 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<u8>& input, +NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output) { switch (command.group) { case 0x0: @@ -98,8 +98,8 @@ NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& i return NvResult::NotImplemented; }; -NvResult nvhost_gpu::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) { +NvResult nvhost_gpu::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::vector<u8>& output) { switch (command.group) { case 'H': switch (command.cmd) { @@ -112,7 +112,7 @@ NvResult nvhost_gpu::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& i return NvResult::NotImplemented; } -NvResult nvhost_gpu::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, +NvResult nvhost_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output, std::vector<u8>& 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<u8>& i void nvhost_gpu::OnOpen(DeviceFD fd) {} void nvhost_gpu::OnClose(DeviceFD fd) {} -NvResult nvhost_gpu::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_gpu::SetNVMAPfd(std::span<const u8> input, std::vector<u8>& 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<u8>& input, std::vector<u8>& o return NvResult::Success; } -NvResult nvhost_gpu::SetClientData(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_gpu::SetClientData(std::span<const u8> input, std::vector<u8>& output) { LOG_DEBUG(Service_NVDRV, "called"); IoctlClientData params{}; @@ -139,7 +139,7 @@ NvResult nvhost_gpu::SetClientData(const std::vector<u8>& input, std::vector<u8> return NvResult::Success; } -NvResult nvhost_gpu::GetClientData(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_gpu::GetClientData(std::span<const u8> input, std::vector<u8>& output) { LOG_DEBUG(Service_NVDRV, "called"); IoctlClientData params{}; @@ -149,7 +149,7 @@ NvResult nvhost_gpu::GetClientData(const std::vector<u8>& input, std::vector<u8> return NvResult::Success; } -NvResult nvhost_gpu::ZCullBind(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_gpu::ZCullBind(std::span<const u8> input, std::vector<u8>& 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<u8>& input, std::vector<u8>& ou return NvResult::Success; } -NvResult nvhost_gpu::SetErrorNotifier(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_gpu::SetErrorNotifier(std::span<const u8> input, std::vector<u8>& 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<u8>& input, std::vector< return NvResult::Success; } -NvResult nvhost_gpu::SetChannelPriority(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_gpu::SetChannelPriority(std::span<const u8> input, std::vector<u8>& 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<u8>& input, std::vector<u8>& output) { +NvResult nvhost_gpu::AllocGPFIFOEx2(std::span<const u8> input, std::vector<u8>& 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<u8>& input, std::vector<u8 return NvResult::Success; } -NvResult nvhost_gpu::AllocateObjectContext(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_gpu::AllocateObjectContext(std::span<const u8> input, std::vector<u8>& 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<u8> return NvResult::Success; } -NvResult nvhost_gpu::SubmitGPFIFOBase(const std::vector<u8>& input, std::vector<u8>& output, +NvResult nvhost_gpu::SubmitGPFIFOBase(std::span<const u8> input, std::vector<u8>& output, bool kickoff) { if (input.size() < sizeof(IoctlSubmitGpfifo)) { UNIMPLEMENTED(); @@ -314,8 +314,7 @@ NvResult nvhost_gpu::SubmitGPFIFOBase(const std::vector<u8>& input, std::vector< return SubmitGPFIFOImpl(params, output, std::move(entries)); } -NvResult nvhost_gpu::SubmitGPFIFOBase(const std::vector<u8>& input, - const std::vector<u8>& input_inline, +NvResult nvhost_gpu::SubmitGPFIFOBase(std::span<const u8> input, std::span<const u8> input_inline, std::vector<u8>& output) { if (input.size() < sizeof(IoctlSubmitGpfifo)) { UNIMPLEMENTED(); @@ -328,7 +327,7 @@ NvResult nvhost_gpu::SubmitGPFIFOBase(const std::vector<u8>& input, return SubmitGPFIFOImpl(params, output, std::move(entries)); } -NvResult nvhost_gpu::GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_gpu::GetWaitbase(std::span<const u8> input, std::vector<u8>& 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<u8>& input, std::vector<u8>& return NvResult::Success; } -NvResult nvhost_gpu::ChannelSetTimeout(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_gpu::ChannelSetTimeout(std::span<const u8> input, std::vector<u8>& 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<u8>& input, std::vector return NvResult::Success; } -NvResult nvhost_gpu::ChannelSetTimeslice(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_gpu::ChannelSetTimeslice(std::span<const u8> input, std::vector<u8>& 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 1e4ecd55b..3ca58202d 100644 --- 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<u8>& input, + NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output) override; - NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) override; - NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output, std::vector<u8>& inline_output) override; + NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::vector<u8>& output) override; + NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output, + std::vector<u8>& 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<u8>& input, std::vector<u8>& output); - NvResult SetClientData(const std::vector<u8>& input, std::vector<u8>& output); - NvResult GetClientData(const std::vector<u8>& input, std::vector<u8>& output); - NvResult ZCullBind(const std::vector<u8>& input, std::vector<u8>& output); - NvResult SetErrorNotifier(const std::vector<u8>& input, std::vector<u8>& output); - NvResult SetChannelPriority(const std::vector<u8>& input, std::vector<u8>& output); - NvResult AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& output); - NvResult AllocateObjectContext(const std::vector<u8>& input, std::vector<u8>& output); + NvResult SetNVMAPfd(std::span<const u8> input, std::vector<u8>& output); + NvResult SetClientData(std::span<const u8> input, std::vector<u8>& output); + NvResult GetClientData(std::span<const u8> input, std::vector<u8>& output); + NvResult ZCullBind(std::span<const u8> input, std::vector<u8>& output); + NvResult SetErrorNotifier(std::span<const u8> input, std::vector<u8>& output); + NvResult SetChannelPriority(std::span<const u8> input, std::vector<u8>& output); + NvResult AllocGPFIFOEx2(std::span<const u8> input, std::vector<u8>& output); + NvResult AllocateObjectContext(std::span<const u8> input, std::vector<u8>& output); NvResult SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::vector<u8>& output, Tegra::CommandList&& entries); - NvResult SubmitGPFIFOBase(const std::vector<u8>& input, std::vector<u8>& output, + NvResult SubmitGPFIFOBase(std::span<const u8> input, std::vector<u8>& output, bool kickoff = false); - NvResult SubmitGPFIFOBase(const std::vector<u8>& input, const std::vector<u8>& input_inline, + NvResult SubmitGPFIFOBase(std::span<const u8> input, std::span<const u8> input_inline, std::vector<u8>& output); - NvResult GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output); - NvResult ChannelSetTimeout(const std::vector<u8>& input, std::vector<u8>& output); - NvResult ChannelSetTimeslice(const std::vector<u8>& input, std::vector<u8>& output); + NvResult GetWaitbase(std::span<const u8> input, std::vector<u8>& output); + NvResult ChannelSetTimeout(std::span<const u8> input, std::vector<u8>& output); + NvResult ChannelSetTimeslice(std::span<const u8> input, std::vector<u8>& 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 1703f9cc3..0c7aee1b8 100644 --- 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<u8>& input, +NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output) { switch (command.group) { case 0x0: @@ -55,13 +55,13 @@ NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& return NvResult::NotImplemented; } -NvResult nvhost_nvdec::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) { +NvResult nvhost_nvdec::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::vector<u8>& output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; } -NvResult nvhost_nvdec::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, +NvResult nvhost_nvdec::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output, std::vector<u8>& 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 c1b4e53e8..0d615bbcb 100644 --- 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<u8>& input, + NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output) override; - NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) override; - NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output, std::vector<u8>& inline_output) override; + NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::vector<u8>& output) override; + NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output, + std::vector<u8>& 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 99eede702..7bcef105b 100644 --- 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 <typename T> -std::size_t SliceVectors(const std::vector<u8>& input, std::vector<T>& dst, std::size_t count, +std::size_t SliceVectors(std::span<const u8> input, std::vector<T>& 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<u8>& input) { +NvResult nvhost_nvdec_common::SetNVMAPfd(std::span<const u8> 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<u8>& input) { return NvResult::Success; } -NvResult nvhost_nvdec_common::Submit(DeviceFD fd, const std::vector<u8>& input, +NvResult nvhost_nvdec_common::Submit(DeviceFD fd, std::span<const u8> input, std::vector<u8>& output) { IoctlSubmit params{}; std::memcpy(¶ms, input.data(), sizeof(IoctlSubmit)); @@ -121,7 +121,7 @@ NvResult nvhost_nvdec_common::Submit(DeviceFD fd, const std::vector<u8>& input, return NvResult::Success; } -NvResult nvhost_nvdec_common::GetSyncpoint(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_nvdec_common::GetSyncpoint(std::span<const u8> input, std::vector<u8>& 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<u8>& input, std::ve return NvResult::Success; } -NvResult nvhost_nvdec_common::GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_nvdec_common::GetWaitbase(std::span<const u8> input, std::vector<u8>& 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<u8>& input, std::vec return NvResult::Success; } -NvResult nvhost_nvdec_common::MapBuffer(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_nvdec_common::MapBuffer(std::span<const u8> input, std::vector<u8>& output) { IoctlMapBuffer params{}; std::memcpy(¶ms, input.data(), sizeof(IoctlMapBuffer)); std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries); @@ -159,7 +159,7 @@ NvResult nvhost_nvdec_common::MapBuffer(const std::vector<u8>& input, std::vecto return NvResult::Success; } -NvResult nvhost_nvdec_common::UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_nvdec_common::UnmapBuffer(std::span<const u8> input, std::vector<u8>& output) { IoctlMapBuffer params{}; std::memcpy(¶ms, input.data(), sizeof(IoctlMapBuffer)); std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries); @@ -173,8 +173,7 @@ NvResult nvhost_nvdec_common::UnmapBuffer(const std::vector<u8>& input, std::vec return NvResult::Success; } -NvResult nvhost_nvdec_common::SetSubmitTimeout(const std::vector<u8>& input, - std::vector<u8>& output) { +NvResult nvhost_nvdec_common::SetSubmitTimeout(std::span<const u8> input, std::vector<u8>& 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 fe76100c8..5af26a26f 100644 --- 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<u8>& input); - NvResult Submit(DeviceFD fd, const std::vector<u8>& input, std::vector<u8>& output); - NvResult GetSyncpoint(const std::vector<u8>& input, std::vector<u8>& output); - NvResult GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output); - NvResult MapBuffer(const std::vector<u8>& input, std::vector<u8>& output); - NvResult UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output); - NvResult SetSubmitTimeout(const std::vector<u8>& input, std::vector<u8>& output); + NvResult SetNVMAPfd(std::span<const u8> input); + NvResult Submit(DeviceFD fd, std::span<const u8> input, std::vector<u8>& output); + NvResult GetSyncpoint(std::span<const u8> input, std::vector<u8>& output); + NvResult GetWaitbase(std::span<const u8> input, std::vector<u8>& output); + NvResult MapBuffer(std::span<const u8> input, std::vector<u8>& output); + NvResult UnmapBuffer(std::span<const u8> input, std::vector<u8>& output); + NvResult SetSubmitTimeout(std::span<const u8> input, std::vector<u8>& 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 bdbc2f9e1..39f30e7c8 100644 --- 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<u8>& input, +NvResult nvhost_nvjpg::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output) { switch (command.group) { case 'H': @@ -31,13 +31,13 @@ NvResult nvhost_nvjpg::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& return NvResult::NotImplemented; } -NvResult nvhost_nvjpg::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) { +NvResult nvhost_nvjpg::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::vector<u8>& output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; } -NvResult nvhost_nvjpg::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, +NvResult nvhost_nvjpg::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output, std::vector<u8>& 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<u8>& void nvhost_nvjpg::OnOpen(DeviceFD fd) {} void nvhost_nvjpg::OnClose(DeviceFD fd) {} -NvResult nvhost_nvjpg::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_nvjpg::SetNVMAPfd(std::span<const u8> input, std::vector<u8>& 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 440e7d371..41b57e872 100644 --- 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<u8>& input, + NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output) override; - NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) override; - NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output, std::vector<u8>& inline_output) override; + NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::vector<u8>& output) override; + NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output, + std::vector<u8>& 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<u8>& input, std::vector<u8>& output); + NvResult SetNVMAPfd(std::span<const u8> input, std::vector<u8>& 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 73f97136e..b0ea402a7 100644 --- 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<u8>& input, +NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output) { switch (command.group) { case 0x0: @@ -55,13 +55,13 @@ NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& i return NvResult::NotImplemented; } -NvResult nvhost_vic::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) { +NvResult nvhost_vic::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::vector<u8>& output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; } -NvResult nvhost_vic::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, +NvResult nvhost_vic::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output, std::vector<u8>& 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 f164caafb..b5e350a83 100644 --- 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<u8>& input, + NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output) override; - NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) override; - NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output, std::vector<u8>& inline_output) override; + NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::vector<u8>& output) override; + NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output, + std::vector<u8>& 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 fa29db758..29c1e0f01 100644 --- 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<u8>& input, +NvResult nvmap::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output) { switch (command.group) { case 0x1: @@ -54,13 +54,13 @@ NvResult nvmap::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, return NvResult::NotImplemented; } -NvResult nvmap::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) { +NvResult nvmap::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::vector<u8>& output) { UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); return NvResult::NotImplemented; } -NvResult nvmap::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, +NvResult nvmap::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output, std::vector<u8>& 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<u8>& input, void nvmap::OnOpen(DeviceFD fd) {} void nvmap::OnClose(DeviceFD fd) {} -NvResult nvmap::IocCreate(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvmap::IocCreate(std::span<const u8> input, std::vector<u8>& 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<u8>& input, std::vector<u8>& output) return NvResult::Success; } -NvResult nvmap::IocAlloc(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvmap::IocAlloc(std::span<const u8> input, std::vector<u8>& 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<u8>& input, std::vector<u8>& output) return result; } -NvResult nvmap::IocGetId(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvmap::IocGetId(std::span<const u8> input, std::vector<u8>& output) { IocGetIdParams params; std::memcpy(¶ms, input.data(), sizeof(params)); @@ -161,7 +161,7 @@ NvResult nvmap::IocGetId(const std::vector<u8>& input, std::vector<u8>& output) return NvResult::Success; } -NvResult nvmap::IocFromId(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvmap::IocFromId(std::span<const u8> input, std::vector<u8>& output) { IocFromIdParams params; std::memcpy(¶ms, input.data(), sizeof(params)); @@ -192,7 +192,7 @@ NvResult nvmap::IocFromId(const std::vector<u8>& input, std::vector<u8>& output) return NvResult::Success; } -NvResult nvmap::IocParam(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvmap::IocParam(std::span<const u8> input, std::vector<u8>& 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<u8>& input, std::vector<u8>& output) return NvResult::Success; } -NvResult nvmap::IocFree(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvmap::IocFree(std::span<const u8> input, std::vector<u8>& 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 e9bfd0358..82bd3b118 100644 --- 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<u8>& input, + NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output) override; - NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) override; - NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output, std::vector<u8>& inline_output) override; + NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::vector<u8>& output) override; + NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output, + std::vector<u8>& 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<u8>& input, std::vector<u8>& output); - NvResult IocAlloc(const std::vector<u8>& input, std::vector<u8>& output); - NvResult IocGetId(const std::vector<u8>& input, std::vector<u8>& output); - NvResult IocFromId(const std::vector<u8>& input, std::vector<u8>& output); - NvResult IocParam(const std::vector<u8>& input, std::vector<u8>& output); - NvResult IocFree(const std::vector<u8>& input, std::vector<u8>& output); + NvResult IocCreate(std::span<const u8> input, std::vector<u8>& output); + NvResult IocAlloc(std::span<const u8> input, std::vector<u8>& output); + NvResult IocGetId(std::span<const u8> input, std::vector<u8>& output); + NvResult IocFromId(std::span<const u8> input, std::vector<u8>& output); + NvResult IocParam(std::span<const u8> input, std::vector<u8>& output); + NvResult IocFree(std::span<const u8> input, std::vector<u8>& 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 6fc8565c0..52d27e755 100644 --- 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<u8>& input, +NvResult Module::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& 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<u8>& input return itr->second->Ioctl1(fd, command, input, output); } -NvResult Module::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output) { +NvResult Module::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::vector<u8>& 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<u8>& input return itr->second->Ioctl2(fd, command, input, inline_input, output); } -NvResult Module::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, +NvResult Module::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output, std::vector<u8>& 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 f3c81bd88..b09b6e585 100644 --- a/src/core/hle/service/nvdrv/nvdrv.h +++ b/src/core/hle/service/nvdrv/nvdrv.h @@ -7,6 +7,7 @@ #include <functional> #include <list> #include <memory> +#include <span> #include <string> #include <unordered_map> #include <vector> @@ -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<u8>& input, - std::vector<u8>& output); + NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output); - NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& inline_input, std::vector<u8>& output); + NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, + std::span<const u8> inline_input, std::vector<u8>& output); - NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, - std::vector<u8>& output, std::vector<u8>& inline_output); + NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output, + std::vector<u8>& 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 e601b5da1..bcbe05b0d 100644 --- 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 4043c91f1..769e8c0a3 100644 --- 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 6ea327bbe..2969f0fd5 100644 --- 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<s32>* 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 f3fa2587d..d1b6201e0 100644 --- a/src/core/hle/service/nvflinger/parcel.h +++ b/src/core/hle/service/nvflinger/parcel.h @@ -4,6 +4,7 @@ #pragma once #include <memory> +#include <span> #include <vector> #include "common/alignment.h" @@ -12,18 +13,17 @@ namespace Service::android { -class Parcel final { -public: - static constexpr std::size_t DefaultBufferSize = 0x40; - - Parcel() : buffer(DefaultBufferSize) {} - - template <typename T> - explicit Parcel(const T& out_data) : buffer(DefaultBufferSize) { - Write(out_data); - } +struct ParcelHeader { + u32 data_size; + u32 data_offset; + u32 objects_size; + u32 objects_offset; +}; +static_assert(sizeof(ParcelHeader) == 16, "ParcelHeader has wrong size"); - explicit Parcel(std::vector<u8> in_data) : buffer(std::move(in_data)) { +class InputParcel final { +public: + explicit InputParcel(std::span<const u8> in_data) : read_buffer(std::move(in_data)) { DeserializeHeader(); [[maybe_unused]] const std::u16string token = ReadInterfaceToken(); } @@ -31,9 +31,9 @@ public: template <typename T> void Read(T& val) { static_assert(std::is_trivially_copyable_v<T>, "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 <typename T> T ReadUnaligned() { static_assert(std::is_trivially_copyable_v<T>, "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<const u8> read_buffer; + std::size_t read_index = 0; +}; + +class OutputParcel final { +public: + static constexpr std::size_t DefaultBufferSize = 0x40; + + OutputParcel() : buffer(DefaultBufferSize) {} + + template <typename T> + explicit OutputParcel(const T& out_data) : buffer(DefaultBufferSize) { + Write(out_data); + } + template <typename T> void Write(const T& val) { static_assert(std::is_trivially_copyable_v<T>, "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<u8> Serialize() const { - ASSERT(read_index == 0); - - Header header{}; - header.data_size = static_cast<u32>(write_index - sizeof(Header)); - header.data_offset = sizeof(Header); + ParcelHeader header{}; + header.data_size = static_cast<u32>(write_index - sizeof(ParcelHeader)); + header.data_offset = sizeof(ParcelHeader); header.objects_size = 4; - header.objects_offset = static_cast<u32>(sizeof(Header) + header.data_size); - std::memcpy(buffer.data(), &header, sizeof(Header)); + header.objects_offset = static_cast<u32>(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<u8> 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 78f897d3e..01040b32a 100644 --- 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<u8>{}; + return std::span<const u8>{}; }(); LOG_DEBUG(Service_PREPO, @@ -90,7 +90,7 @@ private: return ctx.ReadBuffer(1); } - return std::vector<u8>{}; + return std::span<const u8>{}; }(); LOG_DEBUG(Service_PREPO, @@ -142,7 +142,7 @@ private: return ctx.ReadBuffer(1); } - return std::vector<u8>{}; + return std::span<const u8>{}; }(); 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<u8>{}; + return std::span<const u8>{}; }(); LOG_DEBUG(Service_PREPO, diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp index 9e94a462f..bdb499268 100644 --- 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<s32>(); 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<u32>(); const OptName optname = static_cast<OptName>(rp.Pop<u32>()); - const std::vector<u8> 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<s32, Errno> BSD::SocketImpl(Domain domain, Type type, Protocol protoco return {fd, Errno::SUCCESS}; } -std::pair<s32, Errno> BSD::PollImpl(std::vector<u8>& write_buffer, std::vector<u8> read_buffer, +std::pair<s32, Errno> BSD::PollImpl(std::vector<u8>& write_buffer, std::span<const u8> read_buffer, s32 nfds, s32 timeout) { if (write_buffer.size() < nfds * sizeof(PollFD)) { return {-1, Errno::INVAL}; @@ -584,7 +583,7 @@ std::pair<s32, Errno> BSD::AcceptImpl(s32 fd, std::vector<u8>& write_buffer) { return {new_fd, Errno::SUCCESS}; } -Errno BSD::BindImpl(s32 fd, const std::vector<u8>& addr) { +Errno BSD::BindImpl(s32 fd, std::span<const u8> addr) { if (!IsFileDescriptorValid(fd)) { return Errno::BADF; } @@ -595,7 +594,7 @@ Errno BSD::BindImpl(s32 fd, const std::vector<u8>& addr) { return Translate(file_descriptors[fd]->socket->Bind(Translate(addr_in))); } -Errno BSD::ConnectImpl(s32 fd, const std::vector<u8>& addr) { +Errno BSD::ConnectImpl(s32 fd, std::span<const u8> addr) { if (!IsFileDescriptorValid(fd)) { return Errno::BADF; } @@ -800,15 +799,15 @@ std::pair<s32, Errno> BSD::RecvFromImpl(s32 fd, u32 flags, std::vector<u8>& mess return {ret, bsd_errno}; } -std::pair<s32, Errno> BSD::SendImpl(s32 fd, u32 flags, const std::vector<u8>& message) { +std::pair<s32, Errno> BSD::SendImpl(s32 fd, u32 flags, std::span<const u8> message) { if (!IsFileDescriptorValid(fd)) { return {-1, Errno::BADF}; } return Translate(file_descriptors[fd]->socket->Send(message, flags)); } -std::pair<s32, Errno> BSD::SendToImpl(s32 fd, u32 flags, const std::vector<u8>& message, - const std::vector<u8>& addr) { +std::pair<s32, Errno> BSD::SendToImpl(s32 fd, u32 flags, std::span<const u8> message, + std::span<const u8> 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 81e855e0f..56bb3f8b1 100644 --- a/src/core/hle/service/sockets/bsd.h +++ b/src/core/hle/service/sockets/bsd.h @@ -4,6 +4,7 @@ #pragma once #include <memory> +#include <span> #include <vector> #include "common/common_types.h" @@ -44,7 +45,7 @@ private: s32 nfds; s32 timeout; - std::vector<u8> read_buffer; + std::span<const u8> read_buffer; std::vector<u8> write_buffer; s32 ret{}; Errno bsd_errno{}; @@ -65,7 +66,7 @@ private: void Response(Kernel::HLERequestContext& ctx); s32 fd; - std::vector<u8> addr; + std::span<const u8> addr; Errno bsd_errno{}; }; @@ -98,7 +99,7 @@ private: s32 fd; u32 flags; - std::vector<u8> message; + std::span<const u8> message; s32 ret{}; Errno bsd_errno{}; }; @@ -109,8 +110,8 @@ private: s32 fd; u32 flags; - std::vector<u8> message; - std::vector<u8> addr; + std::span<const u8> message; + std::span<const u8> addr; s32 ret{}; Errno bsd_errno{}; }; @@ -143,11 +144,11 @@ private: void ExecuteWork(Kernel::HLERequestContext& ctx, Work work); std::pair<s32, Errno> SocketImpl(Domain domain, Type type, Protocol protocol); - std::pair<s32, Errno> PollImpl(std::vector<u8>& write_buffer, std::vector<u8> read_buffer, + std::pair<s32, Errno> PollImpl(std::vector<u8>& write_buffer, std::span<const u8> read_buffer, s32 nfds, s32 timeout); std::pair<s32, Errno> AcceptImpl(s32 fd, std::vector<u8>& write_buffer); - Errno BindImpl(s32 fd, const std::vector<u8>& addr); - Errno ConnectImpl(s32 fd, const std::vector<u8>& addr); + Errno BindImpl(s32 fd, std::span<const u8> addr); + Errno ConnectImpl(s32 fd, std::span<const u8> addr); Errno GetPeerNameImpl(s32 fd, std::vector<u8>& write_buffer); Errno GetSockNameImpl(s32 fd, std::vector<u8>& write_buffer); Errno ListenImpl(s32 fd, s32 backlog); @@ -157,9 +158,9 @@ private: std::pair<s32, Errno> RecvImpl(s32 fd, u32 flags, std::vector<u8>& message); std::pair<s32, Errno> RecvFromImpl(s32 fd, u32 flags, std::vector<u8>& message, std::vector<u8>& addr); - std::pair<s32, Errno> SendImpl(s32 fd, u32 flags, const std::vector<u8>& message); - std::pair<s32, Errno> SendToImpl(s32 fd, u32 flags, const std::vector<u8>& message, - const std::vector<u8>& addr); + std::pair<s32, Errno> SendImpl(s32 fd, u32 flags, std::span<const u8> message); + std::pair<s32, Errno> SendToImpl(s32 fd, u32 flags, std::span<const u8> message, + std::span<const u8> 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 097c37d7a..e96eda7f3 100644 --- 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 3735e0452..dcf47083f 100644 --- 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<CertificateFormat>(); - 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<u8>{}; + return std::span<const u8>{}; }(); constexpr u64 client_id = 0; diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index bb283e74e..2fb631183 100644 --- 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 282ea1ff9..7494fb62d 100644 --- a/src/core/internal_network/network.cpp +++ b/src/core/internal_network/network.cpp @@ -550,7 +550,7 @@ std::pair<s32, Errno> Socket::RecvFrom(int flags, std::vector<u8>& message, Sock return {-1, GetAndLogLastError()}; } -std::pair<s32, Errno> Socket::Send(const std::vector<u8>& message, int flags) { +std::pair<s32, Errno> Socket::Send(std::span<const u8> message, int flags) { ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max())); ASSERT(flags == 0); @@ -563,7 +563,7 @@ std::pair<s32, Errno> Socket::Send(const std::vector<u8>& message, int flags) { return {-1, GetAndLogLastError()}; } -std::pair<s32, Errno> Socket::SendTo(u32 flags, const std::vector<u8>& message, +std::pair<s32, Errno> Socket::SendTo(u32 flags, std::span<const u8> 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 1e1c42cea..7a77171c2 100644 --- a/src/core/internal_network/socket_proxy.cpp +++ b/src/core/internal_network/socket_proxy.cpp @@ -182,7 +182,7 @@ std::pair<s32, Errno> ProxySocket::ReceivePacket(int flags, std::vector<u8>& mes return {static_cast<u32>(read_bytes), Errno::SUCCESS}; } -std::pair<s32, Errno> ProxySocket::Send(const std::vector<u8>& message, int flags) { +std::pair<s32, Errno> ProxySocket::Send(std::span<const u8> message, int flags) { LOG_WARNING(Network, "(STUBBED) called"); ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max())); ASSERT(flags == 0); @@ -200,7 +200,7 @@ void ProxySocket::SendPacket(ProxyPacket& packet) { } } -std::pair<s32, Errno> ProxySocket::SendTo(u32 flags, const std::vector<u8>& message, +std::pair<s32, Errno> ProxySocket::SendTo(u32 flags, std::span<const u8> 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 f12b5f567..9421492bc 100644 --- a/src/core/internal_network/socket_proxy.h +++ b/src/core/internal_network/socket_proxy.h @@ -4,6 +4,7 @@ #pragma once #include <mutex> +#include <span> #include <vector> #include <queue> @@ -48,11 +49,11 @@ public: std::pair<s32, Errno> ReceivePacket(int flags, std::vector<u8>& message, SockAddrIn* addr, std::size_t max_length); - std::pair<s32, Errno> Send(const std::vector<u8>& message, int flags) override; + std::pair<s32, Errno> Send(std::span<const u8> message, int flags) override; void SendPacket(ProxyPacket& packet); - std::pair<s32, Errno> SendTo(u32 flags, const std::vector<u8>& message, + std::pair<s32, Errno> SendTo(u32 flags, std::span<const u8> 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 2e328c645..4c7489258 100644 --- a/src/core/internal_network/sockets.h +++ b/src/core/internal_network/sockets.h @@ -5,6 +5,7 @@ #include <map> #include <memory> +#include <span> #include <utility> #if defined(_WIN32) @@ -66,9 +67,9 @@ public: virtual std::pair<s32, Errno> RecvFrom(int flags, std::vector<u8>& message, SockAddrIn* addr) = 0; - virtual std::pair<s32, Errno> Send(const std::vector<u8>& message, int flags) = 0; + virtual std::pair<s32, Errno> Send(std::span<const u8> message, int flags) = 0; - virtual std::pair<s32, Errno> SendTo(u32 flags, const std::vector<u8>& message, + virtual std::pair<s32, Errno> SendTo(u32 flags, std::span<const u8> message, const SockAddrIn* addr) = 0; virtual Errno SetLinger(bool enable, u32 linger) = 0; @@ -138,9 +139,9 @@ public: std::pair<s32, Errno> RecvFrom(int flags, std::vector<u8>& message, SockAddrIn* addr) override; - std::pair<s32, Errno> Send(const std::vector<u8>& message, int flags) override; + std::pair<s32, Errno> Send(std::span<const u8> message, int flags) override; - std::pair<s32, Errno> SendTo(u32 flags, const std::vector<u8>& message, + std::pair<s32, Errno> SendTo(u32 flags, std::span<const u8> 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 77821e047..59dfb8767 100644 --- 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<std::vector<u8>>& data, + const std::vector<std::span<const u8>>& data, std::optional<u64> process_id, std::optional<u128> user_id) const { if (!IsReportingEnabled()) { return; diff --git a/src/core/reporter.h b/src/core/reporter.h index 9fdb9d6c1..bb11f8e7c 100644 --- a/src/core/reporter.h +++ b/src/core/reporter.h @@ -5,6 +5,7 @@ #include <array> #include <optional> +#include <span> #include <string> #include <vector> #include "common/common_types.h" @@ -56,7 +57,8 @@ public: System, }; - void SavePlayReport(PlayReportType type, u64 title_id, const std::vector<std::vector<u8>>& data, + void SavePlayReport(PlayReportType type, u64 title_id, + const std::vector<std::span<const u8>>& data, std::optional<u64> process_id = {}, std::optional<u128> user_id = {}) const; // Used by error applet diff --git a/src/input_common/drivers/joycon.cpp b/src/input_common/drivers/joycon.cpp index cedc94e63..4fcfb4510 100644 --- a/src/input_common/drivers/joycon.cpp +++ b/src/input_common/drivers/joycon.cpp @@ -668,12 +668,10 @@ std::string Joycons::JoyconName(Joycon::ControllerType type) const { return "Right Joycon"; case Joycon::ControllerType::Pro: return "Pro Controller"; - case Joycon::ControllerType::Grip: - return "Grip Controller"; case Joycon::ControllerType::Dual: return "Dual Joycon"; default: - return "Unknown Joycon"; + return "Unknown Switch Controller"; } } } // namespace InputCommon diff --git a/src/input_common/drivers/joycon.h b/src/input_common/drivers/joycon.h index 316d383d8..2149ab7fd 100644 --- a/src/input_common/drivers/joycon.h +++ b/src/input_common/drivers/joycon.h @@ -15,7 +15,7 @@ using SerialNumber = std::array<u8, 15>; struct Battery; struct Color; struct MotionData; -enum class ControllerType; +enum class ControllerType : u8; enum class DriverResult; enum class IrsResolution; class JoyconDriver; diff --git a/src/input_common/helpers/joycon_driver.cpp b/src/input_common/helpers/joycon_driver.cpp index 3775e2d35..8f94c9f45 100644 --- a/src/input_common/helpers/joycon_driver.cpp +++ b/src/input_common/helpers/joycon_driver.cpp @@ -162,14 +162,14 @@ void JoyconDriver::InputThread(std::stop_token stop_token) { } void JoyconDriver::OnNewData(std::span<u8> buffer) { - const auto report_mode = static_cast<InputReport>(buffer[0]); + const auto report_mode = static_cast<ReportMode>(buffer[0]); // Packages can be a litte bit inconsistent. Average the delta time to provide a smoother motion // experience switch (report_mode) { - case InputReport::STANDARD_FULL_60HZ: - case InputReport::NFC_IR_MODE_60HZ: - case InputReport::SIMPLE_HID_MODE: { + case ReportMode::STANDARD_FULL_60HZ: + case ReportMode::NFC_IR_MODE_60HZ: + case ReportMode::SIMPLE_HID_MODE: { const auto now = std::chrono::steady_clock::now(); const auto new_delta_time = static_cast<u64>( std::chrono::duration_cast<std::chrono::microseconds>(now - last_update).count()); @@ -190,7 +190,7 @@ void JoyconDriver::OnNewData(std::span<u8> buffer) { }; // TODO: Remove this when calibration is properly loaded and not calculated - if (ring_connected && report_mode == InputReport::STANDARD_FULL_60HZ) { + if (ring_connected && report_mode == ReportMode::STANDARD_FULL_60HZ) { InputReportActive data{}; memcpy(&data, buffer.data(), sizeof(InputReportActive)); calibration_protocol->GetRingCalibration(ring_calibration, data.ring_input); @@ -228,16 +228,16 @@ void JoyconDriver::OnNewData(std::span<u8> buffer) { } switch (report_mode) { - case InputReport::STANDARD_FULL_60HZ: + case ReportMode::STANDARD_FULL_60HZ: joycon_poller->ReadActiveMode(buffer, motion_status, ring_status); break; - case InputReport::NFC_IR_MODE_60HZ: + case ReportMode::NFC_IR_MODE_60HZ: joycon_poller->ReadNfcIRMode(buffer, motion_status); break; - case InputReport::SIMPLE_HID_MODE: + case ReportMode::SIMPLE_HID_MODE: joycon_poller->ReadPassiveMode(buffer); break; - case InputReport::SUBCMD_REPLY: + case ReportMode::SUBCMD_REPLY: LOG_DEBUG(Input, "Unhandled command reply"); break; default: diff --git a/src/input_common/helpers/joycon_protocol/common_protocol.cpp b/src/input_common/helpers/joycon_protocol/common_protocol.cpp index 0ef240344..2b42a4555 100644 --- a/src/input_common/helpers/joycon_protocol/common_protocol.cpp +++ b/src/input_common/helpers/joycon_protocol/common_protocol.cpp @@ -22,12 +22,9 @@ void JoyconCommonProtocol::SetNonBlocking() { } DriverResult JoyconCommonProtocol::GetDeviceType(ControllerType& controller_type) { - std::array<u8, 1> buffer{}; - const auto result = ReadRawSPI(SpiAddress::DEVICE_TYPE, buffer); - controller_type = ControllerType::None; + const auto result = ReadSPI(SpiAddress::DEVICE_TYPE, controller_type); if (result == DriverResult::Success) { - controller_type = static_cast<ControllerType>(buffer[0]); // Fallback to 3rd party pro controllers if (controller_type == ControllerType::None) { controller_type = ControllerType::Pro; @@ -40,6 +37,7 @@ DriverResult JoyconCommonProtocol::GetDeviceType(ControllerType& controller_type DriverResult JoyconCommonProtocol::CheckDeviceAccess(SDL_hid_device_info* device_info) { ControllerType controller_type{ControllerType::None}; const auto result = GetDeviceType(controller_type); + if (result != DriverResult::Success || controller_type == ControllerType::None) { return DriverResult::UnsupportedControllerType; } @@ -62,7 +60,7 @@ DriverResult JoyconCommonProtocol::SetReportMode(ReportMode report_mode) { return SendSubCommand(SubCommand::SET_REPORT_MODE, buffer); } -DriverResult JoyconCommonProtocol::SendData(std::span<const u8> buffer) { +DriverResult JoyconCommonProtocol::SendRawData(std::span<const u8> buffer) { const auto result = SDL_hid_write(hidapi_handle->handle, buffer.data(), buffer.size()); if (result == -1) { @@ -72,15 +70,15 @@ DriverResult JoyconCommonProtocol::SendData(std::span<const u8> buffer) { return DriverResult::Success; } -DriverResult JoyconCommonProtocol::GetSubCommandResponse(SubCommand sc, std::vector<u8>& output) { +DriverResult JoyconCommonProtocol::GetSubCommandResponse(SubCommand sc, + SubCommandResponse& output) { constexpr int timeout_mili = 66; constexpr int MaxTries = 15; int tries = 0; - output.resize(MaxSubCommandResponseSize); do { - int result = SDL_hid_read_timeout(hidapi_handle->handle, output.data(), - MaxSubCommandResponseSize, timeout_mili); + int result = SDL_hid_read_timeout(hidapi_handle->handle, reinterpret_cast<u8*>(&output), + sizeof(SubCommandResponse), timeout_mili); if (result < 1) { LOG_ERROR(Input, "No response from joycon"); @@ -88,27 +86,28 @@ DriverResult JoyconCommonProtocol::GetSubCommandResponse(SubCommand sc, std::vec if (tries++ > MaxTries) { return DriverResult::Timeout; } - } while (output[0] != 0x21 && output[14] != static_cast<u8>(sc)); - - if (output[0] != 0x21 && output[14] != static_cast<u8>(sc)) { - return DriverResult::WrongReply; - } + } while (output.input_report.report_mode != ReportMode::SUBCMD_REPLY && + output.sub_command != sc); return DriverResult::Success; } DriverResult JoyconCommonProtocol::SendSubCommand(SubCommand sc, std::span<const u8> buffer, - std::vector<u8>& output) { - std::vector<u8> local_buffer(MaxResponseSize); - - local_buffer[0] = static_cast<u8>(OutputReport::RUMBLE_AND_SUBCMD); - local_buffer[1] = GetCounter(); - local_buffer[10] = static_cast<u8>(sc); - for (std::size_t i = 0; i < buffer.size(); ++i) { - local_buffer[11 + i] = buffer[i]; + SubCommandResponse& output) { + SubCommandPacket packet{ + .output_report = OutputReport::RUMBLE_AND_SUBCMD, + .packet_counter = GetCounter(), + .sub_command = sc, + .command_data = {}, + }; + + if (buffer.size() > packet.command_data.size()) { + return DriverResult::InvalidParameters; } - auto result = SendData(local_buffer); + memcpy(packet.command_data.data(), buffer.data(), buffer.size()); + + auto result = SendData(packet); if (result != DriverResult::Success) { return result; @@ -120,46 +119,57 @@ DriverResult JoyconCommonProtocol::SendSubCommand(SubCommand sc, std::span<const } DriverResult JoyconCommonProtocol::SendSubCommand(SubCommand sc, std::span<const u8> buffer) { - std::vector<u8> output; + SubCommandResponse output{}; return SendSubCommand(sc, buffer, output); } DriverResult JoyconCommonProtocol::SendMCUCommand(SubCommand sc, std::span<const u8> buffer) { - std::vector<u8> local_buffer(MaxResponseSize); - - local_buffer[0] = static_cast<u8>(OutputReport::MCU_DATA); - local_buffer[1] = GetCounter(); - local_buffer[10] = static_cast<u8>(sc); - for (std::size_t i = 0; i < buffer.size(); ++i) { - local_buffer[11 + i] = buffer[i]; + SubCommandPacket packet{ + .output_report = OutputReport::MCU_DATA, + .packet_counter = GetCounter(), + .sub_command = sc, + .command_data = {}, + }; + + if (buffer.size() > packet.command_data.size()) { + return DriverResult::InvalidParameters; } - return SendData(local_buffer); + memcpy(packet.command_data.data(), buffer.data(), buffer.size()); + + return SendData(packet); } DriverResult JoyconCommonProtocol::SendVibrationReport(std::span<const u8> buffer) { - std::vector<u8> local_buffer(MaxResponseSize); - - local_buffer[0] = static_cast<u8>(Joycon::OutputReport::RUMBLE_ONLY); - local_buffer[1] = GetCounter(); + VibrationPacket packet{ + .output_report = OutputReport::RUMBLE_ONLY, + .packet_counter = GetCounter(), + .vibration_data = {}, + }; + + if (buffer.size() > packet.vibration_data.size()) { + return DriverResult::InvalidParameters; + } - memcpy(local_buffer.data() + 2, buffer.data(), buffer.size()); + memcpy(packet.vibration_data.data(), buffer.data(), buffer.size()); - return SendData(local_buffer); + return SendData(packet); } DriverResult JoyconCommonProtocol::ReadRawSPI(SpiAddress addr, std::span<u8> output) { - constexpr std::size_t HeaderSize = 20; + constexpr std::size_t HeaderSize = 5; constexpr std::size_t MaxTries = 10; - const auto size = output.size(); std::size_t tries = 0; - std::array<u8, 5> buffer = {0x00, 0x00, 0x00, 0x00, static_cast<u8>(size)}; - std::vector<u8> local_buffer{}; - - buffer[0] = static_cast<u8>(static_cast<u16>(addr) & 0x00FF); - buffer[1] = static_cast<u8>((static_cast<u16>(addr) & 0xFF00) >> 8); + SubCommandResponse response{}; + std::array<u8, sizeof(ReadSpiPacket)> buffer{}; + const ReadSpiPacket packet_data{ + .spi_address = addr, + .size = static_cast<u8>(output.size()), + }; + + memcpy(buffer.data(), &packet_data, sizeof(ReadSpiPacket)); do { - const auto result = SendSubCommand(SubCommand::SPI_FLASH_READ, buffer, local_buffer); + const auto result = SendSubCommand(SubCommand::SPI_FLASH_READ, buffer, response); if (result != DriverResult::Success) { return result; } @@ -167,14 +177,14 @@ DriverResult JoyconCommonProtocol::ReadRawSPI(SpiAddress addr, std::span<u8> out if (tries++ > MaxTries) { return DriverResult::Timeout; } - } while (local_buffer[15] != buffer[0] || local_buffer[16] != buffer[1]); + } while (response.spi_address != addr); - if (local_buffer.size() < size + HeaderSize) { + if (response.command_data.size() < packet_data.size + HeaderSize) { return DriverResult::WrongReply; } // Remove header from output - memcpy(output.data(), local_buffer.data() + HeaderSize, size); + memcpy(output.data(), response.command_data.data() + HeaderSize, packet_data.size); return DriverResult::Success; } @@ -183,7 +193,7 @@ DriverResult JoyconCommonProtocol::EnableMCU(bool enable) { const auto result = SendSubCommand(SubCommand::SET_MCU_STATE, mcu_state); if (result != DriverResult::Success) { - LOG_ERROR(Input, "SendMCUData failed with error {}", result); + LOG_ERROR(Input, "Failed with error {}", result); } return result; @@ -198,22 +208,21 @@ DriverResult JoyconCommonProtocol::ConfigureMCU(const MCUConfig& config) { const auto result = SendSubCommand(SubCommand::SET_MCU_CONFIG, config_buffer); if (result != DriverResult::Success) { - LOG_ERROR(Input, "Set MCU config failed with error {}", result); + LOG_ERROR(Input, "Failed with error {}", result); } return result; } -DriverResult JoyconCommonProtocol::GetMCUDataResponse(ReportMode report_mode_, - std::vector<u8>& output) { - const int report_mode = static_cast<u8>(report_mode_); +DriverResult JoyconCommonProtocol::GetMCUDataResponse(ReportMode report_mode, + MCUCommandResponse& output) { constexpr int TimeoutMili = 200; constexpr int MaxTries = 9; int tries = 0; - output.resize(0x170); do { - int result = SDL_hid_read_timeout(hidapi_handle->handle, output.data(), 0x170, TimeoutMili); + int result = SDL_hid_read_timeout(hidapi_handle->handle, reinterpret_cast<u8*>(&output), + sizeof(MCUCommandResponse), TimeoutMili); if (result < 1) { LOG_ERROR(Input, "No response from joycon attempt {}", tries); @@ -221,28 +230,29 @@ DriverResult JoyconCommonProtocol::GetMCUDataResponse(ReportMode report_mode_, if (tries++ > MaxTries) { return DriverResult::Timeout; } - } while (output[0] != report_mode || output[49] == 0xFF); - - if (output[0] != report_mode || output[49] == 0xFF) { - return DriverResult::WrongReply; - } + } while (output.input_report.report_mode != report_mode || + output.mcu_report == MCUReport::EmptyAwaitingCmd); return DriverResult::Success; } DriverResult JoyconCommonProtocol::SendMCUData(ReportMode report_mode, SubCommand sc, std::span<const u8> buffer, - std::vector<u8>& output) { - std::vector<u8> local_buffer(MaxResponseSize); - - local_buffer[0] = static_cast<u8>(OutputReport::MCU_DATA); - local_buffer[1] = GetCounter(); - local_buffer[9] = static_cast<u8>(sc); - for (std::size_t i = 0; i < buffer.size(); ++i) { - local_buffer[10 + i] = buffer[i]; + MCUCommandResponse& output) { + SubCommandPacket packet{ + .output_report = OutputReport::MCU_DATA, + .packet_counter = GetCounter(), + .sub_command = sc, + .command_data = {}, + }; + + if (buffer.size() > packet.command_data.size()) { + return DriverResult::InvalidParameters; } - auto result = SendData(local_buffer); + memcpy(packet.command_data.data(), buffer.data(), buffer.size()); + + auto result = SendData(packet); if (result != DriverResult::Success) { return result; @@ -254,7 +264,7 @@ DriverResult JoyconCommonProtocol::SendMCUData(ReportMode report_mode, SubComman } DriverResult JoyconCommonProtocol::WaitSetMCUMode(ReportMode report_mode, MCUMode mode) { - std::vector<u8> output; + MCUCommandResponse output{}; constexpr std::size_t MaxTries{8}; std::size_t tries{}; @@ -269,7 +279,8 @@ DriverResult JoyconCommonProtocol::WaitSetMCUMode(ReportMode report_mode, MCUMod if (tries++ > MaxTries) { return DriverResult::WrongReply; } - } while (output[49] != 1 || output[56] != static_cast<u8>(mode)); + } while (output.mcu_report != MCUReport::StateReport || + output.mcu_data[6] != static_cast<u8>(mode)); 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 75d3f20a4..f44f73ba4 100644 --- a/src/input_common/helpers/joycon_protocol/common_protocol.h +++ b/src/input_common/helpers/joycon_protocol/common_protocol.h @@ -57,22 +57,31 @@ public: * Sends data to the joycon device * @param buffer data to be send */ - DriverResult SendData(std::span<const u8> buffer); + DriverResult SendRawData(std::span<const u8> buffer); + + template <typename Output> + requires std::is_trivially_copyable_v<Output> + DriverResult SendData(const Output& output) { + std::array<u8, sizeof(Output)> buffer; + std::memcpy(buffer.data(), &output, sizeof(Output)); + return SendRawData(buffer); + } /** * Waits for incoming data of the joycon device that matchs the subcommand * @param sub_command type of data to be returned - * @returns a buffer containing the responce + * @returns a buffer containing the response */ - DriverResult GetSubCommandResponse(SubCommand sub_command, std::vector<u8>& output); + DriverResult GetSubCommandResponse(SubCommand sub_command, SubCommandResponse& output); /** * Sends a sub command to the device and waits for it's reply * @param sc sub command to be send * @param buffer data to be send - * @returns output buffer containing the responce + * @returns output buffer containing the response */ - DriverResult SendSubCommand(SubCommand sc, std::span<const u8> buffer, std::vector<u8>& output); + DriverResult SendSubCommand(SubCommand sc, std::span<const u8> buffer, + SubCommandResponse& output); /** * Sends a sub command to the device and waits for it's reply and ignores the output @@ -97,18 +106,18 @@ public: /** * Reads the SPI memory stored on the joycon * @param Initial address location - * @returns output buffer containing the responce + * @returns output buffer containing the response */ DriverResult ReadRawSPI(SpiAddress addr, std::span<u8> output); /** * Reads the SPI memory stored on the joycon * @param Initial address location - * @returns output object containing the responce + * @returns output object containing the response */ template <typename Output> - requires std::is_trivially_copyable_v<Output> DriverResult ReadSPI(SpiAddress addr, - Output& output) { + requires std::is_trivially_copyable_v<Output> + DriverResult ReadSPI(SpiAddress addr, Output& output) { std::array<u8, sizeof(Output)> buffer; output = {}; @@ -136,19 +145,19 @@ public: /** * Waits until there's MCU data available. On timeout returns error * @param report mode of the expected reply - * @returns a buffer containing the responce + * @returns a buffer containing the response */ - DriverResult GetMCUDataResponse(ReportMode report_mode_, std::vector<u8>& output); + DriverResult GetMCUDataResponse(ReportMode report_mode_, MCUCommandResponse& output); /** * Sends data to the MCU chip and waits for it's reply * @param report mode of the expected reply * @param sub command to be send * @param buffer data to be send - * @returns output buffer containing the responce + * @returns output buffer containing the response */ DriverResult SendMCUData(ReportMode report_mode, SubCommand sc, std::span<const u8> buffer, - std::vector<u8>& output); + MCUCommandResponse& output); /** * Wait's until the MCU chip is on the specified mode diff --git a/src/input_common/helpers/joycon_protocol/generic_functions.cpp b/src/input_common/helpers/joycon_protocol/generic_functions.cpp index 484c208e6..548a4b9e3 100644 --- a/src/input_common/helpers/joycon_protocol/generic_functions.cpp +++ b/src/input_common/helpers/joycon_protocol/generic_functions.cpp @@ -32,13 +32,13 @@ DriverResult GenericProtocol::TriggersElapsed() { DriverResult GenericProtocol::GetDeviceInfo(DeviceInfo& device_info) { ScopedSetBlocking sb(this); - std::vector<u8> output; + SubCommandResponse output{}; const auto result = SendSubCommand(SubCommand::REQ_DEV_INFO, {}, output); device_info = {}; if (result == DriverResult::Success) { - memcpy(&device_info, output.data(), sizeof(DeviceInfo)); + device_info = output.device_info; } return result; diff --git a/src/input_common/helpers/joycon_protocol/irs.cpp b/src/input_common/helpers/joycon_protocol/irs.cpp index 09e17bc5b..731fd5981 100644 --- a/src/input_common/helpers/joycon_protocol/irs.cpp +++ b/src/input_common/helpers/joycon_protocol/irs.cpp @@ -132,7 +132,7 @@ DriverResult IrsProtocol::RequestImage(std::span<u8> buffer) { DriverResult IrsProtocol::ConfigureIrs() { LOG_DEBUG(Input, "Configure IRS"); constexpr std::size_t max_tries = 28; - std::vector<u8> output; + SubCommandResponse output{}; std::size_t tries = 0; const IrsConfigure irs_configuration{ @@ -158,7 +158,7 @@ DriverResult IrsProtocol::ConfigureIrs() { if (tries++ >= max_tries) { return DriverResult::WrongReply; } - } while (output[15] != 0x0b); + } while (output.command_data[0] != 0x0b); return DriverResult::Success; } @@ -167,7 +167,7 @@ DriverResult IrsProtocol::WriteRegistersStep1() { LOG_DEBUG(Input, "WriteRegistersStep1"); DriverResult result{DriverResult::Success}; constexpr std::size_t max_tries = 28; - std::vector<u8> output; + SubCommandResponse output{}; std::size_t tries = 0; const IrsWriteRegisters irs_registers{ @@ -218,7 +218,8 @@ DriverResult IrsProtocol::WriteRegistersStep1() { if (tries++ >= max_tries) { return DriverResult::WrongReply; } - } while (!(output[15] == 0x13 && output[17] == 0x07) && output[15] != 0x23); + } while (!(output.command_data[0] == 0x13 && output.command_data[2] == 0x07) && + output.command_data[0] != 0x23); return DriverResult::Success; } @@ -226,7 +227,7 @@ DriverResult IrsProtocol::WriteRegistersStep1() { DriverResult IrsProtocol::WriteRegistersStep2() { LOG_DEBUG(Input, "WriteRegistersStep2"); constexpr std::size_t max_tries = 28; - std::vector<u8> output; + SubCommandResponse output{}; std::size_t tries = 0; const IrsWriteRegisters irs_registers{ @@ -260,7 +261,7 @@ DriverResult IrsProtocol::WriteRegistersStep2() { if (tries++ >= max_tries) { return DriverResult::WrongReply; } - } while (output[15] != 0x13 && output[15] != 0x23); + } while (output.command_data[0] != 0x13 && output.command_data[0] != 0x23); return 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 14b07bfb5..b91934990 100644 --- a/src/input_common/helpers/joycon_protocol/joycon_types.h +++ b/src/input_common/helpers/joycon_protocol/joycon_types.h @@ -19,20 +19,24 @@ namespace InputCommon::Joycon { constexpr u32 MaxErrorCount = 50; constexpr u32 MaxBufferSize = 368; -constexpr u32 MaxResponseSize = 49; -constexpr u32 MaxSubCommandResponseSize = 64; constexpr std::array<u8, 8> DefaultVibrationBuffer{0x0, 0x1, 0x40, 0x40, 0x0, 0x1, 0x40, 0x40}; using MacAddress = std::array<u8, 6>; using SerialNumber = std::array<u8, 15>; -enum class ControllerType { - None, - Left, - Right, - Pro, - Grip, - Dual, +enum class ControllerType : u8 { + None = 0x00, + Left = 0x01, + Right = 0x02, + Pro = 0x03, + Dual = 0x05, // TODO: Verify this id + LarkHvc1 = 0x07, + LarkHvc2 = 0x08, + LarkNesLeft = 0x09, + LarkNesRight = 0x0A, + Lucia = 0x0B, + Lagon = 0x0C, + Lager = 0x0D, }; enum class PadAxes { @@ -99,14 +103,6 @@ enum class OutputReport : u8 { USB_CMD = 0x80, }; -enum class InputReport : u8 { - SUBCMD_REPLY = 0x21, - STANDARD_FULL_60HZ = 0x30, - NFC_IR_MODE_60HZ = 0x31, - SIMPLE_HID_MODE = 0x3F, - INPUT_USB_RESPONSE = 0x81, -}; - enum class FeatureReport : u8 { Last_SUBCMD = 0x02, OTA_GW_UPGRADE = 0x70, @@ -143,9 +139,10 @@ enum class SubCommand : u8 { ENABLE_VIBRATION = 0x48, GET_REGULATED_VOLTAGE = 0x50, SET_EXTERNAL_CONFIG = 0x58, - UNKNOWN_RINGCON = 0x59, - UNKNOWN_RINGCON2 = 0x5A, - UNKNOWN_RINGCON3 = 0x5C, + GET_EXTERNAL_DEVICE_INFO = 0x59, + ENABLE_EXTERNAL_POLLING = 0x5A, + DISABLE_EXTERNAL_POLLING = 0x5B, + SET_EXTERNAL_FORMAT_CONFIG = 0x5C, }; enum class UsbSubCommand : u8 { @@ -164,20 +161,26 @@ enum class CalibrationMagic : u8 { USR_MAGIC_1 = 0xA1, }; -enum class SpiAddress { - SERIAL_NUMBER = 0X6000, - DEVICE_TYPE = 0X6012, - COLOR_EXIST = 0X601B, - FACT_LEFT_DATA = 0X603d, - FACT_RIGHT_DATA = 0X6046, - COLOR_DATA = 0X6050, - FACT_IMU_DATA = 0X6020, - USER_LEFT_MAGIC = 0X8010, - USER_LEFT_DATA = 0X8012, - USER_RIGHT_MAGIC = 0X801B, - USER_RIGHT_DATA = 0X801D, - USER_IMU_MAGIC = 0X8026, - USER_IMU_DATA = 0X8028, +enum class SpiAddress : u16 { + MAGIC = 0x0000, + MAC_ADDRESS = 0x0015, + PAIRING_INFO = 0x2000, + SHIPMENT = 0x5000, + SERIAL_NUMBER = 0x6000, + DEVICE_TYPE = 0x6012, + FORMAT_VERSION = 0x601B, + FACT_IMU_DATA = 0x6020, + FACT_LEFT_DATA = 0x603d, + FACT_RIGHT_DATA = 0x6046, + COLOR_DATA = 0x6050, + DESIGN_VARIATION = 0x605C, + SENSOR_DATA = 0x6080, + USER_LEFT_MAGIC = 0x8010, + USER_LEFT_DATA = 0x8012, + USER_RIGHT_MAGIC = 0x801B, + USER_RIGHT_DATA = 0x801D, + USER_IMU_MAGIC = 0x8026, + USER_IMU_DATA = 0x8028, }; enum class ReportMode : u8 { @@ -185,10 +188,12 @@ enum class ReportMode : u8 { ACTIVE_POLLING_NFC_IR_CAMERA_CONFIGURATION = 0x01, ACTIVE_POLLING_NFC_IR_CAMERA_DATA_CONFIGURATION = 0x02, ACTIVE_POLLING_IR_CAMERA_DATA = 0x03, + SUBCMD_REPLY = 0x21, MCU_UPDATE_STATE = 0x23, STANDARD_FULL_60HZ = 0x30, NFC_IR_MODE_60HZ = 0x31, SIMPLE_HID_MODE = 0x3F, + INPUT_USB_RESPONSE = 0x81, }; enum class GyroSensitivity : u8 { @@ -359,10 +364,16 @@ enum class IrRegistersAddress : u16 { DenoiseColor = 0x6901, }; +enum class ExternalDeviceId : u16 { + RingController = 0x2000, + Starlink = 0x2800, +}; + enum class DriverResult { Success, WrongReply, Timeout, + InvalidParameters, UnsupportedControllerType, HandleInUse, ErrorReadingData, @@ -485,7 +496,7 @@ static_assert(sizeof(MCUConfig) == 0x26, "MCUConfig is an invalid size"); #pragma pack(push, 1) struct InputReportPassive { - InputReport report_mode; + ReportMode report_mode; u16 button_input; u8 stick_state; std::array<u8, 10> unknown_data; @@ -493,7 +504,7 @@ struct InputReportPassive { static_assert(sizeof(InputReportPassive) == 0xE, "InputReportPassive is an invalid size"); struct InputReportActive { - InputReport report_mode; + ReportMode report_mode; u8 packet_id; Battery battery_status; std::array<u8, 3> button_input; @@ -507,7 +518,7 @@ struct InputReportActive { static_assert(sizeof(InputReportActive) == 0x29, "InputReportActive is an invalid size"); struct InputReportNfcIr { - InputReport report_mode; + ReportMode report_mode; u8 packet_id; Battery battery_status; std::array<u8, 3> button_input; @@ -605,9 +616,11 @@ static_assert(sizeof(FirmwareVersion) == 0x2, "FirmwareVersion is an invalid siz struct DeviceInfo { FirmwareVersion firmware; + std::array<u8, 2> unknown_1; MacAddress mac_address; + std::array<u8, 2> unknown_2; }; -static_assert(sizeof(DeviceInfo) == 0x8, "DeviceInfo is an invalid size"); +static_assert(sizeof(DeviceInfo) == 0xC, "DeviceInfo is an invalid size"); struct MotionStatus { bool is_enabled; @@ -623,6 +636,53 @@ struct RingStatus { s16 min_value; }; +struct VibrationPacket { + OutputReport output_report; + u8 packet_counter; + std::array<u8, 0x8> vibration_data; +}; +static_assert(sizeof(VibrationPacket) == 0xA, "VibrationPacket is an invalid size"); + +struct SubCommandPacket { + OutputReport output_report; + u8 packet_counter; + INSERT_PADDING_BYTES(0x8); // This contains vibration data + SubCommand sub_command; + std::array<u8, 0x26> command_data; +}; +static_assert(sizeof(SubCommandPacket) == 0x31, "SubCommandPacket is an invalid size"); + +#pragma pack(push, 1) +struct ReadSpiPacket { + SpiAddress spi_address; + INSERT_PADDING_BYTES(0x2); + u8 size; +}; +static_assert(sizeof(ReadSpiPacket) == 0x5, "ReadSpiPacket is an invalid size"); + +struct SubCommandResponse { + InputReportPassive input_report; + SubCommand sub_command; + union { + std::array<u8, 0x30> command_data; + SpiAddress spi_address; // Reply from SPI_FLASH_READ subcommand + ExternalDeviceId external_device_id; // Reply from GET_EXTERNAL_DEVICE_INFO subcommand + DeviceInfo device_info; // Reply from REQ_DEV_INFO subcommand + }; + u8 crc; // This is never used +}; +static_assert(sizeof(SubCommandResponse) == 0x40, "SubCommandResponse is an invalid size"); +#pragma pack(pop) + +struct MCUCommandResponse { + InputReportNfcIr input_report; + INSERT_PADDING_BYTES(0x8); + MCUReport mcu_report; + std::array<u8, 0x13D> mcu_data; + u8 crc; +}; +static_assert(sizeof(MCUCommandResponse) == 0x170, "MCUCommandResponse is an invalid size"); + struct JoyconCallbacks { std::function<void(Battery)> on_battery_data; std::function<void(Color)> on_color_data; diff --git a/src/input_common/helpers/joycon_protocol/nfc.cpp b/src/input_common/helpers/joycon_protocol/nfc.cpp index 5c0f71722..eeba82986 100644 --- a/src/input_common/helpers/joycon_protocol/nfc.cpp +++ b/src/input_common/helpers/joycon_protocol/nfc.cpp @@ -110,7 +110,7 @@ bool NfcProtocol::HasAmiibo() { DriverResult NfcProtocol::WaitUntilNfcIsReady() { constexpr std::size_t timeout_limit = 10; - std::vector<u8> output; + MCUCommandResponse output{}; std::size_t tries = 0; do { @@ -122,8 +122,9 @@ DriverResult NfcProtocol::WaitUntilNfcIsReady() { if (tries++ > timeout_limit) { return DriverResult::Timeout; } - } while (output[49] != 0x2a || (output[51] << 8) + output[50] != 0x0500 || output[55] != 0x31 || - output[56] != 0x00); + } while (output.mcu_report != MCUReport::NFCState || + (output.mcu_data[1] << 8) + output.mcu_data[0] != 0x0500 || + output.mcu_data[5] != 0x31 || output.mcu_data[6] != 0x00); return DriverResult::Success; } @@ -131,7 +132,7 @@ DriverResult NfcProtocol::WaitUntilNfcIsReady() { DriverResult NfcProtocol::StartPolling(TagFoundData& data) { LOG_DEBUG(Input, "Start Polling for tag"); constexpr std::size_t timeout_limit = 7; - std::vector<u8> output; + MCUCommandResponse output{}; std::size_t tries = 0; do { @@ -142,18 +143,20 @@ DriverResult NfcProtocol::StartPolling(TagFoundData& data) { if (tries++ > timeout_limit) { return DriverResult::Timeout; } - } while (output[49] != 0x2a || (output[51] << 8) + output[50] != 0x0500 || output[56] != 0x09); + } while (output.mcu_report != MCUReport::NFCState || + (output.mcu_data[1] << 8) + output.mcu_data[0] != 0x0500 || + output.mcu_data[6] != 0x09); - data.type = output[62]; - data.uuid.resize(output[64]); - memcpy(data.uuid.data(), output.data() + 65, data.uuid.size()); + data.type = output.mcu_data[12]; + data.uuid.resize(output.mcu_data[14]); + memcpy(data.uuid.data(), output.mcu_data.data() + 15, data.uuid.size()); return DriverResult::Success; } DriverResult NfcProtocol::ReadTag(const TagFoundData& data) { constexpr std::size_t timeout_limit = 10; - std::vector<u8> output; + MCUCommandResponse output{}; std::size_t tries = 0; std::string uuid_string; @@ -168,23 +171,24 @@ DriverResult NfcProtocol::ReadTag(const TagFoundData& data) { // Read Tag data while (true) { auto result = SendReadAmiiboRequest(output, ntag_pages); - const auto mcu_report = static_cast<MCUReport>(output[49]); - const auto nfc_status = static_cast<NFCStatus>(output[56]); + const auto nfc_status = static_cast<NFCStatus>(output.mcu_data[6]); if (result != DriverResult::Success) { return result; } - if ((mcu_report == MCUReport::NFCReadData || mcu_report == MCUReport::NFCState) && + if ((output.mcu_report == MCUReport::NFCReadData || + output.mcu_report == MCUReport::NFCState) && nfc_status == NFCStatus::TagLost) { return DriverResult::ErrorReadingData; } - if (mcu_report == MCUReport::NFCReadData && output[51] == 0x07 && output[52] == 0x01) { + if (output.mcu_report == MCUReport::NFCReadData && output.mcu_data[1] == 0x07 && + output.mcu_data[2] == 0x01) { if (data.type != 2) { continue; } - switch (output[74]) { + switch (output.mcu_data[24]) { case 0: ntag_pages = NFCPages::Block135; break; @@ -200,14 +204,14 @@ DriverResult NfcProtocol::ReadTag(const TagFoundData& data) { continue; } - if (mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::LastPackage) { + if (output.mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::LastPackage) { // finished SendStopPollingRequest(output); return DriverResult::Success; } // Ignore other state reports - if (mcu_report == MCUReport::NFCState) { + if (output.mcu_report == MCUReport::NFCState) { continue; } @@ -221,7 +225,7 @@ DriverResult NfcProtocol::ReadTag(const TagFoundData& data) { DriverResult NfcProtocol::GetAmiiboData(std::vector<u8>& ntag_data) { constexpr std::size_t timeout_limit = 10; - std::vector<u8> output; + MCUCommandResponse output{}; std::size_t tries = 0; NFCPages ntag_pages = NFCPages::Block135; @@ -229,36 +233,38 @@ DriverResult NfcProtocol::GetAmiiboData(std::vector<u8>& ntag_data) { // Read Tag data while (true) { auto result = SendReadAmiiboRequest(output, ntag_pages); - const auto mcu_report = static_cast<MCUReport>(output[49]); - const auto nfc_status = static_cast<NFCStatus>(output[56]); + const auto nfc_status = static_cast<NFCStatus>(output.mcu_data[6]); if (result != DriverResult::Success) { return result; } - if ((mcu_report == MCUReport::NFCReadData || mcu_report == MCUReport::NFCState) && + if ((output.mcu_report == MCUReport::NFCReadData || + output.mcu_report == MCUReport::NFCState) && nfc_status == NFCStatus::TagLost) { return DriverResult::ErrorReadingData; } - if (mcu_report == MCUReport::NFCReadData && output[51] == 0x07) { - std::size_t payload_size = (output[54] << 8 | output[55]) & 0x7FF; - if (output[52] == 0x01) { - memcpy(ntag_data.data() + ntag_buffer_pos, output.data() + 116, payload_size - 60); + if (output.mcu_report == MCUReport::NFCReadData && output.mcu_data[1] == 0x07) { + std::size_t payload_size = (output.mcu_data[4] << 8 | output.mcu_data[5]) & 0x7FF; + if (output.mcu_data[2] == 0x01) { + memcpy(ntag_data.data() + ntag_buffer_pos, output.mcu_data.data() + 66, + payload_size - 60); ntag_buffer_pos += payload_size - 60; } else { - memcpy(ntag_data.data() + ntag_buffer_pos, output.data() + 56, payload_size); + memcpy(ntag_data.data() + ntag_buffer_pos, output.mcu_data.data() + 6, + payload_size); } continue; } - if (mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::LastPackage) { + if (output.mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::LastPackage) { LOG_INFO(Input, "Finished reading amiibo"); return DriverResult::Success; } // Ignore other state reports - if (mcu_report == MCUReport::NFCState) { + if (output.mcu_report == MCUReport::NFCState) { continue; } @@ -270,7 +276,7 @@ DriverResult NfcProtocol::GetAmiiboData(std::vector<u8>& ntag_data) { return DriverResult::Success; } -DriverResult NfcProtocol::SendStartPollingRequest(std::vector<u8>& output) { +DriverResult NfcProtocol::SendStartPollingRequest(MCUCommandResponse& output) { NFCRequestState request{ .sub_command = MCUSubCommand::ReadDeviceMode, .command_argument = NFCReadCommand::StartPolling, @@ -294,7 +300,7 @@ DriverResult NfcProtocol::SendStartPollingRequest(std::vector<u8>& output) { return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output); } -DriverResult NfcProtocol::SendStopPollingRequest(std::vector<u8>& output) { +DriverResult NfcProtocol::SendStopPollingRequest(MCUCommandResponse& output) { NFCRequestState request{ .sub_command = MCUSubCommand::ReadDeviceMode, .command_argument = NFCReadCommand::StopPolling, @@ -311,7 +317,7 @@ DriverResult NfcProtocol::SendStopPollingRequest(std::vector<u8>& output) { return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output); } -DriverResult NfcProtocol::SendStartWaitingRecieveRequest(std::vector<u8>& output) { +DriverResult NfcProtocol::SendStartWaitingRecieveRequest(MCUCommandResponse& output) { NFCRequestState request{ .sub_command = MCUSubCommand::ReadDeviceMode, .command_argument = NFCReadCommand::StartWaitingRecieve, @@ -328,7 +334,7 @@ DriverResult NfcProtocol::SendStartWaitingRecieveRequest(std::vector<u8>& output return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output); } -DriverResult NfcProtocol::SendReadAmiiboRequest(std::vector<u8>& output, NFCPages ntag_pages) { +DriverResult NfcProtocol::SendReadAmiiboRequest(MCUCommandResponse& output, NFCPages ntag_pages) { NFCRequestState request{ .sub_command = MCUSubCommand::ReadDeviceMode, .command_argument = NFCReadCommand::Ntag, diff --git a/src/input_common/helpers/joycon_protocol/nfc.h b/src/input_common/helpers/joycon_protocol/nfc.h index e63665aa9..11e263e07 100644 --- a/src/input_common/helpers/joycon_protocol/nfc.h +++ b/src/input_common/helpers/joycon_protocol/nfc.h @@ -45,13 +45,13 @@ private: DriverResult GetAmiiboData(std::vector<u8>& data); - DriverResult SendStartPollingRequest(std::vector<u8>& output); + DriverResult SendStartPollingRequest(MCUCommandResponse& output); - DriverResult SendStopPollingRequest(std::vector<u8>& output); + DriverResult SendStopPollingRequest(MCUCommandResponse& output); - DriverResult SendStartWaitingRecieveRequest(std::vector<u8>& output); + DriverResult SendStartWaitingRecieveRequest(MCUCommandResponse& output); - DriverResult SendReadAmiiboRequest(std::vector<u8>& output, NFCPages ntag_pages); + DriverResult SendReadAmiiboRequest(MCUCommandResponse& output, NFCPages ntag_pages); NFCReadBlockCommand GetReadBlockCommand(NFCPages pages) const; diff --git a/src/input_common/helpers/joycon_protocol/poller.cpp b/src/input_common/helpers/joycon_protocol/poller.cpp index 7f8e093fa..9bb15e935 100644 --- a/src/input_common/helpers/joycon_protocol/poller.cpp +++ b/src/input_common/helpers/joycon_protocol/poller.cpp @@ -31,9 +31,7 @@ void JoyconPoller::ReadActiveMode(std::span<u8> buffer, const MotionStatus& moti case Joycon::ControllerType::Pro: UpdateActiveProPadInput(data, motion_status); break; - case Joycon::ControllerType::Grip: - case Joycon::ControllerType::Dual: - case Joycon::ControllerType::None: + default: break; } @@ -58,9 +56,7 @@ void JoyconPoller::ReadPassiveMode(std::span<u8> buffer) { case Joycon::ControllerType::Pro: UpdatePasiveProPadInput(data); break; - case Joycon::ControllerType::Grip: - case Joycon::ControllerType::Dual: - case Joycon::ControllerType::None: + default: break; } } diff --git a/src/input_common/helpers/joycon_protocol/ringcon.cpp b/src/input_common/helpers/joycon_protocol/ringcon.cpp index 12f81309e..190cef812 100644 --- a/src/input_common/helpers/joycon_protocol/ringcon.cpp +++ b/src/input_common/helpers/joycon_protocol/ringcon.cpp @@ -70,14 +70,12 @@ DriverResult RingConProtocol::StartRingconPolling() { DriverResult RingConProtocol::IsRingConnected(bool& is_connected) { LOG_DEBUG(Input, "IsRingConnected"); constexpr std::size_t max_tries = 28; - constexpr u8 ring_controller_id = 0x20; - std::vector<u8> output; + SubCommandResponse output{}; std::size_t tries = 0; is_connected = false; do { - std::array<u8, 1> empty_data{}; - const auto result = SendSubCommand(SubCommand::UNKNOWN_RINGCON, empty_data, output); + const auto result = SendSubCommand(SubCommand::GET_EXTERNAL_DEVICE_INFO, {}, output); if (result != DriverResult::Success) { return result; @@ -86,7 +84,7 @@ DriverResult RingConProtocol::IsRingConnected(bool& is_connected) { if (tries++ >= max_tries) { return DriverResult::NoDeviceDetected; } - } while (output[16] != ring_controller_id); + } while (output.external_device_id != ExternalDeviceId::RingController); is_connected = true; return DriverResult::Success; @@ -100,14 +98,14 @@ DriverResult RingConProtocol::ConfigureRing() { 0x00, 0x00, 0x00, 0x0A, 0x64, 0x0B, 0xE6, 0xA9, 0x22, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0xA8, 0xE1, 0x34, 0x36}; - const DriverResult result = SendSubCommand(SubCommand::UNKNOWN_RINGCON3, ring_config); + const DriverResult result = SendSubCommand(SubCommand::SET_EXTERNAL_FORMAT_CONFIG, ring_config); if (result != DriverResult::Success) { return result; } static constexpr std::array<u8, 4> ringcon_data{0x04, 0x01, 0x01, 0x02}; - return SendSubCommand(SubCommand::UNKNOWN_RINGCON2, ringcon_data); + return SendSubCommand(SubCommand::ENABLE_EXTERNAL_POLLING, ringcon_data); } bool RingConProtocol::IsEnabled() const { diff --git a/src/input_common/input_poller.cpp b/src/input_common/input_poller.cpp index 15cbf7e5f..8c6a6521a 100644 --- 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<Common::Input::InputDevice> 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<InputFromButton>(identifier, keyboard_key, toggle, inverted, + return std::make_unique<InputFromButton>(identifier, keyboard_key, turbo, toggle, inverted, input_engine.get()); } - return std::make_unique<InputFromButton>(identifier, button_id, toggle, inverted, + return std::make_unique<InputFromButton>(identifier, button_id, turbo, toggle, inverted, input_engine.get()); } @@ -876,11 +881,12 @@ std::unique_ptr<Common::Input::InputDevice> 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<InputFromHatButton>(identifier, button_id, direction, toggle, inverted, - input_engine.get()); + return std::make_unique<InputFromHatButton>(identifier, button_id, direction, turbo, toggle, + inverted, input_engine.get()); } std::unique_ptr<Common::Input::InputDevice> 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 b7bc11416..85ee27333 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp @@ -59,6 +59,13 @@ std::string Image(EmitContext& ctx, IR::TextureInstInfo info, } } +bool IsTextureMsaa(EmitContext& ctx, const IR::TextureInstInfo& info) { + if (info.type == TextureType::Buffer) { + return false; + } + return ctx.info.texture_descriptors.at(info.descriptor_index).is_multisample; +} + std::string_view TextureType(IR::TextureInstInfo info, bool is_ms = false) { if (info.is_depth) { switch (info.type) { @@ -535,7 +542,8 @@ void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& ScalarS32 lod, [[maybe_unused]] const IR::Value& skip_mips) { const auto info{inst.Flags<IR::TextureInstInfo>()}; const std::string texture{Texture(ctx, info, index)}; - const std::string_view type{TextureType(info)}; + const bool is_msaa{IsTextureMsaa(ctx, info)}; + const std::string_view type{TextureType(info, is_msaa)}; ctx.Add("TXQ {},{},{},{};", inst, lod, texture, type); } diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp index 4be2c25ec..f335c8af0 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp @@ -25,6 +25,13 @@ std::string Image(EmitContext& ctx, const IR::TextureInstInfo& info, const IR::V return fmt::format("img{}{}", def.binding, index_offset); } +bool IsTextureMsaa(EmitContext& ctx, const IR::TextureInstInfo& info) { + if (info.type == TextureType::Buffer) { + return false; + } + return ctx.info.texture_descriptors.at(info.descriptor_index).is_multisample; +} + std::string CastToIntVec(std::string_view value, const IR::TextureInstInfo& info) { switch (info.type) { case TextureType::Color1D: @@ -463,26 +470,33 @@ void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& std::string_view lod, const IR::Value& skip_mips_val) { const auto info{inst.Flags<IR::TextureInstInfo>()}; const auto texture{Texture(ctx, info, index)}; + const bool is_msaa{IsTextureMsaa(ctx, info)}; const bool skip_mips{skip_mips_val.U1()}; - const auto mips{ - [&] { return skip_mips ? "0u" : fmt::format("uint(textureQueryLevels({}))", texture); }}; + const auto mips{skip_mips ? "0u" : fmt::format("uint(textureQueryLevels({}))", texture)}; + if (is_msaa && !skip_mips) { + throw NotImplementedException("EmitImageQueryDimensions MSAA QueryLevels"); + } + if (info.type == TextureType::Buffer && !skip_mips) { + throw NotImplementedException("EmitImageQueryDimensions TextureType::Buffer QueryLevels"); + } + const bool uses_lod{!is_msaa && info.type != TextureType::Buffer}; + const auto lod_str{uses_lod ? fmt::format(",int({})", lod) : ""}; switch (info.type) { case TextureType::Color1D: - return ctx.AddU32x4("{}=uvec4(uint(textureSize({},int({}))),0u,0u,{});", inst, texture, lod, - mips()); + return ctx.AddU32x4("{}=uvec4(uint(textureSize({}{})),0u,0u,{});", inst, texture, lod_str, + mips); case TextureType::ColorArray1D: case TextureType::Color2D: case TextureType::ColorCube: case TextureType::Color2DRect: - return ctx.AddU32x4("{}=uvec4(uvec2(textureSize({},int({}))),0u,{});", inst, texture, lod, - mips()); + return ctx.AddU32x4("{}=uvec4(uvec2(textureSize({}{})),0u,{});", inst, texture, lod_str, + mips); case TextureType::ColorArray2D: case TextureType::Color3D: case TextureType::ColorArrayCube: - return ctx.AddU32x4("{}=uvec4(uvec3(textureSize({},int({}))),{});", inst, texture, lod, - mips()); + return ctx.AddU32x4("{}=uvec4(uvec3(textureSize({}{})),{});", inst, texture, lod_str, mips); case TextureType::Buffer: - throw NotImplementedException("EmitImageQueryDimensions Texture buffers"); + return ctx.AddU32x4("{}=uvec4(uint(textureSize({})),0u,0u,{});", inst, texture, mips); } throw LogicError("Unspecified image type {}", info.type.Value()); } diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp index 3b969d915..02073c420 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp @@ -201,6 +201,13 @@ Id Image(EmitContext& ctx, const IR::Value& index, IR::TextureInstInfo info) { } } +bool IsTextureMsaa(EmitContext& ctx, const IR::TextureInstInfo& info) { + if (info.type == TextureType::Buffer) { + return false; + } + return ctx.textures.at(info.descriptor_index).is_multisample; +} + Id Decorate(EmitContext& ctx, IR::Inst* inst, Id sample) { const auto info{inst->Flags<IR::TextureInstInfo>()}; if (info.relaxed_precision != 0) { @@ -452,24 +459,26 @@ Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& i const Id zero{ctx.u32_zero_value}; const bool skip_mips{skip_mips_val.U1()}; const auto mips{[&] { return skip_mips ? zero : ctx.OpImageQueryLevels(ctx.U32[1], image); }}; + const bool is_msaa{IsTextureMsaa(ctx, info)}; + const bool uses_lod{!is_msaa && info.type != TextureType::Buffer}; + const auto query{[&](Id type) { + return uses_lod ? ctx.OpImageQuerySizeLod(type, image, lod) + : ctx.OpImageQuerySize(type, image); + }}; switch (info.type) { case TextureType::Color1D: - return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[1], image, lod), - zero, zero, mips()); + return ctx.OpCompositeConstruct(ctx.U32[4], query(ctx.U32[1]), zero, zero, mips()); case TextureType::ColorArray1D: case TextureType::Color2D: case TextureType::ColorCube: case TextureType::Color2DRect: - return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[2], image, lod), - zero, mips()); + return ctx.OpCompositeConstruct(ctx.U32[4], query(ctx.U32[2]), zero, mips()); case TextureType::ColorArray2D: case TextureType::Color3D: case TextureType::ColorArrayCube: - return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[3], image, lod), - mips()); + return ctx.OpCompositeConstruct(ctx.U32[4], query(ctx.U32[3]), mips()); case TextureType::Buffer: - return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySize(ctx.U32[1], image), zero, - zero, mips()); + return ctx.OpCompositeConstruct(ctx.U32[4], query(ctx.U32[1]), zero, zero, mips()); } throw LogicError("Unspecified image type {}", info.type.Value()); } diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index 3b97721e1..d48d4860e 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp @@ -1288,6 +1288,7 @@ void EmitContext::DefineTextures(const Info& info, u32& binding, u32& scaling_in .pointer_type = pointer_type, .image_type = image_type, .count = desc.count, + .is_multisample = desc.is_multisample, }); if (profile.supported_spirv >= 0x00010400) { interfaces.push_back(id); diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.h b/src/shader_recompiler/backend/spirv/spirv_emit_context.h index dbc5c55b9..768a4fbb5 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.h +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.h @@ -35,6 +35,7 @@ struct TextureDefinition { Id pointer_type; Id image_type; u32 count; + bool is_multisample; }; struct TextureBufferDefinition { diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h index df158c928..f3c81dbe1 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.h +++ b/src/shader_recompiler/frontend/ir/ir_emitter.h @@ -409,7 +409,8 @@ private: } template <typename T> - requires(sizeof(T) <= sizeof(u32) && std::is_trivially_copyable_v<T>) struct Flags { + requires(sizeof(T) <= sizeof(u32) && std::is_trivially_copyable_v<T>) + struct Flags { Flags() = default; Flags(T proxy_) : proxy{proxy_} {} diff --git a/src/shader_recompiler/frontend/ir/value.h b/src/shader_recompiler/frontend/ir/value.h index 883dfa24e..22e89dd1b 100644 --- a/src/shader_recompiler/frontend/ir/value.h +++ b/src/shader_recompiler/frontend/ir/value.h @@ -101,9 +101,8 @@ public: TypedValue() = default; template <IR::Type other_type> - requires((other_type & type_) != IR::Type::Void) explicit(false) - TypedValue(const TypedValue<other_type>& value) - : Value(value) {} + requires((other_type & type_) != IR::Type::Void) + explicit(false) TypedValue(const TypedValue<other_type>& value) : Value(value) {} explicit TypedValue(const Value& value) : Value(value) { if ((value.Type() & type_) == IR::Type::Void) { @@ -194,16 +193,16 @@ public: void ReplaceOpcode(IR::Opcode opcode); template <typename FlagsType> - requires(sizeof(FlagsType) <= sizeof(u32) && std::is_trivially_copyable_v<FlagsType>) - [[nodiscard]] FlagsType Flags() const noexcept { + requires(sizeof(FlagsType) <= sizeof(u32) && std::is_trivially_copyable_v<FlagsType>) + [[nodiscard]] FlagsType Flags() const noexcept { FlagsType ret; std::memcpy(reinterpret_cast<char*>(&ret), &flags, sizeof(ret)); return ret; } template <typename FlagsType> - requires(sizeof(FlagsType) <= sizeof(u32) && - std::is_trivially_copyable_v<FlagsType>) void SetFlags(FlagsType value) noexcept { + requires(sizeof(FlagsType) <= sizeof(u32) && std::is_trivially_copyable_v<FlagsType>) + void SetFlags(FlagsType value) noexcept { std::memcpy(&flags, &value, sizeof(value)); } diff --git a/src/shader_recompiler/object_pool.h b/src/shader_recompiler/object_pool.h index 2b42c4ba2..5d648b159 100644 --- a/src/shader_recompiler/object_pool.h +++ b/src/shader_recompiler/object_pool.h @@ -10,7 +10,7 @@ namespace Shader { template <typename T> -requires std::is_destructible_v<T> + requires std::is_destructible_v<T> class ObjectPool { public: explicit ObjectPool(size_t chunk_size = 8192) : new_chunk_size{chunk_size} { @@ -18,7 +18,7 @@ public: } template <typename... Args> - requires std::is_constructible_v<T, Args...> + requires std::is_constructible_v<T, Args...> [[nodiscard]] T* Create(Args&&... args) { return std::construct_at(Memory(), std::forward<Args>(args)...); } diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt index dad7b07d4..52cd5bb81 100644 --- 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/host_shaders/vulkan_color_clear.frag b/src/video_core/host_shaders/vulkan_color_clear.frag new file mode 100644 index 000000000..617bf01e1 --- /dev/null +++ b/src/video_core/host_shaders/vulkan_color_clear.frag @@ -0,0 +1,14 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#version 460 core + +layout (push_constant) uniform PushConstants { + vec4 clear_color; +}; + +layout(location = 0) out vec4 color; + +void main() { + color = clear_color; +} diff --git a/src/video_core/host_shaders/vulkan_color_clear.vert b/src/video_core/host_shaders/vulkan_color_clear.vert new file mode 100644 index 000000000..d85883141 --- /dev/null +++ b/src/video_core/host_shaders/vulkan_color_clear.vert @@ -0,0 +1,10 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#version 460 core + +void main() { + float x = float((gl_VertexIndex & 1) << 2); + float y = float((gl_VertexIndex & 2) << 1); + gl_Position = vec4(x - 1.0, y - 1.0, 0.0, 1.0); +} diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp index dd00d3edf..cf2964a3f 100644 --- 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<u32>(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 <VkShaderStageFlags stageFlags, size_t size> +inline constexpr VkPushConstantRange PUSH_CONSTANT_RANGE{ + .stageFlags = stageFlags, .offset = 0, - .size = sizeof(PushConstants), + .size = static_cast<u32>(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<VkPushConstantRange> 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<float>(src_region.end.x - src_region.start.x) / static_cast<float>(src_size.width); const float scale_y = static_cast<float>(src_region.end.y - src_region.start.y) / @@ -335,8 +342,6 @@ void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout, const Regi static_cast<float>(src_region.start.y) / static_cast<float>(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<VK_SHADER_STAGE_VERTEX_BIT, sizeof(PushConstants)>))), + two_textures_pipeline_layout( + device.GetLogical().CreatePipelineLayout(PipelineLayoutCreateInfo( + two_textures_set_layout.address(), + PUSH_CONSTANT_RANGE<VK_SHADER_STAGE_VERTEX_BIT, sizeof(PushConstants)>))), + clear_color_pipeline_layout(device.GetLogical().CreatePipelineLayout(PipelineLayoutCreateInfo( + nullptr, PUSH_CONSTANT_RANGE<VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(float) * 4>))), 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<f32, 4>& 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<u32>(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 be8a9a2f6..2976a7d91 100644 --- 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<f32, 4>& 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<vk::Pipeline> blit_color_pipelines; std::vector<BlitImagePipelineKey> blit_depth_stencil_keys; std::vector<vk::Pipeline> blit_depth_stencil_pipelines; + std::vector<BlitImagePipelineKey> clear_color_keys; + std::vector<vk::Pipeline> 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 86ef0daeb..719edbcfb 100644 --- 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<u8>(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<s32>(clear_rect.rect.extent.width), + .y = clear_rect.rect.offset.y + + static_cast<s32>(clear_rect.rect.extent.height)}}; + blit_image.ClearColor(framebuffer, color_mask, regs.clear_color, dst_region); } } diff --git a/src/video_core/texture_cache/descriptor_table.h b/src/video_core/texture_cache/descriptor_table.h index ee4240288..1bad83fb4 100644 --- a/src/video_core/texture_cache/descriptor_table.h +++ b/src/video_core/texture_cache/descriptor_table.h @@ -19,9 +19,7 @@ public: explicit DescriptorTable(Tegra::MemoryManager& gpu_memory_) : gpu_memory{gpu_memory_} {} [[nodiscard]] bool Synchronize(GPUVAddr gpu_addr, u32 limit) { - [[likely]] if (current_gpu_addr == gpu_addr && current_limit == limit) { - return false; - } + [[likely]] if (current_gpu_addr == gpu_addr && current_limit == limit) { return false; } Refresh(gpu_addr, limit); return true; } diff --git a/src/video_core/texture_cache/slot_vector.h b/src/video_core/texture_cache/slot_vector.h index 1e2aad76a..9df6a2903 100644 --- a/src/video_core/texture_cache/slot_vector.h +++ b/src/video_core/texture_cache/slot_vector.h @@ -29,7 +29,7 @@ struct SlotId { }; template <class T> -requires std::is_nothrow_move_assignable_v<T> && std::is_nothrow_move_constructible_v<T> + requires std::is_nothrow_move_assignable_v<T> && std::is_nothrow_move_constructible_v<T> class SlotVector { public: class Iterator { diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index 4b7e3b01b..723690e71 100644 --- 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/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp index 68af6c20c..c287220fc 100644 --- a/src/yuzu/configuration/configure_input_player_widget.cpp +++ b/src/yuzu/configuration/configure_input_player_widget.cpp @@ -81,7 +81,6 @@ void PlayerControlPreview::UpdateColors() { colors.outline = QColor(0, 0, 0); colors.primary = QColor(225, 225, 225); colors.button = QColor(109, 111, 114); - colors.button2 = QColor(109, 111, 114); colors.button2 = QColor(77, 80, 84); colors.slider_arrow = QColor(65, 68, 73); colors.font2 = QColor(0, 0, 0); @@ -100,6 +99,7 @@ void PlayerControlPreview::UpdateColors() { colors.led_off = QColor(170, 238, 255); colors.indicator2 = QColor(59, 165, 93); colors.charging = QColor(250, 168, 26); + colors.button_turbo = QColor(217, 158, 4); colors.left = colors.primary; colors.right = colors.primary; @@ -2469,7 +2469,6 @@ void PlayerControlPreview::DrawJoystickDot(QPainter& p, const QPointF center, void PlayerControlPreview::DrawRoundButton(QPainter& p, QPointF center, const Common::Input::ButtonStatus& pressed, float width, float height, Direction direction, float radius) { - p.setBrush(button_color); if (pressed.value) { switch (direction) { case Direction::Left: @@ -2487,16 +2486,16 @@ void PlayerControlPreview::DrawRoundButton(QPainter& p, QPointF center, case Direction::None: break; } - p.setBrush(colors.highlight); } QRectF rect = {center.x() - width, center.y() - height, width * 2.0f, height * 2.0f}; + p.setBrush(GetButtonColor(button_color, pressed.value, pressed.turbo)); p.drawRoundedRect(rect, radius, radius); } void PlayerControlPreview::DrawMinusButton(QPainter& p, const QPointF center, const Common::Input::ButtonStatus& pressed, int button_size) { p.setPen(colors.outline); - p.setBrush(pressed.value ? colors.highlight : colors.button); + p.setBrush(GetButtonColor(colors.button, pressed.value, pressed.turbo)); DrawRectangle(p, center, button_size, button_size / 3.0f); } void PlayerControlPreview::DrawPlusButton(QPainter& p, const QPointF center, @@ -2504,7 +2503,7 @@ void PlayerControlPreview::DrawPlusButton(QPainter& p, const QPointF center, int button_size) { // Draw outer line p.setPen(colors.outline); - p.setBrush(pressed.value ? colors.highlight : colors.button); + p.setBrush(GetButtonColor(colors.button, pressed.value, pressed.turbo)); DrawRectangle(p, center, button_size, button_size / 3.0f); DrawRectangle(p, center, button_size / 3.0f, button_size); @@ -2526,7 +2525,7 @@ void PlayerControlPreview::DrawGCButtonX(QPainter& p, const QPointF center, } p.setPen(colors.outline); - p.setBrush(pressed.value ? colors.highlight : colors.button); + p.setBrush(GetButtonColor(colors.button, pressed.value, pressed.turbo)); DrawPolygon(p, button_x); } @@ -2539,7 +2538,7 @@ void PlayerControlPreview::DrawGCButtonY(QPainter& p, const QPointF center, } p.setPen(colors.outline); - p.setBrush(pressed.value ? colors.highlight : colors.button); + p.setBrush(GetButtonColor(colors.button, pressed.value, pressed.turbo)); DrawPolygon(p, button_x); } @@ -2553,17 +2552,15 @@ void PlayerControlPreview::DrawGCButtonZ(QPainter& p, const QPointF center, } p.setPen(colors.outline); - p.setBrush(pressed.value ? colors.highlight : colors.button2); + p.setBrush(GetButtonColor(colors.button2, pressed.value, pressed.turbo)); DrawPolygon(p, button_x); } void PlayerControlPreview::DrawCircleButton(QPainter& p, const QPointF center, const Common::Input::ButtonStatus& pressed, float button_size) { - p.setBrush(button_color); - if (pressed.value) { - p.setBrush(colors.highlight); - } + + p.setBrush(GetButtonColor(button_color, pressed.value, pressed.turbo)); p.drawEllipse(center, button_size, button_size); } @@ -2620,7 +2617,7 @@ void PlayerControlPreview::DrawArrowButton(QPainter& p, const QPointF center, // Draw arrow button p.setPen(pressed.value ? colors.highlight : colors.button); - p.setBrush(pressed.value ? colors.highlight : colors.button); + p.setBrush(GetButtonColor(colors.button, pressed.value, pressed.turbo)); DrawPolygon(p, arrow_button); switch (direction) { @@ -2672,10 +2669,20 @@ void PlayerControlPreview::DrawTriggerButton(QPainter& p, const QPointF center, // Draw arrow button p.setPen(colors.outline); - p.setBrush(pressed.value ? colors.highlight : colors.button); + p.setBrush(GetButtonColor(colors.button, pressed.value, pressed.turbo)); DrawPolygon(p, qtrigger_button); } +QColor PlayerControlPreview::GetButtonColor(QColor default_color, bool is_pressed, bool turbo) { + if (is_pressed && turbo) { + return colors.button_turbo; + } + if (is_pressed) { + return colors.highlight; + } + return default_color; +} + void PlayerControlPreview::DrawBattery(QPainter& p, QPointF center, Common::Input::BatteryLevel battery) { if (battery == Common::Input::BatteryLevel::None) { diff --git a/src/yuzu/configuration/configure_input_player_widget.h b/src/yuzu/configuration/configure_input_player_widget.h index b258c6d77..0e9e95e85 100644 --- a/src/yuzu/configuration/configure_input_player_widget.h +++ b/src/yuzu/configuration/configure_input_player_widget.h @@ -81,6 +81,7 @@ private: QColor right{}; QColor button{}; QColor button2{}; + QColor button_turbo{}; QColor font{}; QColor font2{}; QColor highlight{}; @@ -183,6 +184,7 @@ private: const Common::Input::ButtonStatus& pressed, float size = 1.0f); void DrawTriggerButton(QPainter& p, QPointF center, Direction direction, const Common::Input::ButtonStatus& pressed); + QColor GetButtonColor(QColor default_color, bool is_pressed, bool turbo); // Draw battery functions void DrawBattery(QPainter& p, QPointF center, Common::Input::BatteryLevel battery); |