1 // BEGIN_COPYRIGHT -*- glean -*-
3 // Copyright (C) 2000 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 // tvtxperf.cpp: Test performance of various ways to specify vertex data
52 class TvtxBaseTimer
: public GLEAN::Timer
{
58 GLEAN::Environment
* env
;
60 TvtxBaseTimer(int v
, GLuint
* i
, int t
, GLEAN::Window
* win
,
61 GLEAN::Environment
* 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
74 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
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
{
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
) {
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
98 for (int i
= nVertices
/ 3; i
; --i
) {
112 }; // coloredLit_imIndTri
114 class ColoredTex_imIndTri
: public TvtxBaseTimer
{
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
) {
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
129 for (int i
= nVertices
/ 3; i
; --i
) {
131 glTexCoord2fv(p
[0].t
);
134 glTexCoord2fv(p
[0].t
);
137 glTexCoord2fv(p
[0].t
);
143 }; // coloredTex_imIndTri
145 class ColoredLit_imTriStrip
: public TvtxBaseTimer
{
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
) {
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) {
186 }; // coloredLit_imTriStrip
188 class ColoredTex_imTriStrip
: public TvtxBaseTimer
{
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
) {
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) {
230 }; // coloredTex_imTriStrip
232 class daIndTriTimer
: public TvtxBaseTimer
{
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
); }
241 class daTriStripTimer
: public TvtxBaseTimer
{
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
{
252 deIndTriTimer(int v
, GLuint
* i
, int t
, GLEAN::Window
* w
,
253 GLEAN::Environment
* env
):
254 TvtxBaseTimer(v
, i
, t
, w
, env
) {
257 glDrawElements(GL_TRIANGLES
, nVertices
, GL_UNSIGNED_INT
,
262 class deTriStripTimer
: public TvtxBaseTimer
{
264 deTriStripTimer(int v
, GLuint
* i
, int t
, GLEAN::Window
* w
,
265 GLEAN::Environment
* env
):
266 TvtxBaseTimer(v
, i
, t
, w
, env
) {
269 glDrawElements(GL_TRIANGLE_STRIP
, nVertices
, GL_UNSIGNED_INT
,
272 }; // deTriStripTimer
275 class callDListTimer
: public TvtxBaseTimer
{
278 callDListTimer(int d
, int t
, GLEAN::Window
* w
,
279 GLEAN::Environment
* env
):
280 TvtxBaseTimer(0, 0, t
, w
, env
) {
283 virtual void op() { glCallList(dList
); }
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");
301 diffHeader(bool& same
, const string
& name
,
302 GLEAN::DrawingSurfaceConfig
* config
, GLEAN::Environment
* env
) {
305 env
->log
<< name
<< ": DIFF "
306 << config
->conciseDescription() << '\n';
311 failHeader(bool& pass
, const string
& name
,
312 GLEAN::DrawingSurfaceConfig
* config
, GLEAN::Environment
* env
) {
315 env
->log
<< name
<< ": FAIL "
316 << config
->conciseDescription() << '\n';
321 doComparison(const GLEAN::VPSubResult
& oldR
,
322 const GLEAN::VPSubResult
& newR
,
323 GLEAN::DrawingSurfaceConfig
* config
,
324 bool& same
, const string
& name
, GLEAN::Environment
* env
,
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");
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;
367 missingSome(GLEAN::Environment
* env
, const char* title
) {
368 env
->log
<< '\t' << title
<< " rendering is missing\n"
369 << "\t\tsome triangles.\n";
373 theyDiffer(GLEAN::Environment
* env
, const char* title
) {
374 env
->log
<< '\t' << title
<< " image differs from\n"
375 << "\t\tthe reference image.\n";
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
);
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;
402 } // anonymous namespace
406 ///////////////////////////////////////////////////////////////////////////////
407 // runOne: Run a single test case
408 ///////////////////////////////////////////////////////////////////////////////
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();
418 if ((*erRes
)->config
== r
.config
)
420 if (erRes
== exactRGBATest
.results
.end() || !(*erRes
)->ub
.pass
) {
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
);
459 for (int j
= 0; j
< nTris
; ++j
) {
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;
500 GLuint
*indices
= new GLuint
[nVertices
];
501 for (k
= 0; k
< nVertices
; ++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);
518 GLUtils::LightModel lm
;
519 lm
.ambient(0, 0, 0, 0);
520 lm
.localViewer(false);
522 lm
.colorControl(GL_SINGLE_COLOR
);
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);
532 glColorMaterial(GL_FRONT_AND_BACK
, GL_AMBIENT_AND_DIFFUSE
);
533 glEnable(GL_COLOR_MATERIAL
);
535 glEnable(GL_LIGHTING
);
538 glDisable(GL_SCISSOR_TEST
);
539 glDisable(GL_ALPHA_TEST
);
540 glDisable(GL_STENCIL_TEST
);
541 glDepthFunc(GL_LEQUAL
);
542 glEnable(GL_DEPTH_TEST
);
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
);
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
,
565 coloredLit_imIndTri
.measure(5, &r
.imTri
.tpsLow
, &r
.imTri
.tps
,
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();
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]),
591 glEnableClientState(GL_COLOR_ARRAY
);
592 glNormalPointer(GL_FLOAT
, sizeof(c4ub_n3f_v3f
[0]),
594 glEnableClientState(GL_NORMAL_ARRAY
);
595 glVertexPointer(3, GL_FLOAT
, sizeof(c4ub_n3f_v3f
[0]),
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
609 ////////////////////////////////////////////////////////////
611 glLockArraysEXT(0, nVertices
);
612 daIndTri
.measure(5, &r
.ldaTri
.tpsLow
, &r
.ldaTri
.tps
,
614 if (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 ////////////////////////////////////////////////////////////
635 glLockArraysEXT(0, nVertices
);
636 deIndTri
.measure(5, &r
.ldeTri
.tpsLow
, &r
.ldeTri
.tps
,
638 if (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
;
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
) {
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
)
682 ////////////////////////////////////////////////////////////
683 // Immediate-mode triangle strips
684 ////////////////////////////////////////////////////////////
685 ColoredLit_imTriStrip
coloredLit_imTriStrip(nVertices
, c4ub_n3f_v3f
,
687 coloredLit_imTriStrip
.measure(5, &r
.imTS
.tpsLow
, &r
.imTS
.tps
,
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();
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]),
712 glEnableClientState(GL_COLOR_ARRAY
);
713 glNormalPointer(GL_FLOAT
, sizeof(c4ub_n3f_v3f
[0]),
715 glEnableClientState(GL_NORMAL_ARRAY
);
716 glVertexPointer(3, GL_FLOAT
, sizeof(c4ub_n3f_v3f
[0]),
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 ////////////////////////////////////////////////////////////
730 glLockArraysEXT(0, nVertices
);
731 daTriStrip
.measure(5, &r
.ldaTS
.tpsLow
, &r
.ldaTS
.tps
, &r
.ldaTS
.tpsHigh
);
732 if (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 ////////////////////////////////////////////////////////////
753 glLockArraysEXT(0, nVertices
);
754 deTriStrip
.measure(5, &r
.ldeTS
.tpsLow
, &r
.ldeTS
.tps
, &r
.ldeTS
.tpsHigh
);
755 if (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
;
773 } // ColoredLitPerf::runOne
775 ///////////////////////////////////////////////////////////////////////////////
776 // logOne: Log a single test case
777 ///////////////////////////////////////////////////////////////////////////////
779 ColoredLitPerf::logOne(VPResult
& r
) {
781 env
->log
<< name
<< ": NOTE ";
783 env
->log
<< "\tTest skipped; prerequisite test "
784 << exactRGBATest
.name
785 << " failed or was not run\n";
791 } else env
->log
<< '\n'; // because verify logs failure
793 } // ColoredLitPerf::logOne
795 ///////////////////////////////////////////////////////////////////////////////
796 // compareOne: Compare results for a single test case
797 ///////////////////////////////////////////////////////////////////////////////
799 ColoredLitPerf::compareOne(VPResult
& oldR
, VPResult
& newR
) {
800 if (oldR
.skipped
|| newR
.skipped
) {
802 << ((oldR
.skipped
&& newR
.skipped
)? ": SAME "
804 << newR
.config
->conciseDescription()
808 << env
->options
.db1Name
812 << env
->options
.db2Name
814 env
->log
<< "\tNo comparison is possible.\n";
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()
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
<< ':';
859 env
->log
<< env
->options
.db2Name
<< ':';
862 } // ColoredLitPerf::compareOne
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 ///////////////////////////////////////////////////////////////////////////////
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();
919 if ((*erRes
)->config
== r
.config
)
921 if (erRes
== exactRGBATest
.results
.end() || !(*erRes
)->ub
.pass
) {
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
);
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
);
960 for (int j
= 0; j
< nTris
; ++j
) {
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;
998 GLuint
*indices
= new GLuint
[nVertices
];
999 for (k
= 0; k
< nVertices
; ++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
)
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
);
1047 glMatrixMode(GL_MODELVIEW
);
1049 glDisable(GL_TEXTURE_GEN_S
);
1050 glDisable(GL_TEXTURE_GEN_T
);
1052 glEnable(GL_TEXTURE_2D
);
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
,
1083 coloredTex_imIndTri
.measure(5, &r
.imTri
.tpsLow
, &r
.imTri
.tps
,
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();
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]),
1109 glEnableClientState(GL_COLOR_ARRAY
);
1110 glTexCoordPointer(2, GL_FLOAT
, sizeof(c4ub_t2f_v3f
[0]),
1112 glEnableClientState(GL_TEXTURE_COORD_ARRAY
);
1113 glVertexPointer(3, GL_FLOAT
, sizeof(c4ub_t2f_v3f
[0]),
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
1127 ////////////////////////////////////////////////////////////
1128 if (glLockArraysEXT
)
1129 glLockArraysEXT(0, nVertices
);
1130 daIndTri
.measure(5, &r
.ldaTri
.tpsLow
, &r
.ldaTri
.tps
,
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
,
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
;
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
) {
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
)
1199 ////////////////////////////////////////////////////////////
1200 // Immediate-mode triangle strips
1201 ////////////////////////////////////////////////////////////
1202 ColoredTex_imTriStrip
coloredTex_imTriStrip(nVertices
, c4ub_t2f_v3f
,
1204 coloredTex_imTriStrip
.measure(5, &r
.imTS
.tpsLow
, &r
.imTS
.tps
,
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();
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]),
1229 glEnableClientState(GL_COLOR_ARRAY
);
1230 glTexCoordPointer(2, GL_FLOAT
, sizeof(c4ub_t2f_v3f
[0]),
1232 glEnableClientState(GL_TEXTURE_COORD_ARRAY
);
1233 glVertexPointer(3, GL_FLOAT
, sizeof(c4ub_t2f_v3f
[0]),
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
;
1290 } // ColoredTexPerf::runOne
1292 ///////////////////////////////////////////////////////////////////////////////
1293 // logOne: Log a single test case
1294 ///////////////////////////////////////////////////////////////////////////////
1296 ColoredTexPerf::logOne(VPResult
& r
) {
1298 env
->log
<< name
<< ": NOTE ";
1300 env
->log
<< "\tTest skipped; prerequisite test "
1301 << exactRGBATest
.name
1302 << " failed or was not run\n"
1309 } else env
->log
<< '\n'; // because verify logs failure
1311 } // ColoredTexPerf::logOne
1313 ///////////////////////////////////////////////////////////////////////////////
1314 // compareOne: Compare results for a single test case
1315 ///////////////////////////////////////////////////////////////////////////////
1317 ColoredTexPerf::compareOne(VPResult
& oldR
, VPResult
& newR
) {
1318 if (oldR
.skipped
|| newR
.skipped
) {
1320 << ((oldR
.skipped
&& newR
.skipped
)? ": SAME "
1322 << newR
.config
->conciseDescription()
1326 << env
->options
.db1Name
1330 << env
->options
.db2Name
1332 env
->log
<< "\tNo comparison is possible.\n";
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()
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
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