• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "GrVkResourceProvider.h"
9 
10 #include "GrSamplerParams.h"
11 #include "GrVkCommandBuffer.h"
12 #include "GrVkCopyPipeline.h"
13 #include "GrVkGpu.h"
14 #include "GrVkPipeline.h"
15 #include "GrVkRenderTarget.h"
16 #include "GrVkSampler.h"
17 #include "GrVkUniformBuffer.h"
18 #include "GrVkUtil.h"
19 
20 #ifdef SK_TRACE_VK_RESOURCES
21 GrVkResource::Trace GrVkResource::fTrace;
22 uint32_t GrVkResource::fKeyCounter = 0;
23 #endif
24 
GrVkResourceProvider(GrVkGpu * gpu)25 GrVkResourceProvider::GrVkResourceProvider(GrVkGpu* gpu)
26     : fGpu(gpu)
27     , fPipelineCache(VK_NULL_HANDLE) {
28     fPipelineStateCache = new PipelineStateCache(gpu);
29 }
30 
~GrVkResourceProvider()31 GrVkResourceProvider::~GrVkResourceProvider() {
32     SkASSERT(0 == fRenderPassArray.count());
33     SkASSERT(VK_NULL_HANDLE == fPipelineCache);
34     delete fPipelineStateCache;
35 }
36 
init()37 void GrVkResourceProvider::init() {
38     VkPipelineCacheCreateInfo createInfo;
39     memset(&createInfo, 0, sizeof(VkPipelineCacheCreateInfo));
40     createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
41     createInfo.pNext = nullptr;
42     createInfo.flags = 0;
43     createInfo.initialDataSize = 0;
44     createInfo.pInitialData = nullptr;
45     VkResult result = GR_VK_CALL(fGpu->vkInterface(),
46                                  CreatePipelineCache(fGpu->device(), &createInfo, nullptr,
47                                                      &fPipelineCache));
48     SkASSERT(VK_SUCCESS == result);
49     if (VK_SUCCESS != result) {
50         fPipelineCache = VK_NULL_HANDLE;
51     }
52 
53     // Init uniform descriptor objects
54     GrVkDescriptorSetManager* dsm = GrVkDescriptorSetManager::CreateUniformManager(fGpu);
55     fDescriptorSetManagers.emplace_back(dsm);
56     SkASSERT(1 == fDescriptorSetManagers.count());
57     fUniformDSHandle = GrVkDescriptorSetManager::Handle(0);
58 }
59 
createPipeline(const GrPipeline & pipeline,const GrStencilSettings & stencil,const GrPrimitiveProcessor & primProc,VkPipelineShaderStageCreateInfo * shaderStageInfo,int shaderStageCount,GrPrimitiveType primitiveType,const GrVkRenderPass & renderPass,VkPipelineLayout layout)60 GrVkPipeline* GrVkResourceProvider::createPipeline(const GrPipeline& pipeline,
61                                                    const GrStencilSettings& stencil,
62                                                    const GrPrimitiveProcessor& primProc,
63                                                    VkPipelineShaderStageCreateInfo* shaderStageInfo,
64                                                    int shaderStageCount,
65                                                    GrPrimitiveType primitiveType,
66                                                    const GrVkRenderPass& renderPass,
67                                                    VkPipelineLayout layout) {
68 
69     return GrVkPipeline::Create(fGpu, pipeline, stencil, primProc, shaderStageInfo,
70                                 shaderStageCount, primitiveType, renderPass, layout,
71                                 fPipelineCache);
72 }
73 
findOrCreateCopyPipeline(const GrVkRenderTarget * dst,VkPipelineShaderStageCreateInfo * shaderStageInfo,VkPipelineLayout pipelineLayout)74 GrVkCopyPipeline* GrVkResourceProvider::findOrCreateCopyPipeline(
75         const GrVkRenderTarget* dst,
76         VkPipelineShaderStageCreateInfo* shaderStageInfo,
77         VkPipelineLayout pipelineLayout) {
78     // Find or Create a compatible pipeline
79     GrVkCopyPipeline* pipeline = nullptr;
80     for (int i = 0; i < fCopyPipelines.count() && !pipeline; ++i) {
81         if (fCopyPipelines[i]->isCompatible(*dst->simpleRenderPass())) {
82             pipeline = fCopyPipelines[i];
83         }
84     }
85     if (!pipeline) {
86         pipeline = GrVkCopyPipeline::Create(fGpu, shaderStageInfo,
87                                             pipelineLayout,
88                                             dst->numColorSamples(),
89                                             *dst->simpleRenderPass(),
90                                             fPipelineCache);
91         fCopyPipelines.push_back(pipeline);
92     }
93     SkASSERT(pipeline);
94     pipeline->ref();
95     return pipeline;
96 }
97 
98 // To create framebuffers, we first need to create a simple RenderPass that is
99 // only used for framebuffer creation. When we actually render we will create
100 // RenderPasses as needed that are compatible with the framebuffer.
101 const GrVkRenderPass*
findCompatibleRenderPass(const GrVkRenderTarget & target,CompatibleRPHandle * compatibleHandle)102 GrVkResourceProvider::findCompatibleRenderPass(const GrVkRenderTarget& target,
103                                                CompatibleRPHandle* compatibleHandle) {
104     for (int i = 0; i < fRenderPassArray.count(); ++i) {
105         if (fRenderPassArray[i].isCompatible(target)) {
106             const GrVkRenderPass* renderPass = fRenderPassArray[i].getCompatibleRenderPass();
107             renderPass->ref();
108             if (compatibleHandle) {
109                 *compatibleHandle = CompatibleRPHandle(i);
110             }
111             return renderPass;
112         }
113     }
114 
115     const GrVkRenderPass* renderPass =
116         fRenderPassArray.emplace_back(fGpu, target).getCompatibleRenderPass();
117     renderPass->ref();
118 
119     if (compatibleHandle) {
120         *compatibleHandle = CompatibleRPHandle(fRenderPassArray.count() - 1);
121     }
122     return renderPass;
123 }
124 
125 const GrVkRenderPass*
findCompatibleRenderPass(const CompatibleRPHandle & compatibleHandle)126 GrVkResourceProvider::findCompatibleRenderPass(const CompatibleRPHandle& compatibleHandle) {
127     SkASSERT(compatibleHandle.isValid() && compatibleHandle.toIndex() < fRenderPassArray.count());
128     int index = compatibleHandle.toIndex();
129     const GrVkRenderPass* renderPass = fRenderPassArray[index].getCompatibleRenderPass();
130     renderPass->ref();
131     return renderPass;
132 }
133 
findRenderPass(const GrVkRenderTarget & target,const GrVkRenderPass::LoadStoreOps & colorOps,const GrVkRenderPass::LoadStoreOps & stencilOps,CompatibleRPHandle * compatibleHandle)134 const GrVkRenderPass* GrVkResourceProvider::findRenderPass(
135                                                      const GrVkRenderTarget& target,
136                                                      const GrVkRenderPass::LoadStoreOps& colorOps,
137                                                      const GrVkRenderPass::LoadStoreOps& stencilOps,
138                                                      CompatibleRPHandle* compatibleHandle) {
139     GrVkResourceProvider::CompatibleRPHandle tempRPHandle;
140     GrVkResourceProvider::CompatibleRPHandle* pRPHandle = compatibleHandle ? compatibleHandle
141                                                                            : &tempRPHandle;
142     *pRPHandle = target.compatibleRenderPassHandle();
143 
144     // This will get us the handle to (and possible create) the compatible set for the specific
145     // GrVkRenderPass we are looking for.
146     this->findCompatibleRenderPass(target, compatibleHandle);
147     return this->findRenderPass(*pRPHandle, colorOps, stencilOps);
148 }
149 
150 const GrVkRenderPass*
findRenderPass(const CompatibleRPHandle & compatibleHandle,const GrVkRenderPass::LoadStoreOps & colorOps,const GrVkRenderPass::LoadStoreOps & stencilOps)151 GrVkResourceProvider::findRenderPass(const CompatibleRPHandle& compatibleHandle,
152                                      const GrVkRenderPass::LoadStoreOps& colorOps,
153                                      const GrVkRenderPass::LoadStoreOps& stencilOps) {
154     SkASSERT(compatibleHandle.isValid() && compatibleHandle.toIndex() < fRenderPassArray.count());
155     CompatibleRenderPassSet& compatibleSet = fRenderPassArray[compatibleHandle.toIndex()];
156     const GrVkRenderPass* renderPass = compatibleSet.getRenderPass(fGpu,
157                                                                    colorOps,
158                                                                    stencilOps);
159     renderPass->ref();
160     return renderPass;
161 }
162 
findOrCreateCompatibleDescriptorPool(VkDescriptorType type,uint32_t count)163 GrVkDescriptorPool* GrVkResourceProvider::findOrCreateCompatibleDescriptorPool(
164                                                             VkDescriptorType type, uint32_t count) {
165     return new GrVkDescriptorPool(fGpu, type, count);
166 }
167 
findOrCreateCompatibleSampler(const GrSamplerParams & params,uint32_t mipLevels)168 GrVkSampler* GrVkResourceProvider::findOrCreateCompatibleSampler(const GrSamplerParams& params,
169                                                                  uint32_t mipLevels) {
170     GrVkSampler* sampler = fSamplers.find(GrVkSampler::GenerateKey(params, mipLevels));
171     if (!sampler) {
172         sampler = GrVkSampler::Create(fGpu, params, mipLevels);
173         fSamplers.add(sampler);
174     }
175     SkASSERT(sampler);
176     sampler->ref();
177     return sampler;
178 }
179 
findOrCreateCompatiblePipelineState(const GrPipeline & pipeline,const GrPrimitiveProcessor & proc,GrPrimitiveType primitiveType,const GrVkRenderPass & renderPass)180 sk_sp<GrVkPipelineState> GrVkResourceProvider::findOrCreateCompatiblePipelineState(
181                                                                  const GrPipeline& pipeline,
182                                                                  const GrPrimitiveProcessor& proc,
183                                                                  GrPrimitiveType primitiveType,
184                                                                  const GrVkRenderPass& renderPass) {
185     return fPipelineStateCache->refPipelineState(pipeline, proc, primitiveType, renderPass);
186 }
187 
getSamplerDescriptorSetHandle(VkDescriptorType type,const GrVkUniformHandler & uniformHandler,GrVkDescriptorSetManager::Handle * handle)188 void GrVkResourceProvider::getSamplerDescriptorSetHandle(VkDescriptorType type,
189                                                          const GrVkUniformHandler& uniformHandler,
190                                                          GrVkDescriptorSetManager::Handle* handle) {
191     SkASSERT(handle);
192     SkASSERT(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER == type ||
193              VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER == type);
194     for (int i = 0; i < fDescriptorSetManagers.count(); ++i) {
195         if (fDescriptorSetManagers[i]->isCompatible(type, &uniformHandler)) {
196            *handle = GrVkDescriptorSetManager::Handle(i);
197            return;
198         }
199     }
200 
201     GrVkDescriptorSetManager* dsm = GrVkDescriptorSetManager::CreateSamplerManager(fGpu, type,
202                                                                                    uniformHandler);
203     fDescriptorSetManagers.emplace_back(dsm);
204     *handle = GrVkDescriptorSetManager::Handle(fDescriptorSetManagers.count() - 1);
205 }
206 
getSamplerDescriptorSetHandle(VkDescriptorType type,const SkTArray<uint32_t> & visibilities,GrVkDescriptorSetManager::Handle * handle)207 void GrVkResourceProvider::getSamplerDescriptorSetHandle(VkDescriptorType type,
208                                                          const SkTArray<uint32_t>& visibilities,
209                                                          GrVkDescriptorSetManager::Handle* handle) {
210     SkASSERT(handle);
211     SkASSERT(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER == type ||
212              VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER == type);
213     for (int i = 0; i < fDescriptorSetManagers.count(); ++i) {
214         if (fDescriptorSetManagers[i]->isCompatible(type, visibilities)) {
215             *handle = GrVkDescriptorSetManager::Handle(i);
216             return;
217         }
218     }
219 
220     GrVkDescriptorSetManager* dsm = GrVkDescriptorSetManager::CreateSamplerManager(fGpu, type,
221                                                                                    visibilities);
222     fDescriptorSetManagers.emplace_back(dsm);
223     *handle = GrVkDescriptorSetManager::Handle(fDescriptorSetManagers.count() - 1);
224 }
225 
getUniformDSLayout() const226 VkDescriptorSetLayout GrVkResourceProvider::getUniformDSLayout() const {
227     SkASSERT(fUniformDSHandle.isValid());
228     return fDescriptorSetManagers[fUniformDSHandle.toIndex()]->layout();
229 }
230 
getSamplerDSLayout(const GrVkDescriptorSetManager::Handle & handle) const231 VkDescriptorSetLayout GrVkResourceProvider::getSamplerDSLayout(
232         const GrVkDescriptorSetManager::Handle& handle) const {
233     SkASSERT(handle.isValid());
234     return fDescriptorSetManagers[handle.toIndex()]->layout();
235 }
236 
getUniformDescriptorSet()237 const GrVkDescriptorSet* GrVkResourceProvider::getUniformDescriptorSet() {
238     SkASSERT(fUniformDSHandle.isValid());
239     return fDescriptorSetManagers[fUniformDSHandle.toIndex()]->getDescriptorSet(fGpu,
240                                                                                 fUniformDSHandle);
241 }
242 
getSamplerDescriptorSet(const GrVkDescriptorSetManager::Handle & handle)243 const GrVkDescriptorSet* GrVkResourceProvider::getSamplerDescriptorSet(
244         const GrVkDescriptorSetManager::Handle& handle) {
245     SkASSERT(handle.isValid());
246     return fDescriptorSetManagers[handle.toIndex()]->getDescriptorSet(fGpu, handle);
247 }
248 
recycleDescriptorSet(const GrVkDescriptorSet * descSet,const GrVkDescriptorSetManager::Handle & handle)249 void GrVkResourceProvider::recycleDescriptorSet(const GrVkDescriptorSet* descSet,
250                                                 const GrVkDescriptorSetManager::Handle& handle) {
251     SkASSERT(descSet);
252     SkASSERT(handle.isValid());
253     int managerIdx = handle.toIndex();
254     SkASSERT(managerIdx < fDescriptorSetManagers.count());
255     fDescriptorSetManagers[managerIdx]->recycleDescriptorSet(descSet);
256 }
257 
findOrCreatePrimaryCommandBuffer()258 GrVkPrimaryCommandBuffer* GrVkResourceProvider::findOrCreatePrimaryCommandBuffer() {
259     GrVkPrimaryCommandBuffer* cmdBuffer = nullptr;
260     int count = fAvailableCommandBuffers.count();
261     if (count > 0) {
262         cmdBuffer = fAvailableCommandBuffers[count - 1];
263         SkASSERT(cmdBuffer->finished(fGpu));
264         fAvailableCommandBuffers.removeShuffle(count - 1);
265     } else {
266         cmdBuffer = GrVkPrimaryCommandBuffer::Create(fGpu, fGpu->cmdPool());
267     }
268     fActiveCommandBuffers.push_back(cmdBuffer);
269     cmdBuffer->ref();
270     return cmdBuffer;
271 }
272 
checkCommandBuffers()273 void GrVkResourceProvider::checkCommandBuffers() {
274     for (int i = fActiveCommandBuffers.count()-1; i >= 0; --i) {
275         if (fActiveCommandBuffers[i]->finished(fGpu)) {
276             GrVkPrimaryCommandBuffer* cmdBuffer = fActiveCommandBuffers[i];
277             cmdBuffer->reset(fGpu);
278             fAvailableCommandBuffers.push_back(cmdBuffer);
279             fActiveCommandBuffers.removeShuffle(i);
280         }
281     }
282 }
283 
findOrCreateSecondaryCommandBuffer()284 GrVkSecondaryCommandBuffer* GrVkResourceProvider::findOrCreateSecondaryCommandBuffer() {
285     GrVkSecondaryCommandBuffer* cmdBuffer = nullptr;
286     int count = fAvailableSecondaryCommandBuffers.count();
287     if (count > 0) {
288         cmdBuffer = fAvailableSecondaryCommandBuffers[count-1];
289         fAvailableSecondaryCommandBuffers.removeShuffle(count - 1);
290     } else {
291         cmdBuffer = GrVkSecondaryCommandBuffer::Create(fGpu, fGpu->cmdPool());
292     }
293     return cmdBuffer;
294 }
295 
recycleSecondaryCommandBuffer(GrVkSecondaryCommandBuffer * cb)296 void GrVkResourceProvider::recycleSecondaryCommandBuffer(GrVkSecondaryCommandBuffer* cb) {
297     cb->reset(fGpu);
298     fAvailableSecondaryCommandBuffers.push_back(cb);
299 }
300 
findOrCreateStandardUniformBufferResource()301 const GrVkResource* GrVkResourceProvider::findOrCreateStandardUniformBufferResource() {
302     const GrVkResource* resource = nullptr;
303     int count = fAvailableUniformBufferResources.count();
304     if (count > 0) {
305         resource = fAvailableUniformBufferResources[count - 1];
306         fAvailableUniformBufferResources.removeShuffle(count - 1);
307     } else {
308         resource = GrVkUniformBuffer::CreateResource(fGpu, GrVkUniformBuffer::kStandardSize);
309     }
310     return resource;
311 }
312 
recycleStandardUniformBufferResource(const GrVkResource * resource)313 void GrVkResourceProvider::recycleStandardUniformBufferResource(const GrVkResource* resource) {
314     fAvailableUniformBufferResources.push_back(resource);
315 }
316 
destroyResources(bool deviceLost)317 void GrVkResourceProvider::destroyResources(bool deviceLost) {
318     // release our active command buffers
319     for (int i = 0; i < fActiveCommandBuffers.count(); ++i) {
320         SkASSERT(deviceLost || fActiveCommandBuffers[i]->finished(fGpu));
321         SkASSERT(fActiveCommandBuffers[i]->unique());
322         fActiveCommandBuffers[i]->reset(fGpu);
323         fActiveCommandBuffers[i]->unref(fGpu);
324     }
325     fActiveCommandBuffers.reset();
326     // release our available command buffers
327     for (int i = 0; i < fAvailableCommandBuffers.count(); ++i) {
328         SkASSERT(deviceLost || fAvailableCommandBuffers[i]->finished(fGpu));
329         SkASSERT(fAvailableCommandBuffers[i]->unique());
330         fAvailableCommandBuffers[i]->unref(fGpu);
331     }
332     fAvailableCommandBuffers.reset();
333 
334     // release our available secondary command buffers
335     for (int i = 0; i < fAvailableSecondaryCommandBuffers.count(); ++i) {
336         SkASSERT(fAvailableSecondaryCommandBuffers[i]->unique());
337         fAvailableSecondaryCommandBuffers[i]->unref(fGpu);
338     }
339     fAvailableSecondaryCommandBuffers.reset();
340 
341     // Release all copy pipelines
342     for (int i = 0; i < fCopyPipelines.count(); ++i) {
343         fCopyPipelines[i]->unref(fGpu);
344     }
345 
346     // loop over all render pass sets to make sure we destroy all the internal VkRenderPasses
347     for (int i = 0; i < fRenderPassArray.count(); ++i) {
348         fRenderPassArray[i].releaseResources(fGpu);
349     }
350     fRenderPassArray.reset();
351 
352     // Iterate through all store GrVkSamplers and unref them before resetting the hash.
353     SkTDynamicHash<GrVkSampler, uint16_t>::Iter iter(&fSamplers);
354     for (; !iter.done(); ++iter) {
355         (*iter).unref(fGpu);
356     }
357     fSamplers.reset();
358 
359     fPipelineStateCache->release();
360 
361     GR_VK_CALL(fGpu->vkInterface(), DestroyPipelineCache(fGpu->device(), fPipelineCache, nullptr));
362     fPipelineCache = VK_NULL_HANDLE;
363 
364     // We must release/destroy all command buffers and pipeline states before releasing the
365     // GrVkDescriptorSetManagers
366     for (int i = 0; i < fDescriptorSetManagers.count(); ++i) {
367         fDescriptorSetManagers[i]->release(fGpu);
368     }
369     fDescriptorSetManagers.reset();
370 
371     // release our uniform buffers
372     for (int i = 0; i < fAvailableUniformBufferResources.count(); ++i) {
373         SkASSERT(fAvailableUniformBufferResources[i]->unique());
374         fAvailableUniformBufferResources[i]->unref(fGpu);
375     }
376     fAvailableUniformBufferResources.reset();
377 }
378 
abandonResources()379 void GrVkResourceProvider::abandonResources() {
380     // release our active command buffers
381     for (int i = 0; i < fActiveCommandBuffers.count(); ++i) {
382         SkASSERT(fActiveCommandBuffers[i]->finished(fGpu));
383         SkASSERT(fActiveCommandBuffers[i]->unique());
384         fActiveCommandBuffers[i]->unrefAndAbandon();
385     }
386     fActiveCommandBuffers.reset();
387     // release our available command buffers
388     for (int i = 0; i < fAvailableCommandBuffers.count(); ++i) {
389         SkASSERT(fAvailableCommandBuffers[i]->finished(fGpu));
390         SkASSERT(fAvailableCommandBuffers[i]->unique());
391         fAvailableCommandBuffers[i]->unrefAndAbandon();
392     }
393     fAvailableCommandBuffers.reset();
394 
395     // release our available secondary command buffers
396     for (int i = 0; i < fAvailableSecondaryCommandBuffers.count(); ++i) {
397         SkASSERT(fAvailableSecondaryCommandBuffers[i]->unique());
398         fAvailableSecondaryCommandBuffers[i]->unrefAndAbandon();
399     }
400     fAvailableSecondaryCommandBuffers.reset();
401 
402     // Abandon all copy pipelines
403     for (int i = 0; i < fCopyPipelines.count(); ++i) {
404         fCopyPipelines[i]->unrefAndAbandon();
405     }
406 
407     // loop over all render pass sets to make sure we destroy all the internal VkRenderPasses
408     for (int i = 0; i < fRenderPassArray.count(); ++i) {
409         fRenderPassArray[i].abandonResources();
410     }
411     fRenderPassArray.reset();
412 
413     // Iterate through all store GrVkSamplers and unrefAndAbandon them before resetting the hash.
414     SkTDynamicHash<GrVkSampler, uint16_t>::Iter iter(&fSamplers);
415     for (; !iter.done(); ++iter) {
416         (*iter).unrefAndAbandon();
417     }
418     fSamplers.reset();
419 
420     fPipelineStateCache->abandon();
421 
422     fPipelineCache = VK_NULL_HANDLE;
423 
424     // We must abandon all command buffers and pipeline states before abandoning the
425     // GrVkDescriptorSetManagers
426     for (int i = 0; i < fDescriptorSetManagers.count(); ++i) {
427         fDescriptorSetManagers[i]->abandon();
428     }
429     fDescriptorSetManagers.reset();
430 
431     // release our uniform buffers
432     for (int i = 0; i < fAvailableUniformBufferResources.count(); ++i) {
433         SkASSERT(fAvailableUniformBufferResources[i]->unique());
434         fAvailableUniformBufferResources[i]->unrefAndAbandon();
435     }
436     fAvailableUniformBufferResources.reset();
437 }
438 
439 ////////////////////////////////////////////////////////////////////////////////
440 
CompatibleRenderPassSet(const GrVkGpu * gpu,const GrVkRenderTarget & target)441 GrVkResourceProvider::CompatibleRenderPassSet::CompatibleRenderPassSet(
442                                                                      const GrVkGpu* gpu,
443                                                                      const GrVkRenderTarget& target)
444     : fLastReturnedIndex(0) {
445     fRenderPasses.emplace_back(new GrVkRenderPass());
446     fRenderPasses[0]->initSimple(gpu, target);
447 }
448 
isCompatible(const GrVkRenderTarget & target) const449 bool GrVkResourceProvider::CompatibleRenderPassSet::isCompatible(
450                                                              const GrVkRenderTarget& target) const {
451     // The first GrVkRenderpass should always exists since we create the basic load store
452     // render pass on create
453     SkASSERT(fRenderPasses[0]);
454     return fRenderPasses[0]->isCompatible(target);
455 }
456 
getRenderPass(const GrVkGpu * gpu,const GrVkRenderPass::LoadStoreOps & colorOps,const GrVkRenderPass::LoadStoreOps & stencilOps)457 GrVkRenderPass* GrVkResourceProvider::CompatibleRenderPassSet::getRenderPass(
458                                                    const GrVkGpu* gpu,
459                                                    const GrVkRenderPass::LoadStoreOps& colorOps,
460                                                    const GrVkRenderPass::LoadStoreOps& stencilOps) {
461     for (int i = 0; i < fRenderPasses.count(); ++i) {
462         int idx = (i + fLastReturnedIndex) % fRenderPasses.count();
463         if (fRenderPasses[idx]->equalLoadStoreOps(colorOps, stencilOps)) {
464             fLastReturnedIndex = idx;
465             return fRenderPasses[idx];
466         }
467     }
468     GrVkRenderPass* renderPass = fRenderPasses.emplace_back(new GrVkRenderPass());
469     renderPass->init(gpu, *this->getCompatibleRenderPass(), colorOps, stencilOps);
470     fLastReturnedIndex = fRenderPasses.count() - 1;
471     return renderPass;
472 }
473 
releaseResources(const GrVkGpu * gpu)474 void GrVkResourceProvider::CompatibleRenderPassSet::releaseResources(const GrVkGpu* gpu) {
475     for (int i = 0; i < fRenderPasses.count(); ++i) {
476         if (fRenderPasses[i]) {
477             fRenderPasses[i]->unref(gpu);
478             fRenderPasses[i] = nullptr;
479         }
480     }
481 }
482 
abandonResources()483 void GrVkResourceProvider::CompatibleRenderPassSet::abandonResources() {
484     for (int i = 0; i < fRenderPasses.count(); ++i) {
485         if (fRenderPasses[i]) {
486             fRenderPasses[i]->unrefAndAbandon();
487             fRenderPasses[i] = nullptr;
488         }
489     }
490 }
491