247 lines
6.2 KiB
C
247 lines
6.2 KiB
C
|
/*
|
||
|
* 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"
|
||
|
|
||
|
/* Copy data out of a large array to avoid caching effects:
|
||
|
*/
|
||
|
#define DATA_SIZE (16*1024*1024)
|
||
|
|
||
|
int WinWidth = 100, WinHeight = 100;
|
||
|
|
||
|
static GLuint VBO;
|
||
|
|
||
|
static GLsizei VBOSize = 0;
|
||
|
static GLsizei SubSize = 0;
|
||
|
static GLubyte *VBOData = NULL; /* array[DATA_SIZE] */
|
||
|
|
||
|
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;
|
||
|
unsigned total = 0;
|
||
|
unsigned src = 0;
|
||
|
|
||
|
for (i = 0; i < count; i++) {
|
||
|
glBufferDataARB(GL_ARRAY_BUFFER, VBOSize, VBOData + src, GL_STREAM_DRAW_ARB);
|
||
|
glDrawArrays(GL_POINTS, 0, 1);
|
||
|
|
||
|
/* Throw in an occasional flush to work around a driver crash:
|
||
|
*/
|
||
|
total += VBOSize;
|
||
|
if (total >= 16*1024*1024) {
|
||
|
glFlush();
|
||
|
total = 0;
|
||
|
}
|
||
|
|
||
|
src += VBOSize;
|
||
|
src %= DATA_SIZE;
|
||
|
}
|
||
|
glFinish();
|
||
|
}
|
||
|
|
||
|
|
||
|
static void
|
||
|
UploadSubVBO(unsigned count)
|
||
|
{
|
||
|
unsigned i;
|
||
|
unsigned src = 0;
|
||
|
|
||
|
for (i = 0; i < count; i++) {
|
||
|
unsigned offset = (i * SubSize) % VBOSize;
|
||
|
glBufferSubDataARB(GL_ARRAY_BUFFER, offset, SubSize, VBOData + src);
|
||
|
|
||
|
if (DrawPoint) {
|
||
|
glDrawArrays(GL_POINTS, offset / sizeof(Vertex0), 1);
|
||
|
}
|
||
|
|
||
|
src += SubSize;
|
||
|
src %= DATA_SIZE;
|
||
|
}
|
||
|
glFinish();
|
||
|
}
|
||
|
|
||
|
|
||
|
/* Do multiple small SubData uploads, then call DrawArrays. This may be a
|
||
|
* fairer comparison to back-to-back BufferData calls:
|
||
|
*/
|
||
|
static void
|
||
|
BatchUploadSubVBO(unsigned count)
|
||
|
{
|
||
|
unsigned i = 0, j;
|
||
|
unsigned period = VBOSize / SubSize;
|
||
|
unsigned src = 0;
|
||
|
|
||
|
while (i < count) {
|
||
|
for (j = 0; j < period && i < count; j++, i++) {
|
||
|
unsigned offset = j * SubSize;
|
||
|
glBufferSubDataARB(GL_ARRAY_BUFFER, offset, SubSize, VBOData + src);
|
||
|
}
|
||
|
|
||
|
glDrawArrays(GL_POINTS, 0, 1);
|
||
|
|
||
|
src += SubSize;
|
||
|
src %= DATA_SIZE;
|
||
|
}
|
||
|
glFinish();
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Test the sequence:
|
||
|
* create/load VBO
|
||
|
* draw
|
||
|
* destroy VBO
|
||
|
*/
|
||
|
static void
|
||
|
CreateDrawDestroyVBO(unsigned count)
|
||
|
{
|
||
|
unsigned i;
|
||
|
for (i = 0; i < count; i++) {
|
||
|
GLuint vbo;
|
||
|
/* create/load */
|
||
|
glGenBuffersARB(1, &vbo);
|
||
|
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
|
||
|
glBufferDataARB(GL_ARRAY_BUFFER, VBOSize, VBOData, GL_STREAM_DRAW_ARB);
|
||
|
/* draw */
|
||
|
glVertexPointer(2, GL_FLOAT, sizeof(Vertex0), (void *) 0);
|
||
|
glDrawArrays(GL_POINTS, 0, 1);
|
||
|
/* destroy */
|
||
|
glDeleteBuffersARB(1, &vbo);
|
||
|
}
|
||
|
glFinish();
|
||
|
}
|
||
|
|
||
|
|
||
|
static const GLsizei Sizes[] = {
|
||
|
64,
|
||
|
1024,
|
||
|
16*1024,
|
||
|
256*1024,
|
||
|
1024*1024,
|
||
|
16*1024*1024,
|
||
|
0 /* end of list */
|
||
|
};
|
||
|
|
||
|
void
|
||
|
PerfNextRound(void)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
/** Called from test harness/main */
|
||
|
void
|
||
|
PerfDraw(void)
|
||
|
{
|
||
|
double rate, mbPerSec;
|
||
|
int i, sz;
|
||
|
|
||
|
/* Load VBOData buffer with duplicated Vertex0.
|
||
|
*/
|
||
|
VBOData = calloc(DATA_SIZE, 1);
|
||
|
|
||
|
for (i = 0; i < DATA_SIZE / sizeof(Vertex0); i++) {
|
||
|
memcpy(VBOData + i * sizeof(Vertex0),
|
||
|
Vertex0,
|
||
|
sizeof(Vertex0));
|
||
|
}
|
||
|
|
||
|
/* glBufferDataARB()
|
||
|
*/
|
||
|
for (sz = 0; Sizes[sz]; sz++) {
|
||
|
SubSize = VBOSize = Sizes[sz];
|
||
|
rate = PerfMeasureRate(UploadVBO);
|
||
|
mbPerSec = rate * VBOSize / (1024.0 * 1024.0);
|
||
|
perf_printf(" glBufferDataARB(size = %d): %.1f MB/sec\n",
|
||
|
VBOSize, mbPerSec);
|
||
|
}
|
||
|
|
||
|
/* glBufferSubDataARB()
|
||
|
*/
|
||
|
for (sz = 0; Sizes[sz]; sz++) {
|
||
|
SubSize = VBOSize = Sizes[sz];
|
||
|
rate = PerfMeasureRate(UploadSubVBO);
|
||
|
mbPerSec = rate * VBOSize / (1024.0 * 1024.0);
|
||
|
perf_printf(" glBufferSubDataARB(size = %d): %.1f MB/sec\n",
|
||
|
VBOSize, mbPerSec);
|
||
|
}
|
||
|
|
||
|
/* Batch upload
|
||
|
*/
|
||
|
VBOSize = 1024 * 1024;
|
||
|
glBufferDataARB(GL_ARRAY_BUFFER, VBOSize, VBOData, GL_STREAM_DRAW_ARB);
|
||
|
|
||
|
for (sz = 0; Sizes[sz] < VBOSize; sz++) {
|
||
|
SubSize = Sizes[sz];
|
||
|
rate = PerfMeasureRate(UploadSubVBO);
|
||
|
mbPerSec = rate * SubSize / (1024.0 * 1024.0);
|
||
|
perf_printf(" glBufferSubDataARB(size = %d, VBOSize = %d): %.1f MB/sec\n",
|
||
|
SubSize, VBOSize, mbPerSec);
|
||
|
}
|
||
|
|
||
|
for (sz = 0; Sizes[sz] < VBOSize; sz++) {
|
||
|
SubSize = Sizes[sz];
|
||
|
rate = PerfMeasureRate(BatchUploadSubVBO);
|
||
|
mbPerSec = rate * SubSize / (1024.0 * 1024.0);
|
||
|
perf_printf(" glBufferSubDataARB(size = %d, VBOSize = %d), batched: %.1f MB/sec\n",
|
||
|
SubSize, VBOSize, mbPerSec);
|
||
|
}
|
||
|
|
||
|
/* Create/Draw/Destroy
|
||
|
*/
|
||
|
for (sz = 0; Sizes[sz]; sz++) {
|
||
|
SubSize = VBOSize = Sizes[sz];
|
||
|
rate = PerfMeasureRate(CreateDrawDestroyVBO);
|
||
|
mbPerSec = rate * VBOSize / (1024.0 * 1024.0);
|
||
|
perf_printf(" VBO Create/Draw/Destroy(size = %d): %.1f MB/sec, %.1f draws/sec\n",
|
||
|
VBOSize, mbPerSec, rate);
|
||
|
}
|
||
|
|
||
|
exit(0);
|
||
|
}
|