diff options
| author | 2023-10-25 00:34:40 -0400 | |
|---|---|---|
| committer | 2023-10-25 13:05:56 -0400 | |
| commit | 723df0f3685f01ce5a0330d567932136a9de7a8f (patch) | |
| tree | 5b26229e14b70dba5d59d9265b750e5edff874b5 | |
| parent | nvdrv: fix up remaining copy calls (diff) | |
| download | yuzu-723df0f3685f01ce5a0330d567932136a9de7a8f.tar.gz yuzu-723df0f3685f01ce5a0330d567932136a9de7a8f.tar.xz yuzu-723df0f3685f01ce5a0330d567932136a9de7a8f.zip | |
nvdrv: rework to remove memcpy
16 files changed, 243 insertions, 225 deletions
diff --git a/src/core/hle/service/nvdrv/devices/ioctl_serialization.h b/src/core/hle/service/nvdrv/devices/ioctl_serialization.h index c560974f1..b12bcd138 100644 --- a/src/core/hle/service/nvdrv/devices/ioctl_serialization.h +++ b/src/core/hle/service/nvdrv/devices/ioctl_serialization.h | |||
| @@ -11,97 +11,149 @@ | |||
| 11 | 11 | ||
| 12 | namespace Service::Nvidia::Devices { | 12 | namespace Service::Nvidia::Devices { |
| 13 | 13 | ||
| 14 | struct Ioctl1Traits { | 14 | struct IoctlOneArgTraits { |
| 15 | template <typename T, typename R, typename A> | 15 | template <typename T, typename R, typename A, typename... B> |
| 16 | static T GetClassImpl(R (T::*)(A)); | 16 | static A GetFirstArgImpl(R (T::*)(A, B...)); |
| 17 | |||
| 18 | template <typename T, typename R, typename A> | ||
| 19 | static A GetArgImpl(R (T::*)(A)); | ||
| 20 | }; | 17 | }; |
| 21 | 18 | ||
| 22 | struct Ioctl23Traits { | 19 | struct IoctlTwoArgTraits { |
| 23 | template <typename T, typename R, typename A, typename B> | 20 | template <typename T, typename R, typename A, typename B, typename... C> |
| 24 | static T GetClassImpl(R (T::*)(A, B)); | 21 | static A GetFirstArgImpl(R (T::*)(A, B, C...)); |
| 25 | 22 | ||
| 26 | template <typename T, typename R, typename A, typename B> | 23 | template <typename T, typename R, typename A, typename B, typename... C> |
| 27 | static A GetArgImpl(R (T::*)(A, B)); | 24 | static B GetSecondArgImpl(R (T::*)(A, B, C...)); |
| 28 | }; | 25 | }; |
| 29 | 26 | ||
| 30 | template <typename T> | 27 | struct Null {}; |
| 31 | struct ContainerType { | ||
| 32 | using ValueType = T; | ||
| 33 | }; | ||
| 34 | 28 | ||
| 35 | template <Common::IsContiguousContainer T> | 29 | // clang-format off |
| 36 | struct ContainerType<T> { | ||
| 37 | using ValueType = T::value_type; | ||
| 38 | }; | ||
| 39 | 30 | ||
| 40 | template <typename InnerArg, typename F, typename Self, typename... Rest> | 31 | template <typename FixedArg, typename VarArg, typename InlInVarArg, typename InlOutVarArg, typename F> |
| 41 | NvResult Wrap(std::span<const u8> input, std::span<u8> output, Self* self, F&& callable, | 32 | NvResult WrapGeneric(F&& callable, std::span<const u8> input, std::span<const u8> inline_input, std::span<u8> output, std::span<u8> inline_output) { |
| 42 | Rest&&... rest) { | 33 | constexpr bool HasFixedArg = !std::is_same_v<FixedArg, Null>; |
| 43 | using Arg = ContainerType<InnerArg>::ValueType; | 34 | constexpr bool HasVarArg = !std::is_same_v<VarArg, Null>; |
| 44 | constexpr bool ArgumentIsContainer = Common::IsContiguousContainer<InnerArg>; | 35 | constexpr bool HasInlInVarArg = !std::is_same_v<InlInVarArg, Null>; |
| 45 | 36 | constexpr bool HasInlOutVarArg = !std::is_same_v<InlOutVarArg, Null>; | |
| 46 | // Verify that the input and output sizes are valid. | 37 | |
| 47 | const size_t in_params = input.size() / sizeof(Arg); | 38 | // Declare the fixed-size input value. |
| 48 | const size_t out_params = output.size() / sizeof(Arg); | 39 | FixedArg fixed{}; |
| 49 | if (in_params * sizeof(Arg) != input.size()) { | 40 | size_t var_offset = 0; |
| 50 | return NvResult::InvalidSize; | 41 | |
| 51 | } | 42 | if constexpr (HasFixedArg) { |
| 52 | if (out_params * sizeof(Arg) != output.size()) { | 43 | // Read the fixed-size input value. |
| 53 | return NvResult::InvalidSize; | 44 | var_offset = std::min(sizeof(FixedArg), input.size()); |
| 45 | if (var_offset > 0) { | ||
| 46 | std::memcpy(&fixed, input.data(), var_offset); | ||
| 47 | } | ||
| 54 | } | 48 | } |
| 55 | if (in_params == 0 && out_params == 0 && !ArgumentIsContainer) { | 49 | |
| 56 | return NvResult::InvalidSize; | 50 | // Read the variable-sized inputs. |
| 51 | const size_t num_var_args = HasVarArg ? ((input.size() - var_offset) / sizeof(VarArg)) : 0; | ||
| 52 | std::vector<VarArg> var_args(num_var_args); | ||
| 53 | if constexpr (HasVarArg) { | ||
| 54 | if (num_var_args > 0) { | ||
| 55 | std::memcpy(var_args.data(), input.data() + var_offset, num_var_args * sizeof(VarArg)); | ||
| 56 | } | ||
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | // Copy inputs, if needed. | 59 | const size_t num_inl_in_var_args = HasInlInVarArg ? (inline_input.size() / sizeof(InlInVarArg)) : 0; |
| 60 | std::vector<Arg> params(std::max(in_params, out_params)); | 60 | std::vector<InlInVarArg> inl_in_var_args(num_inl_in_var_args); |
| 61 | if (in_params > 0) { | 61 | if constexpr (HasInlInVarArg) { |
| 62 | std::memcpy(params.data(), input.data(), input.size()); | 62 | if (num_inl_in_var_args > 0) { |
| 63 | std::memcpy(inl_in_var_args.data(), inline_input.data(), num_inl_in_var_args * sizeof(InlInVarArg)); | ||
| 64 | } | ||
| 63 | } | 65 | } |
| 64 | 66 | ||
| 67 | // Construct inline output data. | ||
| 68 | const size_t num_inl_out_var_args = HasInlOutVarArg ? (inline_output.size() / sizeof(InlOutVarArg)) : 0; | ||
| 69 | std::vector<InlOutVarArg> inl_out_var_args(num_inl_out_var_args); | ||
| 70 | |||
| 65 | // Perform the call. | 71 | // Perform the call. |
| 66 | NvResult result; | 72 | NvResult result = callable(fixed, var_args, inl_in_var_args, inl_out_var_args); |
| 67 | if constexpr (ArgumentIsContainer) { | 73 | |
| 68 | result = (self->*callable)(params, std::forward<Rest>(rest)...); | 74 | // Copy outputs. |
| 69 | } else { | 75 | if constexpr (HasFixedArg) { |
| 70 | result = (self->*callable)(params.front(), std::forward<Rest>(rest)...); | 76 | if (output.size() > 0) { |
| 77 | std::memcpy(output.data(), &fixed, std::min(output.size(), sizeof(FixedArg))); | ||
| 78 | } | ||
| 71 | } | 79 | } |
| 72 | 80 | ||
| 73 | // Copy outputs, if needed. | 81 | if constexpr (HasVarArg) { |
| 74 | if (out_params > 0) { | 82 | if (num_var_args > 0 && output.size() > var_offset) { |
| 75 | std::memcpy(output.data(), params.data(), output.size()); | 83 | const size_t max_var_size = output.size() - var_offset; |
| 84 | std::memcpy(output.data() + var_offset, var_args.data(), std::min(max_var_size, num_var_args * sizeof(VarArg))); | ||
| 85 | } | ||
| 76 | } | 86 | } |
| 77 | 87 | ||
| 88 | // Copy inline outputs. | ||
| 89 | if constexpr (HasInlOutVarArg) { | ||
| 90 | if (num_inl_out_var_args > 0) { | ||
| 91 | std::memcpy(inline_output.data(), inl_out_var_args.data(), num_inl_out_var_args * sizeof(InlOutVarArg)); | ||
| 92 | } | ||
| 93 | } | ||
| 94 | |||
| 95 | // We're done. | ||
| 78 | return result; | 96 | return result; |
| 79 | } | 97 | } |
| 80 | 98 | ||
| 81 | template <typename F> | 99 | template <typename Self, typename F, typename... Rest> |
| 82 | NvResult nvdevice::Wrap1(F&& callable, std::span<const u8> input, std::span<u8> output) { | 100 | NvResult WrapFixed(Self* self, F&& callable, std::span<const u8> input, std::span<u8> output, Rest&&... rest) { |
| 83 | using Self = decltype(Ioctl1Traits::GetClassImpl(callable)); | 101 | using FixedArg = typename std::remove_reference_t<decltype(IoctlOneArgTraits::GetFirstArgImpl(callable))>; |
| 84 | using InnerArg = std::remove_reference_t<decltype(Ioctl1Traits::GetArgImpl(callable))>; | 102 | |
| 103 | const auto Callable = [&](auto& fixed, auto& var, auto& inl_in, auto& inl_out) -> NvResult { | ||
| 104 | return (self->*callable)(fixed, std::forward<Rest>(rest)...); | ||
| 105 | }; | ||
| 85 | 106 | ||
| 86 | return Wrap<InnerArg>(input, output, static_cast<Self*>(this), callable); | 107 | return WrapGeneric<FixedArg, Null, Null, Null>(std::move(Callable), input, {}, output, {}); |
| 87 | } | 108 | } |
| 88 | 109 | ||
| 89 | template <typename F> | 110 | template <typename Self, typename F, typename... Rest> |
| 90 | NvResult nvdevice::Wrap2(F&& callable, std::span<const u8> input, std::span<const u8> inline_input, | 111 | NvResult WrapFixedInlOut(Self* self, F&& callable, std::span<const u8> input, std::span<u8> output, std::span<u8> inline_output, Rest&&... rest) { |
| 91 | std::span<u8> output) { | 112 | using FixedArg = typename std::remove_reference_t<decltype(IoctlTwoArgTraits::GetFirstArgImpl(callable))>; |
| 92 | using Self = decltype(Ioctl23Traits::GetClassImpl(callable)); | 113 | using InlOutVarArg = typename std::remove_reference_t<decltype(IoctlTwoArgTraits::GetSecondArgImpl(callable))>::value_type; |
| 93 | using InnerArg = std::remove_reference_t<decltype(Ioctl23Traits::GetArgImpl(callable))>; | ||
| 94 | 114 | ||
| 95 | return Wrap<InnerArg>(input, output, static_cast<Self*>(this), callable, inline_input); | 115 | const auto Callable = [&](auto& fixed, auto& var, auto& inl_in, auto& inl_out) -> NvResult { |
| 116 | return (self->*callable)(fixed, inl_out, std::forward<Rest>(rest)...); | ||
| 117 | }; | ||
| 118 | |||
| 119 | return WrapGeneric<FixedArg, Null, Null, InlOutVarArg>(std::move(Callable), input, {}, output, inline_output); | ||
| 120 | } | ||
| 121 | |||
| 122 | template <typename Self, typename F, typename... Rest> | ||
| 123 | NvResult WrapVariable(Self* self, F&& callable, std::span<const u8> input, std::span<u8> output, Rest&&... rest) { | ||
| 124 | using VarArg = typename std::remove_reference_t<decltype(IoctlOneArgTraits::GetFirstArgImpl(callable))>::value_type; | ||
| 125 | |||
| 126 | const auto Callable = [&](auto& fixed, auto& var, auto& inl_in, auto& inl_out) -> NvResult { | ||
| 127 | return (self->*callable)(var, std::forward<Rest>(rest)...); | ||
| 128 | }; | ||
| 129 | |||
| 130 | return WrapGeneric<Null, VarArg, Null, Null>(std::move(Callable), input, {}, output, {}); | ||
| 96 | } | 131 | } |
| 97 | 132 | ||
| 98 | template <typename F> | 133 | template <typename Self, typename F, typename... Rest> |
| 99 | NvResult nvdevice::Wrap3(F&& callable, std::span<const u8> input, std::span<u8> output, | 134 | NvResult WrapFixedVariable(Self* self, F&& callable, std::span<const u8> input, std::span<u8> output, Rest&&... rest) { |
| 100 | std::span<u8> inline_output) { | 135 | using FixedArg = typename std::remove_reference_t<decltype(IoctlTwoArgTraits::GetFirstArgImpl(callable))>; |
| 101 | using Self = decltype(Ioctl23Traits::GetClassImpl(callable)); | 136 | using VarArg = typename std::remove_reference_t<decltype(IoctlTwoArgTraits::GetSecondArgImpl(callable))>::value_type; |
| 102 | using InnerArg = std::remove_reference_t<decltype(Ioctl23Traits::GetArgImpl(callable))>; | 137 | |
| 138 | const auto Callable = [&](auto& fixed, auto& var, auto& inl_in, auto& inl_out) -> NvResult { | ||
| 139 | return (self->*callable)(fixed, var, std::forward<Rest>(rest)...); | ||
| 140 | }; | ||
| 103 | 141 | ||
| 104 | return Wrap<InnerArg>(input, output, static_cast<Self*>(this), callable, inline_output); | 142 | return WrapGeneric<FixedArg, VarArg, Null, Null>(std::move(Callable), input, {}, output, {}); |
| 105 | } | 143 | } |
| 106 | 144 | ||
| 145 | template <typename Self, typename F, typename... Rest> | ||
| 146 | NvResult WrapFixedInlIn(Self* self, F&& callable, std::span<const u8> input, std::span<const u8> inline_input, std::span<u8> output, Rest&&... rest) { | ||
| 147 | using FixedArg = typename std::remove_reference_t<decltype(IoctlTwoArgTraits::GetFirstArgImpl(callable))>; | ||
| 148 | using InlInVarArg = typename std::remove_reference_t<decltype(IoctlTwoArgTraits::GetSecondArgImpl(callable))>::value_type; | ||
| 149 | |||
| 150 | const auto Callable = [&](auto& fixed, auto& var, auto& inl_in, auto& inl_out) -> NvResult { | ||
| 151 | return (self->*callable)(fixed, inl_in, std::forward<Rest>(rest)...); | ||
| 152 | }; | ||
| 153 | |||
| 154 | return WrapGeneric<FixedArg, Null, InlInVarArg, Null>(std::move(Callable), input, inline_input, output, {}); | ||
| 155 | } | ||
| 156 | |||
| 157 | // clang-format on | ||
| 158 | |||
| 107 | } // namespace Service::Nvidia::Devices | 159 | } // namespace Service::Nvidia::Devices |
diff --git a/src/core/hle/service/nvdrv/devices/nvdevice.h b/src/core/hle/service/nvdrv/devices/nvdevice.h index af766f320..a04538d5d 100644 --- a/src/core/hle/service/nvdrv/devices/nvdevice.h +++ b/src/core/hle/service/nvdrv/devices/nvdevice.h | |||
| @@ -75,18 +75,6 @@ public: | |||
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | protected: | 77 | protected: |
| 78 | template <typename F> | ||
| 79 | NvResult Wrap1(F&& callable, std::span<const u8> input, std::span<u8> output); | ||
| 80 | |||
| 81 | template <typename F> | ||
| 82 | NvResult Wrap2(F&& callable, std::span<const u8> input, std::span<const u8> inline_input, | ||
| 83 | std::span<u8> output); | ||
| 84 | |||
| 85 | template <typename F> | ||
| 86 | NvResult Wrap3(F&& callable, std::span<const u8> input, std::span<u8> output, | ||
| 87 | std::span<u8> inline_output); | ||
| 88 | |||
| 89 | protected: | ||
| 90 | Core::System& system; | 78 | Core::System& system; |
| 91 | }; | 79 | }; |
| 92 | 80 | ||
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 484001071..6b3639008 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp | |||
| @@ -34,21 +34,21 @@ NvResult nvhost_as_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> i | |||
| 34 | case 'A': | 34 | case 'A': |
| 35 | switch (command.cmd) { | 35 | switch (command.cmd) { |
| 36 | case 0x1: | 36 | case 0x1: |
| 37 | return Wrap1(&nvhost_as_gpu::BindChannel, input, output); | 37 | return WrapFixed(this, &nvhost_as_gpu::BindChannel, input, output); |
| 38 | case 0x2: | 38 | case 0x2: |
| 39 | return Wrap1(&nvhost_as_gpu::AllocateSpace, input, output); | 39 | return WrapFixed(this, &nvhost_as_gpu::AllocateSpace, input, output); |
| 40 | case 0x3: | 40 | case 0x3: |
| 41 | return Wrap1(&nvhost_as_gpu::FreeSpace, input, output); | 41 | return WrapFixed(this, &nvhost_as_gpu::FreeSpace, input, output); |
| 42 | case 0x5: | 42 | case 0x5: |
| 43 | return Wrap1(&nvhost_as_gpu::UnmapBuffer, input, output); | 43 | return WrapFixed(this, &nvhost_as_gpu::UnmapBuffer, input, output); |
| 44 | case 0x6: | 44 | case 0x6: |
| 45 | return Wrap1(&nvhost_as_gpu::MapBufferEx, input, output); | 45 | return WrapFixed(this, &nvhost_as_gpu::MapBufferEx, input, output); |
| 46 | case 0x8: | 46 | case 0x8: |
| 47 | return Wrap1(&nvhost_as_gpu::GetVARegions1, input, output); | 47 | return WrapFixed(this, &nvhost_as_gpu::GetVARegions1, input, output); |
| 48 | case 0x9: | 48 | case 0x9: |
| 49 | return Wrap1(&nvhost_as_gpu::AllocAsEx, input, output); | 49 | return WrapFixed(this, &nvhost_as_gpu::AllocAsEx, input, output); |
| 50 | case 0x14: | 50 | case 0x14: |
| 51 | return Wrap1(&nvhost_as_gpu::Remap, input, output); | 51 | return WrapVariable(this, &nvhost_as_gpu::Remap, input, output); |
| 52 | default: | 52 | default: |
| 53 | break; | 53 | break; |
| 54 | } | 54 | } |
| @@ -73,7 +73,8 @@ NvResult nvhost_as_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> i | |||
| 73 | case 'A': | 73 | case 'A': |
| 74 | switch (command.cmd) { | 74 | switch (command.cmd) { |
| 75 | case 0x8: | 75 | case 0x8: |
| 76 | return Wrap3(&nvhost_as_gpu::GetVARegions3, input, output, inline_output); | 76 | return WrapFixedInlOut(this, &nvhost_as_gpu::GetVARegions3, input, output, |
| 77 | inline_output); | ||
| 77 | default: | 78 | default: |
| 78 | break; | 79 | break; |
| 79 | } | 80 | } |
| @@ -482,7 +483,7 @@ NvResult nvhost_as_gpu::GetVARegions1(IoctlGetVaRegions& params) { | |||
| 482 | return NvResult::Success; | 483 | return NvResult::Success; |
| 483 | } | 484 | } |
| 484 | 485 | ||
| 485 | NvResult nvhost_as_gpu::GetVARegions3(IoctlGetVaRegions& params, std::span<u8> inline_output) { | 486 | NvResult nvhost_as_gpu::GetVARegions3(IoctlGetVaRegions& params, std::span<VaRegion> regions) { |
| 486 | LOG_DEBUG(Service_NVDRV, "called, buf_addr={:X}, buf_size={:X}", params.buf_addr, | 487 | LOG_DEBUG(Service_NVDRV, "called, buf_addr={:X}, buf_size={:X}", params.buf_addr, |
| 487 | params.buf_size); | 488 | params.buf_size); |
| 488 | 489 | ||
| @@ -494,7 +495,10 @@ NvResult nvhost_as_gpu::GetVARegions3(IoctlGetVaRegions& params, std::span<u8> i | |||
| 494 | 495 | ||
| 495 | GetVARegionsImpl(params); | 496 | GetVARegionsImpl(params); |
| 496 | 497 | ||
| 497 | std::memcpy(inline_output.data(), params.regions.data(), 2 * sizeof(VaRegion)); | 498 | const size_t num_regions = std::min(params.regions.size(), regions.size()); |
| 499 | for (size_t i = 0; i < num_regions; i++) { | ||
| 500 | regions[i] = params.regions[i]; | ||
| 501 | } | ||
| 498 | 502 | ||
| 499 | return NvResult::Success; | 503 | return NvResult::Success; |
| 500 | } | 504 | } |
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 bc041f215..932997e75 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h | |||
| @@ -149,7 +149,7 @@ private: | |||
| 149 | 149 | ||
| 150 | void GetVARegionsImpl(IoctlGetVaRegions& params); | 150 | void GetVARegionsImpl(IoctlGetVaRegions& params); |
| 151 | NvResult GetVARegions1(IoctlGetVaRegions& params); | 151 | NvResult GetVARegions1(IoctlGetVaRegions& params); |
| 152 | NvResult GetVARegions3(IoctlGetVaRegions& params, std::span<u8> inline_output); | 152 | NvResult GetVARegions3(IoctlGetVaRegions& params, std::span<VaRegion> regions); |
| 153 | 153 | ||
| 154 | void FreeMappingLocked(u64 offset); | 154 | void FreeMappingLocked(u64 offset); |
| 155 | 155 | ||
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index 8cefff6d1..b8dd34e24 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp | |||
| @@ -41,19 +41,19 @@ NvResult nvhost_ctrl::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inp | |||
| 41 | case 0x0: | 41 | case 0x0: |
| 42 | switch (command.cmd) { | 42 | switch (command.cmd) { |
| 43 | case 0x1b: | 43 | case 0x1b: |
| 44 | return Wrap1(&nvhost_ctrl::NvOsGetConfigU32, input, output); | 44 | return WrapFixed(this, &nvhost_ctrl::NvOsGetConfigU32, input, output); |
| 45 | case 0x1c: | 45 | case 0x1c: |
| 46 | return Wrap1(&nvhost_ctrl::IocCtrlClearEventWait, input, output); | 46 | return WrapFixed(this, &nvhost_ctrl::IocCtrlClearEventWait, input, output); |
| 47 | case 0x1d: | 47 | case 0x1d: |
| 48 | return Wrap1(&nvhost_ctrl::IocCtrlEventWaitWithAllocation, input, output); | 48 | return WrapFixed(this, &nvhost_ctrl::IocCtrlEventWait, input, output, true); |
| 49 | case 0x1e: | 49 | case 0x1e: |
| 50 | return Wrap1(&nvhost_ctrl::IocCtrlEventWaitNotAllocation, input, output); | 50 | return WrapFixed(this, &nvhost_ctrl::IocCtrlEventWait, input, output, false); |
| 51 | case 0x1f: | 51 | case 0x1f: |
| 52 | return Wrap1(&nvhost_ctrl::IocCtrlEventRegister, input, output); | 52 | return WrapFixed(this, &nvhost_ctrl::IocCtrlEventRegister, input, output); |
| 53 | case 0x20: | 53 | case 0x20: |
| 54 | return Wrap1(&nvhost_ctrl::IocCtrlEventUnregister, input, output); | 54 | return WrapFixed(this, &nvhost_ctrl::IocCtrlEventUnregister, input, output); |
| 55 | case 0x21: | 55 | case 0x21: |
| 56 | return Wrap1(&nvhost_ctrl::IocCtrlEventUnregisterBatch, input, output); | 56 | return WrapFixed(this, &nvhost_ctrl::IocCtrlEventUnregisterBatch, input, output); |
| 57 | } | 57 | } |
| 58 | break; | 58 | break; |
| 59 | default: | 59 | default: |
| @@ -86,7 +86,7 @@ NvResult nvhost_ctrl::NvOsGetConfigU32(IocGetConfigParams& params) { | |||
| 86 | return NvResult::ConfigVarNotFound; // Returns error on production mode | 86 | return NvResult::ConfigVarNotFound; // Returns error on production mode |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | NvResult nvhost_ctrl::IocCtrlEventWaitImpl(IocCtrlEventWaitParams& params, bool is_allocation) { | 89 | NvResult nvhost_ctrl::IocCtrlEventWait(IocCtrlEventWaitParams& params, bool is_allocation) { |
| 90 | LOG_DEBUG(Service_NVDRV, "syncpt_id={}, threshold={}, timeout={}, is_allocation={}", | 90 | LOG_DEBUG(Service_NVDRV, "syncpt_id={}, threshold={}, timeout={}, is_allocation={}", |
| 91 | params.fence.id, params.fence.value, params.timeout, is_allocation); | 91 | params.fence.id, params.fence.value, params.timeout, is_allocation); |
| 92 | 92 | ||
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h index 6913c61ac..992124b60 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h | |||
| @@ -190,20 +190,11 @@ private: | |||
| 190 | NvResult IocCtrlEventRegister(IocCtrlEventRegisterParams& params); | 190 | NvResult IocCtrlEventRegister(IocCtrlEventRegisterParams& params); |
| 191 | NvResult IocCtrlEventUnregister(IocCtrlEventUnregisterParams& params); | 191 | NvResult IocCtrlEventUnregister(IocCtrlEventUnregisterParams& params); |
| 192 | NvResult IocCtrlEventUnregisterBatch(IocCtrlEventUnregisterBatchParams& params); | 192 | NvResult IocCtrlEventUnregisterBatch(IocCtrlEventUnregisterBatchParams& params); |
| 193 | NvResult IocCtrlEventWait(IocCtrlEventWaitParams& params, bool is_allocation); | ||
| 193 | NvResult IocCtrlClearEventWait(IocCtrlEventClearParams& params); | 194 | NvResult IocCtrlClearEventWait(IocCtrlEventClearParams& params); |
| 194 | 195 | ||
| 195 | NvResult FreeEvent(u32 slot); | 196 | NvResult FreeEvent(u32 slot); |
| 196 | 197 | ||
| 197 | // TODO: these are not the correct names | ||
| 198 | NvResult IocCtrlEventWaitNotAllocation(IocCtrlEventWaitParams& params) { | ||
| 199 | return this->IocCtrlEventWaitImpl(params, false); | ||
| 200 | } | ||
| 201 | NvResult IocCtrlEventWaitWithAllocation(IocCtrlEventWaitParams& params) { | ||
| 202 | return this->IocCtrlEventWaitImpl(params, true); | ||
| 203 | } | ||
| 204 | |||
| 205 | NvResult IocCtrlEventWaitImpl(IocCtrlEventWaitParams& params, bool is_allocation); | ||
| 206 | |||
| 207 | EventInterface& events_interface; | 198 | EventInterface& events_interface; |
| 208 | NvCore::Container& core; | 199 | NvCore::Container& core; |
| 209 | NvCore::SyncpointManager& syncpoint_manager; | 200 | NvCore::SyncpointManager& syncpoint_manager; |
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 92e677b3d..61a2df121 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp | |||
| @@ -28,23 +28,23 @@ NvResult nvhost_ctrl_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> | |||
| 28 | case 'G': | 28 | case 'G': |
| 29 | switch (command.cmd) { | 29 | switch (command.cmd) { |
| 30 | case 0x1: | 30 | case 0x1: |
| 31 | return Wrap1(&nvhost_ctrl_gpu::ZCullGetCtxSize, input, output); | 31 | return WrapFixed(this, &nvhost_ctrl_gpu::ZCullGetCtxSize, input, output); |
| 32 | case 0x2: | 32 | case 0x2: |
| 33 | return Wrap1(&nvhost_ctrl_gpu::ZCullGetInfo, input, output); | 33 | return WrapFixed(this, &nvhost_ctrl_gpu::ZCullGetInfo, input, output); |
| 34 | case 0x3: | 34 | case 0x3: |
| 35 | return Wrap1(&nvhost_ctrl_gpu::ZBCSetTable, input, output); | 35 | return WrapFixed(this, &nvhost_ctrl_gpu::ZBCSetTable, input, output); |
| 36 | case 0x4: | 36 | case 0x4: |
| 37 | return Wrap1(&nvhost_ctrl_gpu::ZBCQueryTable, input, output); | 37 | return WrapFixed(this, &nvhost_ctrl_gpu::ZBCQueryTable, input, output); |
| 38 | case 0x5: | 38 | case 0x5: |
| 39 | return Wrap1(&nvhost_ctrl_gpu::GetCharacteristics1, input, output); | 39 | return WrapFixed(this, &nvhost_ctrl_gpu::GetCharacteristics1, input, output); |
| 40 | case 0x6: | 40 | case 0x6: |
| 41 | return Wrap1(&nvhost_ctrl_gpu::GetTPCMasks1, input, output); | 41 | return WrapFixed(this, &nvhost_ctrl_gpu::GetTPCMasks1, input, output); |
| 42 | case 0x7: | 42 | case 0x7: |
| 43 | return Wrap1(&nvhost_ctrl_gpu::FlushL2, input, output); | 43 | return WrapFixed(this, &nvhost_ctrl_gpu::FlushL2, input, output); |
| 44 | case 0x14: | 44 | case 0x14: |
| 45 | return Wrap1(&nvhost_ctrl_gpu::GetActiveSlotMask, input, output); | 45 | return WrapFixed(this, &nvhost_ctrl_gpu::GetActiveSlotMask, input, output); |
| 46 | case 0x1c: | 46 | case 0x1c: |
| 47 | return Wrap1(&nvhost_ctrl_gpu::GetGpuTime, input, output); | 47 | return WrapFixed(this, &nvhost_ctrl_gpu::GetGpuTime, input, output); |
| 48 | default: | 48 | default: |
| 49 | break; | 49 | break; |
| 50 | } | 50 | } |
| @@ -66,9 +66,11 @@ NvResult nvhost_ctrl_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> | |||
| 66 | case 'G': | 66 | case 'G': |
| 67 | switch (command.cmd) { | 67 | switch (command.cmd) { |
| 68 | case 0x5: | 68 | case 0x5: |
| 69 | return Wrap3(&nvhost_ctrl_gpu::GetCharacteristics3, input, output, inline_output); | 69 | return WrapFixedInlOut(this, &nvhost_ctrl_gpu::GetCharacteristics3, input, output, |
| 70 | inline_output); | ||
| 70 | case 0x6: | 71 | case 0x6: |
| 71 | return Wrap3(&nvhost_ctrl_gpu::GetTPCMasks3, input, output, inline_output); | 72 | return WrapFixedInlOut(this, &nvhost_ctrl_gpu::GetTPCMasks3, input, output, |
| 73 | inline_output); | ||
| 72 | default: | 74 | default: |
| 73 | break; | 75 | break; |
| 74 | } | 76 | } |
| @@ -125,8 +127,8 @@ NvResult nvhost_ctrl_gpu::GetCharacteristics1(IoctlCharacteristics& params) { | |||
| 125 | return NvResult::Success; | 127 | return NvResult::Success; |
| 126 | } | 128 | } |
| 127 | 129 | ||
| 128 | NvResult nvhost_ctrl_gpu::GetCharacteristics3(IoctlCharacteristics& params, | 130 | NvResult nvhost_ctrl_gpu::GetCharacteristics3( |
| 129 | std::span<u8> inline_output) { | 131 | IoctlCharacteristics& params, std::span<IoctlGpuCharacteristics> gpu_characteristics) { |
| 130 | LOG_DEBUG(Service_NVDRV, "called"); | 132 | LOG_DEBUG(Service_NVDRV, "called"); |
| 131 | 133 | ||
| 132 | params.gc.arch = 0x120; | 134 | params.gc.arch = 0x120; |
| @@ -166,8 +168,9 @@ NvResult nvhost_ctrl_gpu::GetCharacteristics3(IoctlCharacteristics& params, | |||
| 166 | params.gc.gr_compbit_store_base_hw = 0x0; | 168 | params.gc.gr_compbit_store_base_hw = 0x0; |
| 167 | params.gpu_characteristics_buf_size = 0xA0; | 169 | params.gpu_characteristics_buf_size = 0xA0; |
| 168 | params.gpu_characteristics_buf_addr = 0xdeadbeef; // Cannot be 0 (UNUSED) | 170 | params.gpu_characteristics_buf_addr = 0xdeadbeef; // Cannot be 0 (UNUSED) |
| 169 | std::memcpy(inline_output.data(), ¶ms.gc, | 171 | if (!gpu_characteristics.empty()) { |
| 170 | std::min(sizeof(params.gc), inline_output.size())); | 172 | gpu_characteristics.front() = params.gc; |
| 173 | } | ||
| 171 | return NvResult::Success; | 174 | return NvResult::Success; |
| 172 | } | 175 | } |
| 173 | 176 | ||
| @@ -179,14 +182,14 @@ NvResult nvhost_ctrl_gpu::GetTPCMasks1(IoctlGpuGetTpcMasksArgs& params) { | |||
| 179 | return NvResult::Success; | 182 | return NvResult::Success; |
| 180 | } | 183 | } |
| 181 | 184 | ||
| 182 | NvResult nvhost_ctrl_gpu::GetTPCMasks3(IoctlGpuGetTpcMasksArgs& params, | 185 | NvResult nvhost_ctrl_gpu::GetTPCMasks3(IoctlGpuGetTpcMasksArgs& params, std::span<u32> tpc_mask) { |
| 183 | std::span<u8> inline_output) { | ||
| 184 | LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size=0x{:X}", params.mask_buffer_size); | 186 | LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size=0x{:X}", params.mask_buffer_size); |
| 185 | if (params.mask_buffer_size != 0) { | 187 | if (params.mask_buffer_size != 0) { |
| 186 | params.tcp_mask = 3; | 188 | params.tcp_mask = 3; |
| 187 | } | 189 | } |
| 188 | std::memcpy(inline_output.data(), ¶ms.tcp_mask, | 190 | if (!tpc_mask.empty()) { |
| 189 | std::min(sizeof(params.tcp_mask), inline_output.size())); | 191 | tpc_mask.front() = params.tcp_mask; |
| 192 | } | ||
| 190 | return NvResult::Success; | 193 | return NvResult::Success; |
| 191 | } | 194 | } |
| 192 | 195 | ||
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 e1977a6b5..d170299bd 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h | |||
| @@ -152,10 +152,11 @@ private: | |||
| 152 | static_assert(sizeof(IoctlGetGpuTime) == 0x10, "IoctlGetGpuTime is incorrect size"); | 152 | static_assert(sizeof(IoctlGetGpuTime) == 0x10, "IoctlGetGpuTime is incorrect size"); |
| 153 | 153 | ||
| 154 | NvResult GetCharacteristics1(IoctlCharacteristics& params); | 154 | NvResult GetCharacteristics1(IoctlCharacteristics& params); |
| 155 | NvResult GetCharacteristics3(IoctlCharacteristics& params, std::span<u8> inline_output); | 155 | NvResult GetCharacteristics3(IoctlCharacteristics& params, |
| 156 | std::span<IoctlGpuCharacteristics> gpu_characteristics); | ||
| 156 | 157 | ||
| 157 | NvResult GetTPCMasks1(IoctlGpuGetTpcMasksArgs& params); | 158 | NvResult GetTPCMasks1(IoctlGpuGetTpcMasksArgs& params); |
| 158 | NvResult GetTPCMasks3(IoctlGpuGetTpcMasksArgs& params, std::span<u8> inline_output); | 159 | NvResult GetTPCMasks3(IoctlGpuGetTpcMasksArgs& params, std::span<u32> tpc_mask); |
| 159 | 160 | ||
| 160 | NvResult GetActiveSlotMask(IoctlActiveSlotMask& params); | 161 | NvResult GetActiveSlotMask(IoctlActiveSlotMask& params); |
| 161 | NvResult ZCullGetCtxSize(IoctlZcullGetCtxSize& params); | 162 | NvResult ZCullGetCtxSize(IoctlZcullGetCtxSize& params); |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp index 2d67acc6a..b0395c2f0 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp | |||
| @@ -53,7 +53,7 @@ NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inpu | |||
| 53 | case 0x0: | 53 | case 0x0: |
| 54 | switch (command.cmd) { | 54 | switch (command.cmd) { |
| 55 | case 0x3: | 55 | case 0x3: |
| 56 | return Wrap1(&nvhost_gpu::GetWaitbase, input, output); | 56 | return WrapFixed(this, &nvhost_gpu::GetWaitbase, input, output); |
| 57 | default: | 57 | default: |
| 58 | break; | 58 | break; |
| 59 | } | 59 | } |
| @@ -61,25 +61,25 @@ NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inpu | |||
| 61 | case 'H': | 61 | case 'H': |
| 62 | switch (command.cmd) { | 62 | switch (command.cmd) { |
| 63 | case 0x1: | 63 | case 0x1: |
| 64 | return Wrap1(&nvhost_gpu::SetNVMAPfd, input, output); | 64 | return WrapFixed(this, &nvhost_gpu::SetNVMAPfd, input, output); |
| 65 | case 0x3: | 65 | case 0x3: |
| 66 | return Wrap1(&nvhost_gpu::ChannelSetTimeout, input, output); | 66 | return WrapFixed(this, &nvhost_gpu::ChannelSetTimeout, input, output); |
| 67 | case 0x8: | 67 | case 0x8: |
| 68 | return SubmitGPFIFOBase1(input, false); | 68 | return WrapFixedVariable(this, &nvhost_gpu::SubmitGPFIFOBase1, input, output, false); |
| 69 | case 0x9: | 69 | case 0x9: |
| 70 | return Wrap1(&nvhost_gpu::AllocateObjectContext, input, output); | 70 | return WrapFixed(this, &nvhost_gpu::AllocateObjectContext, input, output); |
| 71 | case 0xb: | 71 | case 0xb: |
| 72 | return Wrap1(&nvhost_gpu::ZCullBind, input, output); | 72 | return WrapFixed(this, &nvhost_gpu::ZCullBind, input, output); |
| 73 | case 0xc: | 73 | case 0xc: |
| 74 | return Wrap1(&nvhost_gpu::SetErrorNotifier, input, output); | 74 | return WrapFixed(this, &nvhost_gpu::SetErrorNotifier, input, output); |
| 75 | case 0xd: | 75 | case 0xd: |
| 76 | return Wrap1(&nvhost_gpu::SetChannelPriority, input, output); | 76 | return WrapFixed(this, &nvhost_gpu::SetChannelPriority, input, output); |
| 77 | case 0x1a: | 77 | case 0x1a: |
| 78 | return Wrap1(&nvhost_gpu::AllocGPFIFOEx2, input, output); | 78 | return WrapFixed(this, &nvhost_gpu::AllocGPFIFOEx2, input, output); |
| 79 | case 0x1b: | 79 | case 0x1b: |
| 80 | return SubmitGPFIFOBase1(input, true); | 80 | return WrapFixedVariable(this, &nvhost_gpu::SubmitGPFIFOBase1, input, output, true); |
| 81 | case 0x1d: | 81 | case 0x1d: |
| 82 | return Wrap1(&nvhost_gpu::ChannelSetTimeslice, input, output); | 82 | return WrapFixed(this, &nvhost_gpu::ChannelSetTimeslice, input, output); |
| 83 | default: | 83 | default: |
| 84 | break; | 84 | break; |
| 85 | } | 85 | } |
| @@ -87,9 +87,9 @@ NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inpu | |||
| 87 | case 'G': | 87 | case 'G': |
| 88 | switch (command.cmd) { | 88 | switch (command.cmd) { |
| 89 | case 0x14: | 89 | case 0x14: |
| 90 | return Wrap1(&nvhost_gpu::SetClientData, input, output); | 90 | return WrapFixed(this, &nvhost_gpu::SetClientData, input, output); |
| 91 | case 0x15: | 91 | case 0x15: |
| 92 | return Wrap1(&nvhost_gpu::GetClientData, input, output); | 92 | return WrapFixed(this, &nvhost_gpu::GetClientData, input, output); |
| 93 | default: | 93 | default: |
| 94 | break; | 94 | break; |
| 95 | } | 95 | } |
| @@ -105,7 +105,8 @@ NvResult nvhost_gpu::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> inpu | |||
| 105 | case 'H': | 105 | case 'H': |
| 106 | switch (command.cmd) { | 106 | switch (command.cmd) { |
| 107 | case 0x1b: | 107 | case 0x1b: |
| 108 | return SubmitGPFIFOBase2(input, inline_input); | 108 | return WrapFixedInlIn(this, &nvhost_gpu::SubmitGPFIFOBase2, input, inline_input, |
| 109 | output); | ||
| 109 | } | 110 | } |
| 110 | break; | 111 | break; |
| 111 | } | 112 | } |
| @@ -271,36 +272,35 @@ NvResult nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, Tegra::CommandL | |||
| 271 | return NvResult::Success; | 272 | return NvResult::Success; |
| 272 | } | 273 | } |
| 273 | 274 | ||
| 274 | NvResult nvhost_gpu::SubmitGPFIFOBase1(std::span<const u8> input, bool kickoff) { | 275 | NvResult nvhost_gpu::SubmitGPFIFOBase1(IoctlSubmitGpfifo& params, |
| 275 | if (input.size() < sizeof(IoctlSubmitGpfifo)) { | 276 | std::span<Tegra::CommandListHeader> commands, bool kickoff) { |
| 277 | if (params.num_entries > commands.size()) { | ||
| 276 | UNIMPLEMENTED(); | 278 | UNIMPLEMENTED(); |
| 277 | return NvResult::InvalidSize; | 279 | return NvResult::InvalidSize; |
| 278 | } | 280 | } |
| 279 | IoctlSubmitGpfifo params{}; | ||
| 280 | std::memcpy(¶ms, input.data(), sizeof(IoctlSubmitGpfifo)); | ||
| 281 | Tegra::CommandList entries(params.num_entries); | ||
| 282 | 281 | ||
| 282 | Tegra::CommandList entries(params.num_entries); | ||
| 283 | if (kickoff) { | 283 | if (kickoff) { |
| 284 | system.ApplicationMemory().ReadBlock(params.address, entries.command_lists.data(), | 284 | system.ApplicationMemory().ReadBlock(params.address, entries.command_lists.data(), |
| 285 | params.num_entries * sizeof(Tegra::CommandListHeader)); | 285 | params.num_entries * sizeof(Tegra::CommandListHeader)); |
| 286 | } else { | 286 | } else { |
| 287 | std::memcpy(entries.command_lists.data(), &input[sizeof(IoctlSubmitGpfifo)], | 287 | std::memcpy(entries.command_lists.data(), commands.data(), |
| 288 | params.num_entries * sizeof(Tegra::CommandListHeader)); | 288 | params.num_entries * sizeof(Tegra::CommandListHeader)); |
| 289 | } | 289 | } |
| 290 | 290 | ||
| 291 | return SubmitGPFIFOImpl(params, std::move(entries)); | 291 | return SubmitGPFIFOImpl(params, std::move(entries)); |
| 292 | } | 292 | } |
| 293 | 293 | ||
| 294 | NvResult nvhost_gpu::SubmitGPFIFOBase2(std::span<const u8> input, | 294 | NvResult nvhost_gpu::SubmitGPFIFOBase2(IoctlSubmitGpfifo& params, |
| 295 | std::span<const u8> input_inline) { | 295 | std::span<const Tegra::CommandListHeader> commands) { |
| 296 | if (input.size() < sizeof(IoctlSubmitGpfifo)) { | 296 | if (params.num_entries > commands.size()) { |
| 297 | UNIMPLEMENTED(); | 297 | UNIMPLEMENTED(); |
| 298 | return NvResult::InvalidSize; | 298 | return NvResult::InvalidSize; |
| 299 | } | 299 | } |
| 300 | IoctlSubmitGpfifo params{}; | 300 | |
| 301 | std::memcpy(¶ms, input.data(), sizeof(IoctlSubmitGpfifo)); | ||
| 302 | Tegra::CommandList entries(params.num_entries); | 301 | Tegra::CommandList entries(params.num_entries); |
| 303 | std::memcpy(entries.command_lists.data(), input_inline.data(), input_inline.size()); | 302 | std::memcpy(entries.command_lists.data(), commands.data(), |
| 303 | params.num_entries * sizeof(Tegra::CommandListHeader)); | ||
| 304 | return SubmitGPFIFOImpl(params, std::move(entries)); | 304 | return SubmitGPFIFOImpl(params, std::move(entries)); |
| 305 | } | 305 | } |
| 306 | 306 | ||
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h index 703079a54..88fd228ff 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h | |||
| @@ -196,8 +196,10 @@ private: | |||
| 196 | NvResult AllocateObjectContext(IoctlAllocObjCtx& params); | 196 | NvResult AllocateObjectContext(IoctlAllocObjCtx& params); |
| 197 | 197 | ||
| 198 | NvResult SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, Tegra::CommandList&& entries); | 198 | NvResult SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, Tegra::CommandList&& entries); |
| 199 | NvResult SubmitGPFIFOBase1(std::span<const u8> input, bool kickoff = false); | 199 | NvResult SubmitGPFIFOBase1(IoctlSubmitGpfifo& params, |
| 200 | NvResult SubmitGPFIFOBase2(std::span<const u8> input, std::span<const u8> input_inline); | 200 | std::span<Tegra::CommandListHeader> commands, bool kickoff = false); |
| 201 | NvResult SubmitGPFIFOBase2(IoctlSubmitGpfifo& params, | ||
| 202 | std::span<const Tegra::CommandListHeader> commands); | ||
| 201 | 203 | ||
| 202 | NvResult GetWaitbase(IoctlGetWaitbase& params); | 204 | NvResult GetWaitbase(IoctlGetWaitbase& params); |
| 203 | NvResult ChannelSetTimeout(IoctlChannelSetTimeout& params); | 205 | NvResult ChannelSetTimeout(IoctlChannelSetTimeout& params); |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp index 74790a7d8..f43914e1b 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp | |||
| @@ -26,18 +26,18 @@ NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> in | |||
| 26 | if (!host1x_file.fd_to_id.contains(fd)) { | 26 | if (!host1x_file.fd_to_id.contains(fd)) { |
| 27 | host1x_file.fd_to_id[fd] = host1x_file.nvdec_next_id++; | 27 | host1x_file.fd_to_id[fd] = host1x_file.nvdec_next_id++; |
| 28 | } | 28 | } |
| 29 | return Submit(fd, input, output); | 29 | return WrapFixedVariable(this, &nvhost_nvdec::Submit, input, output, fd); |
| 30 | } | 30 | } |
| 31 | case 0x2: | 31 | case 0x2: |
| 32 | return Wrap1(&nvhost_nvdec::GetSyncpoint, input, output); | 32 | return WrapFixed(this, &nvhost_nvdec::GetSyncpoint, input, output); |
| 33 | case 0x3: | 33 | case 0x3: |
| 34 | return Wrap1(&nvhost_nvdec::GetWaitbase, input, output); | 34 | return WrapFixed(this, &nvhost_nvdec::GetWaitbase, input, output); |
| 35 | case 0x7: | 35 | case 0x7: |
| 36 | return Wrap1(&nvhost_nvdec::SetSubmitTimeout, input, output); | 36 | return WrapFixed(this, &nvhost_nvdec::SetSubmitTimeout, input, output); |
| 37 | case 0x9: | 37 | case 0x9: |
| 38 | return MapBuffer(input, output); | 38 | return WrapFixedVariable(this, &nvhost_nvdec::MapBuffer, input, output); |
| 39 | case 0xa: | 39 | case 0xa: |
| 40 | return UnmapBuffer(input, output); | 40 | return WrapFixedVariable(this, &nvhost_nvdec::UnmapBuffer, input, output); |
| 41 | default: | 41 | default: |
| 42 | break; | 42 | break; |
| 43 | } | 43 | } |
| @@ -45,7 +45,7 @@ NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> in | |||
| 45 | case 'H': | 45 | case 'H': |
| 46 | switch (command.cmd) { | 46 | switch (command.cmd) { |
| 47 | case 0x1: | 47 | case 0x1: |
| 48 | return Wrap1(&nvhost_nvdec::SetNVMAPfd, input, output); | 48 | return WrapFixed(this, &nvhost_nvdec::SetNVMAPfd, input, output); |
| 49 | default: | 49 | default: |
| 50 | break; | 50 | break; |
| 51 | } | 51 | } |
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 3fdf383f0..74c701b95 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp | |||
| @@ -76,13 +76,7 @@ NvResult nvhost_nvdec_common::SetNVMAPfd(IoctlSetNvmapFD& params) { | |||
| 76 | return NvResult::Success; | 76 | return NvResult::Success; |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | NvResult nvhost_nvdec_common::Submit(DeviceFD fd, std::span<const u8> input, std::span<u8> output) { | 79 | NvResult nvhost_nvdec_common::Submit(IoctlSubmit& params, std::span<u8> data, DeviceFD fd) { |
| 80 | if (input.size() < sizeof(IoctlSubmit) || output.size() < sizeof(IoctlSubmit)) { | ||
| 81 | UNIMPLEMENTED(); | ||
| 82 | return NvResult::InvalidSize; | ||
| 83 | } | ||
| 84 | IoctlSubmit params{}; | ||
| 85 | std::memcpy(¶ms, input.data(), std::min(input.size(), sizeof(IoctlSubmit))); | ||
| 86 | LOG_DEBUG(Service_NVDRV, "called NVDEC Submit, cmd_buffer_count={}", params.cmd_buffer_count); | 80 | LOG_DEBUG(Service_NVDRV, "called NVDEC Submit, cmd_buffer_count={}", params.cmd_buffer_count); |
| 87 | 81 | ||
| 88 | // Instantiate param buffers | 82 | // Instantiate param buffers |
| @@ -93,12 +87,12 @@ NvResult nvhost_nvdec_common::Submit(DeviceFD fd, std::span<const u8> input, std | |||
| 93 | std::vector<u32> fence_thresholds(params.fence_count); | 87 | std::vector<u32> fence_thresholds(params.fence_count); |
| 94 | 88 | ||
| 95 | // Slice input into their respective buffers | 89 | // Slice input into their respective buffers |
| 96 | std::size_t offset = sizeof(IoctlSubmit); | 90 | std::size_t offset = 0; |
| 97 | offset += SliceVectors(input, command_buffers, params.cmd_buffer_count, offset); | 91 | offset += SliceVectors(data, command_buffers, params.cmd_buffer_count, offset); |
| 98 | offset += SliceVectors(input, relocs, params.relocation_count, offset); | 92 | offset += SliceVectors(data, relocs, params.relocation_count, offset); |
| 99 | offset += SliceVectors(input, reloc_shifts, params.relocation_count, offset); | 93 | offset += SliceVectors(data, reloc_shifts, params.relocation_count, offset); |
| 100 | offset += SliceVectors(input, syncpt_increments, params.syncpoint_count, offset); | 94 | offset += SliceVectors(data, syncpt_increments, params.syncpoint_count, offset); |
| 101 | offset += SliceVectors(input, fence_thresholds, params.fence_count, offset); | 95 | offset += SliceVectors(data, fence_thresholds, params.fence_count, offset); |
| 102 | 96 | ||
| 103 | auto& gpu = system.GPU(); | 97 | auto& gpu = system.GPU(); |
| 104 | if (gpu.UseNvdec()) { | 98 | if (gpu.UseNvdec()) { |
| @@ -116,14 +110,13 @@ NvResult nvhost_nvdec_common::Submit(DeviceFD fd, std::span<const u8> input, std | |||
| 116 | cmdlist.size() * sizeof(u32)); | 110 | cmdlist.size() * sizeof(u32)); |
| 117 | gpu.PushCommandBuffer(core.Host1xDeviceFile().fd_to_id[fd], cmdlist); | 111 | gpu.PushCommandBuffer(core.Host1xDeviceFile().fd_to_id[fd], cmdlist); |
| 118 | } | 112 | } |
| 119 | std::memcpy(output.data(), ¶ms, sizeof(IoctlSubmit)); | ||
| 120 | // Some games expect command_buffers to be written back | 113 | // Some games expect command_buffers to be written back |
| 121 | offset = sizeof(IoctlSubmit); | 114 | offset = 0; |
| 122 | offset += WriteVectors(output, command_buffers, offset); | 115 | offset += WriteVectors(data, command_buffers, offset); |
| 123 | offset += WriteVectors(output, relocs, offset); | 116 | offset += WriteVectors(data, relocs, offset); |
| 124 | offset += WriteVectors(output, reloc_shifts, offset); | 117 | offset += WriteVectors(data, reloc_shifts, offset); |
| 125 | offset += WriteVectors(output, syncpt_increments, offset); | 118 | offset += WriteVectors(data, syncpt_increments, offset); |
| 126 | offset += WriteVectors(output, fence_thresholds, offset); | 119 | offset += WriteVectors(data, fence_thresholds, offset); |
| 127 | 120 | ||
| 128 | return NvResult::Success; | 121 | return NvResult::Success; |
| 129 | } | 122 | } |
| @@ -140,40 +133,24 @@ NvResult nvhost_nvdec_common::GetWaitbase(IoctlGetWaitbase& params) { | |||
| 140 | return NvResult::Success; | 133 | return NvResult::Success; |
| 141 | } | 134 | } |
| 142 | 135 | ||
| 143 | NvResult nvhost_nvdec_common::MapBuffer(std::span<const u8> input, std::span<u8> output) { | 136 | NvResult nvhost_nvdec_common::MapBuffer(IoctlMapBuffer& params, std::span<MapBufferEntry> entries) { |
| 144 | IoctlMapBuffer params{}; | 137 | const size_t num_entries = std::min(params.num_entries, static_cast<u32>(entries.size())); |
| 145 | std::memcpy(¶ms, input.data(), sizeof(IoctlMapBuffer)); | 138 | for (size_t i = 0; i < num_entries; i++) { |
| 146 | std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries); | 139 | entries[i].map_address = nvmap.PinHandle(entries[i].map_handle); |
| 147 | |||
| 148 | SliceVectors(input, cmd_buffer_handles, params.num_entries, sizeof(IoctlMapBuffer)); | ||
| 149 | |||
| 150 | for (auto& cmd_buffer : cmd_buffer_handles) { | ||
| 151 | cmd_buffer.map_address = nvmap.PinHandle(cmd_buffer.map_handle); | ||
| 152 | } | 140 | } |
| 153 | 141 | ||
| 154 | if (output.size() < | ||
| 155 | sizeof(IoctlMapBuffer) + cmd_buffer_handles.size() * sizeof(MapBufferEntry)) { | ||
| 156 | return NvResult::InvalidSize; | ||
| 157 | } | ||
| 158 | |||
| 159 | std::memcpy(output.data(), ¶ms, sizeof(IoctlMapBuffer)); | ||
| 160 | std::memcpy(output.data() + sizeof(IoctlMapBuffer), cmd_buffer_handles.data(), | ||
| 161 | cmd_buffer_handles.size() * sizeof(MapBufferEntry)); | ||
| 162 | |||
| 163 | return NvResult::Success; | 142 | return NvResult::Success; |
| 164 | } | 143 | } |
| 165 | 144 | ||
| 166 | NvResult nvhost_nvdec_common::UnmapBuffer(std::span<const u8> input, std::span<u8> output) { | 145 | NvResult nvhost_nvdec_common::UnmapBuffer(IoctlMapBuffer& params, |
| 167 | IoctlMapBuffer params{}; | 146 | std::span<MapBufferEntry> entries) { |
| 168 | std::memcpy(¶ms, input.data(), std::min(input.size(), sizeof(IoctlMapBuffer))); | 147 | const size_t num_entries = std::min(params.num_entries, static_cast<u32>(entries.size())); |
| 169 | std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries); | 148 | for (size_t i = 0; i < num_entries; i++) { |
| 170 | 149 | nvmap.UnpinHandle(entries[i].map_handle); | |
| 171 | SliceVectors(input, cmd_buffer_handles, params.num_entries, sizeof(IoctlMapBuffer)); | 150 | entries[i] = {}; |
| 172 | for (auto& cmd_buffer : cmd_buffer_handles) { | ||
| 173 | nvmap.UnpinHandle(cmd_buffer.map_handle); | ||
| 174 | } | 151 | } |
| 175 | 152 | ||
| 176 | std::memset(output.data(), 0, output.size()); | 153 | params = {}; |
| 177 | return NvResult::Success; | 154 | return NvResult::Success; |
| 178 | } | 155 | } |
| 179 | 156 | ||
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 cc988b897..7ce748e18 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h | |||
| @@ -108,11 +108,11 @@ protected: | |||
| 108 | 108 | ||
| 109 | /// Ioctl command implementations | 109 | /// Ioctl command implementations |
| 110 | NvResult SetNVMAPfd(IoctlSetNvmapFD&); | 110 | NvResult SetNVMAPfd(IoctlSetNvmapFD&); |
| 111 | NvResult Submit(DeviceFD fd, std::span<const u8> input, std::span<u8> output); | 111 | NvResult Submit(IoctlSubmit& params, std::span<u8> input, DeviceFD fd); |
| 112 | NvResult GetSyncpoint(IoctlGetSyncpoint& params); | 112 | NvResult GetSyncpoint(IoctlGetSyncpoint& params); |
| 113 | NvResult GetWaitbase(IoctlGetWaitbase& params); | 113 | NvResult GetWaitbase(IoctlGetWaitbase& params); |
| 114 | NvResult MapBuffer(std::span<const u8> input, std::span<u8> output); | 114 | NvResult MapBuffer(IoctlMapBuffer& params, std::span<MapBufferEntry> entries); |
| 115 | NvResult UnmapBuffer(std::span<const u8> input, std::span<u8> output); | 115 | NvResult UnmapBuffer(IoctlMapBuffer& params, std::span<MapBufferEntry> entries); |
| 116 | NvResult SetSubmitTimeout(u32 timeout); | 116 | NvResult SetSubmitTimeout(u32 timeout); |
| 117 | 117 | ||
| 118 | Kernel::KEvent* QueryEvent(u32 event_id) override; | 118 | 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 23a57c4d5..9e6b86458 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp | |||
| @@ -19,7 +19,7 @@ NvResult nvhost_nvjpg::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> in | |||
| 19 | case 'H': | 19 | case 'H': |
| 20 | switch (command.cmd) { | 20 | switch (command.cmd) { |
| 21 | case 0x1: | 21 | case 0x1: |
| 22 | return Wrap1(&nvhost_nvjpg::SetNVMAPfd, input, output); | 22 | return WrapFixed(this, &nvhost_nvjpg::SetNVMAPfd, input, output); |
| 23 | default: | 23 | default: |
| 24 | break; | 24 | break; |
| 25 | } | 25 | } |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp index 20af75872..87f8d7c22 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp | |||
| @@ -26,16 +26,16 @@ NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inpu | |||
| 26 | if (!host1x_file.fd_to_id.contains(fd)) { | 26 | if (!host1x_file.fd_to_id.contains(fd)) { |
| 27 | host1x_file.fd_to_id[fd] = host1x_file.vic_next_id++; | 27 | host1x_file.fd_to_id[fd] = host1x_file.vic_next_id++; |
| 28 | } | 28 | } |
| 29 | return Submit(fd, input, output); | 29 | return WrapFixedVariable(this, &nvhost_vic::Submit, input, output, fd); |
| 30 | } | 30 | } |
| 31 | case 0x2: | 31 | case 0x2: |
| 32 | return Wrap1(&nvhost_vic::GetSyncpoint, input, output); | 32 | return WrapFixed(this, &nvhost_vic::GetSyncpoint, input, output); |
| 33 | case 0x3: | 33 | case 0x3: |
| 34 | return Wrap1(&nvhost_vic::GetWaitbase, input, output); | 34 | return WrapFixed(this, &nvhost_vic::GetWaitbase, input, output); |
| 35 | case 0x9: | 35 | case 0x9: |
| 36 | return MapBuffer(input, output); | 36 | return WrapFixedVariable(this, &nvhost_vic::MapBuffer, input, output); |
| 37 | case 0xa: | 37 | case 0xa: |
| 38 | return UnmapBuffer(input, output); | 38 | return WrapFixedVariable(this, &nvhost_vic::UnmapBuffer, input, output); |
| 39 | default: | 39 | default: |
| 40 | break; | 40 | break; |
| 41 | } | 41 | } |
| @@ -43,7 +43,7 @@ NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inpu | |||
| 43 | case 'H': | 43 | case 'H': |
| 44 | switch (command.cmd) { | 44 | switch (command.cmd) { |
| 45 | case 0x1: | 45 | case 0x1: |
| 46 | return Wrap1(&nvhost_vic::SetNVMAPfd, input, output); | 46 | return WrapFixed(this, &nvhost_vic::SetNVMAPfd, input, output); |
| 47 | default: | 47 | default: |
| 48 | break; | 48 | break; |
| 49 | } | 49 | } |
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp index 94286e295..71b2e62ec 100644 --- a/src/core/hle/service/nvdrv/devices/nvmap.cpp +++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp | |||
| @@ -32,17 +32,17 @@ NvResult nvmap::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, | |||
| 32 | case 0x1: | 32 | case 0x1: |
| 33 | switch (command.cmd) { | 33 | switch (command.cmd) { |
| 34 | case 0x1: | 34 | case 0x1: |
| 35 | return Wrap1(&nvmap::IocCreate, input, output); | 35 | return WrapFixed(this, &nvmap::IocCreate, input, output); |
| 36 | case 0x3: | 36 | case 0x3: |
| 37 | return Wrap1(&nvmap::IocFromId, input, output); | 37 | return WrapFixed(this, &nvmap::IocFromId, input, output); |
| 38 | case 0x4: | 38 | case 0x4: |
| 39 | return Wrap1(&nvmap::IocAlloc, input, output); | 39 | return WrapFixed(this, &nvmap::IocAlloc, input, output); |
| 40 | case 0x5: | 40 | case 0x5: |
| 41 | return Wrap1(&nvmap::IocFree, input, output); | 41 | return WrapFixed(this, &nvmap::IocFree, input, output); |
| 42 | case 0x9: | 42 | case 0x9: |
| 43 | return Wrap1(&nvmap::IocParam, input, output); | 43 | return WrapFixed(this, &nvmap::IocParam, input, output); |
| 44 | case 0xe: | 44 | case 0xe: |
| 45 | return Wrap1(&nvmap::IocGetId, input, output); | 45 | return WrapFixed(this, &nvmap::IocGetId, input, output); |
| 46 | default: | 46 | default: |
| 47 | break; | 47 | break; |
| 48 | } | 48 | } |