19#include "vulkan/vulkan.hpp"
26 bool enable_gpu_tracing)
27 : context_(
std::move(context)) {
28 if (!enable_gpu_tracing) {
31 timestamp_period_ = context_.lock()
35 .limits.timestampPeriod;
36 if (timestamp_period_ <= 0) {
50 Lock lock(trace_state_mutex_);
54 for (
auto i = 0u;
i < kTraceStatesSize;
i++) {
55 vk::QueryPoolCreateInfo
info;
57 info.queryType = vk::QueryType::eTimestamp;
60 if (status != vk::Result::eSuccess) {
64 trace_states_[
i].query_pool = std::move(
pool);
65 buffer_vk.
GetEncoder()->GetCommandBuffer().resetQueryPool(
66 trace_states_[
i].query_pool.get(), 0,
kPoolSize);
84 raster_thread_id_ = std::this_thread::get_id();
94 Lock lock(trace_state_mutex_);
95 current_state_ = (current_state_ + 1) % kTraceStatesSize;
97 auto&
state = trace_states_[current_state_];
104 state.pending_buffers = 0;
105 state.current_index = 0;
109 return std::make_unique<GPUProbe>(weak_from_this());
112void GPUTracerVK::RecordCmdBufferStart(
const vk::CommandBuffer&
buffer,
114 if (!enabled_ || std::this_thread::get_id() != raster_thread_id_ ||
118 Lock lock(trace_state_mutex_);
119 auto&
state = trace_states_[current_state_];
122 if (!states_to_reset_.empty()) {
123 for (
auto i = 0u;
i < states_to_reset_.size();
i++) {
124 buffer.resetQueryPool(trace_states_[states_to_reset_[
i]].query_pool.get(),
127 states_to_reset_.clear();
137 buffer.writeTimestamp(vk::PipelineStageFlagBits::eTopOfPipe,
138 trace_states_[current_state_].query_pool.get(),
139 state.current_index);
140 state.current_index += 1;
141 probe.index_ = current_state_;
142 state.pending_buffers += 1;
145void GPUTracerVK::RecordCmdBufferEnd(
const vk::CommandBuffer&
buffer,
147 if (!enabled_ || std::this_thread::get_id() != raster_thread_id_ ||
148 !in_frame_ || !probe.index_.has_value()) {
151 Lock lock(trace_state_mutex_);
152 GPUTraceState&
state = trace_states_[current_state_];
158 buffer.writeTimestamp(vk::PipelineStageFlagBits::eBottomOfPipe,
161 state.current_index += 1;
164void GPUTracerVK::OnFenceComplete(
size_t frame_index) {
170 size_t query_count = 0;
173 Lock lock(trace_state_mutex_);
174 GPUTraceState&
state = trace_states_[frame_index];
177 state.pending_buffers -= 1;
178 pending =
state.pending_buffers;
179 query_count =
state.current_index;
184 std::vector<uint64_t>
bits(query_count);
185 std::shared_ptr<ContextVK> context = context_.lock();
190 auto result = context->GetDevice().getQueryPoolResults(
191 pool, 0, query_count, query_count *
sizeof(uint64_t),
bits.data(),
192 sizeof(uint64_t), vk::QueryResultFlagBits::e64);
201 if (
result == vk::Result::eSuccess) {
203 uint64_t largest_timestamp = 0;
204 for (
auto i = 0u;
i <
bits.size();
i++) {
209 (((largest_timestamp - smallest_timestamp) * timestamp_period_) /
212 reinterpret_cast<int64_t
>(
this),
213 "FrameTimeMS", gpu_ms);
217 Lock lock(trace_state_mutex_);
218 states_to_reset_.push_back(frame_index);
226 if (!index_.has_value()) {
229 auto tracer = tracer_.lock();
233 tracer->OnFenceComplete(index_.value());
237 auto tracer = tracer_.lock();
241 tracer->RecordCmdBufferStart(
buffer, *
this);
245 auto tracer = tracer_.lock();
249 tracer->RecordCmdBufferEnd(
buffer, *
this);
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
static CommandBufferVK & Cast(CommandBuffer &base)
const std::shared_ptr< CommandEncoderVK > & GetEncoder()
const vk::Device & GetDevice() const
std::shared_ptr< CommandBuffer > CreateCommandBuffer() const override
Create a new command buffer. Command buffers can be used to encode graphics, blit,...
std::shared_ptr< CommandQueue > GetCommandQueue() const override
Return the graphics queue for submitting command buffers.
void RecordCmdBufferStart(const vk::CommandBuffer &buffer)
Record a timestamp query into the provided cmd buffer to record start time.
GPUProbe(const std::weak_ptr< GPUTracerVK > &tracer)
void RecordCmdBufferEnd(const vk::CommandBuffer &buffer)
Record a timestamp query into the provided cmd buffer to record end time.
void MarkFrameStart()
Signal the start of a frame workload.
void MarkFrameEnd()
Signal the end of a frame workload.
std::unique_ptr< GPUProbe > CreateGPUProbe()
Create a GPUProbe to trace the execution of a command buffer on the GPU.
void InitializeQueryPool(const ContextVK &context)
Initialize the set of query pools.
GPUTracerVK(std::weak_ptr< ContextVK > context, bool enable_gpu_tracing)
#define FML_DCHECK(condition)
static float max(float r, float g, float b)
static float min(float r, float g, float b)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
static constexpr uint32_t kPoolSize
#define FML_TRACE_COUNTER(category_group, name, counter_id, arg1,...)