Home | History | Annotate | Download | only in gpu
      1 /*
      2  * Copyright 2013 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "GrTest.h"
      9 
     10 #include "GrContextOptions.h"
     11 #include "GrDrawOpAtlas.h"
     12 #include "GrDrawingManager.h"
     13 #include "GrGpuResourceCacheAccess.h"
     14 #include "GrPipelineBuilder.h"
     15 #include "GrRenderTargetContextPriv.h"
     16 #include "GrRenderTargetProxy.h"
     17 #include "GrResourceCache.h"
     18 #include "GrSemaphore.h"
     19 
     20 #include "SkGr.h"
     21 #include "SkImage_Gpu.h"
     22 #include "SkMathPriv.h"
     23 #include "SkString.h"
     24 
     25 #include "text/GrAtlasGlyphCache.h"
     26 #include "text/GrTextBlobCache.h"
     27 
     28 namespace GrTest {
     29 void SetupAlwaysEvictAtlas(GrContext* context) {
     30     // These sizes were selected because they allow each atlas to hold a single plot and will thus
     31     // stress the atlas
     32     int dim = GrDrawOpAtlas::kGlyphMaxDim;
     33     GrDrawOpAtlasConfig configs[3];
     34     configs[kA8_GrMaskFormat].fWidth = dim;
     35     configs[kA8_GrMaskFormat].fHeight = dim;
     36     configs[kA8_GrMaskFormat].fLog2Width = SkNextLog2(dim);
     37     configs[kA8_GrMaskFormat].fLog2Height = SkNextLog2(dim);
     38     configs[kA8_GrMaskFormat].fPlotWidth = dim;
     39     configs[kA8_GrMaskFormat].fPlotHeight = dim;
     40 
     41     configs[kA565_GrMaskFormat].fWidth = dim;
     42     configs[kA565_GrMaskFormat].fHeight = dim;
     43     configs[kA565_GrMaskFormat].fLog2Width = SkNextLog2(dim);
     44     configs[kA565_GrMaskFormat].fLog2Height = SkNextLog2(dim);
     45     configs[kA565_GrMaskFormat].fPlotWidth = dim;
     46     configs[kA565_GrMaskFormat].fPlotHeight = dim;
     47 
     48     configs[kARGB_GrMaskFormat].fWidth = dim;
     49     configs[kARGB_GrMaskFormat].fHeight = dim;
     50     configs[kARGB_GrMaskFormat].fLog2Width = SkNextLog2(dim);
     51     configs[kARGB_GrMaskFormat].fLog2Height = SkNextLog2(dim);
     52     configs[kARGB_GrMaskFormat].fPlotWidth = dim;
     53     configs[kARGB_GrMaskFormat].fPlotHeight = dim;
     54 
     55     context->setTextContextAtlasSizes_ForTesting(configs);
     56 }
     57 };
     58 
     59 bool GrSurfaceProxy::isWrapped_ForTesting() const {
     60     return SkToBool(fTarget);
     61 }
     62 
     63 bool GrRenderTargetContext::isWrapped_ForTesting() const {
     64     return fRenderTargetProxy->isWrapped_ForTesting();
     65 }
     66 
     67 void GrContext::setTextBlobCacheLimit_ForTesting(size_t bytes) {
     68     fTextBlobCache->setBudget(bytes);
     69 }
     70 
     71 void GrContext::setTextContextAtlasSizes_ForTesting(const GrDrawOpAtlasConfig* configs) {
     72     fAtlasGlyphCache->setAtlasSizes_ForTesting(configs);
     73 }
     74 
     75 ///////////////////////////////////////////////////////////////////////////////
     76 
     77 void GrContext::purgeAllUnlockedResources() {
     78     fResourceCache->purgeAllUnlocked();
     79 }
     80 
     81 void GrContext::resetGpuStats() const {
     82 #if GR_GPU_STATS
     83     fGpu->stats()->reset();
     84 #endif
     85 }
     86 
     87 void GrContext::dumpCacheStats(SkString* out) const {
     88 #if GR_CACHE_STATS
     89     fResourceCache->dumpStats(out);
     90 #endif
     91 }
     92 
     93 void GrContext::dumpCacheStatsKeyValuePairs(SkTArray<SkString>* keys,
     94                                             SkTArray<double>* values) const {
     95 #if GR_CACHE_STATS
     96     fResourceCache->dumpStatsKeyValuePairs(keys, values);
     97 #endif
     98 }
     99 
    100 void GrContext::printCacheStats() const {
    101     SkString out;
    102     this->dumpCacheStats(&out);
    103     SkDebugf("%s", out.c_str());
    104 }
    105 
    106 void GrContext::dumpGpuStats(SkString* out) const {
    107 #if GR_GPU_STATS
    108     return fGpu->stats()->dump(out);
    109 #endif
    110 }
    111 
    112 void GrContext::dumpGpuStatsKeyValuePairs(SkTArray<SkString>* keys,
    113                                           SkTArray<double>* values) const {
    114 #if GR_GPU_STATS
    115     return fGpu->stats()->dumpKeyValuePairs(keys, values);
    116 #endif
    117 }
    118 
    119 void GrContext::printGpuStats() const {
    120     SkString out;
    121     this->dumpGpuStats(&out);
    122     SkDebugf("%s", out.c_str());
    123 }
    124 
    125 sk_sp<SkImage> GrContext::getFontAtlasImage_ForTesting(GrMaskFormat format) {
    126     GrAtlasGlyphCache* cache = this->getAtlasGlyphCache();
    127 
    128     sk_sp<GrTextureProxy> proxy = cache->getProxy(format);
    129     if (!proxy) {
    130         return nullptr;
    131     }
    132 
    133     SkASSERT(proxy->priv().isExact());
    134     sk_sp<SkImage> image(new SkImage_Gpu(this, kNeedNewImageUniqueID, kPremul_SkAlphaType,
    135                                          std::move(proxy), nullptr, SkBudgeted::kNo));
    136     return image;
    137 }
    138 
    139 #if GR_GPU_STATS
    140 void GrGpu::Stats::dump(SkString* out) {
    141     out->appendf("Render Target Binds: %d\n", fRenderTargetBinds);
    142     out->appendf("Shader Compilations: %d\n", fShaderCompilations);
    143     out->appendf("Textures Created: %d\n", fTextureCreates);
    144     out->appendf("Texture Uploads: %d\n", fTextureUploads);
    145     out->appendf("Transfers to Texture: %d\n", fTransfersToTexture);
    146     out->appendf("Stencil Buffer Creates: %d\n", fStencilAttachmentCreates);
    147     out->appendf("Number of draws: %d\n", fNumDraws);
    148 }
    149 
    150 void GrGpu::Stats::dumpKeyValuePairs(SkTArray<SkString>* keys, SkTArray<double>* values) {
    151     keys->push_back(SkString("render_target_binds")); values->push_back(fRenderTargetBinds);
    152     keys->push_back(SkString("shader_compilations")); values->push_back(fShaderCompilations);
    153     keys->push_back(SkString("texture_uploads")); values->push_back(fTextureUploads);
    154     keys->push_back(SkString("number_of_draws")); values->push_back(fNumDraws);
    155     keys->push_back(SkString("number_of_failed_draws")); values->push_back(fNumFailedDraws);
    156 }
    157 
    158 #endif
    159 
    160 #if GR_CACHE_STATS
    161 void GrResourceCache::getStats(Stats* stats) const {
    162     stats->reset();
    163 
    164     stats->fTotal = this->getResourceCount();
    165     stats->fNumNonPurgeable = fNonpurgeableResources.count();
    166     stats->fNumPurgeable = fPurgeableQueue.count();
    167 
    168     for (int i = 0; i < fNonpurgeableResources.count(); ++i) {
    169         stats->update(fNonpurgeableResources[i]);
    170     }
    171     for (int i = 0; i < fPurgeableQueue.count(); ++i) {
    172         stats->update(fPurgeableQueue.at(i));
    173     }
    174 }
    175 
    176 void GrResourceCache::dumpStats(SkString* out) const {
    177     this->validate();
    178 
    179     Stats stats;
    180 
    181     this->getStats(&stats);
    182 
    183     float countUtilization = (100.f * fBudgetedCount) / fMaxCount;
    184     float byteUtilization = (100.f * fBudgetedBytes) / fMaxBytes;
    185 
    186     out->appendf("Budget: %d items %d bytes\n", fMaxCount, (int)fMaxBytes);
    187     out->appendf("\t\tEntry Count: current %d"
    188                  " (%d budgeted, %d wrapped, %d locked, %d scratch %.2g%% full), high %d\n",
    189                  stats.fTotal, fBudgetedCount, stats.fWrapped, stats.fNumNonPurgeable,
    190                  stats.fScratch, countUtilization, fHighWaterCount);
    191     out->appendf("\t\tEntry Bytes: current %d (budgeted %d, %.2g%% full, %d unbudgeted) high %d\n",
    192                  SkToInt(fBytes), SkToInt(fBudgetedBytes), byteUtilization,
    193                  SkToInt(stats.fUnbudgetedSize), SkToInt(fHighWaterBytes));
    194 }
    195 
    196 void GrResourceCache::dumpStatsKeyValuePairs(SkTArray<SkString>* keys,
    197                                              SkTArray<double>* values) const {
    198     this->validate();
    199 
    200     Stats stats;
    201     this->getStats(&stats);
    202 
    203     keys->push_back(SkString("gpu_cache_purgable_entries")); values->push_back(stats.fNumPurgeable);
    204 }
    205 
    206 #endif
    207 
    208 ///////////////////////////////////////////////////////////////////////////////
    209 
    210 void GrResourceCache::changeTimestamp(uint32_t newTimestamp) { fTimestamp = newTimestamp; }
    211 
    212 #ifdef SK_DEBUG
    213 int GrResourceCache::countUniqueKeysWithTag(const char* tag) const {
    214     int count = 0;
    215     UniqueHash::ConstIter iter(&fUniqueHash);
    216     while (!iter.done()) {
    217         if (0 == strcmp(tag, (*iter).getUniqueKey().tag())) {
    218             ++count;
    219         }
    220         ++iter;
    221     }
    222     return count;
    223 }
    224 #endif
    225 
    226 ///////////////////////////////////////////////////////////////////////////////
    227 
    228 #define ASSERT_SINGLE_OWNER \
    229     SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fRenderTargetContext->fSingleOwner);)
    230 
    231 uint32_t GrRenderTargetContextPriv::testingOnly_addMeshDrawOp(GrPaint&& paint,
    232                                                               GrAAType aaType,
    233                                                               std::unique_ptr<GrMeshDrawOp> op,
    234                                                               const GrUserStencilSettings* uss,
    235                                                               bool snapToCenters) {
    236     ASSERT_SINGLE_OWNER
    237     if (fRenderTargetContext->drawingManager()->wasAbandoned()) {
    238         return SK_InvalidUniqueID;
    239     }
    240     SkDEBUGCODE(fRenderTargetContext->validate();)
    241     GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
    242                               "GrRenderTargetContext::testingOnly_addMeshDrawOp");
    243 
    244     GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
    245     if (uss) {
    246         pipelineBuilder.setUserStencil(uss);
    247     }
    248     pipelineBuilder.setSnapVerticesToPixelCenters(snapToCenters);
    249 
    250     return fRenderTargetContext->addMeshDrawOp(pipelineBuilder, GrNoClip(), std::move(op));
    251 }
    252 
    253 #undef ASSERT_SINGLE_OWNER
    254 
    255 ///////////////////////////////////////////////////////////////////////////////
    256 
    257 GrRenderTarget::Flags GrRenderTargetProxy::testingOnly_getFlags() const {
    258     return fRenderTargetFlags;
    259 }
    260 
    261 ///////////////////////////////////////////////////////////////////////////////
    262 // Code for the mock context. It's built on a mock GrGpu class that does nothing.
    263 ////
    264 
    265 #include "GrGpu.h"
    266 
    267 class GrPipeline;
    268 
    269 class MockCaps : public GrCaps {
    270 public:
    271     explicit MockCaps(const GrContextOptions& options) : INHERITED(options) {}
    272     bool isConfigTexturable(GrPixelConfig config) const override { return false; }
    273     bool isConfigRenderable(GrPixelConfig config, bool withMSAA) const override { return false; }
    274     bool canConfigBeImageStorage(GrPixelConfig) const override { return false; }
    275     bool initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc) const override {
    276         return false;
    277     }
    278 
    279 private:
    280     typedef GrCaps INHERITED;
    281 };
    282 
    283 class MockGpu : public GrGpu {
    284 public:
    285     MockGpu(GrContext* context, const GrContextOptions& options) : INHERITED(context) {
    286         fCaps.reset(new MockCaps(options));
    287     }
    288     ~MockGpu() override {}
    289 
    290     bool onGetReadPixelsInfo(GrSurface* srcSurface, int readWidth, int readHeight, size_t rowBytes,
    291                              GrPixelConfig readConfig, DrawPreference*,
    292                              ReadPixelTempDrawInfo*) override { return false; }
    293 
    294     bool onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height,
    295                               GrPixelConfig srcConfig, DrawPreference*,
    296                               WritePixelTempDrawInfo*) override { return false; }
    297 
    298     bool onCopySurface(GrSurface* dst,
    299                        GrSurface* src,
    300                        const SkIRect& srcRect,
    301                        const SkIPoint& dstPoint) override { return false; }
    302 
    303     void onQueryMultisampleSpecs(GrRenderTarget* rt, const GrStencilSettings&,
    304                                  int* effectiveSampleCnt, SamplePattern*) override {
    305         *effectiveSampleCnt = rt->desc().fSampleCnt;
    306     }
    307 
    308     GrGpuCommandBuffer* createCommandBuffer(const GrGpuCommandBuffer::LoadAndStoreInfo&,
    309                                             const GrGpuCommandBuffer::LoadAndStoreInfo&) override {
    310         return nullptr;
    311     }
    312 
    313     void drawDebugWireRect(GrRenderTarget*, const SkIRect&, GrColor) override {}
    314 
    315     GrFence SK_WARN_UNUSED_RESULT insertFence() override { return 0; }
    316     bool waitFence(GrFence, uint64_t) override { return true; }
    317     void deleteFence(GrFence) const override {}
    318     void flush() override {}
    319 
    320     sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT makeSemaphore() override { return nullptr; }
    321     void insertSemaphore(sk_sp<GrSemaphore> semaphore) override {}
    322     void waitSemaphore(sk_sp<GrSemaphore> semaphore) override {}
    323 
    324 private:
    325     void onResetContext(uint32_t resetBits) override {}
    326 
    327     void xferBarrier(GrRenderTarget*, GrXferBarrierType) override {}
    328 
    329     GrTexture* onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
    330                                const SkTArray<GrMipLevel>& texels) override {
    331         return nullptr;
    332     }
    333 
    334     GrTexture* onCreateCompressedTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
    335                                          const SkTArray<GrMipLevel>& texels) override {
    336         return nullptr;
    337     }
    338 
    339     sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTextureDesc&, GrWrapOwnership) override {
    340         return nullptr;
    341     }
    342 
    343     sk_sp<GrRenderTarget> onWrapBackendRenderTarget(const GrBackendRenderTargetDesc&) override {
    344         return nullptr;
    345     }
    346 
    347     sk_sp<GrRenderTarget> onWrapBackendTextureAsRenderTarget(const GrBackendTextureDesc&) override {
    348         return nullptr;
    349     }
    350 
    351     GrBuffer* onCreateBuffer(size_t, GrBufferType, GrAccessPattern, const void*) override {
    352         return nullptr;
    353     }
    354 
    355     gr_instanced::InstancedRendering* onCreateInstancedRendering() override { return nullptr; }
    356 
    357     bool onReadPixels(GrSurface* surface,
    358                       int left, int top, int width, int height,
    359                       GrPixelConfig,
    360                       void* buffer,
    361                       size_t rowBytes) override {
    362         return false;
    363     }
    364 
    365     bool onWritePixels(GrSurface* surface,
    366                        int left, int top, int width, int height,
    367                        GrPixelConfig config, const SkTArray<GrMipLevel>& texels) override {
    368         return false;
    369     }
    370 
    371     bool onTransferPixels(GrSurface* surface,
    372                           int left, int top, int width, int height,
    373                           GrPixelConfig config, GrBuffer* transferBuffer,
    374                           size_t offset, size_t rowBytes) override {
    375         return false;
    376     }
    377 
    378     void onResolveRenderTarget(GrRenderTarget* target) override { return; }
    379 
    380     GrStencilAttachment* createStencilAttachmentForRenderTarget(const GrRenderTarget*,
    381                                                                 int width,
    382                                                                 int height) override {
    383         return nullptr;
    384     }
    385 
    386     void clearStencil(GrRenderTarget* target) override  {}
    387 
    388     GrBackendObject createTestingOnlyBackendTexture(void* pixels, int w, int h,
    389                                                     GrPixelConfig config, bool isRT) override {
    390         return 0;
    391     }
    392     bool isTestingOnlyBackendTexture(GrBackendObject ) const override { return false; }
    393     void deleteTestingOnlyBackendTexture(GrBackendObject, bool abandonTexture) override {}
    394 
    395     typedef GrGpu INHERITED;
    396 };
    397 
    398 GrContext* GrContext::CreateMockContext() {
    399     GrContext* context = new GrContext;
    400 
    401     context->initMockContext();
    402     return context;
    403 }
    404 
    405 void GrContext::initMockContext() {
    406     GrContextOptions options;
    407     options.fBufferMapThreshold = 0;
    408     SkASSERT(nullptr == fGpu);
    409     fGpu = new MockGpu(this, options);
    410     SkASSERT(fGpu);
    411     this->initCommon(options);
    412 
    413     // We delete these because we want to test the cache starting with zero resources. Also, none of
    414     // these objects are required for any of tests that use this context. TODO: make stop allocating
    415     // resources in the buffer pools.
    416     fDrawingManager->abandon();
    417 }
    418