1 // 2 // Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 #include "BufferSubData.h" 8 9 #include <cassert> 10 #include <sstream> 11 12 #include "shader_utils.h" 13 14 namespace 15 { 16 17 GLfloat *GetFloatData(GLint componentCount) 18 { 19 static GLfloat vertices2[] = 20 { 21 1, 2, 22 0, 0, 23 2, 0, 24 }; 25 26 static GLfloat vertices3[] = 27 { 28 1, 2, 1, 29 0, 0, 1, 30 2, 0, 1, 31 }; 32 33 static GLfloat vertices4[] = 34 { 35 1, 2, 1, 3, 36 0, 0, 1, 3, 37 2, 0, 1, 3, 38 }; 39 40 switch (componentCount) 41 { 42 case 2: return vertices2; 43 case 3: return vertices3; 44 case 4: return vertices4; 45 default: return NULL; 46 } 47 } 48 49 template <class T> 50 GLsizeiptr GetNormalizedData(GLsizeiptr numElements, GLfloat *floatData, std::vector<uint8_t> *data) 51 { 52 GLsizeiptr triDataSize = sizeof(T) * numElements; 53 data->resize(triDataSize); 54 55 T *destPtr = reinterpret_cast<T*>(data->data()); 56 57 for (GLsizeiptr dataIndex = 0; dataIndex < numElements; dataIndex++) 58 { 59 GLfloat scaled = floatData[dataIndex] * 0.25f; 60 destPtr[dataIndex] = static_cast<T>(scaled * static_cast<GLfloat>(std::numeric_limits<T>::max())); 61 } 62 63 return triDataSize; 64 } 65 66 template <class T> 67 GLsizeiptr GetIntData(GLsizeiptr numElements, GLfloat *floatData, std::vector<uint8_t> *data) 68 { 69 GLsizeiptr triDataSize = sizeof(T) * numElements; 70 data->resize(triDataSize); 71 72 T *destPtr = reinterpret_cast<T*>(data->data()); 73 74 for (GLsizeiptr dataIndex = 0; dataIndex < numElements; dataIndex++) 75 { 76 destPtr[dataIndex] = static_cast<T>(floatData[dataIndex]); 77 } 78 79 return triDataSize; 80 } 81 82 GLsizeiptr GetVertexData(GLenum type, GLint componentCount, GLboolean normalized, std::vector<uint8_t> *data) 83 { 84 GLsizeiptr triDataSize = 0; 85 GLfloat *floatData = GetFloatData(componentCount); 86 87 if (type == GL_FLOAT) 88 { 89 triDataSize = sizeof(GLfloat) * componentCount * 3; 90 data->resize(triDataSize); 91 memcpy(data->data(), floatData, triDataSize); 92 } 93 else if (normalized == GL_TRUE) 94 { 95 GLsizeiptr numElements = componentCount * 3; 96 97 switch (type) 98 { 99 case GL_BYTE: triDataSize = GetNormalizedData<GLbyte>(numElements, floatData, data); break; 100 case GL_SHORT: triDataSize = GetNormalizedData<GLshort>(numElements, floatData, data); break; 101 case GL_INT: triDataSize = GetNormalizedData<GLint>(numElements, floatData, data); break; 102 case GL_UNSIGNED_BYTE: triDataSize = GetNormalizedData<GLubyte>(numElements, floatData, data); break; 103 case GL_UNSIGNED_SHORT: triDataSize = GetNormalizedData<GLushort>(numElements, floatData, data); break; 104 case GL_UNSIGNED_INT: triDataSize = GetNormalizedData<GLuint>(numElements, floatData, data); break; 105 default: assert(0); 106 } 107 } 108 else 109 { 110 GLsizeiptr numElements = componentCount * 3; 111 112 switch (type) 113 { 114 case GL_BYTE: triDataSize = GetIntData<GLbyte>(numElements, floatData, data); break; 115 case GL_SHORT: triDataSize = GetIntData<GLshort>(numElements, floatData, data); break; 116 case GL_INT: triDataSize = GetIntData<GLint>(numElements, floatData, data); break; 117 case GL_UNSIGNED_BYTE: triDataSize = GetIntData<GLubyte>(numElements, floatData, data); break; 118 case GL_UNSIGNED_SHORT: triDataSize = GetIntData<GLushort>(numElements, floatData, data); break; 119 case GL_UNSIGNED_INT: triDataSize = GetIntData<GLuint>(numElements, floatData, data); break; 120 default: assert(0); 121 } 122 } 123 124 return triDataSize; 125 } 126 127 } 128 129 std::string BufferSubDataParams::name() const 130 { 131 std::stringstream strstr; 132 133 strstr << "BufferSubData - " << BenchmarkParams::name() << " - "; 134 135 if (vertexNormalized) 136 { 137 strstr << "Norm"; 138 } 139 140 switch (vertexType) 141 { 142 case GL_FLOAT: strstr << "Float"; break; 143 case GL_INT: strstr << "Int"; break; 144 case GL_BYTE: strstr << "Byte"; break; 145 case GL_SHORT: strstr << "Short"; break; 146 case GL_UNSIGNED_INT: strstr << "UInt"; break; 147 case GL_UNSIGNED_BYTE: strstr << "UByte"; break; 148 case GL_UNSIGNED_SHORT: strstr << "UShort"; break; 149 default: strstr << "UNKNOWN FORMAT (" << vertexType << ")"; break; 150 } 151 152 strstr << vertexComponentCount; 153 154 strstr << " - " << updateSize << "b updates (per " << updatesEveryNFrames << ") - "; 155 strstr << (bufferSize >> 10) << "k buffer - "; 156 strstr << iterations << " updates"; 157 158 return strstr.str(); 159 } 160 161 BufferSubDataBenchmark::BufferSubDataBenchmark(const BufferSubDataParams ¶ms) 162 : SimpleBenchmark(params.name(), 1280, 720, 2, params.requestedRenderer), 163 mProgram(0), 164 mBuffer(0), 165 mUpdateData(NULL), 166 mNumTris(0), 167 mParams(params) 168 { 169 mDrawIterations = mParams.iterations; 170 171 assert(mParams.vertexComponentCount > 1); 172 assert(mParams.iterations > 0); 173 } 174 175 bool BufferSubDataBenchmark::initializeBenchmark() 176 { 177 const std::string vs = SHADER_SOURCE 178 ( 179 attribute vec2 vPosition; 180 uniform float uScale; 181 uniform float uOffset; 182 void main() 183 { 184 gl_Position = vec4(vPosition * vec2(uScale) - vec2(uOffset), 0, 1); 185 } 186 ); 187 188 const std::string fs = SHADER_SOURCE 189 ( 190 precision mediump float; 191 void main() 192 { 193 gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); 194 } 195 ); 196 197 mProgram = CompileProgram(vs, fs); 198 if (!mProgram) 199 { 200 return false; 201 } 202 203 // Use the program object 204 glUseProgram(mProgram); 205 206 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 207 208 209 std::vector<uint8_t> zeroData(mParams.bufferSize); 210 memset(zeroData.data(), 0, zeroData.size()); 211 212 glGenBuffers(1, &mBuffer); 213 glBindBuffer(GL_ARRAY_BUFFER, mBuffer); 214 glBufferData(GL_ARRAY_BUFFER, mParams.bufferSize, zeroData.data(), GL_DYNAMIC_DRAW); 215 216 glVertexAttribPointer(0, mParams.vertexComponentCount, mParams.vertexType, 217 mParams.vertexNormalized, 0, 0); 218 glEnableVertexAttribArray(0); 219 220 if (mParams.updateSize > 0) 221 { 222 mUpdateData = new uint8_t[mParams.updateSize]; 223 } 224 225 std::vector<uint8_t> data; 226 GLsizei triDataSize = GetVertexData(mParams.vertexType, 227 mParams.vertexComponentCount, 228 mParams.vertexNormalized, &data); 229 230 mNumTris = mParams.updateSize / triDataSize; 231 for (int i = 0, offset = 0; i < mNumTris; ++i) 232 { 233 memcpy(mUpdateData + offset, data.data(), triDataSize); 234 offset += triDataSize; 235 } 236 237 if (mParams.updateSize == 0) 238 { 239 mNumTris = 1; 240 glBufferSubData(GL_ARRAY_BUFFER, 0, data.size(), data.data()); 241 } 242 243 // Set the viewport 244 glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight()); 245 246 GLfloat scale = 0.5f; 247 GLfloat offset = 0.5f; 248 249 if (mParams.vertexNormalized == GL_TRUE) 250 { 251 scale = 2.0f; 252 offset = 0.5f; 253 } 254 255 glUniform1f(glGetUniformLocation(mProgram, "uScale"), scale); 256 glUniform1f(glGetUniformLocation(mProgram, "uOffset"), offset); 257 258 GLenum glErr = glGetError(); 259 if (glErr != GL_NO_ERROR) 260 { 261 return false; 262 } 263 264 return true; 265 } 266 267 void BufferSubDataBenchmark::destroyBenchmark() 268 { 269 glDeleteProgram(mProgram); 270 glDeleteBuffers(1, &mBuffer); 271 delete[] mUpdateData; 272 } 273 274 void BufferSubDataBenchmark::beginDrawBenchmark() 275 { 276 // Clear the color buffer 277 glClear(GL_COLOR_BUFFER_BIT); 278 } 279 280 void BufferSubDataBenchmark::drawBenchmark() 281 { 282 for (unsigned int it = 0; it < mParams.iterations; it++) 283 { 284 if (mParams.updateSize > 0 && ((mNumFrames % mParams.updatesEveryNFrames) == 0)) 285 { 286 glBufferSubData(GL_ARRAY_BUFFER, 0, mParams.updateSize, mUpdateData); 287 } 288 289 glDrawArrays(GL_TRIANGLES, 0, 3 * mNumTris); 290 } 291 } 292