aboutsummaryrefslogtreecommitdiff
path: root/src/video_core/control/scheduler.cpp
diff options
context:
space:
mode:
authorDjihads <76681596+Djihads80@users.noreply.github.com>2026-10-30 11:33:03 +0100
committerGitHub <noreply@github.com>2026-10-30 11:33:03 +0100
commit9560dec549134cf50a7bcde3f86f87ed7658b25f (patch)
tree75493cfac29ed9d1dc350658e17c366f7e10a3c4 /src/video_core/control/scheduler.cpp
parent666d2447639594c7cd2b184acf2117b38766ac22 (diff)
parent937bb4dd30401a339a062386c121b9714e33e38d (diff)
Merge pull request #26 from Djihads80/nx2-experimental
Nx2 experimental
Diffstat (limited to 'src/video_core/control/scheduler.cpp')
-rw-r--r--src/video_core/control/scheduler.cpp29
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;
}