15#include <tracy/Tracy.hpp>
16#include <tracy/TracyVulkan.hpp>
18#include <vsg/utils/Instrumentation.h>
28 uint32_t cpu_instrumentation_level = 3;
29 uint32_t gpu_instrumentation_level = 3;
35 class TracyContexts :
public Inherit<Object, TracyContexts>
40 std::scoped_lock<std::mutex> lock(mutex);
43 auto& [ctx, requiresCollection] = ctxMap[device];
46 auto queue = device->getQueue(commandBuffer.getCommandPool()->queueFamilyIndex, 0);
47 auto commandPool = CommandPool::create(device, queue->queueFamilyIndex(), VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
48 auto temporaryCommandBuffer = commandPool->allocate();
49 auto extensions = device->getInstance()->getExtensions();
51 if (device->supportsDeviceExtension(
"VK_EXT_calibrated_timestamps"))
53 ctx = TracyVkContextCalibrated(device->getPhysicalDevice()->vk(), device->vk(), queue->vk(), temporaryCommandBuffer->vk(),
54 extensions->vkGetPhysicalDeviceCalibrateableTimeDomainsEXT, extensions->vkGetCalibratedTimestampsEXT);
58 ctx = TracyVkContext(device->getPhysicalDevice()->vk(), device->vk(), queue->vk(), temporaryCommandBuffer->vk());
60 requiresCollection =
false;
63 if (ctx && requiresCollection)
65 TracyVkCollect(ctx, commandBuffer.vk());
66 requiresCollection =
false;
74 std::scoped_lock<std::mutex> lock(mutex);
75 for (
auto itr = ctxMap.begin(); itr != ctxMap.end(); ++itr)
77 itr->second.second =
true;
81 mutable std::mutex mutex;
82 mutable std::map<ref_ptr<Device>, std::pair<VkCtx*, bool>> ctxMap;
87 for (
auto itr = ctxMap.begin(); itr != ctxMap.end(); ++itr)
89 TracyVkDestroy(itr->second.first);
93 VSG_type_name(vsg::TracyContexts);
96 class TracyInstrumentation :
public Inherit<Instrumentation, TracyInstrumentation>
99 TracyInstrumentation() :
100 settings(TracySettings::create()),
101 contexts(TracyContexts::create())
105 TracyInstrumentation(TracyInstrumentation& parent) :
106 settings(parent.settings),
107 contexts(parent.contexts)
111 ref_ptr<TracySettings> settings;
112 ref_ptr<TracyContexts> contexts;
113 mutable VkCtx* ctx =
nullptr;
114 bool requiresCollection =
false;
116 ref_ptr<Instrumentation> shareOrDuplicateForThreadSafety()
override
118 return TracyInstrumentation::create(*
this);
121 void setThreadName(
const std::string& name)
const override
123 tracy::SetThreadName(name.c_str());
126 void enterFrame(
const SourceLocation*, uint64_t&, FrameStamp&)
const override {}
128 void leaveFrame(
const SourceLocation*, uint64_t&, FrameStamp&)
const override
130 contexts->frameComplete();
135 void enter(
const SourceLocation* slcloc, uint64_t& reference,
const Object*)
const override
137# ifdef TRACY_ON_DEMAND
138 if (!GetProfiler().IsConnected() || (slcloc->level > settings->cpu_instrumentation_level))
140 if (slcloc->level > settings->cpu_instrumentation_level)
147# ifdef TRACY_ON_DEMAND
148 reference = GetProfiler().ConnectionId();
153 TracyQueuePrepare(QueueType::ZoneBegin);
154 MemWrite(&item->zoneBegin.time, tracy::Profiler::GetTime());
155 MemWrite(&item->zoneBegin.srcloc, (uint64_t)slcloc);
156 TracyQueueCommit(zoneBeginThread);
159 void leave(
const SourceLocation*, uint64_t& reference,
const Object*)
const override
161# ifdef TRACY_ON_DEMAND
162 if (reference == 0 || GetProfiler().ConnectionId() != reference)
return;
164 if (reference == 0)
return;
167 TracyQueuePrepare(QueueType::ZoneEnd);
168 MemWrite(&item->zoneEnd.time, tracy::Profiler::GetTime());
169 TracyQueueCommit(zoneEndThread);
172 void enterCommandBuffer(
const SourceLocation* slcloc, uint64_t& reference, CommandBuffer& commandBuffer)
const override
174 if (ctx = contexts->getOrCreateContext(commandBuffer))
176 enter(slcloc, reference, commandBuffer,
nullptr);
180 void leaveCommandBuffer(
const SourceLocation* slcloc, uint64_t& reference, CommandBuffer& commandBuffer)
const override
184 leave(slcloc, reference, commandBuffer,
nullptr);
190 void enter(
const SourceLocation* slcloc, uint64_t& reference, CommandBuffer& cmdbuf,
const Object*)
const override
192# ifdef TRACY_ON_DEMAND
193 if (!ctx || !GetProfiler().IsConnected() || (slcloc->level > settings->gpu_instrumentation_level))
195 if (!ctx || slcloc->level > settings->gpu_instrumentation_level)
202# ifdef TRACY_ON_DEMAND
203 reference = GetProfiler().ConnectionId();
208 const auto queryId = ctx->NextQueryId();
209 CONTEXT_VK_FUNCTION_WRAPPER(vkCmdWriteTimestamp(cmdbuf, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, ctx->GetQueryPool(), queryId));
211 auto item = tracy::Profiler::QueueSerial();
212 MemWrite(&item->hdr.type, QueueType::GpuZoneBeginSerial);
213 MemWrite(&item->gpuZoneBegin.cpuTime, tracy::Profiler::GetTime());
214 MemWrite(&item->gpuZoneBegin.srcloc, (uint64_t)slcloc);
215 MemWrite(&item->gpuZoneBegin.thread, GetThreadHandle());
216 MemWrite(&item->gpuZoneBegin.queryId, uint16_t(queryId));
217 MemWrite(&item->gpuZoneBegin.context, ctx->GetId());
218 tracy::Profiler::QueueSerialFinish();
221 void leave(
const SourceLocation*, uint64_t& reference, CommandBuffer& cmdbuf,
const Object*)
const override
223# ifdef TRACY_ON_DEMAND
224 if (reference == 0 || GetProfiler().ConnectionId() != reference)
return;
226 if (reference == 0)
return;
229 const auto queryId = ctx->NextQueryId();
230 CONTEXT_VK_FUNCTION_WRAPPER(vkCmdWriteTimestamp(cmdbuf, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, ctx->GetQueryPool(), queryId));
232 auto item = tracy::Profiler::QueueSerial();
233 MemWrite(&item->hdr.type, QueueType::GpuZoneEndSerial);
234 MemWrite(&item->gpuZoneEnd.cpuTime, tracy::Profiler::GetTime());
235 MemWrite(&item->gpuZoneEnd.thread, GetThreadHandle());
236 MemWrite(&item->gpuZoneEnd.queryId, uint16_t(queryId));
237 MemWrite(&item->gpuZoneEnd.context, ctx->GetId());
238 tracy::Profiler::QueueSerialFinish();
248 vsg::info(
"TracyInstrumentation not supported and the tracy's TRACY_ENABLE is set to OFF.");
CommandBuffer encapsulates VkCommandBuffer.
Definition CommandBuffer.h:27
Definition TracyInstrumentation.h:244
Definition TracyInstrumentation.h:26