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