Merge lp:~linaro-graphics-wg/glmark2/main-loop-consolidation into lp:glmark2/2011.11

Proposed by Alexandros Frantzis
Status: Merged
Merged at revision: 197
Proposed branch: lp:~linaro-graphics-wg/glmark2/main-loop-consolidation
Merge into: lp:glmark2/2011.11
Diff against target: 655 lines (+403/-156)
6 files modified
src/android.cpp (+24/-44)
src/main-loop.cpp (+236/-0)
src/main-loop.h (+121/-0)
src/main.cpp (+14/-104)
src/scene.cpp (+0/-7)
src/scene.h (+8/-1)
To merge this branch: bzr merge lp:~linaro-graphics-wg/glmark2/main-loop-consolidation
Reviewer Review Type Date Requested Status
Jesse Barker Approve
Review via email: mp+92734@code.launchpad.net

Description of the change

Consolidate the X11 and Android main loops.

To post a comment you must log in.
Revision history for this message
Jesse Barker (jesse-barker) wrote :

I suppose an argument could be made for avoiding the creation of an extra MainLoop object in do_benchmark(), but I don't feel strongly about it.

review: Approve
Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

I did this in order to avoid creating any objects on the heap. I guess a better alternative would be:

MainLoop &loop(Options::show_fps ? MainLoopDecoration(canvas, benchmarks) :
                                    MainLoop(canvas, benchmarks));

How does that look? Any better way to achieve this?

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/android.cpp'
2--- src/android.cpp 2012-02-13 09:53:57 +0000
3+++ src/android.cpp 2012-02-13 11:04:30 +0000
4@@ -30,9 +30,26 @@
5 #include "log.h"
6 #include "util.h"
7 #include "default-benchmarks.h"
8+#include "main-loop.h"
9
10 static Canvas *g_canvas;
11 static std::vector<Benchmark *> g_benchmarks;
12+static MainLoop *g_loop;
13+
14+class MainLoopAndroid : public MainLoop
15+{
16+public:
17+ MainLoopAndroid(Canvas &canvas, const std::vector<Benchmark *> &benchmarks) :
18+ MainLoop(canvas, benchmarks) {}
19+
20+ virtual void after_scene_setup() {}
21+
22+ virtual void before_scene_teardown()
23+ {
24+ Log::info("%s FPS: %u", scene_->info_string().c_str(),
25+ scene_->average_fps());
26+ }
27+};
28
29 static void
30 add_default_benchmarks(std::vector<Benchmark *> &benchmarks)
31@@ -53,6 +70,7 @@
32 {
33 static_cast<void>(clazz);
34
35+ Options::reuse_context = true;
36 Log::init("glmark2", false);
37 Util::android_set_asset_manager(AAssetManager_fromJava(env, asset_manager));
38
39@@ -76,6 +94,7 @@
40 Benchmark::register_scene(*new SceneBuffer(*g_canvas));
41
42 add_default_benchmarks(g_benchmarks);
43+ g_loop = new MainLoopAndroid(*g_canvas, g_benchmarks);
44 }
45
46 void
47@@ -96,6 +115,7 @@
48 {
49 static_cast<void>(env);
50
51+ delete g_loop;
52 delete g_canvas;
53 }
54
55@@ -103,50 +123,10 @@
56 Java_org_linaro_glmark2_Glmark2Renderer_nativeRender(JNIEnv* env)
57 {
58 static_cast<void>(env);
59- static std::vector<Benchmark *>::iterator bench_iter = g_benchmarks.begin();
60- static Scene *scene = 0;
61- static unsigned int score = 0;
62- static unsigned int benchmarks_run = 0;
63-
64- if (!scene) {
65- /* Find the next normal scene */
66- while (bench_iter != g_benchmarks.end()) {
67- scene = &(*bench_iter)->setup_scene();
68- if (!scene->name().empty())
69- break;
70- bench_iter++;
71- }
72-
73- if (bench_iter == g_benchmarks.end()) {
74- if (benchmarks_run)
75- score /= benchmarks_run;
76- Log::info("glmark2 Score: %u\n", score);
77- /* Reset the rendering state, in case we get called again */
78- bench_iter = g_benchmarks.begin();
79- score = 0;
80- benchmarks_run = 0;
81- return false;
82- }
83- }
84-
85- if (scene->is_running()) {
86- g_canvas->clear();
87-
88- scene->draw();
89- scene->update();
90- }
91-
92- /*
93- * Need to recheck whether screen is running, because scene->update()
94- * may have changed the state.
95- */
96- if (!scene->is_running()) {
97- Log::info("%s FPS: %u", scene->info_string().c_str(), scene->average_fps());
98- score += scene->average_fps();
99- (*bench_iter)->teardown_scene();
100- scene = 0;
101- bench_iter++;
102- benchmarks_run++;
103+
104+ if (!g_loop->step()) {
105+ Log::info("glmark2 Score: %u\n", g_loop->score());
106+ return false;
107 }
108
109 return true;
110
111=== added file 'src/main-loop.cpp'
112--- src/main-loop.cpp 1970-01-01 00:00:00 +0000
113+++ src/main-loop.cpp 2012-02-13 11:04:30 +0000
114@@ -0,0 +1,236 @@
115+/*
116+ * Copyright © 2012 Linaro Limited
117+ *
118+ * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
119+ *
120+ * glmark2 is free software: you can redistribute it and/or modify it under the
121+ * terms of the GNU General Public License as published by the Free Software
122+ * Foundation, either version 3 of the License, or (at your option) any later
123+ * version.
124+ *
125+ * glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY
126+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
127+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
128+ * details.
129+ *
130+ * You should have received a copy of the GNU General Public License along with
131+ * glmark2. If not, see <http://www.gnu.org/licenses/>.
132+ *
133+ * Authors:
134+ * Alexandros Frantzis
135+ */
136+#include "options.h"
137+#include "main-loop.h"
138+#include "util.h"
139+#include "log.h"
140+
141+#include <string>
142+#include <sstream>
143+
144+/************
145+ * MainLoop *
146+ ************/
147+
148+MainLoop::MainLoop(Canvas &canvas, const std::vector<Benchmark *> &benchmarks) :
149+ canvas_(canvas), benchmarks_(benchmarks)
150+{
151+ reset();
152+}
153+
154+void
155+MainLoop::reset()
156+{
157+ scene_ = 0;
158+ score_ = 0;
159+ benchmarks_run_ = 0;
160+ bench_iter_ = benchmarks_.begin();
161+}
162+
163+unsigned int
164+MainLoop::score()
165+{
166+ if (benchmarks_run_)
167+ return score_ / benchmarks_run_;
168+ else
169+ return score_;
170+}
171+
172+bool
173+MainLoop::step()
174+{
175+ /* Find the next normal scene */
176+ if (!scene_) {
177+ /* Find a normal scene */
178+ while (bench_iter_ != benchmarks_.end()) {
179+ scene_ = &(*bench_iter_)->scene();
180+
181+ /*
182+ * Scenes with empty names are option-setting scenes.
183+ * Just set them up and continue with the search.
184+ */
185+ if (scene_->name().empty())
186+ (*bench_iter_)->setup_scene();
187+ else
188+ break;
189+
190+ bench_iter_++;
191+ }
192+
193+ /* If we have found a valid scene, set it up */
194+ if (bench_iter_ != benchmarks_.end()) {
195+ if (!Options::reuse_context)
196+ canvas_.reset();
197+ before_scene_setup();
198+ scene_ = &(*bench_iter_)->setup_scene();
199+ after_scene_setup();
200+ }
201+ else {
202+ /* ... otherwise we are done */
203+ return false;
204+ }
205+ }
206+
207+ bool should_quit = canvas_.should_quit();
208+
209+ if (scene_ ->running() && !should_quit)
210+ draw();
211+
212+ /*
213+ * Need to recheck whether the scene is still running, because code
214+ * in draw() may have changed the state.
215+ */
216+ if (!scene_->running() || should_quit) {
217+ score_ += scene_->average_fps();
218+ before_scene_teardown();
219+ (*bench_iter_)->teardown_scene();
220+ scene_ = 0;
221+ bench_iter_++;
222+ benchmarks_run_++;
223+ }
224+
225+ return !should_quit;
226+}
227+
228+void
229+MainLoop::draw()
230+{
231+ canvas_.clear();
232+
233+ scene_->draw();
234+ scene_->update();
235+
236+ canvas_.update();
237+}
238+
239+void
240+MainLoop::after_scene_setup()
241+{
242+ Log::info("%s", scene_->info_string().c_str());
243+ Log::flush();
244+}
245+
246+void
247+MainLoop::before_scene_teardown()
248+{
249+ static const std::string format(Log::continuation_prefix + " FPS: %u\n");
250+ Log::info(format.c_str(), scene_->average_fps());
251+}
252+
253+/**********************
254+ * MainLoopDecoration *
255+ **********************/
256+
257+MainLoopDecoration::MainLoopDecoration(Canvas &canvas, const std::vector<Benchmark *> &benchmarks) :
258+ MainLoop(canvas, benchmarks), fps_renderer_(0), last_fps_(0)
259+{
260+
261+}
262+
263+MainLoopDecoration::~MainLoopDecoration()
264+{
265+ delete fps_renderer_;
266+ fps_renderer_ = 0;
267+}
268+
269+void
270+MainLoopDecoration::draw()
271+{
272+ static const unsigned int fps_interval = 500000;
273+ uint64_t now = Util::get_timestamp_us();
274+
275+ canvas_.clear();
276+
277+ scene_->draw();
278+ scene_->update();
279+
280+ if (now - fps_timestamp_ >= fps_interval) {
281+ last_fps_ = scene_->average_fps();
282+ fps_renderer_update_text(last_fps_);
283+ fps_timestamp_ = now;
284+ }
285+ fps_renderer_->render();
286+
287+ canvas_.update();
288+}
289+
290+void
291+MainLoopDecoration::before_scene_setup()
292+{
293+ delete fps_renderer_;
294+ fps_renderer_ = new TextRenderer(canvas_);
295+ fps_renderer_update_text(last_fps_);
296+ fps_timestamp_ = Util::get_timestamp_us();
297+}
298+
299+void
300+MainLoopDecoration::fps_renderer_update_text(unsigned int fps)
301+{
302+ std::stringstream ss;
303+ ss << "FPS: " << fps;
304+ fps_renderer_->text(ss.str());
305+}
306+
307+/**********************
308+ * MainLoopValidation *
309+ **********************/
310+
311+MainLoopValidation::MainLoopValidation(Canvas &canvas, const std::vector<Benchmark *> &benchmarks) :
312+ MainLoop(canvas, benchmarks)
313+{
314+}
315+
316+void
317+MainLoopValidation::draw()
318+{
319+ /* Draw only the first frame of the scene and stop */
320+ canvas_.clear();
321+
322+ scene_->draw();
323+
324+ canvas_.update();
325+
326+ scene_->running(false);
327+}
328+
329+void
330+MainLoopValidation::before_scene_teardown()
331+{
332+ static const std::string format(Log::continuation_prefix + " Validation: %s\n");
333+ std::string result;
334+
335+ switch(scene_->validate()) {
336+ case Scene::ValidationSuccess:
337+ result = "Success";
338+ break;
339+ case Scene::ValidationFailure:
340+ result = "Failure";
341+ break;
342+ case Scene::ValidationUnknown:
343+ result = "Unknown";
344+ break;
345+ default:
346+ break;
347+ }
348+
349+ Log::info(format.c_str(), result.c_str());
350+}
351
352=== added file 'src/main-loop.h'
353--- src/main-loop.h 1970-01-01 00:00:00 +0000
354+++ src/main-loop.h 2012-02-13 11:04:30 +0000
355@@ -0,0 +1,121 @@
356+/*
357+ * Copyright © 2012 Linaro Limited
358+ *
359+ * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
360+ *
361+ * glmark2 is free software: you can redistribute it and/or modify it under the
362+ * terms of the GNU General Public License as published by the Free Software
363+ * Foundation, either version 3 of the License, or (at your option) any later
364+ * version.
365+ *
366+ * glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY
367+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
368+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
369+ * details.
370+ *
371+ * You should have received a copy of the GNU General Public License along with
372+ * glmark2. If not, see <http://www.gnu.org/licenses/>.
373+ *
374+ * Authors:
375+ * Alexandros Frantzis
376+ */
377+#ifndef GLMARK2_MAIN_LOOP_H_
378+#define GLMARK2_MAIN_LOOP_H_
379+
380+#include "canvas.h"
381+#include "benchmark.h"
382+#include "text-renderer.h"
383+#include <vector>
384+
385+/**
386+ * Main loop for benchmarking.
387+ */
388+class MainLoop
389+{
390+public:
391+ MainLoop(Canvas &canvas, const std::vector<Benchmark *> &benchmarks);
392+
393+ virtual ~MainLoop() {}
394+
395+ /**
396+ * Resets the main loop.
397+ *
398+ * You need to call reset() if the loop has finished and
399+ * you need to run it again.
400+ */
401+ void reset();
402+
403+ /**
404+ * Gets the current total benchmarking score.
405+ */
406+ unsigned int score();
407+
408+ /**
409+ * Perform the next main loop step.
410+ *
411+ * @returns whether the loop has finished
412+ */
413+ bool step();
414+
415+ /**
416+ * Overridable method for drawing the canvas contents.
417+ */
418+ virtual void draw();
419+
420+ /**
421+ * Overridable method for pre scene-setup customizations.
422+ */
423+ virtual void before_scene_setup() {}
424+
425+ /**
426+ * Overridable method for post scene-setup customizations.
427+ */
428+ virtual void after_scene_setup();
429+
430+ /**
431+ * Overridable method for pre scene-teardown customizations.
432+ */
433+ virtual void before_scene_teardown();
434+
435+protected:
436+ Canvas &canvas_;
437+ Scene *scene_;
438+ const std::vector<Benchmark *> &benchmarks_;
439+ unsigned int score_;
440+ unsigned int benchmarks_run_;
441+
442+ std::vector<Benchmark *>::const_iterator bench_iter_;
443+};
444+
445+/**
446+ * Main loop for benchmarking with decorations (eg FPS, demo)
447+ */
448+class MainLoopDecoration : public MainLoop
449+{
450+public:
451+ MainLoopDecoration(Canvas &canvas, const std::vector<Benchmark *> &benchmarks);
452+ virtual ~MainLoopDecoration();
453+
454+ virtual void draw();
455+ virtual void before_scene_setup();
456+
457+protected:
458+ void fps_renderer_update_text(unsigned int fps);
459+ TextRenderer *fps_renderer_;
460+ unsigned int last_fps_;
461+ uint64_t fps_timestamp_;
462+};
463+
464+/**
465+ * Main loop for validation.
466+ */
467+class MainLoopValidation : public MainLoop
468+{
469+public:
470+ MainLoopValidation(Canvas &canvas, const std::vector<Benchmark *> &benchmarks);
471+
472+ virtual void draw();
473+ virtual void before_scene_teardown();
474+};
475+
476+#endif /* GLMARK2_MAIN_LOOP_H_ */
477
478=== modified file 'src/main.cpp'
479--- src/main.cpp 2012-01-27 22:01:59 +0000
480+++ src/main.cpp 2012-02-13 11:04:30 +0000
481@@ -30,6 +30,7 @@
482 #include "util.h"
483 #include "default-benchmarks.h"
484 #include "text-renderer.h"
485+#include "main-loop.h"
486
487 #include <iostream>
488 #include <fstream>
489@@ -174,115 +175,24 @@
490 void
491 do_benchmark(Canvas &canvas, vector<Benchmark *> &benchmarks)
492 {
493- static const unsigned int fps_interval = 500000;
494- unsigned score = 0;
495- unsigned int last_fps = 0;
496- unsigned int benchmarks_run = 0;
497- static const string format(Log::continuation_prefix + " FPS: %u\n");
498-
499- for (vector<Benchmark *>::iterator bench_iter = benchmarks.begin();
500- bench_iter != benchmarks.end();
501- bench_iter++)
502- {
503- if (!Options::reuse_context)
504- canvas.reset();
505-
506- TextRenderer fps_renderer(canvas);
507- if (Options::show_fps)
508- fps_renderer_update_text(fps_renderer, last_fps);
509-
510- bool keep_running = true;
511- Benchmark *bench = *bench_iter;
512- uint64_t fps_timestamp = Util::get_timestamp_us();
513- Scene &scene = bench->setup_scene();
514-
515- if (!scene.name().empty()) {
516- Log::info("%s", scene.info_string().c_str());
517- Log::flush();
518-
519- while (scene.is_running() &&
520- (keep_running = !canvas.should_quit()))
521- {
522- canvas.clear();
523-
524- scene.draw();
525- scene.update();
526-
527- if (Options::show_fps) {
528- uint64_t now = Util::get_timestamp_us();
529- if (now - fps_timestamp >= fps_interval) {
530- last_fps = scene.average_fps();
531- fps_renderer_update_text(fps_renderer, last_fps);
532- fps_timestamp = now;
533- }
534- fps_renderer.render();
535- }
536-
537- canvas.update();
538- }
539-
540- Log::info(format.c_str(), scene.average_fps());
541- score += scene.average_fps();
542- benchmarks_run++;
543- }
544-
545- bench->teardown_scene();
546-
547- if (!keep_running)
548- break;
549- }
550-
551- if (benchmarks_run)
552- score /= benchmarks_run;
553-
554- Log::info("=======================================================\n");
555- Log::info(" glmark2 Score: %u \n", score);
556- Log::info("=======================================================\n");
557-
558+ MainLoop loop_normal(canvas, benchmarks);
559+ MainLoopDecoration loop_decoration(canvas, benchmarks);
560+
561+ MainLoop &loop(Options::show_fps ? loop_decoration : loop_normal);
562+
563+ while (loop.step());
564+
565+ Log::info("=======================================================\n");
566+ Log::info(" glmark2 Score: %u \n", loop.score());
567+ Log::info("=======================================================\n");
568 }
569
570 void
571 do_validation(Canvas &canvas, vector<Benchmark *> &benchmarks)
572 {
573- static const string format(Log::continuation_prefix + " Validation: %s\n");
574- for (vector<Benchmark *>::iterator bench_iter = benchmarks.begin();
575- bench_iter != benchmarks.end();
576- bench_iter++)
577- {
578- if (!Options::reuse_context)
579- canvas.reset();
580-
581- Benchmark *bench = *bench_iter;
582- Scene &scene = bench->setup_scene();
583-
584- if (!scene.name().empty()) {
585- Log::info("%s", scene.info_string().c_str());
586- Log::flush();
587-
588- canvas.clear();
589- scene.draw();
590- canvas.update();
591-
592- string result;
593- switch(scene.validate()) {
594- case Scene::ValidationSuccess:
595- result = "Success";
596- break;
597- case Scene::ValidationFailure:
598- result = "Failure";
599- break;
600- case Scene::ValidationUnknown:
601- result = "Unknown";
602- break;
603- default:
604- break;
605- }
606-
607- Log::info(format.c_str(), result.c_str());
608- }
609-
610- bench->teardown_scene();
611- }
612+ MainLoopValidation loop(canvas, benchmarks);
613+
614+ while (loop.step());
615 }
616
617 int
618
619=== modified file 'src/scene.cpp'
620--- src/scene.cpp 2011-12-08 13:19:41 +0000
621+++ src/scene.cpp 2012-02-13 11:04:30 +0000
622@@ -121,13 +121,6 @@
623 return currentFrame_ / elapsed_time;
624 }
625
626-
627-bool
628-Scene::is_running()
629-{
630- return running_;
631-}
632-
633 bool
634 Scene::set_option(const string &opt, const string &val)
635 {
636
637=== modified file 'src/scene.h'
638--- src/scene.h 2011-12-08 13:19:41 +0000
639+++ src/scene.h 2012-02-13 11:04:30 +0000
640@@ -146,7 +146,14 @@
641 *
642 * @return true if running, false otherwise
643 */
644- bool is_running();
645+ bool running() { return running_; }
646+
647+ /**
648+ * Sets whether this scene is running.
649+ *
650+ * @return true if running, false otherwise
651+ */
652+ void running(bool r) { running_ = r; }
653
654 /**
655 * Gets the average FPS value for this scene.

Subscribers

People subscribed via source and target branches