• 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 "GrResourceHandle.h"
12 #include "GrVkDescriptorPool.h"
13 #include "GrVkDescriptorSetManager.h"
14 #include "GrVkPipelineStateBuilder.h"
15 #include "GrVkRenderPass.h"
16 #include "GrVkResource.h"
17 #include "GrVkSampler.h"
18 #include "GrVkSamplerYcbcrConversion.h"
19 #include "GrVkUtil.h"
20 #include "SkLRUCache.h"
21 #include "SkTArray.h"
22 #include "SkTDynamicHash.h"
23 #include "SkTInternalLList.h"
24 #include "vk/GrVkTypes.h"
25 
26 #include <mutex>
27 #include <thread>
28 
29 class GrVkCommandPool;
30 class GrVkCopyPipeline;
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 
44     // Set up any initial vk objects
45     void init();
46 
47     GrVkPipeline* createPipeline(int numColorSamples,
48                                  const GrPrimitiveProcessor& primProc,
49                                  const GrPipeline& pipeline,
50                                  const GrStencilSettings& stencil,
51                                  VkPipelineShaderStageCreateInfo* shaderStageInfo,
52                                  int shaderStageCount,
53                                  GrPrimitiveType primitiveType,
54                                  VkRenderPass compatibleRenderPass,
55                                  VkPipelineLayout layout);
56 
57     GrVkCopyPipeline* findOrCreateCopyPipeline(const GrVkRenderTarget* dst,
58                                                VkPipelineShaderStageCreateInfo*,
59                                                VkPipelineLayout);
60 
61     GR_DEFINE_RESOURCE_HANDLE_CLASS(CompatibleRPHandle);
62 
63     // Finds or creates a simple render pass that matches the target, increments the refcount,
64     // and returns. The caller can optionally pass in a pointer to a CompatibleRPHandle. If this is
65     // non null it will be set to a handle that can be used in the furutre to quickly return a
66     // compatible GrVkRenderPasses without the need inspecting a GrVkRenderTarget.
67     const GrVkRenderPass* findCompatibleRenderPass(const GrVkRenderTarget& target,
68                                                    CompatibleRPHandle* compatibleHandle = nullptr);
69     // The CompatibleRPHandle must be a valid handle previously set by a call to
70     // findCompatibleRenderPass(GrVkRenderTarget&, CompatibleRPHandle*).
71     const GrVkRenderPass* findCompatibleRenderPass(const CompatibleRPHandle& compatibleHandle);
72 
73     const GrVkRenderPass* findCompatibleExternalRenderPass(VkRenderPass,
74                                                            uint32_t colorAttachmentIndex);
75 
76     // Finds or creates a render pass that matches the target and LoadStoreOps, increments the
77     // refcount, and returns. The caller can optionally pass in a pointer to a CompatibleRPHandle.
78     // If this is non null it will be set to a handle that can be used in the furutre to quickly
79     // return a GrVkRenderPasses without the need inspecting a GrVkRenderTarget.
80     const GrVkRenderPass* findRenderPass(const GrVkRenderTarget& target,
81                                          const GrVkRenderPass::LoadStoreOps& colorOps,
82                                          const GrVkRenderPass::LoadStoreOps& stencilOps,
83                                          CompatibleRPHandle* compatibleHandle = nullptr);
84 
85     // The CompatibleRPHandle must be a valid handle previously set by a call to findRenderPass or
86     // findCompatibleRenderPass.
87     const GrVkRenderPass* findRenderPass(const CompatibleRPHandle& compatibleHandle,
88                                          const GrVkRenderPass::LoadStoreOps& colorOps,
89                                          const GrVkRenderPass::LoadStoreOps& stencilOps);
90 
91     GrVkCommandPool* findOrCreateCommandPool();
92 
93     void checkCommandBuffers();
94 
95     // Finds or creates a compatible GrVkDescriptorPool for the requested type and count.
96     // The refcount is incremented and a pointer returned.
97     // TODO: Currently this will just create a descriptor pool without holding onto a ref itself
98     //       so we currently do not reuse them. Rquires knowing if another draw is currently using
99     //       the GrVkDescriptorPool, the ability to reset pools, and the ability to purge pools out
100     //       of our cache of GrVkDescriptorPools.
101     GrVkDescriptorPool* findOrCreateCompatibleDescriptorPool(VkDescriptorType type, uint32_t count);
102 
103     // Finds or creates a compatible GrVkSampler based on the GrSamplerState and
104     // GrVkYcbcrConversionInfo. The refcount is incremented and a pointer returned.
105     GrVkSampler* findOrCreateCompatibleSampler(const GrSamplerState&,
106                                                const GrVkYcbcrConversionInfo& ycbcrInfo);
107 
108     // Finds or creates a compatible GrVkSamplerYcbcrConversion based on the GrSamplerState and
109     // GrVkYcbcrConversionInfo. The refcount is incremented and a pointer returned.
110     GrVkSamplerYcbcrConversion* findOrCreateCompatibleSamplerYcbcrConversion(
111             const GrVkYcbcrConversionInfo& ycbcrInfo);
112 
113     GrVkPipelineState* findOrCreateCompatiblePipelineState(
114             GrRenderTarget*, GrSurfaceOrigin,
115             const GrPipeline&,
116             const GrPrimitiveProcessor&,
117             const GrTextureProxy* const primProcProxies[],
118             GrPrimitiveType,
119             VkRenderPass compatibleRenderPass);
120 
121     void getSamplerDescriptorSetHandle(VkDescriptorType type,
122                                        const GrVkUniformHandler&,
123                                        GrVkDescriptorSetManager::Handle* handle);
124     void getSamplerDescriptorSetHandle(VkDescriptorType type,
125                                        const SkTArray<uint32_t>& visibilities,
126                                        GrVkDescriptorSetManager::Handle* handle);
127 
128     // Returns the compatible VkDescriptorSetLayout to use for uniform buffers. The caller does not
129     // own the VkDescriptorSetLayout and thus should not delete it. This function should be used
130     // when the caller needs the layout to create a VkPipelineLayout.
131     VkDescriptorSetLayout getUniformDSLayout() const;
132 
133     // Returns the compatible VkDescriptorSetLayout to use for a specific sampler handle. The caller
134     // does not own the VkDescriptorSetLayout and thus should not delete it. This function should be
135     // used when the caller needs the layout to create a VkPipelineLayout.
136     VkDescriptorSetLayout getSamplerDSLayout(const GrVkDescriptorSetManager::Handle&) const;
137 
138     // Returns a GrVkDescriptorSet that can be used for uniform buffers. The GrVkDescriptorSet
139     // is already reffed for the caller.
140     const GrVkDescriptorSet* getUniformDescriptorSet();
141 
142     // Returns a GrVkDescriptorSet that can be used for sampler descriptors that are compatible with
143     // the GrVkDescriptorSetManager::Handle passed in. The GrVkDescriptorSet is already reffed for
144     // the caller.
145     const GrVkDescriptorSet* getSamplerDescriptorSet(const GrVkDescriptorSetManager::Handle&);
146 
147 
148     // Signals that the descriptor set passed it, which is compatible with the passed in handle,
149     // can be reused by the next allocation request.
150     void recycleDescriptorSet(const GrVkDescriptorSet* descSet,
151                               const GrVkDescriptorSetManager::Handle&);
152 
153     // Creates or finds free uniform buffer resources of size GrVkUniformBuffer::kStandardSize.
154     // Anything larger will need to be created and released by the client.
155     const GrVkResource* findOrCreateStandardUniformBufferResource();
156 
157     // Signals that the resource passed to it (which should be a uniform buffer resource)
158     // can be reused by the next uniform buffer resource request.
159     void recycleStandardUniformBufferResource(const GrVkResource*);
160 
161     void storePipelineCacheData();
162 
163     // Destroy any cached resources. To be called before destroying the VkDevice.
164     // The assumption is that all queues are idle and all command buffers are finished.
165     // For resource tracing to work properly, this should be called after unrefing all other
166     // resource usages.
167     // If deviceLost is true, then resources will not be checked to see if they've finished
168     // before deleting (see section 4.2.4 of the Vulkan spec).
169     void destroyResources(bool deviceLost);
170 
171     // Abandon any cached resources. To be used when the context/VkDevice is lost.
172     // For resource tracing to work properly, this should be called after unrefing all other
173     // resource usages.
174     void abandonResources();
175 
176     void backgroundReset(GrVkCommandPool* pool);
177 
178     void reset(GrVkCommandPool* pool);
179 
180 private:
181 
182 #ifdef SK_DEBUG
183 #define GR_PIPELINE_STATE_CACHE_STATS
184 #endif
185 
186     class PipelineStateCache : public ::SkNoncopyable {
187     public:
188         PipelineStateCache(GrVkGpu* gpu);
189         ~PipelineStateCache();
190 
191         void abandon();
192         void release();
193         GrVkPipelineState* refPipelineState(GrRenderTarget*, GrSurfaceOrigin,
194                                             const GrPrimitiveProcessor&,
195                                             const GrTextureProxy* const primProcProxies[],
196                                             const GrPipeline&,
197                                             GrPrimitiveType,
198                                             VkRenderPass compatibleRenderPass);
199 
200     private:
201         enum {
202             // We may actually have kMaxEntries+1 PipelineStates in context because we create a new
203             // PipelineState before evicting from the cache.
204             kMaxEntries = 128,
205         };
206 
207         struct Entry;
208 
209         struct DescHash {
operatorDescHash210             uint32_t operator()(const GrProgramDesc& desc) const {
211                 return SkOpts::hash_fn(desc.asKey(), desc.keyLength(), 0);
212             }
213         };
214 
215         SkLRUCache<const GrVkPipelineStateBuilder::Desc, std::unique_ptr<Entry>, DescHash> fMap;
216 
217         GrVkGpu*                    fGpu;
218 
219 #ifdef GR_PIPELINE_STATE_CACHE_STATS
220         int                         fTotalRequests;
221         int                         fCacheMisses;
222 #endif
223     };
224 
225     class CompatibleRenderPassSet {
226     public:
227         // This will always construct the basic load store render pass (all attachments load and
228         // store their data) so that there is at least one compatible VkRenderPass that can be used
229         // with this set.
230         CompatibleRenderPassSet(const GrVkGpu* gpu, const GrVkRenderTarget& target);
231 
232         bool isCompatible(const GrVkRenderTarget& target) const;
233 
getCompatibleRenderPass()234         GrVkRenderPass* getCompatibleRenderPass() const {
235             // The first GrVkRenderpass should always exist since we create the basic load store
236             // render pass on create
237             SkASSERT(fRenderPasses[0]);
238             return fRenderPasses[0];
239         }
240 
241         GrVkRenderPass* getRenderPass(const GrVkGpu* gpu,
242                                       const GrVkRenderPass::LoadStoreOps& colorOps,
243                                       const GrVkRenderPass::LoadStoreOps& stencilOps);
244 
245         void releaseResources(GrVkGpu* gpu);
246         void abandonResources();
247 
248     private:
249         SkSTArray<4, GrVkRenderPass*> fRenderPasses;
250         int                           fLastReturnedIndex;
251     };
252 
253     VkPipelineCache pipelineCache();
254 
255     GrVkGpu* fGpu;
256 
257     // Central cache for creating pipelines
258     VkPipelineCache fPipelineCache;
259 
260     // Cache of previously created copy pipelines
261     SkTArray<GrVkCopyPipeline*> fCopyPipelines;
262 
263     SkSTArray<4, CompatibleRenderPassSet> fRenderPassArray;
264 
265     SkTArray<const GrVkRenderPass*> fExternalRenderPasses;
266 
267     // Array of command pools that we are waiting on
268     SkSTArray<4, GrVkCommandPool*, true> fActiveCommandPools;
269 
270     // Array of available command pools that are not in flight
271     SkSTArray<4, GrVkCommandPool*, true> fAvailableCommandPools;
272 
273     // Array of available uniform buffer resources
274     SkSTArray<16, const GrVkResource*, true> fAvailableUniformBufferResources;
275 
276     // Stores GrVkSampler objects that we've already created so we can reuse them across multiple
277     // GrVkPipelineStates
278     SkTDynamicHash<GrVkSampler, GrVkSampler::Key> fSamplers;
279 
280     // Stores GrVkSamplerYcbcrConversion objects that we've already created so we can reuse them.
281     SkTDynamicHash<GrVkSamplerYcbcrConversion, GrVkSamplerYcbcrConversion::Key> fYcbcrConversions;
282 
283     // Cache of GrVkPipelineStates
284     PipelineStateCache* fPipelineStateCache;
285 
286     SkSTArray<4, std::unique_ptr<GrVkDescriptorSetManager>> fDescriptorSetManagers;
287 
288     GrVkDescriptorSetManager::Handle fUniformDSHandle;
289 
290     std::recursive_mutex fBackgroundMutex;
291 };
292 
293 #endif
294