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