Unravel Engine C++ Reference
Loading...
Searching...
No Matches
profiler_gpu_resources_section.cpp
Go to the documentation of this file.
2
5#include <graphics/graphics.h>
6#include <imgui/imgui.h>
7#include <imgui_widgets/tooltips.h>
8
9#include <algorithm>
10#include <array>
11#include <cstdint>
12#include <cstdio>
13
14namespace unravel
15{
16
17namespace
18{
19constexpr ImVec4 usage_low_color{0.27f, 0.72f, 0.42f, 1.0f}; // green
20constexpr ImVec4 usage_medium_color{0.93f, 0.74f, 0.20f, 1.0f}; // amber
21constexpr ImVec4 usage_high_color{0.90f, 0.32f, 0.28f, 1.0f}; // red
22constexpr ImVec4 category_text_color{0.62f, 0.80f, 1.0f, 1.0f};
23constexpr ImVec4 muted_text_color{0.55f, 0.55f, 0.55f, 1.0f};
24
25constexpr float usage_medium_threshold = 0.60f;
26constexpr float usage_high_threshold = 0.85f;
27constexpr float bar_height_scale = 0.72f;
28
29enum class resource_unit : uint8_t
30{
31 count,
32 bytes
33};
34
35auto pick_usage_color(float fraction) -> ImVec4
36{
37 if(fraction >= usage_high_threshold)
38 {
39 return usage_high_color;
40 }
41 if(fraction >= usage_medium_threshold)
42 {
43 return usage_medium_color;
44 }
45 return usage_low_color;
46}
47
48void format_count(uint64_t value, char* buffer, size_t buffer_size)
49{
50 std::array<char, 32> digits{};
51 const int written = std::snprintf(digits.data(), digits.size(), "%llu", static_cast<unsigned long long>(value));
52 if(written <= 0)
53 {
54 std::snprintf(buffer, buffer_size, "0");
55 return;
56 }
57 size_t out = 0;
58 for(int read = 0; read < written && out + 1 < buffer_size; ++read)
59 {
60 if(read > 0 && ((written - read) % 3) == 0)
61 {
62 buffer[out++] = ',';
63 }
64 if(out + 1 < buffer_size)
65 {
66 buffer[out++] = digits[static_cast<size_t>(read)];
67 }
68 }
69 buffer[out] = '\0';
70}
71
72void format_value(uint64_t value, resource_unit unit, char* buffer, size_t buffer_size)
73{
74 if(unit == resource_unit::bytes)
75 {
76 unravel::format_bytes(value, buffer, buffer_size);
77 return;
78 }
79 format_count(value, buffer, buffer_size);
80}
81
82void draw_right_aligned_text(const char* text, const ImVec4* color = nullptr)
83{
84 const float available_width = ImGui::GetContentRegionAvail().x;
85 const float text_width = ImGui::CalcTextSize(text).x;
86 const float offset = available_width - text_width;
87 if(offset > 0.0f)
88 {
89 ImGui::SetCursorPosX(ImGui::GetCursorPosX() + offset);
90 }
91 if(color != nullptr)
92 {
93 ImGui::TextColored(*color, "%s", text);
94 return;
95 }
96 ImGui::TextUnformatted(text);
97}
98
99void draw_category_row(const char* icon, const char* label)
100{
101 ImGui::TableNextRow();
102 ImGui::TableSetColumnIndex(0);
103 const ImU32 background = ImGui::GetColorU32(ImVec4(0.16f, 0.20f, 0.27f, 1.0f));
104 ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0, background);
105 ImGui::AlignTextToFramePadding();
106 ImGui::TextColored(category_text_color, "%s %s", icon, label);
107}
108
109void draw_resource_row(const char* name,
110 const char* description,
111 uint64_t current_value,
112 uint64_t max_value,
113 resource_unit unit)
114{
115 ImGui::PushID(name);
116 ImGui::TableNextRow();
117
118 ImGui::TableSetColumnIndex(0);
119 ImGui::AlignTextToFramePadding();
120 ImGui::TextUnformatted(name);
121 ImGui::SetItemTooltipEx("%s", description);
122
123 std::array<char, 32> used_buffer{};
124 format_value(current_value, unit, used_buffer.data(), used_buffer.size());
125 ImGui::TableSetColumnIndex(1);
126 ImGui::AlignTextToFramePadding();
127 draw_right_aligned_text(used_buffer.data());
128
129 ImGui::TableSetColumnIndex(2);
130 ImGui::AlignTextToFramePadding();
131 if(max_value == 0)
132 {
133 draw_right_aligned_text("--", &muted_text_color);
134 }
135 else
136 {
137 std::array<char, 32> max_buffer{};
138 format_value(max_value, unit, max_buffer.data(), max_buffer.size());
139 draw_right_aligned_text(max_buffer.data());
140 }
141
142 ImGui::TableSetColumnIndex(3);
143 if(max_value == 0)
144 {
145 draw_right_aligned_text("n/a", &muted_text_color);
146 ImGui::PopID();
147 return;
148 }
149 const float fraction =
150 std::clamp(static_cast<float>(current_value) / static_cast<float>(max_value), 0.0f, 1.0f);
151 std::array<char, 16> overlay{};
152 std::snprintf(overlay.data(), overlay.size(), "%.1f%%", static_cast<double>(fraction * 100.0f));
153 ImGui::PushStyleColor(ImGuiCol_PlotHistogram, pick_usage_color(fraction));
154 ImGui::ProgressBar(fraction, ImVec2(-1.0f, ImGui::GetFrameHeight() * bar_height_scale), overlay.data());
155 ImGui::PopStyleColor();
156 ImGui::SetItemTooltipEx("%s: %.2f%% used", description, static_cast<double>(fraction * 100.0f));
157
158 ImGui::PopID();
159}
160} // namespace
161
163{
164 if(!ImGui::CollapsingHeader(ICON_MDI_PUZZLE "\tGPU Resources"))
165 {
166 return;
167 }
168 const auto* caps = gfx::get_caps();
169 const auto* stats = gfx::get_stats();
170 if(caps == nullptr || stats == nullptr)
171 {
172 return;
173 }
174
175 constexpr ImGuiTableFlags table_flags = ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersInnerV |
176 ImGuiTableFlags_BordersOuter | ImGuiTableFlags_PadOuterX |
177 ImGuiTableFlags_NoBordersInBodyUntilResize;
178 if(!ImGui::BeginTable("##gpu_resources", 4, table_flags))
179 {
180 return;
181 }
182
183 ImGui::TableSetupColumn("Resource", ImGuiTableColumnFlags_WidthStretch, 0.9f);
184 ImGui::TableSetupColumn("Used", ImGuiTableColumnFlags_WidthFixed, 96.0f);
185 ImGui::TableSetupColumn("Limit", ImGuiTableColumnFlags_WidthFixed, 96.0f);
186 ImGui::TableSetupColumn("Usage", ImGuiTableColumnFlags_WidthStretch, 1.6f);
187 ImGui::TableHeadersRow();
188
189 draw_category_row(ICON_MDI_DATABASE, "Buffers");
190 draw_resource_row("Transient Index Buffer",
191 "GPU memory used by transient index buffers this frame.",
192 static_cast<uint64_t>(stats->transientIbUsed),
193 caps->limits.maxTransientIbSize,
194 resource_unit::bytes);
195 draw_resource_row("Transient Vertex Buffer",
196 "GPU memory used by transient vertex buffers this frame.",
197 static_cast<uint64_t>(stats->transientVbUsed),
198 caps->limits.maxTransientVbSize,
199 resource_unit::bytes);
200 draw_resource_row("Dynamic Index Buffers",
201 "Number of dynamic index buffers currently allocated.",
202 stats->numDynamicIndexBuffers,
203 caps->limits.maxDynamicIndexBuffers,
204 resource_unit::count);
205 draw_resource_row("Dynamic Vertex Buffers",
206 "Number of dynamic vertex buffers currently allocated.",
207 stats->numDynamicVertexBuffers,
208 caps->limits.maxDynamicVertexBuffers,
209 resource_unit::count);
210 draw_resource_row("Index Buffers",
211 "Number of static index buffers currently allocated.",
212 stats->numIndexBuffers,
213 caps->limits.maxIndexBuffers,
214 resource_unit::count);
215 draw_resource_row("Vertex Buffers",
216 "Number of static vertex buffers currently allocated.",
217 stats->numVertexBuffers,
218 caps->limits.maxVertexBuffers,
219 resource_unit::count);
220
221 draw_category_row(ICON_MDI_CODE_BRACES, "Shading");
222 draw_resource_row("Shader Programs",
223 "Number of linked shader programs currently allocated.",
224 stats->numPrograms,
225 caps->limits.maxPrograms,
226 resource_unit::count);
227 draw_resource_row("Shaders",
228 "Number of compiled shaders currently allocated.",
229 stats->numShaders,
230 caps->limits.maxShaders,
231 resource_unit::count);
232 draw_resource_row("Uniforms",
233 "Number of uniform handles currently allocated.",
234 stats->numUniforms,
235 caps->limits.maxUniforms,
236 resource_unit::count);
237
238 draw_category_row(ICON_MDI_MONITOR, "Rendering");
239 draw_resource_row("Textures",
240 "Number of textures currently allocated.",
241 stats->numTextures,
242 caps->limits.maxTextures,
243 resource_unit::count);
244 draw_resource_row("Frame Buffers",
245 "Number of frame buffers currently allocated.",
246 stats->numFrameBuffers,
247 caps->limits.maxFrameBuffers,
248 resource_unit::count);
249 draw_resource_row("Vertex Layouts",
250 "Number of vertex layouts currently allocated.",
251 stats->numVertexLayouts,
252 caps->limits.maxVertexLayouts,
253 resource_unit::count);
254 draw_resource_row("Occlusion Queries",
255 "Number of occlusion queries currently allocated.",
256 stats->numOcclusionQueries,
257 caps->limits.maxOcclusionQueries,
258 resource_unit::count);
259
260 draw_category_row(ICON_MDI_MEMORY, "Estimated Memory");
261 draw_resource_row("Texture Memory",
262 "Estimated GPU memory used by textures.",
263 static_cast<uint64_t>(std::max<int64_t>(0, stats->textureMemoryUsed)),
264 0,
265 resource_unit::bytes);
266 draw_resource_row("Render Target Memory",
267 "Estimated GPU memory used by render targets.",
268 static_cast<uint64_t>(std::max<int64_t>(0, stats->rtMemoryUsed)),
269 0,
270 resource_unit::bytes);
271
272 ImGui::EndTable();
273}
274
275} // namespace unravel
btScalar fraction
const char * description
const char * icon
std::uint64_t bytes
Definition eviction.cpp:823
std::string name
Definition hub.cpp:33
#define ICON_MDI_MONITOR
#define ICON_MDI_PUZZLE
#define ICON_MDI_DATABASE
#define ICON_MDI_MEMORY
#define ICON_MDI_CODE_BRACES
const stats * get_stats()
Definition graphics.cpp:450
const caps * get_caps()
Definition graphics.cpp:445
auto format_bytes(std::uint64_t bytes, std::uint8_t num_frac) -> std::string
std::vector< math::color > color