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

Unified 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, 4 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « build/all.gyp ('k') | gpu/tools/compositor_model_bench/forward_render_model.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: gpu/tools/compositor_model_bench/compositor_model_bench.cc
===================================================================
--- gpu/tools/compositor_model_bench/compositor_model_bench.cc (revision 0)
+++ gpu/tools/compositor_model_bench/compositor_model_bench.cc (revision 0)
@@ -0,0 +1,406 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This tool is used to benchmark the render model used by the compositor
+
+// Most of this file is derived from the source of the tile_render_bench tool,
+// and has been changed to support running a sequence of independent
+// simulations for our different render models and test cases.
+
+#include <stdio.h>
+#include <sys/dir.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <X11/keysym.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#include <queue>
+#include <string>
+#include <vector>
+
+#include "base/at_exit.h"
+#include "base/basictypes.h"
+#include "base/command_line.h"
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop.h"
+#include "base/task.h"
+#include "base/time.h"
+
+#include "gpu/tools/compositor_model_bench/render_model_utils.h"
+#include "gpu/tools/compositor_model_bench/render_models.h"
+#include "gpu/tools/compositor_model_bench/render_tree.h"
+
+
+using base::TimeTicks;
+using file_util::CloseFile;
+using file_util::DirectoryExists;
+using file_util::FileEnumerator;
+using file_util::OpenFile;
+using file_util::PathExists;
+using std::queue;
+using std::string;
+
+struct SimulationSpecification {
+ string simulation_name;
+ FilePath input_path;
+ RenderModel model_under_test;
+ TimeTicks simulation_start_time;
+ int frames_rendered;
+};
+
+// Forward declarations
+class Simulator;
+void _process_events(Simulator* sim);
+void _update_loop(Simulator* sim);
+
+class Simulator {
+ public:
+ Simulator(int seconds_per_test, const FilePath& output_path)
+ : running_(false),
+ current_sim_(NULL),
+ output_path_(output_path),
+ seconds_per_test_(seconds_per_test),
+ ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)),
+ display_(NULL),
+ window_(0),
+ gl_context_(NULL),
+ window_width_(WINDOW_WIDTH),
+ window_height_(WINDOW_HEIGHT) {
+ }
+
+ ~Simulator() {
+ // Cleanup GL.
+ glXMakeCurrent(display_, 0, NULL);
+ glXDestroyContext(display_, gl_context_);
+
+ // Destroy window and display.
+ XDestroyWindow(display_, window_);
+ XCloseDisplay(display_);
+ }
+
+ void QueueTest(const FilePath& path) {
+ SimulationSpecification spec;
+
+ // To get a std::string, we'll try to get an ASCII simulation name.
+ // If the name of the file wasn't ASCII, this will give an empty simulation
+ // name, but that's not really harmful (we'll still warn about it though.)
+ spec.simulation_name = path.BaseName().RemoveExtension().MaybeAsASCII();
+ if (spec.simulation_name == "") {
+ LOG(WARNING) << "Simulation for path " << path.LossyDisplayName() <<
+ " will have a blank simulation name, since the file name isn't ASCII";
+ }
+ spec.input_path = path;
+ spec.model_under_test = ForwardRenderModel;
+ spec.frames_rendered = 0;
+
+ sims_remaining_.push(spec);
+
+ // The following lines are commented out pending the addition
+ // of the new render model once this version gets fully checked in.
+ //
+ // spec.model_under_test = KDTreeRenderModel;
+ // sims_remaining_.push(spec);
+ }
+
+ void Run() {
+ if (!sims_remaining_.size()) {
+ LOG(WARNING) << "No configuration files loaded.";
+ return;
+ }
+
+ base::AtExitManager at_exit;
+ MessageLoop loop;
+ if (!InitX11() || !InitGLContext()) {
+ LOG(FATAL) << "Failed to set up GUI.";
+ }
+
+ InitBuffers();
+
+ LOG(INFO) << "Running " << sims_remaining_.size() << " simulations.";
+
+ loop.PostTask(FROM_HERE,
+ method_factory_.NewRunnableMethod(&Simulator::ProcessEvents));
+ loop.Run();
+ }
+
+ void ProcessEvents() {
+ // Consume all the X events.
+ while (XPending(display_)) {
+ XEvent e;
+ XNextEvent(display_, &e);
+ switch (e.type) {
+ case Expose:
+ UpdateLoop();
+ break;
+ case ConfigureNotify:
+ Resize(e.xconfigure.width, e.xconfigure.height);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ void UpdateLoop() {
+ if (UpdateTestStatus())
+ UpdateCurrentTest();
+ }
+
+ private:
+ // Initialize X11. Returns true if successful. This method creates the
+ // X11 window. Further initialization is done in X11VideoRenderer.
+ bool InitX11() {
+ display_ = XOpenDisplay(NULL);
+ if (!display_) {
+ LOG(FATAL) << "Cannot open display";
+ return false;
+ }
+
+ // Get properties of the screen.
+ int screen = DefaultScreen(display_);
+ int root_window = RootWindow(display_, screen);
+
+ // Creates the window.
+ window_ = XCreateSimpleWindow(display_,
+ root_window,
+ 1,
+ 1,
+ window_width_,
+ window_height_,
+ 0,
+ BlackPixel(display_, screen),
+ BlackPixel(display_, screen));
+ XStoreName(display_, window_, "Compositor Model Bench");
+
+ XSelectInput(display_, window_,
+ ExposureMask | KeyPressMask | StructureNotifyMask);
+ XMapWindow(display_, window_);
+
+ XResizeWindow(display_, window_, WINDOW_WIDTH, WINDOW_HEIGHT);
+
+ return true;
+ }
+
+ // Initialize the OpenGL context.
+ bool InitGLContext() {
+ if (!InitializeGLBindings(gfx::kGLImplementationDesktopGL)) {
+ LOG(FATAL) << "InitializeGLBindings failed";
+ return false;
+ }
+
+ XWindowAttributes attributes;
+ XGetWindowAttributes(display_, window_, &attributes);
+ XVisualInfo visual_info_template;
+ visual_info_template.visualid = XVisualIDFromVisual(attributes.visual);
+ int visual_info_count = 0;
+ XVisualInfo* visual_info_list = XGetVisualInfo(display_, VisualIDMask,
+ &visual_info_template,
+ &visual_info_count);
+
+ for (int i = 0; i < visual_info_count && !gl_context_; ++i) {
+ gl_context_ = glXCreateContext(display_, visual_info_list + i, 0,
+ True /* Direct rendering */);
+ }
+
+ XFree(visual_info_list);
+ if (!gl_context_) {
+ return false;
+ }
+
+ if (!glXMakeCurrent(display_, window_, gl_context_)) {
+ glXDestroyContext(display_, gl_context_);
+ gl_context_ = NULL;
+ return false;
+ }
+
+ return true;
+ }
+
+ bool InitializeNextTest() {
+ SimulationSpecification& spec = sims_remaining_.front();
+ LOG(INFO) << "Initializing test for " << spec.simulation_name <<
+ "(" << ModelToString(spec.model_under_test) << ")";
+ const FilePath& path = spec.input_path;
+
+ RenderNode* root = NULL;
+ if (!(root = BuildRenderTreeFromFile(path))) {
+ LOG(ERROR) << "Couldn't parse test configuration file " <<
+ path.LossyDisplayName();
+ return false;
+ }
+
+ current_sim_ = ConstructSimulationModel(spec.model_under_test,
+ root,
+ window_width_,
+ window_height_);
+ if (!current_sim_)
+ return false;
+
+ return true;
+ }
+
+ void CleanupCurrentTest() {
+ LOG(INFO) << "Finished test " << sims_remaining_.front().simulation_name;
+
+ delete current_sim_;
+ current_sim_ = NULL;
+ }
+
+ void UpdateCurrentTest() {
+ ++sims_remaining_.front().frames_rendered;
+
+ if (current_sim_)
+ current_sim_->Update();
+
+ glXSwapBuffers(display_, window_);
+
+ XExposeEvent ev = { Expose, 0, 1, display_, window_,
+ 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0 };
+ XSendEvent(display_,
+ window_,
+ False,
+ ExposureMask,
+ reinterpret_cast<XEvent*>(&ev));
+
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ method_factory_.NewRunnableMethod(&Simulator::UpdateLoop));
+ }
+
+ void DumpOutput() {
+ LOG(INFO) << "Successfully ran " << sims_completed_.size() << " tests";
+
+ FILE* f = OpenFile(output_path_, "w");
+
+ if (!f) {
+ LOG(ERROR) << "Failed to open output file " <<
+ output_path_.LossyDisplayName();
+ exit(-1);
+ }
+
+ LOG(INFO) << "Writing results to " << output_path_.LossyDisplayName();
+
+ fputs("{\n\t\"results\": [\n", f);
+
+ while (sims_completed_.size()) {
+ SimulationSpecification i = sims_completed_.front();
+ fprintf(f,
+ "\t\t{\"simulation_name\":\"%s\",\n"
+ "\t\t\t\"render_model\":\"%s\",\n"
+ "\t\t\t\"frames_drawn\":%d\n"
+ "\t\t},\n",
+ i.simulation_name.c_str(),
+ ModelToString(i.model_under_test),
+ i.frames_rendered);
+ sims_completed_.pop();
+ }
+
+ fputs("\t]\n}", f);
+ CloseFile(f);
+ }
+
+ bool UpdateTestStatus() {
+ TimeTicks& current_start = sims_remaining_.front().simulation_start_time;
+ base::TimeDelta d = TimeTicks::Now() - current_start;
+ if (!current_start.is_null() && d.InSeconds() > seconds_per_test_) {
+ CleanupCurrentTest();
+ sims_completed_.push(sims_remaining_.front());
+ sims_remaining_.pop();
+ }
+
+ if (sims_remaining_.size() &&
+ sims_remaining_.front().simulation_start_time.is_null()) {
+ while (sims_remaining_.size() && !InitializeNextTest()) {
+ sims_remaining_.pop();
+ }
+ if (sims_remaining_.size()) {
+ sims_remaining_.front().simulation_start_time = TimeTicks::Now();
+ }
+ }
+
+ if (!sims_remaining_.size()) {
+ DumpOutput();
+ MessageLoop::current()->Quit();
+ return false;
+ }
+
+ return true;
+ }
+
+ void Resize(int width, int height) {
+ window_width_ = width;
+ window_height_ = height;
+ if (current_sim_)
+ current_sim_->Resize(window_width_, window_height_);
+ }
+
+ // Simulation task list for this execution
+ bool running_;
+ RenderModelSimulator* current_sim_;
+ queue<SimulationSpecification> sims_remaining_;
+ queue<SimulationSpecification> sims_completed_;
+ FilePath output_path_;
+ // Amount of time to run each simulation
+ int seconds_per_test_;
+ // GUI data
+ ScopedRunnableMethodFactory<Simulator> method_factory_;
+ Display* display_;
+ Window window_;
+ GLXContext gl_context_;
+ int window_width_;
+ int window_height_;
+};
+
+int main(int argc, char* argv[]) {
+ CommandLine::Init(argc, argv);
+ const CommandLine* cl = CommandLine::ForCurrentProcess();
+
+ if (argc != 3 && argc != 4) {
+ LOG(INFO) << "Usage: \n" <<
+ cl->GetProgram().BaseName().LossyDisplayName() <<
+ "--in=[input path] --out=[output path] (duration=[seconds])\n"
+ "The input path specifies either a JSON configuration file or\n"
+ "a directory containing only these files\n"
+ "(if a directory is specified, simulations will be run for\n"
+ "all files in that directory and subdirectories)\n"
+ "The optional duration parameter specifies the (integer)\n"
+ "number of seconds to be spent on each simulation.\n"
+ "Performance measurements for the specified simulation(s) are\n"
+ "written to the output path.";
+ return -1;
+ }
+
+ int seconds_per_test = 1;
+ if (cl->HasSwitch("duration")) {
+ seconds_per_test = atoi(cl->GetSwitchValueASCII("duration").c_str());
+ }
+
+ Simulator sim(seconds_per_test, cl->GetSwitchValuePath("out"));
+ FilePath inPath = cl->GetSwitchValuePath("in");
+
+ if (!PathExists(inPath)) {
+ LOG(FATAL) << "Path does not exist: " << inPath.LossyDisplayName();
+ return -1;
+ }
+
+ if (DirectoryExists(inPath)) {
+ LOG(INFO) << "(input path is a directory)";
+ FileEnumerator dirItr(inPath, true, FileEnumerator::FILES);
+ for (FilePath f = dirItr.Next(); !f.empty(); f = dirItr.Next()) {
+ sim.QueueTest(f);
+ }
+ } else {
+ LOG(INFO) << "(input path is a file)";
+ sim.QueueTest(inPath);
+ }
+
+ sim.Run();
+
+ return 0;
+}
+
« no previous file with comments | « build/all.gyp ('k') | gpu/tools/compositor_model_bench/forward_render_model.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698