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