summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Subv2018-07-21 15:50:02 -0500
committerGravatar Subv2018-07-21 15:50:02 -0500
commit5c49e56d417fd98523574e54eb8705d11ea83d88 (patch)
tree6bfae33c9ae40c2be7fb04266a2c941e63040a9c /src
parentMerge pull request #754 from lioncash/part (diff)
downloadyuzu-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.cpp30
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_gpu.h8
-rw-r--r--src/core/hle/service/nvdrv/interface.cpp2
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(&params, input.data(), sizeof(IoctlSubmitGpfifo)); 131 std::memcpy(&params, 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(), &params, output.size());
146 return 0;
147}
148
149u32 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(&params, 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 {
15class nvmap; 15class nvmap;
16constexpr u32 NVGPU_IOCTL_MAGIC('H'); 16constexpr u32 NVGPU_IOCTL_MAGIC('H');
17constexpr u32 NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO(0x8); 17constexpr u32 NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO(0x8);
18constexpr u32 NVGPU_IOCTL_CHANNEL_KICKOFF_PB(0x1b);
18 19
19class nvhost_gpu final : public nvdevice { 20class nvhost_gpu final : public nvdevice {
20public: 21public:
@@ -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 };