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/raster_buffer.h"
16 #include "cc/raster/tile_task_runner.h"
17 #include "cc/raster/zero_copy_tile_task_worker_pool.h"
18 #include "cc/resources/resource_pool.h"
19 #include "cc/resources/resource_provider.h"
20 #include "cc/resources/scoped_resource.h"
21 #include "cc/test/fake_output_surface.h"
22 #include "cc/test/fake_output_surface_client.h"
23 #include "cc/test/fake_resource_provider.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 InvalidateGrContext(uint32_t state
) override
{
95 gr_context_
.get()->resetContext(state
);
97 void SetupLock() override
{}
98 base::Lock
* GetLock() override
{ return &context_lock_
; }
99 void VerifyContexts() override
{}
100 void DeleteCachedResources() override
{}
101 bool DestroyedOnMainThread() override
{ return false; }
102 void SetLostContextCallback(const LostContextCallback
& cb
) override
{}
103 void SetMemoryPolicyChangedCallback(
104 const MemoryPolicyChangedCallback
& cb
) override
{}
107 ~PerfContextProvider() override
{}
109 scoped_ptr
<PerfGLES2Interface
> context_gl_
;
110 skia::RefPtr
<class GrContext
> gr_context_
;
111 TestContextSupport support_
;
112 base::Lock context_lock_
;
115 enum TileTaskWorkerPoolType
{
116 TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY
,
117 TILE_TASK_WORKER_POOL_TYPE_ONE_COPY
,
118 TILE_TASK_WORKER_POOL_TYPE_GPU
,
119 TILE_TASK_WORKER_POOL_TYPE_BITMAP
122 static const int kTimeLimitMillis
= 2000;
123 static const int kWarmupRuns
= 5;
124 static const int kTimeCheckInterval
= 10;
126 class PerfImageDecodeTaskImpl
: public ImageDecodeTask
{
128 PerfImageDecodeTaskImpl() {}
130 // Overridden from Task:
131 void RunOnWorkerThread() override
{}
133 // Overridden from TileTask:
134 void ScheduleOnOriginThread(TileTaskClient
* client
) override
{}
135 void CompleteOnOriginThread(TileTaskClient
* client
) override
{}
136 void RunReplyOnOriginThread() override
{ Reset(); }
140 did_complete_
= false;
144 ~PerfImageDecodeTaskImpl() override
{}
147 DISALLOW_COPY_AND_ASSIGN(PerfImageDecodeTaskImpl
);
150 class PerfRasterTaskImpl
: public RasterTask
{
152 PerfRasterTaskImpl(scoped_ptr
<ScopedResource
> resource
,
153 ImageDecodeTask::Vector
* dependencies
)
154 : RasterTask(resource
.get(), dependencies
), resource_(resource
.Pass()) {}
156 // Overridden from Task:
157 void RunOnWorkerThread() override
{}
159 // Overridden from TileTask:
160 void ScheduleOnOriginThread(TileTaskClient
* client
) override
{
161 // No tile ids are given to support partial updates.
162 raster_buffer_
= client
->AcquireBufferForRaster(resource(), 0, 0);
164 void CompleteOnOriginThread(TileTaskClient
* client
) override
{
165 client
->ReleaseBufferForRaster(raster_buffer_
.Pass());
167 void RunReplyOnOriginThread() override
{ Reset(); }
171 did_complete_
= false;
175 ~PerfRasterTaskImpl() override
{}
178 scoped_ptr
<ScopedResource
> resource_
;
179 scoped_ptr
<RasterBuffer
> raster_buffer_
;
181 DISALLOW_COPY_AND_ASSIGN(PerfRasterTaskImpl
);
184 class TileTaskWorkerPoolPerfTestBase
{
186 typedef std::vector
<scoped_refptr
<RasterTask
>> RasterTaskVector
;
188 enum NamedTaskSet
{ REQUIRED_FOR_ACTIVATION
, REQUIRED_FOR_DRAW
, ALL
};
190 TileTaskWorkerPoolPerfTestBase()
191 : context_provider_(make_scoped_refptr(new PerfContextProvider
)),
192 task_runner_(new base::TestSimpleTaskRunner
),
193 task_graph_runner_(new TaskGraphRunner
),
195 base::TimeDelta::FromMilliseconds(kTimeLimitMillis
),
196 kTimeCheckInterval
) {}
198 void CreateImageDecodeTasks(unsigned num_image_decode_tasks
,
199 ImageDecodeTask::Vector
* image_decode_tasks
) {
200 for (unsigned i
= 0; i
< num_image_decode_tasks
; ++i
)
201 image_decode_tasks
->push_back(new PerfImageDecodeTaskImpl
);
204 void CreateRasterTasks(unsigned num_raster_tasks
,
205 const ImageDecodeTask::Vector
& image_decode_tasks
,
206 RasterTaskVector
* raster_tasks
) {
207 const gfx::Size
size(1, 1);
209 for (unsigned i
= 0; i
< num_raster_tasks
; ++i
) {
210 scoped_ptr
<ScopedResource
> resource(
211 ScopedResource::Create(resource_provider_
.get()));
212 resource
->Allocate(size
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
215 ImageDecodeTask::Vector dependencies
= image_decode_tasks
;
216 raster_tasks
->push_back(
217 new PerfRasterTaskImpl(resource
.Pass(), &dependencies
));
221 void BuildTileTaskQueue(TileTaskQueue
* queue
,
222 const RasterTaskVector
& raster_tasks
) {
223 for (size_t i
= 0u; i
< raster_tasks
.size(); ++i
) {
224 bool required_for_activation
= (i
% 2) == 0;
225 TaskSetCollection task_set_collection
;
226 task_set_collection
[ALL
] = true;
227 task_set_collection
[REQUIRED_FOR_ACTIVATION
] = required_for_activation
;
228 queue
->items
.push_back(
229 TileTaskQueue::Item(raster_tasks
[i
].get(), task_set_collection
));
234 scoped_refptr
<ContextProvider
> context_provider_
;
235 FakeOutputSurfaceClient output_surface_client_
;
236 scoped_ptr
<FakeOutputSurface
> output_surface_
;
237 scoped_ptr
<ResourceProvider
> resource_provider_
;
238 scoped_refptr
<base::TestSimpleTaskRunner
> task_runner_
;
239 scoped_ptr
<TaskGraphRunner
> task_graph_runner_
;
243 class TileTaskWorkerPoolPerfTest
244 : public TileTaskWorkerPoolPerfTestBase
,
245 public testing::TestWithParam
<TileTaskWorkerPoolType
>,
246 public TileTaskRunnerClient
{
248 // Overridden from testing::Test:
249 void SetUp() override
{
250 switch (GetParam()) {
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 tile_task_worker_pool_
= OneCopyTileTaskWorkerPool::Create(
260 task_runner_
.get(), task_graph_runner_
.get(),
261 context_provider_
.get(), resource_provider_
.get(),
262 std::numeric_limits
<int>::max(), false,
263 std::numeric_limits
<int>::max());
265 case TILE_TASK_WORKER_POOL_TYPE_GPU
:
266 Create3dOutputSurfaceAndResourceProvider();
267 tile_task_worker_pool_
= GpuTileTaskWorkerPool::Create(
268 task_runner_
.get(), task_graph_runner_
.get(),
269 context_provider_
.get(), resource_provider_
.get(), false, 0);
271 case TILE_TASK_WORKER_POOL_TYPE_BITMAP
:
272 CreateSoftwareOutputSurfaceAndResourceProvider();
273 tile_task_worker_pool_
= BitmapTileTaskWorkerPool::Create(
274 task_runner_
.get(), task_graph_runner_
.get(),
275 resource_provider_
.get());
279 DCHECK(tile_task_worker_pool_
);
280 tile_task_worker_pool_
->AsTileTaskRunner()->SetClient(this);
282 void TearDown() override
{
283 tile_task_worker_pool_
->AsTileTaskRunner()->Shutdown();
284 tile_task_worker_pool_
->AsTileTaskRunner()->CheckForCompletedTasks();
287 // Overriden from TileTaskRunnerClient:
288 void DidFinishRunningTileTasks(TaskSet task_set
) override
{
289 tile_task_worker_pool_
->AsTileTaskRunner()->CheckForCompletedTasks();
291 TaskSetCollection
TasksThatShouldBeForcedToComplete() const override
{
292 return TaskSetCollection();
295 void RunMessageLoopUntilAllTasksHaveCompleted() {
296 task_graph_runner_
->RunUntilIdle();
297 task_runner_
->RunUntilIdle();
300 void RunScheduleTasksTest(const std::string
& test_name
,
301 unsigned num_raster_tasks
,
302 unsigned num_image_decode_tasks
) {
303 ImageDecodeTask::Vector image_decode_tasks
;
304 RasterTaskVector raster_tasks
;
305 CreateImageDecodeTasks(num_image_decode_tasks
, &image_decode_tasks
);
306 CreateRasterTasks(num_raster_tasks
, image_decode_tasks
, &raster_tasks
);
308 // Avoid unnecessary heap allocations by reusing the same queue.
314 BuildTileTaskQueue(&queue
, raster_tasks
);
315 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&queue
);
316 tile_task_worker_pool_
->AsTileTaskRunner()->CheckForCompletedTasks();
318 } while (!timer_
.HasTimeLimitExpired());
321 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&empty
);
322 RunMessageLoopUntilAllTasksHaveCompleted();
324 perf_test::PrintResult("schedule_tasks", TestModifierString(), test_name
,
325 timer_
.LapsPerSecond(), "runs/s", true);
328 void RunScheduleAlternateTasksTest(const std::string
& test_name
,
329 unsigned num_raster_tasks
,
330 unsigned num_image_decode_tasks
) {
331 const size_t kNumVersions
= 2;
332 ImageDecodeTask::Vector image_decode_tasks
[kNumVersions
];
333 RasterTaskVector raster_tasks
[kNumVersions
];
334 for (size_t i
= 0; i
< kNumVersions
; ++i
) {
335 CreateImageDecodeTasks(num_image_decode_tasks
, &image_decode_tasks
[i
]);
336 CreateRasterTasks(num_raster_tasks
, image_decode_tasks
[i
],
340 // Avoid unnecessary heap allocations by reusing the same queue.
347 BuildTileTaskQueue(&queue
, raster_tasks
[count
% kNumVersions
]);
348 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&queue
);
349 tile_task_worker_pool_
->AsTileTaskRunner()->CheckForCompletedTasks();
352 } while (!timer_
.HasTimeLimitExpired());
355 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&empty
);
356 RunMessageLoopUntilAllTasksHaveCompleted();
358 perf_test::PrintResult("schedule_alternate_tasks", TestModifierString(),
359 test_name
, timer_
.LapsPerSecond(), "runs/s", true);
362 void RunScheduleAndExecuteTasksTest(const std::string
& test_name
,
363 unsigned num_raster_tasks
,
364 unsigned num_image_decode_tasks
) {
365 ImageDecodeTask::Vector image_decode_tasks
;
366 RasterTaskVector raster_tasks
;
367 CreateImageDecodeTasks(num_image_decode_tasks
, &image_decode_tasks
);
368 CreateRasterTasks(num_raster_tasks
, image_decode_tasks
, &raster_tasks
);
370 // Avoid unnecessary heap allocations by reusing the same queue.
376 BuildTileTaskQueue(&queue
, raster_tasks
);
377 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&queue
);
378 RunMessageLoopUntilAllTasksHaveCompleted();
380 } while (!timer_
.HasTimeLimitExpired());
383 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&empty
);
384 RunMessageLoopUntilAllTasksHaveCompleted();
386 perf_test::PrintResult("schedule_and_execute_tasks", TestModifierString(),
387 test_name
, timer_
.LapsPerSecond(), "runs/s", true);
391 void Create3dOutputSurfaceAndResourceProvider() {
392 output_surface_
= FakeOutputSurface::Create3d(context_provider_
).Pass();
393 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
394 resource_provider_
= FakeResourceProvider::Create(
395 output_surface_
.get(), nullptr, &gpu_memory_buffer_manager_
);
398 void CreateSoftwareOutputSurfaceAndResourceProvider() {
399 output_surface_
= FakeOutputSurface::CreateSoftware(
400 make_scoped_ptr(new SoftwareOutputDevice
));
401 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
402 resource_provider_
= FakeResourceProvider::Create(
403 output_surface_
.get(), &shared_bitmap_manager_
, nullptr);
406 std::string
TestModifierString() const {
407 switch (GetParam()) {
408 case TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY
:
409 return std::string("_zero_copy_tile_task_worker_pool");
410 case TILE_TASK_WORKER_POOL_TYPE_ONE_COPY
:
411 return std::string("_one_copy_tile_task_worker_pool");
412 case TILE_TASK_WORKER_POOL_TYPE_GPU
:
413 return std::string("_gpu_tile_task_worker_pool");
414 case TILE_TASK_WORKER_POOL_TYPE_BITMAP
:
415 return std::string("_bitmap_tile_task_worker_pool");
418 return std::string();
421 scoped_ptr
<TileTaskWorkerPool
> tile_task_worker_pool_
;
422 TestGpuMemoryBufferManager gpu_memory_buffer_manager_
;
423 TestSharedBitmapManager shared_bitmap_manager_
;
426 TEST_P(TileTaskWorkerPoolPerfTest
, ScheduleTasks
) {
427 RunScheduleTasksTest("1_0", 1, 0);
428 RunScheduleTasksTest("32_0", 32, 0);
429 RunScheduleTasksTest("1_1", 1, 1);
430 RunScheduleTasksTest("32_1", 32, 1);
431 RunScheduleTasksTest("1_4", 1, 4);
432 RunScheduleTasksTest("32_4", 32, 4);
435 TEST_P(TileTaskWorkerPoolPerfTest
, ScheduleAlternateTasks
) {
436 RunScheduleAlternateTasksTest("1_0", 1, 0);
437 RunScheduleAlternateTasksTest("32_0", 32, 0);
438 RunScheduleAlternateTasksTest("1_1", 1, 1);
439 RunScheduleAlternateTasksTest("32_1", 32, 1);
440 RunScheduleAlternateTasksTest("1_4", 1, 4);
441 RunScheduleAlternateTasksTest("32_4", 32, 4);
444 TEST_P(TileTaskWorkerPoolPerfTest
, ScheduleAndExecuteTasks
) {
445 RunScheduleAndExecuteTasksTest("1_0", 1, 0);
446 RunScheduleAndExecuteTasksTest("32_0", 32, 0);
447 RunScheduleAndExecuteTasksTest("1_1", 1, 1);
448 RunScheduleAndExecuteTasksTest("32_1", 32, 1);
449 RunScheduleAndExecuteTasksTest("1_4", 1, 4);
450 RunScheduleAndExecuteTasksTest("32_4", 32, 4);
453 INSTANTIATE_TEST_CASE_P(TileTaskWorkerPoolPerfTests
,
454 TileTaskWorkerPoolPerfTest
,
455 ::testing::Values(TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY
,
456 TILE_TASK_WORKER_POOL_TYPE_ONE_COPY
,
457 TILE_TASK_WORKER_POOL_TYPE_GPU
,
458 TILE_TASK_WORKER_POOL_TYPE_BITMAP
));
460 class TileTaskWorkerPoolCommonPerfTest
: public TileTaskWorkerPoolPerfTestBase
,
461 public testing::Test
{
463 // Overridden from testing::Test:
464 void SetUp() override
{
465 output_surface_
= FakeOutputSurface::Create3d(context_provider_
).Pass();
466 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
468 FakeResourceProvider::Create(output_surface_
.get(), nullptr);
471 void RunBuildTileTaskQueueTest(const std::string
& test_name
,
472 unsigned num_raster_tasks
,
473 unsigned num_image_decode_tasks
) {
474 ImageDecodeTask::Vector image_decode_tasks
;
475 RasterTaskVector raster_tasks
;
476 CreateImageDecodeTasks(num_image_decode_tasks
, &image_decode_tasks
);
477 CreateRasterTasks(num_raster_tasks
, image_decode_tasks
, &raster_tasks
);
479 // Avoid unnecessary heap allocations by reusing the same queue.
485 BuildTileTaskQueue(&queue
, raster_tasks
);
487 } while (!timer_
.HasTimeLimitExpired());
489 perf_test::PrintResult("build_raster_task_queue", "", test_name
,
490 timer_
.LapsPerSecond(), "runs/s", true);
494 TEST_F(TileTaskWorkerPoolCommonPerfTest
, BuildTileTaskQueue
) {
495 RunBuildTileTaskQueueTest("1_0", 1, 0);
496 RunBuildTileTaskQueueTest("32_0", 32, 0);
497 RunBuildTileTaskQueueTest("1_1", 1, 1);
498 RunBuildTileTaskQueueTest("32_1", 32, 1);
499 RunBuildTileTaskQueueTest("1_4", 1, 4);
500 RunBuildTileTaskQueueTest("32_4", 32, 4);