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