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/GrVkOpsRenderPass.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/core/SkDrawable.h" 11cb93a386Sopenharmony_ci#include "include/core/SkRect.h" 12cb93a386Sopenharmony_ci#include "include/gpu/GrBackendDrawableInfo.h" 13cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h" 14cb93a386Sopenharmony_ci#include "src/core/SkTraceEvent.h" 15cb93a386Sopenharmony_ci#include "src/gpu/GrBackendUtils.h" 16cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h" 17cb93a386Sopenharmony_ci#include "src/gpu/GrOpFlushState.h" 18cb93a386Sopenharmony_ci#include "src/gpu/GrPipeline.h" 19cb93a386Sopenharmony_ci#include "src/gpu/GrRenderTarget.h" 20cb93a386Sopenharmony_ci#include "src/gpu/effects/GrTextureEffect.h" 21cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkBuffer.h" 22cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkCommandBuffer.h" 23cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkCommandPool.h" 24cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkFramebuffer.h" 25cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkGpu.h" 26cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkImage.h" 27cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkImageView.h" 28cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkPipeline.h" 29cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkRenderPass.h" 30cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkRenderTarget.h" 31cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkResourceProvider.h" 32cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkSemaphore.h" 33cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkTexture.h" 34cb93a386Sopenharmony_ci 35cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////// 36cb93a386Sopenharmony_ci 37cb93a386Sopenharmony_civoid get_vk_load_store_ops(GrLoadOp loadOpIn, GrStoreOp storeOpIn, 38cb93a386Sopenharmony_ci VkAttachmentLoadOp* loadOp, VkAttachmentStoreOp* storeOp) { 39cb93a386Sopenharmony_ci switch (loadOpIn) { 40cb93a386Sopenharmony_ci case GrLoadOp::kLoad: 41cb93a386Sopenharmony_ci *loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; 42cb93a386Sopenharmony_ci break; 43cb93a386Sopenharmony_ci case GrLoadOp::kClear: 44cb93a386Sopenharmony_ci *loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; 45cb93a386Sopenharmony_ci break; 46cb93a386Sopenharmony_ci case GrLoadOp::kDiscard: 47cb93a386Sopenharmony_ci *loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; 48cb93a386Sopenharmony_ci break; 49cb93a386Sopenharmony_ci default: 50cb93a386Sopenharmony_ci SK_ABORT("Invalid LoadOp"); 51cb93a386Sopenharmony_ci *loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; 52cb93a386Sopenharmony_ci } 53cb93a386Sopenharmony_ci 54cb93a386Sopenharmony_ci switch (storeOpIn) { 55cb93a386Sopenharmony_ci case GrStoreOp::kStore: 56cb93a386Sopenharmony_ci *storeOp = VK_ATTACHMENT_STORE_OP_STORE; 57cb93a386Sopenharmony_ci break; 58cb93a386Sopenharmony_ci case GrStoreOp::kDiscard: 59cb93a386Sopenharmony_ci *storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; 60cb93a386Sopenharmony_ci break; 61cb93a386Sopenharmony_ci default: 62cb93a386Sopenharmony_ci SK_ABORT("Invalid StoreOp"); 63cb93a386Sopenharmony_ci *storeOp = VK_ATTACHMENT_STORE_OP_STORE; 64cb93a386Sopenharmony_ci } 65cb93a386Sopenharmony_ci} 66cb93a386Sopenharmony_ci 67cb93a386Sopenharmony_ciGrVkOpsRenderPass::GrVkOpsRenderPass(GrVkGpu* gpu) : fGpu(gpu) {} 68cb93a386Sopenharmony_ci 69cb93a386Sopenharmony_civoid GrVkOpsRenderPass::setAttachmentLayouts(LoadFromResolve loadFromResolve) { 70cb93a386Sopenharmony_ci bool withStencil = fCurrentRenderPass->hasStencilAttachment(); 71cb93a386Sopenharmony_ci bool withResolve = fCurrentRenderPass->hasResolveAttachment(); 72cb93a386Sopenharmony_ci 73cb93a386Sopenharmony_ci if (fSelfDependencyFlags == SelfDependencyFlags::kForInputAttachment) { 74cb93a386Sopenharmony_ci // We need to use the GENERAL layout in this case since we'll be using texture barriers 75cb93a386Sopenharmony_ci // with an input attachment. 76cb93a386Sopenharmony_ci VkAccessFlags dstAccess = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT | 77cb93a386Sopenharmony_ci VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | 78cb93a386Sopenharmony_ci VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 79cb93a386Sopenharmony_ci VkPipelineStageFlags dstStages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | 80cb93a386Sopenharmony_ci VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 81cb93a386Sopenharmony_ci fFramebuffer->colorAttachment()->setImageLayout( 82cb93a386Sopenharmony_ci fGpu, VK_IMAGE_LAYOUT_GENERAL, dstAccess, dstStages, false); 83cb93a386Sopenharmony_ci } else { 84cb93a386Sopenharmony_ci // Change layout of our render target so it can be used as the color attachment. 85cb93a386Sopenharmony_ci // TODO: If we know that we will never be blending or loading the attachment we could drop 86cb93a386Sopenharmony_ci // the VK_ACCESS_COLOR_ATTACHMENT_READ_BIT. 87cb93a386Sopenharmony_ci fFramebuffer->colorAttachment()->setImageLayout( 88cb93a386Sopenharmony_ci fGpu, 89cb93a386Sopenharmony_ci VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 90cb93a386Sopenharmony_ci VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 91cb93a386Sopenharmony_ci VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 92cb93a386Sopenharmony_ci false); 93cb93a386Sopenharmony_ci } 94cb93a386Sopenharmony_ci 95cb93a386Sopenharmony_ci if (withResolve) { 96cb93a386Sopenharmony_ci GrVkImage* resolveAttachment = fFramebuffer->resolveAttachment(); 97cb93a386Sopenharmony_ci SkASSERT(resolveAttachment); 98cb93a386Sopenharmony_ci if (loadFromResolve == LoadFromResolve::kLoad) { 99cb93a386Sopenharmony_ci resolveAttachment->setImageLayout(fGpu, 100cb93a386Sopenharmony_ci VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 101cb93a386Sopenharmony_ci VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, 102cb93a386Sopenharmony_ci VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 103cb93a386Sopenharmony_ci false); 104cb93a386Sopenharmony_ci } else { 105cb93a386Sopenharmony_ci resolveAttachment->setImageLayout( 106cb93a386Sopenharmony_ci fGpu, 107cb93a386Sopenharmony_ci VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 108cb93a386Sopenharmony_ci VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 109cb93a386Sopenharmony_ci VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 110cb93a386Sopenharmony_ci false); 111cb93a386Sopenharmony_ci } 112cb93a386Sopenharmony_ci } 113cb93a386Sopenharmony_ci 114cb93a386Sopenharmony_ci // If we are using a stencil attachment we also need to update its layout 115cb93a386Sopenharmony_ci if (withStencil) { 116cb93a386Sopenharmony_ci auto* vkStencil = fFramebuffer->stencilAttachment(); 117cb93a386Sopenharmony_ci SkASSERT(vkStencil); 118cb93a386Sopenharmony_ci 119cb93a386Sopenharmony_ci // We need the write and read access bits since we may load and store the stencil. 120cb93a386Sopenharmony_ci // The initial load happens in the VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT so we 121cb93a386Sopenharmony_ci // wait there. 122cb93a386Sopenharmony_ci vkStencil->setImageLayout(fGpu, 123cb93a386Sopenharmony_ci VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 124cb93a386Sopenharmony_ci VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | 125cb93a386Sopenharmony_ci VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, 126cb93a386Sopenharmony_ci VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, 127cb93a386Sopenharmony_ci false); 128cb93a386Sopenharmony_ci } 129cb93a386Sopenharmony_ci} 130cb93a386Sopenharmony_ci 131cb93a386Sopenharmony_ci// The RenderArea bounds we pass into BeginRenderPass must have a start x value that is a multiple 132cb93a386Sopenharmony_ci// of the granularity. The width must also be a multiple of the granularity or eaqual to the width 133cb93a386Sopenharmony_ci// the the entire attachment. Similar requirements for the y and height components. 134cb93a386Sopenharmony_civoid adjust_bounds_to_granularity(SkIRect* dstBounds, 135cb93a386Sopenharmony_ci const SkIRect& srcBounds, 136cb93a386Sopenharmony_ci const VkExtent2D& granularity, 137cb93a386Sopenharmony_ci int maxWidth, 138cb93a386Sopenharmony_ci int maxHeight) { 139cb93a386Sopenharmony_ci // Adjust Width 140cb93a386Sopenharmony_ci if ((0 != granularity.width && 1 != granularity.width)) { 141cb93a386Sopenharmony_ci // Start with the right side of rect so we know if we end up going pass the maxWidth. 142cb93a386Sopenharmony_ci int rightAdj = srcBounds.fRight % granularity.width; 143cb93a386Sopenharmony_ci if (rightAdj != 0) { 144cb93a386Sopenharmony_ci rightAdj = granularity.width - rightAdj; 145cb93a386Sopenharmony_ci } 146cb93a386Sopenharmony_ci dstBounds->fRight = srcBounds.fRight + rightAdj; 147cb93a386Sopenharmony_ci if (dstBounds->fRight > maxWidth) { 148cb93a386Sopenharmony_ci dstBounds->fRight = maxWidth; 149cb93a386Sopenharmony_ci dstBounds->fLeft = 0; 150cb93a386Sopenharmony_ci } else { 151cb93a386Sopenharmony_ci dstBounds->fLeft = srcBounds.fLeft - srcBounds.fLeft % granularity.width; 152cb93a386Sopenharmony_ci } 153cb93a386Sopenharmony_ci } else { 154cb93a386Sopenharmony_ci dstBounds->fLeft = srcBounds.fLeft; 155cb93a386Sopenharmony_ci dstBounds->fRight = srcBounds.fRight; 156cb93a386Sopenharmony_ci } 157cb93a386Sopenharmony_ci 158cb93a386Sopenharmony_ci // Adjust height 159cb93a386Sopenharmony_ci if ((0 != granularity.height && 1 != granularity.height)) { 160cb93a386Sopenharmony_ci // Start with the bottom side of rect so we know if we end up going pass the maxHeight. 161cb93a386Sopenharmony_ci int bottomAdj = srcBounds.fBottom % granularity.height; 162cb93a386Sopenharmony_ci if (bottomAdj != 0) { 163cb93a386Sopenharmony_ci bottomAdj = granularity.height - bottomAdj; 164cb93a386Sopenharmony_ci } 165cb93a386Sopenharmony_ci dstBounds->fBottom = srcBounds.fBottom + bottomAdj; 166cb93a386Sopenharmony_ci if (dstBounds->fBottom > maxHeight) { 167cb93a386Sopenharmony_ci dstBounds->fBottom = maxHeight; 168cb93a386Sopenharmony_ci dstBounds->fTop = 0; 169cb93a386Sopenharmony_ci } else { 170cb93a386Sopenharmony_ci dstBounds->fTop = srcBounds.fTop - srcBounds.fTop % granularity.height; 171cb93a386Sopenharmony_ci } 172cb93a386Sopenharmony_ci } else { 173cb93a386Sopenharmony_ci dstBounds->fTop = srcBounds.fTop; 174cb93a386Sopenharmony_ci dstBounds->fBottom = srcBounds.fBottom; 175cb93a386Sopenharmony_ci } 176cb93a386Sopenharmony_ci} 177cb93a386Sopenharmony_ci 178cb93a386Sopenharmony_cibool GrVkOpsRenderPass::beginRenderPass(const VkClearValue& clearColor, 179cb93a386Sopenharmony_ci LoadFromResolve loadFromResolve) { 180cb93a386Sopenharmony_ci this->setAttachmentLayouts(loadFromResolve); 181cb93a386Sopenharmony_ci 182cb93a386Sopenharmony_ci bool firstSubpassUsesSecondaryCB = 183cb93a386Sopenharmony_ci loadFromResolve != LoadFromResolve::kLoad && SkToBool(fCurrentSecondaryCommandBuffer); 184cb93a386Sopenharmony_ci 185cb93a386Sopenharmony_ci bool useFullBounds = fCurrentRenderPass->hasResolveAttachment() && 186cb93a386Sopenharmony_ci fGpu->vkCaps().mustLoadFullImageWithDiscardableMSAA(); 187cb93a386Sopenharmony_ci 188cb93a386Sopenharmony_ci auto dimensions = fFramebuffer->colorAttachment()->dimensions(); 189cb93a386Sopenharmony_ci 190cb93a386Sopenharmony_ci auto nativeBounds = GrNativeRect::MakeIRectRelativeTo( 191cb93a386Sopenharmony_ci fOrigin, 192cb93a386Sopenharmony_ci dimensions.height(), useFullBounds ? SkIRect::MakeSize(dimensions) : fBounds); 193cb93a386Sopenharmony_ci 194cb93a386Sopenharmony_ci // The bounds we use for the render pass should be of the granularity supported 195cb93a386Sopenharmony_ci // by the device. 196cb93a386Sopenharmony_ci const VkExtent2D& granularity = fCurrentRenderPass->granularity(); 197cb93a386Sopenharmony_ci SkIRect adjustedBounds; 198cb93a386Sopenharmony_ci if ((0 != granularity.width && 1 != granularity.width) || 199cb93a386Sopenharmony_ci (0 != granularity.height && 1 != granularity.height)) { 200cb93a386Sopenharmony_ci adjust_bounds_to_granularity(&adjustedBounds, 201cb93a386Sopenharmony_ci nativeBounds, 202cb93a386Sopenharmony_ci granularity, 203cb93a386Sopenharmony_ci dimensions.width(), 204cb93a386Sopenharmony_ci dimensions.height()); 205cb93a386Sopenharmony_ci } else { 206cb93a386Sopenharmony_ci adjustedBounds = nativeBounds; 207cb93a386Sopenharmony_ci } 208cb93a386Sopenharmony_ci 209cb93a386Sopenharmony_ci if (!fGpu->beginRenderPass(fCurrentRenderPass, fFramebuffer, &clearColor, fRenderTarget, 210cb93a386Sopenharmony_ci adjustedBounds, firstSubpassUsesSecondaryCB)) { 211cb93a386Sopenharmony_ci if (fCurrentSecondaryCommandBuffer) { 212cb93a386Sopenharmony_ci fCurrentSecondaryCommandBuffer->end(fGpu); 213cb93a386Sopenharmony_ci } 214cb93a386Sopenharmony_ci fCurrentRenderPass = nullptr; 215cb93a386Sopenharmony_ci return false; 216cb93a386Sopenharmony_ci } 217cb93a386Sopenharmony_ci 218cb93a386Sopenharmony_ci if (loadFromResolve == LoadFromResolve::kLoad) { 219cb93a386Sopenharmony_ci this->loadResolveIntoMSAA(adjustedBounds); 220cb93a386Sopenharmony_ci } 221cb93a386Sopenharmony_ci 222cb93a386Sopenharmony_ci return true; 223cb93a386Sopenharmony_ci} 224cb93a386Sopenharmony_ci 225cb93a386Sopenharmony_cibool GrVkOpsRenderPass::init(const GrOpsRenderPass::LoadAndStoreInfo& colorInfo, 226cb93a386Sopenharmony_ci const GrOpsRenderPass::LoadAndStoreInfo& resolveInfo, 227cb93a386Sopenharmony_ci const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo) { 228cb93a386Sopenharmony_ci VkAttachmentLoadOp loadOp; 229cb93a386Sopenharmony_ci VkAttachmentStoreOp storeOp; 230cb93a386Sopenharmony_ci get_vk_load_store_ops(colorInfo.fLoadOp, colorInfo.fStoreOp, &loadOp, &storeOp); 231cb93a386Sopenharmony_ci GrVkRenderPass::LoadStoreOps vkColorOps(loadOp, storeOp); 232cb93a386Sopenharmony_ci 233cb93a386Sopenharmony_ci get_vk_load_store_ops(resolveInfo.fLoadOp, resolveInfo.fStoreOp, &loadOp, &storeOp); 234cb93a386Sopenharmony_ci GrVkRenderPass::LoadStoreOps vkResolveOps(loadOp, storeOp); 235cb93a386Sopenharmony_ci 236cb93a386Sopenharmony_ci get_vk_load_store_ops(stencilInfo.fLoadOp, stencilInfo.fStoreOp, &loadOp, &storeOp); 237cb93a386Sopenharmony_ci GrVkRenderPass::LoadStoreOps vkStencilOps(loadOp, storeOp); 238cb93a386Sopenharmony_ci 239cb93a386Sopenharmony_ci GrVkResourceProvider::CompatibleRPHandle rpHandle = fFramebuffer->compatibleRenderPassHandle(); 240cb93a386Sopenharmony_ci SkASSERT(rpHandle.isValid()); 241cb93a386Sopenharmony_ci fCurrentRenderPass = fGpu->resourceProvider().findRenderPass(rpHandle, 242cb93a386Sopenharmony_ci vkColorOps, 243cb93a386Sopenharmony_ci vkResolveOps, 244cb93a386Sopenharmony_ci vkStencilOps); 245cb93a386Sopenharmony_ci 246cb93a386Sopenharmony_ci if (!fCurrentRenderPass) { 247cb93a386Sopenharmony_ci return false; 248cb93a386Sopenharmony_ci } 249cb93a386Sopenharmony_ci 250cb93a386Sopenharmony_ci if (!fGpu->vkCaps().preferPrimaryOverSecondaryCommandBuffers()) { 251cb93a386Sopenharmony_ci SkASSERT(fGpu->cmdPool()); 252cb93a386Sopenharmony_ci fCurrentSecondaryCommandBuffer = fGpu->cmdPool()->findOrCreateSecondaryCommandBuffer(fGpu); 253cb93a386Sopenharmony_ci if (!fCurrentSecondaryCommandBuffer) { 254cb93a386Sopenharmony_ci fCurrentRenderPass = nullptr; 255cb93a386Sopenharmony_ci return false; 256cb93a386Sopenharmony_ci } 257cb93a386Sopenharmony_ci fCurrentSecondaryCommandBuffer->begin(fGpu, fFramebuffer.get(), fCurrentRenderPass); 258cb93a386Sopenharmony_ci } 259cb93a386Sopenharmony_ci 260cb93a386Sopenharmony_ci VkClearValue vkClearColor; 261cb93a386Sopenharmony_ci vkClearColor.color.float32[0] = colorInfo.fClearColor[0]; 262cb93a386Sopenharmony_ci vkClearColor.color.float32[1] = colorInfo.fClearColor[1]; 263cb93a386Sopenharmony_ci vkClearColor.color.float32[2] = colorInfo.fClearColor[2]; 264cb93a386Sopenharmony_ci vkClearColor.color.float32[3] = colorInfo.fClearColor[3]; 265cb93a386Sopenharmony_ci 266cb93a386Sopenharmony_ci return this->beginRenderPass(vkClearColor, fLoadFromResolve); 267cb93a386Sopenharmony_ci} 268cb93a386Sopenharmony_ci 269cb93a386Sopenharmony_cibool GrVkOpsRenderPass::initWrapped() { 270cb93a386Sopenharmony_ci SkASSERT(fFramebuffer->isExternal()); 271cb93a386Sopenharmony_ci fCurrentRenderPass = fFramebuffer->externalRenderPass(); 272cb93a386Sopenharmony_ci SkASSERT(fCurrentRenderPass); 273cb93a386Sopenharmony_ci fCurrentRenderPass->ref(); 274cb93a386Sopenharmony_ci 275cb93a386Sopenharmony_ci fCurrentSecondaryCommandBuffer = fFramebuffer->externalCommandBuffer(); 276cb93a386Sopenharmony_ci if (!fCurrentSecondaryCommandBuffer) { 277cb93a386Sopenharmony_ci return false; 278cb93a386Sopenharmony_ci } 279cb93a386Sopenharmony_ci return true; 280cb93a386Sopenharmony_ci} 281cb93a386Sopenharmony_ci 282cb93a386Sopenharmony_ciGrVkOpsRenderPass::~GrVkOpsRenderPass() { 283cb93a386Sopenharmony_ci this->reset(); 284cb93a386Sopenharmony_ci} 285cb93a386Sopenharmony_ci 286cb93a386Sopenharmony_ciGrGpu* GrVkOpsRenderPass::gpu() { return fGpu; } 287cb93a386Sopenharmony_ci 288cb93a386Sopenharmony_ciGrVkCommandBuffer* GrVkOpsRenderPass::currentCommandBuffer() { 289cb93a386Sopenharmony_ci if (fCurrentSecondaryCommandBuffer) { 290cb93a386Sopenharmony_ci return fCurrentSecondaryCommandBuffer.get(); 291cb93a386Sopenharmony_ci } 292cb93a386Sopenharmony_ci // We checked this when we setup the GrVkOpsRenderPass and it should not have changed while we 293cb93a386Sopenharmony_ci // are still using this object. 294cb93a386Sopenharmony_ci SkASSERT(fGpu->currentCommandBuffer()); 295cb93a386Sopenharmony_ci return fGpu->currentCommandBuffer(); 296cb93a386Sopenharmony_ci} 297cb93a386Sopenharmony_ci 298cb93a386Sopenharmony_civoid GrVkOpsRenderPass::loadResolveIntoMSAA(const SkIRect& nativeBounds) { 299cb93a386Sopenharmony_ci fGpu->loadMSAAFromResolve(this->currentCommandBuffer(), *fCurrentRenderPass, 300cb93a386Sopenharmony_ci fFramebuffer->colorAttachment(), fFramebuffer->resolveAttachment(), 301cb93a386Sopenharmony_ci nativeBounds); 302cb93a386Sopenharmony_ci fGpu->currentCommandBuffer()->nexSubpass(fGpu, SkToBool(fCurrentSecondaryCommandBuffer)); 303cb93a386Sopenharmony_ci 304cb93a386Sopenharmony_ci // If we loaded the resolve attachment, then we would have set the image layout to be 305cb93a386Sopenharmony_ci // VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL so that it could be used at the start as an input 306cb93a386Sopenharmony_ci // attachment. However, when we switched to the main subpass it will transition the layout 307cb93a386Sopenharmony_ci // internally to VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL. Thus we need to update our tracking 308cb93a386Sopenharmony_ci // of the layout to match the new layout. 309cb93a386Sopenharmony_ci SkASSERT(fFramebuffer->resolveAttachment()); 310cb93a386Sopenharmony_ci fFramebuffer->resolveAttachment()->updateImageLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); 311cb93a386Sopenharmony_ci} 312cb93a386Sopenharmony_ci 313cb93a386Sopenharmony_civoid GrVkOpsRenderPass::submit() { 314cb93a386Sopenharmony_ci if (!fRenderTarget) { 315cb93a386Sopenharmony_ci return; 316cb93a386Sopenharmony_ci } 317cb93a386Sopenharmony_ci if (!fCurrentRenderPass) { 318cb93a386Sopenharmony_ci SkASSERT(fGpu->isDeviceLost()); 319cb93a386Sopenharmony_ci return; 320cb93a386Sopenharmony_ci } 321cb93a386Sopenharmony_ci 322cb93a386Sopenharmony_ci // We don't want to actually submit the secondary command buffer if it is wrapped. 323cb93a386Sopenharmony_ci if (this->wrapsSecondaryCommandBuffer()) { 324cb93a386Sopenharmony_ci // We pass the ownership of the GrVkSecondaryCommandBuffer to the external framebuffer 325cb93a386Sopenharmony_ci // since it's lifetime matches the lifetime we need to keep the GrManagedResources on the 326cb93a386Sopenharmony_ci // GrVkSecondaryCommandBuffer alive. 327cb93a386Sopenharmony_ci fFramebuffer->returnExternalGrSecondaryCommandBuffer( 328cb93a386Sopenharmony_ci std::move(fCurrentSecondaryCommandBuffer)); 329cb93a386Sopenharmony_ci return; 330cb93a386Sopenharmony_ci } 331cb93a386Sopenharmony_ci 332cb93a386Sopenharmony_ci if (fCurrentSecondaryCommandBuffer) { 333cb93a386Sopenharmony_ci fGpu->submitSecondaryCommandBuffer(std::move(fCurrentSecondaryCommandBuffer)); 334cb93a386Sopenharmony_ci } 335cb93a386Sopenharmony_ci fGpu->endRenderPass(fRenderTarget, fOrigin, fBounds); 336cb93a386Sopenharmony_ci} 337cb93a386Sopenharmony_ci 338cb93a386Sopenharmony_cibool GrVkOpsRenderPass::set(GrRenderTarget* rt, 339cb93a386Sopenharmony_ci sk_sp<GrVkFramebuffer> framebuffer, 340cb93a386Sopenharmony_ci GrSurfaceOrigin origin, 341cb93a386Sopenharmony_ci const SkIRect& bounds, 342cb93a386Sopenharmony_ci const GrOpsRenderPass::LoadAndStoreInfo& colorInfo, 343cb93a386Sopenharmony_ci const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo, 344cb93a386Sopenharmony_ci const GrOpsRenderPass::LoadAndStoreInfo& resolveInfo, 345cb93a386Sopenharmony_ci GrVkRenderPass::SelfDependencyFlags selfDepFlags, 346cb93a386Sopenharmony_ci GrVkRenderPass::LoadFromResolve loadFromResolve, 347cb93a386Sopenharmony_ci const SkTArray<GrSurfaceProxy*, true>& sampledProxies) { 348cb93a386Sopenharmony_ci SkASSERT(!fRenderTarget); 349cb93a386Sopenharmony_ci SkASSERT(fGpu == rt->getContext()->priv().getGpu()); 350cb93a386Sopenharmony_ci 351cb93a386Sopenharmony_ci#ifdef SK_DEBUG 352cb93a386Sopenharmony_ci fIsActive = true; 353cb93a386Sopenharmony_ci#endif 354cb93a386Sopenharmony_ci 355cb93a386Sopenharmony_ci // We check to make sure the GrVkGpu has a valid current command buffer instead of each time we 356cb93a386Sopenharmony_ci // access it. If the command buffer is valid here should be valid throughout the use of the 357cb93a386Sopenharmony_ci // render pass since nothing should trigger a submit while this render pass is active. 358cb93a386Sopenharmony_ci if (!fGpu->currentCommandBuffer()) { 359cb93a386Sopenharmony_ci return false; 360cb93a386Sopenharmony_ci } 361cb93a386Sopenharmony_ci 362cb93a386Sopenharmony_ci this->INHERITED::set(rt, origin); 363cb93a386Sopenharmony_ci 364cb93a386Sopenharmony_ci for (int i = 0; i < sampledProxies.count(); ++i) { 365cb93a386Sopenharmony_ci if (sampledProxies[i]->isInstantiated()) { 366cb93a386Sopenharmony_ci SkASSERT(sampledProxies[i]->asTextureProxy()); 367cb93a386Sopenharmony_ci GrVkTexture* vkTex = static_cast<GrVkTexture*>(sampledProxies[i]->peekTexture()); 368cb93a386Sopenharmony_ci SkASSERT(vkTex); 369cb93a386Sopenharmony_ci GrVkImage* texture = vkTex->textureImage(); 370cb93a386Sopenharmony_ci SkASSERT(texture); 371cb93a386Sopenharmony_ci texture->setImageLayout( 372cb93a386Sopenharmony_ci fGpu, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_SHADER_READ_BIT, 373cb93a386Sopenharmony_ci VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, false); 374cb93a386Sopenharmony_ci } 375cb93a386Sopenharmony_ci } 376cb93a386Sopenharmony_ci 377cb93a386Sopenharmony_ci SkASSERT(framebuffer); 378cb93a386Sopenharmony_ci fFramebuffer = std::move(framebuffer); 379cb93a386Sopenharmony_ci 380cb93a386Sopenharmony_ci SkASSERT(bounds.isEmpty() || 381cb93a386Sopenharmony_ci SkIRect::MakeSize(fFramebuffer->colorAttachment()->dimensions()).contains(bounds)); 382cb93a386Sopenharmony_ci fBounds = bounds; 383cb93a386Sopenharmony_ci 384cb93a386Sopenharmony_ci fSelfDependencyFlags = selfDepFlags; 385cb93a386Sopenharmony_ci fLoadFromResolve = loadFromResolve; 386cb93a386Sopenharmony_ci 387cb93a386Sopenharmony_ci if (this->wrapsSecondaryCommandBuffer()) { 388cb93a386Sopenharmony_ci return this->initWrapped(); 389cb93a386Sopenharmony_ci } 390cb93a386Sopenharmony_ci 391cb93a386Sopenharmony_ci return this->init(colorInfo, resolveInfo, stencilInfo); 392cb93a386Sopenharmony_ci} 393cb93a386Sopenharmony_ci 394cb93a386Sopenharmony_civoid GrVkOpsRenderPass::reset() { 395cb93a386Sopenharmony_ci if (fCurrentSecondaryCommandBuffer) { 396cb93a386Sopenharmony_ci // The active GrVkCommandPool on the GrVkGpu should still be the same pool we got the 397cb93a386Sopenharmony_ci // secondary command buffer from since we haven't submitted any work yet. 398cb93a386Sopenharmony_ci SkASSERT(fGpu->cmdPool()); 399cb93a386Sopenharmony_ci fCurrentSecondaryCommandBuffer.release()->recycle(fGpu->cmdPool()); 400cb93a386Sopenharmony_ci } 401cb93a386Sopenharmony_ci if (fCurrentRenderPass) { 402cb93a386Sopenharmony_ci fCurrentRenderPass->unref(); 403cb93a386Sopenharmony_ci fCurrentRenderPass = nullptr; 404cb93a386Sopenharmony_ci } 405cb93a386Sopenharmony_ci fCurrentCBIsEmpty = true; 406cb93a386Sopenharmony_ci 407cb93a386Sopenharmony_ci fRenderTarget = nullptr; 408cb93a386Sopenharmony_ci fFramebuffer.reset(); 409cb93a386Sopenharmony_ci 410cb93a386Sopenharmony_ci fSelfDependencyFlags = GrVkRenderPass::SelfDependencyFlags::kNone; 411cb93a386Sopenharmony_ci 412cb93a386Sopenharmony_ci fLoadFromResolve = LoadFromResolve::kNo; 413cb93a386Sopenharmony_ci fOverridePipelinesForResolveLoad = false; 414cb93a386Sopenharmony_ci 415cb93a386Sopenharmony_ci#ifdef SK_DEBUG 416cb93a386Sopenharmony_ci fIsActive = false; 417cb93a386Sopenharmony_ci#endif 418cb93a386Sopenharmony_ci} 419cb93a386Sopenharmony_ci 420cb93a386Sopenharmony_cibool GrVkOpsRenderPass::wrapsSecondaryCommandBuffer() const { 421cb93a386Sopenharmony_ci return fFramebuffer->isExternal(); 422cb93a386Sopenharmony_ci} 423cb93a386Sopenharmony_ci 424cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////// 425cb93a386Sopenharmony_ci 426cb93a386Sopenharmony_civoid GrVkOpsRenderPass::onClearStencilClip(const GrScissorState& scissor, bool insideStencilMask) { 427cb93a386Sopenharmony_ci if (!fCurrentRenderPass) { 428cb93a386Sopenharmony_ci SkASSERT(fGpu->isDeviceLost()); 429cb93a386Sopenharmony_ci return; 430cb93a386Sopenharmony_ci } 431cb93a386Sopenharmony_ci 432cb93a386Sopenharmony_ci GrAttachment* sb = fFramebuffer->stencilAttachment(); 433cb93a386Sopenharmony_ci // this should only be called internally when we know we have a 434cb93a386Sopenharmony_ci // stencil buffer. 435cb93a386Sopenharmony_ci SkASSERT(sb); 436cb93a386Sopenharmony_ci int stencilBitCount = GrBackendFormatStencilBits(sb->backendFormat()); 437cb93a386Sopenharmony_ci 438cb93a386Sopenharmony_ci // The contract with the callers does not guarantee that we preserve all bits in the stencil 439cb93a386Sopenharmony_ci // during this clear. Thus we will clear the entire stencil to the desired value. 440cb93a386Sopenharmony_ci 441cb93a386Sopenharmony_ci VkClearDepthStencilValue vkStencilColor; 442cb93a386Sopenharmony_ci memset(&vkStencilColor, 0, sizeof(VkClearDepthStencilValue)); 443cb93a386Sopenharmony_ci if (insideStencilMask) { 444cb93a386Sopenharmony_ci vkStencilColor.stencil = (1 << (stencilBitCount - 1)); 445cb93a386Sopenharmony_ci } else { 446cb93a386Sopenharmony_ci vkStencilColor.stencil = 0; 447cb93a386Sopenharmony_ci } 448cb93a386Sopenharmony_ci 449cb93a386Sopenharmony_ci VkClearRect clearRect; 450cb93a386Sopenharmony_ci // Flip rect if necessary 451cb93a386Sopenharmony_ci SkIRect vkRect; 452cb93a386Sopenharmony_ci if (!scissor.enabled()) { 453cb93a386Sopenharmony_ci vkRect.setXYWH(0, 0, sb->width(), sb->height()); 454cb93a386Sopenharmony_ci } else if (kBottomLeft_GrSurfaceOrigin != fOrigin) { 455cb93a386Sopenharmony_ci vkRect = scissor.rect(); 456cb93a386Sopenharmony_ci } else { 457cb93a386Sopenharmony_ci vkRect.setLTRB(scissor.rect().fLeft, sb->height() - scissor.rect().fBottom, 458cb93a386Sopenharmony_ci scissor.rect().fRight, sb->height() - scissor.rect().fTop); 459cb93a386Sopenharmony_ci } 460cb93a386Sopenharmony_ci 461cb93a386Sopenharmony_ci clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop }; 462cb93a386Sopenharmony_ci clearRect.rect.extent = { (uint32_t)vkRect.width(), (uint32_t)vkRect.height() }; 463cb93a386Sopenharmony_ci 464cb93a386Sopenharmony_ci clearRect.baseArrayLayer = 0; 465cb93a386Sopenharmony_ci clearRect.layerCount = 1; 466cb93a386Sopenharmony_ci 467cb93a386Sopenharmony_ci uint32_t stencilIndex; 468cb93a386Sopenharmony_ci SkAssertResult(fCurrentRenderPass->stencilAttachmentIndex(&stencilIndex)); 469cb93a386Sopenharmony_ci 470cb93a386Sopenharmony_ci VkClearAttachment attachment; 471cb93a386Sopenharmony_ci attachment.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; 472cb93a386Sopenharmony_ci attachment.colorAttachment = 0; // this value shouldn't matter 473cb93a386Sopenharmony_ci attachment.clearValue.depthStencil = vkStencilColor; 474cb93a386Sopenharmony_ci 475cb93a386Sopenharmony_ci this->currentCommandBuffer()->clearAttachments(fGpu, 1, &attachment, 1, &clearRect); 476cb93a386Sopenharmony_ci fCurrentCBIsEmpty = false; 477cb93a386Sopenharmony_ci} 478cb93a386Sopenharmony_ci 479cb93a386Sopenharmony_civoid GrVkOpsRenderPass::onClear(const GrScissorState& scissor, std::array<float, 4> color) { 480cb93a386Sopenharmony_ci if (!fCurrentRenderPass) { 481cb93a386Sopenharmony_ci SkASSERT(fGpu->isDeviceLost()); 482cb93a386Sopenharmony_ci return; 483cb93a386Sopenharmony_ci } 484cb93a386Sopenharmony_ci 485cb93a386Sopenharmony_ci VkClearColorValue vkColor = {{color[0], color[1], color[2], color[3]}}; 486cb93a386Sopenharmony_ci 487cb93a386Sopenharmony_ci // If we end up in a situation where we are calling clear without a scissior then in general it 488cb93a386Sopenharmony_ci // means we missed an opportunity higher up the stack to set the load op to be a clear. However, 489cb93a386Sopenharmony_ci // there are situations where higher up we couldn't discard the previous ops and set a clear 490cb93a386Sopenharmony_ci // load op (e.g. if we needed to execute a wait op). Thus we also have the empty check here. 491cb93a386Sopenharmony_ci // TODO: Make the waitOp a RenderTask instead so we can clear out the OpsTask for a clear. We 492cb93a386Sopenharmony_ci // can then reenable this assert assuming we can't get messed up by a waitOp. 493cb93a386Sopenharmony_ci //SkASSERT(!fCurrentCBIsEmpty || scissor); 494cb93a386Sopenharmony_ci 495cb93a386Sopenharmony_ci auto dimensions = fFramebuffer->colorAttachment()->dimensions(); 496cb93a386Sopenharmony_ci // We always do a sub rect clear with clearAttachments since we are inside a render pass 497cb93a386Sopenharmony_ci VkClearRect clearRect; 498cb93a386Sopenharmony_ci // Flip rect if necessary 499cb93a386Sopenharmony_ci SkIRect vkRect; 500cb93a386Sopenharmony_ci if (!scissor.enabled()) { 501cb93a386Sopenharmony_ci vkRect.setSize(dimensions); 502cb93a386Sopenharmony_ci } else if (kBottomLeft_GrSurfaceOrigin != fOrigin) { 503cb93a386Sopenharmony_ci vkRect = scissor.rect(); 504cb93a386Sopenharmony_ci } else { 505cb93a386Sopenharmony_ci vkRect.setLTRB(scissor.rect().fLeft, dimensions.height() - scissor.rect().fBottom, 506cb93a386Sopenharmony_ci scissor.rect().fRight, dimensions.height() - scissor.rect().fTop); 507cb93a386Sopenharmony_ci } 508cb93a386Sopenharmony_ci clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop }; 509cb93a386Sopenharmony_ci clearRect.rect.extent = { (uint32_t)vkRect.width(), (uint32_t)vkRect.height() }; 510cb93a386Sopenharmony_ci clearRect.baseArrayLayer = 0; 511cb93a386Sopenharmony_ci clearRect.layerCount = 1; 512cb93a386Sopenharmony_ci 513cb93a386Sopenharmony_ci uint32_t colorIndex; 514cb93a386Sopenharmony_ci SkAssertResult(fCurrentRenderPass->colorAttachmentIndex(&colorIndex)); 515cb93a386Sopenharmony_ci 516cb93a386Sopenharmony_ci VkClearAttachment attachment; 517cb93a386Sopenharmony_ci attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 518cb93a386Sopenharmony_ci attachment.colorAttachment = colorIndex; 519cb93a386Sopenharmony_ci attachment.clearValue.color = vkColor; 520cb93a386Sopenharmony_ci 521cb93a386Sopenharmony_ci this->currentCommandBuffer()->clearAttachments(fGpu, 1, &attachment, 1, &clearRect); 522cb93a386Sopenharmony_ci fCurrentCBIsEmpty = false; 523cb93a386Sopenharmony_ci return; 524cb93a386Sopenharmony_ci} 525cb93a386Sopenharmony_ci 526cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////// 527cb93a386Sopenharmony_ci 528cb93a386Sopenharmony_civoid GrVkOpsRenderPass::addAdditionalRenderPass(bool mustUseSecondaryCommandBuffer) { 529cb93a386Sopenharmony_ci SkASSERT(!this->wrapsSecondaryCommandBuffer()); 530cb93a386Sopenharmony_ci 531cb93a386Sopenharmony_ci bool withResolve = fFramebuffer->resolveAttachment(); 532cb93a386Sopenharmony_ci bool withStencil = fFramebuffer->stencilAttachment(); 533cb93a386Sopenharmony_ci 534cb93a386Sopenharmony_ci // If we have a resolve attachment we must do a resolve load in the new render pass since we 535cb93a386Sopenharmony_ci // broke up the original one. GrProgramInfos were made without any knowledge that the render 536cb93a386Sopenharmony_ci // pass may be split up. Thus they may try to make VkPipelines that only use one subpass. We 537cb93a386Sopenharmony_ci // need to override that to make sure they are compatible with the extra load subpass. 538cb93a386Sopenharmony_ci fOverridePipelinesForResolveLoad |= 539cb93a386Sopenharmony_ci withResolve && fCurrentRenderPass->loadFromResolve() != LoadFromResolve::kLoad; 540cb93a386Sopenharmony_ci 541cb93a386Sopenharmony_ci GrVkRenderPass::LoadStoreOps vkColorOps(VK_ATTACHMENT_LOAD_OP_LOAD, 542cb93a386Sopenharmony_ci VK_ATTACHMENT_STORE_OP_STORE); 543cb93a386Sopenharmony_ci GrVkRenderPass::LoadStoreOps vkResolveOps(VK_ATTACHMENT_LOAD_OP_LOAD, 544cb93a386Sopenharmony_ci VK_ATTACHMENT_STORE_OP_STORE); 545cb93a386Sopenharmony_ci LoadFromResolve loadFromResolve = LoadFromResolve::kNo; 546cb93a386Sopenharmony_ci if (withResolve) { 547cb93a386Sopenharmony_ci vkColorOps = {VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE}; 548cb93a386Sopenharmony_ci loadFromResolve = LoadFromResolve::kLoad; 549cb93a386Sopenharmony_ci } 550cb93a386Sopenharmony_ci GrVkRenderPass::LoadStoreOps vkStencilOps(VK_ATTACHMENT_LOAD_OP_LOAD, 551cb93a386Sopenharmony_ci VK_ATTACHMENT_STORE_OP_STORE); 552cb93a386Sopenharmony_ci 553cb93a386Sopenharmony_ci SkASSERT(fCurrentRenderPass); 554cb93a386Sopenharmony_ci fCurrentRenderPass->unref(); 555cb93a386Sopenharmony_ci fCurrentRenderPass = nullptr; 556cb93a386Sopenharmony_ci 557cb93a386Sopenharmony_ci GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(fRenderTarget); 558cb93a386Sopenharmony_ci auto fb = vkRT->getFramebuffer(withResolve, withStencil, fSelfDependencyFlags, loadFromResolve); 559cb93a386Sopenharmony_ci if (!fb) { 560cb93a386Sopenharmony_ci return; 561cb93a386Sopenharmony_ci } 562cb93a386Sopenharmony_ci fFramebuffer = sk_ref_sp(fb); 563cb93a386Sopenharmony_ci 564cb93a386Sopenharmony_ci SkASSERT(fFramebuffer); 565cb93a386Sopenharmony_ci const GrVkResourceProvider::CompatibleRPHandle& rpHandle = 566cb93a386Sopenharmony_ci fFramebuffer->compatibleRenderPassHandle(); 567cb93a386Sopenharmony_ci SkASSERT(rpHandle.isValid()); 568cb93a386Sopenharmony_ci 569cb93a386Sopenharmony_ci fCurrentRenderPass = fGpu->resourceProvider().findRenderPass(rpHandle, 570cb93a386Sopenharmony_ci vkColorOps, 571cb93a386Sopenharmony_ci vkResolveOps, 572cb93a386Sopenharmony_ci vkStencilOps); 573cb93a386Sopenharmony_ci 574cb93a386Sopenharmony_ci if (!fCurrentRenderPass) { 575cb93a386Sopenharmony_ci return; 576cb93a386Sopenharmony_ci } 577cb93a386Sopenharmony_ci 578cb93a386Sopenharmony_ci if (!fGpu->vkCaps().preferPrimaryOverSecondaryCommandBuffers() || 579cb93a386Sopenharmony_ci mustUseSecondaryCommandBuffer) { 580cb93a386Sopenharmony_ci SkASSERT(fGpu->cmdPool()); 581cb93a386Sopenharmony_ci fCurrentSecondaryCommandBuffer = fGpu->cmdPool()->findOrCreateSecondaryCommandBuffer(fGpu); 582cb93a386Sopenharmony_ci if (!fCurrentSecondaryCommandBuffer) { 583cb93a386Sopenharmony_ci fCurrentRenderPass = nullptr; 584cb93a386Sopenharmony_ci return; 585cb93a386Sopenharmony_ci } 586cb93a386Sopenharmony_ci fCurrentSecondaryCommandBuffer->begin(fGpu, fFramebuffer.get(), fCurrentRenderPass); 587cb93a386Sopenharmony_ci } 588cb93a386Sopenharmony_ci 589cb93a386Sopenharmony_ci VkClearValue vkClearColor; 590cb93a386Sopenharmony_ci memset(&vkClearColor, 0, sizeof(VkClearValue)); 591cb93a386Sopenharmony_ci 592cb93a386Sopenharmony_ci this->beginRenderPass(vkClearColor, loadFromResolve); 593cb93a386Sopenharmony_ci} 594cb93a386Sopenharmony_ci 595cb93a386Sopenharmony_civoid GrVkOpsRenderPass::inlineUpload(GrOpFlushState* state, GrDeferredTextureUploadFn& upload) { 596cb93a386Sopenharmony_ci if (!fCurrentRenderPass) { 597cb93a386Sopenharmony_ci SkASSERT(fGpu->isDeviceLost()); 598cb93a386Sopenharmony_ci return; 599cb93a386Sopenharmony_ci } 600cb93a386Sopenharmony_ci if (fCurrentSecondaryCommandBuffer) { 601cb93a386Sopenharmony_ci fCurrentSecondaryCommandBuffer->end(fGpu); 602cb93a386Sopenharmony_ci fGpu->submitSecondaryCommandBuffer(std::move(fCurrentSecondaryCommandBuffer)); 603cb93a386Sopenharmony_ci } 604cb93a386Sopenharmony_ci fGpu->endRenderPass(fRenderTarget, fOrigin, fBounds); 605cb93a386Sopenharmony_ci 606cb93a386Sopenharmony_ci // We pass in true here to signal that after the upload we need to set the upload textures 607cb93a386Sopenharmony_ci // layout back to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL. 608cb93a386Sopenharmony_ci state->doUpload(upload, true); 609cb93a386Sopenharmony_ci 610cb93a386Sopenharmony_ci this->addAdditionalRenderPass(false); 611cb93a386Sopenharmony_ci} 612cb93a386Sopenharmony_ci 613cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////// 614cb93a386Sopenharmony_ci 615cb93a386Sopenharmony_civoid GrVkOpsRenderPass::onEnd() { 616cb93a386Sopenharmony_ci if (fCurrentSecondaryCommandBuffer && !this->wrapsSecondaryCommandBuffer()) { 617cb93a386Sopenharmony_ci fCurrentSecondaryCommandBuffer->end(fGpu); 618cb93a386Sopenharmony_ci } 619cb93a386Sopenharmony_ci} 620cb93a386Sopenharmony_ci 621cb93a386Sopenharmony_cibool GrVkOpsRenderPass::onBindPipeline(const GrProgramInfo& programInfo, const SkRect& drawBounds) { 622cb93a386Sopenharmony_ci if (!fCurrentRenderPass) { 623cb93a386Sopenharmony_ci SkASSERT(fGpu->isDeviceLost()); 624cb93a386Sopenharmony_ci return false; 625cb93a386Sopenharmony_ci } 626cb93a386Sopenharmony_ci 627cb93a386Sopenharmony_ci SkRect rtRect = SkRect::Make(fBounds); 628cb93a386Sopenharmony_ci if (rtRect.intersect(drawBounds)) { 629cb93a386Sopenharmony_ci rtRect.roundOut(&fCurrentPipelineBounds); 630cb93a386Sopenharmony_ci } else { 631cb93a386Sopenharmony_ci fCurrentPipelineBounds.setEmpty(); 632cb93a386Sopenharmony_ci } 633cb93a386Sopenharmony_ci 634cb93a386Sopenharmony_ci GrVkCommandBuffer* currentCB = this->currentCommandBuffer(); 635cb93a386Sopenharmony_ci SkASSERT(fCurrentRenderPass); 636cb93a386Sopenharmony_ci 637cb93a386Sopenharmony_ci VkRenderPass compatibleRenderPass = fCurrentRenderPass->vkRenderPass(); 638cb93a386Sopenharmony_ci fCurrentPipelineState = fGpu->resourceProvider().findOrCreateCompatiblePipelineState( 639cb93a386Sopenharmony_ci fRenderTarget, programInfo, compatibleRenderPass, fOverridePipelinesForResolveLoad); 640cb93a386Sopenharmony_ci if (!fCurrentPipelineState) { 641cb93a386Sopenharmony_ci return false; 642cb93a386Sopenharmony_ci } 643cb93a386Sopenharmony_ci 644cb93a386Sopenharmony_ci fCurrentPipelineState->bindPipeline(fGpu, currentCB); 645cb93a386Sopenharmony_ci 646cb93a386Sopenharmony_ci // Both the 'programInfo' and this renderPass have an origin. Since they come from the 647cb93a386Sopenharmony_ci // same place (i.e., the target renderTargetProxy) they had best agree. 648cb93a386Sopenharmony_ci SkASSERT(programInfo.origin() == fOrigin); 649cb93a386Sopenharmony_ci 650cb93a386Sopenharmony_ci auto colorAttachment = fFramebuffer->colorAttachment(); 651cb93a386Sopenharmony_ci if (!fCurrentPipelineState->setAndBindUniforms(fGpu, colorAttachment->dimensions(), programInfo, 652cb93a386Sopenharmony_ci currentCB)) { 653cb93a386Sopenharmony_ci return false; 654cb93a386Sopenharmony_ci } 655cb93a386Sopenharmony_ci 656cb93a386Sopenharmony_ci if (!programInfo.pipeline().isScissorTestEnabled()) { 657cb93a386Sopenharmony_ci // "Disable" scissor by setting it to the full pipeline bounds. 658cb93a386Sopenharmony_ci GrVkPipeline::SetDynamicScissorRectState( 659cb93a386Sopenharmony_ci fGpu, currentCB, colorAttachment->dimensions(), fOrigin, 660cb93a386Sopenharmony_ci fCurrentPipelineBounds); 661cb93a386Sopenharmony_ci } 662cb93a386Sopenharmony_ci GrVkPipeline::SetDynamicViewportState(fGpu, currentCB, colorAttachment->dimensions()); 663cb93a386Sopenharmony_ci GrVkPipeline::SetDynamicBlendConstantState(fGpu, currentCB, 664cb93a386Sopenharmony_ci programInfo.pipeline().writeSwizzle(), 665cb93a386Sopenharmony_ci programInfo.pipeline().getXferProcessor()); 666cb93a386Sopenharmony_ci 667cb93a386Sopenharmony_ci return true; 668cb93a386Sopenharmony_ci} 669cb93a386Sopenharmony_ci 670cb93a386Sopenharmony_civoid GrVkOpsRenderPass::onSetScissorRect(const SkIRect& scissor) { 671cb93a386Sopenharmony_ci SkIRect combinedScissorRect; 672cb93a386Sopenharmony_ci if (!combinedScissorRect.intersect(fCurrentPipelineBounds, scissor)) { 673cb93a386Sopenharmony_ci combinedScissorRect = SkIRect::MakeEmpty(); 674cb93a386Sopenharmony_ci } 675cb93a386Sopenharmony_ci GrVkPipeline::SetDynamicScissorRectState(fGpu, this->currentCommandBuffer(), 676cb93a386Sopenharmony_ci fFramebuffer->colorAttachment()->dimensions(), 677cb93a386Sopenharmony_ci fOrigin, combinedScissorRect); 678cb93a386Sopenharmony_ci} 679cb93a386Sopenharmony_ci 680cb93a386Sopenharmony_ci#ifdef SK_DEBUG 681cb93a386Sopenharmony_civoid check_sampled_texture(GrTexture* tex, GrAttachment* colorAttachment, GrVkGpu* gpu) { 682cb93a386Sopenharmony_ci SkASSERT(!tex->isProtected() || (colorAttachment->isProtected() && gpu->protectedContext())); 683cb93a386Sopenharmony_ci auto vkTex = static_cast<GrVkTexture*>(tex)->textureImage(); 684cb93a386Sopenharmony_ci SkASSERT(vkTex->currentLayout() == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); 685cb93a386Sopenharmony_ci} 686cb93a386Sopenharmony_ci#endif 687cb93a386Sopenharmony_ci 688cb93a386Sopenharmony_cibool GrVkOpsRenderPass::onBindTextures(const GrGeometryProcessor& geomProc, 689cb93a386Sopenharmony_ci const GrSurfaceProxy* const geomProcTextures[], 690cb93a386Sopenharmony_ci const GrPipeline& pipeline) { 691cb93a386Sopenharmony_ci#ifdef SK_DEBUG 692cb93a386Sopenharmony_ci SkASSERT(fCurrentPipelineState); 693cb93a386Sopenharmony_ci auto colorAttachment = fFramebuffer->colorAttachment(); 694cb93a386Sopenharmony_ci for (int i = 0; i < geomProc.numTextureSamplers(); ++i) { 695cb93a386Sopenharmony_ci check_sampled_texture(geomProcTextures[i]->peekTexture(), colorAttachment, fGpu); 696cb93a386Sopenharmony_ci } 697cb93a386Sopenharmony_ci pipeline.visitTextureEffects([&](const GrTextureEffect& te) { 698cb93a386Sopenharmony_ci check_sampled_texture(te.texture(), colorAttachment, fGpu); 699cb93a386Sopenharmony_ci }); 700cb93a386Sopenharmony_ci if (GrTexture* dstTexture = pipeline.peekDstTexture()) { 701cb93a386Sopenharmony_ci check_sampled_texture(dstTexture, colorAttachment, fGpu); 702cb93a386Sopenharmony_ci } 703cb93a386Sopenharmony_ci#endif 704cb93a386Sopenharmony_ci if (!fCurrentPipelineState->setAndBindTextures(fGpu, geomProc, pipeline, geomProcTextures, 705cb93a386Sopenharmony_ci this->currentCommandBuffer())) { 706cb93a386Sopenharmony_ci return false; 707cb93a386Sopenharmony_ci } 708cb93a386Sopenharmony_ci if (fSelfDependencyFlags == SelfDependencyFlags::kForInputAttachment) { 709cb93a386Sopenharmony_ci // We bind the color attachment as an input attachment 710cb93a386Sopenharmony_ci auto ds = fFramebuffer->colorAttachment()->inputDescSetForBlending(fGpu); 711cb93a386Sopenharmony_ci if (!ds) { 712cb93a386Sopenharmony_ci return false; 713cb93a386Sopenharmony_ci } 714cb93a386Sopenharmony_ci return fCurrentPipelineState->setAndBindInputAttachment(fGpu, std::move(ds), 715cb93a386Sopenharmony_ci this->currentCommandBuffer()); 716cb93a386Sopenharmony_ci } 717cb93a386Sopenharmony_ci return true; 718cb93a386Sopenharmony_ci} 719cb93a386Sopenharmony_ci 720cb93a386Sopenharmony_civoid GrVkOpsRenderPass::onBindBuffers(sk_sp<const GrBuffer> indexBuffer, 721cb93a386Sopenharmony_ci sk_sp<const GrBuffer> instanceBuffer, 722cb93a386Sopenharmony_ci sk_sp<const GrBuffer> vertexBuffer, 723cb93a386Sopenharmony_ci GrPrimitiveRestart primRestart) { 724cb93a386Sopenharmony_ci SkASSERT(GrPrimitiveRestart::kNo == primRestart); 725cb93a386Sopenharmony_ci if (!fCurrentRenderPass) { 726cb93a386Sopenharmony_ci SkASSERT(fGpu->isDeviceLost()); 727cb93a386Sopenharmony_ci return; 728cb93a386Sopenharmony_ci } 729cb93a386Sopenharmony_ci SkASSERT(fCurrentPipelineState); 730cb93a386Sopenharmony_ci SkASSERT(!fGpu->caps()->usePrimitiveRestart()); // Ignore primitiveRestart parameter. 731cb93a386Sopenharmony_ci 732cb93a386Sopenharmony_ci GrVkCommandBuffer* currCmdBuf = this->currentCommandBuffer(); 733cb93a386Sopenharmony_ci SkASSERT(currCmdBuf); 734cb93a386Sopenharmony_ci 735cb93a386Sopenharmony_ci // There is no need to put any memory barriers to make sure host writes have finished here. 736cb93a386Sopenharmony_ci // When a command buffer is submitted to a queue, there is an implicit memory barrier that 737cb93a386Sopenharmony_ci // occurs for all host writes. Additionally, BufferMemoryBarriers are not allowed inside of 738cb93a386Sopenharmony_ci // an active RenderPass. 739cb93a386Sopenharmony_ci 740cb93a386Sopenharmony_ci // Here our vertex and instance inputs need to match the same 0-based bindings they were 741cb93a386Sopenharmony_ci // assigned in GrVkPipeline. That is, vertex first (if any) followed by instance. 742cb93a386Sopenharmony_ci uint32_t binding = 0; 743cb93a386Sopenharmony_ci if (auto* gpuVertexBuffer = static_cast<const GrGpuBuffer*>(vertexBuffer.get())) { 744cb93a386Sopenharmony_ci SkASSERT(!gpuVertexBuffer->isCpuBuffer()); 745cb93a386Sopenharmony_ci SkASSERT(!gpuVertexBuffer->isMapped()); 746cb93a386Sopenharmony_ci currCmdBuf->bindInputBuffer(fGpu, binding++, std::move(vertexBuffer)); 747cb93a386Sopenharmony_ci } 748cb93a386Sopenharmony_ci if (auto* gpuInstanceBuffer = static_cast<const GrGpuBuffer*>(instanceBuffer.get())) { 749cb93a386Sopenharmony_ci SkASSERT(!gpuInstanceBuffer->isCpuBuffer()); 750cb93a386Sopenharmony_ci SkASSERT(!gpuInstanceBuffer->isMapped()); 751cb93a386Sopenharmony_ci currCmdBuf->bindInputBuffer(fGpu, binding++, std::move(instanceBuffer)); 752cb93a386Sopenharmony_ci } 753cb93a386Sopenharmony_ci if (auto* gpuIndexBuffer = static_cast<const GrGpuBuffer*>(indexBuffer.get())) { 754cb93a386Sopenharmony_ci SkASSERT(!gpuIndexBuffer->isCpuBuffer()); 755cb93a386Sopenharmony_ci SkASSERT(!gpuIndexBuffer->isMapped()); 756cb93a386Sopenharmony_ci currCmdBuf->bindIndexBuffer(fGpu, std::move(indexBuffer)); 757cb93a386Sopenharmony_ci } 758cb93a386Sopenharmony_ci} 759cb93a386Sopenharmony_ci 760cb93a386Sopenharmony_civoid GrVkOpsRenderPass::onDrawInstanced(int instanceCount, 761cb93a386Sopenharmony_ci int baseInstance, 762cb93a386Sopenharmony_ci int vertexCount, int baseVertex) { 763cb93a386Sopenharmony_ci if (!fCurrentRenderPass) { 764cb93a386Sopenharmony_ci SkASSERT(fGpu->isDeviceLost()); 765cb93a386Sopenharmony_ci return; 766cb93a386Sopenharmony_ci } 767cb93a386Sopenharmony_ci SkASSERT(fCurrentPipelineState); 768cb93a386Sopenharmony_ci this->currentCommandBuffer()->draw(fGpu, vertexCount, instanceCount, baseVertex, baseInstance); 769cb93a386Sopenharmony_ci fGpu->stats()->incNumDraws(); 770cb93a386Sopenharmony_ci fCurrentCBIsEmpty = false; 771cb93a386Sopenharmony_ci} 772cb93a386Sopenharmony_ci 773cb93a386Sopenharmony_civoid GrVkOpsRenderPass::onDrawIndexedInstanced(int indexCount, int baseIndex, int instanceCount, 774cb93a386Sopenharmony_ci int baseInstance, int baseVertex) { 775cb93a386Sopenharmony_ci if (!fCurrentRenderPass) { 776cb93a386Sopenharmony_ci SkASSERT(fGpu->isDeviceLost()); 777cb93a386Sopenharmony_ci return; 778cb93a386Sopenharmony_ci } 779cb93a386Sopenharmony_ci SkASSERT(fCurrentPipelineState); 780cb93a386Sopenharmony_ci this->currentCommandBuffer()->drawIndexed(fGpu, indexCount, instanceCount, 781cb93a386Sopenharmony_ci baseIndex, baseVertex, baseInstance); 782cb93a386Sopenharmony_ci fGpu->stats()->incNumDraws(); 783cb93a386Sopenharmony_ci fCurrentCBIsEmpty = false; 784cb93a386Sopenharmony_ci} 785cb93a386Sopenharmony_ci 786cb93a386Sopenharmony_civoid GrVkOpsRenderPass::onDrawIndirect(const GrBuffer* drawIndirectBuffer, size_t offset, 787cb93a386Sopenharmony_ci int drawCount) { 788cb93a386Sopenharmony_ci SkASSERT(!drawIndirectBuffer->isCpuBuffer()); 789cb93a386Sopenharmony_ci if (!fCurrentRenderPass) { 790cb93a386Sopenharmony_ci SkASSERT(fGpu->isDeviceLost()); 791cb93a386Sopenharmony_ci return; 792cb93a386Sopenharmony_ci } 793cb93a386Sopenharmony_ci const GrVkCaps& caps = fGpu->vkCaps(); 794cb93a386Sopenharmony_ci SkASSERT(caps.nativeDrawIndirectSupport()); 795cb93a386Sopenharmony_ci SkASSERT(fCurrentPipelineState); 796cb93a386Sopenharmony_ci 797cb93a386Sopenharmony_ci const uint32_t maxDrawCount = caps.maxDrawIndirectDrawCount(); 798cb93a386Sopenharmony_ci uint32_t remainingDraws = drawCount; 799cb93a386Sopenharmony_ci const size_t stride = sizeof(GrDrawIndirectCommand); 800cb93a386Sopenharmony_ci while (remainingDraws >= 1) { 801cb93a386Sopenharmony_ci uint32_t currDrawCount = std::min(remainingDraws, maxDrawCount); 802cb93a386Sopenharmony_ci this->currentCommandBuffer()->drawIndirect( 803cb93a386Sopenharmony_ci fGpu, sk_ref_sp(drawIndirectBuffer), offset, currDrawCount, stride); 804cb93a386Sopenharmony_ci remainingDraws -= currDrawCount; 805cb93a386Sopenharmony_ci offset += stride * currDrawCount; 806cb93a386Sopenharmony_ci fGpu->stats()->incNumDraws(); 807cb93a386Sopenharmony_ci } 808cb93a386Sopenharmony_ci fCurrentCBIsEmpty = false; 809cb93a386Sopenharmony_ci} 810cb93a386Sopenharmony_ci 811cb93a386Sopenharmony_civoid GrVkOpsRenderPass::onDrawIndexedIndirect(const GrBuffer* drawIndirectBuffer, size_t offset, 812cb93a386Sopenharmony_ci int drawCount) { 813cb93a386Sopenharmony_ci SkASSERT(!drawIndirectBuffer->isCpuBuffer()); 814cb93a386Sopenharmony_ci if (!fCurrentRenderPass) { 815cb93a386Sopenharmony_ci SkASSERT(fGpu->isDeviceLost()); 816cb93a386Sopenharmony_ci return; 817cb93a386Sopenharmony_ci } 818cb93a386Sopenharmony_ci const GrVkCaps& caps = fGpu->vkCaps(); 819cb93a386Sopenharmony_ci SkASSERT(caps.nativeDrawIndirectSupport()); 820cb93a386Sopenharmony_ci SkASSERT(fCurrentPipelineState); 821cb93a386Sopenharmony_ci const uint32_t maxDrawCount = caps.maxDrawIndirectDrawCount(); 822cb93a386Sopenharmony_ci uint32_t remainingDraws = drawCount; 823cb93a386Sopenharmony_ci const size_t stride = sizeof(GrDrawIndexedIndirectCommand); 824cb93a386Sopenharmony_ci while (remainingDraws >= 1) { 825cb93a386Sopenharmony_ci uint32_t currDrawCount = std::min(remainingDraws, maxDrawCount); 826cb93a386Sopenharmony_ci this->currentCommandBuffer()->drawIndexedIndirect( 827cb93a386Sopenharmony_ci fGpu, sk_ref_sp(drawIndirectBuffer), offset, currDrawCount, stride); 828cb93a386Sopenharmony_ci remainingDraws -= currDrawCount; 829cb93a386Sopenharmony_ci offset += stride * currDrawCount; 830cb93a386Sopenharmony_ci fGpu->stats()->incNumDraws(); 831cb93a386Sopenharmony_ci } 832cb93a386Sopenharmony_ci fCurrentCBIsEmpty = false; 833cb93a386Sopenharmony_ci} 834cb93a386Sopenharmony_ci 835cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////// 836cb93a386Sopenharmony_ci 837cb93a386Sopenharmony_civoid GrVkOpsRenderPass::onExecuteDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler> drawable) { 838cb93a386Sopenharmony_ci if (!fCurrentRenderPass) { 839cb93a386Sopenharmony_ci SkASSERT(fGpu->isDeviceLost()); 840cb93a386Sopenharmony_ci return; 841cb93a386Sopenharmony_ci } 842cb93a386Sopenharmony_ci 843cb93a386Sopenharmony_ci VkRect2D bounds; 844cb93a386Sopenharmony_ci bounds.offset = { 0, 0 }; 845cb93a386Sopenharmony_ci bounds.extent = { 0, 0 }; 846cb93a386Sopenharmony_ci 847cb93a386Sopenharmony_ci if (!fCurrentSecondaryCommandBuffer) { 848cb93a386Sopenharmony_ci fGpu->endRenderPass(fRenderTarget, fOrigin, fBounds); 849cb93a386Sopenharmony_ci this->addAdditionalRenderPass(true); 850cb93a386Sopenharmony_ci // We may have failed to start a new render pass 851cb93a386Sopenharmony_ci if (!fCurrentRenderPass) { 852cb93a386Sopenharmony_ci SkASSERT(fGpu->isDeviceLost()); 853cb93a386Sopenharmony_ci return; 854cb93a386Sopenharmony_ci } 855cb93a386Sopenharmony_ci } 856cb93a386Sopenharmony_ci SkASSERT(fCurrentSecondaryCommandBuffer); 857cb93a386Sopenharmony_ci 858cb93a386Sopenharmony_ci GrVkDrawableInfo vkInfo; 859cb93a386Sopenharmony_ci vkInfo.fSecondaryCommandBuffer = fCurrentSecondaryCommandBuffer->vkCommandBuffer(); 860cb93a386Sopenharmony_ci vkInfo.fCompatibleRenderPass = fCurrentRenderPass->vkRenderPass(); 861cb93a386Sopenharmony_ci SkAssertResult(fCurrentRenderPass->colorAttachmentIndex(&vkInfo.fColorAttachmentIndex)); 862cb93a386Sopenharmony_ci vkInfo.fFormat = fFramebuffer->colorAttachment()->imageFormat(); 863cb93a386Sopenharmony_ci vkInfo.fDrawBounds = &bounds; 864cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK 865cb93a386Sopenharmony_ci vkInfo.fImage = fFramebuffer->colorAttachment()->image(); 866cb93a386Sopenharmony_ci#else 867cb93a386Sopenharmony_ci vkInfo.fImage = VK_NULL_HANDLE; 868cb93a386Sopenharmony_ci#endif //SK_BUILD_FOR_ANDROID_FRAMEWORK 869cb93a386Sopenharmony_ci 870cb93a386Sopenharmony_ci GrBackendDrawableInfo info(vkInfo); 871cb93a386Sopenharmony_ci 872cb93a386Sopenharmony_ci // After we draw into the command buffer via the drawable, cached state we have may be invalid. 873cb93a386Sopenharmony_ci this->currentCommandBuffer()->invalidateState(); 874cb93a386Sopenharmony_ci // Also assume that the drawable produced output. 875cb93a386Sopenharmony_ci fCurrentCBIsEmpty = false; 876cb93a386Sopenharmony_ci 877cb93a386Sopenharmony_ci drawable->draw(info); 878cb93a386Sopenharmony_ci fGpu->addDrawable(std::move(drawable)); 879cb93a386Sopenharmony_ci} 880cb93a386Sopenharmony_ci 881cb93a386Sopenharmony_ci 882cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////// 883cb93a386Sopenharmony_ci 884cb93a386Sopenharmony_civoid GrVkOpsRenderPass::onDrawBlurImage(const GrSurfaceProxyView& proxyView, const SkBlurArg& blurArg) 885cb93a386Sopenharmony_ci{ 886cb93a386Sopenharmony_ci if (!proxyView.proxy()) { 887cb93a386Sopenharmony_ci return; 888cb93a386Sopenharmony_ci } 889cb93a386Sopenharmony_ci 890cb93a386Sopenharmony_ci GrVkTexture* texture = static_cast<GrVkTexture*>(proxyView.proxy()->peekTexture()); 891cb93a386Sopenharmony_ci if (!texture) { 892cb93a386Sopenharmony_ci return; 893cb93a386Sopenharmony_ci } 894cb93a386Sopenharmony_ci GrVkImage* image = texture->textureImage(); 895cb93a386Sopenharmony_ci if (!image) { 896cb93a386Sopenharmony_ci return; 897cb93a386Sopenharmony_ci } 898cb93a386Sopenharmony_ci 899cb93a386Sopenharmony_ci HITRACE_OHOS_NAME_ALWAYS("DrawBlurImage"); 900cb93a386Sopenharmony_ci // reference textureop, resource's refcount should add. 901cb93a386Sopenharmony_ci fGpu->currentCommandBuffer()->addResource(image->textureView()); 902cb93a386Sopenharmony_ci fGpu->currentCommandBuffer()->addResource(image->resource()); 903cb93a386Sopenharmony_ci // OH ISSUE : fix hps blur, add GrSurface reference protection 904cb93a386Sopenharmony_ci fGpu->currentCommandBuffer()->addGrSurface(sk_ref_sp<const GrSurface>(texture)); 905cb93a386Sopenharmony_ci SkOriginInfo originInfo {}; 906cb93a386Sopenharmony_ci originInfo.imageOrigin = proxyView.origin(); 907cb93a386Sopenharmony_ci originInfo.rtOrigin = fOrigin; 908cb93a386Sopenharmony_ci fGpu->currentCommandBuffer()->drawBlurImage(fGpu, image, fFramebuffer->colorAttachment()->dimensions(), 909cb93a386Sopenharmony_ci originInfo, blurArg); 910cb93a386Sopenharmony_ci return; 911cb93a386Sopenharmony_ci} 912