Flutter Impeller
gpu_tracer_vk.h
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_GPU_TRACER_VK_H_
6 #define FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_GPU_TRACER_VK_H_
7 
8 #include <memory>
9 #include <thread>
10 
13 #include "vulkan/vulkan_handles.hpp"
14 
15 namespace impeller {
16 
17 class GPUProbe;
18 
19 /// @brief A class that uses timestamp queries to record the approximate GPU
20 /// execution time.
21 ///
22 /// To enable, add the following metadata to the application's Android manifest:
23 /// <meta-data
24 /// android:name="io.flutter.embedding.android.EnableVulkanGPUTracing"
25 /// android:value="false" />
26 class GPUTracerVK : public std::enable_shared_from_this<GPUTracerVK> {
27  public:
28  GPUTracerVK(std::weak_ptr<ContextVK> context, bool enable_gpu_tracing);
29 
30  ~GPUTracerVK() = default;
31 
32  /// @brief Create a GPUProbe to trace the execution of a command buffer on the
33  /// GPU.
34  std::unique_ptr<GPUProbe> CreateGPUProbe();
35 
36  /// @brief Signal the start of a frame workload.
37  ///
38  /// Any cmd buffers that are created after this call and before
39  /// [MarkFrameEnd] will be attributed to the current frame.
40  void MarkFrameStart();
41 
42  /// @brief Signal the end of a frame workload.
43  void MarkFrameEnd();
44 
45  // visible for testing.
46  bool IsEnabled() const;
47 
48  /// Initialize the set of query pools.
49  void InitializeQueryPool(const ContextVK& context);
50 
51  private:
52  friend class GPUProbe;
53 
54  static const constexpr size_t kTraceStatesSize = 16u;
55 
56  /// @brief Signal that the cmd buffer is completed.
57  ///
58  /// If [frame_index] is std::nullopt, this frame recording is ignored.
59  void OnFenceComplete(size_t frame);
60 
61  /// @brief Record a timestamp query into the provided cmd buffer to record
62  /// start time.
63  void RecordCmdBufferStart(const vk::CommandBuffer& buffer, GPUProbe& probe);
64 
65  /// @brief Record a timestamp query into the provided cmd buffer to record end
66  /// time.
67  void RecordCmdBufferEnd(const vk::CommandBuffer& buffer, GPUProbe& probe);
68 
69  std::weak_ptr<ContextVK> context_;
70 
71  struct GPUTraceState {
72  size_t current_index = 0;
73  size_t pending_buffers = 0;
74  vk::UniqueQueryPool query_pool;
75  };
76 
77  mutable Mutex trace_state_mutex_;
78  GPUTraceState trace_states_[kTraceStatesSize] IPLR_GUARDED_BY(
79  trace_state_mutex_);
80  size_t current_state_ IPLR_GUARDED_BY(trace_state_mutex_) = 0u;
81  std::vector<size_t> IPLR_GUARDED_BY(trace_state_mutex_) states_to_reset_ = {};
82 
83  // The number of nanoseconds for each timestamp unit.
84  float timestamp_period_ = 1;
85 
86  // If in_frame_ is not true, then this cmd buffer was started as a part of
87  // some non-frame workload like image decoding. We should not record this as
88  // part of the frame workload, as the gap between this non-frame and a
89  // frameworkload may be substantial. For example, support the engine creates a
90  // cmd buffer to perform an image upload at timestamp 0 and then 30 ms later
91  // actually renders a frame. Without the in_frame_ guard, the GPU frame time
92  // would include this 30ms gap during which the engine was idle.
93  bool in_frame_ = false;
94 
95  // Track the raster thread id to avoid recording mipmap/image cmd buffers
96  // that are not guaranteed to start/end according to frame boundaries.
97  std::thread::id raster_thread_id_;
98  bool enabled_ = false;
99 };
100 
101 class GPUProbe {
102  public:
103  explicit GPUProbe(const std::weak_ptr<GPUTracerVK>& tracer);
104 
105  GPUProbe(GPUProbe&&) = delete;
107 
108  ~GPUProbe();
109 
110  /// @brief Record a timestamp query into the provided cmd buffer to record
111  /// start time.
112  void RecordCmdBufferStart(const vk::CommandBuffer& buffer);
113 
114  /// @brief Record a timestamp query into the provided cmd buffer to record end
115  /// time.
116  void RecordCmdBufferEnd(const vk::CommandBuffer& buffer);
117 
118  private:
119  friend class GPUTracerVK;
120 
121  std::weak_ptr<GPUTracerVK> tracer_;
122  std::optional<size_t> index_ = std::nullopt;
123 };
124 
125 } // namespace impeller
126 
127 #endif // FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_GPU_TRACER_VK_H_
GPUProbe & operator=(GPUProbe &&)=delete
void RecordCmdBufferStart(const vk::CommandBuffer &buffer)
Record a timestamp query into the provided cmd buffer to record start time.
GPUProbe(GPUProbe &&)=delete
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.
A class that uses timestamp queries to record the approximate GPU execution time.
Definition: gpu_tracer_vk.h:26
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)
bool IsEnabled() const