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
21 static const bool c_DisplayVkPipelineCache{false};
22 #endif
23
24 struct GrVkResourceProvider::PipelineStateCache::Entry {
EntryGrVkResourceProvider::PipelineStateCache::Entry25 Entry(GrVkGpu* gpu, GrVkPipelineState* pipelineState)
26 : fGpu(gpu)
27 , fPipelineState(pipelineState) {}
28
~EntryGrVkResourceProvider::PipelineStateCache::Entry29 ~Entry() {
30 if (fPipelineState) {
31 fPipelineState->freeGPUResources(fGpu);
32 }
33 }
34
35 GrVkGpu* fGpu;
36 std::unique_ptr<GrVkPipelineState> fPipelineState;
37 };
38
PipelineStateCache(GrVkGpu * gpu)39 GrVkResourceProvider::PipelineStateCache::PipelineStateCache(GrVkGpu* gpu)
40 : fMap(kMaxEntries)
41 , fGpu(gpu)
42 #ifdef GR_PIPELINE_STATE_CACHE_STATS
43 , fTotalRequests(0)
44 , fCacheMisses(0)
45 #endif
46 {}
47
~PipelineStateCache()48 GrVkResourceProvider::PipelineStateCache::~PipelineStateCache() {
49 SkASSERT(0 == fMap.count());
50 // dump stats
51 #ifdef GR_PIPELINE_STATE_CACHE_STATS
52 if (c_DisplayVkPipelineCache) {
53 SkDebugf("--- Pipeline State Cache ---\n");
54 SkDebugf("Total requests: %d\n", fTotalRequests);
55 SkDebugf("Cache misses: %d\n", fCacheMisses);
56 SkDebugf("Cache miss %%: %f\n", (fTotalRequests > 0) ?
57 100.f * fCacheMisses / fTotalRequests :
58 0.f);
59 SkDebugf("---------------------\n");
60 }
61 #endif
62 }
63
abandon()64 void GrVkResourceProvider::PipelineStateCache::abandon() {
65 fMap.foreach([](std::unique_ptr<Entry>* e) {
66 (*e)->fPipelineState->abandonGPUResources();
67 (*e)->fPipelineState = nullptr;
68 });
69 fMap.reset();
70 }
71
release()72 void GrVkResourceProvider::PipelineStateCache::release() {
73 fMap.reset();
74 }
75
refPipelineState(const GrPipeline & pipeline,const GrPrimitiveProcessor & primProc,GrPrimitiveType primitiveType,const GrVkRenderPass & renderPass)76 GrVkPipelineState* GrVkResourceProvider::PipelineStateCache::refPipelineState(
77 const GrPipeline& pipeline,
78 const GrPrimitiveProcessor& primProc,
79 GrPrimitiveType primitiveType,
80 const GrVkRenderPass& renderPass) {
81 #ifdef GR_PIPELINE_STATE_CACHE_STATS
82 ++fTotalRequests;
83 #endif
84 GrStencilSettings stencil;
85 if (pipeline.isStencilEnabled()) {
86 GrRenderTarget* rt = pipeline.renderTarget();
87 // TODO: attach stencil and create settings during render target flush.
88 SkASSERT(rt->renderTargetPriv().getStencilAttachment());
89 stencil.reset(*pipeline.getUserStencil(), pipeline.hasStencilClip(),
90 rt->renderTargetPriv().numStencilBits());
91 }
92
93 // Get GrVkProgramDesc
94 GrVkPipelineState::Desc desc;
95 if (!GrVkPipelineState::Desc::Build(&desc, primProc, pipeline, stencil,
96 primitiveType, *fGpu->caps()->shaderCaps())) {
97 GrCapsDebugf(fGpu->caps(), "Failed to build vk program descriptor!\n");
98 return nullptr;
99 }
100 desc.finalize();
101
102 std::unique_ptr<Entry>* entry = fMap.find(desc);
103 if (!entry) {
104 // Didn't find an origin-independent version, check with the specific origin
105 GrSurfaceOrigin origin = pipeline.proxy()->origin();
106 desc.setSurfaceOriginKey(GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(origin));
107 desc.finalize();
108 entry = fMap.find(desc);
109 }
110 if (!entry) {
111 #ifdef GR_PIPELINE_STATE_CACHE_STATS
112 ++fCacheMisses;
113 #endif
114 GrVkPipelineState* pipelineState(
115 GrVkPipelineStateBuilder::CreatePipelineState(fGpu,
116 pipeline,
117 stencil,
118 primProc,
119 primitiveType,
120 &desc,
121 renderPass));
122 if (nullptr == pipelineState) {
123 return nullptr;
124 }
125 entry = fMap.insert(desc, std::unique_ptr<Entry>(new Entry(fGpu, pipelineState)));
126 return (*entry)->fPipelineState.get();
127 }
128 return (*entry)->fPipelineState.get();
129 }
130