progs/egl: Move demos a level deeper.
[mesa.git] / progs / perf / vbo.c
1 /*
2 * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * VMWARE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 */
21
22 /**
23 * Measure VBO upload speed.
24 * That is, measure glBufferDataARB() and glBufferSubDataARB().
25 *
26 * Brian Paul
27 * 16 Sep 2009
28 */
29
30 #include <string.h>
31 #include "glmain.h"
32 #include "common.h"
33
34 /* Copy data out of a large array to avoid caching effects:
35 */
36 #define DATA_SIZE (16*1024*1024)
37
38 int WinWidth = 100, WinHeight = 100;
39
40 static GLuint VBO;
41
42 static GLsizei VBOSize = 0;
43 static GLsizei SubSize = 0;
44 static GLubyte *VBOData = NULL; /* array[DATA_SIZE] */
45
46 static const GLboolean DrawPoint = GL_TRUE;
47 static const GLboolean BufferSubDataInHalves = GL_TRUE;
48
49 static const GLfloat Vertex0[2] = { 0.0, 0.0 };
50
51
52 /** Called from test harness/main */
53 void
54 PerfInit(void)
55 {
56 /* setup VBO */
57 glGenBuffersARB(1, &VBO);
58 glBindBufferARB(GL_ARRAY_BUFFER_ARB, VBO);
59 glVertexPointer(2, GL_FLOAT, sizeof(Vertex0), (void *) 0);
60 glEnableClientState(GL_VERTEX_ARRAY);
61 }
62
63
64 static void
65 UploadVBO(unsigned count)
66 {
67 unsigned i;
68 unsigned total = 0;
69 unsigned src = 0;
70
71 for (i = 0; i < count; i++) {
72 glBufferDataARB(GL_ARRAY_BUFFER, VBOSize, VBOData + src, GL_STREAM_DRAW_ARB);
73 glDrawArrays(GL_POINTS, 0, 1);
74
75 /* Throw in an occasional flush to work around a driver crash:
76 */
77 total += VBOSize;
78 if (total >= 16*1024*1024) {
79 glFlush();
80 total = 0;
81 }
82
83 src += VBOSize;
84 src %= DATA_SIZE;
85 }
86 glFinish();
87 }
88
89
90 static void
91 UploadSubVBO(unsigned count)
92 {
93 unsigned i;
94 unsigned src = 0;
95
96 for (i = 0; i < count; i++) {
97 unsigned offset = (i * SubSize) % VBOSize;
98 glBufferSubDataARB(GL_ARRAY_BUFFER, offset, SubSize, VBOData + src);
99
100 if (DrawPoint) {
101 glDrawArrays(GL_POINTS, offset / sizeof(Vertex0), 1);
102 }
103
104 src += SubSize;
105 src %= DATA_SIZE;
106 }
107 glFinish();
108 }
109
110
111 /* Do multiple small SubData uploads, then call DrawArrays. This may be a
112 * fairer comparison to back-to-back BufferData calls:
113 */
114 static void
115 BatchUploadSubVBO(unsigned count)
116 {
117 unsigned i = 0, j;
118 unsigned period = VBOSize / SubSize;
119 unsigned src = 0;
120
121 while (i < count) {
122 for (j = 0; j < period && i < count; j++, i++) {
123 unsigned offset = j * SubSize;
124 glBufferSubDataARB(GL_ARRAY_BUFFER, offset, SubSize, VBOData + src);
125 }
126
127 glDrawArrays(GL_POINTS, 0, 1);
128
129 src += SubSize;
130 src %= DATA_SIZE;
131 }
132 glFinish();
133 }
134
135
136 /**
137 * Test the sequence:
138 * create/load VBO
139 * draw
140 * destroy VBO
141 */
142 static void
143 CreateDrawDestroyVBO(unsigned count)
144 {
145 unsigned i;
146 for (i = 0; i < count; i++) {
147 GLuint vbo;
148 /* create/load */
149 glGenBuffersARB(1, &vbo);
150 glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
151 glBufferDataARB(GL_ARRAY_BUFFER, VBOSize, VBOData, GL_STREAM_DRAW_ARB);
152 /* draw */
153 glVertexPointer(2, GL_FLOAT, sizeof(Vertex0), (void *) 0);
154 glDrawArrays(GL_POINTS, 0, 1);
155 /* destroy */
156 glDeleteBuffersARB(1, &vbo);
157 }
158 glFinish();
159 }
160
161
162 static const GLsizei Sizes[] = {
163 64,
164 1024,
165 16*1024,
166 256*1024,
167 1024*1024,
168 16*1024*1024,
169 0 /* end of list */
170 };
171
172 void
173 PerfNextRound(void)
174 {
175 }
176
177 /** Called from test harness/main */
178 void
179 PerfDraw(void)
180 {
181 double rate, mbPerSec;
182 int i, sz;
183
184 /* Load VBOData buffer with duplicated Vertex0.
185 */
186 VBOData = calloc(DATA_SIZE, 1);
187
188 for (i = 0; i < DATA_SIZE / sizeof(Vertex0); i++) {
189 memcpy(VBOData + i * sizeof(Vertex0),
190 Vertex0,
191 sizeof(Vertex0));
192 }
193
194 /* glBufferDataARB()
195 */
196 for (sz = 0; Sizes[sz]; sz++) {
197 SubSize = VBOSize = Sizes[sz];
198 rate = PerfMeasureRate(UploadVBO);
199 mbPerSec = rate * VBOSize / (1024.0 * 1024.0);
200 perf_printf(" glBufferDataARB(size = %d): %.1f MB/sec\n",
201 VBOSize, mbPerSec);
202 }
203
204 /* glBufferSubDataARB()
205 */
206 for (sz = 0; Sizes[sz]; sz++) {
207 SubSize = VBOSize = Sizes[sz];
208 rate = PerfMeasureRate(UploadSubVBO);
209 mbPerSec = rate * VBOSize / (1024.0 * 1024.0);
210 perf_printf(" glBufferSubDataARB(size = %d): %.1f MB/sec\n",
211 VBOSize, mbPerSec);
212 }
213
214 /* Batch upload
215 */
216 VBOSize = 1024 * 1024;
217 glBufferDataARB(GL_ARRAY_BUFFER, VBOSize, VBOData, GL_STREAM_DRAW_ARB);
218
219 for (sz = 0; Sizes[sz] < VBOSize; sz++) {
220 SubSize = Sizes[sz];
221 rate = PerfMeasureRate(UploadSubVBO);
222 mbPerSec = rate * SubSize / (1024.0 * 1024.0);
223 perf_printf(" glBufferSubDataARB(size = %d, VBOSize = %d): %.1f MB/sec\n",
224 SubSize, VBOSize, mbPerSec);
225 }
226
227 for (sz = 0; Sizes[sz] < VBOSize; sz++) {
228 SubSize = Sizes[sz];
229 rate = PerfMeasureRate(BatchUploadSubVBO);
230 mbPerSec = rate * SubSize / (1024.0 * 1024.0);
231 perf_printf(" glBufferSubDataARB(size = %d, VBOSize = %d), batched: %.1f MB/sec\n",
232 SubSize, VBOSize, mbPerSec);
233 }
234
235 /* Create/Draw/Destroy
236 */
237 for (sz = 0; Sizes[sz]; sz++) {
238 SubSize = VBOSize = Sizes[sz];
239 rate = PerfMeasureRate(CreateDrawDestroyVBO);
240 mbPerSec = rate * VBOSize / (1024.0 * 1024.0);
241 perf_printf(" VBO Create/Draw/Destroy(size = %d): %.1f MB/sec, %.1f draws/sec\n",
242 VBOSize, mbPerSec, rate);
243 }
244
245 exit(0);
246 }