mirror of
https://github.com/wolfpld/tracy.git
synced 2026-06-08 08:33:48 +00:00
Compare commits
3 Commits
e5aa8eba51
...
19519bbeb0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
19519bbeb0 | ||
|
|
fc4f52e61d | ||
|
|
e2ac8f7973 |
@@ -137,6 +137,7 @@ set_option(TRACY_SYMBOL_OFFLINE_RESOLVE "Instead of full runtime symbol resoluti
|
|||||||
set_option(TRACY_LIBBACKTRACE_ELF_DYNLOAD_SUPPORT "Enable libbacktrace to support dynamically loaded elfs in symbol resolution resolution after the first symbol resolve operation" OFF TracyClient)
|
set_option(TRACY_LIBBACKTRACE_ELF_DYNLOAD_SUPPORT "Enable libbacktrace to support dynamically loaded elfs in symbol resolution resolution after the first symbol resolve operation" OFF TracyClient)
|
||||||
set_option(TRACY_DEBUGINFOD "Enable debuginfod support" OFF TracyClient)
|
set_option(TRACY_DEBUGINFOD "Enable debuginfod support" OFF TracyClient)
|
||||||
set_option(TRACY_IGNORE_MEMORY_FAULTS "Ignore instrumentation errors from memory free events that do not have a matching allocation" OFF TracyClient)
|
set_option(TRACY_IGNORE_MEMORY_FAULTS "Ignore instrumentation errors from memory free events that do not have a matching allocation" OFF TracyClient)
|
||||||
|
set_option(TRACY_OPENGL_AUTO_CALIBRATION "Periodically recalibrate OpenGL GPU/CPU clock drift (forces a CPU/GPU sync each time)" OFF TracyClient)
|
||||||
|
|
||||||
# advanced
|
# advanced
|
||||||
set_option(TRACY_VERBOSE "[advanced] Verbose output from the profiler" OFF TracyClient)
|
set_option(TRACY_VERBOSE "[advanced] Verbose output from the profiler" OFF TracyClient)
|
||||||
|
|||||||
@@ -1701,6 +1701,12 @@ logo=\bcattention
|
|||||||
\end{itemize}
|
\end{itemize}
|
||||||
\end{bclogo}
|
\end{bclogo}
|
||||||
|
|
||||||
|
\subparagraph{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~\ref{options} describes correcting this drift manually). Defining \texttt{TRACY\_OPENGL\_AUTO\_CALIBRATION} before including \texttt{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 \texttt{VK\_EXT\_calibrated\_timestamps} or Direct3D~12, whose contexts are always calibrated). Recalibration therefore reads the GPU clock with \texttt{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.
|
||||||
|
|
||||||
\subsubsection{Vulkan}
|
\subsubsection{Vulkan}
|
||||||
|
|
||||||
Similarly, for Vulkan support you should include the \texttt{public/tracy/TracyVulkan.hpp} header file. Tracing Vulkan devices and queues is a bit more involved, and the Vulkan initialization macro \texttt{TracyVkContext(physdev, device, queue, cmdbuf)} returns an instance of \texttt{TracyVkCtx} object, which tracks an associated Vulkan queue. Cleanup is performed using the \texttt{TracyVkDestroy(ctx)} macro. You may create multiple Vulkan contexts. To set a custom name for the context, use the \texttt{TracyVkContextName(ctx, name, size)} macro.
|
Similarly, for Vulkan support you should include the \texttt{public/tracy/TracyVulkan.hpp} header file. Tracing Vulkan devices and queues is a bit more involved, and the Vulkan initialization macro \texttt{TracyVkContext(physdev, device, queue, cmdbuf)} returns an instance of \texttt{TracyVkCtx} object, which tracks an associated Vulkan queue. Cleanup is performed using the \texttt{TracyVkDestroy(ctx)} macro. You may create multiple Vulkan contexts. To set a custom name for the context, use the \texttt{TracyVkContextName(ctx, name, size)} macro.
|
||||||
|
|||||||
@@ -135,6 +135,10 @@ if get_option('ignore_memory_faults')
|
|||||||
tracy_common_args += ['-DTRACY_IGNORE_MEMORY_FAULTS']
|
tracy_common_args += ['-DTRACY_IGNORE_MEMORY_FAULTS']
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if get_option('opengl_auto_calibration')
|
||||||
|
tracy_common_args += ['-DTRACY_OPENGL_AUTO_CALIBRATION']
|
||||||
|
endif
|
||||||
|
|
||||||
tracy_shared_libs = get_option('default_library') == 'shared'
|
tracy_shared_libs = get_option('default_library') == 'shared'
|
||||||
|
|
||||||
if tracy_shared_libs
|
if tracy_shared_libs
|
||||||
|
|||||||
@@ -29,3 +29,4 @@ option('verbose', type : 'boolean', value : false, description : 'Enable verbose
|
|||||||
option('no_internal_message', type : 'boolean', value : false, description : 'Prevent the profiler from logging messages')
|
option('no_internal_message', type : 'boolean', value : false, description : 'Prevent the profiler from logging messages')
|
||||||
option('debuginfod', type : 'boolean', value : false, description : 'Enable debuginfod support')
|
option('debuginfod', type : 'boolean', value : false, description : 'Enable debuginfod support')
|
||||||
option('ignore_memory_faults', type : 'boolean', value : false, description : 'Ignore instrumentation errors from memory free events that do not have a matching allocation')
|
option('ignore_memory_faults', type : 'boolean', value : false, description : 'Ignore instrumentation errors from memory free events that do not have a matching allocation')
|
||||||
|
option('opengl_auto_calibration', type : 'boolean', value : false, description : 'Periodically recalibrate OpenGL GPU/CPU clock drift (forces a CPU/GPU sync each time)')
|
||||||
|
|||||||
@@ -34,6 +34,9 @@ public:
|
|||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#ifdef TRACY_OPENGL_AUTO_CALIBRATION
|
||||||
|
# include <chrono>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "Tracy.hpp"
|
#include "Tracy.hpp"
|
||||||
#include "../client/TracyProfiler.hpp"
|
#include "../client/TracyProfiler.hpp"
|
||||||
@@ -106,6 +109,14 @@ public:
|
|||||||
GLint bits;
|
GLint bits;
|
||||||
glGetQueryiv( GL_TIMESTAMP, GL_QUERY_COUNTER_BITS, &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,
|
||||||
|
// because Recalibrate() calls glGetInteger64v( GL_TIMESTAMP ), which forces a
|
||||||
|
// CPU/GPU sync.
|
||||||
|
m_prevCalibration = GetHostTimeNs();
|
||||||
|
#endif
|
||||||
|
|
||||||
const float period = 1.f;
|
const float period = 1.f;
|
||||||
const auto thread = GetThreadHandle();
|
const auto thread = GetThreadHandle();
|
||||||
TracyLfqPrepare( QueueType::GpuNewContext );
|
TracyLfqPrepare( QueueType::GpuNewContext );
|
||||||
@@ -114,7 +125,11 @@ public:
|
|||||||
MemWrite( &item->gpuNewContext.thread, thread );
|
MemWrite( &item->gpuNewContext.thread, thread );
|
||||||
MemWrite( &item->gpuNewContext.period, period );
|
MemWrite( &item->gpuNewContext.period, period );
|
||||||
MemWrite( &item->gpuNewContext.context, m_context );
|
MemWrite( &item->gpuNewContext.context, m_context );
|
||||||
|
#ifdef TRACY_OPENGL_AUTO_CALIBRATION
|
||||||
|
MemWrite( &item->gpuNewContext.flags, GpuContextFlags( GpuContextCalibration ) );
|
||||||
|
#else
|
||||||
MemWrite( &item->gpuNewContext.flags, GpuContextFlags( 0 ) );
|
MemWrite( &item->gpuNewContext.flags, GpuContextFlags( 0 ) );
|
||||||
|
#endif
|
||||||
MemWrite( &item->gpuNewContext.type, GpuContextType::OpenGl );
|
MemWrite( &item->gpuNewContext.type, GpuContextType::OpenGl );
|
||||||
|
|
||||||
#ifdef TRACY_ON_DEMAND
|
#ifdef TRACY_ON_DEMAND
|
||||||
@@ -143,8 +158,6 @@ public:
|
|||||||
{
|
{
|
||||||
ZoneScopedC( Color::Red4 );
|
ZoneScopedC( Color::Red4 );
|
||||||
|
|
||||||
if( m_tail == m_head ) return;
|
|
||||||
|
|
||||||
#ifdef TRACY_ON_DEMAND
|
#ifdef TRACY_ON_DEMAND
|
||||||
if( !GetProfiler().IsConnected() )
|
if( !GetProfiler().IsConnected() )
|
||||||
{
|
{
|
||||||
@@ -153,6 +166,14 @@ public:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef TRACY_OPENGL_AUTO_CALIBRATION
|
||||||
|
// Before the drain's early-returns, so it runs even on frames with no
|
||||||
|
// completed queries.
|
||||||
|
Recalibrate();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if( m_tail == m_head ) return;
|
||||||
|
|
||||||
while( m_tail != m_head )
|
while( m_tail != m_head )
|
||||||
{
|
{
|
||||||
GLint available;
|
GLint available;
|
||||||
@@ -173,6 +194,38 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
#ifdef TRACY_OPENGL_AUTO_CALIBRATION
|
||||||
|
// Monotonic host ns for the inter-calibration interval (cpuDelta), kept
|
||||||
|
// separate from Profiler::GetTime() as in the D3D12/Vulkan backends.
|
||||||
|
static tracy_force_inline int64_t GetHostTimeNs()
|
||||||
|
{
|
||||||
|
return std::chrono::duration_cast<std::chrono::nanoseconds>(
|
||||||
|
std::chrono::steady_clock::now().time_since_epoch() ).count();
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenGL has no atomic CPU+GPU timestamp query, so sample back-to-back; the
|
||||||
|
// gap is negligible against the recalibration interval below. Note this forces
|
||||||
|
// a CPU/GPU sync, which is why the whole path is opt-in (TRACY_OPENGL_AUTO_CALIBRATION).
|
||||||
|
tracy_force_inline void Recalibrate()
|
||||||
|
{
|
||||||
|
const int64_t hostNow = GetHostTimeNs();
|
||||||
|
const int64_t delta = hostNow - m_prevCalibration;
|
||||||
|
if( delta < 1000ll * 1000 * 1000 ) return; // throttle: ~once per second
|
||||||
|
|
||||||
|
int64_t tgpu;
|
||||||
|
glGetInteger64v( GL_TIMESTAMP, &tgpu );
|
||||||
|
const int64_t refCpu = Profiler::GetTime();
|
||||||
|
m_prevCalibration = hostNow;
|
||||||
|
|
||||||
|
TracyLfqPrepare( QueueType::GpuCalibration );
|
||||||
|
MemWrite( &item->gpuCalibration.gpuTime, tgpu );
|
||||||
|
MemWrite( &item->gpuCalibration.cpuTime, refCpu );
|
||||||
|
MemWrite( &item->gpuCalibration.cpuDelta, delta );
|
||||||
|
MemWrite( &item->gpuCalibration.context, m_context );
|
||||||
|
TracyLfqCommit;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
tracy_force_inline unsigned int NextQueryId()
|
tracy_force_inline unsigned int NextQueryId()
|
||||||
{
|
{
|
||||||
const auto id = m_head;
|
const auto id = m_head;
|
||||||
@@ -196,6 +249,10 @@ private:
|
|||||||
|
|
||||||
unsigned int m_head;
|
unsigned int m_head;
|
||||||
unsigned int m_tail;
|
unsigned int m_tail;
|
||||||
|
|
||||||
|
#ifdef TRACY_OPENGL_AUTO_CALIBRATION
|
||||||
|
int64_t m_prevCalibration; // host-ns timestamp of the last emitted calibration
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
class GpuCtxScope
|
class GpuCtxScope
|
||||||
|
|||||||
Reference in New Issue
Block a user