From 7ce0421fb712fd4e595f6c2ecede91c16fb3e133 Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Mon, 21 Sep 2009 15:56:17 +0100 Subject: [PATCH] progs/perf: a few more vbo upload modes Some tests, eg small SubData are probably overwhelmed by the cost of performing the draw after each upload. Add a varient which does a lot of subdata uploads and then a single draw. Also try to avoid cache-artifacts in the upload timings. --- progs/perf/vbo.c | 121 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 97 insertions(+), 24 deletions(-) diff --git a/progs/perf/vbo.c b/progs/perf/vbo.c index d2630796ae2..4b6e3f18746 100644 --- a/progs/perf/vbo.c +++ b/progs/perf/vbo.c @@ -31,12 +31,16 @@ #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; static const GLboolean DrawPoint = GL_TRUE; @@ -61,11 +65,23 @@ 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, GL_STREAM_DRAW_ARB); + 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; + } - if (DrawPoint) - glDrawArrays(GL_POINTS, 0, 1); + src += VBOSize; + src %= DATA_SIZE; } glFinish(); } @@ -75,18 +91,42 @@ static void UploadSubVBO(unsigned count) { unsigned i; + unsigned src = 0; + 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); + unsigned offset = (i * SubSize) % VBOSize; + glBufferSubDataARB(GL_ARRAY_BUFFER, offset, SubSize, VBOData + src); + + if (DrawPoint) { + glDrawArrays(GL_POINTS, offset / sizeof(Vertex0), 1); } - else { - glBufferSubDataARB(GL_ARRAY_BUFFER, 0, VBOSize, VBOData); + + src += SubSize; + src %= DATA_SIZE; + } + glFinish(); +} + +/* Do multiple small SubData uploads, the a 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); } - if (DrawPoint) - glDrawArrays(GL_POINTS, 0, 1); + glDrawArrays(GL_POINTS, 0, 1); + + src += SubSize; + src %= DATA_SIZE; } glFinish(); } @@ -109,28 +149,61 @@ PerfDraw(void) { double rate, mbPerSec; int sub, sz; + int i; + + VBOData = calloc(DATA_SIZE, 1); + + for (i = 0; i < DATA_SIZE / sizeof(Vertex0); i++) { + memcpy(VBOData + i * sizeof(Vertex0), + Vertex0, + sizeof(Vertex0)); + } + /* loop over whole/sub buffer upload */ - for (sub = 0; sub < 2; sub++) { + for (sub = 0; sub < 3; sub++) { - /* loop over VBO sizes */ - for (sz = 0; Sizes[sz]; sz++) { - VBOSize = Sizes[sz]; + if (sub == 2) { + VBOSize = 1024 * 1024; - VBOData = malloc(VBOSize); - memcpy(VBOData, Vertex0, sizeof(Vertex0)); + glBufferDataARB(GL_ARRAY_BUFFER, VBOSize, VBOData, GL_STREAM_DRAW_ARB); - if (sub) + for (sz = 0; Sizes[sz] < VBOSize; sz++) { + SubSize = Sizes[sz]; rate = PerfMeasureRate(UploadSubVBO); - else - rate = PerfMeasureRate(UploadVBO); - mbPerSec = rate * VBOSize / (1024.0 * 1024.0); + 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); + } + } + else { + + /* loop over VBO sizes */ + for (sz = 0; Sizes[sz]; sz++) { + SubSize = VBOSize = Sizes[sz]; + + if (sub == 1) + rate = PerfMeasureRate(UploadSubVBO); + else + rate = PerfMeasureRate(UploadVBO); - perf_printf(" glBuffer%sDataARB(size = %d): %.1f MB/sec\n", - (sub ? "Sub" : ""), VBOSize, mbPerSec); + mbPerSec = rate * VBOSize / (1024.0 * 1024.0); - free(VBOData); + perf_printf(" glBuffer%sDataARB(size = %d): %.1f MB/sec\n", + (sub ? "Sub" : ""), VBOSize, mbPerSec); + } } } -- 2.30.2