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