Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1051)

Side by Side Diff: gpu/tools/compositor_model_bench/compositor_model_bench.cc

Issue 7718020: Initial checkin of the compositor_model_bench tool, which simulates the GPU demands of Chromium's... (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: '' Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // This tool is used to benchmark the render model used by the compositor
6
7 // Most of this file is derived from the source of the tile_render_bench tool,
8 // and has been changed to support running a sequence of independent
9 // simulations for our different render models and test cases.
10
11 #include <stdio.h>
12 #include <sys/dir.h>
13 #include <sys/file.h>
14 #include <sys/stat.h>
15 #include <sys/types.h>
16 #include <X11/keysym.h>
17 #include <X11/Xlib.h>
18 #include <X11/Xutil.h>
19
20 #include <queue>
21 #include <string>
22 #include <vector>
23
24 #include "base/at_exit.h"
25 #include "base/basictypes.h"
26 #include "base/command_line.h"
27 #include "base/file_path.h"
28 #include "base/file_util.h"
29 #include "base/memory/scoped_ptr.h"
30 #include "base/message_loop.h"
31 #include "base/task.h"
32 #include "base/time.h"
33
34 #include "gpu/tools/compositor_model_bench/render_model_utils.h"
35 #include "gpu/tools/compositor_model_bench/render_models.h"
36 #include "gpu/tools/compositor_model_bench/render_tree.h"
37
38
39 using base::TimeTicks;
40 using file_util::CloseFile;
41 using file_util::DirectoryExists;
42 using file_util::FileEnumerator;
43 using file_util::OpenFile;
44 using file_util::PathExists;
45 using std::queue;
46 using std::string;
47
48 struct SimulationSpecification {
49 string simulation_name;
50 FilePath input_path;
51 RenderModel model_under_test;
52 TimeTicks simulation_start_time;
53 int frames_rendered;
54 };
55
56 // Forward declarations
57 class Simulator;
58 void _process_events(Simulator* sim);
59 void _update_loop(Simulator* sim);
60
61 class Simulator {
62 public:
63 Simulator(int seconds_per_test, const FilePath& output_path)
64 : running_(false),
65 current_sim_(NULL),
66 output_path_(output_path),
67 seconds_per_test_(seconds_per_test),
68 display_(NULL),
69 window_(0),
70 gl_context_(NULL),
71 window_width_(WINDOW_WIDTH),
72 window_height_(WINDOW_HEIGHT) {
73 }
74
75 ~Simulator() {
76 // Cleanup GL.
77 glXMakeCurrent(display_, 0, NULL);
78 glXDestroyContext(display_, gl_context_);
79
80 // Destroy window and display.
81 XDestroyWindow(display_, window_);
82 XCloseDisplay(display_);
83 }
84
85 void QueueTest(const FilePath& path) {
86 SimulationSpecification spec;
87
88 // To get a std::string, we'll try to get an ASCII simulation name.
89 // If the name of the file wasn't ASCII, this will give an empty simulation
90 // name, but that's not really harmful (we'll still warn about it though.)
91 spec.simulation_name = path.BaseName().RemoveExtension().MaybeAsASCII();
92 if (spec.simulation_name == "") {
93 LOG(WARNING) << "Simulation for path " << path.LossyDisplayName() <<
94 " will have a blank simulation name, since the file name isn't ASCII";
95 }
96 spec.input_path = path;
97 spec.model_under_test = ForwardRenderModel;
98 spec.frames_rendered = 0;
99
100 sims_remaining_.push(spec);
101
102 // The following lines are commented out pending the addition
103 // of the new render model once this version gets fully checked in.
104 //
105 // spec.model_under_test = KDTreeRenderModel;
106 // sims_remaining_.push(spec);
107 }
108
109 void Run() {
110 if (!sims_remaining_.size()) {
111 LOG(WARNING) << "No configuration files loaded.";
112 return;
113 }
114
115 base::AtExitManager at_exit;
116 MessageLoop loop;
117 if (!InitX11() || !InitGLContext()) {
118 LOG(FATAL) << "Failed to set up GUI.";
119 }
120
121 InitBuffers();
122
123 LOG(INFO) << "Running " << sims_remaining_.size() << " simulations.";
124
125 loop.PostTask(FROM_HERE, NewRunnableFunction(&_process_events, this));
126 loop.Run();
127 }
128
129 void ProcessEvents() {
130 // Consume all the X events.
131 while (XPending(display_)) {
132 XEvent e;
133 XNextEvent(display_, &e);
134 switch (e.type) {
135 case Expose:
136 UpdateLoop();
137 break;
138 case ConfigureNotify:
139 Resize(e.xconfigure.width, e.xconfigure.height);
piman 2011/08/26 02:24:16 If you intend to fall-through, you need to be expl
140 default:
141 break;
142 }
143 }
144 }
145
146 void UpdateLoop() {
147 if (UpdateTestStatus())
148 UpdateCurrentTest();
149 }
150 private:
piman 2011/08/26 02:24:16 nit: blank line before private:
151 // Initialize X11. Returns true if successful. This method creates the
152 // X11 window. Further initialization is done in X11VideoRenderer.
153 bool InitX11() {
154 display_ = XOpenDisplay(NULL);
155 if (!display_) {
156 LOG(FATAL) << "Cannot open display";
157 return false;
158 }
159
160 // Get properties of the screen.
161 int screen = DefaultScreen(display_);
162 int root_window = RootWindow(display_, screen);
163
164 // Creates the window.
165 window_ = XCreateSimpleWindow(display_,
166 root_window,
piman 2011/08/26 02:24:16 nit: indentation (align with display_ above).
167 1,
168 1,
169 window_width_,
170 window_height_,
171 0,
172 BlackPixel(display_, screen),
173 BlackPixel(display_, screen));
174 XStoreName(display_, window_, "Compositor Model Bench");
175
176 XSelectInput(display_, window_,
177 ExposureMask | KeyPressMask | StructureNotifyMask);
178 XMapWindow(display_, window_);
179
180 XResizeWindow(display_, window_, WINDOW_WIDTH, WINDOW_HEIGHT);
181
182 return true;
183 }
184
185 // Initialize the OpenGL context.
186 bool InitGLContext() {
187 if (!InitializeGLBindings(gfx::kGLImplementationDesktopGL)) {
188 LOG(FATAL) << "InitializeGLBindings failed";
189 return false;
190 }
191
192 XWindowAttributes attributes;
193 XGetWindowAttributes(display_, window_, &attributes);
194 XVisualInfo visual_info_template;
195 visual_info_template.visualid = XVisualIDFromVisual(attributes.visual);
196 int visual_info_count = 0;
197 XVisualInfo* visual_info_list = XGetVisualInfo(display_, VisualIDMask,
198 &visual_info_template,
199 &visual_info_count);
200
201 for (int i = 0; i < visual_info_count && !gl_context_; ++i) {
202 gl_context_ = glXCreateContext(display_, visual_info_list + i, 0,
203 True /* Direct rendering */);
piman 2011/08/26 02:24:16 nit: indentation
204 }
205
206 XFree(visual_info_list);
207 if (!gl_context_) {
208 return false;
209 }
210
211 if (!glXMakeCurrent(display_, window_, gl_context_)) {
212 glXDestroyContext(display_, gl_context_);
213 gl_context_ = NULL;
214 return false;
215 }
216
217 return true;
218 }
219
220 bool InitializeNextTest() {
221 SimulationSpecification& spec = sims_remaining_.front();
222 LOG(INFO) << "Initializing test for " << spec.simulation_name <<
223 "(" << ModelToString(spec.model_under_test) << ")";
piman 2011/08/26 02:24:16 nit: indentation (continuations are 4 spaces).
224 const FilePath& path = spec.input_path;
225
226 RenderNode* root = NULL;
227 if (!(root = BuildRenderTreeFromFile(path))) {
228 LOG(ERROR) << "Couldn't parse test configuration file " <<
229 path.LossyDisplayName();
piman 2011/08/26 02:24:16 nit: indentation (4 spaces)
230 return false;
231 }
232
233 current_sim_ = ConstructSimulationModel(spec.model_under_test,
234 root,
piman 2011/08/26 02:24:16 nit: intdentation (arguments should align)
235 window_width_,
236 window_height_);
237 if (!current_sim_)
238 return false;
239
240 return true;
241 }
242
243 void CleanupCurrentTest() {
244 LOG(INFO) << "Finished test " << sims_remaining_.front().simulation_name;
245
246 delete current_sim_;
247 current_sim_ = NULL;
248 }
249
250 void UpdateCurrentTest() {
251 ++sims_remaining_.front().frames_rendered;
252
253 if (current_sim_)
254 current_sim_->Update();
255
256 glXSwapBuffers(display_, window_);
257
258 XExposeEvent ev = { Expose, 0, 1, display_, window_,
259 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0 };
260 XSendEvent(display_,
261 window_,
262 False,
263 ExposureMask,
264 reinterpret_cast<XEvent*>(&ev));
265
266 MessageLoop::current()->PostTask(FROM_HERE,
267 NewRunnableFunction(&_update_loop, this));
268 }
269
270 void DumpOutput() {
271 LOG(INFO) << "Successfully ran " << sims_completed_.size() << " tests";
272
273 FILE* f = OpenFile(output_path_, "w");
274
275 if (!f) {
276 LOG(ERROR) << "Failed to open output file " <<
277 output_path_.LossyDisplayName();
278 exit(-1);
279 }
280
281 LOG(INFO) << "Writing results to " << output_path_.LossyDisplayName();
282
283 fputs("{\n\t\"results\": [\n", f);
284
285 while (sims_completed_.size()) {
286 SimulationSpecification i = sims_completed_.front();
287 fprintf(f,
288 "\t\t{\"simulation_name\":\"%s\",\n"
289 "\t\t\t\"render_model\":\"%s\",\n"
290 "\t\t\t\"frames_drawn\":%d\n"
291 "\t\t},\n",
292 i.simulation_name.c_str(),
293 ModelToString(i.model_under_test),
294 i.frames_rendered);
295 sims_completed_.pop();
296 }
297
298 fputs("\t]\n}", f);
299 CloseFile(f);
300 }
301
302 bool UpdateTestStatus() {
303 TimeTicks& current_start = sims_remaining_.front().simulation_start_time;
304 base::TimeDelta d = TimeTicks::Now() - current_start;
305 if (!current_start.is_null() && d.InSeconds() > seconds_per_test_) {
306 CleanupCurrentTest();
307 sims_completed_.push(sims_remaining_.front());
308 sims_remaining_.pop();
309 }
310
311 if (sims_remaining_.size() &&
312 sims_remaining_.front().simulation_start_time.is_null()) {
313 while (sims_remaining_.size() && !InitializeNextTest()) {
314 sims_remaining_.pop();
315 }
316 if (sims_remaining_.size()) {
317 sims_remaining_.front().simulation_start_time = TimeTicks::Now();
318 }
319 }
320
321 if (!sims_remaining_.size()) {
322 DumpOutput();
323 MessageLoop::current()->Quit();
324 return false;
325 }
326
327 return true;
328 }
329
330 void Resize(int width, int height) {
331 window_width_ = width;
332 window_height_ = height;
333 if (current_sim_)
334 current_sim_->Resize(window_width_, window_height_);
335 }
336
337 // Simulation task list for this execution
338 bool running_;
339 RenderModelSimulator* current_sim_;
340 queue<SimulationSpecification> sims_remaining_;
341 queue<SimulationSpecification> sims_completed_;
342 FilePath output_path_;
343 // Amount of time to run each simulation
344 int seconds_per_test_;
345 // GUI data
346 Display* display_;
347 Window window_;
348 GLXContext gl_context_;
349 int window_width_;
350 int window_height_;
351 };
352
353 // This is a wrapper to forward into our Simulator instance.
354 void _process_events(Simulator* sim) {
piman 2011/08/26 02:24:16 This wrapper is not necessary, you can use NewRunn
355 sim->ProcessEvents();
356 }
357
358 // This is a wrapper to forward into our Simulator instance.
359 void _update_loop(Simulator* sim) {
360 sim->UpdateLoop();
361 }
362
363 int main(int argc, char* argv[]) {
364 CommandLine::Init(argc, argv);
365 const CommandLine* cl = CommandLine::ForCurrentProcess();
366
367 if (argc != 3 && argc != 4) {
368 LOG(INFO) << "Usage: \n" <<
369 cl->GetProgram().BaseName().LossyDisplayName() <<
370 "--in=[input path] --out=[output path] (duration=[seconds])\n"
371 "The input path specifies either a JSON configuration file or\n"
372 "a directory containing only these files\n"
373 "(if a directory is specified, simulations will be run for\n"
374 "all files in that directory and subdirectories)\n"
375 "The optional duration parameter specifies the (integer)\n"
376 "number of seconds to be spent on each simulation.\n"
377 "Performance measurements for the specified simulation(s) are\n"
378 "written to the output path.";
379 return -1;
380 }
381
382 int seconds_per_test = 1;
383 if (cl->HasSwitch("duration")) {
384 seconds_per_test = atoi(cl->GetSwitchValueASCII("duration").c_str());
385 }
386
387 Simulator sim(seconds_per_test, cl->GetSwitchValuePath("out"));
388 FilePath inPath = cl->GetSwitchValuePath("in");
389
390 if (!PathExists(inPath)) {
391 LOG(FATAL) << "Path does not exist: " << inPath.LossyDisplayName();
392 return -1;
393 }
394
395 if (DirectoryExists(inPath)) {
396 LOG(INFO) << "(input path is a directory)";
397 FileEnumerator dirItr(inPath, true, FileEnumerator::FILES);
398 for (FilePath f = dirItr.Next(); !f.empty(); f = dirItr.Next()) {
399 sim.QueueTest(f);
400 }
401 } else {
402 LOG(INFO) << "(input path is a file)";
403 sim.QueueTest(inPath);
404 }
405
406 sim.Run();
407
408 return 0;
409 }
410
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698