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