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"},
|
||||||
};
|
};
|
||||||
|
|
Reference in New Issue