mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu.git
				synced 2025-05-12 00:45:25 +00:00 
			
		
		
		
	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:
		
							parent
							
								
									0f20fa5a1e
								
							
						
					
					
						commit
						5c49e56d41
					
				@ -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) {
 | 
					        if (command.cmd == NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO) {
 | 
				
			||||||
            return SubmitGPFIFO(input, output);
 | 
					            return SubmitGPFIFO(input, output);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        if (command.cmd == NVGPU_IOCTL_CHANNEL_KICKOFF_PB) {
 | 
				
			||||||
 | 
					            return KickoffPB(input, output);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    UNIMPLEMENTED_MSG("Unimplemented ioctl");
 | 
					    UNIMPLEMENTED_MSG("Unimplemented ioctl");
 | 
				
			||||||
@ -127,14 +130,37 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& outp
 | 
				
			|||||||
    IoctlSubmitGpfifo params{};
 | 
					    IoctlSubmitGpfifo params{};
 | 
				
			||||||
    std::memcpy(¶ms, input.data(), sizeof(IoctlSubmitGpfifo));
 | 
					    std::memcpy(¶ms, input.data(), sizeof(IoctlSubmitGpfifo));
 | 
				
			||||||
    LOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo={:X}, num_entries={:X}, flags={:X}",
 | 
					    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>();
 | 
					    auto entries = std::vector<IoctlGpfifoEntry>();
 | 
				
			||||||
    entries.resize(params.num_entries);
 | 
					    entries.resize(params.num_entries);
 | 
				
			||||||
    std::memcpy(&entries[0], &input.data()[sizeof(IoctlSubmitGpfifo)],
 | 
					    std::memcpy(&entries[0], &input.data()[sizeof(IoctlSubmitGpfifo)],
 | 
				
			||||||
                params.num_entries * sizeof(IoctlGpfifoEntry));
 | 
					                params.num_entries * sizeof(IoctlGpfifoEntry));
 | 
				
			||||||
    for (auto entry : entries) {
 | 
					    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);
 | 
					        Core::System::GetInstance().GPU().ProcessCommandList(va_addr, entry.sz);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    params.fence_out.id = 0;
 | 
					    params.fence_out.id = 0;
 | 
				
			||||||
 | 
				
			|||||||
@ -15,6 +15,7 @@ namespace Service::Nvidia::Devices {
 | 
				
			|||||||
class nvmap;
 | 
					class nvmap;
 | 
				
			||||||
constexpr u32 NVGPU_IOCTL_MAGIC('H');
 | 
					constexpr u32 NVGPU_IOCTL_MAGIC('H');
 | 
				
			||||||
constexpr u32 NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO(0x8);
 | 
					constexpr u32 NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO(0x8);
 | 
				
			||||||
 | 
					constexpr u32 NVGPU_IOCTL_CHANNEL_KICKOFF_PB(0x1b);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class nvhost_gpu final : public nvdevice {
 | 
					class nvhost_gpu final : public nvdevice {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
@ -158,14 +159,14 @@ private:
 | 
				
			|||||||
            BitField<31, 1, u32_le> unk2;
 | 
					            BitField<31, 1, u32_le> unk2;
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        VAddr Address() const {
 | 
					        Tegra::GPUVAddr Address() const {
 | 
				
			||||||
            return (static_cast<VAddr>(gpu_va_hi) << 32) | entry0;
 | 
					            return (static_cast<Tegra::GPUVAddr>(gpu_va_hi) << 32) | entry0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    static_assert(sizeof(IoctlGpfifoEntry) == 8, "IoctlGpfifoEntry is incorrect size");
 | 
					    static_assert(sizeof(IoctlGpfifoEntry) == 8, "IoctlGpfifoEntry is incorrect size");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct IoctlSubmitGpfifo {
 | 
					    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 num_entries; // number of fence objects being submitted
 | 
				
			||||||
        u32_le flags;
 | 
					        u32_le flags;
 | 
				
			||||||
        IoctlFence fence_out; // returned new fence object for others to wait on
 | 
					        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 AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& output);
 | 
				
			||||||
    u32 AllocateObjectContext(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 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 GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output);
 | 
				
			||||||
    u32 ChannelSetTimeout(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"},
 | 
					        {8, &NVDRV::SetClientPID, "SetClientPID"},
 | 
				
			||||||
        {9, nullptr, "DumpGraphicsMemoryInfo"},
 | 
					        {9, nullptr, "DumpGraphicsMemoryInfo"},
 | 
				
			||||||
        {10, nullptr, "InitializeDevtools"},
 | 
					        {10, nullptr, "InitializeDevtools"},
 | 
				
			||||||
        {11, nullptr, "Ioctl2"},
 | 
					        {11, &NVDRV::Ioctl, "Ioctl2"},
 | 
				
			||||||
        {12, nullptr, "Ioctl3"},
 | 
					        {12, nullptr, "Ioctl3"},
 | 
				
			||||||
        {13, &NVDRV::FinishInitialize, "FinishInitialize"},
 | 
					        {13, &NVDRV::FinishInitialize, "FinishInitialize"},
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user