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