Add more structure constructor tests.
[piglit/hramrach.git] / tests / glean / tvtxperf.cpp
blobfa5bd877d58d8addfc52934743aa29f7794d8012
1 // BEGIN_COPYRIGHT -*- glean -*-
2 //
3 // Copyright (C) 2000 Allen Akin All Rights Reserved.
4 //
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
12 // conditions:
13 //
14 // The above copyright notice and this permission notice shall be
15 // included in all copies or substantial portions of the
16 // Software.
17 //
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.
26 //
27 // END_COPYRIGHT
29 // tvtxperf.cpp: Test performance of various ways to specify vertex data
31 #include "tvtxperf.h"
32 #include "geomutil.h"
33 #include "timer.h"
34 #include "rand.h"
35 #include "image.h"
36 #include "codedid.h"
37 #include "treadpix.h"
39 namespace {
40 struct C4UB_N3F_V3F {
41 GLubyte c[4];
42 GLfloat n[3];
43 GLfloat v[3];
46 struct C4UB_T2F_V3F {
47 GLubyte c[4];
48 GLfloat t[2];
49 GLfloat v[3];
52 class TvtxBaseTimer: public GLEAN::Timer {
53 public:
54 int nVertices;
55 GLuint* indices;
56 int nTris;
57 GLEAN::Window* w;
58 GLEAN::Environment* env;
60 TvtxBaseTimer(int v, GLuint* i, int t, GLEAN::Window* win,
61 GLEAN::Environment* e) {
62 nVertices = v;
63 indices = i;
64 nTris = t;
65 w = win;
66 env = e;
69 virtual double compute(double t) { return nTris/t; }
70 virtual void premeasure() {
71 // Clear both front and back buffers and swap, to avoid
72 // confusing this test with results of the previous
73 // test:
74 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
75 w->swap();
76 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
78 virtual void postmeasure() { w->swap(); }
79 virtual void preop() { env->quiesce(); glFinish(); }
80 virtual void postop() { glFinish(); }
83 class ColoredLit_imIndTri: public TvtxBaseTimer {
84 public:
85 C4UB_N3F_V3F* data;
86 ColoredLit_imIndTri(int v, C4UB_N3F_V3F* c, int t, GLEAN::Window* w,
87 GLEAN::Environment* env):
88 TvtxBaseTimer(v, 0, t, w, env) {
89 data = c;
92 virtual void op() {
93 C4UB_N3F_V3F* p = data;
94 glBegin(GL_TRIANGLES);
95 // Assume that the data is complete, thus allowing us
96 // to unroll 3X and do one tri per iteration rather than
97 // one vertex.
98 for (int i = nVertices / 3; i; --i) {
99 glColor4ubv(p[0].c);
100 glNormal3fv(p[0].n);
101 glVertex3fv(p[0].v);
102 glColor4ubv(p[1].c);
103 glNormal3fv(p[1].n);
104 glVertex3fv(p[1].v);
105 glColor4ubv(p[2].c);
106 glNormal3fv(p[2].n);
107 glVertex3fv(p[2].v);
108 p += 3;
110 glEnd();
112 }; // coloredLit_imIndTri
114 class ColoredTex_imIndTri: public TvtxBaseTimer {
115 public:
116 C4UB_T2F_V3F* data;
117 ColoredTex_imIndTri(int v, C4UB_T2F_V3F* c, int t, GLEAN::Window* w,
118 GLEAN::Environment* env):
119 TvtxBaseTimer(v, 0, t, w, env) {
120 data = c;
123 virtual void op() {
124 C4UB_T2F_V3F* p = data;
125 glBegin(GL_TRIANGLES);
126 // Assume that the data is complete, thus allowing us
127 // to unroll 3X and do one tri per iteration rather than
128 // one vertex.
129 for (int i = nVertices / 3; i; --i) {
130 glColor4ubv(p[0].c);
131 glTexCoord2fv(p[0].t);
132 glVertex3fv(p[0].v);
133 glColor4ubv(p[1].c);
134 glTexCoord2fv(p[0].t);
135 glVertex3fv(p[1].v);
136 glColor4ubv(p[2].c);
137 glTexCoord2fv(p[0].t);
138 glVertex3fv(p[2].v);
139 p += 3;
141 glEnd();
143 }; // coloredTex_imIndTri
145 class ColoredLit_imTriStrip: public TvtxBaseTimer {
146 public:
147 C4UB_N3F_V3F* data;
148 ColoredLit_imTriStrip(int v, C4UB_N3F_V3F* c, int t,
149 GLEAN::Window* w, GLEAN::Environment* env):
150 TvtxBaseTimer(v, 0, t, w, env) {
151 data = c;
154 virtual void op() {
155 C4UB_N3F_V3F* p = data;
156 glBegin(GL_TRIANGLE_STRIP);
158 int n = (nVertices + 3) >> 2;
159 // Duff's device. Yes, this is legal C (and C++).
160 // See Stroustrup, 3rd ed., p. 141
161 switch (nVertices & 0x3) {
162 case 0: do {
163 glColor4ubv(p->c);
164 glNormal3fv(p->n);
165 glVertex3fv(p->v);
166 ++p;
167 case 3:
168 glColor4ubv(p->c);
169 glNormal3fv(p->n);
170 glVertex3fv(p->v);
171 ++p;
172 case 2:
173 glColor4ubv(p->c);
174 glNormal3fv(p->n);
175 glVertex3fv(p->v);
176 ++p;
177 case 1:
178 glColor4ubv(p->c);
179 glNormal3fv(p->n);
180 glVertex3fv(p->v);
181 ++p;
182 } while (--n > 0);
184 glEnd();
186 }; // coloredLit_imTriStrip
188 class ColoredTex_imTriStrip: public TvtxBaseTimer {
189 public:
190 C4UB_T2F_V3F* data;
192 ColoredTex_imTriStrip(int v, C4UB_T2F_V3F* c, int t,
193 GLEAN::Window* w, GLEAN::Environment* env):
194 TvtxBaseTimer(v, 0, t, w, env) {
195 data = c;
198 virtual void op() {
199 C4UB_T2F_V3F* p = data;
200 glBegin(GL_TRIANGLE_STRIP);
202 int n = (nVertices + 3) >> 2;
203 // Duff's device. Yes, this is legal C (and C++).
204 // See Stroustrup, 3rd ed., p. 141
205 switch (nVertices & 0x3) {
206 case 0: do {
207 glColor4ubv(p->c);
208 glTexCoord2fv(p->t);
209 glVertex3fv(p->v);
210 ++p;
211 case 3:
212 glColor4ubv(p->c);
213 glTexCoord2fv(p->t);
214 glVertex3fv(p->v);
215 ++p;
216 case 2:
217 glColor4ubv(p->c);
218 glTexCoord2fv(p->t);
219 glVertex3fv(p->v);
220 ++p;
221 case 1:
222 glColor4ubv(p->c);
223 glTexCoord2fv(p->t);
224 glVertex3fv(p->v);
225 ++p;
226 } while (--n > 0);
228 glEnd();
230 }; // coloredTex_imTriStrip
232 class daIndTriTimer: public TvtxBaseTimer {
233 public:
234 daIndTriTimer(int v, GLuint* i, int t, GLEAN::Window* w,
235 GLEAN::Environment* env):
236 TvtxBaseTimer(v, i, t, w, env) {
238 virtual void op() {glDrawArrays(GL_TRIANGLES, 0, nVertices); }
239 }; // daIndTriTimer
241 class daTriStripTimer: public TvtxBaseTimer {
242 public:
243 daTriStripTimer(int v, int t, GLEAN::Window* w,
244 GLEAN::Environment* env):
245 TvtxBaseTimer(v, 0, t, w, env) {
247 virtual void op() { glDrawArrays(GL_TRIANGLE_STRIP, 0, nVertices); }
248 }; // daTriStripTimer
250 class deIndTriTimer: public TvtxBaseTimer {
251 public:
252 deIndTriTimer(int v, GLuint* i, int t, GLEAN::Window* w,
253 GLEAN::Environment* env):
254 TvtxBaseTimer(v, i, t, w, env) {
256 virtual void op() {
257 glDrawElements(GL_TRIANGLES, nVertices, GL_UNSIGNED_INT,
258 indices);
260 }; // deIndTriTimer
262 class deTriStripTimer: public TvtxBaseTimer {
263 public:
264 deTriStripTimer(int v, GLuint* i, int t, GLEAN::Window* w,
265 GLEAN::Environment* env):
266 TvtxBaseTimer(v, i, t, w, env) {
268 virtual void op() {
269 glDrawElements(GL_TRIANGLE_STRIP, nVertices, GL_UNSIGNED_INT,
270 indices);
272 }; // deTriStripTimer
275 class callDListTimer: public TvtxBaseTimer {
276 public:
277 int dList;
278 callDListTimer(int d, int t, GLEAN::Window* w,
279 GLEAN::Environment* env):
280 TvtxBaseTimer(0, 0, t, w, env) {
281 dList = d;
283 virtual void op() { glCallList(dList); }
284 }; // callDList
286 void
287 logStats1(const char* title, GLEAN::VPSubResult& r,
288 GLEAN::Environment* env) {
289 env->log << '\t' << title << " rate = "
290 << r.tps << " tri/sec.\n"
291 << "\t\tRange of valid measurements = ["
292 << r.tpsLow << ", " << r.tpsHigh << "]\n"
293 << "\t\tImage sanity check "
294 << (r.imageOK? "passed\n": "failed\n")
295 << "\t\tImage consistency check "
296 << (r.imageMatch? "passed\n": "failed\n");
298 } // logStats1
300 void
301 diffHeader(bool& same, const string& name,
302 GLEAN::DrawingSurfaceConfig* config, GLEAN::Environment* env) {
303 if (same) {
304 same = false;
305 env->log << name << ": DIFF "
306 << config->conciseDescription() << '\n';
308 } // diffHeader
310 void
311 failHeader(bool& pass, const string& name,
312 GLEAN::DrawingSurfaceConfig* config, GLEAN::Environment* env) {
313 if (pass) {
314 pass = false;
315 env->log << name << ": FAIL "
316 << config->conciseDescription() << '\n';
318 } // failHeader
320 void
321 doComparison(const GLEAN::VPSubResult& oldR,
322 const GLEAN::VPSubResult& newR,
323 GLEAN::DrawingSurfaceConfig* config,
324 bool& same, const string& name, GLEAN::Environment* env,
325 const char* title) {
326 if (newR.tps < oldR.tpsLow) {
327 int percent = static_cast<int>(
328 100.0 * (oldR.tps - newR.tps) / newR.tps + 0.5);
329 diffHeader(same, name, config, env);
330 env->log << '\t' << env->options.db1Name
331 << " may be " << percent << "% faster on "
332 << title << " drawing.\n";
334 if (newR.tps > oldR.tpsHigh) {
335 int percent = static_cast<int>(
336 100.0 * (newR.tps - oldR.tps) / oldR.tps + 0.5);
337 diffHeader(same, name, config, env);
338 env->log << '\t' << env->options.db2Name
339 << " may be " << percent << "% faster on "
340 << title << " drawing.\n";
342 if (newR.imageOK != oldR.imageOK) {
343 diffHeader(same, name, config, env);
344 env->log << '\t' << env->options.db1Name << " image check "
345 << (oldR.imageOK? "passed\n": "failed\n");
346 env->log << '\t' << env->options.db2Name << " image check "
347 << (newR.imageOK? "passed\n": "failed\n");
349 if (newR.imageMatch != oldR.imageMatch) {
350 diffHeader(same, name, config, env);
351 env->log << '\t' << env->options.db1Name << " image compare "
352 << (oldR.imageMatch? "passed\n": "failed\n");
353 env->log << '\t' << env->options.db2Name << " image compare "
354 << (newR.imageMatch? "passed\n": "failed\n");
356 } // doComparison
358 bool
359 imagesDiffer(GLEAN::Image& testImage, GLEAN::Image& goldenImage) {
360 GLEAN::Image::Registration imageReg(testImage.reg(goldenImage));
361 return (imageReg.stats[0].max()
362 + imageReg.stats[1].max()
363 + imageReg.stats[2].max()) != 0.0;
364 } // imagesDiffer
366 void
367 missingSome(GLEAN::Environment* env, const char* title) {
368 env->log << '\t' << title << " rendering is missing\n"
369 << "\t\tsome triangles.\n";
370 } // missingSome
372 void
373 theyDiffer(GLEAN::Environment* env, const char* title) {
374 env->log << '\t' << title << " image differs from\n"
375 << "\t\tthe reference image.\n";
376 } // theyDiffer
378 void
379 verifyVtxPerf(GLEAN::Image& testImage, GLEAN::RGBCodedID& colorGen,
380 int firstID, int lastID, GLEAN::Image& refImage,
381 bool& passed, string& name, GLEAN::DrawingSurfaceConfig* config,
382 GLEAN::VPSubResult& res, GLEAN::Environment* env, const char* title) {
384 // Verify that the entire range of RGB coded identifiers is
385 // present in the image. (This is an indicator that all triangles
386 // were actually drawn.)
387 testImage.read(0, 0);
388 if (!colorGen.allPresent(testImage, firstID, lastID)) {
389 failHeader(passed, name, config, env);
390 missingSome(env, title);
391 res.imageOK = false;
394 // Verify that the test image is the same as the reference image.
395 if (imagesDiffer(testImage, refImage)) {
396 failHeader(passed, name, config, env);
397 theyDiffer(env, title);
398 res.imageMatch = false;
400 } // verify
402 } // anonymous namespace
404 namespace GLEAN {
406 ///////////////////////////////////////////////////////////////////////////////
407 // runOne: Run a single test case
408 ///////////////////////////////////////////////////////////////////////////////
410 void
411 ColoredLitPerf::runOne(VPResult& r, Window& w) {
412 // Don't bother running if the ExactRGBA test for this display
413 // surface configuration failed:
414 vector<ExactRGBAResult*>::const_iterator erRes;
415 for (erRes = exactRGBATest.results.begin();
416 erRes != exactRGBATest.results.end();
417 ++erRes)
418 if ((*erRes)->config == r.config)
419 break;
420 if (erRes == exactRGBATest.results.end() || !(*erRes)->ub.pass) {
421 r.skipped = true;
422 r.pass = false;
423 return;
426 bool passed = true;
427 PFNGLLOCKARRAYSEXTPROC glLockArraysEXT = 0;
428 PFNGLUNLOCKARRAYSEXTPROC glUnlockArraysEXT = 0;
429 if (GLUtils::haveExtension("GL_EXT_compiled_vertex_array")) {
430 glLockArraysEXT = reinterpret_cast<PFNGLLOCKARRAYSEXTPROC>
431 (GLUtils::getProcAddress("glLockArraysEXT"));
432 glUnlockArraysEXT = reinterpret_cast<PFNGLUNLOCKARRAYSEXTPROC>
433 (GLUtils::getProcAddress("glUnlockArraysEXT"));
436 Image imTriImage(drawingSize, drawingSize, GL_RGB, GL_UNSIGNED_BYTE);
437 Image testImage(drawingSize, drawingSize, GL_RGB, GL_UNSIGNED_BYTE);
439 // Make colors deterministic, so we can check them:
440 RGBCodedID colorGen(r.config->r, r.config->g, r.config->b);
441 int IDModulus = colorGen.maxID() + 1;
443 // We need to minimize the number of pixels per triangle, so that
444 // we're measuring vertex-processing rate rather than fill rate.
445 // However, we'd also like to guarantee that every triangle covers
446 // at least one pixel, so that we can confirm drawing actually took
447 // place. As a compromise, we'll choose a number of triangles that
448 // yields approximately 3 pixels per triangle.
449 // We're drawing a filled spiral that approximates a circular area,
450 // so pi * (drawingSize/2)**2 / nTris = 3 implies...
451 const int nTris = static_cast<int>
452 (((3.14159 / 4.0) * drawingSize * drawingSize) / 3.0 + 0.5);
453 int nVertices = nTris * 3;
454 int lastID = min(IDModulus - 1, nTris - 1);
456 C4UB_N3F_V3F *c4ub_n3f_v3f = new C4UB_N3F_V3F[nVertices];
457 SpiralTri2D it(nTris, 0, drawingSize, 0, drawingSize);
458 int k = 0;
459 for (int j = 0; j < nTris; ++j) {
460 float* t = it(j);
461 GLubyte r, g, b;
462 colorGen.toRGB(j % IDModulus, r, g, b);
464 c4ub_n3f_v3f[k+0].c[0] = r;
465 c4ub_n3f_v3f[k+0].c[1] = g;
466 c4ub_n3f_v3f[k+0].c[2] = b;
467 c4ub_n3f_v3f[k+0].c[3] = 0xFF;
468 c4ub_n3f_v3f[k+0].n[0] = 0.0;
469 c4ub_n3f_v3f[k+0].n[1] = 0.0;
470 c4ub_n3f_v3f[k+0].n[2] = 1.0;
471 c4ub_n3f_v3f[k+0].v[0] = t[0];
472 c4ub_n3f_v3f[k+0].v[1] = t[1];
473 c4ub_n3f_v3f[k+0].v[2] = 0.0;
475 c4ub_n3f_v3f[k+1].c[0] = r;
476 c4ub_n3f_v3f[k+1].c[1] = g;
477 c4ub_n3f_v3f[k+1].c[2] = b;
478 c4ub_n3f_v3f[k+1].c[3] = 0xFF;
479 c4ub_n3f_v3f[k+1].n[0] = 0.0;
480 c4ub_n3f_v3f[k+1].n[1] = 0.0;
481 c4ub_n3f_v3f[k+1].n[2] = 1.0;
482 c4ub_n3f_v3f[k+1].v[0] = t[2];
483 c4ub_n3f_v3f[k+1].v[1] = t[3];
484 c4ub_n3f_v3f[k+1].v[2] = 0.0;
486 c4ub_n3f_v3f[k+2].c[0] = r;
487 c4ub_n3f_v3f[k+2].c[1] = g;
488 c4ub_n3f_v3f[k+2].c[2] = b;
489 c4ub_n3f_v3f[k+2].c[3] = 0xFF;
490 c4ub_n3f_v3f[k+2].n[0] = 0.0;
491 c4ub_n3f_v3f[k+2].n[1] = 0.0;
492 c4ub_n3f_v3f[k+2].n[2] = 1.0;
493 c4ub_n3f_v3f[k+2].v[0] = t[4];
494 c4ub_n3f_v3f[k+2].v[1] = t[5];
495 c4ub_n3f_v3f[k+2].v[2] = 0.0;
497 k += 3;
500 GLuint *indices = new GLuint[nVertices];
501 for (k = 0; k < nVertices; ++k)
502 indices[k] = k;
504 GLUtils::useScreenCoords(drawingSize, drawingSize);
506 // Diffuse white light at infinity, behind the eye:
507 GLUtils::Light light(0);
508 light.ambient(0, 0, 0, 0);
509 light.diffuse(1, 1, 1, 0);
510 light.specular(0, 0, 0, 0);
511 light.position(0, 0, 1, 0);
512 light.spotCutoff(180);
513 light.constantAttenuation(1);
514 light.linearAttenuation(0);
515 light.quadraticAttenuation(0);
516 light.enable();
518 GLUtils::LightModel lm;
519 lm.ambient(0, 0, 0, 0);
520 lm.localViewer(false);
521 lm.twoSide(false);
522 lm.colorControl(GL_SINGLE_COLOR);
524 glFrontFace(GL_CCW);
525 glEnable(GL_NORMALIZE);
526 GLUtils::Material mat;
527 mat.ambient(0, 0, 0, 1);
528 mat.ambientAndDiffuse(1, 1, 1, 1);
529 mat.specular(0, 0, 0, 1);
530 mat.emission(0, 0, 0, 1);
531 mat.shininess(0);
532 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
533 glEnable(GL_COLOR_MATERIAL);
535 glEnable(GL_LIGHTING);
537 glDisable(GL_FOG);
538 glDisable(GL_SCISSOR_TEST);
539 glDisable(GL_ALPHA_TEST);
540 glDisable(GL_STENCIL_TEST);
541 glDepthFunc(GL_LEQUAL);
542 glEnable(GL_DEPTH_TEST);
543 glDisable(GL_BLEND);
544 glDisable(GL_DITHER);
545 glDisable(GL_COLOR_LOGIC_OP);
547 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
548 glDepthMask(GL_TRUE);
550 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
551 glCullFace(GL_BACK);
552 glEnable(GL_CULL_FACE);
553 glDisable(GL_POLYGON_STIPPLE);
554 glDisable(GL_POLYGON_OFFSET_FILL);
556 glShadeModel(GL_FLAT);
558 glReadBuffer(GL_FRONT);
560 ////////////////////////////////////////////////////////////
561 // Immediate-mode independent triangles
562 ////////////////////////////////////////////////////////////
563 ColoredLit_imIndTri coloredLit_imIndTri(nVertices, c4ub_n3f_v3f,
564 nTris, &w, env);
565 coloredLit_imIndTri.measure(5, &r.imTri.tpsLow, &r.imTri.tps,
566 &r.imTri.tpsHigh);
567 imTriImage.read(0, 0);
568 verifyVtxPerf(testImage, colorGen, 0, lastID, imTriImage,
569 passed, name, r.config, r.imTri, env,
570 "Immediate-mode independent triangle");
572 ////////////////////////////////////////////////////////////
573 // Display-listed independent triangles
574 ////////////////////////////////////////////////////////////
575 int dList = glGenLists(1);
576 glNewList(dList, GL_COMPILE);
577 coloredLit_imIndTri.op();
578 glEndList();
579 callDListTimer callDList(dList, nTris, &w, env);
580 callDList.measure(5, &r.dlTri.tpsLow, &r.dlTri.tps, &r.dlTri.tpsHigh);
581 glDeleteLists(dList, 1);
582 verifyVtxPerf(testImage, colorGen, 0, lastID, imTriImage,
583 passed, name, r.config, r.dlTri, env,
584 "Display-listed independent triangle");
586 ////////////////////////////////////////////////////////////
587 // DrawArrays on independent triangles
588 ////////////////////////////////////////////////////////////
589 glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(c4ub_n3f_v3f[0]),
590 c4ub_n3f_v3f[0].c);
591 glEnableClientState(GL_COLOR_ARRAY);
592 glNormalPointer(GL_FLOAT, sizeof(c4ub_n3f_v3f[0]),
593 c4ub_n3f_v3f[0].n);
594 glEnableClientState(GL_NORMAL_ARRAY);
595 glVertexPointer(3, GL_FLOAT, sizeof(c4ub_n3f_v3f[0]),
596 c4ub_n3f_v3f[0].v);
597 glEnableClientState(GL_VERTEX_ARRAY);
599 daIndTriTimer daIndTri(nVertices, indices, nTris, &w, env);
600 daIndTri.measure(5, &r.daTri.tpsLow, &r.daTri.tps, &r.daTri.tpsHigh);
601 verifyVtxPerf(testImage, colorGen, 0, lastID, imTriImage,
602 passed, name, r.config, r.daTri, env,
603 "DrawArrays independent triangle");
605 ////////////////////////////////////////////////////////////
606 // Locked DrawArrays on independent triangles
607 // XXX This is probably unrealistically favorable to
608 // locked arrays.
609 ////////////////////////////////////////////////////////////
610 if (glLockArraysEXT)
611 glLockArraysEXT(0, nVertices);
612 daIndTri.measure(5, &r.ldaTri.tpsLow, &r.ldaTri.tps,
613 &r.ldaTri.tpsHigh);
614 if (glUnlockArraysEXT)
615 glUnlockArraysEXT();
616 if (!glLockArraysEXT)
617 r.ldaTri.tps = r.ldaTri.tpsLow = r.ldaTri.tpsHigh = 0.0;
618 verifyVtxPerf(testImage, colorGen, 0, lastID, imTriImage,
619 passed, name, r.config, r.ldaTri, env,
620 "Locked DrawArrays independent triangle");
622 ////////////////////////////////////////////////////////////
623 // DrawElements on independent triangles
624 ////////////////////////////////////////////////////////////
625 deIndTriTimer deIndTri(nVertices, indices, nTris, &w, env);
626 deIndTri.measure(5, &r.deTri.tpsLow, &r.deTri.tps, &r.deTri.tpsHigh);
627 verifyVtxPerf(testImage, colorGen, 0, lastID, imTriImage,
628 passed, name, r.config, r.deTri, env,
629 "DrawElements independent triangle");
631 ////////////////////////////////////////////////////////////
632 // Locked DrawElements on independent triangles
633 ////////////////////////////////////////////////////////////
634 if (glLockArraysEXT)
635 glLockArraysEXT(0, nVertices);
636 deIndTri.measure(5, &r.ldeTri.tpsLow, &r.ldeTri.tps,
637 &r.ldeTri.tpsHigh);
638 if (glUnlockArraysEXT)
639 glUnlockArraysEXT();
640 if (!glLockArraysEXT)
641 r.ldeTri.tps = r.ldeTri.tpsLow = r.ldeTri.tpsHigh = 0.0;
642 verifyVtxPerf(testImage, colorGen, 0, lastID, imTriImage,
643 passed, name, r.config, r.ldeTri, env,
644 "Locked DrawElements independent triangle");
646 glDisableClientState(GL_COLOR_ARRAY);
647 glDisableClientState(GL_NORMAL_ARRAY);
648 glDisableClientState(GL_VERTEX_ARRAY);
650 delete[] c4ub_n3f_v3f;
651 delete[] indices;
653 // Now we test triangle strips, rather than independent triangles.
655 nVertices = nTris + 2;
656 lastID = min(IDModulus - 1, nTris - 1);
658 c4ub_n3f_v3f = new C4UB_N3F_V3F[nVertices];
659 SpiralStrip2D is(nVertices, 0, drawingSize, 0, drawingSize);
660 for (int j2 = 0; j2 < nVertices; ++j2) {
661 float* t = is(j2);
662 GLubyte r, g, b;
663 // Take care to get the correct color on the provoking vertex:
664 colorGen.toRGB((j2 - 2) % IDModulus, r, g, b);
666 c4ub_n3f_v3f[j2].c[0] = r;
667 c4ub_n3f_v3f[j2].c[1] = g;
668 c4ub_n3f_v3f[j2].c[2] = b;
669 c4ub_n3f_v3f[j2].c[3] = 0xFF;
670 c4ub_n3f_v3f[j2].n[0] = 0.0;
671 c4ub_n3f_v3f[j2].n[1] = 0.0;
672 c4ub_n3f_v3f[j2].n[2] = 1.0;
673 c4ub_n3f_v3f[j2].v[0] = t[0];
674 c4ub_n3f_v3f[j2].v[1] = t[1];
675 c4ub_n3f_v3f[j2].v[2] = 0.0;
678 indices = new GLuint[nVertices];
679 for (int j3 = 0; j3 < nVertices; ++j3)
680 indices[j3] = j3;
682 ////////////////////////////////////////////////////////////
683 // Immediate-mode triangle strips
684 ////////////////////////////////////////////////////////////
685 ColoredLit_imTriStrip coloredLit_imTriStrip(nVertices, c4ub_n3f_v3f,
686 nTris, &w, env);
687 coloredLit_imTriStrip.measure(5, &r.imTS.tpsLow, &r.imTS.tps,
688 &r.imTS.tpsHigh);
689 verifyVtxPerf(testImage, colorGen, 0, lastID, imTriImage,
690 passed, name, r.config, r.imTS, env,
691 "Immediate-mode triangle strip");
693 ////////////////////////////////////////////////////////////
694 // Display-listed triangle strips
695 ////////////////////////////////////////////////////////////
696 dList = glGenLists(1);
697 glNewList(dList, GL_COMPILE);
698 coloredLit_imTriStrip.op();
699 glEndList();
700 callDList.dList = dList;
701 callDList.measure(5, &r.dlTS.tpsLow, &r.dlTS.tps, &r.dlTS.tpsHigh);
702 glDeleteLists(dList, 1);
703 verifyVtxPerf(testImage, colorGen, 0, lastID, imTriImage,
704 passed, name, r.config, r.dlTS, env,
705 "Display-listed triangle strip");
707 ////////////////////////////////////////////////////////////
708 // DrawArrays on triangle strips
709 ////////////////////////////////////////////////////////////
710 glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(c4ub_n3f_v3f[0]),
711 c4ub_n3f_v3f[0].c);
712 glEnableClientState(GL_COLOR_ARRAY);
713 glNormalPointer(GL_FLOAT, sizeof(c4ub_n3f_v3f[0]),
714 c4ub_n3f_v3f[0].n);
715 glEnableClientState(GL_NORMAL_ARRAY);
716 glVertexPointer(3, GL_FLOAT, sizeof(c4ub_n3f_v3f[0]),
717 c4ub_n3f_v3f[0].v);
718 glEnableClientState(GL_VERTEX_ARRAY);
720 daTriStripTimer daTriStrip(nVertices, nTris, &w, env);
721 daTriStrip.measure(5, &r.daTS.tpsLow, &r.daTS.tps, &r.daTS.tpsHigh);
722 verifyVtxPerf(testImage, colorGen, 0, lastID, imTriImage,
723 passed, name, r.config, r.daTS, env,
724 "DrawArrays triangle strip");
726 ////////////////////////////////////////////////////////////
727 // Locked DrawArrays on triangle strips
728 ////////////////////////////////////////////////////////////
729 if (glLockArraysEXT)
730 glLockArraysEXT(0, nVertices);
731 daTriStrip.measure(5, &r.ldaTS.tpsLow, &r.ldaTS.tps, &r.ldaTS.tpsHigh);
732 if (glUnlockArraysEXT)
733 glUnlockArraysEXT();
734 if (!glLockArraysEXT)
735 r.ldaTS.tps = r.ldaTS.tpsLow = r.ldaTS.tpsHigh = 0.0;
736 verifyVtxPerf(testImage, colorGen, 0, lastID, imTriImage,
737 passed, name, r.config, r.ldaTS, env,
738 "Locked DrawArrays triangle strip");
740 ////////////////////////////////////////////////////////////
741 // DrawElements on triangle strips
742 ////////////////////////////////////////////////////////////
743 deTriStripTimer deTriStrip(nVertices, indices, nTris, &w, env);
744 deTriStrip.measure(5, &r.deTS.tpsLow, &r.deTS.tps, &r.deTS.tpsHigh);
745 verifyVtxPerf(testImage, colorGen, 0, lastID, imTriImage,
746 passed, name, r.config, r.deTS, env,
747 "DrawElements triangle strip");
749 ////////////////////////////////////////////////////////////
750 // Locked DrawElements on triangle strips
751 ////////////////////////////////////////////////////////////
752 if (glLockArraysEXT)
753 glLockArraysEXT(0, nVertices);
754 deTriStrip.measure(5, &r.ldeTS.tpsLow, &r.ldeTS.tps, &r.ldeTS.tpsHigh);
755 if (glUnlockArraysEXT)
756 glUnlockArraysEXT();
757 if (!glLockArraysEXT)
758 r.ldeTS.tps = r.ldeTS.tpsLow = r.ldeTS.tpsHigh = 0.0;
760 verifyVtxPerf(testImage, colorGen, 0, lastID, imTriImage,
761 passed, name, r.config, r.ldeTS, env,
762 "Locked DrawElements triangle strip");
764 glDisableClientState(GL_COLOR_ARRAY);
765 glDisableClientState(GL_NORMAL_ARRAY);
766 glDisableClientState(GL_VERTEX_ARRAY);
768 delete[] c4ub_n3f_v3f;
769 delete[] indices;
771 r.pass = passed;
772 r.skipped = false;
773 } // ColoredLitPerf::runOne
775 ///////////////////////////////////////////////////////////////////////////////
776 // logOne: Log a single test case
777 ///////////////////////////////////////////////////////////////////////////////
778 void
779 ColoredLitPerf::logOne(VPResult& r) {
780 if (r.skipped) {
781 env->log << name << ": NOTE ";
782 logConcise(r);
783 env->log << "\tTest skipped; prerequisite test "
784 << exactRGBATest.name
785 << " failed or was not run\n";
786 return;
788 if (r.pass) {
789 logPassFail(r);
790 logConcise(r);
791 } else env->log << '\n'; // because verify logs failure
792 logStats(r, env);
793 } // ColoredLitPerf::logOne
795 ///////////////////////////////////////////////////////////////////////////////
796 // compareOne: Compare results for a single test case
797 ///////////////////////////////////////////////////////////////////////////////
798 void
799 ColoredLitPerf::compareOne(VPResult& oldR, VPResult& newR) {
800 if (oldR.skipped || newR.skipped) {
801 env->log << name
802 << ((oldR.skipped && newR.skipped)? ": SAME "
803 : ": DIFF ")
804 << newR.config->conciseDescription()
805 << '\n';
806 if (oldR.skipped)
807 env->log << "\t"
808 << env->options.db1Name
809 << " skipped\n";
810 if (newR.skipped)
811 env->log << "\t"
812 << env->options.db2Name
813 << " skipped\n";
814 env->log << "\tNo comparison is possible.\n";
815 return;
818 bool same = true;
819 doComparison(oldR.imTri, newR.imTri, newR.config, same, name,
820 env, "immediate-mode independent triangle");
821 doComparison(oldR.dlTri, newR.dlTri, newR.config, same, name,
822 env, "display-listed independent triangle");
823 doComparison(oldR.daTri, newR.daTri, newR.config, same, name,
824 env, "DrawArrays independent triangle");
825 doComparison(oldR.ldaTri, newR.ldaTri, newR.config, same, name,
826 env, "Locked DrawArrays independent triangle");
827 doComparison(oldR.deTri, newR.deTri, newR.config, same, name,
828 env, "DrawElements independent triangle");
829 doComparison(oldR.ldeTri, newR.ldeTri, newR.config, same, name,
830 env, "Locked DrawElements independent triangle");
831 doComparison(oldR.imTS, newR.imTS, newR.config, same, name,
832 env, "immediate-mode triangle strip");
833 doComparison(oldR.dlTS, newR.dlTS, newR.config, same, name,
834 env, "display-listed triangle strip");
835 doComparison(oldR.daTS, newR.daTS, newR.config, same, name,
836 env, "DrawArrays triangle strip");
837 doComparison(oldR.ldaTS, newR.ldaTS, newR.config, same, name,
838 env, "Locked DrawArrays triangle strip");
839 doComparison(oldR.deTS, newR.deTS, newR.config, same, name,
840 env, "DrawElements triangle strip");
841 doComparison(oldR.ldeTS, newR.ldeTS, newR.config, same, name,
842 env, "Locked DrawElements triangle strip");
844 if (same && env->options.verbosity) {
845 env->log << name << ": SAME "
846 << newR.config->conciseDescription()
847 << "\n\t"
848 << env->options.db2Name
849 << " test time falls within the "
850 << "valid measurement range of\n\t"
851 << env->options.db1Name
852 << " test time; both have the same"
853 << " image comparison results.\n";
856 if (env->options.verbosity) {
857 env->log << env->options.db1Name << ':';
858 logStats(oldR, env);
859 env->log << env->options.db2Name << ':';
860 logStats(newR, env);
862 } // ColoredLitPerf::compareOne
864 void
865 ColoredLitPerf::logStats(VPResult& r, GLEAN::Environment* env) {
866 logStats1("Immediate-mode independent triangle", r.imTri, env);
867 logStats1("Display-listed independent triangle", r.dlTri, env);
868 logStats1("DrawArrays independent triangle", r.daTri, env);
869 logStats1("Locked DrawArrays independent triangle", r.ldaTri, env);
870 logStats1("DrawElements independent triangle", r.deTri, env);
871 logStats1("Locked DrawElements independent triangle", r.ldeTri, env);
872 logStats1("Immediate-mode triangle strip", r.imTS, env);
873 logStats1("Display-listed triangle strip", r.dlTS, env);
874 logStats1("DrawArrays triangle strip", r.daTS, env);
875 logStats1("Locked DrawArrays triangle strip", r.ldaTS, env);
876 logStats1("DrawElements triangle strip", r.deTS, env);
877 logStats1("Locked DrawElements triangle strip", r.ldeTS, env);
878 } // ColoredLitPerf::logStats
880 ///////////////////////////////////////////////////////////////////////////////
881 // The test object itself:
882 ///////////////////////////////////////////////////////////////////////////////
884 Test* coloredLitPerfTestPrereqs[] = {&exactRGBATest, 0};
886 ColoredLitPerf coloredLitPerfTest("coloredLitPerf2", "window, rgb, z, fast",
887 coloredLitPerfTestPrereqs,
889 "This test examines rendering performance for colored, lit,\n"
890 "flat-shaded triangles. It checks several different ways to\n"
891 "specify the vertex data in order to determine which is\n"
892 "fastest: fine-grained API calls, DrawArrays, DrawElements,\n"
893 "locked (compiled) DrawArrays, and locked DrawElements; for\n"
894 "independent triangles and for triangle strips. The test\n"
895 "result is performance measured in triangles per second for\n"
896 "each of the various vertex specification methods.\n"
898 "\nAs a sanity-check on the correctness of each method, the test\n"
899 "colors each triangle with a unique color, and verifies that all\n"
900 "such colors are actually present in the final image. For\n"
901 "consistency, the test also verifies that the images are identical\n"
902 "for each of the specification methods.\n"
907 ///////////////////////////////////////////////////////////////////////////////
908 // runOne: Run a single test case
909 ///////////////////////////////////////////////////////////////////////////////
911 void
912 ColoredTexPerf::runOne(VPResult& r, Window& w) {
913 // Don't bother running if the ExactRGBA test for this display
914 // surface configuration failed:
915 vector<ExactRGBAResult*>::const_iterator erRes;
916 for (erRes = exactRGBATest.results.begin();
917 erRes != exactRGBATest.results.end();
918 ++erRes)
919 if ((*erRes)->config == r.config)
920 break;
921 if (erRes == exactRGBATest.results.end() || !(*erRes)->ub.pass) {
922 r.skipped = true;
923 r.pass = false;
924 return;
927 PFNGLLOCKARRAYSEXTPROC glLockArraysEXT = 0;
928 PFNGLUNLOCKARRAYSEXTPROC glUnlockArraysEXT = 0;
929 if (GLUtils::haveExtension("GL_EXT_compiled_vertex_array")) {
930 glLockArraysEXT = reinterpret_cast<PFNGLLOCKARRAYSEXTPROC>
931 (GLUtils::getProcAddress("glLockArraysEXT"));
932 glUnlockArraysEXT = reinterpret_cast<PFNGLUNLOCKARRAYSEXTPROC>
933 (GLUtils::getProcAddress("glUnlockArraysEXT"));
936 Image imTriImage(drawingSize, drawingSize, GL_RGB, GL_UNSIGNED_BYTE);
937 Image testImage(drawingSize, drawingSize, GL_RGB, GL_UNSIGNED_BYTE);
938 bool passed = true;
940 // Make colors deterministic, so we can check them:
941 RGBCodedID colorGen(r.config->r, r.config->g, r.config->b);
942 int IDModulus = colorGen.maxID() + 1;
944 // We need to minimize the number of pixels per triangle, so that
945 // we're measuring vertex-processing rate rather than fill rate.
946 // However, we'd also like to guarantee that every triangle covers
947 // at least one pixel, so that we can confirm drawing actually took
948 // place. As a compromise, we'll choose a number of triangles that
949 // yields approximately 3 pixels per triangle.
950 // We're drawing a filled spiral that approximates a circular area,
951 // so pi * (drawingSize/2)**2 / nTris = 3 implies...
952 const int nTris = static_cast<int>
953 (((3.14159 / 4.0) * drawingSize * drawingSize) / 3.0 + 0.5);
954 int nVertices = nTris * 3;
955 int lastID = min(IDModulus - 1, nTris - 1);
957 C4UB_T2F_V3F *c4ub_t2f_v3f = new C4UB_T2F_V3F[nVertices];
958 SpiralTri2D it(nTris, 0, drawingSize, 0, drawingSize);
959 int k = 0;
960 for (int j = 0; j < nTris; ++j) {
961 float* t = it(j);
962 GLubyte r, g, b;
963 colorGen.toRGB(j % IDModulus, r, g, b);
965 c4ub_t2f_v3f[k+0].c[0] = r;
966 c4ub_t2f_v3f[k+0].c[1] = g;
967 c4ub_t2f_v3f[k+0].c[2] = b;
968 c4ub_t2f_v3f[k+0].c[3] = 0xFF;
969 c4ub_t2f_v3f[k+0].t[0] = 0.5;
970 c4ub_t2f_v3f[k+0].t[1] = 0.5;
971 c4ub_t2f_v3f[k+0].v[0] = t[0];
972 c4ub_t2f_v3f[k+0].v[1] = t[1];
973 c4ub_t2f_v3f[k+0].v[2] = 0.0;
975 c4ub_t2f_v3f[k+1].c[0] = r;
976 c4ub_t2f_v3f[k+1].c[1] = g;
977 c4ub_t2f_v3f[k+1].c[2] = b;
978 c4ub_t2f_v3f[k+1].c[3] = 0xFF;
979 c4ub_t2f_v3f[k+1].t[0] = 0.5;
980 c4ub_t2f_v3f[k+1].t[1] = 0.5;
981 c4ub_t2f_v3f[k+1].v[0] = t[2];
982 c4ub_t2f_v3f[k+1].v[1] = t[3];
983 c4ub_t2f_v3f[k+1].v[2] = 0.0;
985 c4ub_t2f_v3f[k+2].c[0] = r;
986 c4ub_t2f_v3f[k+2].c[1] = g;
987 c4ub_t2f_v3f[k+2].c[2] = b;
988 c4ub_t2f_v3f[k+2].c[3] = 0xFF;
989 c4ub_t2f_v3f[k+2].t[0] = 0.5;
990 c4ub_t2f_v3f[k+2].t[1] = 0.5;
991 c4ub_t2f_v3f[k+2].v[0] = t[4];
992 c4ub_t2f_v3f[k+2].v[1] = t[5];
993 c4ub_t2f_v3f[k+2].v[2] = 0.0;
995 k += 3;
998 GLuint *indices = new GLuint[nVertices];
999 for (k = 0; k < nVertices; ++k)
1000 indices[k] = k;
1002 GLUtils::useScreenCoords(drawingSize, drawingSize);
1004 glFrontFace(GL_CCW);
1005 glDisable(GL_NORMALIZE);
1006 glDisable(GL_COLOR_MATERIAL);
1008 glDisable(GL_LIGHTING);
1010 // Set up an all-white RGB texture, including mipmap levels:
1012 const int width = 8;
1013 const int height = 8;
1014 GLubyte whiteTex[width * height * 3];
1015 for (int i = 0; i < width * height * 3; ++i)
1016 whiteTex[i] = 255;
1017 glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
1018 glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
1019 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1020 glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
1021 glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
1022 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1023 glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
1024 glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
1025 glPixelTransferi(GL_MAP_COLOR, GL_FALSE);
1026 glPixelTransferf(GL_RED_SCALE, 1.0);
1027 glPixelTransferf(GL_GREEN_SCALE, 1.0);
1028 glPixelTransferf(GL_BLUE_SCALE, 1.0);
1029 glPixelTransferf(GL_ALPHA_SCALE, 1.0);
1030 glPixelTransferf(GL_RED_BIAS, 0.0);
1031 glPixelTransferf(GL_GREEN_BIAS, 0.0);
1032 glPixelTransferf(GL_BLUE_BIAS, 0.0);
1033 glPixelTransferf(GL_ALPHA_BIAS, 0.0);
1034 gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, width, height, GL_RGB,
1035 GL_UNSIGNED_BYTE, whiteTex);
1037 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1038 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1039 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1040 GL_LINEAR_MIPMAP_LINEAR);
1041 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1043 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1045 glMatrixMode(GL_TEXTURE);
1046 glLoadIdentity();
1047 glMatrixMode(GL_MODELVIEW);
1049 glDisable(GL_TEXTURE_GEN_S);
1050 glDisable(GL_TEXTURE_GEN_T);
1052 glEnable(GL_TEXTURE_2D);
1055 glDisable(GL_FOG);
1056 glDisable(GL_SCISSOR_TEST);
1057 glDisable(GL_ALPHA_TEST);
1058 glDisable(GL_STENCIL_TEST);
1059 glDepthFunc(GL_LEQUAL);
1060 glEnable(GL_DEPTH_TEST);
1061 glDisable(GL_BLEND);
1062 glDisable(GL_DITHER);
1063 glDisable(GL_COLOR_LOGIC_OP);
1065 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1066 glDepthMask(GL_TRUE);
1068 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1069 glCullFace(GL_BACK);
1070 glEnable(GL_CULL_FACE);
1071 glDisable(GL_POLYGON_STIPPLE);
1072 glDisable(GL_POLYGON_OFFSET_FILL);
1074 glShadeModel(GL_FLAT);
1076 glReadBuffer(GL_FRONT);
1078 ////////////////////////////////////////////////////////////
1079 // Immediate-mode independent triangles
1080 ////////////////////////////////////////////////////////////
1081 ColoredTex_imIndTri coloredTex_imIndTri(nVertices, c4ub_t2f_v3f,
1082 nTris, &w, env);
1083 coloredTex_imIndTri.measure(5, &r.imTri.tpsLow, &r.imTri.tps,
1084 &r.imTri.tpsHigh);
1085 imTriImage.read(0, 0);
1086 verifyVtxPerf(testImage, colorGen, 0, lastID, imTriImage,
1087 passed, name, r.config, r.imTri, env,
1088 "Immediate-mode independent triangle");
1090 ////////////////////////////////////////////////////////////
1091 // Display-listed independent triangles
1092 ////////////////////////////////////////////////////////////
1093 int dList = glGenLists(1);
1094 glNewList(dList, GL_COMPILE);
1095 coloredTex_imIndTri.op();
1096 glEndList();
1097 callDListTimer callDList(dList, nTris, &w, env);
1098 callDList.measure(5, &r.dlTri.tpsLow, &r.dlTri.tps, &r.dlTri.tpsHigh);
1099 glDeleteLists(dList, 1);
1100 verifyVtxPerf(testImage, colorGen, 0, lastID, imTriImage,
1101 passed, name, r.config, r.dlTri, env,
1102 "Display-listed independent triangle");
1104 ////////////////////////////////////////////////////////////
1105 // DrawArrays on independent triangles
1106 ////////////////////////////////////////////////////////////
1107 glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(c4ub_t2f_v3f[0]),
1108 c4ub_t2f_v3f[0].c);
1109 glEnableClientState(GL_COLOR_ARRAY);
1110 glTexCoordPointer(2, GL_FLOAT, sizeof(c4ub_t2f_v3f[0]),
1111 c4ub_t2f_v3f[0].t);
1112 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1113 glVertexPointer(3, GL_FLOAT, sizeof(c4ub_t2f_v3f[0]),
1114 c4ub_t2f_v3f[0].v);
1115 glEnableClientState(GL_VERTEX_ARRAY);
1117 daIndTriTimer daIndTri(nVertices, indices, nTris, &w, env);
1118 daIndTri.measure(5, &r.daTri.tpsLow, &r.daTri.tps, &r.daTri.tpsHigh);
1119 verifyVtxPerf(testImage, colorGen, 0, lastID, imTriImage,
1120 passed, name, r.config, r.daTri, env,
1121 "DrawArrays independent triangle");
1123 ////////////////////////////////////////////////////////////
1124 // Locked DrawArrays on independent triangles
1125 // XXX This is probably unrealistically favorable to
1126 // locked arrays.
1127 ////////////////////////////////////////////////////////////
1128 if (glLockArraysEXT)
1129 glLockArraysEXT(0, nVertices);
1130 daIndTri.measure(5, &r.ldaTri.tpsLow, &r.ldaTri.tps,
1131 &r.ldaTri.tpsHigh);
1132 if (glUnlockArraysEXT)
1133 glUnlockArraysEXT();
1134 if (!glLockArraysEXT)
1135 r.ldaTri.tps = r.ldaTri.tpsLow = r.ldaTri.tpsHigh = 0.0;
1136 verifyVtxPerf(testImage, colorGen, 0, lastID, imTriImage,
1137 passed, name, r.config, r.ldaTri, env,
1138 "Locked DrawArrays independent triangle");
1140 ////////////////////////////////////////////////////////////
1141 // DrawElements on independent triangles
1142 ////////////////////////////////////////////////////////////
1143 deIndTriTimer deIndTri(nVertices, indices, nTris, &w, env);
1144 deIndTri.measure(5, &r.deTri.tpsLow, &r.deTri.tps, &r.deTri.tpsHigh);
1145 verifyVtxPerf(testImage, colorGen, 0, lastID, imTriImage,
1146 passed, name, r.config, r.deTri, env,
1147 "DrawElements independent triangle");
1149 ////////////////////////////////////////////////////////////
1150 // Locked DrawElements on independent triangles
1151 ////////////////////////////////////////////////////////////
1152 if (glLockArraysEXT)
1153 glLockArraysEXT(0, nVertices);
1154 deIndTri.measure(5, &r.ldeTri.tpsLow, &r.ldeTri.tps,
1155 &r.ldeTri.tpsHigh);
1156 if (glUnlockArraysEXT)
1157 glUnlockArraysEXT();
1158 if (!glLockArraysEXT)
1159 r.ldeTri.tps = r.ldeTri.tpsLow = r.ldeTri.tpsHigh = 0.0;
1160 verifyVtxPerf(testImage, colorGen, 0, lastID, imTriImage,
1161 passed, name, r.config, r.ldeTri, env,
1162 "Locked DrawElements independent triangle");
1164 glDisableClientState(GL_COLOR_ARRAY);
1165 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1166 glDisableClientState(GL_VERTEX_ARRAY);
1168 delete[] c4ub_t2f_v3f;
1169 delete[] indices;
1171 // Now we test triangle strips, rather than independent triangles.
1173 nVertices = nTris + 2;
1174 lastID = min(IDModulus - 1, nTris - 1);
1176 c4ub_t2f_v3f = new C4UB_T2F_V3F[nVertices];
1177 SpiralStrip2D is(nVertices, 0, drawingSize, 0, drawingSize);
1178 for (int j2 = 0; j2 < nVertices; ++j2) {
1179 float* t = is(j2);
1180 GLubyte r, g, b;
1181 // Take care to get the correct color on the provoking vertex:
1182 colorGen.toRGB((j2 - 2) % IDModulus, r, g, b);
1184 c4ub_t2f_v3f[j2].c[0] = r;
1185 c4ub_t2f_v3f[j2].c[1] = g;
1186 c4ub_t2f_v3f[j2].c[2] = b;
1187 c4ub_t2f_v3f[j2].c[3] = 0xFF;
1188 c4ub_t2f_v3f[j2].t[0] = 0.5;
1189 c4ub_t2f_v3f[j2].t[1] = 0.5;
1190 c4ub_t2f_v3f[j2].v[0] = t[0];
1191 c4ub_t2f_v3f[j2].v[1] = t[1];
1192 c4ub_t2f_v3f[j2].v[2] = 0.0;
1195 indices = new GLuint[nVertices];
1196 for (int j3 = 0; j3 < nVertices; ++j3)
1197 indices[j3] = j3;
1199 ////////////////////////////////////////////////////////////
1200 // Immediate-mode triangle strips
1201 ////////////////////////////////////////////////////////////
1202 ColoredTex_imTriStrip coloredTex_imTriStrip(nVertices, c4ub_t2f_v3f,
1203 nTris, &w, env);
1204 coloredTex_imTriStrip.measure(5, &r.imTS.tpsLow, &r.imTS.tps,
1205 &r.imTS.tpsHigh);
1206 verifyVtxPerf(testImage, colorGen, 0, lastID, imTriImage,
1207 passed, name, r.config, r.imTS, env,
1208 "Immediate-mode triangle strip");
1210 ////////////////////////////////////////////////////////////
1211 // Display-listed triangle strips
1212 ////////////////////////////////////////////////////////////
1213 dList = glGenLists(1);
1214 glNewList(dList, GL_COMPILE);
1215 coloredTex_imTriStrip.op();
1216 glEndList();
1217 callDList.dList = dList;
1218 callDList.measure(5, &r.dlTS.tpsLow, &r.dlTS.tps, &r.dlTS.tpsHigh);
1219 glDeleteLists(dList, 1);
1220 verifyVtxPerf(testImage, colorGen, 0, lastID, imTriImage,
1221 passed, name, r.config, r.dlTS, env,
1222 "Display-listed triangle strip");
1224 ////////////////////////////////////////////////////////////
1225 // DrawArrays on triangle strips
1226 ////////////////////////////////////////////////////////////
1227 glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(c4ub_t2f_v3f[0]),
1228 c4ub_t2f_v3f[0].c);
1229 glEnableClientState(GL_COLOR_ARRAY);
1230 glTexCoordPointer(2, GL_FLOAT, sizeof(c4ub_t2f_v3f[0]),
1231 c4ub_t2f_v3f[0].t);
1232 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1233 glVertexPointer(3, GL_FLOAT, sizeof(c4ub_t2f_v3f[0]),
1234 c4ub_t2f_v3f[0].v);
1235 glEnableClientState(GL_VERTEX_ARRAY);
1237 daTriStripTimer daTriStrip(nVertices, nTris, &w, env);
1238 daTriStrip.measure(5, &r.daTS.tpsLow, &r.daTS.tps, &r.daTS.tpsHigh);
1239 verifyVtxPerf(testImage, colorGen, 0, lastID, imTriImage,
1240 passed, name, r.config, r.daTS, env,
1241 "DrawArrays triangle strip");
1243 ////////////////////////////////////////////////////////////
1244 // Locked DrawArrays on triangle strips
1245 ////////////////////////////////////////////////////////////
1246 if (glLockArraysEXT)
1247 glLockArraysEXT(0, nVertices);
1248 daTriStrip.measure(5, &r.ldaTS.tpsLow, &r.ldaTS.tps, &r.ldaTS.tpsHigh);
1249 if (glUnlockArraysEXT)
1250 glUnlockArraysEXT();
1251 if (!glLockArraysEXT)
1252 r.ldaTS.tps = r.ldaTS.tpsLow = r.ldaTS.tpsHigh = 0.0;
1253 verifyVtxPerf(testImage, colorGen, 0, lastID, imTriImage,
1254 passed, name, r.config, r.ldaTS, env,
1255 "Locked DrawArrays triangle strip");
1257 ////////////////////////////////////////////////////////////
1258 // DrawElements on triangle strips
1259 ////////////////////////////////////////////////////////////
1260 deTriStripTimer deTriStrip(nVertices, indices, nTris, &w, env);
1261 deTriStrip.measure(5, &r.deTS.tpsLow, &r.deTS.tps, &r.deTS.tpsHigh);
1262 verifyVtxPerf(testImage, colorGen, 0, lastID, imTriImage,
1263 passed, name, r.config, r.deTS, env,
1264 "DrawElements triangle strip");
1266 ////////////////////////////////////////////////////////////
1267 // Locked DrawElements on triangle strips
1268 ////////////////////////////////////////////////////////////
1269 if (glLockArraysEXT)
1270 glLockArraysEXT(0, nVertices);
1271 deTriStrip.measure(5, &r.ldeTS.tpsLow, &r.ldeTS.tps, &r.ldeTS.tpsHigh);
1272 if (glUnlockArraysEXT)
1273 glUnlockArraysEXT();
1274 if (!glLockArraysEXT)
1275 r.ldeTS.tps = r.ldeTS.tpsLow = r.ldeTS.tpsHigh = 0.0;
1276 verifyVtxPerf(testImage, colorGen, 0, lastID, imTriImage,
1277 passed, name, r.config, r.ldeTS, env,
1278 "Locked DrawElements triangle strip");
1281 glDisableClientState(GL_COLOR_ARRAY);
1282 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1283 glDisableClientState(GL_VERTEX_ARRAY);
1285 delete[] c4ub_t2f_v3f;
1286 delete[] indices;
1288 r.pass = passed;
1289 r.skipped = false;
1290 } // ColoredTexPerf::runOne
1292 ///////////////////////////////////////////////////////////////////////////////
1293 // logOne: Log a single test case
1294 ///////////////////////////////////////////////////////////////////////////////
1295 void
1296 ColoredTexPerf::logOne(VPResult& r) {
1297 if (r.skipped) {
1298 env->log << name << ": NOTE ";
1299 logConcise(r);
1300 env->log << "\tTest skipped; prerequisite test "
1301 << exactRGBATest.name
1302 << " failed or was not run\n"
1304 return;
1306 if (r.pass) {
1307 logPassFail(r);
1308 logConcise(r);
1309 } else env->log << '\n'; // because verify logs failure
1310 logStats(r, env);
1311 } // ColoredTexPerf::logOne
1313 ///////////////////////////////////////////////////////////////////////////////
1314 // compareOne: Compare results for a single test case
1315 ///////////////////////////////////////////////////////////////////////////////
1316 void
1317 ColoredTexPerf::compareOne(VPResult& oldR, VPResult& newR) {
1318 if (oldR.skipped || newR.skipped) {
1319 env->log << name
1320 << ((oldR.skipped && newR.skipped)? ": SAME "
1321 : ": DIFF ")
1322 << newR.config->conciseDescription()
1323 << '\n';
1324 if (oldR.skipped)
1325 env->log << "\t"
1326 << env->options.db1Name
1327 << " skipped\n";
1328 if (newR.skipped)
1329 env->log << "\t"
1330 << env->options.db2Name
1331 << " skipped\n";
1332 env->log << "\tNo comparison is possible.\n";
1333 return;
1336 bool same = true;
1337 doComparison(oldR.imTri, newR.imTri, newR.config, same, name,
1338 env, "immediate-mode independent triangle");
1339 doComparison(oldR.dlTri, newR.dlTri, newR.config, same, name,
1340 env, "display-listed independent triangle");
1341 doComparison(oldR.daTri, newR.daTri, newR.config, same, name,
1342 env, "DrawArrays independent triangle");
1343 doComparison(oldR.ldaTri, newR.ldaTri, newR.config, same, name,
1344 env, "Locked DrawArrays independent triangle");
1345 doComparison(oldR.deTri, newR.deTri, newR.config, same, name,
1346 env, "DrawElements independent triangle");
1347 doComparison(oldR.ldeTri, newR.ldeTri, newR.config, same, name,
1348 env, "Locked DrawElements independent triangle");
1349 doComparison(oldR.imTS, newR.imTS, newR.config, same, name,
1350 env, "immediate-mode triangle strip");
1351 doComparison(oldR.dlTS, newR.dlTS, newR.config, same, name,
1352 env, "display-listed triangle strip");
1353 doComparison(oldR.daTS, newR.daTS, newR.config, same, name,
1354 env, "DrawArrays triangle strip");
1355 doComparison(oldR.ldaTS, newR.ldaTS, newR.config, same, name,
1356 env, "Locked DrawArrays triangle strip");
1357 doComparison(oldR.deTS, newR.deTS, newR.config, same, name,
1358 env, "DrawElements triangle strip");
1359 doComparison(oldR.ldeTS, newR.ldeTS, newR.config, same, name,
1360 env, "Locked DrawElements triangle strip");
1362 if (same && env->options.verbosity) {
1363 env->log << name << ": SAME "
1364 << newR.config->conciseDescription()
1365 << "\n\t"
1366 << env->options.db2Name
1367 << " test time falls within the "
1368 << "valid measurement range of\n\t"
1369 << env->options.db1Name
1370 << " test time; both have the same"
1371 << " image comparison results.\n";
1374 if (env->options.verbosity) {
1375 env->log << env->options.db1Name << ':';
1376 logStats(oldR, env);
1377 env->log << env->options.db2Name << ':';
1378 logStats(newR, env);
1380 } // ColoredTexPerf::compareOne
1382 void
1383 ColoredTexPerf::logStats(VPResult& r, GLEAN::Environment* env) {
1384 logStats1("Immediate-mode independent triangle", r.imTri, env);
1385 logStats1("Display-listed independent triangle", r.dlTri, env);
1386 logStats1("DrawArrays independent triangle", r.daTri, env);
1387 logStats1("Locked DrawArrays independent triangle", r.ldaTri, env);
1388 logStats1("DrawElements independent triangle", r.deTri, env);
1389 logStats1("Locked DrawElements independent triangle", r.ldeTri, env);
1390 logStats1("Immediate-mode triangle strip", r.imTS, env);
1391 logStats1("Display-listed triangle strip", r.dlTS, env);
1392 logStats1("DrawArrays triangle strip", r.daTS, env);
1393 logStats1("Locked DrawArrays triangle strip", r.ldaTS, env);
1394 logStats1("DrawElements triangle strip", r.deTS, env);
1395 logStats1("Locked DrawElements triangle strip", r.ldeTS, env);
1396 } // ColoredTexPerf::logStats
1398 ///////////////////////////////////////////////////////////////////////////////
1399 // The test object itself:
1400 ///////////////////////////////////////////////////////////////////////////////
1402 Test* coloredTexPerfTestPrereqs[] = {&exactRGBATest, 0};
1404 ColoredTexPerf coloredTexPerfTest("coloredTexPerf2", "window, rgb, z, fast",
1405 coloredTexPerfTestPrereqs,
1407 "This test examines rendering performance for colored, textured,\n"
1408 "flat-shaded triangles. It checks several different ways to\n"
1409 "specify the vertex data in order to determine which is\n"
1410 "fastest: fine-grained API calls, DrawArrays, DrawElements,\n"
1411 "locked (compiled) DrawArrays, and locked DrawElements; for\n"
1412 "independent triangles and for triangle strips. The test\n"
1413 "result is performance measured in triangles per second for\n"
1414 "each of the various vertex specification methods.\n"
1416 "\nAs a sanity-check on the correctness of each method, the test\n"
1417 "colors each triangle with a unique color, and verifies that all\n"
1418 "such colors are actually present in the final image. For\n"
1419 "consistency, the test also verifies that the images are identical\n"
1420 "for each of the specification methods.\n"
1424 } // namespace GLEAN