From patchwork Thu Jul 21 12:36:36 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: alexandros.frantzis@linaro.org X-Patchwork-Id: 2956 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 5BBAF23F4D for ; Thu, 21 Jul 2011 12:42:49 +0000 (UTC) Received: from mail-qw0-f52.google.com (mail-qw0-f52.google.com [209.85.216.52]) by fiordland.canonical.com (Postfix) with ESMTP id 2AA72A18287 for ; Thu, 21 Jul 2011 12:42:49 +0000 (UTC) Received: by mail-qw0-f52.google.com with SMTP id 8so853237qwb.11 for ; Thu, 21 Jul 2011 05:42:49 -0700 (PDT) Received: by 10.224.195.193 with SMTP id ed1mr180468qab.162.1311252168963; Thu, 21 Jul 2011 05:42:48 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.229.217.78 with SMTP id hl14cs139514qcb; Thu, 21 Jul 2011 05:42:48 -0700 (PDT) Received: by 10.227.11.65 with SMTP id s1mr158250wbs.108.1311251797379; Thu, 21 Jul 2011 05:36:37 -0700 (PDT) Received: from adelie.canonical.com (adelie.canonical.com [91.189.90.139]) by mx.google.com with ESMTP id fm12si2380163wbb.87.2011.07.21.05.36.36; Thu, 21 Jul 2011 05:36:37 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of bounces@canonical.com designates 91.189.90.139 as permitted sender) client-ip=91.189.90.139; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of bounces@canonical.com designates 91.189.90.139 as permitted sender) smtp.mail=bounces@canonical.com Received: from loganberry.canonical.com ([91.189.90.37]) by adelie.canonical.com with esmtp (Exim 4.71 #1 (Debian)) id 1QjsUW-0000Cq-28 for ; Thu, 21 Jul 2011 12:36:36 +0000 Received: from loganberry.canonical.com (localhost [127.0.0.1]) by loganberry.canonical.com (Postfix) with ESMTP id 0EAC72E890E for ; Thu, 21 Jul 2011 12:36:36 +0000 (UTC) MIME-Version: 1.0 X-Launchpad-Project: glmark2 X-Launchpad-Branch: ~glmark2-dev/glmark2/trunk X-Launchpad-Message-Rationale: Subscriber X-Launchpad-Branch-Revision-Number: 83 X-Launchpad-Notification-Type: branch-revision To: Linaro Patch Tracker From: noreply@launchpad.net Subject: [Branch ~glmark2-dev/glmark2/trunk] Rev 83: Merge validation branch. Message-Id: <20110721123636.17019.83316.launchpad@loganberry.canonical.com> Date: Thu, 21 Jul 2011 12:36:36 -0000 Reply-To: noreply@launchpad.net Sender: bounces@canonical.com Errors-To: bounces@canonical.com Precedence: bulk X-Generated-By: Launchpad (canonical.com); Revision="13475"; Instance="initZopeless config overlay" X-Launchpad-Hash: 8e67a3d12425d1eb63ff640c724c36cc8cea9ac6 Merge authors: Alexandros Frantzis (afrantzis) ------------------------------------------------------------ revno: 83 [merge] committer: Alexandros Frantzis timestamp: Thu 2011-06-16 12:54:42 +0300 message: Merge validation branch. modified: src/log.cpp src/log.h src/main.cpp src/options.cpp src/options.h src/scene.cpp src/scene.h src/scenebuild.cpp src/sceneshading.cpp src/scenetexture.cpp src/screen-sdl-gl.cpp src/screen-sdl-gl.h src/screen-sdl-glesv2.cpp src/screen-sdl-glesv2.h src/screen.h --- lp:glmark2 https://code.launchpad.net/~glmark2-dev/glmark2/trunk You are subscribed to branch lp:glmark2. To unsubscribe from this branch go to https://code.launchpad.net/~glmark2-dev/glmark2/trunk/+edit-subscription === modified file 'src/log.cpp' --- src/log.cpp 2011-06-08 11:24:18 +0000 +++ src/log.cpp 2011-06-15 11:33:20 +0000 @@ -56,3 +56,9 @@ va_end(ap); } +void +Log::flush() +{ + fflush(stdout); + fflush(stderr); +} === modified file 'src/log.h' --- src/log.h 2011-06-08 11:24:18 +0000 +++ src/log.h 2011-06-15 11:33:20 +0000 @@ -30,6 +30,7 @@ static void info(const char *fmt, ...); static void debug(const char *fmt, ...); static void error(const char *fmt, ...); + static void flush(); }; #endif /* LOG_H_ */ === modified file 'src/main.cpp' --- src/main.cpp 2011-06-10 11:27:56 +0000 +++ src/main.cpp 2011-06-15 11:36:32 +0000 @@ -119,9 +119,86 @@ } } +void +do_benchmark(Screen &screen, vector &benchmarks) +{ + unsigned score = 0; + + for (vector::iterator bench_iter = benchmarks.begin(); + bench_iter != benchmarks.end(); + bench_iter++) + { + bool keep_running = true; + Benchmark *bench = *bench_iter; + Scene &scene = bench->setup_scene(); + Log::info("%s", scene.info_string().c_str()); + Log::flush(); + + while (scene.is_running() && + (keep_running = should_keep_running())) + { + screen.clear(); + + scene.draw(); + scene.update(); + + screen.update(); + } + + Log::info(" FPS: %u\n", scene.average_fps()); + score += scene.average_fps(); + + bench->teardown_scene(); + + if (!keep_running) + break; + } + + Log::info("=======================================================\n"); + Log::info(" glmark2 Score: %u \n", score); + Log::info("=======================================================\n"); + +} + +void +do_validation(Screen &screen, vector &benchmarks) +{ + for (vector::iterator bench_iter = benchmarks.begin(); + bench_iter != benchmarks.end(); + bench_iter++) + { + Benchmark *bench = *bench_iter; + Scene &scene = bench->setup_scene(); + Log::info("%s", scene.info_string().c_str()); + Log::flush(); + + screen.clear(); + scene.draw(); + screen.update(); + + string result; + switch(scene.validate()) { + case Scene::ValidationSuccess: + result = "Success"; + break; + case Scene::ValidationFailure: + result = "Failure"; + break; + case Scene::ValidationUnknown: + result = "Unknown"; + break; + default: + break; + } + + Log::info(" Validation: %s\n", result.c_str()); + + bench->teardown_scene(); + } +} + int main(int argc, char *argv[]) { - unsigned score = 0; if (!Options::parse_args(argc, argv)) return 1; @@ -139,7 +216,7 @@ #endif if (!screen.mInitSuccess) { - printf("Error: %s: Could not initialize screen\n", __FUNCTION__); + Log::error("Error: %s: Could not initialize screen\n", __FUNCTION__); return 1; } @@ -161,45 +238,16 @@ else add_custom_benchmarks(benchmarks); - printf("=======================================================\n"); - printf(" glmark2 %s\n", GLMARK_VERSION); - printf("=======================================================\n"); + Log::info("=======================================================\n"); + Log::info(" glmark2 %s\n", GLMARK_VERSION); + Log::info("=======================================================\n"); screen.print_info(); - printf("=======================================================\n"); - - // Run the benchmarks - for (vector::iterator bench_iter = benchmarks.begin(); - bench_iter != benchmarks.end(); - bench_iter++) - { - bool keep_running = true; - Benchmark *bench = *bench_iter; - Scene &scene = bench->setup_scene(); - std::cout << scene.info_string() << std::flush; - - while (scene.is_running() && - (keep_running = should_keep_running())) - { - screen.clear(); - - scene.draw(); - scene.update(); - - screen.update(); - } - - std::cout << " FPS: " << scene.average_fps() << std::endl; - score += scene.average_fps(); - - bench->teardown_scene(); - - if (!keep_running) - break; - } - - printf("=======================================================\n"); - printf(" glmark2 Score: %u \n", score); - printf("=======================================================\n"); + Log::info("=======================================================\n"); + + if (Options::validate) + do_validation(screen, benchmarks); + else + do_benchmark(screen, benchmarks); return 0; } === modified file 'src/options.cpp' --- src/options.cpp 2011-06-09 14:54:24 +0000 +++ src/options.cpp 2011-06-15 11:25:14 +0000 @@ -29,6 +29,7 @@ #include "options.h" std::vector Options::benchmarks; +bool Options::validate = false; bool Options::swap_buffers = true; bool Options::list_scenes = false; bool Options::show_debug = false; @@ -36,6 +37,7 @@ static struct option long_options[] = { {"benchmark", 1, 0, 0}, + {"validate", 0, 0, 0}, {"no-swap-buffers", 0, 0, 0}, {"list-scenes", 0, 0, 0}, {"debug", 0, 0, 0}, @@ -51,6 +53,8 @@ "Options:\n" " -b, --benchmark BENCH A benchmark to run: 'scene(:opt1=val1)*'\n" " (the option can be used multiple times)\n" + " --validate Run a quick output validation test instead of \n" + " running the benchmarks\n" " --no-swap-buffers Don't update the screen by swapping the front and\n" " back buffer, use glFinish() instead\n" " -l, --list-scenes Display information about the available scenes\n" @@ -79,6 +83,8 @@ if (c == 'b' || !strcmp(optname, "benchmark")) Options::benchmarks.push_back(optarg); + else if (!strcmp(optname, "validate")) + Options::validate = true; else if (!strcmp(optname, "no-swap-buffers")) Options::swap_buffers = false; else if (c == 'l' || !strcmp(optname, "list-scenes")) === modified file 'src/options.h' --- src/options.h 2011-06-09 14:24:50 +0000 +++ src/options.h 2011-06-15 11:25:14 +0000 @@ -32,6 +32,7 @@ static void print_help(); static std::vector benchmarks; + static bool validate; static bool swap_buffers; static bool list_scenes; static bool show_debug; === modified file 'src/scene.cpp' --- src/scene.cpp 2011-06-07 21:06:38 +0000 +++ src/scene.cpp 2011-06-15 11:20:45 +0000 @@ -23,6 +23,7 @@ */ #include "scene.h" #include +#include using std::stringstream; using std::string; @@ -133,4 +134,23 @@ ss << title; return ss.str(); + +} + +double +Scene::pixel_value_distance(Screen::Pixel p1, Screen::Pixel p2, + bool use_alpha) +{ + double s(0.0); + + // These work without casts because of integer promotion rules + // (the Uint8s are promoted to ints) + s += (p1.r - p2.r) * (p1.r - p2.r); + s += (p1.g - p2.g) * (p1.g - p2.g); + s += (p1.b - p2.b) * (p1.b - p2.b); + + if (use_alpha) + s += (p1.a - p2.a) * (p1.a - p2.a); + + return std::sqrt(s); } === modified file 'src/scene.h' --- src/scene.h 2011-06-09 13:07:57 +0000 +++ src/scene.h 2011-06-16 07:43:05 +0000 @@ -51,6 +51,12 @@ std::string description; }; + enum ValidationResult { + ValidationFailure, + ValidationSuccess, + ValidationUnknown + }; + // load() and unload() handle option-independent configuration. // It should be safe to call these only once per program execution, // although you may choose to do so more times to better manage @@ -82,9 +88,13 @@ return dummy_scene; } + virtual ValidationResult validate() { return ValidationUnknown; } + protected: Scene(Screen &pScreen, const std::string &name); std::string construct_title(const std::string &title); + double pixel_value_distance(Screen::Pixel p1, Screen::Pixel p2, + bool use_alpha=false); Screen &mScreen; std::string mName; @@ -109,6 +119,7 @@ void teardown(); void update(); void draw(); + ValidationResult validate(); ~SceneBuild(); @@ -131,6 +142,7 @@ void teardown(); void update(); void draw(); + ValidationResult validate(); ~SceneTexture(); @@ -153,6 +165,7 @@ void teardown(); void update(); void draw(); + ValidationResult validate(); ~SceneShading(); === modified file 'src/scenebuild.cpp' --- src/scenebuild.cpp 2011-06-07 14:36:16 +0000 +++ src/scenebuild.cpp 2011-06-15 11:44:36 +0000 @@ -22,6 +22,8 @@ * Alexandros Frantzis (glmark2) */ #include "scene.h" +#include "log.h" +#include SceneBuild::SceneBuild(Screen &pScreen) : Scene(pScreen, "build") @@ -146,3 +148,26 @@ else mMesh.render_array(); } + +Scene::ValidationResult +SceneBuild::validate() +{ + static const double radius_3d(std::sqrt(3.0)); + + if (mRotation != 0) + return Scene::ValidationUnknown; + + Screen::Pixel ref(0xa7, 0xa7, 0xa7, 0xff); + Screen::Pixel pixel = mScreen.read_pixel(mScreen.mWidth / 2, + mScreen.mHeight / 2); + + double dist = pixel_value_distance(pixel, ref); + if (dist < radius_3d + 0.01) { + return Scene::ValidationSuccess; + } + else { + Log::debug("Validation failed! Expected: 0x%x Actual: 0x%x Distance: %f\n", + ref.to_le32(), pixel.to_le32(), dist); + return Scene::ValidationFailure; + } +} === modified file 'src/sceneshading.cpp' --- src/sceneshading.cpp 2011-06-07 21:06:38 +0000 +++ src/sceneshading.cpp 2011-06-16 07:43:05 +0000 @@ -23,6 +23,9 @@ */ #include "scene.h" #include "matrix.h" +#include "log.h" + +#include SceneShading::SceneShading(Screen &pScreen) : Scene(pScreen, "shading") @@ -160,3 +163,37 @@ mMesh.render_vbo(); } + +Scene::ValidationResult +SceneShading::validate() +{ + static const double radius_3d(std::sqrt(3.0)); + + if (mRotation != 0) + return Scene::ValidationUnknown; + + Screen::Pixel ref; + + Screen::Pixel pixel = mScreen.read_pixel(mScreen.mWidth / 2, + mScreen.mHeight / 2); + + const std::string &filter = mOptions["shading"].value; + + if (filter == "gouraud") + ref = Screen::Pixel(0x00, 0x00, 0xca, 0xff); + else if (filter == "phong") + ref = Screen::Pixel(0x1a, 0x1a, 0xbb, 0xff); + else + return Scene::ValidationUnknown; + + double dist = pixel_value_distance(pixel, ref); + + if (dist < radius_3d + 0.01) { + return Scene::ValidationSuccess; + } + else { + Log::debug("Validation failed! Expected: 0x%x Actual: 0x%x Distance: %f\n", + ref.to_le32(), pixel.to_le32(), dist); + return Scene::ValidationFailure; + } +} === modified file 'src/scenetexture.cpp' --- src/scenetexture.cpp 2011-06-07 21:06:38 +0000 +++ src/scenetexture.cpp 2011-06-16 07:39:55 +0000 @@ -23,6 +23,9 @@ */ #include "scene.h" #include "matrix.h" +#include "log.h" + +#include SceneTexture::SceneTexture(Screen &pScreen) : Scene(pScreen, "texture") @@ -161,3 +164,39 @@ mCubeMesh.render_vbo(); } + +Scene::ValidationResult +SceneTexture::validate() +{ + static const double radius_3d(std::sqrt(3.0)); + + if (mRotation.x != 0 || mRotation.y != 0 || mRotation.z != 0) + return Scene::ValidationUnknown; + + Screen::Pixel ref; + + Screen::Pixel pixel = mScreen.read_pixel(mScreen.mWidth / 2, + mScreen.mHeight / 2); + + const std::string &filter = mOptions["texture-filter"].value; + + if (filter == "nearest") + ref = Screen::Pixel(0x3a, 0x3a, 0x3b, 0xff); + else if (filter == "linear") + ref = Screen::Pixel(0x34, 0x34, 0x35, 0xff); + else if (filter == "mipmap") + ref = Screen::Pixel(0x33, 0x33, 0x35, 0xff); + else + return Scene::ValidationUnknown; + + double dist = pixel_value_distance(pixel, ref); + + if (dist < radius_3d + 0.01) { + return Scene::ValidationSuccess; + } + else { + Log::debug("Validation failed! Expected: 0x%x Actual: 0x%x Distance: %f\n", + ref.to_le32(), pixel.to_le32(), dist); + return Scene::ValidationFailure; + } +} === modified file 'src/screen-sdl-gl.cpp' --- src/screen-sdl-gl.cpp 2011-06-09 10:13:18 +0000 +++ src/screen-sdl-gl.cpp 2011-06-15 10:11:13 +0000 @@ -23,6 +23,7 @@ */ #include "screen-sdl-gl.h" #include "options.h" +#include ScreenSDLGL::ScreenSDLGL(int pWidth, int pHeight, int pBpp, int pFullScreen, int pFlags) : ScreenSDL(pWidth, pHeight, pBpp, pFullScreen, pFlags | SDL_OPENGL) @@ -64,3 +65,29 @@ printf(" GL_RENDERER: %s\n", glGetString(GL_RENDERER)); printf(" GL_VERSION: %s\n", glGetString(GL_VERSION)); } + +Screen::Pixel +ScreenSDLGL::read_pixel(int x, int y) +{ + Uint8 pixel[4]; + + glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel); + + return Screen::Pixel(pixel[0], pixel[1], pixel[2], pixel[3]); +} + +void +ScreenSDLGL::write_to_file(std::string &filename) +{ + char *pixels = new char[mWidth * mHeight * 4]; + + for (int i = 0; i < mHeight; i++) { + glReadPixels(0, i, mWidth, 1, GL_RGBA, GL_UNSIGNED_BYTE, + &pixels[(mHeight - i - 1) * mWidth * 4]); + } + + std::ofstream output(filename.c_str(), std::ios::out | std::ios::binary); + output.write(pixels, 4 * mWidth * mHeight); + + delete [] pixels; +} === modified file 'src/screen-sdl-gl.h' --- src/screen-sdl-gl.h 2011-01-25 15:06:04 +0000 +++ src/screen-sdl-gl.h 2011-06-15 10:11:13 +0000 @@ -35,6 +35,8 @@ virtual void clear(); virtual void update(); virtual void print_info(); + virtual Pixel read_pixel(int x, int y); + virtual void write_to_file(std::string &filename); }; #endif === modified file 'src/screen-sdl-glesv2.cpp' --- src/screen-sdl-glesv2.cpp 2011-06-09 10:13:18 +0000 +++ src/screen-sdl-glesv2.cpp 2011-06-15 10:11:13 +0000 @@ -24,6 +24,7 @@ #include "screen-sdl-glesv2.h" #include "sdlgles/SDL_gles.h" #include "options.h" +#include ScreenSDLGLESv2::ScreenSDLGLESv2(int pWidth, int pHeight, int pBpp, int pFullScreen, int pFlags) : ScreenSDL(pWidth, pHeight, pBpp, pFullScreen, pFlags) @@ -111,3 +112,28 @@ printf(" GL_VERSION: %s\n", glGetString(GL_VERSION)); } +Screen::Pixel +ScreenSDLGLESv2::read_pixel(int x, int y) +{ + Uint8 pixel[4]; + + glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel); + + return Screen::Pixel(pixel[0], pixel[1], pixel[2], pixel[3]); +} + +void +ScreenSDLGLESv2::write_to_file(std::string &filename) +{ + char *pixels = new char[mWidth * mHeight * 4]; + + for (int i = 0; i < mHeight; i++) { + glReadPixels(0, i, mWidth, 1, GL_RGBA, GL_UNSIGNED_BYTE, + &pixels[(mHeight - i - 1) * mWidth * 4]); + } + + std::ofstream output (filename.c_str(), std::ios::out | std::ios::binary); + output.write(pixels, 4 * mWidth * mHeight); + + delete [] pixels; +} === modified file 'src/screen-sdl-glesv2.h' --- src/screen-sdl-glesv2.h 2011-01-25 15:06:04 +0000 +++ src/screen-sdl-glesv2.h 2011-06-15 10:11:13 +0000 @@ -35,6 +35,8 @@ virtual void clear(); virtual void update(); virtual void print_info(); + virtual Pixel read_pixel(int x, int y); + virtual void write_to_file(std::string &filename); }; #endif === modified file 'src/screen.h' --- src/screen.h 2011-06-09 13:07:57 +0000 +++ src/screen.h 2011-06-15 10:11:13 +0000 @@ -27,6 +27,7 @@ #include "oglsdl.h" #include "matrix.h" +#include #include class Screen @@ -34,6 +35,25 @@ public: ~Screen() {} + struct Pixel { + Pixel(): + r(0), g(0), b(0), a(0) {} + Pixel(Uint8 r, Uint8 g, Uint8 b, Uint8 a): + r(r), g(g), b(b), a(a) {} + Uint32 to_le32() + { + return static_cast(r) + + (static_cast(g) << 8) + + (static_cast(b) << 16) + + (static_cast(a) << 24); + + } + Uint8 r; + Uint8 g; + Uint8 b; + Uint8 a; + }; + int mWidth; int mHeight; int mBpp; @@ -44,6 +64,13 @@ virtual void clear() {} virtual void update() {} virtual void print_info() {} + virtual Pixel read_pixel(int x, int y) + { + (void)x; + (void)y; + return Pixel(); + } + virtual void write_to_file(std::string &filename) { (void)filename; } static Screen &dummy() {