blob: 8baf60e1e8696669a3f210ce3e8c5806ab07a25f [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
csmartdalton29df7602016-08-31 11:55:52 -070010#include "GrFixedClip.h"
egdaniel9cb63402016-06-23 08:37:05 -070011#include "GrMesh.h"
Brian Salomon742e31d2016-12-07 17:06:19 -050012#include "GrOpFlushState.h"
egdaniel9cb63402016-06-23 08:37:05 -070013#include "GrPipeline.h"
14#include "GrRenderTargetPriv.h"
egdaniel9cb63402016-06-23 08:37:05 -070015#include "GrTexturePriv.h"
egdaniel066df7c2016-06-08 14:02:27 -070016#include "GrVkCommandBuffer.h"
17#include "GrVkGpu.h"
egdaniel9cb63402016-06-23 08:37:05 -070018#include "GrVkPipeline.h"
egdaniel066df7c2016-06-08 14:02:27 -070019#include "GrVkRenderPass.h"
20#include "GrVkRenderTarget.h"
21#include "GrVkResourceProvider.h"
egdaniel9cb63402016-06-23 08:37:05 -070022#include "GrVkTexture.h"
Greg Daniel36a77ee2016-10-18 10:33:25 -040023#include "SkRect.h"
egdaniel066df7c2016-06-08 14:02:27 -070024
egdaniel9cb63402016-06-23 08:37:05 -070025void get_vk_load_store_ops(const GrGpuCommandBuffer::LoadAndStoreInfo& info,
egdaniel066df7c2016-06-08 14:02:27 -070026 VkAttachmentLoadOp* loadOp, VkAttachmentStoreOp* storeOp) {
egdaniel9cb63402016-06-23 08:37:05 -070027 switch (info.fLoadOp) {
28 case GrGpuCommandBuffer::LoadOp::kLoad:
egdaniel066df7c2016-06-08 14:02:27 -070029 *loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
egdaniel066df7c2016-06-08 14:02:27 -070030 break;
egdaniel9cb63402016-06-23 08:37:05 -070031 case GrGpuCommandBuffer::LoadOp::kClear:
32 *loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
33 break;
34 case GrGpuCommandBuffer::LoadOp::kDiscard:
35 *loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
36 break;
37 default:
38 SK_ABORT("Invalid LoadOp");
egdaniel066df7c2016-06-08 14:02:27 -070039 *loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
egdaniel9cb63402016-06-23 08:37:05 -070040 }
41
42 switch (info.fStoreOp) {
43 case GrGpuCommandBuffer::StoreOp::kStore:
egdaniel066df7c2016-06-08 14:02:27 -070044 *storeOp = VK_ATTACHMENT_STORE_OP_STORE;
45 break;
egdaniel9cb63402016-06-23 08:37:05 -070046 case GrGpuCommandBuffer::StoreOp::kDiscard:
egdaniel066df7c2016-06-08 14:02:27 -070047 *storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
48 break;
brianosman0bbc3712016-06-14 04:53:09 -070049 default:
egdaniel9cb63402016-06-23 08:37:05 -070050 SK_ABORT("Invalid StoreOp");
brianosman0bbc3712016-06-14 04:53:09 -070051 *storeOp = VK_ATTACHMENT_STORE_OP_STORE;
egdaniel066df7c2016-06-08 14:02:27 -070052 }
53}
54
55GrVkGpuCommandBuffer::GrVkGpuCommandBuffer(GrVkGpu* gpu,
egdaniel9cb63402016-06-23 08:37:05 -070056 const LoadAndStoreInfo& colorInfo,
57 const LoadAndStoreInfo& stencilInfo)
58 : fGpu(gpu)
Brian Salomonc293a292016-11-30 13:38:32 -050059 , fRenderTarget(nullptr)
Greg Daniel22bc8652017-03-22 15:45:43 -040060 , fClearColor(GrColor4f::FromGrColor(colorInfo.fClearColor))
61 , fLastPipelineState(nullptr) {
egdaniel066df7c2016-06-08 14:02:27 -070062
Brian Salomonc293a292016-11-30 13:38:32 -050063 get_vk_load_store_ops(colorInfo, &fVkColorLoadOp, &fVkColorStoreOp);
egdaniel066df7c2016-06-08 14:02:27 -070064
Brian Salomonc293a292016-11-30 13:38:32 -050065 get_vk_load_store_ops(stencilInfo, &fVkStencilLoadOp, &fVkStencilStoreOp);
66
Greg Daniel22bc8652017-03-22 15:45:43 -040067 fCurrentCmdInfo = -1;
Brian Salomonc293a292016-11-30 13:38:32 -050068}
69
70void GrVkGpuCommandBuffer::init(GrVkRenderTarget* target) {
71 SkASSERT(!fRenderTarget);
72 fRenderTarget = target;
73
74 GrVkRenderPass::LoadStoreOps vkColorOps(fVkColorLoadOp, fVkColorStoreOp);
75 GrVkRenderPass::LoadStoreOps vkStencilOps(fVkStencilLoadOp, fVkStencilStoreOp);
egdaniel9cb63402016-06-23 08:37:05 -070076
Greg Daniel36a77ee2016-10-18 10:33:25 -040077 CommandBufferInfo& cbInfo = fCommandBufferInfos.push_back();
Brian Salomonc293a292016-11-30 13:38:32 -050078 SkASSERT(fCommandBufferInfos.count() == 1);
Greg Daniel22bc8652017-03-22 15:45:43 -040079 fCurrentCmdInfo = 0;
Greg Daniel36a77ee2016-10-18 10:33:25 -040080
egdaniel9cb63402016-06-23 08:37:05 -070081 const GrVkResourceProvider::CompatibleRPHandle& rpHandle = target->compatibleRenderPassHandle();
egdaniel066df7c2016-06-08 14:02:27 -070082 if (rpHandle.isValid()) {
Greg Daniel36a77ee2016-10-18 10:33:25 -040083 cbInfo.fRenderPass = fGpu->resourceProvider().findRenderPass(rpHandle,
84 vkColorOps,
85 vkStencilOps);
egdaniel066df7c2016-06-08 14:02:27 -070086 } else {
Greg Daniel36a77ee2016-10-18 10:33:25 -040087 cbInfo.fRenderPass = fGpu->resourceProvider().findRenderPass(*target,
88 vkColorOps,
89 vkStencilOps);
egdaniel066df7c2016-06-08 14:02:27 -070090 }
91
Brian Salomonc293a292016-11-30 13:38:32 -050092 cbInfo.fColorClearValue.color.float32[0] = fClearColor.fRGBA[0];
93 cbInfo.fColorClearValue.color.float32[1] = fClearColor.fRGBA[1];
94 cbInfo.fColorClearValue.color.float32[2] = fClearColor.fRGBA[2];
95 cbInfo.fColorClearValue.color.float32[3] = fClearColor.fRGBA[3];
egdaniel9cb63402016-06-23 08:37:05 -070096
Greg Daniel36a77ee2016-10-18 10:33:25 -040097 cbInfo.fBounds.setEmpty();
Greg Daniel77b53f62016-10-18 11:48:51 -040098 cbInfo.fIsEmpty = true;
99 cbInfo.fStartsWithClear = false;
Greg Daniel36a77ee2016-10-18 10:33:25 -0400100
Greg Daniel22bc8652017-03-22 15:45:43 -0400101 cbInfo.fCommandBuffers.push_back(fGpu->resourceProvider().findOrCreateSecondaryCommandBuffer());
102 cbInfo.currentCmdBuf()->begin(fGpu, target->framebuffer(), cbInfo.fRenderPass);
egdaniel066df7c2016-06-08 14:02:27 -0700103}
104
Brian Salomonc293a292016-11-30 13:38:32 -0500105
egdaniel066df7c2016-06-08 14:02:27 -0700106GrVkGpuCommandBuffer::~GrVkGpuCommandBuffer() {
Greg Daniel36a77ee2016-10-18 10:33:25 -0400107 for (int i = 0; i < fCommandBufferInfos.count(); ++i) {
108 CommandBufferInfo& cbInfo = fCommandBufferInfos[i];
Greg Daniel22bc8652017-03-22 15:45:43 -0400109 for (int j = 0; j < cbInfo.fCommandBuffers.count(); ++j) {
110 cbInfo.fCommandBuffers[j]->unref(fGpu);
111 }
Greg Daniel36a77ee2016-10-18 10:33:25 -0400112 cbInfo.fRenderPass->unref(fGpu);
113 }
egdaniel066df7c2016-06-08 14:02:27 -0700114}
115
egdaniel9cb63402016-06-23 08:37:05 -0700116GrGpu* GrVkGpuCommandBuffer::gpu() { return fGpu; }
Greg Daniel65a09272016-10-12 09:47:22 -0400117GrRenderTarget* GrVkGpuCommandBuffer::renderTarget() { return fRenderTarget; }
egdaniel9cb63402016-06-23 08:37:05 -0700118
egdaniel066df7c2016-06-08 14:02:27 -0700119void GrVkGpuCommandBuffer::end() {
Greg Daniel22bc8652017-03-22 15:45:43 -0400120 if (fCurrentCmdInfo >= 0) {
121 fCommandBufferInfos[fCurrentCmdInfo].currentCmdBuf()->end(fGpu);
Brian Salomonc293a292016-11-30 13:38:32 -0500122 }
egdaniel066df7c2016-06-08 14:02:27 -0700123}
124
Greg Daniel36a77ee2016-10-18 10:33:25 -0400125void GrVkGpuCommandBuffer::onSubmit() {
Brian Salomonc293a292016-11-30 13:38:32 -0500126 if (!fRenderTarget) {
127 return;
128 }
egdanielce3bfb12016-08-26 11:05:13 -0700129 // Change layout of our render target so it can be used as the color attachment. Currently
130 // we don't attach the resolve to the framebuffer so no need to change its layout.
egdaniel8d2141f2016-09-02 11:19:13 -0700131 GrVkImage* targetImage = fRenderTarget->msaaImage() ? fRenderTarget->msaaImage()
egdanielce3bfb12016-08-26 11:05:13 -0700132 : fRenderTarget;
egdanielbc9b2962016-09-27 08:00:53 -0700133
134 // Change layout of our render target so it can be used as the color attachment
egdanielce3bfb12016-08-26 11:05:13 -0700135 targetImage->setImageLayout(fGpu,
136 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
137 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
egdanielbc9b2962016-09-27 08:00:53 -0700138 VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
egdanielce3bfb12016-08-26 11:05:13 -0700139 false);
egdaniel9cb63402016-06-23 08:37:05 -0700140
141 // If we are using a stencil attachment we also need to update its layout
142 if (GrStencilAttachment* stencil = fRenderTarget->renderTargetPriv().getStencilAttachment()) {
143 GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil;
144 vkStencil->setImageLayout(fGpu,
145 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
146 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
147 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
egdanielbc9b2962016-09-27 08:00:53 -0700148 VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
egdaniel9cb63402016-06-23 08:37:05 -0700149 false);
150 }
151
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
160 // TODO: We can't add this optimization yet since many things create a scratch texture which
161 // adds the discard immediately, but then don't draw to it right away. This causes the
162 // discard to be ignored and we get yelled at for loading uninitialized data. However, once
163 // MDP lands, the discard will get reordered with the rest of the draw commands and we can
164 // re-enable this.
165#if 0
166 if (cbInfo.fIsEmpty && !cbInfo.fStartsWithClear) {
167 // We have sumbitted no actual draw commands to the command buffer and we are not using
168 // the render pass to do a clear so there is no need to submit anything.
169 continue;
170 }
171#endif
Greg Daniel36a77ee2016-10-18 10:33:25 -0400172 if (cbInfo.fBounds.intersect(0, 0,
173 SkIntToScalar(fRenderTarget->width()),
174 SkIntToScalar(fRenderTarget->height()))) {
175 SkIRect iBounds;
176 cbInfo.fBounds.roundOut(&iBounds);
177
Greg Daniel22bc8652017-03-22 15:45:43 -0400178 fGpu->submitSecondaryCommandBuffer(cbInfo.fCommandBuffers, cbInfo.fRenderPass,
Greg Daniel36a77ee2016-10-18 10:33:25 -0400179 &cbInfo.fColorClearValue, fRenderTarget, iBounds);
180 }
181 }
egdaniel9cb63402016-06-23 08:37:05 -0700182}
183
Brian Salomonc293a292016-11-30 13:38:32 -0500184void GrVkGpuCommandBuffer::discard(GrRenderTarget* rt) {
185 GrVkRenderTarget* target = static_cast<GrVkRenderTarget*>(rt);
186 if (!fRenderTarget) {
187 this->init(target);
188 }
189 SkASSERT(target == fRenderTarget);
190
Greg Daniel22bc8652017-03-22 15:45:43 -0400191 CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdInfo];
Greg Daniel77b53f62016-10-18 11:48:51 -0400192 if (cbInfo.fIsEmpty) {
egdaniel37535c92016-06-30 08:23:30 -0700193 // We will change the render pass to do a clear load instead
194 GrVkRenderPass::LoadStoreOps vkColorOps(VK_ATTACHMENT_LOAD_OP_DONT_CARE,
195 VK_ATTACHMENT_STORE_OP_STORE);
196 GrVkRenderPass::LoadStoreOps vkStencilOps(VK_ATTACHMENT_LOAD_OP_DONT_CARE,
197 VK_ATTACHMENT_STORE_OP_STORE);
egdaniel37535c92016-06-30 08:23:30 -0700198
Greg Daniel36a77ee2016-10-18 10:33:25 -0400199 const GrVkRenderPass* oldRP = cbInfo.fRenderPass;
egdaniel37535c92016-06-30 08:23:30 -0700200
egdaniel37535c92016-06-30 08:23:30 -0700201 const GrVkResourceProvider::CompatibleRPHandle& rpHandle =
Greg Daniel65a09272016-10-12 09:47:22 -0400202 fRenderTarget->compatibleRenderPassHandle();
egdaniel37535c92016-06-30 08:23:30 -0700203 if (rpHandle.isValid()) {
Greg Daniel36a77ee2016-10-18 10:33:25 -0400204 cbInfo.fRenderPass = fGpu->resourceProvider().findRenderPass(rpHandle,
205 vkColorOps,
206 vkStencilOps);
egdaniel37535c92016-06-30 08:23:30 -0700207 } else {
Greg Daniel36a77ee2016-10-18 10:33:25 -0400208 cbInfo.fRenderPass = fGpu->resourceProvider().findRenderPass(*fRenderTarget,
209 vkColorOps,
210 vkStencilOps);
egdaniel37535c92016-06-30 08:23:30 -0700211 }
212
Greg Daniel36a77ee2016-10-18 10:33:25 -0400213 SkASSERT(cbInfo.fRenderPass->isCompatible(*oldRP));
egdaniel37535c92016-06-30 08:23:30 -0700214 oldRP->unref(fGpu);
Greg Daniel5011f852016-10-28 15:07:16 -0400215 cbInfo.fBounds.join(fRenderTarget->getBoundsRect());
Greg Daniel77b53f62016-10-18 11:48:51 -0400216 cbInfo.fStartsWithClear = false;
egdaniel37535c92016-06-30 08:23:30 -0700217 }
218}
219
Brian Salomonc293a292016-11-30 13:38:32 -0500220void GrVkGpuCommandBuffer::onClearStencilClip(GrRenderTarget* rt, const GrFixedClip& clip,
csmartdalton29df7602016-08-31 11:55:52 -0700221 bool insideStencilMask) {
csmartdaltonbf4a8f92016-09-06 10:01:06 -0700222 SkASSERT(!clip.hasWindowRectangles());
egdaniel9cb63402016-06-23 08:37:05 -0700223
Brian Salomonc293a292016-11-30 13:38:32 -0500224 GrVkRenderTarget* target = static_cast<GrVkRenderTarget*>(rt);
225 if (!fRenderTarget) {
226 this->init(target);
227 }
228 SkASSERT(target == fRenderTarget);
229
Greg Daniel22bc8652017-03-22 15:45:43 -0400230 CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdInfo];
Greg Daniel36a77ee2016-10-18 10:33:25 -0400231
Greg Daniel65a09272016-10-12 09:47:22 -0400232 GrStencilAttachment* sb = fRenderTarget->renderTargetPriv().getStencilAttachment();
egdaniel9cb63402016-06-23 08:37:05 -0700233 // this should only be called internally when we know we have a
234 // stencil buffer.
235 SkASSERT(sb);
236 int stencilBitCount = sb->bits();
237
238 // The contract with the callers does not guarantee that we preserve all bits in the stencil
239 // during this clear. Thus we will clear the entire stencil to the desired value.
240
241 VkClearDepthStencilValue vkStencilColor;
242 memset(&vkStencilColor, 0, sizeof(VkClearDepthStencilValue));
csmartdalton29df7602016-08-31 11:55:52 -0700243 if (insideStencilMask) {
egdaniel9cb63402016-06-23 08:37:05 -0700244 vkStencilColor.stencil = (1 << (stencilBitCount - 1));
245 } else {
246 vkStencilColor.stencil = 0;
247 }
248
249 VkClearRect clearRect;
250 // Flip rect if necessary
csmartdalton29df7602016-08-31 11:55:52 -0700251 SkIRect vkRect;
252 if (!clip.scissorEnabled()) {
Greg Daniel65a09272016-10-12 09:47:22 -0400253 vkRect.setXYWH(0, 0, fRenderTarget->width(), fRenderTarget->height());
254 } else if (kBottomLeft_GrSurfaceOrigin != fRenderTarget->origin()) {
csmartdalton29df7602016-08-31 11:55:52 -0700255 vkRect = clip.scissorRect();
256 } else {
257 const SkIRect& scissor = clip.scissorRect();
Greg Daniel65a09272016-10-12 09:47:22 -0400258 vkRect.setLTRB(scissor.fLeft, fRenderTarget->height() - scissor.fBottom,
259 scissor.fRight, fRenderTarget->height() - scissor.fTop);
egdaniel9cb63402016-06-23 08:37:05 -0700260 }
261
262 clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop };
263 clearRect.rect.extent = { (uint32_t)vkRect.width(), (uint32_t)vkRect.height() };
264
265 clearRect.baseArrayLayer = 0;
266 clearRect.layerCount = 1;
267
268 uint32_t stencilIndex;
Greg Daniel36a77ee2016-10-18 10:33:25 -0400269 SkAssertResult(cbInfo.fRenderPass->stencilAttachmentIndex(&stencilIndex));
egdaniel9cb63402016-06-23 08:37:05 -0700270
271 VkClearAttachment attachment;
272 attachment.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
273 attachment.colorAttachment = 0; // this value shouldn't matter
274 attachment.clearValue.depthStencil = vkStencilColor;
275
Greg Daniel22bc8652017-03-22 15:45:43 -0400276 cbInfo.currentCmdBuf()->clearAttachments(fGpu, 1, &attachment, 1, &clearRect);
Greg Daniel77b53f62016-10-18 11:48:51 -0400277 cbInfo.fIsEmpty = false;
Greg Daniel36a77ee2016-10-18 10:33:25 -0400278
279 // Update command buffer bounds
280 if (!clip.scissorEnabled()) {
281 cbInfo.fBounds.join(fRenderTarget->getBoundsRect());
282 } else {
283 cbInfo.fBounds.join(SkRect::Make(clip.scissorRect()));
284 }
egdaniel9cb63402016-06-23 08:37:05 -0700285}
286
Brian Salomonc293a292016-11-30 13:38:32 -0500287void GrVkGpuCommandBuffer::onClear(GrRenderTarget* rt, const GrFixedClip& clip, GrColor color) {
egdaniel9cb63402016-06-23 08:37:05 -0700288 // parent class should never let us get here with no RT
csmartdaltonbf4a8f92016-09-06 10:01:06 -0700289 SkASSERT(!clip.hasWindowRectangles());
egdaniel9cb63402016-06-23 08:37:05 -0700290
Brian Salomonc293a292016-11-30 13:38:32 -0500291 GrVkRenderTarget* target = static_cast<GrVkRenderTarget*>(rt);
292 if (!fRenderTarget) {
293 this->init(target);
294 }
295 SkASSERT(target == fRenderTarget);
296
Greg Daniel22bc8652017-03-22 15:45:43 -0400297 CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdInfo];
Greg Daniel36a77ee2016-10-18 10:33:25 -0400298
egdaniel9cb63402016-06-23 08:37:05 -0700299 VkClearColorValue vkColor;
300 GrColorToRGBAFloat(color, vkColor.float32);
301
Greg Daniel77b53f62016-10-18 11:48:51 -0400302 if (cbInfo.fIsEmpty && !clip.scissorEnabled()) {
egdaniel9cb63402016-06-23 08:37:05 -0700303 // We will change the render pass to do a clear load instead
304 GrVkRenderPass::LoadStoreOps vkColorOps(VK_ATTACHMENT_LOAD_OP_CLEAR,
305 VK_ATTACHMENT_STORE_OP_STORE);
306 GrVkRenderPass::LoadStoreOps vkStencilOps(VK_ATTACHMENT_LOAD_OP_LOAD,
307 VK_ATTACHMENT_STORE_OP_STORE);
egdaniel9cb63402016-06-23 08:37:05 -0700308
Greg Daniel36a77ee2016-10-18 10:33:25 -0400309 const GrVkRenderPass* oldRP = cbInfo.fRenderPass;
egdaniel9cb63402016-06-23 08:37:05 -0700310
311 const GrVkResourceProvider::CompatibleRPHandle& rpHandle =
Greg Daniel65a09272016-10-12 09:47:22 -0400312 fRenderTarget->compatibleRenderPassHandle();
egdaniel9cb63402016-06-23 08:37:05 -0700313 if (rpHandle.isValid()) {
Greg Daniel36a77ee2016-10-18 10:33:25 -0400314 cbInfo.fRenderPass = fGpu->resourceProvider().findRenderPass(rpHandle,
315 vkColorOps,
316 vkStencilOps);
egdaniel9cb63402016-06-23 08:37:05 -0700317 } else {
Greg Daniel36a77ee2016-10-18 10:33:25 -0400318 cbInfo.fRenderPass = fGpu->resourceProvider().findRenderPass(*fRenderTarget,
319 vkColorOps,
320 vkStencilOps);
egdaniel9cb63402016-06-23 08:37:05 -0700321 }
322
Greg Daniel36a77ee2016-10-18 10:33:25 -0400323 SkASSERT(cbInfo.fRenderPass->isCompatible(*oldRP));
egdaniel9cb63402016-06-23 08:37:05 -0700324 oldRP->unref(fGpu);
325
Greg Daniel36a77ee2016-10-18 10:33:25 -0400326 GrColorToRGBAFloat(color, cbInfo.fColorClearValue.color.float32);
Greg Daniel77b53f62016-10-18 11:48:51 -0400327 cbInfo.fStartsWithClear = true;
Greg Daniel36a77ee2016-10-18 10:33:25 -0400328
329 // Update command buffer bounds
330 cbInfo.fBounds.join(fRenderTarget->getBoundsRect());
egdaniel9cb63402016-06-23 08:37:05 -0700331 return;
332 }
333
334 // We always do a sub rect clear with clearAttachments since we are inside a render pass
335 VkClearRect clearRect;
336 // Flip rect if necessary
csmartdalton29df7602016-08-31 11:55:52 -0700337 SkIRect vkRect;
338 if (!clip.scissorEnabled()) {
Greg Daniel65a09272016-10-12 09:47:22 -0400339 vkRect.setXYWH(0, 0, fRenderTarget->width(), fRenderTarget->height());
340 } else if (kBottomLeft_GrSurfaceOrigin != fRenderTarget->origin()) {
csmartdalton29df7602016-08-31 11:55:52 -0700341 vkRect = clip.scissorRect();
342 } else {
343 const SkIRect& scissor = clip.scissorRect();
Greg Daniel65a09272016-10-12 09:47:22 -0400344 vkRect.setLTRB(scissor.fLeft, fRenderTarget->height() - scissor.fBottom,
345 scissor.fRight, fRenderTarget->height() - scissor.fTop);
egdaniel9cb63402016-06-23 08:37:05 -0700346 }
347 clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop };
348 clearRect.rect.extent = { (uint32_t)vkRect.width(), (uint32_t)vkRect.height() };
349 clearRect.baseArrayLayer = 0;
350 clearRect.layerCount = 1;
351
352 uint32_t colorIndex;
Greg Daniel36a77ee2016-10-18 10:33:25 -0400353 SkAssertResult(cbInfo.fRenderPass->colorAttachmentIndex(&colorIndex));
egdaniel9cb63402016-06-23 08:37:05 -0700354
355 VkClearAttachment attachment;
356 attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
357 attachment.colorAttachment = colorIndex;
358 attachment.clearValue.color = vkColor;
359
Greg Daniel22bc8652017-03-22 15:45:43 -0400360 cbInfo.currentCmdBuf()->clearAttachments(fGpu, 1, &attachment, 1, &clearRect);
Greg Daniel77b53f62016-10-18 11:48:51 -0400361 cbInfo.fIsEmpty = false;
Greg Daniel36a77ee2016-10-18 10:33:25 -0400362
363 // Update command buffer bounds
364 if (!clip.scissorEnabled()) {
365 cbInfo.fBounds.join(fRenderTarget->getBoundsRect());
366 } else {
367 cbInfo.fBounds.join(SkRect::Make(clip.scissorRect()));
368 }
egdaniel9cb63402016-06-23 08:37:05 -0700369 return;
370}
371
Greg Daniel77b53f62016-10-18 11:48:51 -0400372void GrVkGpuCommandBuffer::addAdditionalCommandBuffer() {
Greg Daniel22bc8652017-03-22 15:45:43 -0400373 CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdInfo];
374 cbInfo.currentCmdBuf()->end(fGpu);
375 cbInfo.fCommandBuffers.push_back(fGpu->resourceProvider().findOrCreateSecondaryCommandBuffer());
376 cbInfo.currentCmdBuf()->begin(fGpu, fRenderTarget->framebuffer(), cbInfo.fRenderPass);
377}
378
379void GrVkGpuCommandBuffer::addAdditionalRenderPass() {
380 fCommandBufferInfos[fCurrentCmdInfo].currentCmdBuf()->end(fGpu);
Greg Daniel77b53f62016-10-18 11:48:51 -0400381
382 CommandBufferInfo& cbInfo = fCommandBufferInfos.push_back();
Greg Daniel22bc8652017-03-22 15:45:43 -0400383 fCurrentCmdInfo++;
Greg Daniel77b53f62016-10-18 11:48:51 -0400384
385 GrVkRenderPass::LoadStoreOps vkColorOps(VK_ATTACHMENT_LOAD_OP_LOAD,
386 VK_ATTACHMENT_STORE_OP_STORE);
387 GrVkRenderPass::LoadStoreOps vkStencilOps(VK_ATTACHMENT_LOAD_OP_LOAD,
388 VK_ATTACHMENT_STORE_OP_STORE);
389
390 const GrVkResourceProvider::CompatibleRPHandle& rpHandle =
391 fRenderTarget->compatibleRenderPassHandle();
392 if (rpHandle.isValid()) {
393 cbInfo.fRenderPass = fGpu->resourceProvider().findRenderPass(rpHandle,
394 vkColorOps,
395 vkStencilOps);
396 } else {
397 cbInfo.fRenderPass = fGpu->resourceProvider().findRenderPass(*fRenderTarget,
398 vkColorOps,
399 vkStencilOps);
400 }
401
Greg Daniel22bc8652017-03-22 15:45:43 -0400402 cbInfo.fCommandBuffers.push_back(fGpu->resourceProvider().findOrCreateSecondaryCommandBuffer());
Greg Daniel77b53f62016-10-18 11:48:51 -0400403 // It shouldn't matter what we set the clear color to here since we will assume loading of the
404 // attachment.
405 memset(&cbInfo.fColorClearValue, 0, sizeof(VkClearValue));
406 cbInfo.fBounds.setEmpty();
407 cbInfo.fIsEmpty = true;
408 cbInfo.fStartsWithClear = false;
409
Greg Daniel22bc8652017-03-22 15:45:43 -0400410 cbInfo.currentCmdBuf()->begin(fGpu, fRenderTarget->framebuffer(), cbInfo.fRenderPass);
Greg Daniel77b53f62016-10-18 11:48:51 -0400411}
412
Greg Danieldbd11ec2017-03-21 16:56:31 -0400413void GrVkGpuCommandBuffer::inlineUpload(GrOpFlushState* state, GrDrawOp::DeferredUploadFn& upload,
414 GrRenderTarget* rt) {
415 GrVkRenderTarget* target = static_cast<GrVkRenderTarget*>(rt);
416 if (!fRenderTarget) {
417 this->init(target);
418 }
Greg Daniel22bc8652017-03-22 15:45:43 -0400419 if (!fCommandBufferInfos[fCurrentCmdInfo].fIsEmpty) {
420 this->addAdditionalRenderPass();
Greg Daniel77b53f62016-10-18 11:48:51 -0400421 }
Greg Daniel22bc8652017-03-22 15:45:43 -0400422 fCommandBufferInfos[fCurrentCmdInfo].fPreDrawUploads.emplace_back(state, upload);
Greg Daniel77b53f62016-10-18 11:48:51 -0400423}
424
egdaniel9cb63402016-06-23 08:37:05 -0700425////////////////////////////////////////////////////////////////////////////////
426
427void GrVkGpuCommandBuffer::bindGeometry(const GrPrimitiveProcessor& primProc,
428 const GrNonInstancedMesh& mesh) {
Greg Daniel22bc8652017-03-22 15:45:43 -0400429 CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdInfo];
egdaniel9cb63402016-06-23 08:37:05 -0700430 // There is no need to put any memory barriers to make sure host writes have finished here.
431 // When a command buffer is submitted to a queue, there is an implicit memory barrier that
432 // occurs for all host writes. Additionally, BufferMemoryBarriers are not allowed inside of
433 // an active RenderPass.
csmartdalton485a1202016-07-13 10:16:32 -0700434 SkASSERT(!mesh.vertexBuffer()->isCPUBacked());
egdaniel9cb63402016-06-23 08:37:05 -0700435 GrVkVertexBuffer* vbuf;
436 vbuf = (GrVkVertexBuffer*)mesh.vertexBuffer();
437 SkASSERT(vbuf);
438 SkASSERT(!vbuf->isMapped());
439
Greg Daniel22bc8652017-03-22 15:45:43 -0400440 cbInfo.currentCmdBuf()->bindVertexBuffer(fGpu, vbuf);
egdaniel9cb63402016-06-23 08:37:05 -0700441
442 if (mesh.isIndexed()) {
csmartdalton485a1202016-07-13 10:16:32 -0700443 SkASSERT(!mesh.indexBuffer()->isCPUBacked());
egdaniel9cb63402016-06-23 08:37:05 -0700444 GrVkIndexBuffer* ibuf = (GrVkIndexBuffer*)mesh.indexBuffer();
445 SkASSERT(ibuf);
446 SkASSERT(!ibuf->isMapped());
447
Greg Daniel22bc8652017-03-22 15:45:43 -0400448 cbInfo.currentCmdBuf()->bindIndexBuffer(fGpu, ibuf);
egdaniel9cb63402016-06-23 08:37:05 -0700449 }
450}
451
452sk_sp<GrVkPipelineState> GrVkGpuCommandBuffer::prepareDrawState(
453 const GrPipeline& pipeline,
454 const GrPrimitiveProcessor& primProc,
Greg Daniel36a77ee2016-10-18 10:33:25 -0400455 GrPrimitiveType primitiveType) {
Greg Daniel22bc8652017-03-22 15:45:43 -0400456 CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdInfo];
457 SkASSERT(cbInfo.fRenderPass);
Greg Daniel36a77ee2016-10-18 10:33:25 -0400458
egdaniel9cb63402016-06-23 08:37:05 -0700459 sk_sp<GrVkPipelineState> pipelineState =
460 fGpu->resourceProvider().findOrCreateCompatiblePipelineState(pipeline,
461 primProc,
462 primitiveType,
Greg Daniel36a77ee2016-10-18 10:33:25 -0400463 *cbInfo.fRenderPass);
egdaniel9cb63402016-06-23 08:37:05 -0700464 if (!pipelineState) {
465 return pipelineState;
466 }
467
Greg Daniel22bc8652017-03-22 15:45:43 -0400468 if (!cbInfo.fIsEmpty &&
469 fLastPipelineState && fLastPipelineState != pipelineState.get() &&
470 fGpu->vkCaps().newSecondaryCBOnPipelineChange()) {
471 this->addAdditionalCommandBuffer();
472 }
473 fLastPipelineState = pipelineState.get();
474
egdaniel9cb63402016-06-23 08:37:05 -0700475 pipelineState->setData(fGpu, primProc, pipeline);
476
Greg Daniel22bc8652017-03-22 15:45:43 -0400477 pipelineState->bind(fGpu, cbInfo.currentCmdBuf());
egdaniel9cb63402016-06-23 08:37:05 -0700478
Greg Daniel22bc8652017-03-22 15:45:43 -0400479 GrVkPipeline::SetDynamicState(fGpu, cbInfo.currentCmdBuf(), pipeline);
egdaniel9cb63402016-06-23 08:37:05 -0700480
481 return pipelineState;
482}
483
Brian Salomon18dfa982017-04-03 16:57:43 -0400484static void set_texture_layout(GrVkTexture* vkTexture, GrVkGpu* gpu) {
485 // TODO: If we ever decide to create the secondary command buffers ahead of time before we
486 // are actually going to submit them, we will need to track the sampled images and delay
487 // adding the layout change/barrier until we are ready to submit.
488 vkTexture->setImageLayout(gpu,
489 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
490 VK_ACCESS_SHADER_READ_BIT,
491 VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
492 false);
493}
494
egdaniel8d2141f2016-09-02 11:19:13 -0700495static void prepare_sampled_images(const GrProcessor& processor, GrVkGpu* gpu) {
Brian Salomon0bbecb22016-11-17 11:38:22 -0500496 for (int i = 0; i < processor.numTextureSamplers(); ++i) {
497 const GrProcessor::TextureSampler& sampler = processor.textureSampler(i);
Brian Salomondb4183d2016-11-17 12:48:40 -0500498 GrVkTexture* vkTexture = static_cast<GrVkTexture*>(sampler.texture());
egdaniel8d2141f2016-09-02 11:19:13 -0700499 SkASSERT(vkTexture);
egdaniel66933552016-08-24 07:22:19 -0700500
egdaniel8d2141f2016-09-02 11:19:13 -0700501 // We may need to resolve the texture first if it is also a render target
502 GrVkRenderTarget* texRT = static_cast<GrVkRenderTarget*>(vkTexture->asRenderTarget());
503 if (texRT) {
504 gpu->onResolveRenderTarget(texRT);
505 }
506
Brian Salomon514baff2016-11-17 15:17:07 -0500507 const GrSamplerParams& params = sampler.params();
egdaniel8d2141f2016-09-02 11:19:13 -0700508 // Check if we need to regenerate any mip maps
Brian Salomon514baff2016-11-17 15:17:07 -0500509 if (GrSamplerParams::kMipMap_FilterMode == params.filterMode()) {
egdaniel8d2141f2016-09-02 11:19:13 -0700510 if (vkTexture->texturePriv().mipMapsAreDirty()) {
511 gpu->generateMipmap(vkTexture);
512 vkTexture->texturePriv().dirtyMipMaps(false);
egdaniel66933552016-08-24 07:22:19 -0700513 }
egdaniel8d2141f2016-09-02 11:19:13 -0700514 }
Brian Salomon18dfa982017-04-03 16:57:43 -0400515 set_texture_layout(vkTexture, gpu);
egdaniel9cb63402016-06-23 08:37:05 -0700516 }
517}
518
519void GrVkGpuCommandBuffer::onDraw(const GrPipeline& pipeline,
520 const GrPrimitiveProcessor& primProc,
521 const GrMesh* meshes,
Greg Daniel36a77ee2016-10-18 10:33:25 -0400522 int meshCount,
523 const SkRect& bounds) {
Brian Salomonc293a292016-11-30 13:38:32 -0500524 GrVkRenderTarget* target = static_cast<GrVkRenderTarget*>(pipeline.getRenderTarget());
525 if (!fRenderTarget) {
526 this->init(target);
527 }
528 SkASSERT(target == fRenderTarget);
529
egdaniel9cb63402016-06-23 08:37:05 -0700530 if (!meshCount) {
531 return;
532 }
egdaniel8d2141f2016-09-02 11:19:13 -0700533 prepare_sampled_images(primProc, fGpu);
bsalomonb58a2b42016-09-26 06:55:02 -0700534 GrFragmentProcessor::Iter iter(pipeline);
535 while (const GrFragmentProcessor* fp = iter.next()) {
536 prepare_sampled_images(*fp, fGpu);
egdaniel2f5792a2016-07-06 08:51:23 -0700537 }
Brian Salomon18dfa982017-04-03 16:57:43 -0400538 if (GrVkTexture* dstTexture = static_cast<GrVkTexture*>(pipeline.dstTexture())) {
539 set_texture_layout(dstTexture, fGpu);
540 }
egdaniel2f5792a2016-07-06 08:51:23 -0700541
egdaniel9cb63402016-06-23 08:37:05 -0700542 GrPrimitiveType primitiveType = meshes[0].primitiveType();
543 sk_sp<GrVkPipelineState> pipelineState = this->prepareDrawState(pipeline,
544 primProc,
Greg Daniel36a77ee2016-10-18 10:33:25 -0400545 primitiveType);
egdaniel9cb63402016-06-23 08:37:05 -0700546 if (!pipelineState) {
547 return;
548 }
549
Greg Daniel22bc8652017-03-22 15:45:43 -0400550 CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdInfo];
551
egdaniel9cb63402016-06-23 08:37:05 -0700552 for (int i = 0; i < meshCount; ++i) {
553 const GrMesh& mesh = meshes[i];
554 GrMesh::Iterator iter;
555 const GrNonInstancedMesh* nonIdxMesh = iter.init(mesh);
556 do {
557 if (nonIdxMesh->primitiveType() != primitiveType) {
558 // Technically we don't have to call this here (since there is a safety check in
559 // pipelineState:setData but this will allow for quicker freeing of resources if the
560 // pipelineState sits in a cache for a while.
561 pipelineState->freeTempResources(fGpu);
562 SkDEBUGCODE(pipelineState = nullptr);
563 primitiveType = nonIdxMesh->primitiveType();
564 pipelineState = this->prepareDrawState(pipeline,
565 primProc,
Greg Daniel36a77ee2016-10-18 10:33:25 -0400566 primitiveType);
egdaniel9cb63402016-06-23 08:37:05 -0700567 if (!pipelineState) {
568 return;
569 }
570 }
571 SkASSERT(pipelineState);
572 this->bindGeometry(primProc, *nonIdxMesh);
573
574 if (nonIdxMesh->isIndexed()) {
Greg Daniel22bc8652017-03-22 15:45:43 -0400575 cbInfo.currentCmdBuf()->drawIndexed(fGpu,
Greg Daniel36a77ee2016-10-18 10:33:25 -0400576 nonIdxMesh->indexCount(),
577 1,
578 nonIdxMesh->startIndex(),
579 nonIdxMesh->startVertex(),
580 0);
581 } else {
Greg Daniel22bc8652017-03-22 15:45:43 -0400582 cbInfo.currentCmdBuf()->draw(fGpu,
Greg Daniel36a77ee2016-10-18 10:33:25 -0400583 nonIdxMesh->vertexCount(),
egdaniel9cb63402016-06-23 08:37:05 -0700584 1,
egdaniel9cb63402016-06-23 08:37:05 -0700585 nonIdxMesh->startVertex(),
586 0);
egdaniel9cb63402016-06-23 08:37:05 -0700587 }
Greg Daniel77b53f62016-10-18 11:48:51 -0400588 cbInfo.fIsEmpty = false;
egdaniel9cb63402016-06-23 08:37:05 -0700589
590 fGpu->stats()->incNumDraws();
591 } while ((nonIdxMesh = iter.next()));
592 }
593
Greg Daniel36a77ee2016-10-18 10:33:25 -0400594 // Update command buffer bounds
595 cbInfo.fBounds.join(bounds);
596
egdaniel9cb63402016-06-23 08:37:05 -0700597 // Technically we don't have to call this here (since there is a safety check in
598 // pipelineState:setData but this will allow for quicker freeing of resources if the
599 // pipelineState sits in a cache for a while.
600 pipelineState->freeTempResources(fGpu);
egdaniel066df7c2016-06-08 14:02:27 -0700601}
602