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