Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(222)

Side by Side Diff: src/gpu/vk/GrVkGpuCommandBuffer.cpp

Issue 2078483002: Start using GrGpuCommandBuffer in GrDrawTarget. (Closed) Base URL: https://skia.googlesource.com/skia.git@memoryWAR
Patch Set: Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2016 Google Inc. 2 * Copyright 2016 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "GrVkGpuCommandBuffer.h" 8 #include "GrVkGpuCommandBuffer.h"
9 9
10 #include "GrMesh.h"
11 #include "GrPipeline.h"
12 #include "GrRenderTargetPriv.h"
13 #include "GrTextureAccess.h"
14 #include "GrTexturePriv.h"
10 #include "GrVkCommandBuffer.h" 15 #include "GrVkCommandBuffer.h"
11 #include "GrVkGpu.h" 16 #include "GrVkGpu.h"
17 #include "GrVkPipeline.h"
12 #include "GrVkRenderPass.h" 18 #include "GrVkRenderPass.h"
13 #include "GrVkRenderTarget.h" 19 #include "GrVkRenderTarget.h"
14 #include "GrVkResourceProvider.h" 20 #include "GrVkResourceProvider.h"
21 #include "GrVkTexture.h"
15 22
16 void get_vk_load_store_ops(GrGpuCommandBuffer::LoadAndStoreOp op, 23 void get_vk_load_store_ops(GrGpuCommandBuffer::LoadAndStoreOp op,
17 VkAttachmentLoadOp* loadOp, VkAttachmentStoreOp* stor eOp) { 24 VkAttachmentLoadOp* loadOp, VkAttachmentStoreOp* stor eOp) {
18 switch (op) { 25 switch (op) {
19 case GrGpuCommandBuffer::kLoadAndStore_LoadAndStoreOp: 26 case GrGpuCommandBuffer::kLoadAndStore_LoadAndStoreOp:
20 *loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; 27 *loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
21 *storeOp = VK_ATTACHMENT_STORE_OP_STORE; 28 *storeOp = VK_ATTACHMENT_STORE_OP_STORE;
22 break; 29 break;
23 case GrGpuCommandBuffer::kLoadAndDiscard_LoadAndStoreOp: 30 case GrGpuCommandBuffer::kLoadAndDiscard_LoadAndStoreOp:
24 *loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; 31 *loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
(...skipping 17 matching lines...) Expand all
42 break; 49 break;
43 default: 50 default:
44 SK_ABORT("Invalid LoadAndStoreOp"); 51 SK_ABORT("Invalid LoadAndStoreOp");
45 *loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; 52 *loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
46 *storeOp = VK_ATTACHMENT_STORE_OP_STORE; 53 *storeOp = VK_ATTACHMENT_STORE_OP_STORE;
47 break; 54 break;
48 } 55 }
49 } 56 }
50 57
51 GrVkGpuCommandBuffer::GrVkGpuCommandBuffer(GrVkGpu* gpu, 58 GrVkGpuCommandBuffer::GrVkGpuCommandBuffer(GrVkGpu* gpu,
52 const GrVkRenderTarget& target, 59 GrVkRenderTarget* target,
53 LoadAndStoreOp colorOp, GrColor color Clear, 60 LoadAndStoreOp colorOp, GrColor color Clear,
54 LoadAndStoreOp stencilOp, GrColor ste ncilClear) 61 LoadAndStoreOp stencilOp, GrColor ste ncilClear)
55 : fGpu(gpu) { 62 : fGpu(gpu)
63 , fRenderTarget(target) {
56 VkAttachmentLoadOp vkLoadOp; 64 VkAttachmentLoadOp vkLoadOp;
57 VkAttachmentStoreOp vkStoreOp; 65 VkAttachmentStoreOp vkStoreOp;
58 66
59 get_vk_load_store_ops(colorOp, &vkLoadOp, &vkStoreOp); 67 get_vk_load_store_ops(colorOp, &vkLoadOp, &vkStoreOp);
60 GrVkRenderPass::LoadStoreOps vkColorOps(vkLoadOp, vkStoreOp); 68 GrVkRenderPass::LoadStoreOps vkColorOps(vkLoadOp, vkStoreOp);
61 69
62 get_vk_load_store_ops(stencilOp, &vkLoadOp, &vkStoreOp); 70 get_vk_load_store_ops(stencilOp, &vkLoadOp, &vkStoreOp);
63 GrVkRenderPass::LoadStoreOps vkStencilOps(vkLoadOp, vkStoreOp); 71 GrVkRenderPass::LoadStoreOps vkStencilOps(vkLoadOp, vkStoreOp);
64 72
65 GrVkRenderPass::LoadStoreOps vkResolveOps(VK_ATTACHMENT_LOAD_OP_LOAD, 73 GrVkRenderPass::LoadStoreOps vkResolveOps(VK_ATTACHMENT_LOAD_OP_LOAD,
66 VK_ATTACHMENT_STORE_OP_STORE); 74 VK_ATTACHMENT_STORE_OP_STORE);
67 75
68 const GrVkResourceProvider::CompatibleRPHandle& rpHandle = target.compatible RenderPassHandle(); 76 const GrVkResourceProvider::CompatibleRPHandle& rpHandle = target->compatibl eRenderPassHandle();
69 if (rpHandle.isValid()) { 77 if (rpHandle.isValid()) {
70 fRenderPass = fGpu->resourceProvider().findRenderPass(rpHandle, 78 fRenderPass = fGpu->resourceProvider().findRenderPass(rpHandle,
71 vkColorOps, 79 vkColorOps,
72 vkResolveOps, 80 vkResolveOps,
73 vkStencilOps); 81 vkStencilOps);
74 } else { 82 } else {
75 fRenderPass = fGpu->resourceProvider().findRenderPass(target, 83 fRenderPass = fGpu->resourceProvider().findRenderPass(*target,
76 vkColorOps, 84 vkColorOps,
77 vkResolveOps, 85 vkResolveOps,
78 vkStencilOps); 86 vkStencilOps);
79 } 87 }
80 88
81 fCommandBuffer = GrVkSecondaryCommandBuffer::Create(gpu, gpu->cmdPool(), fRe nderPass); 89 fCommandBuffer = GrVkSecondaryCommandBuffer::Create(gpu, gpu->cmdPool(), fRe nderPass);
82 fCommandBuffer->begin(gpu, target.framebuffer()); 90 fCommandBuffer->begin(gpu, target->framebuffer());
83 } 91 }
84 92
85 GrVkGpuCommandBuffer::~GrVkGpuCommandBuffer() { 93 GrVkGpuCommandBuffer::~GrVkGpuCommandBuffer() {
86 fCommandBuffer->unref(fGpu); 94 fCommandBuffer->unref(fGpu);
87 fRenderPass->unref(fGpu); 95 fRenderPass->unref(fGpu);
88 } 96 }
89 97
98 GrGpu* GrVkGpuCommandBuffer::gpu() { return fGpu; }
99
90 void GrVkGpuCommandBuffer::end() { 100 void GrVkGpuCommandBuffer::end() {
91 fCommandBuffer->end(fGpu); 101 fCommandBuffer->end(fGpu);
92 } 102 }
93 103
94 void GrVkGpuCommandBuffer::submit() { 104 void GrVkGpuCommandBuffer::onSubmit(const SkIRect& bounds) {
95 fGpu->submitSecondaryCommandBuffer(fCommandBuffer); 105 // Change layout of our render target so it can be used as the color attachm ent
96 } 106 fRenderTarget->setImageLayout(fGpu,
97 107 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
108 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
109 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
110 false);
111
112 // If we are using a stencil attachment we also need to update its layout
113 if (GrStencilAttachment* stencil = fRenderTarget->renderTargetPriv().getSten cilAttachment()) {
114 GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil;
115 vkStencil->setImageLayout(fGpu,
116 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIM AL,
117 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
118 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
119 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
120 false);
121 }
122
123 for (int i = 0; i < fSampledImages.count(); ++i) {
124 fSampledImages[i]->setImageLayout(fGpu,
125 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIM AL,
126 VK_ACCESS_SHADER_READ_BIT,
127 VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
128 false);
129 }
130
131 fGpu->submitSecondaryCommandBuffer(fCommandBuffer, fRenderPass, fRenderTarge t, bounds);
132 }
133
134 void GrVkGpuCommandBuffer::onClearStencilClip(GrRenderTarget* target,
135 const SkIRect& rect,
136 bool insideClip) {
137 SkASSERT(target);
138
139 GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(target);
140 GrStencilAttachment* sb = target->renderTargetPriv().getStencilAttachment();
141 // this should only be called internally when we know we have a
142 // stencil buffer.
143 SkASSERT(sb);
144 int stencilBitCount = sb->bits();
145
146 // The contract with the callers does not guarantee that we preserve all bit s in the stencil
147 // during this clear. Thus we will clear the entire stencil to the desired v alue.
148
149 VkClearDepthStencilValue vkStencilColor;
150 memset(&vkStencilColor, 0, sizeof(VkClearDepthStencilValue));
151 if (insideClip) {
152 vkStencilColor.stencil = (1 << (stencilBitCount - 1));
153 } else {
154 vkStencilColor.stencil = 0;
155 }
156
157 VkClearRect clearRect;
158 // Flip rect if necessary
159 SkIRect vkRect = rect;
160
161 if (kBottomLeft_GrSurfaceOrigin == vkRT->origin()) {
162 vkRect.fTop = vkRT->height() - rect.fBottom;
163 vkRect.fBottom = vkRT->height() - rect.fTop;
164 }
165
166 clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop };
167 clearRect.rect.extent = { (uint32_t)vkRect.width(), (uint32_t)vkRect.height( ) };
168
169 clearRect.baseArrayLayer = 0;
170 clearRect.layerCount = 1;
171
172 uint32_t stencilIndex;
173 SkAssertResult(fRenderPass->stencilAttachmentIndex(&stencilIndex));
174
175 VkClearAttachment attachment;
176 attachment.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
177 attachment.colorAttachment = 0; // this value shouldn't matter
178 attachment.clearValue.depthStencil = vkStencilColor;
179
180 fCommandBuffer->clearAttachments(fGpu, 1, &attachment, 1, &clearRect);
181 }
182
183 void GrVkGpuCommandBuffer::onClear(GrRenderTarget* target, const SkIRect& rect, GrColor color) {
184 // Currently we should not see clears in vulkan since we are converting them all to draws.
185 // We do this since some clears currently can come in the must happen outsid e a render pass
186 // and we assume all commands in this buffer are inside a renderpass.
187 SkASSERT(false);
188 #if 0
189 // parent class should never let us get here with no RT
190 SkASSERT(target);
191
192 VkClearColorValue vkColor;
193 GrColorToRGBAFloat(color, vkColor.float32);
194
195 GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(target);
196
197 if (rect.width() != target->width() || rect.height() != target->height()) {
198 vkRT->setImageLayout(fGpu,
199 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
200 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
201 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
202 false);
203
204 // If we are using a stencil attachment we also need to change its layou t to what the render
205 // pass is expecting.
206 if (GrStencilAttachment* stencil = vkRT->renderTargetPriv().getStencilAt tachment()) {
207 GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil;
208 vkStencil->setImageLayout(fGpu,
209 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_O PTIMAL,
210 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_B IT |
211 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BI T,
212 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
213 false);
214 }
215
216 VkClearRect clearRect;
217 // Flip rect if necessary
218 SkIRect vkRect = rect;
219 if (kBottomLeft_GrSurfaceOrigin == vkRT->origin()) {
220 vkRect.fTop = vkRT->height() - rect.fBottom;
221 vkRect.fBottom = vkRT->height() - rect.fTop;
222 }
223 clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop };
224 clearRect.rect.extent = { (uint32_t)vkRect.width(), (uint32_t)vkRect.hei ght() };
225 clearRect.baseArrayLayer = 0;
226 clearRect.layerCount = 1;
227
228 const GrVkRenderPass* renderPass = vkRT->simpleRenderPass();
229 SkASSERT(renderPass);
230 fCommandBuffer->beginRenderPass(fGpu, renderPass, *vkRT);
231
232 uint32_t colorIndex;
233 SkAssertResult(renderPass->colorAttachmentIndex(&colorIndex));
234
235 VkClearAttachment attachment;
236 attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
237 attachment.colorAttachment = colorIndex;
238 attachment.clearValue.color = vkColor;
239
240 fCurrentCmdBuffer->clearAttachments(fGpu, 1, &attachment, 1, &clearRect) ;
241 fCurrentCmdBuffer->endRenderPass(fGpu);
242 return;
243 }
244
245 vkRT->setImageLayout(this,
246 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
247 VK_ACCESS_TRANSFER_WRITE_BIT,
248 VK_PIPELINE_STAGE_TRANSFER_BIT,
249 false);
250
251 VkImageSubresourceRange subRange;
252 memset(&subRange, 0, sizeof(VkImageSubresourceRange));
253 subRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
254 subRange.baseMipLevel = 0;
255 subRange.levelCount = 1;
256 subRange.baseArrayLayer = 0;
257 subRange.layerCount = 1;
258
259 // In the future we may not actually be doing this type of clear at all. If we are inside a
260 // render pass or doing a non full clear then we will use CmdClearColorAttac hment. The more
261 // common use case will be clearing an attachment at the start of a render p ass, in which case
262 // we will use the clear load ops.
263 fCommandBuffer->clearColorImage(this,
264 vkRT,
265 &vkColor,
266 1, &subRange);
267 #endif
268 }
269
270 ////////////////////////////////////////////////////////////////////////////////
271
272 void GrVkGpuCommandBuffer::bindGeometry(const GrPrimitiveProcessor& primProc,
273 const GrNonInstancedMesh& mesh) {
274 // There is no need to put any memory barriers to make sure host writes have finished here.
275 // When a command buffer is submitted to a queue, there is an implicit memor y barrier that
276 // occurs for all host writes. Additionally, BufferMemoryBarriers are not al lowed inside of
277 // an active RenderPass.
278 GrVkVertexBuffer* vbuf;
279 vbuf = (GrVkVertexBuffer*)mesh.vertexBuffer();
280 SkASSERT(vbuf);
281 SkASSERT(!vbuf->isMapped());
282
283 fCommandBuffer->bindVertexBuffer(fGpu, vbuf);
284
285 if (mesh.isIndexed()) {
286 GrVkIndexBuffer* ibuf = (GrVkIndexBuffer*)mesh.indexBuffer();
287 SkASSERT(ibuf);
288 SkASSERT(!ibuf->isMapped());
289
290 fCommandBuffer->bindIndexBuffer(fGpu, ibuf);
291 }
292 }
293
294 sk_sp<GrVkPipelineState> GrVkGpuCommandBuffer::prepareDrawState(
295 const GrPipeline& pipeline,
296 const GrPrimitive Processor& primProc,
297 GrPrimitiveType p rimitiveType,
298 const GrVkRenderP ass& renderPass) {
299 sk_sp<GrVkPipelineState> pipelineState =
300 fGpu->resourceProvider().findOrCreateCompatiblePipelineState(pipeline,
301 primProc,
302 primitiveTy pe,
303 renderPass) ;
304 if (!pipelineState) {
305 return pipelineState;
306 }
307
308 pipelineState->setData(fGpu, primProc, pipeline);
309
310 pipelineState->bind(fGpu, fCommandBuffer);
311
312 GrVkPipeline::SetDynamicState(fGpu, fCommandBuffer, pipeline);
313
314 return pipelineState;
315 }
316
317 static void append_sampled_images(const GrProcessor& processor,
318 const GrVkGpu* gpu,
319 SkTArray<GrVkImage*>* sampledImages) {
320 if (int numTextures = processor.numTextures()) {
321 GrVkImage** images = sampledImages->push_back_n(numTextures);
322 int i = 0;
323 do {
324 const GrTextureAccess& texAccess = processor.textureAccess(i);
325 GrVkTexture* vkTexture = static_cast<GrVkTexture*>(processor.texture (i));
326 SkASSERT(vkTexture);
327 const GrTextureParams& params = texAccess.getParams();
328 // Check if we need to regenerate any mip maps
329 if (GrTextureParams::kMipMap_FilterMode == params.filterMode()) {
330 if (vkTexture->texturePriv().mipMapsAreDirty()) {
331 gpu->generateMipmap(vkTexture);
332 vkTexture->texturePriv().dirtyMipMaps(false);
333 }
334 }
335
336 images[i] = vkTexture;
337 } while (++i < numTextures);
338
339 }
340 }
341
342 void GrVkGpuCommandBuffer::onDraw(const GrPipeline& pipeline,
343 const GrPrimitiveProcessor& primProc,
344 const GrMesh* meshes,
345 int meshCount) {
346 if (!meshCount) {
347 return;
348 }
349 GrRenderTarget* rt = pipeline.getRenderTarget();
350 GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(rt);
351 const GrVkRenderPass* renderPass = vkRT->simpleRenderPass();
352 SkASSERT(renderPass);
353
354 GrPrimitiveType primitiveType = meshes[0].primitiveType();
355 sk_sp<GrVkPipelineState> pipelineState = this->prepareDrawState(pipeline,
356 primProc,
357 primitiveTyp e,
358 *renderPass) ;
359 if (!pipelineState) {
360 return;
361 }
362
363 append_sampled_images(primProc, fGpu, &fSampledImages);
364 for (int i = 0; i < pipeline.numFragmentProcessors(); ++i) {
365 append_sampled_images(pipeline.getFragmentProcessor(i), fGpu, &fSampledI mages);
366 }
367 append_sampled_images(pipeline.getXferProcessor(), fGpu, &fSampledImages);
368
369 for (int i = 0; i < meshCount; ++i) {
370 const GrMesh& mesh = meshes[i];
371 GrMesh::Iterator iter;
372 const GrNonInstancedMesh* nonIdxMesh = iter.init(mesh);
373 do {
374 if (nonIdxMesh->primitiveType() != primitiveType) {
375 // Technically we don't have to call this here (since there is a safety check in
376 // pipelineState:setData but this will allow for quicker freeing of resources if the
377 // pipelineState sits in a cache for a while.
378 pipelineState->freeTempResources(fGpu);
379 SkDEBUGCODE(pipelineState = nullptr);
380 primitiveType = nonIdxMesh->primitiveType();
381 pipelineState = this->prepareDrawState(pipeline,
382 primProc,
383 primitiveType,
384 *renderPass);
385 if (!pipelineState) {
386 return;
387 }
388 }
389 SkASSERT(pipelineState);
390 this->bindGeometry(primProc, *nonIdxMesh);
391
392 if (nonIdxMesh->isIndexed()) {
393 fCommandBuffer->drawIndexed(fGpu,
394 nonIdxMesh->indexCount(),
395 1,
396 nonIdxMesh->startIndex(),
397 nonIdxMesh->startVertex(),
398 0);
399 } else {
400 fCommandBuffer->draw(fGpu,
401 nonIdxMesh->vertexCount(),
402 1,
403 nonIdxMesh->startVertex(),
404 0);
405 }
406
407 fGpu->stats()->incNumDraws();
408 } while ((nonIdxMesh = iter.next()));
409 }
410
411 // Technically we don't have to call this here (since there is a safety chec k in
412 // pipelineState:setData but this will allow for quicker freeing of resource s if the
413 // pipelineState sits in a cache for a while.
414 pipelineState->freeTempResources(fGpu);
415 }
416
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698