From 2ee5118d7a4a59d3ccfaed305bfc05c79cea7637 Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Wed, 30 Apr 2025 11:35:25 -0500 Subject: render: properly release rendered buffers (#9807) * cleanup eglSync * properly release buffers in renderer * add renderingDoneCallback and use it in screencopy * use static constructor for CEGLSync --- src/render/Renderer.cpp | 70 ++++++++++++++++++++----------------------------- 1 file changed, 28 insertions(+), 42 deletions(-) (limited to 'src/render/Renderer.cpp') diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 0db305af..93d3620f 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1,7 +1,6 @@ #include "Renderer.hpp" #include "../Compositor.hpp" #include "../helpers/math/Math.hpp" -#include "../helpers/sync/SyncReleaser.hpp" #include #include #include @@ -1571,25 +1570,6 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) { } } - auto explicitOptions = getExplicitSyncSettings(pMonitor->output); - if (!explicitOptions.explicitEnabled) - return ok; - - Debug::log(TRACE, "Explicit: {} presented", explicitPresented.size()); - - if (!pMonitor->eglSync) - Debug::log(TRACE, "Explicit: can't add sync, monitor has no EGLSync"); - else { - for (auto const& e : explicitPresented) { - if (!e->current.buffer || !e->current.buffer->syncReleaser) - continue; - - e->current.buffer->syncReleaser->addReleaseSync(pMonitor->eglSync); - } - } - - explicitPresented.clear(); - return ok; } @@ -2275,7 +2255,7 @@ bool CHyprRenderer::beginRender(PHLMONITOR pMonitor, CRegion& damage, eRenderMod return true; } -void CHyprRenderer::endRender() { +void CHyprRenderer::endRender(const std::function& renderingDoneCallback) { const auto PMONITOR = g_pHyprOpenGL->m_RenderData.pMonitor; static auto PNVIDIAANTIFLICKER = CConfigValue("opengl:nvidia_anti_flicker"); @@ -2296,42 +2276,48 @@ void CHyprRenderer::endRender() { g_pHyprOpenGL->m_RenderData.mouseZoomUseMouse = true; } + // send all queued opengl commands so rendering starts happening immediately + glFlush(); + if (m_eRenderMode == RENDER_MODE_FULL_FAKE) return; if (m_eRenderMode == RENDER_MODE_NORMAL) PMONITOR->output->state->setBuffer(m_pCurrentBuffer); - auto explicitOptions = getExplicitSyncSettings(PMONITOR->output); - - if (PMONITOR->inTimeline && explicitOptions.explicitEnabled) { - PMONITOR->eglSync = g_pHyprOpenGL->createEGLSync(); - if (!PMONITOR->eglSync) { - Debug::log(ERR, "renderer: couldn't create an EGLSync for out in endRender"); - return; + UP eglSync = CEGLSync::create(); + if (eglSync && eglSync->isValid()) { + for (auto const& buf : usedAsyncBuffers) { + for (const auto& releaser : buf->syncReleasers) { + releaser->addSyncFileFd(eglSync->fd()); + } } - PMONITOR->inTimelinePoint++; - bool ok = PMONITOR->inTimeline->importFromSyncFileFD(PMONITOR->inTimelinePoint, PMONITOR->eglSync->fd()); - if (!ok) { - Debug::log(ERR, "renderer: couldn't import from sync file fd in endRender"); - return; - } + // release buffer refs with release points now, since syncReleaser handles actual buffer release based on EGLSync + std::erase_if(usedAsyncBuffers, [](const auto& buf) { return !buf->syncReleasers.empty(); }); - if (m_eRenderMode == RENDER_MODE_NORMAL && explicitOptions.explicitKMSEnabled) { - PMONITOR->inFence = CFileDescriptor{PMONITOR->inTimeline->exportAsSyncFileFD(PMONITOR->inTimelinePoint)}; - if (!PMONITOR->inFence.isValid()) { - Debug::log(ERR, "renderer: couldn't export from sync timeline in endRender"); - return; - } + // release buffer refs without release points when EGLSync sync_file/fence is signalled + g_pEventLoopManager->doOnReadable(eglSync->fd().duplicate(), [renderingDoneCallback, prevbfs = std::move(usedAsyncBuffers)]() mutable { + prevbfs.clear(); + if (renderingDoneCallback) + renderingDoneCallback(); + }); + usedAsyncBuffers.clear(); + if (m_eRenderMode == RENDER_MODE_NORMAL) { + PMONITOR->inFence = eglSync->takeFd(); PMONITOR->output->state->setExplicitInFence(PMONITOR->inFence.get()); } } else { + Debug::log(ERR, "renderer: couldn't use EGLSync for explicit gpu synchronization"); + + // nvidia doesn't have implicit sync, so we have to explicitly wait here if (isNvidia() && *PNVIDIAANTIFLICKER) glFinish(); - else - glFlush(); + + usedAsyncBuffers.clear(); // release all buffer refs and hope implicit sync works + if (renderingDoneCallback) + renderingDoneCallback(); } } -- cgit v1.2.3