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/tile_task_worker_pool.h"
7 #include "base/test/test_simple_task_runner.h"
8 #include "base/time/time.h"
9 #include "cc/debug/lap_timer.h"
10 #include "cc/output/context_provider.h"
11 #include "cc/resources/bitmap_tile_task_worker_pool.h"
12 #include "cc/resources/gpu_rasterizer.h"
13 #include "cc/resources/gpu_tile_task_worker_pool.h"
14 #include "cc/resources/one_copy_tile_task_worker_pool.h"
15 #include "cc/resources/pixel_buffer_tile_task_worker_pool.h"
16 #include "cc/resources/raster_buffer.h"
17 #include "cc/resources/resource_pool.h"
18 #include "cc/resources/resource_provider.h"
19 #include "cc/resources/scoped_resource.h"
20 #include "cc/resources/tile_task_runner.h"
21 #include "cc/resources/zero_copy_tile_task_worker_pool.h"
22 #include "cc/test/fake_output_surface.h"
23 #include "cc/test/fake_output_surface_client.h"
24 #include "cc/test/test_context_support.h"
25 #include "cc/test/test_gpu_memory_buffer_manager.h"
26 #include "cc/test/test_shared_bitmap_manager.h"
27 #include "cc/test/test_web_graphics_context_3d.h"
28 #include "testing/gtest/include/gtest/gtest.h"
29 #include "testing/perf/perf_test.h"
30 #include "third_party/khronos/GLES2/gl2.h"
31 #include "third_party/skia/include/gpu/GrContext.h"
32 #include "third_party/skia/include/gpu/gl/GrGLInterface.h"
37 class PerfGLES2Interface
: public gpu::gles2::GLES2InterfaceStub
{
38 // Overridden from gpu::gles2::GLES2Interface:
39 GLuint
CreateImageCHROMIUM(ClientBuffer buffer
,
42 GLenum internalformat
) override
{
45 void GenBuffers(GLsizei n
, GLuint
* buffers
) override
{
46 for (GLsizei i
= 0; i
< n
; ++i
)
49 void GenTextures(GLsizei n
, GLuint
* textures
) override
{
50 for (GLsizei i
= 0; i
< n
; ++i
)
53 void GetIntegerv(GLenum pname
, GLint
* params
) override
{
54 if (pname
== GL_MAX_TEXTURE_SIZE
)
57 void GenQueriesEXT(GLsizei n
, GLuint
* queries
) override
{
58 for (GLsizei i
= 0; i
< n
; ++i
)
61 void GetQueryObjectuivEXT(GLuint query
,
63 GLuint
* params
) override
{
64 if (pname
== GL_QUERY_RESULT_AVAILABLE_EXT
)
69 class PerfContextProvider
: public ContextProvider
{
71 PerfContextProvider() : context_gl_(new PerfGLES2Interface
) {}
73 bool BindToCurrentThread() override
{ return true; }
74 Capabilities
ContextCapabilities() override
{
75 Capabilities capabilities
;
76 capabilities
.gpu
.image
= true;
77 capabilities
.gpu
.sync_query
= true;
80 gpu::gles2::GLES2Interface
* ContextGL() override
{ return context_gl_
.get(); }
81 gpu::ContextSupport
* ContextSupport() override
{ return &support_
; }
82 class GrContext
* GrContext() override
{
84 return gr_context_
.get();
86 skia::RefPtr
<const GrGLInterface
> null_interface
=
87 skia::AdoptRef(GrGLCreateNullInterface());
88 gr_context_
= skia::AdoptRef(GrContext::Create(
90 reinterpret_cast<GrBackendContext
>(null_interface
.get())));
91 return gr_context_
.get();
93 void SetupLock() override
{}
94 base::Lock
* GetLock() override
{ return &context_lock_
; }
95 bool IsContextLost() override
{ return false; }
96 void VerifyContexts() override
{}
97 void DeleteCachedResources() override
{}
98 bool DestroyedOnMainThread() override
{ return false; }
99 void SetLostContextCallback(const LostContextCallback
& cb
) override
{}
100 void SetMemoryPolicyChangedCallback(
101 const MemoryPolicyChangedCallback
& cb
) override
{}
104 ~PerfContextProvider() override
{}
106 scoped_ptr
<PerfGLES2Interface
> context_gl_
;
107 skia::RefPtr
<class GrContext
> gr_context_
;
108 TestContextSupport support_
;
109 base::Lock context_lock_
;
112 enum TileTaskWorkerPoolType
{
113 TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER
,
114 TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY
,
115 TILE_TASK_WORKER_POOL_TYPE_ONE_COPY
,
116 TILE_TASK_WORKER_POOL_TYPE_GPU
,
117 TILE_TASK_WORKER_POOL_TYPE_BITMAP
120 static const int kTimeLimitMillis
= 2000;
121 static const int kWarmupRuns
= 5;
122 static const int kTimeCheckInterval
= 10;
124 class PerfImageDecodeTaskImpl
: public ImageDecodeTask
{
126 PerfImageDecodeTaskImpl() {}
128 // Overridden from Task:
129 void RunOnWorkerThread() override
{}
131 // Overridden from TileTask:
132 void ScheduleOnOriginThread(TileTaskClient
* client
) override
{}
133 void CompleteOnOriginThread(TileTaskClient
* client
) override
{}
134 void RunReplyOnOriginThread() override
{ Reset(); }
138 did_complete_
= false;
142 ~PerfImageDecodeTaskImpl() override
{}
145 DISALLOW_COPY_AND_ASSIGN(PerfImageDecodeTaskImpl
);
148 class PerfRasterTaskImpl
: public RasterTask
{
150 PerfRasterTaskImpl(scoped_ptr
<ScopedResource
> resource
,
151 ImageDecodeTask::Vector
* dependencies
)
152 : RasterTask(resource
.get(), dependencies
), resource_(resource
.Pass()) {}
154 // Overridden from Task:
155 void RunOnWorkerThread() override
{}
157 // Overridden from TileTask:
158 void ScheduleOnOriginThread(TileTaskClient
* client
) override
{
159 raster_buffer_
= client
->AcquireBufferForRaster(resource());
161 void CompleteOnOriginThread(TileTaskClient
* client
) override
{
162 client
->ReleaseBufferForRaster(raster_buffer_
.Pass());
164 void RunReplyOnOriginThread() override
{ Reset(); }
168 did_complete_
= false;
172 ~PerfRasterTaskImpl() override
{}
175 scoped_ptr
<ScopedResource
> resource_
;
176 scoped_ptr
<RasterBuffer
> raster_buffer_
;
178 DISALLOW_COPY_AND_ASSIGN(PerfRasterTaskImpl
);
181 class TileTaskWorkerPoolPerfTestBase
{
183 typedef std::vector
<scoped_refptr
<RasterTask
>> RasterTaskVector
;
185 enum NamedTaskSet
{ REQUIRED_FOR_ACTIVATION
, REQUIRED_FOR_DRAW
, ALL
};
187 TileTaskWorkerPoolPerfTestBase()
188 : context_provider_(make_scoped_refptr(new PerfContextProvider
)),
189 task_runner_(new base::TestSimpleTaskRunner
),
190 task_graph_runner_(new TaskGraphRunner
),
192 base::TimeDelta::FromMilliseconds(kTimeLimitMillis
),
193 kTimeCheckInterval
) {}
195 void CreateImageDecodeTasks(unsigned num_image_decode_tasks
,
196 ImageDecodeTask::Vector
* image_decode_tasks
) {
197 for (unsigned i
= 0; i
< num_image_decode_tasks
; ++i
)
198 image_decode_tasks
->push_back(new PerfImageDecodeTaskImpl
);
201 void CreateRasterTasks(unsigned num_raster_tasks
,
202 const ImageDecodeTask::Vector
& image_decode_tasks
,
203 RasterTaskVector
* raster_tasks
) {
204 const gfx::Size
size(1, 1);
206 for (unsigned i
= 0; i
< num_raster_tasks
; ++i
) {
207 scoped_ptr
<ScopedResource
> resource(
208 ScopedResource::Create(resource_provider_
.get()));
209 resource
->Allocate(size
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
212 ImageDecodeTask::Vector dependencies
= image_decode_tasks
;
213 raster_tasks
->push_back(
214 new PerfRasterTaskImpl(resource
.Pass(), &dependencies
));
218 void BuildTileTaskQueue(TileTaskQueue
* queue
,
219 const RasterTaskVector
& raster_tasks
) {
220 for (size_t i
= 0u; i
< raster_tasks
.size(); ++i
) {
221 bool required_for_activation
= (i
% 2) == 0;
222 TaskSetCollection task_set_collection
;
223 task_set_collection
[ALL
] = true;
224 task_set_collection
[REQUIRED_FOR_ACTIVATION
] = required_for_activation
;
225 queue
->items
.push_back(
226 TileTaskQueue::Item(raster_tasks
[i
].get(), task_set_collection
));
231 scoped_refptr
<ContextProvider
> context_provider_
;
232 FakeOutputSurfaceClient output_surface_client_
;
233 scoped_ptr
<FakeOutputSurface
> output_surface_
;
234 scoped_ptr
<ResourceProvider
> resource_provider_
;
235 scoped_ptr
<Rasterizer
> rasterizer_
;
236 scoped_refptr
<base::TestSimpleTaskRunner
> task_runner_
;
237 scoped_ptr
<TaskGraphRunner
> task_graph_runner_
;
241 class TileTaskWorkerPoolPerfTest
242 : public TileTaskWorkerPoolPerfTestBase
,
243 public testing::TestWithParam
<TileTaskWorkerPoolType
>,
244 public TileTaskRunnerClient
{
246 // Overridden from testing::Test:
247 void SetUp() override
{
248 switch (GetParam()) {
249 case TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER
:
250 Create3dOutputSurfaceAndResourceProvider();
251 tile_task_worker_pool_
= PixelBufferTileTaskWorkerPool::Create(
252 task_runner_
.get(), task_graph_runner_
.get(),
253 context_provider_
.get(), resource_provider_
.get(),
254 std::numeric_limits
<size_t>::max());
256 case TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY
:
257 Create3dOutputSurfaceAndResourceProvider();
258 tile_task_worker_pool_
= ZeroCopyTileTaskWorkerPool::Create(
259 task_runner_
.get(), task_graph_runner_
.get(),
260 resource_provider_
.get());
262 case TILE_TASK_WORKER_POOL_TYPE_ONE_COPY
:
263 Create3dOutputSurfaceAndResourceProvider();
264 staging_resource_pool_
= ResourcePool::Create(resource_provider_
.get(),
266 tile_task_worker_pool_
= OneCopyTileTaskWorkerPool::Create(
267 task_runner_
.get(), task_graph_runner_
.get(),
268 context_provider_
.get(), resource_provider_
.get(),
269 staging_resource_pool_
.get());
271 case TILE_TASK_WORKER_POOL_TYPE_GPU
:
272 Create3dOutputSurfaceAndResourceProvider();
273 rasterizer_
= GpuRasterizer::Create(
274 context_provider_
.get(), resource_provider_
.get(), false, false, 0);
275 tile_task_worker_pool_
= GpuTileTaskWorkerPool::Create(
276 task_runner_
.get(), task_graph_runner_
.get(),
277 static_cast<GpuRasterizer
*>(rasterizer_
.get()));
279 case TILE_TASK_WORKER_POOL_TYPE_BITMAP
:
280 CreateSoftwareOutputSurfaceAndResourceProvider();
281 tile_task_worker_pool_
= BitmapTileTaskWorkerPool::Create(
282 task_runner_
.get(), task_graph_runner_
.get(),
283 resource_provider_
.get());
287 DCHECK(tile_task_worker_pool_
);
288 tile_task_worker_pool_
->AsTileTaskRunner()->SetClient(this);
290 void TearDown() override
{
291 tile_task_worker_pool_
->AsTileTaskRunner()->Shutdown();
292 tile_task_worker_pool_
->AsTileTaskRunner()->CheckForCompletedTasks();
295 // Overriden from TileTaskRunnerClient:
296 void DidFinishRunningTileTasks(TaskSet task_set
) override
{
297 tile_task_worker_pool_
->AsTileTaskRunner()->CheckForCompletedTasks();
299 TaskSetCollection
TasksThatShouldBeForcedToComplete() const override
{
300 return TaskSetCollection();
303 void RunMessageLoopUntilAllTasksHaveCompleted() {
304 task_graph_runner_
->RunUntilIdle();
305 task_runner_
->RunUntilIdle();
308 void RunScheduleTasksTest(const std::string
& test_name
,
309 unsigned num_raster_tasks
,
310 unsigned num_image_decode_tasks
) {
311 ImageDecodeTask::Vector image_decode_tasks
;
312 RasterTaskVector raster_tasks
;
313 CreateImageDecodeTasks(num_image_decode_tasks
, &image_decode_tasks
);
314 CreateRasterTasks(num_raster_tasks
, image_decode_tasks
, &raster_tasks
);
316 // Avoid unnecessary heap allocations by reusing the same queue.
322 BuildTileTaskQueue(&queue
, raster_tasks
);
323 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&queue
);
324 tile_task_worker_pool_
->AsTileTaskRunner()->CheckForCompletedTasks();
326 } while (!timer_
.HasTimeLimitExpired());
329 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&empty
);
330 RunMessageLoopUntilAllTasksHaveCompleted();
332 perf_test::PrintResult("schedule_tasks", TestModifierString(), test_name
,
333 timer_
.LapsPerSecond(), "runs/s", true);
336 void RunScheduleAlternateTasksTest(const std::string
& test_name
,
337 unsigned num_raster_tasks
,
338 unsigned num_image_decode_tasks
) {
339 const size_t kNumVersions
= 2;
340 ImageDecodeTask::Vector image_decode_tasks
[kNumVersions
];
341 RasterTaskVector raster_tasks
[kNumVersions
];
342 for (size_t i
= 0; i
< kNumVersions
; ++i
) {
343 CreateImageDecodeTasks(num_image_decode_tasks
, &image_decode_tasks
[i
]);
344 CreateRasterTasks(num_raster_tasks
, image_decode_tasks
[i
],
348 // Avoid unnecessary heap allocations by reusing the same queue.
355 BuildTileTaskQueue(&queue
, raster_tasks
[count
% kNumVersions
]);
356 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&queue
);
357 tile_task_worker_pool_
->AsTileTaskRunner()->CheckForCompletedTasks();
360 } while (!timer_
.HasTimeLimitExpired());
363 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&empty
);
364 RunMessageLoopUntilAllTasksHaveCompleted();
366 perf_test::PrintResult("schedule_alternate_tasks", TestModifierString(),
367 test_name
, timer_
.LapsPerSecond(), "runs/s", true);
370 void RunScheduleAndExecuteTasksTest(const std::string
& test_name
,
371 unsigned num_raster_tasks
,
372 unsigned num_image_decode_tasks
) {
373 ImageDecodeTask::Vector image_decode_tasks
;
374 RasterTaskVector raster_tasks
;
375 CreateImageDecodeTasks(num_image_decode_tasks
, &image_decode_tasks
);
376 CreateRasterTasks(num_raster_tasks
, image_decode_tasks
, &raster_tasks
);
378 // Avoid unnecessary heap allocations by reusing the same queue.
384 BuildTileTaskQueue(&queue
, raster_tasks
);
385 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&queue
);
386 RunMessageLoopUntilAllTasksHaveCompleted();
388 } while (!timer_
.HasTimeLimitExpired());
391 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&empty
);
392 RunMessageLoopUntilAllTasksHaveCompleted();
394 perf_test::PrintResult("schedule_and_execute_tasks", TestModifierString(),
395 test_name
, timer_
.LapsPerSecond(), "runs/s", true);
399 void Create3dOutputSurfaceAndResourceProvider() {
400 output_surface_
= FakeOutputSurface::Create3d(context_provider_
).Pass();
401 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
402 resource_provider_
= ResourceProvider::Create(output_surface_
.get(), NULL
,
403 &gpu_memory_buffer_manager_
,
404 NULL
, 0, false, 1).Pass();
407 void CreateSoftwareOutputSurfaceAndResourceProvider() {
408 output_surface_
= FakeOutputSurface::CreateSoftware(
409 make_scoped_ptr(new SoftwareOutputDevice
));
410 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
412 ResourceProvider::Create(output_surface_
.get(), &shared_bitmap_manager_
,
413 NULL
, NULL
, 0, false, 1).Pass();
416 std::string
TestModifierString() const {
417 switch (GetParam()) {
418 case TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER
:
419 return std::string("_pixel_tile_task_worker_pool");
420 case TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY
:
421 return std::string("_zero_copy_tile_task_worker_pool");
422 case TILE_TASK_WORKER_POOL_TYPE_ONE_COPY
:
423 return std::string("_one_copy_tile_task_worker_pool");
424 case TILE_TASK_WORKER_POOL_TYPE_GPU
:
425 return std::string("_gpu_tile_task_worker_pool");
426 case TILE_TASK_WORKER_POOL_TYPE_BITMAP
:
427 return std::string("_bitmap_tile_task_worker_pool");
430 return std::string();
433 scoped_ptr
<ResourcePool
> staging_resource_pool_
;
434 scoped_ptr
<TileTaskWorkerPool
> tile_task_worker_pool_
;
435 TestGpuMemoryBufferManager gpu_memory_buffer_manager_
;
436 TestSharedBitmapManager shared_bitmap_manager_
;
439 TEST_P(TileTaskWorkerPoolPerfTest
, ScheduleTasks
) {
440 RunScheduleTasksTest("1_0", 1, 0);
441 RunScheduleTasksTest("32_0", 32, 0);
442 RunScheduleTasksTest("1_1", 1, 1);
443 RunScheduleTasksTest("32_1", 32, 1);
444 RunScheduleTasksTest("1_4", 1, 4);
445 RunScheduleTasksTest("32_4", 32, 4);
448 TEST_P(TileTaskWorkerPoolPerfTest
, ScheduleAlternateTasks
) {
449 RunScheduleAlternateTasksTest("1_0", 1, 0);
450 RunScheduleAlternateTasksTest("32_0", 32, 0);
451 RunScheduleAlternateTasksTest("1_1", 1, 1);
452 RunScheduleAlternateTasksTest("32_1", 32, 1);
453 RunScheduleAlternateTasksTest("1_4", 1, 4);
454 RunScheduleAlternateTasksTest("32_4", 32, 4);
457 TEST_P(TileTaskWorkerPoolPerfTest
, ScheduleAndExecuteTasks
) {
458 RunScheduleAndExecuteTasksTest("1_0", 1, 0);
459 RunScheduleAndExecuteTasksTest("32_0", 32, 0);
460 RunScheduleAndExecuteTasksTest("1_1", 1, 1);
461 RunScheduleAndExecuteTasksTest("32_1", 32, 1);
462 RunScheduleAndExecuteTasksTest("1_4", 1, 4);
463 RunScheduleAndExecuteTasksTest("32_4", 32, 4);
466 INSTANTIATE_TEST_CASE_P(
467 TileTaskWorkerPoolPerfTests
,
468 TileTaskWorkerPoolPerfTest
,
469 ::testing::Values(TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER
,
470 TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY
,
471 TILE_TASK_WORKER_POOL_TYPE_ONE_COPY
,
472 TILE_TASK_WORKER_POOL_TYPE_GPU
,
473 TILE_TASK_WORKER_POOL_TYPE_BITMAP
));
475 class TileTaskWorkerPoolCommonPerfTest
: public TileTaskWorkerPoolPerfTestBase
,
476 public testing::Test
{
478 // Overridden from testing::Test:
479 void SetUp() override
{
480 output_surface_
= FakeOutputSurface::Create3d(context_provider_
).Pass();
481 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
483 ResourceProvider::Create(output_surface_
.get(), NULL
, NULL
, NULL
, 0,
487 void RunBuildTileTaskQueueTest(const std::string
& test_name
,
488 unsigned num_raster_tasks
,
489 unsigned num_image_decode_tasks
) {
490 ImageDecodeTask::Vector image_decode_tasks
;
491 RasterTaskVector raster_tasks
;
492 CreateImageDecodeTasks(num_image_decode_tasks
, &image_decode_tasks
);
493 CreateRasterTasks(num_raster_tasks
, image_decode_tasks
, &raster_tasks
);
495 // Avoid unnecessary heap allocations by reusing the same queue.
501 BuildTileTaskQueue(&queue
, raster_tasks
);
503 } while (!timer_
.HasTimeLimitExpired());
505 perf_test::PrintResult("build_raster_task_queue", "", test_name
,
506 timer_
.LapsPerSecond(), "runs/s", true);
510 TEST_F(TileTaskWorkerPoolCommonPerfTest
, BuildTileTaskQueue
) {
511 RunBuildTileTaskQueueTest("1_0", 1, 0);
512 RunBuildTileTaskQueueTest("32_0", 32, 0);
513 RunBuildTileTaskQueueTest("1_1", 1, 1);
514 RunBuildTileTaskQueueTest("32_1", 32, 1);
515 RunBuildTileTaskQueueTest("1_4", 1, 4);
516 RunBuildTileTaskQueueTest("32_4", 32, 4);