cgv
Loading...
Searching...
No Matches
performance_monitor.cxx
1#include "performance_monitor.h"
2
3#include <cgv/gui/theme_info.h>
4#include <cgv/math/ftransform.h>
5#include <cgv_g2d/msdf_gl_font_renderer.h>
6
7namespace cgv {
8namespace app {
9
10performance_monitor::performance_monitor() {
11
12 set_name("Performance Monitor");
14
15 layout.padding = padding();
16 layout.total_size = ivec2(180, 80);
17
18 set_size(layout.total_size);
19
20 bar_renderer = cgv::g2d::generic_2d_renderer(cgv::g2d::shaders::rectangle);
21}
22
24
25 cgv::g2d::ref_msdf_gl_font_renderer_2d(ctx, -1);
26
28
29 bar_renderer.destruct(ctx);
30 bars.destruct(ctx);
31 static_text_geometry.destruct(ctx);
32 dynamic_text_geometry.destruct(ctx);
33}
34
36
37 if(m.is(show_plot)) {
38 layout.total_size.y() = show_plot ? 80 : 45;
39 set_size(layout.total_size);
40 if(get_context())
41 create_static_texts(*get_context());
42 }
43
44 if(m.one_of(background_visible_, invert_color))
45 init_styles();
46
47 if(m.is(monitor.enabled)) {
48 if(monitor.enabled)
49 monitor.reset();
50 }
51}
52
54
55 cgv::g2d::ref_msdf_gl_font_renderer_2d(ctx, 1);
56
57 register_shader("rectangle", cgv::g2d::shaders::rectangle);
58 register_shader("line", cgv::g2d::shaders::line);
59
60 bool success = canvas_overlay::init(ctx);
61
62 success &= bar_renderer.init(ctx);
63 success &= static_text_geometry.init(ctx);
64 success &= dynamic_text_geometry.init(ctx);
65
66 plot_color_map.add_color_point(0.0f, rgb(0.5f, 1.0f, 0.5f));
67 plot_color_map.add_color_point(0.25f, rgb(0.0f, 0.9f, 0.0f));
68 plot_color_map.add_color_point(0.5f, rgb(0.8f, 0.9f, 0.0f));
69 plot_color_map.add_color_point(1.0f, rgb(0.9f, 0.0f, 0.0f));
70
71 return success;
72}
73
75
76 if(ensure_layout(ctx)) {
77 layout.update(get_rectangle().size);
78 create_static_texts(ctx);
79 create_dynamic_texts(ctx);
80 }
81
82 bool enabled = monitor.enabled;
83 if(monitor.enabled_only_when_visible && !is_visible()) {
84 enabled = false;
85 }
86 if(enabled) {
87 if(show_plot)
88 update_plot();
89 update_dynamic_texts(ctx);
90 }
91}
92
93void performance_monitor::draw_content(cgv::render::context& ctx) {
94
95 begin_content(ctx);
96 auto& font_renderer = cgv::g2d::ref_msdf_gl_font_renderer_2d(ctx);
97
98 if(show_plot) {
99 // draw plot border
100 content_canvas.enable_shader(ctx, "rectangle");
101 content_canvas.set_style(ctx, border_style);
102 content_canvas.draw_shape(ctx, layout.plot_rect.position - 1, layout.plot_rect.size + 2);
103
104 // draw plot bars
105 bar_renderer.render(ctx, content_canvas, cgv::render::PT_POINTS, bars, bar_style);
106
107 // draw line
108 const auto& r = layout.plot_rect;
109 ivec2 a(r.x() + 12, r.center().y());
110 ivec2 b = a;
111 b.x() = r.x1();
112
113 content_canvas.enable_shader(ctx, "line");
114 content_canvas.set_style(ctx, line_style);
115 content_canvas.draw_shape2(ctx, a, b);
116 content_canvas.disable_current_shader(ctx);
117 }
118
119 // draw text
120 font_renderer.render(ctx, content_canvas, static_text_geometry, text_style);
121 font_renderer.render(ctx, content_canvas, dynamic_text_geometry, text_style);
122
123 end_content(ctx);
124}
125
127
129
130 bool enabled = monitor.enabled;
131 if(monitor.enabled_only_when_visible && !is_visible())
132 enabled = false;
133
134 if(enabled) {
135 ++monitor.total_frame_count;
136 ++monitor.interval_frame_count;
137
138 double seconds_since_start = monitor.timer.get_elapsed_time();
139 monitor.delta_time = seconds_since_start - monitor.last_seconds_since_start;
140
141 monitor.running_time += monitor.delta_time;
142
143 monitor.last_seconds_since_start = seconds_since_start;
144
145 if(monitor.running_time >= monitor.interval) {
146 monitor.avg_fps = (double)monitor.interval_frame_count / monitor.running_time;
147 monitor.running_time = 0.0;
148 monitor.interval_frame_count = 0u;
149 }
150 }
151}
152
153void performance_monitor::set_invert_color(bool flag) {
154
155 invert_color = flag;
156 on_set(&invert_color);
157}
158
159void performance_monitor::enable_monitoring(bool enabled) {
160 monitor.enabled = enabled;
161 on_set(&monitor.enabled);
162}
163
164void performance_monitor::enable_monitoring_only_when_visible(bool enabled) {
165 monitor.enabled_only_when_visible = enabled;
166}
167
169
170 if(monitor.enabled_only_when_visible && is_visible()) {
171 if(monitor.enabled)
172 monitor.reset();
173 }
174}
175
177
178 add_member_control(this, "Enable", monitor.enabled, "check", "w=110", " ");
179 add_member_control(this, "Show Plot", show_plot, "check", "w=78");
180 add_member_control(this, "Measure Interval (s)", monitor.interval, "value_slider", "min=0.01;max=1;step=0.01;ticks=true");
181
182 add_member_control(this, "Background", background_visible_, "check", "w=100", " ");
183 add_member_control(this, "Invert Color", invert_color, "check", "w=88");
184}
185
186void performance_monitor::init_styles() {
187 auto& theme = cgv::gui::theme_info::instance();
188 rgb border_color = theme.text();
189
190 if(invert_color)
191 border_color = pow(rgb(1.0f) - pow(border_color, 2.2f), 1.0f / 2.2f);
192
193 // configure style for the border rectangle
194 border_style.fill_color = background_visible_ ? rgba(theme.text_background(), 1.0f) : rgba(0.0f);
195 border_style.border_color = rgba(border_color, 1.0);
196 border_style.border_width = 1.0f;
197 border_style.feather_width = 0.0f;
198 border_style.use_blending = true;
199
200 line_style.use_blending = true;
201 line_style.fill_color = rgba(border_color, invert_color ? 0.666f : 0.333f);
202 line_style.feather_width = 0.0f;
203 line_style.dash_length = 10.0f;
204
205 bar_style.use_fill_color = false;
206 bar_style.feather_width = 0.0f;
207
208 // configure text style
209 text_style.fill_color = border_color;
210 text_style.font_size = 12.0f;
211
212 tick_text_style = text_style;
213 tick_text_style.font_size = 10.0f;
214}
215
216void performance_monitor::create_static_texts(const cgv::render::context& ctx) {
217
218 static_text_geometry.clear();
219
220 std::vector<std::string> texts = {
221 "Frames per second:",
222 "Frametime (ms):"
223 };
224
225 const float line_spacing = 1.25f * text_style.font_size;
226 cgv::g2d::rect content_rect = static_cast<cgv::g2d::rect>(layout.content_rect);
227
228 vec3 caret_pos(content_rect.x(), content_rect.y1() - text_style.font_size, 0.0f);
229 static_text_geometry.positions.push_back(caret_pos);
230 caret_pos.y() -= line_spacing;
231 static_text_geometry.positions.push_back(caret_pos);
232
233 static_text_geometry.alignments = {
236
237 };
238
239 if(show_plot) {
240 texts.push_back("30");
241 texts.push_back("60");
242 texts.push_back("120");
243
244 cgv::g2d::rect plot_rect = static_cast<cgv::g2d::rect>(layout.plot_rect);
245
246 caret_pos = vec3(plot_rect.x(), plot_rect.y1(), 0.0f);
247 static_text_geometry.positions.push_back(caret_pos);
248 caret_pos.y() = plot_rect.center().y();
249 static_text_geometry.positions.push_back(caret_pos);
250 caret_pos.y() = plot_rect.y();
251 static_text_geometry.positions.push_back(caret_pos);
252
253 static_text_geometry.alignments.push_back(cgv::render::TA_TOP_LEFT),
254 static_text_geometry.alignments.push_back(cgv::render::TA_LEFT);
255 static_text_geometry.alignments.push_back(cgv::render::TA_BOTTOM_LEFT);
256 }
257
258 static_text_geometry.set_text_array(ctx, texts);
259}
260
261void performance_monitor::create_dynamic_texts(const cgv::render::context& ctx) {
262
263 dynamic_text_geometry.clear();
264
265 dynamic_text_geometry.set_text_array(ctx, { "", "" });
266
267 const float line_spacing = 1.25f * text_style.font_size;
268 cgv::g2d::rect content_rect = static_cast<cgv::g2d::rect>(layout.content_rect);
269
270 vec3 caret_pos = vec3(content_rect.x1(), content_rect.y1() - text_style.font_size, 0.0f);
271 dynamic_text_geometry.positions.push_back(caret_pos);
272 caret_pos.y() -= line_spacing;
273 dynamic_text_geometry.positions.push_back(caret_pos);
274
275 dynamic_text_geometry.alignments = {
278 };
279}
280
281void performance_monitor::update_dynamic_texts(const cgv::render::context& ctx) {
282
283 std::vector<std::string> value_labels(2);
284
285 std::stringstream ss;
286 ss.precision(2);
287 ss << std::fixed;
288 ss << monitor.avg_fps;
289
290 value_labels[0] = ss.str();
291
292 ss.str(std::string());
293 if(monitor.avg_fps < 0.001f)
294 ss << "-";
295 else
296 ss << 1000.0 / monitor.avg_fps;
297
298 value_labels[1] = ss.str();
299
300 dynamic_text_geometry.set_text_array(ctx, value_labels);
301 post_damage();
302}
303
304
305
306void performance_monitor::update_plot() {
307
308 ivec2 plot_size = layout.plot_rect.size;
309
310 float a = static_cast<float>(1000.0 * monitor.delta_time / 33.333333333);
311 float b = std::min(a, 1.0f);
312 float bar_height = plot_size.y() * b;
313 bar_height = std::max(bar_height, 1.0f);
314
315 rgb bar_color = a > 1.0f ? rgb(0.7f, 0.0f, 0.0f) : plot_color_map.interpolate_color(b);
316
317 if(bars.render_count() < plot_size.x()) {
318 for(auto& position : bars.position)
319 position.x() -= 1.0f;
320
321 int x = layout.plot_rect.x1() - 1;
322 x = std::max(x, 0);
323 float bar_x = static_cast<float>(x);
324 bars.add(vec2(bar_x, static_cast<float>(layout.plot_rect.y())), vec2(1.0f, bar_height), bar_color);
325
326 } else {
327 for(size_t i = 0; i < bars.position.size() - 1; ++i) {
328 bars.size[i].y() = bars.size[i + 1].y();
329 bars.color[i] = bars.color[i + 1];
330 }
331
332 bars.size.back() = vec2(1.0f, bar_height);
333 bars.color.back() = bar_color;
334 }
335
336 bars.set_out_of_date();
337 post_damage();
338}
339
340}
341}
void clear(cgv::render::context &ctx) override
clear all objects living in the context like textures or display lists
virtual void on_set(void *member_ptr) override
default implementation of that calls handle_member_change and afterwards upates the member in the gui...
bool init(cgv::render::context &ctx) override
this method is called after creation or recreation of the context, return whether all necessary funct...
cgv::g2d::irect get_rectangle() const
return the current rectangle area (in screen coordinates) of the overlay taking layout into account
Definition overlay.h:139
gui_options_t gui_options
options for the GUI creation of this overlay (must be set before GUI creation)
Definition overlay.h:103
void set_size(const ivec2 &size)
set the default size of the overlay before stretch gets applied
Definition overlay.cxx:108
void after_finish(cgv::render::context &ctx) override
draw the content of the canvas overlay
void on_visibility_change() override
called when the overlay visibility is changed through the default gui
struct cgv::app::performance_monitor::@20 monitor
measuring state fields
void init_frame(cgv::render::context &ctx) override
this method is called in one pass over all drawables before the draw method
void clear(cgv::render::context &ctx) override
clear all objects living in the context like textures or display lists
bool enabled
whether measuring is enabled
bool init(cgv::render::context &ctx) override
this method is called after creation or recreation of the context, return whether all necessary funct...
void create_gui_impl() override
virtual method to implement the derived class gui creation
void handle_member_change(const cgv::utils::pointer_test &m) override
implement to handle member changes
bool background_visible_
whether the background is visible (true by default)
void set_name(const std::string &_name)
set a new parent node
Definition named.cxx:13
data::ref_ptr< control< T > > add_member_control(cgv::base::base *base_ptr, const std::string &label, T &value, const std::string &gui_type="", const std::string &options="", const std::string &align="\n")
add control with callback to cgv::base::on_set method on cgv::gui::control::value_change
Definition provider.h:137
T & y()
second element
Definition fvec.h:159
T & x()
first element
Definition fvec.h:155
base class for all drawables, which is independent of the used rendering API.
Definition context.h:621
context * get_context() const
access the current context. The context will be available latestly in the init method but not in the ...
Definition drawable.cxx:37
virtual void after_finish(context &)
this method is called in one pass over all drawables after finish frame
Definition drawable.cxx:125
bool is_visible() const
check whether the drawable is visible
Definition drawable.cxx:31
bool is(const void *ptr) const
Test if the stored pointer points to the given pointer address.
@ TA_BOTTOM_RIGHT
bottom right corner of text bounds
Definition context.h:282
@ TA_BOTTOM_LEFT
bottom left corner of text bounds
Definition context.h:281
@ TA_TOP_LEFT
top left corner of text bounds
Definition context.h:279
@ TA_LEFT
center of left edge of text bounds
Definition context.h:275
the cgv namespace
Definition print.h:11
cgv::media::color< float, cgv::media::RGB, cgv::media::OPACITY > rgba
declare rgba color type with 32 bit components
Definition color.h:855
cgv::media::color< float, cgv::media::RGB > rgb
declare rgb color type with 32 bit components
Definition color.h:853
cgv::math::fvec< int32_t, 2 > ivec2
declare type of 2d 32 bit integer vectors
Definition fvec.h:694
cgv::math::fvec< float, 2 > vec2
declare type of 2d single precision floating point vectors
Definition fvec.h:667
cgv::math::fvec< float, 3 > vec3
declare type of 3d single precision floating point vectors
Definition fvec.h:669
bool allow_stretch
whether to show the stretch options (show_layout_options must be enabled)
Definition overlay.h:98