progs/perf: convert some DOS line-endings

It seems like some of these files were committed with CRLF initially.
This commit is contained in:
Keith Whitwell 2009-09-17 12:09:16 +01:00
parent e95a3a23dc
commit 2884c31d94
4 changed files with 756 additions and 756 deletions

View File

@ -1,134 +1,134 @@
/*
* Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* VMWARE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* Measure drawing overhead
*
* This is the first in a series of simple performance benchmarks.
* The code in this file should be as simple as possible to make it
* easily portable to other APIs.
*
* All the window-system stuff should be contained in glmain.c (or TBDmain.c).
* All the re-usable, generic code should be in common.c (XXX not done yet).
*
* Brian Paul
* 15 Sep 2009
*/
#include "glmain.h"
#include "common.h"
int WinWidth = 100, WinHeight = 100;
static GLuint VBO;
struct vertex
{
GLfloat x, y;
};
static const struct vertex vertices[4] = {
{ -1.0, -1.0 },
{ 1.0, -1.0 },
{ 1.0, 1.0 },
{ -1.0, 1.0 }
};
/** Called from test harness/main */
void
PerfInit(void)
{
/* setup VBO w/ vertex data */
glGenBuffersARB(1, &VBO);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, VBO);
glBufferDataARB(GL_ARRAY_BUFFER_ARB,
sizeof(vertices), vertices, GL_STATIC_DRAW_ARB);
glVertexPointer(2, GL_FLOAT, sizeof(struct vertex), (void *) 0);
glEnableClientState(GL_VERTEX_ARRAY);
/* misc GL state */
glAlphaFunc(GL_ALWAYS, 0.0);
}
static void
DrawNoStateChange(unsigned count)
{
unsigned i;
for (i = 0; i < count; i++) {
glDrawArrays(GL_POINTS, 0, 4);
}
glFinish();
}
static void
DrawNopStateChange(unsigned count)
{
unsigned i;
for (i = 0; i < count; i++) {
glDisable(GL_ALPHA_TEST);
glDrawArrays(GL_POINTS, 0, 4);
}
glFinish();
}
static void
DrawStateChange(unsigned count)
{
unsigned i;
for (i = 0; i < count; i++) {
if (i & 1)
glEnable(GL_TEXTURE_GEN_S);
else
glDisable(GL_TEXTURE_GEN_S);
glDrawArrays(GL_POINTS, 0, 4);
}
glFinish();
}
/** Called from test harness/main */
void
PerfDraw(void)
{
double rate0, rate1, rate2, overhead;
rate0 = PerfMeasureRate(DrawNoStateChange);
perf_printf(" Draw only: %.1f draws/second\n", rate0);
rate1 = PerfMeasureRate(DrawNopStateChange);
overhead = 1000.0 * (1.0 / rate1 - 1.0 / rate0);
perf_printf(" Draw w/ nop state change: %.1f draws/sec (overhead: %f ms/draw)\n",
rate1, overhead);
rate2 = PerfMeasureRate(DrawStateChange);
overhead = 1000.0 * (1.0 / rate2 - 1.0 / rate0);
perf_printf(" Draw w/ state change: %.1f draws/sec (overhead: %f ms/draw)\n",
rate2, overhead);
exit(0);
}
/*
* Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* VMWARE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* Measure drawing overhead
*
* This is the first in a series of simple performance benchmarks.
* The code in this file should be as simple as possible to make it
* easily portable to other APIs.
*
* All the window-system stuff should be contained in glmain.c (or TBDmain.c).
* All the re-usable, generic code should be in common.c (XXX not done yet).
*
* Brian Paul
* 15 Sep 2009
*/
#include "glmain.h"
#include "common.h"
int WinWidth = 100, WinHeight = 100;
static GLuint VBO;
struct vertex
{
GLfloat x, y;
};
static const struct vertex vertices[4] = {
{ -1.0, -1.0 },
{ 1.0, -1.0 },
{ 1.0, 1.0 },
{ -1.0, 1.0 }
};
/** Called from test harness/main */
void
PerfInit(void)
{
/* setup VBO w/ vertex data */
glGenBuffersARB(1, &VBO);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, VBO);
glBufferDataARB(GL_ARRAY_BUFFER_ARB,
sizeof(vertices), vertices, GL_STATIC_DRAW_ARB);
glVertexPointer(2, GL_FLOAT, sizeof(struct vertex), (void *) 0);
glEnableClientState(GL_VERTEX_ARRAY);
/* misc GL state */
glAlphaFunc(GL_ALWAYS, 0.0);
}
static void
DrawNoStateChange(unsigned count)
{
unsigned i;
for (i = 0; i < count; i++) {
glDrawArrays(GL_POINTS, 0, 4);
}
glFinish();
}
static void
DrawNopStateChange(unsigned count)
{
unsigned i;
for (i = 0; i < count; i++) {
glDisable(GL_ALPHA_TEST);
glDrawArrays(GL_POINTS, 0, 4);
}
glFinish();
}
static void
DrawStateChange(unsigned count)
{
unsigned i;
for (i = 0; i < count; i++) {
if (i & 1)
glEnable(GL_TEXTURE_GEN_S);
else
glDisable(GL_TEXTURE_GEN_S);
glDrawArrays(GL_POINTS, 0, 4);
}
glFinish();
}
/** Called from test harness/main */
void
PerfDraw(void)
{
double rate0, rate1, rate2, overhead;
rate0 = PerfMeasureRate(DrawNoStateChange);
perf_printf(" Draw only: %.1f draws/second\n", rate0);
rate1 = PerfMeasureRate(DrawNopStateChange);
overhead = 1000.0 * (1.0 / rate1 - 1.0 / rate0);
perf_printf(" Draw w/ nop state change: %.1f draws/sec (overhead: %f ms/draw)\n",
rate1, overhead);
rate2 = PerfMeasureRate(DrawStateChange);
overhead = 1000.0 * (1.0 / rate2 - 1.0 / rate0);
perf_printf(" Draw w/ state change: %.1f draws/sec (overhead: %f ms/draw)\n",
rate2, overhead);
exit(0);
}

View File

@ -1,213 +1,213 @@
/*
* Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* VMWARE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* Measure glTexSubImage2D rate
*
* Brian Paul
* 16 Sep 2009
*/
#include "glmain.h"
#include "common.h"
int WinWidth = 100, WinHeight = 100;
static GLuint VBO;
static GLuint TexObj = 0;
static GLubyte *TexImage = NULL;
static GLsizei TexSize;
static GLenum TexSrcFormat, TexSrcType;
static const GLboolean DrawPoint = GL_TRUE;
static const GLboolean TexSubImage4 = GL_TRUE;
struct vertex
{
GLfloat x, y, s, t;
};
static const struct vertex vertices[1] = {
{ 0.0, 0.0, 0.5, 0.5 },
};
#if 0
#define VOFFSET(F) ((void *) offsetof(struct vertex, F))
#else
#define VOFFSET(F) ((void *) &((struct vertex *)NULL)->F)
#endif
/** Called from test harness/main */
void
PerfInit(void)
{
/* setup VBO w/ vertex data */
glGenBuffersARB(1, &VBO);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, VBO);
glBufferDataARB(GL_ARRAY_BUFFER_ARB,
sizeof(vertices), vertices, GL_STATIC_DRAW_ARB);
glVertexPointer(2, GL_FLOAT, sizeof(struct vertex), VOFFSET(x));
glTexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), VOFFSET(s));
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
/* texture */
glGenTextures(1, &TexObj);
glBindTexture(GL_TEXTURE_2D, TexObj);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glEnable(GL_TEXTURE_2D);
}
static void
UploadTexImage2D(unsigned count)
{
unsigned i;
for (i = 0; i < count; i++) {
/* XXX is this equivalent to a glTexSubImage call since we're
* always specifying the same image size? That case isn't optimized
* in Mesa but may be optimized in other drivers. Note sure how
* much difference that might make.
*/
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
TexSize, TexSize, 0,
TexSrcFormat, TexSrcType, TexImage);
if (DrawPoint)
glDrawArrays(GL_POINTS, 0, 1);
}
glFinish();
}
static void
UploadTexSubImage2D(unsigned count)
{
unsigned i;
for (i = 0; i < count; i++) {
if (TexSubImage4) {
GLsizei halfSize = (TexSize == 1) ? 1 : TexSize / 2;
GLsizei halfPos = TexSize - halfSize;
/* do glTexSubImage2D in four pieces */
/* lower-left */
glPixelStorei(GL_UNPACK_ROW_LENGTH, TexSize);
glTexSubImage2D(GL_TEXTURE_2D, 0,
0, 0, halfSize, halfSize,
TexSrcFormat, TexSrcType, TexImage);
/* lower-right */
glPixelStorei(GL_UNPACK_SKIP_PIXELS, halfPos);
glTexSubImage2D(GL_TEXTURE_2D, 0,
halfPos, 0, halfSize, halfSize,
TexSrcFormat, TexSrcType, TexImage);
/* upper-left */
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS, halfPos);
glTexSubImage2D(GL_TEXTURE_2D, 0,
0, halfPos, halfSize, halfSize,
TexSrcFormat, TexSrcType, TexImage);
/* upper-right */
glPixelStorei(GL_UNPACK_SKIP_PIXELS, halfPos);
glPixelStorei(GL_UNPACK_SKIP_ROWS, halfPos);
glTexSubImage2D(GL_TEXTURE_2D, 0,
halfPos, halfPos, halfSize, halfSize,
TexSrcFormat, TexSrcType, TexImage);
/* reset the unpacking state */
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
}
else {
/* replace whole texture image at once */
glTexSubImage2D(GL_TEXTURE_2D, 0,
0, 0, TexSize, TexSize,
TexSrcFormat, TexSrcType, TexImage);
}
if (DrawPoint)
glDrawArrays(GL_POINTS, 0, 1);
}
glFinish();
}
/* XXX any other formats to measure? */
static const struct {
GLenum format, type;
const char *name;
} SrcFormats[] = {
{ GL_RGBA, GL_UNSIGNED_BYTE, "GL_RGBA/GLubyte" },
{ GL_BGRA, GL_UNSIGNED_BYTE, "GL_BGRA/GLubyte" },
{ 0, 0, NULL }
};
/** Called from test harness/main */
void
PerfDraw(void)
{
GLint maxSize;
double rate;
GLint fmt, subImage;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxSize);
/* loop over source data formats */
for (fmt = 0; SrcFormats[fmt].format; fmt++) {
TexSrcFormat = SrcFormats[fmt].format;
TexSrcType = SrcFormats[fmt].type;
/* loop over glTexImage, glTexSubImage */
for (subImage = 0; subImage < 2; subImage++) {
/* loop over texture sizes */
for (TexSize = 16; TexSize <= maxSize; TexSize *= 2) {
GLint bytesPerImage;
double mbPerSec;
bytesPerImage = TexSize * TexSize * 4;
TexImage = malloc(bytesPerImage);
if (subImage) {
/* create initial, empty texture */
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
TexSize, TexSize, 0,
TexSrcFormat, TexSrcType, NULL);
rate = PerfMeasureRate(UploadTexSubImage2D);
}
else {
rate = PerfMeasureRate(UploadTexImage2D);
}
mbPerSec = rate * bytesPerImage / (1024.0 * 1024.0);
perf_printf(" glTex%sImage2D(%s %d x %d): "
"%.1f images/sec, %.1f MB/sec\n",
(subImage ? "Sub" : ""),
SrcFormats[fmt].name, TexSize, TexSize, rate, mbPerSec);
free(TexImage);
}
}
}
exit(0);
}
/*
* Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* VMWARE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* Measure glTexSubImage2D rate
*
* Brian Paul
* 16 Sep 2009
*/
#include "glmain.h"
#include "common.h"
int WinWidth = 100, WinHeight = 100;
static GLuint VBO;
static GLuint TexObj = 0;
static GLubyte *TexImage = NULL;
static GLsizei TexSize;
static GLenum TexSrcFormat, TexSrcType;
static const GLboolean DrawPoint = GL_TRUE;
static const GLboolean TexSubImage4 = GL_TRUE;
struct vertex
{
GLfloat x, y, s, t;
};
static const struct vertex vertices[1] = {
{ 0.0, 0.0, 0.5, 0.5 },
};
#if 0
#define VOFFSET(F) ((void *) offsetof(struct vertex, F))
#else
#define VOFFSET(F) ((void *) &((struct vertex *)NULL)->F)
#endif
/** Called from test harness/main */
void
PerfInit(void)
{
/* setup VBO w/ vertex data */
glGenBuffersARB(1, &VBO);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, VBO);
glBufferDataARB(GL_ARRAY_BUFFER_ARB,
sizeof(vertices), vertices, GL_STATIC_DRAW_ARB);
glVertexPointer(2, GL_FLOAT, sizeof(struct vertex), VOFFSET(x));
glTexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), VOFFSET(s));
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
/* texture */
glGenTextures(1, &TexObj);
glBindTexture(GL_TEXTURE_2D, TexObj);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glEnable(GL_TEXTURE_2D);
}
static void
UploadTexImage2D(unsigned count)
{
unsigned i;
for (i = 0; i < count; i++) {
/* XXX is this equivalent to a glTexSubImage call since we're
* always specifying the same image size? That case isn't optimized
* in Mesa but may be optimized in other drivers. Note sure how
* much difference that might make.
*/
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
TexSize, TexSize, 0,
TexSrcFormat, TexSrcType, TexImage);
if (DrawPoint)
glDrawArrays(GL_POINTS, 0, 1);
}
glFinish();
}
static void
UploadTexSubImage2D(unsigned count)
{
unsigned i;
for (i = 0; i < count; i++) {
if (TexSubImage4) {
GLsizei halfSize = (TexSize == 1) ? 1 : TexSize / 2;
GLsizei halfPos = TexSize - halfSize;
/* do glTexSubImage2D in four pieces */
/* lower-left */
glPixelStorei(GL_UNPACK_ROW_LENGTH, TexSize);
glTexSubImage2D(GL_TEXTURE_2D, 0,
0, 0, halfSize, halfSize,
TexSrcFormat, TexSrcType, TexImage);
/* lower-right */
glPixelStorei(GL_UNPACK_SKIP_PIXELS, halfPos);
glTexSubImage2D(GL_TEXTURE_2D, 0,
halfPos, 0, halfSize, halfSize,
TexSrcFormat, TexSrcType, TexImage);
/* upper-left */
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS, halfPos);
glTexSubImage2D(GL_TEXTURE_2D, 0,
0, halfPos, halfSize, halfSize,
TexSrcFormat, TexSrcType, TexImage);
/* upper-right */
glPixelStorei(GL_UNPACK_SKIP_PIXELS, halfPos);
glPixelStorei(GL_UNPACK_SKIP_ROWS, halfPos);
glTexSubImage2D(GL_TEXTURE_2D, 0,
halfPos, halfPos, halfSize, halfSize,
TexSrcFormat, TexSrcType, TexImage);
/* reset the unpacking state */
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
}
else {
/* replace whole texture image at once */
glTexSubImage2D(GL_TEXTURE_2D, 0,
0, 0, TexSize, TexSize,
TexSrcFormat, TexSrcType, TexImage);
}
if (DrawPoint)
glDrawArrays(GL_POINTS, 0, 1);
}
glFinish();
}
/* XXX any other formats to measure? */
static const struct {
GLenum format, type;
const char *name;
} SrcFormats[] = {
{ GL_RGBA, GL_UNSIGNED_BYTE, "GL_RGBA/GLubyte" },
{ GL_BGRA, GL_UNSIGNED_BYTE, "GL_BGRA/GLubyte" },
{ 0, 0, NULL }
};
/** Called from test harness/main */
void
PerfDraw(void)
{
GLint maxSize;
double rate;
GLint fmt, subImage;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxSize);
/* loop over source data formats */
for (fmt = 0; SrcFormats[fmt].format; fmt++) {
TexSrcFormat = SrcFormats[fmt].format;
TexSrcType = SrcFormats[fmt].type;
/* loop over glTexImage, glTexSubImage */
for (subImage = 0; subImage < 2; subImage++) {
/* loop over texture sizes */
for (TexSize = 16; TexSize <= maxSize; TexSize *= 2) {
GLint bytesPerImage;
double mbPerSec;
bytesPerImage = TexSize * TexSize * 4;
TexImage = malloc(bytesPerImage);
if (subImage) {
/* create initial, empty texture */
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
TexSize, TexSize, 0,
TexSrcFormat, TexSrcType, NULL);
rate = PerfMeasureRate(UploadTexSubImage2D);
}
else {
rate = PerfMeasureRate(UploadTexImage2D);
}
mbPerSec = rate * bytesPerImage / (1024.0 * 1024.0);
perf_printf(" glTex%sImage2D(%s %d x %d): "
"%.1f images/sec, %.1f MB/sec\n",
(subImage ? "Sub" : ""),
SrcFormats[fmt].name, TexSize, TexSize, rate, mbPerSec);
free(TexImage);
}
}
}
exit(0);
}

View File

@ -1,138 +1,138 @@
/*
* Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* VMWARE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* Measure VBO upload speed.
* That is, measure glBufferDataARB() and glBufferSubDataARB().
*
* Brian Paul
* 16 Sep 2009
*/
#include <string.h>
#include "glmain.h"
#include "common.h"
int WinWidth = 100, WinHeight = 100;
static GLuint VBO;
static GLsizei VBOSize = 0;
static GLubyte *VBOData = NULL;
static const GLboolean DrawPoint = GL_TRUE;
static const GLboolean BufferSubDataInHalves = GL_TRUE;
static const GLfloat Vertex0[2] = { 0.0, 0.0 };
/** Called from test harness/main */
void
PerfInit(void)
{
/* setup VBO */
glGenBuffersARB(1, &VBO);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, VBO);
glVertexPointer(2, GL_FLOAT, sizeof(Vertex0), (void *) 0);
glEnableClientState(GL_VERTEX_ARRAY);
}
static void
UploadVBO(unsigned count)
{
unsigned i;
for (i = 0; i < count; i++) {
glBufferDataARB(GL_ARRAY_BUFFER, VBOSize, VBOData, GL_STREAM_DRAW_ARB);
if (DrawPoint)
glDrawArrays(GL_POINTS, 0, 1);
}
glFinish();
}
static void
UploadSubVBO(unsigned count)
{
unsigned i;
for (i = 0; i < count; i++) {
if (BufferSubDataInHalves) {
GLsizei half = VBOSize / 2;
glBufferSubDataARB(GL_ARRAY_BUFFER, 0, half, VBOData);
glBufferSubDataARB(GL_ARRAY_BUFFER, half, half, VBOData + half);
}
else {
glBufferSubDataARB(GL_ARRAY_BUFFER, 0, VBOSize, VBOData);
}
if (DrawPoint)
glDrawArrays(GL_POINTS, 0, 1);
}
glFinish();
}
static const GLsizei Sizes[] = {
64,
1024,
16*1024,
256*1024,
1024*1024,
16*1024*1024,
0 /* end of list */
};
/** Called from test harness/main */
void
PerfDraw(void)
{
double rate, mbPerSec;
int sub, sz;
/* loop over whole/sub buffer upload */
for (sub = 0; sub < 2; sub++) {
/* loop over VBO sizes */
for (sz = 0; Sizes[sz]; sz++) {
VBOSize = Sizes[sz];
VBOData = malloc(VBOSize);
memcpy(VBOData, Vertex0, sizeof(Vertex0));
if (sub)
rate = PerfMeasureRate(UploadSubVBO);
else
rate = PerfMeasureRate(UploadVBO);
mbPerSec = rate * VBOSize / (1024.0 * 1024.0);
perf_printf(" glBuffer%sDataARB(size = %d): %.1f MB/sec\n",
(sub ? "Sub" : ""), VBOSize, mbPerSec);
free(VBOData);
}
}
exit(0);
}
/*
* Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* VMWARE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* Measure VBO upload speed.
* That is, measure glBufferDataARB() and glBufferSubDataARB().
*
* Brian Paul
* 16 Sep 2009
*/
#include <string.h>
#include "glmain.h"
#include "common.h"
int WinWidth = 100, WinHeight = 100;
static GLuint VBO;
static GLsizei VBOSize = 0;
static GLubyte *VBOData = NULL;
static const GLboolean DrawPoint = GL_TRUE;
static const GLboolean BufferSubDataInHalves = GL_TRUE;
static const GLfloat Vertex0[2] = { 0.0, 0.0 };
/** Called from test harness/main */
void
PerfInit(void)
{
/* setup VBO */
glGenBuffersARB(1, &VBO);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, VBO);
glVertexPointer(2, GL_FLOAT, sizeof(Vertex0), (void *) 0);
glEnableClientState(GL_VERTEX_ARRAY);
}
static void
UploadVBO(unsigned count)
{
unsigned i;
for (i = 0; i < count; i++) {
glBufferDataARB(GL_ARRAY_BUFFER, VBOSize, VBOData, GL_STREAM_DRAW_ARB);
if (DrawPoint)
glDrawArrays(GL_POINTS, 0, 1);
}
glFinish();
}
static void
UploadSubVBO(unsigned count)
{
unsigned i;
for (i = 0; i < count; i++) {
if (BufferSubDataInHalves) {
GLsizei half = VBOSize / 2;
glBufferSubDataARB(GL_ARRAY_BUFFER, 0, half, VBOData);
glBufferSubDataARB(GL_ARRAY_BUFFER, half, half, VBOData + half);
}
else {
glBufferSubDataARB(GL_ARRAY_BUFFER, 0, VBOSize, VBOData);
}
if (DrawPoint)
glDrawArrays(GL_POINTS, 0, 1);
}
glFinish();
}
static const GLsizei Sizes[] = {
64,
1024,
16*1024,
256*1024,
1024*1024,
16*1024*1024,
0 /* end of list */
};
/** Called from test harness/main */
void
PerfDraw(void)
{
double rate, mbPerSec;
int sub, sz;
/* loop over whole/sub buffer upload */
for (sub = 0; sub < 2; sub++) {
/* loop over VBO sizes */
for (sz = 0; Sizes[sz]; sz++) {
VBOSize = Sizes[sz];
VBOData = malloc(VBOSize);
memcpy(VBOData, Vertex0, sizeof(Vertex0));
if (sub)
rate = PerfMeasureRate(UploadSubVBO);
else
rate = PerfMeasureRate(UploadVBO);
mbPerSec = rate * VBOSize / (1024.0 * 1024.0);
perf_printf(" glBuffer%sDataARB(size = %d): %.1f MB/sec\n",
(sub ? "Sub" : ""), VBOSize, mbPerSec);
free(VBOData);
}
}
exit(0);
}

View File

@ -1,271 +1,271 @@
/*
* Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* VMWARE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* Measure simple vertex processing rate via:
* - immediate mode
* - vertex arrays
* - VBO vertex arrays
* - glDrawElements
* - VBO glDrawElements
* - glDrawRangeElements
* - VBO glDrawRangeElements
*
* Brian Paul
* 16 Sep 2009
*/
#include <assert.h>
#include <string.h>
#include "glmain.h"
#include "common.h"
#define MAX_VERTS (100 * 100)
/** glVertex2/3/4 size */
#define VERT_SIZE 4
int WinWidth = 500, WinHeight = 500;
static GLuint VertexBO, ElementBO;
static unsigned NumVerts = MAX_VERTS;
static unsigned VertBytes = VERT_SIZE * sizeof(float);
static float *VertexData = NULL;
static unsigned NumElements = MAX_VERTS;
static GLuint *Elements = NULL;
/**
* Load VertexData buffer with a 2-D grid of points in the range [-1,1]^2.
*/
static void
InitializeVertexData(void)
{
unsigned i;
float x = -1.0, y = -1.0;
float dx = 2.0 / 100;
float dy = 2.0 / 100;
VertexData = (float *) malloc(NumVerts * VertBytes);
for (i = 0; i < NumVerts; i++) {
VertexData[i * VERT_SIZE + 0] = x;
VertexData[i * VERT_SIZE + 1] = y;
VertexData[i * VERT_SIZE + 2] = 0.0;
VertexData[i * VERT_SIZE + 3] = 1.0;
x += dx;
if (x > 1.0) {
x = -1.0;
y += dy;
}
}
Elements = (GLuint *) malloc(NumVerts * sizeof(GLuint));
for (i = 0; i < NumVerts; i++) {
Elements[i] = NumVerts - i - 1;
}
}
/** Called from test harness/main */
void
PerfInit(void)
{
InitializeVertexData();
/* setup VertexBO */
glGenBuffersARB(1, &VertexBO);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, VertexBO);
glBufferDataARB(GL_ARRAY_BUFFER_ARB,
NumVerts * VertBytes, VertexData, GL_STATIC_DRAW_ARB);
glEnableClientState(GL_VERTEX_ARRAY);
/* setup ElementBO */
glGenBuffersARB(1, &ElementBO);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ElementBO);
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
NumElements * sizeof(GLuint), Elements, GL_STATIC_DRAW_ARB);
}
static void
DrawImmediate(unsigned count)
{
unsigned i;
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBufferARB(GL_ARRAY_BUFFER, 0);
for (i = 0; i < count; i++) {
unsigned j;
glBegin(GL_POINTS);
for (j = 0; j < NumVerts; j++) {
#if VERT_SIZE == 4
glVertex4fv(VertexData + j * 4);
#elif VERT_SIZE == 3
glVertex3fv(VertexData + j * 3);
#elif VERT_SIZE == 2
glVertex2fv(VertexData + j * 2);
#else
abort();
#endif
}
glEnd();
}
glFinish();
PerfSwapBuffers();
}
static void
DrawArraysMem(unsigned count)
{
unsigned i;
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBufferARB(GL_ARRAY_BUFFER, 0);
glVertexPointer(VERT_SIZE, GL_FLOAT, VertBytes, VertexData);
for (i = 0; i < count; i++) {
glDrawArrays(GL_POINTS, 0, NumVerts);
}
glFinish();
PerfSwapBuffers();
}
static void
DrawArraysVBO(unsigned count)
{
unsigned i;
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBufferARB(GL_ARRAY_BUFFER, VertexBO);
glVertexPointer(VERT_SIZE, GL_FLOAT, VertBytes, (void *) 0);
for (i = 0; i < count; i++) {
glDrawArrays(GL_POINTS, 0, NumVerts);
}
glFinish();
PerfSwapBuffers();
}
static void
DrawElementsMem(unsigned count)
{
unsigned i;
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBufferARB(GL_ARRAY_BUFFER, 0);
glVertexPointer(VERT_SIZE, GL_FLOAT, VertBytes, VertexData);
for (i = 0; i < count; i++) {
glDrawElements(GL_POINTS, NumVerts, GL_UNSIGNED_INT, Elements);
}
glFinish();
PerfSwapBuffers();
}
static void
DrawElementsBO(unsigned count)
{
unsigned i;
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, ElementBO);
glBindBufferARB(GL_ARRAY_BUFFER, VertexBO);
glVertexPointer(VERT_SIZE, GL_FLOAT, VertBytes, (void *) 0);
for (i = 0; i < count; i++) {
glDrawElements(GL_POINTS, NumVerts, GL_UNSIGNED_INT, (void *) 0);
}
glFinish();
PerfSwapBuffers();
}
static void
DrawRangeElementsMem(unsigned count)
{
unsigned i;
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBufferARB(GL_ARRAY_BUFFER, 0);
glVertexPointer(VERT_SIZE, GL_FLOAT, VertBytes, VertexData);
for (i = 0; i < count; i++) {
glDrawRangeElements(GL_POINTS, 0, NumVerts - 1,
NumVerts, GL_UNSIGNED_INT, Elements);
}
glFinish();
PerfSwapBuffers();
}
static void
DrawRangeElementsBO(unsigned count)
{
unsigned i;
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, ElementBO);
glBindBufferARB(GL_ARRAY_BUFFER, VertexBO);
glVertexPointer(VERT_SIZE, GL_FLOAT, VertBytes, (void *) 0);
for (i = 0; i < count; i++) {
glDrawRangeElements(GL_POINTS, 0, NumVerts - 1,
NumVerts, GL_UNSIGNED_INT, (void *) 0);
}
glFinish();
PerfSwapBuffers();
}
/** Called from test harness/main */
void
PerfDraw(void)
{
double rate;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
perf_printf("Vertex rate (%d x Vertex%df)\n", NumVerts, VERT_SIZE);
rate = PerfMeasureRate(DrawImmediate);
rate *= NumVerts;
perf_printf(" Immediate mode: %.1f verts/sec\n", rate);
rate = PerfMeasureRate(DrawArraysMem);
rate *= NumVerts;
perf_printf(" glDrawArrays: %.1f verts/sec\n", rate);
rate = PerfMeasureRate(DrawArraysVBO);
rate *= NumVerts;
perf_printf(" VBO glDrawArrays: %.1f verts/sec\n", rate);
rate = PerfMeasureRate(DrawElementsMem);
rate *= NumVerts;
perf_printf(" glDrawElements: %.1f verts/sec\n", rate);
rate = PerfMeasureRate(DrawElementsBO);
rate *= NumVerts;
perf_printf(" VBO glDrawElements: %.1f verts/sec\n", rate);
rate = PerfMeasureRate(DrawRangeElementsMem);
rate *= NumVerts;
perf_printf(" glDrawRangeElements: %.1f verts/sec\n", rate);
rate = PerfMeasureRate(DrawRangeElementsBO);
rate *= NumVerts;
perf_printf(" VBO glDrawRangeElements: %.1f verts/sec\n", rate);
exit(0);
}
/*
* Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* VMWARE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* Measure simple vertex processing rate via:
* - immediate mode
* - vertex arrays
* - VBO vertex arrays
* - glDrawElements
* - VBO glDrawElements
* - glDrawRangeElements
* - VBO glDrawRangeElements
*
* Brian Paul
* 16 Sep 2009
*/
#include <assert.h>
#include <string.h>
#include "glmain.h"
#include "common.h"
#define MAX_VERTS (100 * 100)
/** glVertex2/3/4 size */
#define VERT_SIZE 4
int WinWidth = 500, WinHeight = 500;
static GLuint VertexBO, ElementBO;
static unsigned NumVerts = MAX_VERTS;
static unsigned VertBytes = VERT_SIZE * sizeof(float);
static float *VertexData = NULL;
static unsigned NumElements = MAX_VERTS;
static GLuint *Elements = NULL;
/**
* Load VertexData buffer with a 2-D grid of points in the range [-1,1]^2.
*/
static void
InitializeVertexData(void)
{
unsigned i;
float x = -1.0, y = -1.0;
float dx = 2.0 / 100;
float dy = 2.0 / 100;
VertexData = (float *) malloc(NumVerts * VertBytes);
for (i = 0; i < NumVerts; i++) {
VertexData[i * VERT_SIZE + 0] = x;
VertexData[i * VERT_SIZE + 1] = y;
VertexData[i * VERT_SIZE + 2] = 0.0;
VertexData[i * VERT_SIZE + 3] = 1.0;
x += dx;
if (x > 1.0) {
x = -1.0;
y += dy;
}
}
Elements = (GLuint *) malloc(NumVerts * sizeof(GLuint));
for (i = 0; i < NumVerts; i++) {
Elements[i] = NumVerts - i - 1;
}
}
/** Called from test harness/main */
void
PerfInit(void)
{
InitializeVertexData();
/* setup VertexBO */
glGenBuffersARB(1, &VertexBO);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, VertexBO);
glBufferDataARB(GL_ARRAY_BUFFER_ARB,
NumVerts * VertBytes, VertexData, GL_STATIC_DRAW_ARB);
glEnableClientState(GL_VERTEX_ARRAY);
/* setup ElementBO */
glGenBuffersARB(1, &ElementBO);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ElementBO);
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
NumElements * sizeof(GLuint), Elements, GL_STATIC_DRAW_ARB);
}
static void
DrawImmediate(unsigned count)
{
unsigned i;
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBufferARB(GL_ARRAY_BUFFER, 0);
for (i = 0; i < count; i++) {
unsigned j;
glBegin(GL_POINTS);
for (j = 0; j < NumVerts; j++) {
#if VERT_SIZE == 4
glVertex4fv(VertexData + j * 4);
#elif VERT_SIZE == 3
glVertex3fv(VertexData + j * 3);
#elif VERT_SIZE == 2
glVertex2fv(VertexData + j * 2);
#else
abort();
#endif
}
glEnd();
}
glFinish();
PerfSwapBuffers();
}
static void
DrawArraysMem(unsigned count)
{
unsigned i;
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBufferARB(GL_ARRAY_BUFFER, 0);
glVertexPointer(VERT_SIZE, GL_FLOAT, VertBytes, VertexData);
for (i = 0; i < count; i++) {
glDrawArrays(GL_POINTS, 0, NumVerts);
}
glFinish();
PerfSwapBuffers();
}
static void
DrawArraysVBO(unsigned count)
{
unsigned i;
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBufferARB(GL_ARRAY_BUFFER, VertexBO);
glVertexPointer(VERT_SIZE, GL_FLOAT, VertBytes, (void *) 0);
for (i = 0; i < count; i++) {
glDrawArrays(GL_POINTS, 0, NumVerts);
}
glFinish();
PerfSwapBuffers();
}
static void
DrawElementsMem(unsigned count)
{
unsigned i;
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBufferARB(GL_ARRAY_BUFFER, 0);
glVertexPointer(VERT_SIZE, GL_FLOAT, VertBytes, VertexData);
for (i = 0; i < count; i++) {
glDrawElements(GL_POINTS, NumVerts, GL_UNSIGNED_INT, Elements);
}
glFinish();
PerfSwapBuffers();
}
static void
DrawElementsBO(unsigned count)
{
unsigned i;
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, ElementBO);
glBindBufferARB(GL_ARRAY_BUFFER, VertexBO);
glVertexPointer(VERT_SIZE, GL_FLOAT, VertBytes, (void *) 0);
for (i = 0; i < count; i++) {
glDrawElements(GL_POINTS, NumVerts, GL_UNSIGNED_INT, (void *) 0);
}
glFinish();
PerfSwapBuffers();
}
static void
DrawRangeElementsMem(unsigned count)
{
unsigned i;
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBufferARB(GL_ARRAY_BUFFER, 0);
glVertexPointer(VERT_SIZE, GL_FLOAT, VertBytes, VertexData);
for (i = 0; i < count; i++) {
glDrawRangeElements(GL_POINTS, 0, NumVerts - 1,
NumVerts, GL_UNSIGNED_INT, Elements);
}
glFinish();
PerfSwapBuffers();
}
static void
DrawRangeElementsBO(unsigned count)
{
unsigned i;
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, ElementBO);
glBindBufferARB(GL_ARRAY_BUFFER, VertexBO);
glVertexPointer(VERT_SIZE, GL_FLOAT, VertBytes, (void *) 0);
for (i = 0; i < count; i++) {
glDrawRangeElements(GL_POINTS, 0, NumVerts - 1,
NumVerts, GL_UNSIGNED_INT, (void *) 0);
}
glFinish();
PerfSwapBuffers();
}
/** Called from test harness/main */
void
PerfDraw(void)
{
double rate;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
perf_printf("Vertex rate (%d x Vertex%df)\n", NumVerts, VERT_SIZE);
rate = PerfMeasureRate(DrawImmediate);
rate *= NumVerts;
perf_printf(" Immediate mode: %.1f verts/sec\n", rate);
rate = PerfMeasureRate(DrawArraysMem);
rate *= NumVerts;
perf_printf(" glDrawArrays: %.1f verts/sec\n", rate);
rate = PerfMeasureRate(DrawArraysVBO);
rate *= NumVerts;
perf_printf(" VBO glDrawArrays: %.1f verts/sec\n", rate);
rate = PerfMeasureRate(DrawElementsMem);
rate *= NumVerts;
perf_printf(" glDrawElements: %.1f verts/sec\n", rate);
rate = PerfMeasureRate(DrawElementsBO);
rate *= NumVerts;
perf_printf(" VBO glDrawElements: %.1f verts/sec\n", rate);
rate = PerfMeasureRate(DrawRangeElementsMem);
rate *= NumVerts;
perf_printf(" glDrawRangeElements: %.1f verts/sec\n", rate);
rate = PerfMeasureRate(DrawRangeElementsBO);
rate *= NumVerts;
perf_printf(" VBO glDrawRangeElements: %.1f verts/sec\n", rate);
exit(0);
}