Home | History | Annotate | Download | only in bench
      1 
      2 /*
      3  * Copyright 2013 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 #if SK_SUPPORT_GPU
     10 
     11 #include "Benchmark.h"
     12 #include "GrGpuResource.h"
     13 #include "GrContext.h"
     14 #include "GrResourceCache.h"
     15 #include "GrStencilBuffer.h"
     16 #include "GrTexture.h"
     17 #include "SkCanvas.h"
     18 
     19 enum {
     20     CACHE_SIZE_COUNT = 2048,
     21     CACHE_SIZE_BYTES = 2 * 1024 * 1024,
     22 };
     23 
     24 class StencilResource : public GrGpuResource {
     25 public:
     26     SK_DECLARE_INST_COUNT(StencilResource);
     27     StencilResource(GrGpu* gpu, int id)
     28         : INHERITED(gpu, false)
     29         , fID(id) {
     30         this->registerWithCache();
     31     }
     32 
     33     virtual ~StencilResource() { this->release(); }
     34 
     35     virtual size_t gpuMemorySize() const SK_OVERRIDE {
     36         return 100 + ((fID % 1 == 0) ? -5 : 6);
     37     }
     38 
     39     static GrResourceKey ComputeKey(int width, int height, int sampleCnt) {
     40         return GrStencilBuffer::ComputeKey(width, height, sampleCnt);
     41     }
     42 
     43     int fID;
     44 
     45 private:
     46     typedef GrGpuResource INHERITED;
     47 };
     48 
     49 class TextureResource : public GrGpuResource {
     50 public:
     51     SK_DECLARE_INST_COUNT(TextureResource);
     52     TextureResource(GrGpu* gpu, int id)
     53         : INHERITED(gpu, false)
     54         , fID(id) {
     55         this->registerWithCache();
     56     }
     57 
     58     virtual ~TextureResource() { this->release(); }
     59 
     60     virtual size_t gpuMemorySize() const SK_OVERRIDE {
     61         return 100 + ((fID % 1 == 0) ? -40 : 33);
     62     }
     63 
     64     static GrResourceKey ComputeKey(const GrTextureDesc& desc) {
     65         return GrTextureImpl::ComputeScratchKey(desc);
     66     }
     67 
     68     int fID;
     69 
     70 private:
     71     typedef GrGpuResource INHERITED;
     72 };
     73 
     74 static void get_stencil(int i, int* w, int* h, int* s) {
     75     *w = i % 1024;
     76     *h = i * 2 % 1024;
     77     *s = i % 1 == 0 ? 0 : 4;
     78 }
     79 
     80 static void get_texture_desc(int i, GrTextureDesc* desc) {
     81     desc->fFlags = kRenderTarget_GrTextureFlagBit |
     82         kNoStencil_GrTextureFlagBit;
     83     desc->fWidth  = i % 1024;
     84     desc->fHeight = i * 2 % 1024;
     85     desc->fConfig = static_cast<GrPixelConfig>(i % (kLast_GrPixelConfig + 1));
     86     desc->fSampleCnt = i % 1 == 0 ? 0 : 4;
     87 }
     88 
     89 static void populate_cache(GrResourceCache* cache, GrGpu* gpu, int resourceCount) {
     90     for (int i = 0; i < resourceCount; ++i) {
     91         int w, h, s;
     92         get_stencil(i, &w, &h, &s);
     93         GrResourceKey key = GrStencilBuffer::ComputeKey(w, h, s);
     94         GrGpuResource* resource = SkNEW_ARGS(StencilResource, (gpu, i));
     95         cache->purgeAsNeeded(1, resource->gpuMemorySize());
     96         cache->addResource(key, resource);
     97         resource->unref();
     98     }
     99 
    100     for (int i = 0; i < resourceCount; ++i) {
    101         GrTextureDesc desc;
    102         get_texture_desc(i, &desc);
    103         GrResourceKey key =  TextureResource::ComputeKey(desc);
    104         GrGpuResource* resource = SkNEW_ARGS(TextureResource, (gpu, i));
    105         cache->purgeAsNeeded(1, resource->gpuMemorySize());
    106         cache->addResource(key, resource);
    107         resource->unref();
    108     }
    109 }
    110 
    111 static void check_cache_contents_or_die(GrResourceCache* cache, int k) {
    112     // Benchmark find calls that succeed.
    113     {
    114         GrTextureDesc desc;
    115         get_texture_desc(k, &desc);
    116         GrResourceKey key = TextureResource::ComputeKey(desc);
    117         GrGpuResource* item = cache->find(key);
    118         if (NULL == item) {
    119             SkFAIL("cache add does not work as expected");
    120             return;
    121         }
    122         if (static_cast<TextureResource*>(item)->fID != k) {
    123             SkFAIL("cache add does not work as expected");
    124             return;
    125         }
    126     }
    127     {
    128         int w, h, s;
    129         get_stencil(k, &w, &h, &s);
    130         GrResourceKey key = StencilResource::ComputeKey(w, h, s);
    131         GrGpuResource* item = cache->find(key);
    132         if (NULL == item) {
    133             SkFAIL("cache add does not work as expected");
    134             return;
    135         }
    136         if (static_cast<TextureResource*>(item)->fID != k) {
    137             SkFAIL("cache add does not work as expected");
    138             return;
    139         }
    140     }
    141 
    142     // Benchmark also find calls that always fail.
    143     {
    144         GrTextureDesc desc;
    145         get_texture_desc(k, &desc);
    146         desc.fHeight |= 1;
    147         GrResourceKey key = TextureResource::ComputeKey(desc);
    148         GrGpuResource* item = cache->find(key);
    149         if (item) {
    150             SkFAIL("cache add does not work as expected");
    151             return;
    152         }
    153     }
    154     {
    155         int w, h, s;
    156         get_stencil(k, &w, &h, &s);
    157         h |= 1;
    158         GrResourceKey key = StencilResource::ComputeKey(w, h, s);
    159         GrGpuResource* item = cache->find(key);
    160         if (item) {
    161             SkFAIL("cache add does not work as expected");
    162             return;
    163         }
    164     }
    165 }
    166 
    167 class GrResourceCacheBenchAdd : public Benchmark {
    168     enum {
    169         RESOURCE_COUNT = CACHE_SIZE_COUNT / 2,
    170         DUPLICATE_COUNT = CACHE_SIZE_COUNT / 4,
    171     };
    172 
    173 public:
    174     virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
    175         return backend == kGPU_Backend;
    176     }
    177 
    178 protected:
    179     virtual const char* onGetName() SK_OVERRIDE {
    180         return "grresourcecache_add";
    181     }
    182 
    183     virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
    184         GrGpu* gpu = canvas->getGrContext()->getGpu();
    185 
    186         for (int i = 0; i < loops; ++i) {
    187             GrResourceCache cache(CACHE_SIZE_COUNT, CACHE_SIZE_BYTES);
    188             populate_cache(&cache, gpu, DUPLICATE_COUNT);
    189             populate_cache(&cache, gpu, RESOURCE_COUNT);
    190 
    191             // Check that cache works.
    192             for (int k = 0; k < RESOURCE_COUNT; k += 33) {
    193                 check_cache_contents_or_die(&cache, k);
    194             }
    195             cache.purgeAllUnlocked();
    196         }
    197     }
    198 
    199 private:
    200     typedef Benchmark INHERITED;
    201 };
    202 
    203 class GrResourceCacheBenchFind : public Benchmark {
    204     enum {
    205         RESOURCE_COUNT = (CACHE_SIZE_COUNT / 2) - 100,
    206         DUPLICATE_COUNT = 100
    207     };
    208 
    209 public:
    210     virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
    211         return backend == kGPU_Backend;
    212     }
    213 
    214 protected:
    215     virtual const char* onGetName() SK_OVERRIDE {
    216         return "grresourcecache_find";
    217     }
    218 
    219     virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
    220         GrGpu* gpu = canvas->getGrContext()->getGpu();
    221         GrResourceCache cache(CACHE_SIZE_COUNT, CACHE_SIZE_BYTES);
    222         populate_cache(&cache, gpu, DUPLICATE_COUNT);
    223         populate_cache(&cache, gpu, RESOURCE_COUNT);
    224 
    225         for (int i = 0; i < loops; ++i) {
    226             for (int k = 0; k < RESOURCE_COUNT; ++k) {
    227                 check_cache_contents_or_die(&cache, k);
    228             }
    229         }
    230     }
    231 
    232 private:
    233     typedef Benchmark INHERITED;
    234 };
    235 
    236 DEF_BENCH( return new GrResourceCacheBenchAdd(); )
    237 DEF_BENCH( return new GrResourceCacheBenchFind(); )
    238 
    239 #endif
    240