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 "include/gpu/vk/GrVkTypes.h" 12 #include "include/private/SkMutex.h" 13 #include "include/private/SkTArray.h" 14 #include "src/core/SkLRUCache.h" 15 #include "src/core/SkTDynamicHash.h" 16 #include "src/core/SkTInternalLList.h" 17 #include "src/gpu/GrGpu.h" 18 #include "src/gpu/GrManagedResource.h" 19 #include "src/gpu/GrProgramDesc.h" 20 #include "src/gpu/GrResourceHandle.h" 21 #include "src/gpu/GrThreadSafePipelineBuilder.h" 22 #include "src/gpu/vk/GrVkDescriptorPool.h" 23 #include "src/gpu/vk/GrVkDescriptorSetManager.h" 24 #include "src/gpu/vk/GrVkPipelineStateBuilder.h" 25 #include "src/gpu/vk/GrVkRenderPass.h" 26 #include "src/gpu/vk/GrVkSampler.h" 27 #include "src/gpu/vk/GrVkSamplerYcbcrConversion.h" 28 #include "src/gpu/vk/GrVkUtil.h" 29 30 class GrVkCommandPool; 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 pipelineStateCache()44 GrThreadSafePipelineBuilder* pipelineStateCache() { 45 return fPipelineStateCache.get(); 46 } 47 refPipelineStateCache()48 sk_sp<GrThreadSafePipelineBuilder> refPipelineStateCache() { 49 return fPipelineStateCache; 50 } 51 52 // Set up any initial vk objects 53 void init(); 54 55 sk_sp<const GrVkPipeline> makePipeline(const GrProgramInfo&, 56 VkPipelineShaderStageCreateInfo* shaderStageInfo, 57 int shaderStageCount, 58 VkRenderPass compatibleRenderPass, 59 VkPipelineLayout layout, 60 uint32_t subpass); 61 62 GR_DEFINE_RESOURCE_HANDLE_CLASS(CompatibleRPHandle); 63 64 using SelfDependencyFlags = GrVkRenderPass::SelfDependencyFlags; 65 using LoadFromResolve = GrVkRenderPass::LoadFromResolve; 66 67 // Finds or creates a simple render pass that matches the target, increments the refcount, 68 // and returns. The caller can optionally pass in a pointer to a CompatibleRPHandle. If this is 69 // non null it will be set to a handle that can be used in the furutre to quickly return a 70 // compatible GrVkRenderPasses without the need inspecting a GrVkRenderTarget. 71 const GrVkRenderPass* findCompatibleRenderPass(GrVkRenderTarget* target, 72 CompatibleRPHandle* compatibleHandle, 73 bool withResolve, 74 bool withStencil, 75 SelfDependencyFlags selfDepFlags, 76 LoadFromResolve); 77 const GrVkRenderPass* findCompatibleRenderPass(GrVkRenderPass::AttachmentsDescriptor*, 78 GrVkRenderPass::AttachmentFlags, 79 SelfDependencyFlags selfDepFlags, 80 LoadFromResolve, 81 CompatibleRPHandle* compatibleHandle = nullptr); 82 83 const GrVkRenderPass* findCompatibleExternalRenderPass(VkRenderPass, 84 uint32_t colorAttachmentIndex); 85 86 87 // Finds or creates a render pass that matches the target and LoadStoreOps, increments the 88 // refcount, and returns. The caller can optionally pass in a pointer to a CompatibleRPHandle. 89 // If this is non null it will be set to a handle that can be used in the future to quickly 90 // return a GrVkRenderPass without the need to inspect a GrVkRenderTarget. 91 // TODO: sk_sp? 92 const GrVkRenderPass* findRenderPass(GrVkRenderTarget* target, 93 const GrVkRenderPass::LoadStoreOps& colorOps, 94 const GrVkRenderPass::LoadStoreOps& resolveOps, 95 const GrVkRenderPass::LoadStoreOps& stencilOps, 96 CompatibleRPHandle* compatibleHandle, 97 bool withResolve, 98 bool withStencil, 99 SelfDependencyFlags selfDepFlags, 100 LoadFromResolve); 101 102 // The CompatibleRPHandle must be a valid handle previously set by a call to findRenderPass or 103 // findCompatibleRenderPass. 104 const GrVkRenderPass* findRenderPass(const CompatibleRPHandle& compatibleHandle, 105 const GrVkRenderPass::LoadStoreOps& colorOps, 106 const GrVkRenderPass::LoadStoreOps& resolveOps, 107 const GrVkRenderPass::LoadStoreOps& stencilOps); 108 109 GrVkCommandPool* findOrCreateCommandPool(); 110 111 void checkCommandBuffers(); 112 113 void forceSyncAllCommandBuffers(); 114 115 // We must add the finishedProc to all active command buffers since we may have flushed work 116 // that the client cares about before they explicitly called flush and the GPU may reorder 117 // command execution. So we make sure all previously submitted work finishes before we call the 118 // finishedProc. 119 void addFinishedProcToActiveCommandBuffers(sk_sp<GrRefCntedCallback> finishedCallback); 120 121 // Finds or creates a compatible GrVkDescriptorPool for the requested type and count. 122 // The refcount is incremented and a pointer returned. 123 // TODO: Currently this will just create a descriptor pool without holding onto a ref itself 124 // so we currently do not reuse them. Rquires knowing if another draw is currently using 125 // the GrVkDescriptorPool, the ability to reset pools, and the ability to purge pools out 126 // of our cache of GrVkDescriptorPools. 127 GrVkDescriptorPool* findOrCreateCompatibleDescriptorPool(VkDescriptorType type, uint32_t count); 128 129 // Finds or creates a compatible GrVkSampler based on the GrSamplerState and 130 // GrVkYcbcrConversionInfo. The refcount is incremented and a pointer returned. 131 GrVkSampler* findOrCreateCompatibleSampler(GrSamplerState, 132 const GrVkYcbcrConversionInfo& ycbcrInfo); 133 134 // Finds or creates a compatible GrVkSamplerYcbcrConversion based on the GrSamplerState and 135 // GrVkYcbcrConversionInfo. The refcount is incremented and a pointer returned. 136 GrVkSamplerYcbcrConversion* findOrCreateCompatibleSamplerYcbcrConversion( 137 const GrVkYcbcrConversionInfo& ycbcrInfo); 138 139 GrVkPipelineState* findOrCreateCompatiblePipelineState( 140 GrRenderTarget*, 141 const GrProgramInfo&, 142 VkRenderPass compatibleRenderPass, 143 bool overrideSubpassForResolveLoad); 144 145 GrVkPipelineState* findOrCreateCompatiblePipelineState( 146 const GrProgramDesc&, 147 const GrProgramInfo&, 148 VkRenderPass compatibleRenderPass, 149 GrThreadSafePipelineBuilder::Stats::ProgramCacheResult* stat); 150 151 sk_sp<const GrVkPipeline> findOrCreateMSAALoadPipeline( 152 const GrVkRenderPass& renderPass, 153 int numSamples, 154 VkPipelineShaderStageCreateInfo*, 155 VkPipelineLayout); 156 157 void getSamplerDescriptorSetHandle(VkDescriptorType type, 158 const GrVkUniformHandler&, 159 GrVkDescriptorSetManager::Handle* handle); 160 161 // This is a convenience function to return a descriptor set for zero sammples. When making a 162 // VkPipelineLayout we must pass in an array of valid descriptor set handles. However, we have 163 // set up our system to have the descriptor sets be in the order uniform, sampler, input. So 164 // if we have a uniform and input we will need to have a valid handle for the sampler as well. 165 // When using the GrVkMSAALoadManager this is the case, but we also don't have a 166 // GrVkUniformHandler to pass into the more general function. Thus we use this call instead. 167 void getZeroSamplerDescriptorSetHandle(GrVkDescriptorSetManager::Handle* handle); 168 169 // Returns the compatible VkDescriptorSetLayout to use for uniform buffers. The caller does not 170 // own the VkDescriptorSetLayout and thus should not delete it. This function should be used 171 // when the caller needs the layout to create a VkPipelineLayout. 172 VkDescriptorSetLayout getUniformDSLayout() const; 173 174 // Returns the compatible VkDescriptorSetLayout to use for input attachments. The caller does 175 // not own the VkDescriptorSetLayout and thus should not delete it. This function should be used 176 // when the caller needs the layout to create a VkPipelineLayout. 177 VkDescriptorSetLayout getInputDSLayout() const; 178 179 // Returns the compatible VkDescriptorSetLayout to use for a specific sampler handle. The caller 180 // does not own the VkDescriptorSetLayout and thus should not delete it. This function should be 181 // used when the caller needs the layout to create a VkPipelineLayout. 182 VkDescriptorSetLayout getSamplerDSLayout(const GrVkDescriptorSetManager::Handle&) const; 183 184 // Returns a GrVkDescriptorSet that can be used for uniform buffers. The GrVkDescriptorSet 185 // is already reffed for the caller. 186 const GrVkDescriptorSet* getUniformDescriptorSet(); 187 188 // Returns a GrVkDescriptorSet that can be used for sampler descriptors that are compatible with 189 // the GrVkDescriptorSetManager::Handle passed in. The GrVkDescriptorSet is already reffed for 190 // the caller. 191 const GrVkDescriptorSet* getSamplerDescriptorSet(const GrVkDescriptorSetManager::Handle&); 192 193 // Returns a GrVkDescriptorSet that can be used for input attachments. The GrVkDescriptorSet 194 // is already reffed for the caller. 195 const GrVkDescriptorSet* getInputDescriptorSet(); 196 197 // Signals that the descriptor set passed it, which is compatible with the passed in handle, 198 // can be reused by the next allocation request. 199 void recycleDescriptorSet(const GrVkDescriptorSet* descSet, 200 const GrVkDescriptorSetManager::Handle&); 201 202 void storePipelineCacheData(); 203 204 // Destroy any cached resources. To be called before destroying the VkDevice. 205 // The assumption is that all queues are idle and all command buffers are finished. 206 // For resource tracing to work properly, this should be called after unrefing all other 207 // resource usages. 208 void destroyResources(); 209 210 // Currently we just release available command pools (which also releases their buffers). The 211 // command buffers and pools take up the most memory. Other objects (e.g. samples, 212 // ycbcr conversions, etc.) tend to be fairly light weight and not worth the effort to remove 213 // them and then possibly remake them. Additionally many of those objects have refs/handles that 214 // are held by other objects that aren't deleted here. Thus the memory wins for removing these 215 // objects from the cache are probably not worth the complexity of safely releasing them. 216 void releaseUnlockedBackendObjects(); 217 218 void backgroundReset(GrVkCommandPool* pool); 219 220 void reset(GrVkCommandPool* pool); 221 222 #if GR_TEST_UTILS resetShaderCacheForTesting()223 void resetShaderCacheForTesting() const { fPipelineStateCache->release(); } 224 #endif 225 226 private: 227 class PipelineStateCache : public GrThreadSafePipelineBuilder { 228 public: 229 PipelineStateCache(GrVkGpu* gpu); 230 ~PipelineStateCache() override; 231 232 void release(); 233 GrVkPipelineState* findOrCreatePipelineState(GrRenderTarget*, 234 const GrProgramInfo&, 235 VkRenderPass compatibleRenderPass, 236 bool overrideSubpassForResolveLoad); findOrCreatePipelineState(const GrProgramDesc & desc,const GrProgramInfo & programInfo,VkRenderPass compatibleRenderPass,Stats::ProgramCacheResult * stat)237 GrVkPipelineState* findOrCreatePipelineState(const GrProgramDesc& desc, 238 const GrProgramInfo& programInfo, 239 VkRenderPass compatibleRenderPass, 240 Stats::ProgramCacheResult* stat) { 241 return this->findOrCreatePipelineStateImpl(desc, programInfo, compatibleRenderPass, 242 false, stat); 243 } 244 245 private: 246 struct Entry; 247 248 GrVkPipelineState* findOrCreatePipelineStateImpl(const GrProgramDesc&, 249 const GrProgramInfo&, 250 VkRenderPass compatibleRenderPass, 251 bool overrideSubpassForResolveLoad, 252 Stats::ProgramCacheResult*); 253 254 struct DescHash { operatorDescHash255 uint32_t operator()(const GrProgramDesc& desc) const { 256 return SkOpts::hash_fn(desc.asKey(), desc.keyLength(), 0); 257 } 258 }; 259 260 SkLRUCache<const GrProgramDesc, std::unique_ptr<Entry>, DescHash> fMap; 261 262 GrVkGpu* fGpu; 263 }; 264 265 class CompatibleRenderPassSet { 266 public: 267 // This will always construct the basic load store render pass (all attachments load and 268 // store their data) so that there is at least one compatible VkRenderPass that can be used 269 // with this set. 270 CompatibleRenderPassSet(GrVkRenderPass* renderPass); 271 272 bool isCompatible(const GrVkRenderPass::AttachmentsDescriptor&, 273 GrVkRenderPass::AttachmentFlags, 274 SelfDependencyFlags selfDepFlags, 275 LoadFromResolve) const; 276 getCompatibleRenderPass()277 const GrVkRenderPass* getCompatibleRenderPass() const { 278 // The first GrVkRenderpass should always exist since we create the basic load store 279 // render pass on create 280 SkASSERT(fRenderPasses[0]); 281 return fRenderPasses[0]; 282 } 283 284 GrVkRenderPass* getRenderPass(GrVkGpu* gpu, 285 const GrVkRenderPass::LoadStoreOps& colorOps, 286 const GrVkRenderPass::LoadStoreOps& resolveOps, 287 const GrVkRenderPass::LoadStoreOps& stencilOps); 288 289 void releaseResources(); 290 291 private: 292 SkSTArray<4, GrVkRenderPass*> fRenderPasses; 293 int fLastReturnedIndex; 294 }; 295 296 VkPipelineCache pipelineCache(); 297 298 GrVkGpu* fGpu; 299 300 // Central cache for creating pipelines 301 VkPipelineCache fPipelineCache; 302 //CAUTION: should only used in GrVkResourceProvider 303 size_t fPipelineCacheSize; 304 305 struct MSAALoadPipeline { 306 sk_sp<const GrVkPipeline> fPipeline; 307 const GrVkRenderPass* fRenderPass; 308 }; 309 310 // Cache of previously created msaa load pipelines 311 SkTArray<MSAALoadPipeline> fMSAALoadPipelines; 312 313 SkSTArray<4, CompatibleRenderPassSet> fRenderPassArray; 314 315 SkTArray<const GrVkRenderPass*> fExternalRenderPasses; 316 317 // Array of command pools that we are waiting on 318 SkSTArray<4, GrVkCommandPool*, true> fActiveCommandPools; 319 320 SkMutex fBackgroundMutex; 321 322 // Array of available command pools that are not in flight 323 SkSTArray<4, GrVkCommandPool*, true> fAvailableCommandPools SK_GUARDED_BY(fBackgroundMutex); 324 325 // Stores GrVkSampler objects that we've already created so we can reuse them across multiple 326 // GrVkPipelineStates 327 SkTDynamicHash<GrVkSampler, GrVkSampler::Key> fSamplers; 328 329 // Stores GrVkSamplerYcbcrConversion objects that we've already created so we can reuse them. 330 SkTDynamicHash<GrVkSamplerYcbcrConversion, GrVkSamplerYcbcrConversion::Key> fYcbcrConversions; 331 332 // Cache of GrVkPipelineStates 333 sk_sp<PipelineStateCache> fPipelineStateCache; 334 335 SkSTArray<4, std::unique_ptr<GrVkDescriptorSetManager>> fDescriptorSetManagers; 336 337 GrVkDescriptorSetManager::Handle fUniformDSHandle; 338 GrVkDescriptorSetManager::Handle fInputDSHandle; 339 }; 340 341 #endif 342