diff --git a/.gitmodules b/.gitmodules index 26dbceeb..c62f5b53 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "subprojects/udis86"] path = subprojects/udis86 url = https://github.com/canihavesomecoffee/udis86 +[submodule "subprojects/tracy"] + path = subprojects/tracy + url = https://github.com/wolfpld/tracy diff --git a/CMakeLists.txt b/CMakeLists.txt index 88d2d279..490e8a42 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -141,6 +141,21 @@ else() endif() endif() +if(USE_TRACY) + message(STATUS "Tracy is turned on") + + option( TRACY_ENABLE "" ON) + option( TRACY_ON_DEMAND "" ON) + add_subdirectory (subprojects/tracy) + + target_link_libraries(Hyprland PkgConfig::deps Tracy::TracyClient) + + if(USE_TRACY_GPU) + message(STATUS "Tracy GPU Profiling is turned on") + add_compile_definitions(USE_TRACY_GPU) + endif() +endif() + target_compile_definitions(Hyprland PRIVATE "GIT_COMMIT_HASH=\"${GIT_COMMIT_HASH}\"" @@ -177,8 +192,6 @@ function(protocol protoPath protoName external) endif() endfunction() -target_link_libraries(Hyprland PkgConfig::deps) - target_link_libraries(Hyprland ${CMAKE_SOURCE_DIR}/subprojects/wlroots/build/libwlroots.so.12032 # wlroots is provided by us OpenGL::EGL diff --git a/src/debug/TracyDefines.hpp b/src/debug/TracyDefines.hpp new file mode 100644 index 00000000..b96a71dd --- /dev/null +++ b/src/debug/TracyDefines.hpp @@ -0,0 +1,35 @@ +#pragma once + +#ifdef USE_TRACY_GPU + +#include "Log.hpp" + +#include +#include + +inline PFNGLQUERYCOUNTEREXTPROC glQueryCounter; +inline PFNGLGETQUERYOBJECTIVEXTPROC glGetQueryObjectiv; +inline PFNGLGETQUERYOBJECTUI64VEXTPROC glGetQueryObjectui64v; + +#include "../../subprojects/tracy/public/tracy/TracyOpenGL.hpp" + +inline void loadGLProc(void* pProc, const char* name) { + void* proc = (void*)eglGetProcAddress(name); + if (proc == NULL) { + Debug::log(CRIT, "[Tracy GPU Profiling] eglGetProcAddress(%s) failed", name); + abort(); + } + *(void**)pProc = proc; +} + +#define TRACY_GPU_CONTEXT TracyGpuContext +#define TRACY_GPU_ZONE(e) TracyGpuZone(e) +#define TRACY_GPU_COLLECT TracyGpuCollect + +#else + +#define TRACY_GPU_CONTEXT +#define TRACY_GPU_ZONE(e) +#define TRACY_GPU_COLLECT + +#endif \ No newline at end of file diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 8f25c686..1ecbc297 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -23,6 +23,16 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() { Debug::log(LOG, "Renderer: %s", glGetString(GL_RENDERER)); Debug::log(LOG, "Supported extensions size: %d", std::count(m_szExtensions.begin(), m_szExtensions.end(), ' ')); +#ifdef USE_TRACY_GPU + + loadGLProc(&glQueryCounter, "glQueryCounterEXT"); + loadGLProc(&glGetQueryObjectiv, "glGetQueryObjectivEXT"); + loadGLProc(&glGetQueryObjectui64v, "glGetQueryObjectui64vEXT"); + +#endif + + TRACY_GPU_CONTEXT; + #ifdef GLES2 Debug::log(WARN, "!RENDERER: Using the legacy GLES2 renderer!"); #endif @@ -96,6 +106,8 @@ GLuint CHyprOpenGLImpl::compileShader(const GLuint& type, std::string src, bool void CHyprOpenGLImpl::begin(CMonitor* pMonitor, CRegion* pDamage, bool fake) { m_RenderData.pMonitor = pMonitor; + TRACY_GPU_ZONE("RenderBegin"); + if (eglGetCurrentContext() != wlr_egl_get_context(g_pCompositor->m_sWLREGL)) { eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, wlr_egl_get_context(g_pCompositor->m_sWLREGL)); } @@ -148,6 +160,8 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, CRegion* pDamage, bool fake) { void CHyprOpenGLImpl::end() { static auto* const PZOOMRIGID = &g_pConfigManager->getConfigValuePtr("misc:cursor_zoom_rigid")->intValue; + TRACY_GPU_ZONE("RenderEnd"); + // end the render, copy the data to the WLR framebuffer if (!m_bFakeFrame) { m_RenderData.damage = m_RenderData.pMonitor->lastFrameDamage; @@ -379,6 +393,8 @@ void CHyprOpenGLImpl::applyScreenShader(const std::string& path) { void CHyprOpenGLImpl::clear(const CColor& color) { RASSERT(m_RenderData.pMonitor, "Tried to render without begin()!"); + TRACY_GPU_ZONE("RenderClear"); + glClearColor(color.r, color.g, color.b, color.a); if (!m_RenderData.damage.empty()) { @@ -449,6 +465,8 @@ void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, CReg RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!"); RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!"); + TRACY_GPU_ZONE("RenderRectWithDamage"); + wlr_box newBox = *box; scaleBox(&newBox, m_RenderData.renderModif.scale); newBox.x += m_RenderData.renderModif.translate.x; @@ -535,6 +553,8 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!"); + TRACY_GPU_ZONE("RenderTextureInternalWithDamage"); + alpha = std::clamp(alpha, 0.f, 1.f); if (m_RenderData.damage.empty()) @@ -939,6 +959,8 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox, static auto* const PBLURNEWOPTIMIZE = &g_pConfigManager->getConfigValuePtr("decoration:blur_new_optimizations")->intValue; static auto* const PBLURXRAY = &g_pConfigManager->getConfigValuePtr("decoration:blur_xray")->intValue; + TRACY_GPU_ZONE("RenderTextureWithBlur"); + // make a damage region for this window CRegion texDamage{m_RenderData.damage}; texDamage.intersect(pBox->x, pBox->y, pBox->width, pBox->height); @@ -1041,6 +1063,8 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CGradientValueData& grad, RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!"); RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!"); + TRACY_GPU_ZONE("RenderBorder"); + if (m_RenderData.damage.empty() || (m_pCurrentWindow && m_pCurrentWindow->m_sAdditionalConfigData.forceNoBorder)) return; @@ -1384,6 +1408,8 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl if (m_RenderData.damage.empty()) return; + TRACY_GPU_ZONE("RenderShadow"); + wlr_box newBox = *box; scaleBox(&newBox, m_RenderData.renderModif.scale); newBox.x += m_RenderData.renderModif.translate.x; @@ -1605,6 +1631,7 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) { void CHyprOpenGLImpl::clearWithTex() { RASSERT(m_RenderData.pMonitor, "Tried to render BGtex without begin()!"); + TRACY_GPU_ZONE("RenderClearWithTex"); auto TEXIT = m_mMonitorBGTextures.find(m_RenderData.pMonitor); diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index db8b37d1..8e834eeb 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -14,6 +14,8 @@ #include "Texture.hpp" #include "Framebuffer.hpp" +#include "../debug/TracyDefines.hpp" + class CHyprRenderer; inline const float fullVerts[] = { diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 6bf783af..4514a3d4 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -10,6 +10,8 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) { if (!TEXTURE) return; + TRACY_GPU_ZONE("RenderSurface"); + double outputX = 0, outputY = 0; wlr_output_layout_output_coords(g_pCompositor->m_sWLROutputLayout, RDATA->pMonitor->output, &outputX, &outputY); @@ -257,6 +259,8 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* return; } + TRACY_GPU_ZONE("RenderWindow"); + const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID); const auto REALPOS = pWindow->m_vRealPosition.vec() + (pWindow->m_bPinned ? Vector2D{} : PWORKSPACE->m_vRenderOffset.vec()); static auto* const PNOFLOATINGBORDERS = &g_pConfigManager->getConfigValuePtr("general:no_border_on_floating")->intValue; @@ -399,6 +403,8 @@ void CHyprRenderer::renderLayer(SLayerSurface* pLayer, CMonitor* pMonitor, times return; } + TRACY_GPU_ZONE("RenderLayer"); + SRenderData renderdata = {pMonitor, time, pLayer->geometry.x, pLayer->geometry.y}; renderdata.fadeAlpha = pLayer->alpha.fl(); renderdata.blur = pLayer->forceBlur; @@ -638,6 +644,8 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace* } void CHyprRenderer::renderLockscreen(CMonitor* pMonitor, timespec* now) { + TRACY_GPU_ZONE("RenderLockscreen"); + if (g_pSessionLockManager->isSessionLocked()) { const auto PSLS = g_pSessionLockManager->getSessionLockSurfaceForMonitor(pMonitor->ID); @@ -984,6 +992,8 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { // TODO: this is getting called with extents being 0,0,0,0 should it be? // potentially can save on resources. + TRACY_GPU_ZONE("Render"); + g_pHyprOpenGL->begin(pMonitor, &damage); EMIT_HOOK_EVENT("render", RENDER_BEGIN); @@ -1031,6 +1041,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { } if (wlr_renderer_begin(g_pCompositor->m_sWLRRenderer, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y)) { + TRACY_GPU_ZONE("RenderCursor"); if (pMonitor == g_pCompositor->getMonitorFromCursor() && *PZOOMFACTOR != 1.f) { wlr_output_lock_software_cursors(pMonitor->output, true); wlr_output_render_software_cursors(pMonitor->output, NULL); @@ -1056,6 +1067,8 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { g_pHyprOpenGL->end(); + TRACY_GPU_COLLECT; + // calc frame damage CRegion frameDamage{}; @@ -1111,6 +1124,8 @@ void CHyprRenderer::renderWorkspace(CMonitor* pMonitor, CWorkspace* pWorkspace, Vector2D translate = {geometry.x, geometry.y}; float scale = (float)geometry.width / pMonitor->vecPixelSize.x; + TRACY_GPU_ZONE("RenderWorkspace"); + if (!DELTALESSTHAN((double)geometry.width / (double)geometry.height, pMonitor->vecPixelSize.x / pMonitor->vecPixelSize.y, 0.01)) { Debug::log(ERR, "Ignoring geometry in renderWorkspace: aspect ratio mismatch"); scale = 1.f; diff --git a/subprojects/tracy b/subprojects/tracy new file mode 160000 index 00000000..897aec5b --- /dev/null +++ b/subprojects/tracy @@ -0,0 +1 @@ +Subproject commit 897aec5b062664d2485f4f9a213715d2e527e0ca