diff options
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/nvdata.h | 2 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_3d.cpp | 5 | ||||
| -rw-r--r-- | src/video_core/gpu.cpp | 24 | ||||
| -rw-r--r-- | src/video_core/gpu.h | 24 |
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(¶ms, input.data(), sizeof(IoctlSubmitGpfifo)); | 144 | std::memcpy(¶ms, 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(¶ms, input.data(), sizeof(IoctlSubmitGpfifo)); | 179 | std::memcpy(¶ms, 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(), ¶ms, output.size()); | 199 | std::memcpy(output.data(), ¶ms, 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 | ||
| 6 | namespace Service::Nvidia { | 6 | namespace Service::Nvidia { |
| 7 | 7 | ||
| 8 | constexpr u32 MaxSyncPoints = 192; | ||
| 9 | |||
| 8 | struct Fence { | 10 | struct 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 | ||
| 353 | void Maxwell3D::DrawArrays() { | 354 | void 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 | ||
| 69 | void 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 | |||
| 85 | u32 GPU::GetSyncpointValue(const u32 syncpoint_id) const { | ||
| 86 | return syncpoints[syncpoint_id].load(); | ||
| 87 | } | ||
| 88 | |||
| 89 | void GPU::RegisterEvent(const u32 event_id, const u32 syncpoint_id, const u32 value) { | ||
| 90 | events[syncpoint_id].emplace_back(event_id, value); | ||
| 91 | } | ||
| 92 | |||
| 69 | u32 RenderTargetBytesPerPixel(RenderTargetFormat format) { | 93 | u32 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 | ||
| 240 | protected: | ||
| 241 | virtual void TriggerCpuInterrupt(const u32 event_id) const { | ||
| 242 | // Todo implement this | ||
| 243 | } | ||
| 244 | |||
| 231 | private: | 245 | private: |
| 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) \ |