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 #include <algorithm>
     10 #include "GrBackendSurface.h"
     11 #include "GrContextOptions.h"
     12 #include "GrContextPriv.h"
     13 #include "GrDrawOpAtlas.h"
     14 #include "GrDrawingManager.h"
     15 #include "GrGpu.h"
     16 #include "GrGpuResourceCacheAccess.h"
     17 #include "GrRenderTargetContext.h"
     18 #include "GrRenderTargetContextPriv.h"
     19 #include "GrRenderTargetProxy.h"
     20 #include "GrResourceCache.h"
     21 #include "GrSemaphore.h"
     22 #include "GrSurfaceContextPriv.h"
     23 #include "GrTexture.h"
     24 #include "SkGr.h"
     25 #include "SkImage_Gpu.h"
     26 #include "SkMathPriv.h"
     27 #include "SkString.h"
     28 #include "ops/GrMeshDrawOp.h"
     29 #include "text/GrAtlasGlyphCache.h"
     30 #include "text/GrTextBlobCache.h"
     31 
     32 namespace GrTest {
     33 void SetupAlwaysEvictAtlas(GrContext* context) {
     34     // These sizes were selected because they allow each atlas to hold a single plot and will thus
     35     // stress the atlas
     36     int dim = GrDrawOpAtlas::kGlyphMaxDim;
     37     GrDrawOpAtlasConfig configs[3];
     38     configs[kA8_GrMaskFormat].fWidth = dim;
     39     configs[kA8_GrMaskFormat].fHeight = dim;
     40     configs[kA8_GrMaskFormat].fLog2Width = SkNextLog2(dim);
     41     configs[kA8_GrMaskFormat].fLog2Height = SkNextLog2(dim);
     42     configs[kA8_GrMaskFormat].fPlotWidth = dim;
     43     configs[kA8_GrMaskFormat].fPlotHeight = dim;
     44 
     45     configs[kA565_GrMaskFormat].fWidth = dim;
     46     configs[kA565_GrMaskFormat].fHeight = dim;
     47     configs[kA565_GrMaskFormat].fLog2Width = SkNextLog2(dim);
     48     configs[kA565_GrMaskFormat].fLog2Height = SkNextLog2(dim);
     49     configs[kA565_GrMaskFormat].fPlotWidth = dim;
     50     configs[kA565_GrMaskFormat].fPlotHeight = dim;
     51 
     52     configs[kARGB_GrMaskFormat].fWidth = dim;
     53     configs[kARGB_GrMaskFormat].fHeight = dim;
     54     configs[kARGB_GrMaskFormat].fLog2Width = SkNextLog2(dim);
     55     configs[kARGB_GrMaskFormat].fLog2Height = SkNextLog2(dim);
     56     configs[kARGB_GrMaskFormat].fPlotWidth = dim;
     57     configs[kARGB_GrMaskFormat].fPlotHeight = dim;
     58 
     59     context->setTextContextAtlasSizes_ForTesting(configs);
     60 }
     61 
     62 GrBackendTexture CreateBackendTexture(GrBackend backend, int width, int height,
     63                                       GrPixelConfig config, GrBackendObject handle) {
     64 #ifdef SK_VULKAN
     65     if (kVulkan_GrBackend == backend) {
     66         GrVkImageInfo* vkInfo = (GrVkImageInfo*)(handle);
     67         return GrBackendTexture(width, height, *vkInfo);
     68     }
     69 #endif
     70     SkASSERT(kOpenGL_GrBackend == backend);
     71     GrGLTextureInfo* glInfo = (GrGLTextureInfo*)(handle);
     72     return GrBackendTexture(width, height, config, *glInfo);
     73 }
     74 };
     75 
     76 bool GrSurfaceProxy::isWrapped_ForTesting() const {
     77     return SkToBool(fTarget);
     78 }
     79 
     80 bool GrRenderTargetContext::isWrapped_ForTesting() const {
     81     return fRenderTargetProxy->isWrapped_ForTesting();
     82 }
     83 
     84 void GrContext::setTextBlobCacheLimit_ForTesting(size_t bytes) {
     85     fTextBlobCache->setBudget(bytes);
     86 }
     87 
     88 void GrContext::setTextContextAtlasSizes_ForTesting(const GrDrawOpAtlasConfig* configs) {
     89     fAtlasGlyphCache->setAtlasSizes_ForTesting(configs);
     90 }
     91 
     92 ///////////////////////////////////////////////////////////////////////////////
     93 
     94 void GrContext::purgeAllUnlockedResources() {
     95     fResourceCache->purgeAllUnlocked();
     96 }
     97 
     98 void GrContext::resetGpuStats() const {
     99 #if GR_GPU_STATS
    100     fGpu->stats()->reset();
    101 #endif
    102 }
    103 
    104 void GrContext::dumpCacheStats(SkString* out) const {
    105 #if GR_CACHE_STATS
    106     fResourceCache->dumpStats(out);
    107 #endif
    108 }
    109 
    110 void GrContext::dumpCacheStatsKeyValuePairs(SkTArray<SkString>* keys,
    111                                             SkTArray<double>* values) const {
    112 #if GR_CACHE_STATS
    113     fResourceCache->dumpStatsKeyValuePairs(keys, values);
    114 #endif
    115 }
    116 
    117 void GrContext::printCacheStats() const {
    118     SkString out;
    119     this->dumpCacheStats(&out);
    120     SkDebugf("%s", out.c_str());
    121 }
    122 
    123 void GrContext::dumpGpuStats(SkString* out) const {
    124 #if GR_GPU_STATS
    125     return fGpu->stats()->dump(out);
    126 #endif
    127 }
    128 
    129 void GrContext::dumpGpuStatsKeyValuePairs(SkTArray<SkString>* keys,
    130                                           SkTArray<double>* values) const {
    131 #if GR_GPU_STATS
    132     return fGpu->stats()->dumpKeyValuePairs(keys, values);
    133 #endif
    134 }
    135 
    136 void GrContext::printGpuStats() const {
    137     SkString out;
    138     this->dumpGpuStats(&out);
    139     SkDebugf("%s", out.c_str());
    140 }
    141 
    142 sk_sp<SkImage> GrContext::getFontAtlasImage_ForTesting(GrMaskFormat format) {
    143     GrAtlasGlyphCache* cache = this->getAtlasGlyphCache();
    144 
    145     sk_sp<GrTextureProxy> proxy = cache->getProxy(format);
    146     if (!proxy) {
    147         return nullptr;
    148     }
    149 
    150     SkASSERT(proxy->priv().isExact());
    151     sk_sp<SkImage> image(new SkImage_Gpu(this, kNeedNewImageUniqueID, kPremul_SkAlphaType,
    152                                          std::move(proxy), nullptr, SkBudgeted::kNo));
    153     return image;
    154 }
    155 
    156 #if GR_GPU_STATS
    157 void GrGpu::Stats::dump(SkString* out) {
    158     out->appendf("Render Target Binds: %d\n", fRenderTargetBinds);
    159     out->appendf("Shader Compilations: %d\n", fShaderCompilations);
    160     out->appendf("Textures Created: %d\n", fTextureCreates);
    161     out->appendf("Texture Uploads: %d\n", fTextureUploads);
    162     out->appendf("Transfers to Texture: %d\n", fTransfersToTexture);
    163     out->appendf("Stencil Buffer Creates: %d\n", fStencilAttachmentCreates);
    164     out->appendf("Number of draws: %d\n", fNumDraws);
    165 }
    166 
    167 void GrGpu::Stats::dumpKeyValuePairs(SkTArray<SkString>* keys, SkTArray<double>* values) {
    168     keys->push_back(SkString("render_target_binds")); values->push_back(fRenderTargetBinds);
    169     keys->push_back(SkString("shader_compilations")); values->push_back(fShaderCompilations);
    170     keys->push_back(SkString("texture_uploads")); values->push_back(fTextureUploads);
    171     keys->push_back(SkString("number_of_draws")); values->push_back(fNumDraws);
    172     keys->push_back(SkString("number_of_failed_draws")); values->push_back(fNumFailedDraws);
    173 }
    174 
    175 #endif
    176 
    177 #if GR_CACHE_STATS
    178 void GrResourceCache::getStats(Stats* stats) const {
    179     stats->reset();
    180 
    181     stats->fTotal = this->getResourceCount();
    182     stats->fNumNonPurgeable = fNonpurgeableResources.count();
    183     stats->fNumPurgeable = fPurgeableQueue.count();
    184 
    185     for (int i = 0; i < fNonpurgeableResources.count(); ++i) {
    186         stats->update(fNonpurgeableResources[i]);
    187     }
    188     for (int i = 0; i < fPurgeableQueue.count(); ++i) {
    189         stats->update(fPurgeableQueue.at(i));
    190     }
    191 }
    192 
    193 void GrResourceCache::dumpStats(SkString* out) const {
    194     this->validate();
    195 
    196     Stats stats;
    197 
    198     this->getStats(&stats);
    199 
    200     float countUtilization = (100.f * fBudgetedCount) / fMaxCount;
    201     float byteUtilization = (100.f * fBudgetedBytes) / fMaxBytes;
    202 
    203     out->appendf("Budget: %d items %d bytes\n", fMaxCount, (int)fMaxBytes);
    204     out->appendf("\t\tEntry Count: current %d"
    205                  " (%d budgeted, %d wrapped, %d locked, %d scratch %.2g%% full), high %d\n",
    206                  stats.fTotal, fBudgetedCount, stats.fWrapped, stats.fNumNonPurgeable,
    207                  stats.fScratch, countUtilization, fHighWaterCount);
    208     out->appendf("\t\tEntry Bytes: current %d (budgeted %d, %.2g%% full, %d unbudgeted) high %d\n",
    209                  SkToInt(fBytes), SkToInt(fBudgetedBytes), byteUtilization,
    210                  SkToInt(stats.fUnbudgetedSize), SkToInt(fHighWaterBytes));
    211 }
    212 
    213 void GrResourceCache::dumpStatsKeyValuePairs(SkTArray<SkString>* keys,
    214                                              SkTArray<double>* values) const {
    215     this->validate();
    216 
    217     Stats stats;
    218     this->getStats(&stats);
    219 
    220     keys->push_back(SkString("gpu_cache_purgable_entries")); values->push_back(stats.fNumPurgeable);
    221 }
    222 
    223 #endif
    224 
    225 ///////////////////////////////////////////////////////////////////////////////
    226 
    227 void GrResourceCache::changeTimestamp(uint32_t newTimestamp) { fTimestamp = newTimestamp; }
    228 
    229 #ifdef SK_DEBUG
    230 int GrResourceCache::countUniqueKeysWithTag(const char* tag) const {
    231     int count = 0;
    232     UniqueHash::ConstIter iter(&fUniqueHash);
    233     while (!iter.done()) {
    234         if (0 == strcmp(tag, (*iter).getUniqueKey().tag())) {
    235             ++count;
    236         }
    237         ++iter;
    238     }
    239     return count;
    240 }
    241 #endif
    242 
    243 ///////////////////////////////////////////////////////////////////////////////
    244 
    245 #define ASSERT_SINGLE_OWNER \
    246     SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fRenderTargetContext->singleOwner());)
    247 
    248 uint32_t GrRenderTargetContextPriv::testingOnly_addDrawOp(std::unique_ptr<GrDrawOp> op) {
    249     ASSERT_SINGLE_OWNER
    250     if (fRenderTargetContext->drawingManager()->wasAbandoned()) {
    251         return SK_InvalidUniqueID;
    252     }
    253     SkDEBUGCODE(fRenderTargetContext->validate());
    254     GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
    255                               "GrRenderTargetContext::testingOnly_addDrawOp");
    256     return fRenderTargetContext->addDrawOp(GrNoClip(), std::move(op));
    257 }
    258 
    259 #undef ASSERT_SINGLE_OWNER
    260 
    261 ///////////////////////////////////////////////////////////////////////////////
    262 
    263 GrRenderTargetFlags GrRenderTargetProxy::testingOnly_getFlags() const {
    264     return fRenderTargetFlags;
    265 }
    266 
    267 //////////////////////////////////////////////////////////////////////////////
    268 
    269 void GrContextPriv::testingOnly_flushAndRemoveOnFlushCallbackObject(GrOnFlushCallbackObject* cb) {
    270     fContext->flush();
    271     fContext->fDrawingManager->testingOnly_removeOnFlushCallbackObject(cb);
    272 }
    273 
    274 void GrDrawingManager::testingOnly_removeOnFlushCallbackObject(GrOnFlushCallbackObject* cb) {
    275     int n = std::find(fOnFlushCBObjects.begin(), fOnFlushCBObjects.end(), cb) -
    276             fOnFlushCBObjects.begin();
    277     SkASSERT(n < fOnFlushCBObjects.count());
    278     fOnFlushCBObjects.removeShuffle(n);
    279 }
    280 
    281 //////////////////////////////////////////////////////////////////////////////
    282 
    283 #define DRAW_OP_TEST_EXTERN(Op) \
    284     extern std::unique_ptr<GrDrawOp> Op##__Test(GrPaint&&, SkRandom*, GrContext*, GrFSAAType)
    285 #define DRAW_OP_TEST_ENTRY(Op) Op##__Test
    286 
    287 DRAW_OP_TEST_EXTERN(AAConvexPathOp);
    288 DRAW_OP_TEST_EXTERN(AAFillRectOp);
    289 DRAW_OP_TEST_EXTERN(AAFlatteningConvexPathOp);
    290 DRAW_OP_TEST_EXTERN(AAHairlineOp);
    291 DRAW_OP_TEST_EXTERN(AAStrokeRectOp);
    292 DRAW_OP_TEST_EXTERN(CircleOp);
    293 DRAW_OP_TEST_EXTERN(DashOp);
    294 DRAW_OP_TEST_EXTERN(DefaultPathOp);
    295 DRAW_OP_TEST_EXTERN(DIEllipseOp);
    296 DRAW_OP_TEST_EXTERN(EllipseOp);
    297 DRAW_OP_TEST_EXTERN(GrAtlasTextOp);
    298 DRAW_OP_TEST_EXTERN(GrDrawAtlasOp);
    299 DRAW_OP_TEST_EXTERN(GrDrawVerticesOp);
    300 DRAW_OP_TEST_EXTERN(NonAAFillRectOp);
    301 DRAW_OP_TEST_EXTERN(NonAALatticeOp);
    302 DRAW_OP_TEST_EXTERN(NonAAStrokeRectOp);
    303 DRAW_OP_TEST_EXTERN(ShadowRRectOp);
    304 DRAW_OP_TEST_EXTERN(SmallPathOp);
    305 DRAW_OP_TEST_EXTERN(RegionOp);
    306 DRAW_OP_TEST_EXTERN(RRectOp);
    307 DRAW_OP_TEST_EXTERN(TesselatingPathOp);
    308 
    309 void GrDrawRandomOp(SkRandom* random, GrRenderTargetContext* renderTargetContext, GrPaint&& paint) {
    310     GrContext* context = renderTargetContext->surfPriv().getContext();
    311     using MakeDrawOpFn = std::unique_ptr<GrDrawOp>(GrPaint&&, SkRandom*, GrContext*, GrFSAAType);
    312     static constexpr MakeDrawOpFn* gFactories[] = {
    313         DRAW_OP_TEST_ENTRY(AAConvexPathOp),
    314         DRAW_OP_TEST_ENTRY(AAFillRectOp),
    315         DRAW_OP_TEST_ENTRY(AAFlatteningConvexPathOp),
    316         DRAW_OP_TEST_ENTRY(AAHairlineOp),
    317         DRAW_OP_TEST_ENTRY(AAStrokeRectOp),
    318         DRAW_OP_TEST_ENTRY(CircleOp),
    319         DRAW_OP_TEST_ENTRY(DashOp),
    320         DRAW_OP_TEST_ENTRY(DefaultPathOp),
    321         DRAW_OP_TEST_ENTRY(DIEllipseOp),
    322         DRAW_OP_TEST_ENTRY(EllipseOp),
    323         DRAW_OP_TEST_ENTRY(GrAtlasTextOp),
    324         DRAW_OP_TEST_ENTRY(GrDrawAtlasOp),
    325         DRAW_OP_TEST_ENTRY(GrDrawVerticesOp),
    326         DRAW_OP_TEST_ENTRY(NonAAFillRectOp),
    327         DRAW_OP_TEST_ENTRY(NonAALatticeOp),
    328         DRAW_OP_TEST_ENTRY(NonAAStrokeRectOp),
    329         DRAW_OP_TEST_ENTRY(ShadowRRectOp),
    330         DRAW_OP_TEST_ENTRY(SmallPathOp),
    331         DRAW_OP_TEST_ENTRY(RegionOp),
    332         DRAW_OP_TEST_ENTRY(RRectOp),
    333         DRAW_OP_TEST_ENTRY(TesselatingPathOp),
    334     };
    335 
    336     static constexpr size_t kTotal = SK_ARRAY_COUNT(gFactories);
    337     uint32_t index = random->nextULessThan(static_cast<uint32_t>(kTotal));
    338     auto op = gFactories[index](
    339             std::move(paint), random, context, renderTargetContext->fsaaType());
    340     SkASSERT(op);
    341     renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
    342 }
    343