blob: d200266c2893e772ae77e302f363f929b699fa6e [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
5#include <stdio.h>
6
7#include "testbase.h"
8
9namespace glbench {
10
11uint64_t TimeTest(TestBase* test, int iter) {
12 SwapBuffers();
13 glFinish();
14 uint64_t time1 = GetUTime();
Alexey Marinichev9c891ef2010-05-21 15:28:59 -070015 if (!test->TestFunc(iter))
16 return ~0;
Alexey Marinichev9f9b8732010-05-20 19:33:44 -070017 glFinish();
18 uint64_t time2 = GetUTime();
19 return time2 - time1;
20}
21
22#define MAX_ITERATION_DURATION_MS 100000
23
24// Benchmark some draw commands, by running it many times.
25// We want to measure the marginal cost, so we try more and more iterations
26// until we get a somewhat linear response (to eliminate constant cost), and we
27// do a linear regression on a few samples.
28bool Bench(TestBase* test, float *slope, int64_t *bias) {
29 // Do one iteration in case the driver needs to set up states.
30 if (TimeTest(test, 1) > MAX_ITERATION_DURATION_MS)
31 return false;
32 int64_t count = 0;
33 int64_t sum_x = 0;
34 int64_t sum_y = 0;
35 int64_t sum_xy = 0;
36 int64_t sum_x2 = 0;
37 uint64_t last_time = 0;
38 bool do_count = false;
39 uint64_t iter;
40 for (iter = 8; iter < 1<<30; iter *= 2) {
41 uint64_t time = TimeTest(test, iter);
42 if (last_time > 0 && (time > last_time * 1.8))
43 do_count = true;
44 last_time = time;
45 if (do_count) {
46 ++count;
47 sum_x += iter;
48 sum_y += time;
49 sum_xy += iter * time;
50 sum_x2 += iter * iter;
51 }
52 if ((time >= 500000 && count > 4))
53 break;
54 }
55 if (count < 2) {
56 *slope = 0.f;
57 *bias = 0;
58 }
59 *slope = static_cast<float>(sum_x * sum_y - count * sum_xy) /
60 (sum_x * sum_x - count * sum_x2);
61 *bias = (sum_x * sum_xy - sum_x2 * sum_y) / (sum_x * sum_x - count * sum_x2);
62 return true;
63}
64
65void RunTest(TestBase* test, const char *name,
66 float coefficient, bool inverse) {
67 float slope;
68 int64_t bias;
69
70 GLenum err = glGetError();
71 if (err != 0) {
72 printf("# %s failed, glGetError returned 0x%x.\n", name, err);
73 // float() in python will happily parse Nan.
74 printf("%s: Nan\n", name);
75 } else {
76 if (Bench(test, &slope, &bias)) {
77 printf("%s: %g\n", name, coefficient * (inverse ? 1.f / slope : slope));
78 } else {
79 printf("# %s is too slow, returning zero.\n", name);
80 printf("%s: 0\n", name);
81 }
82 }
83}
84
85bool DrawArraysTestFunc::TestFunc(int iter) {
86 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
87 glFlush();
88 for (int i = 0; i < iter-1; ++i) {
89 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
90 }
91 return true;
92}
93
94
95void DrawArraysTestFunc::FillRateTestNormal(const char* name) {
96 FillRateTestNormalSubWindow(name, g_width, g_height);
97}
98
99
100void DrawArraysTestFunc::FillRateTestNormalSubWindow(const char* name,
101 float width, float height)
102{
103 const int buffer_len = 64;
104 char buffer[buffer_len];
105 snprintf(buffer, buffer_len, "mpixels_sec_%s", name);
106 RunTest(this, buffer, width * height, true);
107}
108
109
Alexey Marinicheve735df62010-05-24 15:52:07 -0700110#if defined(USE_OPENGL)
Alexey Marinichev9f9b8732010-05-20 19:33:44 -0700111void DrawArraysTestFunc::FillRateTestBlendDepth(const char *name) {
112 const int buffer_len = 64;
113 char buffer[buffer_len];
114
115 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
116 glEnable(GL_BLEND);
117 snprintf(buffer, buffer_len, "mpixels_sec_%s_blended", name);
118 RunTest(this, buffer, g_width * g_height, true);
119 glDisable(GL_BLEND);
120
121 glEnable(GL_DEPTH_TEST);
122 glDepthFunc(GL_NOTEQUAL);
123 snprintf(buffer, buffer_len, "mpixels_sec_%s_depth_neq", name);
124 RunTest(this, buffer, g_width * g_height, true);
125 glDepthFunc(GL_NEVER);
126 snprintf(buffer, buffer_len, "mpixels_sec_%s_depth_never", name);
127 RunTest(this, buffer, g_width * g_height, true);
128 glDisable(GL_DEPTH_TEST);
129}
130#endif
131
132
133bool DrawElementsTestFunc::TestFunc(int iter) {
134 glDrawElements(GL_TRIANGLES, count_, GL_UNSIGNED_INT, 0);
135 glFlush();
136 for (int i = 0 ; i < iter-1; ++i) {
137 glDrawElements(GL_TRIANGLES, count_, GL_UNSIGNED_INT, 0);
138 }
139 return true;
140}
141
142} // namespace glbench