mirror of
https://git.h3cjp.net/H3cJP/citra.git
synced 2024-11-23 20:23:05 +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) {
|
||||
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"},
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue