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
) OVERRIDE
{
37 virtual void GenBuffers(GLsizei n
, GLuint
* buffers
) OVERRIDE
{
38 for (GLsizei i
= 0; i
< n
; ++i
)
41 virtual void GenTextures(GLsizei n
, GLuint
* textures
) OVERRIDE
{
42 for (GLsizei i
= 0; i
< n
; ++i
)
45 virtual void GetIntegerv(GLenum pname
, GLint
* params
) OVERRIDE
{
46 if (pname
== GL_MAX_TEXTURE_SIZE
)
51 class PerfContextProvider
: public ContextProvider
{
53 PerfContextProvider() : context_gl_(new PerfGLES2Interface
) {}
55 virtual bool BindToCurrentThread() OVERRIDE
{ return true; }
56 virtual Capabilities
ContextCapabilities() OVERRIDE
{ return Capabilities(); }
57 virtual gpu::gles2::GLES2Interface
* ContextGL() OVERRIDE
{
58 return context_gl_
.get();
60 virtual gpu::ContextSupport
* ContextSupport() OVERRIDE
{ return &support_
; }
61 virtual class GrContext
* GrContext() OVERRIDE
{ return NULL
; }
62 virtual bool IsContextLost() OVERRIDE
{ return false; }
63 virtual void VerifyContexts() OVERRIDE
{}
64 virtual void DeleteCachedResources() OVERRIDE
{}
65 virtual bool DestroyedOnMainThread() OVERRIDE
{ return false; }
66 virtual void SetLostContextCallback(const LostContextCallback
& cb
) OVERRIDE
{}
67 virtual void SetMemoryPolicyChangedCallback(
68 const MemoryPolicyChangedCallback
& cb
) OVERRIDE
{}
71 virtual ~PerfContextProvider() {}
73 scoped_ptr
<PerfGLES2Interface
> context_gl_
;
74 TestContextSupport support_
;
77 enum RasterWorkerPoolType
{
78 RASTER_WORKER_POOL_TYPE_PIXEL_BUFFER
,
79 RASTER_WORKER_POOL_TYPE_IMAGE
,
80 RASTER_WORKER_POOL_TYPE_IMAGE_COPY
,
81 RASTER_WORKER_POOL_TYPE_DIRECT
84 static const int kTimeLimitMillis
= 2000;
85 static const int kWarmupRuns
= 5;
86 static const int kTimeCheckInterval
= 10;
88 class PerfImageDecodeTaskImpl
: public ImageDecodeTask
{
90 PerfImageDecodeTaskImpl() {}
92 // Overridden from Task:
93 virtual void RunOnWorkerThread() OVERRIDE
{}
95 // Overridden from RasterizerTask:
96 virtual void ScheduleOnOriginThread(RasterizerTaskClient
* client
) OVERRIDE
{}
97 virtual void CompleteOnOriginThread(RasterizerTaskClient
* client
) OVERRIDE
{}
98 virtual void RunReplyOnOriginThread() OVERRIDE
{ Reset(); }
102 did_complete_
= false;
106 virtual ~PerfImageDecodeTaskImpl() {}
109 DISALLOW_COPY_AND_ASSIGN(PerfImageDecodeTaskImpl
);
112 class PerfRasterTaskImpl
: public RasterTask
{
114 PerfRasterTaskImpl(scoped_ptr
<ScopedResource
> resource
,
115 ImageDecodeTask::Vector
* dependencies
)
116 : RasterTask(resource
.get(), dependencies
), resource_(resource
.Pass()) {}
118 // Overridden from Task:
119 virtual void RunOnWorkerThread() OVERRIDE
{}
121 // Overridden from RasterizerTask:
122 virtual void ScheduleOnOriginThread(RasterizerTaskClient
* client
) OVERRIDE
{
123 client
->AcquireCanvasForRaster(this);
125 virtual void CompleteOnOriginThread(RasterizerTaskClient
* client
) OVERRIDE
{
126 client
->ReleaseCanvasForRaster(this);
128 virtual void RunReplyOnOriginThread() OVERRIDE
{ Reset(); }
132 did_complete_
= false;
136 virtual ~PerfRasterTaskImpl() {}
139 scoped_ptr
<ScopedResource
> resource_
;
141 DISALLOW_COPY_AND_ASSIGN(PerfRasterTaskImpl
);
144 class RasterWorkerPoolPerfTestBase
{
146 typedef std::vector
<scoped_refptr
<RasterTask
> > RasterTaskVector
;
148 RasterWorkerPoolPerfTestBase()
149 : context_provider_(make_scoped_refptr(new PerfContextProvider
)),
150 task_graph_runner_(new TaskGraphRunner
),
152 base::TimeDelta::FromMilliseconds(kTimeLimitMillis
),
153 kTimeCheckInterval
) {
154 output_surface_
= FakeOutputSurface::Create3d(context_provider_
).Pass();
155 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
157 shared_bitmap_manager_
.reset(new TestSharedBitmapManager());
159 ResourceProvider::Create(
160 output_surface_
.get(), shared_bitmap_manager_
.get(), 0, false, 1)
162 staging_resource_pool_
= ResourcePool::Create(
163 resource_provider_
.get(), GL_TEXTURE_2D
, RGBA_8888
);
166 void CreateImageDecodeTasks(unsigned num_image_decode_tasks
,
167 ImageDecodeTask::Vector
* image_decode_tasks
) {
168 for (unsigned i
= 0; i
< num_image_decode_tasks
; ++i
)
169 image_decode_tasks
->push_back(new PerfImageDecodeTaskImpl
);
172 void CreateRasterTasks(unsigned num_raster_tasks
,
173 const ImageDecodeTask::Vector
& image_decode_tasks
,
174 RasterTaskVector
* raster_tasks
) {
175 const gfx::Size
size(1, 1);
177 for (unsigned i
= 0; i
< num_raster_tasks
; ++i
) {
178 scoped_ptr
<ScopedResource
> resource(
179 ScopedResource::Create(resource_provider_
.get()));
180 resource
->Allocate(size
, ResourceProvider::TextureUsageAny
, RGBA_8888
);
182 ImageDecodeTask::Vector dependencies
= image_decode_tasks
;
183 raster_tasks
->push_back(
184 new PerfRasterTaskImpl(resource
.Pass(), &dependencies
));
188 void BuildRasterTaskQueue(RasterTaskQueue
* queue
,
189 const RasterTaskVector
& raster_tasks
) {
190 for (size_t i
= 0u; i
< raster_tasks
.size(); ++i
) {
191 bool required_for_activation
= (i
% 2) == 0;
192 queue
->items
.push_back(RasterTaskQueue::Item(raster_tasks
[i
].get(),
193 required_for_activation
));
194 queue
->required_for_activation_count
+= required_for_activation
;
199 scoped_refptr
<ContextProvider
> context_provider_
;
200 FakeOutputSurfaceClient output_surface_client_
;
201 scoped_ptr
<FakeOutputSurface
> output_surface_
;
202 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager_
;
203 scoped_ptr
<ResourceProvider
> resource_provider_
;
204 scoped_ptr
<ResourcePool
> staging_resource_pool_
;
205 scoped_ptr
<TaskGraphRunner
> task_graph_runner_
;
209 class RasterWorkerPoolPerfTest
210 : public RasterWorkerPoolPerfTestBase
,
211 public testing::TestWithParam
<RasterWorkerPoolType
>,
212 public RasterizerClient
{
214 RasterWorkerPoolPerfTest() {
215 switch (GetParam()) {
216 case RASTER_WORKER_POOL_TYPE_PIXEL_BUFFER
:
217 raster_worker_pool_
= PixelBufferRasterWorkerPool::Create(
218 base::MessageLoopProxy::current().get(),
219 task_graph_runner_
.get(),
220 resource_provider_
.get(),
221 std::numeric_limits
<size_t>::max());
223 case RASTER_WORKER_POOL_TYPE_IMAGE
:
224 raster_worker_pool_
= ImageRasterWorkerPool::Create(
225 base::MessageLoopProxy::current().get(),
226 task_graph_runner_
.get(),
227 resource_provider_
.get());
229 case RASTER_WORKER_POOL_TYPE_IMAGE_COPY
:
230 raster_worker_pool_
= ImageCopyRasterWorkerPool::Create(
231 base::MessageLoopProxy::current().get(),
232 task_graph_runner_
.get(),
233 resource_provider_
.get(),
234 staging_resource_pool_
.get());
236 case RASTER_WORKER_POOL_TYPE_DIRECT
:
237 raster_worker_pool_
= DirectRasterWorkerPool::Create(
238 base::MessageLoopProxy::current().get(),
239 resource_provider_
.get(),
240 context_provider_
.get());
244 DCHECK(raster_worker_pool_
);
245 raster_worker_pool_
->AsRasterizer()->SetClient(this);
248 // Overridden from testing::Test:
249 virtual void TearDown() OVERRIDE
{
250 raster_worker_pool_
->AsRasterizer()->Shutdown();
251 raster_worker_pool_
->AsRasterizer()->CheckForCompletedTasks();
254 // Overriden from RasterizerClient:
255 virtual bool ShouldForceTasksRequiredForActivationToComplete() const
259 virtual void DidFinishRunningTasks() OVERRIDE
{
260 raster_worker_pool_
->AsRasterizer()->CheckForCompletedTasks();
261 base::MessageLoop::current()->Quit();
263 virtual void DidFinishRunningTasksRequiredForActivation() OVERRIDE
{}
265 void RunMessageLoopUntilAllTasksHaveCompleted() {
266 task_graph_runner_
->RunUntilIdle();
267 base::MessageLoop::current()->Run();
270 void RunScheduleTasksTest(const std::string
& test_name
,
271 unsigned num_raster_tasks
,
272 unsigned num_image_decode_tasks
) {
273 ImageDecodeTask::Vector image_decode_tasks
;
274 RasterTaskVector raster_tasks
;
275 CreateImageDecodeTasks(num_image_decode_tasks
, &image_decode_tasks
);
276 CreateRasterTasks(num_raster_tasks
, image_decode_tasks
, &raster_tasks
);
278 // Avoid unnecessary heap allocations by reusing the same queue.
279 RasterTaskQueue queue
;
284 BuildRasterTaskQueue(&queue
, raster_tasks
);
285 raster_worker_pool_
->AsRasterizer()->ScheduleTasks(&queue
);
286 raster_worker_pool_
->AsRasterizer()->CheckForCompletedTasks();
288 } while (!timer_
.HasTimeLimitExpired());
290 RasterTaskQueue empty
;
291 raster_worker_pool_
->AsRasterizer()->ScheduleTasks(&empty
);
292 RunMessageLoopUntilAllTasksHaveCompleted();
294 perf_test::PrintResult("schedule_tasks",
295 TestModifierString(),
297 timer_
.LapsPerSecond(),
302 void RunScheduleAlternateTasksTest(const std::string
& test_name
,
303 unsigned num_raster_tasks
,
304 unsigned num_image_decode_tasks
) {
305 const size_t kNumVersions
= 2;
306 ImageDecodeTask::Vector image_decode_tasks
[kNumVersions
];
307 RasterTaskVector raster_tasks
[kNumVersions
];
308 for (size_t i
= 0; i
< kNumVersions
; ++i
) {
309 CreateImageDecodeTasks(num_image_decode_tasks
, &image_decode_tasks
[i
]);
311 num_raster_tasks
, image_decode_tasks
[i
], &raster_tasks
[i
]);
314 // Avoid unnecessary heap allocations by reusing the same queue.
315 RasterTaskQueue queue
;
321 BuildRasterTaskQueue(&queue
, raster_tasks
[count
% kNumVersions
]);
322 raster_worker_pool_
->AsRasterizer()->ScheduleTasks(&queue
);
323 raster_worker_pool_
->AsRasterizer()->CheckForCompletedTasks();
326 } while (!timer_
.HasTimeLimitExpired());
328 RasterTaskQueue empty
;
329 raster_worker_pool_
->AsRasterizer()->ScheduleTasks(&empty
);
330 RunMessageLoopUntilAllTasksHaveCompleted();
332 perf_test::PrintResult("schedule_alternate_tasks",
333 TestModifierString(),
335 timer_
.LapsPerSecond(),
340 void RunScheduleAndExecuteTasksTest(const std::string
& test_name
,
341 unsigned num_raster_tasks
,
342 unsigned num_image_decode_tasks
) {
343 ImageDecodeTask::Vector image_decode_tasks
;
344 RasterTaskVector raster_tasks
;
345 CreateImageDecodeTasks(num_image_decode_tasks
, &image_decode_tasks
);
346 CreateRasterTasks(num_raster_tasks
, image_decode_tasks
, &raster_tasks
);
348 // Avoid unnecessary heap allocations by reusing the same queue.
349 RasterTaskQueue queue
;
354 BuildRasterTaskQueue(&queue
, raster_tasks
);
355 raster_worker_pool_
->AsRasterizer()->ScheduleTasks(&queue
);
356 RunMessageLoopUntilAllTasksHaveCompleted();
358 } while (!timer_
.HasTimeLimitExpired());
360 RasterTaskQueue empty
;
361 raster_worker_pool_
->AsRasterizer()->ScheduleTasks(&empty
);
362 RunMessageLoopUntilAllTasksHaveCompleted();
364 perf_test::PrintResult("schedule_and_execute_tasks",
365 TestModifierString(),
367 timer_
.LapsPerSecond(),
373 std::string
TestModifierString() const {
374 switch (GetParam()) {
375 case RASTER_WORKER_POOL_TYPE_PIXEL_BUFFER
:
376 return std::string("_pixel_raster_worker_pool");
377 case RASTER_WORKER_POOL_TYPE_IMAGE
:
378 return std::string("_image_raster_worker_pool");
379 case RASTER_WORKER_POOL_TYPE_IMAGE_COPY
:
380 return std::string("_image_copy_raster_worker_pool");
381 case RASTER_WORKER_POOL_TYPE_DIRECT
:
382 return std::string("_direct_raster_worker_pool");
385 return std::string();
388 scoped_ptr
<RasterWorkerPool
> raster_worker_pool_
;
391 TEST_P(RasterWorkerPoolPerfTest
, ScheduleTasks
) {
392 RunScheduleTasksTest("1_0", 1, 0);
393 RunScheduleTasksTest("32_0", 32, 0);
394 RunScheduleTasksTest("1_1", 1, 1);
395 RunScheduleTasksTest("32_1", 32, 1);
396 RunScheduleTasksTest("1_4", 1, 4);
397 RunScheduleTasksTest("32_4", 32, 4);
400 TEST_P(RasterWorkerPoolPerfTest
, ScheduleAlternateTasks
) {
401 RunScheduleAlternateTasksTest("1_0", 1, 0);
402 RunScheduleAlternateTasksTest("32_0", 32, 0);
403 RunScheduleAlternateTasksTest("1_1", 1, 1);
404 RunScheduleAlternateTasksTest("32_1", 32, 1);
405 RunScheduleAlternateTasksTest("1_4", 1, 4);
406 RunScheduleAlternateTasksTest("32_4", 32, 4);
409 TEST_P(RasterWorkerPoolPerfTest
, ScheduleAndExecuteTasks
) {
410 RunScheduleAndExecuteTasksTest("1_0", 1, 0);
411 RunScheduleAndExecuteTasksTest("32_0", 32, 0);
412 RunScheduleAndExecuteTasksTest("1_1", 1, 1);
413 RunScheduleAndExecuteTasksTest("32_1", 32, 1);
414 RunScheduleAndExecuteTasksTest("1_4", 1, 4);
415 RunScheduleAndExecuteTasksTest("32_4", 32, 4);
418 INSTANTIATE_TEST_CASE_P(RasterWorkerPoolPerfTests
,
419 RasterWorkerPoolPerfTest
,
420 ::testing::Values(RASTER_WORKER_POOL_TYPE_PIXEL_BUFFER
,
421 RASTER_WORKER_POOL_TYPE_IMAGE
,
422 RASTER_WORKER_POOL_TYPE_IMAGE_COPY
,
423 RASTER_WORKER_POOL_TYPE_DIRECT
));
425 class RasterWorkerPoolCommonPerfTest
: public RasterWorkerPoolPerfTestBase
,
426 public testing::Test
{
428 void RunBuildRasterTaskQueueTest(const std::string
& test_name
,
429 unsigned num_raster_tasks
,
430 unsigned num_image_decode_tasks
) {
431 ImageDecodeTask::Vector image_decode_tasks
;
432 RasterTaskVector raster_tasks
;
433 CreateImageDecodeTasks(num_image_decode_tasks
, &image_decode_tasks
);
434 CreateRasterTasks(num_raster_tasks
, image_decode_tasks
, &raster_tasks
);
436 // Avoid unnecessary heap allocations by reusing the same queue.
437 RasterTaskQueue queue
;
442 BuildRasterTaskQueue(&queue
, raster_tasks
);
444 } while (!timer_
.HasTimeLimitExpired());
446 perf_test::PrintResult("build_raster_task_queue",
449 timer_
.LapsPerSecond(),
455 TEST_F(RasterWorkerPoolCommonPerfTest
, BuildRasterTaskQueue
) {
456 RunBuildRasterTaskQueueTest("1_0", 1, 0);
457 RunBuildRasterTaskQueueTest("32_0", 32, 0);
458 RunBuildRasterTaskQueueTest("1_1", 1, 1);
459 RunBuildRasterTaskQueueTest("32_1", 32, 1);
460 RunBuildRasterTaskQueueTest("1_4", 1, 4);
461 RunBuildRasterTaskQueueTest("32_4", 32, 4);