GrResourceCacheBench.cpp revision 91175f19664a62851da4ca4e0984a7c7c45b258f
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#include "Benchmark.h" 10 11#if SK_SUPPORT_GPU 12 13#include "GrGpuResource.h" 14#include "GrContext.h" 15#include "GrGpu.h" 16#include "GrResourceCache2.h" 17#include "SkCanvas.h" 18 19enum { 20 CACHE_SIZE_COUNT = 2048, 21 CACHE_SIZE_BYTES = 2 * 1024 * 1024, 22}; 23 24class FooResource : public GrGpuResource { 25public: 26 SK_DECLARE_INST_COUNT(FooResource); 27 FooResource(GrGpu* gpu, int id) 28 : INHERITED(gpu, false) 29 , fID(id) { 30 this->registerWithCache(); 31 } 32 33 static GrResourceKey ComputeKey(int width, int height, int sampleCnt) { 34 GrCacheID::Key key; 35 memset(&key, 0, sizeof(key)); 36 key.fData32[0] = width; 37 key.fData32[1] = height; 38 key.fData32[2] = sampleCnt; 39 static int gType = GrResourceKey::GenerateResourceType(); 40 static int gDomain = GrCacheID::GenerateDomain(); 41 return GrResourceKey(GrCacheID(gDomain, key), gType, 0); 42 } 43 44 int fID; 45 46private: 47 virtual size_t onGpuMemorySize() const SK_OVERRIDE { 48 return 100 + ((fID % 1 == 0) ? -5 : 6); 49 } 50 51 typedef GrGpuResource INHERITED; 52}; 53 54class BarResource : public GrGpuResource { 55public: 56 SK_DECLARE_INST_COUNT(BarResource); 57 BarResource(GrGpu* gpu, int id) 58 : INHERITED(gpu, false) 59 , fID(id) { 60 this->registerWithCache(); 61 } 62 63 static GrResourceKey ComputeKey(const GrSurfaceDesc& desc) { 64 GrCacheID::Key key; 65 memset(&key, 0, sizeof(key)); 66 key.fData32[0] = (desc.fWidth) | (desc.fHeight << 16); 67 key.fData32[1] = desc.fConfig | desc.fSampleCnt << 16; 68 key.fData32[2] = desc.fFlags; 69 static int gType = GrResourceKey::GenerateResourceType(); 70 static int gDomain = GrCacheID::GenerateDomain(); 71 return GrResourceKey(GrCacheID(gDomain, key), gType, 0); 72 } 73 74 int fID; 75 76private: 77 virtual size_t onGpuMemorySize() const SK_OVERRIDE { 78 return 100 + ((fID % 1 == 0) ? -40 : 33); 79 } 80 81 typedef GrGpuResource INHERITED; 82}; 83 84static void get_foo_params(int i, int* w, int* h, int* s) { 85 *w = i % 1024; 86 *h = i * 2 % 1024; 87 *s = i % 2 == 0 ? 0 : 4; 88} 89 90static void get_bar_surf_desc(int i, GrSurfaceDesc* desc) { 91 desc->fFlags = kRenderTarget_GrSurfaceFlag | kNoStencil_GrSurfaceFlag; 92 desc->fWidth = i % 1024; 93 desc->fHeight = i * 2 % 1024; 94 desc->fConfig = static_cast<GrPixelConfig>(i % (kLast_GrPixelConfig + 1)); 95 desc->fSampleCnt = ((i % 2) == 0) ? 0 : 4; 96} 97 98static void populate_cache(GrGpu* gpu, int resourceCount) { 99 for (int i = 0; i < resourceCount; ++i) { 100 int w, h, s; 101 get_foo_params(i, &w, &h, &s); 102 GrResourceKey key = FooResource::ComputeKey(w, h, s); 103 GrGpuResource* resource = SkNEW_ARGS(FooResource, (gpu, i)); 104 resource->cacheAccess().setContentKey(key); 105 resource->unref(); 106 } 107 108 for (int i = 0; i < resourceCount; ++i) { 109 GrSurfaceDesc desc; 110 get_bar_surf_desc(i, &desc); 111 GrResourceKey key = BarResource::ComputeKey(desc); 112 GrGpuResource* resource = SkNEW_ARGS(BarResource, (gpu, i)); 113 resource->cacheAccess().setContentKey(key); 114 resource->unref(); 115 } 116} 117 118static void check_cache_contents_or_die(GrResourceCache2* cache, int k) { 119 // Benchmark find calls that succeed. 120 { 121 GrSurfaceDesc desc; 122 get_bar_surf_desc(k, &desc); 123 GrResourceKey key = BarResource::ComputeKey(desc); 124 SkAutoTUnref<GrGpuResource> item(cache->findAndRefContentResource(key)); 125 if (!item) { 126 SkFAIL("cache add does not work as expected"); 127 return; 128 } 129 if (static_cast<BarResource*>(item.get())->fID != k) { 130 SkFAIL("cache add does not work as expected"); 131 return; 132 } 133 } 134 { 135 int w, h, s; 136 get_foo_params(k, &w, &h, &s); 137 GrResourceKey key = FooResource::ComputeKey(w, h, s); 138 SkAutoTUnref<GrGpuResource> item(cache->findAndRefContentResource(key)); 139 if (!item) { 140 SkFAIL("cache add does not work as expected"); 141 return; 142 } 143 if (static_cast<FooResource*>(item.get())->fID != k) { 144 SkFAIL("cache add does not work as expected"); 145 return; 146 } 147 } 148 149 // Benchmark also find calls that always fail. 150 { 151 GrSurfaceDesc desc; 152 get_bar_surf_desc(k, &desc); 153 desc.fHeight |= 1; 154 GrResourceKey key = BarResource::ComputeKey(desc); 155 SkAutoTUnref<GrGpuResource> item(cache->findAndRefContentResource(key)); 156 if (item) { 157 SkFAIL("cache add does not work as expected"); 158 return; 159 } 160 } 161 { 162 int w, h, s; 163 get_foo_params(k, &w, &h, &s); 164 h |= 1; 165 GrResourceKey key = FooResource::ComputeKey(w, h, s); 166 SkAutoTUnref<GrGpuResource> item(cache->findAndRefContentResource(key)); 167 if (item) { 168 SkFAIL("cache add does not work as expected"); 169 return; 170 } 171 } 172} 173 174class GrResourceCacheBenchAdd : public Benchmark { 175 enum { 176 RESOURCE_COUNT = CACHE_SIZE_COUNT / 2, 177 }; 178 179public: 180 virtual bool isSuitableFor(Backend backend) SK_OVERRIDE { 181 return backend == kNonRendering_Backend; 182 } 183 184protected: 185 virtual const char* onGetName() SK_OVERRIDE { 186 return "grresourcecache_add"; 187 } 188 189 virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE { 190 SkAutoTUnref<GrContext> context(GrContext::CreateMockContext()); 191 if (NULL == context) { 192 return; 193 } 194 // Set the cache budget to be very large so no purging occurs. 195 context->setResourceCacheLimits(2 * RESOURCE_COUNT, 1 << 30); 196 197 GrResourceCache2* cache2 = context->getResourceCache2(); 198 199 // Make sure the cache is empty. 200 cache2->purgeAllUnlocked(); 201 SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes()); 202 203 GrGpu* gpu = context->getGpu(); 204 205 for (int i = 0; i < loops; ++i) { 206 SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes()); 207 208 populate_cache(gpu, RESOURCE_COUNT); 209 210 // Check that cache works. 211 for (int k = 0; k < RESOURCE_COUNT; k += 33) { 212 check_cache_contents_or_die(cache2, k); 213 } 214 cache2->purgeAllUnlocked(); 215 } 216 } 217 218private: 219 typedef Benchmark INHERITED; 220}; 221 222class GrResourceCacheBenchFind : public Benchmark { 223 enum { 224 RESOURCE_COUNT = CACHE_SIZE_COUNT / 2, 225 }; 226 227public: 228 virtual bool isSuitableFor(Backend backend) SK_OVERRIDE { 229 return backend == kNonRendering_Backend; 230 } 231 232protected: 233 virtual const char* onGetName() SK_OVERRIDE { 234 return "grresourcecache_find"; 235 } 236 237 virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE { 238 SkAutoTUnref<GrContext> context(GrContext::CreateMockContext()); 239 if (NULL == context) { 240 return; 241 } 242 // Set the cache budget to be very large so no purging occurs. 243 context->setResourceCacheLimits(2 * RESOURCE_COUNT, 1 << 30); 244 245 GrResourceCache2* cache2 = context->getResourceCache2(); 246 247 // Make sure the cache is empty. 248 cache2->purgeAllUnlocked(); 249 SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes()); 250 251 GrGpu* gpu = context->getGpu(); 252 253 populate_cache(gpu, RESOURCE_COUNT); 254 255 for (int i = 0; i < loops; ++i) { 256 for (int k = 0; k < RESOURCE_COUNT; ++k) { 257 check_cache_contents_or_die(cache2, k); 258 } 259 } 260 } 261 262private: 263 typedef Benchmark INHERITED; 264}; 265 266DEF_BENCH( return new GrResourceCacheBenchAdd(); ) 267DEF_BENCH( return new GrResourceCacheBenchFind(); ) 268 269#endif 270