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 fill rates. 24 * 25 * Brian Paul 26 * 21 Sep 2009 27 */ 28 29#include "glmain.h" 30#include "common.h" 31 32 33int WinWidth = 1000, WinHeight = 1000; 34 35static GLuint VBO, TexObj; 36 37 38struct vertex 39{ 40 GLfloat x, y, s, t, r, g, b, a; 41}; 42 43#define VOFFSET(F) ((void *) offsetof(struct vertex, F)) 44 45static const struct vertex vertices[4] = { 46 /* x y s t r g b a */ 47 { -1.0, -1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.5 }, 48 { 1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.5 }, 49 { 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.5 }, 50 { -1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.5 } 51}; 52 53 54static const char *VertexShader = 55 "void main() \n" 56 "{ \n" 57 " gl_Position = ftransform(); \n" 58 " gl_TexCoord[0] = gl_MultiTexCoord0; \n" 59 " gl_FrontColor = gl_Color; \n" 60 "} \n"; 61 62/* simple fragment shader */ 63static const char *FragmentShader1 = 64 "uniform sampler2D Tex; \n" 65 "void main() \n" 66 "{ \n" 67 " vec4 t = texture2D(Tex, gl_TexCoord[0].xy); \n" 68 " gl_FragColor = vec4(1.0) - t * gl_Color; \n" 69 "} \n"; 70 71/** 72 * A more complex fragment shader (but equivalent to first shader). 73 * A good optimizer should catch some of these no-op operations, but 74 * probably not all of them. 75 */ 76static const char *FragmentShader2 = 77 "uniform sampler2D Tex; \n" 78 "void main() \n" 79 "{ \n" 80 " // as above \n" 81 " vec4 t = texture2D(Tex, gl_TexCoord[0].xy); \n" 82 " t = vec4(1.0) - t * gl_Color; \n" 83 84 " vec4 u; \n" 85 86 " // no-op negate/swizzle \n" 87 " u = -t.wzyx; \n" 88 " t = -u.wzyx; \n" 89 90 " // no-op inverts \n" 91 " t = vec4(1.0) - t; \n" 92 " t = vec4(1.0) - t; \n" 93 94 " // no-op min/max \n" 95 " t = min(t, t); \n" 96 " t = max(t, t); \n" 97 98 " // no-op moves \n" 99 " u = t; \n" 100 " t = u; \n" 101 " u = t; \n" 102 " t = u; \n" 103 104 " // no-op add/mul \n" 105 " t = (t + t + t + t) * 0.25; \n" 106 107 " // no-op mul/sub \n" 108 " t = 3.0 * t - 2.0 * t; \n" 109 110 " // no-op negate/min/max \n" 111 " t = -min(-t, -t); \n" 112 " t = -max(-t, -t); \n" 113 114 " gl_FragColor = t; \n" 115 "} \n"; 116 117static GLuint ShaderProg1, ShaderProg2; 118 119 120 121/** Called from test harness/main */ 122void 123PerfInit(void) 124{ 125 GLint u; 126 127 /* setup VBO w/ vertex data */ 128 glGenBuffersARB(1, &VBO); 129 glBindBufferARB(GL_ARRAY_BUFFER_ARB, VBO); 130 glBufferDataARB(GL_ARRAY_BUFFER_ARB, 131 sizeof(vertices), vertices, GL_STATIC_DRAW_ARB); 132 glVertexPointer(2, GL_FLOAT, sizeof(struct vertex), VOFFSET(x)); 133 glTexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), VOFFSET(s)); 134 glColorPointer(4, GL_FLOAT, sizeof(struct vertex), VOFFSET(r)); 135 glEnableClientState(GL_VERTEX_ARRAY); 136 glEnableClientState(GL_COLOR_ARRAY); 137 138 /* setup texture */ 139 TexObj = PerfCheckerTexture(128, 128); 140 141 /* setup shaders */ 142 ShaderProg1 = PerfShaderProgram(VertexShader, FragmentShader1); 143 glUseProgram(ShaderProg1); 144 u = glGetUniformLocation(ShaderProg1, "Tex"); 145 glUniform1i(u, 0); /* texture unit 0 */ 146 147 ShaderProg2 = PerfShaderProgram(VertexShader, FragmentShader2); 148 glUseProgram(ShaderProg2); 149 u = glGetUniformLocation(ShaderProg2, "Tex"); 150 glUniform1i(u, 0); /* texture unit 0 */ 151 152 glUseProgram(0); 153} 154 155 156static void 157Ortho(void) 158{ 159 glMatrixMode(GL_PROJECTION); 160 glLoadIdentity(); 161 glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); 162 glMatrixMode(GL_MODELVIEW); 163 glLoadIdentity(); 164} 165 166 167 168static void 169DrawQuad(unsigned count) 170{ 171 unsigned i; 172 glClear(GL_COLOR_BUFFER_BIT); 173 174 for (i = 0; i < count; i++) { 175 glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 176 177 /* Avoid sending command buffers with huge numbers of fullscreen 178 * quads. Graphics schedulers don't always cope well with 179 * this... 180 */ 181 if (i % 128 == 0) { 182 PerfSwapBuffers(); 183 glClear(GL_COLOR_BUFFER_BIT); 184 } 185 } 186 187 glFinish(); 188 189 if (1) 190 PerfSwapBuffers(); 191} 192 193void 194PerfNextRound(void) 195{ 196} 197 198/** Called from test harness/main */ 199void 200PerfDraw(void) 201{ 202 double rate; 203 double pixelsPerDraw = WinWidth * WinHeight; 204 205 Ortho(); 206 207 /* simple fill */ 208 rate = PerfMeasureRate(DrawQuad) * pixelsPerDraw; 209 perf_printf(" Simple fill: %s pixels/second\n", 210 PerfHumanFloat(rate)); 211 212 /* blended fill */ 213 glEnable(GL_BLEND); 214 rate = PerfMeasureRate(DrawQuad) * pixelsPerDraw; 215 glDisable(GL_BLEND); 216 perf_printf(" Blended fill: %s pixels/second\n", 217 PerfHumanFloat(rate)); 218 219 /* textured fill */ 220 glEnable(GL_TEXTURE_2D); 221 glEnableClientState(GL_TEXTURE_COORD_ARRAY); 222 rate = PerfMeasureRate(DrawQuad) * pixelsPerDraw; 223 glDisable(GL_TEXTURE_2D); 224 glDisableClientState(GL_TEXTURE_COORD_ARRAY); 225 perf_printf(" Textured fill: %s pixels/second\n", 226 PerfHumanFloat(rate)); 227 228 /* shader1 fill */ 229 glUseProgram(ShaderProg1); 230 glEnableClientState(GL_TEXTURE_COORD_ARRAY); 231 rate = PerfMeasureRate(DrawQuad) * pixelsPerDraw; 232 glUseProgram(0); 233 glDisableClientState(GL_TEXTURE_COORD_ARRAY); 234 perf_printf(" Shader1 fill: %s pixels/second\n", 235 PerfHumanFloat(rate)); 236 237 /* shader2 fill */ 238 glUseProgram(ShaderProg2); 239 glEnableClientState(GL_TEXTURE_COORD_ARRAY); 240 rate = PerfMeasureRate(DrawQuad) * pixelsPerDraw; 241 glUseProgram(0); 242 glDisableClientState(GL_TEXTURE_COORD_ARRAY); 243 perf_printf(" Shader2 fill: %s pixels/second\n", 244 PerfHumanFloat(rate)); 245 246 exit(0); 247} 248 249