#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;
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();
}
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();
}
{
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);
+ }
}
}