summaryrefslogtreecommitdiff
path: root/progs/perf/vbo.c
diff options
context:
space:
mode:
Diffstat (limited to 'progs/perf/vbo.c')
-rw-r--r--progs/perf/vbo.c246
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);
+}