1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci* Copyright 2016 Google Inc.
3cb93a386Sopenharmony_ci*
4cb93a386Sopenharmony_ci* Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci* found in the LICENSE file.
6cb93a386Sopenharmony_ci*/
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkResourceProvider.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h"
11cb93a386Sopenharmony_ci#include "src/core/SkTaskGroup.h"
12cb93a386Sopenharmony_ci#include "src/core/SkTraceEvent.h"
13cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h"
14cb93a386Sopenharmony_ci#include "src/gpu/GrSamplerState.h"
15cb93a386Sopenharmony_ci#include "src/gpu/GrStencilSettings.h"
16cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkCommandBuffer.h"
17cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkCommandPool.h"
18cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkGpu.h"
19cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkPipeline.h"
20cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkRenderTarget.h"
21cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkUtil.h"
22cb93a386Sopenharmony_ci
23cb93a386Sopenharmony_ciGrVkResourceProvider::GrVkResourceProvider(GrVkGpu* gpu)
24cb93a386Sopenharmony_ci    : fGpu(gpu)
25cb93a386Sopenharmony_ci    , fPipelineCache(VK_NULL_HANDLE)
26cb93a386Sopenharmony_ci    , fPipelineCacheSize(0) {
27cb93a386Sopenharmony_ci    fPipelineStateCache = sk_make_sp<PipelineStateCache>(gpu);
28cb93a386Sopenharmony_ci}
29cb93a386Sopenharmony_ci
30cb93a386Sopenharmony_ciGrVkResourceProvider::~GrVkResourceProvider() {
31cb93a386Sopenharmony_ci    SkASSERT(0 == fRenderPassArray.count());
32cb93a386Sopenharmony_ci    SkASSERT(0 == fExternalRenderPasses.count());
33cb93a386Sopenharmony_ci    SkASSERT(0 == fMSAALoadPipelines.count());
34cb93a386Sopenharmony_ci    SkASSERT(VK_NULL_HANDLE == fPipelineCache);
35cb93a386Sopenharmony_ci}
36cb93a386Sopenharmony_ci
37cb93a386Sopenharmony_ciVkPipelineCache GrVkResourceProvider::pipelineCache() {
38cb93a386Sopenharmony_ci    if (fPipelineCache == VK_NULL_HANDLE) {
39cb93a386Sopenharmony_ci        VkPipelineCacheCreateInfo createInfo;
40cb93a386Sopenharmony_ci        memset(&createInfo, 0, sizeof(VkPipelineCacheCreateInfo));
41cb93a386Sopenharmony_ci        createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
42cb93a386Sopenharmony_ci        createInfo.pNext = nullptr;
43cb93a386Sopenharmony_ci        createInfo.flags = 0;
44cb93a386Sopenharmony_ci
45cb93a386Sopenharmony_ci        auto persistentCache = fGpu->getContext()->priv().getPersistentCache();
46cb93a386Sopenharmony_ci        sk_sp<SkData> cached;
47cb93a386Sopenharmony_ci        if (persistentCache) {
48cb93a386Sopenharmony_ci            uint32_t key = GrVkGpu::kPipelineCache_PersistentCacheKeyType;
49cb93a386Sopenharmony_ci            sk_sp<SkData> keyData = SkData::MakeWithoutCopy(&key, sizeof(uint32_t));
50cb93a386Sopenharmony_ci            cached = persistentCache->load(*keyData);
51cb93a386Sopenharmony_ci        }
52cb93a386Sopenharmony_ci        bool usedCached = false;
53cb93a386Sopenharmony_ci        if (cached) {
54cb93a386Sopenharmony_ci            uint32_t* cacheHeader = (uint32_t*)cached->data();
55cb93a386Sopenharmony_ci            if (cacheHeader[1] == VK_PIPELINE_CACHE_HEADER_VERSION_ONE) {
56cb93a386Sopenharmony_ci                // For version one of the header, the total header size is 16 bytes plus
57cb93a386Sopenharmony_ci                // VK_UUID_SIZE bytes. See Section 9.6 (Pipeline Cache) in the vulkan spec to see
58cb93a386Sopenharmony_ci                // the breakdown of these bytes.
59cb93a386Sopenharmony_ci                SkASSERT(cacheHeader[0] == 16 + VK_UUID_SIZE);
60cb93a386Sopenharmony_ci                const VkPhysicalDeviceProperties& devProps = fGpu->physicalDeviceProperties();
61cb93a386Sopenharmony_ci                const uint8_t* supportedPipelineCacheUUID = devProps.pipelineCacheUUID;
62cb93a386Sopenharmony_ci                if (cacheHeader[2] == devProps.vendorID && cacheHeader[3] == devProps.deviceID &&
63cb93a386Sopenharmony_ci                    !memcmp(&cacheHeader[4], supportedPipelineCacheUUID, VK_UUID_SIZE)) {
64cb93a386Sopenharmony_ci                    createInfo.initialDataSize = cached->size();
65cb93a386Sopenharmony_ci                    createInfo.pInitialData = cached->data();
66cb93a386Sopenharmony_ci                    usedCached = true;
67cb93a386Sopenharmony_ci                }
68cb93a386Sopenharmony_ci            }
69cb93a386Sopenharmony_ci        }
70cb93a386Sopenharmony_ci        if (!usedCached) {
71cb93a386Sopenharmony_ci            createInfo.initialDataSize = 0;
72cb93a386Sopenharmony_ci            createInfo.pInitialData = nullptr;
73cb93a386Sopenharmony_ci        }
74cb93a386Sopenharmony_ci
75cb93a386Sopenharmony_ci        VkResult result;
76cb93a386Sopenharmony_ci        GR_VK_CALL_RESULT(fGpu, result, CreatePipelineCache(fGpu->device(), &createInfo, nullptr,
77cb93a386Sopenharmony_ci                                                            &fPipelineCache));
78cb93a386Sopenharmony_ci        if (VK_SUCCESS != result) {
79cb93a386Sopenharmony_ci            fPipelineCache = VK_NULL_HANDLE;
80cb93a386Sopenharmony_ci        }
81cb93a386Sopenharmony_ci    }
82cb93a386Sopenharmony_ci    return fPipelineCache;
83cb93a386Sopenharmony_ci}
84cb93a386Sopenharmony_ci
85cb93a386Sopenharmony_civoid GrVkResourceProvider::init() {
86cb93a386Sopenharmony_ci    // Init uniform descriptor objects
87cb93a386Sopenharmony_ci    GrVkDescriptorSetManager* dsm = GrVkDescriptorSetManager::CreateUniformManager(fGpu);
88cb93a386Sopenharmony_ci    fDescriptorSetManagers.emplace_back(dsm);
89cb93a386Sopenharmony_ci    SkASSERT(1 == fDescriptorSetManagers.count());
90cb93a386Sopenharmony_ci    fUniformDSHandle = GrVkDescriptorSetManager::Handle(0);
91cb93a386Sopenharmony_ci    dsm = GrVkDescriptorSetManager::CreateInputManager(fGpu);
92cb93a386Sopenharmony_ci    fDescriptorSetManagers.emplace_back(dsm);
93cb93a386Sopenharmony_ci    SkASSERT(2 == fDescriptorSetManagers.count());
94cb93a386Sopenharmony_ci    fInputDSHandle = GrVkDescriptorSetManager::Handle(1);
95cb93a386Sopenharmony_ci}
96cb93a386Sopenharmony_ci
97cb93a386Sopenharmony_cisk_sp<const GrVkPipeline> GrVkResourceProvider::makePipeline(
98cb93a386Sopenharmony_ci        const GrProgramInfo& programInfo,
99cb93a386Sopenharmony_ci        VkPipelineShaderStageCreateInfo* shaderStageInfo,
100cb93a386Sopenharmony_ci        int shaderStageCount,
101cb93a386Sopenharmony_ci        VkRenderPass compatibleRenderPass,
102cb93a386Sopenharmony_ci        VkPipelineLayout layout,
103cb93a386Sopenharmony_ci        uint32_t subpass) {
104cb93a386Sopenharmony_ci    return GrVkPipeline::Make(fGpu, programInfo, shaderStageInfo, shaderStageCount,
105cb93a386Sopenharmony_ci                              compatibleRenderPass, layout, this->pipelineCache(), subpass);
106cb93a386Sopenharmony_ci}
107cb93a386Sopenharmony_ci
108cb93a386Sopenharmony_ci// To create framebuffers, we first need to create a simple RenderPass that is
109cb93a386Sopenharmony_ci// only used for framebuffer creation. When we actually render we will create
110cb93a386Sopenharmony_ci// RenderPasses as needed that are compatible with the framebuffer.
111cb93a386Sopenharmony_ciconst GrVkRenderPass*
112cb93a386Sopenharmony_ciGrVkResourceProvider::findCompatibleRenderPass(GrVkRenderTarget* target,
113cb93a386Sopenharmony_ci                                               CompatibleRPHandle* compatibleHandle,
114cb93a386Sopenharmony_ci                                               bool withResolve,
115cb93a386Sopenharmony_ci                                               bool withStencil,
116cb93a386Sopenharmony_ci                                               SelfDependencyFlags selfDepFlags,
117cb93a386Sopenharmony_ci                                               LoadFromResolve loadFromResolve) {
118cb93a386Sopenharmony_ci    // Get attachment information from render target. This includes which attachments the render
119cb93a386Sopenharmony_ci    // target has (color, stencil) and the attachments format and sample count.
120cb93a386Sopenharmony_ci    GrVkRenderPass::AttachmentFlags attachmentFlags;
121cb93a386Sopenharmony_ci    GrVkRenderPass::AttachmentsDescriptor attachmentsDesc;
122cb93a386Sopenharmony_ci    target->getAttachmentsDescriptor(&attachmentsDesc, &attachmentFlags, withResolve, withStencil);
123cb93a386Sopenharmony_ci
124cb93a386Sopenharmony_ci    return this->findCompatibleRenderPass(&attachmentsDesc, attachmentFlags, selfDepFlags,
125cb93a386Sopenharmony_ci                                          loadFromResolve, compatibleHandle);
126cb93a386Sopenharmony_ci}
127cb93a386Sopenharmony_ci
128cb93a386Sopenharmony_ciconst GrVkRenderPass*
129cb93a386Sopenharmony_ciGrVkResourceProvider::findCompatibleRenderPass(GrVkRenderPass::AttachmentsDescriptor* desc,
130cb93a386Sopenharmony_ci                                               GrVkRenderPass::AttachmentFlags attachmentFlags,
131cb93a386Sopenharmony_ci                                               SelfDependencyFlags selfDepFlags,
132cb93a386Sopenharmony_ci                                               LoadFromResolve loadFromResolve,
133cb93a386Sopenharmony_ci                                               CompatibleRPHandle* compatibleHandle) {
134cb93a386Sopenharmony_ci    for (int i = 0; i < fRenderPassArray.count(); ++i) {
135cb93a386Sopenharmony_ci        if (fRenderPassArray[i].isCompatible(*desc, attachmentFlags, selfDepFlags,
136cb93a386Sopenharmony_ci                                             loadFromResolve)) {
137cb93a386Sopenharmony_ci            const GrVkRenderPass* renderPass = fRenderPassArray[i].getCompatibleRenderPass();
138cb93a386Sopenharmony_ci            renderPass->ref();
139cb93a386Sopenharmony_ci            if (compatibleHandle) {
140cb93a386Sopenharmony_ci                *compatibleHandle = CompatibleRPHandle(i);
141cb93a386Sopenharmony_ci            }
142cb93a386Sopenharmony_ci            return renderPass;
143cb93a386Sopenharmony_ci        }
144cb93a386Sopenharmony_ci    }
145cb93a386Sopenharmony_ci
146cb93a386Sopenharmony_ci    GrVkRenderPass* renderPass = GrVkRenderPass::CreateSimple(fGpu, desc, attachmentFlags,
147cb93a386Sopenharmony_ci                                                              selfDepFlags, loadFromResolve);
148cb93a386Sopenharmony_ci    if (!renderPass) {
149cb93a386Sopenharmony_ci        return nullptr;
150cb93a386Sopenharmony_ci    }
151cb93a386Sopenharmony_ci    fRenderPassArray.emplace_back(renderPass);
152cb93a386Sopenharmony_ci
153cb93a386Sopenharmony_ci    if (compatibleHandle) {
154cb93a386Sopenharmony_ci        *compatibleHandle = CompatibleRPHandle(fRenderPassArray.count() - 1);
155cb93a386Sopenharmony_ci    }
156cb93a386Sopenharmony_ci    return renderPass;
157cb93a386Sopenharmony_ci}
158cb93a386Sopenharmony_ci
159cb93a386Sopenharmony_ciconst GrVkRenderPass* GrVkResourceProvider::findCompatibleExternalRenderPass(
160cb93a386Sopenharmony_ci        VkRenderPass renderPass, uint32_t colorAttachmentIndex) {
161cb93a386Sopenharmony_ci    for (int i = 0; i < fExternalRenderPasses.count(); ++i) {
162cb93a386Sopenharmony_ci        if (fExternalRenderPasses[i]->isCompatibleExternalRP(renderPass)) {
163cb93a386Sopenharmony_ci            fExternalRenderPasses[i]->ref();
164cb93a386Sopenharmony_ci#ifdef SK_DEBUG
165cb93a386Sopenharmony_ci            uint32_t cachedColorIndex;
166cb93a386Sopenharmony_ci            SkASSERT(fExternalRenderPasses[i]->colorAttachmentIndex(&cachedColorIndex));
167cb93a386Sopenharmony_ci            SkASSERT(cachedColorIndex == colorAttachmentIndex);
168cb93a386Sopenharmony_ci#endif
169cb93a386Sopenharmony_ci            return fExternalRenderPasses[i];
170cb93a386Sopenharmony_ci        }
171cb93a386Sopenharmony_ci    }
172cb93a386Sopenharmony_ci
173cb93a386Sopenharmony_ci    const GrVkRenderPass* newRenderPass = new GrVkRenderPass(fGpu, renderPass,
174cb93a386Sopenharmony_ci                                                             colorAttachmentIndex);
175cb93a386Sopenharmony_ci    fExternalRenderPasses.push_back(newRenderPass);
176cb93a386Sopenharmony_ci    newRenderPass->ref();
177cb93a386Sopenharmony_ci    return newRenderPass;
178cb93a386Sopenharmony_ci}
179cb93a386Sopenharmony_ci
180cb93a386Sopenharmony_ciconst GrVkRenderPass* GrVkResourceProvider::findRenderPass(
181cb93a386Sopenharmony_ci        GrVkRenderTarget* target,
182cb93a386Sopenharmony_ci        const GrVkRenderPass::LoadStoreOps& colorOps,
183cb93a386Sopenharmony_ci        const GrVkRenderPass::LoadStoreOps& resolveOps,
184cb93a386Sopenharmony_ci        const GrVkRenderPass::LoadStoreOps& stencilOps,
185cb93a386Sopenharmony_ci        CompatibleRPHandle* compatibleHandle,
186cb93a386Sopenharmony_ci        bool withResolve,
187cb93a386Sopenharmony_ci        bool withStencil,
188cb93a386Sopenharmony_ci        SelfDependencyFlags selfDepFlags,
189cb93a386Sopenharmony_ci        LoadFromResolve loadFromResolve) {
190cb93a386Sopenharmony_ci    GrVkResourceProvider::CompatibleRPHandle tempRPHandle;
191cb93a386Sopenharmony_ci    GrVkResourceProvider::CompatibleRPHandle* pRPHandle = compatibleHandle ? compatibleHandle
192cb93a386Sopenharmony_ci                                                                           : &tempRPHandle;
193cb93a386Sopenharmony_ci    *pRPHandle = target->compatibleRenderPassHandle(withResolve, withStencil, selfDepFlags,
194cb93a386Sopenharmony_ci                                                    loadFromResolve);
195cb93a386Sopenharmony_ci    if (!pRPHandle->isValid()) {
196cb93a386Sopenharmony_ci        return nullptr;
197cb93a386Sopenharmony_ci    }
198cb93a386Sopenharmony_ci
199cb93a386Sopenharmony_ci    return this->findRenderPass(*pRPHandle, colorOps, resolveOps, stencilOps);
200cb93a386Sopenharmony_ci}
201cb93a386Sopenharmony_ci
202cb93a386Sopenharmony_ciconst GrVkRenderPass*
203cb93a386Sopenharmony_ciGrVkResourceProvider::findRenderPass(const CompatibleRPHandle& compatibleHandle,
204cb93a386Sopenharmony_ci                                     const GrVkRenderPass::LoadStoreOps& colorOps,
205cb93a386Sopenharmony_ci                                     const GrVkRenderPass::LoadStoreOps& resolveOps,
206cb93a386Sopenharmony_ci                                     const GrVkRenderPass::LoadStoreOps& stencilOps) {
207cb93a386Sopenharmony_ci    SkASSERT(compatibleHandle.isValid() && compatibleHandle.toIndex() < fRenderPassArray.count());
208cb93a386Sopenharmony_ci    CompatibleRenderPassSet& compatibleSet = fRenderPassArray[compatibleHandle.toIndex()];
209cb93a386Sopenharmony_ci    const GrVkRenderPass* renderPass = compatibleSet.getRenderPass(fGpu,
210cb93a386Sopenharmony_ci                                                                   colorOps,
211cb93a386Sopenharmony_ci                                                                   resolveOps,
212cb93a386Sopenharmony_ci                                                                   stencilOps);
213cb93a386Sopenharmony_ci    if (!renderPass) {
214cb93a386Sopenharmony_ci        return nullptr;
215cb93a386Sopenharmony_ci    }
216cb93a386Sopenharmony_ci    renderPass->ref();
217cb93a386Sopenharmony_ci    return renderPass;
218cb93a386Sopenharmony_ci}
219cb93a386Sopenharmony_ci
220cb93a386Sopenharmony_ciGrVkDescriptorPool* GrVkResourceProvider::findOrCreateCompatibleDescriptorPool(
221cb93a386Sopenharmony_ci                                                            VkDescriptorType type, uint32_t count) {
222cb93a386Sopenharmony_ci    return GrVkDescriptorPool::Create(fGpu, type, count);
223cb93a386Sopenharmony_ci}
224cb93a386Sopenharmony_ci
225cb93a386Sopenharmony_ciGrVkSampler* GrVkResourceProvider::findOrCreateCompatibleSampler(
226cb93a386Sopenharmony_ci        GrSamplerState params, const GrVkYcbcrConversionInfo& ycbcrInfo) {
227cb93a386Sopenharmony_ci    GrVkSampler* sampler = fSamplers.find(GrVkSampler::GenerateKey(params, ycbcrInfo));
228cb93a386Sopenharmony_ci    if (!sampler) {
229cb93a386Sopenharmony_ci        sampler = GrVkSampler::Create(fGpu, params, ycbcrInfo);
230cb93a386Sopenharmony_ci        if (!sampler) {
231cb93a386Sopenharmony_ci            return nullptr;
232cb93a386Sopenharmony_ci        }
233cb93a386Sopenharmony_ci        fSamplers.add(sampler);
234cb93a386Sopenharmony_ci    }
235cb93a386Sopenharmony_ci    SkASSERT(sampler);
236cb93a386Sopenharmony_ci    sampler->ref();
237cb93a386Sopenharmony_ci    return sampler;
238cb93a386Sopenharmony_ci}
239cb93a386Sopenharmony_ci
240cb93a386Sopenharmony_ciGrVkSamplerYcbcrConversion* GrVkResourceProvider::findOrCreateCompatibleSamplerYcbcrConversion(
241cb93a386Sopenharmony_ci        const GrVkYcbcrConversionInfo& ycbcrInfo) {
242cb93a386Sopenharmony_ci    GrVkSamplerYcbcrConversion* ycbcrConversion =
243cb93a386Sopenharmony_ci            fYcbcrConversions.find(GrVkSamplerYcbcrConversion::GenerateKey(ycbcrInfo));
244cb93a386Sopenharmony_ci    if (!ycbcrConversion) {
245cb93a386Sopenharmony_ci        ycbcrConversion = GrVkSamplerYcbcrConversion::Create(fGpu, ycbcrInfo);
246cb93a386Sopenharmony_ci        if (!ycbcrConversion) {
247cb93a386Sopenharmony_ci            return nullptr;
248cb93a386Sopenharmony_ci        }
249cb93a386Sopenharmony_ci        fYcbcrConversions.add(ycbcrConversion);
250cb93a386Sopenharmony_ci    }
251cb93a386Sopenharmony_ci    SkASSERT(ycbcrConversion);
252cb93a386Sopenharmony_ci    ycbcrConversion->ref();
253cb93a386Sopenharmony_ci    return ycbcrConversion;
254cb93a386Sopenharmony_ci}
255cb93a386Sopenharmony_ci
256cb93a386Sopenharmony_ciGrVkPipelineState* GrVkResourceProvider::findOrCreateCompatiblePipelineState(
257cb93a386Sopenharmony_ci        GrRenderTarget* renderTarget,
258cb93a386Sopenharmony_ci        const GrProgramInfo& programInfo,
259cb93a386Sopenharmony_ci        VkRenderPass compatibleRenderPass,
260cb93a386Sopenharmony_ci        bool overrideSubpassForResolveLoad) {
261cb93a386Sopenharmony_ci    return fPipelineStateCache->findOrCreatePipelineState(renderTarget, programInfo,
262cb93a386Sopenharmony_ci                                                          compatibleRenderPass,
263cb93a386Sopenharmony_ci                                                          overrideSubpassForResolveLoad);
264cb93a386Sopenharmony_ci}
265cb93a386Sopenharmony_ci
266cb93a386Sopenharmony_ciGrVkPipelineState* GrVkResourceProvider::findOrCreateCompatiblePipelineState(
267cb93a386Sopenharmony_ci        const GrProgramDesc& desc,
268cb93a386Sopenharmony_ci        const GrProgramInfo& programInfo,
269cb93a386Sopenharmony_ci        VkRenderPass compatibleRenderPass,
270cb93a386Sopenharmony_ci        GrThreadSafePipelineBuilder::Stats::ProgramCacheResult* stat) {
271cb93a386Sopenharmony_ci
272cb93a386Sopenharmony_ci    auto tmp =  fPipelineStateCache->findOrCreatePipelineState(desc, programInfo,
273cb93a386Sopenharmony_ci                                                               compatibleRenderPass, stat);
274cb93a386Sopenharmony_ci    if (!tmp) {
275cb93a386Sopenharmony_ci        fPipelineStateCache->stats()->incNumPreCompilationFailures();
276cb93a386Sopenharmony_ci    } else {
277cb93a386Sopenharmony_ci        fPipelineStateCache->stats()->incNumPreProgramCacheResult(*stat);
278cb93a386Sopenharmony_ci    }
279cb93a386Sopenharmony_ci
280cb93a386Sopenharmony_ci    return tmp;
281cb93a386Sopenharmony_ci}
282cb93a386Sopenharmony_ci
283cb93a386Sopenharmony_cisk_sp<const GrVkPipeline> GrVkResourceProvider::findOrCreateMSAALoadPipeline(
284cb93a386Sopenharmony_ci        const GrVkRenderPass& renderPass,
285cb93a386Sopenharmony_ci        int numSamples,
286cb93a386Sopenharmony_ci        VkPipelineShaderStageCreateInfo* shaderStageInfo,
287cb93a386Sopenharmony_ci        VkPipelineLayout pipelineLayout) {
288cb93a386Sopenharmony_ci    // Find or Create a compatible pipeline
289cb93a386Sopenharmony_ci    sk_sp<const GrVkPipeline> pipeline;
290cb93a386Sopenharmony_ci    for (int i = 0; i < fMSAALoadPipelines.count() && !pipeline; ++i) {
291cb93a386Sopenharmony_ci        if (fMSAALoadPipelines[i].fRenderPass->isCompatible(renderPass)) {
292cb93a386Sopenharmony_ci            pipeline = fMSAALoadPipelines[i].fPipeline;
293cb93a386Sopenharmony_ci        }
294cb93a386Sopenharmony_ci    }
295cb93a386Sopenharmony_ci    if (!pipeline) {
296cb93a386Sopenharmony_ci        pipeline = GrVkPipeline::Make(
297cb93a386Sopenharmony_ci                fGpu,
298cb93a386Sopenharmony_ci                /*vertexAttribs=*/GrGeometryProcessor::AttributeSet(),
299cb93a386Sopenharmony_ci                /*instanceAttribs=*/GrGeometryProcessor::AttributeSet(),
300cb93a386Sopenharmony_ci                GrPrimitiveType::kTriangleStrip,
301cb93a386Sopenharmony_ci                kTopLeft_GrSurfaceOrigin,
302cb93a386Sopenharmony_ci                GrStencilSettings(),
303cb93a386Sopenharmony_ci                numSamples,
304cb93a386Sopenharmony_ci                /*isHWantialiasState=*/false,
305cb93a386Sopenharmony_ci                GrXferProcessor::BlendInfo(),
306cb93a386Sopenharmony_ci                /*isWireframe=*/false,
307cb93a386Sopenharmony_ci                /*useConservativeRaster=*/false,
308cb93a386Sopenharmony_ci                /*subpass=*/0,
309cb93a386Sopenharmony_ci                shaderStageInfo,
310cb93a386Sopenharmony_ci                /*shaderStageCount=*/2,
311cb93a386Sopenharmony_ci                renderPass.vkRenderPass(),
312cb93a386Sopenharmony_ci                pipelineLayout,
313cb93a386Sopenharmony_ci                /*ownsLayout=*/false,
314cb93a386Sopenharmony_ci                this->pipelineCache());
315cb93a386Sopenharmony_ci        if (!pipeline) {
316cb93a386Sopenharmony_ci            return nullptr;
317cb93a386Sopenharmony_ci        }
318cb93a386Sopenharmony_ci        fMSAALoadPipelines.push_back({pipeline, &renderPass});
319cb93a386Sopenharmony_ci    }
320cb93a386Sopenharmony_ci    SkASSERT(pipeline);
321cb93a386Sopenharmony_ci    return pipeline;
322cb93a386Sopenharmony_ci}
323cb93a386Sopenharmony_ci
324cb93a386Sopenharmony_civoid GrVkResourceProvider::getZeroSamplerDescriptorSetHandle(
325cb93a386Sopenharmony_ci        GrVkDescriptorSetManager::Handle* handle) {
326cb93a386Sopenharmony_ci    SkASSERT(handle);
327cb93a386Sopenharmony_ci    for (int i = 0; i < fDescriptorSetManagers.count(); ++i) {
328cb93a386Sopenharmony_ci        if (fDescriptorSetManagers[i]->isZeroSampler()) {
329cb93a386Sopenharmony_ci            *handle = GrVkDescriptorSetManager::Handle(i);
330cb93a386Sopenharmony_ci            return;
331cb93a386Sopenharmony_ci        }
332cb93a386Sopenharmony_ci    }
333cb93a386Sopenharmony_ci
334cb93a386Sopenharmony_ci    GrVkDescriptorSetManager* dsm =
335cb93a386Sopenharmony_ci            GrVkDescriptorSetManager::CreateZeroSamplerManager(fGpu);
336cb93a386Sopenharmony_ci    fDescriptorSetManagers.emplace_back(dsm);
337cb93a386Sopenharmony_ci    *handle = GrVkDescriptorSetManager::Handle(fDescriptorSetManagers.count() - 1);
338cb93a386Sopenharmony_ci}
339cb93a386Sopenharmony_ci
340cb93a386Sopenharmony_civoid GrVkResourceProvider::getSamplerDescriptorSetHandle(VkDescriptorType type,
341cb93a386Sopenharmony_ci                                                         const GrVkUniformHandler& uniformHandler,
342cb93a386Sopenharmony_ci                                                         GrVkDescriptorSetManager::Handle* handle) {
343cb93a386Sopenharmony_ci    SkASSERT(handle);
344cb93a386Sopenharmony_ci    SkASSERT(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER == type ||
345cb93a386Sopenharmony_ci             VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER == type);
346cb93a386Sopenharmony_ci    for (int i = 0; i < fDescriptorSetManagers.count(); ++i) {
347cb93a386Sopenharmony_ci        if (fDescriptorSetManagers[i]->isCompatible(type, &uniformHandler)) {
348cb93a386Sopenharmony_ci           *handle = GrVkDescriptorSetManager::Handle(i);
349cb93a386Sopenharmony_ci           return;
350cb93a386Sopenharmony_ci        }
351cb93a386Sopenharmony_ci    }
352cb93a386Sopenharmony_ci
353cb93a386Sopenharmony_ci    GrVkDescriptorSetManager* dsm = GrVkDescriptorSetManager::CreateSamplerManager(fGpu, type,
354cb93a386Sopenharmony_ci                                                                                   uniformHandler);
355cb93a386Sopenharmony_ci    fDescriptorSetManagers.emplace_back(dsm);
356cb93a386Sopenharmony_ci    *handle = GrVkDescriptorSetManager::Handle(fDescriptorSetManagers.count() - 1);
357cb93a386Sopenharmony_ci}
358cb93a386Sopenharmony_ci
359cb93a386Sopenharmony_ciVkDescriptorSetLayout GrVkResourceProvider::getUniformDSLayout() const {
360cb93a386Sopenharmony_ci    SkASSERT(fUniformDSHandle.isValid());
361cb93a386Sopenharmony_ci    return fDescriptorSetManagers[fUniformDSHandle.toIndex()]->layout();
362cb93a386Sopenharmony_ci}
363cb93a386Sopenharmony_ci
364cb93a386Sopenharmony_ciVkDescriptorSetLayout GrVkResourceProvider::getInputDSLayout() const {
365cb93a386Sopenharmony_ci    SkASSERT(fInputDSHandle.isValid());
366cb93a386Sopenharmony_ci    return fDescriptorSetManagers[fInputDSHandle.toIndex()]->layout();
367cb93a386Sopenharmony_ci}
368cb93a386Sopenharmony_ci
369cb93a386Sopenharmony_ciVkDescriptorSetLayout GrVkResourceProvider::getSamplerDSLayout(
370cb93a386Sopenharmony_ci        const GrVkDescriptorSetManager::Handle& handle) const {
371cb93a386Sopenharmony_ci    SkASSERT(handle.isValid());
372cb93a386Sopenharmony_ci    return fDescriptorSetManagers[handle.toIndex()]->layout();
373cb93a386Sopenharmony_ci}
374cb93a386Sopenharmony_ci
375cb93a386Sopenharmony_ciconst GrVkDescriptorSet* GrVkResourceProvider::getUniformDescriptorSet() {
376cb93a386Sopenharmony_ci    SkASSERT(fUniformDSHandle.isValid());
377cb93a386Sopenharmony_ci    return fDescriptorSetManagers[fUniformDSHandle.toIndex()]->getDescriptorSet(fGpu,
378cb93a386Sopenharmony_ci                                                                                fUniformDSHandle);
379cb93a386Sopenharmony_ci}
380cb93a386Sopenharmony_ci
381cb93a386Sopenharmony_ciconst GrVkDescriptorSet* GrVkResourceProvider::getInputDescriptorSet() {
382cb93a386Sopenharmony_ci    SkASSERT(fInputDSHandle.isValid());
383cb93a386Sopenharmony_ci    return fDescriptorSetManagers[fInputDSHandle.toIndex()]->getDescriptorSet(fGpu, fInputDSHandle);
384cb93a386Sopenharmony_ci}
385cb93a386Sopenharmony_ci
386cb93a386Sopenharmony_ciconst GrVkDescriptorSet* GrVkResourceProvider::getSamplerDescriptorSet(
387cb93a386Sopenharmony_ci        const GrVkDescriptorSetManager::Handle& handle) {
388cb93a386Sopenharmony_ci    SkASSERT(handle.isValid());
389cb93a386Sopenharmony_ci    return fDescriptorSetManagers[handle.toIndex()]->getDescriptorSet(fGpu, handle);
390cb93a386Sopenharmony_ci}
391cb93a386Sopenharmony_ci
392cb93a386Sopenharmony_civoid GrVkResourceProvider::recycleDescriptorSet(const GrVkDescriptorSet* descSet,
393cb93a386Sopenharmony_ci                                                const GrVkDescriptorSetManager::Handle& handle) {
394cb93a386Sopenharmony_ci    SkASSERT(descSet);
395cb93a386Sopenharmony_ci    SkASSERT(handle.isValid());
396cb93a386Sopenharmony_ci    int managerIdx = handle.toIndex();
397cb93a386Sopenharmony_ci    SkASSERT(managerIdx < fDescriptorSetManagers.count());
398cb93a386Sopenharmony_ci    fDescriptorSetManagers[managerIdx]->recycleDescriptorSet(descSet);
399cb93a386Sopenharmony_ci}
400cb93a386Sopenharmony_ci
401cb93a386Sopenharmony_ciGrVkCommandPool* GrVkResourceProvider::findOrCreateCommandPool() {
402cb93a386Sopenharmony_ci    SkAutoMutexExclusive lock(fBackgroundMutex);
403cb93a386Sopenharmony_ci    GrVkCommandPool* result;
404cb93a386Sopenharmony_ci    if (fAvailableCommandPools.count()) {
405cb93a386Sopenharmony_ci        result = fAvailableCommandPools.back();
406cb93a386Sopenharmony_ci        fAvailableCommandPools.pop_back();
407cb93a386Sopenharmony_ci    } else {
408cb93a386Sopenharmony_ci        result = GrVkCommandPool::Create(fGpu);
409cb93a386Sopenharmony_ci        if (!result) {
410cb93a386Sopenharmony_ci            return nullptr;
411cb93a386Sopenharmony_ci        }
412cb93a386Sopenharmony_ci    }
413cb93a386Sopenharmony_ci    SkASSERT(result->unique());
414cb93a386Sopenharmony_ci    SkDEBUGCODE(
415cb93a386Sopenharmony_ci        for (const GrVkCommandPool* pool : fActiveCommandPools) {
416cb93a386Sopenharmony_ci            SkASSERT(pool != result);
417cb93a386Sopenharmony_ci        }
418cb93a386Sopenharmony_ci        for (const GrVkCommandPool* pool : fAvailableCommandPools) {
419cb93a386Sopenharmony_ci            SkASSERT(pool != result);
420cb93a386Sopenharmony_ci        }
421cb93a386Sopenharmony_ci    )
422cb93a386Sopenharmony_ci    fActiveCommandPools.push_back(result);
423cb93a386Sopenharmony_ci    result->ref();
424cb93a386Sopenharmony_ci    return result;
425cb93a386Sopenharmony_ci}
426cb93a386Sopenharmony_ci
427cb93a386Sopenharmony_civoid GrVkResourceProvider::checkCommandBuffers() {
428cb93a386Sopenharmony_ci    // When resetting a command buffer it can trigger client provided procs (e.g. release or
429cb93a386Sopenharmony_ci    // finished) to be called. During these calls the client could trigger us to abandon the vk
430cb93a386Sopenharmony_ci    // context, e.g. if we are in a DEVICE_LOST state. When we abandon the vk context we will
431cb93a386Sopenharmony_ci    // unref all the fActiveCommandPools and reset the array. Since this can happen in the middle
432cb93a386Sopenharmony_ci    // of the loop here, we need to additionally check that fActiveCommandPools still has pools on
433cb93a386Sopenharmony_ci    // each iteration.
434cb93a386Sopenharmony_ci    //
435cb93a386Sopenharmony_ci    // TODO: We really need to have a more robust way to protect us from client proc calls that
436cb93a386Sopenharmony_ci    // happen in the middle of us doing work. This may be just one of many potential pitfalls that
437cb93a386Sopenharmony_ci    // could happen from the client triggering GrDirectContext changes during a proc call.
438cb93a386Sopenharmony_ci    for (int i = fActiveCommandPools.count() - 1; fActiveCommandPools.count() && i >= 0; --i) {
439cb93a386Sopenharmony_ci        GrVkCommandPool* pool = fActiveCommandPools[i];
440cb93a386Sopenharmony_ci        if (!pool->isOpen()) {
441cb93a386Sopenharmony_ci            GrVkPrimaryCommandBuffer* buffer = pool->getPrimaryCommandBuffer();
442cb93a386Sopenharmony_ci            if (buffer->finished(fGpu)) {
443cb93a386Sopenharmony_ci                fActiveCommandPools.removeShuffle(i);
444cb93a386Sopenharmony_ci                // This passes ownership of the pool to the backgroundReset call. The pool should
445cb93a386Sopenharmony_ci                // not be used again from this function.
446cb93a386Sopenharmony_ci                // TODO: We should see if we can use sk_sps here to make this more explicit.
447cb93a386Sopenharmony_ci                this->backgroundReset(pool);
448cb93a386Sopenharmony_ci            }
449cb93a386Sopenharmony_ci        }
450cb93a386Sopenharmony_ci    }
451cb93a386Sopenharmony_ci}
452cb93a386Sopenharmony_ci
453cb93a386Sopenharmony_civoid GrVkResourceProvider::forceSyncAllCommandBuffers() {
454cb93a386Sopenharmony_ci    for (int i = fActiveCommandPools.count() - 1; fActiveCommandPools.count() && i >= 0; --i) {
455cb93a386Sopenharmony_ci        GrVkCommandPool* pool = fActiveCommandPools[i];
456cb93a386Sopenharmony_ci        if (!pool->isOpen()) {
457cb93a386Sopenharmony_ci            GrVkPrimaryCommandBuffer* buffer = pool->getPrimaryCommandBuffer();
458cb93a386Sopenharmony_ci            buffer->forceSync(fGpu);
459cb93a386Sopenharmony_ci        }
460cb93a386Sopenharmony_ci    }
461cb93a386Sopenharmony_ci}
462cb93a386Sopenharmony_ci
463cb93a386Sopenharmony_civoid GrVkResourceProvider::addFinishedProcToActiveCommandBuffers(
464cb93a386Sopenharmony_ci        sk_sp<GrRefCntedCallback> finishedCallback) {
465cb93a386Sopenharmony_ci    for (int i = 0; i < fActiveCommandPools.count(); ++i) {
466cb93a386Sopenharmony_ci        GrVkCommandPool* pool = fActiveCommandPools[i];
467cb93a386Sopenharmony_ci        GrVkPrimaryCommandBuffer* buffer = pool->getPrimaryCommandBuffer();
468cb93a386Sopenharmony_ci        buffer->addFinishedProc(finishedCallback);
469cb93a386Sopenharmony_ci    }
470cb93a386Sopenharmony_ci}
471cb93a386Sopenharmony_ci
472cb93a386Sopenharmony_civoid GrVkResourceProvider::destroyResources() {
473cb93a386Sopenharmony_ci    SkTaskGroup* taskGroup = fGpu->getContext()->priv().getTaskGroup();
474cb93a386Sopenharmony_ci    if (taskGroup) {
475cb93a386Sopenharmony_ci        taskGroup->wait();
476cb93a386Sopenharmony_ci    }
477cb93a386Sopenharmony_ci
478cb93a386Sopenharmony_ci    // Release all msaa load pipelines
479cb93a386Sopenharmony_ci    fMSAALoadPipelines.reset();
480cb93a386Sopenharmony_ci
481cb93a386Sopenharmony_ci    // loop over all render pass sets to make sure we destroy all the internal VkRenderPasses
482cb93a386Sopenharmony_ci    for (int i = 0; i < fRenderPassArray.count(); ++i) {
483cb93a386Sopenharmony_ci        fRenderPassArray[i].releaseResources();
484cb93a386Sopenharmony_ci    }
485cb93a386Sopenharmony_ci    fRenderPassArray.reset();
486cb93a386Sopenharmony_ci
487cb93a386Sopenharmony_ci    for (int i = 0; i < fExternalRenderPasses.count(); ++i) {
488cb93a386Sopenharmony_ci        fExternalRenderPasses[i]->unref();
489cb93a386Sopenharmony_ci    }
490cb93a386Sopenharmony_ci    fExternalRenderPasses.reset();
491cb93a386Sopenharmony_ci
492cb93a386Sopenharmony_ci    // Iterate through all store GrVkSamplers and unref them before resetting the hash table.
493cb93a386Sopenharmony_ci    fSamplers.foreach([&](auto* elt) { elt->unref(); });
494cb93a386Sopenharmony_ci    fSamplers.reset();
495cb93a386Sopenharmony_ci
496cb93a386Sopenharmony_ci    fYcbcrConversions.foreach([&](auto* elt) { elt->unref(); });
497cb93a386Sopenharmony_ci    fYcbcrConversions.reset();
498cb93a386Sopenharmony_ci
499cb93a386Sopenharmony_ci    fPipelineStateCache->release();
500cb93a386Sopenharmony_ci
501cb93a386Sopenharmony_ci    GR_VK_CALL(fGpu->vkInterface(), DestroyPipelineCache(fGpu->device(), fPipelineCache, nullptr));
502cb93a386Sopenharmony_ci    fPipelineCache = VK_NULL_HANDLE;
503cb93a386Sopenharmony_ci
504cb93a386Sopenharmony_ci    for (GrVkCommandPool* pool : fActiveCommandPools) {
505cb93a386Sopenharmony_ci        SkASSERT(pool->unique());
506cb93a386Sopenharmony_ci        pool->unref();
507cb93a386Sopenharmony_ci    }
508cb93a386Sopenharmony_ci    fActiveCommandPools.reset();
509cb93a386Sopenharmony_ci
510cb93a386Sopenharmony_ci    {
511cb93a386Sopenharmony_ci        SkAutoMutexExclusive lock(fBackgroundMutex);
512cb93a386Sopenharmony_ci        for (GrVkCommandPool* pool : fAvailableCommandPools) {
513cb93a386Sopenharmony_ci            SkASSERT(pool->unique());
514cb93a386Sopenharmony_ci            pool->unref();
515cb93a386Sopenharmony_ci        }
516cb93a386Sopenharmony_ci        fAvailableCommandPools.reset();
517cb93a386Sopenharmony_ci    }
518cb93a386Sopenharmony_ci
519cb93a386Sopenharmony_ci    // We must release/destroy all command buffers and pipeline states before releasing the
520cb93a386Sopenharmony_ci    // GrVkDescriptorSetManagers. Additionally, we must release all uniform buffers since they hold
521cb93a386Sopenharmony_ci    // refs to GrVkDescriptorSets.
522cb93a386Sopenharmony_ci    for (int i = 0; i < fDescriptorSetManagers.count(); ++i) {
523cb93a386Sopenharmony_ci        fDescriptorSetManagers[i]->release(fGpu);
524cb93a386Sopenharmony_ci    }
525cb93a386Sopenharmony_ci    fDescriptorSetManagers.reset();
526cb93a386Sopenharmony_ci
527cb93a386Sopenharmony_ci}
528cb93a386Sopenharmony_ci
529cb93a386Sopenharmony_civoid GrVkResourceProvider::releaseUnlockedBackendObjects() {
530cb93a386Sopenharmony_ci    SkAutoMutexExclusive lock(fBackgroundMutex);
531cb93a386Sopenharmony_ci    for (GrVkCommandPool* pool : fAvailableCommandPools) {
532cb93a386Sopenharmony_ci        SkASSERT(pool->unique());
533cb93a386Sopenharmony_ci        pool->unref();
534cb93a386Sopenharmony_ci    }
535cb93a386Sopenharmony_ci    fAvailableCommandPools.reset();
536cb93a386Sopenharmony_ci}
537cb93a386Sopenharmony_ci
538cb93a386Sopenharmony_civoid GrVkResourceProvider::backgroundReset(GrVkCommandPool* pool) {
539cb93a386Sopenharmony_ci    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
540cb93a386Sopenharmony_ci    SkASSERT(pool->unique());
541cb93a386Sopenharmony_ci    pool->releaseResources();
542cb93a386Sopenharmony_ci    // After releasing resources we may have called a client callback proc which may have
543cb93a386Sopenharmony_ci    // disconnected the GrVkGpu. In that case we do not want to push the pool back onto the cache,
544cb93a386Sopenharmony_ci    // but instead just drop the pool.
545cb93a386Sopenharmony_ci    if (fGpu->disconnected()) {
546cb93a386Sopenharmony_ci        pool->unref();
547cb93a386Sopenharmony_ci        return;
548cb93a386Sopenharmony_ci    }
549cb93a386Sopenharmony_ci    SkTaskGroup* taskGroup = fGpu->getContext()->priv().getTaskGroup();
550cb93a386Sopenharmony_ci    if (taskGroup) {
551cb93a386Sopenharmony_ci        taskGroup->add([this, pool]() {
552cb93a386Sopenharmony_ci            this->reset(pool);
553cb93a386Sopenharmony_ci        });
554cb93a386Sopenharmony_ci    } else {
555cb93a386Sopenharmony_ci        this->reset(pool);
556cb93a386Sopenharmony_ci    }
557cb93a386Sopenharmony_ci}
558cb93a386Sopenharmony_ci
559cb93a386Sopenharmony_civoid GrVkResourceProvider::reset(GrVkCommandPool* pool) {
560cb93a386Sopenharmony_ci    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
561cb93a386Sopenharmony_ci    SkASSERT(pool->unique());
562cb93a386Sopenharmony_ci    pool->reset(fGpu);
563cb93a386Sopenharmony_ci    SkAutoMutexExclusive lock(fBackgroundMutex);
564cb93a386Sopenharmony_ci    fAvailableCommandPools.push_back(pool);
565cb93a386Sopenharmony_ci}
566cb93a386Sopenharmony_ci
567cb93a386Sopenharmony_civoid GrVkResourceProvider::storePipelineCacheData() {
568cb93a386Sopenharmony_ci    if (this->pipelineCache() == VK_NULL_HANDLE) {
569cb93a386Sopenharmony_ci        return;
570cb93a386Sopenharmony_ci    }
571cb93a386Sopenharmony_ci    size_t dataSize = 0;
572cb93a386Sopenharmony_ci    VkResult result;
573cb93a386Sopenharmony_ci    GR_VK_CALL_RESULT(fGpu, result, GetPipelineCacheData(fGpu->device(), this->pipelineCache(),
574cb93a386Sopenharmony_ci                                                         &dataSize, nullptr));
575cb93a386Sopenharmony_ci    if (result != VK_SUCCESS) {
576cb93a386Sopenharmony_ci        return;
577cb93a386Sopenharmony_ci    }
578cb93a386Sopenharmony_ci    // store VkPipelineCache when cache size update
579cb93a386Sopenharmony_ci    if (dataSize == fPipelineCacheSize) {
580cb93a386Sopenharmony_ci        return;
581cb93a386Sopenharmony_ci    }
582cb93a386Sopenharmony_ci    std::unique_ptr<uint8_t[]> data(new uint8_t[dataSize]);
583cb93a386Sopenharmony_ci
584cb93a386Sopenharmony_ci    GR_VK_CALL_RESULT(fGpu, result, GetPipelineCacheData(fGpu->device(), this->pipelineCache(),
585cb93a386Sopenharmony_ci                                                         &dataSize, (void*)data.get()));
586cb93a386Sopenharmony_ci    if (result != VK_SUCCESS) {
587cb93a386Sopenharmony_ci        return;
588cb93a386Sopenharmony_ci    }
589cb93a386Sopenharmony_ci    fPipelineCacheSize = dataSize;
590cb93a386Sopenharmony_ci    uint32_t key = GrVkGpu::kPipelineCache_PersistentCacheKeyType;
591cb93a386Sopenharmony_ci    sk_sp<SkData> keyData = SkData::MakeWithoutCopy(&key, sizeof(uint32_t));
592cb93a386Sopenharmony_ci
593cb93a386Sopenharmony_ci    SkDebugf("store vkPipelineCache, data size:%zu", fPipelineCacheSize);
594cb93a386Sopenharmony_ci    fGpu->getContext()->priv().getPersistentCache()->store(
595cb93a386Sopenharmony_ci            *keyData, *SkData::MakeWithoutCopy(data.get(), dataSize), SkString("VkPipelineCache"));
596cb93a386Sopenharmony_ci}
597cb93a386Sopenharmony_ci
598cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////////
599cb93a386Sopenharmony_ci
600cb93a386Sopenharmony_ciGrVkResourceProvider::CompatibleRenderPassSet::CompatibleRenderPassSet(GrVkRenderPass* renderPass)
601cb93a386Sopenharmony_ci        : fLastReturnedIndex(0) {
602cb93a386Sopenharmony_ci    renderPass->ref();
603cb93a386Sopenharmony_ci    fRenderPasses.push_back(renderPass);
604cb93a386Sopenharmony_ci}
605cb93a386Sopenharmony_ci
606cb93a386Sopenharmony_cibool GrVkResourceProvider::CompatibleRenderPassSet::isCompatible(
607cb93a386Sopenharmony_ci        const GrVkRenderPass::AttachmentsDescriptor& attachmentsDescriptor,
608cb93a386Sopenharmony_ci        GrVkRenderPass::AttachmentFlags attachmentFlags,
609cb93a386Sopenharmony_ci        SelfDependencyFlags selfDepFlags,
610cb93a386Sopenharmony_ci        LoadFromResolve loadFromResolve) const {
611cb93a386Sopenharmony_ci    // The first GrVkRenderpass should always exists since we create the basic load store
612cb93a386Sopenharmony_ci    // render pass on create
613cb93a386Sopenharmony_ci    SkASSERT(fRenderPasses[0]);
614cb93a386Sopenharmony_ci    return fRenderPasses[0]->isCompatible(attachmentsDescriptor, attachmentFlags, selfDepFlags,
615cb93a386Sopenharmony_ci                                          loadFromResolve);
616cb93a386Sopenharmony_ci}
617cb93a386Sopenharmony_ci
618cb93a386Sopenharmony_ciGrVkRenderPass* GrVkResourceProvider::CompatibleRenderPassSet::getRenderPass(
619cb93a386Sopenharmony_ci        GrVkGpu* gpu,
620cb93a386Sopenharmony_ci        const GrVkRenderPass::LoadStoreOps& colorOps,
621cb93a386Sopenharmony_ci        const GrVkRenderPass::LoadStoreOps& resolveOps,
622cb93a386Sopenharmony_ci        const GrVkRenderPass::LoadStoreOps& stencilOps) {
623cb93a386Sopenharmony_ci    for (int i = 0; i < fRenderPasses.count(); ++i) {
624cb93a386Sopenharmony_ci        int idx = (i + fLastReturnedIndex) % fRenderPasses.count();
625cb93a386Sopenharmony_ci        if (fRenderPasses[idx]->equalLoadStoreOps(colorOps, resolveOps, stencilOps)) {
626cb93a386Sopenharmony_ci            fLastReturnedIndex = idx;
627cb93a386Sopenharmony_ci            return fRenderPasses[idx];
628cb93a386Sopenharmony_ci        }
629cb93a386Sopenharmony_ci    }
630cb93a386Sopenharmony_ci    GrVkRenderPass* renderPass = GrVkRenderPass::Create(gpu, *this->getCompatibleRenderPass(),
631cb93a386Sopenharmony_ci                                                        colorOps, resolveOps, stencilOps);
632cb93a386Sopenharmony_ci    if (!renderPass) {
633cb93a386Sopenharmony_ci        return nullptr;
634cb93a386Sopenharmony_ci    }
635cb93a386Sopenharmony_ci    fRenderPasses.push_back(renderPass);
636cb93a386Sopenharmony_ci    fLastReturnedIndex = fRenderPasses.count() - 1;
637cb93a386Sopenharmony_ci    return renderPass;
638cb93a386Sopenharmony_ci}
639cb93a386Sopenharmony_ci
640cb93a386Sopenharmony_civoid GrVkResourceProvider::CompatibleRenderPassSet::releaseResources() {
641cb93a386Sopenharmony_ci    for (int i = 0; i < fRenderPasses.count(); ++i) {
642cb93a386Sopenharmony_ci        if (fRenderPasses[i]) {
643cb93a386Sopenharmony_ci            fRenderPasses[i]->unref();
644cb93a386Sopenharmony_ci            fRenderPasses[i] = nullptr;
645cb93a386Sopenharmony_ci        }
646cb93a386Sopenharmony_ci    }
647cb93a386Sopenharmony_ci}
648cb93a386Sopenharmony_ci
649