Compare commits

...

21 Commits

Author SHA1 Message Date
Marcos Slomp
debda1df55 scoping the GpuCtx constructor 2026-06-10 18:57:22 -07:00
Marcos Slomp
d98608b022 issue a Tracy warning message when timestamp queries are supported but not properly implemented 2026-06-10 18:52:57 -07:00
Marcos Slomp
eb88c6eba0 adding warning about TracyOpenGL usage on Apple devices 2026-06-10 18:52:09 -07:00
Marcos Slomp
e83429c926 replacing the various platform layers by RGFW 2026-06-10 18:38:48 -07:00
Marcos Slomp
1b207d3e2a adding OpenGL example (spinning triangle) 2026-06-10 14:14:54 -07:00
Bartosz Taudul
9ab39d8af3 Merge pull request #1398 from Lectem/fix/concurrentqueue-and-malloc-define
WORKAROUND_malloc/free should properly route to tracy_malloc/free
2026-06-10 17:57:32 +02:00
Clément Grégoire
bfab6d03f4 WORKAROUND_malloc/free should properly route to tracy_malloc/free 2026-06-10 17:15:33 +02:00
Bartosz Taudul
66e4f5cef7 Merge pull request #1397 from MaximeCoutantSonos/master
Fixed typo inconsistency in Shared lock C api
2026-06-10 14:47:56 +02:00
MaximeCoutantSonos
7637971e9e Fixed typo inconsistency in Shared lock C api 2026-06-10 14:26:36 +02:00
Bartosz Taudul
4e3cffc4ba Add name bank related to games. 2026-06-10 01:34:40 +02:00
Bartosz Taudul
3956616fc2 Fix repeated entries. 2026-06-10 01:14:22 +02:00
Bartosz Taudul
d34c45fa5a Use variable structure for random name generator. 2026-06-10 00:27:18 +02:00
Bartosz Taudul
8fe5a511c9 Expand name generator banks. 2026-06-10 00:15:55 +02:00
Bartosz Taudul
afdd2e2f81 Regenerate markdown manual. 2026-06-09 23:49:57 +02:00
Bartosz Taudul
3c1b1b2f80 Update manual. 2026-06-09 23:48:14 +02:00
Bartosz Taudul
992134f85e Fix regression with no tooltips on disabled items. 2026-06-09 23:31:59 +02:00
Bartosz Taudul
37bc986584 Add button for re-rolling annotation name. 2026-06-09 23:27:07 +02:00
Bartosz Taudul
feb4e7c989 Generate random names for new annotations. 2026-06-09 23:24:58 +02:00
Bartosz Taudul
4a8fe6f56e Add button to generate random trace description. 2026-06-09 23:22:21 +02:00
Bartosz Taudul
a960a25285 Add random name generator. 2026-06-09 23:22:21 +02:00
Marcos Slomp
9588912aa9 Speeding-up GitHub build-bots (#1392)
* disabling LTO when building the profiler on macos via the github workflow

* diagnosing where in the linking stage it's getting stuck

* fowrward declarations

* compilation time report

* trying clang build analyzer...

* reducing number of parallel workers

* limiting parallel workers on windows/linux as well

* re-enabling LTO on macos

* reverting forward declaration header include (emscripten is failing with them).

* reverting act changes

* removing comments
2026-06-09 11:21:09 +02:00
19 changed files with 695 additions and 24 deletions

View File

@@ -32,7 +32,7 @@ jobs:
if [ "${ACT:-}" != "true" ] && [ "${FORGEJO_ACTIONS:-}" != "true" ]; then
cmake --build profiler/build
else
cmake --build profiler/build --parallel
cmake --build profiler/build --parallel 2
fi
- name: Update utility
run: |

View File

@@ -28,7 +28,7 @@ jobs:
- name: Build profiler
run: |
cmake -B profiler/build -S profiler -DCMAKE_BUILD_TYPE=Release -DGIT_REV=${{ github.sha }}
cmake --build profiler/build --parallel --config Release
cmake --build profiler/build --parallel 2 --config Release
- name: Build update
run: |
cmake -B update/build -S update -DCMAKE_BUILD_TYPE=Release -DGIT_REV=${{ github.sha }}

View File

@@ -32,7 +32,7 @@ jobs:
- name: Build profiler
run: |
cmake -B profiler/build -S profiler -DCMAKE_BUILD_TYPE=Release -DGIT_REV=${{ github.sha }}
cmake --build profiler/build --parallel --config Release
cmake --build profiler/build --parallel 2 --config Release
- name: Build update
run: |
cmake -B update/build -S update -DCMAKE_BUILD_TYPE=Release -DGIT_REV=${{ github.sha }}

View File

@@ -0,0 +1,84 @@
# CMakeLists.txt — OpenGL spinning triangle demo
#
# macOS:
# cmake -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo -B build/ninja .
# cmake --build build/ninja
#
# Linux (requires libx11-dev libgl1-mesa-dev libglew-dev):
# cmake -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo -B build/ninja .
# cmake --build build/ninja
#
# Windows (MSVC, requires GLEW):
# cmake -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DGLEW_ROOT=<path> -B build/ninja .
# cmake --build build/ninja
cmake_minimum_required(VERSION 3.16)
project(gl_spinning_triangle LANGUAGES C CXX)
# ---------------------------------------------------------------------------
# Tracy root — defaults to three directories above this CMakeLists.txt.
# ---------------------------------------------------------------------------
set(TRACY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../..")
option(TRACY_ENABLE "Enable Tracy profiling" ON)
option(TRACY_OPENGL_AUTO_CALIBRATION "Enable periodic GPU/CPU recalibration" ON)
# ---------------------------------------------------------------------------
# Platform — RGFW (cross-platform windowing, fetched automatically)
# ---------------------------------------------------------------------------
include(FetchContent)
FetchContent_Declare(rgfw
GIT_REPOSITORY https://github.com/ColleagueRiley/RGFW.git
GIT_TAG main # pin to a specific commit for reproducible builds
GIT_SHALLOW TRUE
)
FetchContent_MakeAvailable(rgfw)
set(PLATFORM_SOURCES platform/platform_rgfw.cpp)
set(PLATFORM_INCLUDES ${rgfw_SOURCE_DIR})
if(APPLE)
set(PLATFORM_LIBS "-framework Cocoa" "-framework OpenGL"
"-framework CoreVideo" "-framework IOKit")
elseif(WIN32)
find_package(GLEW REQUIRED)
set(PLATFORM_LIBS opengl32 user32 gdi32 GLEW::GLEW)
else()
find_package(GLEW REQUIRED)
find_package(X11 REQUIRED)
set(PLATFORM_LIBS X11::X11 GL GLEW::GLEW)
endif()
# ---------------------------------------------------------------------------
# Target
# ---------------------------------------------------------------------------
add_executable(gl_spinning_triangle
spinning_triangle.cpp
"${TRACY_DIR}/public/TracyClient.cpp"
${PLATFORM_SOURCES}
)
# Suppress upstream warnings from TracyClient.cpp
if(MSVC)
set_source_files_properties("${TRACY_DIR}/public/TracyClient.cpp"
PROPERTIES COMPILE_FLAGS "/w"
)
else()
set_source_files_properties("${TRACY_DIR}/public/TracyClient.cpp"
PROPERTIES COMPILE_FLAGS "-w"
)
endif()
target_compile_features(gl_spinning_triangle PRIVATE cxx_std_17)
if(TRACY_ENABLE)
target_compile_definitions(gl_spinning_triangle PRIVATE TRACY_ENABLE)
endif()
if(TRACY_OPENGL_AUTO_CALIBRATION)
target_compile_definitions(gl_spinning_triangle PRIVATE TRACY_OPENGL_AUTO_CALIBRATION)
endif()
target_include_directories(gl_spinning_triangle PRIVATE
"${TRACY_DIR}/public"
${PLATFORM_INCLUDES}
)
target_link_libraries(gl_spinning_triangle PRIVATE ${PLATFORM_LIBS})

View File

@@ -0,0 +1,41 @@
// platform.h — interface between platform-agnostic code and platform backends
//
// Each platform_*.mm / platform_*.cpp file implements these four functions.
// Exactly one backend must be linked into the final binary.
#pragma once
#ifdef __APPLE__
// OpenGL is only available on MacOS (no iOS support)
// Anything from gl3.h will spew deprecation warnings when used,
// unless GL_SILENCE_DEPRECATION has been defined beforehand
//# define GL_SILENCE_DEPRECATION
# include <OpenGL/gl3.h>
#else
# include <GL/glew.h>
#endif
// Initialize the windowing system, create a window, and make an OpenGL 3.3
// Core Profile context current on the calling thread.
// Returns true on success.
bool platformInit(int width, int height, const char* title);
// Load OpenGL function pointers (no-op on macOS where the framework exports them directly).
// Must be called after platformInit() while the GL context is current.
// Returns true on success.
bool platformInitGL();
// Elapsed wall-clock time in seconds since platformInit().
double platformGetTime();
// Swap front and back buffers (present the rendered frame).
void platformSwapBuffers();
// Pixel scaling factor relative to the logical window size (1.0 on non-HiDPI displays).
// Must be called after platformInit().
void platformGetPixelDensityScale(float* x, float* y);
// Enter the platform event/render loop.
// Calls render() each frame at ~60 fps.
// Calls shutdown() exactly once before returning.
void platformRunLoop(void (*render)(), void (*shutdown)());

View File

@@ -0,0 +1,73 @@
// platform_rgfw.cpp — RGFW windowing backend (cross-platform)
// https://github.com/ColleagueRiley/RGFW
#include "platform.h" // GL headers first (gl3.h / glew.h) so RGFW sees guards set
#define RGFW_OPENGL
#define RGFW_IMPLEMENTATION
#include <RGFW.h>
#include <chrono>
#include <cstdio>
static RGFW_window* sWin = nullptr;
static std::chrono::steady_clock::time_point sStartTime;
bool platformInit(int width, int height, const char* title) {
RGFW_glHints* hints = RGFW_getGlobalHints_OpenGL();
hints->major = 3;
hints->minor = 3;
RGFW_setGlobalHints_OpenGL(hints);
sWin = RGFW_createWindow(title, 0, 0, width, height,
RGFW_windowCenter | RGFW_windowOpenGL);
if (!sWin) {
fprintf(stderr, "RGFW: failed to create window\n");
return false;
}
RGFW_window_makeCurrentContext_OpenGL(sWin);
RGFW_window_swapInterval_OpenGL(sWin, 1);
RGFW_window_setExitKey(sWin, RGFW_keyEscape);
sStartTime = std::chrono::steady_clock::now();
return true;
}
bool platformInitGL() {
#ifndef __APPLE__
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
return false;
}
#endif
return true;
}
double platformGetTime() {
return std::chrono::duration<double>(
std::chrono::steady_clock::now() - sStartTime).count();
}
void platformSwapBuffers() { RGFW_window_swapBuffers_OpenGL(sWin); }
void platformGetPixelDensityScale(float* x, float* y) {
i32 pw, ph;
RGFW_window_getSizeInPixels(sWin, &pw, &ph);
*x = (float)pw / (float)sWin->w;
*y = (float)ph / (float)sWin->h;
}
void platformRunLoop(void (*render)(), void (*shutdown)()) {
while (RGFW_window_shouldClose(sWin) == RGFW_FALSE) {
RGFW_event event;
while (RGFW_window_checkEvent(sWin, &event)) {
if (event.type == RGFW_windowClose) goto done;
}
render();
}
done:
shutdown();
RGFW_window_close(sWin);
sWin = nullptr;
}

View File

@@ -0,0 +1,136 @@
// spinning_triangle.cpp — OpenGL spinning triangle demo with Tracy GPU profiling.
//
// Tracy GPU zones are active on non-Apple platforms when TRACY_ENABLE is defined.
// TRACY_OPENGL_AUTO_CALIBRATION (enabled by default in CMakeLists.txt) enables
// periodic GPU/CPU drift correction via glGetInteger64v(GL_TIMESTAMP).
#include "platform/platform.h"
#include <cmath>
#include <cstdio>
#include <tracy/Tracy.hpp>
#include <tracy/TracyOpenGL.hpp>
static const int kWidth = 800;
static const int kHeight = 600;
static GLuint gProgram = 0;
static GLuint gVao = 0;
static GLint gAngleLoc = -1;
// Vertex colors and positions are baked in; rotation is driven by a uniform.
static const char* kVertSrc = R"(
#version 150 core
uniform float uAngle;
const vec2 kPos[3] = vec2[3](
vec2( 0.0, 0.5 ),
vec2(-0.433, -0.25 ),
vec2( 0.433, -0.25 )
);
const vec3 kCol[3] = vec3[3](
vec3(1.0, 0.0, 0.0),
vec3(0.0, 1.0, 0.0),
vec3(0.0, 0.0, 1.0)
);
out vec3 vColor;
void main() {
float c = cos(uAngle);
float s = sin(uAngle);
vec2 p = kPos[gl_VertexID];
gl_Position = vec4(p.x*c - p.y*s, p.x*s + p.y*c, 0.0, 1.0);
vColor = kCol[gl_VertexID];
}
)";
static const char* kFragSrc = R"(
#version 150 core
in vec3 vColor;
out vec4 fragColor;
void main() { fragColor = vec4(vColor, 1.0); }
)";
static GLuint compileShader(GLenum type, const char* src) {
GLuint s = glCreateShader(type);
glShaderSource(s, 1, &src, nullptr);
glCompileShader(s);
GLint ok = 0;
glGetShaderiv(s, GL_COMPILE_STATUS, &ok);
if (!ok) {
char log[512];
glGetShaderInfoLog(s, sizeof(log), nullptr, log);
fprintf(stderr, "Shader compile error: %s\n", log);
glDeleteShader(s);
return 0;
}
return s;
}
static int initGL() {
if (!platformInitGL()) return 1;
TracyGpuContext;
TracyGpuContextName("OpenGL", 6);
GLuint vert = compileShader(GL_VERTEX_SHADER, kVertSrc);
GLuint frag = compileShader(GL_FRAGMENT_SHADER, kFragSrc);
if (!vert || !frag) return 1;
gProgram = glCreateProgram();
glAttachShader(gProgram, vert);
glAttachShader(gProgram, frag);
glLinkProgram(gProgram);
glDeleteShader(vert);
glDeleteShader(frag);
GLint ok = 0;
glGetProgramiv(gProgram, GL_LINK_STATUS, &ok);
if (!ok) {
char log[512];
glGetProgramInfoLog(gProgram, sizeof(log), nullptr, log);
fprintf(stderr, "Program link error: %s\n", log);
return 1;
}
gAngleLoc = glGetUniformLocation(gProgram, "uAngle");
// Core profile requires a bound VAO even with no vertex attributes.
glGenVertexArrays(1, &gVao);
glBindVertexArray(gVao);
glClearColor(0.05f, 0.05f, 0.08f, 1.0f);
float scaleX, scaleY;
platformGetPixelDensityScale(&scaleX, &scaleY);
glViewport(0, 0, (int)(kWidth * scaleX), (int)(kHeight * scaleY));
return 0;
}
static void renderFrame() {
ZoneScoped;
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(gProgram);
{
TracyGpuZone("triangle draw");
glUniform1f(gAngleLoc, (float)platformGetTime());
glDrawArrays(GL_TRIANGLES, 0, 3);
}
platformSwapBuffers();
TracyGpuCollect;
}
static void shutdown() {
fprintf(stderr, "application is shutting down...\n");
glDeleteVertexArrays(1, &gVao);
glDeleteProgram(gProgram);
}
int main() {
if (!platformInit(kWidth, kHeight, "OpenGL Spinning Triangle"))
return 1;
if (initGL() != 0)
return 2;
platformRunLoop(renderFrame, shutdown);
return 0;
}

View File

@@ -11,7 +11,7 @@ The user manual
**Bartosz Taudul** [\<wolf@nereid.pl\>](mailto:wolf@nereid.pl)
2026-06-06 <https://github.com/wolfpld/tracy>
2026-06-09 <https://github.com/wolfpld/tracy>
# Quick overview {#quick-overview .unnumbered}
@@ -1495,6 +1495,12 @@ You also need to periodically collect the GPU events using the `TracyGpuCollect`
[^49]: Because Apple is unable to implement standards properly.
##### Calibrated context
By default, the OpenGL context is uncalibrated: the CPU and GPU clocks are aligned only once, when the context is created, so over long captures the two time domains may drift apart (section [5.4](#options) describes correcting this drift manually). Defining `TRACY_OPENGL_AUTO_CALIBRATION` before including `TracyOpenGL.hpp` enables periodic recalibration instead: roughly once per second Tracy samples the GPU and CPU clocks together and emits a calibration event, allowing the profiler to track and remove the drift automatically.
This is opt-in because OpenGL exposes no atomic CPU+GPU timestamp query (unlike Vulkan's `VK_EXT_calibrated_timestamps` or Direct3D 12, whose contexts are always calibrated). Recalibration therefore reads the GPU clock with `glGetInteger64v(GL_TIMESTAMP)`, which forces a CPU/GPU synchronization (a pipeline stall) each time it runs. Enable it only when the improved long-capture alignment is worth the periodic stall.
### Vulkan
Similarly, for Vulkan support you should include the `public/tracy/TracyVulkan.hpp` header file. Tracing Vulkan devices and queues is a bit more involved, and the Vulkan initialization macro `TracyVkContext(physdev, device, queue, cmdbuf)` returns an instance of `TracyVkCtx` object, which tracks an associated Vulkan queue. Cleanup is performed using the `TracyVkDestroy(ctx)` macro. You may create multiple Vulkan contexts. To set a custom name for the context, use the `TracyVkContextName(ctx, name, size)` macro.
@@ -1794,6 +1800,10 @@ By default, tracy client resolves callstack symbols in a background thread at ru
The generated tracy capture will have callstack frames symbols showing `[unresolved]`. The `update` tool can be used to load that capture, perform symbol resolution offline (by passing `-r`) and writing out a new capture with symbols resolved. By default `update` will use the original shared libraries paths that were recorded in the capture (which assumes running in the same machine or a machine with identical filesystem setup as the one used to run the tracy instrumented application). You can do path substitution with the `-p` option to perform any number of path substitions in order to use symbols located elsewhere.
By default symbol resolution is performed with the platform's native facility: the DbgHelp library on Windows, and the `addr2line` tool found in `PATH` elsewhere. You can override this with the `-a` option, passing the path to a custom `addr2line`-compatible tool (for instance an `addr2line` from a cross-compilation toolchain, or `llvm-addr2line`). The `-a` option works on all platforms, including Windows, and takes precedence over the platform default.
Extra arguments can be passed verbatim to the resolution tool with the `-A` option. Tracy records callstack frame offsets relative to the image base, but `addr2line`-compatible tools expect a full virtual address for images that have a non-zero preferred image base (such as PE on Windows or Mach-O on Apple). For these, pass `-A "--relative-address"` so that `llvm-addr2line` or `llvm-symbolizer` adds the image base back. ELF images need no such adjustment.
> [!IMPORTANT]
> **Important**
>
@@ -1988,6 +1998,39 @@ After you release the lock use the `TracyCLockAfterUnlock` macro:
You can optionally mark the location of where the lock is held by using the `TracyCLockMark` macro, this should be done after acquiring the lock.
Similarly, you can use the following macros to mark a shared lock using the C API:
- `TracyCSharedLockAnnounce(lock_ctx)`
- `TracyCSharedLockTerminate(lock_ctx)`
- `TracyCSharedLockBeforeLock(lock_ctx)`
- `TracyCSharedLockAfterLock(lock_ctx)`
- `TracyCSharedLockAfterUnlock(lock_ctx)`
- `TracyCSharedLockAfterTryLock(lock_ctx, acquired)`
- `TracyCSharedLockBeforeSharedLock(lock_ctx)`
- `TracyCSharedLockAfterSharedLock(lock_ctx)`
- `TracyCSharedLockAfterSharedUnlock(lock_ctx)`
- `TracyCSharedLockAfterTrySharedLock(lock_ctx, acquired)`
- `TracyCSharedLockMark(lock_ctx)`
- `TracyCSharedLockCustomName(lock_ctx, name, size)`
A shared lock context has to be defined next to the shared lock that it will be marking:
TracyCSharedLockCtx tracy_shared_lock_ctx;
HANDLE shared_lock;
The same rules apply to shared locks as to regular locks, but you need to use the shared lock macros instead. Lock implementations in classes `Lockable` and `SharedLockable` show how to properly perform context handling.
### Memory profiling {#cmemoryprofiling}
Use the following macros in your implementations of `malloc` and `free`:
@@ -3582,7 +3625,7 @@ You can freely adjust each time range on the timeline by clicking the left mouse
Tracy allows adding custom notes to the trace. For example, you may want to mark a region to ignore because the application was out-of-focus or a region where a new user was connecting to the game, which resulted in a frame drop that needs to be investigated.
Methods of specifying the annotation region are described in section [5.3](#timeranges). When a new annotation is added, a settings window is displayed (section [5.21](#annotationsettings)), allowing you to enter a description.
Methods of specifying the annotation region are described in section [5.3](#timeranges). When a new annotation is added, it is assigned a semi-unique random name to make it distinguishable. The settings window is also opened (section [5.21](#annotationsettings)), allowing you to enter your own description of the annotation.
Annotations are displayed on the timeline, as presented in figure [21](#annotation). Clicking on the circle next to the text description will open the annotation settings window, in which you can modify or remove the region. List of all annotations in the trace is available in the annotations list window described in section [5.22](#annotationlist), which is accessible through the * Tools* button on the control menu.
@@ -4125,7 +4168,9 @@ The information about the selected memory allocation is displayed in this window
## Trace information window {#traceinfo}
This window contains information about the current trace: captured program name, time of the capture, profiler version which performed the capture, and a custom trace description, which you can fill in.
This window contains information about the current trace: captured program name, time of the capture, profiler version which performed the capture.
There's an text entry field for an optional custom description of the trace for you to fill in. This description will appear on the profiler window title bar, or when comparing two traces (section [5.8](#compare)), enabling you to quickly recognize what the trace contains. For some people it's fine to just have *any* semi-unique description to be able to identify a specific trace. For such purposes there's an * Generate name* button, which will set the trace description to an abstract meaningless identifier.
If the * Public sidecar* option is selected, the file containing trace-specific user settings (see section [9.2](#tracespecific)) will be saved on disk next to the trace file.
@@ -4159,6 +4204,7 @@ If an application should crash during profiling (section [2.5](#crashhandling))
-----
 - Dice icon
 - User Gear icon
## Zone information window {#zoneinfo}
@@ -4562,7 +4608,12 @@ The profiled program is highlighted using green color. Furthermore, the yellow h
## Annotation settings window {#annotationsettings}
In this window, you may modify how a timeline annotation (section [5.3.1](#annotatingtrace)) is presented by setting its text description or selecting region highlight color. If the note is no longer needed, you may also remove it here.
In this window, you may modify how a timeline annotation (section [5.3.1](#annotatingtrace)) is presented by setting its text description or selecting region highlight color. A random annotation description can be set with the * Generate name* button. If the note is no longer needed, you may also remove it here.
-----
 - Dice icon
## Annotation list window {#annotationlist}

View File

@@ -4071,7 +4071,7 @@ You can freely adjust each time range on the timeline by clicking the \LMB{}~lef
Tracy allows adding custom notes to the trace. For example, you may want to mark a region to ignore because the application was out-of-focus or a region where a new user was connecting to the game, which resulted in a frame drop that needs to be investigated.
Methods of specifying the annotation region are described in section~\ref{timeranges}. When a new annotation is added, a settings window is displayed (section~\ref{annotationsettings}), allowing you to enter a description.
Methods of specifying the annotation region are described in section~\ref{timeranges}. When a new annotation is added, it is assigned a semi-unique random name to make it distinguishable. The settings window is also opened (section~\ref{annotationsettings}), allowing you to enter your own description of the annotation.
Annotations are displayed on the timeline, as presented in figure~\ref{annotation}. Clicking on the circle next to the text description will open the annotation settings window, in which you can modify or remove the region. List of all annotations in the trace is available in the annotations list window described in section~\ref{annotationlist}, which is accessible through the \emph{\faScrewdriverWrench{} Tools} button on the control menu.
@@ -4582,7 +4582,9 @@ The information about the selected memory allocation is displayed in this window
\subsection{Trace information window}
\label{traceinfo}
This window contains information about the current trace: captured program name, time of the capture, profiler version which performed the capture, and a custom trace description, which you can fill in.
This window contains information about the current trace: captured program name, time of the capture, profiler version which performed the capture.
There's an text entry field for an optional custom description of the trace for you to fill in. This description will appear on the profiler window title bar, or when comparing two traces (section~\ref{compare}), enabling you to quickly recognize what the trace contains. For some people it's fine to just have \emph{any} semi-unique description to be able to identify a specific trace. For such purposes there's an \emph{\faDice{}~Generate name} button, which will set the trace description to an abstract meaningless identifier.
If the \emph{\faUserGear{}~Public sidecar} option is selected, the file containing trace-specific user settings (see section~\ref{tracespecific}) will be saved on disk next to the trace file.
@@ -4922,7 +4924,7 @@ The profiled program is highlighted using green color. Furthermore, the yellow h
\subsection{Annotation settings window}
\label{annotationsettings}
In this window, you may modify how a timeline annotation (section~\ref{annotatingtrace}) is presented by setting its text description or selecting region highlight color. If the note is no longer needed, you may also remove it here.
In this window, you may modify how a timeline annotation (section~\ref{annotatingtrace}) is presented by setting its text description or selecting region highlight color. A random annotation description can be set with the \emph{\faDice{}~Generate name} button. If the note is no longer needed, you may also remove it here.
\subsection{Annotation list window}
\label{annotationlist}

View File

@@ -70,6 +70,7 @@ set(SERVER_FILES
TracyMarkdown.cpp
TracyMicroArchitecture.cpp
TracyMouse.cpp
TracyNameGen.cpp
TracyProtoHistory.cpp
TracySourceContents.cpp
TracySourceTokenizer.cpp

View File

@@ -290,7 +290,7 @@ static constexpr const uint32_t AsmSyntaxColors[] = {
[[maybe_unused]] static tracy_force_inline void TooltipIfHovered( const char* text )
{
if( !ImGui::IsItemHovered() ) return;
if( !ImGui::IsItemHovered( ImGuiHoveredFlags_AllowWhenDisabled ) ) return;
ImGui::BeginTooltip();
ImGui::TextUnformatted( text );
ImGui::EndTooltip();

View File

@@ -0,0 +1,221 @@
#include <algorithm>
#include <array>
#include <assert.h>
#include <stdint.h>
#include <random>
#include <vector>
#include "TracyNameGen.hpp"
namespace tracy
{
struct NameBank
{
const char* const* adjectives;
const char* const* nouns;
size_t numAdjectives;
size_t numNouns;
};
constexpr const char* AnalysisAdjectives[] = {
"Granular", "Forensic", "Acute", "Lucid", "Precise",
"Deep", "Exact", "Critical", "Analytical", "Transparent",
"Subtle", "Sharp", "Rigid", "Focused", "Absolute",
"Meticulous", "Spectral", "Diagnostic", "Pervasive", "Introspective",
"Systematic", "Optical", "Minute", "Piercing", "Detailed",
"Scrutinized", "Clear", "Keen", "Rigorous", "Vast",
"Incisive", "Exhaustive", "Lateral", "Prismatic", "Observant"
};
constexpr const char* AnalysisNouns[] = {
"Probe", "Trace", "Lens", "Scope", "Metric",
"Insight", "Scan", "Audit", "Point", "Vector",
"Signal", "Marker", "Frame", "Detail", "View",
"Spectrum", "Snapshot", "Blueprint", "Aperture", "Index",
"Radar", "Prism", "Gauge", "Focal", "Pattern",
"Echo", "Signature", "Horizon", "Mirror", "Scale",
"Telemetry", "Graph", "Stratum", "Artifact", "Aspect"
};
constexpr const char* PerformanceAdjectives[] = {
"Swift", "Lean", "Kinetic", "Agile", "Hyper",
"Rapid", "Fluid", "Peak", "Instant", "Nimble",
"Optimal", "Sonic", "Linear", "Warp", "Turbo",
"Frictionless", "Seamless", "Electric", "Blazing", "Aerodynamic",
"Quantum", "Prompt", "Direct", "Streamlined", "Volatile",
"Highgain", "Rapidfire", "Torrential", "Sleek", "Velocity",
"Dynamic", "Active", "Persistent", "Lightweight", "Snappy"
};
constexpr const char* PerformanceNouns[] = {
"Pulse", "Flow", "Cycle", "Burst", "Stream",
"Tick", "Glide", "Shift", "Velocity", "Spike",
"Pace", "Rhythm", "Drive", "Path", "Edge",
"Sprint", "Torrent", "Current", "Surge", "Momentum",
"Flux", "Wave", "Accelerator", "Spark", "Jet",
"Thrust", "Orbit", "Apex", "Bolt", "Phase",
"Rush", "Impact", "Frequency", "Lapse", "Kick"
};
constexpr const char* CoreAdjectives[] = {
"Binary", "Raw", "Atomic", "Static", "Core",
"Virtual", "Base", "Solid", "Dense", "Opaque",
"Primitive", "Native", "Hard", "Stable", "Immutable",
"Monolithic", "Bare", "Rigid", "Concrete", "Fundamental",
"Discrete", "Fixed", "Heavy", "Latent", "Symmetric",
"Implicit", "Explicit", "Cold", "Basic", "Granite",
"Stark", "Brute", "Firm", "Stout", "Coarse"
};
constexpr const char* CoreNouns[] = {
"Stack", "Heap", "Node", "Buffer", "Segment",
"Thread", "Kernel", "Block", "Page", "Shell",
"Layer", "Bit", "Logic", "Port", "Root",
"Register", "Pointer", "Address", "Cache", "Opcode",
"Slab", "Pipeline", "Bus", "Socket", "Sector",
"Vault", "Anchor", "Pillar", "Base", "Primitive",
"Offset", "Handle", "Struct", "Memory", "Word"
};
constexpr const char* ModernAdjectives[] = {
"Synthetic", "Neural", "Async", "Elastic", "Cloud",
"Distributed", "Reactive", "Orbital", "Poly", "Infinite",
"Parallel", "Modular", "Virtualized", "Scalable", "Agnostic",
"Adaptive", "Hybrid", "Autonomous", "Global", "Synergic",
"Omnipresent", "Evolving", "Abstract", "Unified", "Concurrent",
"Remote", "Digital", "Cluster", "Ephemeral", "Stateful",
"Stateless", "Serverless", "Decoupled", "Fluent", "Native"
};
constexpr const char* ModernNouns[] = {
"Nexus", "Grid", "Matrix", "Vertex", "Sync",
"Axiom", "Sphere", "Hub", "Mesh", "Bridge",
"Link", "Unit", "Fabric", "Cluster", "Portal",
"Ecosystem", "Catalyst", "Interface", "Domain", "Gateway",
"Lattice", "Cloud", "Instance", "Schema", "Registry",
"Tenant", "Namespace", "Pod", "Stream", "Endpoint",
"Payload", "Relay", "Orchestrator", "Broker", "Agent"
};
constexpr const char* FailureAdjectives[] = {
"Clumsy", "Wobbly", "Confused", "Chaotic", "Sneaky",
"Lazy", "Dizzy", "Broken", "Leaky", "Fragile",
"Shaky", "Erratic", "Sleepy", "Lost", "Random",
"Glitchy", "Unstable", "Paradoxical", "Cluttery", "Hiccupy",
"Wonky", "Flaky", "Stubborn", "Moody", "Nervous",
"Fumbling", "Drifting", "Tangled", "Blurred", "Absent",
"Haphazard", "Spasmodic", "Clunky", "Jittery", "Bewildered"
};
constexpr const char* FailureNouns[] = {
"Crash", "Bug", "Leak", "Hang", "Timeout",
"Panic", "Loop", "Spill", "Hiccup", "Glitch",
"Wobble", "Tumble", "Void", "Abyss", "Maze",
"Knot", "Static", "Noise", "Drift", "Stumble",
"Gap", "Fragment", "Shard", "Spark", "Bubble",
"Slip", "Trip", "Fall", "Ghost", "Shadow",
"Blur", "Overflow", "Sinkhole", "Echo", "Mirage"
};
constexpr const char* MythicAdjectives[] = {
"Mythic", "Arcane", "Ancient", "Eternal", "Sacred",
"Divine", "Forgotten", "Elder", "Primordial", "Venerable",
"Runic", "Prophetic", "Colossal", "Imperial", "Regal",
"Sovereign", "Mystic", "Occult", "Hidden", "Cryptic",
"Ethereal", "Celestial", "Gnostic", "Hermetic", "Alchemical",
"Astral", "Golden", "Iron", "Bronze", "Obsidian",
"Silver", "Timeless", "Boundless", "Omnipotent", "Everlasting"
};
constexpr const char* MythicNouns[] = {
"Aegis", "Helios", "Oracle", "Titan", "Rune",
"Lex", "Codex", "Obelisk", "Monolith", "Temple",
"Altar", "Scepter", "Crown", "Sigil", "Glyph",
"Tome", "Relic", "Artifact", "Sanctum", "Citadel",
"Bastion", "Spire", "Pillar", "Throne", "Vault",
"Key", "Gate", "Bridge", "Seal", "Pact",
"Covenant", "Legacy", "Epoch", "Era", "Myth"
};
constexpr const char* CosmosAdjectives[] = {
"Relativistic", "Baryonic", "Intergalactic", "Event-Horizon", "Singular",
"Celestial", "Nebular", "Void-Born", "Astral", "Luminous",
"Spectral", "Ionized", "Gravitational", "Ecliptic", "Zenithal",
"Stellar", "Cosmological", "Parallactic", "Zero-Point", "Dark-Matter",
"Radiant", "Orbital", "Supernova", "Hyper-Spatial", "Aetheric",
"Cold-Void", "Infinite", "Dimensional", "Crystalline", "Tidal",
"Planetary", "Solar", "Lunar", "Galactic", "Oblique"
};
constexpr const char* CosmosNouns[] = {
"Pulsar", "Quasar", "Singularity", "Void", "Nebula",
"Horizon", "Apex", "Zenith", "Equinox", "Corona",
"Aperture", "Axis", "Parallax", "Cluster", "Constellation",
"Vacuum", "Symmetry", "Continuum", "Flux", "Vortex",
"Nova", "Eclipse", "Solenoid", "Sphere", "Vector",
"Siderostat", "Sextant", "Obliquity", "Precession", "Azimuth",
"Wavelength", "Frequency", "Radiance", "Entropy", "Magnitude"
};
constexpr const char* GameAdjectives[] = {
"Frame-Locked", "Pixel-Perfect", "Arcade", "Retro", "Hardcore",
"Unlocked", "Godlike", "Buffed", "Nerfed", "Overclocked",
"Clutch", "Lagless", "Sweaty", "Tryhard", "Broken",
"Turbo", "Min-Max", "Rage-Quit", "No-Scope", "Frame-Perfect",
"Savescum", "Co-Op", "Modded", "Patched", "Hotfixed",
"Debugged", "Optimized", "Smoothed", "Playtest", "Sandbox",
"Scripted", "Speedrun", "Cheat-Code", "Invincible", "Flawless"
};
constexpr const char* GameNouns[] = {
"Frame", "Tick", "Sprite", "Polygon", "Shader",
"Texture", "Voxel", "Render", "Hitbox", "Hurtbox",
"Collision", "Input", "Viewport", "Level", "Checkpoint",
"Boss", "Loot", "Quest", "Spawn", "Respawn",
"Grind", "Scroll", "Tilemap", "Backdrop", "Rig",
"Build", "Frag", "Gib", "Drawcall", "Pass",
"Batch", "Delta", "Pool", "Arena", "Worker"
};
constexpr std::array NameBanks = {
NameBank { AnalysisAdjectives, AnalysisNouns, sizeof(AnalysisAdjectives) / sizeof(AnalysisAdjectives[0]), sizeof(AnalysisNouns) / sizeof(AnalysisNouns[0]) },
NameBank { PerformanceAdjectives, PerformanceNouns, sizeof(PerformanceAdjectives) / sizeof(PerformanceAdjectives[0]), sizeof(PerformanceNouns) / sizeof(PerformanceNouns[0]) },
NameBank { CoreAdjectives, CoreNouns, sizeof(CoreAdjectives) / sizeof(CoreAdjectives[0]), sizeof(CoreNouns) / sizeof(CoreNouns[0]) },
NameBank { ModernAdjectives, ModernNouns, sizeof(ModernAdjectives) / sizeof(ModernAdjectives[0]), sizeof(ModernNouns) / sizeof(ModernNouns[0]) },
NameBank { FailureAdjectives, FailureNouns, sizeof(FailureAdjectives) / sizeof(FailureAdjectives[0]), sizeof(FailureNouns) / sizeof(FailureNouns[0]) },
NameBank { MythicAdjectives, MythicNouns, sizeof(MythicAdjectives) / sizeof(MythicAdjectives[0]), sizeof(MythicNouns) / sizeof(MythicNouns[0]) },
NameBank { CosmosAdjectives, CosmosNouns, sizeof(CosmosAdjectives) / sizeof(CosmosAdjectives[0]), sizeof(CosmosNouns) / sizeof(CosmosNouns[0]) },
NameBank { GameAdjectives, GameNouns, sizeof(GameAdjectives) / sizeof(GameAdjectives[0]), sizeof(GameNouns) / sizeof(GameNouns[0]) },
};
constexpr std::array NameStructure = { "an", "aan", "nn" };
std::string GenerateAbstractName()
{
std::random_device rd;
std::default_random_engine gen( rd() );
std::uniform_int_distribution<uint32_t> dist( 0, UINT32_MAX );
const auto baseBank = NameBanks[dist( gen ) % NameBanks.size()];
const char* structure = NameStructure[dist( gen ) % NameStructure.size()];
std::vector<std::string> parts;
while( *structure )
{
const auto type = *structure++;
assert( type == 'a' || type == 'n' );
const auto bank = dist( gen ) % 6 == 0 ? NameBanks[dist( gen ) % NameBanks.size()] : baseBank;
for(;;)
{
auto part = std::string( type == 'a' ? bank.adjectives[dist( gen ) % bank.numAdjectives] : bank.nouns[dist( gen ) % bank.numNouns] );
if( std::ranges::find( parts, part ) == parts.end() )
{
parts.emplace_back( std::move( part ) );
break;
}
}
};
std::string ret = parts[0];
for( size_t i=1; i<parts.size(); i++ )
{
ret += " " + parts[i];
}
return ret;
}
}

View File

@@ -0,0 +1,13 @@
#ifndef __TRACYNAMEGEN_HPP__
#define __TRACYNAMEGEN_HPP__
#include <string>
namespace tracy
{
std::string GenerateAbstractName();
}
#endif

View File

@@ -1,4 +1,7 @@
#include <string.h>
#include "TracyImGui.hpp"
#include "TracyNameGen.hpp"
#include "TracyPrint.hpp"
#include "TracyView.hpp"
#include "tracy_pdqsort.h"
@@ -10,6 +13,7 @@ namespace tracy
void View::AddAnnotation( int64_t start, int64_t end )
{
auto ann = std::make_shared<Annotation>();
ann->text = GenerateAbstractName();
ann->range.active = true;
ann->range.min = start;
ann->range.max = end;
@@ -52,7 +56,22 @@ void View::DrawSelectedAnnotation()
char buf[1024];
buf[descsz] = '\0';
memcpy( buf, desc, descsz );
if( ImGui::InputTextWithHint( "##anndesc", "Describe annotation", buf, 256 ) )
const char* buttonText = ICON_FA_DICE;
auto buttonSize = ImGui::CalcTextSize( buttonText );
buttonSize.x += ImGui::GetStyle().FramePadding.x * 2.0f + ImGui::GetStyle().ItemSpacing.x;
ImGui::SetNextItemWidth( ImGui::GetContentRegionAvail().x - buttonSize.x );
bool changed = ImGui::InputTextWithHint( "##anndesc", "Describe annotation", buf, 256 );
ImGui::SameLine();
if( ImGui::Button( buttonText ) )
{
changed = true;
const auto name = GenerateAbstractName();
const auto len = std::min( sizeof( buf ) - 1, name.size() );
memcpy( buf, name.c_str(), len );
buf[len] = '\0';
}
if( changed )
{
m_selectedAnnotation->text.assign( buf );
}

View File

@@ -1,6 +1,7 @@
#include <inttypes.h>
#include "TracyImGui.hpp"
#include "TracyNameGen.hpp"
#include "TracyPrint.hpp"
#include "TracyView.hpp"
#include "tracy_pdqsort.h"
@@ -55,8 +56,22 @@ void View::DrawInfo()
char buf[256];
buf[descsz] = '\0';
memcpy( buf, desc.c_str(), descsz );
ImGui::SetNextItemWidth( -1 );
if( ImGui::InputTextWithHint( "##traceDesc", "Enter description of the trace", buf, 256 ) )
const char* buttonText = ICON_FA_DICE;
auto buttonSize = ImGui::CalcTextSize( buttonText );
buttonSize.x += ImGui::GetStyle().FramePadding.x * 2.0f + ImGui::GetStyle().ItemSpacing.x;
ImGui::SetNextItemWidth( ImGui::GetContentRegionAvail().x - buttonSize.x );
bool changed = ImGui::InputTextWithHint( "##traceDesc", "Enter description of the trace", buf, 256 );
ImGui::SameLine();
if( ImGui::Button( buttonText ) )
{
changed = true;
const auto name = GenerateAbstractName();
const auto len = std::min( sizeof( buf ) - 1, name.size() );
memcpy( buf, name.c_str(), len );
buf[len] = '\0';
}
if( changed )
{
m_userData.SetDescription( buf );
if( m_stcb ) UpdateTitle();

View File

@@ -5257,7 +5257,7 @@ TRACY_API int32_t ___tracy_before_lock_shared_shared_lockable_ctx( struct __trac
return static_cast<int32_t>(true);
}
TRACY_API void ___tracy_after_locked_shared_shared_lockable_ctx( struct __tracy_shared_lockable_context_data* lockdata )
TRACY_API void ___tracy_after_lock_shared_shared_lockable_ctx( struct __tracy_shared_lockable_context_data* lockdata )
{
auto item = tracy::Profiler::QueueSerial();
tracy::MemWrite( &item->hdr.type, tracy::QueueType::LockSharedObtain );

View File

@@ -171,8 +171,8 @@ struct ConcurrentQueueDefaultTraits
#if defined(malloc) || defined(free)
// Gah, this is 2015, stop defining macros that break standard code already!
// Work around malloc/free being special macros:
static inline void* WORKAROUND_malloc(size_t size) { return malloc(size); }
static inline void WORKAROUND_free(void* ptr) { return free(ptr); }
static inline void* WORKAROUND_malloc(size_t size) { return tracy::tracy_malloc(size); }
static inline void WORKAROUND_free(void* ptr) { return tracy::tracy_free(ptr); }
static inline void* (malloc)(size_t size) { return WORKAROUND_malloc(size); }
static inline void (free)(void* ptr) { return WORKAROUND_free(ptr); }
#else

View File

@@ -391,7 +391,7 @@ TRACY_API void ___tracy_after_lock_shared_lockable_ctx( struct __tracy_shared_lo
TRACY_API void ___tracy_after_unlock_shared_lockable_ctx( struct __tracy_shared_lockable_context_data* lockdata );
TRACY_API void ___tracy_after_try_lock_shared_lockable_ctx( struct __tracy_shared_lockable_context_data* lockdata, int32_t acquired );
TRACY_API int32_t ___tracy_before_lock_shared_shared_lockable_ctx( struct __tracy_shared_lockable_context_data* lockdata );
TRACY_API void ___tracy_after_locked_shared_shared_lockable_ctx( struct __tracy_shared_lockable_context_data* lockdata );
TRACY_API void ___tracy_after_lock_shared_shared_lockable_ctx( struct __tracy_shared_lockable_context_data* lockdata );
TRACY_API void ___tracy_after_unlock_shared_shared_lockable_ctx( struct __tracy_shared_lockable_context_data* lockdata );
TRACY_API void ___tracy_after_try_lock_shared_shared_lockable_ctx( struct __tracy_shared_lockable_context_data* lockdata, int32_t acquired );
TRACY_API void ___tracy_mark_shared_lockable_ctx( struct __tracy_shared_lockable_context_data* lockdata, const struct ___tracy_source_location_data* srcloc );
@@ -414,7 +414,7 @@ TRACY_API void ___tracy_custom_name_shared_lockable_ctx( struct __tracy_shared_l
#define TracyCSharedLockAfterUnlock( lock ) ___tracy_after_unlock_shared_lockable_ctx( lock );
#define TracyCSharedLockAfterTryLock( lock, acquired ) ___tracy_after_try_lock_shared_lockable_ctx( lock, acquired );
#define TracyCSharedLockBeforeSharedLock( lock ) ___tracy_before_lock_shared_shared_lockable_ctx( lock );
#define TracyCSharedLockAfterSharedLock( lock ) ___tracy_after_locked_shared_shared_lockable_ctx( lock );
#define TracyCSharedLockAfterSharedLock( lock ) ___tracy_after_lock_shared_shared_lockable_ctx( lock );
#define TracyCSharedLockAfterSharedUnlock( lock ) ___tracy_after_unlock_shared_shared_lockable_ctx( lock );
#define TracyCSharedLockAfterTrySharedLock( lock, acquired ) ___tracy_after_try_lock_shared_shared_lockable_ctx( lock, acquired );
#define TracyCSharedLockMark( lock ) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,TracyLine) = { NULL, __func__, TracyFile, (uint32_t)TracyLine, 0 }; ___tracy_mark_shared_lockable_ctx( lock, &TracyConcat(__tracy_source_location,TracyLine) );

View File

@@ -1,7 +1,12 @@
#ifndef __TRACYOPENGL_HPP__
#define __TRACYOPENGL_HPP__
#if !defined TRACY_ENABLE || defined __APPLE__
#ifdef __APPLE__
#define TRACY_OPENGL_DISABLE
#warning "OpenGL support on Apple devices is deprecated or unavailable."
#endif
#if !defined TRACY_ENABLE || defined TRACY_OPENGL_DISABLE
#define TracyGpuContext
#define TracyGpuContextName(x,y)
@@ -98,17 +103,25 @@ public:
, m_head( 0 )
, m_tail( 0 )
{
ZoneScopedC( Color::Red4 );
assert( m_context != 255 );
glGenQueries( QueryCount, m_query );
GLint bits;
glGetQueryiv( GL_TIMESTAMP, GL_QUERY_COUNTER_BITS, &bits );
if( bits == 0 )
{
// all timestamp queries would resolve to 0 (and produce 0ns GPU zones).
// (this is the case for many TBDR GPUs, including Apple Silicon)
Profiler::LogString( MessageSourceType::Tracy, MessageSeverity::Warning, Color::Tomato, 0,
"OpenGL driver does not implement GL_TIMESTAMP precision." );
}
assert( bits > 0 );
int64_t tgpu;
glGetInteger64v( GL_TIMESTAMP, &tgpu );
int64_t tcpu = Profiler::GetTime();
GLint bits;
glGetQueryiv( GL_TIMESTAMP, GL_QUERY_COUNTER_BITS, &bits );
#ifdef TRACY_OPENGL_AUTO_CALIBRATION
// The anchor above is never refreshed; advertise calibration and emit periodic
// GpuCalibration events to correct CPU/GPU drift (see Recalibrate). Opt-in,
@@ -117,6 +130,8 @@ public:
m_prevCalibration = GetHostTimeNs();
#endif
glGenQueries( QueryCount, m_query );
const float period = 1.f;
const auto thread = GetThreadHandle();
TracyLfqPrepare( QueueType::GpuNewContext );