GrVkPipelineStateCache.cpp revision 1edc5b92fecefb79f01cf0e302646eacf32b06c7
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 21static const bool c_DisplayVkPipelineCache{false}; 22#endif 23 24struct GrVkResourceProvider::PipelineStateCache::Entry { 25 26 Entry() : fPipelineState(nullptr) {} 27 28 static const GrVkPipelineState::Desc& GetKey(const Entry* entry) { 29 return entry->fPipelineState->getDesc(); 30 } 31 32 static uint32_t Hash(const GrVkPipelineState::Desc& key) { 33 return key.getChecksum(); 34 } 35 36 sk_sp<GrVkPipelineState> fPipelineState; 37 38private: 39 SK_DECLARE_INTERNAL_LLIST_INTERFACE(Entry); 40}; 41 42GrVkResourceProvider::PipelineStateCache::PipelineStateCache(GrVkGpu* gpu) 43 : fCount(0) 44 , fGpu(gpu) 45#ifdef GR_PIPELINE_STATE_CACHE_STATS 46 , fTotalRequests(0) 47 , fCacheMisses(0) 48#endif 49{} 50 51GrVkResourceProvider::PipelineStateCache::~PipelineStateCache() { 52 SkASSERT(0 == fCount); 53 // dump stats 54#ifdef GR_PIPELINE_STATE_CACHE_STATS 55 if (c_DisplayVkPipelineCache) { 56 SkDebugf("--- Pipeline State Cache ---\n"); 57 SkDebugf("Total requests: %d\n", fTotalRequests); 58 SkDebugf("Cache misses: %d\n", fCacheMisses); 59 SkDebugf("Cache miss %%: %f\n", (fTotalRequests > 0) ? 60 100.f * fCacheMisses / fTotalRequests : 61 0.f); 62 SkDebugf("---------------------\n"); 63 } 64#endif 65} 66 67void GrVkResourceProvider::PipelineStateCache::reset() { 68 fHashTable.foreach([](Entry** entry) { 69 delete *entry; 70 }); 71 fHashTable.reset(); 72 fCount = 0; 73} 74 75void GrVkResourceProvider::PipelineStateCache::abandon() { 76 fHashTable.foreach([](Entry** entry) { 77 SkASSERT((*entry)->fPipelineState.get()); 78 (*entry)->fPipelineState->abandonGPUResources(); 79 }); 80 81 this->reset(); 82} 83 84void GrVkResourceProvider::PipelineStateCache::release() { 85 fHashTable.foreach([this](Entry** entry) { 86 SkASSERT((*entry)->fPipelineState.get()); 87 (*entry)->fPipelineState->freeGPUResources(fGpu); 88 }); 89 90 this->reset(); 91} 92 93sk_sp<GrVkPipelineState> GrVkResourceProvider::PipelineStateCache::refPipelineState( 94 const GrPipeline& pipeline, 95 const GrPrimitiveProcessor& primProc, 96 GrPrimitiveType primitiveType, 97 const GrVkRenderPass& renderPass) { 98#ifdef GR_PIPELINE_STATE_CACHE_STATS 99 ++fTotalRequests; 100#endif 101 GrStencilSettings stencil; 102 if (pipeline.isStencilEnabled()) { 103 GrRenderTarget* rt = pipeline.getRenderTarget(); 104 // TODO: attach stencil and create settings during render target flush. 105 SkASSERT(rt->renderTargetPriv().getStencilAttachment()); 106 stencil.reset(*pipeline.getUserStencil(), pipeline.hasStencilClip(), 107 rt->renderTargetPriv().numStencilBits()); 108 } 109 110 // Get GrVkProgramDesc 111 GrVkPipelineState::Desc desc; 112 if (!GrVkPipelineState::Desc::Build(&desc, primProc, pipeline, stencil, 113 primitiveType, *fGpu->caps()->shaderCaps())) { 114 GrCapsDebugf(fGpu->caps(), "Failed to build vk program descriptor!\n"); 115 return nullptr; 116 } 117 desc.finalize(); 118 119 Entry* entry = nullptr; 120 if (Entry** entryptr = fHashTable.find(desc)) { 121 SkASSERT(*entryptr); 122 entry = *entryptr; 123 } 124 if (!entry) { 125#ifdef GR_PIPELINE_STATE_CACHE_STATS 126 ++fCacheMisses; 127#endif 128 sk_sp<GrVkPipelineState> pipelineState( 129 GrVkPipelineStateBuilder::CreatePipelineState(fGpu, 130 pipeline, 131 stencil, 132 primProc, 133 primitiveType, 134 desc, 135 renderPass)); 136 if (nullptr == pipelineState) { 137 return nullptr; 138 } 139 if (fCount < kMaxEntries) { 140 entry = new Entry; 141 fCount++; 142 } else { 143 SkASSERT(fCount == kMaxEntries); 144 entry = fLRUList.head(); 145 fLRUList.remove(entry); 146 entry->fPipelineState->freeGPUResources(fGpu); 147 fHashTable.remove(entry->fPipelineState->getDesc()); 148 } 149 entry->fPipelineState = std::move(pipelineState); 150 fHashTable.set(entry); 151 fLRUList.addToTail(entry); 152 return entry->fPipelineState; 153 } else { 154 fLRUList.remove(entry); 155 fLRUList.addToTail(entry); 156 } 157 return entry->fPipelineState; 158} 159