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_tile_task_worker_pool.h"
13 #include "cc/resources/one_copy_tile_task_worker_pool.h"
14 #include "cc/resources/pixel_buffer_tile_task_worker_pool.h"
15 #include "cc/resources/raster_buffer.h"
16 #include "cc/resources/resource_pool.h"
17 #include "cc/resources/resource_provider.h"
18 #include "cc/resources/scoped_resource.h"
19 #include "cc/resources/tile_task_runner.h"
20 #include "cc/resources/zero_copy_tile_task_worker_pool.h"
21 #include "cc/test/fake_output_surface.h"
22 #include "cc/test/fake_output_surface_client.h"
23 #include "cc/test/test_context_support.h"
24 #include "cc/test/test_gpu_memory_buffer_manager.h"
25 #include "cc/test/test_shared_bitmap_manager.h"
26 #include "cc/test/test_web_graphics_context_3d.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28 #include "testing/perf/perf_test.h"
29 #include "third_party/khronos/GLES2/gl2.h"
30 #include "third_party/skia/include/gpu/GrContext.h"
31 #include "third_party/skia/include/gpu/gl/GrGLInterface.h"
36 class PerfGLES2Interface
: public gpu::gles2::GLES2InterfaceStub
{
37 // Overridden from gpu::gles2::GLES2Interface:
38 GLuint
CreateImageCHROMIUM(ClientBuffer buffer
,
41 GLenum internalformat
) override
{
44 void GenBuffers(GLsizei n
, GLuint
* buffers
) override
{
45 for (GLsizei i
= 0; i
< n
; ++i
)
48 void GenTextures(GLsizei n
, GLuint
* textures
) override
{
49 for (GLsizei i
= 0; i
< n
; ++i
)
52 void GetIntegerv(GLenum pname
, GLint
* params
) override
{
53 if (pname
== GL_MAX_TEXTURE_SIZE
)
56 void GenQueriesEXT(GLsizei n
, GLuint
* queries
) override
{
57 for (GLsizei i
= 0; i
< n
; ++i
)
60 void GetQueryObjectuivEXT(GLuint query
,
62 GLuint
* params
) override
{
63 if (pname
== GL_QUERY_RESULT_AVAILABLE_EXT
)
68 class PerfContextProvider
: public ContextProvider
{
70 PerfContextProvider() : context_gl_(new PerfGLES2Interface
) {}
72 bool BindToCurrentThread() override
{ return true; }
73 Capabilities
ContextCapabilities() override
{
74 Capabilities capabilities
;
75 capabilities
.gpu
.image
= true;
76 capabilities
.gpu
.sync_query
= true;
79 gpu::gles2::GLES2Interface
* ContextGL() override
{ return context_gl_
.get(); }
80 gpu::ContextSupport
* ContextSupport() override
{ return &support_
; }
81 class GrContext
* GrContext() override
{
83 return gr_context_
.get();
85 skia::RefPtr
<const GrGLInterface
> null_interface
=
86 skia::AdoptRef(GrGLCreateNullInterface());
87 gr_context_
= skia::AdoptRef(GrContext::Create(
89 reinterpret_cast<GrBackendContext
>(null_interface
.get())));
90 return gr_context_
.get();
92 bool IsContextLost() override
{ return false; }
93 void VerifyContexts() override
{}
94 void DeleteCachedResources() override
{}
95 bool DestroyedOnMainThread() override
{ return false; }
96 void SetLostContextCallback(const LostContextCallback
& cb
) override
{}
97 void SetMemoryPolicyChangedCallback(
98 const MemoryPolicyChangedCallback
& cb
) override
{}
101 ~PerfContextProvider() override
{}
103 scoped_ptr
<PerfGLES2Interface
> context_gl_
;
104 skia::RefPtr
<class GrContext
> gr_context_
;
105 TestContextSupport support_
;
108 enum TileTaskWorkerPoolType
{
109 TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER
,
110 TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY
,
111 TILE_TASK_WORKER_POOL_TYPE_ONE_COPY
,
112 TILE_TASK_WORKER_POOL_TYPE_GPU
,
113 TILE_TASK_WORKER_POOL_TYPE_BITMAP
116 static const int kTimeLimitMillis
= 2000;
117 static const int kWarmupRuns
= 5;
118 static const int kTimeCheckInterval
= 10;
120 class PerfImageDecodeTaskImpl
: public ImageDecodeTask
{
122 PerfImageDecodeTaskImpl() {}
124 // Overridden from Task:
125 void RunOnWorkerThread() override
{}
127 // Overridden from TileTask:
128 void ScheduleOnOriginThread(TileTaskClient
* client
) override
{}
129 void CompleteOnOriginThread(TileTaskClient
* client
) override
{}
130 void RunReplyOnOriginThread() override
{ Reset(); }
134 did_complete_
= false;
138 ~PerfImageDecodeTaskImpl() override
{}
141 DISALLOW_COPY_AND_ASSIGN(PerfImageDecodeTaskImpl
);
144 class PerfRasterTaskImpl
: public RasterTask
{
146 PerfRasterTaskImpl(scoped_ptr
<ScopedResource
> resource
,
147 ImageDecodeTask::Vector
* dependencies
)
148 : RasterTask(resource
.get(), dependencies
), resource_(resource
.Pass()) {}
150 // Overridden from Task:
151 void RunOnWorkerThread() override
{}
153 // Overridden from TileTask:
154 void ScheduleOnOriginThread(TileTaskClient
* client
) override
{
155 raster_buffer_
= client
->AcquireBufferForRaster(resource());
157 void CompleteOnOriginThread(TileTaskClient
* client
) override
{
158 client
->ReleaseBufferForRaster(raster_buffer_
.Pass());
160 void RunReplyOnOriginThread() override
{ Reset(); }
164 did_complete_
= false;
168 ~PerfRasterTaskImpl() override
{}
171 scoped_ptr
<ScopedResource
> resource_
;
172 scoped_ptr
<RasterBuffer
> raster_buffer_
;
174 DISALLOW_COPY_AND_ASSIGN(PerfRasterTaskImpl
);
177 class TileTaskWorkerPoolPerfTestBase
{
179 typedef std::vector
<scoped_refptr
<RasterTask
>> RasterTaskVector
;
181 enum NamedTaskSet
{ REQUIRED_FOR_ACTIVATION
, REQUIRED_FOR_DRAW
, ALL
};
183 TileTaskWorkerPoolPerfTestBase()
184 : context_provider_(make_scoped_refptr(new PerfContextProvider
)),
185 task_runner_(new base::TestSimpleTaskRunner
),
186 task_graph_runner_(new TaskGraphRunner
),
188 base::TimeDelta::FromMilliseconds(kTimeLimitMillis
),
189 kTimeCheckInterval
) {}
191 void CreateImageDecodeTasks(unsigned num_image_decode_tasks
,
192 ImageDecodeTask::Vector
* image_decode_tasks
) {
193 for (unsigned i
= 0; i
< num_image_decode_tasks
; ++i
)
194 image_decode_tasks
->push_back(new PerfImageDecodeTaskImpl
);
197 void CreateRasterTasks(unsigned num_raster_tasks
,
198 const ImageDecodeTask::Vector
& image_decode_tasks
,
199 RasterTaskVector
* raster_tasks
) {
200 const gfx::Size
size(1, 1);
202 for (unsigned i
= 0; i
< num_raster_tasks
; ++i
) {
203 scoped_ptr
<ScopedResource
> resource(
204 ScopedResource::Create(resource_provider_
.get()));
205 resource
->Allocate(size
, ResourceProvider::TextureHintImmutable
,
208 ImageDecodeTask::Vector dependencies
= image_decode_tasks
;
209 raster_tasks
->push_back(
210 new PerfRasterTaskImpl(resource
.Pass(), &dependencies
));
214 void BuildTileTaskQueue(TileTaskQueue
* queue
,
215 const RasterTaskVector
& raster_tasks
) {
216 for (size_t i
= 0u; i
< raster_tasks
.size(); ++i
) {
217 bool required_for_activation
= (i
% 2) == 0;
218 TaskSetCollection task_set_collection
;
219 task_set_collection
[ALL
] = true;
220 task_set_collection
[REQUIRED_FOR_ACTIVATION
] = required_for_activation
;
221 queue
->items
.push_back(
222 TileTaskQueue::Item(raster_tasks
[i
].get(), task_set_collection
));
227 scoped_refptr
<ContextProvider
> context_provider_
;
228 FakeOutputSurfaceClient output_surface_client_
;
229 scoped_ptr
<FakeOutputSurface
> output_surface_
;
230 scoped_ptr
<ResourceProvider
> resource_provider_
;
231 scoped_refptr
<base::TestSimpleTaskRunner
> task_runner_
;
232 scoped_ptr
<TaskGraphRunner
> task_graph_runner_
;
236 class TileTaskWorkerPoolPerfTest
237 : public TileTaskWorkerPoolPerfTestBase
,
238 public testing::TestWithParam
<TileTaskWorkerPoolType
>,
239 public TileTaskRunnerClient
{
241 // Overridden from testing::Test:
242 void SetUp() override
{
243 switch (GetParam()) {
244 case TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER
:
245 Create3dOutputSurfaceAndResourceProvider();
246 tile_task_worker_pool_
= PixelBufferTileTaskWorkerPool::Create(
247 task_runner_
.get(), task_graph_runner_
.get(),
248 context_provider_
.get(), resource_provider_
.get(),
249 std::numeric_limits
<size_t>::max());
251 case TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY
:
252 Create3dOutputSurfaceAndResourceProvider();
253 tile_task_worker_pool_
= ZeroCopyTileTaskWorkerPool::Create(
254 task_runner_
.get(), task_graph_runner_
.get(),
255 resource_provider_
.get());
257 case TILE_TASK_WORKER_POOL_TYPE_ONE_COPY
:
258 Create3dOutputSurfaceAndResourceProvider();
259 staging_resource_pool_
= ResourcePool::Create(resource_provider_
.get(),
261 tile_task_worker_pool_
= OneCopyTileTaskWorkerPool::Create(
262 task_runner_
.get(), task_graph_runner_
.get(),
263 context_provider_
.get(), resource_provider_
.get(),
264 staging_resource_pool_
.get());
266 case TILE_TASK_WORKER_POOL_TYPE_GPU
:
267 Create3dOutputSurfaceAndResourceProvider();
268 tile_task_worker_pool_
= GpuTileTaskWorkerPool::Create(
269 task_runner_
.get(), task_graph_runner_
.get(),
270 resource_provider_
.get());
272 case TILE_TASK_WORKER_POOL_TYPE_BITMAP
:
273 CreateSoftwareOutputSurfaceAndResourceProvider();
274 tile_task_worker_pool_
= BitmapTileTaskWorkerPool::Create(
275 task_runner_
.get(), task_graph_runner_
.get(),
276 resource_provider_
.get());
280 DCHECK(tile_task_worker_pool_
);
281 tile_task_worker_pool_
->AsTileTaskRunner()->SetClient(this);
283 void TearDown() override
{
284 tile_task_worker_pool_
->AsTileTaskRunner()->Shutdown();
285 tile_task_worker_pool_
->AsTileTaskRunner()->CheckForCompletedTasks();
288 // Overriden from TileTaskRunnerClient:
289 void DidFinishRunningTileTasks(TaskSet task_set
) override
{
290 tile_task_worker_pool_
->AsTileTaskRunner()->CheckForCompletedTasks();
292 TaskSetCollection
TasksThatShouldBeForcedToComplete() const override
{
293 return TaskSetCollection();
296 void RunMessageLoopUntilAllTasksHaveCompleted() {
297 task_graph_runner_
->RunUntilIdle();
298 task_runner_
->RunUntilIdle();
301 void RunScheduleTasksTest(const std::string
& test_name
,
302 unsigned num_raster_tasks
,
303 unsigned num_image_decode_tasks
) {
304 ImageDecodeTask::Vector image_decode_tasks
;
305 RasterTaskVector raster_tasks
;
306 CreateImageDecodeTasks(num_image_decode_tasks
, &image_decode_tasks
);
307 CreateRasterTasks(num_raster_tasks
, image_decode_tasks
, &raster_tasks
);
309 // Avoid unnecessary heap allocations by reusing the same queue.
315 BuildTileTaskQueue(&queue
, raster_tasks
);
316 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&queue
);
317 tile_task_worker_pool_
->AsTileTaskRunner()->CheckForCompletedTasks();
319 } while (!timer_
.HasTimeLimitExpired());
322 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&empty
);
323 RunMessageLoopUntilAllTasksHaveCompleted();
325 perf_test::PrintResult("schedule_tasks", TestModifierString(), test_name
,
326 timer_
.LapsPerSecond(), "runs/s", true);
329 void RunScheduleAlternateTasksTest(const std::string
& test_name
,
330 unsigned num_raster_tasks
,
331 unsigned num_image_decode_tasks
) {
332 const size_t kNumVersions
= 2;
333 ImageDecodeTask::Vector image_decode_tasks
[kNumVersions
];
334 RasterTaskVector raster_tasks
[kNumVersions
];
335 for (size_t i
= 0; i
< kNumVersions
; ++i
) {
336 CreateImageDecodeTasks(num_image_decode_tasks
, &image_decode_tasks
[i
]);
337 CreateRasterTasks(num_raster_tasks
, image_decode_tasks
[i
],
341 // Avoid unnecessary heap allocations by reusing the same queue.
348 BuildTileTaskQueue(&queue
, raster_tasks
[count
% kNumVersions
]);
349 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&queue
);
350 tile_task_worker_pool_
->AsTileTaskRunner()->CheckForCompletedTasks();
353 } while (!timer_
.HasTimeLimitExpired());
356 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&empty
);
357 RunMessageLoopUntilAllTasksHaveCompleted();
359 perf_test::PrintResult("schedule_alternate_tasks", TestModifierString(),
360 test_name
, timer_
.LapsPerSecond(), "runs/s", true);
363 void RunScheduleAndExecuteTasksTest(const std::string
& test_name
,
364 unsigned num_raster_tasks
,
365 unsigned num_image_decode_tasks
) {
366 ImageDecodeTask::Vector image_decode_tasks
;
367 RasterTaskVector raster_tasks
;
368 CreateImageDecodeTasks(num_image_decode_tasks
, &image_decode_tasks
);
369 CreateRasterTasks(num_raster_tasks
, image_decode_tasks
, &raster_tasks
);
371 // Avoid unnecessary heap allocations by reusing the same queue.
377 BuildTileTaskQueue(&queue
, raster_tasks
);
378 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&queue
);
379 RunMessageLoopUntilAllTasksHaveCompleted();
381 } while (!timer_
.HasTimeLimitExpired());
384 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&empty
);
385 RunMessageLoopUntilAllTasksHaveCompleted();
387 perf_test::PrintResult("schedule_and_execute_tasks", TestModifierString(),
388 test_name
, timer_
.LapsPerSecond(), "runs/s", true);
392 void Create3dOutputSurfaceAndResourceProvider() {
393 output_surface_
= FakeOutputSurface::Create3d(context_provider_
).Pass();
394 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
395 resource_provider_
= ResourceProvider::Create(output_surface_
.get(), NULL
,
396 &gpu_memory_buffer_manager_
,
397 NULL
, 0, false, 1).Pass();
400 void CreateSoftwareOutputSurfaceAndResourceProvider() {
401 output_surface_
= FakeOutputSurface::CreateSoftware(
402 make_scoped_ptr(new SoftwareOutputDevice
));
403 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
405 ResourceProvider::Create(output_surface_
.get(), &shared_bitmap_manager_
,
406 NULL
, NULL
, 0, false, 1).Pass();
409 std::string
TestModifierString() const {
410 switch (GetParam()) {
411 case TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER
:
412 return std::string("_pixel_tile_task_worker_pool");
413 case TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY
:
414 return std::string("_zero_copy_tile_task_worker_pool");
415 case TILE_TASK_WORKER_POOL_TYPE_ONE_COPY
:
416 return std::string("_one_copy_tile_task_worker_pool");
417 case TILE_TASK_WORKER_POOL_TYPE_GPU
:
418 return std::string("_gpu_tile_task_worker_pool");
419 case TILE_TASK_WORKER_POOL_TYPE_BITMAP
:
420 return std::string("_bitmap_tile_task_worker_pool");
423 return std::string();
426 scoped_ptr
<ResourcePool
> staging_resource_pool_
;
427 scoped_ptr
<TileTaskWorkerPool
> tile_task_worker_pool_
;
428 TestGpuMemoryBufferManager gpu_memory_buffer_manager_
;
429 TestSharedBitmapManager shared_bitmap_manager_
;
432 TEST_P(TileTaskWorkerPoolPerfTest
, ScheduleTasks
) {
433 RunScheduleTasksTest("1_0", 1, 0);
434 RunScheduleTasksTest("32_0", 32, 0);
435 RunScheduleTasksTest("1_1", 1, 1);
436 RunScheduleTasksTest("32_1", 32, 1);
437 RunScheduleTasksTest("1_4", 1, 4);
438 RunScheduleTasksTest("32_4", 32, 4);
441 TEST_P(TileTaskWorkerPoolPerfTest
, ScheduleAlternateTasks
) {
442 RunScheduleAlternateTasksTest("1_0", 1, 0);
443 RunScheduleAlternateTasksTest("32_0", 32, 0);
444 RunScheduleAlternateTasksTest("1_1", 1, 1);
445 RunScheduleAlternateTasksTest("32_1", 32, 1);
446 RunScheduleAlternateTasksTest("1_4", 1, 4);
447 RunScheduleAlternateTasksTest("32_4", 32, 4);
450 TEST_P(TileTaskWorkerPoolPerfTest
, ScheduleAndExecuteTasks
) {
451 RunScheduleAndExecuteTasksTest("1_0", 1, 0);
452 RunScheduleAndExecuteTasksTest("32_0", 32, 0);
453 RunScheduleAndExecuteTasksTest("1_1", 1, 1);
454 RunScheduleAndExecuteTasksTest("32_1", 32, 1);
455 RunScheduleAndExecuteTasksTest("1_4", 1, 4);
456 RunScheduleAndExecuteTasksTest("32_4", 32, 4);
459 INSTANTIATE_TEST_CASE_P(
460 TileTaskWorkerPoolPerfTests
,
461 TileTaskWorkerPoolPerfTest
,
462 ::testing::Values(TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER
,
463 TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY
,
464 TILE_TASK_WORKER_POOL_TYPE_ONE_COPY
,
465 TILE_TASK_WORKER_POOL_TYPE_GPU
,
466 TILE_TASK_WORKER_POOL_TYPE_BITMAP
));
468 class TileTaskWorkerPoolCommonPerfTest
: public TileTaskWorkerPoolPerfTestBase
,
469 public testing::Test
{
471 // Overridden from testing::Test:
472 void SetUp() override
{
473 output_surface_
= FakeOutputSurface::Create3d(context_provider_
).Pass();
474 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
476 ResourceProvider::Create(output_surface_
.get(), NULL
, NULL
, NULL
, 0,
480 void RunBuildTileTaskQueueTest(const std::string
& test_name
,
481 unsigned num_raster_tasks
,
482 unsigned num_image_decode_tasks
) {
483 ImageDecodeTask::Vector image_decode_tasks
;
484 RasterTaskVector raster_tasks
;
485 CreateImageDecodeTasks(num_image_decode_tasks
, &image_decode_tasks
);
486 CreateRasterTasks(num_raster_tasks
, image_decode_tasks
, &raster_tasks
);
488 // Avoid unnecessary heap allocations by reusing the same queue.
494 BuildTileTaskQueue(&queue
, raster_tasks
);
496 } while (!timer_
.HasTimeLimitExpired());
498 perf_test::PrintResult("build_raster_task_queue", "", test_name
,
499 timer_
.LapsPerSecond(), "runs/s", true);
503 TEST_F(TileTaskWorkerPoolCommonPerfTest
, BuildTileTaskQueue
) {
504 RunBuildTileTaskQueueTest("1_0", 1, 0);
505 RunBuildTileTaskQueueTest("32_0", 32, 0);
506 RunBuildTileTaskQueueTest("1_1", 1, 1);
507 RunBuildTileTaskQueueTest("32_1", 32, 1);
508 RunBuildTileTaskQueueTest("1_4", 1, 4);
509 RunBuildTileTaskQueueTest("32_4", 32, 4);