• 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 "src/core/SkOpts.h"
10 #include "src/gpu/GrProcessor.h"
11 #include "src/gpu/GrRenderTargetPriv.h"
12 #include "src/gpu/GrStencilSettings.h"
13 #include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
14 #include "src/gpu/glsl/GrGLSLProgramDataManager.h"
15 #include "src/gpu/vk/GrVkGpu.h"
16 #include "src/gpu/vk/GrVkPipelineState.h"
17 #include "src/gpu/vk/GrVkPipelineStateBuilder.h"
18 #include "src/gpu/vk/GrVkResourceProvider.h"
19 
20 #ifdef GR_PIPELINE_STATE_CACHE_STATS
21 // Display pipeline state cache usage
22 static const bool c_DisplayVkPipelineCache{false};
23 #endif
24 
25 struct GrVkResourceProvider::PipelineStateCache::Entry {
EntryGrVkResourceProvider::PipelineStateCache::Entry26     Entry(GrVkGpu* gpu, GrVkPipelineState* pipelineState)
27     : fGpu(gpu)
28     , fPipelineState(pipelineState) {}
29 
~EntryGrVkResourceProvider::PipelineStateCache::Entry30     ~Entry() {
31         if (fPipelineState) {
32             fPipelineState->freeGPUResources(fGpu);
33         }
34     }
35 
36     GrVkGpu* fGpu;
37     std::unique_ptr<GrVkPipelineState> fPipelineState;
38 };
39 
PipelineStateCache(GrVkGpu * gpu)40 GrVkResourceProvider::PipelineStateCache::PipelineStateCache(GrVkGpu* gpu)
41     : fMap(kMaxEntries)
42     , fGpu(gpu)
43 #ifdef GR_PIPELINE_STATE_CACHE_STATS
44     , fTotalRequests(0)
45     , fCacheMisses(0)
46 #endif
47 {}
48 
~PipelineStateCache()49 GrVkResourceProvider::PipelineStateCache::~PipelineStateCache() {
50     SkASSERT(0 == fMap.count());
51     // dump stats
52 #ifdef GR_PIPELINE_STATE_CACHE_STATS
53     if (c_DisplayVkPipelineCache) {
54         SkDebugf("--- Pipeline State Cache ---\n");
55         SkDebugf("Total requests: %d\n", fTotalRequests);
56         SkDebugf("Cache misses: %d\n", fCacheMisses);
57         SkDebugf("Cache miss %%: %f\n", (fTotalRequests > 0) ?
58                  100.f * fCacheMisses / fTotalRequests :
59                  0.f);
60         SkDebugf("---------------------\n");
61     }
62 #endif
63 }
64 
abandon()65 void GrVkResourceProvider::PipelineStateCache::abandon() {
66     fMap.foreach([](std::unique_ptr<Entry>* e) {
67         (*e)->fPipelineState->abandonGPUResources();
68         (*e)->fPipelineState = nullptr;
69     });
70     fMap.reset();
71 }
72 
release()73 void GrVkResourceProvider::PipelineStateCache::release() {
74     fMap.reset();
75 }
76 
refPipelineState(GrRenderTarget * renderTarget,GrSurfaceOrigin origin,const GrPrimitiveProcessor & primProc,const GrTextureProxy * const primProcProxies[],const GrPipeline & pipeline,GrPrimitiveType primitiveType,VkRenderPass compatibleRenderPass)77 GrVkPipelineState* GrVkResourceProvider::PipelineStateCache::refPipelineState(
78         GrRenderTarget* renderTarget,
79         GrSurfaceOrigin origin,
80         const GrPrimitiveProcessor& primProc,
81         const GrTextureProxy* const primProcProxies[],
82         const GrPipeline& pipeline,
83         GrPrimitiveType primitiveType,
84         VkRenderPass compatibleRenderPass) {
85 #ifdef GR_PIPELINE_STATE_CACHE_STATS
86     ++fTotalRequests;
87 #endif
88     GrStencilSettings stencil;
89     if (pipeline.isStencilEnabled()) {
90         // TODO: attach stencil and create settings during render target flush.
91         SkASSERT(renderTarget->renderTargetPriv().getStencilAttachment());
92         stencil.reset(*pipeline.getUserStencil(), pipeline.hasStencilClip(),
93                       renderTarget->renderTargetPriv().numStencilBits());
94     }
95 
96     // Get GrVkProgramDesc
97     GrVkPipelineStateBuilder::Desc desc;
98     if (!GrVkPipelineStateBuilder::Desc::Build(&desc, renderTarget, primProc, pipeline, stencil,
99                                                primitiveType, fGpu)) {
100         GrCapsDebugf(fGpu->caps(), "Failed to build vk program descriptor!\n");
101         return nullptr;
102     }
103     // If we knew the shader won't depend on origin, we could skip this (and use the same program
104     // for both origins). Instrumenting all fragment processors would be difficult and error prone.
105     desc.setSurfaceOriginKey(GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(origin));
106 
107     std::unique_ptr<Entry>* entry = fMap.find(desc);
108     if (!entry) {
109 #ifdef GR_PIPELINE_STATE_CACHE_STATS
110         ++fCacheMisses;
111 #endif
112         GrVkPipelineState* pipelineState(GrVkPipelineStateBuilder::CreatePipelineState(
113                 fGpu, renderTarget, origin, primProc, primProcProxies, pipeline, stencil,
114                 primitiveType, &desc, compatibleRenderPass));
115         if (nullptr == pipelineState) {
116             return nullptr;
117         }
118         entry = fMap.insert(desc, std::unique_ptr<Entry>(new Entry(fGpu, pipelineState)));
119         return (*entry)->fPipelineState.get();
120     }
121     return (*entry)->fPipelineState.get();
122 }
123