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!
This commit is contained in:
		| @@ -42,6 +42,9 @@ u32 nvhost_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u | ||||
|         if (command.cmd == NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO) { | ||||
|             return SubmitGPFIFO(input, output); | ||||
|         } | ||||
|         if (command.cmd == NVGPU_IOCTL_CHANNEL_KICKOFF_PB) { | ||||
|             return KickoffPB(input, output); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     UNIMPLEMENTED_MSG("Unimplemented ioctl"); | ||||
| @@ -127,14 +130,37 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& 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<IoctlGpfifoEntry>(); | ||||
|     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<u8>& input, std::vector<u8>& 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<IoctlGpfifoEntry> 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; | ||||
|   | ||||
| @@ -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<VAddr>(gpu_va_hi) << 32) | entry0; | ||||
|         Tegra::GPUVAddr Address() const { | ||||
|             return (static_cast<Tegra::GPUVAddr>(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<u8>& input, std::vector<u8>& output); | ||||
|     u32 AllocateObjectContext(const std::vector<u8>& input, std::vector<u8>& output); | ||||
|     u32 SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& output); | ||||
|     u32 KickoffPB(const std::vector<u8>& input, std::vector<u8>& output); | ||||
|     u32 GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output); | ||||
|     u32 ChannelSetTimeout(const std::vector<u8>& input, std::vector<u8>& output); | ||||
|  | ||||
|   | ||||
| @@ -101,7 +101,7 @@ NVDRV::NVDRV(std::shared_ptr<Module> nvdrv, const char* name) | ||||
|         {8, &NVDRV::SetClientPID, "SetClientPID"}, | ||||
|         {9, nullptr, "DumpGraphicsMemoryInfo"}, | ||||
|         {10, nullptr, "InitializeDevtools"}, | ||||
|         {11, nullptr, "Ioctl2"}, | ||||
|         {11, &NVDRV::Ioctl, "Ioctl2"}, | ||||
|         {12, nullptr, "Ioctl3"}, | ||||
|         {13, &NVDRV::FinishInitialize, "FinishInitialize"}, | ||||
|     }; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user