• 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 #ifndef GrVkResourceProvider_DEFINED
9 #define GrVkResourceProvider_DEFINED
10 
11 #include "include/gpu/vk/GrVkTypes.h"
12 #include "include/private/SkMutex.h"
13 #include "include/private/SkTArray.h"
14 #include "src/core/SkLRUCache.h"
15 #include "src/core/SkTDynamicHash.h"
16 #include "src/core/SkTInternalLList.h"
17 #include "src/gpu/GrGpu.h"
18 #include "src/gpu/GrManagedResource.h"
19 #include "src/gpu/GrProgramDesc.h"
20 #include "src/gpu/GrResourceHandle.h"
21 #include "src/gpu/GrThreadSafePipelineBuilder.h"
22 #include "src/gpu/vk/GrVkDescriptorPool.h"
23 #include "src/gpu/vk/GrVkDescriptorSetManager.h"
24 #include "src/gpu/vk/GrVkPipelineStateBuilder.h"
25 #include "src/gpu/vk/GrVkRenderPass.h"
26 #include "src/gpu/vk/GrVkSampler.h"
27 #include "src/gpu/vk/GrVkSamplerYcbcrConversion.h"
28 #include "src/gpu/vk/GrVkUtil.h"
29 
30 class GrVkCommandPool;
31 class GrVkGpu;
32 class GrVkPipeline;
33 class GrVkPipelineState;
34 class GrVkPrimaryCommandBuffer;
35 class GrVkRenderTarget;
36 class GrVkSecondaryCommandBuffer;
37 class GrVkUniformHandler;
38 
39 class GrVkResourceProvider {
40 public:
41     GrVkResourceProvider(GrVkGpu* gpu);
42     ~GrVkResourceProvider();
43 
pipelineStateCache()44     GrThreadSafePipelineBuilder* pipelineStateCache() {
45         return fPipelineStateCache.get();
46     }
47 
refPipelineStateCache()48     sk_sp<GrThreadSafePipelineBuilder> refPipelineStateCache() {
49         return fPipelineStateCache;
50     }
51 
52     // Set up any initial vk objects
53     void init();
54 
55     sk_sp<const GrVkPipeline> makePipeline(const GrProgramInfo&,
56                                            VkPipelineShaderStageCreateInfo* shaderStageInfo,
57                                            int shaderStageCount,
58                                            VkRenderPass compatibleRenderPass,
59                                            VkPipelineLayout layout,
60                                            uint32_t subpass);
61 
62     GR_DEFINE_RESOURCE_HANDLE_CLASS(CompatibleRPHandle);
63 
64     using SelfDependencyFlags = GrVkRenderPass::SelfDependencyFlags;
65     using LoadFromResolve = GrVkRenderPass::LoadFromResolve;
66 
67     // Finds or creates a simple render pass that matches the target, increments the refcount,
68     // and returns. The caller can optionally pass in a pointer to a CompatibleRPHandle. If this is
69     // non null it will be set to a handle that can be used in the furutre to quickly return a
70     // compatible GrVkRenderPasses without the need inspecting a GrVkRenderTarget.
71     const GrVkRenderPass* findCompatibleRenderPass(GrVkRenderTarget* target,
72                                                    CompatibleRPHandle* compatibleHandle,
73                                                    bool withResolve,
74                                                    bool withStencil,
75                                                    SelfDependencyFlags selfDepFlags,
76                                                    LoadFromResolve);
77     const GrVkRenderPass* findCompatibleRenderPass(GrVkRenderPass::AttachmentsDescriptor*,
78                                                    GrVkRenderPass::AttachmentFlags,
79                                                    SelfDependencyFlags selfDepFlags,
80                                                    LoadFromResolve,
81                                                    CompatibleRPHandle* compatibleHandle = nullptr);
82 
83     const GrVkRenderPass* findCompatibleExternalRenderPass(VkRenderPass,
84                                                            uint32_t colorAttachmentIndex);
85 
86 
87     // Finds or creates a render pass that matches the target and LoadStoreOps, increments the
88     // refcount, and returns. The caller can optionally pass in a pointer to a CompatibleRPHandle.
89     // If this is non null it will be set to a handle that can be used in the future to quickly
90     // return a GrVkRenderPass without the need to inspect a GrVkRenderTarget.
91     // TODO: sk_sp?
92     const GrVkRenderPass* findRenderPass(GrVkRenderTarget* target,
93                                          const GrVkRenderPass::LoadStoreOps& colorOps,
94                                          const GrVkRenderPass::LoadStoreOps& resolveOps,
95                                          const GrVkRenderPass::LoadStoreOps& stencilOps,
96                                          CompatibleRPHandle* compatibleHandle,
97                                          bool withResolve,
98                                          bool withStencil,
99                                          SelfDependencyFlags selfDepFlags,
100                                          LoadFromResolve);
101 
102     // The CompatibleRPHandle must be a valid handle previously set by a call to findRenderPass or
103     // findCompatibleRenderPass.
104     const GrVkRenderPass* findRenderPass(const CompatibleRPHandle& compatibleHandle,
105                                          const GrVkRenderPass::LoadStoreOps& colorOps,
106                                          const GrVkRenderPass::LoadStoreOps& resolveOps,
107                                          const GrVkRenderPass::LoadStoreOps& stencilOps);
108 
109     GrVkCommandPool* findOrCreateCommandPool();
110 
111     void checkCommandBuffers();
112 
113     void forceSyncAllCommandBuffers();
114 
115     // We must add the finishedProc to all active command buffers since we may have flushed work
116     // that the client cares about before they explicitly called flush and the GPU may reorder
117     // command execution. So we make sure all previously submitted work finishes before we call the
118     // finishedProc.
119     void addFinishedProcToActiveCommandBuffers(sk_sp<GrRefCntedCallback> finishedCallback);
120 
121     // Finds or creates a compatible GrVkDescriptorPool for the requested type and count.
122     // The refcount is incremented and a pointer returned.
123     // TODO: Currently this will just create a descriptor pool without holding onto a ref itself
124     //       so we currently do not reuse them. Rquires knowing if another draw is currently using
125     //       the GrVkDescriptorPool, the ability to reset pools, and the ability to purge pools out
126     //       of our cache of GrVkDescriptorPools.
127     GrVkDescriptorPool* findOrCreateCompatibleDescriptorPool(VkDescriptorType type, uint32_t count);
128 
129     // Finds or creates a compatible GrVkSampler based on the GrSamplerState and
130     // GrVkYcbcrConversionInfo. The refcount is incremented and a pointer returned.
131     GrVkSampler* findOrCreateCompatibleSampler(GrSamplerState,
132                                                const GrVkYcbcrConversionInfo& ycbcrInfo);
133 
134     // Finds or creates a compatible GrVkSamplerYcbcrConversion based on the GrSamplerState and
135     // GrVkYcbcrConversionInfo. The refcount is incremented and a pointer returned.
136     GrVkSamplerYcbcrConversion* findOrCreateCompatibleSamplerYcbcrConversion(
137             const GrVkYcbcrConversionInfo& ycbcrInfo);
138 
139     GrVkPipelineState* findOrCreateCompatiblePipelineState(
140             GrRenderTarget*,
141             const GrProgramInfo&,
142             VkRenderPass compatibleRenderPass,
143             bool overrideSubpassForResolveLoad);
144 
145     GrVkPipelineState* findOrCreateCompatiblePipelineState(
146             const GrProgramDesc&,
147             const GrProgramInfo&,
148             VkRenderPass compatibleRenderPass,
149             GrThreadSafePipelineBuilder::Stats::ProgramCacheResult* stat);
150 
151     sk_sp<const GrVkPipeline> findOrCreateMSAALoadPipeline(
152             const GrVkRenderPass& renderPass,
153             int numSamples,
154             VkPipelineShaderStageCreateInfo*,
155             VkPipelineLayout);
156 
157     void getSamplerDescriptorSetHandle(VkDescriptorType type,
158                                        const GrVkUniformHandler&,
159                                        GrVkDescriptorSetManager::Handle* handle);
160 
161     // This is a convenience function to return a descriptor set for zero sammples. When making a
162     // VkPipelineLayout we must pass in an array of valid descriptor set handles. However, we have
163     // set up our system to have the descriptor sets be in the order uniform, sampler, input. So
164     // if we have a uniform and input we will need to have a valid handle for the sampler as well.
165     // When using the GrVkMSAALoadManager this is the case, but we also don't have a
166     // GrVkUniformHandler to pass into the more general function. Thus we use this call instead.
167     void getZeroSamplerDescriptorSetHandle(GrVkDescriptorSetManager::Handle* handle);
168 
169     // Returns the compatible VkDescriptorSetLayout to use for uniform buffers. The caller does not
170     // own the VkDescriptorSetLayout and thus should not delete it. This function should be used
171     // when the caller needs the layout to create a VkPipelineLayout.
172     VkDescriptorSetLayout getUniformDSLayout() const;
173 
174     // Returns the compatible VkDescriptorSetLayout to use for input attachments. The caller does
175     // not own the VkDescriptorSetLayout and thus should not delete it. This function should be used
176     // when the caller needs the layout to create a VkPipelineLayout.
177     VkDescriptorSetLayout getInputDSLayout() const;
178 
179     // Returns the compatible VkDescriptorSetLayout to use for a specific sampler handle. The caller
180     // does not own the VkDescriptorSetLayout and thus should not delete it. This function should be
181     // used when the caller needs the layout to create a VkPipelineLayout.
182     VkDescriptorSetLayout getSamplerDSLayout(const GrVkDescriptorSetManager::Handle&) const;
183 
184     // Returns a GrVkDescriptorSet that can be used for uniform buffers. The GrVkDescriptorSet
185     // is already reffed for the caller.
186     const GrVkDescriptorSet* getUniformDescriptorSet();
187 
188     // Returns a GrVkDescriptorSet that can be used for sampler descriptors that are compatible with
189     // the GrVkDescriptorSetManager::Handle passed in. The GrVkDescriptorSet is already reffed for
190     // the caller.
191     const GrVkDescriptorSet* getSamplerDescriptorSet(const GrVkDescriptorSetManager::Handle&);
192 
193     // Returns a GrVkDescriptorSet that can be used for input attachments. The GrVkDescriptorSet
194     // is already reffed for the caller.
195     const GrVkDescriptorSet* getInputDescriptorSet();
196 
197     // Signals that the descriptor set passed it, which is compatible with the passed in handle,
198     // can be reused by the next allocation request.
199     void recycleDescriptorSet(const GrVkDescriptorSet* descSet,
200                               const GrVkDescriptorSetManager::Handle&);
201 
202     void storePipelineCacheData();
203 
204     // Destroy any cached resources. To be called before destroying the VkDevice.
205     // The assumption is that all queues are idle and all command buffers are finished.
206     // For resource tracing to work properly, this should be called after unrefing all other
207     // resource usages.
208     void destroyResources();
209 
210     // Currently we just release available command pools (which also releases their buffers). The
211     // command buffers and pools take up the most memory. Other objects (e.g. samples,
212     // ycbcr conversions, etc.) tend to be fairly light weight and not worth the effort to remove
213     // them and then possibly remake them. Additionally many of those objects have refs/handles that
214     // are held by other objects that aren't deleted here. Thus the memory wins for removing these
215     // objects from the cache are probably not worth the complexity of safely releasing them.
216     void releaseUnlockedBackendObjects();
217 
218     void backgroundReset(GrVkCommandPool* pool);
219 
220     void reset(GrVkCommandPool* pool);
221 
222 #if GR_TEST_UTILS
resetShaderCacheForTesting()223     void resetShaderCacheForTesting() const { fPipelineStateCache->release(); }
224 #endif
225 
226 private:
227     class PipelineStateCache : public GrThreadSafePipelineBuilder {
228     public:
229         PipelineStateCache(GrVkGpu* gpu);
230         ~PipelineStateCache() override;
231 
232         void release();
233         GrVkPipelineState* findOrCreatePipelineState(GrRenderTarget*,
234                                                      const GrProgramInfo&,
235                                                      VkRenderPass compatibleRenderPass,
236                                                      bool overrideSubpassForResolveLoad);
findOrCreatePipelineState(const GrProgramDesc & desc,const GrProgramInfo & programInfo,VkRenderPass compatibleRenderPass,Stats::ProgramCacheResult * stat)237         GrVkPipelineState* findOrCreatePipelineState(const GrProgramDesc& desc,
238                                                      const GrProgramInfo& programInfo,
239                                                      VkRenderPass compatibleRenderPass,
240                                                      Stats::ProgramCacheResult* stat) {
241             return this->findOrCreatePipelineStateImpl(desc, programInfo, compatibleRenderPass,
242                                                        false, stat);
243         }
244 
245     private:
246         struct Entry;
247 
248         GrVkPipelineState* findOrCreatePipelineStateImpl(const GrProgramDesc&,
249                                                          const GrProgramInfo&,
250                                                          VkRenderPass compatibleRenderPass,
251                                                          bool overrideSubpassForResolveLoad,
252                                                          Stats::ProgramCacheResult*);
253 
254         struct DescHash {
operatorDescHash255             uint32_t operator()(const GrProgramDesc& desc) const {
256                 return SkOpts::hash_fn(desc.asKey(), desc.keyLength(), 0);
257             }
258         };
259 
260         SkLRUCache<const GrProgramDesc, std::unique_ptr<Entry>, DescHash> fMap;
261 
262         GrVkGpu*                    fGpu;
263     };
264 
265     class CompatibleRenderPassSet {
266     public:
267         // This will always construct the basic load store render pass (all attachments load and
268         // store their data) so that there is at least one compatible VkRenderPass that can be used
269         // with this set.
270         CompatibleRenderPassSet(GrVkRenderPass* renderPass);
271 
272         bool isCompatible(const GrVkRenderPass::AttachmentsDescriptor&,
273                           GrVkRenderPass::AttachmentFlags,
274                           SelfDependencyFlags selfDepFlags,
275                           LoadFromResolve) const;
276 
getCompatibleRenderPass()277         const GrVkRenderPass* getCompatibleRenderPass() const {
278             // The first GrVkRenderpass should always exist since we create the basic load store
279             // render pass on create
280             SkASSERT(fRenderPasses[0]);
281             return fRenderPasses[0];
282         }
283 
284         GrVkRenderPass* getRenderPass(GrVkGpu* gpu,
285                                       const GrVkRenderPass::LoadStoreOps& colorOps,
286                                       const GrVkRenderPass::LoadStoreOps& resolveOps,
287                                       const GrVkRenderPass::LoadStoreOps& stencilOps);
288 
289         void releaseResources();
290 
291     private:
292         SkSTArray<4, GrVkRenderPass*> fRenderPasses;
293         int                           fLastReturnedIndex;
294     };
295 
296     VkPipelineCache pipelineCache();
297 
298     GrVkGpu* fGpu;
299 
300     // Central cache for creating pipelines
301     VkPipelineCache fPipelineCache;
302     //CAUTION: should only used in GrVkResourceProvider
303     size_t fPipelineCacheSize;
304 
305     struct MSAALoadPipeline {
306         sk_sp<const GrVkPipeline> fPipeline;
307         const GrVkRenderPass* fRenderPass;
308     };
309 
310     // Cache of previously created msaa load pipelines
311     SkTArray<MSAALoadPipeline> fMSAALoadPipelines;
312 
313     SkSTArray<4, CompatibleRenderPassSet> fRenderPassArray;
314 
315     SkTArray<const GrVkRenderPass*> fExternalRenderPasses;
316 
317     // Array of command pools that we are waiting on
318     SkSTArray<4, GrVkCommandPool*, true> fActiveCommandPools;
319 
320     SkMutex fBackgroundMutex;
321 
322     // Array of available command pools that are not in flight
323     SkSTArray<4, GrVkCommandPool*, true> fAvailableCommandPools SK_GUARDED_BY(fBackgroundMutex);
324 
325     // Stores GrVkSampler objects that we've already created so we can reuse them across multiple
326     // GrVkPipelineStates
327     SkTDynamicHash<GrVkSampler, GrVkSampler::Key> fSamplers;
328 
329     // Stores GrVkSamplerYcbcrConversion objects that we've already created so we can reuse them.
330     SkTDynamicHash<GrVkSamplerYcbcrConversion, GrVkSamplerYcbcrConversion::Key> fYcbcrConversions;
331 
332     // Cache of GrVkPipelineStates
333     sk_sp<PipelineStateCache> fPipelineStateCache;
334 
335     SkSTArray<4, std::unique_ptr<GrVkDescriptorSetManager>> fDescriptorSetManagers;
336 
337     GrVkDescriptorSetManager::Handle fUniformDSHandle;
338     GrVkDescriptorSetManager::Handle fInputDSHandle;
339 };
340 
341 #endif
342