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

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

Issue 1001833005: Update from https://crrev.com/320343 (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Supress 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') | gpu/tools/tools.gyp » ('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/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"
18 #include "ui/gfx/geometry/vector2d_f.h"
17 #include "ui/gl/gl_bindings.h" 19 #include "ui/gl/gl_bindings.h"
18 #include "ui/gl/gl_context.h" 20 #include "ui/gl/gl_context.h"
21 #include "ui/gl/gl_enums.h"
19 #include "ui/gl/gl_surface.h" 22 #include "ui/gl/gl_surface.h"
20 #include "ui/gl/gpu_timing.h" 23 #include "ui/gl/gpu_timing.h"
21 #include "ui/gl/scoped_make_current.h" 24 #include "ui/gl/scoped_make_current.h"
22 25
23 namespace gpu { 26 namespace gpu {
24 namespace { 27 namespace {
25 28
26 const int kUploadPerfWarmupRuns = 10; 29 const int kUploadPerfWarmupRuns = 10;
27 const int kUploadPerfTestRuns = 100; 30 const int kUploadPerfTestRuns = 100;
28 31
29 #define SHADER(Src) #Src 32 #define SHADER(Src) #Src
30 33
31 // clang-format off 34 // clang-format off
32 const char kVertexShader[] = 35 const char kVertexShader[] =
33 SHADER( 36 SHADER(
37 uniform vec2 translation = vec2(0.0, 0.0);
34 attribute vec2 a_position; 38 attribute vec2 a_position;
35 attribute vec2 a_texCoord; 39 attribute vec2 a_texCoord;
36 varying vec2 v_texCoord; 40 varying vec2 v_texCoord;
37 void main() { 41 void main() {
38 gl_Position = vec4(a_position.x, a_position.y, 0.0, 1.0); 42 gl_Position = vec4(
43 translation.x + a_position.x, translation.y + a_position.y, 0.0, 1.0);
39 v_texCoord = a_texCoord; 44 v_texCoord = a_texCoord;
40 } 45 }
41 ); 46 );
42 const char kFragmentShader[] = 47 const char kFragmentShader[] =
43 SHADER( 48 SHADER(
44 uniform sampler2D a_texture; 49 uniform sampler2D a_texture;
45 varying vec2 v_texCoord; 50 varying vec2 v_texCoord;
46 void main() { 51 void main() {
47 gl_FragColor = texture2D(a_texture, v_texCoord); 52 gl_FragColor = texture2D(a_texture, v_texCoord);
48 } 53 }
(...skipping 21 matching lines...) Expand all
70 scoped_ptr<char> error_log(new char[len]); 75 scoped_ptr<char> error_log(new char[len]);
71 glGetShaderInfoLog(shader, len, NULL, error_log.get()); 76 glGetShaderInfoLog(shader, len, NULL, error_log.get());
72 LOG(ERROR) << "Error compiling shader: " << error_log.get(); 77 LOG(ERROR) << "Error compiling shader: " << error_log.get();
73 } 78 }
74 } 79 }
75 CHECK_NE(0, compiled); 80 CHECK_NE(0, compiled);
76 return shader; 81 return shader;
77 } 82 }
78 83
79 void GenerateTextureData(const gfx::Size& size, 84 void GenerateTextureData(const gfx::Size& size,
85 int bytes_per_pixel,
80 const int seed, 86 const int seed,
81 std::vector<uint8>* const pixels) { 87 std::vector<uint8>* const pixels) {
82 pixels->resize(size.GetArea() * 4); 88 int bytes = size.GetArea() * bytes_per_pixel;
83 for (int y = 0; y < size.height(); ++y) { 89 pixels->resize(bytes);
84 for (int x = 0; x < size.width(); ++x) { 90 for (int i = 0; i < bytes; ++i) {
85 const size_t offset = (y * size.width() + x) * 4; 91 int channel = i % bytes_per_pixel;
86 pixels->at(offset) = (y + seed) % 64; 92 if (channel == 3) { // Alpha channel.
87 pixels->at(offset + 1) = (x + seed) % 128; 93 pixels->at(i) = 255;
88 pixels->at(offset + 2) = (y + x + seed) % 256; 94 } else {
89 pixels->at(offset + 3) = 255; 95 pixels->at(i) = (i + (seed << 2)) % (32 << channel);
90 } 96 }
91 } 97 }
92 } 98 }
93 99
100 // Compare a buffer containing pixels in a specified format to GL_RGBA buffer
101 // where the former buffer have been uploaded as a texture and drawn on the
102 // RGBA buffer.
103 bool CompareBufferToRGBABuffer(GLenum format,
104 const std::vector<uint8>& pixels,
105 const std::vector<uint8>& pixels_rgba) {
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 default:
130 NOTREACHED();
131 }
132 }
133 return true;
134 }
135
94 // PerfTest to check costs of texture upload at different stages 136 // PerfTest to check costs of texture upload at different stages
95 // on different platforms. 137 // on different platforms.
96 class TextureUploadPerfTest : public testing::Test { 138 class TextureUploadPerfTest : public testing::Test {
97 public: 139 public:
98 TextureUploadPerfTest() : fbo_size_(1024, 1024) {} 140 TextureUploadPerfTest() : fbo_size_(1024, 1024) {}
99 141
100 // Overridden from testing::Test 142 // Overridden from testing::Test
101 void SetUp() override { 143 void SetUp() override {
144 static bool gl_initialized = gfx::GLSurface::InitializeOneOff();
145 DCHECK(gl_initialized);
102 // Initialize an offscreen surface and a gl context. 146 // Initialize an offscreen surface and a gl context.
103 gfx::GLSurface::InitializeOneOff();
104 surface_ = gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size(4, 4)); 147 surface_ = gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size(4, 4));
105 gl_context_ = gfx::GLContext::CreateGLContext(NULL, // share_group 148 gl_context_ = gfx::GLContext::CreateGLContext(NULL, // share_group
106 surface_.get(), 149 surface_.get(),
107 gfx::PreferIntegratedGpu); 150 gfx::PreferIntegratedGpu);
108 ui::ScopedMakeCurrent smc(gl_context_.get(), surface_.get()); 151 ui::ScopedMakeCurrent smc(gl_context_.get(), surface_.get());
109 glGenTextures(1, &color_texture_); 152 glGenTextures(1, &color_texture_);
110 glBindTexture(GL_TEXTURE_2D, color_texture_); 153 glBindTexture(GL_TEXTURE_2D, color_texture_);
111 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 154 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
112 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 155 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
113 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 156 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
(...skipping 25 matching lines...) Expand all
139 fragment_shader_ = LoadShader(GL_FRAGMENT_SHADER, kFragmentShader); 182 fragment_shader_ = LoadShader(GL_FRAGMENT_SHADER, kFragmentShader);
140 program_object_ = glCreateProgram(); 183 program_object_ = glCreateProgram();
141 CHECK_NE(0u, program_object_); 184 CHECK_NE(0u, program_object_);
142 185
143 glAttachShader(program_object_, vertex_shader_); 186 glAttachShader(program_object_, vertex_shader_);
144 glAttachShader(program_object_, fragment_shader_); 187 glAttachShader(program_object_, fragment_shader_);
145 glBindAttribLocation(program_object_, 0, "a_position"); 188 glBindAttribLocation(program_object_, 0, "a_position");
146 glBindAttribLocation(program_object_, 1, "a_texCoord"); 189 glBindAttribLocation(program_object_, 1, "a_texCoord");
147 glLinkProgram(program_object_); 190 glLinkProgram(program_object_);
148 191
192 translation_location_ =
193 glGetUniformLocation(program_object_, "translation");
194 DCHECK_NE(-1, translation_location_);
195
149 GLint linked = -1; 196 GLint linked = -1;
150 glGetProgramiv(program_object_, GL_LINK_STATUS, &linked); 197 glGetProgramiv(program_object_, GL_LINK_STATUS, &linked);
151 CHECK_NE(0, linked); 198 CHECK_NE(0, linked);
199 glUseProgram(program_object_);
200 glUniform1i(sampler_location_, 0);
152 201
153 sampler_location_ = glGetUniformLocation(program_object_, "a_texture"); 202 sampler_location_ = glGetUniformLocation(program_object_, "a_texture");
154 CHECK_NE(-1, sampler_location_); 203 CHECK_NE(-1, sampler_location_);
155 204
156 glGenBuffersARB(1, &vertex_buffer_); 205 glGenBuffersARB(1, &vertex_buffer_);
157 CHECK_NE(0u, vertex_buffer_); 206 CHECK_NE(0u, vertex_buffer_);
207 DCHECK_NE(0u, vertex_buffer_);
208 glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_);
209 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, 0);
210 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4,
211 reinterpret_cast<void*>(sizeof(GLfloat) * 2));
212 glEnableVertexAttribArray(0);
213 glEnableVertexAttribArray(1);
158 CheckNoGlError(); 214 CheckNoGlError();
159 } 215 }
160 216
161 void GenerateVertexBuffer(const gfx::Size& size) { 217 void GenerateVertexBuffer(const gfx::Size& size) {
162 DCHECK_NE(0u, vertex_buffer_); 218 DCHECK_NE(0u, vertex_buffer_);
163 glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_); 219 glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_);
164 // right and top are in clipspace 220 // right and top are in clipspace
165 float right = -1.f + 2.f * size.width() / fbo_size_.width(); 221 float right = -1.f + 2.f * size.width() / fbo_size_.width();
166 float top = -1.f + 2.f * size.height() / fbo_size_.height(); 222 float top = -1.f + 2.f * size.height() / fbo_size_.height();
167 // Four vertexes, one per line. Each vertex has two components per 223 // Four vertexes, one per line. Each vertex has two components per
168 // position and two per texcoord. 224 // position and two per texcoord.
169 // It represents a quad formed by two triangles if interpreted 225 // It represents a quad formed by two triangles if interpreted
170 // as a tristrip. 226 // as a tristrip.
171 227
172 // clang-format off 228 // clang-format off
173 GLfloat data[16] = { 229 GLfloat data[16] = {
174 -1.f, -1.f, 0.f, 0.f, 230 -1.f, -1.f, 0.f, 0.f,
175 right, -1.f, 1.f, 0.f, 231 right, -1.f, 1.f, 0.f,
176 -1.f, top, 0.f, 1.f, 232 -1.f, top, 0.f, 1.f,
177 right, top, 1.f, 1.f}; 233 right, top, 1.f, 1.f};
178 // clang-format on 234 // clang-format on
179
180 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW); 235 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
181 CheckNoGlError(); 236 CheckNoGlError();
182 } 237 }
183 238
184 void TearDown() override { 239 void TearDown() override {
185 ui::ScopedMakeCurrent smc(gl_context_.get(), surface_.get()); 240 ui::ScopedMakeCurrent smc(gl_context_.get(), surface_.get());
186 glDeleteProgram(program_object_); 241 glDeleteProgram(program_object_);
187 glDeleteShader(vertex_shader_); 242 glDeleteShader(vertex_shader_);
188 glDeleteShader(fragment_shader_); 243 glDeleteShader(fragment_shader_);
189 glDeleteBuffersARB(1, &vertex_buffer_); 244 glDeleteBuffersARB(1, &vertex_buffer_);
190 245
191 glBindFramebufferEXT(GL_FRAMEBUFFER, 0); 246 glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
192 glDeleteFramebuffersEXT(1, &framebuffer_object_); 247 glDeleteFramebuffersEXT(1, &framebuffer_object_);
193 glDeleteTextures(1, &color_texture_); 248 glDeleteTextures(1, &color_texture_);
194 CheckNoGlError(); 249 CheckNoGlError();
195 250
196 gpu_timing_client_ = nullptr; 251 gpu_timing_client_ = nullptr;
197 gl_context_ = nullptr; 252 gl_context_ = nullptr;
198 surface_ = nullptr; 253 surface_ = nullptr;
199 } 254 }
200 255
201 protected: 256 protected:
257 GLuint CreateGLTexture() {
258 GLuint texture_id = 0;
259 glActiveTexture(GL_TEXTURE0);
260 glGenTextures(1, &texture_id);
261 glBindTexture(GL_TEXTURE_2D, texture_id);
262 return texture_id;
263 }
264
265 void UploadTexture(GLuint texture_id,
266 const gfx::Size& size,
267 const std::vector<uint8>& pixels,
268 GLenum format) {
269 glTexImage2D(GL_TEXTURE_2D, 0, format, size.width(), size.height(), 0,
270 format, GL_UNSIGNED_BYTE, &pixels[0]);
271 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
272 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
273 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
274 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
275 CheckNoGlError();
276 }
277
202 // Upload and draw on the offscren surface. 278 // Upload and draw on the offscren surface.
203 // Return a list of pair. Each pair describe a gl operation and the wall 279 // Return a list of pair. Each pair describe a gl operation and the wall
204 // time elapsed in milliseconds. 280 // time elapsed in milliseconds.
205 std::vector<Measurement> UploadAndDraw(const gfx::Size& size, 281 std::vector<Measurement> UploadAndDraw(const gfx::Size& size,
206 const std::vector<uint8>& pixels, 282 const std::vector<uint8>& pixels,
207 const GLenum format, 283 const GLenum format) {
208 const GLenum type) { 284 GLuint texture_id = CreateGLTexture();
209 MeasurementTimers total_timers(gpu_timing_client_.get());
210 GLuint texture_id = 0;
211
212 MeasurementTimers tex_timers(gpu_timing_client_.get()); 285 MeasurementTimers tex_timers(gpu_timing_client_.get());
213 glActiveTexture(GL_TEXTURE0); 286 UploadTexture(texture_id, size, pixels, format);
214 glGenTextures(1, &texture_id);
215 glBindTexture(GL_TEXTURE_2D, texture_id);
216
217 glTexImage2D(GL_TEXTURE_2D, 0, format, size.width(), size.height(), 0,
218 format, type, &pixels[0]);
219 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
220 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
221 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);
223 CheckNoGlError();
224 tex_timers.Record(); 287 tex_timers.Record();
225 288
226 MeasurementTimers draw_timers(gpu_timing_client_.get()); 289 MeasurementTimers draw_timers(gpu_timing_client_.get());
227 glUseProgram(program_object_);
228 glUniform1i(sampler_location_, 0);
229
230 DCHECK_NE(0u, vertex_buffer_);
231 glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_);
232 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, 0);
233 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4,
234 reinterpret_cast<void*>(sizeof(GLfloat) * 2));
235 glEnableVertexAttribArray(0);
236 glEnableVertexAttribArray(1);
237 290
238 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 291 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
239 draw_timers.Record(); 292 draw_timers.Record();
240 293
241 MeasurementTimers finish_timers(gpu_timing_client_.get()); 294 MeasurementTimers finish_timers(gpu_timing_client_.get());
242 glFinish(); 295 glFinish();
243 CheckNoGlError(); 296 CheckNoGlError();
244 finish_timers.Record(); 297 finish_timers.Record();
245 total_timers.Record();
246 298
247 glDeleteTextures(1, &texture_id); 299 glDeleteTextures(1, &texture_id);
248 300
249 std::vector<uint8> pixels_rendered(size.GetArea() * 4); 301 std::vector<uint8> pixels_rendered(size.GetArea() * 4);
250 glReadPixels(0, 0, size.width(), size.height(), GL_RGBA, type, 302 glReadPixels(0, 0, size.width(), size.height(), GL_RGBA, GL_UNSIGNED_BYTE,
251 &pixels_rendered[0]); 303 &pixels_rendered[0]);
252 CheckNoGlError(); 304 CheckNoGlError();
253 305 EXPECT_TRUE(CompareBufferToRGBABuffer(format, pixels, pixels_rendered))
254 // TODO(dcastagna): don't assume the format of the texture and do 306 << "Format is: " << gfx::GLEnums::GetStringEnum(format);
255 // the appropriate format conversion.
256 EXPECT_EQ(static_cast<GLenum>(GL_RGBA), format);
257 EXPECT_EQ(pixels, pixels_rendered);
258 307
259 std::vector<Measurement> measurements; 308 std::vector<Measurement> measurements;
260 bool gpu_timer_errors = 309 bool gpu_timer_errors =
261 gpu_timing_client_->IsAvailable() && 310 gpu_timing_client_->IsAvailable() &&
262 gpu_timing_client_->CheckAndResetTimerErrors(); 311 gpu_timing_client_->CheckAndResetTimerErrors();
263 if (!gpu_timer_errors) { 312 if (!gpu_timer_errors) {
264 measurements.push_back(total_timers.GetAsMeasurement("total"));
265 measurements.push_back(tex_timers.GetAsMeasurement("teximage2d")); 313 measurements.push_back(tex_timers.GetAsMeasurement("teximage2d"));
266 measurements.push_back(draw_timers.GetAsMeasurement("drawarrays")); 314 measurements.push_back(draw_timers.GetAsMeasurement("drawarrays"));
267 measurements.push_back(finish_timers.GetAsMeasurement("finish")); 315 measurements.push_back(finish_timers.GetAsMeasurement("finish"));
268 } 316 }
269 return measurements; 317 return measurements;
270 } 318 }
271 319
272 void RunUploadAndDrawMultipleTimes(const gfx::Size& size) { 320 void RunUploadAndDrawMultipleTimes(const gfx::Size& size,
321 const GLenum format) {
273 std::vector<uint8> pixels; 322 std::vector<uint8> pixels;
274 base::SmallMap<std::map<std::string, Measurement>> 323 base::SmallMap<std::map<std::string, Measurement>>
275 aggregates; // indexed by name 324 aggregates; // indexed by name
276 int successful_runs = 0; 325 int successful_runs = 0;
326 ASSERT_THAT(format, testing::AnyOf(GL_RGBA, GL_LUMINANCE, GL_RED_EXT));
277 for (int i = 0; i < kUploadPerfWarmupRuns + kUploadPerfTestRuns; ++i) { 327 for (int i = 0; i < kUploadPerfWarmupRuns + kUploadPerfTestRuns; ++i) {
278 GenerateTextureData(size, i + 1, &pixels); 328 GenerateTextureData(size, format == GL_RGBA ? 4 : 1, i + 1, &pixels);
279 auto run = UploadAndDraw(size, pixels, GL_RGBA, GL_UNSIGNED_BYTE); 329 auto run = UploadAndDraw(size, pixels, format);
280 if (i < kUploadPerfWarmupRuns || !run.size()) { 330 if (i < kUploadPerfWarmupRuns || !run.size()) {
281 continue; 331 continue;
282 } 332 }
283 successful_runs++; 333 successful_runs++;
284 for (const Measurement& measurement : run) { 334 for (const Measurement& measurement : run) {
285 auto& aggregate = aggregates[measurement.name]; 335 auto& aggregate = aggregates[measurement.name];
286 aggregate.name = measurement.name; 336 aggregate.name = measurement.name;
287 aggregate.Increment(measurement); 337 aggregate.Increment(measurement);
288 } 338 }
289 } 339 }
340 std::string suffix = base::StringPrintf(
341 "_%d_%s", size.width(), gfx::GLEnums::GetStringEnum(format).c_str());
290 if (successful_runs) { 342 if (successful_runs) {
291 for (const auto& entry : aggregates) { 343 for (const auto& entry : aggregates) {
292 const auto m = entry.second.Divide(successful_runs); 344 const auto m = entry.second.Divide(successful_runs);
293 m.PrintResult(base::StringPrintf("_%d", size.width())); 345 m.PrintResult(suffix);
294 } 346 }
295 } 347 }
296 perf_test::PrintResult("sample_runs", "", "", 348 perf_test::PrintResult("sample_runs", suffix, "",
297 static_cast<size_t>(successful_runs), "laps", true); 349 static_cast<size_t>(successful_runs), "laps", true);
298 } 350 }
299 351
300 const gfx::Size fbo_size_; // for the fbo 352 const gfx::Size fbo_size_; // for the fbo
301 scoped_refptr<gfx::GLContext> gl_context_; 353 scoped_refptr<gfx::GLContext> gl_context_;
302 scoped_refptr<gfx::GLSurface> surface_; 354 scoped_refptr<gfx::GLSurface> surface_;
303 scoped_refptr<gfx::GPUTimingClient> gpu_timing_client_; 355 scoped_refptr<gfx::GPUTimingClient> gpu_timing_client_;
304 356
305 GLuint color_texture_ = 0; 357 GLuint color_texture_ = 0;
306 GLuint framebuffer_object_ = 0; 358 GLuint framebuffer_object_ = 0;
307 GLuint vertex_shader_ = 0; 359 GLuint vertex_shader_ = 0;
308 GLuint fragment_shader_ = 0; 360 GLuint fragment_shader_ = 0;
309 GLuint program_object_ = 0; 361 GLuint program_object_ = 0;
310 GLint sampler_location_ = -1; 362 GLint sampler_location_ = -1;
363 GLint translation_location_ = -1;
311 GLuint vertex_buffer_ = 0; 364 GLuint vertex_buffer_ = 0;
312 }; 365 };
313 366
314 // Perf test that generates, uploads and draws a texture on a surface repeatedly 367 // Perf test that generates, uploads and draws a texture on a surface repeatedly
315 // and prints out aggregated measurements for all the runs. 368 // and prints out aggregated measurements for all the runs.
316 TEST_F(TextureUploadPerfTest, glTexImage2d) { 369 TEST_F(TextureUploadPerfTest, glTexImage2d) {
317 int sizes[] = {128, 256, 512, 1024}; 370 int sizes[] = {128, 256, 512, 1024};
371 std::vector<GLenum> formats;
372 formats.push_back(GL_RGBA);
373 // Used by default for ResourceProvider::yuv_resource_format_.
374 formats.push_back(GL_LUMINANCE);
375
376 ui::ScopedMakeCurrent smc(gl_context_.get(), surface_.get());
377 bool has_texture_rg = gl_context_->HasExtension("GL_EXT_texture_rg") ||
378 gl_context_->HasExtension("GL_ARB_texture_rg");
379
380 if (has_texture_rg) {
381 // Used as ResourceProvider::yuv_resource_format_ if
382 // {ARB,EXT}_texture_rg is available.
383 formats.push_back(GL_RED_EXT);
384 }
318 for (int side : sizes) { 385 for (int side : sizes) {
319 ASSERT_GE(fbo_size_.width(), side); 386 ASSERT_GE(fbo_size_.width(), side);
320 ASSERT_GE(fbo_size_.height(), side); 387 ASSERT_GE(fbo_size_.height(), side);
321
322 gfx::Size size(side, side); 388 gfx::Size size(side, side);
323 ui::ScopedMakeCurrent smc(gl_context_.get(), surface_.get());
324 GenerateVertexBuffer(size); 389 GenerateVertexBuffer(size);
325 390 for (GLenum format : formats) {
326 DCHECK_NE(0u, framebuffer_object_); 391 RunUploadAndDrawMultipleTimes(size, format);
327 glBindFramebufferEXT(GL_FRAMEBUFFER, framebuffer_object_); 392 }
328
329 RunUploadAndDrawMultipleTimes(size);
330 } 393 }
331 } 394 }
332 395
396 // Perf test to check if the driver is doing texture renaming.
397 // This test creates one GL texture_id and four different images. For
398 // every image it uploads it using texture_id and it draws multiple
399 // times. The cpu/wall time and the gpu time for all the uploads and
400 // draws, but before glFinish, is computed and is printed out at the end as
401 // "upload_and_draw". If the gpu time is >> than the cpu/wall time we expect the
402 // driver to do texture renaming: this means that while the gpu is drawing using
403 // texture_id it didn't block cpu side the texture upload using the same
404 // texture_id.
405 TEST_F(TextureUploadPerfTest, renaming) {
406 gfx::Size texture_size(fbo_size_.width() / 2, fbo_size_.height() / 2);
407
408 std::vector<uint8> pixels[4];
409 for (int i = 0; i < 4; ++i) {
410 GenerateTextureData(texture_size, 4, i + 1, &pixels[i]);
411 }
412
413 ui::ScopedMakeCurrent smc(gl_context_.get(), surface_.get());
414 GenerateVertexBuffer(texture_size);
415
416 gfx::Vector2dF positions[] = {gfx::Vector2dF(0.f, 0.f),
417 gfx::Vector2dF(1.f, 0.f),
418 gfx::Vector2dF(0.f, 1.f),
419 gfx::Vector2dF(1.f, 1.f)};
420 GLuint texture_id = CreateGLTexture();
421
422 MeasurementTimers upload_and_draw_timers(gpu_timing_client_.get());
423
424 for (int i = 0; i < 4; ++i) {
425 UploadTexture(texture_id, texture_size, pixels[i % 4], GL_RGBA);
426 DCHECK_NE(-1, translation_location_);
427 glUniform2f(translation_location_, positions[i % 4].x(),
428 positions[i % 4].y());
429 // Draw the same quad multiple times to make sure that the time spent on the
430 // gpu is more than the cpu time.
431 for (int draw = 0; draw < 128; ++draw) {
432 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
433 }
434 }
435
436 upload_and_draw_timers.Record();
437 MeasurementTimers finish_timers(gpu_timing_client_.get());
438 glFinish();
439 CheckNoGlError();
440 finish_timers.Record();
441
442 glDeleteTextures(1, &texture_id);
443
444 for (int i = 0; i < 4; ++i) {
445 std::vector<uint8> pixels_rendered(texture_size.GetArea() * 4);
446 glReadPixels(texture_size.width() * positions[i].x(),
447 texture_size.height() * positions[i].y(), texture_size.width(),
448 texture_size.height(), GL_RGBA, GL_UNSIGNED_BYTE,
449 &pixels_rendered[0]);
450 CheckNoGlError();
451 ASSERT_EQ(pixels[i].size(), pixels_rendered.size());
452 EXPECT_EQ(pixels[i], pixels_rendered);
453 }
454
455 bool gpu_timer_errors = gpu_timing_client_->IsAvailable() &&
456 gpu_timing_client_->CheckAndResetTimerErrors();
457 if (!gpu_timer_errors) {
458 upload_and_draw_timers.GetAsMeasurement("upload_and_draw").PrintResult("");
459 finish_timers.GetAsMeasurement("finish").PrintResult("");
460 }
461 }
462
333 } // namespace 463 } // namespace
334 } // namespace gpu 464 } // namespace gpu
OLDNEW
« no previous file with comments | « gpu/gpu_unittests.isolate ('k') | gpu/tools/tools.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698