• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "cc/resources/raster_worker_pool.h"
6 
7 #include "base/time/time.h"
8 #include "cc/debug/lap_timer.h"
9 #include "cc/output/context_provider.h"
10 #include "cc/resources/direct_raster_worker_pool.h"
11 #include "cc/resources/image_copy_raster_worker_pool.h"
12 #include "cc/resources/image_raster_worker_pool.h"
13 #include "cc/resources/pixel_buffer_raster_worker_pool.h"
14 #include "cc/resources/rasterizer.h"
15 #include "cc/resources/resource_pool.h"
16 #include "cc/resources/resource_provider.h"
17 #include "cc/resources/scoped_resource.h"
18 #include "cc/test/fake_output_surface.h"
19 #include "cc/test/fake_output_surface_client.h"
20 #include "cc/test/test_context_support.h"
21 #include "cc/test/test_shared_bitmap_manager.h"
22 #include "cc/test/test_web_graphics_context_3d.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24 #include "testing/perf/perf_test.h"
25 #include "third_party/khronos/GLES2/gl2.h"
26 
27 namespace cc {
28 namespace {
29 
30 class PerfGLES2Interface : public gpu::gles2::GLES2InterfaceStub {
31   // Overridden from gpu::gles2::GLES2Interface:
CreateImageCHROMIUM(GLsizei width,GLsizei height,GLenum internalformat,GLenum usage)32   virtual GLuint CreateImageCHROMIUM(GLsizei width,
33                                      GLsizei height,
34                                      GLenum internalformat,
35                                      GLenum usage) OVERRIDE {
36     return 1u;
37   }
GenBuffers(GLsizei n,GLuint * buffers)38   virtual void GenBuffers(GLsizei n, GLuint* buffers) OVERRIDE {
39     for (GLsizei i = 0; i < n; ++i)
40       buffers[i] = 1u;
41   }
GenTextures(GLsizei n,GLuint * textures)42   virtual void GenTextures(GLsizei n, GLuint* textures) OVERRIDE {
43     for (GLsizei i = 0; i < n; ++i)
44       textures[i] = 1u;
45   }
GetIntegerv(GLenum pname,GLint * params)46   virtual void GetIntegerv(GLenum pname, GLint* params) OVERRIDE {
47     if (pname == GL_MAX_TEXTURE_SIZE)
48       *params = INT_MAX;
49   }
50 };
51 
52 class PerfContextProvider : public ContextProvider {
53  public:
PerfContextProvider()54   PerfContextProvider() : context_gl_(new PerfGLES2Interface) {}
55 
BindToCurrentThread()56   virtual bool BindToCurrentThread() OVERRIDE { return true; }
ContextCapabilities()57   virtual Capabilities ContextCapabilities() OVERRIDE { return Capabilities(); }
ContextGL()58   virtual gpu::gles2::GLES2Interface* ContextGL() OVERRIDE {
59     return context_gl_.get();
60   }
ContextSupport()61   virtual gpu::ContextSupport* ContextSupport() OVERRIDE { return &support_; }
GrContext()62   virtual class GrContext* GrContext() OVERRIDE { return NULL; }
IsContextLost()63   virtual bool IsContextLost() OVERRIDE { return false; }
VerifyContexts()64   virtual void VerifyContexts() OVERRIDE {}
DeleteCachedResources()65   virtual void DeleteCachedResources() OVERRIDE {}
DestroyedOnMainThread()66   virtual bool DestroyedOnMainThread() OVERRIDE { return false; }
SetLostContextCallback(const LostContextCallback & cb)67   virtual void SetLostContextCallback(const LostContextCallback& cb) OVERRIDE {}
SetMemoryPolicyChangedCallback(const MemoryPolicyChangedCallback & cb)68   virtual void SetMemoryPolicyChangedCallback(
69       const MemoryPolicyChangedCallback& cb) OVERRIDE {}
70 
71  private:
~PerfContextProvider()72   virtual ~PerfContextProvider() {}
73 
74   scoped_ptr<PerfGLES2Interface> context_gl_;
75   TestContextSupport support_;
76 };
77 
78 enum RasterWorkerPoolType {
79   RASTER_WORKER_POOL_TYPE_PIXEL_BUFFER,
80   RASTER_WORKER_POOL_TYPE_IMAGE,
81   RASTER_WORKER_POOL_TYPE_IMAGE_COPY,
82   RASTER_WORKER_POOL_TYPE_DIRECT
83 };
84 
85 static const int kTimeLimitMillis = 2000;
86 static const int kWarmupRuns = 5;
87 static const int kTimeCheckInterval = 10;
88 
89 class PerfImageDecodeTaskImpl : public ImageDecodeTask {
90  public:
PerfImageDecodeTaskImpl()91   PerfImageDecodeTaskImpl() {}
92 
93   // Overridden from Task:
RunOnWorkerThread()94   virtual void RunOnWorkerThread() OVERRIDE {}
95 
96   // Overridden from RasterizerTask:
ScheduleOnOriginThread(RasterizerTaskClient * client)97   virtual void ScheduleOnOriginThread(RasterizerTaskClient* client) OVERRIDE {}
CompleteOnOriginThread(RasterizerTaskClient * client)98   virtual void CompleteOnOriginThread(RasterizerTaskClient* client) OVERRIDE {}
RunReplyOnOriginThread()99   virtual void RunReplyOnOriginThread() OVERRIDE { Reset(); }
100 
Reset()101   void Reset() {
102     did_run_ = false;
103     did_complete_ = false;
104   }
105 
106  protected:
~PerfImageDecodeTaskImpl()107   virtual ~PerfImageDecodeTaskImpl() {}
108 
109  private:
110   DISALLOW_COPY_AND_ASSIGN(PerfImageDecodeTaskImpl);
111 };
112 
113 class PerfRasterTaskImpl : public RasterTask {
114  public:
PerfRasterTaskImpl(scoped_ptr<ScopedResource> resource,ImageDecodeTask::Vector * dependencies)115   PerfRasterTaskImpl(scoped_ptr<ScopedResource> resource,
116                      ImageDecodeTask::Vector* dependencies)
117       : RasterTask(resource.get(), dependencies), resource_(resource.Pass()) {}
118 
119   // Overridden from Task:
RunOnWorkerThread()120   virtual void RunOnWorkerThread() OVERRIDE {}
121 
122   // Overridden from RasterizerTask:
ScheduleOnOriginThread(RasterizerTaskClient * client)123   virtual void ScheduleOnOriginThread(RasterizerTaskClient* client) OVERRIDE {
124     client->AcquireCanvasForRaster(this);
125   }
CompleteOnOriginThread(RasterizerTaskClient * client)126   virtual void CompleteOnOriginThread(RasterizerTaskClient* client) OVERRIDE {
127     client->ReleaseCanvasForRaster(this);
128   }
RunReplyOnOriginThread()129   virtual void RunReplyOnOriginThread() OVERRIDE { Reset(); }
130 
Reset()131   void Reset() {
132     did_run_ = false;
133     did_complete_ = false;
134   }
135 
136  protected:
~PerfRasterTaskImpl()137   virtual ~PerfRasterTaskImpl() {}
138 
139  private:
140   scoped_ptr<ScopedResource> resource_;
141 
142   DISALLOW_COPY_AND_ASSIGN(PerfRasterTaskImpl);
143 };
144 
145 class RasterWorkerPoolPerfTestBase {
146  public:
147   typedef std::vector<scoped_refptr<RasterTask> > RasterTaskVector;
148 
RasterWorkerPoolPerfTestBase()149   RasterWorkerPoolPerfTestBase()
150       : context_provider_(make_scoped_refptr(new PerfContextProvider)),
151         task_graph_runner_(new TaskGraphRunner),
152         timer_(kWarmupRuns,
153                base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
154                kTimeCheckInterval) {
155     output_surface_ = FakeOutputSurface::Create3d(context_provider_).Pass();
156     CHECK(output_surface_->BindToClient(&output_surface_client_));
157 
158     shared_bitmap_manager_.reset(new TestSharedBitmapManager());
159     resource_provider_ =
160         ResourceProvider::Create(
161             output_surface_.get(), shared_bitmap_manager_.get(), 0, false, 1,
162             false).Pass();
163     staging_resource_pool_ = ResourcePool::Create(
164         resource_provider_.get(), GL_TEXTURE_2D, RGBA_8888);
165   }
166 
CreateImageDecodeTasks(unsigned num_image_decode_tasks,ImageDecodeTask::Vector * image_decode_tasks)167   void CreateImageDecodeTasks(unsigned num_image_decode_tasks,
168                               ImageDecodeTask::Vector* image_decode_tasks) {
169     for (unsigned i = 0; i < num_image_decode_tasks; ++i)
170       image_decode_tasks->push_back(new PerfImageDecodeTaskImpl);
171   }
172 
CreateRasterTasks(unsigned num_raster_tasks,const ImageDecodeTask::Vector & image_decode_tasks,RasterTaskVector * raster_tasks)173   void CreateRasterTasks(unsigned num_raster_tasks,
174                          const ImageDecodeTask::Vector& image_decode_tasks,
175                          RasterTaskVector* raster_tasks) {
176     const gfx::Size size(1, 1);
177 
178     for (unsigned i = 0; i < num_raster_tasks; ++i) {
179       scoped_ptr<ScopedResource> resource(
180           ScopedResource::Create(resource_provider_.get()));
181       resource->Allocate(size, ResourceProvider::TextureUsageAny, RGBA_8888);
182 
183       ImageDecodeTask::Vector dependencies = image_decode_tasks;
184       raster_tasks->push_back(
185           new PerfRasterTaskImpl(resource.Pass(), &dependencies));
186     }
187   }
188 
BuildRasterTaskQueue(RasterTaskQueue * queue,const RasterTaskVector & raster_tasks)189   void BuildRasterTaskQueue(RasterTaskQueue* queue,
190                             const RasterTaskVector& raster_tasks) {
191     for (size_t i = 0u; i < raster_tasks.size(); ++i) {
192       bool required_for_activation = (i % 2) == 0;
193       queue->items.push_back(RasterTaskQueue::Item(raster_tasks[i].get(),
194                                                    required_for_activation));
195       queue->required_for_activation_count += required_for_activation;
196     }
197   }
198 
199  protected:
200   scoped_refptr<ContextProvider> context_provider_;
201   FakeOutputSurfaceClient output_surface_client_;
202   scoped_ptr<FakeOutputSurface> output_surface_;
203   scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
204   scoped_ptr<ResourceProvider> resource_provider_;
205   scoped_ptr<ResourcePool> staging_resource_pool_;
206   scoped_ptr<TaskGraphRunner> task_graph_runner_;
207   LapTimer timer_;
208 };
209 
210 class RasterWorkerPoolPerfTest
211     : public RasterWorkerPoolPerfTestBase,
212       public testing::TestWithParam<RasterWorkerPoolType>,
213       public RasterizerClient {
214  public:
RasterWorkerPoolPerfTest()215   RasterWorkerPoolPerfTest() {
216     switch (GetParam()) {
217       case RASTER_WORKER_POOL_TYPE_PIXEL_BUFFER:
218         raster_worker_pool_ = PixelBufferRasterWorkerPool::Create(
219             base::MessageLoopProxy::current().get(),
220             task_graph_runner_.get(),
221             resource_provider_.get(),
222             std::numeric_limits<size_t>::max());
223         break;
224       case RASTER_WORKER_POOL_TYPE_IMAGE:
225         raster_worker_pool_ = ImageRasterWorkerPool::Create(
226             base::MessageLoopProxy::current().get(),
227             task_graph_runner_.get(),
228             resource_provider_.get());
229         break;
230       case RASTER_WORKER_POOL_TYPE_IMAGE_COPY:
231         raster_worker_pool_ = ImageCopyRasterWorkerPool::Create(
232             base::MessageLoopProxy::current().get(),
233             task_graph_runner_.get(),
234             resource_provider_.get(),
235             staging_resource_pool_.get());
236         break;
237       case RASTER_WORKER_POOL_TYPE_DIRECT:
238         raster_worker_pool_ = DirectRasterWorkerPool::Create(
239             base::MessageLoopProxy::current().get(),
240             resource_provider_.get(),
241             context_provider_.get());
242         break;
243     }
244 
245     DCHECK(raster_worker_pool_);
246     raster_worker_pool_->AsRasterizer()->SetClient(this);
247   }
248 
249   // Overridden from testing::Test:
TearDown()250   virtual void TearDown() OVERRIDE {
251     raster_worker_pool_->AsRasterizer()->Shutdown();
252     raster_worker_pool_->AsRasterizer()->CheckForCompletedTasks();
253   }
254 
255   // Overriden from RasterizerClient:
ShouldForceTasksRequiredForActivationToComplete() const256   virtual bool ShouldForceTasksRequiredForActivationToComplete() const
257       OVERRIDE {
258     return false;
259   }
DidFinishRunningTasks()260   virtual void DidFinishRunningTasks() OVERRIDE {
261     raster_worker_pool_->AsRasterizer()->CheckForCompletedTasks();
262     base::MessageLoop::current()->Quit();
263   }
DidFinishRunningTasksRequiredForActivation()264   virtual void DidFinishRunningTasksRequiredForActivation() OVERRIDE {}
265 
RunMessageLoopUntilAllTasksHaveCompleted()266   void RunMessageLoopUntilAllTasksHaveCompleted() {
267     task_graph_runner_->RunUntilIdle();
268     base::MessageLoop::current()->Run();
269   }
270 
RunScheduleTasksTest(const std::string & test_name,unsigned num_raster_tasks,unsigned num_image_decode_tasks)271   void RunScheduleTasksTest(const std::string& test_name,
272                             unsigned num_raster_tasks,
273                             unsigned num_image_decode_tasks) {
274     ImageDecodeTask::Vector image_decode_tasks;
275     RasterTaskVector raster_tasks;
276     CreateImageDecodeTasks(num_image_decode_tasks, &image_decode_tasks);
277     CreateRasterTasks(num_raster_tasks, image_decode_tasks, &raster_tasks);
278 
279     // Avoid unnecessary heap allocations by reusing the same queue.
280     RasterTaskQueue queue;
281 
282     timer_.Reset();
283     do {
284       queue.Reset();
285       BuildRasterTaskQueue(&queue, raster_tasks);
286       raster_worker_pool_->AsRasterizer()->ScheduleTasks(&queue);
287       raster_worker_pool_->AsRasterizer()->CheckForCompletedTasks();
288       timer_.NextLap();
289     } while (!timer_.HasTimeLimitExpired());
290 
291     RasterTaskQueue empty;
292     raster_worker_pool_->AsRasterizer()->ScheduleTasks(&empty);
293     RunMessageLoopUntilAllTasksHaveCompleted();
294 
295     perf_test::PrintResult("schedule_tasks",
296                            TestModifierString(),
297                            test_name,
298                            timer_.LapsPerSecond(),
299                            "runs/s",
300                            true);
301   }
302 
RunScheduleAlternateTasksTest(const std::string & test_name,unsigned num_raster_tasks,unsigned num_image_decode_tasks)303   void RunScheduleAlternateTasksTest(const std::string& test_name,
304                                      unsigned num_raster_tasks,
305                                      unsigned num_image_decode_tasks) {
306     const size_t kNumVersions = 2;
307     ImageDecodeTask::Vector image_decode_tasks[kNumVersions];
308     RasterTaskVector raster_tasks[kNumVersions];
309     for (size_t i = 0; i < kNumVersions; ++i) {
310       CreateImageDecodeTasks(num_image_decode_tasks, &image_decode_tasks[i]);
311       CreateRasterTasks(
312           num_raster_tasks, image_decode_tasks[i], &raster_tasks[i]);
313     }
314 
315     // Avoid unnecessary heap allocations by reusing the same queue.
316     RasterTaskQueue queue;
317 
318     size_t count = 0;
319     timer_.Reset();
320     do {
321       queue.Reset();
322       BuildRasterTaskQueue(&queue, raster_tasks[count % kNumVersions]);
323       raster_worker_pool_->AsRasterizer()->ScheduleTasks(&queue);
324       raster_worker_pool_->AsRasterizer()->CheckForCompletedTasks();
325       ++count;
326       timer_.NextLap();
327     } while (!timer_.HasTimeLimitExpired());
328 
329     RasterTaskQueue empty;
330     raster_worker_pool_->AsRasterizer()->ScheduleTasks(&empty);
331     RunMessageLoopUntilAllTasksHaveCompleted();
332 
333     perf_test::PrintResult("schedule_alternate_tasks",
334                            TestModifierString(),
335                            test_name,
336                            timer_.LapsPerSecond(),
337                            "runs/s",
338                            true);
339   }
340 
RunScheduleAndExecuteTasksTest(const std::string & test_name,unsigned num_raster_tasks,unsigned num_image_decode_tasks)341   void RunScheduleAndExecuteTasksTest(const std::string& test_name,
342                                       unsigned num_raster_tasks,
343                                       unsigned num_image_decode_tasks) {
344     ImageDecodeTask::Vector image_decode_tasks;
345     RasterTaskVector raster_tasks;
346     CreateImageDecodeTasks(num_image_decode_tasks, &image_decode_tasks);
347     CreateRasterTasks(num_raster_tasks, image_decode_tasks, &raster_tasks);
348 
349     // Avoid unnecessary heap allocations by reusing the same queue.
350     RasterTaskQueue queue;
351 
352     timer_.Reset();
353     do {
354       queue.Reset();
355       BuildRasterTaskQueue(&queue, raster_tasks);
356       raster_worker_pool_->AsRasterizer()->ScheduleTasks(&queue);
357       RunMessageLoopUntilAllTasksHaveCompleted();
358       timer_.NextLap();
359     } while (!timer_.HasTimeLimitExpired());
360 
361     RasterTaskQueue empty;
362     raster_worker_pool_->AsRasterizer()->ScheduleTasks(&empty);
363     RunMessageLoopUntilAllTasksHaveCompleted();
364 
365     perf_test::PrintResult("schedule_and_execute_tasks",
366                            TestModifierString(),
367                            test_name,
368                            timer_.LapsPerSecond(),
369                            "runs/s",
370                            true);
371   }
372 
373  private:
TestModifierString() const374   std::string TestModifierString() const {
375     switch (GetParam()) {
376       case RASTER_WORKER_POOL_TYPE_PIXEL_BUFFER:
377         return std::string("_pixel_raster_worker_pool");
378       case RASTER_WORKER_POOL_TYPE_IMAGE:
379         return std::string("_image_raster_worker_pool");
380       case RASTER_WORKER_POOL_TYPE_IMAGE_COPY:
381         return std::string("_image_copy_raster_worker_pool");
382       case RASTER_WORKER_POOL_TYPE_DIRECT:
383         return std::string("_direct_raster_worker_pool");
384     }
385     NOTREACHED();
386     return std::string();
387   }
388 
389   scoped_ptr<RasterWorkerPool> raster_worker_pool_;
390 };
391 
TEST_P(RasterWorkerPoolPerfTest,ScheduleTasks)392 TEST_P(RasterWorkerPoolPerfTest, ScheduleTasks) {
393   RunScheduleTasksTest("1_0", 1, 0);
394   RunScheduleTasksTest("32_0", 32, 0);
395   RunScheduleTasksTest("1_1", 1, 1);
396   RunScheduleTasksTest("32_1", 32, 1);
397   RunScheduleTasksTest("1_4", 1, 4);
398   RunScheduleTasksTest("32_4", 32, 4);
399 }
400 
TEST_P(RasterWorkerPoolPerfTest,ScheduleAlternateTasks)401 TEST_P(RasterWorkerPoolPerfTest, ScheduleAlternateTasks) {
402   RunScheduleAlternateTasksTest("1_0", 1, 0);
403   RunScheduleAlternateTasksTest("32_0", 32, 0);
404   RunScheduleAlternateTasksTest("1_1", 1, 1);
405   RunScheduleAlternateTasksTest("32_1", 32, 1);
406   RunScheduleAlternateTasksTest("1_4", 1, 4);
407   RunScheduleAlternateTasksTest("32_4", 32, 4);
408 }
409 
TEST_P(RasterWorkerPoolPerfTest,ScheduleAndExecuteTasks)410 TEST_P(RasterWorkerPoolPerfTest, ScheduleAndExecuteTasks) {
411   RunScheduleAndExecuteTasksTest("1_0", 1, 0);
412   RunScheduleAndExecuteTasksTest("32_0", 32, 0);
413   RunScheduleAndExecuteTasksTest("1_1", 1, 1);
414   RunScheduleAndExecuteTasksTest("32_1", 32, 1);
415   RunScheduleAndExecuteTasksTest("1_4", 1, 4);
416   RunScheduleAndExecuteTasksTest("32_4", 32, 4);
417 }
418 
419 INSTANTIATE_TEST_CASE_P(RasterWorkerPoolPerfTests,
420                         RasterWorkerPoolPerfTest,
421                         ::testing::Values(RASTER_WORKER_POOL_TYPE_PIXEL_BUFFER,
422                                           RASTER_WORKER_POOL_TYPE_IMAGE,
423                                           RASTER_WORKER_POOL_TYPE_IMAGE_COPY,
424                                           RASTER_WORKER_POOL_TYPE_DIRECT));
425 
426 class RasterWorkerPoolCommonPerfTest : public RasterWorkerPoolPerfTestBase,
427                                        public testing::Test {
428  public:
RunBuildRasterTaskQueueTest(const std::string & test_name,unsigned num_raster_tasks,unsigned num_image_decode_tasks)429   void RunBuildRasterTaskQueueTest(const std::string& test_name,
430                                    unsigned num_raster_tasks,
431                                    unsigned num_image_decode_tasks) {
432     ImageDecodeTask::Vector image_decode_tasks;
433     RasterTaskVector raster_tasks;
434     CreateImageDecodeTasks(num_image_decode_tasks, &image_decode_tasks);
435     CreateRasterTasks(num_raster_tasks, image_decode_tasks, &raster_tasks);
436 
437     // Avoid unnecessary heap allocations by reusing the same queue.
438     RasterTaskQueue queue;
439 
440     timer_.Reset();
441     do {
442       queue.Reset();
443       BuildRasterTaskQueue(&queue, raster_tasks);
444       timer_.NextLap();
445     } while (!timer_.HasTimeLimitExpired());
446 
447     perf_test::PrintResult("build_raster_task_queue",
448                            "",
449                            test_name,
450                            timer_.LapsPerSecond(),
451                            "runs/s",
452                            true);
453   }
454 };
455 
TEST_F(RasterWorkerPoolCommonPerfTest,BuildRasterTaskQueue)456 TEST_F(RasterWorkerPoolCommonPerfTest, BuildRasterTaskQueue) {
457   RunBuildRasterTaskQueueTest("1_0", 1, 0);
458   RunBuildRasterTaskQueueTest("32_0", 32, 0);
459   RunBuildRasterTaskQueueTest("1_1", 1, 1);
460   RunBuildRasterTaskQueueTest("32_1", 32, 1);
461   RunBuildRasterTaskQueueTest("1_4", 1, 4);
462   RunBuildRasterTaskQueueTest("32_4", 32, 4);
463 }
464 
465 }  // namespace
466 }  // namespace cc
467