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

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

Issue 974913003: gpu: Run texture upload perf test with different texture formats. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase on master. 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.gyp ('k') | 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/gtest/include/gtest/gtest.h" 15 #include "testing/gtest/include/gtest/gtest.h"
15 #include "testing/perf/perf_test.h" 16 #include "testing/perf/perf_test.h"
16 #include "ui/gfx/geometry/size.h" 17 #include "ui/gfx/geometry/size.h"
17 #include "ui/gl/gl_bindings.h" 18 #include "ui/gl/gl_bindings.h"
18 #include "ui/gl/gl_context.h" 19 #include "ui/gl/gl_context.h"
20 #include "ui/gl/gl_enums.h"
19 #include "ui/gl/gl_surface.h" 21 #include "ui/gl/gl_surface.h"
20 #include "ui/gl/gpu_timing.h" 22 #include "ui/gl/gpu_timing.h"
21 #include "ui/gl/scoped_make_current.h" 23 #include "ui/gl/scoped_make_current.h"
22 24
23 namespace gpu { 25 namespace gpu {
24 namespace { 26 namespace {
25 27
26 const int kUploadPerfWarmupRuns = 10; 28 const int kUploadPerfWarmupRuns = 10;
27 const int kUploadPerfTestRuns = 100; 29 const int kUploadPerfTestRuns = 100;
28 30
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 scoped_ptr<char> error_log(new char[len]); 72 scoped_ptr<char> error_log(new char[len]);
71 glGetShaderInfoLog(shader, len, NULL, error_log.get()); 73 glGetShaderInfoLog(shader, len, NULL, error_log.get());
72 LOG(ERROR) << "Error compiling shader: " << error_log.get(); 74 LOG(ERROR) << "Error compiling shader: " << error_log.get();
73 } 75 }
74 } 76 }
75 CHECK_NE(0, compiled); 77 CHECK_NE(0, compiled);
76 return shader; 78 return shader;
77 } 79 }
78 80
79 void GenerateTextureData(const gfx::Size& size, 81 void GenerateTextureData(const gfx::Size& size,
82 GLenum format,
80 const int seed, 83 const int seed,
81 std::vector<uint8>* const pixels) { 84 std::vector<uint8>* const pixels) {
82 pixels->resize(size.GetArea() * 4); 85 DCHECK(format == GL_RGBA || format == GL_LUMINANCE || format == GL_RED_EXT);
83 for (int y = 0; y < size.height(); ++y) { 86 int bytes_per_pixel = format == GL_RGBA ? 4 : 1;
reveman 2015/03/03 21:59:40 If all you use is bytes_per_pixel in this function
Daniele Castagna 2015/03/06 17:29:16 Done.
84 for (int x = 0; x < size.width(); ++x) { 87 int bytes = size.GetArea() * bytes_per_pixel;
85 const size_t offset = (y * size.width() + x) * 4; 88 pixels->resize(bytes);
86 pixels->at(offset) = (y + seed) % 64; 89 for (int i = 0; i < bytes; ++i) {
87 pixels->at(offset + 1) = (x + seed) % 128; 90 int channel = i % bytes_per_pixel;
88 pixels->at(offset + 2) = (y + x + seed) % 256; 91 if (channel == 3) { // Alpha channel.
89 pixels->at(offset + 3) = 255; 92 pixels->at(i) = 255;
93 } else {
94 pixels->at(i) = (i + (seed << 2)) % (32 << channel);
90 } 95 }
91 } 96 }
92 } 97 }
93 98
99 // Compare a buffer containing pixels in a specified format to GL_RGBA buffer
100 // where the former buffer have been uploaded as a texture and drawn on the
101 // RGBA buffer.
102 bool CompareBufferToRGBABuffer(GLenum format,
103 const std::vector<uint8>& pixels,
104 const std::vector<uint8>& pixels_rgba) {
105 DCHECK(format == GL_RGBA || format == GL_LUMINANCE || format == GL_RED_EXT);
reveman 2015/03/03 21:59:40 how about a default: NOTREACHED() case in the swit
Daniele Castagna 2015/03/06 17:29:16 Done.
106 for (size_t i = 0; i < pixels.size(); i += 4) {
107 switch (format) {
108 case GL_RED_EXT: // (R_t, 0, 0, 1)
109 if (pixels_rgba[i] != pixels[i / 4] || pixels_rgba[i + 1] != 0 ||
110 pixels_rgba[i + 2] != 0 || pixels_rgba[i + 3] != 255) {
111 return false;
112 }
113 break;
114 case GL_LUMINANCE: // (L_t, L_t, L_t, 1)
115 if (pixels_rgba[i] != pixels[i / 4] ||
116 pixels_rgba[i + 1] != pixels[i / 4] ||
117 pixels_rgba[i + 2] != pixels[i / 4] || pixels_rgba[i + 3] != 255) {
118 return false;
119 }
120 break;
121 case GL_RGBA: // (R_t, G_t, B_t, A_t)
122 if (pixels_rgba[i] != pixels[i] ||
123 pixels_rgba[i + 1] != pixels[i + 1] ||
124 pixels_rgba[i + 2] != pixels[i + 2] ||
125 pixels_rgba[i + 3] != pixels[i + 3]) {
126 return false;
127 }
128 break;
129 }
130 }
131 return true;
132 }
133
94 // PerfTest to check costs of texture upload at different stages 134 // PerfTest to check costs of texture upload at different stages
95 // on different platforms. 135 // on different platforms.
96 class TextureUploadPerfTest : public testing::Test { 136 class TextureUploadPerfTest : public testing::Test {
97 public: 137 public:
98 TextureUploadPerfTest() : fbo_size_(1024, 1024) {} 138 TextureUploadPerfTest() : fbo_size_(1024, 1024) {}
99 139
100 // Overridden from testing::Test 140 // Overridden from testing::Test
101 void SetUp() override { 141 void SetUp() override {
102 // Initialize an offscreen surface and a gl context. 142 // Initialize an offscreen surface and a gl context.
103 gfx::GLSurface::InitializeOneOff(); 143 gfx::GLSurface::InitializeOneOff();
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
197 gl_context_ = nullptr; 237 gl_context_ = nullptr;
198 surface_ = nullptr; 238 surface_ = nullptr;
199 } 239 }
200 240
201 protected: 241 protected:
202 // Upload and draw on the offscren surface. 242 // Upload and draw on the offscren surface.
203 // Return a list of pair. Each pair describe a gl operation and the wall 243 // Return a list of pair. Each pair describe a gl operation and the wall
204 // time elapsed in milliseconds. 244 // time elapsed in milliseconds.
205 std::vector<Measurement> UploadAndDraw(const gfx::Size& size, 245 std::vector<Measurement> UploadAndDraw(const gfx::Size& size,
206 const std::vector<uint8>& pixels, 246 const std::vector<uint8>& pixels,
207 const GLenum format, 247 const GLenum format) {
208 const GLenum type) {
209 MeasurementTimers total_timers(gpu_timing_client_.get()); 248 MeasurementTimers total_timers(gpu_timing_client_.get());
210 GLuint texture_id = 0; 249 GLuint texture_id = 0;
211 250
212 MeasurementTimers tex_timers(gpu_timing_client_.get()); 251 MeasurementTimers tex_timers(gpu_timing_client_.get());
213 glActiveTexture(GL_TEXTURE0); 252 glActiveTexture(GL_TEXTURE0);
214 glGenTextures(1, &texture_id); 253 glGenTextures(1, &texture_id);
215 glBindTexture(GL_TEXTURE_2D, texture_id); 254 glBindTexture(GL_TEXTURE_2D, texture_id);
216 255
217 glTexImage2D(GL_TEXTURE_2D, 0, format, size.width(), size.height(), 0, 256 glTexImage2D(GL_TEXTURE_2D, 0, format, size.width(), size.height(), 0,
218 format, type, &pixels[0]); 257 format, GL_UNSIGNED_BYTE, &pixels[0]);
219 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 258 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
220 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 259 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
221 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 260 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
222 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 261 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
223 CheckNoGlError(); 262 CheckNoGlError();
224 tex_timers.Record(); 263 tex_timers.Record();
225 264
226 MeasurementTimers draw_timers(gpu_timing_client_.get()); 265 MeasurementTimers draw_timers(gpu_timing_client_.get());
227 glUseProgram(program_object_); 266 glUseProgram(program_object_);
228 glUniform1i(sampler_location_, 0); 267 glUniform1i(sampler_location_, 0);
(...skipping 11 matching lines...) Expand all
240 279
241 MeasurementTimers finish_timers(gpu_timing_client_.get()); 280 MeasurementTimers finish_timers(gpu_timing_client_.get());
242 glFinish(); 281 glFinish();
243 CheckNoGlError(); 282 CheckNoGlError();
244 finish_timers.Record(); 283 finish_timers.Record();
245 total_timers.Record(); 284 total_timers.Record();
246 285
247 glDeleteTextures(1, &texture_id); 286 glDeleteTextures(1, &texture_id);
248 287
249 std::vector<uint8> pixels_rendered(size.GetArea() * 4); 288 std::vector<uint8> pixels_rendered(size.GetArea() * 4);
250 glReadPixels(0, 0, size.width(), size.height(), GL_RGBA, type, 289 glReadPixels(0, 0, size.width(), size.height(), GL_RGBA, GL_UNSIGNED_BYTE,
251 &pixels_rendered[0]); 290 &pixels_rendered[0]);
252 CheckNoGlError(); 291 CheckNoGlError();
253 292 EXPECT_THAT(format, testing::AnyOf(GL_RGBA, GL_LUMINANCE, GL_RED_EXT));
254 // TODO(dcastagna): don't assume the format of the texture and do 293 EXPECT_TRUE(CompareBufferToRGBABuffer(format, pixels, pixels_rendered))
255 // the appropriate format conversion. 294 << "Format is: " << gfx::GLEnums::GetStringEnum(format);
256 EXPECT_EQ(static_cast<GLenum>(GL_RGBA), format);
257 EXPECT_EQ(pixels, pixels_rendered);
258 295
259 std::vector<Measurement> measurements; 296 std::vector<Measurement> measurements;
260 bool gpu_timer_errors = 297 bool gpu_timer_errors =
261 gpu_timing_client_->IsAvailable() && 298 gpu_timing_client_->IsAvailable() &&
262 gpu_timing_client_->CheckAndResetTimerErrors(); 299 gpu_timing_client_->CheckAndResetTimerErrors();
263 if (!gpu_timer_errors) { 300 if (!gpu_timer_errors) {
264 measurements.push_back(total_timers.GetAsMeasurement("total")); 301 measurements.push_back(total_timers.GetAsMeasurement("total"));
265 measurements.push_back(tex_timers.GetAsMeasurement("teximage2d")); 302 measurements.push_back(tex_timers.GetAsMeasurement("teximage2d"));
266 measurements.push_back(draw_timers.GetAsMeasurement("drawarrays")); 303 measurements.push_back(draw_timers.GetAsMeasurement("drawarrays"));
267 measurements.push_back(finish_timers.GetAsMeasurement("finish")); 304 measurements.push_back(finish_timers.GetAsMeasurement("finish"));
268 } 305 }
269 return measurements; 306 return measurements;
270 } 307 }
271 308
272 void RunUploadAndDrawMultipleTimes(const gfx::Size& size) { 309 void RunUploadAndDrawMultipleTimes(const gfx::Size& size,
310 const GLenum format) {
273 std::vector<uint8> pixels; 311 std::vector<uint8> pixels;
274 base::SmallMap<std::map<std::string, Measurement>> 312 base::SmallMap<std::map<std::string, Measurement>>
275 aggregates; // indexed by name 313 aggregates; // indexed by name
276 int successful_runs = 0; 314 int successful_runs = 0;
277 for (int i = 0; i < kUploadPerfWarmupRuns + kUploadPerfTestRuns; ++i) { 315 for (int i = 0; i < kUploadPerfWarmupRuns + kUploadPerfTestRuns; ++i) {
278 GenerateTextureData(size, i + 1, &pixels); 316 GenerateTextureData(size, format, i + 1, &pixels);
279 auto run = UploadAndDraw(size, pixels, GL_RGBA, GL_UNSIGNED_BYTE); 317 auto run = UploadAndDraw(size, pixels, format);
280 if (i < kUploadPerfWarmupRuns || !run.size()) { 318 if (i < kUploadPerfWarmupRuns || !run.size()) {
281 continue; 319 continue;
282 } 320 }
283 successful_runs++; 321 successful_runs++;
284 for (const Measurement& measurement : run) { 322 for (const Measurement& measurement : run) {
285 auto& aggregate = aggregates[measurement.name]; 323 auto& aggregate = aggregates[measurement.name];
286 aggregate.name = measurement.name; 324 aggregate.name = measurement.name;
287 aggregate.Increment(measurement); 325 aggregate.Increment(measurement);
288 } 326 }
289 } 327 }
328 std::string suffix = base::StringPrintf(
329 "_%d_%s", size.width(), gfx::GLEnums::GetStringEnum(format).c_str());
290 if (successful_runs) { 330 if (successful_runs) {
291 for (const auto& entry : aggregates) { 331 for (const auto& entry : aggregates) {
292 const auto m = entry.second.Divide(successful_runs); 332 const auto m = entry.second.Divide(successful_runs);
293 m.PrintResult(base::StringPrintf("_%d", size.width())); 333 m.PrintResult(suffix);
294 } 334 }
295 } 335 }
296 perf_test::PrintResult("sample_runs", "", "", 336 perf_test::PrintResult("sample_runs", suffix, "",
297 static_cast<size_t>(successful_runs), "laps", true); 337 static_cast<size_t>(successful_runs), "laps", true);
298 } 338 }
299 339
300 const gfx::Size fbo_size_; // for the fbo 340 const gfx::Size fbo_size_; // for the fbo
301 scoped_refptr<gfx::GLContext> gl_context_; 341 scoped_refptr<gfx::GLContext> gl_context_;
302 scoped_refptr<gfx::GLSurface> surface_; 342 scoped_refptr<gfx::GLSurface> surface_;
303 scoped_refptr<gfx::GPUTimingClient> gpu_timing_client_; 343 scoped_refptr<gfx::GPUTimingClient> gpu_timing_client_;
304 344
305 GLuint color_texture_ = 0; 345 GLuint color_texture_ = 0;
306 GLuint framebuffer_object_ = 0; 346 GLuint framebuffer_object_ = 0;
307 GLuint vertex_shader_ = 0; 347 GLuint vertex_shader_ = 0;
308 GLuint fragment_shader_ = 0; 348 GLuint fragment_shader_ = 0;
309 GLuint program_object_ = 0; 349 GLuint program_object_ = 0;
310 GLint sampler_location_ = -1; 350 GLint sampler_location_ = -1;
311 GLuint vertex_buffer_ = 0; 351 GLuint vertex_buffer_ = 0;
312 }; 352 };
313 353
314 // Perf test that generates, uploads and draws a texture on a surface repeatedly 354 // Perf test that generates, uploads and draws a texture on a surface repeatedly
315 // and prints out aggregated measurements for all the runs. 355 // and prints out aggregated measurements for all the runs.
316 TEST_F(TextureUploadPerfTest, glTexImage2d) { 356 TEST_F(TextureUploadPerfTest, glTexImage2d) {
317 int sizes[] = {128, 256, 512, 1024}; 357 int sizes[] = {128, 256, 512, 1024};
358 std::vector<GLenum> formats;
359 formats.push_back(GL_RGBA);
360 // Used by default for ResourceProvider::yuv_resource_format_.
361 formats.push_back(GL_LUMINANCE);
362
363 ui::ScopedMakeCurrent smc(gl_context_.get(), surface_.get());
364 bool has_texture_rg = gl_context_->HasExtension("GL_EXT_texture_rg") ||
365 gl_context_->HasExtension("GL_ARB_texture_rg");
366
367 if (has_texture_rg) {
368 // Used as ResourceProvider::yuv_resource_format_ if
369 // {ARB,EXT}_texture_rg is available.
370 formats.push_back(GL_RED_EXT);
371 }
318 for (int side : sizes) { 372 for (int side : sizes) {
319 ASSERT_GE(fbo_size_.width(), side); 373 ASSERT_GE(fbo_size_.width(), side);
320 ASSERT_GE(fbo_size_.height(), side); 374 ASSERT_GE(fbo_size_.height(), side);
375 gfx::Size size(side, side);
321 376
322 gfx::Size size(side, side); 377 for (GLenum format : formats) {
323 ui::ScopedMakeCurrent smc(gl_context_.get(), surface_.get()); 378 GenerateVertexBuffer(size);
324 GenerateVertexBuffer(size); 379 DCHECK_NE(0u, framebuffer_object_);
380 glBindFramebufferEXT(GL_FRAMEBUFFER, framebuffer_object_);
325 381
326 DCHECK_NE(0u, framebuffer_object_); 382 RunUploadAndDrawMultipleTimes(size, format);
327 glBindFramebufferEXT(GL_FRAMEBUFFER, framebuffer_object_); 383 }
328
329 RunUploadAndDrawMultipleTimes(size);
330 } 384 }
331 } 385 }
332 386
333 } // namespace 387 } // namespace
334 } // namespace gpu 388 } // namespace gpu
OLDNEW
« no previous file with comments | « gpu/gpu.gyp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698