blob: faeba926b07009e327197c0c609fd5df2e58b29c [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
8#include "GrVkGpuCommandBuffer.h"
9
Greg Daniel64cc9aa2018-10-19 13:54:56 -040010#include "GrBackendDrawableInfo.h"
csmartdalton29df7602016-08-31 11:55:52 -070011#include "GrFixedClip.h"
egdaniel9cb63402016-06-23 08:37:05 -070012#include "GrMesh.h"
Brian Salomon742e31d2016-12-07 17:06:19 -050013#include "GrOpFlushState.h"
egdaniel9cb63402016-06-23 08:37:05 -070014#include "GrPipeline.h"
15#include "GrRenderTargetPriv.h"
egdaniel9cb63402016-06-23 08:37:05 -070016#include "GrTexturePriv.h"
egdaniel066df7c2016-06-08 14:02:27 -070017#include "GrVkCommandBuffer.h"
Ethan Nicholas8e265a72018-12-12 16:22:40 -050018#include "GrVkCommandPool.h"
egdaniel066df7c2016-06-08 14:02:27 -070019#include "GrVkGpu.h"
egdaniel9cb63402016-06-23 08:37:05 -070020#include "GrVkPipeline.h"
egdaniel066df7c2016-06-08 14:02:27 -070021#include "GrVkRenderPass.h"
22#include "GrVkRenderTarget.h"
23#include "GrVkResourceProvider.h"
Greg Daniel64cc9aa2018-10-19 13:54:56 -040024#include "GrVkSemaphore.h"
egdaniel9cb63402016-06-23 08:37:05 -070025#include "GrVkTexture.h"
Greg Daniel64cc9aa2018-10-19 13:54:56 -040026#include "SkDrawable.h"
Greg Daniel36a77ee2016-10-18 10:33:25 -040027#include "SkRect.h"
egdaniel066df7c2016-06-08 14:02:27 -070028
Robert Phillipsb0e93a22017-08-29 08:26:54 -040029void GrVkGpuTextureCommandBuffer::copy(GrSurface* src, GrSurfaceOrigin srcOrigin,
30 const SkIRect& srcRect, const SkIPoint& dstPoint) {
31 fCopies.emplace_back(src, srcOrigin, srcRect, dstPoint);
Greg Daniel500d58b2017-08-24 15:59:33 -040032}
33
34void GrVkGpuTextureCommandBuffer::insertEventMarker(const char* msg) {
35 // TODO: does Vulkan have a correlate?
36}
37
38void GrVkGpuTextureCommandBuffer::submit() {
39 for (int i = 0; i < fCopies.count(); ++i) {
40 CopyInfo& copyInfo = fCopies[i];
Robert Phillipsb0e93a22017-08-29 08:26:54 -040041 fGpu->copySurface(fTexture, fOrigin, copyInfo.fSrc, copyInfo.fSrcOrigin, copyInfo.fSrcRect,
42 copyInfo.fDstPoint);
Greg Daniel500d58b2017-08-24 15:59:33 -040043 }
44}
45
46GrVkGpuTextureCommandBuffer::~GrVkGpuTextureCommandBuffer() {}
47
48////////////////////////////////////////////////////////////////////////////////
49
Robert Phillips6b47c7d2017-08-29 07:24:09 -040050void get_vk_load_store_ops(GrLoadOp loadOpIn, GrStoreOp storeOpIn,
egdaniel066df7c2016-06-08 14:02:27 -070051 VkAttachmentLoadOp* loadOp, VkAttachmentStoreOp* storeOp) {
Robert Phillips95214472017-08-08 18:00:03 -040052 switch (loadOpIn) {
Robert Phillips6b47c7d2017-08-29 07:24:09 -040053 case GrLoadOp::kLoad:
egdaniel066df7c2016-06-08 14:02:27 -070054 *loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
egdaniel066df7c2016-06-08 14:02:27 -070055 break;
Robert Phillips6b47c7d2017-08-29 07:24:09 -040056 case GrLoadOp::kClear:
egdaniel9cb63402016-06-23 08:37:05 -070057 *loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
58 break;
Robert Phillips6b47c7d2017-08-29 07:24:09 -040059 case GrLoadOp::kDiscard:
egdaniel9cb63402016-06-23 08:37:05 -070060 *loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
61 break;
62 default:
63 SK_ABORT("Invalid LoadOp");
egdaniel066df7c2016-06-08 14:02:27 -070064 *loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
egdaniel9cb63402016-06-23 08:37:05 -070065 }
66
Robert Phillips95214472017-08-08 18:00:03 -040067 switch (storeOpIn) {
Robert Phillips6b47c7d2017-08-29 07:24:09 -040068 case GrStoreOp::kStore:
egdaniel066df7c2016-06-08 14:02:27 -070069 *storeOp = VK_ATTACHMENT_STORE_OP_STORE;
70 break;
Robert Phillips6b47c7d2017-08-29 07:24:09 -040071 case GrStoreOp::kDiscard:
egdaniel066df7c2016-06-08 14:02:27 -070072 *storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
73 break;
brianosman0bbc3712016-06-14 04:53:09 -070074 default:
egdaniel9cb63402016-06-23 08:37:05 -070075 SK_ABORT("Invalid StoreOp");
brianosman0bbc3712016-06-14 04:53:09 -070076 *storeOp = VK_ATTACHMENT_STORE_OP_STORE;
egdaniel066df7c2016-06-08 14:02:27 -070077 }
78}
79
Robert Phillips5b5d84c2018-08-09 15:12:18 -040080GrVkGpuRTCommandBuffer::GrVkGpuRTCommandBuffer(GrVkGpu* gpu)
81 : fCurrentCmdInfo(-1)
Robert Phillips19e51dc2017-08-09 09:30:51 -040082 , fGpu(gpu)
Robert Phillips19e51dc2017-08-09 09:30:51 -040083 , fLastPipelineState(nullptr) {
Brian Salomonc293a292016-11-30 13:38:32 -050084}
85
Greg Daniel500d58b2017-08-24 15:59:33 -040086void GrVkGpuRTCommandBuffer::init() {
Brian Salomonc293a292016-11-30 13:38:32 -050087 GrVkRenderPass::LoadStoreOps vkColorOps(fVkColorLoadOp, fVkColorStoreOp);
88 GrVkRenderPass::LoadStoreOps vkStencilOps(fVkStencilLoadOp, fVkStencilStoreOp);
egdaniel9cb63402016-06-23 08:37:05 -070089
Greg Daniel36a77ee2016-10-18 10:33:25 -040090 CommandBufferInfo& cbInfo = fCommandBufferInfos.push_back();
Brian Salomonc293a292016-11-30 13:38:32 -050091 SkASSERT(fCommandBufferInfos.count() == 1);
Greg Daniel22bc8652017-03-22 15:45:43 -040092 fCurrentCmdInfo = 0;
Greg Daniel36a77ee2016-10-18 10:33:25 -040093
Robert Phillips19e51dc2017-08-09 09:30:51 -040094 GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(fRenderTarget);
95 const GrVkResourceProvider::CompatibleRPHandle& rpHandle = vkRT->compatibleRenderPassHandle();
egdaniel066df7c2016-06-08 14:02:27 -070096 if (rpHandle.isValid()) {
Greg Daniel36a77ee2016-10-18 10:33:25 -040097 cbInfo.fRenderPass = fGpu->resourceProvider().findRenderPass(rpHandle,
98 vkColorOps,
99 vkStencilOps);
egdaniel066df7c2016-06-08 14:02:27 -0700100 } else {
Robert Phillips19e51dc2017-08-09 09:30:51 -0400101 cbInfo.fRenderPass = fGpu->resourceProvider().findRenderPass(*vkRT,
Greg Daniel36a77ee2016-10-18 10:33:25 -0400102 vkColorOps,
103 vkStencilOps);
egdaniel066df7c2016-06-08 14:02:27 -0700104 }
105
Brian Osmancb3d0872018-10-16 15:19:28 -0400106 cbInfo.fColorClearValue.color.float32[0] = fClearColor[0];
107 cbInfo.fColorClearValue.color.float32[1] = fClearColor[1];
108 cbInfo.fColorClearValue.color.float32[2] = fClearColor[2];
109 cbInfo.fColorClearValue.color.float32[3] = fClearColor[3];
egdaniel9cb63402016-06-23 08:37:05 -0700110
Robert Phillips380b90c2017-08-30 07:41:07 -0400111 if (VK_ATTACHMENT_LOAD_OP_CLEAR == fVkColorLoadOp) {
Greg Daniela41a74a2018-10-09 12:59:23 +0000112 cbInfo.fBounds = SkRect::MakeWH(vkRT->width(), vkRT->height());
Robert Phillips380b90c2017-08-30 07:41:07 -0400113 } else {
114 cbInfo.fBounds.setEmpty();
115 }
Greg Daniela3c68df2018-03-16 13:46:53 -0400116
117 if (VK_ATTACHMENT_LOAD_OP_CLEAR == fVkColorLoadOp) {
118 cbInfo.fLoadStoreState = LoadStoreState::kStartsWithClear;
119 } else if (VK_ATTACHMENT_LOAD_OP_LOAD == fVkColorLoadOp &&
120 VK_ATTACHMENT_STORE_OP_STORE == fVkColorStoreOp) {
121 cbInfo.fLoadStoreState = LoadStoreState::kLoadAndStore;
122 } else if (VK_ATTACHMENT_LOAD_OP_DONT_CARE == fVkColorLoadOp) {
123 cbInfo.fLoadStoreState = LoadStoreState::kStartsWithDiscard;
124 }
Greg Daniel36a77ee2016-10-18 10:33:25 -0400125
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500126 cbInfo.fCommandBuffers.push_back(fGpu->cmdPool()->findOrCreateSecondaryCommandBuffer(fGpu));
Robert Phillips19e51dc2017-08-09 09:30:51 -0400127 cbInfo.currentCmdBuf()->begin(fGpu, vkRT->framebuffer(), cbInfo.fRenderPass);
egdaniel066df7c2016-06-08 14:02:27 -0700128}
129
Brian Salomonc293a292016-11-30 13:38:32 -0500130
Greg Daniel500d58b2017-08-24 15:59:33 -0400131GrVkGpuRTCommandBuffer::~GrVkGpuRTCommandBuffer() {
Robert Phillips5b5d84c2018-08-09 15:12:18 -0400132 this->reset();
egdaniel066df7c2016-06-08 14:02:27 -0700133}
134
Greg Daniel500d58b2017-08-24 15:59:33 -0400135GrGpu* GrVkGpuRTCommandBuffer::gpu() { return fGpu; }
egdaniel9cb63402016-06-23 08:37:05 -0700136
Greg Daniel500d58b2017-08-24 15:59:33 -0400137void GrVkGpuRTCommandBuffer::end() {
Greg Daniel22bc8652017-03-22 15:45:43 -0400138 if (fCurrentCmdInfo >= 0) {
139 fCommandBufferInfos[fCurrentCmdInfo].currentCmdBuf()->end(fGpu);
Brian Salomonc293a292016-11-30 13:38:32 -0500140 }
egdaniel066df7c2016-06-08 14:02:27 -0700141}
142
Greg Daniel500d58b2017-08-24 15:59:33 -0400143void GrVkGpuRTCommandBuffer::submit() {
Brian Salomonc293a292016-11-30 13:38:32 -0500144 if (!fRenderTarget) {
145 return;
146 }
Robert Phillips19e51dc2017-08-09 09:30:51 -0400147
148 GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(fRenderTarget);
Robert Phillips19e51dc2017-08-09 09:30:51 -0400149 GrVkImage* targetImage = vkRT->msaaImage() ? vkRT->msaaImage() : vkRT;
Greg Daniel45a44de2018-02-27 10:07:29 -0500150 GrStencilAttachment* stencil = fRenderTarget->renderTargetPriv().getStencilAttachment();
egdaniel9cb63402016-06-23 08:37:05 -0700151
Greg Daniel36a77ee2016-10-18 10:33:25 -0400152 for (int i = 0; i < fCommandBufferInfos.count(); ++i) {
153 CommandBufferInfo& cbInfo = fCommandBufferInfos[i];
154
Greg Daniel77b53f62016-10-18 11:48:51 -0400155 for (int j = 0; j < cbInfo.fPreDrawUploads.count(); ++j) {
156 InlineUploadInfo& iuInfo = cbInfo.fPreDrawUploads[j];
157 iuInfo.fFlushState->doUpload(iuInfo.fUpload);
158 }
159
Greg Daniel500d58b2017-08-24 15:59:33 -0400160 for (int j = 0; j < cbInfo.fPreCopies.count(); ++j) {
161 CopyInfo& copyInfo = cbInfo.fPreCopies[j];
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400162 fGpu->copySurface(fRenderTarget, fOrigin, copyInfo.fSrc, copyInfo.fSrcOrigin,
Greg Daniel55fa6472018-03-16 16:13:10 -0400163 copyInfo.fSrcRect, copyInfo.fDstPoint, copyInfo.fShouldDiscardDst);
Greg Daniel500d58b2017-08-24 15:59:33 -0400164 }
165
Greg Daniel45a44de2018-02-27 10:07:29 -0500166
Greg Daniel38c3d932018-03-16 14:22:30 -0400167 // TODO: Many things create a scratch texture which adds the discard immediately, but then
168 // don't draw to it right away. This causes the discard to be ignored and we get yelled at
169 // for loading uninitialized data. However, once MDB lands with reordering, the discard will
170 // get reordered with the rest of the draw commands and we can remove the discard check.
171 if (cbInfo.fIsEmpty &&
172 cbInfo.fLoadStoreState != LoadStoreState::kStartsWithClear &&
173 cbInfo.fLoadStoreState != LoadStoreState::kStartsWithDiscard) {
Greg Daniel77b53f62016-10-18 11:48:51 -0400174 // We have sumbitted no actual draw commands to the command buffer and we are not using
175 // the render pass to do a clear so there is no need to submit anything.
176 continue;
177 }
Greg Daniel38c3d932018-03-16 14:22:30 -0400178
Greg Danieldbdba602018-04-20 11:52:43 -0400179 // Make sure if we only have a discard load that we execute the discard on the whole image.
180 // TODO: Once we improve our tracking of discards so that we never end up flushing a discard
181 // call with no actually ops, remove this.
182 if (cbInfo.fIsEmpty && cbInfo.fLoadStoreState == LoadStoreState::kStartsWithDiscard) {
Greg Daniela41a74a2018-10-09 12:59:23 +0000183 cbInfo.fBounds = SkRect::MakeWH(vkRT->width(), vkRT->height());
Greg Danieldbdba602018-04-20 11:52:43 -0400184 }
185
Greg Daniela41a74a2018-10-09 12:59:23 +0000186 if (cbInfo.fBounds.intersect(0, 0,
187 SkIntToScalar(fRenderTarget->width()),
188 SkIntToScalar(fRenderTarget->height()))) {
Greg Daniel38c3d932018-03-16 14:22:30 -0400189 // Make sure we do the following layout changes after all copies, uploads, or any other
190 // pre-work is done since we may change the layouts in the pre-work. Also since the
191 // draws will be submitted in different render passes, we need to guard againts write
192 // and write issues.
193
194 // Change layout of our render target so it can be used as the color attachment.
Greg Danielf7828d02018-10-09 12:01:32 -0400195 // TODO: If we know that we will never be blending or loading the attachment we could
196 // drop the VK_ACCESS_COLOR_ATTACHMENT_READ_BIT.
Greg Daniel38c3d932018-03-16 14:22:30 -0400197 targetImage->setImageLayout(fGpu,
198 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
Greg Danielf7828d02018-10-09 12:01:32 -0400199 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
Greg Daniel38c3d932018-03-16 14:22:30 -0400200 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
Greg Danielf7828d02018-10-09 12:01:32 -0400201 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
Greg Daniel38c3d932018-03-16 14:22:30 -0400202 false);
203
204 // If we are using a stencil attachment we also need to update its layout
205 if (stencil) {
206 GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil;
Greg Danielf7828d02018-10-09 12:01:32 -0400207 // We need the write and read access bits since we may load and store the stencil.
208 // The initial load happens in the VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT so we
209 // wait there.
Greg Daniel38c3d932018-03-16 14:22:30 -0400210 vkStencil->setImageLayout(fGpu,
211 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
212 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
213 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
Greg Danielf7828d02018-10-09 12:01:32 -0400214 VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
Greg Daniel38c3d932018-03-16 14:22:30 -0400215 false);
216 }
217
218 // If we have any sampled images set their layout now.
219 for (int j = 0; j < cbInfo.fSampledImages.count(); ++j) {
220 cbInfo.fSampledImages[j]->setImageLayout(fGpu,
221 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
222 VK_ACCESS_SHADER_READ_BIT,
Greg Danielf7828d02018-10-09 12:01:32 -0400223 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
Greg Daniel38c3d932018-03-16 14:22:30 -0400224 false);
225 }
226
Greg Daniel36a77ee2016-10-18 10:33:25 -0400227 SkIRect iBounds;
228 cbInfo.fBounds.roundOut(&iBounds);
229
Greg Daniel22bc8652017-03-22 15:45:43 -0400230 fGpu->submitSecondaryCommandBuffer(cbInfo.fCommandBuffers, cbInfo.fRenderPass,
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400231 &cbInfo.fColorClearValue, vkRT, fOrigin, iBounds);
Greg Daniel36a77ee2016-10-18 10:33:25 -0400232 }
233 }
egdaniel9cb63402016-06-23 08:37:05 -0700234}
235
Robert Phillips5b5d84c2018-08-09 15:12:18 -0400236void GrVkGpuRTCommandBuffer::set(GrRenderTarget* rt, GrSurfaceOrigin origin,
237 const GrGpuRTCommandBuffer::LoadAndStoreInfo& colorInfo,
238 const GrGpuRTCommandBuffer::StencilLoadAndStoreInfo& stencilInfo) {
239 SkASSERT(!fRenderTarget);
240 SkASSERT(fCommandBufferInfos.empty());
241 SkASSERT(-1 == fCurrentCmdInfo);
242 SkASSERT(fGpu == rt->getContext()->contextPriv().getGpu());
243 SkASSERT(!fLastPipelineState);
244
245 this->INHERITED::set(rt, origin);
246
Brian Osman9a9baae2018-11-05 15:06:26 -0500247 fClearColor = colorInfo.fClearColor;
Robert Phillips5b5d84c2018-08-09 15:12:18 -0400248
249 get_vk_load_store_ops(colorInfo.fLoadOp, colorInfo.fStoreOp,
250 &fVkColorLoadOp, &fVkColorStoreOp);
251
252 get_vk_load_store_ops(stencilInfo.fLoadOp, stencilInfo.fStoreOp,
253 &fVkStencilLoadOp, &fVkStencilStoreOp);
254
255 this->init();
256}
257
258void GrVkGpuRTCommandBuffer::reset() {
259 for (int i = 0; i < fCommandBufferInfos.count(); ++i) {
260 CommandBufferInfo& cbInfo = fCommandBufferInfos[i];
261 for (int j = 0; j < cbInfo.fCommandBuffers.count(); ++j) {
262 cbInfo.fCommandBuffers[j]->unref(fGpu);
263 }
264 cbInfo.fRenderPass->unref(fGpu);
265 }
266 fCommandBufferInfos.reset();
267
268 fCurrentCmdInfo = -1;
269
270 fLastPipelineState = nullptr;
271 fRenderTarget = nullptr;
272}
273
Greg Daniel64cc9aa2018-10-19 13:54:56 -0400274////////////////////////////////////////////////////////////////////////////////
275
Greg Daniel500d58b2017-08-24 15:59:33 -0400276void GrVkGpuRTCommandBuffer::discard() {
Robert Phillips19e51dc2017-08-09 09:30:51 -0400277 GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(fRenderTarget);
Brian Salomonc293a292016-11-30 13:38:32 -0500278
Greg Daniel22bc8652017-03-22 15:45:43 -0400279 CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdInfo];
Greg Daniel77b53f62016-10-18 11:48:51 -0400280 if (cbInfo.fIsEmpty) {
Robert Phillips74c627f2017-08-09 10:28:00 -0400281 // Change the render pass to do a don't-care load for both color & stencil
egdaniel37535c92016-06-30 08:23:30 -0700282 GrVkRenderPass::LoadStoreOps vkColorOps(VK_ATTACHMENT_LOAD_OP_DONT_CARE,
283 VK_ATTACHMENT_STORE_OP_STORE);
284 GrVkRenderPass::LoadStoreOps vkStencilOps(VK_ATTACHMENT_LOAD_OP_DONT_CARE,
285 VK_ATTACHMENT_STORE_OP_STORE);
egdaniel37535c92016-06-30 08:23:30 -0700286
Greg Daniel36a77ee2016-10-18 10:33:25 -0400287 const GrVkRenderPass* oldRP = cbInfo.fRenderPass;
egdaniel37535c92016-06-30 08:23:30 -0700288
egdaniel37535c92016-06-30 08:23:30 -0700289 const GrVkResourceProvider::CompatibleRPHandle& rpHandle =
Robert Phillips19e51dc2017-08-09 09:30:51 -0400290 vkRT->compatibleRenderPassHandle();
egdaniel37535c92016-06-30 08:23:30 -0700291 if (rpHandle.isValid()) {
Greg Daniel36a77ee2016-10-18 10:33:25 -0400292 cbInfo.fRenderPass = fGpu->resourceProvider().findRenderPass(rpHandle,
293 vkColorOps,
294 vkStencilOps);
egdaniel37535c92016-06-30 08:23:30 -0700295 } else {
Robert Phillips19e51dc2017-08-09 09:30:51 -0400296 cbInfo.fRenderPass = fGpu->resourceProvider().findRenderPass(*vkRT,
Greg Daniel36a77ee2016-10-18 10:33:25 -0400297 vkColorOps,
298 vkStencilOps);
egdaniel37535c92016-06-30 08:23:30 -0700299 }
300
Greg Daniel36a77ee2016-10-18 10:33:25 -0400301 SkASSERT(cbInfo.fRenderPass->isCompatible(*oldRP));
egdaniel37535c92016-06-30 08:23:30 -0700302 oldRP->unref(fGpu);
Greg Daniel5011f852016-10-28 15:07:16 -0400303 cbInfo.fBounds.join(fRenderTarget->getBoundsRect());
Greg Daniela3c68df2018-03-16 13:46:53 -0400304 cbInfo.fLoadStoreState = LoadStoreState::kStartsWithDiscard;
305 // If we are going to discard the whole render target then the results of any copies we did
306 // immediately before to the target won't matter, so just drop them.
307 cbInfo.fPreCopies.reset();
egdaniel37535c92016-06-30 08:23:30 -0700308 }
309}
310
Greg Daniel500d58b2017-08-24 15:59:33 -0400311void GrVkGpuRTCommandBuffer::insertEventMarker(const char* msg) {
Robert Phillips65a88fa2017-08-08 08:36:22 -0400312 // TODO: does Vulkan have a correlate?
313}
314
Greg Daniel500d58b2017-08-24 15:59:33 -0400315void GrVkGpuRTCommandBuffer::onClearStencilClip(const GrFixedClip& clip, bool insideStencilMask) {
Chris Dalton94c04682017-11-01 17:15:06 -0600316 SkASSERT(!clip.hasWindowRectangles());
317
Jim Van Verth6a40abc2017-11-02 16:56:09 +0000318 CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdInfo];
319
Greg Daniel65a09272016-10-12 09:47:22 -0400320 GrStencilAttachment* sb = fRenderTarget->renderTargetPriv().getStencilAttachment();
egdaniel9cb63402016-06-23 08:37:05 -0700321 // this should only be called internally when we know we have a
322 // stencil buffer.
323 SkASSERT(sb);
324 int stencilBitCount = sb->bits();
325
326 // The contract with the callers does not guarantee that we preserve all bits in the stencil
327 // during this clear. Thus we will clear the entire stencil to the desired value.
328
329 VkClearDepthStencilValue vkStencilColor;
330 memset(&vkStencilColor, 0, sizeof(VkClearDepthStencilValue));
csmartdalton29df7602016-08-31 11:55:52 -0700331 if (insideStencilMask) {
egdaniel9cb63402016-06-23 08:37:05 -0700332 vkStencilColor.stencil = (1 << (stencilBitCount - 1));
333 } else {
334 vkStencilColor.stencil = 0;
335 }
336
337 VkClearRect clearRect;
338 // Flip rect if necessary
csmartdalton29df7602016-08-31 11:55:52 -0700339 SkIRect vkRect;
Brian Salomond818ebf2018-07-02 14:08:49 +0000340 if (!clip.scissorEnabled()) {
Greg Daniela41a74a2018-10-09 12:59:23 +0000341 vkRect.setXYWH(0, 0, fRenderTarget->width(), fRenderTarget->height());
Robert Phillips4f101a72017-07-28 08:42:04 -0400342 } else if (kBottomLeft_GrSurfaceOrigin != fOrigin) {
csmartdalton29df7602016-08-31 11:55:52 -0700343 vkRect = clip.scissorRect();
344 } else {
345 const SkIRect& scissor = clip.scissorRect();
Greg Daniel65a09272016-10-12 09:47:22 -0400346 vkRect.setLTRB(scissor.fLeft, fRenderTarget->height() - scissor.fBottom,
347 scissor.fRight, fRenderTarget->height() - scissor.fTop);
egdaniel9cb63402016-06-23 08:37:05 -0700348 }
349
350 clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop };
351 clearRect.rect.extent = { (uint32_t)vkRect.width(), (uint32_t)vkRect.height() };
352
353 clearRect.baseArrayLayer = 0;
354 clearRect.layerCount = 1;
355
356 uint32_t stencilIndex;
Greg Daniel36a77ee2016-10-18 10:33:25 -0400357 SkAssertResult(cbInfo.fRenderPass->stencilAttachmentIndex(&stencilIndex));
egdaniel9cb63402016-06-23 08:37:05 -0700358
359 VkClearAttachment attachment;
360 attachment.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
361 attachment.colorAttachment = 0; // this value shouldn't matter
362 attachment.clearValue.depthStencil = vkStencilColor;
363
Greg Daniel22bc8652017-03-22 15:45:43 -0400364 cbInfo.currentCmdBuf()->clearAttachments(fGpu, 1, &attachment, 1, &clearRect);
Greg Daniel77b53f62016-10-18 11:48:51 -0400365 cbInfo.fIsEmpty = false;
Greg Daniel36a77ee2016-10-18 10:33:25 -0400366
367 // Update command buffer bounds
Brian Salomond818ebf2018-07-02 14:08:49 +0000368 if (!clip.scissorEnabled()) {
Greg Daniel36a77ee2016-10-18 10:33:25 -0400369 cbInfo.fBounds.join(fRenderTarget->getBoundsRect());
370 } else {
371 cbInfo.fBounds.join(SkRect::Make(clip.scissorRect()));
372 }
egdaniel9cb63402016-06-23 08:37:05 -0700373}
374
Brian Osman9a9baae2018-11-05 15:06:26 -0500375void GrVkGpuRTCommandBuffer::onClear(const GrFixedClip& clip, const SkPMColor4f& color) {
Robert Phillips19e51dc2017-08-09 09:30:51 -0400376 GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(fRenderTarget);
377
Jim Van Verth6a40abc2017-11-02 16:56:09 +0000378 // parent class should never let us get here with no RT
csmartdaltonbf4a8f92016-09-06 10:01:06 -0700379 SkASSERT(!clip.hasWindowRectangles());
egdaniel9cb63402016-06-23 08:37:05 -0700380
Greg Daniel22bc8652017-03-22 15:45:43 -0400381 CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdInfo];
Greg Daniel36a77ee2016-10-18 10:33:25 -0400382
Brian Osman9a9baae2018-11-05 15:06:26 -0500383 VkClearColorValue vkColor = {{color.fR, color.fG, color.fB, color.fA}};
egdaniel9cb63402016-06-23 08:37:05 -0700384
Brian Salomond818ebf2018-07-02 14:08:49 +0000385 if (cbInfo.fIsEmpty && !clip.scissorEnabled()) {
Robert Phillips74c627f2017-08-09 10:28:00 -0400386 // Change the render pass to do a clear load
egdaniel9cb63402016-06-23 08:37:05 -0700387 GrVkRenderPass::LoadStoreOps vkColorOps(VK_ATTACHMENT_LOAD_OP_CLEAR,
388 VK_ATTACHMENT_STORE_OP_STORE);
Robert Phillips74c627f2017-08-09 10:28:00 -0400389 // Preserve the stencil buffer's load & store settings
390 GrVkRenderPass::LoadStoreOps vkStencilOps(fVkStencilLoadOp, fVkStencilStoreOp);
egdaniel9cb63402016-06-23 08:37:05 -0700391
Greg Daniel36a77ee2016-10-18 10:33:25 -0400392 const GrVkRenderPass* oldRP = cbInfo.fRenderPass;
egdaniel9cb63402016-06-23 08:37:05 -0700393
394 const GrVkResourceProvider::CompatibleRPHandle& rpHandle =
Robert Phillips19e51dc2017-08-09 09:30:51 -0400395 vkRT->compatibleRenderPassHandle();
egdaniel9cb63402016-06-23 08:37:05 -0700396 if (rpHandle.isValid()) {
Greg Daniel36a77ee2016-10-18 10:33:25 -0400397 cbInfo.fRenderPass = fGpu->resourceProvider().findRenderPass(rpHandle,
398 vkColorOps,
399 vkStencilOps);
egdaniel9cb63402016-06-23 08:37:05 -0700400 } else {
Robert Phillips19e51dc2017-08-09 09:30:51 -0400401 cbInfo.fRenderPass = fGpu->resourceProvider().findRenderPass(*vkRT,
Greg Daniel36a77ee2016-10-18 10:33:25 -0400402 vkColorOps,
403 vkStencilOps);
egdaniel9cb63402016-06-23 08:37:05 -0700404 }
405
Greg Daniel36a77ee2016-10-18 10:33:25 -0400406 SkASSERT(cbInfo.fRenderPass->isCompatible(*oldRP));
egdaniel9cb63402016-06-23 08:37:05 -0700407 oldRP->unref(fGpu);
408
Brian Osman9a9baae2018-11-05 15:06:26 -0500409 cbInfo.fColorClearValue.color = {{color.fR, color.fG, color.fB, color.fA}};
Greg Daniela3c68df2018-03-16 13:46:53 -0400410 cbInfo.fLoadStoreState = LoadStoreState::kStartsWithClear;
411 // If we are going to clear the whole render target then the results of any copies we did
412 // immediately before to the target won't matter, so just drop them.
413 cbInfo.fPreCopies.reset();
Greg Daniel36a77ee2016-10-18 10:33:25 -0400414
415 // Update command buffer bounds
416 cbInfo.fBounds.join(fRenderTarget->getBoundsRect());
egdaniel9cb63402016-06-23 08:37:05 -0700417 return;
418 }
419
420 // We always do a sub rect clear with clearAttachments since we are inside a render pass
421 VkClearRect clearRect;
422 // Flip rect if necessary
csmartdalton29df7602016-08-31 11:55:52 -0700423 SkIRect vkRect;
Brian Salomond818ebf2018-07-02 14:08:49 +0000424 if (!clip.scissorEnabled()) {
Greg Daniela41a74a2018-10-09 12:59:23 +0000425 vkRect.setXYWH(0, 0, fRenderTarget->width(), fRenderTarget->height());
Robert Phillips4f101a72017-07-28 08:42:04 -0400426 } else if (kBottomLeft_GrSurfaceOrigin != fOrigin) {
csmartdalton29df7602016-08-31 11:55:52 -0700427 vkRect = clip.scissorRect();
428 } else {
429 const SkIRect& scissor = clip.scissorRect();
Greg Daniel65a09272016-10-12 09:47:22 -0400430 vkRect.setLTRB(scissor.fLeft, fRenderTarget->height() - scissor.fBottom,
431 scissor.fRight, fRenderTarget->height() - scissor.fTop);
egdaniel9cb63402016-06-23 08:37:05 -0700432 }
433 clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop };
434 clearRect.rect.extent = { (uint32_t)vkRect.width(), (uint32_t)vkRect.height() };
435 clearRect.baseArrayLayer = 0;
436 clearRect.layerCount = 1;
437
438 uint32_t colorIndex;
Greg Daniel36a77ee2016-10-18 10:33:25 -0400439 SkAssertResult(cbInfo.fRenderPass->colorAttachmentIndex(&colorIndex));
egdaniel9cb63402016-06-23 08:37:05 -0700440
441 VkClearAttachment attachment;
442 attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
443 attachment.colorAttachment = colorIndex;
444 attachment.clearValue.color = vkColor;
445
Greg Daniel22bc8652017-03-22 15:45:43 -0400446 cbInfo.currentCmdBuf()->clearAttachments(fGpu, 1, &attachment, 1, &clearRect);
Greg Daniel77b53f62016-10-18 11:48:51 -0400447 cbInfo.fIsEmpty = false;
Greg Daniel36a77ee2016-10-18 10:33:25 -0400448
449 // Update command buffer bounds
Brian Salomond818ebf2018-07-02 14:08:49 +0000450 if (!clip.scissorEnabled()) {
Greg Daniel36a77ee2016-10-18 10:33:25 -0400451 cbInfo.fBounds.join(fRenderTarget->getBoundsRect());
452 } else {
453 cbInfo.fBounds.join(SkRect::Make(clip.scissorRect()));
454 }
egdaniel9cb63402016-06-23 08:37:05 -0700455 return;
456}
457
Greg Daniel500d58b2017-08-24 15:59:33 -0400458////////////////////////////////////////////////////////////////////////////////
459
460void GrVkGpuRTCommandBuffer::addAdditionalCommandBuffer() {
Robert Phillips19e51dc2017-08-09 09:30:51 -0400461 GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(fRenderTarget);
462
Greg Daniel22bc8652017-03-22 15:45:43 -0400463 CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdInfo];
464 cbInfo.currentCmdBuf()->end(fGpu);
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500465 cbInfo.fCommandBuffers.push_back(fGpu->cmdPool()->findOrCreateSecondaryCommandBuffer(fGpu));
Robert Phillips19e51dc2017-08-09 09:30:51 -0400466 cbInfo.currentCmdBuf()->begin(fGpu, vkRT->framebuffer(), cbInfo.fRenderPass);
Greg Daniel22bc8652017-03-22 15:45:43 -0400467}
468
Greg Daniel500d58b2017-08-24 15:59:33 -0400469void GrVkGpuRTCommandBuffer::addAdditionalRenderPass() {
Robert Phillips19e51dc2017-08-09 09:30:51 -0400470 GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(fRenderTarget);
471
Greg Daniel22bc8652017-03-22 15:45:43 -0400472 fCommandBufferInfos[fCurrentCmdInfo].currentCmdBuf()->end(fGpu);
Greg Daniel77b53f62016-10-18 11:48:51 -0400473
474 CommandBufferInfo& cbInfo = fCommandBufferInfos.push_back();
Greg Daniel22bc8652017-03-22 15:45:43 -0400475 fCurrentCmdInfo++;
Greg Daniel77b53f62016-10-18 11:48:51 -0400476
477 GrVkRenderPass::LoadStoreOps vkColorOps(VK_ATTACHMENT_LOAD_OP_LOAD,
478 VK_ATTACHMENT_STORE_OP_STORE);
479 GrVkRenderPass::LoadStoreOps vkStencilOps(VK_ATTACHMENT_LOAD_OP_LOAD,
480 VK_ATTACHMENT_STORE_OP_STORE);
481
482 const GrVkResourceProvider::CompatibleRPHandle& rpHandle =
Robert Phillips19e51dc2017-08-09 09:30:51 -0400483 vkRT->compatibleRenderPassHandle();
Greg Daniel77b53f62016-10-18 11:48:51 -0400484 if (rpHandle.isValid()) {
485 cbInfo.fRenderPass = fGpu->resourceProvider().findRenderPass(rpHandle,
486 vkColorOps,
487 vkStencilOps);
488 } else {
Robert Phillips19e51dc2017-08-09 09:30:51 -0400489 cbInfo.fRenderPass = fGpu->resourceProvider().findRenderPass(*vkRT,
Greg Daniel77b53f62016-10-18 11:48:51 -0400490 vkColorOps,
491 vkStencilOps);
492 }
Greg Daniela3c68df2018-03-16 13:46:53 -0400493 cbInfo.fLoadStoreState = LoadStoreState::kLoadAndStore;
Greg Daniel77b53f62016-10-18 11:48:51 -0400494
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500495 cbInfo.fCommandBuffers.push_back(fGpu->cmdPool()->findOrCreateSecondaryCommandBuffer(fGpu));
Greg Daniel77b53f62016-10-18 11:48:51 -0400496 // It shouldn't matter what we set the clear color to here since we will assume loading of the
497 // attachment.
498 memset(&cbInfo.fColorClearValue, 0, sizeof(VkClearValue));
499 cbInfo.fBounds.setEmpty();
Greg Daniel77b53f62016-10-18 11:48:51 -0400500
Robert Phillips19e51dc2017-08-09 09:30:51 -0400501 cbInfo.currentCmdBuf()->begin(fGpu, vkRT->framebuffer(), cbInfo.fRenderPass);
Greg Daniel77b53f62016-10-18 11:48:51 -0400502}
503
Brian Salomon943ed792017-10-30 09:37:55 -0400504void GrVkGpuRTCommandBuffer::inlineUpload(GrOpFlushState* state,
505 GrDeferredTextureUploadFn& upload) {
Greg Daniel22bc8652017-03-22 15:45:43 -0400506 if (!fCommandBufferInfos[fCurrentCmdInfo].fIsEmpty) {
507 this->addAdditionalRenderPass();
Greg Daniel77b53f62016-10-18 11:48:51 -0400508 }
Greg Daniel22bc8652017-03-22 15:45:43 -0400509 fCommandBufferInfos[fCurrentCmdInfo].fPreDrawUploads.emplace_back(state, upload);
Greg Daniel77b53f62016-10-18 11:48:51 -0400510}
511
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400512void GrVkGpuRTCommandBuffer::copy(GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIRect& srcRect,
Greg Daniel500d58b2017-08-24 15:59:33 -0400513 const SkIPoint& dstPoint) {
Greg Daniela3c68df2018-03-16 13:46:53 -0400514 CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdInfo];
515 if (!cbInfo.fIsEmpty || LoadStoreState::kStartsWithClear == cbInfo.fLoadStoreState) {
Greg Daniel500d58b2017-08-24 15:59:33 -0400516 this->addAdditionalRenderPass();
517 }
Greg Daniela3c68df2018-03-16 13:46:53 -0400518
Greg Daniel55fa6472018-03-16 16:13:10 -0400519 fCommandBufferInfos[fCurrentCmdInfo].fPreCopies.emplace_back(
520 src, srcOrigin, srcRect, dstPoint,
521 LoadStoreState::kStartsWithDiscard == cbInfo.fLoadStoreState);
522
Greg Daniela3c68df2018-03-16 13:46:53 -0400523 if (LoadStoreState::kLoadAndStore != cbInfo.fLoadStoreState) {
524 // Change the render pass to do a load and store so we don't lose the results of our copy
525 GrVkRenderPass::LoadStoreOps vkColorOps(VK_ATTACHMENT_LOAD_OP_LOAD,
526 VK_ATTACHMENT_STORE_OP_STORE);
527 GrVkRenderPass::LoadStoreOps vkStencilOps(VK_ATTACHMENT_LOAD_OP_LOAD,
528 VK_ATTACHMENT_STORE_OP_STORE);
529
530 const GrVkRenderPass* oldRP = cbInfo.fRenderPass;
531
532 GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(fRenderTarget);
533 const GrVkResourceProvider::CompatibleRPHandle& rpHandle =
534 vkRT->compatibleRenderPassHandle();
535 if (rpHandle.isValid()) {
536 cbInfo.fRenderPass = fGpu->resourceProvider().findRenderPass(rpHandle,
537 vkColorOps,
538 vkStencilOps);
539 } else {
540 cbInfo.fRenderPass = fGpu->resourceProvider().findRenderPass(*vkRT,
541 vkColorOps,
542 vkStencilOps);
543 }
544 SkASSERT(cbInfo.fRenderPass->isCompatible(*oldRP));
545 oldRP->unref(fGpu);
546
547 cbInfo.fLoadStoreState = LoadStoreState::kLoadAndStore;
548
549 }
Greg Daniel500d58b2017-08-24 15:59:33 -0400550}
551
egdaniel9cb63402016-06-23 08:37:05 -0700552////////////////////////////////////////////////////////////////////////////////
553
Brian Salomon802cb312018-06-08 18:05:20 -0400554void GrVkGpuRTCommandBuffer::bindGeometry(const GrBuffer* indexBuffer,
Greg Daniel500d58b2017-08-24 15:59:33 -0400555 const GrBuffer* vertexBuffer,
556 const GrBuffer* instanceBuffer) {
Chris Daltonff926502017-05-03 14:36:54 -0400557 GrVkSecondaryCommandBuffer* currCmdBuf = fCommandBufferInfos[fCurrentCmdInfo].currentCmdBuf();
egdaniel9cb63402016-06-23 08:37:05 -0700558 // There is no need to put any memory barriers to make sure host writes have finished here.
559 // When a command buffer is submitted to a queue, there is an implicit memory barrier that
560 // occurs for all host writes. Additionally, BufferMemoryBarriers are not allowed inside of
561 // an active RenderPass.
egdaniel9cb63402016-06-23 08:37:05 -0700562
Chris Dalton1d616352017-05-31 12:51:23 -0600563 // Here our vertex and instance inputs need to match the same 0-based bindings they were
564 // assigned in GrVkPipeline. That is, vertex first (if any) followed by instance.
565 uint32_t binding = 0;
566
Brian Salomon802cb312018-06-08 18:05:20 -0400567 if (vertexBuffer) {
Chris Dalton1d616352017-05-31 12:51:23 -0600568 SkASSERT(vertexBuffer);
569 SkASSERT(!vertexBuffer->isCPUBacked());
570 SkASSERT(!vertexBuffer->isMapped());
571
572 currCmdBuf->bindInputBuffer(fGpu, binding++,
573 static_cast<const GrVkVertexBuffer*>(vertexBuffer));
574 }
575
Brian Salomon802cb312018-06-08 18:05:20 -0400576 if (instanceBuffer) {
Chris Dalton1d616352017-05-31 12:51:23 -0600577 SkASSERT(instanceBuffer);
578 SkASSERT(!instanceBuffer->isCPUBacked());
579 SkASSERT(!instanceBuffer->isMapped());
580
581 currCmdBuf->bindInputBuffer(fGpu, binding++,
582 static_cast<const GrVkVertexBuffer*>(instanceBuffer));
583 }
Chris Daltonff926502017-05-03 14:36:54 -0400584 if (indexBuffer) {
585 SkASSERT(indexBuffer);
586 SkASSERT(!indexBuffer->isMapped());
587 SkASSERT(!indexBuffer->isCPUBacked());
egdaniel9cb63402016-06-23 08:37:05 -0700588
Chris Daltonff926502017-05-03 14:36:54 -0400589 currCmdBuf->bindIndexBuffer(fGpu, static_cast<const GrVkIndexBuffer*>(indexBuffer));
egdaniel9cb63402016-06-23 08:37:05 -0700590 }
591}
592
Brian Salomon49348902018-06-26 09:12:38 -0400593GrVkPipelineState* GrVkGpuRTCommandBuffer::prepareDrawState(
594 const GrPrimitiveProcessor& primProc,
595 const GrPipeline& pipeline,
596 const GrPipeline::FixedDynamicState* fixedDynamicState,
597 const GrPipeline::DynamicStateArrays* dynamicStateArrays,
598 GrPrimitiveType primitiveType) {
Greg Daniel22bc8652017-03-22 15:45:43 -0400599 CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdInfo];
600 SkASSERT(cbInfo.fRenderPass);
Greg Daniel36a77ee2016-10-18 10:33:25 -0400601
Greg Daniel99b88e02018-10-03 15:31:20 -0400602 VkRenderPass compatibleRenderPass = cbInfo.fRenderPass->vkRenderPass();
603
Greg Daniel9a51a862018-11-30 10:18:14 -0500604 const GrTextureProxy* const* primProcProxies = nullptr;
605 if (dynamicStateArrays && dynamicStateArrays->fPrimitiveProcessorTextures) {
606 primProcProxies = dynamicStateArrays->fPrimitiveProcessorTextures;
607 } else if (fixedDynamicState) {
608 primProcProxies = fixedDynamicState->fPrimitiveProcessorTextures;
609 }
610
611 SkASSERT(SkToBool(primProcProxies) == SkToBool(primProc.numTextureSamplers()));
612
Greg Daniel09eeefb2017-10-16 15:15:02 -0400613 GrVkPipelineState* pipelineState =
egdaniel9cb63402016-06-23 08:37:05 -0700614 fGpu->resourceProvider().findOrCreateCompatiblePipelineState(pipeline,
615 primProc,
Greg Daniel9a51a862018-11-30 10:18:14 -0500616 primProcProxies,
egdaniel9cb63402016-06-23 08:37:05 -0700617 primitiveType,
Greg Daniel99b88e02018-10-03 15:31:20 -0400618 compatibleRenderPass);
egdaniel9cb63402016-06-23 08:37:05 -0700619 if (!pipelineState) {
620 return pipelineState;
621 }
622
Greg Daniel22bc8652017-03-22 15:45:43 -0400623 if (!cbInfo.fIsEmpty &&
Greg Daniel09eeefb2017-10-16 15:15:02 -0400624 fLastPipelineState && fLastPipelineState != pipelineState &&
Greg Daniele3cd6912017-05-17 11:15:55 -0400625 fGpu->vkCaps().newCBOnPipelineChange()) {
Greg Daniel22bc8652017-03-22 15:45:43 -0400626 this->addAdditionalCommandBuffer();
627 }
Greg Daniel09eeefb2017-10-16 15:15:02 -0400628 fLastPipelineState = pipelineState;
Greg Daniel22bc8652017-03-22 15:45:43 -0400629
Brian Salomonf7232642018-09-19 08:58:08 -0400630 pipelineState->bindPipeline(fGpu, cbInfo.currentCmdBuf());
Brian Salomoncd7907b2018-08-30 08:36:18 -0400631
Brian Salomonf7232642018-09-19 08:58:08 -0400632 pipelineState->setAndBindUniforms(fGpu, primProc, pipeline, cbInfo.currentCmdBuf());
633
634 // Check whether we need to bind textures between each GrMesh. If not we can bind them all now.
635 bool setTextures = !(dynamicStateArrays && dynamicStateArrays->fPrimitiveProcessorTextures);
636 if (setTextures) {
Brian Salomonf7232642018-09-19 08:58:08 -0400637 pipelineState->setAndBindTextures(fGpu, primProc, pipeline, primProcProxies,
638 cbInfo.currentCmdBuf());
639 }
egdaniel9cb63402016-06-23 08:37:05 -0700640
Robert Phillips2890fbf2017-07-26 15:48:41 -0400641 GrRenderTarget* rt = pipeline.renderTarget();
Chris Dalton46983b72017-06-06 12:27:16 -0600642
Brian Salomond818ebf2018-07-02 14:08:49 +0000643 if (!pipeline.isScissorEnabled()) {
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400644 GrVkPipeline::SetDynamicScissorRectState(fGpu, cbInfo.currentCmdBuf(),
645 rt, pipeline.proxy()->origin(),
Greg Daniela41a74a2018-10-09 12:59:23 +0000646 SkIRect::MakeWH(rt->width(), rt->height()));
Brian Salomon49348902018-06-26 09:12:38 -0400647 } else if (!dynamicStateArrays || !dynamicStateArrays->fScissorRects) {
648 SkASSERT(fixedDynamicState);
649 GrVkPipeline::SetDynamicScissorRectState(fGpu, cbInfo.currentCmdBuf(), rt,
650 pipeline.proxy()->origin(),
651 fixedDynamicState->fScissorRect);
Chris Dalton46983b72017-06-06 12:27:16 -0600652 }
Jim Van Verth6a40abc2017-11-02 16:56:09 +0000653 GrVkPipeline::SetDynamicViewportState(fGpu, cbInfo.currentCmdBuf(), rt);
Chris Dalton46983b72017-06-06 12:27:16 -0600654 GrVkPipeline::SetDynamicBlendConstantState(fGpu, cbInfo.currentCmdBuf(), rt->config(),
655 pipeline.getXferProcessor());
egdaniel9cb63402016-06-23 08:37:05 -0700656
657 return pipelineState;
658}
659
Brian Salomonff168d92018-06-23 15:17:27 -0400660void GrVkGpuRTCommandBuffer::onDraw(const GrPrimitiveProcessor& primProc,
661 const GrPipeline& pipeline,
Brian Salomon49348902018-06-26 09:12:38 -0400662 const GrPipeline::FixedDynamicState* fixedDynamicState,
663 const GrPipeline::DynamicStateArrays* dynamicStateArrays,
Greg Daniel500d58b2017-08-24 15:59:33 -0400664 const GrMesh meshes[],
Greg Daniel500d58b2017-08-24 15:59:33 -0400665 int meshCount,
666 const SkRect& bounds) {
Robert Phillips19e51dc2017-08-09 09:30:51 -0400667 SkASSERT(pipeline.renderTarget() == fRenderTarget);
Brian Salomonc293a292016-11-30 13:38:32 -0500668
egdaniel9cb63402016-06-23 08:37:05 -0700669 if (!meshCount) {
670 return;
671 }
Greg Danielea022cd2018-03-16 11:10:03 -0400672
673 CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdInfo];
674
Brian Salomone782f842018-07-31 13:53:11 -0400675 auto prepareSampledImage = [&](GrTexture* texture, GrSamplerState::Filter filter) {
676 GrVkTexture* vkTexture = static_cast<GrVkTexture*>(texture);
677 // We may need to resolve the texture first if it is also a render target
678 GrVkRenderTarget* texRT = static_cast<GrVkRenderTarget*>(vkTexture->asRenderTarget());
679 if (texRT) {
Greg Daniel0a77f432018-12-06 11:23:32 -0500680 fGpu->resolveRenderTargetNoFlush(texRT);
Brian Salomone782f842018-07-31 13:53:11 -0400681 }
682
683 // Check if we need to regenerate any mip maps
684 if (GrSamplerState::Filter::kMipMap == filter &&
685 (vkTexture->width() != 1 || vkTexture->height() != 1)) {
686 SkASSERT(vkTexture->texturePriv().mipMapped() == GrMipMapped::kYes);
687 if (vkTexture->texturePriv().mipMapsAreDirty()) {
688 fGpu->regenerateMipMapLevels(vkTexture);
689 }
690 }
691 cbInfo.fSampledImages.push_back(vkTexture);
692 };
693
Brian Salomonf7232642018-09-19 08:58:08 -0400694 if (dynamicStateArrays && dynamicStateArrays->fPrimitiveProcessorTextures) {
695 for (int m = 0, i = 0; m < meshCount; ++m) {
696 for (int s = 0; s < primProc.numTextureSamplers(); ++s, ++i) {
697 auto texture = dynamicStateArrays->fPrimitiveProcessorTextures[i]->peekTexture();
698 prepareSampledImage(texture, primProc.textureSampler(s).samplerState().filter());
699 }
700 }
701 } else {
702 for (int i = 0; i < primProc.numTextureSamplers(); ++i) {
703 auto texture = fixedDynamicState->fPrimitiveProcessorTextures[i]->peekTexture();
704 prepareSampledImage(texture, primProc.textureSampler(i).samplerState().filter());
705 }
Brian Salomone782f842018-07-31 13:53:11 -0400706 }
bsalomonb58a2b42016-09-26 06:55:02 -0700707 GrFragmentProcessor::Iter iter(pipeline);
708 while (const GrFragmentProcessor* fp = iter.next()) {
Brian Salomone782f842018-07-31 13:53:11 -0400709 for (int i = 0; i < fp->numTextureSamplers(); ++i) {
710 const GrFragmentProcessor::TextureSampler& sampler = fp->textureSampler(i);
711 prepareSampledImage(sampler.peekTexture(), sampler.samplerState().filter());
712 }
egdaniel2f5792a2016-07-06 08:51:23 -0700713 }
Robert Phillipsbb581ce2017-05-29 15:05:15 -0400714 if (GrTexture* dstTexture = pipeline.peekDstTexture()) {
Greg Danielea022cd2018-03-16 11:10:03 -0400715 cbInfo.fSampledImages.push_back(static_cast<GrVkTexture*>(dstTexture));
Brian Salomon18dfa982017-04-03 16:57:43 -0400716 }
egdaniel2f5792a2016-07-06 08:51:23 -0700717
Chris Daltonbca46e22017-05-15 11:03:26 -0600718 GrPrimitiveType primitiveType = meshes[0].primitiveType();
Brian Salomon49348902018-06-26 09:12:38 -0400719 GrVkPipelineState* pipelineState = this->prepareDrawState(primProc, pipeline, fixedDynamicState,
720 dynamicStateArrays, primitiveType);
egdaniel9cb63402016-06-23 08:37:05 -0700721 if (!pipelineState) {
722 return;
723 }
724
Brian Salomond818ebf2018-07-02 14:08:49 +0000725 bool dynamicScissor =
726 pipeline.isScissorEnabled() && dynamicStateArrays && dynamicStateArrays->fScissorRects;
Brian Salomonf7232642018-09-19 08:58:08 -0400727 bool dynamicTextures = dynamicStateArrays && dynamicStateArrays->fPrimitiveProcessorTextures;
Brian Salomon49348902018-06-26 09:12:38 -0400728
egdaniel9cb63402016-06-23 08:37:05 -0700729 for (int i = 0; i < meshCount; ++i) {
730 const GrMesh& mesh = meshes[i];
Chris Daltonbca46e22017-05-15 11:03:26 -0600731 if (mesh.primitiveType() != primitiveType) {
Chris Dalton6f241802017-05-08 13:58:38 -0400732 SkDEBUGCODE(pipelineState = nullptr);
Chris Daltonbca46e22017-05-15 11:03:26 -0600733 primitiveType = mesh.primitiveType();
Brian Salomon49348902018-06-26 09:12:38 -0400734 pipelineState = this->prepareDrawState(primProc, pipeline, fixedDynamicState,
735 dynamicStateArrays, primitiveType);
Chris Dalton6f241802017-05-08 13:58:38 -0400736 if (!pipelineState) {
737 return;
egdaniel9cb63402016-06-23 08:37:05 -0700738 }
Chris Dalton6f241802017-05-08 13:58:38 -0400739 }
egdaniel9cb63402016-06-23 08:37:05 -0700740
Brian Salomon49348902018-06-26 09:12:38 -0400741 if (dynamicScissor) {
742 GrVkPipeline::SetDynamicScissorRectState(fGpu, cbInfo.currentCmdBuf(), fRenderTarget,
743 pipeline.proxy()->origin(),
744 dynamicStateArrays->fScissorRects[i]);
Chris Dalton46983b72017-06-06 12:27:16 -0600745 }
Brian Salomonf7232642018-09-19 08:58:08 -0400746 if (dynamicTextures) {
747 GrTextureProxy* const* meshProxies = dynamicStateArrays->fPrimitiveProcessorTextures +
748 primProc.numTextureSamplers() * i;
749 pipelineState->setAndBindTextures(fGpu, primProc, pipeline, meshProxies,
750 cbInfo.currentCmdBuf());
751 }
Chris Daltonbca46e22017-05-15 11:03:26 -0600752 SkASSERT(pipelineState);
Brian Salomon802cb312018-06-08 18:05:20 -0400753 mesh.sendToGpu(this);
egdaniel9cb63402016-06-23 08:37:05 -0700754 }
755
Greg Daniel36a77ee2016-10-18 10:33:25 -0400756 cbInfo.fBounds.join(bounds);
Chris Dalton114a3c02017-05-26 15:17:19 -0600757 cbInfo.fIsEmpty = false;
egdaniel066df7c2016-06-08 14:02:27 -0700758}
759
Brian Salomon802cb312018-06-08 18:05:20 -0400760void GrVkGpuRTCommandBuffer::sendInstancedMeshToGpu(GrPrimitiveType,
Greg Daniel500d58b2017-08-24 15:59:33 -0400761 const GrBuffer* vertexBuffer,
762 int vertexCount,
763 int baseVertex,
764 const GrBuffer* instanceBuffer,
765 int instanceCount,
766 int baseInstance) {
Chris Dalton114a3c02017-05-26 15:17:19 -0600767 CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdInfo];
Brian Salomon802cb312018-06-08 18:05:20 -0400768 this->bindGeometry(nullptr, vertexBuffer, instanceBuffer);
Chris Dalton1d616352017-05-31 12:51:23 -0600769 cbInfo.currentCmdBuf()->draw(fGpu, vertexCount, instanceCount, baseVertex, baseInstance);
Chris Dalton114a3c02017-05-26 15:17:19 -0600770 fGpu->stats()->incNumDraws();
771}
772
Brian Salomon802cb312018-06-08 18:05:20 -0400773void GrVkGpuRTCommandBuffer::sendIndexedInstancedMeshToGpu(GrPrimitiveType,
Greg Daniel500d58b2017-08-24 15:59:33 -0400774 const GrBuffer* indexBuffer,
775 int indexCount,
776 int baseIndex,
777 const GrBuffer* vertexBuffer,
778 int baseVertex,
779 const GrBuffer* instanceBuffer,
780 int instanceCount,
Brian Salomon802cb312018-06-08 18:05:20 -0400781 int baseInstance,
782 GrPrimitiveRestart restart) {
783 SkASSERT(restart == GrPrimitiveRestart::kNo);
Chris Dalton114a3c02017-05-26 15:17:19 -0600784 CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdInfo];
Brian Salomon802cb312018-06-08 18:05:20 -0400785 this->bindGeometry(indexBuffer, vertexBuffer, instanceBuffer);
Chris Dalton1d616352017-05-31 12:51:23 -0600786 cbInfo.currentCmdBuf()->drawIndexed(fGpu, indexCount, instanceCount,
787 baseIndex, baseVertex, baseInstance);
Chris Dalton114a3c02017-05-26 15:17:19 -0600788 fGpu->stats()->incNumDraws();
789}
Greg Daniel64cc9aa2018-10-19 13:54:56 -0400790
791////////////////////////////////////////////////////////////////////////////////
792
793void GrVkGpuRTCommandBuffer::executeDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler> drawable) {
794 GrVkRenderTarget* target = static_cast<GrVkRenderTarget*>(fRenderTarget);
795
796 GrVkImage* targetImage = target->msaaImage() ? target->msaaImage() : target;
797
798 CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdInfo];
799 VkRect2D bounds;
800 bounds.offset = { 0, 0 };
801 bounds.extent = { 0, 0 };
802
803 GrVkDrawableInfo vkInfo;
804 vkInfo.fSecondaryCommandBuffer = cbInfo.currentCmdBuf()->vkCommandBuffer();
805 vkInfo.fCompatibleRenderPass = cbInfo.fRenderPass->vkRenderPass();
Greg Danielb353eeb2018-12-05 11:01:58 -0500806 SkAssertResult(cbInfo.fRenderPass->colorAttachmentIndex(&vkInfo.fColorAttachmentIndex));
Greg Daniel64cc9aa2018-10-19 13:54:56 -0400807 vkInfo.fFormat = targetImage->imageFormat();
808 vkInfo.fDrawBounds = &bounds;
809
810 GrBackendDrawableInfo info(vkInfo);
811
812 drawable->draw(info);
813 fGpu->addDrawable(std::move(drawable));
814
815 if (bounds.extent.width == 0 || bounds.extent.height == 0) {
816 cbInfo.fBounds.join(target->getBoundsRect());
817 } else {
818 cbInfo.fBounds.join(SkRect::MakeXYWH(bounds.offset.x, bounds.offset.y,
819 bounds.extent.width, bounds.extent.height));
820 }
821}
822