1 // Copyright 2018 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "VkCommandBuffer.hpp"
16
17 #include "VkBuffer.hpp"
18 #include "VkConfig.hpp"
19 #include "VkDevice.hpp"
20 #include "VkEvent.hpp"
21 #include "VkFence.hpp"
22 #include "VkFramebuffer.hpp"
23 #include "VkImage.hpp"
24 #include "VkImageView.hpp"
25 #include "VkPipeline.hpp"
26 #include "VkPipelineLayout.hpp"
27 #include "VkQueryPool.hpp"
28 #include "VkRenderPass.hpp"
29 #include "Device/Renderer.hpp"
30
31 #include "./Debug/Context.hpp"
32 #include "./Debug/File.hpp"
33 #include "./Debug/Thread.hpp"
34
35 #include "marl/defer.h"
36
37 #include <cstring>
38
39 namespace {
40
41 class CmdBeginRenderPass : public vk::CommandBuffer::Command
42 {
43 public:
CmdBeginRenderPass(vk::RenderPass * renderPass,vk::Framebuffer * framebuffer,VkRect2D renderArea,uint32_t clearValueCount,const VkClearValue * pClearValues)44 CmdBeginRenderPass(vk::RenderPass *renderPass, vk::Framebuffer *framebuffer, VkRect2D renderArea,
45 uint32_t clearValueCount, const VkClearValue *pClearValues)
46 : renderPass(renderPass)
47 , framebuffer(framebuffer)
48 , renderArea(renderArea)
49 , clearValueCount(clearValueCount)
50 {
51 // FIXME (b/119409619): use an allocator here so we can control all memory allocations
52 clearValues = new VkClearValue[clearValueCount];
53 memcpy(clearValues, pClearValues, clearValueCount * sizeof(VkClearValue));
54 }
55
~CmdBeginRenderPass()56 ~CmdBeginRenderPass() override
57 {
58 delete[] clearValues;
59 }
60
play(vk::CommandBuffer::ExecutionState & executionState)61 void play(vk::CommandBuffer::ExecutionState &executionState) override
62 {
63 executionState.renderPass = renderPass;
64 executionState.renderPassFramebuffer = framebuffer;
65 executionState.subpassIndex = 0;
66 framebuffer->clear(executionState.renderPass, clearValueCount, clearValues, renderArea);
67 }
68
description()69 std::string description() override { return "vkCmdBeginRenderPass()"; }
70
71 private:
72 vk::RenderPass *renderPass;
73 vk::Framebuffer *framebuffer;
74 VkRect2D renderArea;
75 uint32_t clearValueCount;
76 VkClearValue *clearValues;
77 };
78
79 class CmdNextSubpass : public vk::CommandBuffer::Command
80 {
81 public:
play(vk::CommandBuffer::ExecutionState & executionState)82 void play(vk::CommandBuffer::ExecutionState &executionState) override
83 {
84 bool hasResolveAttachments = (executionState.renderPass->getSubpass(executionState.subpassIndex).pResolveAttachments != nullptr);
85 if(hasResolveAttachments)
86 {
87 // FIXME(sugoi): remove the following lines and resolve in Renderer::finishRendering()
88 // for a Draw command or after the last command of the current subpass
89 // which modifies pixels.
90 executionState.renderer->synchronize();
91 executionState.renderPassFramebuffer->resolve(executionState.renderPass, executionState.subpassIndex);
92 }
93
94 ++executionState.subpassIndex;
95 }
96
description()97 std::string description() override { return "vkCmdNextSubpass()"; }
98 };
99
100 class CmdEndRenderPass : public vk::CommandBuffer::Command
101 {
102 public:
play(vk::CommandBuffer::ExecutionState & executionState)103 void play(vk::CommandBuffer::ExecutionState &executionState) override
104 {
105 // Execute (implicit or explicit) VkSubpassDependency to VK_SUBPASS_EXTERNAL
106 // This is somewhat heavier than the actual ordering required.
107 executionState.renderer->synchronize();
108
109 // FIXME(sugoi): remove the following line and resolve in Renderer::finishRendering()
110 // for a Draw command or after the last command of the current subpass
111 // which modifies pixels.
112 executionState.renderPassFramebuffer->resolve(executionState.renderPass, executionState.subpassIndex);
113 executionState.renderPass = nullptr;
114 executionState.renderPassFramebuffer = nullptr;
115 }
116
description()117 std::string description() override { return "vkCmdEndRenderPass()"; }
118 };
119
120 class CmdExecuteCommands : public vk::CommandBuffer::Command
121 {
122 public:
CmdExecuteCommands(const vk::CommandBuffer * commandBuffer)123 CmdExecuteCommands(const vk::CommandBuffer *commandBuffer)
124 : commandBuffer(commandBuffer)
125 {
126 }
127
play(vk::CommandBuffer::ExecutionState & executionState)128 void play(vk::CommandBuffer::ExecutionState &executionState) override
129 {
130 commandBuffer->submitSecondary(executionState);
131 }
132
description()133 std::string description() override { return "vkCmdExecuteCommands()"; }
134
135 private:
136 const vk::CommandBuffer *commandBuffer;
137 };
138
139 class CmdPipelineBind : public vk::CommandBuffer::Command
140 {
141 public:
CmdPipelineBind(VkPipelineBindPoint pipelineBindPoint,vk::Pipeline * pipeline)142 CmdPipelineBind(VkPipelineBindPoint pipelineBindPoint, vk::Pipeline *pipeline)
143 : pipelineBindPoint(pipelineBindPoint)
144 , pipeline(pipeline)
145 {
146 }
147
play(vk::CommandBuffer::ExecutionState & executionState)148 void play(vk::CommandBuffer::ExecutionState &executionState) override
149 {
150 executionState.pipelineState[pipelineBindPoint].pipeline = pipeline;
151 }
152
description()153 std::string description() override { return "vkCmdPipelineBind()"; }
154
155 private:
156 VkPipelineBindPoint pipelineBindPoint;
157 vk::Pipeline *pipeline;
158 };
159
160 class CmdDispatch : public vk::CommandBuffer::Command
161 {
162 public:
CmdDispatch(uint32_t baseGroupX,uint32_t baseGroupY,uint32_t baseGroupZ,uint32_t groupCountX,uint32_t groupCountY,uint32_t groupCountZ)163 CmdDispatch(uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ)
164 : baseGroupX(baseGroupX)
165 , baseGroupY(baseGroupY)
166 , baseGroupZ(baseGroupZ)
167 , groupCountX(groupCountX)
168 , groupCountY(groupCountY)
169 , groupCountZ(groupCountZ)
170 {
171 }
172
play(vk::CommandBuffer::ExecutionState & executionState)173 void play(vk::CommandBuffer::ExecutionState &executionState) override
174 {
175 auto const &pipelineState = executionState.pipelineState[VK_PIPELINE_BIND_POINT_COMPUTE];
176
177 vk::ComputePipeline *pipeline = static_cast<vk::ComputePipeline *>(pipelineState.pipeline);
178 pipeline->run(baseGroupX, baseGroupY, baseGroupZ,
179 groupCountX, groupCountY, groupCountZ,
180 pipelineState.descriptorSetObjects,
181 pipelineState.descriptorSets,
182 pipelineState.descriptorDynamicOffsets,
183 executionState.pushConstants);
184 }
185
description()186 std::string description() override { return "vkCmdDispatch()"; }
187
188 private:
189 uint32_t baseGroupX;
190 uint32_t baseGroupY;
191 uint32_t baseGroupZ;
192 uint32_t groupCountX;
193 uint32_t groupCountY;
194 uint32_t groupCountZ;
195 };
196
197 class CmdDispatchIndirect : public vk::CommandBuffer::Command
198 {
199 public:
CmdDispatchIndirect(vk::Buffer * buffer,VkDeviceSize offset)200 CmdDispatchIndirect(vk::Buffer *buffer, VkDeviceSize offset)
201 : buffer(buffer)
202 , offset(offset)
203 {
204 }
205
play(vk::CommandBuffer::ExecutionState & executionState)206 void play(vk::CommandBuffer::ExecutionState &executionState) override
207 {
208 auto cmd = reinterpret_cast<VkDispatchIndirectCommand const *>(buffer->getOffsetPointer(offset));
209
210 auto const &pipelineState = executionState.pipelineState[VK_PIPELINE_BIND_POINT_COMPUTE];
211
212 auto pipeline = static_cast<vk::ComputePipeline *>(pipelineState.pipeline);
213 pipeline->run(0, 0, 0, cmd->x, cmd->y, cmd->z,
214 pipelineState.descriptorSetObjects,
215 pipelineState.descriptorSets,
216 pipelineState.descriptorDynamicOffsets,
217 executionState.pushConstants);
218 }
219
description()220 std::string description() override { return "vkCmdDispatchIndirect()"; }
221
222 private:
223 const vk::Buffer *buffer;
224 VkDeviceSize offset;
225 };
226
227 class CmdVertexBufferBind : public vk::CommandBuffer::Command
228 {
229 public:
CmdVertexBufferBind(uint32_t binding,vk::Buffer * buffer,const VkDeviceSize offset)230 CmdVertexBufferBind(uint32_t binding, vk::Buffer *buffer, const VkDeviceSize offset)
231 : binding(binding)
232 , buffer(buffer)
233 , offset(offset)
234 {
235 }
236
play(vk::CommandBuffer::ExecutionState & executionState)237 void play(vk::CommandBuffer::ExecutionState &executionState) override
238 {
239 executionState.vertexInputBindings[binding] = { buffer, offset };
240 }
241
description()242 std::string description() override { return "vkCmdVertexBufferBind()"; }
243
244 private:
245 uint32_t binding;
246 vk::Buffer *buffer;
247 const VkDeviceSize offset;
248 };
249
250 class CmdIndexBufferBind : public vk::CommandBuffer::Command
251 {
252 public:
CmdIndexBufferBind(vk::Buffer * buffer,const VkDeviceSize offset,const VkIndexType indexType)253 CmdIndexBufferBind(vk::Buffer *buffer, const VkDeviceSize offset, const VkIndexType indexType)
254 : buffer(buffer)
255 , offset(offset)
256 , indexType(indexType)
257 {
258 }
259
play(vk::CommandBuffer::ExecutionState & executionState)260 void play(vk::CommandBuffer::ExecutionState &executionState) override
261 {
262 executionState.indexBufferBinding = { buffer, offset };
263 executionState.indexType = indexType;
264 }
265
description()266 std::string description() override { return "vkCmdIndexBufferBind()"; }
267
268 private:
269 vk::Buffer *buffer;
270 const VkDeviceSize offset;
271 const VkIndexType indexType;
272 };
273
274 class CmdSetViewport : public vk::CommandBuffer::Command
275 {
276 public:
CmdSetViewport(const VkViewport & viewport,uint32_t viewportID)277 CmdSetViewport(const VkViewport &viewport, uint32_t viewportID)
278 : viewport(viewport)
279 , viewportID(viewportID)
280 {
281 }
282
play(vk::CommandBuffer::ExecutionState & executionState)283 void play(vk::CommandBuffer::ExecutionState &executionState) override
284 {
285 executionState.dynamicState.viewport = viewport;
286 }
287
description()288 std::string description() override { return "vkCmdSetViewport()"; }
289
290 private:
291 const VkViewport viewport;
292 uint32_t viewportID;
293 };
294
295 class CmdSetScissor : public vk::CommandBuffer::Command
296 {
297 public:
CmdSetScissor(const VkRect2D & scissor,uint32_t scissorID)298 CmdSetScissor(const VkRect2D &scissor, uint32_t scissorID)
299 : scissor(scissor)
300 , scissorID(scissorID)
301 {
302 }
303
play(vk::CommandBuffer::ExecutionState & executionState)304 void play(vk::CommandBuffer::ExecutionState &executionState) override
305 {
306 executionState.dynamicState.scissor = scissor;
307 }
308
description()309 std::string description() override { return "vkCmdSetScissor()"; }
310
311 private:
312 const VkRect2D scissor;
313 uint32_t scissorID;
314 };
315
316 class CmdSetDepthBias : public vk::CommandBuffer::Command
317 {
318 public:
CmdSetDepthBias(float depthBiasConstantFactor,float depthBiasClamp,float depthBiasSlopeFactor)319 CmdSetDepthBias(float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor)
320 : depthBiasConstantFactor(depthBiasConstantFactor)
321 , depthBiasClamp(depthBiasClamp)
322 , depthBiasSlopeFactor(depthBiasSlopeFactor)
323 {
324 }
325
play(vk::CommandBuffer::ExecutionState & executionState)326 void play(vk::CommandBuffer::ExecutionState &executionState) override
327 {
328 executionState.dynamicState.depthBiasConstantFactor = depthBiasConstantFactor;
329 executionState.dynamicState.depthBiasClamp = depthBiasClamp;
330 executionState.dynamicState.depthBiasSlopeFactor = depthBiasSlopeFactor;
331 }
332
description()333 std::string description() override { return "vkCmdSetDepthBias()"; }
334
335 private:
336 float depthBiasConstantFactor;
337 float depthBiasClamp;
338 float depthBiasSlopeFactor;
339 };
340
341 class CmdSetBlendConstants : public vk::CommandBuffer::Command
342 {
343 public:
CmdSetBlendConstants(const float blendConstants[4])344 CmdSetBlendConstants(const float blendConstants[4])
345 {
346 memcpy(this->blendConstants, blendConstants, sizeof(this->blendConstants));
347 }
348
play(vk::CommandBuffer::ExecutionState & executionState)349 void play(vk::CommandBuffer::ExecutionState &executionState) override
350 {
351 memcpy(&(executionState.dynamicState.blendConstants[0]), blendConstants, sizeof(blendConstants));
352 }
353
description()354 std::string description() override { return "vkCmdSetBlendConstants()"; }
355
356 private:
357 float blendConstants[4];
358 };
359
360 class CmdSetDepthBounds : public vk::CommandBuffer::Command
361 {
362 public:
CmdSetDepthBounds(float minDepthBounds,float maxDepthBounds)363 CmdSetDepthBounds(float minDepthBounds, float maxDepthBounds)
364 : minDepthBounds(minDepthBounds)
365 , maxDepthBounds(maxDepthBounds)
366 {
367 }
368
play(vk::CommandBuffer::ExecutionState & executionState)369 void play(vk::CommandBuffer::ExecutionState &executionState) override
370 {
371 executionState.dynamicState.minDepthBounds = minDepthBounds;
372 executionState.dynamicState.maxDepthBounds = maxDepthBounds;
373 }
374
description()375 std::string description() override { return "vkCmdSetDepthBounds()"; }
376
377 private:
378 float minDepthBounds;
379 float maxDepthBounds;
380 };
381
382 class CmdSetStencilCompareMask : public vk::CommandBuffer::Command
383 {
384 public:
CmdSetStencilCompareMask(VkStencilFaceFlags faceMask,uint32_t compareMask)385 CmdSetStencilCompareMask(VkStencilFaceFlags faceMask, uint32_t compareMask)
386 : faceMask(faceMask)
387 , compareMask(compareMask)
388 {
389 }
390
play(vk::CommandBuffer::ExecutionState & executionState)391 void play(vk::CommandBuffer::ExecutionState &executionState) override
392 {
393 if(faceMask & VK_STENCIL_FACE_FRONT_BIT)
394 {
395 executionState.dynamicState.compareMask[0] = compareMask;
396 }
397 if(faceMask & VK_STENCIL_FACE_BACK_BIT)
398 {
399 executionState.dynamicState.compareMask[1] = compareMask;
400 }
401 }
402
description()403 std::string description() override { return "vkCmdSetStencilCompareMask()"; }
404
405 private:
406 VkStencilFaceFlags faceMask;
407 uint32_t compareMask;
408 };
409
410 class CmdSetStencilWriteMask : public vk::CommandBuffer::Command
411 {
412 public:
CmdSetStencilWriteMask(VkStencilFaceFlags faceMask,uint32_t writeMask)413 CmdSetStencilWriteMask(VkStencilFaceFlags faceMask, uint32_t writeMask)
414 : faceMask(faceMask)
415 , writeMask(writeMask)
416 {
417 }
418
play(vk::CommandBuffer::ExecutionState & executionState)419 void play(vk::CommandBuffer::ExecutionState &executionState) override
420 {
421 if(faceMask & VK_STENCIL_FACE_FRONT_BIT)
422 {
423 executionState.dynamicState.writeMask[0] = writeMask;
424 }
425 if(faceMask & VK_STENCIL_FACE_BACK_BIT)
426 {
427 executionState.dynamicState.writeMask[1] = writeMask;
428 }
429 }
430
description()431 std::string description() override { return "vkCmdSetStencilWriteMask()"; }
432
433 private:
434 VkStencilFaceFlags faceMask;
435 uint32_t writeMask;
436 };
437
438 class CmdSetStencilReference : public vk::CommandBuffer::Command
439 {
440 public:
CmdSetStencilReference(VkStencilFaceFlags faceMask,uint32_t reference)441 CmdSetStencilReference(VkStencilFaceFlags faceMask, uint32_t reference)
442 : faceMask(faceMask)
443 , reference(reference)
444 {
445 }
446
play(vk::CommandBuffer::ExecutionState & executionState)447 void play(vk::CommandBuffer::ExecutionState &executionState) override
448 {
449 if(faceMask & VK_STENCIL_FACE_FRONT_BIT)
450 {
451 executionState.dynamicState.reference[0] = reference;
452 }
453 if(faceMask & VK_STENCIL_FACE_BACK_BIT)
454 {
455 executionState.dynamicState.reference[1] = reference;
456 }
457 }
458
description()459 std::string description() override { return "vkCmdSetStencilReference()"; }
460
461 private:
462 VkStencilFaceFlags faceMask;
463 uint32_t reference;
464 };
465
466 class CmdDrawBase : public vk::CommandBuffer::Command
467 {
468 public:
draw(vk::CommandBuffer::ExecutionState & executionState,bool indexed,uint32_t count,uint32_t instanceCount,uint32_t first,int32_t vertexOffset,uint32_t firstInstance)469 void draw(vk::CommandBuffer::ExecutionState &executionState, bool indexed,
470 uint32_t count, uint32_t instanceCount, uint32_t first, int32_t vertexOffset, uint32_t firstInstance)
471 {
472 auto const &pipelineState = executionState.pipelineState[VK_PIPELINE_BIND_POINT_GRAPHICS];
473
474 auto *pipeline = static_cast<vk::GraphicsPipeline *>(pipelineState.pipeline);
475
476 vk::Attachments &attachments = pipeline->getAttachments();
477 executionState.bindAttachments(&attachments);
478
479 vk::Inputs &inputs = pipeline->getInputs();
480 inputs.updateDescriptorSets(pipelineState.descriptorSetObjects,
481 pipelineState.descriptorSets,
482 pipelineState.descriptorDynamicOffsets);
483 inputs.setVertexInputBinding(executionState.vertexInputBindings);
484 inputs.bindVertexInputs(firstInstance);
485
486 vk::IndexBuffer &indexBuffer = pipeline->getIndexBuffer();
487 indexBuffer.setIndexBufferBinding(executionState.indexBufferBinding, executionState.indexType);
488
489 std::vector<std::pair<uint32_t, void *>> indexBuffers;
490 pipeline->getIndexBuffers(count, first, indexed, &indexBuffers);
491
492 for(uint32_t instance = firstInstance; instance != firstInstance + instanceCount; instance++)
493 {
494 // FIXME: reconsider instances/views nesting.
495 auto viewMask = executionState.renderPass->getViewMask(executionState.subpassIndex);
496 while(viewMask)
497 {
498 int viewID = sw::log2i(viewMask);
499 viewMask &= ~(1 << viewID);
500
501 for(auto indexBuffer : indexBuffers)
502 {
503 executionState.renderer->draw(pipeline, executionState.dynamicState, indexBuffer.first, vertexOffset,
504 executionState.events, instance, viewID, indexBuffer.second,
505 executionState.renderPassFramebuffer->getExtent(),
506 executionState.pushConstants);
507 }
508 }
509
510 inputs.advanceInstanceAttributes();
511 }
512 }
513 };
514
515 class CmdDraw : public CmdDrawBase
516 {
517 public:
CmdDraw(uint32_t vertexCount,uint32_t instanceCount,uint32_t firstVertex,uint32_t firstInstance)518 CmdDraw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance)
519 : vertexCount(vertexCount)
520 , instanceCount(instanceCount)
521 , firstVertex(firstVertex)
522 , firstInstance(firstInstance)
523 {
524 }
525
play(vk::CommandBuffer::ExecutionState & executionState)526 void play(vk::CommandBuffer::ExecutionState &executionState) override
527 {
528 draw(executionState, false, vertexCount, instanceCount, 0, firstVertex, firstInstance);
529 }
530
description()531 std::string description() override { return "vkCmdDraw()"; }
532
533 private:
534 uint32_t vertexCount;
535 uint32_t instanceCount;
536 uint32_t firstVertex;
537 uint32_t firstInstance;
538 };
539
540 class CmdDrawIndexed : public CmdDrawBase
541 {
542 public:
CmdDrawIndexed(uint32_t indexCount,uint32_t instanceCount,uint32_t firstIndex,int32_t vertexOffset,uint32_t firstInstance)543 CmdDrawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance)
544 : indexCount(indexCount)
545 , instanceCount(instanceCount)
546 , firstIndex(firstIndex)
547 , vertexOffset(vertexOffset)
548 , firstInstance(firstInstance)
549 {
550 }
551
play(vk::CommandBuffer::ExecutionState & executionState)552 void play(vk::CommandBuffer::ExecutionState &executionState) override
553 {
554 draw(executionState, true, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
555 }
556
description()557 std::string description() override { return "vkCmdDrawIndexed()"; }
558
559 private:
560 uint32_t indexCount;
561 uint32_t instanceCount;
562 uint32_t firstIndex;
563 int32_t vertexOffset;
564 uint32_t firstInstance;
565 };
566
567 class CmdDrawIndirect : public CmdDrawBase
568 {
569 public:
CmdDrawIndirect(vk::Buffer * buffer,VkDeviceSize offset,uint32_t drawCount,uint32_t stride)570 CmdDrawIndirect(vk::Buffer *buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride)
571 : buffer(buffer)
572 , offset(offset)
573 , drawCount(drawCount)
574 , stride(stride)
575 {
576 }
577
play(vk::CommandBuffer::ExecutionState & executionState)578 void play(vk::CommandBuffer::ExecutionState &executionState) override
579 {
580 for(auto drawId = 0u; drawId < drawCount; drawId++)
581 {
582 auto cmd = reinterpret_cast<VkDrawIndirectCommand const *>(buffer->getOffsetPointer(offset + drawId * stride));
583 draw(executionState, false, cmd->vertexCount, cmd->instanceCount, 0, cmd->firstVertex, cmd->firstInstance);
584 }
585 }
586
description()587 std::string description() override { return "vkCmdDrawIndirect()"; }
588
589 private:
590 const vk::Buffer *buffer;
591 VkDeviceSize offset;
592 uint32_t drawCount;
593 uint32_t stride;
594 };
595
596 class CmdDrawIndexedIndirect : public CmdDrawBase
597 {
598 public:
CmdDrawIndexedIndirect(vk::Buffer * buffer,VkDeviceSize offset,uint32_t drawCount,uint32_t stride)599 CmdDrawIndexedIndirect(vk::Buffer *buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride)
600 : buffer(buffer)
601 , offset(offset)
602 , drawCount(drawCount)
603 , stride(stride)
604 {
605 }
606
play(vk::CommandBuffer::ExecutionState & executionState)607 void play(vk::CommandBuffer::ExecutionState &executionState) override
608 {
609 for(auto drawId = 0u; drawId < drawCount; drawId++)
610 {
611 auto cmd = reinterpret_cast<VkDrawIndexedIndirectCommand const *>(buffer->getOffsetPointer(offset + drawId * stride));
612 draw(executionState, true, cmd->indexCount, cmd->instanceCount, cmd->firstIndex, cmd->vertexOffset, cmd->firstInstance);
613 }
614 }
615
description()616 std::string description() override { return "vkCmdDrawIndexedIndirect()"; }
617
618 private:
619 const vk::Buffer *buffer;
620 VkDeviceSize offset;
621 uint32_t drawCount;
622 uint32_t stride;
623 };
624
625 class CmdCopyImage : public vk::CommandBuffer::Command
626 {
627 public:
CmdCopyImage(const vk::Image * srcImage,vk::Image * dstImage,const VkImageCopy & region)628 CmdCopyImage(const vk::Image *srcImage, vk::Image *dstImage, const VkImageCopy ®ion)
629 : srcImage(srcImage)
630 , dstImage(dstImage)
631 , region(region)
632 {
633 }
634
play(vk::CommandBuffer::ExecutionState & executionState)635 void play(vk::CommandBuffer::ExecutionState &executionState) override
636 {
637 srcImage->copyTo(dstImage, region);
638 }
639
description()640 std::string description() override { return "vkCmdCopyImage()"; }
641
642 private:
643 const vk::Image *srcImage;
644 vk::Image *dstImage;
645 const VkImageCopy region;
646 };
647
648 class CmdCopyBuffer : public vk::CommandBuffer::Command
649 {
650 public:
CmdCopyBuffer(const vk::Buffer * srcBuffer,vk::Buffer * dstBuffer,const VkBufferCopy & region)651 CmdCopyBuffer(const vk::Buffer *srcBuffer, vk::Buffer *dstBuffer, const VkBufferCopy ®ion)
652 : srcBuffer(srcBuffer)
653 , dstBuffer(dstBuffer)
654 , region(region)
655 {
656 }
657
play(vk::CommandBuffer::ExecutionState & executionState)658 void play(vk::CommandBuffer::ExecutionState &executionState) override
659 {
660 srcBuffer->copyTo(dstBuffer, region);
661 }
662
description()663 std::string description() override { return "vkCmdCopyBuffer()"; }
664
665 private:
666 const vk::Buffer *srcBuffer;
667 vk::Buffer *dstBuffer;
668 const VkBufferCopy region;
669 };
670
671 class CmdCopyImageToBuffer : public vk::CommandBuffer::Command
672 {
673 public:
CmdCopyImageToBuffer(vk::Image * srcImage,vk::Buffer * dstBuffer,const VkBufferImageCopy & region)674 CmdCopyImageToBuffer(vk::Image *srcImage, vk::Buffer *dstBuffer, const VkBufferImageCopy ®ion)
675 : srcImage(srcImage)
676 , dstBuffer(dstBuffer)
677 , region(region)
678 {
679 }
680
play(vk::CommandBuffer::ExecutionState & executionState)681 void play(vk::CommandBuffer::ExecutionState &executionState) override
682 {
683 srcImage->copyTo(dstBuffer, region);
684 }
685
description()686 std::string description() override { return "vkCmdCopyImageToBuffer()"; }
687
688 private:
689 vk::Image *srcImage;
690 vk::Buffer *dstBuffer;
691 const VkBufferImageCopy region;
692 };
693
694 class CmdCopyBufferToImage : public vk::CommandBuffer::Command
695 {
696 public:
CmdCopyBufferToImage(vk::Buffer * srcBuffer,vk::Image * dstImage,const VkBufferImageCopy & region)697 CmdCopyBufferToImage(vk::Buffer *srcBuffer, vk::Image *dstImage, const VkBufferImageCopy ®ion)
698 : srcBuffer(srcBuffer)
699 , dstImage(dstImage)
700 , region(region)
701 {
702 }
703
play(vk::CommandBuffer::ExecutionState & executionState)704 void play(vk::CommandBuffer::ExecutionState &executionState) override
705 {
706 dstImage->copyFrom(srcBuffer, region);
707 }
708
description()709 std::string description() override { return "vkCmdCopyBufferToImage()"; }
710
711 private:
712 vk::Buffer *srcBuffer;
713 vk::Image *dstImage;
714 const VkBufferImageCopy region;
715 };
716
717 class CmdFillBuffer : public vk::CommandBuffer::Command
718 {
719 public:
CmdFillBuffer(vk::Buffer * dstBuffer,VkDeviceSize dstOffset,VkDeviceSize size,uint32_t data)720 CmdFillBuffer(vk::Buffer *dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data)
721 : dstBuffer(dstBuffer)
722 , dstOffset(dstOffset)
723 , size(size)
724 , data(data)
725 {
726 }
727
play(vk::CommandBuffer::ExecutionState & executionState)728 void play(vk::CommandBuffer::ExecutionState &executionState) override
729 {
730 dstBuffer->fill(dstOffset, size, data);
731 }
732
description()733 std::string description() override { return "vkCmdFillBuffer()"; }
734
735 private:
736 vk::Buffer *dstBuffer;
737 VkDeviceSize dstOffset;
738 VkDeviceSize size;
739 uint32_t data;
740 };
741
742 class CmdUpdateBuffer : public vk::CommandBuffer::Command
743 {
744 public:
CmdUpdateBuffer(vk::Buffer * dstBuffer,VkDeviceSize dstOffset,VkDeviceSize dataSize,const uint8_t * pData)745 CmdUpdateBuffer(vk::Buffer *dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const uint8_t *pData)
746 : dstBuffer(dstBuffer)
747 , dstOffset(dstOffset)
748 , data(pData, &pData[dataSize])
749 {
750 }
751
play(vk::CommandBuffer::ExecutionState & executionState)752 void play(vk::CommandBuffer::ExecutionState &executionState) override
753 {
754 dstBuffer->update(dstOffset, data.size(), data.data());
755 }
756
description()757 std::string description() override { return "vkCmdUpdateBuffer()"; }
758
759 private:
760 vk::Buffer *dstBuffer;
761 VkDeviceSize dstOffset;
762 std::vector<uint8_t> data; // FIXME (b/119409619): replace this vector by an allocator so we can control all memory allocations
763 };
764
765 class CmdClearColorImage : public vk::CommandBuffer::Command
766 {
767 public:
CmdClearColorImage(vk::Image * image,const VkClearColorValue & color,const VkImageSubresourceRange & range)768 CmdClearColorImage(vk::Image *image, const VkClearColorValue &color, const VkImageSubresourceRange &range)
769 : image(image)
770 , color(color)
771 , range(range)
772 {
773 }
774
play(vk::CommandBuffer::ExecutionState & executionState)775 void play(vk::CommandBuffer::ExecutionState &executionState) override
776 {
777 image->clear(color, range);
778 }
779
description()780 std::string description() override { return "vkCmdClearColorImage()"; }
781
782 private:
783 vk::Image *image;
784 const VkClearColorValue color;
785 const VkImageSubresourceRange range;
786 };
787
788 class CmdClearDepthStencilImage : public vk::CommandBuffer::Command
789 {
790 public:
CmdClearDepthStencilImage(vk::Image * image,const VkClearDepthStencilValue & depthStencil,const VkImageSubresourceRange & range)791 CmdClearDepthStencilImage(vk::Image *image, const VkClearDepthStencilValue &depthStencil, const VkImageSubresourceRange &range)
792 : image(image)
793 , depthStencil(depthStencil)
794 , range(range)
795 {
796 }
797
play(vk::CommandBuffer::ExecutionState & executionState)798 void play(vk::CommandBuffer::ExecutionState &executionState) override
799 {
800 image->clear(depthStencil, range);
801 }
802
description()803 std::string description() override { return "vkCmdClearDepthStencilImage()"; }
804
805 private:
806 vk::Image *image;
807 const VkClearDepthStencilValue depthStencil;
808 const VkImageSubresourceRange range;
809 };
810
811 class CmdClearAttachment : public vk::CommandBuffer::Command
812 {
813 public:
CmdClearAttachment(const VkClearAttachment & attachment,const VkClearRect & rect)814 CmdClearAttachment(const VkClearAttachment &attachment, const VkClearRect &rect)
815 : attachment(attachment)
816 , rect(rect)
817 {
818 }
819
play(vk::CommandBuffer::ExecutionState & executionState)820 void play(vk::CommandBuffer::ExecutionState &executionState) override
821 {
822 // attachment clears are drawing operations, and so have rasterization-order guarantees.
823 // however, we don't do the clear through the rasterizer, so need to ensure prior drawing
824 // has completed first.
825 executionState.renderer->synchronize();
826 executionState.renderPassFramebuffer->clearAttachment(executionState.renderPass, executionState.subpassIndex, attachment, rect);
827 }
828
description()829 std::string description() override { return "vkCmdClearAttachment()"; }
830
831 private:
832 const VkClearAttachment attachment;
833 const VkClearRect rect;
834 };
835
836 class CmdBlitImage : public vk::CommandBuffer::Command
837 {
838 public:
CmdBlitImage(const vk::Image * srcImage,vk::Image * dstImage,const VkImageBlit & region,VkFilter filter)839 CmdBlitImage(const vk::Image *srcImage, vk::Image *dstImage, const VkImageBlit ®ion, VkFilter filter)
840 : srcImage(srcImage)
841 , dstImage(dstImage)
842 , region(region)
843 , filter(filter)
844 {
845 }
846
play(vk::CommandBuffer::ExecutionState & executionState)847 void play(vk::CommandBuffer::ExecutionState &executionState) override
848 {
849 srcImage->blitTo(dstImage, region, filter);
850 }
851
description()852 std::string description() override { return "vkCmdBlitImage()"; }
853
854 private:
855 const vk::Image *srcImage;
856 vk::Image *dstImage;
857 VkImageBlit region;
858 VkFilter filter;
859 };
860
861 class CmdResolveImage : public vk::CommandBuffer::Command
862 {
863 public:
CmdResolveImage(const vk::Image * srcImage,vk::Image * dstImage,const VkImageResolve & region)864 CmdResolveImage(const vk::Image *srcImage, vk::Image *dstImage, const VkImageResolve ®ion)
865 : srcImage(srcImage)
866 , dstImage(dstImage)
867 , region(region)
868 {
869 }
870
play(vk::CommandBuffer::ExecutionState & executionState)871 void play(vk::CommandBuffer::ExecutionState &executionState) override
872 {
873 srcImage->resolveTo(dstImage, region);
874 }
875
description()876 std::string description() override { return "vkCmdBlitImage()"; }
877
878 private:
879 const vk::Image *srcImage;
880 vk::Image *dstImage;
881 VkImageResolve region;
882 };
883
884 class CmdPipelineBarrier : public vk::CommandBuffer::Command
885 {
886 public:
play(vk::CommandBuffer::ExecutionState & executionState)887 void play(vk::CommandBuffer::ExecutionState &executionState) override
888 {
889 // This is a very simple implementation that simply calls sw::Renderer::synchronize(),
890 // since the driver is free to move the source stage towards the bottom of the pipe
891 // and the target stage towards the top, so a full pipeline sync is spec compliant.
892 executionState.renderer->synchronize();
893
894 // Right now all buffers are read-only in drawcalls but a similar mechanism will be required once we support SSBOs.
895
896 // Also note that this would be a good moment to update cube map borders or decompress compressed textures, if necessary.
897 }
898
description()899 std::string description() override { return "vkCmdPipelineBarrier()"; }
900 };
901
902 class CmdSignalEvent : public vk::CommandBuffer::Command
903 {
904 public:
CmdSignalEvent(vk::Event * ev,VkPipelineStageFlags stageMask)905 CmdSignalEvent(vk::Event *ev, VkPipelineStageFlags stageMask)
906 : ev(ev)
907 , stageMask(stageMask)
908 {
909 }
910
play(vk::CommandBuffer::ExecutionState & executionState)911 void play(vk::CommandBuffer::ExecutionState &executionState) override
912 {
913 executionState.renderer->synchronize();
914 ev->signal();
915 }
916
description()917 std::string description() override { return "vkCmdSignalEvent()"; }
918
919 private:
920 vk::Event *ev;
921 VkPipelineStageFlags stageMask; // FIXME(b/117835459) : We currently ignore the flags and signal the event at the last stage
922 };
923
924 class CmdResetEvent : public vk::CommandBuffer::Command
925 {
926 public:
CmdResetEvent(vk::Event * ev,VkPipelineStageFlags stageMask)927 CmdResetEvent(vk::Event *ev, VkPipelineStageFlags stageMask)
928 : ev(ev)
929 , stageMask(stageMask)
930 {
931 }
932
play(vk::CommandBuffer::ExecutionState & executionState)933 void play(vk::CommandBuffer::ExecutionState &executionState) override
934 {
935 ev->reset();
936 }
937
description()938 std::string description() override { return "vkCmdResetEvent()"; }
939
940 private:
941 vk::Event *ev;
942 VkPipelineStageFlags stageMask; // FIXME(b/117835459) : We currently ignore the flags and reset the event at the last stage
943 };
944
945 class CmdWaitEvent : public vk::CommandBuffer::Command
946 {
947 public:
CmdWaitEvent(vk::Event * ev)948 CmdWaitEvent(vk::Event *ev)
949 : ev(ev)
950 {
951 }
952
play(vk::CommandBuffer::ExecutionState & executionState)953 void play(vk::CommandBuffer::ExecutionState &executionState) override
954 {
955 executionState.renderer->synchronize();
956 ev->wait();
957 }
958
description()959 std::string description() override { return "vkCmdWaitEvent()"; }
960
961 private:
962 vk::Event *ev;
963 };
964
965 class CmdBindDescriptorSets : public vk::CommandBuffer::Command
966 {
967 public:
CmdBindDescriptorSets(VkPipelineBindPoint pipelineBindPoint,uint32_t firstSet,uint32_t descriptorSetCount,const VkDescriptorSet * pDescriptorSets,uint32_t firstDynamicOffset,uint32_t dynamicOffsetCount,const uint32_t * pDynamicOffsets)968 CmdBindDescriptorSets(VkPipelineBindPoint pipelineBindPoint,
969 uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet *pDescriptorSets,
970 uint32_t firstDynamicOffset, uint32_t dynamicOffsetCount, const uint32_t *pDynamicOffsets)
971 : pipelineBindPoint(pipelineBindPoint)
972 , firstSet(firstSet)
973 , descriptorSetCount(descriptorSetCount)
974 , firstDynamicOffset(firstDynamicOffset)
975 , dynamicOffsetCount(dynamicOffsetCount)
976 {
977 for(uint32_t i = 0; i < descriptorSetCount; i++)
978 {
979 // We need both a descriptor set object for updates and a descriptor set data pointer for routines
980 descriptorSetObjects[firstSet + i] = vk::Cast(pDescriptorSets[i]);
981 descriptorSets[firstSet + i] = vk::Cast(pDescriptorSets[i])->data;
982 }
983
984 for(uint32_t i = 0; i < dynamicOffsetCount; i++)
985 {
986 dynamicOffsets[firstDynamicOffset + i] = pDynamicOffsets[i];
987 }
988 }
989
play(vk::CommandBuffer::ExecutionState & executionState)990 void play(vk::CommandBuffer::ExecutionState &executionState) override
991 {
992 ASSERT(pipelineBindPoint < vk::VK_PIPELINE_BIND_POINT_RANGE_SIZE);
993 ASSERT(firstSet + descriptorSetCount <= vk::MAX_BOUND_DESCRIPTOR_SETS);
994 ASSERT(firstDynamicOffset + dynamicOffsetCount <= vk::MAX_DESCRIPTOR_SET_COMBINED_BUFFERS_DYNAMIC);
995
996 auto &pipelineState = executionState.pipelineState[pipelineBindPoint];
997
998 for(uint32_t i = firstSet; i < firstSet + descriptorSetCount; i++)
999 {
1000 pipelineState.descriptorSetObjects[i] = descriptorSetObjects[i];
1001 pipelineState.descriptorSets[i] = descriptorSets[i];
1002 }
1003
1004 for(uint32_t i = firstDynamicOffset; i < firstDynamicOffset + dynamicOffsetCount; i++)
1005 {
1006 pipelineState.descriptorDynamicOffsets[i] = dynamicOffsets[i];
1007 }
1008 }
1009
description()1010 std::string description() override { return "vkCmdBindDescriptorSets()"; }
1011
1012 private:
1013 const VkPipelineBindPoint pipelineBindPoint;
1014 const uint32_t firstSet;
1015 const uint32_t descriptorSetCount;
1016 const uint32_t firstDynamicOffset;
1017 const uint32_t dynamicOffsetCount;
1018
1019 vk::DescriptorSet::Array descriptorSetObjects;
1020 vk::DescriptorSet::Bindings descriptorSets;
1021 vk::DescriptorSet::DynamicOffsets dynamicOffsets;
1022 };
1023
1024 class CmdSetPushConstants : public vk::CommandBuffer::Command
1025 {
1026 public:
CmdSetPushConstants(uint32_t offset,uint32_t size,void const * pValues)1027 CmdSetPushConstants(uint32_t offset, uint32_t size, void const *pValues)
1028 : offset(offset)
1029 , size(size)
1030 {
1031 ASSERT(offset < vk::MAX_PUSH_CONSTANT_SIZE);
1032 ASSERT(offset + size <= vk::MAX_PUSH_CONSTANT_SIZE);
1033
1034 memcpy(data, pValues, size);
1035 }
1036
play(vk::CommandBuffer::ExecutionState & executionState)1037 void play(vk::CommandBuffer::ExecutionState &executionState) override
1038 {
1039 memcpy(&executionState.pushConstants.data[offset], data, size);
1040 }
1041
description()1042 std::string description() override { return "vkCmdSetPushConstants()"; }
1043
1044 private:
1045 uint32_t offset;
1046 uint32_t size;
1047 unsigned char data[vk::MAX_PUSH_CONSTANT_SIZE];
1048 };
1049
1050 class CmdBeginQuery : public vk::CommandBuffer::Command
1051 {
1052 public:
CmdBeginQuery(vk::QueryPool * queryPool,uint32_t query,VkQueryControlFlags flags)1053 CmdBeginQuery(vk::QueryPool *queryPool, uint32_t query, VkQueryControlFlags flags)
1054 : queryPool(queryPool)
1055 , query(query)
1056 , flags(flags)
1057 {
1058 }
1059
play(vk::CommandBuffer::ExecutionState & executionState)1060 void play(vk::CommandBuffer::ExecutionState &executionState) override
1061 {
1062 queryPool->begin(query, flags);
1063 executionState.renderer->addQuery(queryPool->getQuery(query));
1064 }
1065
description()1066 std::string description() override { return "vkCmdBeginQuery()"; }
1067
1068 private:
1069 vk::QueryPool *queryPool;
1070 uint32_t query;
1071 VkQueryControlFlags flags;
1072 };
1073
1074 class CmdEndQuery : public vk::CommandBuffer::Command
1075 {
1076 public:
CmdEndQuery(vk::QueryPool * queryPool,uint32_t query)1077 CmdEndQuery(vk::QueryPool *queryPool, uint32_t query)
1078 : queryPool(queryPool)
1079 , query(query)
1080 {
1081 }
1082
play(vk::CommandBuffer::ExecutionState & executionState)1083 void play(vk::CommandBuffer::ExecutionState &executionState) override
1084 {
1085 executionState.renderer->removeQuery(queryPool->getQuery(query));
1086 queryPool->end(query);
1087 }
1088
description()1089 std::string description() override { return "vkCmdEndQuery()"; }
1090
1091 private:
1092 vk::QueryPool *queryPool;
1093 uint32_t query;
1094 };
1095
1096 class CmdResetQueryPool : public vk::CommandBuffer::Command
1097 {
1098 public:
CmdResetQueryPool(vk::QueryPool * queryPool,uint32_t firstQuery,uint32_t queryCount)1099 CmdResetQueryPool(vk::QueryPool *queryPool, uint32_t firstQuery, uint32_t queryCount)
1100 : queryPool(queryPool)
1101 , firstQuery(firstQuery)
1102 , queryCount(queryCount)
1103 {
1104 }
1105
play(vk::CommandBuffer::ExecutionState & executionState)1106 void play(vk::CommandBuffer::ExecutionState &executionState) override
1107 {
1108 queryPool->reset(firstQuery, queryCount);
1109 }
1110
description()1111 std::string description() override { return "vkCmdResetQueryPool()"; }
1112
1113 private:
1114 vk::QueryPool *queryPool;
1115 uint32_t firstQuery;
1116 uint32_t queryCount;
1117 };
1118
1119 class CmdWriteTimeStamp : public vk::CommandBuffer::Command
1120 {
1121 public:
CmdWriteTimeStamp(vk::QueryPool * queryPool,uint32_t query,VkPipelineStageFlagBits stage)1122 CmdWriteTimeStamp(vk::QueryPool *queryPool, uint32_t query, VkPipelineStageFlagBits stage)
1123 : queryPool(queryPool)
1124 , query(query)
1125 , stage(stage)
1126 {
1127 }
1128
play(vk::CommandBuffer::ExecutionState & executionState)1129 void play(vk::CommandBuffer::ExecutionState &executionState) override
1130 {
1131 if(stage & ~(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT))
1132 {
1133 // The `top of pipe` and `draw indirect` stages are handled in command buffer processing so a timestamp write
1134 // done in those stages can just be done here without any additional synchronization.
1135 // Everything else is deferred to the Renderer; we will treat those stages all as if they were
1136 // `bottom of pipe`.
1137 //
1138 // FIXME(chrisforbes): once Marl is integrated, do this in a task so we don't have to stall here.
1139 executionState.renderer->synchronize();
1140 }
1141
1142 queryPool->writeTimestamp(query);
1143 }
1144
description()1145 std::string description() override { return "vkCmdWriteTimeStamp()"; }
1146
1147 private:
1148 vk::QueryPool *queryPool;
1149 uint32_t query;
1150 VkPipelineStageFlagBits stage;
1151 };
1152
1153 class CmdCopyQueryPoolResults : public vk::CommandBuffer::Command
1154 {
1155 public:
CmdCopyQueryPoolResults(const vk::QueryPool * queryPool,uint32_t firstQuery,uint32_t queryCount,vk::Buffer * dstBuffer,VkDeviceSize dstOffset,VkDeviceSize stride,VkQueryResultFlags flags)1156 CmdCopyQueryPoolResults(const vk::QueryPool *queryPool, uint32_t firstQuery, uint32_t queryCount,
1157 vk::Buffer *dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags)
1158 : queryPool(queryPool)
1159 , firstQuery(firstQuery)
1160 , queryCount(queryCount)
1161 , dstBuffer(dstBuffer)
1162 , dstOffset(dstOffset)
1163 , stride(stride)
1164 , flags(flags)
1165 {
1166 }
1167
play(vk::CommandBuffer::ExecutionState & executionState)1168 void play(vk::CommandBuffer::ExecutionState &executionState) override
1169 {
1170 queryPool->getResults(firstQuery, queryCount, dstBuffer->getSize() - dstOffset,
1171 dstBuffer->getOffsetPointer(dstOffset), stride, flags);
1172 }
1173
description()1174 std::string description() override { return "vkCmdCopyQueryPoolResults()"; }
1175
1176 private:
1177 const vk::QueryPool *queryPool;
1178 uint32_t firstQuery;
1179 uint32_t queryCount;
1180 vk::Buffer *dstBuffer;
1181 VkDeviceSize dstOffset;
1182 VkDeviceSize stride;
1183 VkQueryResultFlags flags;
1184 };
1185
1186 } // anonymous namespace
1187
1188 namespace vk {
1189
CommandBuffer(Device * device,VkCommandBufferLevel pLevel)1190 CommandBuffer::CommandBuffer(Device *device, VkCommandBufferLevel pLevel)
1191 : device(device)
1192 , level(pLevel)
1193 {
1194 }
1195
destroy(const VkAllocationCallbacks * pAllocator)1196 void CommandBuffer::destroy(const VkAllocationCallbacks *pAllocator)
1197 {
1198 }
1199
resetState()1200 void CommandBuffer::resetState()
1201 {
1202 // FIXME (b/119409619): replace this vector by an allocator so we can control all memory allocations
1203 commands.clear();
1204
1205 state = INITIAL;
1206 }
1207
begin(VkCommandBufferUsageFlags flags,const VkCommandBufferInheritanceInfo * pInheritanceInfo)1208 VkResult CommandBuffer::begin(VkCommandBufferUsageFlags flags, const VkCommandBufferInheritanceInfo *pInheritanceInfo)
1209 {
1210 ASSERT((state != RECORDING) && (state != PENDING));
1211
1212 // Nothing interesting to do based on flags. We don't have any optimizations
1213 // to apply for ONE_TIME_SUBMIT or (lack of) SIMULTANEOUS_USE. RENDER_PASS_CONTINUE
1214 // must also provide a non-null pInheritanceInfo, which we don't implement yet, but is caught below.
1215 (void)flags;
1216
1217 // pInheritanceInfo merely contains optimization hints, so we currently ignore it
1218
1219 // "pInheritanceInfo is a pointer to a VkCommandBufferInheritanceInfo structure, used if commandBuffer is a
1220 // secondary command buffer. If this is a primary command buffer, then this value is ignored."
1221 if(level == VK_COMMAND_BUFFER_LEVEL_SECONDARY)
1222 {
1223 if(pInheritanceInfo->queryFlags != 0)
1224 {
1225 // "If the inherited queries feature is not enabled, queryFlags must be 0"
1226 UNSUPPORTED("VkPhysicalDeviceFeatures::inheritedQueries");
1227 }
1228 }
1229
1230 if(state != INITIAL)
1231 {
1232 // Implicit reset
1233 resetState();
1234 }
1235
1236 state = RECORDING;
1237
1238 return VK_SUCCESS;
1239 }
1240
end()1241 VkResult CommandBuffer::end()
1242 {
1243 ASSERT(state == RECORDING);
1244
1245 state = EXECUTABLE;
1246
1247 #ifdef ENABLE_VK_DEBUGGER
1248 auto debuggerContext = device->getDebuggerContext();
1249 if(debuggerContext)
1250 {
1251 std::string source;
1252 for(auto &command : commands)
1253 {
1254 source += command->description() + "\n";
1255 }
1256 debuggerFile = debuggerContext->lock().createVirtualFile("VkCommandBuffer", source.c_str());
1257 }
1258 #endif // ENABLE_VK_DEBUGGER
1259
1260 return VK_SUCCESS;
1261 }
1262
reset(VkCommandPoolResetFlags flags)1263 VkResult CommandBuffer::reset(VkCommandPoolResetFlags flags)
1264 {
1265 ASSERT(state != PENDING);
1266
1267 resetState();
1268
1269 return VK_SUCCESS;
1270 }
1271
1272 template<typename T, typename... Args>
addCommand(Args &&...args)1273 void CommandBuffer::addCommand(Args &&... args)
1274 {
1275 // FIXME (b/119409619): use an allocator here so we can control all memory allocations
1276 commands.push_back(std::make_unique<T>(std::forward<Args>(args)...));
1277 }
1278
beginRenderPass(RenderPass * renderPass,Framebuffer * framebuffer,VkRect2D renderArea,uint32_t clearValueCount,const VkClearValue * clearValues,VkSubpassContents contents,const VkRenderPassAttachmentBeginInfo * attachmentInfo)1279 void CommandBuffer::beginRenderPass(RenderPass *renderPass, Framebuffer *framebuffer, VkRect2D renderArea,
1280 uint32_t clearValueCount, const VkClearValue *clearValues, VkSubpassContents contents,
1281 const VkRenderPassAttachmentBeginInfo *attachmentInfo)
1282 {
1283 ASSERT(state == RECORDING);
1284
1285 if(attachmentInfo)
1286 {
1287 for(uint32_t i = 0; i < attachmentInfo->attachmentCount; i++)
1288 {
1289 framebuffer->setAttachment(vk::Cast(attachmentInfo->pAttachments[i]), i);
1290 }
1291 }
1292 addCommand<::CmdBeginRenderPass>(renderPass, framebuffer, renderArea, clearValueCount, clearValues);
1293 }
1294
nextSubpass(VkSubpassContents contents)1295 void CommandBuffer::nextSubpass(VkSubpassContents contents)
1296 {
1297 ASSERT(state == RECORDING);
1298
1299 addCommand<::CmdNextSubpass>();
1300 }
1301
endRenderPass()1302 void CommandBuffer::endRenderPass()
1303 {
1304 addCommand<::CmdEndRenderPass>();
1305 }
1306
executeCommands(uint32_t commandBufferCount,const VkCommandBuffer * pCommandBuffers)1307 void CommandBuffer::executeCommands(uint32_t commandBufferCount, const VkCommandBuffer *pCommandBuffers)
1308 {
1309 ASSERT(state == RECORDING);
1310
1311 for(uint32_t i = 0; i < commandBufferCount; ++i)
1312 {
1313 addCommand<::CmdExecuteCommands>(vk::Cast(pCommandBuffers[i]));
1314 }
1315 }
1316
setDeviceMask(uint32_t deviceMask)1317 void CommandBuffer::setDeviceMask(uint32_t deviceMask)
1318 {
1319 // SwiftShader only has one device, so we ignore the device mask
1320 }
1321
dispatchBase(uint32_t baseGroupX,uint32_t baseGroupY,uint32_t baseGroupZ,uint32_t groupCountX,uint32_t groupCountY,uint32_t groupCountZ)1322 void CommandBuffer::dispatchBase(uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ,
1323 uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ)
1324 {
1325 addCommand<::CmdDispatch>(baseGroupX, baseGroupY, baseGroupZ, groupCountX, groupCountY, groupCountZ);
1326 }
1327
pipelineBarrier(VkPipelineStageFlags srcStageMask,VkPipelineStageFlags dstStageMask,VkDependencyFlags dependencyFlags,uint32_t memoryBarrierCount,const VkMemoryBarrier * pMemoryBarriers,uint32_t bufferMemoryBarrierCount,const VkBufferMemoryBarrier * pBufferMemoryBarriers,uint32_t imageMemoryBarrierCount,const VkImageMemoryBarrier * pImageMemoryBarriers)1328 void CommandBuffer::pipelineBarrier(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
1329 VkDependencyFlags dependencyFlags,
1330 uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
1331 uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers,
1332 uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers)
1333 {
1334 addCommand<::CmdPipelineBarrier>();
1335 }
1336
bindPipeline(VkPipelineBindPoint pipelineBindPoint,Pipeline * pipeline)1337 void CommandBuffer::bindPipeline(VkPipelineBindPoint pipelineBindPoint, Pipeline *pipeline)
1338 {
1339 switch(pipelineBindPoint)
1340 {
1341 case VK_PIPELINE_BIND_POINT_COMPUTE:
1342 case VK_PIPELINE_BIND_POINT_GRAPHICS:
1343 addCommand<::CmdPipelineBind>(pipelineBindPoint, pipeline);
1344 break;
1345 default:
1346 UNSUPPORTED("VkPipelineBindPoint %d", int(pipelineBindPoint));
1347 }
1348 }
1349
bindVertexBuffers(uint32_t firstBinding,uint32_t bindingCount,const VkBuffer * pBuffers,const VkDeviceSize * pOffsets)1350 void CommandBuffer::bindVertexBuffers(uint32_t firstBinding, uint32_t bindingCount,
1351 const VkBuffer *pBuffers, const VkDeviceSize *pOffsets)
1352 {
1353 for(uint32_t i = 0; i < bindingCount; ++i)
1354 {
1355 addCommand<::CmdVertexBufferBind>(i + firstBinding, vk::Cast(pBuffers[i]), pOffsets[i]);
1356 }
1357 }
1358
beginQuery(QueryPool * queryPool,uint32_t query,VkQueryControlFlags flags)1359 void CommandBuffer::beginQuery(QueryPool *queryPool, uint32_t query, VkQueryControlFlags flags)
1360 {
1361 addCommand<::CmdBeginQuery>(queryPool, query, flags);
1362 }
1363
endQuery(QueryPool * queryPool,uint32_t query)1364 void CommandBuffer::endQuery(QueryPool *queryPool, uint32_t query)
1365 {
1366 addCommand<::CmdEndQuery>(queryPool, query);
1367 }
1368
resetQueryPool(QueryPool * queryPool,uint32_t firstQuery,uint32_t queryCount)1369 void CommandBuffer::resetQueryPool(QueryPool *queryPool, uint32_t firstQuery, uint32_t queryCount)
1370 {
1371 addCommand<::CmdResetQueryPool>(queryPool, firstQuery, queryCount);
1372 }
1373
writeTimestamp(VkPipelineStageFlagBits pipelineStage,QueryPool * queryPool,uint32_t query)1374 void CommandBuffer::writeTimestamp(VkPipelineStageFlagBits pipelineStage, QueryPool *queryPool, uint32_t query)
1375 {
1376 addCommand<::CmdWriteTimeStamp>(queryPool, query, pipelineStage);
1377 }
1378
copyQueryPoolResults(const QueryPool * queryPool,uint32_t firstQuery,uint32_t queryCount,Buffer * dstBuffer,VkDeviceSize dstOffset,VkDeviceSize stride,VkQueryResultFlags flags)1379 void CommandBuffer::copyQueryPoolResults(const QueryPool *queryPool, uint32_t firstQuery, uint32_t queryCount,
1380 Buffer *dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags)
1381 {
1382 addCommand<::CmdCopyQueryPoolResults>(queryPool, firstQuery, queryCount, dstBuffer, dstOffset, stride, flags);
1383 }
1384
pushConstants(PipelineLayout * layout,VkShaderStageFlags stageFlags,uint32_t offset,uint32_t size,const void * pValues)1385 void CommandBuffer::pushConstants(PipelineLayout *layout, VkShaderStageFlags stageFlags,
1386 uint32_t offset, uint32_t size, const void *pValues)
1387 {
1388 addCommand<::CmdSetPushConstants>(offset, size, pValues);
1389 }
1390
setViewport(uint32_t firstViewport,uint32_t viewportCount,const VkViewport * pViewports)1391 void CommandBuffer::setViewport(uint32_t firstViewport, uint32_t viewportCount, const VkViewport *pViewports)
1392 {
1393 if(firstViewport != 0 || viewportCount > 1)
1394 {
1395 UNSUPPORTED("VkPhysicalDeviceFeatures::multiViewport");
1396 }
1397
1398 for(uint32_t i = 0; i < viewportCount; i++)
1399 {
1400 addCommand<::CmdSetViewport>(pViewports[i], i + firstViewport);
1401 }
1402 }
1403
setScissor(uint32_t firstScissor,uint32_t scissorCount,const VkRect2D * pScissors)1404 void CommandBuffer::setScissor(uint32_t firstScissor, uint32_t scissorCount, const VkRect2D *pScissors)
1405 {
1406 if(firstScissor != 0 || scissorCount > 1)
1407 {
1408 UNSUPPORTED("VkPhysicalDeviceFeatures::multiViewport");
1409 }
1410
1411 for(uint32_t i = 0; i < scissorCount; i++)
1412 {
1413 addCommand<::CmdSetScissor>(pScissors[i], i + firstScissor);
1414 }
1415 }
1416
setLineWidth(float lineWidth)1417 void CommandBuffer::setLineWidth(float lineWidth)
1418 {
1419 // If the wide lines feature is not enabled, lineWidth must be 1.0
1420 ASSERT(lineWidth == 1.0f);
1421 }
1422
setDepthBias(float depthBiasConstantFactor,float depthBiasClamp,float depthBiasSlopeFactor)1423 void CommandBuffer::setDepthBias(float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor)
1424 {
1425 addCommand<::CmdSetDepthBias>(depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor);
1426 }
1427
setBlendConstants(const float blendConstants[4])1428 void CommandBuffer::setBlendConstants(const float blendConstants[4])
1429 {
1430 addCommand<::CmdSetBlendConstants>(blendConstants);
1431 }
1432
setDepthBounds(float minDepthBounds,float maxDepthBounds)1433 void CommandBuffer::setDepthBounds(float minDepthBounds, float maxDepthBounds)
1434 {
1435 addCommand<::CmdSetDepthBounds>(minDepthBounds, maxDepthBounds);
1436 }
1437
setStencilCompareMask(VkStencilFaceFlags faceMask,uint32_t compareMask)1438 void CommandBuffer::setStencilCompareMask(VkStencilFaceFlags faceMask, uint32_t compareMask)
1439 {
1440 // faceMask must not be 0
1441 ASSERT(faceMask != 0);
1442
1443 addCommand<::CmdSetStencilCompareMask>(faceMask, compareMask);
1444 }
1445
setStencilWriteMask(VkStencilFaceFlags faceMask,uint32_t writeMask)1446 void CommandBuffer::setStencilWriteMask(VkStencilFaceFlags faceMask, uint32_t writeMask)
1447 {
1448 // faceMask must not be 0
1449 ASSERT(faceMask != 0);
1450
1451 addCommand<::CmdSetStencilWriteMask>(faceMask, writeMask);
1452 }
1453
setStencilReference(VkStencilFaceFlags faceMask,uint32_t reference)1454 void CommandBuffer::setStencilReference(VkStencilFaceFlags faceMask, uint32_t reference)
1455 {
1456 // faceMask must not be 0
1457 ASSERT(faceMask != 0);
1458
1459 addCommand<::CmdSetStencilReference>(faceMask, reference);
1460 }
1461
bindDescriptorSets(VkPipelineBindPoint pipelineBindPoint,const PipelineLayout * pipelineLayout,uint32_t firstSet,uint32_t descriptorSetCount,const VkDescriptorSet * pDescriptorSets,uint32_t dynamicOffsetCount,const uint32_t * pDynamicOffsets)1462 void CommandBuffer::bindDescriptorSets(VkPipelineBindPoint pipelineBindPoint, const PipelineLayout *pipelineLayout,
1463 uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet *pDescriptorSets,
1464 uint32_t dynamicOffsetCount, const uint32_t *pDynamicOffsets)
1465 {
1466 ASSERT(state == RECORDING);
1467
1468 auto firstDynamicOffset = (dynamicOffsetCount != 0) ? pipelineLayout->getDynamicOffsetIndex(firstSet, 0) : 0;
1469
1470 addCommand<::CmdBindDescriptorSets>(
1471 pipelineBindPoint, firstSet, descriptorSetCount, pDescriptorSets,
1472 firstDynamicOffset, dynamicOffsetCount, pDynamicOffsets);
1473 }
1474
bindIndexBuffer(Buffer * buffer,VkDeviceSize offset,VkIndexType indexType)1475 void CommandBuffer::bindIndexBuffer(Buffer *buffer, VkDeviceSize offset, VkIndexType indexType)
1476 {
1477 addCommand<::CmdIndexBufferBind>(buffer, offset, indexType);
1478 }
1479
dispatch(uint32_t groupCountX,uint32_t groupCountY,uint32_t groupCountZ)1480 void CommandBuffer::dispatch(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ)
1481 {
1482 addCommand<::CmdDispatch>(0, 0, 0, groupCountX, groupCountY, groupCountZ);
1483 }
1484
dispatchIndirect(Buffer * buffer,VkDeviceSize offset)1485 void CommandBuffer::dispatchIndirect(Buffer *buffer, VkDeviceSize offset)
1486 {
1487 addCommand<::CmdDispatchIndirect>(buffer, offset);
1488 }
1489
copyBuffer(const Buffer * srcBuffer,Buffer * dstBuffer,uint32_t regionCount,const VkBufferCopy * pRegions)1490 void CommandBuffer::copyBuffer(const Buffer *srcBuffer, Buffer *dstBuffer, uint32_t regionCount, const VkBufferCopy *pRegions)
1491 {
1492 ASSERT(state == RECORDING);
1493
1494 for(uint32_t i = 0; i < regionCount; i++)
1495 {
1496 addCommand<::CmdCopyBuffer>(srcBuffer, dstBuffer, pRegions[i]);
1497 }
1498 }
1499
copyImage(const Image * srcImage,VkImageLayout srcImageLayout,Image * dstImage,VkImageLayout dstImageLayout,uint32_t regionCount,const VkImageCopy * pRegions)1500 void CommandBuffer::copyImage(const Image *srcImage, VkImageLayout srcImageLayout, Image *dstImage, VkImageLayout dstImageLayout,
1501 uint32_t regionCount, const VkImageCopy *pRegions)
1502 {
1503 ASSERT(state == RECORDING);
1504 ASSERT(srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL ||
1505 srcImageLayout == VK_IMAGE_LAYOUT_GENERAL);
1506 ASSERT(dstImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ||
1507 dstImageLayout == VK_IMAGE_LAYOUT_GENERAL);
1508
1509 for(uint32_t i = 0; i < regionCount; i++)
1510 {
1511 addCommand<::CmdCopyImage>(srcImage, dstImage, pRegions[i]);
1512 }
1513 }
1514
blitImage(const Image * srcImage,VkImageLayout srcImageLayout,Image * dstImage,VkImageLayout dstImageLayout,uint32_t regionCount,const VkImageBlit * pRegions,VkFilter filter)1515 void CommandBuffer::blitImage(const Image *srcImage, VkImageLayout srcImageLayout, Image *dstImage, VkImageLayout dstImageLayout,
1516 uint32_t regionCount, const VkImageBlit *pRegions, VkFilter filter)
1517 {
1518 ASSERT(state == RECORDING);
1519 ASSERT(srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL ||
1520 srcImageLayout == VK_IMAGE_LAYOUT_GENERAL);
1521 ASSERT(dstImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ||
1522 dstImageLayout == VK_IMAGE_LAYOUT_GENERAL);
1523
1524 for(uint32_t i = 0; i < regionCount; i++)
1525 {
1526 addCommand<::CmdBlitImage>(srcImage, dstImage, pRegions[i], filter);
1527 }
1528 }
1529
copyBufferToImage(Buffer * srcBuffer,Image * dstImage,VkImageLayout dstImageLayout,uint32_t regionCount,const VkBufferImageCopy * pRegions)1530 void CommandBuffer::copyBufferToImage(Buffer *srcBuffer, Image *dstImage, VkImageLayout dstImageLayout,
1531 uint32_t regionCount, const VkBufferImageCopy *pRegions)
1532 {
1533 ASSERT(state == RECORDING);
1534
1535 for(uint32_t i = 0; i < regionCount; i++)
1536 {
1537 addCommand<::CmdCopyBufferToImage>(srcBuffer, dstImage, pRegions[i]);
1538 }
1539 }
1540
copyImageToBuffer(Image * srcImage,VkImageLayout srcImageLayout,Buffer * dstBuffer,uint32_t regionCount,const VkBufferImageCopy * pRegions)1541 void CommandBuffer::copyImageToBuffer(Image *srcImage, VkImageLayout srcImageLayout, Buffer *dstBuffer,
1542 uint32_t regionCount, const VkBufferImageCopy *pRegions)
1543 {
1544 ASSERT(state == RECORDING);
1545 ASSERT(srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL || srcImageLayout == VK_IMAGE_LAYOUT_GENERAL);
1546
1547 for(uint32_t i = 0; i < regionCount; i++)
1548 {
1549 addCommand<::CmdCopyImageToBuffer>(srcImage, dstBuffer, pRegions[i]);
1550 }
1551 }
1552
updateBuffer(Buffer * dstBuffer,VkDeviceSize dstOffset,VkDeviceSize dataSize,const void * pData)1553 void CommandBuffer::updateBuffer(Buffer *dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const void *pData)
1554 {
1555 ASSERT(state == RECORDING);
1556
1557 addCommand<::CmdUpdateBuffer>(dstBuffer, dstOffset, dataSize, reinterpret_cast<const uint8_t *>(pData));
1558 }
1559
fillBuffer(Buffer * dstBuffer,VkDeviceSize dstOffset,VkDeviceSize size,uint32_t data)1560 void CommandBuffer::fillBuffer(Buffer *dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data)
1561 {
1562 ASSERT(state == RECORDING);
1563
1564 addCommand<::CmdFillBuffer>(dstBuffer, dstOffset, size, data);
1565 }
1566
clearColorImage(Image * image,VkImageLayout imageLayout,const VkClearColorValue * pColor,uint32_t rangeCount,const VkImageSubresourceRange * pRanges)1567 void CommandBuffer::clearColorImage(Image *image, VkImageLayout imageLayout, const VkClearColorValue *pColor,
1568 uint32_t rangeCount, const VkImageSubresourceRange *pRanges)
1569 {
1570 ASSERT(state == RECORDING);
1571
1572 for(uint32_t i = 0; i < rangeCount; i++)
1573 {
1574 addCommand<::CmdClearColorImage>(image, *pColor, pRanges[i]);
1575 }
1576 }
1577
clearDepthStencilImage(Image * image,VkImageLayout imageLayout,const VkClearDepthStencilValue * pDepthStencil,uint32_t rangeCount,const VkImageSubresourceRange * pRanges)1578 void CommandBuffer::clearDepthStencilImage(Image *image, VkImageLayout imageLayout, const VkClearDepthStencilValue *pDepthStencil,
1579 uint32_t rangeCount, const VkImageSubresourceRange *pRanges)
1580 {
1581 ASSERT(state == RECORDING);
1582
1583 for(uint32_t i = 0; i < rangeCount; i++)
1584 {
1585 addCommand<::CmdClearDepthStencilImage>(image, *pDepthStencil, pRanges[i]);
1586 }
1587 }
1588
clearAttachments(uint32_t attachmentCount,const VkClearAttachment * pAttachments,uint32_t rectCount,const VkClearRect * pRects)1589 void CommandBuffer::clearAttachments(uint32_t attachmentCount, const VkClearAttachment *pAttachments,
1590 uint32_t rectCount, const VkClearRect *pRects)
1591 {
1592 ASSERT(state == RECORDING);
1593
1594 for(uint32_t i = 0; i < attachmentCount; i++)
1595 {
1596 for(uint32_t j = 0; j < rectCount; j++)
1597 {
1598 addCommand<::CmdClearAttachment>(pAttachments[i], pRects[j]);
1599 }
1600 }
1601 }
1602
resolveImage(const Image * srcImage,VkImageLayout srcImageLayout,Image * dstImage,VkImageLayout dstImageLayout,uint32_t regionCount,const VkImageResolve * pRegions)1603 void CommandBuffer::resolveImage(const Image *srcImage, VkImageLayout srcImageLayout, Image *dstImage, VkImageLayout dstImageLayout,
1604 uint32_t regionCount, const VkImageResolve *pRegions)
1605 {
1606 ASSERT(state == RECORDING);
1607 ASSERT(srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL ||
1608 srcImageLayout == VK_IMAGE_LAYOUT_GENERAL);
1609 ASSERT(dstImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ||
1610 dstImageLayout == VK_IMAGE_LAYOUT_GENERAL);
1611
1612 for(uint32_t i = 0; i < regionCount; i++)
1613 {
1614 addCommand<::CmdResolveImage>(srcImage, dstImage, pRegions[i]);
1615 }
1616 }
1617
setEvent(Event * event,VkPipelineStageFlags stageMask)1618 void CommandBuffer::setEvent(Event *event, VkPipelineStageFlags stageMask)
1619 {
1620 ASSERT(state == RECORDING);
1621
1622 addCommand<::CmdSignalEvent>(event, stageMask);
1623 }
1624
resetEvent(Event * event,VkPipelineStageFlags stageMask)1625 void CommandBuffer::resetEvent(Event *event, VkPipelineStageFlags stageMask)
1626 {
1627 ASSERT(state == RECORDING);
1628
1629 addCommand<::CmdResetEvent>(event, stageMask);
1630 }
1631
waitEvents(uint32_t eventCount,const VkEvent * pEvents,VkPipelineStageFlags srcStageMask,VkPipelineStageFlags dstStageMask,uint32_t memoryBarrierCount,const VkMemoryBarrier * pMemoryBarriers,uint32_t bufferMemoryBarrierCount,const VkBufferMemoryBarrier * pBufferMemoryBarriers,uint32_t imageMemoryBarrierCount,const VkImageMemoryBarrier * pImageMemoryBarriers)1632 void CommandBuffer::waitEvents(uint32_t eventCount, const VkEvent *pEvents, VkPipelineStageFlags srcStageMask,
1633 VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
1634 uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers,
1635 uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers)
1636 {
1637 ASSERT(state == RECORDING);
1638
1639 // TODO(b/117835459): Since we always do a full barrier, all memory barrier related arguments are ignored
1640
1641 // Note: srcStageMask and dstStageMask are currently ignored
1642 for(uint32_t i = 0; i < eventCount; i++)
1643 {
1644 addCommand<::CmdWaitEvent>(vk::Cast(pEvents[i]));
1645 }
1646 }
1647
draw(uint32_t vertexCount,uint32_t instanceCount,uint32_t firstVertex,uint32_t firstInstance)1648 void CommandBuffer::draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance)
1649 {
1650 addCommand<::CmdDraw>(vertexCount, instanceCount, firstVertex, firstInstance);
1651 }
1652
drawIndexed(uint32_t indexCount,uint32_t instanceCount,uint32_t firstIndex,int32_t vertexOffset,uint32_t firstInstance)1653 void CommandBuffer::drawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance)
1654 {
1655 addCommand<::CmdDrawIndexed>(indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
1656 }
1657
drawIndirect(Buffer * buffer,VkDeviceSize offset,uint32_t drawCount,uint32_t stride)1658 void CommandBuffer::drawIndirect(Buffer *buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride)
1659 {
1660 addCommand<::CmdDrawIndirect>(buffer, offset, drawCount, stride);
1661 }
1662
drawIndexedIndirect(Buffer * buffer,VkDeviceSize offset,uint32_t drawCount,uint32_t stride)1663 void CommandBuffer::drawIndexedIndirect(Buffer *buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride)
1664 {
1665 addCommand<::CmdDrawIndexedIndirect>(buffer, offset, drawCount, stride);
1666 }
1667
beginDebugUtilsLabel(const VkDebugUtilsLabelEXT * pLabelInfo)1668 void CommandBuffer::beginDebugUtilsLabel(const VkDebugUtilsLabelEXT *pLabelInfo)
1669 {
1670 // Optional debug label region
1671 }
1672
endDebugUtilsLabel()1673 void CommandBuffer::endDebugUtilsLabel()
1674 {
1675 // Close debug label region opened with beginDebugUtilsLabel()
1676 }
1677
insertDebugUtilsLabel(const VkDebugUtilsLabelEXT * pLabelInfo)1678 void CommandBuffer::insertDebugUtilsLabel(const VkDebugUtilsLabelEXT *pLabelInfo)
1679 {
1680 // Optional single debug label
1681 }
1682
submit(CommandBuffer::ExecutionState & executionState)1683 void CommandBuffer::submit(CommandBuffer::ExecutionState &executionState)
1684 {
1685 // Perform recorded work
1686 state = PENDING;
1687
1688 #ifdef ENABLE_VK_DEBUGGER
1689 std::shared_ptr<vk::dbg::Thread> debuggerThread;
1690 auto debuggerContext = device->getDebuggerContext();
1691 if(debuggerContext)
1692 {
1693 debuggerThread = debuggerContext->lock().currentThread();
1694 debuggerThread->setName("vkQueue processor");
1695 debuggerThread->enter(debuggerFile, "vkCommandBuffer::submit");
1696 }
1697 defer(if(debuggerThread) { debuggerThread->exit(); });
1698 int line = 1;
1699 #endif // ENABLE_VK_DEBUGGER
1700
1701 for(auto &command : commands)
1702 {
1703 #ifdef ENABLE_VK_DEBUGGER
1704 if(debuggerThread)
1705 {
1706 debuggerThread->update(true, [&](vk::dbg::Frame &frame) {
1707 frame.location = { debuggerFile, line++, 0 };
1708 });
1709 }
1710 #endif // ENABLE_VK_DEBUGGER
1711
1712 command->play(executionState);
1713 }
1714
1715 // After work is completed
1716 state = EXECUTABLE;
1717 }
1718
submitSecondary(CommandBuffer::ExecutionState & executionState) const1719 void CommandBuffer::submitSecondary(CommandBuffer::ExecutionState &executionState) const
1720 {
1721 for(auto &command : commands)
1722 {
1723 command->play(executionState);
1724 }
1725 }
1726
bindAttachments(Attachments * attachments)1727 void CommandBuffer::ExecutionState::bindAttachments(Attachments *attachments)
1728 {
1729 // Binds all the attachments for the current subpass
1730 // Ideally this would be performed by BeginRenderPass and NextSubpass, but
1731 // there is too much stomping of the renderer's state by setContext() in
1732 // draws.
1733
1734 auto const &subpass = renderPass->getSubpass(subpassIndex);
1735
1736 for(auto i = 0u; i < subpass.colorAttachmentCount; i++)
1737 {
1738 auto attachmentReference = subpass.pColorAttachments[i];
1739 if(attachmentReference.attachment != VK_ATTACHMENT_UNUSED)
1740 {
1741 attachments->renderTarget[i] = renderPassFramebuffer->getAttachment(attachmentReference.attachment);
1742 }
1743 }
1744
1745 auto attachmentReference = subpass.pDepthStencilAttachment;
1746 if(attachmentReference && attachmentReference->attachment != VK_ATTACHMENT_UNUSED)
1747 {
1748 auto attachment = renderPassFramebuffer->getAttachment(attachmentReference->attachment);
1749 if(attachment->hasDepthAspect())
1750 {
1751 attachments->depthBuffer = attachment;
1752 }
1753 if(attachment->hasStencilAspect())
1754 {
1755 attachments->stencilBuffer = attachment;
1756 }
1757 }
1758 }
1759
1760 } // namespace vk
1761