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/raster_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_raster_worker_pool.h"
12 #include "cc/resources/gpu_raster_worker_pool.h"
13 #include "cc/resources/one_copy_raster_worker_pool.h"
14 #include "cc/resources/pixel_buffer_raster_worker_pool.h"
15 #include "cc/resources/raster_buffer.h"
16 #include "cc/resources/rasterizer.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/zero_copy_raster_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"
34 class PerfGLES2Interface
: public gpu::gles2::GLES2InterfaceStub
{
35 // Overridden from gpu::gles2::GLES2Interface:
36 virtual GLuint
CreateImageCHROMIUM(ClientBuffer buffer
,
39 GLenum internalformat
) override
{
42 virtual void GenBuffers(GLsizei n
, GLuint
* buffers
) override
{
43 for (GLsizei i
= 0; i
< n
; ++i
)
46 virtual void GenTextures(GLsizei n
, GLuint
* textures
) override
{
47 for (GLsizei i
= 0; i
< n
; ++i
)
50 virtual void GetIntegerv(GLenum pname
, GLint
* params
) override
{
51 if (pname
== GL_MAX_TEXTURE_SIZE
)
54 virtual void GenQueriesEXT(GLsizei n
, GLuint
* queries
) override
{
55 for (GLsizei i
= 0; i
< n
; ++i
)
58 virtual void GetQueryObjectuivEXT(GLuint query
,
60 GLuint
* params
) override
{
61 if (pname
== GL_QUERY_RESULT_AVAILABLE_EXT
)
66 class PerfContextProvider
: public ContextProvider
{
68 PerfContextProvider() : context_gl_(new PerfGLES2Interface
) {}
70 virtual bool BindToCurrentThread() override
{ return true; }
71 virtual Capabilities
ContextCapabilities() override
{
72 Capabilities capabilities
;
73 capabilities
.gpu
.image
= true;
74 capabilities
.gpu
.sync_query
= true;
77 virtual gpu::gles2::GLES2Interface
* ContextGL() override
{
78 return context_gl_
.get();
80 virtual gpu::ContextSupport
* ContextSupport() override
{ return &support_
; }
81 virtual class GrContext
* GrContext() override
{ return NULL
; }
82 virtual bool IsContextLost() override
{ return false; }
83 virtual void VerifyContexts() override
{}
84 virtual void DeleteCachedResources() override
{}
85 virtual bool DestroyedOnMainThread() override
{ return false; }
86 virtual void SetLostContextCallback(const LostContextCallback
& cb
) override
{}
87 virtual void SetMemoryPolicyChangedCallback(
88 const MemoryPolicyChangedCallback
& cb
) override
{}
91 virtual ~PerfContextProvider() {}
93 scoped_ptr
<PerfGLES2Interface
> context_gl_
;
94 TestContextSupport support_
;
97 enum RasterWorkerPoolType
{
98 RASTER_WORKER_POOL_TYPE_PIXEL_BUFFER
,
99 RASTER_WORKER_POOL_TYPE_ZERO_COPY
,
100 RASTER_WORKER_POOL_TYPE_ONE_COPY
,
101 RASTER_WORKER_POOL_TYPE_GPU
,
102 RASTER_WORKER_POOL_TYPE_BITMAP
105 static const int kTimeLimitMillis
= 2000;
106 static const int kWarmupRuns
= 5;
107 static const int kTimeCheckInterval
= 10;
109 class PerfImageDecodeTaskImpl
: public ImageDecodeTask
{
111 PerfImageDecodeTaskImpl() {}
113 // Overridden from Task:
114 virtual void RunOnWorkerThread() override
{}
116 // Overridden from RasterizerTask:
117 virtual void ScheduleOnOriginThread(RasterizerTaskClient
* client
) override
{}
118 virtual void CompleteOnOriginThread(RasterizerTaskClient
* client
) override
{}
119 virtual void RunReplyOnOriginThread() override
{ Reset(); }
123 did_complete_
= false;
127 virtual ~PerfImageDecodeTaskImpl() {}
130 DISALLOW_COPY_AND_ASSIGN(PerfImageDecodeTaskImpl
);
133 class PerfRasterTaskImpl
: public RasterTask
{
135 PerfRasterTaskImpl(scoped_ptr
<ScopedResource
> resource
,
136 ImageDecodeTask::Vector
* dependencies
)
137 : RasterTask(resource
.get(), dependencies
), resource_(resource
.Pass()) {}
139 // Overridden from Task:
140 virtual void RunOnWorkerThread() override
{}
142 // Overridden from RasterizerTask:
143 virtual void ScheduleOnOriginThread(RasterizerTaskClient
* client
) override
{
144 raster_buffer_
= client
->AcquireBufferForRaster(resource());
146 virtual void CompleteOnOriginThread(RasterizerTaskClient
* client
) override
{
147 client
->ReleaseBufferForRaster(raster_buffer_
.Pass());
149 virtual void RunReplyOnOriginThread() override
{ Reset(); }
153 did_complete_
= false;
157 virtual ~PerfRasterTaskImpl() {}
160 scoped_ptr
<ScopedResource
> resource_
;
161 scoped_ptr
<RasterBuffer
> raster_buffer_
;
163 DISALLOW_COPY_AND_ASSIGN(PerfRasterTaskImpl
);
166 class RasterWorkerPoolPerfTestBase
{
168 typedef std::vector
<scoped_refptr
<RasterTask
>> RasterTaskVector
;
170 enum NamedTaskSet
{ REQUIRED_FOR_ACTIVATION
= 0, ALL
= 1 };
172 RasterWorkerPoolPerfTestBase()
173 : context_provider_(make_scoped_refptr(new PerfContextProvider
)),
174 task_runner_(new base::TestSimpleTaskRunner
),
175 task_graph_runner_(new TaskGraphRunner
),
177 base::TimeDelta::FromMilliseconds(kTimeLimitMillis
),
178 kTimeCheckInterval
) {}
180 void CreateImageDecodeTasks(unsigned num_image_decode_tasks
,
181 ImageDecodeTask::Vector
* image_decode_tasks
) {
182 for (unsigned i
= 0; i
< num_image_decode_tasks
; ++i
)
183 image_decode_tasks
->push_back(new PerfImageDecodeTaskImpl
);
186 void CreateRasterTasks(unsigned num_raster_tasks
,
187 const ImageDecodeTask::Vector
& image_decode_tasks
,
188 RasterTaskVector
* raster_tasks
) {
189 const gfx::Size
size(1, 1);
191 for (unsigned i
= 0; i
< num_raster_tasks
; ++i
) {
192 scoped_ptr
<ScopedResource
> resource(
193 ScopedResource::Create(resource_provider_
.get()));
195 size
, ResourceProvider::TextureHintImmutable
, RGBA_8888
);
197 ImageDecodeTask::Vector dependencies
= image_decode_tasks
;
198 raster_tasks
->push_back(
199 new PerfRasterTaskImpl(resource
.Pass(), &dependencies
));
203 void BuildRasterTaskQueue(RasterTaskQueue
* queue
,
204 const RasterTaskVector
& raster_tasks
) {
205 for (size_t i
= 0u; i
< raster_tasks
.size(); ++i
) {
206 bool required_for_activation
= (i
% 2) == 0;
207 TaskSetCollection task_set_collection
;
208 task_set_collection
[ALL
] = true;
209 task_set_collection
[REQUIRED_FOR_ACTIVATION
] = required_for_activation
;
210 queue
->items
.push_back(
211 RasterTaskQueue::Item(raster_tasks
[i
].get(), task_set_collection
));
216 scoped_refptr
<ContextProvider
> context_provider_
;
217 FakeOutputSurfaceClient output_surface_client_
;
218 scoped_ptr
<FakeOutputSurface
> output_surface_
;
219 scoped_ptr
<ResourceProvider
> resource_provider_
;
220 scoped_refptr
<base::TestSimpleTaskRunner
> task_runner_
;
221 scoped_ptr
<TaskGraphRunner
> task_graph_runner_
;
225 class RasterWorkerPoolPerfTest
226 : public RasterWorkerPoolPerfTestBase
,
227 public testing::TestWithParam
<RasterWorkerPoolType
>,
228 public RasterizerClient
{
230 // Overridden from testing::Test:
231 virtual void SetUp() override
{
232 switch (GetParam()) {
233 case RASTER_WORKER_POOL_TYPE_PIXEL_BUFFER
:
234 Create3dOutputSurfaceAndResourceProvider();
235 raster_worker_pool_
= PixelBufferRasterWorkerPool::Create(
237 task_graph_runner_
.get(),
238 context_provider_
.get(),
239 resource_provider_
.get(),
240 std::numeric_limits
<size_t>::max());
242 case RASTER_WORKER_POOL_TYPE_ZERO_COPY
:
243 Create3dOutputSurfaceAndResourceProvider();
244 raster_worker_pool_
=
245 ZeroCopyRasterWorkerPool::Create(task_runner_
.get(),
246 task_graph_runner_
.get(),
247 resource_provider_
.get());
249 case RASTER_WORKER_POOL_TYPE_ONE_COPY
:
250 Create3dOutputSurfaceAndResourceProvider();
251 staging_resource_pool_
= ResourcePool::Create(
252 resource_provider_
.get(), GL_TEXTURE_2D
, RGBA_8888
);
253 raster_worker_pool_
=
254 OneCopyRasterWorkerPool::Create(task_runner_
.get(),
255 task_graph_runner_
.get(),
256 context_provider_
.get(),
257 resource_provider_
.get(),
258 staging_resource_pool_
.get());
260 case RASTER_WORKER_POOL_TYPE_GPU
:
261 Create3dOutputSurfaceAndResourceProvider();
262 raster_worker_pool_
=
263 GpuRasterWorkerPool::Create(task_runner_
.get(),
264 context_provider_
.get(),
265 resource_provider_
.get());
267 case RASTER_WORKER_POOL_TYPE_BITMAP
:
268 CreateSoftwareOutputSurfaceAndResourceProvider();
269 raster_worker_pool_
=
270 BitmapRasterWorkerPool::Create(task_runner_
.get(),
271 task_graph_runner_
.get(),
272 resource_provider_
.get());
276 DCHECK(raster_worker_pool_
);
277 raster_worker_pool_
->AsRasterizer()->SetClient(this);
279 virtual void TearDown() override
{
280 raster_worker_pool_
->AsRasterizer()->Shutdown();
281 raster_worker_pool_
->AsRasterizer()->CheckForCompletedTasks();
284 // Overriden from RasterizerClient:
285 virtual void DidFinishRunningTasks(TaskSet task_set
) override
{
286 raster_worker_pool_
->AsRasterizer()->CheckForCompletedTasks();
288 virtual TaskSetCollection
TasksThatShouldBeForcedToComplete() const override
{
289 return TaskSetCollection();
292 void RunMessageLoopUntilAllTasksHaveCompleted() {
293 task_graph_runner_
->RunUntilIdle();
294 task_runner_
->RunUntilIdle();
297 void RunScheduleTasksTest(const std::string
& test_name
,
298 unsigned num_raster_tasks
,
299 unsigned num_image_decode_tasks
) {
300 ImageDecodeTask::Vector image_decode_tasks
;
301 RasterTaskVector raster_tasks
;
302 CreateImageDecodeTasks(num_image_decode_tasks
, &image_decode_tasks
);
303 CreateRasterTasks(num_raster_tasks
, image_decode_tasks
, &raster_tasks
);
305 // Avoid unnecessary heap allocations by reusing the same queue.
306 RasterTaskQueue queue
;
311 BuildRasterTaskQueue(&queue
, raster_tasks
);
312 raster_worker_pool_
->AsRasterizer()->ScheduleTasks(&queue
);
313 raster_worker_pool_
->AsRasterizer()->CheckForCompletedTasks();
315 } while (!timer_
.HasTimeLimitExpired());
317 RasterTaskQueue empty
;
318 raster_worker_pool_
->AsRasterizer()->ScheduleTasks(&empty
);
319 RunMessageLoopUntilAllTasksHaveCompleted();
321 perf_test::PrintResult("schedule_tasks",
322 TestModifierString(),
324 timer_
.LapsPerSecond(),
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
]);
338 num_raster_tasks
, image_decode_tasks
[i
], &raster_tasks
[i
]);
341 // Avoid unnecessary heap allocations by reusing the same queue.
342 RasterTaskQueue queue
;
348 BuildRasterTaskQueue(&queue
, raster_tasks
[count
% kNumVersions
]);
349 raster_worker_pool_
->AsRasterizer()->ScheduleTasks(&queue
);
350 raster_worker_pool_
->AsRasterizer()->CheckForCompletedTasks();
353 } while (!timer_
.HasTimeLimitExpired());
355 RasterTaskQueue empty
;
356 raster_worker_pool_
->AsRasterizer()->ScheduleTasks(&empty
);
357 RunMessageLoopUntilAllTasksHaveCompleted();
359 perf_test::PrintResult("schedule_alternate_tasks",
360 TestModifierString(),
362 timer_
.LapsPerSecond(),
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.
376 RasterTaskQueue queue
;
381 BuildRasterTaskQueue(&queue
, raster_tasks
);
382 raster_worker_pool_
->AsRasterizer()->ScheduleTasks(&queue
);
383 RunMessageLoopUntilAllTasksHaveCompleted();
385 } while (!timer_
.HasTimeLimitExpired());
387 RasterTaskQueue empty
;
388 raster_worker_pool_
->AsRasterizer()->ScheduleTasks(&empty
);
389 RunMessageLoopUntilAllTasksHaveCompleted();
391 perf_test::PrintResult("schedule_and_execute_tasks",
392 TestModifierString(),
394 timer_
.LapsPerSecond(),
400 void Create3dOutputSurfaceAndResourceProvider() {
401 output_surface_
= FakeOutputSurface::Create3d(context_provider_
).Pass();
402 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
403 resource_provider_
= ResourceProvider::Create(output_surface_
.get(),
405 &gpu_memory_buffer_manager_
,
413 void CreateSoftwareOutputSurfaceAndResourceProvider() {
414 output_surface_
= FakeOutputSurface::CreateSoftware(
415 make_scoped_ptr(new SoftwareOutputDevice
));
416 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
417 resource_provider_
= ResourceProvider::Create(output_surface_
.get(),
418 &shared_bitmap_manager_
,
427 std::string
TestModifierString() const {
428 switch (GetParam()) {
429 case RASTER_WORKER_POOL_TYPE_PIXEL_BUFFER
:
430 return std::string("_pixel_raster_worker_pool");
431 case RASTER_WORKER_POOL_TYPE_ZERO_COPY
:
432 return std::string("_zero_copy_raster_worker_pool");
433 case RASTER_WORKER_POOL_TYPE_ONE_COPY
:
434 return std::string("_one_copy_raster_worker_pool");
435 case RASTER_WORKER_POOL_TYPE_GPU
:
436 return std::string("_gpu_raster_worker_pool");
437 case RASTER_WORKER_POOL_TYPE_BITMAP
:
438 return std::string("_bitmap_raster_worker_pool");
441 return std::string();
444 scoped_ptr
<ResourcePool
> staging_resource_pool_
;
445 scoped_ptr
<RasterWorkerPool
> raster_worker_pool_
;
446 TestGpuMemoryBufferManager gpu_memory_buffer_manager_
;
447 TestSharedBitmapManager shared_bitmap_manager_
;
450 TEST_P(RasterWorkerPoolPerfTest
, ScheduleTasks
) {
451 RunScheduleTasksTest("1_0", 1, 0);
452 RunScheduleTasksTest("32_0", 32, 0);
453 RunScheduleTasksTest("1_1", 1, 1);
454 RunScheduleTasksTest("32_1", 32, 1);
455 RunScheduleTasksTest("1_4", 1, 4);
456 RunScheduleTasksTest("32_4", 32, 4);
459 TEST_P(RasterWorkerPoolPerfTest
, ScheduleAlternateTasks
) {
460 RunScheduleAlternateTasksTest("1_0", 1, 0);
461 RunScheduleAlternateTasksTest("32_0", 32, 0);
462 RunScheduleAlternateTasksTest("1_1", 1, 1);
463 RunScheduleAlternateTasksTest("32_1", 32, 1);
464 RunScheduleAlternateTasksTest("1_4", 1, 4);
465 RunScheduleAlternateTasksTest("32_4", 32, 4);
468 TEST_P(RasterWorkerPoolPerfTest
, ScheduleAndExecuteTasks
) {
469 RunScheduleAndExecuteTasksTest("1_0", 1, 0);
470 RunScheduleAndExecuteTasksTest("32_0", 32, 0);
471 RunScheduleAndExecuteTasksTest("1_1", 1, 1);
472 RunScheduleAndExecuteTasksTest("32_1", 32, 1);
473 RunScheduleAndExecuteTasksTest("1_4", 1, 4);
474 RunScheduleAndExecuteTasksTest("32_4", 32, 4);
477 INSTANTIATE_TEST_CASE_P(RasterWorkerPoolPerfTests
,
478 RasterWorkerPoolPerfTest
,
479 ::testing::Values(RASTER_WORKER_POOL_TYPE_PIXEL_BUFFER
,
480 RASTER_WORKER_POOL_TYPE_ZERO_COPY
,
481 RASTER_WORKER_POOL_TYPE_ONE_COPY
,
482 RASTER_WORKER_POOL_TYPE_GPU
,
483 RASTER_WORKER_POOL_TYPE_BITMAP
));
485 class RasterWorkerPoolCommonPerfTest
: public RasterWorkerPoolPerfTestBase
,
486 public testing::Test
{
488 // Overridden from testing::Test:
489 virtual void SetUp() override
{
490 output_surface_
= FakeOutputSurface::Create3d(context_provider_
).Pass();
491 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
493 ResourceProvider::Create(
494 output_surface_
.get(), NULL
, NULL
, NULL
, 0, false, 1, false).Pass();
497 void RunBuildRasterTaskQueueTest(const std::string
& test_name
,
498 unsigned num_raster_tasks
,
499 unsigned num_image_decode_tasks
) {
500 ImageDecodeTask::Vector image_decode_tasks
;
501 RasterTaskVector raster_tasks
;
502 CreateImageDecodeTasks(num_image_decode_tasks
, &image_decode_tasks
);
503 CreateRasterTasks(num_raster_tasks
, image_decode_tasks
, &raster_tasks
);
505 // Avoid unnecessary heap allocations by reusing the same queue.
506 RasterTaskQueue queue
;
511 BuildRasterTaskQueue(&queue
, raster_tasks
);
513 } while (!timer_
.HasTimeLimitExpired());
515 perf_test::PrintResult("build_raster_task_queue",
518 timer_
.LapsPerSecond(),
524 TEST_F(RasterWorkerPoolCommonPerfTest
, BuildRasterTaskQueue
) {
525 RunBuildRasterTaskQueueTest("1_0", 1, 0);
526 RunBuildRasterTaskQueueTest("32_0", 32, 0);
527 RunBuildRasterTaskQueueTest("1_1", 1, 1);
528 RunBuildRasterTaskQueueTest("32_1", 32, 1);
529 RunBuildRasterTaskQueueTest("1_4", 1, 4);
530 RunBuildRasterTaskQueueTest("32_4", 32, 4);