Skip to main content

FpsWidget.ixx File

ImGui widget for displaying and configuring FPS metrics and frame pacing. More...

Included Headers

#include <vector> #include <string> #include "imgui.h" #include <helios.engine.tooling.FrameStats> #include <helios.engine.tooling.FramePacer> #include <helios.engine.tooling.FpsMetrics> #include <helios.ext.imgui.ImGuiWidget>

Namespaces Index

namespacehelios
namespaceext

Platform-specific extensions and backend implementations. More...

namespaceimgui
namespacewidgets

Debug and developer widgets for ImGui overlays. More...

Classes Index

classFpsWidget

Debug widget for real-time FPS metrics and frame pacing configuration. More...

Description

ImGui widget for displaying and configuring FPS metrics and frame pacing.

File Listing

The file content with the documentation metadata removed is:

1/**
2 * @file FpsWidget.ixx
3 * @brief ImGui widget for displaying and configuring FPS metrics and frame pacing.
4 */
5module;
6
7#include <vector>
8#include <string>
9#include "imgui.h"
10
11export module helios.ext.imgui.widgets.FpsWidget;
12
13import helios.ext.imgui.ImGuiWidget;
14import helios.engine.tooling.FpsMetrics;
15import helios.engine.tooling.FramePacer;
16import helios.engine.tooling.FrameStats;
17
18export namespace helios::ext::imgui::widgets {
19
20 /**
21 * @class FpsWidget
22 * @brief Debug widget for real-time FPS metrics and frame pacing configuration.
23 *
24 * Displays average FPS, frame time, work time, idle time, and frame history graph.
25 * Optionally allows runtime configuration of frame pacing target FPS via buttons
26 * and sliders (requires a `FramePacer` instance).
27 *
28 * @note This widget is not thread-safe. Use from the main/render thread only.
29 */
30 class FpsWidget : public ImGuiWidget {
31
32 private:
33 /**
34 * @brief Pointer to an FpsMetrics instance used for tracking and displaying FPS metrics.
35 *
36 * This member provides direct access to real-time frame rate statistics,
37 * including current FPS, average FPS, and frame timing data, which are displayed
38 * in the widget. It is expected to be externally managed and supplied during widget
39 * initialization.
40 *
41 * @note The pointer must remain valid throughout the lifetime of the FpsWidget instance.
42 */
43 helios::engine::tooling::FpsMetrics* fpsMetrics_ = nullptr;
44
45 /**
46 * @brief Pointer to a `FramePacer` instance for managing frame pacing and target FPS.
47 *
48 * Provides frame pacing control to synchronize application updates with a
49 * specified frame rate target, if set. When associated with a valid `FramePacer`,
50 * it enables runtime configuration of frame timing and update intervals.
51 *
52 * @note This pointer must be initialized with a valid `FramePacer` instance or
53 * set to `nullptr` if frame pacing is not required. Ensure the lifetime of the
54 * referenced `FramePacer` extends beyond the usage of this pointer.
55 */
56 helios::engine::tooling::FramePacer* framePacer_ = nullptr;
57
58 /**
59 * @brief Stores the user-configured target frames per second (FPS) for frame pacing.
60 *
61 * Acts as the intermediate value for the target FPS, used for runtime adjustments
62 * via buttons or sliders in the UI. This variable gets updated dynamically based on
63 * user input and reflects the desired frame rate. A value of `0.0f` indicates an
64 * uncapped frame rate.
65 *
66 * @note This variable is synchronized with the target FPS of the associated
67 * `FramePacer` instance if provided.
68 */
69 float targetFpsInput_ = 0.0f;
70
71 /**
72 * @brief Determines whether timing information is displayed in seconds or milliseconds.
73 *
74 * If set to `true`, all timing metrics (e.g., frame time, work time, idle time)
75 * are shown in seconds. If set to `false`, they are shown in milliseconds.
76 *
77 * Used to toggle between different units of measurement for presenting
78 * frame timing metrics in the FPS widget UI.
79 */
80 bool showInSeconds_ = false;
81
82 /**
83 * @brief Input value for configuring the size of the FPS history buffer.
84 *
85 * Determines the number of recent frame timing samples to store and display.
86 * This value directly influences the frame history graph rendering in the FPS widget.
87 * Typically adjusted by the user through the UI input field.
88 *
89 * @note Must be within a valid range, with a lower limit of 1 and an upper limit
90 * of 1000 to prevent excessive memory usage or invalid states.
91 */
92 int historySizeInput_ = 60;
93
94 public:
95
96 /**
97 * @brief Constructs the FpsWidget.
98 *
99 * @param fpsMetrics Pointer to the FpsMetrics instance (must remain valid).
100 * @param framePacer Optional pointer to FramePacer for runtime FPS configuration.
101 */
102 explicit FpsWidget(
104 helios::engine::tooling::FramePacer* framePacer = nullptr
105 ) : fpsMetrics_(fpsMetrics), framePacer_(framePacer)
106 {
107 if (fpsMetrics_) {
108 historySizeInput_ = static_cast<int>(fpsMetrics_->getHistorySize());
109 }
110 if (framePacer_) {
111 targetFpsInput_ = framePacer_->getTargetFps();
112 }
113 }
114
115 /**
116 * @brief Renders the FPS metrics UI using ImGui.
117 */
118 void draw() override {
119 if (!fpsMetrics_) {
120 return;
121 }
122
123 // Window settings
124 ImGui::SetNextWindowPos(ImVec2(10, 10), ImGuiCond_FirstUseEver);
125 ImGui::SetNextWindowSize(ImVec2(320, 250), ImGuiCond_FirstUseEver);
126
127 if (ImGui::Begin("FPS Metrics", nullptr, ImGuiWindowFlags_NoCollapse)) {
128
129 // 1 Main Metrics
130 ImGui::SeparatorText("Timing Info");
131
132 float displayFrameTime = showInSeconds_ ? fpsMetrics_->getFrameTimeSeconds() : fpsMetrics_->getFrameTimeMs();
133 float displayWorkTime = showInSeconds_ ? fpsMetrics_->getWorkTimeSeconds() : fpsMetrics_->getWorkTimeMs();
134 float displayIdleTime = showInSeconds_ ? fpsMetrics_->getIdleTimeSeconds() : fpsMetrics_->getIdleTimeMs();
135 const char* unit = showInSeconds_ ? "s" : "ms";
136 const char* format = showInSeconds_ ? "%.5f %s" : "%.2f %s";
137
138 ImGui::Text("FPS: %.1f", fpsMetrics_->getFps());
139 ImGui::Text("Avg Frame: "); ImGui::SameLine(); ImGui::Text(format, displayFrameTime, unit);
140 ImGui::Text("CPU Work: "); ImGui::SameLine(); ImGui::Text(format, displayWorkTime, unit);
141 ImGui::Text("Idle/Wait: "); ImGui::SameLine(); ImGui::Text(format, displayIdleTime, unit);
142 ImGui::Text("Frame #: %llu", fpsMetrics_->getFrameCount());
143
144 // 2 Settings
145 ImGui::SeparatorText("Settings");
146
147 // Checkbox for unit toggle
148 if (ImGui::Checkbox("Show in Seconds", &showInSeconds_)) {
149 // UI state changes; display updates next frame
150 }
151
152 // Input for history size
153 if (ImGui::InputInt("History Size", &historySizeInput_, 1, 10)) {
154 if (historySizeInput_ < 1) historySizeInput_ = 1;
155 if (historySizeInput_ > 1000) historySizeInput_ = 1000;
156
157 fpsMetrics_->setHistorySize(static_cast<size_t>(historySizeInput_));
158 }
159
160 // Frame pacing configuration (if pacer is available)
161 if (framePacer_) {
162 ImGui::SeparatorText("Frame Pacing Config");
163
164 targetFpsInput_ = framePacer_->getTargetFps();
165
166 // Quick preset buttons
167 if (ImGui::Button("Uncapped (0)")) {
168 framePacer_->setTargetFps(0.0f);
169 targetFpsInput_ = 0.0f;
170 }
171 ImGui::SameLine();
172 if (ImGui::Button("30 FPS")) {
173 framePacer_->setTargetFps(30.0f);
174 targetFpsInput_ = 30.0f;
175 }
176 ImGui::SameLine();
177 if (ImGui::Button("60 FPS")) {
178 framePacer_->setTargetFps(60.0f);
179 targetFpsInput_ = 60.0f;
180 }
181 ImGui::SameLine();
182 if (ImGui::Button("120 FPS")) {
183 framePacer_->setTargetFps(120.0f);
184 targetFpsInput_ = 120.0f;
185 }
186 ImGui::SameLine();
187 if (ImGui::Button("144 FPS")) {
188 framePacer_->setTargetFps(144.0f);
189 targetFpsInput_ = 144.0f;
190 }
191
192 // Slider for precise control
193 float sliderFps = targetFpsInput_;
194 if (ImGui::DragFloat("Target FPS", &sliderFps, 1.0f, 0.0f, 300.0f, "%.0f")) {
195 framePacer_->setTargetFps(sliderFps);
196 targetFpsInput_ = sliderFps;
197 }
198 if (ImGui::IsItemHovered()) {
199 ImGui::SetTooltip("Set to 0 for unlimited (V-Sync might still limit)");
200 }
201 }
202
203 // Frame time history graph
204 const auto& history = fpsMetrics_->getHistory();
205 if (!history.empty()) {
206 ImGui::SeparatorText("History");
207
208 std::vector<float> frameTimes;
209 frameTimes.reserve(history.size());
210
211 for (const auto& s : history) {
212 frameTimes.push_back(s.totalFrameTime * 1000.0f);
213 }
214
215 ImGui::PlotLines("Frame Time (ms)",
216 frameTimes.data(),
217 static_cast<int>(frameTimes.size()),
218 0,
219 nullptr,
220 0.0f,
221 FLT_MAX,
222 ImVec2(0, 80.0f));
223 }
224 }
225 ImGui::End();
226 }
227 };
228}

Generated via doxygen2docusaurus 2.0.0 by Doxygen 1.15.0.