blob: e88471038ddfd1b1b6618357d713f294fd0f39fe [file] [log] [blame]
egdaniel066df7c2016-06-08 14:02:27 -07001/*
2* Copyright 2016 Google Inc.
3*
4* Use of this source code is governed by a BSD-style license that can be
5* found in the LICENSE file.
6*/
7
Greg Daniel2d41d0d2019-08-26 11:08:51 -04008#include "src/gpu/vk/GrVkOpsRenderPass.h"
egdaniel066df7c2016-06-08 14:02:27 -07009
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "include/core/SkDrawable.h"
11#include "include/core/SkRect.h"
12#include "include/gpu/GrBackendDrawableInfo.h"
13#include "src/gpu/GrContextPriv.h"
14#include "src/gpu/GrFixedClip.h"
15#include "src/gpu/GrMesh.h"
16#include "src/gpu/GrOpFlushState.h"
17#include "src/gpu/GrPipeline.h"
18#include "src/gpu/GrRenderTargetPriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050019#include "src/gpu/vk/GrVkCommandBuffer.h"
20#include "src/gpu/vk/GrVkCommandPool.h"
21#include "src/gpu/vk/GrVkGpu.h"
22#include "src/gpu/vk/GrVkPipeline.h"
23#include "src/gpu/vk/GrVkRenderPass.h"
24#include "src/gpu/vk/GrVkRenderTarget.h"
25#include "src/gpu/vk/GrVkResourceProvider.h"
26#include "src/gpu/vk/GrVkSemaphore.h"
27#include "src/gpu/vk/GrVkTexture.h"
egdaniel066df7c2016-06-08 14:02:27 -070028
Brian Salomon5d8f1cc2019-04-24 09:03:53 -040029/////////////////////////////////////////////////////////////////////////////
30
Robert Phillips6b47c7d2017-08-29 07:24:09 -040031void get_vk_load_store_ops(GrLoadOp loadOpIn, GrStoreOp storeOpIn,
egdaniel066df7c2016-06-08 14:02:27 -070032 VkAttachmentLoadOp* loadOp, VkAttachmentStoreOp* storeOp) {
Robert Phillips95214472017-08-08 18:00:03 -040033 switch (loadOpIn) {
Robert Phillips6b47c7d2017-08-29 07:24:09 -040034 case GrLoadOp::kLoad:
egdaniel066df7c2016-06-08 14:02:27 -070035 *loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
egdaniel066df7c2016-06-08 14:02:27 -070036 break;
Robert Phillips6b47c7d2017-08-29 07:24:09 -040037 case GrLoadOp::kClear:
egdaniel9cb63402016-06-23 08:37:05 -070038 *loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
39 break;
Robert Phillips6b47c7d2017-08-29 07:24:09 -040040 case GrLoadOp::kDiscard:
egdaniel9cb63402016-06-23 08:37:05 -070041 *loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
42 break;
43 default:
44 SK_ABORT("Invalid LoadOp");
egdaniel066df7c2016-06-08 14:02:27 -070045 *loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
egdaniel9cb63402016-06-23 08:37:05 -070046 }
47
Robert Phillips95214472017-08-08 18:00:03 -040048 switch (storeOpIn) {
Robert Phillips6b47c7d2017-08-29 07:24:09 -040049 case GrStoreOp::kStore:
egdaniel066df7c2016-06-08 14:02:27 -070050 *storeOp = VK_ATTACHMENT_STORE_OP_STORE;
51 break;
Robert Phillips6b47c7d2017-08-29 07:24:09 -040052 case GrStoreOp::kDiscard:
egdaniel066df7c2016-06-08 14:02:27 -070053 *storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
54 break;
brianosman0bbc3712016-06-14 04:53:09 -070055 default:
egdaniel9cb63402016-06-23 08:37:05 -070056 SK_ABORT("Invalid StoreOp");
brianosman0bbc3712016-06-14 04:53:09 -070057 *storeOp = VK_ATTACHMENT_STORE_OP_STORE;
egdaniel066df7c2016-06-08 14:02:27 -070058 }
59}
60
Greg Daniel2d41d0d2019-08-26 11:08:51 -040061GrVkOpsRenderPass::GrVkOpsRenderPass(GrVkGpu* gpu) : fGpu(gpu) {}
Brian Salomonc293a292016-11-30 13:38:32 -050062
Greg Danielf0c681e2019-09-05 14:07:41 -040063void GrVkOpsRenderPass::init(const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
64 const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo,
65 const SkPMColor4f& clearColor) {
egdaniel9cb63402016-06-23 08:37:05 -070066
Greg Danielf0c681e2019-09-05 14:07:41 -040067 VkAttachmentLoadOp loadOp;
68 VkAttachmentStoreOp storeOp;
69 get_vk_load_store_ops(colorInfo.fLoadOp, colorInfo.fStoreOp,
70 &loadOp, &storeOp);
71 GrVkRenderPass::LoadStoreOps vkColorOps(loadOp, storeOp);
72
73 get_vk_load_store_ops(stencilInfo.fLoadOp, stencilInfo.fStoreOp,
74 &loadOp, &storeOp);
75 GrVkRenderPass::LoadStoreOps vkStencilOps(loadOp, storeOp);
Greg Daniel36a77ee2016-10-18 10:33:25 -040076
Robert Phillips19e51dc2017-08-09 09:30:51 -040077 GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(fRenderTarget);
Greg Danielf0c681e2019-09-05 14:07:41 -040078 GrVkImage* targetImage = vkRT->msaaImage() ? vkRT->msaaImage() : vkRT;
79
80 // Change layout of our render target so it can be used as the color attachment.
81 // TODO: If we know that we will never be blending or loading the attachment we could drop the
82 // VK_ACCESS_COLOR_ATTACHMENT_READ_BIT.
83 targetImage->setImageLayout(fGpu,
84 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
85 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
86 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
87 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
88 false);
89
90 // If we are using a stencil attachment we also need to update its layout
91 if (GrStencilAttachment* stencil = fRenderTarget->renderTargetPriv().getStencilAttachment()) {
92 GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil;
93 // We need the write and read access bits since we may load and store the stencil.
94 // The initial load happens in the VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT so we
95 // wait there.
96 vkStencil->setImageLayout(fGpu,
97 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
98 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
99 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
100 VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
101 false);
102 }
103
Robert Phillips19e51dc2017-08-09 09:30:51 -0400104 const GrVkResourceProvider::CompatibleRPHandle& rpHandle = vkRT->compatibleRenderPassHandle();
egdaniel066df7c2016-06-08 14:02:27 -0700105 if (rpHandle.isValid()) {
Greg Danielf0c681e2019-09-05 14:07:41 -0400106 fCurrentRenderPass = fGpu->resourceProvider().findRenderPass(rpHandle,
Greg Daniel36a77ee2016-10-18 10:33:25 -0400107 vkColorOps,
108 vkStencilOps);
egdaniel066df7c2016-06-08 14:02:27 -0700109 } else {
Greg Danielf0c681e2019-09-05 14:07:41 -0400110 fCurrentRenderPass = fGpu->resourceProvider().findRenderPass(*vkRT,
Greg Daniel36a77ee2016-10-18 10:33:25 -0400111 vkColorOps,
112 vkStencilOps);
egdaniel066df7c2016-06-08 14:02:27 -0700113 }
Greg Danielf0c681e2019-09-05 14:07:41 -0400114 SkASSERT(fCurrentRenderPass);
egdaniel066df7c2016-06-08 14:02:27 -0700115
Greg Danielf0c681e2019-09-05 14:07:41 -0400116 VkClearValue vkClearColor;
117 vkClearColor.color.float32[0] = clearColor[0];
118 vkClearColor.color.float32[1] = clearColor[1];
119 vkClearColor.color.float32[2] = clearColor[2];
120 vkClearColor.color.float32[3] = clearColor[3];
egdaniel9cb63402016-06-23 08:37:05 -0700121
Greg Danielf0c681e2019-09-05 14:07:41 -0400122 fGpu->beginRenderPass(fCurrentRenderPass, &vkClearColor, vkRT, fOrigin, fBounds);
Greg Daniela3c68df2018-03-16 13:46:53 -0400123
Greg Danielf0c681e2019-09-05 14:07:41 -0400124 fCurrentSecondaryCommandBuffer = fGpu->cmdPool()->findOrCreateSecondaryCommandBuffer(fGpu);
125 fCurrentSecondaryCommandBuffer->begin(fGpu, vkRT->framebuffer(), fCurrentRenderPass);
egdaniel066df7c2016-06-08 14:02:27 -0700126}
127
Greg Daniel2d41d0d2019-08-26 11:08:51 -0400128void GrVkOpsRenderPass::initWrapped() {
Greg Daniel070cbaf2019-01-03 17:35:54 -0500129 GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(fRenderTarget);
130 SkASSERT(vkRT->wrapsSecondaryCommandBuffer());
Greg Danielf0c681e2019-09-05 14:07:41 -0400131 fCurrentRenderPass = vkRT->externalRenderPass();
132 SkASSERT(fCurrentRenderPass);
133 fCurrentRenderPass->ref();
Greg Daniel070cbaf2019-01-03 17:35:54 -0500134
Greg Danielf0c681e2019-09-05 14:07:41 -0400135 fCurrentSecondaryCommandBuffer.reset(
Greg Daniel8daf3b72019-07-30 09:57:26 -0400136 GrVkSecondaryCommandBuffer::Create(vkRT->getExternalSecondaryCommandBuffer()));
Greg Danielf0c681e2019-09-05 14:07:41 -0400137 fCurrentSecondaryCommandBuffer->begin(fGpu, nullptr, fCurrentRenderPass);
Greg Daniel070cbaf2019-01-03 17:35:54 -0500138}
Brian Salomonc293a292016-11-30 13:38:32 -0500139
Greg Daniel2d41d0d2019-08-26 11:08:51 -0400140GrVkOpsRenderPass::~GrVkOpsRenderPass() {
Robert Phillips5b5d84c2018-08-09 15:12:18 -0400141 this->reset();
egdaniel066df7c2016-06-08 14:02:27 -0700142}
143
Greg Daniel2d41d0d2019-08-26 11:08:51 -0400144GrGpu* GrVkOpsRenderPass::gpu() { return fGpu; }
egdaniel9cb63402016-06-23 08:37:05 -0700145
Greg Danielf0c681e2019-09-05 14:07:41 -0400146GrVkCommandBuffer* GrVkOpsRenderPass::currentCommandBuffer() {
147 // TODO: In the future this function may return the GrVkGpu's primary command buffer.
148 SkASSERT(fCurrentSecondaryCommandBuffer);
149 return fCurrentSecondaryCommandBuffer.get();
150}
151
Greg Daniel2d41d0d2019-08-26 11:08:51 -0400152void GrVkOpsRenderPass::end() {
Greg Danielf0c681e2019-09-05 14:07:41 -0400153 if (fCurrentSecondaryCommandBuffer) {
154 fCurrentSecondaryCommandBuffer->end(fGpu);
Brian Salomonc293a292016-11-30 13:38:32 -0500155 }
egdaniel066df7c2016-06-08 14:02:27 -0700156}
157
Greg Daniel2d41d0d2019-08-26 11:08:51 -0400158void GrVkOpsRenderPass::submit() {
Brian Salomonc293a292016-11-30 13:38:32 -0500159 if (!fRenderTarget) {
160 return;
161 }
Robert Phillips19e51dc2017-08-09 09:30:51 -0400162
Greg Danielf0c681e2019-09-05 14:07:41 -0400163 // We don't want to actually submit the secondary command buffer if it is wrapped.
164 if (this->wrapsSecondaryCommandBuffer()) {
165 return;
Greg Daniel36a77ee2016-10-18 10:33:25 -0400166 }
Greg Danielf0c681e2019-09-05 14:07:41 -0400167
168 if (fCurrentSecondaryCommandBuffer) {
169 fGpu->submitSecondaryCommandBuffer(std::move(fCurrentSecondaryCommandBuffer));
170 }
171 fGpu->endRenderPass(fRenderTarget, fOrigin, fBounds);
egdaniel9cb63402016-06-23 08:37:05 -0700172}
173
Greg Daniel2d41d0d2019-08-26 11:08:51 -0400174void GrVkOpsRenderPass::set(GrRenderTarget* rt, GrSurfaceOrigin origin,
175 const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
Greg Danielb20d7e52019-09-03 13:54:39 -0400176 const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo,
177 const SkTArray<GrTextureProxy*, true>& sampledProxies) {
Robert Phillips5b5d84c2018-08-09 15:12:18 -0400178 SkASSERT(!fRenderTarget);
Robert Phillips9da87e02019-02-04 13:26:26 -0500179 SkASSERT(fGpu == rt->getContext()->priv().getGpu());
Robert Phillips5b5d84c2018-08-09 15:12:18 -0400180
Greg Danielb0c7ad12019-06-06 17:23:35 +0000181#ifdef SK_DEBUG
182 fIsActive = true;
183#endif
184
Robert Phillips5b5d84c2018-08-09 15:12:18 -0400185 this->INHERITED::set(rt, origin);
186
Greg Danielb20d7e52019-09-03 13:54:39 -0400187 for (int i = 0; i < sampledProxies.count(); ++i) {
188 if (sampledProxies[i]->isInstantiated()) {
189 GrVkTexture* vkTex = static_cast<GrVkTexture*>(sampledProxies[i]->peekTexture());
190 SkASSERT(vkTex);
191 vkTex->setImageLayout(
192 fGpu, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_SHADER_READ_BIT,
193 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, false);
194 }
195 }
196
Greg Daniel070cbaf2019-01-03 17:35:54 -0500197 if (this->wrapsSecondaryCommandBuffer()) {
198 this->initWrapped();
199 return;
200 }
201
Greg Danielf0c681e2019-09-05 14:07:41 -0400202 // TODO: This should be passed in via the GrOpsTask instead of always setting it to the full
203 // render target bounds.
204 fBounds = SkIRect::MakeWH(fRenderTarget->width(), fRenderTarget->height());
Robert Phillips5b5d84c2018-08-09 15:12:18 -0400205
Greg Danielf0c681e2019-09-05 14:07:41 -0400206 this->init(colorInfo, stencilInfo, colorInfo.fClearColor);
Robert Phillips5b5d84c2018-08-09 15:12:18 -0400207}
208
Greg Daniel2d41d0d2019-08-26 11:08:51 -0400209void GrVkOpsRenderPass::reset() {
Greg Danielf0c681e2019-09-05 14:07:41 -0400210 if (fCurrentSecondaryCommandBuffer) {
211 fCurrentSecondaryCommandBuffer.release()->recycle(fGpu);
Robert Phillips5b5d84c2018-08-09 15:12:18 -0400212 }
Greg Danielf0c681e2019-09-05 14:07:41 -0400213 if (fCurrentRenderPass) {
214 fCurrentRenderPass->unref(fGpu);
215 fCurrentRenderPass = nullptr;
216 }
217 fCurrentCBIsEmpty = true;
Robert Phillips5b5d84c2018-08-09 15:12:18 -0400218
Robert Phillips5b5d84c2018-08-09 15:12:18 -0400219 fRenderTarget = nullptr;
Greg Danielb0c7ad12019-06-06 17:23:35 +0000220
221#ifdef SK_DEBUG
222 fIsActive = false;
223#endif
Robert Phillips5b5d84c2018-08-09 15:12:18 -0400224}
225
Greg Daniel2d41d0d2019-08-26 11:08:51 -0400226bool GrVkOpsRenderPass::wrapsSecondaryCommandBuffer() const {
Greg Daniel070cbaf2019-01-03 17:35:54 -0500227 GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(fRenderTarget);
228 return vkRT->wrapsSecondaryCommandBuffer();
229}
230
Greg Daniel64cc9aa2018-10-19 13:54:56 -0400231////////////////////////////////////////////////////////////////////////////////
232
Greg Daniel2d41d0d2019-08-26 11:08:51 -0400233void GrVkOpsRenderPass::insertEventMarker(const char* msg) {
Robert Phillips65a88fa2017-08-08 08:36:22 -0400234 // TODO: does Vulkan have a correlate?
235}
236
Greg Daniel2d41d0d2019-08-26 11:08:51 -0400237void GrVkOpsRenderPass::onClearStencilClip(const GrFixedClip& clip, bool insideStencilMask) {
Chris Dalton94c04682017-11-01 17:15:06 -0600238 SkASSERT(!clip.hasWindowRectangles());
239
Greg Daniel65a09272016-10-12 09:47:22 -0400240 GrStencilAttachment* sb = fRenderTarget->renderTargetPriv().getStencilAttachment();
egdaniel9cb63402016-06-23 08:37:05 -0700241 // this should only be called internally when we know we have a
242 // stencil buffer.
243 SkASSERT(sb);
244 int stencilBitCount = sb->bits();
245
246 // The contract with the callers does not guarantee that we preserve all bits in the stencil
247 // during this clear. Thus we will clear the entire stencil to the desired value.
248
249 VkClearDepthStencilValue vkStencilColor;
250 memset(&vkStencilColor, 0, sizeof(VkClearDepthStencilValue));
csmartdalton29df7602016-08-31 11:55:52 -0700251 if (insideStencilMask) {
egdaniel9cb63402016-06-23 08:37:05 -0700252 vkStencilColor.stencil = (1 << (stencilBitCount - 1));
253 } else {
254 vkStencilColor.stencil = 0;
255 }
256
257 VkClearRect clearRect;
258 // Flip rect if necessary
csmartdalton29df7602016-08-31 11:55:52 -0700259 SkIRect vkRect;
Brian Salomond818ebf2018-07-02 14:08:49 +0000260 if (!clip.scissorEnabled()) {
Greg Daniela41a74a2018-10-09 12:59:23 +0000261 vkRect.setXYWH(0, 0, fRenderTarget->width(), fRenderTarget->height());
Robert Phillips4f101a72017-07-28 08:42:04 -0400262 } else if (kBottomLeft_GrSurfaceOrigin != fOrigin) {
csmartdalton29df7602016-08-31 11:55:52 -0700263 vkRect = clip.scissorRect();
264 } else {
265 const SkIRect& scissor = clip.scissorRect();
Greg Daniel65a09272016-10-12 09:47:22 -0400266 vkRect.setLTRB(scissor.fLeft, fRenderTarget->height() - scissor.fBottom,
267 scissor.fRight, fRenderTarget->height() - scissor.fTop);
egdaniel9cb63402016-06-23 08:37:05 -0700268 }
269
270 clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop };
271 clearRect.rect.extent = { (uint32_t)vkRect.width(), (uint32_t)vkRect.height() };
272
273 clearRect.baseArrayLayer = 0;
274 clearRect.layerCount = 1;
275
276 uint32_t stencilIndex;
Greg Danielf0c681e2019-09-05 14:07:41 -0400277 SkAssertResult(fCurrentRenderPass->stencilAttachmentIndex(&stencilIndex));
egdaniel9cb63402016-06-23 08:37:05 -0700278
279 VkClearAttachment attachment;
280 attachment.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
281 attachment.colorAttachment = 0; // this value shouldn't matter
282 attachment.clearValue.depthStencil = vkStencilColor;
283
Greg Danielf0c681e2019-09-05 14:07:41 -0400284 this->currentCommandBuffer()->clearAttachments(fGpu, 1, &attachment, 1, &clearRect);
285 fCurrentCBIsEmpty = false;
egdaniel9cb63402016-06-23 08:37:05 -0700286}
287
Greg Daniel2d41d0d2019-08-26 11:08:51 -0400288void GrVkOpsRenderPass::onClear(const GrFixedClip& clip, const SkPMColor4f& color) {
Jim Van Verth6a40abc2017-11-02 16:56:09 +0000289 // parent class should never let us get here with no RT
csmartdaltonbf4a8f92016-09-06 10:01:06 -0700290 SkASSERT(!clip.hasWindowRectangles());
egdaniel9cb63402016-06-23 08:37:05 -0700291
Brian Osman9a9baae2018-11-05 15:06:26 -0500292 VkClearColorValue vkColor = {{color.fR, color.fG, color.fB, color.fA}};
egdaniel9cb63402016-06-23 08:37:05 -0700293
Greg Daniel674ee742019-08-27 13:12:33 -0400294 // If we end up in a situation where we are calling clear without a scissior then in general it
295 // means we missed an opportunity higher up the stack to set the load op to be a clear. However,
296 // there are situations where higher up we couldn't discard the previous ops and set a clear
297 // load op (e.g. if we needed to execute a wait op). Thus we also have the empty check here.
Greg Daniel4fe92572019-09-03 11:16:40 -0400298 // TODO: Make the waitOp a RenderTask instead so we can clear out the GrOpsTask for a clear. We
299 // can then reenable this assert assuming we can't get messed up by a waitOp.
Greg Danielf0c681e2019-09-05 14:07:41 -0400300 //SkASSERT(!fCurrentCBIsEmpty || clip.scissorEnabled());
egdaniel9cb63402016-06-23 08:37:05 -0700301
302 // We always do a sub rect clear with clearAttachments since we are inside a render pass
303 VkClearRect clearRect;
304 // Flip rect if necessary
csmartdalton29df7602016-08-31 11:55:52 -0700305 SkIRect vkRect;
Brian Salomond818ebf2018-07-02 14:08:49 +0000306 if (!clip.scissorEnabled()) {
Greg Daniela41a74a2018-10-09 12:59:23 +0000307 vkRect.setXYWH(0, 0, fRenderTarget->width(), fRenderTarget->height());
Robert Phillips4f101a72017-07-28 08:42:04 -0400308 } else if (kBottomLeft_GrSurfaceOrigin != fOrigin) {
csmartdalton29df7602016-08-31 11:55:52 -0700309 vkRect = clip.scissorRect();
310 } else {
311 const SkIRect& scissor = clip.scissorRect();
Greg Daniel65a09272016-10-12 09:47:22 -0400312 vkRect.setLTRB(scissor.fLeft, fRenderTarget->height() - scissor.fBottom,
313 scissor.fRight, fRenderTarget->height() - scissor.fTop);
egdaniel9cb63402016-06-23 08:37:05 -0700314 }
315 clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop };
316 clearRect.rect.extent = { (uint32_t)vkRect.width(), (uint32_t)vkRect.height() };
317 clearRect.baseArrayLayer = 0;
318 clearRect.layerCount = 1;
319
320 uint32_t colorIndex;
Greg Danielf0c681e2019-09-05 14:07:41 -0400321 SkAssertResult(fCurrentRenderPass->colorAttachmentIndex(&colorIndex));
egdaniel9cb63402016-06-23 08:37:05 -0700322
323 VkClearAttachment attachment;
324 attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
325 attachment.colorAttachment = colorIndex;
326 attachment.clearValue.color = vkColor;
327
Greg Danielf0c681e2019-09-05 14:07:41 -0400328 this->currentCommandBuffer()->clearAttachments(fGpu, 1, &attachment, 1, &clearRect);
329 fCurrentCBIsEmpty = false;
egdaniel9cb63402016-06-23 08:37:05 -0700330 return;
331}
332
Greg Daniel500d58b2017-08-24 15:59:33 -0400333////////////////////////////////////////////////////////////////////////////////
334
Greg Daniel2d41d0d2019-08-26 11:08:51 -0400335void GrVkOpsRenderPass::addAdditionalRenderPass() {
Greg Danielf0c681e2019-09-05 14:07:41 -0400336 SkASSERT(!this->wrapsSecondaryCommandBuffer());
Robert Phillips19e51dc2017-08-09 09:30:51 -0400337 GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(fRenderTarget);
338
Greg Daniel77b53f62016-10-18 11:48:51 -0400339 GrVkRenderPass::LoadStoreOps vkColorOps(VK_ATTACHMENT_LOAD_OP_LOAD,
340 VK_ATTACHMENT_STORE_OP_STORE);
341 GrVkRenderPass::LoadStoreOps vkStencilOps(VK_ATTACHMENT_LOAD_OP_LOAD,
342 VK_ATTACHMENT_STORE_OP_STORE);
343
344 const GrVkResourceProvider::CompatibleRPHandle& rpHandle =
Robert Phillips19e51dc2017-08-09 09:30:51 -0400345 vkRT->compatibleRenderPassHandle();
Greg Danielf0c681e2019-09-05 14:07:41 -0400346 SkASSERT(fCurrentRenderPass);
347 fCurrentRenderPass->unref(fGpu);
Greg Daniel77b53f62016-10-18 11:48:51 -0400348 if (rpHandle.isValid()) {
Greg Danielf0c681e2019-09-05 14:07:41 -0400349 fCurrentRenderPass = fGpu->resourceProvider().findRenderPass(rpHandle,
Greg Daniel77b53f62016-10-18 11:48:51 -0400350 vkColorOps,
351 vkStencilOps);
352 } else {
Greg Danielf0c681e2019-09-05 14:07:41 -0400353 fCurrentRenderPass = fGpu->resourceProvider().findRenderPass(*vkRT,
Greg Daniel77b53f62016-10-18 11:48:51 -0400354 vkColorOps,
355 vkStencilOps);
356 }
Greg Danielf0c681e2019-09-05 14:07:41 -0400357 SkASSERT(fCurrentRenderPass);
Greg Daniel77b53f62016-10-18 11:48:51 -0400358
Greg Danielf0c681e2019-09-05 14:07:41 -0400359 VkClearValue vkClearColor;
360 memset(&vkClearColor, 0, sizeof(VkClearValue));
361 // We use the same fBounds as the whole GrVkOpsRenderPass since we have no way of tracking the
362 // bounds in GrOpsTask for parts before and after inline uploads separately.
363 fGpu->beginRenderPass(fCurrentRenderPass, &vkClearColor, vkRT, fOrigin, fBounds);
Greg Daniel77b53f62016-10-18 11:48:51 -0400364
Greg Danielf0c681e2019-09-05 14:07:41 -0400365 fCurrentSecondaryCommandBuffer = fGpu->cmdPool()->findOrCreateSecondaryCommandBuffer(fGpu);
366 fCurrentSecondaryCommandBuffer->begin(fGpu, vkRT->framebuffer(), fCurrentRenderPass);
Greg Daniel77b53f62016-10-18 11:48:51 -0400367}
368
Greg Daniel2d41d0d2019-08-26 11:08:51 -0400369void GrVkOpsRenderPass::inlineUpload(GrOpFlushState* state,
Brian Salomon943ed792017-10-30 09:37:55 -0400370 GrDeferredTextureUploadFn& upload) {
Greg Danielf0c681e2019-09-05 14:07:41 -0400371 if (fCurrentSecondaryCommandBuffer) {
372 fCurrentSecondaryCommandBuffer->end(fGpu);
373 fGpu->submitSecondaryCommandBuffer(std::move(fCurrentSecondaryCommandBuffer));
Greg Daniel77b53f62016-10-18 11:48:51 -0400374 }
Greg Danielf0c681e2019-09-05 14:07:41 -0400375 fGpu->endRenderPass(fRenderTarget, fOrigin, fBounds);
Brian Salomon24d377e2019-04-23 15:24:31 -0400376
Greg Danielf0c681e2019-09-05 14:07:41 -0400377 // We pass in true here to signal that after the upload we need to set the upload textures
378 // layout back to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL.
379 state->doUpload(upload, true);
380
381 this->addAdditionalRenderPass();
Greg Daniel77b53f62016-10-18 11:48:51 -0400382}
383
egdaniel9cb63402016-06-23 08:37:05 -0700384////////////////////////////////////////////////////////////////////////////////
385
Greg Daniel2d41d0d2019-08-26 11:08:51 -0400386void GrVkOpsRenderPass::bindGeometry(const GrGpuBuffer* indexBuffer,
Brian Salomondbf70722019-02-07 11:31:24 -0500387 const GrGpuBuffer* vertexBuffer,
388 const GrGpuBuffer* instanceBuffer) {
Greg Danielf0c681e2019-09-05 14:07:41 -0400389 GrVkCommandBuffer* currCmdBuf = this->currentCommandBuffer();
egdaniel9cb63402016-06-23 08:37:05 -0700390 // There is no need to put any memory barriers to make sure host writes have finished here.
391 // When a command buffer is submitted to a queue, there is an implicit memory barrier that
392 // occurs for all host writes. Additionally, BufferMemoryBarriers are not allowed inside of
393 // an active RenderPass.
egdaniel9cb63402016-06-23 08:37:05 -0700394
Chris Dalton1d616352017-05-31 12:51:23 -0600395 // Here our vertex and instance inputs need to match the same 0-based bindings they were
396 // assigned in GrVkPipeline. That is, vertex first (if any) followed by instance.
397 uint32_t binding = 0;
398
Brian Salomon802cb312018-06-08 18:05:20 -0400399 if (vertexBuffer) {
Chris Dalton1d616352017-05-31 12:51:23 -0600400 SkASSERT(vertexBuffer);
Chris Dalton1d616352017-05-31 12:51:23 -0600401 SkASSERT(!vertexBuffer->isMapped());
402
403 currCmdBuf->bindInputBuffer(fGpu, binding++,
404 static_cast<const GrVkVertexBuffer*>(vertexBuffer));
405 }
406
Brian Salomon802cb312018-06-08 18:05:20 -0400407 if (instanceBuffer) {
Chris Dalton1d616352017-05-31 12:51:23 -0600408 SkASSERT(instanceBuffer);
Chris Dalton1d616352017-05-31 12:51:23 -0600409 SkASSERT(!instanceBuffer->isMapped());
410
411 currCmdBuf->bindInputBuffer(fGpu, binding++,
412 static_cast<const GrVkVertexBuffer*>(instanceBuffer));
413 }
Chris Daltonff926502017-05-03 14:36:54 -0400414 if (indexBuffer) {
415 SkASSERT(indexBuffer);
416 SkASSERT(!indexBuffer->isMapped());
egdaniel9cb63402016-06-23 08:37:05 -0700417
Chris Daltonff926502017-05-03 14:36:54 -0400418 currCmdBuf->bindIndexBuffer(fGpu, static_cast<const GrVkIndexBuffer*>(indexBuffer));
egdaniel9cb63402016-06-23 08:37:05 -0700419 }
420}
421
Greg Daniel2d41d0d2019-08-26 11:08:51 -0400422GrVkPipelineState* GrVkOpsRenderPass::prepareDrawState(
Brian Salomon49348902018-06-26 09:12:38 -0400423 const GrPrimitiveProcessor& primProc,
424 const GrPipeline& pipeline,
425 const GrPipeline::FixedDynamicState* fixedDynamicState,
426 const GrPipeline::DynamicStateArrays* dynamicStateArrays,
427 GrPrimitiveType primitiveType) {
Greg Danielf0c681e2019-09-05 14:07:41 -0400428 GrVkCommandBuffer* currentCB = this->currentCommandBuffer();
429 SkASSERT(fCurrentRenderPass);
Greg Daniel36a77ee2016-10-18 10:33:25 -0400430
Greg Danielf0c681e2019-09-05 14:07:41 -0400431 VkRenderPass compatibleRenderPass = fCurrentRenderPass->vkRenderPass();
Greg Daniel99b88e02018-10-03 15:31:20 -0400432
Greg Daniel9a51a862018-11-30 10:18:14 -0500433 const GrTextureProxy* const* primProcProxies = nullptr;
434 if (dynamicStateArrays && dynamicStateArrays->fPrimitiveProcessorTextures) {
435 primProcProxies = dynamicStateArrays->fPrimitiveProcessorTextures;
436 } else if (fixedDynamicState) {
437 primProcProxies = fixedDynamicState->fPrimitiveProcessorTextures;
438 }
439
440 SkASSERT(SkToBool(primProcProxies) == SkToBool(primProc.numTextureSamplers()));
441
Greg Daniel09eeefb2017-10-16 15:15:02 -0400442 GrVkPipelineState* pipelineState =
Robert Phillipsd0fe8752019-01-31 14:13:59 -0500443 fGpu->resourceProvider().findOrCreateCompatiblePipelineState(fRenderTarget, fOrigin,
444 pipeline,
egdaniel9cb63402016-06-23 08:37:05 -0700445 primProc,
Greg Daniel9a51a862018-11-30 10:18:14 -0500446 primProcProxies,
egdaniel9cb63402016-06-23 08:37:05 -0700447 primitiveType,
Greg Daniel99b88e02018-10-03 15:31:20 -0400448 compatibleRenderPass);
egdaniel9cb63402016-06-23 08:37:05 -0700449 if (!pipelineState) {
450 return pipelineState;
451 }
452
Greg Danielf0c681e2019-09-05 14:07:41 -0400453 pipelineState->bindPipeline(fGpu, currentCB);
Greg Daniel22bc8652017-03-22 15:45:43 -0400454
Greg Danielf0c681e2019-09-05 14:07:41 -0400455 pipelineState->setAndBindUniforms(fGpu, fRenderTarget, fOrigin, primProc, pipeline, currentCB);
Brian Salomonf7232642018-09-19 08:58:08 -0400456
457 // Check whether we need to bind textures between each GrMesh. If not we can bind them all now.
458 bool setTextures = !(dynamicStateArrays && dynamicStateArrays->fPrimitiveProcessorTextures);
459 if (setTextures) {
Greg Danielf0c681e2019-09-05 14:07:41 -0400460 pipelineState->setAndBindTextures(fGpu, primProc, pipeline, primProcProxies, currentCB);
Brian Salomonf7232642018-09-19 08:58:08 -0400461 }
egdaniel9cb63402016-06-23 08:37:05 -0700462
Brian Salomond818ebf2018-07-02 14:08:49 +0000463 if (!pipeline.isScissorEnabled()) {
Greg Danielf0c681e2019-09-05 14:07:41 -0400464 GrVkPipeline::SetDynamicScissorRectState(fGpu, currentCB, fRenderTarget, fOrigin,
Robert Phillipsd0fe8752019-01-31 14:13:59 -0500465 SkIRect::MakeWH(fRenderTarget->width(),
466 fRenderTarget->height()));
Brian Salomon49348902018-06-26 09:12:38 -0400467 } else if (!dynamicStateArrays || !dynamicStateArrays->fScissorRects) {
468 SkASSERT(fixedDynamicState);
Greg Danielf0c681e2019-09-05 14:07:41 -0400469 GrVkPipeline::SetDynamicScissorRectState(fGpu, currentCB, fRenderTarget, fOrigin,
Brian Salomon49348902018-06-26 09:12:38 -0400470 fixedDynamicState->fScissorRect);
Chris Dalton46983b72017-06-06 12:27:16 -0600471 }
Greg Danielf0c681e2019-09-05 14:07:41 -0400472 GrVkPipeline::SetDynamicViewportState(fGpu, currentCB, fRenderTarget);
473 GrVkPipeline::SetDynamicBlendConstantState(fGpu, currentCB, pipeline.outputSwizzle(),
Chris Dalton46983b72017-06-06 12:27:16 -0600474 pipeline.getXferProcessor());
egdaniel9cb63402016-06-23 08:37:05 -0700475
476 return pipelineState;
477}
478
Greg Danielb20d7e52019-09-03 13:54:39 -0400479#ifdef SK_DEBUG
480void check_sampled_texture(GrTexture* tex, GrRenderTarget* rt, GrVkGpu* gpu) {
481 SkASSERT(!tex->isProtected() || (rt->isProtected() && gpu->protectedContext()));
482 GrVkTexture* vkTex = static_cast<GrVkTexture*>(tex);
483 SkASSERT(vkTex->currentLayout() == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
484}
485#endif
486
487
Greg Daniel2d41d0d2019-08-26 11:08:51 -0400488void GrVkOpsRenderPass::onDraw(const GrPrimitiveProcessor& primProc,
Brian Salomonff168d92018-06-23 15:17:27 -0400489 const GrPipeline& pipeline,
Brian Salomon49348902018-06-26 09:12:38 -0400490 const GrPipeline::FixedDynamicState* fixedDynamicState,
491 const GrPipeline::DynamicStateArrays* dynamicStateArrays,
Greg Daniel500d58b2017-08-24 15:59:33 -0400492 const GrMesh meshes[],
Greg Daniel500d58b2017-08-24 15:59:33 -0400493 int meshCount,
494 const SkRect& bounds) {
egdaniel9cb63402016-06-23 08:37:05 -0700495 if (!meshCount) {
496 return;
497 }
Greg Danielea022cd2018-03-16 11:10:03 -0400498
Greg Danielb20d7e52019-09-03 13:54:39 -0400499#ifdef SK_DEBUG
Brian Salomonf7232642018-09-19 08:58:08 -0400500 if (dynamicStateArrays && dynamicStateArrays->fPrimitiveProcessorTextures) {
501 for (int m = 0, i = 0; m < meshCount; ++m) {
502 for (int s = 0; s < primProc.numTextureSamplers(); ++s, ++i) {
503 auto texture = dynamicStateArrays->fPrimitiveProcessorTextures[i]->peekTexture();
Greg Danielb20d7e52019-09-03 13:54:39 -0400504 check_sampled_texture(texture, fRenderTarget, fGpu);
Brian Salomonf7232642018-09-19 08:58:08 -0400505 }
506 }
507 } else {
508 for (int i = 0; i < primProc.numTextureSamplers(); ++i) {
509 auto texture = fixedDynamicState->fPrimitiveProcessorTextures[i]->peekTexture();
Greg Danielb20d7e52019-09-03 13:54:39 -0400510 check_sampled_texture(texture, fRenderTarget, fGpu);
Brian Salomonf7232642018-09-19 08:58:08 -0400511 }
Brian Salomone782f842018-07-31 13:53:11 -0400512 }
bsalomonb58a2b42016-09-26 06:55:02 -0700513 GrFragmentProcessor::Iter iter(pipeline);
514 while (const GrFragmentProcessor* fp = iter.next()) {
Brian Salomone782f842018-07-31 13:53:11 -0400515 for (int i = 0; i < fp->numTextureSamplers(); ++i) {
516 const GrFragmentProcessor::TextureSampler& sampler = fp->textureSampler(i);
Greg Danielb20d7e52019-09-03 13:54:39 -0400517 check_sampled_texture(sampler.peekTexture(), fRenderTarget, fGpu);
Brian Salomone782f842018-07-31 13:53:11 -0400518 }
egdaniel2f5792a2016-07-06 08:51:23 -0700519 }
Robert Phillipsbb581ce2017-05-29 15:05:15 -0400520 if (GrTexture* dstTexture = pipeline.peekDstTexture()) {
Greg Danielb20d7e52019-09-03 13:54:39 -0400521 check_sampled_texture(dstTexture, fRenderTarget, fGpu);
Brian Salomon18dfa982017-04-03 16:57:43 -0400522 }
Greg Danielb20d7e52019-09-03 13:54:39 -0400523#endif
egdaniel2f5792a2016-07-06 08:51:23 -0700524
Chris Daltonbca46e22017-05-15 11:03:26 -0600525 GrPrimitiveType primitiveType = meshes[0].primitiveType();
Brian Salomon49348902018-06-26 09:12:38 -0400526 GrVkPipelineState* pipelineState = this->prepareDrawState(primProc, pipeline, fixedDynamicState,
527 dynamicStateArrays, primitiveType);
egdaniel9cb63402016-06-23 08:37:05 -0700528 if (!pipelineState) {
529 return;
530 }
531
Brian Salomond818ebf2018-07-02 14:08:49 +0000532 bool dynamicScissor =
533 pipeline.isScissorEnabled() && dynamicStateArrays && dynamicStateArrays->fScissorRects;
Brian Salomonf7232642018-09-19 08:58:08 -0400534 bool dynamicTextures = dynamicStateArrays && dynamicStateArrays->fPrimitiveProcessorTextures;
Brian Salomon49348902018-06-26 09:12:38 -0400535
egdaniel9cb63402016-06-23 08:37:05 -0700536 for (int i = 0; i < meshCount; ++i) {
537 const GrMesh& mesh = meshes[i];
Chris Daltonbca46e22017-05-15 11:03:26 -0600538 if (mesh.primitiveType() != primitiveType) {
Chris Dalton6f241802017-05-08 13:58:38 -0400539 SkDEBUGCODE(pipelineState = nullptr);
Chris Daltonbca46e22017-05-15 11:03:26 -0600540 primitiveType = mesh.primitiveType();
Brian Salomon49348902018-06-26 09:12:38 -0400541 pipelineState = this->prepareDrawState(primProc, pipeline, fixedDynamicState,
542 dynamicStateArrays, primitiveType);
Chris Dalton6f241802017-05-08 13:58:38 -0400543 if (!pipelineState) {
544 return;
egdaniel9cb63402016-06-23 08:37:05 -0700545 }
Chris Dalton6f241802017-05-08 13:58:38 -0400546 }
egdaniel9cb63402016-06-23 08:37:05 -0700547
Brian Salomon49348902018-06-26 09:12:38 -0400548 if (dynamicScissor) {
Greg Danielf0c681e2019-09-05 14:07:41 -0400549 GrVkPipeline::SetDynamicScissorRectState(fGpu, this->currentCommandBuffer(),
550 fRenderTarget, fOrigin,
Brian Salomon49348902018-06-26 09:12:38 -0400551 dynamicStateArrays->fScissorRects[i]);
Chris Dalton46983b72017-06-06 12:27:16 -0600552 }
Brian Salomonf7232642018-09-19 08:58:08 -0400553 if (dynamicTextures) {
554 GrTextureProxy* const* meshProxies = dynamicStateArrays->fPrimitiveProcessorTextures +
555 primProc.numTextureSamplers() * i;
556 pipelineState->setAndBindTextures(fGpu, primProc, pipeline, meshProxies,
Greg Danielf0c681e2019-09-05 14:07:41 -0400557 this->currentCommandBuffer());
Brian Salomonf7232642018-09-19 08:58:08 -0400558 }
Chris Daltonbca46e22017-05-15 11:03:26 -0600559 SkASSERT(pipelineState);
Brian Salomon802cb312018-06-08 18:05:20 -0400560 mesh.sendToGpu(this);
egdaniel9cb63402016-06-23 08:37:05 -0700561 }
562
Greg Danielf0c681e2019-09-05 14:07:41 -0400563 fCurrentCBIsEmpty = false;
egdaniel066df7c2016-06-08 14:02:27 -0700564}
565
Greg Daniel2d41d0d2019-08-26 11:08:51 -0400566void GrVkOpsRenderPass::sendInstancedMeshToGpu(GrPrimitiveType,
567 const GrBuffer* vertexBuffer,
568 int vertexCount,
569 int baseVertex,
570 const GrBuffer* instanceBuffer,
571 int instanceCount,
572 int baseInstance) {
Brian Salomondbf70722019-02-07 11:31:24 -0500573 SkASSERT(!vertexBuffer || !vertexBuffer->isCpuBuffer());
574 SkASSERT(!instanceBuffer || !instanceBuffer->isCpuBuffer());
575 auto gpuVertexBuffer = static_cast<const GrGpuBuffer*>(vertexBuffer);
576 auto gpuInstanceBuffer = static_cast<const GrGpuBuffer*>(instanceBuffer);
577 this->bindGeometry(nullptr, gpuVertexBuffer, gpuInstanceBuffer);
Greg Danielf0c681e2019-09-05 14:07:41 -0400578 this->currentCommandBuffer()->draw(fGpu, vertexCount, instanceCount, baseVertex, baseInstance);
Chris Dalton114a3c02017-05-26 15:17:19 -0600579 fGpu->stats()->incNumDraws();
580}
581
Greg Daniel2d41d0d2019-08-26 11:08:51 -0400582void GrVkOpsRenderPass::sendIndexedInstancedMeshToGpu(GrPrimitiveType,
583 const GrBuffer* indexBuffer,
584 int indexCount,
585 int baseIndex,
586 const GrBuffer* vertexBuffer,
587 int baseVertex,
588 const GrBuffer* instanceBuffer,
589 int instanceCount,
590 int baseInstance,
591 GrPrimitiveRestart restart) {
Brian Salomon802cb312018-06-08 18:05:20 -0400592 SkASSERT(restart == GrPrimitiveRestart::kNo);
Brian Salomondbf70722019-02-07 11:31:24 -0500593 SkASSERT(!vertexBuffer || !vertexBuffer->isCpuBuffer());
594 SkASSERT(!instanceBuffer || !instanceBuffer->isCpuBuffer());
595 SkASSERT(!indexBuffer->isCpuBuffer());
596 auto gpuIndexxBuffer = static_cast<const GrGpuBuffer*>(indexBuffer);
597 auto gpuVertexBuffer = static_cast<const GrGpuBuffer*>(vertexBuffer);
598 auto gpuInstanceBuffer = static_cast<const GrGpuBuffer*>(instanceBuffer);
599 this->bindGeometry(gpuIndexxBuffer, gpuVertexBuffer, gpuInstanceBuffer);
Greg Danielf0c681e2019-09-05 14:07:41 -0400600 this->currentCommandBuffer()->drawIndexed(fGpu, indexCount, instanceCount,
601 baseIndex, baseVertex, baseInstance);
Chris Dalton114a3c02017-05-26 15:17:19 -0600602 fGpu->stats()->incNumDraws();
603}
Greg Daniel64cc9aa2018-10-19 13:54:56 -0400604
605////////////////////////////////////////////////////////////////////////////////
606
Greg Daniel2d41d0d2019-08-26 11:08:51 -0400607void GrVkOpsRenderPass::executeDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler> drawable) {
Greg Daniel64cc9aa2018-10-19 13:54:56 -0400608 GrVkRenderTarget* target = static_cast<GrVkRenderTarget*>(fRenderTarget);
609
610 GrVkImage* targetImage = target->msaaImage() ? target->msaaImage() : target;
611
Greg Daniel64cc9aa2018-10-19 13:54:56 -0400612 VkRect2D bounds;
613 bounds.offset = { 0, 0 };
614 bounds.extent = { 0, 0 };
615
Greg Danielf0c681e2019-09-05 14:07:41 -0400616 SkASSERT(fCurrentSecondaryCommandBuffer);
617
Greg Daniel64cc9aa2018-10-19 13:54:56 -0400618 GrVkDrawableInfo vkInfo;
Greg Danielf0c681e2019-09-05 14:07:41 -0400619 vkInfo.fSecondaryCommandBuffer = fCurrentSecondaryCommandBuffer->vkCommandBuffer();
620 vkInfo.fCompatibleRenderPass = fCurrentRenderPass->vkRenderPass();
621 SkAssertResult(fCurrentRenderPass->colorAttachmentIndex(&vkInfo.fColorAttachmentIndex));
Greg Daniel64cc9aa2018-10-19 13:54:56 -0400622 vkInfo.fFormat = targetImage->imageFormat();
623 vkInfo.fDrawBounds = &bounds;
Stan Ilievcb580602019-02-26 11:36:07 -0500624#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
625 vkInfo.fImage = targetImage->image();
626#else
627 vkInfo.fImage = VK_NULL_HANDLE;
628#endif //SK_BUILD_FOR_ANDROID_FRAMEWORK
Greg Daniel64cc9aa2018-10-19 13:54:56 -0400629
630 GrBackendDrawableInfo info(vkInfo);
631
Eric Karlc0b2ba22019-01-22 19:40:35 -0800632 // After we draw into the command buffer via the drawable, cached state we have may be invalid.
Greg Danielf0c681e2019-09-05 14:07:41 -0400633 this->currentCommandBuffer()->invalidateState();
Eric Karla8878a12019-02-07 18:17:43 -0800634 // Also assume that the drawable produced output.
Greg Danielf0c681e2019-09-05 14:07:41 -0400635 fCurrentCBIsEmpty = false;
Eric Karlc0b2ba22019-01-22 19:40:35 -0800636
Greg Daniel64cc9aa2018-10-19 13:54:56 -0400637 drawable->draw(info);
638 fGpu->addDrawable(std::move(drawable));
Greg Daniel64cc9aa2018-10-19 13:54:56 -0400639}
640