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
{ Reset(); }
139 did_complete_
= false;
143 ~PerfImageDecodeTaskImpl() override
{}
146 DISALLOW_COPY_AND_ASSIGN(PerfImageDecodeTaskImpl
);
149 class PerfRasterTaskImpl
: public RasterTask
{
151 PerfRasterTaskImpl(scoped_ptr
<ScopedResource
> resource
,
152 ImageDecodeTask::Vector
* dependencies
)
153 : RasterTask(dependencies
), resource_(resource
.Pass()) {}
155 // Overridden from Task:
156 void RunOnWorkerThread() override
{}
158 // Overridden from TileTask:
159 void ScheduleOnOriginThread(TileTaskClient
* client
) override
{
160 // No tile ids are given to support partial updates.
161 raster_buffer_
= client
->AcquireBufferForRaster(resource_
.get(), 0, 0);
163 void CompleteOnOriginThread(TileTaskClient
* client
) override
{
164 client
->ReleaseBufferForRaster(raster_buffer_
.Pass());
170 did_complete_
= false;
174 ~PerfRasterTaskImpl() override
{}
177 scoped_ptr
<ScopedResource
> resource_
;
178 scoped_ptr
<RasterBuffer
> raster_buffer_
;
180 DISALLOW_COPY_AND_ASSIGN(PerfRasterTaskImpl
);
183 class TileTaskWorkerPoolPerfTestBase
{
185 typedef std::vector
<scoped_refptr
<RasterTask
>> RasterTaskVector
;
187 enum NamedTaskSet
{ REQUIRED_FOR_ACTIVATION
, REQUIRED_FOR_DRAW
, ALL
};
189 TileTaskWorkerPoolPerfTestBase()
190 : context_provider_(make_scoped_refptr(new PerfContextProvider
)),
191 task_runner_(new base::TestSimpleTaskRunner
),
192 task_graph_runner_(new TaskGraphRunner
),
194 base::TimeDelta::FromMilliseconds(kTimeLimitMillis
),
195 kTimeCheckInterval
) {}
197 void CreateImageDecodeTasks(unsigned num_image_decode_tasks
,
198 ImageDecodeTask::Vector
* image_decode_tasks
) {
199 for (unsigned i
= 0; i
< num_image_decode_tasks
; ++i
)
200 image_decode_tasks
->push_back(new PerfImageDecodeTaskImpl
);
203 void CreateRasterTasks(unsigned num_raster_tasks
,
204 const ImageDecodeTask::Vector
& image_decode_tasks
,
205 RasterTaskVector
* raster_tasks
) {
206 const gfx::Size
size(1, 1);
208 for (unsigned i
= 0; i
< num_raster_tasks
; ++i
) {
209 scoped_ptr
<ScopedResource
> resource(
210 ScopedResource::Create(resource_provider_
.get()));
211 resource
->Allocate(size
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
214 ImageDecodeTask::Vector dependencies
= image_decode_tasks
;
215 raster_tasks
->push_back(
216 new PerfRasterTaskImpl(resource
.Pass(), &dependencies
));
220 void BuildTileTaskQueue(TileTaskQueue
* queue
,
221 const RasterTaskVector
& raster_tasks
) {
222 for (size_t i
= 0u; i
< raster_tasks
.size(); ++i
) {
223 bool required_for_activation
= (i
% 2) == 0;
224 TaskSetCollection task_set_collection
;
225 task_set_collection
[ALL
] = true;
226 task_set_collection
[REQUIRED_FOR_ACTIVATION
] = required_for_activation
;
227 queue
->items
.push_back(
228 TileTaskQueue::Item(raster_tasks
[i
].get(), task_set_collection
));
233 scoped_refptr
<ContextProvider
> context_provider_
;
234 FakeOutputSurfaceClient output_surface_client_
;
235 scoped_ptr
<FakeOutputSurface
> output_surface_
;
236 scoped_ptr
<ResourceProvider
> resource_provider_
;
237 scoped_refptr
<base::TestSimpleTaskRunner
> task_runner_
;
238 scoped_ptr
<TaskGraphRunner
> task_graph_runner_
;
242 class TileTaskWorkerPoolPerfTest
243 : public TileTaskWorkerPoolPerfTestBase
,
244 public testing::TestWithParam
<TileTaskWorkerPoolType
>,
245 public TileTaskRunnerClient
{
247 // Overridden from testing::Test:
248 void SetUp() override
{
249 switch (GetParam()) {
250 case TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY
:
251 Create3dOutputSurfaceAndResourceProvider();
252 tile_task_worker_pool_
= ZeroCopyTileTaskWorkerPool::Create(
253 task_runner_
.get(), task_graph_runner_
.get(),
254 resource_provider_
.get());
256 case TILE_TASK_WORKER_POOL_TYPE_ONE_COPY
:
257 Create3dOutputSurfaceAndResourceProvider();
258 tile_task_worker_pool_
= OneCopyTileTaskWorkerPool::Create(
259 task_runner_
.get(), task_graph_runner_
.get(),
260 context_provider_
.get(), resource_provider_
.get(),
261 std::numeric_limits
<int>::max(), false,
262 std::numeric_limits
<int>::max());
264 case TILE_TASK_WORKER_POOL_TYPE_GPU
:
265 Create3dOutputSurfaceAndResourceProvider();
266 tile_task_worker_pool_
= GpuTileTaskWorkerPool::Create(
267 task_runner_
.get(), task_graph_runner_
.get(),
268 context_provider_
.get(), resource_provider_
.get(), false, 0);
270 case TILE_TASK_WORKER_POOL_TYPE_BITMAP
:
271 CreateSoftwareOutputSurfaceAndResourceProvider();
272 tile_task_worker_pool_
= BitmapTileTaskWorkerPool::Create(
273 task_runner_
.get(), task_graph_runner_
.get(),
274 resource_provider_
.get());
278 DCHECK(tile_task_worker_pool_
);
279 tile_task_worker_pool_
->AsTileTaskRunner()->SetClient(this);
281 void TearDown() override
{
282 tile_task_worker_pool_
->AsTileTaskRunner()->Shutdown();
283 tile_task_worker_pool_
->AsTileTaskRunner()->CheckForCompletedTasks();
286 // Overriden from TileTaskRunnerClient:
287 void DidFinishRunningTileTasks(TaskSet task_set
) override
{
288 tile_task_worker_pool_
->AsTileTaskRunner()->CheckForCompletedTasks();
291 void RunMessageLoopUntilAllTasksHaveCompleted() {
292 task_graph_runner_
->RunUntilIdle();
293 task_runner_
->RunUntilIdle();
296 void RunScheduleTasksTest(const std::string
& test_name
,
297 unsigned num_raster_tasks
,
298 unsigned num_image_decode_tasks
) {
299 ImageDecodeTask::Vector image_decode_tasks
;
300 RasterTaskVector raster_tasks
;
301 CreateImageDecodeTasks(num_image_decode_tasks
, &image_decode_tasks
);
302 CreateRasterTasks(num_raster_tasks
, image_decode_tasks
, &raster_tasks
);
304 // Avoid unnecessary heap allocations by reusing the same queue.
310 BuildTileTaskQueue(&queue
, raster_tasks
);
311 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&queue
);
312 tile_task_worker_pool_
->AsTileTaskRunner()->CheckForCompletedTasks();
314 } while (!timer_
.HasTimeLimitExpired());
317 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&empty
);
318 RunMessageLoopUntilAllTasksHaveCompleted();
320 perf_test::PrintResult("schedule_tasks", TestModifierString(), test_name
,
321 timer_
.LapsPerSecond(), "runs/s", true);
324 void RunScheduleAlternateTasksTest(const std::string
& test_name
,
325 unsigned num_raster_tasks
,
326 unsigned num_image_decode_tasks
) {
327 const size_t kNumVersions
= 2;
328 ImageDecodeTask::Vector image_decode_tasks
[kNumVersions
];
329 RasterTaskVector raster_tasks
[kNumVersions
];
330 for (size_t i
= 0; i
< kNumVersions
; ++i
) {
331 CreateImageDecodeTasks(num_image_decode_tasks
, &image_decode_tasks
[i
]);
332 CreateRasterTasks(num_raster_tasks
, image_decode_tasks
[i
],
336 // Avoid unnecessary heap allocations by reusing the same queue.
343 BuildTileTaskQueue(&queue
, raster_tasks
[count
% kNumVersions
]);
344 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&queue
);
345 tile_task_worker_pool_
->AsTileTaskRunner()->CheckForCompletedTasks();
348 } while (!timer_
.HasTimeLimitExpired());
351 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&empty
);
352 RunMessageLoopUntilAllTasksHaveCompleted();
354 perf_test::PrintResult("schedule_alternate_tasks", TestModifierString(),
355 test_name
, timer_
.LapsPerSecond(), "runs/s", true);
358 void RunScheduleAndExecuteTasksTest(const std::string
& test_name
,
359 unsigned num_raster_tasks
,
360 unsigned num_image_decode_tasks
) {
361 ImageDecodeTask::Vector image_decode_tasks
;
362 RasterTaskVector raster_tasks
;
363 CreateImageDecodeTasks(num_image_decode_tasks
, &image_decode_tasks
);
364 CreateRasterTasks(num_raster_tasks
, image_decode_tasks
, &raster_tasks
);
366 // Avoid unnecessary heap allocations by reusing the same queue.
372 BuildTileTaskQueue(&queue
, raster_tasks
);
373 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&queue
);
374 RunMessageLoopUntilAllTasksHaveCompleted();
376 } while (!timer_
.HasTimeLimitExpired());
379 tile_task_worker_pool_
->AsTileTaskRunner()->ScheduleTasks(&empty
);
380 RunMessageLoopUntilAllTasksHaveCompleted();
382 perf_test::PrintResult("schedule_and_execute_tasks", TestModifierString(),
383 test_name
, timer_
.LapsPerSecond(), "runs/s", true);
387 void Create3dOutputSurfaceAndResourceProvider() {
388 output_surface_
= FakeOutputSurface::Create3d(context_provider_
).Pass();
389 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
390 resource_provider_
= FakeResourceProvider::Create(
391 output_surface_
.get(), nullptr, &gpu_memory_buffer_manager_
);
394 void CreateSoftwareOutputSurfaceAndResourceProvider() {
395 output_surface_
= FakeOutputSurface::CreateSoftware(
396 make_scoped_ptr(new SoftwareOutputDevice
));
397 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
398 resource_provider_
= FakeResourceProvider::Create(
399 output_surface_
.get(), &shared_bitmap_manager_
, nullptr);
402 std::string
TestModifierString() const {
403 switch (GetParam()) {
404 case TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY
:
405 return std::string("_zero_copy_tile_task_worker_pool");
406 case TILE_TASK_WORKER_POOL_TYPE_ONE_COPY
:
407 return std::string("_one_copy_tile_task_worker_pool");
408 case TILE_TASK_WORKER_POOL_TYPE_GPU
:
409 return std::string("_gpu_tile_task_worker_pool");
410 case TILE_TASK_WORKER_POOL_TYPE_BITMAP
:
411 return std::string("_bitmap_tile_task_worker_pool");
414 return std::string();
417 scoped_ptr
<TileTaskWorkerPool
> tile_task_worker_pool_
;
418 TestGpuMemoryBufferManager gpu_memory_buffer_manager_
;
419 TestSharedBitmapManager shared_bitmap_manager_
;
422 TEST_P(TileTaskWorkerPoolPerfTest
, ScheduleTasks
) {
423 RunScheduleTasksTest("1_0", 1, 0);
424 RunScheduleTasksTest("32_0", 32, 0);
425 RunScheduleTasksTest("1_1", 1, 1);
426 RunScheduleTasksTest("32_1", 32, 1);
427 RunScheduleTasksTest("1_4", 1, 4);
428 RunScheduleTasksTest("32_4", 32, 4);
431 TEST_P(TileTaskWorkerPoolPerfTest
, ScheduleAlternateTasks
) {
432 RunScheduleAlternateTasksTest("1_0", 1, 0);
433 RunScheduleAlternateTasksTest("32_0", 32, 0);
434 RunScheduleAlternateTasksTest("1_1", 1, 1);
435 RunScheduleAlternateTasksTest("32_1", 32, 1);
436 RunScheduleAlternateTasksTest("1_4", 1, 4);
437 RunScheduleAlternateTasksTest("32_4", 32, 4);
440 TEST_P(TileTaskWorkerPoolPerfTest
, ScheduleAndExecuteTasks
) {
441 RunScheduleAndExecuteTasksTest("1_0", 1, 0);
442 RunScheduleAndExecuteTasksTest("32_0", 32, 0);
443 RunScheduleAndExecuteTasksTest("1_1", 1, 1);
444 RunScheduleAndExecuteTasksTest("32_1", 32, 1);
445 RunScheduleAndExecuteTasksTest("1_4", 1, 4);
446 RunScheduleAndExecuteTasksTest("32_4", 32, 4);
449 INSTANTIATE_TEST_CASE_P(TileTaskWorkerPoolPerfTests
,
450 TileTaskWorkerPoolPerfTest
,
451 ::testing::Values(TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY
,
452 TILE_TASK_WORKER_POOL_TYPE_ONE_COPY
,
453 TILE_TASK_WORKER_POOL_TYPE_GPU
,
454 TILE_TASK_WORKER_POOL_TYPE_BITMAP
));
456 class TileTaskWorkerPoolCommonPerfTest
: public TileTaskWorkerPoolPerfTestBase
,
457 public testing::Test
{
459 // Overridden from testing::Test:
460 void SetUp() override
{
461 output_surface_
= FakeOutputSurface::Create3d(context_provider_
).Pass();
462 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
464 FakeResourceProvider::Create(output_surface_
.get(), nullptr);
467 void RunBuildTileTaskQueueTest(const std::string
& test_name
,
468 unsigned num_raster_tasks
,
469 unsigned num_image_decode_tasks
) {
470 ImageDecodeTask::Vector image_decode_tasks
;
471 RasterTaskVector raster_tasks
;
472 CreateImageDecodeTasks(num_image_decode_tasks
, &image_decode_tasks
);
473 CreateRasterTasks(num_raster_tasks
, image_decode_tasks
, &raster_tasks
);
475 // Avoid unnecessary heap allocations by reusing the same queue.
481 BuildTileTaskQueue(&queue
, raster_tasks
);
483 } while (!timer_
.HasTimeLimitExpired());
485 perf_test::PrintResult("build_raster_task_queue", "", test_name
,
486 timer_
.LapsPerSecond(), "runs/s", true);
490 TEST_F(TileTaskWorkerPoolCommonPerfTest
, BuildTileTaskQueue
) {
491 RunBuildTileTaskQueueTest("1_0", 1, 0);
492 RunBuildTileTaskQueueTest("32_0", 32, 0);
493 RunBuildTileTaskQueueTest("1_1", 1, 1);
494 RunBuildTileTaskQueueTest("32_1", 32, 1);
495 RunBuildTileTaskQueueTest("1_4", 1, 4);
496 RunBuildTileTaskQueueTest("32_4", 32, 4);