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/raster/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/raster/bitmap_tile_task_worker_pool.h"
12 #include "cc/raster/gpu_rasterizer.h"
13 #include "cc/raster/gpu_tile_task_worker_pool.h"
14 #include "cc/raster/one_copy_tile_task_worker_pool.h"
15 #include "cc/raster/pixel_buffer_tile_task_worker_pool.h"
16 #include "cc/raster/raster_buffer.h"
17 #include "cc/raster/tile_task_runner.h"
18 #include "cc/raster/zero_copy_tile_task_worker_pool.h"
19 #include "cc/resources/resource_pool.h"
20 #include "cc/resources/resource_provider.h"
21 #include "cc/resources/scoped_resource.h"
22 #include "cc/test/fake_output_surface.h"
23 #include "cc/test/fake_output_surface_client.h"
24 #include "cc/test/fake_resource_provider.h"
25 #include "cc/test/test_context_support.h"
26 #include "cc/test/test_gpu_memory_buffer_manager.h"
27 #include "cc/test/test_shared_bitmap_manager.h"
28 #include "cc/test/test_web_graphics_context_3d.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 #include "testing/perf/perf_test.h"
31 #include "third_party/khronos/GLES2/gl2.h"
32 #include "third_party/skia/include/gpu/GrContext.h"
33 #include "third_party/skia/include/gpu/gl/GrGLInterface.h"
38 class PerfGLES2Interface
: public gpu::gles2::GLES2InterfaceStub
{
39 // Overridden from gpu::gles2::GLES2Interface:
40 GLuint
CreateImageCHROMIUM(ClientBuffer buffer
,
43 GLenum internalformat
) override
{
46 void GenBuffers(GLsizei n
, GLuint
* buffers
) override
{
47 for (GLsizei i
= 0; i
< n
; ++i
)
50 void GenTextures(GLsizei n
, GLuint
* textures
) override
{
51 for (GLsizei i
= 0; i
< n
; ++i
)
54 void GetIntegerv(GLenum pname
, GLint
* params
) override
{
55 if (pname
== GL_MAX_TEXTURE_SIZE
)
58 void GenQueriesEXT(GLsizei n
, GLuint
* queries
) override
{
59 for (GLsizei i
= 0; i
< n
; ++i
)
62 void GetQueryObjectuivEXT(GLuint query
,
64 GLuint
* params
) override
{
65 if (pname
== GL_QUERY_RESULT_AVAILABLE_EXT
)
70 class PerfContextProvider
: public ContextProvider
{
72 PerfContextProvider() : context_gl_(new PerfGLES2Interface
) {}
74 bool BindToCurrentThread() override
{ return true; }
75 Capabilities
ContextCapabilities() override
{
76 Capabilities capabilities
;
77 capabilities
.gpu
.image
= true;
78 capabilities
.gpu
.sync_query
= true;
81 gpu::gles2::GLES2Interface
* ContextGL() override
{ return context_gl_
.get(); }
82 gpu::ContextSupport
* ContextSupport() override
{ return &support_
; }
83 class GrContext
* GrContext() override
{
85 return gr_context_
.get();
87 skia::RefPtr
<const GrGLInterface
> null_interface
=
88 skia::AdoptRef(GrGLCreateNullInterface());
89 gr_context_
= skia::AdoptRef(GrContext::Create(
91 reinterpret_cast<GrBackendContext
>(null_interface
.get())));
92 return gr_context_
.get();
94 void InvalidateGrContext(uint32_t state
) override
{
96 gr_context_
.get()->resetContext(state
);
98 void SetupLock() override
{}
99 base::Lock
* GetLock() override
{ return &context_lock_
; }
100 void VerifyContexts() override
{}
101 void DeleteCachedResources() override
{}
102 bool DestroyedOnMainThread() override
{ return false; }
103 void SetLostContextCallback(const LostContextCallback
& cb
) override
{}
104 void SetMemoryPolicyChangedCallback(
105 const MemoryPolicyChangedCallback
& cb
) override
{}
108 ~PerfContextProvider() override
{}
110 scoped_ptr
<PerfGLES2Interface
> context_gl_
;
111 skia::RefPtr
<class GrContext
> gr_context_
;
112 TestContextSupport support_
;
113 base::Lock context_lock_
;
116 enum TileTaskWorkerPoolType
{
117 TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER
,
118 TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY
,
119 TILE_TASK_WORKER_POOL_TYPE_ONE_COPY
,
120 TILE_TASK_WORKER_POOL_TYPE_GPU
,
121 TILE_TASK_WORKER_POOL_TYPE_BITMAP
124 static const int kTimeLimitMillis
= 2000;
125 static const int kWarmupRuns
= 5;
126 static const int kTimeCheckInterval
= 10;
128 class PerfImageDecodeTaskImpl
: public ImageDecodeTask
{
130 PerfImageDecodeTaskImpl() {}
132 // Overridden from Task:
133 void RunOnWorkerThread() override
{}
135 // Overridden from TileTask:
136 void ScheduleOnOriginThread(TileTaskClient
* client
) override
{}
137 void CompleteOnOriginThread(TileTaskClient
* client
) override
{}
138 void RunReplyOnOriginThread() override
{ Reset(); }
142 did_complete_
= false;
146 ~PerfImageDecodeTaskImpl() override
{}
149 DISALLOW_COPY_AND_ASSIGN(PerfImageDecodeTaskImpl
);
152 class PerfRasterTaskImpl
: public RasterTask
{
154 PerfRasterTaskImpl(scoped_ptr
<ScopedResource
> resource
,
155 ImageDecodeTask::Vector
* dependencies
)
156 : RasterTask(resource
.get(), dependencies
), resource_(resource
.Pass()) {}
158 // Overridden from Task:
159 void RunOnWorkerThread() override
{}
161 // Overridden from TileTask:
162 void ScheduleOnOriginThread(TileTaskClient
* client
) override
{
163 // No tile ids are given to support partial updates.
164 raster_buffer_
= client
->AcquireBufferForRaster(resource(), 0, 0);
166 void CompleteOnOriginThread(TileTaskClient
* client
) override
{
167 client
->ReleaseBufferForRaster(raster_buffer_
.Pass());
169 void RunReplyOnOriginThread() override
{ Reset(); }
173 did_complete_
= false;
177 ~PerfRasterTaskImpl() override
{}
180 scoped_ptr
<ScopedResource
> resource_
;
181 scoped_ptr
<RasterBuffer
> raster_buffer_
;
183 DISALLOW_COPY_AND_ASSIGN(PerfRasterTaskImpl
);
186 class TileTaskWorkerPoolPerfTestBase
{
188 typedef std::vector
<scoped_refptr
<RasterTask
>> RasterTaskVector
;
190 enum NamedTaskSet
{ REQUIRED_FOR_ACTIVATION
, REQUIRED_FOR_DRAW
, ALL
};
192 TileTaskWorkerPoolPerfTestBase()
193 : context_provider_(make_scoped_refptr(new PerfContextProvider
)),
194 task_runner_(new base::TestSimpleTaskRunner
),
195 task_graph_runner_(new TaskGraphRunner
),
197 base::TimeDelta::FromMilliseconds(kTimeLimitMillis
),
198 kTimeCheckInterval
) {}
200 void CreateImageDecodeTasks(unsigned num_image_decode_tasks
,
201 ImageDecodeTask::Vector
* image_decode_tasks
) {
202 for (unsigned i
= 0; i
< num_image_decode_tasks
; ++i
)
203 image_decode_tasks
->push_back(new PerfImageDecodeTaskImpl
);
206 void CreateRasterTasks(unsigned num_raster_tasks
,
207 const ImageDecodeTask::Vector
& image_decode_tasks
,
208 RasterTaskVector
* raster_tasks
) {
209 const gfx::Size
size(1, 1);
211 for (unsigned i
= 0; i
< num_raster_tasks
; ++i
) {
212 scoped_ptr
<ScopedResource
> resource(
213 ScopedResource::Create(resource_provider_
.get()));
214 resource
->Allocate(size
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
217 ImageDecodeTask::Vector dependencies
= image_decode_tasks
;
218 raster_tasks
->push_back(
219 new PerfRasterTaskImpl(resource
.Pass(), &dependencies
));
223 void BuildTileTaskQueue(TileTaskQueue
* queue
,
224 const RasterTaskVector
& raster_tasks
) {
225 for (size_t i
= 0u; i
< raster_tasks
.size(); ++i
) {
226 bool required_for_activation
= (i
% 2) == 0;
227 TaskSetCollection task_set_collection
;
228 task_set_collection
[ALL
] = true;
229 task_set_collection
[REQUIRED_FOR_ACTIVATION
] = required_for_activation
;
230 queue
->items
.push_back(
231 TileTaskQueue::Item(raster_tasks
[i
].get(), task_set_collection
));
236 scoped_refptr
<ContextProvider
> context_provider_
;
237 FakeOutputSurfaceClient output_surface_client_
;
238 scoped_ptr
<FakeOutputSurface
> output_surface_
;
239 scoped_ptr
<ResourceProvider
> resource_provider_
;
240 scoped_refptr
<base::TestSimpleTaskRunner
> task_runner_
;
241 scoped_ptr
<TaskGraphRunner
> task_graph_runner_
;
245 class TileTaskWorkerPoolPerfTest
246 : public TileTaskWorkerPoolPerfTestBase
,
247 public testing::TestWithParam
<TileTaskWorkerPoolType
>,
248 public TileTaskRunnerClient
{
250 // Overridden from testing::Test:
251 void SetUp() override
{
252 switch (GetParam()) {
253 case TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER
:
254 Create3dOutputSurfaceAndResourceProvider();
255 tile_task_worker_pool_
= PixelBufferTileTaskWorkerPool::Create(
256 task_runner_
.get(), task_graph_runner_
.get(),
257 context_provider_
.get(), resource_provider_
.get(),
258 std::numeric_limits
<size_t>::max());
260 case TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY
:
261 Create3dOutputSurfaceAndResourceProvider();
262 tile_task_worker_pool_
= ZeroCopyTileTaskWorkerPool::Create(
263 task_runner_
.get(), task_graph_runner_
.get(),
264 resource_provider_
.get());
266 case TILE_TASK_WORKER_POOL_TYPE_ONE_COPY
:
267 Create3dOutputSurfaceAndResourceProvider();
268 staging_resource_pool_
= ResourcePool::Create(resource_provider_
.get(),
270 tile_task_worker_pool_
= OneCopyTileTaskWorkerPool::Create(
271 task_runner_
.get(), task_graph_runner_
.get(),
272 context_provider_
.get(), resource_provider_
.get(),
273 staging_resource_pool_
.get(), std::numeric_limits
<int>::max(),
276 case TILE_TASK_WORKER_POOL_TYPE_GPU
:
277 Create3dOutputSurfaceAndResourceProvider();
278 tile_task_worker_pool_
= GpuTileTaskWorkerPool::Create(
279 task_runner_
.get(), task_graph_runner_
.get(),
280 context_provider_
.get(), resource_provider_
.get(), false, 0);
282 case TILE_TASK_WORKER_POOL_TYPE_BITMAP
:
283 CreateSoftwareOutputSurfaceAndResourceProvider();
284 tile_task_worker_pool_
= BitmapTileTaskWorkerPool::Create(
285 task_runner_
.get(), task_graph_runner_
.get(),
286 resource_provider_
.get());
290 DCHECK(tile_task_worker_pool_
);
291 tile_task_worker_pool_
->AsTileTaskRunner()->SetClient(this);
293 void TearDown() override
{
294 tile_task_worker_pool_
->AsTileTaskRunner()->Shutdown();
295 tile_task_worker_pool_
->AsTileTaskRunner()->CheckForCompletedTasks();
298 // Overriden from TileTaskRunnerClient:
299 void DidFinishRunningTileTasks(TaskSet task_set
) override
{
300 tile_task_worker_pool_
->AsTileTaskRunner()->CheckForCompletedTasks();
302 TaskSetCollection
TasksThatShouldBeForcedToComplete() const override
{
303 return TaskSetCollection();
306 void RunMessageLoopUntilAllTasksHaveCompleted() {
307 task_graph_runner_
->RunUntilIdle();
308 task_runner_
->RunUntilIdle();
311 void RunScheduleTasksTest(const std::string
& test_name
,
312 unsigned num_raster_tasks
,
313 unsigned num_image_decode_tasks
) {
314 ImageDecodeTask::Vector image_decode_tasks
;
315 RasterTaskVector raster_tasks
;
316 CreateImageDecodeTasks(num_image_decode_tasks
, &image_decode_tasks
);
317 CreateRasterTasks(num_raster_tasks
, image_decode_tasks
, &raster_tasks
);
319 // Avoid unnecessary heap allocations by reusing the same queue.
325 BuildTileTaskQueue(&queue
, raster_tasks
);
326 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&queue
);
327 tile_task_worker_pool_
->AsTileTaskRunner()->CheckForCompletedTasks();
329 } while (!timer_
.HasTimeLimitExpired());
332 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&empty
);
333 RunMessageLoopUntilAllTasksHaveCompleted();
335 perf_test::PrintResult("schedule_tasks", TestModifierString(), test_name
,
336 timer_
.LapsPerSecond(), "runs/s", true);
339 void RunScheduleAlternateTasksTest(const std::string
& test_name
,
340 unsigned num_raster_tasks
,
341 unsigned num_image_decode_tasks
) {
342 const size_t kNumVersions
= 2;
343 ImageDecodeTask::Vector image_decode_tasks
[kNumVersions
];
344 RasterTaskVector raster_tasks
[kNumVersions
];
345 for (size_t i
= 0; i
< kNumVersions
; ++i
) {
346 CreateImageDecodeTasks(num_image_decode_tasks
, &image_decode_tasks
[i
]);
347 CreateRasterTasks(num_raster_tasks
, image_decode_tasks
[i
],
351 // Avoid unnecessary heap allocations by reusing the same queue.
358 BuildTileTaskQueue(&queue
, raster_tasks
[count
% kNumVersions
]);
359 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&queue
);
360 tile_task_worker_pool_
->AsTileTaskRunner()->CheckForCompletedTasks();
363 } while (!timer_
.HasTimeLimitExpired());
366 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&empty
);
367 RunMessageLoopUntilAllTasksHaveCompleted();
369 perf_test::PrintResult("schedule_alternate_tasks", TestModifierString(),
370 test_name
, timer_
.LapsPerSecond(), "runs/s", true);
373 void RunScheduleAndExecuteTasksTest(const std::string
& test_name
,
374 unsigned num_raster_tasks
,
375 unsigned num_image_decode_tasks
) {
376 ImageDecodeTask::Vector image_decode_tasks
;
377 RasterTaskVector raster_tasks
;
378 CreateImageDecodeTasks(num_image_decode_tasks
, &image_decode_tasks
);
379 CreateRasterTasks(num_raster_tasks
, image_decode_tasks
, &raster_tasks
);
381 // Avoid unnecessary heap allocations by reusing the same queue.
387 BuildTileTaskQueue(&queue
, raster_tasks
);
388 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&queue
);
389 RunMessageLoopUntilAllTasksHaveCompleted();
391 } while (!timer_
.HasTimeLimitExpired());
394 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&empty
);
395 RunMessageLoopUntilAllTasksHaveCompleted();
397 perf_test::PrintResult("schedule_and_execute_tasks", TestModifierString(),
398 test_name
, timer_
.LapsPerSecond(), "runs/s", true);
402 void Create3dOutputSurfaceAndResourceProvider() {
403 output_surface_
= FakeOutputSurface::Create3d(context_provider_
).Pass();
404 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
405 resource_provider_
= FakeResourceProvider::Create(
406 output_surface_
.get(), nullptr, &gpu_memory_buffer_manager_
);
409 void CreateSoftwareOutputSurfaceAndResourceProvider() {
410 output_surface_
= FakeOutputSurface::CreateSoftware(
411 make_scoped_ptr(new SoftwareOutputDevice
));
412 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
413 resource_provider_
= FakeResourceProvider::Create(
414 output_surface_
.get(), &shared_bitmap_manager_
, nullptr);
417 std::string
TestModifierString() const {
418 switch (GetParam()) {
419 case TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER
:
420 return std::string("_pixel_tile_task_worker_pool");
421 case TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY
:
422 return std::string("_zero_copy_tile_task_worker_pool");
423 case TILE_TASK_WORKER_POOL_TYPE_ONE_COPY
:
424 return std::string("_one_copy_tile_task_worker_pool");
425 case TILE_TASK_WORKER_POOL_TYPE_GPU
:
426 return std::string("_gpu_tile_task_worker_pool");
427 case TILE_TASK_WORKER_POOL_TYPE_BITMAP
:
428 return std::string("_bitmap_tile_task_worker_pool");
431 return std::string();
434 scoped_ptr
<ResourcePool
> staging_resource_pool_
;
435 scoped_ptr
<TileTaskWorkerPool
> tile_task_worker_pool_
;
436 TestGpuMemoryBufferManager gpu_memory_buffer_manager_
;
437 TestSharedBitmapManager shared_bitmap_manager_
;
440 TEST_P(TileTaskWorkerPoolPerfTest
, ScheduleTasks
) {
441 RunScheduleTasksTest("1_0", 1, 0);
442 RunScheduleTasksTest("32_0", 32, 0);
443 RunScheduleTasksTest("1_1", 1, 1);
444 RunScheduleTasksTest("32_1", 32, 1);
445 RunScheduleTasksTest("1_4", 1, 4);
446 RunScheduleTasksTest("32_4", 32, 4);
449 TEST_P(TileTaskWorkerPoolPerfTest
, ScheduleAlternateTasks
) {
450 RunScheduleAlternateTasksTest("1_0", 1, 0);
451 RunScheduleAlternateTasksTest("32_0", 32, 0);
452 RunScheduleAlternateTasksTest("1_1", 1, 1);
453 RunScheduleAlternateTasksTest("32_1", 32, 1);
454 RunScheduleAlternateTasksTest("1_4", 1, 4);
455 RunScheduleAlternateTasksTest("32_4", 32, 4);
458 TEST_P(TileTaskWorkerPoolPerfTest
, ScheduleAndExecuteTasks
) {
459 RunScheduleAndExecuteTasksTest("1_0", 1, 0);
460 RunScheduleAndExecuteTasksTest("32_0", 32, 0);
461 RunScheduleAndExecuteTasksTest("1_1", 1, 1);
462 RunScheduleAndExecuteTasksTest("32_1", 32, 1);
463 RunScheduleAndExecuteTasksTest("1_4", 1, 4);
464 RunScheduleAndExecuteTasksTest("32_4", 32, 4);
467 INSTANTIATE_TEST_CASE_P(
468 TileTaskWorkerPoolPerfTests
,
469 TileTaskWorkerPoolPerfTest
,
470 ::testing::Values(TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER
,
471 TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY
,
472 TILE_TASK_WORKER_POOL_TYPE_ONE_COPY
,
473 TILE_TASK_WORKER_POOL_TYPE_GPU
,
474 TILE_TASK_WORKER_POOL_TYPE_BITMAP
));
476 class TileTaskWorkerPoolCommonPerfTest
: public TileTaskWorkerPoolPerfTestBase
,
477 public testing::Test
{
479 // Overridden from testing::Test:
480 void SetUp() override
{
481 output_surface_
= FakeOutputSurface::Create3d(context_provider_
).Pass();
482 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
484 FakeResourceProvider::Create(output_surface_
.get(), nullptr);
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);