renderer: reduce per-frame heap allocations (#14932)

* renderer: reduce per-frame heap allocations

* renderer: avoid temporary traversal allocations

* renderer: avoid read-only hot-path copies

* config/actions: guard workspace change without active workspace

* config/lua: release owned state on shutdown

---------

Co-authored-by: Pppp1116 <pcaiadoguerreiro@gmail.com>
This commit is contained in:
NotPppp1116
2026-06-07 12:27:12 +02:00
committed by Vaxry
co-authored by Pppp1116
parent 0e21e051a2
commit ff41b04e7c
16 changed files with 152 additions and 93 deletions
+15 -3
View File
@@ -201,6 +201,17 @@ CConfigManager::CConfigManager() : m_mainConfigPath(Supplementary::Jeremy::getMa
});
}
CConfigManager::~CConfigManager() {
m_eventHandler.reset();
cleanTimers();
clearLuaLayoutProviders();
clearHeldLuaRefs();
if (m_lua && m_ownsLuaState)
lua_close(m_lua);
}
CConfigManager* CConfigManager::fromLuaState(lua_State* L) {
if (!L)
return nullptr;
@@ -281,12 +292,13 @@ void CConfigManager::reinitLuaState() {
cleanTimers();
clearLuaLayoutProviders();
if (m_lua) {
if (m_lua && m_ownsLuaState) {
lua_close(m_lua);
m_lua = nullptr;
}
m_lua = nullptr;
m_lua = luaL_newstate();
m_lua = luaL_newstate();
m_ownsLuaState = true;
luaL_openlibs(m_lua);
lua_getglobal(m_lua, "debug");
+3 -1
View File
@@ -52,6 +52,7 @@ namespace Config::Lua {
class CConfigManager : public Config::IConfigManager {
public:
CConfigManager();
virtual ~CConfigManager() override;
virtual eConfigManagerType type() override;
@@ -157,7 +158,8 @@ namespace Config::Lua {
static void watchdogHook(lua_State* L, lua_Debug* ar);
lua_State* m_lua = nullptr;
lua_State* m_lua = nullptr;
bool m_ownsLuaState = false;
bool m_lastConfigVerificationWasSuccessful = true;
bool m_isFirstLaunch = true;
+4 -1
View File
@@ -978,7 +978,10 @@ static PHLWORKSPACE resolveWorkspaceForChange(const std::string& args) {
return nullptr;
const auto PCURRENTWORKSPACE = PMONITOR->m_activeWorkspace;
const bool EXPLICITPREVIOUS = args.contains("previous");
if (!PCURRENTWORKSPACE)
return nullptr;
const bool EXPLICITPREVIOUS = args.contains("previous");
// handle "previous" workspace
if (args.starts_with("previous")) {
+7 -4
View File
@@ -12,6 +12,7 @@
#include "../../managers/eventLoop/EventLoopManager.hpp"
#include "../../render/Renderer.hpp"
#include "../../render/OpenGL.hpp"
#include <array>
#include <ranges>
using namespace Desktop;
@@ -438,6 +439,7 @@ void CPopup::recheckChildrenRecursive() {
return;
std::vector<WP<CPopup>> cpy;
cpy.reserve(m_children.size());
std::ranges::for_each(m_children, [&cpy](const auto& el) { cpy.emplace_back(el); });
for (auto const& c : cpy) {
if (!c || !c->visible())
@@ -464,19 +466,21 @@ void CPopup::sendScale() {
UNREACHABLE();
}
void CPopup::bfHelper(std::vector<SP<CPopup>> const& nodes, std::function<void(SP<CPopup>, void*)> fn, void* data) {
void CPopup::bfHelper(std::span<const SP<CPopup>> nodes, std::function<void(SP<CPopup>, void*)> fn, void* data) {
for (auto const& n : nodes) {
fn(n, data);
}
std::vector<SP<CPopup>> nodes2;
nodes2.reserve(nodes.size() * 2);
for (auto const& n : nodes) {
if (!n)
continue;
for (auto const& c : n->m_children) {
if (nodes2.empty())
nodes2.reserve(nodes.size() * 2);
nodes2.emplace_back(c->m_self.lock());
}
}
@@ -489,8 +493,7 @@ void CPopup::breadthfirst(std::function<void(SP<CPopup>, void*)> fn, void* data)
if (!m_self)
return;
std::vector<SP<CPopup>> popups;
popups.emplace_back(m_self.lock());
const std::array popups = {m_self.lock()};
bfHelper(popups, fn, data);
}
+2 -1
View File
@@ -1,5 +1,6 @@
#pragma once
#include <span>
#include <vector>
#include "Subsurface.hpp"
#include "View.hpp"
@@ -114,6 +115,6 @@ namespace Desktop::View {
Vector2D localToGlobal(const Vector2D& rel) const;
Vector2D t1ParentCoords() const;
void invalidateTreeExtentsCache();
static void bfHelper(std::vector<SP<CPopup>> const& nodes, std::function<void(SP<CPopup>, void*)> fn, void* data);
static void bfHelper(std::span<const SP<CPopup>> nodes, std::function<void(SP<CPopup>, void*)> fn, void* data);
};
}
+23 -12
View File
@@ -1,5 +1,8 @@
#include <algorithm>
#include <array>
#include <cmath>
#include <ranges>
#include <span>
#include <hyprutils/animation/AnimatedVariable.hpp>
#include <re2/re2.h>
@@ -353,20 +356,28 @@ void CWindow::updateWindowDecos() {
m_decosToRemove.clear();
// make a copy because updateWindow can remove decos.
const auto updateDecos = [this](const auto& decos) {
for (auto const& wd : decos) {
if (std::ranges::find_if(m_windowDecorations, [wd](const auto& other) { return other.get() == wd; }) == m_windowDecorations.end())
continue;
wd->updateWindow(m_self.lock());
}
};
// Make a copy because updateWindow can remove decos. The built-in set fits inline,
// while the fallback preserves support for arbitrary plugin decorations.
constexpr size_t INLINE_DECOS = 4;
std::array<IHyprWindowDecoration*, INLINE_DECOS> inlineDecos = {};
if (m_windowDecorations.size() <= inlineDecos.size()) {
std::ranges::transform(m_windowDecorations, inlineDecos.begin(), [](const auto& deco) { return deco.get(); });
updateDecos(std::span{inlineDecos}.first(m_windowDecorations.size()));
return;
}
std::vector<IHyprWindowDecoration*> decos;
// reserve to avoid reallocations
decos.reserve(m_windowDecorations.size());
for (auto const& wd : m_windowDecorations) {
decos.push_back(wd.get());
}
for (auto const& wd : decos) {
if (std::ranges::find_if(m_windowDecorations, [wd](const auto& other) { return other.get() == wd; }) == m_windowDecorations.end())
continue;
wd->updateWindow(m_self.lock());
}
std::ranges::transform(m_windowDecorations, std::back_inserter(decos), [](const auto& deco) { return deco.get(); });
updateDecos(decos);
}
void CWindow::addWindowDeco(UP<IHyprWindowDecoration> deco) {
+1 -1
View File
@@ -41,7 +41,7 @@ CRegion CDamageRing::getBufferDamage(int age) {
}
// don't return a ludicrous amount of rects
if (damage.getRects().size() > 8)
if (pixman_region32_n_rects(damage.pixman()) > 8)
return damage.getExtents();
return damage;
+13 -5
View File
@@ -4,6 +4,7 @@
#include "Seat.hpp"
#include "../types/WLBuffer.hpp"
#include <algorithm>
#include <array>
#include <ranges>
#include "Subcompositor.hpp"
#include "../Viewporter.hpp"
@@ -351,9 +352,8 @@ void CWLSurfaceResource::resetRole() {
m_role = makeShared<CDefaultSurfaceRole>();
}
void CWLSurfaceResource::bfHelper(std::vector<SP<CWLSurfaceResource>> const& nodes, std::function<void(SP<CWLSurfaceResource>, const Vector2D&, void*)> fn, void* data) {
void CWLSurfaceResource::bfHelper(std::span<const SP<CWLSurfaceResource>> nodes, std::function<void(SP<CWLSurfaceResource>, const Vector2D&, void*)> fn, void* data) {
std::vector<SP<CWLSurfaceResource>> nodes2;
nodes2.reserve(nodes.size() * 2);
// first, gather all nodes below
for (auto const& n : nodes) {
@@ -372,6 +372,9 @@ void CWLSurfaceResource::bfHelper(std::vector<SP<CWLSurfaceResource>> const& nod
if (!surface)
continue;
if (nodes2.empty())
nodes2.reserve(nodes.size() * 2);
nodes2.emplace_back(surface);
}
}
@@ -407,6 +410,9 @@ void CWLSurfaceResource::bfHelper(std::vector<SP<CWLSurfaceResource>> const& nod
if (!surface)
continue;
if (nodes2.empty())
nodes2.reserve(nodes.size() * 2);
nodes2.emplace_back(surface);
}
}
@@ -416,8 +422,7 @@ void CWLSurfaceResource::bfHelper(std::vector<SP<CWLSurfaceResource>> const& nod
}
void CWLSurfaceResource::breadthfirst(std::function<void(SP<CWLSurfaceResource>, const Vector2D&, void*)> fn, void* data) {
std::vector<SP<CWLSurfaceResource>> surfs;
surfs.emplace_back(m_self.lock());
const std::array surfs = {m_self.lock()};
bfHelper(surfs, fn, data);
}
@@ -710,7 +715,10 @@ void CWLSurfaceResource::updateCursorShm(CRegion damage) {
shmData.resize(bufLen);
if (const auto RECTS = damage.getRects(); RECTS.size() == 1 && RECTS.at(0).x2 == buf->size.x && RECTS.at(0).y2 == buf->size.y)
int rectsNum = 0;
const auto* rects = pixman_region32_rectangles(damage.pixman(), &rectsNum);
if (rectsNum == 1 && rects[0].x2 == buf->size.x && rects[0].y2 == buf->size.y)
memcpy(shmData.data(), pixelData, bufLen);
else {
damage.forEachRect([&pixelData, &shmData](const auto& box) {
+2 -1
View File
@@ -8,6 +8,7 @@
- wl_callback
*/
#include <span>
#include <vector>
#include <queue>
#include <cstdint>
@@ -142,7 +143,7 @@ class CWLSurfaceResource {
void releaseBuffers(bool onlyCurrent = true);
void dropPendingBuffer();
void dropCurrentBuffer();
void bfHelper(std::vector<SP<CWLSurfaceResource>> const& nodes, std::function<void(SP<CWLSurfaceResource>, const Vector2D&, void*)> fn, void* data);
void bfHelper(std::span<const SP<CWLSurfaceResource>> nodes, std::function<void(SP<CWLSurfaceResource>, const Vector2D&, void*)> fn, void* data);
SP<CWLSurfaceResource> findFirstPreorderHelper(SP<CWLSurfaceResource> root, std::function<bool(SP<CWLSurfaceResource>)> fn);
void updateCursorShm(CRegion damage = CBox{0, 0, INT16_MAX, INT16_MAX});
+3 -3
View File
@@ -187,7 +187,7 @@ void IElementRenderer::drawRect(WP<CRectPassElement> element, const CRegion& dam
}
void IElementRenderer::drawHints(WP<CRendererHintsPassElement> element, const CRegion& damage) {
const auto m_data = element->m_data;
const auto& m_data = element->m_data;
if (m_data.renderModif.has_value())
g_pHyprRenderer->m_renderData.renderModif = *m_data.renderModif;
}
@@ -216,7 +216,7 @@ void IElementRenderer::drawClear(WP<CClearPassElement> element, const CRegion& d
}
void IElementRenderer::drawSurface(WP<CSurfacePassElement> element, const CRegion& damage) {
const auto m_data = element->m_data;
const auto& m_data = element->m_data;
auto& m_renderData = g_pHyprRenderer->m_renderData;
Hyprutils::Utils::CScopeGuard x = {[]() {
@@ -472,7 +472,7 @@ void IElementRenderer::drawTexMatte(WP<CTextureMatteElement> element, const CReg
if (g_pHyprRenderer->m_renderData.damage.empty())
return;
const auto m_data = element->m_data;
const auto& m_data = element->m_data;
if (m_data.disableTransformAndModify) {
g_pHyprRenderer->pushMonitorTransformEnabled(true);
g_pHyprRenderer->m_renderData.renderModif.enabled = false;
+24 -21
View File
@@ -1492,33 +1492,36 @@ void CHyprOpenGLImpl::renderTextureInternal(SP<ITexture> tex, const CBox& box, c
shader->setUniformMatrix3fv(SHADER_PROJ, 1, GL_TRUE, glMatrix.getMatrix());
shader->setUniformInt(SHADER_TEX, 0);
GLCALL(glBindVertexArray(shader->getUniformLocation(SHADER_SHADER_VAO)));
GLCALL(glBindBuffer(GL_ARRAY_BUFFER, shader->getUniformLocation(SHADER_SHADER_VBO)));
// this tells GPU can keep reading the old block for previous draws while the CPU writes to a new one.
// to avoid stalls if renderTextureInternal is called multiple times on same renderpass
// at the cost of some temporar vram usage.
glBufferData(GL_ARRAY_BUFFER, sizeof(fullVerts), nullptr, GL_DYNAMIC_DRAW);
const bool CUSTOMUV = data.allowCustomUV && data.primarySurfaceUVTopLeft != Vector2D(-1, -1);
if (CUSTOMUV || shader->usesCustomUV()) {
GLCALL(glBindBuffer(GL_ARRAY_BUFFER, shader->getUniformLocation(SHADER_SHADER_VBO)));
auto verts = fullVerts;
// Keep the old block available to previous draws while custom UVs update, or while restoring the defaults.
glBufferData(GL_ARRAY_BUFFER, sizeof(fullVerts), nullptr, GL_DYNAMIC_DRAW);
if (data.allowCustomUV && data.primarySurfaceUVTopLeft != Vector2D(-1, -1)) {
const float u0 = data.primarySurfaceUVTopLeft.x;
const float v0 = data.primarySurfaceUVTopLeft.y;
const float u1 = data.primarySurfaceUVBottomRight.x;
const float v1 = data.primarySurfaceUVBottomRight.y;
auto verts = fullVerts;
verts[0].u = u0;
verts[0].v = v0;
verts[1].u = u0;
verts[1].v = v1;
verts[2].u = u1;
verts[2].v = v0;
verts[3].u = u1;
verts[3].v = v1;
if (CUSTOMUV) {
const float u0 = data.primarySurfaceUVTopLeft.x;
const float v0 = data.primarySurfaceUVTopLeft.y;
const float u1 = data.primarySurfaceUVBottomRight.x;
const float v1 = data.primarySurfaceUVBottomRight.y;
verts[0].u = u0;
verts[0].v = v0;
verts[1].u = u0;
verts[1].v = v1;
verts[2].u = u1;
verts[2].v = v0;
verts[3].u = u1;
verts[3].v = v1;
}
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(verts), verts.data());
shader->setUsesCustomUV(CUSTOMUV);
}
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(verts), verts.data());
if (!g_pHyprRenderer->m_renderData.clipBox.empty() || !data.clipRegion.empty()) {
CRegion damageClip = g_pHyprRenderer->m_renderData.clipBox;
+11 -2
View File
@@ -7,7 +7,7 @@
using namespace Render::GL;
static bool compareFloat(auto a, auto b) {
static bool compareFloat(const auto& a, const auto& b) {
if (a.size() != b.size())
return false;
@@ -243,6 +243,7 @@ void CShader::createVao() {
m_uniformLocations[SHADER_SHADER_VAO] = shaderVao;
m_uniformLocations[SHADER_SHADER_VBO] = shaderVbo;
m_usesCustomUV = false;
RASSERT(m_uniformLocations[SHADER_SHADER_VAO] >= 0, "SHADER_SHADER_VAO could not be created");
RASSERT(m_uniformLocations[SHADER_SHADER_VBO] >= 0, "SHADER_SHADER_VBO_POS could not be created");
@@ -365,7 +366,7 @@ void CShader::setUniformfv(eShaderUniform location, GLsizei count, const std::ve
auto& cached = uniformStatus.at(location);
if (cached.index() != 0) {
auto val = std::get<SUniformVData>(cached);
const auto& val = std::get<SUniformVData>(cached);
if (val.count == count && compareFloat(val.value, value))
return;
}
@@ -427,3 +428,11 @@ int CShader::getInitialTime() const {
void CShader::setInitialTime(int time) {
m_initialTime = time;
}
bool CShader::usesCustomUV() const {
return m_usesCustomUV;
}
void CShader::setUsesCustomUV(bool usesCustomUV) {
m_usesCustomUV = usesCustomUV;
}
+5 -2
View File
@@ -107,10 +107,13 @@ class CShader {
GLint getUniformLocation(eShaderUniform location) const;
int getInitialTime() const;
void setInitialTime(int time);
bool usesCustomUV() const;
void setUsesCustomUV(bool usesCustomUV);
private:
GLuint m_program = 0;
float m_initialTime = 0;
GLuint m_program = 0;
float m_initialTime = 0;
bool m_usesCustomUV = false;
std::array<GLint, SHADER_LAST> m_uniformLocations;
struct SUniformMatrix3Data {
+6 -6
View File
@@ -8,7 +8,7 @@
using namespace Render::GL;
void CGLElementRenderer::draw(WP<CBorderPassElement> element, const CRegion& damage) {
const auto m_data = element->m_data;
const auto& m_data = element->m_data;
if (m_data.hasGrad2)
g_pHyprOpenGL->renderBorder(
m_data.box, m_data.grad1, m_data.grad2, m_data.lerp,
@@ -81,7 +81,7 @@ void CGLElementRenderer::draw(WP<CPreBlurElement> element, const CRegion& damage
};
void CGLElementRenderer::draw(WP<CRectPassElement> element, const CRegion& damage) {
const auto m_data = element->m_data;
const auto& m_data = element->m_data;
if (m_data.color.a == 1.F || !m_data.blur)
g_pHyprOpenGL->renderRect(m_data.box, m_data.color, {.damage = &damage, .round = m_data.round, .roundingPower = m_data.roundingPower});
@@ -91,17 +91,17 @@ void CGLElementRenderer::draw(WP<CRectPassElement> element, const CRegion& damag
};
void CGLElementRenderer::draw(WP<CShadowPassElement> element, const CRegion& damage) {
const auto m_data = element->m_data;
const auto& m_data = element->m_data;
m_data.deco->render(g_pHyprRenderer->m_renderData.pMonitor.lock(), m_data.a);
};
void CGLElementRenderer::draw(WP<CInnerGlowPassElement> element, const CRegion& damage) {
const auto m_data = element->m_data;
const auto& m_data = element->m_data;
m_data.deco->render(g_pHyprRenderer->m_renderData.pMonitor.lock(), m_data.a);
};
void CGLElementRenderer::draw(WP<CTexPassElement> element, const CRegion& damage) {
const auto m_data = element->m_data;
const auto& m_data = element->m_data;
g_pHyprOpenGL->renderTexture( //
m_data.tex, m_data.box,
@@ -133,7 +133,7 @@ void CGLElementRenderer::draw(WP<CTexPassElement> element, const CRegion& damage
};
void CGLElementRenderer::draw(WP<CTextureMatteElement> element, const CRegion& damage) {
const auto m_data = element->m_data;
const auto& m_data = element->m_data;
g_pHyprOpenGL->renderTextureMatte(m_data.tex, m_data.box, m_data.fb);
};
+29 -26
View File
@@ -24,7 +24,7 @@ bool CRenderPass::single() const {
}
void CRenderPass::add(UP<IPassElement>&& el) {
m_passElements.emplace_back(makeUnique<SPassElementData>(CRegion{}, std::move(el)));
m_passElements.emplace_back(SPassElementData{.element = std::move(el)});
}
void CRenderPass::simplify(bool willBlur, const CRegion& liveBlurRegion) {
@@ -36,29 +36,32 @@ void CRenderPass::simplify(bool willBlur, const CRegion& liveBlurRegion) {
CRegion newDamage = m_damage.copy().intersect(CBox{{}, pMonitor->m_transformedSize});
for (auto& el : m_passElements | std::views::reverse) {
if (newDamage.empty() && !el->element->undiscardable()) {
el->discard = true;
if (newDamage.empty() && !el.element->undiscardable()) {
el.discard = true;
continue;
}
el->elementDamage = newDamage;
auto bb1 = el->element->boundingBox();
if (!bb1 || newDamage.empty())
auto bb1 = el.element->boundingBox();
if (!bb1 || newDamage.empty()) {
el.elementDamage = newDamage;
continue;
}
auto bb = bb1->scale(pMonitor->m_scale);
// drop if empty
if (CRegion copy = newDamage.copy(); copy.intersect(bb).empty()) {
el->discard = true;
el.discard = true;
continue;
}
auto opaque = el->element->opaqueRegion();
el.elementDamage = newDamage;
auto opaque = el.element->opaqueRegion();
if (!opaque.empty()) {
// scale and rounding is very particular so we have to use CBoxes scale and round functions
if (opaque.getRects().size() == 1)
if (pixman_region32_n_rects(opaque.pixman()) == 1)
opaque = opaque.getExtents().scale(pMonitor->m_scale).round();
else {
CRegion scaledRegion;
@@ -85,10 +88,10 @@ void CRenderPass::simplify(bool willBlur, const CRegion& liveBlurRegion) {
if (*PDEBUGPASS) {
for (auto& el2 : m_passElements) {
if (!el2->element->needsLiveBlurCached)
if (!el2.element->needsLiveBlurCached)
continue;
const auto BB = el2->element->boundingBox();
const auto BB = el2.element->boundingBox();
RASSERT(BB, "No bounding box for an element with live blur is illegal");
m_totalLiveBlurRegion.add(BB->copy().scale(pMonitor->m_scale));
@@ -108,20 +111,20 @@ CRegion CRenderPass::render(const CRegion& damage_) {
bool willBlur = false, willDisableSimplification = false, willPrecomputeBlur = false;
CRegion blurRegion;
for (auto& el : m_passElements) {
el->element->needsLiveBlurCached = el->element->needsLiveBlur();
el->element->needsPrecomputeBlurCached = el->element->needsPrecomputeBlur();
el.element->needsLiveBlurCached = el.element->needsLiveBlur();
el.element->needsPrecomputeBlurCached = el.element->needsPrecomputeBlur();
if (el->element->needsLiveBlurCached) {
if (el.element->needsLiveBlurCached) {
willBlur = true;
const auto BB = el->element->boundingBox();
const auto BB = el.element->boundingBox();
RASSERT(BB, "No bounding box for an element with live blur is illegal");
blurRegion.add(*BB);
}
if (el->element->needsPrecomputeBlurCached)
if (el.element->needsPrecomputeBlurCached)
willPrecomputeBlur = true;
if (el->element->disableSimplification())
if (el.element->disableSimplification())
willDisableSimplification = true;
}
@@ -169,7 +172,7 @@ CRegion CRenderPass::render(const CRegion& damage_) {
if (g_pHyprRenderer->m_renderData.noSimplify || willDisableSimplification) {
for (auto& el : m_passElements) {
el->elementDamage = m_damage;
el.elementDamage = m_damage;
}
} else
simplify(willBlur, liveBlurRegion);
@@ -181,13 +184,13 @@ CRegion CRenderPass::render(const CRegion& damage_) {
return {};
for (auto& el : m_passElements) {
if (el->discard) {
el->element->discard();
if (el.discard) {
el.element->discard();
continue;
}
g_pHyprRenderer->m_renderData.damage = el->elementDamage;
g_pHyprRenderer->draw(el->element, el->elementDamage);
g_pHyprRenderer->m_renderData.damage = el.elementDamage;
g_pHyprRenderer->draw(el.element, el.elementDamage);
}
if (*PDEBUGPASS) {
@@ -273,7 +276,7 @@ void CRenderPass::renderDebugData() {
}
}
const auto DISCARDED_ELEMENTS = std::ranges::count_if(m_passElements, [](const auto& e) { return e->discard; });
const auto DISCARDED_ELEMENTS = std::ranges::count_if(m_passElements, [](const auto& e) { return e.discard; });
auto tex = g_pHyprRenderer->renderText(std::format("occlusion layers: {}\npass elements: {} ({} discarded)\nviewport: {:X0}", m_occludedRegions.size(), m_passElements.size(),
DISCARDED_ELEMENTS, pMonitor->m_pixelSize),
Colors::WHITE, 12);
@@ -290,8 +293,8 @@ void CRenderPass::renderDebugData() {
auto yn = [](const bool val) -> const char* { return val ? "yes" : "no"; };
auto tick = [](const bool val) -> const char* { return val ? "✔" : "✖"; };
for (const auto& el : m_passElements | std::views::reverse) {
passStructure += std::format("{} {} (bb: {} op: {}, pb: {}, lb: {})\n", tick(!el->discard), el->element->passName(), yn(el->element->boundingBox().has_value()),
yn(!el->element->opaqueRegion().empty()), yn(el->element->needsPrecomputeBlurCached), yn(el->element->needsLiveBlurCached));
passStructure += std::format("{} {} (bb: {} op: {}, pb: {}, lb: {})\n", tick(!el.discard), el.element->passName(), yn(el.element->boundingBox().has_value()),
yn(!el.element->opaqueRegion().empty()), yn(el.element->needsPrecomputeBlurCached), yn(el.element->needsLiveBlurCached));
}
if (!passStructure.empty())
@@ -318,5 +321,5 @@ float CRenderPass::oneBlurRadius() {
}
void CRenderPass::removeAllOfType(const std::string& type) {
std::erase_if(m_passElements, [&type](const auto& e) { return e->element->passName() == type; });
std::erase_if(m_passElements, [&type](const auto& e) { return e.element->passName() == type; });
}
+4 -4
View File
@@ -30,11 +30,11 @@ namespace Render {
bool discard = false;
};
std::vector<UP<SPassElementData>> m_passElements;
std::vector<SPassElementData> m_passElements;
void simplify(bool willBlur, const CRegion& liveBlurRegion);
float oneBlurRadius();
void renderDebugData();
void simplify(bool willBlur, const CRegion& liveBlurRegion);
float oneBlurRadius();
void renderDebugData();
struct {
bool present = false;