Base: Add build support and instrumentation for the Tracy profiler.

This commit is contained in:
Joao Matos
2025-03-05 23:22:55 +00:00
committed by tritao
parent 9c5164ab05
commit 0feab195ac
14 changed files with 239 additions and 12 deletions

View File

@@ -17,6 +17,8 @@ macro(InitializeFreeCADBuildOptions)
option(FREECAD_PARALLEL_LINK_JOBS "Linkage jobs pool size to fit memory limitations.")
option(BUILD_WITH_CONDA "Set ON if you build FreeCAD with conda" OFF)
option(BUILD_DYNAMIC_LINK_PYTHON "If OFF extension-modules do not link against python-libraries" ON)
option(BUILD_TRACY_FRAME_PROFILER "If ON then enables support for the Tracy frame profiler" OFF)
option(INSTALL_TO_SITEPACKAGES "If ON the freecad root namespace (python) is installed into python's site-packages" ON)
option(INSTALL_PREFER_SYMLINKS "If ON then fc_copy_sources macro will create symlinks instead of copying files" OFF)
option(OCCT_CMAKE_FALLBACK "disable usage of occt-config files" OFF)

View File

@@ -8,8 +8,17 @@ add_subdirectory(libE57Format)
if (BUILD_ASSEMBLY AND NOT FREECAD_USE_EXTERNAL_ONDSELSOLVER)
if( NOT EXISTS "${CMAKE_SOURCE_DIR}/src/3rdParty/OndselSolver/CMakeLists.txt" )
message( SEND_ERROR "The OndselSolver git submodule is not available. Please run
message(FATAL_ERROR "The OndselSolver git submodule is not available. Please run
git submodule update --init" )
endif()
add_subdirectory(OndselSolver)
endif()
if (BUILD_TRACY_FRAME_PROFILER)
if( NOT EXISTS "${CMAKE_SOURCE_DIR}/src/3rdParty/tracy/CMakeLists.txt" )
message(FATAL_ERROR "The Tracy git directory is not available. Please clone it manually." )
endif()
set(TRACY_STATIC OFF)
add_subdirectory(tracy)
endif()

View File

@@ -3,6 +3,10 @@ if(WIN32)
add_definitions(-DBOOST_DYN_LINK)
endif(WIN32)
if(BUILD_TRACY_FRAME_PROFILER)
add_definitions(-DBUILD_TRACY_FRAME_PROFILER)
endif()
if(FREECAD_RELEASE_SEH)
add_definitions(-DHAVE_SEH)
endif(FREECAD_RELEASE_SEH)
@@ -71,6 +75,10 @@ set(FreeCADApp_LIBS
fmt::fmt
)
if(BUILD_TRACY_FRAME_PROFILER)
list(APPEND FreeCADApp_LIBS TracyClient)
endif()
include_directories(
${QtCore_INCLUDE_DIRS}
${QtXml_INCLUDE_DIRS}

View File

@@ -94,6 +94,7 @@ recompute path. Also, it enables more complicated dependencies beyond trees.
#include <Base/TimeInfo.h>
#include <Base/Reader.h>
#include <Base/Writer.h>
#include <Base/Profiler.h>
#include <Base/Tools.h>
#include <Base/Uuid.h>
#include <Base/Sequencer.h>
@@ -2963,6 +2964,8 @@ int Document::recompute(const std::vector<App::DocumentObject*>& objs,
bool* hasError,
int options)
{
ZoneScoped;
if (d->undoing || d->rollback) {
if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) {
FC_WARN("Ignore document recompute on undo/redo");

View File

@@ -5,6 +5,10 @@ if(WIN32)
add_definitions(-DZIPIOS_UTF8)
endif(WIN32)
if(BUILD_TRACY_FRAME_PROFILER)
add_definitions(-DBUILD_TRACY_FRAME_PROFILER)
endif()
include_directories(
${CMAKE_BINARY_DIR}/src
${CMAKE_SOURCE_DIR}/src
@@ -65,6 +69,11 @@ endif(MSVC)
include_directories(
${QtCore_INCLUDE_DIRS}
)
if(BUILD_TRACY_FRAME_PROFILER)
list(APPEND FreeCADBase_LIBS TracyClient)
endif()
list(APPEND FreeCADBase_LIBS ${QtCore_LIBRARIES})
list(APPEND FreeCADBase_LIBS fmt::fmt)

134
src/Base/Profiler.h Normal file
View File

@@ -0,0 +1,134 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/****************************************************************************
* *
* Copyright (c) 2025 Joao Matos <joao@tritao.eu> *
* *
* This file is part of FreeCAD. *
* *
* FreeCAD is free software: you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 2.1 of the *
* License, or (at your option) any later version. *
* *
* FreeCAD is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with FreeCAD. If not, see *
* <https://www.gnu.org/licenses/>. *
* *
***************************************************************************/
#ifdef TRACY_ENABLE
#include <tracy/Tracy.hpp>
#else
#define TracyNoop
#define ZoneNamed(x, y)
#define ZoneNamedN(x, y, z)
#define ZoneNamedC(x, y, z)
#define ZoneNamedNC(x, y, z, w)
#define ZoneTransient(x, y)
#define ZoneTransientN(x, y, z)
#define ZoneScoped
#define ZoneScopedN(x)
#define ZoneScopedC(x)
#define ZoneScopedNC(x, y)
#define ZoneText(x, y)
#define ZoneTextV(x, y, z)
#define ZoneTextF(x, ...)
#define ZoneTextVF(x, y, ...)
#define ZoneName(x, y)
#define ZoneNameV(x, y, z)
#define ZoneNameF(x, ...)
#define ZoneNameVF(x, y, ...)
#define ZoneColor(x)
#define ZoneColorV(x, y)
#define ZoneValue(x)
#define ZoneValueV(x, y)
#define ZoneIsActive false
#define ZoneIsActiveV(x) false
#define FrameMark
#define FrameMarkNamed(x)
#define FrameMarkStart(x)
#define FrameMarkEnd(x)
#define FrameImage(x, y, z, w, a)
#define TracyLockable(type, varname) type varname
#define TracyLockableN(type, varname, desc) type varname
#define TracySharedLockable(type, varname) type varname
#define TracySharedLockableN(type, varname, desc) type varname
#define LockableBase(type) type
#define SharedLockableBase(type) type
#define LockMark(x) (void)x
#define LockableName(x, y, z)
#define TracyPlot(x, y)
#define TracyPlotConfig(x, y, z, w, a)
#define TracyMessage(x, y)
#define TracyMessageL(x)
#define TracyMessageC(x, y, z)
#define TracyMessageLC(x, y)
#define TracyAppInfo(x, y)
#define TracyAlloc(x, y)
#define TracyFree(x)
#define TracyMemoryDiscard(x)
#define TracySecureAlloc(x, y)
#define TracySecureFree(x)
#define TracySecureMemoryDiscard(x)
#define TracyAllocN(x, y, z)
#define TracyFreeN(x, y)
#define TracySecureAllocN(x, y, z)
#define TracySecureFreeN(x, y)
#define ZoneNamedS(x, y, z)
#define ZoneNamedNS(x, y, z, w)
#define ZoneNamedCS(x, y, z, w)
#define ZoneNamedNCS(x, y, z, w, a)
#define ZoneTransientS(x, y, z)
#define ZoneTransientNS(x, y, z, w)
#define ZoneScopedS(x)
#define ZoneScopedNS(x, y)
#define ZoneScopedCS(x, y)
#define ZoneScopedNCS(x, y, z)
#define TracyAllocS(x, y, z)
#define TracyFreeS(x, y)
#define TracyMemoryDiscardS(x, y)
#define TracySecureAllocS(x, y, z)
#define TracySecureFreeS(x, y)
#define TracySecureMemoryDiscardS(x, y)
#define TracyAllocNS(x, y, z, w)
#define TracyFreeNS(x, y, z)
#define TracySecureAllocNS(x, y, z, w)
#define TracySecureFreeNS(x, y, z)
#define TracyMessageS(x, y, z)
#define TracyMessageLS(x, y)
#define TracyMessageCS(x, y, z, w)
#define TracyMessageLCS(x, y, z)
#define TracySourceCallbackRegister(x, y)
#define TracyParameterRegister(x, y)
#define TracyParameterSetup(x, y, z, w)
#define TracyIsConnected false
#define TracyIsStarted false
#define TracySetProgramName(x)
#define TracyFiberEnter(x)
#define TracyFiberEnterHint(x, y)
#define TracyFiberLeave
#endif

View File

@@ -136,6 +136,9 @@
#include "WidgetFactory.h"
#include "3Dconnexion/navlib/NavlibInterface.h"
#ifdef BUILD_TRACY_FRAME_PROFILER
#include <tracy/Tracy.hpp>
#endif
using namespace Gui;
using namespace Gui::DockWnd;

View File

@@ -44,6 +44,10 @@ if (BUILD_ADDONMGR)
add_definitions(-DBUILD_ADDONMGR )
endif(BUILD_ADDONMGR)
if (BUILD_TRACY_FRAME_PROFILER)
add_definitions(-DBUILD_TRACY_FRAME_PROFILER)
endif()
include_directories(
${CMAKE_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}
@@ -99,6 +103,10 @@ else(MSVC)
)
endif(MSVC)
if(BUILD_TRACY_FRAME_PROFILER)
list(APPEND FreeCADGui_LIBS TracyClient)
endif()
if (TARGET Coin::Coin)
list(APPEND FreeCADGui_LIBS Coin::Coin)
else()

View File

@@ -93,6 +93,8 @@
#include <Inventor/scxml/ScXML.h>
#include <Inventor/scxml/SoScXMLStateMachine.h>
#include <Base/Profiler.h>
#include "QuarterWidget.h"
#include "InteractionMode.h"
#include "QuarterP.h"
@@ -839,6 +841,8 @@ void QuarterWidget::resizeEvent(QResizeEvent* event)
*/
void QuarterWidget::paintEvent(QPaintEvent* event)
{
ZoneScoped;
if (updateDevicePixelRatio()) {
qreal dev_pix_ratio = devicePixelRatio();
int width = static_cast<int>(dev_pix_ratio * this->width());
@@ -990,6 +994,7 @@ QuarterWidget::redraw()
void
QuarterWidget::actualRedraw()
{
ZoneScoped;
PRIVATE(this)->sorendermanager->render(PRIVATE(this)->clearwindow,
PRIVATE(this)->clearzbuffer);
}

View File

@@ -47,6 +47,10 @@
#include "SoQTQuarterAdaptor.h"
#ifdef BUILD_TRACY_FRAME_PROFILER
#include <tracy/Tracy.hpp>
#endif
// NOLINTBEGIN
// clang-format off
static unsigned char fps2dfont[][12] = {
@@ -766,6 +770,10 @@ void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::paintEvent(QPaintEvent* event)
double start = SbTime::getTimeOfDay().getValue();
QuarterWidget::paintEvent(event);
this->framesPerSecond = addFrametime(start);
#ifdef BUILD_TRACY_FRAME_PROFILER
FrameMark;
#endif
}
void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::resetFrameCounter()

View File

@@ -45,6 +45,8 @@
# include <Inventor/actions/SoHandleEventAction.h>
# include <Inventor/actions/SoRayPickAction.h>
# include <Inventor/annex/HardCopy/SoVectorizePSAction.h>
# include <Inventor/annex/Profiler/SoProfiler.h>
# include <Inventor/annex/Profiler/elements/SoProfilerElement.h>
# include <Inventor/details/SoDetail.h>
# include <Inventor/elements/SoLightModelElement.h>
# include <Inventor/elements/SoOverrideElement.h>
@@ -94,6 +96,7 @@
#include <Base/Console.h>
#include <Base/FileInfo.h>
#include <Base/Sequencer.h>
#include <Base/Profiler.h>
#include <Base/Tools.h>
#include <Base/UnitsApi.h>
#include <Base/Tools2D.h>
@@ -430,6 +433,11 @@ void View3DInventorViewer::init()
// setting up the defaults for the spin rotation
initialize();
#ifdef TRACY_ENABLE
SoProfiler::init();
SoProfiler::enable(TRUE);
#endif
// NOLINTBEGIN
auto cam = new SoOrthographicCamera;
cam->position = SbVec3f(0, 0, 1);
@@ -571,9 +579,14 @@ void View3DInventorViewer::init()
// the fix and some details what happens behind the scene have a look at this
// https://forum.freecad.org/viewtopic.php?f=10&t=7486&p=74777#p74736
uint32_t id = this->getSoRenderManager()->getGLRenderAction()->getCacheContext();
this->getSoRenderManager()->setGLRenderAction(new SoBoxSelectionRenderAction);
auto boxSelectionAction = new SoBoxSelectionRenderAction;
this->getSoRenderManager()->setGLRenderAction(boxSelectionAction);
this->getSoRenderManager()->getGLRenderAction()->setCacheContext(id);
#ifdef TRACY_ENABLE
boxSelectionAction->enableElement(SoProfilerElement::getClassTypeId(), SoProfilerElement::getClassStackIndex());
#endif
// set the transparency and antialiasing settings
getSoRenderManager()->getGLRenderAction()->setTransparencyType(SoGLRenderAction::SORTED_OBJECT_SORTED_TRIANGLE_BLEND);
@@ -2415,6 +2428,8 @@ void View3DInventorViewer::renderGLImage()
// upon spin.
void View3DInventorViewer::renderScene()
{
ZoneScoped;
// Must set up the OpenGL viewport manually, as upon resize
// operations, Coin won't set it up until the SoGLRenderAction is
// applied again. And since we need to do glClear() before applying
@@ -2434,15 +2449,19 @@ void View3DInventorViewer::renderScene()
glDepthRange(0.1,1.0);
#endif
// Render our scenegraph with the image.
SoGLRenderAction* glra = this->getSoRenderManager()->getGLRenderAction();
SoState* state = glra->getState();
SoDevicePixelRatioElement::set(state, devicePixelRatio());
SoGLWidgetElement::set(state, qobject_cast<QOpenGLWidget*>(this->getGLWidget()));
SoGLRenderActionElement::set(state, glra);
SoGLVBOActivatedElement::set(state, this->vboEnabled);
drawSingleBackground(col);
glra->apply(this->backgroundroot);
// Render our scenegraph with the image.
{
ZoneScopedN("Background");
SoDevicePixelRatioElement::set(state, devicePixelRatio());
SoGLWidgetElement::set(state, qobject_cast<QOpenGLWidget*>(this->getGLWidget()));
SoGLRenderActionElement::set(state, glra);
SoGLVBOActivatedElement::set(state, this->vboEnabled);
drawSingleBackground(col);
glra->apply(this->backgroundroot);
}
if (!this->shading) {
state->push();
@@ -2480,7 +2499,10 @@ void View3DInventorViewer::renderScene()
#endif
// Render overlay front scenegraph.
glra->apply(this->foregroundroot);
{
ZoneScopedN("Foreground");
glra->apply(this->foregroundroot);
}
if (this->axiscrossEnabled) {
this->drawAxisCross();
@@ -2498,8 +2520,11 @@ void View3DInventorViewer::renderScene()
printDimension();
for (auto it : this->graphicsItems) {
it->paintGL();
{
ZoneScopedN("Graphics items");
for (auto it : this->graphicsItems) {
it->paintGL();
}
}
//fps rendering
@@ -2661,6 +2686,8 @@ void View3DInventorViewer::selectAll()
bool View3DInventorViewer::processSoEvent(const SoEvent* ev)
{
ZoneScoped;
if (naviCubeEnabled && naviCube->processSoEvent(ev)) {
return true;
}

View File

@@ -1,3 +1,6 @@
if(BUILD_TRACY_FRAME_PROFILER)
add_definitions(-DBUILD_TRACY_FRAME_PROFILER)
endif()
add_subdirectory(App)
if(BUILD_GUI)

View File

@@ -24,6 +24,10 @@ set(PartGui_LIBS
MatGui
)
if(BUILD_TRACY_FRAME_PROFILER)
list(APPEND PartGui_LIBS TracyClient)
endif()
if(MSVC)
include_directories(
${CMAKE_SOURCE_DIR}/src/3rdParty/OpenGL/api

View File

@@ -68,6 +68,8 @@
# include <Inventor/C/glue/gl.h>
#endif
#include <Base/Profiler.h>
#include <Gui/SoFCInteractiveElement.h>
#include <Gui/Selection/SoFCSelectionAction.h>
#include <Gui/Selection/SoFCUnifiedSelection.h>
@@ -493,6 +495,8 @@ void SoBrepFaceSet::renderColoredArray(SoMaterialBundle *const materials)
void SoBrepFaceSet::GLRender(SoGLRenderAction *action)
{
ZoneScoped;
//SoBase::staticDataLock();
static bool init = false;
if (!init) {