Toast Engine
Loading...
Searching...
No Matches
gpu_timer.hpp
Go to the documentation of this file.
1
2
3#pragma once
4#include "vulkan_common.hpp"
5
6#include <array>
7#include <chrono>
8#include <cstdint>
9#include <string_view>
10#include <vector>
11
12namespace renderer {
13class VulkanCore;
14
16class GpuTimer {
17public:
18 static constexpr uint32_t k_max_scopes = 64;
19 static constexpr uint32_t k_no_scope = ~uint32_t {0};
20
22 struct ScopeName {
23 std::array<char, 39> chars {};
24 uint8_t length = 0;
25
26 ScopeName() = default;
27 explicit ScopeName(std::string_view text) noexcept;
28
29 [[nodiscard]]
30 auto view() const noexcept -> std::string_view {
31 return {chars.data(), length};
32 }
33 };
34
35 struct ScopeTiming {
36 ScopeName name;
37 uint32_t depth = 0;
38 uint32_t count = 0;
39 double cpu_ms = 0.0;
40 double gpu_ms = 0.0;
41 };
42
43 struct Timings {
44 bool valid = false;
45 double graphics_ms = 0.0;
46 std::vector<ScopeTiming> scopes;
47 };
48
49 GpuTimer(const VulkanCore& core, uint32_t frame_slots);
50
51 [[nodiscard]]
52 auto supported() const noexcept -> bool {
53 return m_supported;
54 }
55
56 void beginGraphics(uint32_t slot, vk::CommandBuffer cmd);
57 void endGraphics(uint32_t slot, vk::CommandBuffer cmd);
58
59 auto beginScope(uint32_t slot, vk::CommandBuffer cmd, std::string_view name) -> uint32_t;
60 void endScope(uint32_t slot, vk::CommandBuffer cmd, uint32_t scope);
61
63 void collect(uint32_t slot);
64
65 [[nodiscard]]
66 auto last() const noexcept -> const Timings& {
67 return m_frame;
68 }
69
71 [[nodiscard]]
72 auto frameSerial() const noexcept -> uint64_t {
73 return m_serial;
74 }
75
76 [[nodiscard]]
77 auto smoothed() const noexcept -> const Timings& {
78 return m_smoothed;
79 }
80
81private:
82 struct PendingScope {
83 ScopeName name;
84 uint32_t depth = 0;
85 std::chrono::steady_clock::time_point cpu_start;
86 double cpu_ms = 0.0;
87 };
88
89 struct Slot {
90 std::vector<PendingScope> scopes;
91 uint32_t depth = 0;
92 bool graphics_written = false;
93 };
94
96 static constexpr uint32_t k_queries_per_slot = 2 + (2 * k_max_scopes);
97
98 [[nodiscard]]
99 static auto base(uint32_t slot) noexcept -> uint32_t {
100 return slot * k_queries_per_slot;
101 }
102
103 [[nodiscard]]
104 auto ticksToMs(uint64_t begin, uint64_t end, uint64_t mask) const noexcept -> double;
105
106 vk::raii::QueryPool m_pool = nullptr;
107 std::vector<Slot> m_slots;
108 double m_ns_per_tick = 1.0;
109 uint64_t m_graphics_mask = ~uint64_t {0};
110 bool m_supported = false;
111 bool m_reported_unavailable = false;
112 uint64_t m_serial = 0;
113
114 Timings m_frame;
115 Timings m_smoothed;
116 Timings m_scratch;
117};
118
119class GpuScope {
120public:
121 GpuScope(GpuTimer* timer, uint32_t slot, vk::CommandBuffer cmd, std::string_view name)
122 : m_timer(timer),
123 m_slot(slot),
124 m_cmd(cmd),
125 m_scope(timer != nullptr ? timer->beginScope(slot, cmd, name) : GpuTimer::k_no_scope) { }
126
127 ~GpuScope() {
128 if (m_timer != nullptr) {
129 m_timer->endScope(m_slot, m_cmd, m_scope);
130 }
131 }
132
133 GpuScope(const GpuScope&) = delete;
134 auto operator=(const GpuScope&) -> GpuScope& = delete;
135 GpuScope(GpuScope&&) = delete;
136 auto operator=(GpuScope&&) -> GpuScope& = delete;
137
138private:
139 GpuTimer* m_timer;
140 uint32_t m_slot;
141 vk::CommandBuffer m_cmd;
142 uint32_t m_scope;
143};
144
145}
Definition gpu_timer.hpp:16
void collect(uint32_t slot)
Definition gpu_timer.cpp:125
auto frameSerial() const noexcept -> uint64_t
Tells a fresh last() from a repeat.
Definition gpu_timer.hpp:72
Definition vulkan_core.hpp:48
Copied since a pass can be destroyed before its frame is read back.
Definition gpu_timer.hpp:22
Definition gpu_timer.hpp:35
Definition gpu_timer.hpp:43