Home | History | Annotate | Download | only in vk
      1 /*
      2  * Copyright 2016 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 "GrVkResourceProvider.h"
      9 
     10 #include "GrVkGpu.h"
     11 #include "GrProcessor.h"
     12 #include "GrRenderTargetPriv.h" // TODO: remove once refPipelineState gets passed stencil settings.
     13 #include "GrVkPipelineState.h"
     14 #include "GrVkPipelineStateBuilder.h"
     15 #include "SkOpts.h"
     16 #include "glsl/GrGLSLFragmentProcessor.h"
     17 #include "glsl/GrGLSLProgramDataManager.h"
     18 
     19 #ifdef GR_PIPELINE_STATE_CACHE_STATS
     20 // Display pipeline state cache usage
     21 static const bool c_DisplayVkPipelineCache{false};
     22 #endif
     23 
     24 struct GrVkResourceProvider::PipelineStateCache::Entry {
     25     Entry(GrVkGpu* gpu, GrVkPipelineState* pipelineState)
     26     : fGpu(gpu)
     27     , fPipelineState(pipelineState) {}
     28 
     29     ~Entry() {
     30         if (fPipelineState) {
     31             fPipelineState->freeGPUResources(fGpu);
     32         }
     33     }
     34 
     35     GrVkGpu* fGpu;
     36     std::unique_ptr<GrVkPipelineState> fPipelineState;
     37 };
     38 
     39 GrVkResourceProvider::PipelineStateCache::PipelineStateCache(GrVkGpu* gpu)
     40     : fMap(kMaxEntries)
     41     , fGpu(gpu)
     42 #ifdef GR_PIPELINE_STATE_CACHE_STATS
     43     , fTotalRequests(0)
     44     , fCacheMisses(0)
     45 #endif
     46 {}
     47 
     48 GrVkResourceProvider::PipelineStateCache::~PipelineStateCache() {
     49     SkASSERT(0 == fMap.count());
     50     // dump stats
     51 #ifdef GR_PIPELINE_STATE_CACHE_STATS
     52     if (c_DisplayVkPipelineCache) {
     53         SkDebugf("--- Pipeline State Cache ---\n");
     54         SkDebugf("Total requests: %d\n", fTotalRequests);
     55         SkDebugf("Cache misses: %d\n", fCacheMisses);
     56         SkDebugf("Cache miss %%: %f\n", (fTotalRequests > 0) ?
     57                  100.f * fCacheMisses / fTotalRequests :
     58                  0.f);
     59         SkDebugf("---------------------\n");
     60     }
     61 #endif
     62 }
     63 
     64 void GrVkResourceProvider::PipelineStateCache::abandon() {
     65     fMap.foreach([](std::unique_ptr<Entry>* e) {
     66         (*e)->fPipelineState->abandonGPUResources();
     67         (*e)->fPipelineState = nullptr;
     68     });
     69     fMap.reset();
     70 }
     71 
     72 void GrVkResourceProvider::PipelineStateCache::release() {
     73     fMap.reset();
     74 }
     75 
     76 GrVkPipelineState* GrVkResourceProvider::PipelineStateCache::refPipelineState(
     77                                                                const GrPipeline& pipeline,
     78                                                                const GrPrimitiveProcessor& primProc,
     79                                                                GrPrimitiveType primitiveType,
     80                                                                const GrVkRenderPass& renderPass) {
     81 #ifdef GR_PIPELINE_STATE_CACHE_STATS
     82     ++fTotalRequests;
     83 #endif
     84     GrStencilSettings stencil;
     85     if (pipeline.isStencilEnabled()) {
     86         GrRenderTarget* rt = pipeline.renderTarget();
     87         // TODO: attach stencil and create settings during render target flush.
     88         SkASSERT(rt->renderTargetPriv().getStencilAttachment());
     89         stencil.reset(*pipeline.getUserStencil(), pipeline.hasStencilClip(),
     90                       rt->renderTargetPriv().numStencilBits());
     91     }
     92 
     93     // Get GrVkProgramDesc
     94     GrVkPipelineState::Desc desc;
     95     if (!GrVkPipelineState::Desc::Build(&desc, primProc, pipeline, stencil,
     96                                         primitiveType, *fGpu->caps()->shaderCaps())) {
     97         GrCapsDebugf(fGpu->caps(), "Failed to build vk program descriptor!\n");
     98         return nullptr;
     99     }
    100     desc.finalize();
    101 
    102     std::unique_ptr<Entry>* entry = fMap.find(desc);
    103     if (!entry) {
    104         // Didn't find an origin-independent version, check with the specific origin
    105         GrSurfaceOrigin origin = pipeline.proxy()->origin();
    106         desc.setSurfaceOriginKey(GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(origin));
    107         desc.finalize();
    108         entry = fMap.find(desc);
    109     }
    110     if (!entry) {
    111 #ifdef GR_PIPELINE_STATE_CACHE_STATS
    112         ++fCacheMisses;
    113 #endif
    114         GrVkPipelineState* pipelineState(
    115             GrVkPipelineStateBuilder::CreatePipelineState(fGpu,
    116                                                           pipeline,
    117                                                           stencil,
    118                                                           primProc,
    119                                                           primitiveType,
    120                                                           &desc,
    121                                                           renderPass));
    122         if (nullptr == pipelineState) {
    123             return nullptr;
    124         }
    125         entry = fMap.insert(desc, std::unique_ptr<Entry>(new Entry(fGpu, pipelineState)));
    126         return (*entry)->fPipelineState.get();
    127     }
    128     return (*entry)->fPipelineState.get();
    129 }
    130