summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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/nvdata.h2
-rw-r--r--src/video_core/engines/maxwell_3d.cpp5
-rw-r--r--src/video_core/gpu.cpp24
-rw-r--r--src/video_core/gpu.h24
6 files changed, 84 insertions, 9 deletions
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
index 8a53eddb1..9d1107594 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
@@ -143,7 +143,7 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& outp
143 IoctlSubmitGpfifo params{}; 143 IoctlSubmitGpfifo params{};
144 std::memcpy(&params, input.data(), sizeof(IoctlSubmitGpfifo)); 144 std::memcpy(&params, input.data(), sizeof(IoctlSubmitGpfifo));
145 LOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo={:X}, num_entries={:X}, flags={:X}", 145 LOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo={:X}, num_entries={:X}, flags={:X}",
146 params.address, params.num_entries, params.flags); 146 params.address, params.num_entries, params.flags.raw);
147 147
148 ASSERT_MSG(input.size() == sizeof(IoctlSubmitGpfifo) + 148 ASSERT_MSG(input.size() == sizeof(IoctlSubmitGpfifo) +
149 params.num_entries * sizeof(Tegra::CommandListHeader), 149 params.num_entries * sizeof(Tegra::CommandListHeader),
@@ -153,7 +153,17 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& outp
153 std::memcpy(entries.data(), &input[sizeof(IoctlSubmitGpfifo)], 153 std::memcpy(entries.data(), &input[sizeof(IoctlSubmitGpfifo)],
154 params.num_entries * sizeof(Tegra::CommandListHeader)); 154 params.num_entries * sizeof(Tegra::CommandListHeader));
155 155
156 Core::System::GetInstance().GPU().PushGPUEntries(std::move(entries)); 156 UNIMPLEMENTED_IF(params.flags.add_wait.Value() != 0);
157 UNIMPLEMENTED_IF(params.flags.add_increment.Value() != 0);
158
159 auto& gpu = Core::System::GetInstance().GPU();
160 u32 current_syncpoint_value = gpu.GetSyncpointValue(params.fence_out.id);
161 if (params.flags.increment.Value()) {
162 params.fence_out.value += current_syncpoint_value;
163 } else {
164 params.fence_out.value = current_syncpoint_value;
165 }
166 gpu.PushGPUEntries(std::move(entries));
157 167
158 // TODO(Blinkhawk): Figure how thoios fence is set 168 // TODO(Blinkhawk): Figure how thoios fence is set
159 // params.fence_out.value = 0; 169 // params.fence_out.value = 0;
@@ -168,16 +178,24 @@ u32 nvhost_gpu::KickoffPB(const std::vector<u8>& input, std::vector<u8>& output)
168 IoctlSubmitGpfifo params{}; 178 IoctlSubmitGpfifo params{};
169 std::memcpy(&params, input.data(), sizeof(IoctlSubmitGpfifo)); 179 std::memcpy(&params, input.data(), sizeof(IoctlSubmitGpfifo));
170 LOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo={:X}, num_entries={:X}, flags={:X}", 180 LOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo={:X}, num_entries={:X}, flags={:X}",
171 params.address, params.num_entries, params.flags); 181 params.address, params.num_entries, params.flags.raw);
172 182
173 Tegra::CommandList entries(params.num_entries); 183 Tegra::CommandList entries(params.num_entries);
174 Memory::ReadBlock(params.address, entries.data(), 184 Memory::ReadBlock(params.address, entries.data(),
175 params.num_entries * sizeof(Tegra::CommandListHeader)); 185 params.num_entries * sizeof(Tegra::CommandListHeader));
176 186
177 Core::System::GetInstance().GPU().PushGPUEntries(std::move(entries)); 187 UNIMPLEMENTED_IF(params.flags.add_wait.Value() != 0);
188 UNIMPLEMENTED_IF(params.flags.add_increment.Value() != 0);
189
190 auto& gpu = Core::System::GetInstance().GPU();
191 u32 current_syncpoint_value = gpu.GetSyncpointValue(params.fence_out.id);
192 if (params.flags.increment.Value()) {
193 params.fence_out.value += current_syncpoint_value;
194 } else {
195 params.fence_out.value = current_syncpoint_value;
196 }
197 gpu.PushGPUEntries(std::move(entries));
178 198
179 // TODO(Blinkhawk): Figure how thoios fence is set
180 // params.fence_out.value = 0;
181 std::memcpy(output.data(), &params, output.size()); 199 std::memcpy(output.data(), &params, output.size());
182 return 0; 200 return 0;
183} 201}
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
index d95cedb09..0729eeb8d 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
@@ -153,7 +153,13 @@ private:
153 struct IoctlSubmitGpfifo { 153 struct IoctlSubmitGpfifo {
154 u64_le address; // pointer to gpfifo entry structs 154 u64_le address; // pointer to gpfifo entry structs
155 u32_le num_entries; // number of fence objects being submitted 155 u32_le num_entries; // number of fence objects being submitted
156 u32_le flags; 156 union {
157 u32_le raw;
158 BitField<0, 1, u32_le> add_wait; // append a wait sync_point to the list
159 BitField<1, 1, u32_le> add_increment; // append an increment to the list
160 BitField<2, 1, u32_le> new_hw_format; // Mostly ignored
161 BitField<8, 1, u32_le> increment; // increment the returned fence
162 } flags;
157 Fence fence_out; // returned new fence object for others to wait on 163 Fence fence_out; // returned new fence object for others to wait on
158 }; 164 };
159 static_assert(sizeof(IoctlSubmitGpfifo) == 16 + sizeof(Fence), 165 static_assert(sizeof(IoctlSubmitGpfifo) == 16 + sizeof(Fence),
diff --git a/src/core/hle/service/nvdrv/nvdata.h b/src/core/hle/service/nvdrv/nvdata.h
index 7e1dce232..fd5f79f36 100644
--- a/src/core/hle/service/nvdrv/nvdata.h
+++ b/src/core/hle/service/nvdrv/nvdata.h
@@ -5,6 +5,8 @@
5 5
6namespace Service::Nvidia { 6namespace Service::Nvidia {
7 7
8constexpr u32 MaxSyncPoints = 192;
9
8struct Fence { 10struct Fence {
9 s32 id; 11 s32 id;
10 u32 value; 12 u32 value;
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index 8755b8af4..224c27bd2 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -346,8 +346,9 @@ void Maxwell3D::ProcessSyncPoint() {
346 const u32 sync_point = regs.sync_info.sync_point.Value(); 346 const u32 sync_point = regs.sync_info.sync_point.Value();
347 const u32 increment = regs.sync_info.increment.Value(); 347 const u32 increment = regs.sync_info.increment.Value();
348 const u32 cache_flush = regs.sync_info.unknown.Value(); 348 const u32 cache_flush = regs.sync_info.unknown.Value();
349 LOG_DEBUG(HW_GPU, "Syncpoint set {}, increment: {}, unk: {}", sync_point, increment, 349 if (increment) {
350 cache_flush); 350 system.GPU().IncrementSyncPoint(sync_point);
351 }
351} 352}
352 353
353void Maxwell3D::DrawArrays() { 354void Maxwell3D::DrawArrays() {
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp
index 52706505b..1d12f0493 100644
--- a/src/video_core/gpu.cpp
+++ b/src/video_core/gpu.cpp
@@ -66,6 +66,30 @@ const DmaPusher& GPU::DmaPusher() const {
66 return *dma_pusher; 66 return *dma_pusher;
67} 67}
68 68
69void GPU::IncrementSyncPoint(const u32 syncpoint_id) {
70 syncpoints[syncpoint_id]++;
71 if (!events[syncpoint_id].empty()) {
72 u32 value = syncpoints[syncpoint_id].load();
73 auto it = events[syncpoint_id].begin();
74 while (it != events[syncpoint_id].end()) {
75 if (value >= it->value) {
76 TriggerCpuInterrupt(it->event_id);
77 it = events[syncpoint_id].erase(it);
78 continue;
79 }
80 it++;
81 }
82 }
83}
84
85u32 GPU::GetSyncpointValue(const u32 syncpoint_id) const {
86 return syncpoints[syncpoint_id].load();
87}
88
89void GPU::RegisterEvent(const u32 event_id, const u32 syncpoint_id, const u32 value) {
90 events[syncpoint_id].emplace_back(event_id, value);
91}
92
69u32 RenderTargetBytesPerPixel(RenderTargetFormat format) { 93u32 RenderTargetBytesPerPixel(RenderTargetFormat format) {
70 ASSERT(format != RenderTargetFormat::NONE); 94 ASSERT(format != RenderTargetFormat::NONE);
71 95
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h
index fe6628923..4c97d6c6f 100644
--- a/src/video_core/gpu.h
+++ b/src/video_core/gpu.h
@@ -5,8 +5,11 @@
5#pragma once 5#pragma once
6 6
7#include <array> 7#include <array>
8#include <atomic>
9#include <list>
8#include <memory> 10#include <memory>
9#include "common/common_types.h" 11#include "common/common_types.h"
12#include "core/hle/service/nvdrv/nvdata.h"
10#include "core/hle/service/nvflinger/buffer_queue.h" 13#include "core/hle/service/nvflinger/buffer_queue.h"
11#include "video_core/dma_pusher.h" 14#include "video_core/dma_pusher.h"
12 15
@@ -164,6 +167,12 @@ public:
164 /// Returns a reference to the GPU DMA pusher. 167 /// Returns a reference to the GPU DMA pusher.
165 Tegra::DmaPusher& DmaPusher(); 168 Tegra::DmaPusher& DmaPusher();
166 169
170 void IncrementSyncPoint(const u32 syncpoint_id);
171
172 u32 GetSyncpointValue(const u32 syncpoint_id) const;
173
174 void RegisterEvent(const u32 event_id, const u32 sync_point_id, const u32 value);
175
167 /// Returns a const reference to the GPU DMA pusher. 176 /// Returns a const reference to the GPU DMA pusher.
168 const Tegra::DmaPusher& DmaPusher() const; 177 const Tegra::DmaPusher& DmaPusher() const;
169 178
@@ -228,6 +237,11 @@ public:
228 /// Notify rasterizer that any caches of the specified region should be flushed and invalidated 237 /// Notify rasterizer that any caches of the specified region should be flushed and invalidated
229 virtual void FlushAndInvalidateRegion(CacheAddr addr, u64 size) = 0; 238 virtual void FlushAndInvalidateRegion(CacheAddr addr, u64 size) = 0;
230 239
240protected:
241 virtual void TriggerCpuInterrupt(const u32 event_id) const {
242 // Todo implement this
243 }
244
231private: 245private:
232 void ProcessBindMethod(const MethodCall& method_call); 246 void ProcessBindMethod(const MethodCall& method_call);
233 void ProcessSemaphoreTriggerMethod(); 247 void ProcessSemaphoreTriggerMethod();
@@ -262,6 +276,16 @@ private:
262 std::unique_ptr<Engines::MaxwellDMA> maxwell_dma; 276 std::unique_ptr<Engines::MaxwellDMA> maxwell_dma;
263 /// Inline memory engine 277 /// Inline memory engine
264 std::unique_ptr<Engines::KeplerMemory> kepler_memory; 278 std::unique_ptr<Engines::KeplerMemory> kepler_memory;
279
280 std::array<std::atomic<u32>, Service::Nvidia::MaxSyncPoints> syncpoints{};
281
282 struct Event {
283 Event(const u32 event_id, const u32 value) : event_id(event_id), value(value) {}
284 u32 event_id;
285 u32 value;
286 };
287
288 std::array<std::list<Event>, Service::Nvidia::MaxSyncPoints> events;
265}; 289};
266 290
267#define ASSERT_REG_POSITION(field_name, position) \ 291#define ASSERT_REG_POSITION(field_name, position) \