• 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/base/SkMutex.h"
13 #include "include/private/base/SkTArray.h"
14 #include "src/base/SkTInternalLList.h"
15 #include "src/core/SkLRUCache.h"
16 #include "src/core/SkTDynamicHash.h"
17 #include "src/gpu/ganesh/GrGpu.h"
18 #include "src/gpu/ganesh/GrManagedResource.h"
19 #include "src/gpu/ganesh/GrProgramDesc.h"
20 #include "src/gpu/ganesh/GrResourceHandle.h"
21 #include "src/gpu/ganesh/GrThreadSafePipelineBuilder.h"
22 #include "src/gpu/ganesh/vk/GrVkDescriptorPool.h"
23 #include "src/gpu/ganesh/vk/GrVkDescriptorSetManager.h"
24 #include "src/gpu/ganesh/vk/GrVkPipelineStateBuilder.h"
25 #include "src/gpu/ganesh/vk/GrVkRenderPass.h"
26 #include "src/gpu/ganesh/vk/GrVkSampler.h"
27 #include "src/gpu/ganesh/vk/GrVkSamplerYcbcrConversion.h"
28 #include "src/gpu/ganesh/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<skgpu::RefCntedCallback> 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 #if GR_TEST_UTILS
resetShaderCacheForTesting()219     void resetShaderCacheForTesting() const { fPipelineStateCache->release(); }
220 #endif
221 
222 private:
223     class PipelineStateCache : public GrThreadSafePipelineBuilder {
224     public:
225         PipelineStateCache(GrVkGpu* gpu);
226         ~PipelineStateCache() override;
227 
228         void release();
229         GrVkPipelineState* findOrCreatePipelineState(GrRenderTarget*,
230                                                      const GrProgramInfo&,
231                                                      VkRenderPass compatibleRenderPass,
232                                                      bool overrideSubpassForResolveLoad);
findOrCreatePipelineState(const GrProgramDesc & desc,const GrProgramInfo & programInfo,VkRenderPass compatibleRenderPass,Stats::ProgramCacheResult * stat)233         GrVkPipelineState* findOrCreatePipelineState(const GrProgramDesc& desc,
234                                                      const GrProgramInfo& programInfo,
235                                                      VkRenderPass compatibleRenderPass,
236                                                      Stats::ProgramCacheResult* stat) {
237             return this->findOrCreatePipelineStateImpl(desc, programInfo, compatibleRenderPass,
238                                                        false, stat);
239         }
240 
241     private:
242         struct Entry;
243 
244         GrVkPipelineState* findOrCreatePipelineStateImpl(const GrProgramDesc&,
245                                                          const GrProgramInfo&,
246                                                          VkRenderPass compatibleRenderPass,
247                                                          bool overrideSubpassForResolveLoad,
248                                                          Stats::ProgramCacheResult*);
249 
250         struct DescHash {
operatorDescHash251             uint32_t operator()(const GrProgramDesc& desc) const {
252                 return SkOpts::hash_fn(desc.asKey(), desc.keyLength(), 0);
253             }
254         };
255 
256         SkLRUCache<const GrProgramDesc, std::unique_ptr<Entry>, DescHash> fMap;
257 
258         GrVkGpu*                    fGpu;
259     };
260 
261     class CompatibleRenderPassSet {
262     public:
263         // This will always construct the basic load store render pass (all attachments load and
264         // store their data) so that there is at least one compatible VkRenderPass that can be used
265         // with this set.
266         CompatibleRenderPassSet(GrVkRenderPass* renderPass);
267 
268         bool isCompatible(const GrVkRenderPass::AttachmentsDescriptor&,
269                           GrVkRenderPass::AttachmentFlags,
270                           SelfDependencyFlags selfDepFlags,
271                           LoadFromResolve) const;
272 
getCompatibleRenderPass()273         const GrVkRenderPass* getCompatibleRenderPass() const {
274             // The first GrVkRenderpass should always exist since we create the basic load store
275             // render pass on create
276             SkASSERT(fRenderPasses[0]);
277             return fRenderPasses[0];
278         }
279 
280         GrVkRenderPass* getRenderPass(GrVkGpu* gpu,
281                                       const GrVkRenderPass::LoadStoreOps& colorOps,
282                                       const GrVkRenderPass::LoadStoreOps& resolveOps,
283                                       const GrVkRenderPass::LoadStoreOps& stencilOps);
284 
285         void releaseResources();
286 
287     private:
288         SkSTArray<4, GrVkRenderPass*> fRenderPasses;
289         int                           fLastReturnedIndex;
290     };
291 
292     VkPipelineCache pipelineCache();
293 
294     GrVkGpu* fGpu;
295 
296     // Central cache for creating pipelines
297     VkPipelineCache fPipelineCache;
298 
299     struct MSAALoadPipeline {
300         sk_sp<const GrVkPipeline> fPipeline;
301         const GrVkRenderPass* fRenderPass;
302     };
303 
304     // Cache of previously created msaa load pipelines
305     SkTArray<MSAALoadPipeline> fMSAALoadPipelines;
306 
307     SkSTArray<4, CompatibleRenderPassSet> fRenderPassArray;
308 
309     SkTArray<const GrVkRenderPass*> fExternalRenderPasses;
310 
311     // Array of command pools that we are waiting on
312     SkSTArray<4, GrVkCommandPool*, true> fActiveCommandPools;
313 
314     // Array of available command pools that are not in flight
315     SkSTArray<4, GrVkCommandPool*, true> fAvailableCommandPools;
316 
317     // Stores GrVkSampler objects that we've already created so we can reuse them across multiple
318     // GrVkPipelineStates
319     SkTDynamicHash<GrVkSampler, GrVkSampler::Key> fSamplers;
320 
321     // Stores GrVkSamplerYcbcrConversion objects that we've already created so we can reuse them.
322     SkTDynamicHash<GrVkSamplerYcbcrConversion, GrVkSamplerYcbcrConversion::Key> fYcbcrConversions;
323 
324     // Cache of GrVkPipelineStates
325     sk_sp<PipelineStateCache> fPipelineStateCache;
326 
327     SkSTArray<4, std::unique_ptr<GrVkDescriptorSetManager>> fDescriptorSetManagers;
328 
329     GrVkDescriptorSetManager::Handle fUniformDSHandle;
330     GrVkDescriptorSetManager::Handle fInputDSHandle;
331 };
332 
333 #endif
334