blob: a3005d0befd3cd029161d4b3799013a66315a2f6 [file] [log] [blame]
Keith Whitwell2884c312009-09-17 12:09:16 +01001/*
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/**
Brian Paulda0e4e52009-09-22 12:25:32 -060023 * Measure glTex[Sub]Image2D() and glGetTexImage() rate
Keith Whitwell2884c312009-09-17 12:09:16 +010024 *
25 * Brian Paul
26 * 16 Sep 2009
27 */
28
29#include "glmain.h"
30#include "common.h"
31
32
33int WinWidth = 100, WinHeight = 100;
34
35static GLuint VBO;
36static GLuint TexObj = 0;
37static GLubyte *TexImage = NULL;
38static GLsizei TexSize;
Keith Whitwell0ec26cc2009-09-22 17:59:24 +010039static GLenum TexIntFormat, TexSrcFormat, TexSrcType;
Keith Whitwell2884c312009-09-17 12:09:16 +010040
41static const GLboolean DrawPoint = GL_TRUE;
Brian Paulaae77312009-09-23 08:06:29 -060042static const GLboolean TexSubImage4 = GL_FALSE;
Keith Whitwell2884c312009-09-17 12:09:16 +010043
Keith Whitwell0ec26cc2009-09-22 17:59:24 +010044enum {
45 MODE_CREATE_TEXIMAGE,
46 MODE_TEXIMAGE,
Brian Paulda0e4e52009-09-22 12:25:32 -060047 MODE_TEXSUBIMAGE,
48 MODE_GETTEXIMAGE,
49 MODE_COUNT
Keith Whitwell0ec26cc2009-09-22 17:59:24 +010050};
51
Brian Paulda0e4e52009-09-22 12:25:32 -060052static const char *mode_name[MODE_COUNT] =
Keith Whitwell0ec26cc2009-09-22 17:59:24 +010053{
54 "Create_TexImage",
55 "TexImage",
Brian Paulda0e4e52009-09-22 12:25:32 -060056 "TexSubImage",
57 "GetTexImage"
Keith Whitwell0ec26cc2009-09-22 17:59:24 +010058};
59
60
61
Keith Whitwell2884c312009-09-17 12:09:16 +010062struct vertex
63{
64 GLfloat x, y, s, t;
65};
66
67static const struct vertex vertices[1] = {
68 { 0.0, 0.0, 0.5, 0.5 },
69};
70
Keith Whitwell2884c312009-09-17 12:09:16 +010071#define VOFFSET(F) ((void *) offsetof(struct vertex, F))
Brian Paul83fbee62009-09-21 11:09:00 -060072
Keith Whitwell2884c312009-09-17 12:09:16 +010073
74/** Called from test harness/main */
75void
76PerfInit(void)
77{
78 /* setup VBO w/ vertex data */
79 glGenBuffersARB(1, &VBO);
80 glBindBufferARB(GL_ARRAY_BUFFER_ARB, VBO);
81 glBufferDataARB(GL_ARRAY_BUFFER_ARB,
82 sizeof(vertices), vertices, GL_STATIC_DRAW_ARB);
83 glVertexPointer(2, GL_FLOAT, sizeof(struct vertex), VOFFSET(x));
84 glTexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), VOFFSET(s));
85 glEnableClientState(GL_VERTEX_ARRAY);
86 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
87
88 /* texture */
89 glGenTextures(1, &TexObj);
90 glBindTexture(GL_TEXTURE_2D, TexObj);
91 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
92 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
93 glEnable(GL_TEXTURE_2D);
94}
95
96
Keith Whitwell0ec26cc2009-09-22 17:59:24 +010097
98
99static void
100CreateUploadTexImage2D(unsigned count)
101{
102 unsigned i;
103 for (i = 0; i < count; i++) {
104 if (TexObj)
105 glDeleteTextures(1, &TexObj);
106
107 glGenTextures(1, &TexObj);
108 glBindTexture(GL_TEXTURE_2D, TexObj);
109 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
110 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
111
112 glTexImage2D(GL_TEXTURE_2D, 0, TexIntFormat,
113 TexSize, TexSize, 0,
114 TexSrcFormat, TexSrcType, TexImage);
115
116 if (DrawPoint)
117 glDrawArrays(GL_POINTS, 0, 1);
118 }
119 glFinish();
120}
121
122
Keith Whitwell2884c312009-09-17 12:09:16 +0100123static void
124UploadTexImage2D(unsigned count)
125{
126 unsigned i;
127 for (i = 0; i < count; i++) {
128 /* XXX is this equivalent to a glTexSubImage call since we're
129 * always specifying the same image size? That case isn't optimized
130 * in Mesa but may be optimized in other drivers. Note sure how
131 * much difference that might make.
132 */
Keith Whitwell0ec26cc2009-09-22 17:59:24 +0100133 glTexImage2D(GL_TEXTURE_2D, 0, TexIntFormat,
Keith Whitwell2884c312009-09-17 12:09:16 +0100134 TexSize, TexSize, 0,
135 TexSrcFormat, TexSrcType, TexImage);
136 if (DrawPoint)
137 glDrawArrays(GL_POINTS, 0, 1);
138 }
139 glFinish();
140}
141
142
143static void
144UploadTexSubImage2D(unsigned count)
145{
146 unsigned i;
147 for (i = 0; i < count; i++) {
Brian Paulaae77312009-09-23 08:06:29 -0600148 if (TexSubImage4) {
Keith Whitwell2884c312009-09-17 12:09:16 +0100149 GLsizei halfSize = (TexSize == 1) ? 1 : TexSize / 2;
150 GLsizei halfPos = TexSize - halfSize;
151 /* do glTexSubImage2D in four pieces */
152 /* lower-left */
153 glPixelStorei(GL_UNPACK_ROW_LENGTH, TexSize);
154 glTexSubImage2D(GL_TEXTURE_2D, 0,
155 0, 0, halfSize, halfSize,
156 TexSrcFormat, TexSrcType, TexImage);
157 /* lower-right */
158 glPixelStorei(GL_UNPACK_SKIP_PIXELS, halfPos);
159 glTexSubImage2D(GL_TEXTURE_2D, 0,
160 halfPos, 0, halfSize, halfSize,
161 TexSrcFormat, TexSrcType, TexImage);
162 /* upper-left */
163 glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
164 glPixelStorei(GL_UNPACK_SKIP_ROWS, halfPos);
165 glTexSubImage2D(GL_TEXTURE_2D, 0,
166 0, halfPos, halfSize, halfSize,
167 TexSrcFormat, TexSrcType, TexImage);
168 /* upper-right */
169 glPixelStorei(GL_UNPACK_SKIP_PIXELS, halfPos);
170 glPixelStorei(GL_UNPACK_SKIP_ROWS, halfPos);
171 glTexSubImage2D(GL_TEXTURE_2D, 0,
172 halfPos, halfPos, halfSize, halfSize,
173 TexSrcFormat, TexSrcType, TexImage);
174 /* reset the unpacking state */
175 glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
Keith Whitwell2884c312009-09-17 12:09:16 +0100176 glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
Keith Whitwell89f27992009-09-22 11:58:09 +0100177 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
Keith Whitwell2884c312009-09-17 12:09:16 +0100178 }
179 else {
180 /* replace whole texture image at once */
181 glTexSubImage2D(GL_TEXTURE_2D, 0,
182 0, 0, TexSize, TexSize,
183 TexSrcFormat, TexSrcType, TexImage);
184 }
185 if (DrawPoint)
186 glDrawArrays(GL_POINTS, 0, 1);
187 }
188 glFinish();
189}
190
191
Brian Paulda0e4e52009-09-22 12:25:32 -0600192static void
193GetTexImage2D(unsigned count)
194{
195 unsigned i;
196 GLubyte *buf = (GLubyte *) malloc(TexSize * TexSize * 4);
197 for (i = 0; i < count; i++) {
198 glGetTexImage(GL_TEXTURE_2D, 0,
199 TexSrcFormat, TexSrcType, buf);
200 }
201 glFinish();
202 free(buf);
203}
204
205
Keith Whitwell2884c312009-09-17 12:09:16 +0100206/* XXX any other formats to measure? */
207static const struct {
208 GLenum format, type;
Keith Whitwell0ec26cc2009-09-22 17:59:24 +0100209 GLenum internal_format;
Keith Whitwell2884c312009-09-17 12:09:16 +0100210 const char *name;
Keith Whitwell0ec26cc2009-09-22 17:59:24 +0100211 GLuint texel_size;
212 GLboolean full_test;
Keith Whitwell2884c312009-09-17 12:09:16 +0100213} SrcFormats[] = {
Brian Paulda0e4e52009-09-22 12:25:32 -0600214 { GL_RGBA, GL_UNSIGNED_BYTE, GL_RGBA, "RGBA/ubyte", 4, GL_TRUE },
215 { GL_RGB, GL_UNSIGNED_BYTE, GL_RGB, "RGB/ubyte", 3, GL_FALSE },
216 { GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_RGB, "RGB/565", 2, GL_FALSE },
217 { GL_BGRA, GL_UNSIGNED_BYTE, GL_RGBA, "BGRA/ubyte", 4, GL_FALSE },
218 { GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_LUMINANCE, "L/ubyte", 1, GL_FALSE },
Keith Whitwell0ec26cc2009-09-22 17:59:24 +0100219 { 0, 0, 0, NULL, 0, 0 }
Keith Whitwell2884c312009-09-17 12:09:16 +0100220};
221
Brian Paulda0e4e52009-09-22 12:25:32 -0600222
223/** Called from test harness/main */
Keith Whitwella7b26592009-09-21 16:55:12 +0100224void
225PerfNextRound(void)
226{
227}
Keith Whitwell2884c312009-09-17 12:09:16 +0100228
229
230/** Called from test harness/main */
231void
232PerfDraw(void)
233{
234 GLint maxSize;
235 double rate;
Keith Whitwell0ec26cc2009-09-22 17:59:24 +0100236 GLint fmt, mode;
Keith Whitwell2884c312009-09-17 12:09:16 +0100237
238 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxSize);
239
240 /* loop over source data formats */
241 for (fmt = 0; SrcFormats[fmt].format; fmt++) {
Keith Whitwell0ec26cc2009-09-22 17:59:24 +0100242 TexIntFormat = SrcFormats[fmt].internal_format;
Keith Whitwell2884c312009-09-17 12:09:16 +0100243 TexSrcFormat = SrcFormats[fmt].format;
244 TexSrcType = SrcFormats[fmt].type;
245
246 /* loop over glTexImage, glTexSubImage */
Brian Paulda0e4e52009-09-22 12:25:32 -0600247 for (mode = 0; mode < MODE_COUNT; mode++) {
Keith Whitwell0ec26cc2009-09-22 17:59:24 +0100248 GLuint minsz, maxsz;
249
250 if (SrcFormats[fmt].full_test) {
251 minsz = 16;
252 maxsz = 4096;
253 }
254 else {
255 minsz = maxsz = 256;
256 if (mode == MODE_CREATE_TEXIMAGE)
257 continue;
258 }
Keith Whitwell2884c312009-09-17 12:09:16 +0100259
Keith Whitwell6a09c9d2009-09-22 12:35:56 +0100260 /* loop over a defined range of texture sizes, test only the
261 * ones which are legal for this driver.
262 */
Keith Whitwell0ec26cc2009-09-22 17:59:24 +0100263 for (TexSize = minsz; TexSize <= maxsz; TexSize *= 4) {
Keith Whitwell2884c312009-09-17 12:09:16 +0100264 double mbPerSec;
265
Keith Whitwell6a09c9d2009-09-22 12:35:56 +0100266 if (TexSize <= maxSize) {
267 GLint bytesPerImage;
Keith Whitwell2884c312009-09-17 12:09:16 +0100268
Keith Whitwell0ec26cc2009-09-22 17:59:24 +0100269 bytesPerImage = TexSize * TexSize * SrcFormats[fmt].texel_size;
Keith Whitwell6a09c9d2009-09-22 12:35:56 +0100270 TexImage = malloc(bytesPerImage);
271
Keith Whitwell0ec26cc2009-09-22 17:59:24 +0100272 switch (mode) {
273 case MODE_TEXIMAGE:
274 rate = PerfMeasureRate(UploadTexImage2D);
275 break;
276
277 case MODE_CREATE_TEXIMAGE:
278 rate = PerfMeasureRate(CreateUploadTexImage2D);
279 break;
280
281 case MODE_TEXSUBIMAGE:
Keith Whitwell6a09c9d2009-09-22 12:35:56 +0100282 /* create initial, empty texture */
Keith Whitwell0ec26cc2009-09-22 17:59:24 +0100283 glTexImage2D(GL_TEXTURE_2D, 0, TexIntFormat,
Keith Whitwell6a09c9d2009-09-22 12:35:56 +0100284 TexSize, TexSize, 0,
285 TexSrcFormat, TexSrcType, NULL);
286 rate = PerfMeasureRate(UploadTexSubImage2D);
Keith Whitwell0ec26cc2009-09-22 17:59:24 +0100287 break;
288
Brian Paulda0e4e52009-09-22 12:25:32 -0600289 case MODE_GETTEXIMAGE:
290 glTexImage2D(GL_TEXTURE_2D, 0, TexIntFormat,
291 TexSize, TexSize, 0,
292 TexSrcFormat, TexSrcType, TexImage);
293 rate = PerfMeasureRate(GetTexImage2D);
294 break;
295
Keith Whitwell0ec26cc2009-09-22 17:59:24 +0100296 default:
297 exit(1);
Keith Whitwell6a09c9d2009-09-22 12:35:56 +0100298 }
299
300 mbPerSec = rate * bytesPerImage / (1024.0 * 1024.0);
301 free(TexImage);
Keith Whitwell0ec26cc2009-09-22 17:59:24 +0100302
303
304 {
305 unsigned err;
306 err = glGetError();
307 if (err) {
308 perf_printf("non-zero glGetError() %d\n", err);
309 exit(1);
310 }
311 }
312
Keith Whitwell2884c312009-09-17 12:09:16 +0100313 }
314 else {
Keith Whitwell6a09c9d2009-09-22 12:35:56 +0100315 rate = 0;
316 mbPerSec = 0;
Keith Whitwell2884c312009-09-17 12:09:16 +0100317 }
318
Keith Whitwell0ec26cc2009-09-22 17:59:24 +0100319 perf_printf(" %s(%s %d x %d): "
Keith Whitwell2884c312009-09-17 12:09:16 +0100320 "%.1f images/sec, %.1f MB/sec\n",
Keith Whitwell0ec26cc2009-09-22 17:59:24 +0100321 mode_name[mode],
Keith Whitwell2884c312009-09-17 12:09:16 +0100322 SrcFormats[fmt].name, TexSize, TexSize, rate, mbPerSec);
Keith Whitwell2884c312009-09-17 12:09:16 +0100323 }
Keith Whitwell6a09c9d2009-09-22 12:35:56 +0100324
Keith Whitwell0ec26cc2009-09-22 17:59:24 +0100325 if (SrcFormats[fmt].full_test)
326 perf_printf("\n");
Keith Whitwell2884c312009-09-17 12:09:16 +0100327 }
328 }
329
330 exit(0);
331}