1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/resources/raster_worker_pool.h"
7 #include "base/time/time.h"
8 #include "cc/output/context_provider.h"
9 #include "cc/resources/direct_raster_worker_pool.h"
10 #include "cc/resources/image_copy_raster_worker_pool.h"
11 #include "cc/resources/image_raster_worker_pool.h"
12 #include "cc/resources/pixel_buffer_raster_worker_pool.h"
13 #include "cc/resources/rasterizer.h"
14 #include "cc/resources/resource_pool.h"
15 #include "cc/resources/resource_provider.h"
16 #include "cc/resources/scoped_resource.h"
17 #include "cc/test/fake_output_surface.h"
18 #include "cc/test/fake_output_surface_client.h"
19 #include "cc/test/lap_timer.h"
20 #include "cc/test/test_context_support.h"
21 #include "cc/test/test_shared_bitmap_manager.h"
22 #include "cc/test/test_web_graphics_context_3d.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24 #include "testing/perf/perf_test.h"
25 #include "third_party/khronos/GLES2/gl2.h"
30 class PerfGLES2Interface : public gpu::gles2::GLES2InterfaceStub {
31 // Overridden from gpu::gles2::GLES2Interface:
32 virtual GLuint CreateImageCHROMIUM(GLsizei width,
34 GLenum internalformat,
35 GLenum usage) OVERRIDE {
38 virtual void GenBuffers(GLsizei n, GLuint* buffers) OVERRIDE {
39 for (GLsizei i = 0; i < n; ++i)
42 virtual void GenTextures(GLsizei n, GLuint* textures) OVERRIDE {
43 for (GLsizei i = 0; i < n; ++i)
46 virtual void GetIntegerv(GLenum pname, GLint* params) OVERRIDE {
47 if (pname == GL_MAX_TEXTURE_SIZE)
52 class PerfContextProvider : public ContextProvider {
54 PerfContextProvider() : context_gl_(new PerfGLES2Interface) {}
56 virtual bool BindToCurrentThread() OVERRIDE { return true; }
57 virtual Capabilities ContextCapabilities() OVERRIDE { return Capabilities(); }
58 virtual gpu::gles2::GLES2Interface* ContextGL() OVERRIDE {
59 return context_gl_.get();
61 virtual gpu::ContextSupport* ContextSupport() OVERRIDE { return &support_; }
62 virtual class GrContext* GrContext() OVERRIDE { return NULL; }
63 virtual bool IsContextLost() OVERRIDE { return false; }
64 virtual void VerifyContexts() OVERRIDE {}
65 virtual void DeleteCachedResources() OVERRIDE {}
66 virtual bool DestroyedOnMainThread() OVERRIDE { return false; }
67 virtual void SetLostContextCallback(const LostContextCallback& cb) OVERRIDE {}
68 virtual void SetMemoryPolicyChangedCallback(
69 const MemoryPolicyChangedCallback& cb) OVERRIDE {}
72 virtual ~PerfContextProvider() {}
74 scoped_ptr<PerfGLES2Interface> context_gl_;
75 TestContextSupport support_;
78 enum RasterWorkerPoolType {
79 RASTER_WORKER_POOL_TYPE_PIXEL_BUFFER,
80 RASTER_WORKER_POOL_TYPE_IMAGE,
81 RASTER_WORKER_POOL_TYPE_IMAGE_COPY,
82 RASTER_WORKER_POOL_TYPE_DIRECT
85 static const int kTimeLimitMillis = 2000;
86 static const int kWarmupRuns = 5;
87 static const int kTimeCheckInterval = 10;
89 class PerfImageDecodeTaskImpl : public ImageDecodeTask {
91 PerfImageDecodeTaskImpl() {}
93 // Overridden from Task:
94 virtual void RunOnWorkerThread() OVERRIDE {}
96 // Overridden from RasterizerTask:
97 virtual void ScheduleOnOriginThread(RasterizerTaskClient* client) OVERRIDE {}
98 virtual void CompleteOnOriginThread(RasterizerTaskClient* client) OVERRIDE {}
99 virtual void RunReplyOnOriginThread() OVERRIDE { Reset(); }
103 did_complete_ = false;
107 virtual ~PerfImageDecodeTaskImpl() {}
110 DISALLOW_COPY_AND_ASSIGN(PerfImageDecodeTaskImpl);
113 class PerfRasterTaskImpl : public RasterTask {
115 PerfRasterTaskImpl(scoped_ptr<ScopedResource> resource,
116 ImageDecodeTask::Vector* dependencies)
117 : RasterTask(resource.get(), dependencies), resource_(resource.Pass()) {}
119 // Overridden from Task:
120 virtual void RunOnWorkerThread() OVERRIDE {}
122 // Overridden from RasterizerTask:
123 virtual void ScheduleOnOriginThread(RasterizerTaskClient* client) OVERRIDE {
124 client->AcquireCanvasForRaster(this);
126 virtual void CompleteOnOriginThread(RasterizerTaskClient* client) OVERRIDE {
127 client->ReleaseCanvasForRaster(this);
129 virtual void RunReplyOnOriginThread() OVERRIDE { Reset(); }
133 did_complete_ = false;
137 virtual ~PerfRasterTaskImpl() {}
140 scoped_ptr<ScopedResource> resource_;
142 DISALLOW_COPY_AND_ASSIGN(PerfRasterTaskImpl);
145 class RasterWorkerPoolPerfTestBase {
147 typedef std::vector<scoped_refptr<RasterTask> > RasterTaskVector;
149 RasterWorkerPoolPerfTestBase()
150 : context_provider_(make_scoped_refptr(new PerfContextProvider)),
151 task_graph_runner_(new TaskGraphRunner),
153 base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
154 kTimeCheckInterval) {
155 output_surface_ = FakeOutputSurface::Create3d(context_provider_).Pass();
156 CHECK(output_surface_->BindToClient(&output_surface_client_));
158 shared_bitmap_manager_.reset(new TestSharedBitmapManager());
160 ResourceProvider::Create(
161 output_surface_.get(), shared_bitmap_manager_.get(), 0, false, 1,
163 staging_resource_pool_ = ResourcePool::Create(
164 resource_provider_.get(), GL_TEXTURE_2D, RGBA_8888);
167 void CreateImageDecodeTasks(unsigned num_image_decode_tasks,
168 ImageDecodeTask::Vector* image_decode_tasks) {
169 for (unsigned i = 0; i < num_image_decode_tasks; ++i)
170 image_decode_tasks->push_back(new PerfImageDecodeTaskImpl);
173 void CreateRasterTasks(unsigned num_raster_tasks,
174 const ImageDecodeTask::Vector& image_decode_tasks,
175 RasterTaskVector* raster_tasks) {
176 const gfx::Size size(1, 1);
178 for (unsigned i = 0; i < num_raster_tasks; ++i) {
179 scoped_ptr<ScopedResource> resource(
180 ScopedResource::Create(resource_provider_.get()));
181 resource->Allocate(size, ResourceProvider::TextureUsageAny, RGBA_8888);
183 ImageDecodeTask::Vector dependencies = image_decode_tasks;
184 raster_tasks->push_back(
185 new PerfRasterTaskImpl(resource.Pass(), &dependencies));
189 void BuildRasterTaskQueue(RasterTaskQueue* queue,
190 const RasterTaskVector& raster_tasks) {
191 for (size_t i = 0u; i < raster_tasks.size(); ++i) {
192 bool required_for_activation = (i % 2) == 0;
193 queue->items.push_back(RasterTaskQueue::Item(raster_tasks[i].get(),
194 required_for_activation));
195 queue->required_for_activation_count += required_for_activation;
200 scoped_refptr<ContextProvider> context_provider_;
201 FakeOutputSurfaceClient output_surface_client_;
202 scoped_ptr<FakeOutputSurface> output_surface_;
203 scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
204 scoped_ptr<ResourceProvider> resource_provider_;
205 scoped_ptr<ResourcePool> staging_resource_pool_;
206 scoped_ptr<TaskGraphRunner> task_graph_runner_;
210 class RasterWorkerPoolPerfTest
211 : public RasterWorkerPoolPerfTestBase,
212 public testing::TestWithParam<RasterWorkerPoolType>,
213 public RasterizerClient {
215 RasterWorkerPoolPerfTest() {
216 switch (GetParam()) {
217 case RASTER_WORKER_POOL_TYPE_PIXEL_BUFFER:
218 raster_worker_pool_ = PixelBufferRasterWorkerPool::Create(
219 base::MessageLoopProxy::current().get(),
220 task_graph_runner_.get(),
221 resource_provider_.get(),
222 std::numeric_limits<size_t>::max());
224 case RASTER_WORKER_POOL_TYPE_IMAGE:
225 raster_worker_pool_ = ImageRasterWorkerPool::Create(
226 base::MessageLoopProxy::current().get(),
227 task_graph_runner_.get(),
228 resource_provider_.get());
230 case RASTER_WORKER_POOL_TYPE_IMAGE_COPY:
231 raster_worker_pool_ = ImageCopyRasterWorkerPool::Create(
232 base::MessageLoopProxy::current().get(),
233 task_graph_runner_.get(),
234 resource_provider_.get(),
235 staging_resource_pool_.get());
237 case RASTER_WORKER_POOL_TYPE_DIRECT:
238 raster_worker_pool_ = DirectRasterWorkerPool::Create(
239 base::MessageLoopProxy::current().get(),
240 resource_provider_.get(),
241 context_provider_.get());
245 DCHECK(raster_worker_pool_);
246 raster_worker_pool_->AsRasterizer()->SetClient(this);
249 // Overridden from testing::Test:
250 virtual void TearDown() OVERRIDE {
251 raster_worker_pool_->AsRasterizer()->Shutdown();
252 raster_worker_pool_->AsRasterizer()->CheckForCompletedTasks();
255 // Overriden from RasterizerClient:
256 virtual bool ShouldForceTasksRequiredForActivationToComplete() const
260 virtual void DidFinishRunningTasks() OVERRIDE {
261 raster_worker_pool_->AsRasterizer()->CheckForCompletedTasks();
262 base::MessageLoop::current()->Quit();
264 virtual void DidFinishRunningTasksRequiredForActivation() OVERRIDE {}
266 void RunMessageLoopUntilAllTasksHaveCompleted() {
267 task_graph_runner_->RunUntilIdle();
268 base::MessageLoop::current()->Run();
271 void RunScheduleTasksTest(const std::string& test_name,
272 unsigned num_raster_tasks,
273 unsigned num_image_decode_tasks) {
274 ImageDecodeTask::Vector image_decode_tasks;
275 RasterTaskVector raster_tasks;
276 CreateImageDecodeTasks(num_image_decode_tasks, &image_decode_tasks);
277 CreateRasterTasks(num_raster_tasks, image_decode_tasks, &raster_tasks);
279 // Avoid unnecessary heap allocations by reusing the same queue.
280 RasterTaskQueue queue;
285 BuildRasterTaskQueue(&queue, raster_tasks);
286 raster_worker_pool_->AsRasterizer()->ScheduleTasks(&queue);
287 raster_worker_pool_->AsRasterizer()->CheckForCompletedTasks();
289 } while (!timer_.HasTimeLimitExpired());
291 RasterTaskQueue empty;
292 raster_worker_pool_->AsRasterizer()->ScheduleTasks(&empty);
293 RunMessageLoopUntilAllTasksHaveCompleted();
295 perf_test::PrintResult("schedule_tasks",
296 TestModifierString(),
298 timer_.LapsPerSecond(),
303 void RunScheduleAlternateTasksTest(const std::string& test_name,
304 unsigned num_raster_tasks,
305 unsigned num_image_decode_tasks) {
306 const size_t kNumVersions = 2;
307 ImageDecodeTask::Vector image_decode_tasks[kNumVersions];
308 RasterTaskVector raster_tasks[kNumVersions];
309 for (size_t i = 0; i < kNumVersions; ++i) {
310 CreateImageDecodeTasks(num_image_decode_tasks, &image_decode_tasks[i]);
312 num_raster_tasks, image_decode_tasks[i], &raster_tasks[i]);
315 // Avoid unnecessary heap allocations by reusing the same queue.
316 RasterTaskQueue queue;
322 BuildRasterTaskQueue(&queue, raster_tasks[count % kNumVersions]);
323 raster_worker_pool_->AsRasterizer()->ScheduleTasks(&queue);
324 raster_worker_pool_->AsRasterizer()->CheckForCompletedTasks();
327 } while (!timer_.HasTimeLimitExpired());
329 RasterTaskQueue empty;
330 raster_worker_pool_->AsRasterizer()->ScheduleTasks(&empty);
331 RunMessageLoopUntilAllTasksHaveCompleted();
333 perf_test::PrintResult("schedule_alternate_tasks",
334 TestModifierString(),
336 timer_.LapsPerSecond(),
341 void RunScheduleAndExecuteTasksTest(const std::string& test_name,
342 unsigned num_raster_tasks,
343 unsigned num_image_decode_tasks) {
344 ImageDecodeTask::Vector image_decode_tasks;
345 RasterTaskVector raster_tasks;
346 CreateImageDecodeTasks(num_image_decode_tasks, &image_decode_tasks);
347 CreateRasterTasks(num_raster_tasks, image_decode_tasks, &raster_tasks);
349 // Avoid unnecessary heap allocations by reusing the same queue.
350 RasterTaskQueue queue;
355 BuildRasterTaskQueue(&queue, raster_tasks);
356 raster_worker_pool_->AsRasterizer()->ScheduleTasks(&queue);
357 RunMessageLoopUntilAllTasksHaveCompleted();
359 } while (!timer_.HasTimeLimitExpired());
361 RasterTaskQueue empty;
362 raster_worker_pool_->AsRasterizer()->ScheduleTasks(&empty);
363 RunMessageLoopUntilAllTasksHaveCompleted();
365 perf_test::PrintResult("schedule_and_execute_tasks",
366 TestModifierString(),
368 timer_.LapsPerSecond(),
374 std::string TestModifierString() const {
375 switch (GetParam()) {
376 case RASTER_WORKER_POOL_TYPE_PIXEL_BUFFER:
377 return std::string("_pixel_raster_worker_pool");
378 case RASTER_WORKER_POOL_TYPE_IMAGE:
379 return std::string("_image_raster_worker_pool");
380 case RASTER_WORKER_POOL_TYPE_IMAGE_COPY:
381 return std::string("_image_copy_raster_worker_pool");
382 case RASTER_WORKER_POOL_TYPE_DIRECT:
383 return std::string("_direct_raster_worker_pool");
386 return std::string();
389 scoped_ptr<RasterWorkerPool> raster_worker_pool_;
392 TEST_P(RasterWorkerPoolPerfTest, ScheduleTasks) {
393 RunScheduleTasksTest("1_0", 1, 0);
394 RunScheduleTasksTest("32_0", 32, 0);
395 RunScheduleTasksTest("1_1", 1, 1);
396 RunScheduleTasksTest("32_1", 32, 1);
397 RunScheduleTasksTest("1_4", 1, 4);
398 RunScheduleTasksTest("32_4", 32, 4);
401 TEST_P(RasterWorkerPoolPerfTest, ScheduleAlternateTasks) {
402 RunScheduleAlternateTasksTest("1_0", 1, 0);
403 RunScheduleAlternateTasksTest("32_0", 32, 0);
404 RunScheduleAlternateTasksTest("1_1", 1, 1);
405 RunScheduleAlternateTasksTest("32_1", 32, 1);
406 RunScheduleAlternateTasksTest("1_4", 1, 4);
407 RunScheduleAlternateTasksTest("32_4", 32, 4);
410 TEST_P(RasterWorkerPoolPerfTest, ScheduleAndExecuteTasks) {
411 RunScheduleAndExecuteTasksTest("1_0", 1, 0);
412 RunScheduleAndExecuteTasksTest("32_0", 32, 0);
413 RunScheduleAndExecuteTasksTest("1_1", 1, 1);
414 RunScheduleAndExecuteTasksTest("32_1", 32, 1);
415 RunScheduleAndExecuteTasksTest("1_4", 1, 4);
416 RunScheduleAndExecuteTasksTest("32_4", 32, 4);
419 INSTANTIATE_TEST_CASE_P(RasterWorkerPoolPerfTests,
420 RasterWorkerPoolPerfTest,
421 ::testing::Values(RASTER_WORKER_POOL_TYPE_PIXEL_BUFFER,
422 RASTER_WORKER_POOL_TYPE_IMAGE,
423 RASTER_WORKER_POOL_TYPE_IMAGE_COPY,
424 RASTER_WORKER_POOL_TYPE_DIRECT));
426 class RasterWorkerPoolCommonPerfTest : public RasterWorkerPoolPerfTestBase,
427 public testing::Test {
429 void RunBuildRasterTaskQueueTest(const std::string& test_name,
430 unsigned num_raster_tasks,
431 unsigned num_image_decode_tasks) {
432 ImageDecodeTask::Vector image_decode_tasks;
433 RasterTaskVector raster_tasks;
434 CreateImageDecodeTasks(num_image_decode_tasks, &image_decode_tasks);
435 CreateRasterTasks(num_raster_tasks, image_decode_tasks, &raster_tasks);
437 // Avoid unnecessary heap allocations by reusing the same queue.
438 RasterTaskQueue queue;
443 BuildRasterTaskQueue(&queue, raster_tasks);
445 } while (!timer_.HasTimeLimitExpired());
447 perf_test::PrintResult("build_raster_task_queue",
450 timer_.LapsPerSecond(),
456 TEST_F(RasterWorkerPoolCommonPerfTest, BuildRasterTaskQueue) {
457 RunBuildRasterTaskQueueTest("1_0", 1, 0);
458 RunBuildRasterTaskQueueTest("32_0", 32, 0);
459 RunBuildRasterTaskQueueTest("1_1", 1, 1);
460 RunBuildRasterTaskQueueTest("32_1", 32, 1);
461 RunBuildRasterTaskQueueTest("1_4", 1, 4);
462 RunBuildRasterTaskQueueTest("32_4", 32, 4);