diff options
Diffstat (limited to 'progs/perf/vbo.c')
| -rw-r--r-- | progs/perf/vbo.c | 246 | 
1 files changed, 246 insertions, 0 deletions
| diff --git a/progs/perf/vbo.c b/progs/perf/vbo.c new file mode 100644 index 0000000000..b326c056ec --- /dev/null +++ b/progs/perf/vbo.c @@ -0,0 +1,246 @@ +/* + * 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); +} | 
