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_refptr
<base::TestSimpleTaskRunner
> task_runner_
;
236 scoped_ptr
<TaskGraphRunner
> task_graph_runner_
;
240 class TileTaskWorkerPoolPerfTest
241 : public TileTaskWorkerPoolPerfTestBase
,
242 public testing::TestWithParam
<TileTaskWorkerPoolType
>,
243 public TileTaskRunnerClient
{
245 // Overridden from testing::Test:
246 void SetUp() override
{
247 switch (GetParam()) {
248 case TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER
:
249 Create3dOutputSurfaceAndResourceProvider();
250 tile_task_worker_pool_
= PixelBufferTileTaskWorkerPool::Create(
251 task_runner_
.get(), task_graph_runner_
.get(),
252 context_provider_
.get(), resource_provider_
.get(),
253 std::numeric_limits
<size_t>::max());
255 case TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY
:
256 Create3dOutputSurfaceAndResourceProvider();
257 tile_task_worker_pool_
= ZeroCopyTileTaskWorkerPool::Create(
258 task_runner_
.get(), task_graph_runner_
.get(),
259 resource_provider_
.get());
261 case TILE_TASK_WORKER_POOL_TYPE_ONE_COPY
:
262 Create3dOutputSurfaceAndResourceProvider();
263 staging_resource_pool_
= ResourcePool::Create(resource_provider_
.get(),
265 tile_task_worker_pool_
= OneCopyTileTaskWorkerPool::Create(
266 task_runner_
.get(), task_graph_runner_
.get(),
267 context_provider_
.get(), resource_provider_
.get(),
268 staging_resource_pool_
.get());
270 case TILE_TASK_WORKER_POOL_TYPE_GPU
:
271 Create3dOutputSurfaceAndResourceProvider();
272 tile_task_worker_pool_
= GpuTileTaskWorkerPool::Create(
273 task_runner_
.get(), task_graph_runner_
.get(),
274 context_provider_
.get(), resource_provider_
.get(), false, 0);
276 case TILE_TASK_WORKER_POOL_TYPE_BITMAP
:
277 CreateSoftwareOutputSurfaceAndResourceProvider();
278 tile_task_worker_pool_
= BitmapTileTaskWorkerPool::Create(
279 task_runner_
.get(), task_graph_runner_
.get(),
280 resource_provider_
.get());
284 DCHECK(tile_task_worker_pool_
);
285 tile_task_worker_pool_
->AsTileTaskRunner()->SetClient(this);
287 void TearDown() override
{
288 tile_task_worker_pool_
->AsTileTaskRunner()->Shutdown();
289 tile_task_worker_pool_
->AsTileTaskRunner()->CheckForCompletedTasks();
292 // Overriden from TileTaskRunnerClient:
293 void DidFinishRunningTileTasks(TaskSet task_set
) override
{
294 tile_task_worker_pool_
->AsTileTaskRunner()->CheckForCompletedTasks();
296 TaskSetCollection
TasksThatShouldBeForcedToComplete() const override
{
297 return TaskSetCollection();
300 void RunMessageLoopUntilAllTasksHaveCompleted() {
301 task_graph_runner_
->RunUntilIdle();
302 task_runner_
->RunUntilIdle();
305 void RunScheduleTasksTest(const std::string
& test_name
,
306 unsigned num_raster_tasks
,
307 unsigned num_image_decode_tasks
) {
308 ImageDecodeTask::Vector image_decode_tasks
;
309 RasterTaskVector raster_tasks
;
310 CreateImageDecodeTasks(num_image_decode_tasks
, &image_decode_tasks
);
311 CreateRasterTasks(num_raster_tasks
, image_decode_tasks
, &raster_tasks
);
313 // Avoid unnecessary heap allocations by reusing the same queue.
319 BuildTileTaskQueue(&queue
, raster_tasks
);
320 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&queue
);
321 tile_task_worker_pool_
->AsTileTaskRunner()->CheckForCompletedTasks();
323 } while (!timer_
.HasTimeLimitExpired());
326 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&empty
);
327 RunMessageLoopUntilAllTasksHaveCompleted();
329 perf_test::PrintResult("schedule_tasks", TestModifierString(), test_name
,
330 timer_
.LapsPerSecond(), "runs/s", true);
333 void RunScheduleAlternateTasksTest(const std::string
& test_name
,
334 unsigned num_raster_tasks
,
335 unsigned num_image_decode_tasks
) {
336 const size_t kNumVersions
= 2;
337 ImageDecodeTask::Vector image_decode_tasks
[kNumVersions
];
338 RasterTaskVector raster_tasks
[kNumVersions
];
339 for (size_t i
= 0; i
< kNumVersions
; ++i
) {
340 CreateImageDecodeTasks(num_image_decode_tasks
, &image_decode_tasks
[i
]);
341 CreateRasterTasks(num_raster_tasks
, image_decode_tasks
[i
],
345 // Avoid unnecessary heap allocations by reusing the same queue.
352 BuildTileTaskQueue(&queue
, raster_tasks
[count
% kNumVersions
]);
353 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&queue
);
354 tile_task_worker_pool_
->AsTileTaskRunner()->CheckForCompletedTasks();
357 } while (!timer_
.HasTimeLimitExpired());
360 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&empty
);
361 RunMessageLoopUntilAllTasksHaveCompleted();
363 perf_test::PrintResult("schedule_alternate_tasks", TestModifierString(),
364 test_name
, timer_
.LapsPerSecond(), "runs/s", true);
367 void RunScheduleAndExecuteTasksTest(const std::string
& test_name
,
368 unsigned num_raster_tasks
,
369 unsigned num_image_decode_tasks
) {
370 ImageDecodeTask::Vector image_decode_tasks
;
371 RasterTaskVector raster_tasks
;
372 CreateImageDecodeTasks(num_image_decode_tasks
, &image_decode_tasks
);
373 CreateRasterTasks(num_raster_tasks
, image_decode_tasks
, &raster_tasks
);
375 // Avoid unnecessary heap allocations by reusing the same queue.
381 BuildTileTaskQueue(&queue
, raster_tasks
);
382 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&queue
);
383 RunMessageLoopUntilAllTasksHaveCompleted();
385 } while (!timer_
.HasTimeLimitExpired());
388 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&empty
);
389 RunMessageLoopUntilAllTasksHaveCompleted();
391 perf_test::PrintResult("schedule_and_execute_tasks", TestModifierString(),
392 test_name
, timer_
.LapsPerSecond(), "runs/s", true);
396 void Create3dOutputSurfaceAndResourceProvider() {
397 output_surface_
= FakeOutputSurface::Create3d(context_provider_
).Pass();
398 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
399 resource_provider_
= ResourceProvider::Create(output_surface_
.get(), NULL
,
400 &gpu_memory_buffer_manager_
,
401 NULL
, 0, false, 1).Pass();
404 void CreateSoftwareOutputSurfaceAndResourceProvider() {
405 output_surface_
= FakeOutputSurface::CreateSoftware(
406 make_scoped_ptr(new SoftwareOutputDevice
));
407 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
409 ResourceProvider::Create(output_surface_
.get(), &shared_bitmap_manager_
,
410 NULL
, NULL
, 0, false, 1).Pass();
413 std::string
TestModifierString() const {
414 switch (GetParam()) {
415 case TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER
:
416 return std::string("_pixel_tile_task_worker_pool");
417 case TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY
:
418 return std::string("_zero_copy_tile_task_worker_pool");
419 case TILE_TASK_WORKER_POOL_TYPE_ONE_COPY
:
420 return std::string("_one_copy_tile_task_worker_pool");
421 case TILE_TASK_WORKER_POOL_TYPE_GPU
:
422 return std::string("_gpu_tile_task_worker_pool");
423 case TILE_TASK_WORKER_POOL_TYPE_BITMAP
:
424 return std::string("_bitmap_tile_task_worker_pool");
427 return std::string();
430 scoped_ptr
<ResourcePool
> staging_resource_pool_
;
431 scoped_ptr
<TileTaskWorkerPool
> tile_task_worker_pool_
;
432 TestGpuMemoryBufferManager gpu_memory_buffer_manager_
;
433 TestSharedBitmapManager shared_bitmap_manager_
;
436 TEST_P(TileTaskWorkerPoolPerfTest
, ScheduleTasks
) {
437 RunScheduleTasksTest("1_0", 1, 0);
438 RunScheduleTasksTest("32_0", 32, 0);
439 RunScheduleTasksTest("1_1", 1, 1);
440 RunScheduleTasksTest("32_1", 32, 1);
441 RunScheduleTasksTest("1_4", 1, 4);
442 RunScheduleTasksTest("32_4", 32, 4);
445 TEST_P(TileTaskWorkerPoolPerfTest
, ScheduleAlternateTasks
) {
446 RunScheduleAlternateTasksTest("1_0", 1, 0);
447 RunScheduleAlternateTasksTest("32_0", 32, 0);
448 RunScheduleAlternateTasksTest("1_1", 1, 1);
449 RunScheduleAlternateTasksTest("32_1", 32, 1);
450 RunScheduleAlternateTasksTest("1_4", 1, 4);
451 RunScheduleAlternateTasksTest("32_4", 32, 4);
454 TEST_P(TileTaskWorkerPoolPerfTest
, ScheduleAndExecuteTasks
) {
455 RunScheduleAndExecuteTasksTest("1_0", 1, 0);
456 RunScheduleAndExecuteTasksTest("32_0", 32, 0);
457 RunScheduleAndExecuteTasksTest("1_1", 1, 1);
458 RunScheduleAndExecuteTasksTest("32_1", 32, 1);
459 RunScheduleAndExecuteTasksTest("1_4", 1, 4);
460 RunScheduleAndExecuteTasksTest("32_4", 32, 4);
463 INSTANTIATE_TEST_CASE_P(
464 TileTaskWorkerPoolPerfTests
,
465 TileTaskWorkerPoolPerfTest
,
466 ::testing::Values(TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER
,
467 TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY
,
468 TILE_TASK_WORKER_POOL_TYPE_ONE_COPY
,
469 TILE_TASK_WORKER_POOL_TYPE_GPU
,
470 TILE_TASK_WORKER_POOL_TYPE_BITMAP
));
472 class TileTaskWorkerPoolCommonPerfTest
: public TileTaskWorkerPoolPerfTestBase
,
473 public testing::Test
{
475 // Overridden from testing::Test:
476 void SetUp() override
{
477 output_surface_
= FakeOutputSurface::Create3d(context_provider_
).Pass();
478 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
480 ResourceProvider::Create(output_surface_
.get(), NULL
, NULL
, NULL
, 0,
484 void RunBuildTileTaskQueueTest(const std::string
& test_name
,
485 unsigned num_raster_tasks
,
486 unsigned num_image_decode_tasks
) {
487 ImageDecodeTask::Vector image_decode_tasks
;
488 RasterTaskVector raster_tasks
;
489 CreateImageDecodeTasks(num_image_decode_tasks
, &image_decode_tasks
);
490 CreateRasterTasks(num_raster_tasks
, image_decode_tasks
, &raster_tasks
);
492 // Avoid unnecessary heap allocations by reusing the same queue.
498 BuildTileTaskQueue(&queue
, raster_tasks
);
500 } while (!timer_
.HasTimeLimitExpired());
502 perf_test::PrintResult("build_raster_task_queue", "", test_name
,
503 timer_
.LapsPerSecond(), "runs/s", true);
507 TEST_F(TileTaskWorkerPoolCommonPerfTest
, BuildTileTaskQueue
) {
508 RunBuildTileTaskQueueTest("1_0", 1, 0);
509 RunBuildTileTaskQueueTest("32_0", 32, 0);
510 RunBuildTileTaskQueueTest("1_1", 1, 1);
511 RunBuildTileTaskQueueTest("32_1", 32, 1);
512 RunBuildTileTaskQueueTest("1_4", 1, 4);
513 RunBuildTileTaskQueueTest("32_4", 32, 4);