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