From 5b1c0fda73fe2ae1ada5ce0cecac43aeab8b0a3b Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Sat, 8 Aug 2026 22:46:26 +0200 Subject: [PATCH] renderer/fp16: fix blur clear and invalidate (#15791) the clear was scissored to m_renderData.damage while we fakeDamaged full monitor. so in render pass when m_blurFBShouldRender is hit the FB was cleared over partial damage but rendered over whole monitor causing stale blur blends into the new outside damage. so save old damage, render fakeDamage, restore old damage. invalidate({GL_DEPTH_STENCIL_ATTACHMENT}) at end of renderTextureWithBlurInternal cant set m_cleared = false because its not invalidated the COLOR_ATTACHMENT, so guard invalidate. --- src/render/ElementRenderer.cpp | 4 ++++ src/render/OpenGL.cpp | 14 ++++++-------- src/render/gl/GLFramebuffer.cpp | 5 ++++- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/render/ElementRenderer.cpp b/src/render/ElementRenderer.cpp index 36ba431f3..d95486395 100644 --- a/src/render/ElementRenderer.cpp +++ b/src/render/ElementRenderer.cpp @@ -197,17 +197,21 @@ void IElementRenderer::drawPreBlur(WP element, const CRegion& d auto& m_renderData = g_pHyprRenderer->m_renderData; const auto SAVEDRENDERMODIF = m_renderData.renderModif; + const auto SAVEDDAMAGE = m_renderData.damage; m_renderData.renderModif = {}; // fix shit // make the fake dmg CRegion fakeDamage{0, 0, m_renderData.pMonitor->m_transformedSize.x, m_renderData.pMonitor->m_transformedSize.y}; + m_renderData.damage = fakeDamage; // the clear inside scissors to renderData.damage, it has to match the blit + draw(element, fakeDamage); m_renderData.pMonitor->m_blurFBDirty = false; m_renderData.pMonitor->m_blurFBShouldRender = false; m_renderData.renderModif = SAVEDRENDERMODIF; + m_renderData.damage = SAVEDDAMAGE; } void IElementRenderer::drawClear(WP element, const CRegion& damage) { diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 346a52db1..c04d1e88d 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -918,14 +918,12 @@ void CHyprOpenGLImpl::end() { g_pHyprRenderer->m_renderData.mainFB.reset(); g_pHyprRenderer->m_renderData.outFB.reset(); // invalidate our render FBs to signal to the driver we don't need them anymore - if (!g_pHyprRenderer->m_renderData.pMonitor->useFP16()) { // FIXME wtf? - g_pHyprRenderer->m_renderData.pMonitor->resources()->forEachUnusedFB( - [](const auto& fb) { - fb->bind(); - GLFB(fb)->invalidate({GL_DEPTH_STENCIL_ATTACHMENT, GL_COLOR_ATTACHMENT0}); - }, - false); - } + g_pHyprRenderer->m_renderData.pMonitor->resources()->forEachUnusedFB( + [](const auto& fb) { + fb->bind(); + GLFB(fb)->invalidate({GL_DEPTH_STENCIL_ATTACHMENT, GL_COLOR_ATTACHMENT0}); + }, + false); m_renderData.pMonitor.reset(); diff --git a/src/render/gl/GLFramebuffer.cpp b/src/render/gl/GLFramebuffer.cpp index bfe4c49e2..f8e70fe0b 100644 --- a/src/render/gl/GLFramebuffer.cpp +++ b/src/render/gl/GLFramebuffer.cpp @@ -4,6 +4,7 @@ #include "macros.hpp" #include "../Framebuffer.hpp" #include +#include #include using namespace Hyprgraphics::Egl; @@ -259,7 +260,9 @@ void CGLFramebuffer::invalidate(const std::vector& attachments) { if (*PFBINVALIDATE) glInvalidateFramebuffer(GL_FRAMEBUFFER, attachments.size(), attachments.data()); - m_cleared = false; + // m_cleared tracks the color attachment only, see clearAfterInvalidation() + if (std::ranges::contains(attachments, sc(GL_COLOR_ATTACHMENT0))) + m_cleared = false; } void CGLFramebuffer::clearAfterInvalidation() {