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