2#include "imgui/imgui.h"
3#include "imgui_widgets/utils.h"
4#include "monopp/mono_gc_handle.h"
26 constexpr float plot_height = 50.0f;
27 constexpr float max_frame_time_ms = 200.0f;
28 constexpr float max_passes = 200.0f;
29 constexpr float profiler_scale = 3.0f;
30 constexpr float profiler_max_width = 30.0f;
31 constexpr float resource_bar_width = 90.0f;
32 constexpr float megabyte_divisor = 1024.0f * 1024.0f;
35 constexpr ImVec4 cpu_color{0.2f, 0.8f, 0.2f, 1.0f};
36 constexpr ImVec4 gpu_color{0.2f, 0.6f, 1.0f, 1.0f};
37 constexpr ImVec4 warning_color{1.0f, 0.7f, 0.0f, 1.0f};
38 constexpr ImVec4 error_color{1.0f, 0.3f, 0.3f, 1.0f};
41 statistics_utils::sample_data frame_time_samples;
42 statistics_utils::sample_data graphics_passes_samples;
43 statistics_utils::sample_data gpu_memory_samples;
44 statistics_utils::sample_data render_target_memory_samples;
45 statistics_utils::sample_data texture_memory_samples;
70 if(ImGui::Begin(
name,
nullptr, ImGuiWindowFlags_MenuBar))
73 draw_statistics_content();
78auto statistics_panel::draw_menubar(
rtti::context& ctx) ->
void
80 if(ImGui::BeginMenuBar())
84 ImGui::Checkbox(
"Show Editor Stats", &show_editor_stats_);
85 ImGui::SetItemTooltip(
"Show editor/UI related draw calls and triangles\n(Focus on scene stats when disabled)");
92 if(ImGui::Checkbox(
"Static Mesh Batching", &batching_enabled))
96 ImGui::SetItemTooltip(
"Enable/disable static mesh batching for performance comparison");
103auto statistics_panel::draw_statistics_content() ->
void
105 const auto& io = ImGui::GetIO();
106 const auto area = ImGui::GetContentRegionAvail();
107 const float overlay_width = area.x;
110 update_sample_data();
113 draw_frame_statistics(overlay_width);
114 draw_profiler_section();
115 draw_memory_info_section(overlay_width);
116 draw_resources_section();
119auto statistics_panel::draw_frame_statistics(
float overlay_width) ->
void
122 const auto& io = ImGui::GetIO();
124 const double to_cpu_ms = 1000.0 /
static_cast<double>(
stats->cpuTimerFreq);
125 const double to_gpu_ms = 1000.0 /
static_cast<double>(
stats->gpuTimerFreq);
128 if(ImGui::CollapsingHeader(
ICON_MDI_CHART_LINE "\tPerformance Overview", ImGuiTreeNodeFlags_DefaultOpen))
133 const float avg_frame_time = frame_time_samples.get_average();
134 const float fps = 1000.0f / avg_frame_time;
137 ImVec4 fps_color = cpu_color;
140 fps_color = error_color;
144 fps_color = warning_color;
148 ImGui::BeginColumns(
"PerformanceColumns", 2, ImGuiOldColumnFlags_NoResize);
149 ImGui::SetColumnWidth(0, overlay_width * 0.5f);
151 ImGui::Text(
"Frame Time:");
152 ImGui::Text(
" Average: %.3f ms", avg_frame_time);
153 ImGui::Text(
" Min/Max: %.3f / %.3f ms", frame_time_samples.get_min(), frame_time_samples.get_max());
157 ImGui::TextColored(fps_color,
"FPS: %.1f", fps);
161 ImGui::TextColored(warning_color, fps < 30.0f ?
" (Poor)" :
" (Low)");
165 if(
stats->gpuMemoryUsed > 0)
167 std::array<char, 64> gpu_used_str;
168 bx::prettify(gpu_used_str.data(), gpu_used_str.size(),
stats->gpuMemoryUsed);
170 ImGui::Text(
"GPU Memory:");
172 if(
stats->gpuMemoryMax > 0)
175 const float gpu_usage_percentage = (
static_cast<float>(
stats->gpuMemoryUsed) /
static_cast<float>(
stats->gpuMemoryMax)) * 100.0f;
178 ImVec4 gpu_memory_color = cpu_color;
179 if(gpu_usage_percentage > 80.0f)
181 gpu_memory_color = error_color;
183 else if(gpu_usage_percentage > 60.0f)
185 gpu_memory_color = warning_color;
188 std::array<char, 64> gpu_max_str;
189 bx::prettify(gpu_max_str.data(), gpu_max_str.size(),
stats->gpuMemoryMax);
191 ImGui::Text(
"%s / %s", gpu_used_str.data(), gpu_max_str.data());
193 ImGui::TextColored(gpu_memory_color,
"(%.1f%%)", gpu_usage_percentage);
198 ImGui::Text(
"%s used", gpu_used_str.data());
200 ImGui::TextColored(warning_color,
"(max unknown)");
205 ImGui::Text(
"GPU Memory:");
206 ImGui::TextColored(warning_color,
"No data available");
212 std::array<char, 256> frame_text_overlay;
213 bx::snprintf(frame_text_overlay.data(),
214 frame_text_overlay.size(),
215 "Performance: %.1f FPS (%.3f ms avg)\nRange: %.3f - %.3f ms",
217 frame_time_samples.get_min(),
218 frame_time_samples.get_max());
220 ImGui::SetNextWindowViewportToCurrent();
221 ImGui::PlotLines(
"##FrameTime",
222 frame_time_samples.get_values(),
224 frame_time_samples.get_offset(),
225 frame_text_overlay.data(),
228 ImVec2(overlay_width, plot_height));
233 const auto submit_cpu_ms =
static_cast<double>(
stats->cpuTimeEnd -
stats->cpuTimeBegin) * to_cpu_ms;
234 const auto submit_gpu_ms =
static_cast<double>(
stats->gpuTimeEnd -
stats->gpuTimeBegin) * to_gpu_ms;
236 ImGui::BeginColumns(
"TimingColumns", 4, ImGuiOldColumnFlags_NoResize);
237 ImGui::SetColumnWidth(0, overlay_width * 0.25f);
238 ImGui::SetColumnWidth(1, overlay_width * 0.25f);
239 ImGui::SetColumnWidth(2, overlay_width * 0.25f);
241 ImGui::TextColored(cpu_color,
"CPU Submit");
242 ImGui::Text(
"%.3f ms", submit_cpu_ms);
245 ImGui::TextColored(gpu_color,
"GPU Submit");
246 ImGui::Text(
"%.3f ms", submit_gpu_ms);
249 ImGui::Text(
"GPU Latency");
250 ImGui::Text(
"%d frames",
stats->maxGpuLatency);
253 ImGui::Text(
"Draw Calls");
255 std::uint32_t scene_calls = 0, editor_calls = 0, total_calls = 0;
256 get_draw_call_breakdown(stats, scene_calls, editor_calls, total_calls);
258 if(show_editor_stats_)
260 ImGui::Text(
"%u total", total_calls);
264 ImGui::Text(
"%u scene", scene_calls);
273 if(ImGui::CollapsingHeader(
ICON_MDI_CUBE_OUTLINE "\tRendering Statistics", ImGuiTreeNodeFlags_DefaultOpen))
282 draw_call_counts(stats, io);
287 draw_primitive_counts(stats, io);
290 draw_pipeline_stats();
297auto statistics_panel::draw_pipeline_stats() ->
void
299 if(ImGui::CollapsingHeader(
ICON_MDI_CUBE_OUTLINE "\tPipeline Statistics", ImGuiTreeNodeFlags_DefaultOpen))
308 scn->registry->view<camera_component>().each([&](
auto e,
auto&& camera_comp)
310 auto& pipeline = camera_comp.get_pipeline_data().get_pipeline();
311 const auto&
stats = pipeline->get_stats();
312 if(!
stats.anything_drawn())
317 ImGui::Text(
"Pipeline Stats for %s:", scn->tag.c_str());
320 ImGui::Text(
"Drawn Particles: %u",
stats.drawn_particles);
321 ImGui::Text(
"Drawn Particles Batches: %u",
stats.drawn_particles_batches);
322 ImGui::Text(
"Drawn Models: %u",
stats.drawn_models);
323 ImGui::Text(
"Drawn Skinned Models: %u",
stats.drawn_skinned_models);
324 ImGui::Text(
"Drawn Lights: %u",
stats.drawn_lights);
325 ImGui::Text(
"Drawn Lights Casting Shadows: %u",
stats.drawn_lights_casting_shadows);
328 if(
stats.batching_stats.total_batches > 0 ||
stats.batching_stats.total_instances > 0)
331 ImGui::Text(
"Static Mesh Batching:");
334 const auto& batch_stats =
stats.batching_stats;
335 ImGui::Text(
"Total Batches: %u", batch_stats.total_batches);
336 ImGui::Text(
"Total Instances: %u", batch_stats.total_instances);
337 ImGui::Text(
"Avg Batch Size: %.1f", batch_stats.average_batch_size);
338 ImGui::Text(
"Batching Efficiency: %.1f%%", batch_stats.batching_efficiency * 100.0f);
340 if(batch_stats.split_batches > 0)
342 ImGui::TextColored(ImVec4(1.0f, 0.7f, 0.0f, 1.0f),
"Split Batches: %u", batch_stats.split_batches);
346 if(batch_stats.collection_time_ms > 0.0f || batch_stats.preparation_time_ms > 0.0f)
348 ImGui::Text(
"Collection Time: %.3f ms", batch_stats.collection_time_ms);
349 ImGui::Text(
"Preparation Time: %.3f ms", batch_stats.preparation_time_ms);
350 ImGui::Text(
"Submission Time: %.3f ms", batch_stats.submission_time_ms);
354 if(batch_stats.instance_buffer_memory_used > 0)
356 float memory_mb =
static_cast<float>(batch_stats.instance_buffer_memory_used) / (1024.0f * 1024.0f);
357 ImGui::Text(
"Instance Buffer Memory: %.2f MB", memory_mb);
369auto statistics_panel::draw_profiler_section() ->
void
379 ImGui::Text(
"CPU Profiler:");
380 draw_app_profiler_data();
385 ImGui::AlignTextToFramePadding();
386 ImGui::Text(
"GPU Profiler:");
389 if(ImGui::Checkbox(
"Enable##GPUProfiler", &enable_gpu_profiler_))
391 if(enable_gpu_profiler_)
402 if(enable_gpu_profiler_)
406 if(
stats->numViews == 0)
408 ImGui::TextColored(warning_color,
"No GPU profiling data available.");
409 ImGui::Text(
"Profiler may be initializing...");
413 ImGui::Text(
"GPU Timing (per view/encoder):");
414 draw_profiler_bars(stats);
419 ImGui::TextColored(warning_color,
"GPU profiler is disabled.");
420 ImGui::Text(
"Enable to see detailed GPU timing information.");
426auto statistics_panel::draw_memory_info_section(
float overlay_width) ->
void
437 std::array<char, 64> str_max;
438 bx::prettify(str_max.data(), str_max.size(),
static_cast<uint64_t
>(mono::gc_get_heap_size()));
440 std::array<char, 64> str_used;
441 bx::prettify(str_used.data(), str_used.size(), mono::gc_get_used_size());
443 ImGui::TextUnformatted(fmt::format(
"GC Heap Size: {}", str_max.data()).c_str());
444 ImGui::TextUnformatted(fmt::format(
"GC Used Size: {}", str_used.data()).c_str());
448 if(ImGui::Button(
"Collect GC"))
455 auto gpu_memory_max =
stats->gpuMemoryMax;
458 if(
stats->gpuMemoryUsed > 0)
460 draw_gpu_memory_section(stats, gpu_memory_max, overlay_width);
464 ImGui::TextColored(warning_color,
"No GPU memory usage data available");
468 draw_render_target_memory_section(stats, gpu_memory_max, overlay_width);
471 draw_texture_memory_section(stats, gpu_memory_max, overlay_width);
477auto statistics_panel::draw_resources_section() ->
void
486 const float item_height = ImGui::GetTextLineHeightWithSpacing();
490 ImGui::Text(
"Resource Usage (Current / Maximum):");
494 ImGui::Text(
"Buffers:");
497 using namespace statistics_utils;
499 stats->transientIbUsed,
caps->limits.transientIbSize,
500 resource_bar_width, item_height);
503 stats->transientVbUsed,
caps->limits.transientVbSize,
504 resource_bar_width, item_height);
507 stats->numDynamicIndexBuffers,
caps->limits.maxDynamicIndexBuffers,
508 resource_bar_width, item_height);
511 stats->numDynamicVertexBuffers,
caps->limits.maxDynamicVertexBuffers,
512 resource_bar_width, item_height);
515 stats->numIndexBuffers,
caps->limits.maxIndexBuffers,
516 resource_bar_width, item_height);
519 stats->numVertexBuffers,
caps->limits.maxVertexBuffers,
520 resource_bar_width, item_height);
525 ImGui::Text(
"Shading:");
529 stats->numPrograms,
caps->limits.maxPrograms,
530 resource_bar_width, item_height);
533 stats->numShaders,
caps->limits.maxShaders,
534 resource_bar_width, item_height);
537 stats->numUniforms,
caps->limits.maxUniforms,
538 resource_bar_width, item_height);
543 ImGui::Text(
"Rendering:");
547 stats->numTextures,
caps->limits.maxTextures,
548 resource_bar_width, item_height);
551 stats->numFrameBuffers,
caps->limits.maxFrameBuffers,
552 resource_bar_width, item_height);
555 stats->numVertexLayouts,
caps->limits.maxVertexLayouts,
556 resource_bar_width, item_height);
559 stats->numOcclusionQueries,
caps->limits.maxOcclusionQueries,
560 resource_bar_width, item_height);
568auto statistics_panel::update_sample_data() ->
void
571 const double to_cpu_ms = 1000.0 /
static_cast<double>(
stats->cpuTimerFreq);
572 const double frame_ms =
static_cast<double>(
stats->cpuTimeFrame) * to_cpu_ms;
574 frame_time_samples.push_sample(
static_cast<float>(frame_ms));
576 gpu_memory_samples.push_sample(
static_cast<float>(
stats->gpuMemoryUsed) / megabyte_divisor);
577 render_target_memory_samples.push_sample(
static_cast<float>(
stats->rtMemoryUsed) / megabyte_divisor);
578 texture_memory_samples.push_sample(
static_cast<float>(
stats->textureMemoryUsed) / megabyte_divisor);
581auto statistics_panel::get_draw_call_breakdown(
const gfx::stats* stats, std::uint32_t& scene_calls, std::uint32_t& editor_calls, std::uint32_t& total_calls) ->
void
583 const ImGuiIO& io = ImGui::GetIO();
584 total_calls =
stats->numDraw;
586 editor_calls = std::min(editor_calls, total_calls);
587 scene_calls = total_calls - editor_calls;
590auto statistics_panel::draw_primitive_counts(
const gfx::stats* stats,
const ImGuiIO& io) ->
void
592 const std::uint32_t total_primitives = std::accumulate(std::begin(
stats->numPrims), std::end(
stats->numPrims), 0u);
593 std::uint32_t ui_primitives = io.MetricsRenderIndices / 3;
594 ui_primitives = std::min(ui_primitives, total_primitives);
595 const auto scene_primitives = total_primitives - ui_primitives;
597 ImGui::Text(
"Triangle Counts:");
600 if(show_editor_stats_)
603 ImGui::BeginColumns(
"PrimitiveColumns", 2, ImGuiOldColumnFlags_NoResize);
604 ImGui::SetColumnWidth(0, 120.0f);
606 ImGui::Text(
"Scene:");
608 ImGui::TextColored(cpu_color,
"%u triangles", scene_primitives);
611 ImGui::Text(
"Editor:");
613 ImGui::TextColored(gpu_color,
"%u triangles", ui_primitives);
616 ImGui::Text(
"Total:");
618 ImGui::Text(
"%u triangles", total_primitives);
625 ImGui::TextColored(cpu_color,
"Scene: %u triangles", scene_primitives);
631auto statistics_panel::draw_call_counts(
const gfx::stats* stats,
const ImGuiIO& io) ->
void
633 std::uint32_t scene_calls = 0, editor_calls = 0, total_calls = 0;
634 get_draw_call_breakdown(stats, scene_calls, editor_calls, total_calls);
636 ImGui::Text(
"GPU Commands:");
639 if(show_editor_stats_)
642 ImGui::BeginColumns(
"CallCountColumns", 2, ImGuiOldColumnFlags_NoResize);
643 ImGui::SetColumnWidth(0, 120.0f);
646 ImGui::Text(
"Draw Calls:");
648 ImGui::Text(
"%u total", total_calls);
651 ImGui::Text(
" Scene:");
653 ImGui::TextColored(cpu_color,
"%u calls", scene_calls);
656 ImGui::Text(
" Editor:");
658 ImGui::TextColored(gpu_color,
"%u calls", editor_calls);
662 ImGui::Text(
"Compute:");
664 ImGui::Text(
"%u calls",
stats->numCompute);
667 ImGui::Text(
"Blit:");
669 ImGui::Text(
"%u calls",
stats->numBlit);
676 ImGui::TextColored(cpu_color,
"Scene Draw Calls: %u", scene_calls);
679 if(
stats->numCompute > 0 ||
stats->numBlit > 0)
681 ImGui::BeginColumns(
"SceneCallColumns", 2, ImGuiOldColumnFlags_NoResize);
682 ImGui::SetColumnWidth(0, 120.0f);
684 if(
stats->numCompute > 0)
686 ImGui::Text(
"Compute:");
688 ImGui::Text(
"%u calls",
stats->numCompute);
692 if(
stats->numBlit > 0)
694 ImGui::Text(
"Blit:");
696 ImGui::Text(
"%u calls",
stats->numBlit);
707auto statistics_panel::draw_profiler_bars(
const gfx::stats* stats) ->
void
709 const float item_height = ImGui::GetTextLineHeightWithSpacing();
710 const float item_height_with_spacing = ImGui::GetFrameHeightWithSpacing();
711 const double to_cpu_ms = 1000.0 /
static_cast<double>(
stats->cpuTimerFreq);
712 const double to_gpu_ms = 1000.0 /
static_cast<double>(
stats->gpuTimerFreq);
715 draw_encoder_stats(stats, item_height, item_height_with_spacing, to_cpu_ms);
720 draw_view_stats(stats, item_height, item_height_with_spacing, to_cpu_ms, to_gpu_ms);
723auto statistics_panel::draw_encoder_stats(
const gfx::stats* stats,
float item_height,
float item_height_with_spacing,
double to_cpu_ms) ->
void
725 if(ImGui::BeginListBox(
"Encoders", ImVec2(ImGui::GetWindowWidth(),
stats->numEncoders * item_height_with_spacing)))
727 ImGuiListClipper clipper;
728 clipper.Begin(
stats->numEncoders, item_height);
730 while(clipper.Step())
732 for(int32_t pos = clipper.DisplayStart; pos < clipper.DisplayEnd; ++pos)
734 const bgfx::EncoderStats& encoder_stats =
stats->encoderStats[pos];
736 ImGui::Text(
"%3d", pos);
737 ImGui::SameLine(64.0f);
739 const float max_width = profiler_max_width * profiler_scale;
740 const float cpu_ms =
static_cast<float>((encoder_stats.cpuTimeEnd - encoder_stats.cpuTimeBegin) * to_cpu_ms);
741 const float cpu_width = bx::clamp(cpu_ms * profiler_scale, 1.0f, max_width);
745 ImGui::SetItemTooltipEx(
"Encoder %d, CPU: %f [ms]", pos, cpu_ms);
755auto statistics_panel::draw_view_stats(
const gfx::stats* stats,
float item_height,
float item_height_with_spacing,
double to_cpu_ms,
double to_gpu_ms) ->
void
757 if(ImGui::BeginListBox(
"Views", ImVec2(ImGui::GetWindowWidth(),
stats->numViews * item_height_with_spacing)))
759 ImGuiListClipper clipper;
760 clipper.Begin(
stats->numViews, item_height);
762 while(clipper.Step())
764 for(int32_t pos = clipper.DisplayStart; pos < clipper.DisplayEnd; ++pos)
766 const bgfx::ViewStats& view_stats =
stats->viewStats[pos];
767 ImGui::PushID(view_stats.view);
768 ImGui::Text(
"%3d %3d %s", pos, view_stats.view, view_stats.name);
770 const float max_width = profiler_max_width * profiler_scale;
771 const float cpu_time_elapsed =
static_cast<float>((view_stats.cpuTimeEnd - view_stats.cpuTimeBegin) * to_cpu_ms);
772 const float gpu_time_elapsed =
static_cast<float>((view_stats.gpuTimeEnd - view_stats.gpuTimeBegin) * to_gpu_ms);
773 const float cpu_width = bx::clamp(cpu_time_elapsed * profiler_scale, 1.0f, max_width);
774 const float gpu_width = bx::clamp(gpu_time_elapsed * profiler_scale, 1.0f, max_width);
776 ImGui::SameLine(64.0f);
778 ImGui::PushID(
"cpu");
781 ImGui::SetItemTooltipEx(
"View %d \"%s\", CPU: %f [ms]", pos, view_stats.name, cpu_time_elapsed);
787 ImGui::PushID(
"gpu");
790 ImGui::SetItemTooltipEx(
"View: %d \"%s\", GPU: %f [ms]", pos, view_stats.name, gpu_time_elapsed);
801auto statistics_panel::draw_app_profiler_data() ->
void
804 const auto& data = profiler->get_per_frame_data_read();
806 for(
const auto& [
name, per_frame_data] : data)
808 ImGui::TextUnformatted(
809 fmt::format(
"{:>7.3f}ms [{:^5}] - {}",
811 per_frame_data.samples,
812 fmt::string_view(
name.data(),
name.size())).c_str());
816auto statistics_panel::draw_gpu_memory_section(
const gfx::stats* stats, int64_t& gpu_memory_max,
float overlay_width) ->
void
818 gpu_memory_max = std::max(
stats->gpuMemoryUsed,
stats->gpuMemoryMax);
820 std::array<char, 64> str_max;
821 bx::prettify(str_max.data(), str_max.size(),
static_cast<uint64_t
>(gpu_memory_max));
823 std::array<char, 64> str_used;
824 bx::prettify(str_used.data(), str_used.size(),
stats->gpuMemoryUsed);
826 const float usage_percentage = gpu_memory_max > 0 ?
827 (
static_cast<float>(
stats->gpuMemoryUsed) /
static_cast<float>(gpu_memory_max)) * 100.0f : 0.0f;
830 ImVec4 usage_color = cpu_color;
831 if(usage_percentage > 80.0f)
833 usage_color = error_color;
835 else if(usage_percentage > 60.0f)
837 usage_color = warning_color;
841 ImGui::Text(
"General GPU Memory:");
843 ImGui::Text(
"Usage: %s / %s", str_used.data(), str_max.data());
845 ImGui::TextColored(usage_color,
"(%.1f%%)", usage_percentage);
847 ImGui::SetNextWindowViewportToCurrent();
848 ImGui::PlotLines(
"##GPUMemory",
849 gpu_memory_samples.get_values(),
851 gpu_memory_samples.get_offset(),
852 "GPU Memory Usage Over Time",
854 static_cast<float>(gpu_memory_max),
855 ImVec2(overlay_width, plot_height));
859auto statistics_panel::draw_render_target_memory_section(
const gfx::stats* stats, int64_t& gpu_memory_max,
float overlay_width) ->
void
861 gpu_memory_max = std::max(
stats->rtMemoryUsed, gpu_memory_max);
863 std::array<char, 64> str_max;
864 bx::prettify(str_max.data(), str_max.size(),
static_cast<uint64_t
>(gpu_memory_max));
866 std::array<char, 64> str_used;
867 bx::prettify(str_used.data(), str_used.size(),
stats->rtMemoryUsed);
869 const float usage_percentage = gpu_memory_max > 0 ?
870 (
static_cast<float>(
stats->rtMemoryUsed) /
static_cast<float>(gpu_memory_max)) * 100.0f : 0.0f;
873 ImVec4 usage_color = cpu_color;
874 if(usage_percentage > 80.0f)
876 usage_color = error_color;
878 else if(usage_percentage > 60.0f)
880 usage_color = warning_color;
884 ImGui::Text(
"Render Target Memory:");
886 ImGui::Text(
"Usage: %s / %s", str_used.data(), str_max.data());
888 ImGui::TextColored(usage_color,
"(%.1f%%)", usage_percentage);
890 ImGui::SetNextWindowViewportToCurrent();
891 ImGui::PlotLines(
"##RenderTargetMemory",
892 render_target_memory_samples.get_values(),
894 render_target_memory_samples.get_offset(),
895 "Render Target Memory Usage Over Time",
897 static_cast<float>(gpu_memory_max),
898 ImVec2(overlay_width, plot_height));
902auto statistics_panel::draw_texture_memory_section(
const gfx::stats* stats, int64_t& gpu_memory_max,
float overlay_width) ->
void
904 gpu_memory_max = std::max(
stats->textureMemoryUsed, gpu_memory_max);
906 std::array<char, 64> str_max;
907 bx::prettify(str_max.data(), str_max.size(),
static_cast<uint64_t
>(gpu_memory_max));
909 std::array<char, 64> str_used;
910 bx::prettify(str_used.data(), str_used.size(),
stats->textureMemoryUsed);
912 const float usage_percentage = gpu_memory_max > 0 ?
913 (
static_cast<float>(
stats->textureMemoryUsed) /
static_cast<float>(gpu_memory_max)) * 100.0f : 0.0f;
916 ImVec4 usage_color = cpu_color;
917 if(usage_percentage > 80.0f)
919 usage_color = error_color;
921 else if(usage_percentage > 60.0f)
923 usage_color = warning_color;
927 ImGui::Text(
"Texture Memory:");
929 ImGui::Text(
"Usage: %s / %s", str_used.data(), str_max.data());
931 ImGui::TextColored(usage_color,
"(%.1f%%)", usage_percentage);
933 ImGui::SetNextWindowViewportToCurrent();
934 ImGui::PlotLines(
"##TextureMemory",
935 texture_memory_samples.get_values(),
937 texture_memory_samples.get_offset(),
938 "Texture Memory Usage Over Time",
940 static_cast<float>(gpu_memory_max),
941 ImVec2(overlay_width, plot_height));
static void set_static_mesh_batching_enabled(bool enabled)
Enable or disable static mesh batching globally.
static auto is_static_mesh_batching_enabled() -> bool
Check if static mesh batching is enabled globally.
auto on_frame_ui_render(rtti::context &ctx, const char *name) -> void
Render the statistics panel UI.
auto on_frame_update(rtti::context &ctx, delta_t dt) -> void
Update the statistics panel logic each frame.
auto deinit(rtti::context &ctx) -> void
Deinitialize the statistics panel and clean up resources.
auto init(rtti::context &ctx) -> void
Initialize the statistics panel.
auto on_frame_render(rtti::context &ctx, delta_t dt) -> void
Render the statistics panel each frame.
static constexpr uint32_t NUM_SAMPLES
std::chrono::duration< float > delta_t
#define ICON_MDI_CLOCK_OUTLINE
#define ICON_MDI_CUBE_OUTLINE
#define ICON_MDI_CHART_LINE
#define ICON_MDI_ARROW_DOWN_BOLD
#define ICON_MDI_INFORMATION
void PushFont(Font::Enum _font)
void set_debug(uint32_t _debug)
const stats * get_stats()
auto draw_resource_bar(const char *name, const char *tooltip, uint32_t current_value, uint32_t max_value, float max_width, float height) -> void
Draw a resource usage bar with label and percentage.
auto draw_progress_bar(float width, float max_width, float height, const ImVec4 &color) -> bool
Draw a colored progress bar with hover effects.
auto get_app_profiler() -> performance_profiler *
static auto get_last_frame_max_pass_id() -> gfx::view_id
static auto get_all_scenes() -> const std::vector< scene * > &