Explicit sync fixes (#6829)

* explicit sync fixes

* more logging

* reremove wlroots

* close explicit fds on rollback

* limit presentFeedback explicit sync to direct scanout mode only

* explicit sync for texture render

* cursor explicit sync initial

* common wait for explicit sync point code

* code style fixes
This commit is contained in:
UjinT34 2024-07-10 22:20:00 +03:00 committed by Vaxry
parent 4c905b1a8b
commit 805a054389
8 changed files with 104 additions and 53 deletions

View File

@ -162,13 +162,13 @@ bool CSyncTimeline::importFromSyncFileFD(uint64_t dst, int fd) {
if (drmSyncobjImportSyncFile(drmFD, syncHandle, fd)) { if (drmSyncobjImportSyncFile(drmFD, syncHandle, fd)) {
Debug::log(ERR, "importFromSyncFileFD: drmSyncobjImportSyncFile failed"); Debug::log(ERR, "importFromSyncFileFD: drmSyncobjImportSyncFile failed");
drmSyncobjDestroy(drmFD, syncHandle); drmSyncobjDestroy(drmFD, syncHandle);
return -1; return false;
} }
if (drmSyncobjTransfer(drmFD, handle, dst, syncHandle, 0, 0)) { if (drmSyncobjTransfer(drmFD, handle, dst, syncHandle, 0, 0)) {
Debug::log(ERR, "importFromSyncFileFD: drmSyncobjTransfer failed"); Debug::log(ERR, "importFromSyncFileFD: drmSyncobjTransfer failed");
drmSyncobjDestroy(drmFD, syncHandle); drmSyncobjDestroy(drmFD, syncHandle);
return -1; return false;
} }
drmSyncobjDestroy(drmFD, syncHandle); drmSyncobjDestroy(drmFD, syncHandle);

View File

@ -448,7 +448,7 @@ void CPointerManager::renderSoftwareCursorsFor(SP<CMonitor> pMonitor, timespec*
box.x = std::round(box.x); box.x = std::round(box.x);
box.y = std::round(box.y); box.y = std::round(box.y);
g_pHyprOpenGL->renderTextureWithDamage(texture, &box, &damage, 1.F); g_pHyprOpenGL->renderTextureWithDamage(texture, &box, &damage, 1.F, 0, false, false, currentCursorImage.waitTimeline, currentCursorImage.waitPoint);
if (currentCursorImage.surface) if (currentCursorImage.surface)
currentCursorImage.surface->resource()->frame(now); currentCursorImage.surface->resource()->frame(now);

View File

@ -147,6 +147,8 @@ class CPointerManager {
CHyprSignalListener destroySurface; CHyprSignalListener destroySurface;
CHyprSignalListener commitSurface; CHyprSignalListener commitSurface;
SP<CSyncTimeline> waitTimeline = nullptr;
uint64_t waitPoint = 0;
} currentCursorImage; // TODO: support various sizes per-output so we can have pixel-perfect cursors } currentCursorImage; // TODO: support various sizes per-output so we can have pixel-perfect cursors
Vector2D pointerPos = {0, 0}; Vector2D pointerPos = {0, 0};

View File

@ -447,21 +447,23 @@ void CWLSurfaceResource::commitPendingState() {
} }
} }
void CWLSurfaceResource::presentFeedback(timespec* when, CMonitor* pMonitor) { void CWLSurfaceResource::presentFeedback(timespec* when, CMonitor* pMonitor, bool needsExplicitSync) {
frame(when); frame(when);
auto FEEDBACK = makeShared<CQueuedPresentationData>(self.lock()); auto FEEDBACK = makeShared<CQueuedPresentationData>(self.lock());
FEEDBACK->attachMonitor(pMonitor); FEEDBACK->attachMonitor(pMonitor);
FEEDBACK->discarded(); FEEDBACK->discarded();
PROTO::presentation->queueData(FEEDBACK); PROTO::presentation->queueData(FEEDBACK);
if (!pMonitor || !pMonitor->outTimeline || !syncobj) if (!pMonitor || !pMonitor->outTimeline || !syncobj || !needsExplicitSync)
return; return;
// attach explicit sync // attach explicit sync
g_pHyprRenderer->explicitPresented.emplace_back(self.lock()); g_pHyprRenderer->explicitPresented.emplace_back(self.lock());
if (syncobj->acquirePoint > pMonitor->lastWaitPoint) if (syncobj->acquirePoint > pMonitor->lastWaitPoint) {
Debug::log(TRACE, "presentFeedback lastWaitPoint {} -> {}", pMonitor->lastWaitPoint, syncobj->acquirePoint);
pMonitor->lastWaitPoint = syncobj->acquirePoint; pMonitor->lastWaitPoint = syncobj->acquirePoint;
}
} }
CWLCompositorResource::CWLCompositorResource(SP<CWlCompositor> resource_) : resource(resource_) { CWLCompositorResource::CWLCompositorResource(SP<CWlCompositor> resource_) : resource(resource_) {

View File

@ -122,7 +122,7 @@ class CWLSurfaceResource {
void breadthfirst(std::function<void(SP<CWLSurfaceResource>, const Vector2D&, void*)> fn, void* data); void breadthfirst(std::function<void(SP<CWLSurfaceResource>, const Vector2D&, void*)> fn, void* data);
CRegion accumulateCurrentBufferDamage(); CRegion accumulateCurrentBufferDamage();
void presentFeedback(timespec* when, CMonitor* pMonitor); void presentFeedback(timespec* when, CMonitor* pMonitor, bool needsExplicitSync = false);
void lockPendingState(); void lockPendingState();
void unlockPendingState(); void unlockPendingState();

View File

@ -1255,16 +1255,17 @@ void CHyprOpenGLImpl::renderTexture(SP<CTexture> tex, CBox* pBox, float alpha, i
scissor((CBox*)nullptr); scissor((CBox*)nullptr);
} }
void CHyprOpenGLImpl::renderTextureWithDamage(SP<CTexture> tex, CBox* pBox, CRegion* damage, float alpha, int round, bool discardActive, bool allowCustomUV) { void CHyprOpenGLImpl::renderTextureWithDamage(SP<CTexture> tex, CBox* pBox, CRegion* damage, float alpha, int round, bool discardActive, bool allowCustomUV,
SP<CSyncTimeline> waitTimeline, uint64_t waitPoint) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
renderTextureInternalWithDamage(tex, pBox, alpha, damage, round, discardActive, false, allowCustomUV, true); renderTextureInternalWithDamage(tex, pBox, alpha, damage, round, discardActive, false, allowCustomUV, true, waitTimeline, waitPoint);
scissor((CBox*)nullptr); scissor((CBox*)nullptr);
} }
void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP<CTexture> tex, CBox* pBox, float alpha, CRegion* damage, int round, bool discardActive, bool noAA, bool allowCustomUV, void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP<CTexture> tex, CBox* pBox, float alpha, CRegion* damage, int round, bool discardActive, bool noAA, bool allowCustomUV,
bool allowDim) { bool allowDim, SP<CSyncTimeline> waitTimeline, uint64_t waitPoint) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
RASSERT((tex->m_iTexID > 0), "Attempted to draw NULL texture!"); RASSERT((tex->m_iTexID > 0), "Attempted to draw NULL texture!");
@ -1289,6 +1290,13 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP<CTexture> tex, CBox* pB
float glMatrix[9]; float glMatrix[9];
matrixMultiply(glMatrix, m_RenderData.projection, matrix); matrixMultiply(glMatrix, m_RenderData.projection, matrix);
if (waitTimeline != nullptr) {
if (!waitForTimelinePoint(waitTimeline, waitPoint)) {
Debug::log(ERR, "renderTextureInternalWithDamage: failed to wait for explicit sync point {}", waitPoint);
return;
}
}
CShader* shader = nullptr; CShader* shader = nullptr;
bool usingFinalShader = false; bool usingFinalShader = false;
@ -2744,6 +2752,8 @@ std::vector<SDRMFormat> CHyprOpenGLImpl::getDRMFormats() {
SP<CEGLSync> CHyprOpenGLImpl::createEGLSync(int fenceFD) { SP<CEGLSync> CHyprOpenGLImpl::createEGLSync(int fenceFD) {
std::vector<EGLint> attribs; std::vector<EGLint> attribs;
int dupFd = -1;
if (fenceFD > 0) {
int dupFd = fcntl(fenceFD, F_DUPFD_CLOEXEC, 0); int dupFd = fcntl(fenceFD, F_DUPFD_CLOEXEC, 0);
if (dupFd < 0) { if (dupFd < 0) {
Debug::log(ERR, "createEGLSync: dup failed"); Debug::log(ERR, "createEGLSync: dup failed");
@ -2753,10 +2763,12 @@ SP<CEGLSync> CHyprOpenGLImpl::createEGLSync(int fenceFD) {
attribs.push_back(EGL_SYNC_NATIVE_FENCE_FD_ANDROID); attribs.push_back(EGL_SYNC_NATIVE_FENCE_FD_ANDROID);
attribs.push_back(dupFd); attribs.push_back(dupFd);
attribs.push_back(EGL_NONE); attribs.push_back(EGL_NONE);
}
EGLSyncKHR sync = m_sProc.eglCreateSyncKHR(m_pEglDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs.data()); EGLSyncKHR sync = m_sProc.eglCreateSyncKHR(m_pEglDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs.data());
if (sync == EGL_NO_SYNC_KHR) { if (sync == EGL_NO_SYNC_KHR) {
Debug::log(ERR, "eglCreateSyncKHR failed"); Debug::log(ERR, "eglCreateSyncKHR failed");
if (dupFd >= 0)
close(dupFd); close(dupFd);
return nullptr; return nullptr;
} }
@ -2766,6 +2778,28 @@ SP<CEGLSync> CHyprOpenGLImpl::createEGLSync(int fenceFD) {
return eglsync; return eglsync;
} }
bool CHyprOpenGLImpl::waitForTimelinePoint(SP<CSyncTimeline> timeline, uint64_t point) {
int fd = timeline->exportAsSyncFileFD(point);
if (fd < 0) {
Debug::log(ERR, "waitForTimelinePoint: failed to get a fd from explicit timeline");
return false;
}
auto sync = g_pHyprOpenGL->createEGLSync(fd);
close(fd);
if (!sync) {
Debug::log(ERR, "waitForTimelinePoint: failed to get an eglsync from explicit timeline");
return false;
}
if (!sync->wait()) {
Debug::log(ERR, "waitForTimelinePoint: failed to wait on an eglsync from explicit timeline");
return false;
}
return true;
}
void SRenderModifData::applyToBox(CBox& box) { void SRenderModifData::applyToBox(CBox& box) {
if (!enabled) if (!enabled)
return; return;

View File

@ -6,6 +6,8 @@
#include "../helpers/Timer.hpp" #include "../helpers/Timer.hpp"
#include "../helpers/math/Math.hpp" #include "../helpers/math/Math.hpp"
#include "../helpers/Format.hpp" #include "../helpers/Format.hpp"
#include "../helpers/sync/SyncTimeline.hpp"
#include <cstdint>
#include <list> #include <list>
#include <unordered_map> #include <unordered_map>
#include <map> #include <map>
@ -152,7 +154,8 @@ class CHyprOpenGLImpl {
void renderRectWithBlur(CBox*, const CColor&, int round = 0, float blurA = 1.f, bool xray = false); void renderRectWithBlur(CBox*, const CColor&, int round = 0, float blurA = 1.f, bool xray = false);
void renderRectWithDamage(CBox*, const CColor&, CRegion* damage, int round = 0); void renderRectWithDamage(CBox*, const CColor&, CRegion* damage, int round = 0);
void renderTexture(SP<CTexture>, CBox*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false); void renderTexture(SP<CTexture>, CBox*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false);
void renderTextureWithDamage(SP<CTexture>, CBox*, CRegion* damage, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false); void renderTextureWithDamage(SP<CTexture>, CBox*, CRegion* damage, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false,
SP<CSyncTimeline> waitTimeline = nullptr, uint64_t waitPoint = 0);
void renderTextureWithBlur(SP<CTexture>, CBox*, float a, SP<CWLSurfaceResource> pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f); void renderTextureWithBlur(SP<CTexture>, CBox*, float a, SP<CWLSurfaceResource> pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f);
void renderRoundedShadow(CBox*, int round, int range, const CColor& color, float a = 1.0); void renderRoundedShadow(CBox*, int round, int range, const CColor& color, float a = 1.0);
void renderBorder(CBox*, const CGradientValueData&, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */); void renderBorder(CBox*, const CGradientValueData&, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */);
@ -203,6 +206,7 @@ class CHyprOpenGLImpl {
std::vector<SDRMFormat> getDRMFormats(); std::vector<SDRMFormat> getDRMFormats();
EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs); EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs);
SP<CEGLSync> createEGLSync(int fenceFD); SP<CEGLSync> createEGLSync(int fenceFD);
bool waitForTimelinePoint(SP<CSyncTimeline> timeline, uint64_t point);
SCurrentRenderData m_RenderData; SCurrentRenderData m_RenderData;
@ -284,7 +288,7 @@ class CHyprOpenGLImpl {
CFramebuffer* blurMainFramebufferWithDamage(float a, CRegion* damage); CFramebuffer* blurMainFramebufferWithDamage(float a, CRegion* damage);
void renderTextureInternalWithDamage(SP<CTexture>, CBox* pBox, float a, CRegion* damage, int round = 0, bool discardOpaque = false, bool noAA = false, void renderTextureInternalWithDamage(SP<CTexture>, CBox* pBox, float a, CRegion* damage, int round = 0, bool discardOpaque = false, bool noAA = false,
bool allowCustomUV = false, bool allowDim = false); bool allowCustomUV = false, bool allowDim = false, SP<CSyncTimeline> = nullptr, uint64_t waitPoint = 0);
void renderTexturePrimitive(SP<CTexture> tex, CBox* pBox); void renderTexturePrimitive(SP<CTexture> tex, CBox* pBox);
void renderSplash(cairo_t* const, cairo_surface_t* const, double offset, const Vector2D& size); void renderSplash(cairo_t* const, cairo_surface_t* const, double offset, const Vector2D& size);

View File

@ -17,6 +17,7 @@
#include "../protocols/DRMSyncobj.hpp" #include "../protocols/DRMSyncobj.hpp"
#include "../protocols/LinuxDMABUF.hpp" #include "../protocols/LinuxDMABUF.hpp"
#include "../helpers/sync/SyncTimeline.hpp" #include "../helpers/sync/SyncTimeline.hpp"
#include "debug/Log.hpp"
extern "C" { extern "C" {
#include <xf86drm.h> #include <xf86drm.h>
@ -114,21 +115,8 @@ static void renderSurface(SP<CWLSurfaceResource> surface, int x, int y, void* da
// explicit sync: wait for the timeline, if any // explicit sync: wait for the timeline, if any
if (surface->syncobj && surface->syncobj->acquireTimeline) { if (surface->syncobj && surface->syncobj->acquireTimeline) {
int fd = surface->syncobj->acquireTimeline->timeline->exportAsSyncFileFD(surface->syncobj->acquirePoint); if (!g_pHyprOpenGL->waitForTimelinePoint(surface->syncobj->acquireTimeline->timeline, surface->syncobj->acquirePoint)) {
if (fd < 0) { Debug::log(ERR, "Renderer: failed to wait for explicit timeline");
Debug::log(ERR, "Renderer: failed to get a fd from explicit timeline");
return;
}
auto sync = g_pHyprOpenGL->createEGLSync(fd);
close(fd);
if (!sync) {
Debug::log(ERR, "Renderer: failed to get an eglsync from explicit timeline");
return;
}
if (!sync->wait()) {
Debug::log(ERR, "Renderer: failed to wait on an eglsync from explicit timeline");
return; return;
} }
} }
@ -191,8 +179,10 @@ static void renderSurface(SP<CWLSurfaceResource> surface, int x, int y, void* da
} }
if (windowBox.width <= 1 || windowBox.height <= 1) { if (windowBox.width <= 1 || windowBox.height <= 1) {
if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) {
Debug::log(TRACE, "presentFeedback for invisible surface");
surface->presentFeedback(RDATA->when, RDATA->pMonitor); surface->presentFeedback(RDATA->when, RDATA->pMonitor);
}
return; // invisible return; // invisible
} }
@ -245,8 +235,10 @@ static void renderSurface(SP<CWLSurfaceResource> surface, int x, int y, void* da
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA, rounding, false, true); g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA, rounding, false, true);
} }
if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) {
Debug::log(TRACE, "presentFeedback for visible surface");
surface->presentFeedback(RDATA->when, RDATA->pMonitor); surface->presentFeedback(RDATA->when, RDATA->pMonitor);
}
g_pHyprOpenGL->blend(true); g_pHyprOpenGL->blend(true);
@ -1099,8 +1091,10 @@ bool CHyprRenderer::attemptDirectScanout(CMonitor* pMonitor) {
if (!pMonitor->mirrors.empty() || pMonitor->isMirror() || m_bDirectScanoutBlocked) if (!pMonitor->mirrors.empty() || pMonitor->isMirror() || m_bDirectScanoutBlocked)
return false; // do not DS if this monitor is being mirrored. Will break the functionality. return false; // do not DS if this monitor is being mirrored. Will break the functionality.
if (g_pPointerManager->softwareLockedFor(pMonitor->self.lock())) if (g_pPointerManager->softwareLockedFor(pMonitor->self.lock())) {
Debug::log(TRACE, "Direct scanout failed: soft locked / HW cursors failed");
return false; return false;
}
const auto PCANDIDATE = pMonitor->solitaryClient.lock(); const auto PCANDIDATE = pMonitor->solitaryClient.lock();
@ -1126,7 +1120,8 @@ bool CHyprRenderer::attemptDirectScanout(CMonitor* pMonitor) {
timespec now; timespec now;
clock_gettime(CLOCK_MONOTONIC, &now); clock_gettime(CLOCK_MONOTONIC, &now);
PSURFACE->presentFeedback(&now, pMonitor); Debug::log(TRACE, "presentFeedback for DS");
PSURFACE->presentFeedback(&now, pMonitor, true);
if (pMonitor->state.commit()) { if (pMonitor->state.commit()) {
if (m_pLastScanout.expired()) { if (m_pLastScanout.expired()) {
@ -1458,16 +1453,27 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(CMonitor* pMonitor) {
// apply timelines for explicit sync // apply timelines for explicit sync
bool anyExplicit = !explicitPresented.empty(); bool anyExplicit = !explicitPresented.empty();
if (anyExplicit) { if (anyExplicit) {
pMonitor->output->state->setExplicitInFence(pMonitor->inTimeline->exportAsSyncFileFD(pMonitor->lastWaitPoint)); Debug::log(TRACE, "Explicit sync presented begin");
auto inFence = pMonitor->inTimeline->exportAsSyncFileFD(pMonitor->lastWaitPoint);
if (inFence < 0)
Debug::log(ERR, "Export lastWaitPoint {} as sync explicitInFence failed", pMonitor->lastWaitPoint);
pMonitor->output->state->setExplicitInFence(inFence);
for (auto& e : explicitPresented) { for (auto& e : explicitPresented) {
Debug::log(TRACE, "Explicit sync presented releasePoint {}", e->syncobj && e->syncobj->releaseTimeline ? e->syncobj->releasePoint : -1);
if (!e->syncobj || !e->syncobj->releaseTimeline) if (!e->syncobj || !e->syncobj->releaseTimeline)
continue; continue;
e->syncobj->releaseTimeline->timeline->transfer(pMonitor->outTimeline, pMonitor->commitSeq, e->syncobj->releasePoint); e->syncobj->releaseTimeline->timeline->transfer(pMonitor->outTimeline, pMonitor->commitSeq, e->syncobj->releasePoint);
} }
explicitPresented.clear(); explicitPresented.clear();
pMonitor->output->state->setExplicitOutFence(pMonitor->outTimeline->exportAsSyncFileFD(pMonitor->commitSeq)); auto outFence = pMonitor->outTimeline->exportAsSyncFileFD(pMonitor->commitSeq);
if (outFence < 0)
Debug::log(ERR, "Export commitSeq {} as sync explicitOutFence failed", pMonitor->commitSeq);
pMonitor->output->state->setExplicitOutFence(outFence);
Debug::log(TRACE, "Explicit sync presented end");
} }
pMonitor->lastWaitPoint = 0; pMonitor->lastWaitPoint = 0;
@ -1475,23 +1481,25 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(CMonitor* pMonitor) {
const auto COMMITTED_OUT = pMonitor->output->state->state().explicitOutFence; const auto COMMITTED_OUT = pMonitor->output->state->state().explicitOutFence;
const auto COMMITTED_IN = pMonitor->output->state->state().explicitInFence; const auto COMMITTED_IN = pMonitor->output->state->state().explicitInFence;
if (!pMonitor->state.commit()) { bool commited = pMonitor->state.commit();
if (!commited) {
Debug::log(TRACE, "Monitor state commit failed");
// rollback the buffer to avoid writing to the front buffer that is being // rollback the buffer to avoid writing to the front buffer that is being
// displayed // displayed
pMonitor->output->swapchain->rollback(); pMonitor->output->swapchain->rollback();
pMonitor->damage.damageEntire(); pMonitor->damage.damageEntire();
return false;
} }
if (COMMITTED_IN >= 0) if (COMMITTED_IN >= 0)
close(COMMITTED_IN); close(COMMITTED_IN);
if (COMMITTED_OUT >= 0) { if (COMMITTED_OUT >= 0) {
if (commited)
pMonitor->outTimeline->importFromSyncFileFD(pMonitor->commitSeq, COMMITTED_OUT); pMonitor->outTimeline->importFromSyncFileFD(pMonitor->commitSeq, COMMITTED_OUT);
close(COMMITTED_OUT); close(COMMITTED_OUT);
} }
return true; return commited;
} }
void CHyprRenderer::renderWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const CBox& geometry) { void CHyprRenderer::renderWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const CBox& geometry) {
@ -2687,13 +2695,10 @@ void CHyprRenderer::endRender() {
if (m_eRenderMode == RENDER_MODE_FULL_FAKE) if (m_eRenderMode == RENDER_MODE_FULL_FAKE)
return; return;
if (isNvidia() && *PNVIDIAANTIFLICKER)
glFinish();
if (m_eRenderMode == RENDER_MODE_NORMAL) { if (m_eRenderMode == RENDER_MODE_NORMAL) {
PMONITOR->output->state->setBuffer(m_pCurrentBuffer); PMONITOR->output->state->setBuffer(m_pCurrentBuffer);
if (PMONITOR->output->state->state().explicitOutFence >= 0) { if (PMONITOR->inTimeline) {
auto sync = g_pHyprOpenGL->createEGLSync(-1); auto sync = g_pHyprOpenGL->createEGLSync(-1);
if (!sync) { if (!sync) {
m_pCurrentRenderbuffer->unbind(); m_pCurrentRenderbuffer->unbind();
@ -2713,7 +2718,7 @@ void CHyprRenderer::endRender() {
return; return;
} }
bool ok = PMONITOR->outTimeline->importFromSyncFileFD(PMONITOR->commitSeq, dupedfd); bool ok = PMONITOR->inTimeline->importFromSyncFileFD(PMONITOR->commitSeq, dupedfd);
close(dupedfd); close(dupedfd);
if (!ok) { if (!ok) {
m_pCurrentRenderbuffer->unbind(); m_pCurrentRenderbuffer->unbind();
@ -2722,9 +2727,13 @@ void CHyprRenderer::endRender() {
Debug::log(ERR, "renderer: couldn't import from sync file fd in endRender"); Debug::log(ERR, "renderer: couldn't import from sync file fd in endRender");
return; return;
} }
} else } else {
if (isNvidia() && *PNVIDIAANTIFLICKER)
glFinish();
else
glFlush(); glFlush();
} }
}
m_pCurrentRenderbuffer->unbind(); m_pCurrentRenderbuffer->unbind();