diff options
| author | 2018-07-21 15:50:02 -0500 | |
|---|---|---|
| committer | 2018-07-21 15:50:02 -0500 | |
| commit | 5c49e56d417fd98523574e54eb8705d11ea83d88 (patch) | |
| tree | 6bfae33c9ae40c2be7fb04266a2c941e63040a9c /src | |
| parent | Merge pull request #754 from lioncash/part (diff) | |
| download | yuzu-5c49e56d417fd98523574e54eb8705d11ea83d88.tar.gz yuzu-5c49e56d417fd98523574e54eb8705d11ea83d88.tar.xz yuzu-5c49e56d417fd98523574e54eb8705d11ea83d88.zip | |
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!
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp | 30 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_gpu.h | 8 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/interface.cpp | 2 |
3 files changed, 34 insertions, 6 deletions
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<u8>& input, std::vector<u | |||
| 42 | if (command.cmd == NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO) { | 42 | if (command.cmd == NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO) { |
| 43 | return SubmitGPFIFO(input, output); | 43 | return SubmitGPFIFO(input, output); |
| 44 | } | 44 | } |
| 45 | if (command.cmd == NVGPU_IOCTL_CHANNEL_KICKOFF_PB) { | ||
| 46 | return KickoffPB(input, output); | ||
| 47 | } | ||
| 45 | } | 48 | } |
| 46 | 49 | ||
| 47 | UNIMPLEMENTED_MSG("Unimplemented ioctl"); | 50 | UNIMPLEMENTED_MSG("Unimplemented ioctl"); |
| @@ -127,14 +130,37 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& outp | |||
| 127 | IoctlSubmitGpfifo params{}; | 130 | IoctlSubmitGpfifo params{}; |
| 128 | std::memcpy(¶ms, input.data(), sizeof(IoctlSubmitGpfifo)); | 131 | std::memcpy(¶ms, input.data(), sizeof(IoctlSubmitGpfifo)); |
| 129 | LOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo={:X}, num_entries={:X}, flags={:X}", | 132 | LOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo={:X}, num_entries={:X}, flags={:X}", |
| 130 | params.gpfifo, params.num_entries, params.flags); | 133 | params.address, params.num_entries, params.flags); |
| 131 | 134 | ||
| 132 | auto entries = std::vector<IoctlGpfifoEntry>(); | 135 | auto entries = std::vector<IoctlGpfifoEntry>(); |
| 133 | entries.resize(params.num_entries); | 136 | entries.resize(params.num_entries); |
| 134 | std::memcpy(&entries[0], &input.data()[sizeof(IoctlSubmitGpfifo)], | 137 | std::memcpy(&entries[0], &input.data()[sizeof(IoctlSubmitGpfifo)], |
| 135 | params.num_entries * sizeof(IoctlGpfifoEntry)); | 138 | params.num_entries * sizeof(IoctlGpfifoEntry)); |
| 136 | for (auto entry : entries) { | 139 | for (auto entry : entries) { |
| 137 | VAddr va_addr = entry.Address(); | 140 | Tegra::GPUVAddr va_addr = entry.Address(); |
| 141 | Core::System::GetInstance().GPU().ProcessCommandList(va_addr, entry.sz); | ||
| 142 | } | ||
| 143 | params.fence_out.id = 0; | ||
| 144 | params.fence_out.value = 0; | ||
| 145 | std::memcpy(output.data(), ¶ms, output.size()); | ||
| 146 | return 0; | ||
| 147 | } | ||
| 148 | |||
| 149 | u32 nvhost_gpu::KickoffPB(const std::vector<u8>& input, std::vector<u8>& output) { | ||
| 150 | if (input.size() < sizeof(IoctlSubmitGpfifo)) { | ||
| 151 | UNIMPLEMENTED(); | ||
| 152 | } | ||
| 153 | IoctlSubmitGpfifo params{}; | ||
| 154 | std::memcpy(¶ms, input.data(), sizeof(IoctlSubmitGpfifo)); | ||
| 155 | LOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo={:X}, num_entries={:X}, flags={:X}", | ||
| 156 | params.address, params.num_entries, params.flags); | ||
| 157 | |||
| 158 | std::vector<IoctlGpfifoEntry> entries(params.num_entries); | ||
| 159 | Memory::ReadBlock(params.address, entries.data(), | ||
| 160 | params.num_entries * sizeof(IoctlGpfifoEntry)); | ||
| 161 | |||
| 162 | for (auto entry : entries) { | ||
| 163 | Tegra::GPUVAddr va_addr = entry.Address(); | ||
| 138 | Core::System::GetInstance().GPU().ProcessCommandList(va_addr, entry.sz); | 164 | Core::System::GetInstance().GPU().ProcessCommandList(va_addr, entry.sz); |
| 139 | } | 165 | } |
| 140 | params.fence_out.id = 0; | 166 | 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 { | |||
| 15 | class nvmap; | 15 | class nvmap; |
| 16 | constexpr u32 NVGPU_IOCTL_MAGIC('H'); | 16 | constexpr u32 NVGPU_IOCTL_MAGIC('H'); |
| 17 | constexpr u32 NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO(0x8); | 17 | constexpr u32 NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO(0x8); |
| 18 | constexpr u32 NVGPU_IOCTL_CHANNEL_KICKOFF_PB(0x1b); | ||
| 18 | 19 | ||
| 19 | class nvhost_gpu final : public nvdevice { | 20 | class nvhost_gpu final : public nvdevice { |
| 20 | public: | 21 | public: |
| @@ -158,14 +159,14 @@ private: | |||
| 158 | BitField<31, 1, u32_le> unk2; | 159 | BitField<31, 1, u32_le> unk2; |
| 159 | }; | 160 | }; |
| 160 | 161 | ||
| 161 | VAddr Address() const { | 162 | Tegra::GPUVAddr Address() const { |
| 162 | return (static_cast<VAddr>(gpu_va_hi) << 32) | entry0; | 163 | return (static_cast<Tegra::GPUVAddr>(gpu_va_hi) << 32) | entry0; |
| 163 | } | 164 | } |
| 164 | }; | 165 | }; |
| 165 | static_assert(sizeof(IoctlGpfifoEntry) == 8, "IoctlGpfifoEntry is incorrect size"); | 166 | static_assert(sizeof(IoctlGpfifoEntry) == 8, "IoctlGpfifoEntry is incorrect size"); |
| 166 | 167 | ||
| 167 | struct IoctlSubmitGpfifo { | 168 | struct IoctlSubmitGpfifo { |
| 168 | u64_le gpfifo; // (ignored) pointer to gpfifo fence structs | 169 | u64_le address; // pointer to gpfifo entry structs |
| 169 | u32_le num_entries; // number of fence objects being submitted | 170 | u32_le num_entries; // number of fence objects being submitted |
| 170 | u32_le flags; | 171 | u32_le flags; |
| 171 | IoctlFence fence_out; // returned new fence object for others to wait on | 172 | IoctlFence fence_out; // returned new fence object for others to wait on |
| @@ -193,6 +194,7 @@ private: | |||
| 193 | u32 AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& output); | 194 | u32 AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& output); |
| 194 | u32 AllocateObjectContext(const std::vector<u8>& input, std::vector<u8>& output); | 195 | u32 AllocateObjectContext(const std::vector<u8>& input, std::vector<u8>& output); |
| 195 | u32 SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& output); | 196 | u32 SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& output); |
| 197 | u32 KickoffPB(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 196 | u32 GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output); | 198 | u32 GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output); |
| 197 | u32 ChannelSetTimeout(const std::vector<u8>& input, std::vector<u8>& output); | 199 | u32 ChannelSetTimeout(const std::vector<u8>& input, std::vector<u8>& output); |
| 198 | 200 | ||
diff --git a/src/core/hle/service/nvdrv/interface.cpp b/src/core/hle/service/nvdrv/interface.cpp index b10efd5c9..1b497b814 100644 --- a/src/core/hle/service/nvdrv/interface.cpp +++ b/src/core/hle/service/nvdrv/interface.cpp | |||
| @@ -101,7 +101,7 @@ NVDRV::NVDRV(std::shared_ptr<Module> nvdrv, const char* name) | |||
| 101 | {8, &NVDRV::SetClientPID, "SetClientPID"}, | 101 | {8, &NVDRV::SetClientPID, "SetClientPID"}, |
| 102 | {9, nullptr, "DumpGraphicsMemoryInfo"}, | 102 | {9, nullptr, "DumpGraphicsMemoryInfo"}, |
| 103 | {10, nullptr, "InitializeDevtools"}, | 103 | {10, nullptr, "InitializeDevtools"}, |
| 104 | {11, nullptr, "Ioctl2"}, | 104 | {11, &NVDRV::Ioctl, "Ioctl2"}, |
| 105 | {12, nullptr, "Ioctl3"}, | 105 | {12, nullptr, "Ioctl3"}, |
| 106 | {13, &NVDRV::FinishInitialize, "FinishInitialize"}, | 106 | {13, &NVDRV::FinishInitialize, "FinishInitialize"}, |
| 107 | }; | 107 | }; |