Home | History | Annotate | Download | only in resources
      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/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_shared_bitmap_manager.h"
     25 #include "cc/test/test_web_graphics_context_3d.h"
     26 #include "testing/gtest/include/gtest/gtest.h"
     27 #include "testing/perf/perf_test.h"
     28 #include "third_party/khronos/GLES2/gl2.h"
     29 
     30 namespace cc {
     31 namespace {
     32 
     33 class PerfGLES2Interface : public gpu::gles2::GLES2InterfaceStub {
     34   // Overridden from gpu::gles2::GLES2Interface:
     35   virtual GLuint CreateImageCHROMIUM(GLsizei width,
     36                                      GLsizei height,
     37                                      GLenum internalformat,
     38                                      GLenum usage) OVERRIDE {
     39     return 1u;
     40   }
     41   virtual void GenBuffers(GLsizei n, GLuint* buffers) OVERRIDE {
     42     for (GLsizei i = 0; i < n; ++i)
     43       buffers[i] = 1u;
     44   }
     45   virtual void GenTextures(GLsizei n, GLuint* textures) OVERRIDE {
     46     for (GLsizei i = 0; i < n; ++i)
     47       textures[i] = 1u;
     48   }
     49   virtual void GetIntegerv(GLenum pname, GLint* params) OVERRIDE {
     50     if (pname == GL_MAX_TEXTURE_SIZE)
     51       *params = INT_MAX;
     52   }
     53   virtual void GenQueriesEXT(GLsizei n, GLuint* queries) OVERRIDE {
     54     for (GLsizei i = 0; i < n; ++i)
     55       queries[i] = 1u;
     56   }
     57   virtual void GetQueryObjectuivEXT(GLuint query,
     58                                     GLenum pname,
     59                                     GLuint* params) OVERRIDE {
     60     if (pname == GL_QUERY_RESULT_AVAILABLE_EXT)
     61       *params = 1;
     62   }
     63 };
     64 
     65 class PerfContextProvider : public ContextProvider {
     66  public:
     67   PerfContextProvider() : context_gl_(new PerfGLES2Interface) {}
     68 
     69   virtual bool BindToCurrentThread() OVERRIDE { return true; }
     70   virtual Capabilities ContextCapabilities() OVERRIDE {
     71     Capabilities capabilities;
     72     capabilities.gpu.map_image = true;
     73     capabilities.gpu.sync_query = true;
     74     return capabilities;
     75   }
     76   virtual gpu::gles2::GLES2Interface* ContextGL() OVERRIDE {
     77     return context_gl_.get();
     78   }
     79   virtual gpu::ContextSupport* ContextSupport() OVERRIDE { return &support_; }
     80   virtual class GrContext* GrContext() OVERRIDE { return NULL; }
     81   virtual bool IsContextLost() OVERRIDE { return false; }
     82   virtual void VerifyContexts() OVERRIDE {}
     83   virtual void DeleteCachedResources() OVERRIDE {}
     84   virtual bool DestroyedOnMainThread() OVERRIDE { return false; }
     85   virtual void SetLostContextCallback(const LostContextCallback& cb) OVERRIDE {}
     86   virtual void SetMemoryPolicyChangedCallback(
     87       const MemoryPolicyChangedCallback& cb) OVERRIDE {}
     88 
     89  private:
     90   virtual ~PerfContextProvider() {}
     91 
     92   scoped_ptr<PerfGLES2Interface> context_gl_;
     93   TestContextSupport support_;
     94 };
     95 
     96 enum RasterWorkerPoolType {
     97   RASTER_WORKER_POOL_TYPE_PIXEL_BUFFER,
     98   RASTER_WORKER_POOL_TYPE_ZERO_COPY,
     99   RASTER_WORKER_POOL_TYPE_ONE_COPY,
    100   RASTER_WORKER_POOL_TYPE_GPU,
    101   RASTER_WORKER_POOL_TYPE_BITMAP
    102 };
    103 
    104 static const int kTimeLimitMillis = 2000;
    105 static const int kWarmupRuns = 5;
    106 static const int kTimeCheckInterval = 10;
    107 
    108 class PerfImageDecodeTaskImpl : public ImageDecodeTask {
    109  public:
    110   PerfImageDecodeTaskImpl() {}
    111 
    112   // Overridden from Task:
    113   virtual void RunOnWorkerThread() OVERRIDE {}
    114 
    115   // Overridden from RasterizerTask:
    116   virtual void ScheduleOnOriginThread(RasterizerTaskClient* client) OVERRIDE {}
    117   virtual void CompleteOnOriginThread(RasterizerTaskClient* client) OVERRIDE {}
    118   virtual void RunReplyOnOriginThread() OVERRIDE { Reset(); }
    119 
    120   void Reset() {
    121     did_run_ = false;
    122     did_complete_ = false;
    123   }
    124 
    125  protected:
    126   virtual ~PerfImageDecodeTaskImpl() {}
    127 
    128  private:
    129   DISALLOW_COPY_AND_ASSIGN(PerfImageDecodeTaskImpl);
    130 };
    131 
    132 class PerfRasterTaskImpl : public RasterTask {
    133  public:
    134   PerfRasterTaskImpl(scoped_ptr<ScopedResource> resource,
    135                      ImageDecodeTask::Vector* dependencies)
    136       : RasterTask(resource.get(), dependencies), resource_(resource.Pass()) {}
    137 
    138   // Overridden from Task:
    139   virtual void RunOnWorkerThread() OVERRIDE {}
    140 
    141   // Overridden from RasterizerTask:
    142   virtual void ScheduleOnOriginThread(RasterizerTaskClient* client) OVERRIDE {
    143     raster_buffer_ = client->AcquireBufferForRaster(resource());
    144   }
    145   virtual void CompleteOnOriginThread(RasterizerTaskClient* client) OVERRIDE {
    146     client->ReleaseBufferForRaster(raster_buffer_.Pass());
    147   }
    148   virtual void RunReplyOnOriginThread() OVERRIDE { Reset(); }
    149 
    150   void Reset() {
    151     did_run_ = false;
    152     did_complete_ = false;
    153   }
    154 
    155  protected:
    156   virtual ~PerfRasterTaskImpl() {}
    157 
    158  private:
    159   scoped_ptr<ScopedResource> resource_;
    160   scoped_ptr<RasterBuffer> raster_buffer_;
    161 
    162   DISALLOW_COPY_AND_ASSIGN(PerfRasterTaskImpl);
    163 };
    164 
    165 class RasterWorkerPoolPerfTestBase {
    166  public:
    167   typedef std::vector<scoped_refptr<RasterTask> > RasterTaskVector;
    168 
    169   enum NamedTaskSet { REQUIRED_FOR_ACTIVATION = 0, ALL = 1 };
    170 
    171   RasterWorkerPoolPerfTestBase()
    172       : context_provider_(make_scoped_refptr(new PerfContextProvider)),
    173         task_runner_(new base::TestSimpleTaskRunner),
    174         task_graph_runner_(new TaskGraphRunner),
    175         timer_(kWarmupRuns,
    176                base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
    177                kTimeCheckInterval) {}
    178 
    179   void CreateImageDecodeTasks(unsigned num_image_decode_tasks,
    180                               ImageDecodeTask::Vector* image_decode_tasks) {
    181     for (unsigned i = 0; i < num_image_decode_tasks; ++i)
    182       image_decode_tasks->push_back(new PerfImageDecodeTaskImpl);
    183   }
    184 
    185   void CreateRasterTasks(unsigned num_raster_tasks,
    186                          const ImageDecodeTask::Vector& image_decode_tasks,
    187                          RasterTaskVector* raster_tasks) {
    188     const gfx::Size size(1, 1);
    189 
    190     for (unsigned i = 0; i < num_raster_tasks; ++i) {
    191       scoped_ptr<ScopedResource> resource(
    192           ScopedResource::Create(resource_provider_.get()));
    193       resource->Allocate(
    194           size, ResourceProvider::TextureHintImmutable, RGBA_8888);
    195 
    196       ImageDecodeTask::Vector dependencies = image_decode_tasks;
    197       raster_tasks->push_back(
    198           new PerfRasterTaskImpl(resource.Pass(), &dependencies));
    199     }
    200   }
    201 
    202   void BuildRasterTaskQueue(RasterTaskQueue* queue,
    203                             const RasterTaskVector& raster_tasks) {
    204     for (size_t i = 0u; i < raster_tasks.size(); ++i) {
    205       bool required_for_activation = (i % 2) == 0;
    206       TaskSetCollection task_set_collection;
    207       task_set_collection[ALL] = true;
    208       task_set_collection[REQUIRED_FOR_ACTIVATION] = required_for_activation;
    209       queue->items.push_back(
    210           RasterTaskQueue::Item(raster_tasks[i].get(), task_set_collection));
    211     }
    212   }
    213 
    214  protected:
    215   scoped_refptr<ContextProvider> context_provider_;
    216   FakeOutputSurfaceClient output_surface_client_;
    217   scoped_ptr<FakeOutputSurface> output_surface_;
    218   scoped_ptr<ResourceProvider> resource_provider_;
    219   scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
    220   scoped_ptr<TaskGraphRunner> task_graph_runner_;
    221   LapTimer timer_;
    222 };
    223 
    224 class RasterWorkerPoolPerfTest
    225     : public RasterWorkerPoolPerfTestBase,
    226       public testing::TestWithParam<RasterWorkerPoolType>,
    227       public RasterizerClient {
    228  public:
    229   // Overridden from testing::Test:
    230   virtual void SetUp() OVERRIDE {
    231     switch (GetParam()) {
    232       case RASTER_WORKER_POOL_TYPE_PIXEL_BUFFER:
    233         Create3dOutputSurfaceAndResourceProvider();
    234         raster_worker_pool_ = PixelBufferRasterWorkerPool::Create(
    235             task_runner_.get(),
    236             task_graph_runner_.get(),
    237             context_provider_.get(),
    238             resource_provider_.get(),
    239             std::numeric_limits<size_t>::max());
    240         break;
    241       case RASTER_WORKER_POOL_TYPE_ZERO_COPY:
    242         Create3dOutputSurfaceAndResourceProvider();
    243         raster_worker_pool_ =
    244             ZeroCopyRasterWorkerPool::Create(task_runner_.get(),
    245                                              task_graph_runner_.get(),
    246                                              resource_provider_.get());
    247         break;
    248       case RASTER_WORKER_POOL_TYPE_ONE_COPY:
    249         Create3dOutputSurfaceAndResourceProvider();
    250         staging_resource_pool_ = ResourcePool::Create(
    251             resource_provider_.get(), GL_TEXTURE_2D, RGBA_8888);
    252         raster_worker_pool_ =
    253             OneCopyRasterWorkerPool::Create(task_runner_.get(),
    254                                             task_graph_runner_.get(),
    255                                             context_provider_.get(),
    256                                             resource_provider_.get(),
    257                                             staging_resource_pool_.get());
    258         break;
    259       case RASTER_WORKER_POOL_TYPE_GPU:
    260         Create3dOutputSurfaceAndResourceProvider();
    261         raster_worker_pool_ =
    262             GpuRasterWorkerPool::Create(task_runner_.get(),
    263                                         context_provider_.get(),
    264                                         resource_provider_.get());
    265         break;
    266       case RASTER_WORKER_POOL_TYPE_BITMAP:
    267         CreateSoftwareOutputSurfaceAndResourceProvider();
    268         raster_worker_pool_ =
    269             BitmapRasterWorkerPool::Create(task_runner_.get(),
    270                                            task_graph_runner_.get(),
    271                                            resource_provider_.get());
    272         break;
    273     }
    274 
    275     DCHECK(raster_worker_pool_);
    276     raster_worker_pool_->AsRasterizer()->SetClient(this);
    277   }
    278   virtual void TearDown() OVERRIDE {
    279     raster_worker_pool_->AsRasterizer()->Shutdown();
    280     raster_worker_pool_->AsRasterizer()->CheckForCompletedTasks();
    281   }
    282 
    283   // Overriden from RasterizerClient:
    284   virtual void DidFinishRunningTasks(TaskSet task_set) OVERRIDE {
    285     raster_worker_pool_->AsRasterizer()->CheckForCompletedTasks();
    286   }
    287   virtual TaskSetCollection TasksThatShouldBeForcedToComplete() const OVERRIDE {
    288     return TaskSetCollection();
    289   }
    290 
    291   void RunMessageLoopUntilAllTasksHaveCompleted() {
    292     task_graph_runner_->RunUntilIdle();
    293     task_runner_->RunUntilIdle();
    294   }
    295 
    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);
    303 
    304     // Avoid unnecessary heap allocations by reusing the same queue.
    305     RasterTaskQueue queue;
    306 
    307     timer_.Reset();
    308     do {
    309       queue.Reset();
    310       BuildRasterTaskQueue(&queue, raster_tasks);
    311       raster_worker_pool_->AsRasterizer()->ScheduleTasks(&queue);
    312       raster_worker_pool_->AsRasterizer()->CheckForCompletedTasks();
    313       timer_.NextLap();
    314     } while (!timer_.HasTimeLimitExpired());
    315 
    316     RasterTaskQueue empty;
    317     raster_worker_pool_->AsRasterizer()->ScheduleTasks(&empty);
    318     RunMessageLoopUntilAllTasksHaveCompleted();
    319 
    320     perf_test::PrintResult("schedule_tasks",
    321                            TestModifierString(),
    322                            test_name,
    323                            timer_.LapsPerSecond(),
    324                            "runs/s",
    325                            true);
    326   }
    327 
    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(
    337           num_raster_tasks, image_decode_tasks[i], &raster_tasks[i]);
    338     }
    339 
    340     // Avoid unnecessary heap allocations by reusing the same queue.
    341     RasterTaskQueue queue;
    342 
    343     size_t count = 0;
    344     timer_.Reset();
    345     do {
    346       queue.Reset();
    347       BuildRasterTaskQueue(&queue, raster_tasks[count % kNumVersions]);
    348       raster_worker_pool_->AsRasterizer()->ScheduleTasks(&queue);
    349       raster_worker_pool_->AsRasterizer()->CheckForCompletedTasks();
    350       ++count;
    351       timer_.NextLap();
    352     } while (!timer_.HasTimeLimitExpired());
    353 
    354     RasterTaskQueue empty;
    355     raster_worker_pool_->AsRasterizer()->ScheduleTasks(&empty);
    356     RunMessageLoopUntilAllTasksHaveCompleted();
    357 
    358     perf_test::PrintResult("schedule_alternate_tasks",
    359                            TestModifierString(),
    360                            test_name,
    361                            timer_.LapsPerSecond(),
    362                            "runs/s",
    363                            true);
    364   }
    365 
    366   void RunScheduleAndExecuteTasksTest(const std::string& test_name,
    367                                       unsigned num_raster_tasks,
    368                                       unsigned num_image_decode_tasks) {
    369     ImageDecodeTask::Vector image_decode_tasks;
    370     RasterTaskVector raster_tasks;
    371     CreateImageDecodeTasks(num_image_decode_tasks, &image_decode_tasks);
    372     CreateRasterTasks(num_raster_tasks, image_decode_tasks, &raster_tasks);
    373 
    374     // Avoid unnecessary heap allocations by reusing the same queue.
    375     RasterTaskQueue queue;
    376 
    377     timer_.Reset();
    378     do {
    379       queue.Reset();
    380       BuildRasterTaskQueue(&queue, raster_tasks);
    381       raster_worker_pool_->AsRasterizer()->ScheduleTasks(&queue);
    382       RunMessageLoopUntilAllTasksHaveCompleted();
    383       timer_.NextLap();
    384     } while (!timer_.HasTimeLimitExpired());
    385 
    386     RasterTaskQueue empty;
    387     raster_worker_pool_->AsRasterizer()->ScheduleTasks(&empty);
    388     RunMessageLoopUntilAllTasksHaveCompleted();
    389 
    390     perf_test::PrintResult("schedule_and_execute_tasks",
    391                            TestModifierString(),
    392                            test_name,
    393                            timer_.LapsPerSecond(),
    394                            "runs/s",
    395                            true);
    396   }
    397 
    398  private:
    399   void Create3dOutputSurfaceAndResourceProvider() {
    400     output_surface_ = FakeOutputSurface::Create3d(context_provider_).Pass();
    401     CHECK(output_surface_->BindToClient(&output_surface_client_));
    402     resource_provider_ =
    403         ResourceProvider::Create(
    404             output_surface_.get(), NULL, NULL, 0, false, 1, false).Pass();
    405   }
    406 
    407   void CreateSoftwareOutputSurfaceAndResourceProvider() {
    408     output_surface_ = FakeOutputSurface::CreateSoftware(
    409         make_scoped_ptr(new SoftwareOutputDevice));
    410     CHECK(output_surface_->BindToClient(&output_surface_client_));
    411     resource_provider_ = ResourceProvider::Create(output_surface_.get(),
    412                                                   &shared_bitmap_manager_,
    413                                                   NULL,
    414                                                   0,
    415                                                   false,
    416                                                   1,
    417                                                   false).Pass();
    418   }
    419 
    420   std::string TestModifierString() const {
    421     switch (GetParam()) {
    422       case RASTER_WORKER_POOL_TYPE_PIXEL_BUFFER:
    423         return std::string("_pixel_raster_worker_pool");
    424       case RASTER_WORKER_POOL_TYPE_ZERO_COPY:
    425         return std::string("_zero_copy_raster_worker_pool");
    426       case RASTER_WORKER_POOL_TYPE_ONE_COPY:
    427         return std::string("_one_copy_raster_worker_pool");
    428       case RASTER_WORKER_POOL_TYPE_GPU:
    429         return std::string("_gpu_raster_worker_pool");
    430       case RASTER_WORKER_POOL_TYPE_BITMAP:
    431         return std::string("_bitmap_raster_worker_pool");
    432     }
    433     NOTREACHED();
    434     return std::string();
    435   }
    436 
    437   scoped_ptr<ResourcePool> staging_resource_pool_;
    438   scoped_ptr<RasterWorkerPool> raster_worker_pool_;
    439   TestSharedBitmapManager shared_bitmap_manager_;
    440 };
    441 
    442 TEST_P(RasterWorkerPoolPerfTest, ScheduleTasks) {
    443   RunScheduleTasksTest("1_0", 1, 0);
    444   RunScheduleTasksTest("32_0", 32, 0);
    445   RunScheduleTasksTest("1_1", 1, 1);
    446   RunScheduleTasksTest("32_1", 32, 1);
    447   RunScheduleTasksTest("1_4", 1, 4);
    448   RunScheduleTasksTest("32_4", 32, 4);
    449 }
    450 
    451 TEST_P(RasterWorkerPoolPerfTest, ScheduleAlternateTasks) {
    452   RunScheduleAlternateTasksTest("1_0", 1, 0);
    453   RunScheduleAlternateTasksTest("32_0", 32, 0);
    454   RunScheduleAlternateTasksTest("1_1", 1, 1);
    455   RunScheduleAlternateTasksTest("32_1", 32, 1);
    456   RunScheduleAlternateTasksTest("1_4", 1, 4);
    457   RunScheduleAlternateTasksTest("32_4", 32, 4);
    458 }
    459 
    460 TEST_P(RasterWorkerPoolPerfTest, ScheduleAndExecuteTasks) {
    461   RunScheduleAndExecuteTasksTest("1_0", 1, 0);
    462   RunScheduleAndExecuteTasksTest("32_0", 32, 0);
    463   RunScheduleAndExecuteTasksTest("1_1", 1, 1);
    464   RunScheduleAndExecuteTasksTest("32_1", 32, 1);
    465   RunScheduleAndExecuteTasksTest("1_4", 1, 4);
    466   RunScheduleAndExecuteTasksTest("32_4", 32, 4);
    467 }
    468 
    469 INSTANTIATE_TEST_CASE_P(RasterWorkerPoolPerfTests,
    470                         RasterWorkerPoolPerfTest,
    471                         ::testing::Values(RASTER_WORKER_POOL_TYPE_PIXEL_BUFFER,
    472                                           RASTER_WORKER_POOL_TYPE_ZERO_COPY,
    473                                           RASTER_WORKER_POOL_TYPE_ONE_COPY,
    474                                           RASTER_WORKER_POOL_TYPE_GPU,
    475                                           RASTER_WORKER_POOL_TYPE_BITMAP));
    476 
    477 class RasterWorkerPoolCommonPerfTest : public RasterWorkerPoolPerfTestBase,
    478                                        public testing::Test {
    479  public:
    480   // Overridden from testing::Test:
    481   virtual void SetUp() OVERRIDE {
    482     output_surface_ = FakeOutputSurface::Create3d(context_provider_).Pass();
    483     CHECK(output_surface_->BindToClient(&output_surface_client_));
    484     resource_provider_ =
    485         ResourceProvider::Create(
    486             output_surface_.get(), NULL, NULL, 0, false, 1, false).Pass();
    487   }
    488 
    489   void RunBuildRasterTaskQueueTest(const std::string& test_name,
    490                                    unsigned num_raster_tasks,
    491                                    unsigned num_image_decode_tasks) {
    492     ImageDecodeTask::Vector image_decode_tasks;
    493     RasterTaskVector raster_tasks;
    494     CreateImageDecodeTasks(num_image_decode_tasks, &image_decode_tasks);
    495     CreateRasterTasks(num_raster_tasks, image_decode_tasks, &raster_tasks);
    496 
    497     // Avoid unnecessary heap allocations by reusing the same queue.
    498     RasterTaskQueue queue;
    499 
    500     timer_.Reset();
    501     do {
    502       queue.Reset();
    503       BuildRasterTaskQueue(&queue, raster_tasks);
    504       timer_.NextLap();
    505     } while (!timer_.HasTimeLimitExpired());
    506 
    507     perf_test::PrintResult("build_raster_task_queue",
    508                            "",
    509                            test_name,
    510                            timer_.LapsPerSecond(),
    511                            "runs/s",
    512                            true);
    513   }
    514 };
    515 
    516 TEST_F(RasterWorkerPoolCommonPerfTest, BuildRasterTaskQueue) {
    517   RunBuildRasterTaskQueueTest("1_0", 1, 0);
    518   RunBuildRasterTaskQueueTest("32_0", 32, 0);
    519   RunBuildRasterTaskQueueTest("1_1", 1, 1);
    520   RunBuildRasterTaskQueueTest("32_1", 32, 1);
    521   RunBuildRasterTaskQueueTest("1_4", 1, 4);
    522   RunBuildRasterTaskQueueTest("32_4", 32, 4);
    523 }
    524 
    525 }  // namespace
    526 }  // namespace cc
    527