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

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

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