• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "include/gpu/GrContextOptions.h"
9 #include "include/gpu/GrDirectContext.h"
10 #include "src/core/SkOpts.h"
11 #include "src/gpu/GrDirectContextPriv.h"
12 #include "src/gpu/GrFragmentProcessor.h"
13 #include "src/gpu/GrProcessor.h"
14 #include "src/gpu/GrRenderTarget.h"
15 #include "src/gpu/GrStencilSettings.h"
16 #include "src/gpu/glsl/GrGLSLProgramDataManager.h"
17 #include "src/gpu/vk/GrVkGpu.h"
18 #include "src/gpu/vk/GrVkPipelineState.h"
19 #include "src/gpu/vk/GrVkPipelineStateBuilder.h"
20 #include "src/gpu/vk/GrVkResourceProvider.h"
21 
22 #ifdef SK_DEBUG
23 // Display pipeline state cache usage
24 static const bool c_DisplayVkPipelineCache{false};
25 #endif
26 
27 struct GrVkResourceProvider::PipelineStateCache::Entry {
EntryGrVkResourceProvider::PipelineStateCache::Entry28     Entry(GrVkGpu* gpu, GrVkPipelineState* pipelineState)
29     : fGpu(gpu)
30     , fPipelineState(pipelineState) {}
31 
~EntryGrVkResourceProvider::PipelineStateCache::Entry32     ~Entry() {
33         if (fPipelineState) {
34             fPipelineState->freeGPUResources(fGpu);
35         }
36     }
37 
38     GrVkGpu* fGpu;
39     std::unique_ptr<GrVkPipelineState> fPipelineState;
40 };
41 
PipelineStateCache(GrVkGpu * gpu)42 GrVkResourceProvider::PipelineStateCache::PipelineStateCache(GrVkGpu* gpu)
43     : fMap(gpu->getContext()->priv().options().fRuntimeProgramCacheSize)
44     , fGpu(gpu) {
45 #ifdef SKIA_DFX_FOR_OHOS
46     fStats.setPipelineCountMax(gpu->getContext()->priv().options().fRuntimeProgramCacheSize);
47 #endif
48 }
49 
~PipelineStateCache()50 GrVkResourceProvider::PipelineStateCache::~PipelineStateCache() {
51     SkASSERT(0 == fMap.count());
52     // dump stats
53 #ifdef SK_DEBUG
54     if (c_DisplayVkPipelineCache) {
55         using CacheResult = Stats::ProgramCacheResult;
56 
57         int misses = fStats.numInlineProgramCacheResult(CacheResult::kMiss) +
58                      fStats.numPreProgramCacheResult(CacheResult::kMiss);
59 
60         int total = misses + fStats.numInlineProgramCacheResult(CacheResult::kHit) +
61                              fStats.numPreProgramCacheResult(CacheResult::kHit);
62 
63         SkDebugf("--- Pipeline State Cache ---\n");
64         SkDebugf("Total requests: %d\n", total);
65         SkDebugf("Cache misses: %d\n", misses);
66         SkDebugf("Cache miss %%: %f\n", (total > 0) ? 100.f * misses / total : 0.0f);
67     }
68 #endif
69 }
70 
release()71 void GrVkResourceProvider::PipelineStateCache::release() {
72     fMap.reset();
73 }
74 
findOrCreatePipelineState(GrRenderTarget * renderTarget,const GrProgramInfo & programInfo,VkRenderPass compatibleRenderPass,bool overrideSubpassForResolveLoad)75 GrVkPipelineState* GrVkResourceProvider::PipelineStateCache::findOrCreatePipelineState(
76         GrRenderTarget* renderTarget,
77         const GrProgramInfo& programInfo,
78         VkRenderPass compatibleRenderPass,
79         bool overrideSubpassForResolveLoad) {
80 #ifdef SK_DEBUG
81     if (programInfo.isStencilEnabled()) {
82         SkASSERT(renderTarget->getStencilAttachment(programInfo.numSamples() > 1));
83         SkASSERT(renderTarget->numStencilBits(programInfo.numSamples() > 1) == 8);
84         SkASSERT(renderTarget->getStencilAttachment(programInfo.numSamples() > 1)->numSamples() ==
85                  programInfo.numSamples());
86     }
87 #endif
88 
89     auto flags = overrideSubpassForResolveLoad
90             ? GrCaps::ProgramDescOverrideFlags::kVulkanHasResolveLoadSubpass
91             : GrCaps::ProgramDescOverrideFlags::kNone;
92 
93     GrProgramDesc desc = fGpu->caps()->makeDesc(renderTarget, programInfo, flags);
94     if (!desc.isValid()) {
95         GrCapsDebugf(fGpu->caps(), "Failed to build vk program descriptor!\n");
96         return nullptr;
97     }
98 
99     Stats::ProgramCacheResult stat;
100     auto tmp = this->findOrCreatePipelineStateImpl(desc, programInfo, compatibleRenderPass,
101                                                    overrideSubpassForResolveLoad, &stat);
102     if (!tmp) {
103         fStats.incNumInlineCompilationFailures();
104     } else {
105         fStats.incNumInlineProgramCacheResult(stat);
106     }
107 #ifdef SKIA_DFX_FOR_OHOS
108     fStats.updatePipelineCount(fMap.count());
109 #endif
110     return tmp;
111 }
112 
findOrCreatePipelineStateImpl(const GrProgramDesc & desc,const GrProgramInfo & programInfo,VkRenderPass compatibleRenderPass,bool overrideSubpassForResolveLoad,Stats::ProgramCacheResult * stat)113 GrVkPipelineState* GrVkResourceProvider::PipelineStateCache::findOrCreatePipelineStateImpl(
114         const GrProgramDesc& desc,
115         const GrProgramInfo& programInfo,
116         VkRenderPass compatibleRenderPass,
117         bool overrideSubpassForResolveLoad,
118         Stats::ProgramCacheResult* stat) {
119     if (stat) {
120         *stat = Stats::ProgramCacheResult::kHit;
121     }
122 
123     std::unique_ptr<Entry>* entry = fMap.find(desc);
124     if (!entry) {
125         if (stat) {
126             *stat = Stats::ProgramCacheResult::kMiss;
127         }
128         GrVkPipelineState* pipelineState(GrVkPipelineStateBuilder::CreatePipelineState(
129                 fGpu, desc, programInfo, compatibleRenderPass, overrideSubpassForResolveLoad));
130         if (!pipelineState) {
131             return nullptr;
132         }
133         entry = fMap.insert(desc, std::make_unique<Entry>(fGpu, pipelineState));
134         return (*entry)->fPipelineState.get();
135     }
136     return (*entry)->fPipelineState.get();
137 }
138