diff options
Diffstat (limited to 'src/video_core/control/scheduler.cpp')
| -rw-r--r-- | src/video_core/control/scheduler.cpp | 29 |
1 files changed, 24 insertions, 5 deletions
diff --git a/src/video_core/control/scheduler.cpp b/src/video_core/control/scheduler.cpp index 24f1db1f7c..dc42906752 100644 --- a/src/video_core/control/scheduler.cpp +++ b/src/video_core/control/scheduler.cpp @@ -9,12 +9,28 @@ #include <vector> #include "common/assert.h" +#include "core/core.h" #include "video_core/control/channel_state.h" #include "video_core/control/scheduler.h" #include "video_core/gpu.h" +#include "video_core/gpu_split.h" namespace Tegra::Control { +void Scheduler::BindChannel(GPU& gpu, s32 bind_id) { + // With the GPU thread split the rasterizer's channel switches with the methods around it, on + // the back thread (deferred outside the lock: the back takes it to bind). + if (auto& split = VideoCommon::GpuSplit::Get(); split.Active()) { + split.Defer([this, gpu_ptr = &gpu, bind_id] { + std::scoped_lock lk{scheduling_guard}; + gpu_ptr->BindChannel(bind_id); + }); + return; + } + std::scoped_lock lk{scheduling_guard}; + gpu.BindChannel(bind_id); +} + void Scheduler::Push(GPU& gpu, s32 channel, CommandList&& entries) { std::shared_ptr<ChannelState> channel_state; { @@ -22,8 +38,8 @@ void Scheduler::Push(GPU& gpu, s32 channel, CommandList&& entries) { auto it = channels.find(channel); ASSERT(it != channels.end()); channel_state = it->second; - gpu.BindChannel(channel_state->bind_id); } + BindChannel(gpu, channel_state->bind_id); // Process commands outside the lock to reduce contention. // Multiple channels can prepare their commands in parallel. channel_state->payload->dma_pusher.Push(std::move(entries)); @@ -44,13 +60,16 @@ void Scheduler::ResumePending(GPU& gpu) { progress = false; for (const auto& state : pending_channels) { auto& dma_pusher = state->payload->dma_pusher; + // Powered off (shutting down), DispatchCalls returns at once and the acquire stays + // pending: resuming it again counted as progress forever and the GPU thread never + // reached its stop request (closing the game hung). + if (!dma_pusher.system.IsPoweredOn()) { + return; + } if (!dma_pusher.HasPendingAcquire() || !dma_pusher.CanResumeAcquire()) { continue; } - { - std::scoped_lock lk{scheduling_guard}; - gpu.BindChannel(state->bind_id); - } + BindChannel(gpu, state->bind_id); dma_pusher.DispatchCalls(); progress = true; } |
