blob: 37af73fc98f70640f20dd06c95dc109d670871b9 [file] [log] [blame]
Alexey Marinichev9f9b8732010-05-20 19:33:44 -07001// Copyright (c) 2010 The Chromium OS 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
Alexey Marinichevf50ecb12010-06-14 15:21:41 -07005#include <gflags/gflags.h>
Alexey Marinichev9f9b8732010-05-20 19:33:44 -07006#include <stdio.h>
7
Alexey Marinichevf50ecb12010-06-14 15:21:41 -07008#include "base/scoped_ptr.h"
9#include "base/file_util.h"
10
Alexey Marinichev9f9b8732010-05-20 19:33:44 -070011#include "testbase.h"
Alexey Marinichevf50ecb12010-06-14 15:21:41 -070012#include "utils.h"
13
14DEFINE_bool(save, false, "save images after each test case");
15DEFINE_string(out, "out", "directory to save images");
Alexey Marinichev9f9b8732010-05-20 19:33:44 -070016
17namespace glbench {
18
19uint64_t TimeTest(TestBase* test, int iter) {
20 SwapBuffers();
21 glFinish();
22 uint64_t time1 = GetUTime();
Alexey Marinichev9c891ef2010-05-21 15:28:59 -070023 if (!test->TestFunc(iter))
24 return ~0;
Alexey Marinichev9f9b8732010-05-20 19:33:44 -070025 glFinish();
26 uint64_t time2 = GetUTime();
27 return time2 - time1;
28}
29
30#define MAX_ITERATION_DURATION_MS 100000
31
32// Benchmark some draw commands, by running it many times.
33// We want to measure the marginal cost, so we try more and more iterations
34// until we get a somewhat linear response (to eliminate constant cost), and we
35// do a linear regression on a few samples.
36bool Bench(TestBase* test, float *slope, int64_t *bias) {
37 // Do one iteration in case the driver needs to set up states.
38 if (TimeTest(test, 1) > MAX_ITERATION_DURATION_MS)
39 return false;
40 int64_t count = 0;
41 int64_t sum_x = 0;
42 int64_t sum_y = 0;
43 int64_t sum_xy = 0;
44 int64_t sum_x2 = 0;
45 uint64_t last_time = 0;
46 bool do_count = false;
47 uint64_t iter;
48 for (iter = 8; iter < 1<<30; iter *= 2) {
49 uint64_t time = TimeTest(test, iter);
50 if (last_time > 0 && (time > last_time * 1.8))
51 do_count = true;
52 last_time = time;
53 if (do_count) {
54 ++count;
55 sum_x += iter;
56 sum_y += time;
57 sum_xy += iter * time;
58 sum_x2 += iter * iter;
59 }
60 if ((time >= 500000 && count > 4))
61 break;
62 }
63 if (count < 2) {
64 *slope = 0.f;
65 *bias = 0;
66 }
67 *slope = static_cast<float>(sum_x * sum_y - count * sum_xy) /
68 (sum_x * sum_x - count * sum_x2);
69 *bias = (sum_x * sum_xy - sum_x2 * sum_y) / (sum_x * sum_x - count * sum_x2);
70 return true;
71}
72
Alexey Marinichevf50ecb12010-06-14 15:21:41 -070073void SaveImage(const char* name) {
74 const int size = g_width * g_height * 4;
75 scoped_array<char> pixels(new char[size]);
76 glReadPixels(0, 0, g_width, g_height, GL_RGBA, GL_UNSIGNED_BYTE,
77 pixels.get());
78 FilePath dirname = GetBasePath().Append(FLAGS_out);
79 file_util::CreateDirectory(dirname);
80 FilePath filename = dirname.Append(name);
81 file_util::WriteFile(filename, pixels.get(), size);
82}
83
84void RunTest(TestBase* test, const char* name,
Alexey Marinichev9f9b8732010-05-20 19:33:44 -070085 float coefficient, bool inverse) {
86 float slope;
87 int64_t bias;
88
89 GLenum err = glGetError();
90 if (err != 0) {
91 printf("# %s failed, glGetError returned 0x%x.\n", name, err);
92 // float() in python will happily parse Nan.
93 printf("%s: Nan\n", name);
94 } else {
95 if (Bench(test, &slope, &bias)) {
Alexey Marinichevf50ecb12010-06-14 15:21:41 -070096 if (FLAGS_save)
97 SaveImage(name);
Alexey Marinichev9f9b8732010-05-20 19:33:44 -070098 printf("%s: %g\n", name, coefficient * (inverse ? 1.f / slope : slope));
99 } else {
100 printf("# %s is too slow, returning zero.\n", name);
101 printf("%s: 0\n", name);
102 }
103 }
104}
105
106bool DrawArraysTestFunc::TestFunc(int iter) {
107 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
108 glFlush();
109 for (int i = 0; i < iter-1; ++i) {
110 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
111 }
112 return true;
113}
114
115
116void DrawArraysTestFunc::FillRateTestNormal(const char* name) {
117 FillRateTestNormalSubWindow(name, g_width, g_height);
118}
119
120
121void DrawArraysTestFunc::FillRateTestNormalSubWindow(const char* name,
122 float width, float height)
123{
124 const int buffer_len = 64;
125 char buffer[buffer_len];
126 snprintf(buffer, buffer_len, "mpixels_sec_%s", name);
127 RunTest(this, buffer, width * height, true);
128}
129
130
Alexey Marinicheve735df62010-05-24 15:52:07 -0700131#if defined(USE_OPENGL)
Alexey Marinichev9f9b8732010-05-20 19:33:44 -0700132void DrawArraysTestFunc::FillRateTestBlendDepth(const char *name) {
133 const int buffer_len = 64;
134 char buffer[buffer_len];
135
136 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
137 glEnable(GL_BLEND);
138 snprintf(buffer, buffer_len, "mpixels_sec_%s_blended", name);
139 RunTest(this, buffer, g_width * g_height, true);
140 glDisable(GL_BLEND);
141
142 glEnable(GL_DEPTH_TEST);
143 glDepthFunc(GL_NOTEQUAL);
144 snprintf(buffer, buffer_len, "mpixels_sec_%s_depth_neq", name);
145 RunTest(this, buffer, g_width * g_height, true);
146 glDepthFunc(GL_NEVER);
147 snprintf(buffer, buffer_len, "mpixels_sec_%s_depth_never", name);
148 RunTest(this, buffer, g_width * g_height, true);
149 glDisable(GL_DEPTH_TEST);
150}
151#endif
152
153
154bool DrawElementsTestFunc::TestFunc(int iter) {
155 glDrawElements(GL_TRIANGLES, count_, GL_UNSIGNED_INT, 0);
156 glFlush();
157 for (int i = 0 ; i < iter-1; ++i) {
158 glDrawElements(GL_TRIANGLES, count_, GL_UNSIGNED_INT, 0);
159 }
160 return true;
161}
162
163} // namespace glbench