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