From 1bf410e1fc319edd2881ffef50f57e7bccf088ff Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Sat, 14 Feb 2026 00:52:00 +0100 Subject: [PATCH] renderer: fix dgpu directscanout explicit sync (#13229) * directscanout: fix dgpu directscanout explicit sync without setting an infence, AQ doesnt explicit sync, nor recreate the dgpu fence for the blit work. and as such attemptdirectscanout path artifacts and breaks. create a dummy CEGLSync even tho we dont really have any pending glwork to get a proper fence, and set it. * monitor: dont use new scheduling if direct scanout using the new_render_scheduling makes no sense in the direct scanout path, add a if guard against it. --- src/helpers/Monitor.cpp | 13 ++++++++++++- src/helpers/MonitorFrameScheduler.cpp | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index be0b78fd..bb710269 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -1893,7 +1893,18 @@ bool CMonitor::attemptDirectScanout() { PSURFACE->presentFeedback(Time::steadyNow(), m_self.lock()); m_output->state->addDamage(PSURFACE->m_current.accumulateBufferDamage()); - m_output->state->resetExplicitFences(); + + // multigpu needs a fence to trigger fence syncing blits and also committing with the recreated dgpu fence + if (m_output->getBackend()->preferredAllocator()->drmFD() != g_pCompositor->m_drm.fd && g_pHyprOpenGL->explicitSyncSupported()) { + auto sync = CEGLSync::create(); + + if (sync->fd().isValid()) { + m_inFence = sync->takeFd(); + m_output->state->setExplicitInFence(m_inFence.get()); + } else + m_output->state->resetExplicitFences(); // good luck. + } else + m_output->state->resetExplicitFences(); // no need to do explicit sync here as surface current can only ever be ready to read diff --git a/src/helpers/MonitorFrameScheduler.cpp b/src/helpers/MonitorFrameScheduler.cpp index 804eec1e..648e6dec 100644 --- a/src/helpers/MonitorFrameScheduler.cpp +++ b/src/helpers/MonitorFrameScheduler.cpp @@ -11,7 +11,7 @@ CMonitorFrameScheduler::CMonitorFrameScheduler(PHLMONITOR m) : m_monitor(m) { bool CMonitorFrameScheduler::newSchedulingEnabled() { static auto PENABLENEW = CConfigValue("render:new_render_scheduling"); - return *PENABLENEW && g_pHyprOpenGL->explicitSyncSupported(); + return *PENABLENEW && g_pHyprOpenGL->explicitSyncSupported() && m_monitor && !m_monitor->m_directScanoutIsActive; } void CMonitorFrameScheduler::onSyncFired() {