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