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

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

Issue 1028333002: Chromium -> Mojo roll. (Closed) Base URL: https://github.com/domokit/mojo.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 | « gpu/gpu_unittests.isolate ('k') | skia/BUILD.gn » ('j') | 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;
41 void main() { 42 void main() {
42 gl_Position = vec4( 43 gl_Position = vec4(
43 translation.x + a_position.x, translation.y + a_position.y, 0.0, 1.0); 44 translation.x + a_position.x, translation.y + a_position.y, 0.0, 1.0);
44 v_texCoord = a_texCoord; 45 v_texCoord = a_texCoord;
45 } 46 }
46 ); 47 );
48 const char kShaderDefaultFloatPrecision[] =
49 SHADER(
50 precision mediump float;
51 );
47 const char kFragmentShader[] = 52 const char kFragmentShader[] =
48 SHADER( 53 SHADER(
49 precision mediump float;
50 uniform sampler2D a_texture; 54 uniform sampler2D a_texture;
51 varying vec2 v_texCoord; 55 varying vec2 v_texCoord;
52 void main() { 56 void main() {
53 gl_FragColor = texture2D(a_texture, v_texCoord); 57 gl_FragColor = texture2D(a_texture, v_texCoord);
54 } 58 }
55 ); 59 );
56 // clang-format on 60 // clang-format on
57 61
58 void CheckNoGlError() { 62 void CheckNoGlError(const std::string& msg) {
59 CHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); 63 CHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()) << " " << msg;
60 } 64 }
61 65
62 // Utility function to compile a shader from a string. 66 // Utility function to compile a shader from a string.
63 GLuint LoadShader(const GLenum type, const char* const src) { 67 GLuint LoadShader(const GLenum type, const char* const src) {
64 GLuint shader = 0; 68 GLuint shader = 0;
65 shader = glCreateShader(type); 69 shader = glCreateShader(type);
66 CHECK_NE(0u, shader); 70 CHECK_NE(0u, shader);
67 glShaderSource(shader, 1, &src, NULL); 71 glShaderSource(shader, 1, &src, NULL);
68 glCompileShader(shader); 72 glCompileShader(shader);
69 73
(...skipping 10 matching lines...) Expand all
80 } 84 }
81 CHECK_NE(0, compiled); 85 CHECK_NE(0, compiled);
82 return shader; 86 return shader;
83 } 87 }
84 88
85 int GLFormatBytePerPixel(GLenum format) { 89 int GLFormatBytePerPixel(GLenum format) {
86 DCHECK(format == GL_RGBA || format == GL_LUMINANCE || format == GL_RED_EXT); 90 DCHECK(format == GL_RGBA || format == GL_LUMINANCE || format == GL_RED_EXT);
87 return format == GL_RGBA ? 4 : 1; 91 return format == GL_RGBA ? 4 : 1;
88 } 92 }
89 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
90 void GenerateTextureData(const gfx::Size& size, 112 void GenerateTextureData(const gfx::Size& size,
91 int bytes_per_pixel, 113 int bytes_per_pixel,
92 const int seed, 114 const int seed,
93 std::vector<uint8>* const pixels) { 115 std::vector<uint8>* const pixels) {
94 // 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).
95 int stride = ((size.width() * bytes_per_pixel) + 3) & ~0x3; 117 int stride = ((size.width() * bytes_per_pixel) + 3) & ~0x3;
96 pixels->resize(size.height() * stride); 118 pixels->resize(size.height() * stride);
97 for (int y = 0; y < size.height(); ++y) { 119 for (int y = 0; y < size.height(); ++y) {
98 for (int x = 0; x < size.width(); ++x) { 120 for (int x = 0; x < size.width(); ++x) {
99 for (int channel = 0; channel < bytes_per_pixel; ++channel) { 121 for (int channel = 0; channel < bytes_per_pixel; ++channel) {
(...skipping 16 matching lines...) Expand all
116 int rgba_stride = size.width() * GLFormatBytePerPixel(GL_RGBA); 138 int rgba_stride = size.width() * GLFormatBytePerPixel(GL_RGBA);
117 for (int y = 0; y < size.height(); ++y) { 139 for (int y = 0; y < size.height(); ++y) {
118 for (int x = 0; x < size.width(); ++x) { 140 for (int x = 0; x < size.width(); ++x) {
119 int rgba_index = y * rgba_stride + x * GLFormatBytePerPixel(GL_RGBA); 141 int rgba_index = y * rgba_stride + x * GLFormatBytePerPixel(GL_RGBA);
120 int pixels_index = y * pixels_stride + x * bytes_per_pixel; 142 int pixels_index = y * pixels_stride + x * bytes_per_pixel;
121 uint8 expected[4] = {0}; 143 uint8 expected[4] = {0};
122 switch (format) { 144 switch (format) {
123 case GL_LUMINANCE: // (L_t, L_t, L_t, 1) 145 case GL_LUMINANCE: // (L_t, L_t, L_t, 1)
124 expected[1] = pixels[pixels_index]; 146 expected[1] = pixels[pixels_index];
125 expected[2] = pixels[pixels_index]; 147 expected[2] = pixels[pixels_index];
126 case GL_RED_EXT: // (R_t, 0, 0, 1)n 148 case GL_RED: // (R_t, 0, 0, 1)
127 expected[0] = pixels[pixels_index]; 149 expected[0] = pixels[pixels_index];
128 expected[3] = 255; 150 expected[3] = 255;
129 break; 151 break;
130 case GL_RGBA: // (R_t, G_t, B_t, A_t) 152 case GL_RGBA: // (R_t, G_t, B_t, A_t)
131 memcpy(expected, &pixels[pixels_index], 4); 153 memcpy(expected, &pixels[pixels_index], 4);
132 break; 154 break;
133 default: 155 default:
134 NOTREACHED(); 156 NOTREACHED();
135 } 157 }
136 if (memcmp(&rgba[rgba_index], expected, 4)) { 158 if (memcmp(&rgba[rgba_index], expected, 4)) {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 if (gpu_timing_client_->IsAvailable()) { 202 if (gpu_timing_client_->IsAvailable()) {
181 LOG(INFO) << "Gpu timing initialized with timer type: " 203 LOG(INFO) << "Gpu timing initialized with timer type: "
182 << gpu_timing_client_->GetTimerTypeName(); 204 << gpu_timing_client_->GetTimerTypeName();
183 gpu_timing_client_->InvalidateTimerOffset(); 205 gpu_timing_client_->InvalidateTimerOffset();
184 } else { 206 } else {
185 LOG(WARNING) << "Can't initialize gpu timing"; 207 LOG(WARNING) << "Can't initialize gpu timing";
186 } 208 }
187 // Prepare a simple program and a vertex buffer that will be 209 // Prepare a simple program and a vertex buffer that will be
188 // used to draw a quad on the offscreen surface. 210 // used to draw a quad on the offscreen surface.
189 vertex_shader_ = LoadShader(GL_VERTEX_SHADER, kVertexShader); 211 vertex_shader_ = LoadShader(GL_VERTEX_SHADER, kVertexShader);
190 fragment_shader_ = LoadShader(GL_FRAGMENT_SHADER, kFragmentShader); 212
213 bool is_gles = gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
214 fragment_shader_ = LoadShader(
215 GL_FRAGMENT_SHADER,
216 base::StringPrintf("%s%s", is_gles ? kShaderDefaultFloatPrecision : "",
217 kFragmentShader).c_str());
191 program_object_ = glCreateProgram(); 218 program_object_ = glCreateProgram();
192 CHECK_NE(0u, program_object_); 219 CHECK_NE(0u, program_object_);
193 220
194 glAttachShader(program_object_, vertex_shader_); 221 glAttachShader(program_object_, vertex_shader_);
195 glAttachShader(program_object_, fragment_shader_); 222 glAttachShader(program_object_, fragment_shader_);
196 glBindAttribLocation(program_object_, 0, "a_position"); 223 glBindAttribLocation(program_object_, 0, "a_position");
197 glBindAttribLocation(program_object_, 1, "a_texCoord"); 224 glBindAttribLocation(program_object_, 1, "a_texCoord");
198 glLinkProgram(program_object_); 225 glLinkProgram(program_object_);
199 226
200 GLint linked = -1; 227 GLint linked = -1;
(...skipping 11 matching lines...) Expand all
212 239
213 glGenBuffersARB(1, &vertex_buffer_); 240 glGenBuffersARB(1, &vertex_buffer_);
214 CHECK_NE(0u, vertex_buffer_); 241 CHECK_NE(0u, vertex_buffer_);
215 DCHECK_NE(0u, vertex_buffer_); 242 DCHECK_NE(0u, vertex_buffer_);
216 glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_); 243 glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_);
217 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, 0); 244 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, 0);
218 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, 245 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4,
219 reinterpret_cast<void*>(sizeof(GLfloat) * 2)); 246 reinterpret_cast<void*>(sizeof(GLfloat) * 2));
220 glEnableVertexAttribArray(0); 247 glEnableVertexAttribArray(0);
221 glEnableVertexAttribArray(1); 248 glEnableVertexAttribArray(1);
222 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");
223 } 255 }
224 256
225 void GenerateVertexBuffer(const gfx::Size& size) { 257 void GenerateVertexBuffer(const gfx::Size& size) {
226 DCHECK_NE(0u, vertex_buffer_); 258 DCHECK_NE(0u, vertex_buffer_);
227 glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_); 259 glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_);
228 // right and top are in clipspace 260 // right and top are in clipspace
229 float right = -1.f + 2.f * size.width() / fbo_size_.width(); 261 float right = -1.f + 2.f * size.width() / fbo_size_.width();
230 float top = -1.f + 2.f * size.height() / fbo_size_.height(); 262 float top = -1.f + 2.f * size.height() / fbo_size_.height();
231 // Four vertexes, one per line. Each vertex has two components per 263 // Four vertexes, one per line. Each vertex has two components per
232 // position and two per texcoord. 264 // position and two per texcoord.
233 // It represents a quad formed by two triangles if interpreted 265 // It represents a quad formed by two triangles if interpreted
234 // as a tristrip. 266 // as a tristrip.
235 267
236 // clang-format off 268 // clang-format off
237 GLfloat data[16] = { 269 GLfloat data[16] = {
238 -1.f, -1.f, 0.f, 0.f, 270 -1.f, -1.f, 0.f, 0.f,
239 right, -1.f, 1.f, 0.f, 271 right, -1.f, 1.f, 0.f,
240 -1.f, top, 0.f, 1.f, 272 -1.f, top, 0.f, 1.f,
241 right, top, 1.f, 1.f}; 273 right, top, 1.f, 1.f};
242 // clang-format on 274 // clang-format on
243 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW); 275 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
244 CheckNoGlError(); 276 CheckNoGlError("glBufferData");
245 } 277 }
246 278
247 void TearDown() override { 279 void TearDown() override {
248 ui::ScopedMakeCurrent smc(gl_context_.get(), surface_.get()); 280 ui::ScopedMakeCurrent smc(gl_context_.get(), surface_.get());
249 glDeleteProgram(program_object_); 281 glDeleteProgram(program_object_);
250 glDeleteShader(vertex_shader_); 282 glDeleteShader(vertex_shader_);
251 glDeleteShader(fragment_shader_); 283 glDeleteShader(fragment_shader_);
252 glDeleteBuffersARB(1, &vertex_buffer_); 284 glDeleteBuffersARB(1, &vertex_buffer_);
253 285
254 glBindFramebufferEXT(GL_FRAMEBUFFER, 0); 286 glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
255 glDeleteFramebuffersEXT(1, &framebuffer_object_); 287 glDeleteFramebuffersEXT(1, &framebuffer_object_);
256 glDeleteTextures(1, &color_texture_); 288 glDeleteTextures(1, &color_texture_);
257 CheckNoGlError(); 289 CheckNoGlError("glDeleteTextures");
258 290
259 gpu_timing_client_ = nullptr; 291 gpu_timing_client_ = nullptr;
260 gl_context_ = nullptr; 292 gl_context_ = nullptr;
261 surface_ = nullptr; 293 surface_ = nullptr;
262 } 294 }
263 295
264 protected: 296 protected:
265 GLuint CreateGLTexture() { 297 GLuint CreateGLTexture(const GLenum format,
298 const gfx::Size& size,
299 const bool specify_storage) {
266 GLuint texture_id = 0; 300 GLuint texture_id = 0;
267 glActiveTexture(GL_TEXTURE0); 301 glActiveTexture(GL_TEXTURE0);
268 glGenTextures(1, &texture_id); 302 glGenTextures(1, &texture_id);
269 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 }
270 return texture_id; 320 return texture_id;
271 } 321 }
272 322
273 void UploadTexture(GLuint texture_id, 323 void UploadTexture(GLuint texture_id,
274 const gfx::Size& size, 324 const gfx::Size& size,
275 const std::vector<uint8>& pixels, 325 const std::vector<uint8>& pixels,
276 GLenum format) { 326 GLenum format,
277 glTexImage2D(GL_TEXTURE_2D, 0, format, size.width(), size.height(), 0, 327 const bool subimage) {
278 format, GL_UNSIGNED_BYTE, &pixels[0]); 328 if (subimage) {
279 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 329 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size.width(), size.height(),
280 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 330 format, GL_UNSIGNED_BYTE, &pixels[0]);
281 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 331 CheckNoGlError("glTexSubImage2D");
282 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 332 } else {
283 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 }
284 } 338 }
285 339
286 // Upload and draw on the offscren surface. 340 // Upload and draw on the offscren surface.
287 // 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
288 // time elapsed in milliseconds. 342 // time elapsed in milliseconds.
289 std::vector<Measurement> UploadAndDraw(const gfx::Size& size, 343 std::vector<Measurement> UploadAndDraw(GLuint texture_id,
344 const gfx::Size& size,
290 const std::vector<uint8>& pixels, 345 const std::vector<uint8>& pixels,
291 const GLenum format) { 346 const GLenum format,
292 GLuint texture_id = CreateGLTexture(); 347 const bool subimage) {
293 MeasurementTimers tex_timers(gpu_timing_client_.get()); 348 MeasurementTimers tex_timers(gpu_timing_client_.get());
294 UploadTexture(texture_id, size, pixels, format); 349 UploadTexture(texture_id, size, pixels, format, subimage);
295 tex_timers.Record(); 350 tex_timers.Record();
296 351
297 MeasurementTimers draw_timers(gpu_timing_client_.get()); 352 MeasurementTimers draw_timers(gpu_timing_client_.get());
298 353
299 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 354 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
300 draw_timers.Record(); 355 draw_timers.Record();
301 356
302 MeasurementTimers finish_timers(gpu_timing_client_.get()); 357 MeasurementTimers finish_timers(gpu_timing_client_.get());
303 glFinish(); 358 glFinish();
304 CheckNoGlError(); 359 CheckNoGlError("glFinish");
305 finish_timers.Record(); 360 finish_timers.Record();
306 361
307 glDeleteTextures(1, &texture_id);
308
309 std::vector<uint8> pixels_rendered(size.GetArea() * 4); 362 std::vector<uint8> pixels_rendered(size.GetArea() * 4);
310 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,
311 &pixels_rendered[0]); 364 &pixels_rendered[0]);
312 CheckNoGlError(); 365 CheckNoGlError("glReadPixels");
313 EXPECT_TRUE( 366 EXPECT_TRUE(
314 CompareBufferToRGBABuffer(format, size, pixels, pixels_rendered)) 367 CompareBufferToRGBABuffer(format, size, pixels, pixels_rendered))
315 << "Format is: " << gfx::GLEnums::GetStringEnum(format); 368 << "Format is: " << gfx::GLEnums::GetStringEnum(format);
316 369
317 std::vector<Measurement> measurements; 370 std::vector<Measurement> measurements;
318 bool gpu_timer_errors = 371 bool gpu_timer_errors =
319 gpu_timing_client_->IsAvailable() && 372 gpu_timing_client_->IsAvailable() &&
320 gpu_timing_client_->CheckAndResetTimerErrors(); 373 gpu_timing_client_->CheckAndResetTimerErrors();
321 if (!gpu_timer_errors) { 374 if (!gpu_timer_errors) {
322 measurements.push_back(tex_timers.GetAsMeasurement("teximage2d")); 375 measurements.push_back(tex_timers.GetAsMeasurement(
376 subimage ? "texsubimage2d" : "teximage2d"));
323 measurements.push_back(draw_timers.GetAsMeasurement("drawarrays")); 377 measurements.push_back(draw_timers.GetAsMeasurement("drawarrays"));
324 measurements.push_back(finish_timers.GetAsMeasurement("finish")); 378 measurements.push_back(finish_timers.GetAsMeasurement("finish"));
325 } 379 }
326 return measurements; 380 return measurements;
327 } 381 }
328 382
329 void RunUploadAndDrawMultipleTimes(const gfx::Size& size, 383 void RunUploadAndDrawMultipleTimes(const gfx::Size& size,
330 const GLenum format) { 384 const GLenum format,
385 const bool subimage) {
331 std::vector<uint8> pixels; 386 std::vector<uint8> pixels;
332 base::SmallMap<std::map<std::string, Measurement>> 387 base::SmallMap<std::map<std::string, Measurement>>
333 aggregates; // indexed by name 388 aggregates; // indexed by name
334 int successful_runs = 0; 389 int successful_runs = 0;
390 GLuint texture_id = CreateGLTexture(format, size, subimage);
335 for (int i = 0; i < kUploadPerfWarmupRuns + kUploadPerfTestRuns; ++i) { 391 for (int i = 0; i < kUploadPerfWarmupRuns + kUploadPerfTestRuns; ++i) {
336 GenerateTextureData(size, GLFormatBytePerPixel(format), i + 1, &pixels); 392 GenerateTextureData(size, GLFormatBytePerPixel(format), i + 1, &pixels);
337 auto run = UploadAndDraw(size, pixels, format); 393 auto run = UploadAndDraw(texture_id, size, pixels, format, subimage);
338 if (i < kUploadPerfWarmupRuns || !run.size()) { 394 if (i < kUploadPerfWarmupRuns || !run.size()) {
339 continue; 395 continue;
340 } 396 }
341 successful_runs++; 397 successful_runs++;
342 for (const Measurement& measurement : run) { 398 for (const Measurement& measurement : run) {
343 auto& aggregate = aggregates[measurement.name]; 399 auto& aggregate = aggregates[measurement.name];
344 aggregate.name = measurement.name; 400 aggregate.name = measurement.name;
345 aggregate.Increment(measurement); 401 aggregate.Increment(measurement);
346 } 402 }
347 } 403 }
404 glDeleteTextures(1, &texture_id);
405
348 std::string graph_name = base::StringPrintf( 406 std::string graph_name = base::StringPrintf(
349 "%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
350 if (successful_runs) { 412 if (successful_runs) {
351 for (const auto& entry : aggregates) { 413 for (const auto& entry : aggregates) {
352 const auto m = entry.second.Divide(successful_runs); 414 const auto m = entry.second.Divide(successful_runs);
353 m.PrintResult(graph_name); 415 m.PrintResult(graph_name);
354 } 416 }
355 } 417 }
356 perf_test::PrintResult("sample_runs", "", graph_name, 418 perf_test::PrintResult("sample_runs", "", graph_name,
357 static_cast<size_t>(successful_runs), "laps", true); 419 static_cast<size_t>(successful_runs), "laps", true);
358 } 420 }
359 421
360 const gfx::Size fbo_size_; // for the fbo 422 const gfx::Size fbo_size_; // for the fbo
361 scoped_refptr<gfx::GLContext> gl_context_; 423 scoped_refptr<gfx::GLContext> gl_context_;
362 scoped_refptr<gfx::GLSurface> surface_; 424 scoped_refptr<gfx::GLSurface> surface_;
363 scoped_refptr<gfx::GPUTimingClient> gpu_timing_client_; 425 scoped_refptr<gfx::GPUTimingClient> gpu_timing_client_;
364 426
365 GLuint color_texture_ = 0; 427 GLuint color_texture_ = 0;
366 GLuint framebuffer_object_ = 0; 428 GLuint framebuffer_object_ = 0;
367 GLuint vertex_shader_ = 0; 429 GLuint vertex_shader_ = 0;
368 GLuint fragment_shader_ = 0; 430 GLuint fragment_shader_ = 0;
369 GLuint program_object_ = 0; 431 GLuint program_object_ = 0;
370 GLint sampler_location_ = -1; 432 GLint sampler_location_ = -1;
371 GLint translation_location_ = -1; 433 GLint translation_location_ = -1;
372 GLuint vertex_buffer_ = 0; 434 GLuint vertex_buffer_ = 0;
435
436 bool has_texture_storage_ = false;
373 }; 437 };
374 438
375 // 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
376 // and prints out aggregated measurements for all the runs. 440 // and prints out aggregated measurements for all the runs.
377 TEST_F(TextureUploadPerfTest, glTexImage2d) { 441 TEST_F(TextureUploadPerfTest, upload) {
378 int sizes[] = {21, 128, 256, 512, 1024}; 442 int sizes[] = {21, 128, 256, 512, 1024};
379 std::vector<GLenum> formats; 443 std::vector<GLenum> formats;
380 formats.push_back(GL_RGBA); 444 formats.push_back(GL_RGBA);
381 // Used by default for ResourceProvider::yuv_resource_format_. 445
382 formats.push_back(GL_LUMINANCE); 446 if (!gl_context_->GetVersionInfo()->is_es3) {
447 // Used by default for ResourceProvider::yuv_resource_format_.
448 formats.push_back(GL_LUMINANCE);
449 }
383 450
384 ui::ScopedMakeCurrent smc(gl_context_.get(), surface_.get()); 451 ui::ScopedMakeCurrent smc(gl_context_.get(), surface_.get());
385 bool has_texture_rg = gl_context_->HasExtension("GL_EXT_texture_rg") || 452 const bool has_texture_rg = gl_context_->GetVersionInfo()->is_es3 ||
386 gl_context_->HasExtension("GL_ARB_texture_rg"); 453 gl_context_->HasExtension("GL_EXT_texture_rg") ||
454 gl_context_->HasExtension("GL_ARB_texture_rg");
387 455
388 if (has_texture_rg) { 456 if (has_texture_rg) {
389 // Used as ResourceProvider::yuv_resource_format_ if 457 // Used as ResourceProvider::yuv_resource_format_ if
390 // {ARB,EXT}_texture_rg are available. 458 // {ARB,EXT}_texture_rg are available.
391 formats.push_back(GL_RED_EXT); 459 formats.push_back(GL_RED);
392 } 460 }
461
393 for (int side : sizes) { 462 for (int side : sizes) {
394 ASSERT_GE(fbo_size_.width(), side); 463 ASSERT_GE(fbo_size_.width(), side);
395 ASSERT_GE(fbo_size_.height(), side); 464 ASSERT_GE(fbo_size_.height(), side);
396 gfx::Size size(side, side); 465 gfx::Size size(side, side);
397 GenerateVertexBuffer(size); 466 GenerateVertexBuffer(size);
398 for (GLenum format : formats) { 467 for (GLenum format : formats) {
399 RunUploadAndDrawMultipleTimes(size, format); 468 RunUploadAndDrawMultipleTimes(size, format, true); // use glTexSubImage2D
469 RunUploadAndDrawMultipleTimes(size, format, false); // use glTexImage2D
400 } 470 }
401 } 471 }
402 } 472 }
403 473
404 // Perf test to check if the driver is doing texture renaming. 474 // Perf test to check if the driver is doing texture renaming.
405 // 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
406 // 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
407 // 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
408 // 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
409 // "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
410 // 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
411 // 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
412 // texture_id. 482 // texture_id.
413 TEST_F(TextureUploadPerfTest, renaming) { 483 TEST_F(TextureUploadPerfTest, renaming) {
414 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);
415 485
416 std::vector<uint8> pixels[4]; 486 std::vector<uint8> pixels[4];
417 for (int i = 0; i < 4; ++i) { 487 for (int i = 0; i < 4; ++i) {
418 GenerateTextureData(texture_size, 4, i + 1, &pixels[i]); 488 GenerateTextureData(texture_size, 4, i + 1, &pixels[i]);
419 } 489 }
420 490
421 ui::ScopedMakeCurrent smc(gl_context_.get(), surface_.get()); 491 ui::ScopedMakeCurrent smc(gl_context_.get(), surface_.get());
422 GenerateVertexBuffer(texture_size); 492 GenerateVertexBuffer(texture_size);
423 493
424 gfx::Vector2dF positions[] = {gfx::Vector2dF(0.f, 0.f), 494 gfx::Vector2dF positions[] = {gfx::Vector2dF(0.f, 0.f),
425 gfx::Vector2dF(1.f, 0.f), 495 gfx::Vector2dF(1.f, 0.f),
426 gfx::Vector2dF(0.f, 1.f), 496 gfx::Vector2dF(0.f, 1.f),
427 gfx::Vector2dF(1.f, 1.f)}; 497 gfx::Vector2dF(1.f, 1.f)};
428 GLuint texture_id = CreateGLTexture(); 498 GLuint texture_id = CreateGLTexture(GL_RGBA, texture_size, true);
429 499
430 MeasurementTimers upload_and_draw_timers(gpu_timing_client_.get()); 500 MeasurementTimers upload_and_draw_timers(gpu_timing_client_.get());
431 501
432 for (int i = 0; i < 4; ++i) { 502 for (int i = 0; i < 4; ++i) {
433 UploadTexture(texture_id, texture_size, pixels[i % 4], GL_RGBA); 503 UploadTexture(texture_id, texture_size, pixels[i % 4], GL_RGBA, true);
434 DCHECK_NE(-1, translation_location_); 504 DCHECK_NE(-1, translation_location_);
435 glUniform2f(translation_location_, positions[i % 4].x(), 505 glUniform2f(translation_location_, positions[i % 4].x(),
436 positions[i % 4].y()); 506 positions[i % 4].y());
437 // 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
438 // gpu is more than the cpu time. 508 // gpu is more than the cpu time.
439 for (int draw = 0; draw < 128; ++draw) { 509 for (int draw = 0; draw < 128; ++draw) {
440 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 510 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
441 } 511 }
442 } 512 }
443 513
444 upload_and_draw_timers.Record(); 514 upload_and_draw_timers.Record();
445 MeasurementTimers finish_timers(gpu_timing_client_.get()); 515 MeasurementTimers finish_timers(gpu_timing_client_.get());
446 glFinish(); 516 glFinish();
447 CheckNoGlError(); 517 CheckNoGlError("glFinish");
448 finish_timers.Record(); 518 finish_timers.Record();
449 519
450 glDeleteTextures(1, &texture_id); 520 glDeleteTextures(1, &texture_id);
451 521
452 for (int i = 0; i < 4; ++i) { 522 for (int i = 0; i < 4; ++i) {
453 std::vector<uint8> pixels_rendered(texture_size.GetArea() * 4); 523 std::vector<uint8> pixels_rendered(texture_size.GetArea() * 4);
454 glReadPixels(texture_size.width() * positions[i].x(), 524 glReadPixels(texture_size.width() * positions[i].x(),
455 texture_size.height() * positions[i].y(), texture_size.width(), 525 texture_size.height() * positions[i].y(), texture_size.width(),
456 texture_size.height(), GL_RGBA, GL_UNSIGNED_BYTE, 526 texture_size.height(), GL_RGBA, GL_UNSIGNED_BYTE,
457 &pixels_rendered[0]); 527 &pixels_rendered[0]);
458 CheckNoGlError(); 528 CheckNoGlError("glReadPixels");
459 ASSERT_EQ(pixels[i].size(), pixels_rendered.size()); 529 ASSERT_EQ(pixels[i].size(), pixels_rendered.size());
460 EXPECT_EQ(pixels[i], pixels_rendered); 530 EXPECT_EQ(pixels[i], pixels_rendered);
461 } 531 }
462 532
463 bool gpu_timer_errors = gpu_timing_client_->IsAvailable() && 533 bool gpu_timer_errors = gpu_timing_client_->IsAvailable() &&
464 gpu_timing_client_->CheckAndResetTimerErrors(); 534 gpu_timing_client_->CheckAndResetTimerErrors();
465 if (!gpu_timer_errors) { 535 if (!gpu_timer_errors) {
466 upload_and_draw_timers.GetAsMeasurement("upload_and_draw") 536 upload_and_draw_timers.GetAsMeasurement("upload_and_draw")
467 .PrintResult("renaming"); 537 .PrintResult("renaming");
468 finish_timers.GetAsMeasurement("finish").PrintResult("renaming"); 538 finish_timers.GetAsMeasurement("finish").PrintResult("renaming");
469 } 539 }
470 } 540 }
471 541
472 } // namespace 542 } // namespace
473 } // namespace gpu 543 } // namespace gpu
OLDNEW
« no previous file with comments | « gpu/gpu_unittests.isolate ('k') | skia/BUILD.gn » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698