diff options
| author | 2022-01-30 10:31:13 +0100 | |
|---|---|---|
| committer | 2022-10-06 21:00:52 +0200 | |
| commit | 668e80a9f42fb4ce0e16f6381d05bcbd286b2da1 (patch) | |
| tree | a1c668d6c3d00eade849b1d31dba4116095e4c12 /src/core | |
| parent | Texture Cache: Fix GC and GPU Modified on Joins. (diff) | |
| download | yuzu-668e80a9f42fb4ce0e16f6381d05bcbd286b2da1.tar.gz yuzu-668e80a9f42fb4ce0e16f6381d05bcbd286b2da1.tar.xz yuzu-668e80a9f42fb4ce0e16f6381d05bcbd286b2da1.zip | |
VideoCore: Refactor syncing.
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/core.cpp | 12 | ||||
| -rw-r--r-- | src/core/core.h | 9 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp | 19 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_ctrl.h | 4 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp | 10 | ||||
| -rw-r--r-- | src/core/hle/service/nvflinger/nvflinger.cpp | 9 |
7 files changed, 53 insertions, 12 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp index 121092868..fa059a394 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -51,6 +51,7 @@ | |||
| 51 | #include "core/telemetry_session.h" | 51 | #include "core/telemetry_session.h" |
| 52 | #include "core/tools/freezer.h" | 52 | #include "core/tools/freezer.h" |
| 53 | #include "network/network.h" | 53 | #include "network/network.h" |
| 54 | #include "video_core/host1x/host1x.h" | ||
| 54 | #include "video_core/renderer_base.h" | 55 | #include "video_core/renderer_base.h" |
| 55 | #include "video_core/video_core.h" | 56 | #include "video_core/video_core.h" |
| 56 | 57 | ||
| @@ -215,6 +216,7 @@ struct System::Impl { | |||
| 215 | 216 | ||
| 216 | telemetry_session = std::make_unique<Core::TelemetrySession>(); | 217 | telemetry_session = std::make_unique<Core::TelemetrySession>(); |
| 217 | 218 | ||
| 219 | host1x_core = std::make_unique<Tegra::Host1x::Host1x>(); | ||
| 218 | gpu_core = VideoCore::CreateGPU(emu_window, system); | 220 | gpu_core = VideoCore::CreateGPU(emu_window, system); |
| 219 | if (!gpu_core) { | 221 | if (!gpu_core) { |
| 220 | return SystemResultStatus::ErrorVideoCore; | 222 | return SystemResultStatus::ErrorVideoCore; |
| @@ -373,6 +375,7 @@ struct System::Impl { | |||
| 373 | app_loader.reset(); | 375 | app_loader.reset(); |
| 374 | audio_core.reset(); | 376 | audio_core.reset(); |
| 375 | gpu_core.reset(); | 377 | gpu_core.reset(); |
| 378 | host1x_core.reset(); | ||
| 376 | perf_stats.reset(); | 379 | perf_stats.reset(); |
| 377 | kernel.Shutdown(); | 380 | kernel.Shutdown(); |
| 378 | memory.Reset(); | 381 | memory.Reset(); |
| @@ -450,6 +453,7 @@ struct System::Impl { | |||
| 450 | /// AppLoader used to load the current executing application | 453 | /// AppLoader used to load the current executing application |
| 451 | std::unique_ptr<Loader::AppLoader> app_loader; | 454 | std::unique_ptr<Loader::AppLoader> app_loader; |
| 452 | std::unique_ptr<Tegra::GPU> gpu_core; | 455 | std::unique_ptr<Tegra::GPU> gpu_core; |
| 456 | std::unique_ptr<Tegra::Host1x::Host1x> host1x_core; | ||
| 453 | std::unique_ptr<Hardware::InterruptManager> interrupt_manager; | 457 | std::unique_ptr<Hardware::InterruptManager> interrupt_manager; |
| 454 | std::unique_ptr<Core::DeviceMemory> device_memory; | 458 | std::unique_ptr<Core::DeviceMemory> device_memory; |
| 455 | std::unique_ptr<AudioCore::AudioCore> audio_core; | 459 | std::unique_ptr<AudioCore::AudioCore> audio_core; |
| @@ -668,6 +672,14 @@ const Tegra::GPU& System::GPU() const { | |||
| 668 | return *impl->gpu_core; | 672 | return *impl->gpu_core; |
| 669 | } | 673 | } |
| 670 | 674 | ||
| 675 | Tegra::Host1x::Host1x& System::Host1x() { | ||
| 676 | return *impl->host1x_core; | ||
| 677 | } | ||
| 678 | |||
| 679 | const Tegra::Host1x::Host1x& System::Host1x() const { | ||
| 680 | return *impl->host1x_core; | ||
| 681 | } | ||
| 682 | |||
| 671 | Core::Hardware::InterruptManager& System::InterruptManager() { | 683 | Core::Hardware::InterruptManager& System::InterruptManager() { |
| 672 | return *impl->interrupt_manager; | 684 | return *impl->interrupt_manager; |
| 673 | } | 685 | } |
diff --git a/src/core/core.h b/src/core/core.h index 0ce3b1d60..e4168a921 100644 --- a/src/core/core.h +++ b/src/core/core.h | |||
| @@ -74,6 +74,9 @@ class TimeManager; | |||
| 74 | namespace Tegra { | 74 | namespace Tegra { |
| 75 | class DebugContext; | 75 | class DebugContext; |
| 76 | class GPU; | 76 | class GPU; |
| 77 | namespace Host1x { | ||
| 78 | class Host1x; | ||
| 79 | } // namespace Host1x | ||
| 77 | } // namespace Tegra | 80 | } // namespace Tegra |
| 78 | 81 | ||
| 79 | namespace VideoCore { | 82 | namespace VideoCore { |
| @@ -260,6 +263,12 @@ public: | |||
| 260 | /// Gets an immutable reference to the GPU interface. | 263 | /// Gets an immutable reference to the GPU interface. |
| 261 | [[nodiscard]] const Tegra::GPU& GPU() const; | 264 | [[nodiscard]] const Tegra::GPU& GPU() const; |
| 262 | 265 | ||
| 266 | /// Gets a mutable reference to the Host1x interface | ||
| 267 | [[nodiscard]] Tegra::Host1x::Host1x& Host1x(); | ||
| 268 | |||
| 269 | /// Gets an immutable reference to the Host1x interface. | ||
| 270 | [[nodiscard]] const Tegra::Host1x::Host1x& Host1x() const; | ||
| 271 | |||
| 263 | /// Gets a mutable reference to the renderer. | 272 | /// Gets a mutable reference to the renderer. |
| 264 | [[nodiscard]] VideoCore::RendererBase& Renderer(); | 273 | [[nodiscard]] VideoCore::RendererBase& Renderer(); |
| 265 | 274 | ||
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp index b1c0e9eb2..e6a976714 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp | |||
| @@ -50,7 +50,7 @@ void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, android::PixelFormat form | |||
| 50 | stride, format, transform, crop_rect}; | 50 | stride, format, transform, crop_rect}; |
| 51 | 51 | ||
| 52 | system.GetPerfStats().EndSystemFrame(); | 52 | system.GetPerfStats().EndSystemFrame(); |
| 53 | system.GPU().SwapBuffers(&framebuffer); | 53 | system.GPU().RequestSwapBuffers(&framebuffer, nullptr, 0); |
| 54 | system.SpeedLimiter().DoSpeedLimiting(system.CoreTiming().GetGlobalTimeUs()); | 54 | system.SpeedLimiter().DoSpeedLimiting(system.CoreTiming().GetGlobalTimeUs()); |
| 55 | system.GetPerfStats().BeginSystemFrame(); | 55 | system.GetPerfStats().BeginSystemFrame(); |
| 56 | } | 56 | } |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index 54074af75..ffe42d423 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include "core/hle/service/nvdrv/core/syncpoint_manager.h" | 18 | #include "core/hle/service/nvdrv/core/syncpoint_manager.h" |
| 19 | #include "core/hle/service/nvdrv/devices/nvhost_ctrl.h" | 19 | #include "core/hle/service/nvdrv/devices/nvhost_ctrl.h" |
| 20 | #include "video_core/gpu.h" | 20 | #include "video_core/gpu.h" |
| 21 | #include "video_core/host1x/host1x.h" | ||
| 21 | 22 | ||
| 22 | namespace Service::Nvidia::Devices { | 23 | namespace Service::Nvidia::Devices { |
| 23 | 24 | ||
| @@ -129,7 +130,7 @@ NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector | |||
| 129 | return NvResult::Success; | 130 | return NvResult::Success; |
| 130 | } | 131 | } |
| 131 | 132 | ||
| 132 | auto& gpu = system.GPU(); | 133 | auto& host1x_syncpoint_manager = system.Host1x().GetSyncpointManager(); |
| 133 | const u32 target_value = params.fence.value; | 134 | const u32 target_value = params.fence.value; |
| 134 | 135 | ||
| 135 | auto lock = NvEventsLock(); | 136 | auto lock = NvEventsLock(); |
| @@ -149,7 +150,7 @@ NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector | |||
| 149 | if (events[slot].fails > 2) { | 150 | if (events[slot].fails > 2) { |
| 150 | { | 151 | { |
| 151 | auto lk = system.StallProcesses(); | 152 | auto lk = system.StallProcesses(); |
| 152 | gpu.WaitFence(fence_id, target_value); | 153 | host1x_syncpoint_manager.WaitHost(fence_id, target_value); |
| 153 | system.UnstallProcesses(); | 154 | system.UnstallProcesses(); |
| 154 | } | 155 | } |
| 155 | params.value.raw = target_value; | 156 | params.value.raw = target_value; |
| @@ -198,7 +199,15 @@ NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector | |||
| 198 | } | 199 | } |
| 199 | params.value.raw |= slot; | 200 | params.value.raw |= slot; |
| 200 | 201 | ||
| 201 | gpu.RegisterSyncptInterrupt(fence_id, target_value); | 202 | event.wait_handle = |
| 203 | host1x_syncpoint_manager.RegisterHostAction(fence_id, target_value, [this, slot]() { | ||
| 204 | auto& event = events[slot]; | ||
| 205 | if (event.status.exchange(EventState::Signalling, std::memory_order_acq_rel) == | ||
| 206 | EventState::Waiting) { | ||
| 207 | event.kevent->GetWritableEvent().Signal(); | ||
| 208 | } | ||
| 209 | event.status.store(EventState::Signalled, std::memory_order_release); | ||
| 210 | }); | ||
| 202 | return NvResult::Timeout; | 211 | return NvResult::Timeout; |
| 203 | } | 212 | } |
| 204 | 213 | ||
| @@ -288,8 +297,10 @@ NvResult nvhost_ctrl::IocCtrlClearEventWait(const std::vector<u8>& input, std::v | |||
| 288 | auto& event = events[event_id]; | 297 | auto& event = events[event_id]; |
| 289 | if (event.status.exchange(EventState::Cancelling, std::memory_order_acq_rel) == | 298 | if (event.status.exchange(EventState::Cancelling, std::memory_order_acq_rel) == |
| 290 | EventState::Waiting) { | 299 | EventState::Waiting) { |
| 291 | system.GPU().CancelSyncptInterrupt(event.assigned_syncpt, event.assigned_value); | 300 | auto& host1x_syncpoint_manager = system.Host1x().GetSyncpointManager(); |
| 301 | host1x_syncpoint_manager.DeregisterHostAction(event.assigned_syncpt, event.wait_handle); | ||
| 292 | syncpoint_manager.RefreshSyncpoint(event.assigned_syncpt); | 302 | syncpoint_manager.RefreshSyncpoint(event.assigned_syncpt); |
| 303 | event.wait_handle = {}; | ||
| 293 | } | 304 | } |
| 294 | event.fails++; | 305 | event.fails++; |
| 295 | event.status.store(EventState::Cancelled, std::memory_order_release); | 306 | event.status.store(EventState::Cancelled, std::memory_order_release); |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h index d56aea405..136a1e925 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include "common/common_types.h" | 11 | #include "common/common_types.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/nvdrv.h" | 13 | #include "core/hle/service/nvdrv/nvdrv.h" |
| 14 | #include "video_core/host1x/syncpoint_manager.h" | ||
| 14 | 15 | ||
| 15 | namespace Service::Nvidia::NvCore { | 16 | namespace Service::Nvidia::NvCore { |
| 16 | class Container; | 17 | class Container; |
| @@ -78,6 +79,9 @@ private: | |||
| 78 | // Tells if an NVEvent is registered or not | 79 | // Tells if an NVEvent is registered or not |
| 79 | bool registered{}; | 80 | bool registered{}; |
| 80 | 81 | ||
| 82 | // Used for waiting on a syncpoint & canceling it. | ||
| 83 | Tegra::Host1x::SyncpointManager::ActionHandle wait_handle{}; | ||
| 84 | |||
| 81 | bool IsBeingUsed() { | 85 | bool IsBeingUsed() { |
| 82 | const auto current_status = status.load(std::memory_order_acquire); | 86 | const auto current_status = status.load(std::memory_order_acquire); |
| 83 | return current_status == EventState::Waiting || | 87 | return current_status == EventState::Waiting || |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp index 38d45cb79..db3e266ad 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp | |||
| @@ -210,10 +210,10 @@ NvResult nvhost_gpu::AllocateObjectContext(const std::vector<u8>& input, std::ve | |||
| 210 | 210 | ||
| 211 | static std::vector<Tegra::CommandHeader> BuildWaitCommandList(NvFence fence) { | 211 | static std::vector<Tegra::CommandHeader> BuildWaitCommandList(NvFence fence) { |
| 212 | return { | 212 | return { |
| 213 | Tegra::BuildCommandHeader(Tegra::BufferMethods::FenceValue, 1, | 213 | Tegra::BuildCommandHeader(Tegra::BufferMethods::SyncpointPayload, 1, |
| 214 | Tegra::SubmissionMode::Increasing), | 214 | Tegra::SubmissionMode::Increasing), |
| 215 | {fence.value}, | 215 | {fence.value}, |
| 216 | Tegra::BuildCommandHeader(Tegra::BufferMethods::FenceAction, 1, | 216 | Tegra::BuildCommandHeader(Tegra::BufferMethods::SyncpointOperation, 1, |
| 217 | Tegra::SubmissionMode::Increasing), | 217 | Tegra::SubmissionMode::Increasing), |
| 218 | BuildFenceAction(Tegra::Engines::Puller::FenceOperation::Acquire, fence.id), | 218 | BuildFenceAction(Tegra::Engines::Puller::FenceOperation::Acquire, fence.id), |
| 219 | }; | 219 | }; |
| @@ -222,12 +222,12 @@ static std::vector<Tegra::CommandHeader> BuildWaitCommandList(NvFence fence) { | |||
| 222 | static std::vector<Tegra::CommandHeader> BuildIncrementCommandList(NvFence fence, | 222 | static std::vector<Tegra::CommandHeader> BuildIncrementCommandList(NvFence fence, |
| 223 | u32 add_increment) { | 223 | u32 add_increment) { |
| 224 | std::vector<Tegra::CommandHeader> result{ | 224 | std::vector<Tegra::CommandHeader> result{ |
| 225 | Tegra::BuildCommandHeader(Tegra::BufferMethods::FenceValue, 1, | 225 | Tegra::BuildCommandHeader(Tegra::BufferMethods::SyncpointPayload, 1, |
| 226 | Tegra::SubmissionMode::Increasing), | 226 | Tegra::SubmissionMode::Increasing), |
| 227 | {}}; | 227 | {}}; |
| 228 | 228 | ||
| 229 | for (u32 count = 0; count < add_increment; ++count) { | 229 | for (u32 count = 0; count < add_increment; ++count) { |
| 230 | result.emplace_back(Tegra::BuildCommandHeader(Tegra::BufferMethods::FenceAction, 1, | 230 | result.emplace_back(Tegra::BuildCommandHeader(Tegra::BufferMethods::SyncpointOperation, 1, |
| 231 | Tegra::SubmissionMode::Increasing)); | 231 | Tegra::SubmissionMode::Increasing)); |
| 232 | result.emplace_back( | 232 | result.emplace_back( |
| 233 | BuildFenceAction(Tegra::Engines::Puller::FenceOperation::Increment, fence.id)); | 233 | BuildFenceAction(Tegra::Engines::Puller::FenceOperation::Increment, fence.id)); |
| @@ -239,7 +239,7 @@ static std::vector<Tegra::CommandHeader> BuildIncrementCommandList(NvFence fence | |||
| 239 | static std::vector<Tegra::CommandHeader> BuildIncrementWithWfiCommandList(NvFence fence, | 239 | static std::vector<Tegra::CommandHeader> BuildIncrementWithWfiCommandList(NvFence fence, |
| 240 | u32 add_increment) { | 240 | u32 add_increment) { |
| 241 | std::vector<Tegra::CommandHeader> result{ | 241 | std::vector<Tegra::CommandHeader> result{ |
| 242 | Tegra::BuildCommandHeader(Tegra::BufferMethods::WaitForInterrupt, 1, | 242 | Tegra::BuildCommandHeader(Tegra::BufferMethods::WaitForIdle, 1, |
| 243 | Tegra::SubmissionMode::Increasing), | 243 | Tegra::SubmissionMode::Increasing), |
| 244 | {}}; | 244 | {}}; |
| 245 | const std::vector<Tegra::CommandHeader> increment{ | 245 | const std::vector<Tegra::CommandHeader> increment{ |
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index 8c3013f83..aa112021d 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp | |||
| @@ -24,6 +24,8 @@ | |||
| 24 | #include "core/hle/service/vi/layer/vi_layer.h" | 24 | #include "core/hle/service/vi/layer/vi_layer.h" |
| 25 | #include "core/hle/service/vi/vi_results.h" | 25 | #include "core/hle/service/vi/vi_results.h" |
| 26 | #include "video_core/gpu.h" | 26 | #include "video_core/gpu.h" |
| 27 | #include "video_core/host1x/host1x.h" | ||
| 28 | #include "video_core/host1x/syncpoint_manager.h" | ||
| 27 | 29 | ||
| 28 | namespace Service::NVFlinger { | 30 | namespace Service::NVFlinger { |
| 29 | 31 | ||
| @@ -267,12 +269,12 @@ void NVFlinger::Compose() { | |||
| 267 | return; // We are likely shutting down | 269 | return; // We are likely shutting down |
| 268 | } | 270 | } |
| 269 | 271 | ||
| 270 | auto& gpu = system.GPU(); | 272 | auto& syncpoint_manager = system.Host1x().GetSyncpointManager(); |
| 271 | const auto& multi_fence = buffer.fence; | 273 | const auto& multi_fence = buffer.fence; |
| 272 | guard->unlock(); | 274 | guard->unlock(); |
| 273 | for (u32 fence_id = 0; fence_id < multi_fence.num_fences; fence_id++) { | 275 | for (u32 fence_id = 0; fence_id < multi_fence.num_fences; fence_id++) { |
| 274 | const auto& fence = multi_fence.fences[fence_id]; | 276 | const auto& fence = multi_fence.fences[fence_id]; |
| 275 | gpu.WaitFence(fence.id, fence.value); | 277 | syncpoint_manager.WaitGuest(fence.id, fence.value); |
| 276 | } | 278 | } |
| 277 | guard->lock(); | 279 | guard->lock(); |
| 278 | 280 | ||
| @@ -284,6 +286,7 @@ void NVFlinger::Compose() { | |||
| 284 | auto nvdisp = nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>(disp_fd); | 286 | auto nvdisp = nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>(disp_fd); |
| 285 | ASSERT(nvdisp); | 287 | ASSERT(nvdisp); |
| 286 | 288 | ||
| 289 | guard->unlock(); | ||
| 287 | Common::Rectangle<int> crop_rect{ | 290 | Common::Rectangle<int> crop_rect{ |
| 288 | static_cast<int>(buffer.crop.Left()), static_cast<int>(buffer.crop.Top()), | 291 | static_cast<int>(buffer.crop.Left()), static_cast<int>(buffer.crop.Top()), |
| 289 | static_cast<int>(buffer.crop.Right()), static_cast<int>(buffer.crop.Bottom())}; | 292 | static_cast<int>(buffer.crop.Right()), static_cast<int>(buffer.crop.Bottom())}; |
| @@ -292,6 +295,8 @@ void NVFlinger::Compose() { | |||
| 292 | igbp_buffer.Width(), igbp_buffer.Height(), igbp_buffer.Stride(), | 295 | igbp_buffer.Width(), igbp_buffer.Height(), igbp_buffer.Stride(), |
| 293 | static_cast<android::BufferTransformFlags>(buffer.transform), crop_rect); | 296 | static_cast<android::BufferTransformFlags>(buffer.transform), crop_rect); |
| 294 | 297 | ||
| 298 | guard->lock(); | ||
| 299 | |||
| 295 | swap_interval = buffer.swap_interval; | 300 | swap_interval = buffer.swap_interval; |
| 296 | 301 | ||
| 297 | auto fence = android::Fence::NoFence(); | 302 | auto fence = android::Fence::NoFence(); |