Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(250)

Side by Side Diff: gpu/perftests/texture_upload_perftest.cc

Issue 1027623002: gpu: Measure texture uploads with glTexSubImage2D and glTexImage2D. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698