blob: 7771de1e8202b67840990ffd4e95342a6bc14388 [file] [log] [blame]
Greg Daniel164a9f02016-02-22 09:56:40 -05001/*
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
Greg Daniel54bfb182018-11-20 17:12:36 -050011#include "GrVkVulkan.h"
12
egdanield62e28b2016-06-07 08:43:30 -070013#include "GrResourceHandle.h"
Greg Daniel164a9f02016-02-22 09:56:40 -050014#include "GrVkDescriptorPool.h"
egdaniela95220d2016-07-21 11:50:37 -070015#include "GrVkDescriptorSetManager.h"
Brian Salomon1471df92018-06-08 10:49:00 -040016#include "GrVkPipelineStateBuilder.h"
egdaniel2feb0932016-06-08 06:48:09 -070017#include "GrVkRenderPass.h"
Greg Daniel164a9f02016-02-22 09:56:40 -050018#include "GrVkResource.h"
Greg Daniel7e000222018-12-03 10:08:21 -050019#include "GrVkSampler.h"
20#include "GrVkSamplerYcbcrConversion.h"
Greg Daniel164a9f02016-02-22 09:56:40 -050021#include "GrVkUtil.h"
Ethan Nicholas87f340e2017-01-03 14:32:01 -050022#include "SkLRUCache.h"
Greg Daniel164a9f02016-02-22 09:56:40 -050023#include "SkTArray.h"
egdaniel8b6394c2016-03-04 07:35:10 -080024#include "SkTDynamicHash.h"
egdanielaf132772016-03-28 12:39:29 -070025#include "SkTInternalLList.h"
Greg Daniel164a9f02016-02-22 09:56:40 -050026
Ethan Nicholasbff4e072018-12-12 18:17:24 +000027class GrPipeline;
28class GrPrimitiveProcessor;
29class GrSamplerState;
egdanielbc9b2962016-09-27 08:00:53 -070030class GrVkCopyPipeline;
Greg Daniel164a9f02016-02-22 09:56:40 -050031class GrVkGpu;
32class GrVkPipeline;
Brian Salomon1471df92018-06-08 10:49:00 -040033class GrVkPipelineState;
jvanverth7ec92412016-07-06 09:24:57 -070034class GrVkPrimaryCommandBuffer;
Greg Daniel164a9f02016-02-22 09:56:40 -050035class GrVkRenderTarget;
jvanverth7ec92412016-07-06 09:24:57 -070036class GrVkSecondaryCommandBuffer;
egdaniel707bbd62016-07-26 07:19:47 -070037class GrVkUniformHandler;
Greg Daniel164a9f02016-02-22 09:56:40 -050038
39class GrVkResourceProvider {
40public:
41 GrVkResourceProvider(GrVkGpu* gpu);
42 ~GrVkResourceProvider();
43
jvanverth03509ea2016-03-02 13:19:47 -080044 // Set up any initial vk objects
45 void init();
46
Brian Salomonff168d92018-06-23 15:17:27 -040047 GrVkPipeline* createPipeline(const GrPrimitiveProcessor& primProc,
48 const GrPipeline& pipeline,
csmartdaltonc633abb2016-11-01 08:55:55 -070049 const GrStencilSettings& stencil,
Greg Daniel164a9f02016-02-22 09:56:40 -050050 VkPipelineShaderStageCreateInfo* shaderStageInfo,
51 int shaderStageCount,
52 GrPrimitiveType primitiveType,
Greg Daniel99b88e02018-10-03 15:31:20 -040053 VkRenderPass compatibleRenderPass,
Greg Daniel164a9f02016-02-22 09:56:40 -050054 VkPipelineLayout layout);
55
egdanielbc9b2962016-09-27 08:00:53 -070056 GrVkCopyPipeline* findOrCreateCopyPipeline(const GrVkRenderTarget* dst,
57 VkPipelineShaderStageCreateInfo*,
58 VkPipelineLayout);
59
egdanield62e28b2016-06-07 08:43:30 -070060 GR_DEFINE_RESOURCE_HANDLE_CLASS(CompatibleRPHandle);
61
Greg Daniel164a9f02016-02-22 09:56:40 -050062 // Finds or creates a simple render pass that matches the target, increments the refcount,
egdanield62e28b2016-06-07 08:43:30 -070063 // and returns. The caller can optionally pass in a pointer to a CompatibleRPHandle. If this is
64 // non null it will be set to a handle that can be used in the furutre to quickly return a
65 // compatible GrVkRenderPasses without the need inspecting a GrVkRenderTarget.
66 const GrVkRenderPass* findCompatibleRenderPass(const GrVkRenderTarget& target,
67 CompatibleRPHandle* compatibleHandle = nullptr);
68 // The CompatibleRPHandle must be a valid handle previously set by a call to
69 // findCompatibleRenderPass(GrVkRenderTarget&, CompatibleRPHandle*).
70 const GrVkRenderPass* findCompatibleRenderPass(const CompatibleRPHandle& compatibleHandle);
71
egdaniel2feb0932016-06-08 06:48:09 -070072 // Finds or creates a render pass that matches the target and LoadStoreOps, increments the
73 // refcount, and returns. The caller can optionally pass in a pointer to a CompatibleRPHandle.
74 // If this is non null it will be set to a handle that can be used in the furutre to quickly
75 // return a GrVkRenderPasses without the need inspecting a GrVkRenderTarget.
egdanield62e28b2016-06-07 08:43:30 -070076 const GrVkRenderPass* findRenderPass(const GrVkRenderTarget& target,
egdaniel2feb0932016-06-08 06:48:09 -070077 const GrVkRenderPass::LoadStoreOps& colorOps,
egdaniel2feb0932016-06-08 06:48:09 -070078 const GrVkRenderPass::LoadStoreOps& stencilOps,
egdanield62e28b2016-06-07 08:43:30 -070079 CompatibleRPHandle* compatibleHandle = nullptr);
80
egdaniel2feb0932016-06-08 06:48:09 -070081 // The CompatibleRPHandle must be a valid handle previously set by a call to findRenderPass or
82 // findCompatibleRenderPass.
egdanield62e28b2016-06-07 08:43:30 -070083 const GrVkRenderPass* findRenderPass(const CompatibleRPHandle& compatibleHandle,
egdaniel2feb0932016-06-08 06:48:09 -070084 const GrVkRenderPass::LoadStoreOps& colorOps,
egdaniel2feb0932016-06-08 06:48:09 -070085 const GrVkRenderPass::LoadStoreOps& stencilOps);
86
Ethan Nicholasbff4e072018-12-12 18:17:24 +000087 GrVkPrimaryCommandBuffer* findOrCreatePrimaryCommandBuffer();
Ethan Nicholas30e63432018-12-11 16:15:15 -050088 void checkCommandBuffers();
jvanverth7ec92412016-07-06 09:24:57 -070089
Ethan Nicholasbff4e072018-12-12 18:17:24 +000090 GrVkSecondaryCommandBuffer* findOrCreateSecondaryCommandBuffer();
91 void recycleSecondaryCommandBuffer(GrVkSecondaryCommandBuffer* cb);
92
egdanielc2dc1b22016-03-18 13:18:23 -070093 // Finds or creates a compatible GrVkDescriptorPool for the requested type and count.
Greg Daniel164a9f02016-02-22 09:56:40 -050094 // The refcount is incremented and a pointer returned.
95 // TODO: Currently this will just create a descriptor pool without holding onto a ref itself
96 // so we currently do not reuse them. Rquires knowing if another draw is currently using
97 // the GrVkDescriptorPool, the ability to reset pools, and the ability to purge pools out
98 // of our cache of GrVkDescriptorPools.
egdanielc2dc1b22016-03-18 13:18:23 -070099 GrVkDescriptorPool* findOrCreateCompatibleDescriptorPool(VkDescriptorType type, uint32_t count);
Greg Daniel164a9f02016-02-22 09:56:40 -0500100
Greg Daniel7e000222018-12-03 10:08:21 -0500101 // Finds or creates a compatible GrVkSampler based on the GrSamplerState and
102 // GrVkYcbcrConversionInfo. The refcount is incremented and a pointer returned.
103 GrVkSampler* findOrCreateCompatibleSampler(const GrSamplerState&,
104 const GrVkYcbcrConversionInfo& ycbcrInfo);
105
106 // Finds or creates a compatible GrVkSamplerYcbcrConversion based on the GrSamplerState and
107 // GrVkYcbcrConversionInfo. The refcount is incremented and a pointer returned.
108 GrVkSamplerYcbcrConversion* findOrCreateCompatibleSamplerYcbcrConversion(
109 const GrVkYcbcrConversionInfo& ycbcrInfo);
egdaniel8b6394c2016-03-04 07:35:10 -0800110
Greg Daniel9a51a862018-11-30 10:18:14 -0500111 GrVkPipelineState* findOrCreateCompatiblePipelineState(
112 const GrPipeline&,
113 const GrPrimitiveProcessor&,
114 const GrTextureProxy* const primProcProxies[],
115 GrPrimitiveType,
116 VkRenderPass compatibleRenderPass);
egdaniel22281c12016-03-23 13:49:40 -0700117
Greg Daniela7543782017-05-02 14:01:43 -0400118 void getSamplerDescriptorSetHandle(VkDescriptorType type,
119 const GrVkUniformHandler&,
egdaniel707bbd62016-07-26 07:19:47 -0700120 GrVkDescriptorSetManager::Handle* handle);
Greg Daniela7543782017-05-02 14:01:43 -0400121 void getSamplerDescriptorSetHandle(VkDescriptorType type,
122 const SkTArray<uint32_t>& visibilities,
egdaniel4d866df2016-08-25 13:52:00 -0700123 GrVkDescriptorSetManager::Handle* handle);
egdaniel707bbd62016-07-26 07:19:47 -0700124
125 // Returns the compatible VkDescriptorSetLayout to use for uniform buffers. The caller does not
126 // own the VkDescriptorSetLayout and thus should not delete it. This function should be used
127 // when the caller needs the layout to create a VkPipelineLayout.
128 VkDescriptorSetLayout getUniformDSLayout() const;
129
130 // Returns the compatible VkDescriptorSetLayout to use for a specific sampler handle. The caller
131 // does not own the VkDescriptorSetLayout and thus should not delete it. This function should be
132 // used when the caller needs the layout to create a VkPipelineLayout.
133 VkDescriptorSetLayout getSamplerDSLayout(const GrVkDescriptorSetManager::Handle&) const;
egdaniela95220d2016-07-21 11:50:37 -0700134
135 // Returns a GrVkDescriptorSet that can be used for uniform buffers. The GrVkDescriptorSet
136 // is already reffed for the caller.
137 const GrVkDescriptorSet* getUniformDescriptorSet();
138
139 // Returns a GrVkDescriptorSet that can be used for sampler descriptors that are compatible with
egdaniel707bbd62016-07-26 07:19:47 -0700140 // the GrVkDescriptorSetManager::Handle passed in. The GrVkDescriptorSet is already reffed for
egdaniela95220d2016-07-21 11:50:37 -0700141 // the caller.
egdaniela95220d2016-07-21 11:50:37 -0700142 const GrVkDescriptorSet* getSamplerDescriptorSet(const GrVkDescriptorSetManager::Handle&);
egdaniel778555c2016-05-02 06:50:36 -0700143
egdaniel778555c2016-05-02 06:50:36 -0700144
egdaniela95220d2016-07-21 11:50:37 -0700145 // Signals that the descriptor set passed it, which is compatible with the passed in handle,
146 // can be reused by the next allocation request.
147 void recycleDescriptorSet(const GrVkDescriptorSet* descSet,
148 const GrVkDescriptorSetManager::Handle&);
149
jvanverth4c6e47a2016-07-22 10:34:52 -0700150 // Creates or finds free uniform buffer resources of size GrVkUniformBuffer::kStandardSize.
151 // Anything larger will need to be created and released by the client.
152 const GrVkResource* findOrCreateStandardUniformBufferResource();
153
154 // Signals that the resource passed to it (which should be a uniform buffer resource)
155 // can be reused by the next uniform buffer resource request.
156 void recycleStandardUniformBufferResource(const GrVkResource*);
157
Greg Daniel164a9f02016-02-22 09:56:40 -0500158 // Destroy any cached resources. To be called before destroying the VkDevice.
159 // The assumption is that all queues are idle and all command buffers are finished.
160 // For resource tracing to work properly, this should be called after unrefing all other
161 // resource usages.
Jim Van Verth09557d72016-11-07 11:10:21 -0500162 // If deviceLost is true, then resources will not be checked to see if they've finished
163 // before deleting (see section 4.2.4 of the Vulkan spec).
164 void destroyResources(bool deviceLost);
Greg Daniel164a9f02016-02-22 09:56:40 -0500165
166 // Abandon any cached resources. To be used when the context/VkDevice is lost.
167 // For resource tracing to work properly, this should be called after unrefing all other
168 // resource usages.
169 void abandonResources();
170
171private:
djsollenefe46d22016-04-29 06:41:35 -0700172#ifdef SK_DEBUG
egdanielaf132772016-03-28 12:39:29 -0700173#define GR_PIPELINE_STATE_CACHE_STATS
174#endif
175
egdaniel22281c12016-03-23 13:49:40 -0700176 class PipelineStateCache : public ::SkNoncopyable {
177 public:
178 PipelineStateCache(GrVkGpu* gpu);
179 ~PipelineStateCache();
180
181 void abandon();
182 void release();
Brian Salomonff168d92018-06-23 15:17:27 -0400183 GrVkPipelineState* refPipelineState(const GrPrimitiveProcessor&,
Greg Daniel9a51a862018-11-30 10:18:14 -0500184 const GrTextureProxy* const primProcProxies[],
Brian Salomonff168d92018-06-23 15:17:27 -0400185 const GrPipeline&,
Greg Daniel09eeefb2017-10-16 15:15:02 -0400186 GrPrimitiveType,
Greg Daniel99b88e02018-10-03 15:31:20 -0400187 VkRenderPass compatibleRenderPass);
egdaniel22281c12016-03-23 13:49:40 -0700188
189 private:
190 enum {
191 // We may actually have kMaxEntries+1 PipelineStates in context because we create a new
192 // PipelineState before evicting from the cache.
193 kMaxEntries = 128,
egdaniel22281c12016-03-23 13:49:40 -0700194 };
195
196 struct Entry;
197
Ethan Nicholas87f340e2017-01-03 14:32:01 -0500198 struct DescHash {
199 uint32_t operator()(const GrProgramDesc& desc) const {
200 return SkOpts::hash_fn(desc.asKey(), desc.keyLength(), 0);
201 }
202 };
egdaniel22281c12016-03-23 13:49:40 -0700203
Brian Salomon1471df92018-06-08 10:49:00 -0400204 SkLRUCache<const GrVkPipelineStateBuilder::Desc, std::unique_ptr<Entry>, DescHash> fMap;
egdanielaf132772016-03-28 12:39:29 -0700205
egdaniel22281c12016-03-23 13:49:40 -0700206 GrVkGpu* fGpu;
egdanielaf132772016-03-28 12:39:29 -0700207
208#ifdef GR_PIPELINE_STATE_CACHE_STATS
egdaniel22281c12016-03-23 13:49:40 -0700209 int fTotalRequests;
210 int fCacheMisses;
egdaniel22281c12016-03-23 13:49:40 -0700211#endif
212 };
213
egdanield62e28b2016-06-07 08:43:30 -0700214 class CompatibleRenderPassSet {
215 public:
216 // This will always construct the basic load store render pass (all attachments load and
217 // store their data) so that there is at least one compatible VkRenderPass that can be used
218 // with this set.
219 CompatibleRenderPassSet(const GrVkGpu* gpu, const GrVkRenderTarget& target);
220
221 bool isCompatible(const GrVkRenderTarget& target) const;
222
223 GrVkRenderPass* getCompatibleRenderPass() const {
224 // The first GrVkRenderpass should always exist since we create the basic load store
225 // render pass on create
226 SkASSERT(fRenderPasses[0]);
227 return fRenderPasses[0];
228 }
229
egdaniel2feb0932016-06-08 06:48:09 -0700230 GrVkRenderPass* getRenderPass(const GrVkGpu* gpu,
231 const GrVkRenderPass::LoadStoreOps& colorOps,
egdaniel2feb0932016-06-08 06:48:09 -0700232 const GrVkRenderPass::LoadStoreOps& stencilOps);
233
Ethan Nicholasbff4e072018-12-12 18:17:24 +0000234 void releaseResources(const GrVkGpu* gpu);
egdanield62e28b2016-06-07 08:43:30 -0700235 void abandonResources();
236
237 private:
238 SkSTArray<4, GrVkRenderPass*> fRenderPasses;
239 int fLastReturnedIndex;
240 };
241
Greg Daniel164a9f02016-02-22 09:56:40 -0500242 GrVkGpu* fGpu;
243
jvanverth03509ea2016-03-02 13:19:47 -0800244 // Central cache for creating pipelines
245 VkPipelineCache fPipelineCache;
246
egdanielbc9b2962016-09-27 08:00:53 -0700247 // Cache of previously created copy pipelines
248 SkTArray<GrVkCopyPipeline*> fCopyPipelines;
249
egdanield62e28b2016-06-07 08:43:30 -0700250 SkSTArray<4, CompatibleRenderPassSet> fRenderPassArray;
Greg Daniel164a9f02016-02-22 09:56:40 -0500251
Ethan Nicholasbff4e072018-12-12 18:17:24 +0000252 // Array of PrimaryCommandBuffers that are currently in flight
253 SkSTArray<4, GrVkPrimaryCommandBuffer*, true> fActiveCommandBuffers;
254 // Array of available primary command buffers that are not in flight
255 SkSTArray<4, GrVkPrimaryCommandBuffer*, true> fAvailableCommandBuffers;
jvanverth7ec92412016-07-06 09:24:57 -0700256
Ethan Nicholasbff4e072018-12-12 18:17:24 +0000257 // Array of available secondary command buffers
258 SkSTArray<16, GrVkSecondaryCommandBuffer*, true> fAvailableSecondaryCommandBuffers;
egdaniel8b6394c2016-03-04 07:35:10 -0800259
jvanverth4c6e47a2016-07-22 10:34:52 -0700260 // Array of available uniform buffer resources
egdaniel707bbd62016-07-26 07:19:47 -0700261 SkSTArray<16, const GrVkResource*, true> fAvailableUniformBufferResources;
jvanverth4c6e47a2016-07-22 10:34:52 -0700262
egdaniel8b6394c2016-03-04 07:35:10 -0800263 // Stores GrVkSampler objects that we've already created so we can reuse them across multiple
egdaniel22281c12016-03-23 13:49:40 -0700264 // GrVkPipelineStates
Greg Daniel7e000222018-12-03 10:08:21 -0500265 SkTDynamicHash<GrVkSampler, GrVkSampler::Key> fSamplers;
266
267 // Stores GrVkSamplerYcbcrConversion objects that we've already created so we can reuse them.
268 SkTDynamicHash<GrVkSamplerYcbcrConversion, GrVkSamplerYcbcrConversion::Key> fYcbcrConversions;
egdaniel22281c12016-03-23 13:49:40 -0700269
270 // Cache of GrVkPipelineStates
271 PipelineStateCache* fPipelineStateCache;
egdaniel778555c2016-05-02 06:50:36 -0700272
Greg Daniel18f96022017-05-04 15:09:03 -0400273 SkSTArray<4, std::unique_ptr<GrVkDescriptorSetManager>> fDescriptorSetManagers;
egdaniela95220d2016-07-21 11:50:37 -0700274
egdaniel707bbd62016-07-26 07:19:47 -0700275 GrVkDescriptorSetManager::Handle fUniformDSHandle;
Greg Daniel164a9f02016-02-22 09:56:40 -0500276};
277
278#endif