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);
99 TracyInstrumentation() :
100 settings(TracySettings::create()),
101 contexts(TracyContexts::create())
105 TracyInstrumentation(TracyInstrumentation& parent) :
107 settings(parent.settings),
108 contexts(parent.contexts)
112 ref_ptr<TracySettings> settings;
113 ref_ptr<TracyContexts> contexts;
114 mutable VkCtx* ctx =
nullptr;
115 bool requiresCollection =
false;
117 ref_ptr<Instrumentation> shareOrDuplicateForThreadSafety()
override
119 return TracyInstrumentation::create(*
this);
122 void setThreadName(
const std::string& name)
const override
124 tracy::SetThreadName(name.c_str());
127 void enterFrame(
const SourceLocation*, uint64_t&, FrameStamp&)
const override {}
129 void leaveFrame(
const SourceLocation*, uint64_t&, FrameStamp&)
const override
131 contexts->frameComplete();
136 void enter(
const SourceLocation* slcloc, uint64_t& reference,
const Object*)
const override
138# ifdef TRACY_ON_DEMAND
139 if (!GetProfiler().IsConnected() || (slcloc->level > settings->cpu_instrumentation_level))
141 if (slcloc->level > settings->cpu_instrumentation_level)
148# ifdef TRACY_ON_DEMAND
149 reference = GetProfiler().ConnectionId();
154 TracyQueuePrepare(QueueType::ZoneBegin);
155 MemWrite(&item->zoneBegin.time, tracy::Profiler::GetTime());
156 MemWrite(&item->zoneBegin.srcloc, (uint64_t)slcloc);
157 TracyQueueCommit(zoneBeginThread);
160 void leave(
const SourceLocation*, uint64_t& reference,
const Object*)
const override
162# ifdef TRACY_ON_DEMAND
163 if (reference == 0 || GetProfiler().ConnectionId() != reference)
return;
165 if (reference == 0)
return;
168 TracyQueuePrepare(QueueType::ZoneEnd);
169 MemWrite(&item->zoneEnd.time, tracy::Profiler::GetTime());
170 TracyQueueCommit(zoneEndThread);
173 void enterCommandBuffer(
const SourceLocation* slcloc, uint64_t& reference, CommandBuffer& commandBuffer)
const override
175 if ((ctx = contexts->getOrCreateContext(commandBuffer)))
177 enter(slcloc, reference, commandBuffer,
nullptr);
181 void leaveCommandBuffer(
const SourceLocation* slcloc, uint64_t& reference, CommandBuffer& commandBuffer)
const override
185 leave(slcloc, reference, commandBuffer,
nullptr);
191 void enter(
const SourceLocation* slcloc, uint64_t& reference, CommandBuffer& cmdbuf,
const Object*)
const override
193# ifdef TRACY_ON_DEMAND
194 if (!ctx || !GetProfiler().IsConnected() || (slcloc->level > settings->gpu_instrumentation_level))
196 if (!ctx || slcloc->level > settings->gpu_instrumentation_level)
203# ifdef TRACY_ON_DEMAND
204 reference = GetProfiler().ConnectionId();
209 const auto queryId = ctx->NextQueryId();
210 CONTEXT_VK_FUNCTION_WRAPPER(vkCmdWriteTimestamp(cmdbuf, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, ctx->GetQueryPool(), queryId));
212 auto item = tracy::Profiler::QueueSerial();
213 MemWrite(&item->hdr.type, QueueType::GpuZoneBeginSerial);
214 MemWrite(&item->gpuZoneBegin.cpuTime, tracy::Profiler::GetTime());
215 MemWrite(&item->gpuZoneBegin.srcloc, (uint64_t)slcloc);
216 MemWrite(&item->gpuZoneBegin.thread, GetThreadHandle());
217 MemWrite(&item->gpuZoneBegin.queryId, uint16_t(queryId));
218 MemWrite(&item->gpuZoneBegin.context, ctx->GetId());
219 tracy::Profiler::QueueSerialFinish();
222 void leave(
const SourceLocation*, uint64_t& reference, CommandBuffer& cmdbuf,
const Object*)
const override
224# ifdef TRACY_ON_DEMAND
225 if (reference == 0 || GetProfiler().ConnectionId() != reference)
return;
227 if (reference == 0)
return;
230 const auto queryId = ctx->NextQueryId();
231 CONTEXT_VK_FUNCTION_WRAPPER(vkCmdWriteTimestamp(cmdbuf, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, ctx->GetQueryPool(), queryId));
233 auto item = tracy::Profiler::QueueSerial();
234 MemWrite(&item->hdr.type, QueueType::GpuZoneEndSerial);
235 MemWrite(&item->gpuZoneEnd.cpuTime, tracy::Profiler::GetTime());
236 MemWrite(&item->gpuZoneEnd.thread, GetThreadHandle());
237 MemWrite(&item->gpuZoneEnd.queryId, uint16_t(queryId));
238 MemWrite(&item->gpuZoneEnd.context, ctx->GetId());
239 tracy::Profiler::QueueSerialFinish();
242 VSG_type_name(vsg::TracyInstrumentation);
244 class TracyInstrumentation :
public Inherit<Instrumentation, TracyInstrumentation>
247 TracyInstrumentation()
249 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:245
Definition TracyInstrumentation.h:26