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 "GrGpu.h" 12 #include "GrResourceHandle.h" 13 #include "GrVkDescriptorPool.h" 14 #include "GrVkDescriptorSetManager.h" 15 #include "GrVkPipelineState.h" 16 #include "GrVkRenderPass.h" 17 #include "GrVkResource.h" 18 #include "GrVkUtil.h" 19 #include "SkLRUCache.h" 20 #include "SkTArray.h" 21 #include "SkTDynamicHash.h" 22 #include "SkTInternalLList.h" 23 24 #include "vk/GrVkDefines.h" 25 26 class GrPipeline; 27 class GrPrimitiveProcessor; 28 class GrSamplerParams; 29 class GrVkCopyPipeline; 30 class GrVkGpu; 31 class GrVkPipeline; 32 class GrVkPrimaryCommandBuffer; 33 class GrVkRenderTarget; 34 class GrVkSampler; 35 class GrVkSecondaryCommandBuffer; 36 class GrVkUniformHandler; 37 38 class GrVkResourceProvider { 39 public: 40 GrVkResourceProvider(GrVkGpu* gpu); 41 ~GrVkResourceProvider(); 42 43 // Set up any initial vk objects 44 void init(); 45 46 GrVkPipeline* createPipeline(const GrPipeline& pipeline, 47 const GrStencilSettings& stencil, 48 const GrPrimitiveProcessor& primProc, 49 VkPipelineShaderStageCreateInfo* shaderStageInfo, 50 int shaderStageCount, 51 GrPrimitiveType primitiveType, 52 const GrVkRenderPass& renderPass, 53 VkPipelineLayout layout); 54 55 GrVkCopyPipeline* findOrCreateCopyPipeline(const GrVkRenderTarget* dst, 56 VkPipelineShaderStageCreateInfo*, 57 VkPipelineLayout); 58 59 GR_DEFINE_RESOURCE_HANDLE_CLASS(CompatibleRPHandle); 60 61 // Finds or creates a simple render pass that matches the target, increments the refcount, 62 // and returns. The caller can optionally pass in a pointer to a CompatibleRPHandle. If this is 63 // non null it will be set to a handle that can be used in the furutre to quickly return a 64 // compatible GrVkRenderPasses without the need inspecting a GrVkRenderTarget. 65 const GrVkRenderPass* findCompatibleRenderPass(const GrVkRenderTarget& target, 66 CompatibleRPHandle* compatibleHandle = nullptr); 67 // The CompatibleRPHandle must be a valid handle previously set by a call to 68 // findCompatibleRenderPass(GrVkRenderTarget&, CompatibleRPHandle*). 69 const GrVkRenderPass* findCompatibleRenderPass(const CompatibleRPHandle& compatibleHandle); 70 71 // Finds or creates a render pass that matches the target and LoadStoreOps, increments the 72 // refcount, and returns. The caller can optionally pass in a pointer to a CompatibleRPHandle. 73 // If this is non null it will be set to a handle that can be used in the furutre to quickly 74 // return a GrVkRenderPasses without the need inspecting a GrVkRenderTarget. 75 const GrVkRenderPass* findRenderPass(const GrVkRenderTarget& target, 76 const GrVkRenderPass::LoadStoreOps& colorOps, 77 const GrVkRenderPass::LoadStoreOps& stencilOps, 78 CompatibleRPHandle* compatibleHandle = nullptr); 79 80 // The CompatibleRPHandle must be a valid handle previously set by a call to findRenderPass or 81 // findCompatibleRenderPass. 82 const GrVkRenderPass* findRenderPass(const CompatibleRPHandle& compatibleHandle, 83 const GrVkRenderPass::LoadStoreOps& colorOps, 84 const GrVkRenderPass::LoadStoreOps& stencilOps); 85 86 GrVkPrimaryCommandBuffer* findOrCreatePrimaryCommandBuffer(); 87 void checkCommandBuffers(); 88 89 GrVkSecondaryCommandBuffer* findOrCreateSecondaryCommandBuffer(); 90 void recycleSecondaryCommandBuffer(GrVkSecondaryCommandBuffer* cb); 91 92 // Finds or creates a compatible GrVkDescriptorPool for the requested type and count. 93 // The refcount is incremented and a pointer returned. 94 // TODO: Currently this will just create a descriptor pool without holding onto a ref itself 95 // so we currently do not reuse them. Rquires knowing if another draw is currently using 96 // the GrVkDescriptorPool, the ability to reset pools, and the ability to purge pools out 97 // of our cache of GrVkDescriptorPools. 98 GrVkDescriptorPool* findOrCreateCompatibleDescriptorPool(VkDescriptorType type, uint32_t count); 99 100 // Finds or creates a compatible GrVkSampler based on the GrSamplerParams. 101 // The refcount is incremented and a pointer returned. 102 GrVkSampler* findOrCreateCompatibleSampler(const GrSamplerParams&, uint32_t mipLevels); 103 104 sk_sp<GrVkPipelineState> findOrCreateCompatiblePipelineState(const GrPipeline&, 105 const GrPrimitiveProcessor&, 106 GrPrimitiveType, 107 const GrVkRenderPass& renderPass); 108 109 void getSamplerDescriptorSetHandle(const GrVkUniformHandler&, 110 GrVkDescriptorSetManager::Handle* handle); 111 void getSamplerDescriptorSetHandle(const SkTArray<uint32_t>& visibilities, 112 GrVkDescriptorSetManager::Handle* handle); 113 114 // Returns the compatible VkDescriptorSetLayout to use for uniform buffers. The caller does not 115 // own the VkDescriptorSetLayout and thus should not delete it. This function should be used 116 // when the caller needs the layout to create a VkPipelineLayout. 117 VkDescriptorSetLayout getUniformDSLayout() const; 118 119 // Returns the compatible VkDescriptorSetLayout to use for a specific sampler handle. The caller 120 // does not own the VkDescriptorSetLayout and thus should not delete it. This function should be 121 // used when the caller needs the layout to create a VkPipelineLayout. 122 VkDescriptorSetLayout getSamplerDSLayout(const GrVkDescriptorSetManager::Handle&) const; 123 124 // Returns a GrVkDescriptorSet that can be used for uniform buffers. The GrVkDescriptorSet 125 // is already reffed for the caller. 126 const GrVkDescriptorSet* getUniformDescriptorSet(); 127 128 // Returns a GrVkDescriptorSet that can be used for sampler descriptors that are compatible with 129 // the GrVkDescriptorSetManager::Handle passed in. The GrVkDescriptorSet is already reffed for 130 // the caller. 131 const GrVkDescriptorSet* getSamplerDescriptorSet(const GrVkDescriptorSetManager::Handle&); 132 133 134 // Signals that the descriptor set passed it, which is compatible with the passed in handle, 135 // can be reused by the next allocation request. 136 void recycleDescriptorSet(const GrVkDescriptorSet* descSet, 137 const GrVkDescriptorSetManager::Handle&); 138 139 // Creates or finds free uniform buffer resources of size GrVkUniformBuffer::kStandardSize. 140 // Anything larger will need to be created and released by the client. 141 const GrVkResource* findOrCreateStandardUniformBufferResource(); 142 143 // Signals that the resource passed to it (which should be a uniform buffer resource) 144 // can be reused by the next uniform buffer resource request. 145 void recycleStandardUniformBufferResource(const GrVkResource*); 146 147 // Destroy any cached resources. To be called before destroying the VkDevice. 148 // The assumption is that all queues are idle and all command buffers are finished. 149 // For resource tracing to work properly, this should be called after unrefing all other 150 // resource usages. 151 // If deviceLost is true, then resources will not be checked to see if they've finished 152 // before deleting (see section 4.2.4 of the Vulkan spec). 153 void destroyResources(bool deviceLost); 154 155 // Abandon any cached resources. To be used when the context/VkDevice is lost. 156 // For resource tracing to work properly, this should be called after unrefing all other 157 // resource usages. 158 void abandonResources(); 159 160 private: 161 #ifdef SK_DEBUG 162 #define GR_PIPELINE_STATE_CACHE_STATS 163 #endif 164 165 class PipelineStateCache : public ::SkNoncopyable { 166 public: 167 PipelineStateCache(GrVkGpu* gpu); 168 ~PipelineStateCache(); 169 170 void abandon(); 171 void release(); 172 sk_sp<GrVkPipelineState> refPipelineState(const GrPipeline&, 173 const GrPrimitiveProcessor&, 174 GrPrimitiveType, 175 const GrVkRenderPass& renderPass); 176 177 private: 178 enum { 179 // We may actually have kMaxEntries+1 PipelineStates in context because we create a new 180 // PipelineState before evicting from the cache. 181 kMaxEntries = 128, 182 }; 183 184 struct Entry; 185 186 struct DescHash { operatorDescHash187 uint32_t operator()(const GrProgramDesc& desc) const { 188 return SkOpts::hash_fn(desc.asKey(), desc.keyLength(), 0); 189 } 190 }; 191 192 SkLRUCache<const GrVkPipelineState::Desc, std::unique_ptr<Entry>, DescHash> fMap; 193 194 GrVkGpu* fGpu; 195 196 #ifdef GR_PIPELINE_STATE_CACHE_STATS 197 int fTotalRequests; 198 int fCacheMisses; 199 #endif 200 }; 201 202 class CompatibleRenderPassSet { 203 public: 204 // This will always construct the basic load store render pass (all attachments load and 205 // store their data) so that there is at least one compatible VkRenderPass that can be used 206 // with this set. 207 CompatibleRenderPassSet(const GrVkGpu* gpu, const GrVkRenderTarget& target); 208 209 bool isCompatible(const GrVkRenderTarget& target) const; 210 getCompatibleRenderPass()211 GrVkRenderPass* getCompatibleRenderPass() const { 212 // The first GrVkRenderpass should always exist since we create the basic load store 213 // render pass on create 214 SkASSERT(fRenderPasses[0]); 215 return fRenderPasses[0]; 216 } 217 218 GrVkRenderPass* getRenderPass(const GrVkGpu* gpu, 219 const GrVkRenderPass::LoadStoreOps& colorOps, 220 const GrVkRenderPass::LoadStoreOps& stencilOps); 221 222 void releaseResources(const GrVkGpu* gpu); 223 void abandonResources(); 224 225 private: 226 SkSTArray<4, GrVkRenderPass*> fRenderPasses; 227 int fLastReturnedIndex; 228 }; 229 230 GrVkGpu* fGpu; 231 232 // Central cache for creating pipelines 233 VkPipelineCache fPipelineCache; 234 235 // Cache of previously created copy pipelines 236 SkTArray<GrVkCopyPipeline*> fCopyPipelines; 237 238 SkSTArray<4, CompatibleRenderPassSet> fRenderPassArray; 239 240 // Array of PrimaryCommandBuffers that are currently in flight 241 SkSTArray<4, GrVkPrimaryCommandBuffer*, true> fActiveCommandBuffers; 242 // Array of available primary command buffers that are not in flight 243 SkSTArray<4, GrVkPrimaryCommandBuffer*, true> fAvailableCommandBuffers; 244 245 // Array of available secondary command buffers 246 SkSTArray<16, GrVkSecondaryCommandBuffer*, true> fAvailableSecondaryCommandBuffers; 247 248 // Array of available uniform buffer resources 249 SkSTArray<16, const GrVkResource*, true> fAvailableUniformBufferResources; 250 251 // Stores GrVkSampler objects that we've already created so we can reuse them across multiple 252 // GrVkPipelineStates 253 SkTDynamicHash<GrVkSampler, uint16_t> fSamplers; 254 255 // Cache of GrVkPipelineStates 256 PipelineStateCache* fPipelineStateCache; 257 258 SkSTArray<4, GrVkDescriptorSetManager, true> fDescriptorSetManagers; 259 260 GrVkDescriptorSetManager::Handle fUniformDSHandle; 261 }; 262 263 #endif 264