From 5c49e56d417fd98523574e54eb8705d11ea83d88 Mon Sep 17 00:00:00 2001 From: Subv Date: Sat, 21 Jul 2018 15:50:02 -0500 Subject: GPU: Implement the NVGPU_IOCTL_CHANNEL_KICKOFF_PB ioctl2 command. This behaves quite similarly to the SubmitGPFIFO command. Referenced from Ryujinx. Many thanks to @gdkchan for investigating this! --- src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp | 30 +++++++++++++++++++++-- src/core/hle/service/nvdrv/devices/nvhost_gpu.h | 8 +++--- 2 files changed, 33 insertions(+), 5 deletions(-) (limited to 'src/core/hle/service/nvdrv/devices') diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp index 8de870596..126782573 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp @@ -42,6 +42,9 @@ u32 nvhost_gpu::ioctl(Ioctl command, const std::vector& input, std::vector& input, std::vector& outp IoctlSubmitGpfifo params{}; std::memcpy(¶ms, input.data(), sizeof(IoctlSubmitGpfifo)); LOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo={:X}, num_entries={:X}, flags={:X}", - params.gpfifo, params.num_entries, params.flags); + params.address, params.num_entries, params.flags); auto entries = std::vector(); entries.resize(params.num_entries); std::memcpy(&entries[0], &input.data()[sizeof(IoctlSubmitGpfifo)], params.num_entries * sizeof(IoctlGpfifoEntry)); for (auto entry : entries) { - VAddr va_addr = entry.Address(); + Tegra::GPUVAddr va_addr = entry.Address(); + Core::System::GetInstance().GPU().ProcessCommandList(va_addr, entry.sz); + } + params.fence_out.id = 0; + params.fence_out.value = 0; + std::memcpy(output.data(), ¶ms, output.size()); + return 0; +} + +u32 nvhost_gpu::KickoffPB(const std::vector& input, std::vector& output) { + if (input.size() < sizeof(IoctlSubmitGpfifo)) { + UNIMPLEMENTED(); + } + IoctlSubmitGpfifo params{}; + std::memcpy(¶ms, input.data(), sizeof(IoctlSubmitGpfifo)); + LOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo={:X}, num_entries={:X}, flags={:X}", + params.address, params.num_entries, params.flags); + + std::vector entries(params.num_entries); + Memory::ReadBlock(params.address, entries.data(), + params.num_entries * sizeof(IoctlGpfifoEntry)); + + for (auto entry : entries) { + Tegra::GPUVAddr va_addr = entry.Address(); Core::System::GetInstance().GPU().ProcessCommandList(va_addr, entry.sz); } params.fence_out.id = 0; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h index c9f6b9b6a..aa8df2e6e 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h @@ -15,6 +15,7 @@ namespace Service::Nvidia::Devices { class nvmap; constexpr u32 NVGPU_IOCTL_MAGIC('H'); constexpr u32 NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO(0x8); +constexpr u32 NVGPU_IOCTL_CHANNEL_KICKOFF_PB(0x1b); class nvhost_gpu final : public nvdevice { public: @@ -158,14 +159,14 @@ private: BitField<31, 1, u32_le> unk2; }; - VAddr Address() const { - return (static_cast(gpu_va_hi) << 32) | entry0; + Tegra::GPUVAddr Address() const { + return (static_cast(gpu_va_hi) << 32) | entry0; } }; static_assert(sizeof(IoctlGpfifoEntry) == 8, "IoctlGpfifoEntry is incorrect size"); struct IoctlSubmitGpfifo { - u64_le gpfifo; // (ignored) pointer to gpfifo fence structs + u64_le address; // pointer to gpfifo entry structs u32_le num_entries; // number of fence objects being submitted u32_le flags; IoctlFence fence_out; // returned new fence object for others to wait on @@ -193,6 +194,7 @@ private: u32 AllocGPFIFOEx2(const std::vector& input, std::vector& output); u32 AllocateObjectContext(const std::vector& input, std::vector& output); u32 SubmitGPFIFO(const std::vector& input, std::vector& output); + u32 KickoffPB(const std::vector& input, std::vector& output); u32 GetWaitbase(const std::vector& input, std::vector& output); u32 ChannelSetTimeout(const std::vector& input, std::vector& output); -- cgit v1.2.3