1 // BEGIN_COPYRIGHT -*- glean -*-
3 // Copyright (C) 1999 Allen Akin All Rights Reserved.
5 // Permission is hereby granted, free of charge, to any person
6 // obtaining a copy of this software and associated documentation
7 // files (the "Software"), to deal in the Software without
8 // restriction, including without limitation the rights to use,
9 // copy, modify, merge, publish, distribute, sublicense, and/or
10 // sell copies of the Software, and to permit persons to whom the
11 // Software is furnished to do so, subject to the following
14 // The above copyright notice and this permission notice shall be
15 // included in all copies or substantial portions of the
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
19 // KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
20 // WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
21 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ALLEN AKIN BE
22 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 // AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
24 // OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 // DEALINGS IN THE SOFTWARE.
29 // tchgperf.cpp: Some basic tests of attribute-change performance.
59 GLEAN::Image
redImage(64, 64, GL_RGB
, GL_UNSIGNED_BYTE
, 1.0, 0.0, 0.0, 0.0);
61 GLEAN::Image
greenImage(64, 64, GL_RGB
, GL_UNSIGNED_BYTE
, 0.0, 1.0, 0.0, 0.0);
70 int rowSize
= 2 * nPoints
;
71 for (int y
= 0; y
< nPoints
- 1; ++y
) {
72 float* t0
= texCoords
+ y
* rowSize
;
73 float* v0
= vertices
+ y
* rowSize
;
74 for (int x
= 0; x
< nPoints
- 1; ++x
) {
75 float* t1
= t0
+ rowSize
;
78 float* v1
= v0
+ rowSize
;
82 glBegin(GL_TRIANGLES
);
90 glBegin(GL_TRIANGLES
);
107 int rowSize
= 2 * nPoints
;
108 for (int y
= 0; y
< nPoints
- 1; ++y
) {
109 float* v0
= vertices
+ y
* rowSize
;
110 float* t0
= texCoords
+ y
* rowSize
;
111 for (int x
= 0; x
< nPoints
- 1; ++x
) {
112 float* t1
= t0
+ rowSize
;
115 float* v1
= v0
+ rowSize
;
119 glBindTexture(GL_TEXTURE_2D
, redTex
);
120 glBegin(GL_TRIANGLES
);
129 glBindTexture(GL_TEXTURE_2D
, greenTex
);
130 glBegin(GL_TRIANGLES
);
145 class BindDrawTimer
: public GLEAN::Timer
{
146 virtual void op() { bindDraw(); }
147 virtual void preop() { glFinish(); }
148 virtual void postop() { glFinish(); }
151 class NoBindDrawTimer
: public GLEAN::Timer
{
152 virtual void op() { noBindDraw(); }
153 virtual void preop() { glFinish(); }
154 virtual void postop() { glFinish(); }
158 logStats(GLEAN::TexBindPerfResult
& r
, GLEAN::Environment
* env
) {
159 env
->log
<< "\tApproximate texture binding time = " << r
.bindTime
160 << " microseconds.\n\tRange of valid measurements = ["
161 << r
.lowerBound
<< ", " << r
.upperBound
<< "]\n";
164 } // anonymous namespace
168 ///////////////////////////////////////////////////////////////////////////////
169 // runOne: Run a single test case
170 ///////////////////////////////////////////////////////////////////////////////
173 TexBindPerf::runOne(TexBindPerfResult
& r
, Window
& w
) {
174 glGenTextures(1, &redTex
);
175 glBindTexture(GL_TEXTURE_2D
, redTex
);
176 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
177 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
178 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
179 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
180 redImage
.makeMipmaps(GL_RGB
);
182 glGenTextures(1, &greenTex
);
183 glBindTexture(GL_TEXTURE_2D
, greenTex
);
184 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
185 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
186 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
187 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
188 greenImage
.makeMipmaps(GL_RGB
);
190 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_DECAL
);
192 GLUtils::useScreenCoords(drawingSize
+ 2, drawingSize
+ 2);
193 glEnable(GL_DEPTH_TEST
);
194 glDepthFunc(GL_LEQUAL
);
195 glEnable(GL_TEXTURE_2D
);
196 glColor4f(1.0, 1.0, 1.0, 1.0);
198 nPoints
= drawingSize
/ 2; // Yields 1-pixel triangles.
200 RandomDouble
vRand(142857);
201 RandomMesh2D
v(1.0, drawingSize
, nPoints
, 1.0, drawingSize
, nPoints
,
205 RandomDouble
tRand(314159);
206 RandomMesh2D
t(0.0, 1.0, nPoints
, 0.0, 1.0, nPoints
, tRand
);
209 int nTris
= (nPoints
- 1) * (nPoints
- 1) / 2;
211 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
213 BindDrawTimer bindDrawTimer
;
214 NoBindDrawTimer noBindDrawTimer
;
216 bindDrawTimer
.calibrate();
217 noBindDrawTimer
.calibrate();
219 vector
<float> measurements
;
220 for (int i
= 0; i
< 5; ++i
) {
222 double tBind
= bindDrawTimer
.time();
223 w
.swap(); // So the user can see something happening.
226 double tNoBind
= noBindDrawTimer
.time();
229 double bindTime
= 1E6
* (tBind
- tNoBind
) / nTris
;
230 if (bindTime
< 0.0) {
231 // This can happen if the system isn't quiescent;
232 // some process sneaks in and takes wall-clock time
233 // when ``noBindDraw'' is running. Just flush it
234 // and try again. (Note: You really shouldn't be
235 // running timing tests on a system where other
236 // processes are active!)
241 measurements
.push_back(bindTime
);
244 sort(measurements
.begin(), measurements
.end());
245 r
.bindTime
= (measurements
[1]+measurements
[2]+measurements
[3]) / 3.0;
246 r
.lowerBound
= measurements
[1];
247 r
.upperBound
= measurements
[3];
249 } // TexBindPerf::runOne
251 ///////////////////////////////////////////////////////////////////////////////
252 // logOne: Log a single test case
253 ///////////////////////////////////////////////////////////////////////////////
255 TexBindPerf::logOne(TexBindPerfResult
& r
) {
259 } // TexBindPerf::logOne
261 ///////////////////////////////////////////////////////////////////////////////
262 // compareOne: Compare results for a single test case
263 ///////////////////////////////////////////////////////////////////////////////
265 TexBindPerf::compareOne(TexBindPerfResult
& oldR
, TexBindPerfResult
& newR
) {
266 if (newR
.bindTime
< oldR
.lowerBound
) {
267 int percent
= static_cast<int>(
268 100.0 * (oldR
.bindTime
- newR
.bindTime
) / newR
.bindTime
270 env
->log
<< name
<< ": DIFF "
271 << newR
.config
->conciseDescription() << '\n'
272 << '\t' << env
->options
.db2Name
<< " may be "
273 << percent
<< "% faster.\n";
274 } else if (newR
.bindTime
> oldR
.upperBound
) {
275 int percent
= static_cast<int>(
276 100.0 * (newR
.bindTime
- oldR
.bindTime
) / oldR
.bindTime
278 env
->log
<< name
<< ": DIFF "
279 << oldR
.config
->conciseDescription() << '\n'
280 << '\t' << env
->options
.db1Name
<< " may be "
281 << percent
<< "% faster.\n";
283 if (env
->options
.verbosity
)
284 env
->log
<< name
<< ": SAME "
285 << newR
.config
->conciseDescription()
287 << env
->options
.db2Name
288 << " test time falls within the "
289 << "valid measurement range of "
290 << env
->options
.db1Name
293 if (env
->options
.verbosity
) {
294 env
->log
<< env
->options
.db1Name
<< ':';
296 env
->log
<< env
->options
.db2Name
<< ':';
299 } // TexBindPerf::compareOne
301 ///////////////////////////////////////////////////////////////////////////////
302 // The test object itself:
303 ///////////////////////////////////////////////////////////////////////////////
304 TexBindPerf
texBindPerfTest("texBindPerf", "window, rgb, z",
306 "This test makes a rough estimate of the cost of a glBindTexture()\n"
307 "operation, expressed in microseconds.\n"
309 "Since the apparent cost of a texture bind is dependent on many\n"
310 "factors (including the fraction of the texture map that's actually\n"
311 "used for drawing, on machines that cache textures; texture map\n"
312 "size; texel format; etc.), a general-purpose test can only estimate\n"
313 "it. In this test we do so by drawing random triangles of very\n"
314 "small size, and reporting simple statistics concerning the cost.\n");