summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2020-10-29 21:16:24 -0700
committerGravatar bunnei2020-11-01 01:52:38 -0700
commite67b8678f8f261b582ff8449fff90058a9a7b901 (patch)
treee13da17862dadcd81a05ebcdf01887c574a9f81b /src
parentvideo_core: dma_pusher: Add support for integrity checks. (diff)
downloadyuzu-e67b8678f8f261b582ff8449fff90058a9a7b901.tar.gz
yuzu-e67b8678f8f261b582ff8449fff90058a9a7b901.tar.xz
yuzu-e67b8678f8f261b582ff8449fff90058a9a7b901.zip
hle service: nvdrv: nvhost_gpu: Update to use SyncpointManager and other improvements.
- Refactor so that SubmitGPFIFO and KickoffPB use shared functionality. - Implement add_wait and add_increment flags.
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp130
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_gpu.h19
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.cpp3
3 files changed, 106 insertions, 46 deletions
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
index f1966ac0e..2b9a8722c 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
@@ -7,14 +7,17 @@
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8#include "core/core.h" 8#include "core/core.h"
9#include "core/hle/service/nvdrv/devices/nvhost_gpu.h" 9#include "core/hle/service/nvdrv/devices/nvhost_gpu.h"
10#include "core/hle/service/nvdrv/syncpoint_manager.h"
10#include "core/memory.h" 11#include "core/memory.h"
11#include "video_core/gpu.h" 12#include "video_core/gpu.h"
12#include "video_core/memory_manager.h" 13#include "video_core/memory_manager.h"
13 14
14namespace Service::Nvidia::Devices { 15namespace Service::Nvidia::Devices {
15 16
16nvhost_gpu::nvhost_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_dev) 17nvhost_gpu::nvhost_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_dev,
17 : nvdevice(system), nvmap_dev(std::move(nvmap_dev)) {} 18 SyncpointManager& syncpoint_manager)
19 : nvdevice(system), nvmap_dev(std::move(nvmap_dev)), syncpoint_manager{syncpoint_manager} {}
20
18nvhost_gpu::~nvhost_gpu() = default; 21nvhost_gpu::~nvhost_gpu() = default;
19 22
20u32 nvhost_gpu::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, 23u32 nvhost_gpu::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
@@ -126,10 +129,9 @@ u32 nvhost_gpu::AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& ou
126 params.num_entries, params.flags, params.unk0, params.unk1, params.unk2, 129 params.num_entries, params.flags, params.unk0, params.unk1, params.unk2,
127 params.unk3); 130 params.unk3);
128 131
129 auto& gpu = system.GPU(); 132 params.fence_out.id = syncpoint_manager.AllocateSyncpoint();
130 params.fence_out.id = assigned_syncpoints; 133 params.fence_out.value = syncpoint_manager.RefreshSyncpoint(params.fence_out.id);
131 params.fence_out.value = gpu.GetSyncpointValue(assigned_syncpoints); 134
132 assigned_syncpoints++;
133 std::memcpy(output.data(), &params, output.size()); 135 std::memcpy(output.data(), &params, output.size());
134 return 0; 136 return 0;
135} 137}
@@ -145,39 +147,97 @@ u32 nvhost_gpu::AllocateObjectContext(const std::vector<u8>& input, std::vector<
145 return 0; 147 return 0;
146} 148}
147 149
148u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& output) { 150static std::vector<Tegra::CommandHeader> BuildWaitCommandList(Fence fence) {
149 if (input.size() < sizeof(IoctlSubmitGpfifo)) { 151 return {
150 UNIMPLEMENTED(); 152 Tegra::BuildCommandHeader(Tegra::BufferMethods::FenceValue, 1,
153 Tegra::SubmissionMode::Increasing),
154 {fence.value},
155 Tegra::BuildCommandHeader(Tegra::BufferMethods::FenceAction, 1,
156 Tegra::SubmissionMode::Increasing),
157 Tegra::GPU::FenceAction::Build(Tegra::GPU::FenceOperation::Acquire, fence.id),
158 };
159}
160
161static std::vector<Tegra::CommandHeader> BuildIncrementCommandList(Fence fence, u32 add_increment) {
162 std::vector<Tegra::CommandHeader> result{
163 Tegra::BuildCommandHeader(Tegra::BufferMethods::FenceValue, 1,
164 Tegra::SubmissionMode::Increasing),
165 {}};
166
167 for (u32 count = 0; count < add_increment; ++count) {
168 result.emplace_back(Tegra::BuildCommandHeader(Tegra::BufferMethods::FenceAction, 1,
169 Tegra::SubmissionMode::Increasing));
170 result.emplace_back(
171 Tegra::GPU::FenceAction::Build(Tegra::GPU::FenceOperation::Increment, fence.id));
151 } 172 }
152 IoctlSubmitGpfifo params{};
153 std::memcpy(&params, input.data(), sizeof(IoctlSubmitGpfifo));
154 LOG_TRACE(Service_NVDRV, "called, gpfifo={:X}, num_entries={:X}, flags={:X}", params.address,
155 params.num_entries, params.flags.raw);
156 173
157 ASSERT_MSG(input.size() == sizeof(IoctlSubmitGpfifo) + 174 return result;
158 params.num_entries * sizeof(Tegra::CommandListHeader), 175}
159 "Incorrect input size");
160 176
161 Tegra::CommandList entries(params.num_entries); 177static std::vector<Tegra::CommandHeader> BuildIncrementWithWfiCommandList(Fence fence,
162 std::memcpy(entries.data(), &input[sizeof(IoctlSubmitGpfifo)], 178 u32 add_increment) {
163 params.num_entries * sizeof(Tegra::CommandListHeader)); 179 std::vector<Tegra::CommandHeader> result{
180 Tegra::BuildCommandHeader(Tegra::BufferMethods::WaitForInterrupt, 1,
181 Tegra::SubmissionMode::Increasing),
182 {}};
183 const std::vector<Tegra::CommandHeader> increment{
184 BuildIncrementCommandList(fence, add_increment)};
185
186 result.insert(result.end(), increment.begin(), increment.end());
187
188 return result;
189}
164 190
165 UNIMPLEMENTED_IF(params.flags.add_wait.Value() != 0); 191u32 nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::vector<u8>& output,
166 UNIMPLEMENTED_IF(params.flags.add_increment.Value() != 0); 192 Tegra::CommandList&& entries) {
193 LOG_TRACE(Service_NVDRV, "called, gpfifo={:X}, num_entries={:X}, flags={:X}", params.address,
194 params.num_entries, params.flags.raw);
167 195
168 auto& gpu = system.GPU(); 196 auto& gpu = system.GPU();
169 u32 current_syncpoint_value = gpu.GetSyncpointValue(params.fence_out.id); 197 if (params.flags.add_wait.Value() &&
170 if (params.flags.increment.Value()) { 198 !syncpoint_manager.IsSyncpointExpired(params.fence_out.id, params.fence_out.value)) {
171 params.fence_out.value += current_syncpoint_value; 199 gpu.PushGPUEntries(Tegra::CommandList{BuildWaitCommandList(params.fence_out)});
200 }
201
202 if (params.flags.add_increment.Value() || params.flags.increment.Value()) {
203 const u32 increment_value = params.flags.increment.Value() ? params.fence_out.value : 0;
204 params.fence_out.value = syncpoint_manager.IncreaseSyncpoint(
205 params.fence_out.id, params.AddIncrementValue() + increment_value);
172 } else { 206 } else {
173 params.fence_out.value = current_syncpoint_value; 207 params.fence_out.value = syncpoint_manager.GetSyncpointMax(params.fence_out.id);
174 } 208 }
209
210 entries.RefreshIntegrityChecks(gpu);
175 gpu.PushGPUEntries(std::move(entries)); 211 gpu.PushGPUEntries(std::move(entries));
176 212
213 if (params.flags.add_increment.Value()) {
214 if (params.flags.suppress_wfi) {
215 gpu.PushGPUEntries(Tegra::CommandList{
216 BuildIncrementCommandList(params.fence_out, params.AddIncrementValue())});
217 } else {
218 gpu.PushGPUEntries(Tegra::CommandList{
219 BuildIncrementWithWfiCommandList(params.fence_out, params.AddIncrementValue())});
220 }
221 }
222
177 std::memcpy(output.data(), &params, sizeof(IoctlSubmitGpfifo)); 223 std::memcpy(output.data(), &params, sizeof(IoctlSubmitGpfifo));
178 return 0; 224 return 0;
179} 225}
180 226
227u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& output) {
228 if (input.size() < sizeof(IoctlSubmitGpfifo)) {
229 UNIMPLEMENTED();
230 }
231 IoctlSubmitGpfifo params{};
232 std::memcpy(&params, input.data(), sizeof(IoctlSubmitGpfifo));
233
234 Tegra::CommandList entries(params.num_entries);
235 std::memcpy(entries.command_lists.data(), &input[sizeof(IoctlSubmitGpfifo)],
236 params.num_entries * sizeof(Tegra::CommandListHeader));
237
238 return SubmitGPFIFOImpl(params, output, std::move(entries));
239}
240
181u32 nvhost_gpu::KickoffPB(const std::vector<u8>& input, std::vector<u8>& output, 241u32 nvhost_gpu::KickoffPB(const std::vector<u8>& input, std::vector<u8>& output,
182 const std::vector<u8>& input2, IoctlVersion version) { 242 const std::vector<u8>& input2, IoctlVersion version) {
183 if (input.size() < sizeof(IoctlSubmitGpfifo)) { 243 if (input.size() < sizeof(IoctlSubmitGpfifo)) {
@@ -185,31 +245,17 @@ u32 nvhost_gpu::KickoffPB(const std::vector<u8>& input, std::vector<u8>& output,
185 } 245 }
186 IoctlSubmitGpfifo params{}; 246 IoctlSubmitGpfifo params{};
187 std::memcpy(&params, input.data(), sizeof(IoctlSubmitGpfifo)); 247 std::memcpy(&params, input.data(), sizeof(IoctlSubmitGpfifo));
188 LOG_TRACE(Service_NVDRV, "called, gpfifo={:X}, num_entries={:X}, flags={:X}", params.address,
189 params.num_entries, params.flags.raw);
190 248
191 Tegra::CommandList entries(params.num_entries); 249 Tegra::CommandList entries(params.num_entries);
192 if (version == IoctlVersion::Version2) { 250 if (version == IoctlVersion::Version2) {
193 std::memcpy(entries.data(), input2.data(), 251 std::memcpy(entries.command_lists.data(), input2.data(),
194 params.num_entries * sizeof(Tegra::CommandListHeader)); 252 params.num_entries * sizeof(Tegra::CommandListHeader));
195 } else { 253 } else {
196 system.Memory().ReadBlock(params.address, entries.data(), 254 system.Memory().ReadBlock(params.address, entries.command_lists.data(),
197 params.num_entries * sizeof(Tegra::CommandListHeader)); 255 params.num_entries * sizeof(Tegra::CommandListHeader));
198 } 256 }
199 UNIMPLEMENTED_IF(params.flags.add_wait.Value() != 0);
200 UNIMPLEMENTED_IF(params.flags.add_increment.Value() != 0);
201 257
202 auto& gpu = system.GPU(); 258 return SubmitGPFIFOImpl(params, output, std::move(entries));
203 u32 current_syncpoint_value = gpu.GetSyncpointValue(params.fence_out.id);
204 if (params.flags.increment.Value()) {
205 params.fence_out.value += current_syncpoint_value;
206 } else {
207 params.fence_out.value = current_syncpoint_value;
208 }
209 gpu.PushGPUEntries(std::move(entries));
210
211 std::memcpy(output.data(), &params, output.size());
212 return 0;
213} 259}
214 260
215u32 nvhost_gpu::GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output) { 261u32 nvhost_gpu::GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output) {
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
index 2ac74743f..80054510f 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
@@ -11,6 +11,11 @@
11#include "common/swap.h" 11#include "common/swap.h"
12#include "core/hle/service/nvdrv/devices/nvdevice.h" 12#include "core/hle/service/nvdrv/devices/nvdevice.h"
13#include "core/hle/service/nvdrv/nvdata.h" 13#include "core/hle/service/nvdrv/nvdata.h"
14#include "video_core/dma_pusher.h"
15
16namespace Service::Nvidia {
17class SyncpointManager;
18}
14 19
15namespace Service::Nvidia::Devices { 20namespace Service::Nvidia::Devices {
16 21
@@ -21,7 +26,8 @@ constexpr u32 NVGPU_IOCTL_CHANNEL_KICKOFF_PB(0x1b);
21 26
22class nvhost_gpu final : public nvdevice { 27class nvhost_gpu final : public nvdevice {
23public: 28public:
24 explicit nvhost_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_dev); 29 explicit nvhost_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_dev,
30 SyncpointManager& syncpoint_manager);
25 ~nvhost_gpu() override; 31 ~nvhost_gpu() override;
26 32
27 u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, 33 u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
@@ -162,10 +168,15 @@ private:
162 u32_le raw; 168 u32_le raw;
163 BitField<0, 1, u32_le> add_wait; // append a wait sync_point to the list 169 BitField<0, 1, u32_le> add_wait; // append a wait sync_point to the list
164 BitField<1, 1, u32_le> add_increment; // append an increment to the list 170 BitField<1, 1, u32_le> add_increment; // append an increment to the list
165 BitField<2, 1, u32_le> new_hw_format; // Mostly ignored 171 BitField<2, 1, u32_le> new_hw_format; // mostly ignored
172 BitField<4, 1, u32_le> suppress_wfi; // suppress wait for interrupt
166 BitField<8, 1, u32_le> increment; // increment the returned fence 173 BitField<8, 1, u32_le> increment; // increment the returned fence
167 } flags; 174 } flags;
168 Fence fence_out; // returned new fence object for others to wait on 175 Fence fence_out; // returned new fence object for others to wait on
176
177 u32 AddIncrementValue() const {
178 return flags.add_increment.Value() << 1;
179 }
169 }; 180 };
170 static_assert(sizeof(IoctlSubmitGpfifo) == 16 + sizeof(Fence), 181 static_assert(sizeof(IoctlSubmitGpfifo) == 16 + sizeof(Fence),
171 "IoctlSubmitGpfifo is incorrect size"); 182 "IoctlSubmitGpfifo is incorrect size");
@@ -190,6 +201,8 @@ private:
190 u32 SetChannelPriority(const std::vector<u8>& input, std::vector<u8>& output); 201 u32 SetChannelPriority(const std::vector<u8>& input, std::vector<u8>& output);
191 u32 AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& output); 202 u32 AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& output);
192 u32 AllocateObjectContext(const std::vector<u8>& input, std::vector<u8>& output); 203 u32 AllocateObjectContext(const std::vector<u8>& input, std::vector<u8>& output);
204 u32 SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::vector<u8>& output,
205 Tegra::CommandList&& entries);
193 u32 SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& output); 206 u32 SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& output);
194 u32 KickoffPB(const std::vector<u8>& input, std::vector<u8>& output, 207 u32 KickoffPB(const std::vector<u8>& input, std::vector<u8>& output,
195 const std::vector<u8>& input2, IoctlVersion version); 208 const std::vector<u8>& input2, IoctlVersion version);
@@ -198,7 +211,7 @@ private:
198 u32 ChannelSetTimeslice(const std::vector<u8>& input, std::vector<u8>& output); 211 u32 ChannelSetTimeslice(const std::vector<u8>& input, std::vector<u8>& output);
199 212
200 std::shared_ptr<nvmap> nvmap_dev; 213 std::shared_ptr<nvmap> nvmap_dev;
201 u32 assigned_syncpoints{}; 214 SyncpointManager& syncpoint_manager;
202}; 215};
203 216
204} // namespace Service::Nvidia::Devices 217} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp
index 2e52f8bd6..a46755cdc 100644
--- a/src/core/hle/service/nvdrv/nvdrv.cpp
+++ b/src/core/hle/service/nvdrv/nvdrv.cpp
@@ -47,7 +47,8 @@ Module::Module(Core::System& system) : syncpoint_manager{system.GPU()} {
47 } 47 }
48 auto nvmap_dev = std::make_shared<Devices::nvmap>(system); 48 auto nvmap_dev = std::make_shared<Devices::nvmap>(system);
49 devices["/dev/nvhost-as-gpu"] = std::make_shared<Devices::nvhost_as_gpu>(system, nvmap_dev); 49 devices["/dev/nvhost-as-gpu"] = std::make_shared<Devices::nvhost_as_gpu>(system, nvmap_dev);
50 devices["/dev/nvhost-gpu"] = std::make_shared<Devices::nvhost_gpu>(system, nvmap_dev); 50 devices["/dev/nvhost-gpu"] =
51 std::make_shared<Devices::nvhost_gpu>(system, nvmap_dev, syncpoint_manager);
51 devices["/dev/nvhost-ctrl-gpu"] = std::make_shared<Devices::nvhost_ctrl_gpu>(system); 52 devices["/dev/nvhost-ctrl-gpu"] = std::make_shared<Devices::nvhost_ctrl_gpu>(system);
52 devices["/dev/nvmap"] = nvmap_dev; 53 devices["/dev/nvmap"] = nvmap_dev;
53 devices["/dev/nvdisp_disp0"] = std::make_shared<Devices::nvdisp_disp0>(system, nvmap_dev); 54 devices["/dev/nvdisp_disp0"] = std::make_shared<Devices::nvdisp_disp0>(system, nvmap_dev);