| OLD | NEW | 
|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include <algorithm> | 5 #include <algorithm> | 
| 6 #include <vector> | 6 #include <vector> | 
| 7 | 7 | 
| 8 #include "base/containers/small_map.h" | 8 #include "base/containers/small_map.h" | 
| 9 #include "base/logging.h" | 9 #include "base/logging.h" | 
| 10 #include "base/memory/ref_counted.h" | 10 #include "base/memory/ref_counted.h" | 
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 52 const char kFragmentShader[] = | 52 const char kFragmentShader[] = | 
| 53 SHADER( | 53 SHADER( | 
| 54   uniform sampler2D a_texture; | 54   uniform sampler2D a_texture; | 
| 55   varying vec2 v_texCoord; | 55   varying vec2 v_texCoord; | 
| 56   void main() { | 56   void main() { | 
| 57     gl_FragColor = texture2D(a_texture, v_texCoord); | 57     gl_FragColor = texture2D(a_texture, v_texCoord); | 
| 58   } | 58   } | 
| 59 ); | 59 ); | 
| 60 // clang-format on | 60 // clang-format on | 
| 61 | 61 | 
| 62 void CheckNoGlError() { | 62 void CheckNoGlError(const std::string& msg) { | 
| 63   CHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | 63   CHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()) << " " << msg; | 
| 64 } | 64 } | 
| 65 | 65 | 
| 66 // Utility function to compile a shader from a string. | 66 // Utility function to compile a shader from a string. | 
| 67 GLuint LoadShader(const GLenum type, const char* const src) { | 67 GLuint LoadShader(const GLenum type, const char* const src) { | 
| 68   GLuint shader = 0; | 68   GLuint shader = 0; | 
| 69   shader = glCreateShader(type); | 69   shader = glCreateShader(type); | 
| 70   CHECK_NE(0u, shader); | 70   CHECK_NE(0u, shader); | 
| 71   glShaderSource(shader, 1, &src, NULL); | 71   glShaderSource(shader, 1, &src, NULL); | 
| 72   glCompileShader(shader); | 72   glCompileShader(shader); | 
| 73 | 73 | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
| 84   } | 84   } | 
| 85   CHECK_NE(0, compiled); | 85   CHECK_NE(0, compiled); | 
| 86   return shader; | 86   return shader; | 
| 87 } | 87 } | 
| 88 | 88 | 
| 89 int GLFormatBytePerPixel(GLenum format) { | 89 int GLFormatBytePerPixel(GLenum format) { | 
| 90   DCHECK(format == GL_RGBA || format == GL_LUMINANCE || format == GL_RED_EXT); | 90   DCHECK(format == GL_RGBA || format == GL_LUMINANCE || format == GL_RED_EXT); | 
| 91   return format == GL_RGBA ? 4 : 1; | 91   return format == GL_RGBA ? 4 : 1; | 
| 92 } | 92 } | 
| 93 | 93 | 
|  | 94 GLenum GLFormatToInternalFormat(GLenum format) { | 
|  | 95   return format == GL_RED ? GL_R8 : format; | 
|  | 96 } | 
|  | 97 | 
|  | 98 GLenum GLFormatToStorageFormat(GLenum format) { | 
|  | 99   switch (format) { | 
|  | 100     case GL_RGBA: | 
|  | 101       return GL_RGBA8; | 
|  | 102     case GL_LUMINANCE: | 
|  | 103       return GL_LUMINANCE8; | 
|  | 104     case GL_RED: | 
|  | 105       return GL_R8; | 
|  | 106     default: | 
|  | 107       NOTREACHED(); | 
|  | 108   } | 
|  | 109   return 0; | 
|  | 110 } | 
|  | 111 | 
| 94 void GenerateTextureData(const gfx::Size& size, | 112 void GenerateTextureData(const gfx::Size& size, | 
| 95                          int bytes_per_pixel, | 113                          int bytes_per_pixel, | 
| 96                          const int seed, | 114                          const int seed, | 
| 97                          std::vector<uint8>* const pixels) { | 115                          std::vector<uint8>* const pixels) { | 
| 98   // Row bytes has to be multiple of 4 (GL_PACK_ALIGNMENT defaults to 4). | 116   // Row bytes has to be multiple of 4 (GL_PACK_ALIGNMENT defaults to 4). | 
| 99   int stride = ((size.width() * bytes_per_pixel) + 3) & ~0x3; | 117   int stride = ((size.width() * bytes_per_pixel) + 3) & ~0x3; | 
| 100   pixels->resize(size.height() * stride); | 118   pixels->resize(size.height() * stride); | 
| 101   for (int y = 0; y < size.height(); ++y) { | 119   for (int y = 0; y < size.height(); ++y) { | 
| 102     for (int x = 0; x < size.width(); ++x) { | 120     for (int x = 0; x < size.width(); ++x) { | 
| 103       for (int channel = 0; channel < bytes_per_pixel; ++channel) { | 121       for (int channel = 0; channel < bytes_per_pixel; ++channel) { | 
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 221 | 239 | 
| 222     glGenBuffersARB(1, &vertex_buffer_); | 240     glGenBuffersARB(1, &vertex_buffer_); | 
| 223     CHECK_NE(0u, vertex_buffer_); | 241     CHECK_NE(0u, vertex_buffer_); | 
| 224     DCHECK_NE(0u, vertex_buffer_); | 242     DCHECK_NE(0u, vertex_buffer_); | 
| 225     glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_); | 243     glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_); | 
| 226     glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, 0); | 244     glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, 0); | 
| 227     glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, | 245     glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, | 
| 228                           reinterpret_cast<void*>(sizeof(GLfloat) * 2)); | 246                           reinterpret_cast<void*>(sizeof(GLfloat) * 2)); | 
| 229     glEnableVertexAttribArray(0); | 247     glEnableVertexAttribArray(0); | 
| 230     glEnableVertexAttribArray(1); | 248     glEnableVertexAttribArray(1); | 
| 231     CheckNoGlError(); | 249     CheckNoGlError("glEnableVertexAttribArray"); | 
|  | 250 | 
|  | 251     has_texture_storage_ = | 
|  | 252         gl_context_->GetVersionInfo()->is_es3 || | 
|  | 253         gl_context_->HasExtension("GL_EXT_texture_storage") || | 
|  | 254         gl_context_->HasExtension("GL_ARB_texture_storage"); | 
| 232   } | 255   } | 
| 233 | 256 | 
| 234   void GenerateVertexBuffer(const gfx::Size& size) { | 257   void GenerateVertexBuffer(const gfx::Size& size) { | 
| 235     DCHECK_NE(0u, vertex_buffer_); | 258     DCHECK_NE(0u, vertex_buffer_); | 
| 236     glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_); | 259     glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_); | 
| 237     // right and top are in clipspace | 260     // right and top are in clipspace | 
| 238     float right = -1.f + 2.f * size.width() / fbo_size_.width(); | 261     float right = -1.f + 2.f * size.width() / fbo_size_.width(); | 
| 239     float top = -1.f + 2.f * size.height() / fbo_size_.height(); | 262     float top = -1.f + 2.f * size.height() / fbo_size_.height(); | 
| 240     // Four vertexes, one per line. Each vertex has two components per | 263     // Four vertexes, one per line. Each vertex has two components per | 
| 241     // position and two per texcoord. | 264     // position and two per texcoord. | 
| 242     // It represents a quad formed by two triangles if interpreted | 265     // It represents a quad formed by two triangles if interpreted | 
| 243     // as a tristrip. | 266     // as a tristrip. | 
| 244 | 267 | 
| 245     // clang-format off | 268     // clang-format off | 
| 246     GLfloat data[16] = { | 269     GLfloat data[16] = { | 
| 247       -1.f, -1.f,    0.f, 0.f, | 270       -1.f, -1.f,    0.f, 0.f, | 
| 248       right, -1.f,   1.f, 0.f, | 271       right, -1.f,   1.f, 0.f, | 
| 249       -1.f, top,     0.f, 1.f, | 272       -1.f, top,     0.f, 1.f, | 
| 250       right, top,    1.f, 1.f}; | 273       right, top,    1.f, 1.f}; | 
| 251     // clang-format on | 274     // clang-format on | 
| 252     glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW); | 275     glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW); | 
| 253     CheckNoGlError(); | 276     CheckNoGlError("glBufferData"); | 
| 254   } | 277   } | 
| 255 | 278 | 
| 256   void TearDown() override { | 279   void TearDown() override { | 
| 257     ui::ScopedMakeCurrent smc(gl_context_.get(), surface_.get()); | 280     ui::ScopedMakeCurrent smc(gl_context_.get(), surface_.get()); | 
| 258     glDeleteProgram(program_object_); | 281     glDeleteProgram(program_object_); | 
| 259     glDeleteShader(vertex_shader_); | 282     glDeleteShader(vertex_shader_); | 
| 260     glDeleteShader(fragment_shader_); | 283     glDeleteShader(fragment_shader_); | 
| 261     glDeleteBuffersARB(1, &vertex_buffer_); | 284     glDeleteBuffersARB(1, &vertex_buffer_); | 
| 262 | 285 | 
| 263     glBindFramebufferEXT(GL_FRAMEBUFFER, 0); | 286     glBindFramebufferEXT(GL_FRAMEBUFFER, 0); | 
| 264     glDeleteFramebuffersEXT(1, &framebuffer_object_); | 287     glDeleteFramebuffersEXT(1, &framebuffer_object_); | 
| 265     glDeleteTextures(1, &color_texture_); | 288     glDeleteTextures(1, &color_texture_); | 
| 266     CheckNoGlError(); | 289     CheckNoGlError("glDeleteTextures"); | 
| 267 | 290 | 
| 268     gpu_timing_client_ = nullptr; | 291     gpu_timing_client_ = nullptr; | 
| 269     gl_context_ = nullptr; | 292     gl_context_ = nullptr; | 
| 270     surface_ = nullptr; | 293     surface_ = nullptr; | 
| 271   } | 294   } | 
| 272 | 295 | 
| 273  protected: | 296  protected: | 
| 274   GLuint CreateGLTexture() { | 297   GLuint CreateGLTexture(const GLenum format, | 
|  | 298                          const gfx::Size& size, | 
|  | 299                          const bool specify_storage) { | 
| 275     GLuint texture_id = 0; | 300     GLuint texture_id = 0; | 
| 276     glActiveTexture(GL_TEXTURE0); | 301     glActiveTexture(GL_TEXTURE0); | 
| 277     glGenTextures(1, &texture_id); | 302     glGenTextures(1, &texture_id); | 
| 278     glBindTexture(GL_TEXTURE_2D, texture_id); | 303     glBindTexture(GL_TEXTURE_2D, texture_id); | 
|  | 304     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 
|  | 305     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | 
|  | 306     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 
|  | 307     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 
|  | 308     if (specify_storage) { | 
|  | 309       if (has_texture_storage_) { | 
|  | 310         glTexStorage2DEXT(GL_TEXTURE_2D, 1, GLFormatToStorageFormat(format), | 
|  | 311                           size.width(), size.height()); | 
|  | 312         CheckNoGlError("glTexStorage2DEXT"); | 
|  | 313       } else { | 
|  | 314         glTexImage2D(GL_TEXTURE_2D, 0, GLFormatToInternalFormat(format), | 
|  | 315                      size.width(), size.height(), 0, format, GL_UNSIGNED_BYTE, | 
|  | 316                      nullptr); | 
|  | 317         CheckNoGlError("glTexImage2D"); | 
|  | 318       } | 
|  | 319     } | 
| 279     return texture_id; | 320     return texture_id; | 
| 280   } | 321   } | 
| 281 | 322 | 
| 282   void UploadTexture(GLuint texture_id, | 323   void UploadTexture(GLuint texture_id, | 
| 283                      const gfx::Size& size, | 324                      const gfx::Size& size, | 
| 284                      const std::vector<uint8>& pixels, | 325                      const std::vector<uint8>& pixels, | 
| 285                      GLenum format) { | 326                      GLenum format, | 
| 286     glTexImage2D(GL_TEXTURE_2D, 0, format, size.width(), size.height(), 0, | 327                      const bool subimage) { | 
| 287                  format, GL_UNSIGNED_BYTE, &pixels[0]); | 328     if (subimage) { | 
| 288     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 329       glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size.width(), size.height(), | 
| 289     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | 330                       format, GL_UNSIGNED_BYTE, &pixels[0]); | 
| 290     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 331       CheckNoGlError("glTexSubImage2D"); | 
| 291     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 332     } else { | 
| 292     CheckNoGlError(); | 333       glTexImage2D(GL_TEXTURE_2D, 0, GLFormatToInternalFormat(format), | 
|  | 334                    size.width(), size.height(), 0, format, GL_UNSIGNED_BYTE, | 
|  | 335                    &pixels[0]); | 
|  | 336       CheckNoGlError("glTexImage2D"); | 
|  | 337     } | 
| 293   } | 338   } | 
| 294 | 339 | 
| 295   // Upload and draw on the offscren surface. | 340   // Upload and draw on the offscren surface. | 
| 296   // Return a list of pair. Each pair describe a gl operation and the wall | 341   // Return a list of pair. Each pair describe a gl operation and the wall | 
| 297   // time elapsed in milliseconds. | 342   // time elapsed in milliseconds. | 
| 298   std::vector<Measurement> UploadAndDraw(const gfx::Size& size, | 343   std::vector<Measurement> UploadAndDraw(GLuint texture_id, | 
|  | 344                                          const gfx::Size& size, | 
| 299                                          const std::vector<uint8>& pixels, | 345                                          const std::vector<uint8>& pixels, | 
| 300                                          const GLenum format) { | 346                                          const GLenum format, | 
| 301     GLuint texture_id = CreateGLTexture(); | 347                                          const bool subimage) { | 
| 302     MeasurementTimers tex_timers(gpu_timing_client_.get()); | 348     MeasurementTimers tex_timers(gpu_timing_client_.get()); | 
| 303     UploadTexture(texture_id, size, pixels, format); | 349     UploadTexture(texture_id, size, pixels, format, subimage); | 
| 304     tex_timers.Record(); | 350     tex_timers.Record(); | 
| 305 | 351 | 
| 306     MeasurementTimers draw_timers(gpu_timing_client_.get()); | 352     MeasurementTimers draw_timers(gpu_timing_client_.get()); | 
| 307 | 353 | 
| 308     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | 354     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | 
| 309     draw_timers.Record(); | 355     draw_timers.Record(); | 
| 310 | 356 | 
| 311     MeasurementTimers finish_timers(gpu_timing_client_.get()); | 357     MeasurementTimers finish_timers(gpu_timing_client_.get()); | 
| 312     glFinish(); | 358     glFinish(); | 
| 313     CheckNoGlError(); | 359     CheckNoGlError("glFinish"); | 
| 314     finish_timers.Record(); | 360     finish_timers.Record(); | 
| 315 | 361 | 
| 316     glDeleteTextures(1, &texture_id); |  | 
| 317 |  | 
| 318     std::vector<uint8> pixels_rendered(size.GetArea() * 4); | 362     std::vector<uint8> pixels_rendered(size.GetArea() * 4); | 
| 319     glReadPixels(0, 0, size.width(), size.height(), GL_RGBA, GL_UNSIGNED_BYTE, | 363     glReadPixels(0, 0, size.width(), size.height(), GL_RGBA, GL_UNSIGNED_BYTE, | 
| 320                  &pixels_rendered[0]); | 364                  &pixels_rendered[0]); | 
| 321     CheckNoGlError(); | 365     CheckNoGlError("glReadPixels"); | 
| 322     EXPECT_TRUE( | 366     EXPECT_TRUE( | 
| 323         CompareBufferToRGBABuffer(format, size, pixels, pixels_rendered)) | 367         CompareBufferToRGBABuffer(format, size, pixels, pixels_rendered)) | 
| 324         << "Format is: " << gfx::GLEnums::GetStringEnum(format); | 368         << "Format is: " << gfx::GLEnums::GetStringEnum(format); | 
| 325 | 369 | 
| 326     std::vector<Measurement> measurements; | 370     std::vector<Measurement> measurements; | 
| 327     bool gpu_timer_errors = | 371     bool gpu_timer_errors = | 
| 328         gpu_timing_client_->IsAvailable() && | 372         gpu_timing_client_->IsAvailable() && | 
| 329         gpu_timing_client_->CheckAndResetTimerErrors(); | 373         gpu_timing_client_->CheckAndResetTimerErrors(); | 
| 330     if (!gpu_timer_errors) { | 374     if (!gpu_timer_errors) { | 
| 331       measurements.push_back(tex_timers.GetAsMeasurement("teximage2d")); | 375       measurements.push_back(tex_timers.GetAsMeasurement( | 
|  | 376           subimage ? "texsubimage2d" : "teximage2d")); | 
| 332       measurements.push_back(draw_timers.GetAsMeasurement("drawarrays")); | 377       measurements.push_back(draw_timers.GetAsMeasurement("drawarrays")); | 
| 333       measurements.push_back(finish_timers.GetAsMeasurement("finish")); | 378       measurements.push_back(finish_timers.GetAsMeasurement("finish")); | 
| 334     } | 379     } | 
| 335     return measurements; | 380     return measurements; | 
| 336   } | 381   } | 
| 337 | 382 | 
| 338   void RunUploadAndDrawMultipleTimes(const gfx::Size& size, | 383   void RunUploadAndDrawMultipleTimes(const gfx::Size& size, | 
| 339                                      const GLenum format) { | 384                                      const GLenum format, | 
|  | 385                                      const bool subimage) { | 
| 340     std::vector<uint8> pixels; | 386     std::vector<uint8> pixels; | 
| 341     base::SmallMap<std::map<std::string, Measurement>> | 387     base::SmallMap<std::map<std::string, Measurement>> | 
| 342         aggregates;  // indexed by name | 388         aggregates;  // indexed by name | 
| 343     int successful_runs = 0; | 389     int successful_runs = 0; | 
|  | 390     GLuint texture_id = CreateGLTexture(format, size, subimage); | 
| 344     for (int i = 0; i < kUploadPerfWarmupRuns + kUploadPerfTestRuns; ++i) { | 391     for (int i = 0; i < kUploadPerfWarmupRuns + kUploadPerfTestRuns; ++i) { | 
| 345       GenerateTextureData(size, GLFormatBytePerPixel(format), i + 1, &pixels); | 392       GenerateTextureData(size, GLFormatBytePerPixel(format), i + 1, &pixels); | 
| 346       auto run = UploadAndDraw(size, pixels, format); | 393       auto run = UploadAndDraw(texture_id, size, pixels, format, subimage); | 
| 347       if (i < kUploadPerfWarmupRuns || !run.size()) { | 394       if (i < kUploadPerfWarmupRuns || !run.size()) { | 
| 348         continue; | 395         continue; | 
| 349       } | 396       } | 
| 350       successful_runs++; | 397       successful_runs++; | 
| 351       for (const Measurement& measurement : run) { | 398       for (const Measurement& measurement : run) { | 
| 352         auto& aggregate = aggregates[measurement.name]; | 399         auto& aggregate = aggregates[measurement.name]; | 
| 353         aggregate.name = measurement.name; | 400         aggregate.name = measurement.name; | 
| 354         aggregate.Increment(measurement); | 401         aggregate.Increment(measurement); | 
| 355       } | 402       } | 
| 356     } | 403     } | 
|  | 404     glDeleteTextures(1, &texture_id); | 
|  | 405 | 
| 357     std::string graph_name = base::StringPrintf( | 406     std::string graph_name = base::StringPrintf( | 
| 358         "%d_%s", size.width(), gfx::GLEnums::GetStringEnum(format).c_str()); | 407         "%d_%s", size.width(), gfx::GLEnums::GetStringEnum(format).c_str()); | 
|  | 408     if (subimage) { | 
|  | 409       graph_name += "_sub"; | 
|  | 410     } | 
|  | 411 | 
| 359     if (successful_runs) { | 412     if (successful_runs) { | 
| 360       for (const auto& entry : aggregates) { | 413       for (const auto& entry : aggregates) { | 
| 361         const auto m = entry.second.Divide(successful_runs); | 414         const auto m = entry.second.Divide(successful_runs); | 
| 362         m.PrintResult(graph_name); | 415         m.PrintResult(graph_name); | 
| 363       } | 416       } | 
| 364     } | 417     } | 
| 365     perf_test::PrintResult("sample_runs", "", graph_name, | 418     perf_test::PrintResult("sample_runs", "", graph_name, | 
| 366                            static_cast<size_t>(successful_runs), "laps", true); | 419                            static_cast<size_t>(successful_runs), "laps", true); | 
| 367   } | 420   } | 
| 368 | 421 | 
| 369   const gfx::Size fbo_size_;  // for the fbo | 422   const gfx::Size fbo_size_;  // for the fbo | 
| 370   scoped_refptr<gfx::GLContext> gl_context_; | 423   scoped_refptr<gfx::GLContext> gl_context_; | 
| 371   scoped_refptr<gfx::GLSurface> surface_; | 424   scoped_refptr<gfx::GLSurface> surface_; | 
| 372   scoped_refptr<gfx::GPUTimingClient> gpu_timing_client_; | 425   scoped_refptr<gfx::GPUTimingClient> gpu_timing_client_; | 
| 373 | 426 | 
| 374   GLuint color_texture_ = 0; | 427   GLuint color_texture_ = 0; | 
| 375   GLuint framebuffer_object_ = 0; | 428   GLuint framebuffer_object_ = 0; | 
| 376   GLuint vertex_shader_ = 0; | 429   GLuint vertex_shader_ = 0; | 
| 377   GLuint fragment_shader_ = 0; | 430   GLuint fragment_shader_ = 0; | 
| 378   GLuint program_object_ = 0; | 431   GLuint program_object_ = 0; | 
| 379   GLint sampler_location_ = -1; | 432   GLint sampler_location_ = -1; | 
| 380   GLint translation_location_ = -1; | 433   GLint translation_location_ = -1; | 
| 381   GLuint vertex_buffer_ = 0; | 434   GLuint vertex_buffer_ = 0; | 
|  | 435 | 
|  | 436   bool has_texture_storage_ = false; | 
| 382 }; | 437 }; | 
| 383 | 438 | 
| 384 // Perf test that generates, uploads and draws a texture on a surface repeatedly | 439 // Perf test that generates, uploads and draws a texture on a surface repeatedly | 
| 385 // and prints out aggregated measurements for all the runs. | 440 // and prints out aggregated measurements for all the runs. | 
| 386 TEST_F(TextureUploadPerfTest, glTexImage2d) { | 441 TEST_F(TextureUploadPerfTest, upload) { | 
| 387   int sizes[] = {21, 128, 256, 512, 1024}; | 442   int sizes[] = {21, 128, 256, 512, 1024}; | 
| 388   std::vector<GLenum> formats; | 443   std::vector<GLenum> formats; | 
| 389   formats.push_back(GL_RGBA); | 444   formats.push_back(GL_RGBA); | 
| 390 | 445 | 
| 391   if (!gl_context_->GetVersionInfo()->is_es3) { | 446   if (!gl_context_->GetVersionInfo()->is_es3) { | 
| 392     // Used by default for ResourceProvider::yuv_resource_format_. | 447     // Used by default for ResourceProvider::yuv_resource_format_. | 
| 393     formats.push_back(GL_LUMINANCE); | 448     formats.push_back(GL_LUMINANCE); | 
| 394   } | 449   } | 
| 395 | 450 | 
| 396   ui::ScopedMakeCurrent smc(gl_context_.get(), surface_.get()); | 451   ui::ScopedMakeCurrent smc(gl_context_.get(), surface_.get()); | 
| 397   const bool has_texture_rg = gl_context_->GetVersionInfo()->is_es3 || | 452   const bool has_texture_rg = gl_context_->GetVersionInfo()->is_es3 || | 
| 398                               gl_context_->HasExtension("GL_EXT_texture_rg") || | 453                               gl_context_->HasExtension("GL_EXT_texture_rg") || | 
| 399                               gl_context_->HasExtension("GL_ARB_texture_rg"); | 454                               gl_context_->HasExtension("GL_ARB_texture_rg"); | 
| 400 | 455 | 
| 401   if (has_texture_rg) { | 456   if (has_texture_rg) { | 
| 402     // Used as ResourceProvider::yuv_resource_format_ if | 457     // Used as ResourceProvider::yuv_resource_format_ if | 
| 403     // {ARB,EXT}_texture_rg are available. | 458     // {ARB,EXT}_texture_rg are available. | 
| 404     formats.push_back(GL_RED); | 459     formats.push_back(GL_RED); | 
| 405   } | 460   } | 
|  | 461 | 
| 406   for (int side : sizes) { | 462   for (int side : sizes) { | 
| 407     ASSERT_GE(fbo_size_.width(), side); | 463     ASSERT_GE(fbo_size_.width(), side); | 
| 408     ASSERT_GE(fbo_size_.height(), side); | 464     ASSERT_GE(fbo_size_.height(), side); | 
| 409     gfx::Size size(side, side); | 465     gfx::Size size(side, side); | 
| 410     GenerateVertexBuffer(size); | 466     GenerateVertexBuffer(size); | 
| 411     for (GLenum format : formats) { | 467     for (GLenum format : formats) { | 
| 412       RunUploadAndDrawMultipleTimes(size, format); | 468       RunUploadAndDrawMultipleTimes(size, format, true);  // use glTexSubImage2D | 
|  | 469       RunUploadAndDrawMultipleTimes(size, format, false);  // use glTexImage2D | 
| 413     } | 470     } | 
| 414   } | 471   } | 
| 415 } | 472 } | 
| 416 | 473 | 
| 417 // Perf test to check if the driver is doing texture renaming. | 474 // Perf test to check if the driver is doing texture renaming. | 
| 418 // This test creates one GL texture_id and four different images. For | 475 // This test creates one GL texture_id and four different images. For | 
| 419 // every image it uploads it using texture_id and it draws multiple | 476 // every image it uploads it using texture_id and it draws multiple | 
| 420 // times. The cpu/wall time and the gpu time for all the uploads and | 477 // times. The cpu/wall time and the gpu time for all the uploads and | 
| 421 // draws, but before glFinish, is computed and is printed out at the end as | 478 // draws, but before glFinish, is computed and is printed out at the end as | 
| 422 // "upload_and_draw". If the gpu time is >> than the cpu/wall time we expect the | 479 // "upload_and_draw". If the gpu time is >> than the cpu/wall time we expect the | 
| 423 // driver to do texture renaming: this means that while the gpu is drawing using | 480 // driver to do texture renaming: this means that while the gpu is drawing using | 
| 424 // texture_id it didn't block cpu side the texture upload using the same | 481 // texture_id it didn't block cpu side the texture upload using the same | 
| 425 // texture_id. | 482 // texture_id. | 
| 426 TEST_F(TextureUploadPerfTest, renaming) { | 483 TEST_F(TextureUploadPerfTest, renaming) { | 
| 427   gfx::Size texture_size(fbo_size_.width() / 2, fbo_size_.height() / 2); | 484   gfx::Size texture_size(fbo_size_.width() / 2, fbo_size_.height() / 2); | 
| 428 | 485 | 
| 429   std::vector<uint8> pixels[4]; | 486   std::vector<uint8> pixels[4]; | 
| 430   for (int i = 0; i < 4; ++i) { | 487   for (int i = 0; i < 4; ++i) { | 
| 431     GenerateTextureData(texture_size, 4, i + 1, &pixels[i]); | 488     GenerateTextureData(texture_size, 4, i + 1, &pixels[i]); | 
| 432   } | 489   } | 
| 433 | 490 | 
| 434   ui::ScopedMakeCurrent smc(gl_context_.get(), surface_.get()); | 491   ui::ScopedMakeCurrent smc(gl_context_.get(), surface_.get()); | 
| 435   GenerateVertexBuffer(texture_size); | 492   GenerateVertexBuffer(texture_size); | 
| 436 | 493 | 
| 437   gfx::Vector2dF positions[] = {gfx::Vector2dF(0.f, 0.f), | 494   gfx::Vector2dF positions[] = {gfx::Vector2dF(0.f, 0.f), | 
| 438                                 gfx::Vector2dF(1.f, 0.f), | 495                                 gfx::Vector2dF(1.f, 0.f), | 
| 439                                 gfx::Vector2dF(0.f, 1.f), | 496                                 gfx::Vector2dF(0.f, 1.f), | 
| 440                                 gfx::Vector2dF(1.f, 1.f)}; | 497                                 gfx::Vector2dF(1.f, 1.f)}; | 
| 441   GLuint texture_id = CreateGLTexture(); | 498   GLuint texture_id = CreateGLTexture(GL_RGBA, texture_size, true); | 
| 442 | 499 | 
| 443   MeasurementTimers upload_and_draw_timers(gpu_timing_client_.get()); | 500   MeasurementTimers upload_and_draw_timers(gpu_timing_client_.get()); | 
| 444 | 501 | 
| 445   for (int i = 0; i < 4; ++i) { | 502   for (int i = 0; i < 4; ++i) { | 
| 446     UploadTexture(texture_id, texture_size, pixels[i % 4], GL_RGBA); | 503     UploadTexture(texture_id, texture_size, pixels[i % 4], GL_RGBA, true); | 
| 447     DCHECK_NE(-1, translation_location_); | 504     DCHECK_NE(-1, translation_location_); | 
| 448     glUniform2f(translation_location_, positions[i % 4].x(), | 505     glUniform2f(translation_location_, positions[i % 4].x(), | 
| 449                 positions[i % 4].y()); | 506                 positions[i % 4].y()); | 
| 450     // Draw the same quad multiple times to make sure that the time spent on the | 507     // Draw the same quad multiple times to make sure that the time spent on the | 
| 451     // gpu is more than the cpu time. | 508     // gpu is more than the cpu time. | 
| 452     for (int draw = 0; draw < 128; ++draw) { | 509     for (int draw = 0; draw < 128; ++draw) { | 
| 453       glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | 510       glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | 
| 454     } | 511     } | 
| 455   } | 512   } | 
| 456 | 513 | 
| 457   upload_and_draw_timers.Record(); | 514   upload_and_draw_timers.Record(); | 
| 458   MeasurementTimers finish_timers(gpu_timing_client_.get()); | 515   MeasurementTimers finish_timers(gpu_timing_client_.get()); | 
| 459   glFinish(); | 516   glFinish(); | 
| 460   CheckNoGlError(); | 517   CheckNoGlError("glFinish"); | 
| 461   finish_timers.Record(); | 518   finish_timers.Record(); | 
| 462 | 519 | 
| 463   glDeleteTextures(1, &texture_id); | 520   glDeleteTextures(1, &texture_id); | 
| 464 | 521 | 
| 465   for (int i = 0; i < 4; ++i) { | 522   for (int i = 0; i < 4; ++i) { | 
| 466     std::vector<uint8> pixels_rendered(texture_size.GetArea() * 4); | 523     std::vector<uint8> pixels_rendered(texture_size.GetArea() * 4); | 
| 467     glReadPixels(texture_size.width() * positions[i].x(), | 524     glReadPixels(texture_size.width() * positions[i].x(), | 
| 468                  texture_size.height() * positions[i].y(), texture_size.width(), | 525                  texture_size.height() * positions[i].y(), texture_size.width(), | 
| 469                  texture_size.height(), GL_RGBA, GL_UNSIGNED_BYTE, | 526                  texture_size.height(), GL_RGBA, GL_UNSIGNED_BYTE, | 
| 470                  &pixels_rendered[0]); | 527                  &pixels_rendered[0]); | 
| 471     CheckNoGlError(); | 528     CheckNoGlError("glReadPixels"); | 
| 472     ASSERT_EQ(pixels[i].size(), pixels_rendered.size()); | 529     ASSERT_EQ(pixels[i].size(), pixels_rendered.size()); | 
| 473     EXPECT_EQ(pixels[i], pixels_rendered); | 530     EXPECT_EQ(pixels[i], pixels_rendered); | 
| 474   } | 531   } | 
| 475 | 532 | 
| 476   bool gpu_timer_errors = gpu_timing_client_->IsAvailable() && | 533   bool gpu_timer_errors = gpu_timing_client_->IsAvailable() && | 
| 477                           gpu_timing_client_->CheckAndResetTimerErrors(); | 534                           gpu_timing_client_->CheckAndResetTimerErrors(); | 
| 478   if (!gpu_timer_errors) { | 535   if (!gpu_timer_errors) { | 
| 479     upload_and_draw_timers.GetAsMeasurement("upload_and_draw") | 536     upload_and_draw_timers.GetAsMeasurement("upload_and_draw") | 
| 480         .PrintResult("renaming"); | 537         .PrintResult("renaming"); | 
| 481     finish_timers.GetAsMeasurement("finish").PrintResult("renaming"); | 538     finish_timers.GetAsMeasurement("finish").PrintResult("renaming"); | 
| 482   } | 539   } | 
| 483 } | 540 } | 
| 484 | 541 | 
| 485 }  // namespace | 542 }  // namespace | 
| 486 }  // namespace gpu | 543 }  // namespace gpu | 
| OLD | NEW | 
|---|