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