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