• 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 
9 #include "include/gpu/GrContextOptions.h"
10 #include "include/gpu/GrDirectContext.h"
11 #include "src/core/SkOpts.h"
12 #include "src/gpu/GrDirectContextPriv.h"
13 #include "src/gpu/GrProcessor.h"
14 #include "src/gpu/GrRenderTarget.h"
15 #include "src/gpu/GrStencilSettings.h"
16 #include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
17 #include "src/gpu/glsl/GrGLSLProgramDataManager.h"
18 #include "src/gpu/vk/GrVkGpu.h"
19 #include "src/gpu/vk/GrVkPipelineState.h"
20 #include "src/gpu/vk/GrVkPipelineStateBuilder.h"
21 #include "src/gpu/vk/GrVkResourceProvider.h"
22 
23 #ifdef SK_DEBUG
24 // Display pipeline state cache usage
25 static const bool c_DisplayVkPipelineCache{false};
26 #endif
27 
28 struct GrVkResourceProvider::PipelineStateCache::Entry {
EntryGrVkResourceProvider::PipelineStateCache::Entry29     Entry(GrVkGpu* gpu, GrVkPipelineState* pipelineState)
30     : fGpu(gpu)
31     , fPipelineState(pipelineState) {}
32 
~EntryGrVkResourceProvider::PipelineStateCache::Entry33     ~Entry() {
34         if (fPipelineState) {
35             fPipelineState->freeGPUResources(fGpu);
36         }
37     }
38 
39     GrVkGpu* fGpu;
40     std::unique_ptr<GrVkPipelineState> fPipelineState;
41 };
42 
PipelineStateCache(GrVkGpu * gpu)43 GrVkResourceProvider::PipelineStateCache::PipelineStateCache(GrVkGpu* gpu)
44     : fMap(gpu->getContext()->priv().options().fRuntimeProgramCacheSize)
45     , fGpu(gpu) {
46 }
47 
~PipelineStateCache()48 GrVkResourceProvider::PipelineStateCache::~PipelineStateCache() {
49     SkASSERT(0 == fMap.count());
50     // dump stats
51 #ifdef SK_DEBUG
52     if (c_DisplayVkPipelineCache) {
53         using CacheResult = Stats::ProgramCacheResult;
54 
55         int misses = fStats.numInlineProgramCacheResult(CacheResult::kMiss) +
56                      fStats.numPreProgramCacheResult(CacheResult::kMiss);
57 
58         int total = misses + fStats.numInlineProgramCacheResult(CacheResult::kHit) +
59                              fStats.numPreProgramCacheResult(CacheResult::kHit);
60 
61         SkDebugf("--- Pipeline State Cache ---\n");
62         SkDebugf("Total requests: %d\n", total);
63         SkDebugf("Cache misses: %d\n", misses);
64         SkDebugf("Cache miss %%: %f\n", (total > 0) ? 100.f * misses / total : 0.0f);
65     }
66 #endif
67 }
68 
release()69 void GrVkResourceProvider::PipelineStateCache::release() {
70     fMap.reset();
71 }
72 
findOrCreatePipelineState(GrRenderTarget * renderTarget,const GrProgramInfo & programInfo,VkRenderPass compatibleRenderPass,bool overrideSubpassForResolveLoad)73 GrVkPipelineState* GrVkResourceProvider::PipelineStateCache::findOrCreatePipelineState(
74         GrRenderTarget* renderTarget,
75         const GrProgramInfo& programInfo,
76         VkRenderPass compatibleRenderPass,
77         bool overrideSubpassForResolveLoad) {
78 #ifdef SK_DEBUG
79     if (programInfo.isStencilEnabled()) {
80         SkASSERT(renderTarget->getStencilAttachment());
81         SkASSERT(renderTarget->numStencilBits(renderTarget->numSamples() > 1) == 8);
82         SkASSERT(renderTarget->getStencilAttachment()->numSamples() == 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