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 "src/core/SkOpts.h"
11 #include "src/gpu/GrContextPriv.h"
12 #include "src/gpu/GrProcessor.h"
13 #include "src/gpu/GrRenderTargetPriv.h"
14 #include "src/gpu/GrStencilSettings.h"
15 #include "src/gpu/glsl/GrGLSLFragmentProcessor.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 GR_PIPELINE_STATE_CACHE_STATS
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 GR_PIPELINE_STATE_CACHE_STATS
46 , fTotalRequests(0)
47 , fCacheMisses(0)
48 #endif
49 {}
50
~PipelineStateCache()51 GrVkResourceProvider::PipelineStateCache::~PipelineStateCache() {
52 SkASSERT(0 == fMap.count());
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
abandon()67 void GrVkResourceProvider::PipelineStateCache::abandon() {
68 fMap.foreach([](std::unique_ptr<Entry>* e) {
69 (*e)->fPipelineState->abandonGPUResources();
70 (*e)->fPipelineState = nullptr;
71 });
72 fMap.reset();
73 }
74
release()75 void GrVkResourceProvider::PipelineStateCache::release() {
76 fMap.reset();
77 }
78
refPipelineState(GrRenderTarget * renderTarget,const GrProgramInfo & programInfo,GrPrimitiveType primitiveType,VkRenderPass compatibleRenderPass)79 GrVkPipelineState* GrVkResourceProvider::PipelineStateCache::refPipelineState(
80 GrRenderTarget* renderTarget,
81 const GrProgramInfo& programInfo,
82 GrPrimitiveType primitiveType,
83 VkRenderPass compatibleRenderPass) {
84 #ifdef GR_PIPELINE_STATE_CACHE_STATS
85 ++fTotalRequests;
86 #endif
87 GrStencilSettings stencil;
88 if (programInfo.pipeline().isStencilEnabled()) {
89 // TODO: attach stencil and create settings during render target flush.
90 SkASSERT(renderTarget->renderTargetPriv().getStencilAttachment());
91 stencil.reset(*programInfo.pipeline().getUserStencil(),
92 programInfo.pipeline().hasStencilClip(),
93 renderTarget->renderTargetPriv().numStencilBits());
94 }
95
96 // TODO: can this be unified between GL, Vk and Mtl?
97 // Get GrVkProgramDesc
98 GrVkPipelineStateBuilder::Desc desc;
99 if (!GrVkPipelineStateBuilder::Desc::Build(&desc, renderTarget, programInfo, stencil,
100 primitiveType, fGpu)) {
101 GrCapsDebugf(fGpu->caps(), "Failed to build vk program descriptor!\n");
102 return nullptr;
103 }
104
105 std::unique_ptr<Entry>* entry = fMap.find(desc);
106 if (!entry) {
107 #ifdef GR_PIPELINE_STATE_CACHE_STATS
108 ++fCacheMisses;
109 #endif
110 GrVkPipelineState* pipelineState(GrVkPipelineStateBuilder::CreatePipelineState(
111 fGpu, renderTarget, programInfo,
112 stencil, primitiveType, &desc, compatibleRenderPass));
113 if (!pipelineState) {
114 return nullptr;
115 }
116 entry = fMap.insert(desc, std::unique_ptr<Entry>(new Entry(fGpu, pipelineState)));
117 return (*entry)->fPipelineState.get();
118 }
119 return (*entry)->fPipelineState.get();
120 }
121