• 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 }
46 
~PipelineStateCache()47 GrVkResourceProvider::PipelineStateCache::~PipelineStateCache() {
48     SkASSERT(0 == fMap.count());
49     // dump stats
50 #ifdef SK_DEBUG
51     if (c_DisplayVkPipelineCache) {
52         using CacheResult = Stats::ProgramCacheResult;
53 
54         int misses = fStats.numInlineProgramCacheResult(CacheResult::kMiss) +
55                      fStats.numPreProgramCacheResult(CacheResult::kMiss);
56 
57         int total = misses + fStats.numInlineProgramCacheResult(CacheResult::kHit) +
58                              fStats.numPreProgramCacheResult(CacheResult::kHit);
59 
60         SkDebugf("--- Pipeline State Cache ---\n");
61         SkDebugf("Total requests: %d\n", total);
62         SkDebugf("Cache misses: %d\n", misses);
63         SkDebugf("Cache miss %%: %f\n", (total > 0) ? 100.f * misses / total : 0.0f);
64     }
65 #endif
66 }
67 
release()68 void GrVkResourceProvider::PipelineStateCache::release() {
69     fMap.reset();
70 }
71 
findOrCreatePipelineState(GrRenderTarget * renderTarget,const GrProgramInfo & programInfo,VkRenderPass compatibleRenderPass,bool overrideSubpassForResolveLoad)72 GrVkPipelineState* GrVkResourceProvider::PipelineStateCache::findOrCreatePipelineState(
73         GrRenderTarget* renderTarget,
74         const GrProgramInfo& programInfo,
75         VkRenderPass compatibleRenderPass,
76         bool overrideSubpassForResolveLoad) {
77 #ifdef SK_DEBUG
78     if (programInfo.isStencilEnabled()) {
79         SkASSERT(renderTarget->getStencilAttachment(programInfo.numSamples() > 1));
80         SkASSERT(renderTarget->numStencilBits(programInfo.numSamples() > 1) == 8);
81         SkASSERT(renderTarget->getStencilAttachment(programInfo.numSamples() > 1)->numSamples() ==
82                  programInfo.numSamples());
83     }
84 #endif
85 
86     auto flags = overrideSubpassForResolveLoad
87             ? GrCaps::ProgramDescOverrideFlags::kVulkanHasResolveLoadSubpass
88             : GrCaps::ProgramDescOverrideFlags::kNone;
89 
90     GrProgramDesc desc = fGpu->caps()->makeDesc(renderTarget, programInfo, flags);
91     if (!desc.isValid()) {
92         GrCapsDebugf(fGpu->caps(), "Failed to build vk program descriptor!\n");
93         return nullptr;
94     }
95 
96     Stats::ProgramCacheResult stat;
97     auto tmp = this->findOrCreatePipelineStateImpl(desc, programInfo, compatibleRenderPass,
98                                                    overrideSubpassForResolveLoad, &stat);
99     if (!tmp) {
100         fStats.incNumInlineCompilationFailures();
101     } else {
102         fStats.incNumInlineProgramCacheResult(stat);
103     }
104 
105     return tmp;
106 }
107 
findOrCreatePipelineStateImpl(const GrProgramDesc & desc,const GrProgramInfo & programInfo,VkRenderPass compatibleRenderPass,bool overrideSubpassForResolveLoad,Stats::ProgramCacheResult * stat)108 GrVkPipelineState* GrVkResourceProvider::PipelineStateCache::findOrCreatePipelineStateImpl(
109         const GrProgramDesc& desc,
110         const GrProgramInfo& programInfo,
111         VkRenderPass compatibleRenderPass,
112         bool overrideSubpassForResolveLoad,
113         Stats::ProgramCacheResult* stat) {
114     if (stat) {
115         *stat = Stats::ProgramCacheResult::kHit;
116     }
117 
118     std::unique_ptr<Entry>* entry = fMap.find(desc);
119     if (!entry) {
120         if (stat) {
121             *stat = Stats::ProgramCacheResult::kMiss;
122         }
123         GrVkPipelineState* pipelineState(GrVkPipelineStateBuilder::CreatePipelineState(
124                 fGpu, desc, programInfo, compatibleRenderPass, overrideSubpassForResolveLoad));
125         if (!pipelineState) {
126             return nullptr;
127         }
128         entry = fMap.insert(desc, std::make_unique<Entry>(fGpu, pipelineState));
129         return (*entry)->fPipelineState.get();
130     }
131     return (*entry)->fPipelineState.get();
132 }
133