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,const VkRenderPassAttachmentBeginInfo * attachmentInfo)45 CmdBeginRenderPass(vk::RenderPass *renderPass, vk::Framebuffer *framebuffer, VkRect2D renderArea,
46 uint32_t clearValueCount, const VkClearValue *pClearValues,
47 const VkRenderPassAttachmentBeginInfo *attachmentInfo)
48 : renderPass(renderPass)
49 , framebuffer(framebuffer)
50 , renderArea(renderArea)
51 , clearValueCount(clearValueCount)
52 , attachmentCount(attachmentInfo ? attachmentInfo->attachmentCount : 0)
53 , attachments(nullptr)
54 {
55 // FIXME(b/119409619): use an allocator here so we can control all memory allocations
56 clearValues = new VkClearValue[clearValueCount];
57 memcpy(clearValues, pClearValues, clearValueCount * sizeof(VkClearValue));
58 if(attachmentCount > 0)
59 {
60 attachments = new vk::ImageView *[attachmentCount];
61 for(uint32_t i = 0; i < attachmentCount; i++)
62 {
63 attachments[i] = vk::Cast(attachmentInfo->pAttachments[i]);
64 }
65 }
66 }
67
~CmdBeginRenderPass()68 ~CmdBeginRenderPass() override
69 {
70 delete[] clearValues;
71 delete[] attachments;
72 }
73
execute(vk::CommandBuffer::ExecutionState & executionState)74 void execute(vk::CommandBuffer::ExecutionState &executionState) override
75 {
76 executionState.renderPass = renderPass;
77 executionState.renderPassFramebuffer = framebuffer;
78 executionState.subpassIndex = 0;
79
80 for(uint32_t i = 0; i < attachmentCount; i++)
81 {
82 framebuffer->setAttachment(attachments[i], i);
83 }
84
85 // Vulkan specifies that the attachments' `loadOp` gets executed "at the beginning of the subpass where it is first used."
86 // Since we don't discard any contents between subpasses, this is equivalent to executing it at the start of the renderpass.
87 framebuffer->executeLoadOp(executionState.renderPass, clearValueCount, clearValues, renderArea);
88 }
89
description()90 std::string description() override { return "vkCmdBeginRenderPass()"; }
91
92 private:
93 vk::RenderPass *const renderPass;
94 vk::Framebuffer *const framebuffer;
95 const VkRect2D renderArea;
96 const uint32_t clearValueCount;
97 VkClearValue *clearValues;
98 uint32_t attachmentCount;
99 vk::ImageView **attachments;
100 };
101
102 class CmdNextSubpass : public vk::CommandBuffer::Command
103 {
104 public:
execute(vk::CommandBuffer::ExecutionState & executionState)105 void execute(vk::CommandBuffer::ExecutionState &executionState) override
106 {
107 bool hasResolveAttachments = (executionState.renderPass->getSubpass(executionState.subpassIndex).pResolveAttachments != nullptr);
108 if(hasResolveAttachments)
109 {
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
117 executionState.subpassIndex++;
118 }
119
description()120 std::string description() override { return "vkCmdNextSubpass()"; }
121 };
122
123 class CmdEndRenderPass : public vk::CommandBuffer::Command
124 {
125 public:
execute(vk::CommandBuffer::ExecutionState & executionState)126 void execute(vk::CommandBuffer::ExecutionState &executionState) override
127 {
128 // Execute (implicit or explicit) VkSubpassDependency to VK_SUBPASS_EXTERNAL.
129 // TODO(b/197691918): Avoid halt-the-world synchronization.
130 executionState.renderer->synchronize();
131
132 // TODO(b/197691917): Eliminate redundant resolve operations.
133 executionState.renderPassFramebuffer->resolve(executionState.renderPass, executionState.subpassIndex);
134
135 executionState.renderPass = nullptr;
136 executionState.renderPassFramebuffer = nullptr;
137 }
138
description()139 std::string description() override { return "vkCmdEndRenderPass()"; }
140 };
141
142 class CmdBeginRendering : public vk::CommandBuffer::Command
143 {
144 public:
CmdBeginRendering(const VkRenderingInfo * pRenderingInfo)145 CmdBeginRendering(const VkRenderingInfo *pRenderingInfo)
146 : dynamicRendering(pRenderingInfo)
147 {
148 }
149
execute(vk::CommandBuffer::ExecutionState & executionState)150 void execute(vk::CommandBuffer::ExecutionState &executionState) override
151 {
152 executionState.dynamicRendering = &dynamicRendering;
153
154 if(!executionState.dynamicRendering->resume())
155 {
156 VkClearRect rect = {};
157 rect.rect = executionState.dynamicRendering->getRenderArea();
158 rect.layerCount = executionState.dynamicRendering->getLayerCount();
159 uint32_t viewMask = executionState.dynamicRendering->getViewMask();
160
161 // Vulkan specifies that the attachments' `loadOp` gets executed "at the beginning of the subpass where it is first used."
162 // Since we don't discard any contents between subpasses, this is equivalent to executing it at the start of the renderpass.
163 for(uint32_t i = 0; i < dynamicRendering.getColorAttachmentCount(); i++)
164 {
165 const VkRenderingAttachmentInfo *colorAttachment = dynamicRendering.getColorAttachment(i);
166
167 if(colorAttachment->loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR)
168 {
169 vk::ImageView *imageView = vk::Cast(colorAttachment->imageView);
170 if(imageView)
171 {
172 imageView->clear(colorAttachment->clearValue, VK_IMAGE_ASPECT_COLOR_BIT, rect, viewMask);
173 }
174 }
175 }
176
177 const VkRenderingAttachmentInfo &stencilAttachment = dynamicRendering.getStencilAttachment();
178 if(stencilAttachment.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR)
179 {
180 vk::ImageView *imageView = vk::Cast(stencilAttachment.imageView);
181 if(imageView)
182 {
183 imageView->clear(stencilAttachment.clearValue, VK_IMAGE_ASPECT_STENCIL_BIT, rect, viewMask);
184 }
185 }
186
187 const VkRenderingAttachmentInfo &depthAttachment = dynamicRendering.getDepthAttachment();
188 if(depthAttachment.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR)
189 {
190 vk::ImageView *imageView = vk::Cast(depthAttachment.imageView);
191
192 if(imageView)
193 {
194 imageView->clear(depthAttachment.clearValue, VK_IMAGE_ASPECT_DEPTH_BIT, rect, viewMask);
195 }
196 }
197 }
198 }
199
description()200 std::string description() override { return "vkCmdBeginRendering()"; }
201
202 private:
203 vk::DynamicRendering dynamicRendering;
204 };
205
206 class CmdEndRendering : public vk::CommandBuffer::Command
207 {
208 public:
execute(vk::CommandBuffer::ExecutionState & executionState)209 void execute(vk::CommandBuffer::ExecutionState &executionState) override
210 {
211 // TODO(b/197691918): Avoid halt-the-world synchronization.
212 executionState.renderer->synchronize();
213
214 if(!executionState.dynamicRendering->suspend())
215 {
216 uint32_t viewMask = executionState.dynamicRendering->getViewMask();
217
218 // TODO(b/197691917): Eliminate redundant resolve operations.
219 uint32_t colorAttachmentCount = executionState.dynamicRendering->getColorAttachmentCount();
220 for(uint32_t i = 0; i < colorAttachmentCount; i++)
221 {
222 const VkRenderingAttachmentInfo *colorAttachment = executionState.dynamicRendering->getColorAttachment(i);
223 if(colorAttachment && colorAttachment->resolveMode != VK_RESOLVE_MODE_NONE)
224 {
225 vk::ImageView *imageView = vk::Cast(colorAttachment->imageView);
226 vk::ImageView *resolveImageView = vk::Cast(colorAttachment->resolveImageView);
227 imageView->resolve(resolveImageView, viewMask);
228 }
229 }
230
231 const VkRenderingAttachmentInfo &depthAttachment = executionState.dynamicRendering->getDepthAttachment();
232 if(depthAttachment.resolveMode != VK_RESOLVE_MODE_NONE)
233 {
234 vk::ImageView *imageView = vk::Cast(depthAttachment.imageView);
235 vk::ImageView *resolveImageView = vk::Cast(depthAttachment.resolveImageView);
236 imageView->resolveDepthStencil(resolveImageView, depthAttachment.resolveMode, VK_RESOLVE_MODE_NONE);
237 }
238
239 const VkRenderingAttachmentInfo &stencilAttachment = executionState.dynamicRendering->getStencilAttachment();
240 if(stencilAttachment.resolveMode != VK_RESOLVE_MODE_NONE)
241 {
242 vk::ImageView *imageView = vk::Cast(stencilAttachment.imageView);
243 vk::ImageView *resolveImageView = vk::Cast(stencilAttachment.resolveImageView);
244 imageView->resolveDepthStencil(resolveImageView, VK_RESOLVE_MODE_NONE, stencilAttachment.resolveMode);
245 }
246 }
247
248 executionState.dynamicRendering = nullptr;
249 }
250
description()251 std::string description() override { return "vkCmdEndRendering()"; }
252 };
253
254 class CmdExecuteCommands : public vk::CommandBuffer::Command
255 {
256 public:
CmdExecuteCommands(const vk::CommandBuffer * commandBuffer)257 CmdExecuteCommands(const vk::CommandBuffer *commandBuffer)
258 : commandBuffer(commandBuffer)
259 {
260 }
261
execute(vk::CommandBuffer::ExecutionState & executionState)262 void execute(vk::CommandBuffer::ExecutionState &executionState) override
263 {
264 commandBuffer->submitSecondary(executionState);
265 }
266
description()267 std::string description() override { return "vkCmdExecuteCommands()"; }
268
269 private:
270 const vk::CommandBuffer *const commandBuffer;
271 };
272
273 class CmdPipelineBind : public vk::CommandBuffer::Command
274 {
275 public:
CmdPipelineBind(VkPipelineBindPoint pipelineBindPoint,vk::Pipeline * pipeline)276 CmdPipelineBind(VkPipelineBindPoint pipelineBindPoint, vk::Pipeline *pipeline)
277 : pipelineBindPoint(pipelineBindPoint)
278 , pipeline(pipeline)
279 {
280 }
281
execute(vk::CommandBuffer::ExecutionState & executionState)282 void execute(vk::CommandBuffer::ExecutionState &executionState) override
283 {
284 executionState.pipelineState[pipelineBindPoint].pipeline = pipeline;
285 }
286
description()287 std::string description() override { return "vkCmdPipelineBind()"; }
288
289 private:
290 const VkPipelineBindPoint pipelineBindPoint;
291 vk::Pipeline *const pipeline;
292 };
293
294 class CmdDispatch : public vk::CommandBuffer::Command
295 {
296 public:
CmdDispatch(uint32_t baseGroupX,uint32_t baseGroupY,uint32_t baseGroupZ,uint32_t groupCountX,uint32_t groupCountY,uint32_t groupCountZ)297 CmdDispatch(uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ)
298 : baseGroupX(baseGroupX)
299 , baseGroupY(baseGroupY)
300 , baseGroupZ(baseGroupZ)
301 , groupCountX(groupCountX)
302 , groupCountY(groupCountY)
303 , groupCountZ(groupCountZ)
304 {
305 }
306
execute(vk::CommandBuffer::ExecutionState & executionState)307 void execute(vk::CommandBuffer::ExecutionState &executionState) override
308 {
309 const auto &pipelineState = executionState.pipelineState[VK_PIPELINE_BIND_POINT_COMPUTE];
310
311 vk::ComputePipeline *pipeline = static_cast<vk::ComputePipeline *>(pipelineState.pipeline);
312 pipeline->run(baseGroupX, baseGroupY, baseGroupZ,
313 groupCountX, groupCountY, groupCountZ,
314 pipelineState.descriptorSetObjects,
315 pipelineState.descriptorSets,
316 pipelineState.descriptorDynamicOffsets,
317 executionState.pushConstants);
318 }
319
description()320 std::string description() override { return "vkCmdDispatch()"; }
321
322 private:
323 const uint32_t baseGroupX;
324 const uint32_t baseGroupY;
325 const uint32_t baseGroupZ;
326 const uint32_t groupCountX;
327 const uint32_t groupCountY;
328 const uint32_t groupCountZ;
329 };
330
331 class CmdDispatchIndirect : public vk::CommandBuffer::Command
332 {
333 public:
CmdDispatchIndirect(vk::Buffer * buffer,VkDeviceSize offset)334 CmdDispatchIndirect(vk::Buffer *buffer, VkDeviceSize offset)
335 : buffer(buffer)
336 , offset(offset)
337 {
338 }
339
execute(vk::CommandBuffer::ExecutionState & executionState)340 void execute(vk::CommandBuffer::ExecutionState &executionState) override
341 {
342 const auto *cmd = reinterpret_cast<const VkDispatchIndirectCommand *>(buffer->getOffsetPointer(offset));
343
344 const auto &pipelineState = executionState.pipelineState[VK_PIPELINE_BIND_POINT_COMPUTE];
345
346 auto *pipeline = static_cast<vk::ComputePipeline *>(pipelineState.pipeline);
347 pipeline->run(0, 0, 0, cmd->x, cmd->y, cmd->z,
348 pipelineState.descriptorSetObjects,
349 pipelineState.descriptorSets,
350 pipelineState.descriptorDynamicOffsets,
351 executionState.pushConstants);
352 }
353
description()354 std::string description() override { return "vkCmdDispatchIndirect()"; }
355
356 private:
357 const vk::Buffer *const buffer;
358 const VkDeviceSize offset;
359 };
360
361 class CmdVertexBufferBind : public vk::CommandBuffer::Command
362 {
363 public:
CmdVertexBufferBind(uint32_t binding,vk::Buffer * buffer,const VkDeviceSize offset,const VkDeviceSize size,const VkDeviceSize stride)364 CmdVertexBufferBind(uint32_t binding, vk::Buffer *buffer, const VkDeviceSize offset, const VkDeviceSize size, const VkDeviceSize stride)
365 : binding(binding)
366 , buffer(buffer)
367 , offset(offset)
368 , size(size)
369 , stride(stride)
370 {
371 }
372
execute(vk::CommandBuffer::ExecutionState & executionState)373 void execute(vk::CommandBuffer::ExecutionState &executionState) override
374 {
375 executionState.vertexInputBindings[binding] = { buffer, offset, size, stride };
376 }
377
description()378 std::string description() override { return "vkCmdVertexBufferBind()"; }
379
380 private:
381 const uint32_t binding;
382 vk::Buffer *const buffer;
383 const VkDeviceSize offset;
384 const VkDeviceSize size;
385 const VkDeviceSize stride;
386 };
387
388 class CmdIndexBufferBind : public vk::CommandBuffer::Command
389 {
390 public:
CmdIndexBufferBind(vk::Buffer * buffer,const VkDeviceSize offset,const VkIndexType indexType)391 CmdIndexBufferBind(vk::Buffer *buffer, const VkDeviceSize offset, const VkIndexType indexType)
392 : buffer(buffer)
393 , offset(offset)
394 , indexType(indexType)
395 {
396 }
397
execute(vk::CommandBuffer::ExecutionState & executionState)398 void execute(vk::CommandBuffer::ExecutionState &executionState) override
399 {
400 executionState.indexBufferBinding = { buffer, offset, 0, 0 };
401 executionState.indexType = indexType;
402 }
403
description()404 std::string description() override { return "vkCmdIndexBufferBind()"; }
405
406 private:
407 vk::Buffer *const buffer;
408 const VkDeviceSize offset;
409 const VkIndexType indexType;
410 };
411
412 class CmdSetViewport : public vk::CommandBuffer::Command
413 {
414 public:
CmdSetViewport(const VkViewport & viewport,uint32_t viewportID)415 CmdSetViewport(const VkViewport &viewport, uint32_t viewportID)
416 : viewport(viewport)
417 , viewportID(viewportID)
418 {
419 }
420
execute(vk::CommandBuffer::ExecutionState & executionState)421 void execute(vk::CommandBuffer::ExecutionState &executionState) override
422 {
423 executionState.dynamicState.viewport = viewport;
424 }
425
description()426 std::string description() override { return "vkCmdSetViewport()"; }
427
428 private:
429 const VkViewport viewport;
430 const uint32_t viewportID;
431 };
432
433 class CmdSetScissor : public vk::CommandBuffer::Command
434 {
435 public:
CmdSetScissor(const VkRect2D & scissor,uint32_t scissorID)436 CmdSetScissor(const VkRect2D &scissor, uint32_t scissorID)
437 : scissor(scissor)
438 , scissorID(scissorID)
439 {
440 }
441
execute(vk::CommandBuffer::ExecutionState & executionState)442 void execute(vk::CommandBuffer::ExecutionState &executionState) override
443 {
444 executionState.dynamicState.scissor = scissor;
445 }
446
description()447 std::string description() override { return "vkCmdSetScissor()"; }
448
449 private:
450 const VkRect2D scissor;
451 const uint32_t scissorID;
452 };
453
454 class CmdSetLineWidth : public vk::CommandBuffer::Command
455 {
456 public:
CmdSetLineWidth(float lineWidth)457 CmdSetLineWidth(float lineWidth)
458 : lineWidth(lineWidth)
459 {
460 }
461
execute(vk::CommandBuffer::ExecutionState & executionState)462 void execute(vk::CommandBuffer::ExecutionState &executionState) override
463 {
464 executionState.dynamicState.lineWidth = lineWidth;
465 }
466
description()467 std::string description() override { return "vkCmdSetLineWidth()"; }
468
469 private:
470 const float lineWidth;
471 };
472
473 class CmdSetDepthBias : public vk::CommandBuffer::Command
474 {
475 public:
CmdSetDepthBias(float depthBiasConstantFactor,float depthBiasClamp,float depthBiasSlopeFactor)476 CmdSetDepthBias(float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor)
477 : depthBiasConstantFactor(depthBiasConstantFactor)
478 , depthBiasClamp(depthBiasClamp)
479 , depthBiasSlopeFactor(depthBiasSlopeFactor)
480 {
481 }
482
execute(vk::CommandBuffer::ExecutionState & executionState)483 void execute(vk::CommandBuffer::ExecutionState &executionState) override
484 {
485 executionState.dynamicState.depthBiasConstantFactor = depthBiasConstantFactor;
486 executionState.dynamicState.depthBiasClamp = depthBiasClamp;
487 executionState.dynamicState.depthBiasSlopeFactor = depthBiasSlopeFactor;
488 }
489
description()490 std::string description() override { return "vkCmdSetDepthBias()"; }
491
492 private:
493 const float depthBiasConstantFactor;
494 const float depthBiasClamp;
495 const float depthBiasSlopeFactor;
496 };
497
498 class CmdSetBlendConstants : public vk::CommandBuffer::Command
499 {
500 public:
CmdSetBlendConstants(const float blendConstants[4])501 CmdSetBlendConstants(const float blendConstants[4])
502 {
503 memcpy(this->blendConstants, blendConstants, sizeof(this->blendConstants));
504 }
505
execute(vk::CommandBuffer::ExecutionState & executionState)506 void execute(vk::CommandBuffer::ExecutionState &executionState) override
507 {
508 memcpy(&(executionState.dynamicState.blendConstants[0]), blendConstants, sizeof(blendConstants));
509 }
510
description()511 std::string description() override { return "vkCmdSetBlendConstants()"; }
512
513 private:
514 float blendConstants[4];
515 };
516
517 class CmdSetDepthBounds : public vk::CommandBuffer::Command
518 {
519 public:
CmdSetDepthBounds(float minDepthBounds,float maxDepthBounds)520 CmdSetDepthBounds(float minDepthBounds, float maxDepthBounds)
521 : minDepthBounds(minDepthBounds)
522 , maxDepthBounds(maxDepthBounds)
523 {
524 }
525
execute(vk::CommandBuffer::ExecutionState & executionState)526 void execute(vk::CommandBuffer::ExecutionState &executionState) override
527 {
528 executionState.dynamicState.minDepthBounds = minDepthBounds;
529 executionState.dynamicState.maxDepthBounds = maxDepthBounds;
530 }
531
description()532 std::string description() override { return "vkCmdSetDepthBounds()"; }
533
534 private:
535 const float minDepthBounds;
536 const float maxDepthBounds;
537 };
538
539 class CmdSetStencilCompareMask : public vk::CommandBuffer::Command
540 {
541 public:
CmdSetStencilCompareMask(VkStencilFaceFlags faceMask,uint32_t compareMask)542 CmdSetStencilCompareMask(VkStencilFaceFlags faceMask, uint32_t compareMask)
543 : faceMask(faceMask)
544 , compareMask(compareMask)
545 {
546 }
547
execute(vk::CommandBuffer::ExecutionState & executionState)548 void execute(vk::CommandBuffer::ExecutionState &executionState) override
549 {
550 if(faceMask & VK_STENCIL_FACE_FRONT_BIT)
551 {
552 executionState.dynamicState.frontStencil.compareMask = compareMask;
553 }
554
555 if(faceMask & VK_STENCIL_FACE_BACK_BIT)
556 {
557 executionState.dynamicState.backStencil.compareMask = compareMask;
558 }
559 }
560
description()561 std::string description() override { return "vkCmdSetStencilCompareMask()"; }
562
563 private:
564 const VkStencilFaceFlags faceMask;
565 const uint32_t compareMask;
566 };
567
568 class CmdSetStencilWriteMask : public vk::CommandBuffer::Command
569 {
570 public:
CmdSetStencilWriteMask(VkStencilFaceFlags faceMask,uint32_t writeMask)571 CmdSetStencilWriteMask(VkStencilFaceFlags faceMask, uint32_t writeMask)
572 : faceMask(faceMask)
573 , writeMask(writeMask)
574 {
575 }
576
execute(vk::CommandBuffer::ExecutionState & executionState)577 void execute(vk::CommandBuffer::ExecutionState &executionState) override
578 {
579 if(faceMask & VK_STENCIL_FACE_FRONT_BIT)
580 {
581 executionState.dynamicState.frontStencil.writeMask = writeMask;
582 }
583
584 if(faceMask & VK_STENCIL_FACE_BACK_BIT)
585 {
586 executionState.dynamicState.backStencil.writeMask = writeMask;
587 }
588 }
589
description()590 std::string description() override { return "vkCmdSetStencilWriteMask()"; }
591
592 private:
593 const VkStencilFaceFlags faceMask;
594 const uint32_t writeMask;
595 };
596
597 class CmdSetStencilReference : public vk::CommandBuffer::Command
598 {
599 public:
CmdSetStencilReference(VkStencilFaceFlags faceMask,uint32_t reference)600 CmdSetStencilReference(VkStencilFaceFlags faceMask, uint32_t reference)
601 : faceMask(faceMask)
602 , reference(reference)
603 {
604 }
605
execute(vk::CommandBuffer::ExecutionState & executionState)606 void execute(vk::CommandBuffer::ExecutionState &executionState) override
607 {
608 if(faceMask & VK_STENCIL_FACE_FRONT_BIT)
609 {
610 executionState.dynamicState.frontStencil.reference = reference;
611 }
612 if(faceMask & VK_STENCIL_FACE_BACK_BIT)
613 {
614 executionState.dynamicState.backStencil.reference = reference;
615 }
616 }
617
description()618 std::string description() override { return "vkCmdSetStencilReference()"; }
619
620 private:
621 const VkStencilFaceFlags faceMask;
622 const uint32_t reference;
623 };
624
625 class CmdSetCullMode : public vk::CommandBuffer::Command
626 {
627 public:
CmdSetCullMode(VkCullModeFlags cullMode)628 CmdSetCullMode(VkCullModeFlags cullMode)
629 : cullMode(cullMode)
630 {}
631
execute(vk::CommandBuffer::ExecutionState & executionState)632 void execute(vk::CommandBuffer::ExecutionState &executionState) override
633 {
634 executionState.dynamicState.cullMode = cullMode;
635 }
636
description()637 std::string description() override { return "vkCmdSetCullModeEXT()"; }
638
639 private:
640 const VkCullModeFlags cullMode;
641 };
642
643 class CmdSetDepthBoundsTestEnable : public vk::CommandBuffer::Command
644 {
645 public:
CmdSetDepthBoundsTestEnable(VkBool32 depthBoundsTestEnable)646 CmdSetDepthBoundsTestEnable(VkBool32 depthBoundsTestEnable)
647 : depthBoundsTestEnable(depthBoundsTestEnable)
648 {}
649
execute(vk::CommandBuffer::ExecutionState & executionState)650 void execute(vk::CommandBuffer::ExecutionState &executionState) override
651 {
652 executionState.dynamicState.depthBoundsTestEnable = depthBoundsTestEnable;
653 }
654
description()655 std::string description() override { return "vkCmdSetDepthBoundsTestEnableEXT()"; }
656
657 private:
658 const VkBool32 depthBoundsTestEnable;
659 };
660
661 class CmdSetDepthCompareOp : public vk::CommandBuffer::Command
662 {
663 public:
CmdSetDepthCompareOp(VkCompareOp depthCompareOp)664 CmdSetDepthCompareOp(VkCompareOp depthCompareOp)
665 : depthCompareOp(depthCompareOp)
666 {}
667
execute(vk::CommandBuffer::ExecutionState & executionState)668 void execute(vk::CommandBuffer::ExecutionState &executionState) override
669 {
670 executionState.dynamicState.depthCompareOp = depthCompareOp;
671 }
672
description()673 std::string description() override { return "vkCmdSetDepthCompareOpEXT()"; }
674
675 private:
676 const VkCompareOp depthCompareOp;
677 };
678
679 class CmdSetDepthTestEnable : public vk::CommandBuffer::Command
680 {
681 public:
CmdSetDepthTestEnable(VkBool32 depthTestEnable)682 CmdSetDepthTestEnable(VkBool32 depthTestEnable)
683 : depthTestEnable(depthTestEnable)
684 {}
685
execute(vk::CommandBuffer::ExecutionState & executionState)686 void execute(vk::CommandBuffer::ExecutionState &executionState) override
687 {
688 executionState.dynamicState.depthTestEnable = depthTestEnable;
689 }
690
description()691 std::string description() override { return "vkCmdSetDepthTestEnableEXT()"; }
692
693 private:
694 const VkBool32 depthTestEnable;
695 };
696
697 class CmdSetDepthWriteEnable : public vk::CommandBuffer::Command
698 {
699 public:
CmdSetDepthWriteEnable(VkBool32 depthWriteEnable)700 CmdSetDepthWriteEnable(VkBool32 depthWriteEnable)
701 : depthWriteEnable(depthWriteEnable)
702 {}
703
execute(vk::CommandBuffer::ExecutionState & executionState)704 void execute(vk::CommandBuffer::ExecutionState &executionState) override
705 {
706 executionState.dynamicState.depthWriteEnable = depthWriteEnable;
707 }
708
description()709 std::string description() override { return "vkCmdSetDepthWriteEnableEXT()"; }
710
711 private:
712 const VkBool32 depthWriteEnable;
713 };
714
715 class CmdSetFrontFace : public vk::CommandBuffer::Command
716 {
717 public:
CmdSetFrontFace(VkFrontFace frontFace)718 CmdSetFrontFace(VkFrontFace frontFace)
719 : frontFace(frontFace)
720 {}
721
execute(vk::CommandBuffer::ExecutionState & executionState)722 void execute(vk::CommandBuffer::ExecutionState &executionState) override
723 {
724 executionState.dynamicState.frontFace = frontFace;
725 }
726
description()727 std::string description() override { return "vkCmdSetFrontFaceEXT()"; }
728
729 private:
730 const VkFrontFace frontFace;
731 };
732
733 class CmdSetPrimitiveTopology : public vk::CommandBuffer::Command
734 {
735 public:
CmdSetPrimitiveTopology(VkPrimitiveTopology primitiveTopology)736 CmdSetPrimitiveTopology(VkPrimitiveTopology primitiveTopology)
737 : primitiveTopology(primitiveTopology)
738 {}
739
execute(vk::CommandBuffer::ExecutionState & executionState)740 void execute(vk::CommandBuffer::ExecutionState &executionState) override
741 {
742 executionState.dynamicState.primitiveTopology = primitiveTopology;
743 }
744
description()745 std::string description() override { return "vkCmdSetPrimitiveTopologyEXT()"; }
746
747 private:
748 const VkPrimitiveTopology primitiveTopology;
749 };
750
751 class CmdSetScissorWithCount : public vk::CommandBuffer::Command
752 {
753 public:
CmdSetScissorWithCount(uint32_t scissorCount,const VkRect2D * pScissors)754 CmdSetScissorWithCount(uint32_t scissorCount, const VkRect2D *pScissors)
755 : scissorCount(scissorCount)
756 {
757 memcpy(&(scissors[0]), pScissors, scissorCount * sizeof(VkRect2D));
758 }
759
execute(vk::CommandBuffer::ExecutionState & executionState)760 void execute(vk::CommandBuffer::ExecutionState &executionState) override
761 {
762 executionState.dynamicState.scissorCount = scissorCount;
763 for(uint32_t i = 0; i < scissorCount; i++)
764 {
765 executionState.dynamicState.scissors[i] = scissors[i];
766 }
767 }
768
description()769 std::string description() override { return "vkCmdSetScissorWithCountEXT()"; }
770
771 private:
772 const uint32_t scissorCount;
773 VkRect2D scissors[vk::MAX_VIEWPORTS];
774 };
775
776 class CmdSetStencilOp : public vk::CommandBuffer::Command
777 {
778 public:
CmdSetStencilOp(VkStencilFaceFlags faceMask,VkStencilOp failOp,VkStencilOp passOp,VkStencilOp depthFailOp,VkCompareOp compareOp)779 CmdSetStencilOp(VkStencilFaceFlags faceMask, VkStencilOp failOp, VkStencilOp passOp, VkStencilOp depthFailOp, VkCompareOp compareOp)
780 : faceMask(faceMask)
781 , failOp(failOp)
782 , passOp(passOp)
783 , depthFailOp(depthFailOp)
784 , compareOp(compareOp)
785 {}
786
execute(vk::CommandBuffer::ExecutionState & executionState)787 void execute(vk::CommandBuffer::ExecutionState &executionState) override
788 {
789 executionState.dynamicState.faceMask |= faceMask;
790
791 if(faceMask & VK_STENCIL_FACE_FRONT_BIT)
792 {
793 executionState.dynamicState.frontStencil.failOp = failOp;
794 executionState.dynamicState.frontStencil.passOp = passOp;
795 executionState.dynamicState.frontStencil.depthFailOp = depthFailOp;
796 executionState.dynamicState.frontStencil.compareOp = compareOp;
797 }
798 if(faceMask & VK_STENCIL_FACE_BACK_BIT)
799 {
800 executionState.dynamicState.backStencil.failOp = failOp;
801 executionState.dynamicState.backStencil.passOp = passOp;
802 executionState.dynamicState.backStencil.depthFailOp = depthFailOp;
803 executionState.dynamicState.backStencil.compareOp = compareOp;
804 }
805 }
806
description()807 std::string description() override { return "vkCmdSetStencilOpEXT()"; }
808
809 private:
810 const VkStencilFaceFlags faceMask;
811 const VkStencilOp failOp;
812 const VkStencilOp passOp;
813 const VkStencilOp depthFailOp;
814 const VkCompareOp compareOp;
815 };
816
817 class CmdSetStencilTestEnable : public vk::CommandBuffer::Command
818 {
819 public:
CmdSetStencilTestEnable(VkBool32 stencilTestEnable)820 CmdSetStencilTestEnable(VkBool32 stencilTestEnable)
821 : stencilTestEnable(stencilTestEnable)
822 {}
823
execute(vk::CommandBuffer::ExecutionState & executionState)824 void execute(vk::CommandBuffer::ExecutionState &executionState) override
825 {
826 executionState.dynamicState.stencilTestEnable = stencilTestEnable;
827 }
828
description()829 std::string description() override { return "vkCmdSetStencilTestEnableEXT()"; }
830
831 private:
832 const VkBool32 stencilTestEnable;
833 };
834
835 class CmdSetViewportWithCount : public vk::CommandBuffer::Command
836 {
837 public:
CmdSetViewportWithCount(uint32_t viewportCount,const VkViewport * pViewports)838 CmdSetViewportWithCount(uint32_t viewportCount, const VkViewport *pViewports)
839 : viewportCount(viewportCount)
840 {
841 memcpy(&(viewports[0]), pViewports, viewportCount * sizeof(VkRect2D));
842 }
843
execute(vk::CommandBuffer::ExecutionState & executionState)844 void execute(vk::CommandBuffer::ExecutionState &executionState) override
845 {
846 executionState.dynamicState.viewportCount = viewportCount;
847 for(uint32_t i = 0; i < viewportCount; i++)
848 {
849 executionState.dynamicState.viewports[i] = viewports[i];
850 }
851 }
852
description()853 std::string description() override { return "vkCmdSetViewportWithCountEXT()"; }
854
855 private:
856 const uint32_t viewportCount;
857 VkRect2D viewports[vk::MAX_VIEWPORTS];
858 };
859
860 class CmdSetRasterizerDiscardEnable : public vk::CommandBuffer::Command
861 {
862 public:
CmdSetRasterizerDiscardEnable(VkBool32 rasterizerDiscardEnable)863 CmdSetRasterizerDiscardEnable(VkBool32 rasterizerDiscardEnable)
864 : rasterizerDiscardEnable(rasterizerDiscardEnable)
865 {}
866
execute(vk::CommandBuffer::ExecutionState & executionState)867 void execute(vk::CommandBuffer::ExecutionState &executionState) override
868 {
869 executionState.dynamicState.rasterizerDiscardEnable = rasterizerDiscardEnable;
870 }
871
description()872 std::string description() override { return "vkCmdSetRasterizerDiscardEnable()"; }
873
874 private:
875 const VkBool32 rasterizerDiscardEnable;
876 };
877
878 class CmdSetDepthBiasEnable : public vk::CommandBuffer::Command
879 {
880 public:
CmdSetDepthBiasEnable(VkBool32 depthBiasEnable)881 CmdSetDepthBiasEnable(VkBool32 depthBiasEnable)
882 : depthBiasEnable(depthBiasEnable)
883 {}
884
execute(vk::CommandBuffer::ExecutionState & executionState)885 void execute(vk::CommandBuffer::ExecutionState &executionState) override
886 {
887 executionState.dynamicState.depthBiasEnable = depthBiasEnable;
888 }
889
description()890 std::string description() override { return "vkCmdSetDepthBiasEnable()"; }
891
892 private:
893 const VkBool32 depthBiasEnable;
894 };
895
896 class CmdSetPrimitiveRestartEnable : public vk::CommandBuffer::Command
897 {
898 public:
CmdSetPrimitiveRestartEnable(VkBool32 primitiveRestartEnable)899 CmdSetPrimitiveRestartEnable(VkBool32 primitiveRestartEnable)
900 : primitiveRestartEnable(primitiveRestartEnable)
901 {}
902
execute(vk::CommandBuffer::ExecutionState & executionState)903 void execute(vk::CommandBuffer::ExecutionState &executionState) override
904 {
905 executionState.dynamicState.primitiveRestartEnable = primitiveRestartEnable;
906 }
907
description()908 std::string description() override { return "vkCmdSetPrimitiveRestartEnable()"; }
909
910 private:
911 const VkBool32 primitiveRestartEnable;
912 };
913
914 class CmdDrawBase : public vk::CommandBuffer::Command
915 {
916 public:
draw(vk::CommandBuffer::ExecutionState & executionState,bool indexed,uint32_t count,uint32_t instanceCount,uint32_t first,int32_t vertexOffset,uint32_t firstInstance)917 void draw(vk::CommandBuffer::ExecutionState &executionState, bool indexed,
918 uint32_t count, uint32_t instanceCount, uint32_t first, int32_t vertexOffset, uint32_t firstInstance)
919 {
920 const auto &pipelineState = executionState.pipelineState[VK_PIPELINE_BIND_POINT_GRAPHICS];
921
922 auto *pipeline = static_cast<vk::GraphicsPipeline *>(pipelineState.pipeline);
923 bool hasDynamicVertexStride = pipeline->hasDynamicVertexStride();
924
925 vk::Attachments &attachments = pipeline->getAttachments();
926 executionState.bindAttachments(&attachments);
927
928 vk::Inputs &inputs = pipeline->getInputs();
929 inputs.updateDescriptorSets(pipelineState.descriptorSetObjects,
930 pipelineState.descriptorSets,
931 pipelineState.descriptorDynamicOffsets);
932 inputs.setVertexInputBinding(executionState.vertexInputBindings);
933 inputs.bindVertexInputs(firstInstance, hasDynamicVertexStride);
934
935 if(indexed)
936 {
937 vk::IndexBuffer &indexBuffer = pipeline->getIndexBuffer();
938 indexBuffer.setIndexBufferBinding(executionState.indexBufferBinding, executionState.indexType);
939 }
940
941 std::vector<std::pair<uint32_t, void *>> indexBuffers;
942 pipeline->getIndexBuffers(executionState.dynamicState, count, first, indexed, &indexBuffers);
943
944 VkRect2D renderArea = executionState.getRenderArea();
945
946 for(uint32_t instance = firstInstance; instance != firstInstance + instanceCount; instance++)
947 {
948 // FIXME: reconsider instances/views nesting.
949 auto layerMask = executionState.getLayerMask();
950 while(layerMask)
951 {
952 int layer = sw::log2i(layerMask);
953 layerMask &= ~(1 << layer);
954
955 for(auto indexBuffer : indexBuffers)
956 {
957 executionState.renderer->draw(pipeline, executionState.dynamicState, indexBuffer.first, vertexOffset,
958 executionState.events, instance, layer, indexBuffer.second,
959 renderArea, executionState.pushConstants);
960 }
961 }
962
963 if(instanceCount > 1)
964 {
965 UNOPTIMIZED("Optimize instancing to use a single draw call."); // TODO(b/137740918)
966 inputs.advanceInstanceAttributes(hasDynamicVertexStride);
967 }
968 }
969 }
970 };
971
972 class CmdDraw : public CmdDrawBase
973 {
974 public:
CmdDraw(uint32_t vertexCount,uint32_t instanceCount,uint32_t firstVertex,uint32_t firstInstance)975 CmdDraw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance)
976 : vertexCount(vertexCount)
977 , instanceCount(instanceCount)
978 , firstVertex(firstVertex)
979 , firstInstance(firstInstance)
980 {
981 }
982
execute(vk::CommandBuffer::ExecutionState & executionState)983 void execute(vk::CommandBuffer::ExecutionState &executionState) override
984 {
985 draw(executionState, false, vertexCount, instanceCount, 0, firstVertex, firstInstance);
986 }
987
description()988 std::string description() override { return "vkCmdDraw()"; }
989
990 private:
991 const uint32_t vertexCount;
992 const uint32_t instanceCount;
993 const uint32_t firstVertex;
994 const uint32_t firstInstance;
995 };
996
997 class CmdDrawIndexed : public CmdDrawBase
998 {
999 public:
CmdDrawIndexed(uint32_t indexCount,uint32_t instanceCount,uint32_t firstIndex,int32_t vertexOffset,uint32_t firstInstance)1000 CmdDrawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance)
1001 : indexCount(indexCount)
1002 , instanceCount(instanceCount)
1003 , firstIndex(firstIndex)
1004 , vertexOffset(vertexOffset)
1005 , firstInstance(firstInstance)
1006 {
1007 }
1008
execute(vk::CommandBuffer::ExecutionState & executionState)1009 void execute(vk::CommandBuffer::ExecutionState &executionState) override
1010 {
1011 draw(executionState, true, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
1012 }
1013
description()1014 std::string description() override { return "vkCmdDrawIndexed()"; }
1015
1016 private:
1017 const uint32_t indexCount;
1018 const uint32_t instanceCount;
1019 const uint32_t firstIndex;
1020 const int32_t vertexOffset;
1021 const uint32_t firstInstance;
1022 };
1023
1024 class CmdDrawIndirect : public CmdDrawBase
1025 {
1026 public:
CmdDrawIndirect(vk::Buffer * buffer,VkDeviceSize offset,uint32_t drawCount,uint32_t stride)1027 CmdDrawIndirect(vk::Buffer *buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride)
1028 : buffer(buffer)
1029 , offset(offset)
1030 , drawCount(drawCount)
1031 , stride(stride)
1032 {
1033 }
1034
execute(vk::CommandBuffer::ExecutionState & executionState)1035 void execute(vk::CommandBuffer::ExecutionState &executionState) override
1036 {
1037 for(auto drawId = 0u; drawId < drawCount; drawId++)
1038 {
1039 const auto *cmd = reinterpret_cast<const VkDrawIndirectCommand *>(buffer->getOffsetPointer(offset + drawId * stride));
1040 draw(executionState, false, cmd->vertexCount, cmd->instanceCount, 0, cmd->firstVertex, cmd->firstInstance);
1041 }
1042 }
1043
description()1044 std::string description() override { return "vkCmdDrawIndirect()"; }
1045
1046 private:
1047 const vk::Buffer *const buffer;
1048 const VkDeviceSize offset;
1049 const uint32_t drawCount;
1050 const uint32_t stride;
1051 };
1052
1053 class CmdDrawIndexedIndirect : public CmdDrawBase
1054 {
1055 public:
CmdDrawIndexedIndirect(vk::Buffer * buffer,VkDeviceSize offset,uint32_t drawCount,uint32_t stride)1056 CmdDrawIndexedIndirect(vk::Buffer *buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride)
1057 : buffer(buffer)
1058 , offset(offset)
1059 , drawCount(drawCount)
1060 , stride(stride)
1061 {
1062 }
1063
execute(vk::CommandBuffer::ExecutionState & executionState)1064 void execute(vk::CommandBuffer::ExecutionState &executionState) override
1065 {
1066 for(auto drawId = 0u; drawId < drawCount; drawId++)
1067 {
1068 const auto *cmd = reinterpret_cast<const VkDrawIndexedIndirectCommand *>(buffer->getOffsetPointer(offset + drawId * stride));
1069 draw(executionState, true, cmd->indexCount, cmd->instanceCount, cmd->firstIndex, cmd->vertexOffset, cmd->firstInstance);
1070 }
1071 }
1072
description()1073 std::string description() override { return "vkCmdDrawIndexedIndirect()"; }
1074
1075 private:
1076 const vk::Buffer *const buffer;
1077 const VkDeviceSize offset;
1078 const uint32_t drawCount;
1079 const uint32_t stride;
1080 };
1081
1082 class CmdCopyImage : public vk::CommandBuffer::Command
1083 {
1084 public:
CmdCopyImage(const vk::Image * srcImage,vk::Image * dstImage,const VkImageCopy2 & region)1085 CmdCopyImage(const vk::Image *srcImage, vk::Image *dstImage, const VkImageCopy2 ®ion)
1086 : srcImage(srcImage)
1087 , dstImage(dstImage)
1088 , region(region)
1089 {
1090 }
1091
execute(vk::CommandBuffer::ExecutionState & executionState)1092 void execute(vk::CommandBuffer::ExecutionState &executionState) override
1093 {
1094 srcImage->copyTo(dstImage, region);
1095 }
1096
description()1097 std::string description() override { return "vkCmdCopyImage()"; }
1098
1099 private:
1100 const vk::Image *const srcImage;
1101 vk::Image *const dstImage;
1102 const VkImageCopy2 region;
1103 };
1104
1105 class CmdCopyBuffer : public vk::CommandBuffer::Command
1106 {
1107 public:
CmdCopyBuffer(const vk::Buffer * srcBuffer,vk::Buffer * dstBuffer,const VkBufferCopy2 & region)1108 CmdCopyBuffer(const vk::Buffer *srcBuffer, vk::Buffer *dstBuffer, const VkBufferCopy2 ®ion)
1109 : srcBuffer(srcBuffer)
1110 , dstBuffer(dstBuffer)
1111 , region(region)
1112 {
1113 }
1114
execute(vk::CommandBuffer::ExecutionState & executionState)1115 void execute(vk::CommandBuffer::ExecutionState &executionState) override
1116 {
1117 srcBuffer->copyTo(dstBuffer, region);
1118 }
1119
description()1120 std::string description() override { return "vkCmdCopyBuffer()"; }
1121
1122 private:
1123 const vk::Buffer *const srcBuffer;
1124 vk::Buffer *const dstBuffer;
1125 const VkBufferCopy2 region;
1126 };
1127
1128 class CmdCopyImageToBuffer : public vk::CommandBuffer::Command
1129 {
1130 public:
CmdCopyImageToBuffer(vk::Image * srcImage,vk::Buffer * dstBuffer,const VkBufferImageCopy2 & region)1131 CmdCopyImageToBuffer(vk::Image *srcImage, vk::Buffer *dstBuffer, const VkBufferImageCopy2 ®ion)
1132 : srcImage(srcImage)
1133 , dstBuffer(dstBuffer)
1134 , region(region)
1135 {
1136 }
1137
execute(vk::CommandBuffer::ExecutionState & executionState)1138 void execute(vk::CommandBuffer::ExecutionState &executionState) override
1139 {
1140 srcImage->copyTo(dstBuffer, region);
1141 }
1142
description()1143 std::string description() override { return "vkCmdCopyImageToBuffer()"; }
1144
1145 private:
1146 vk::Image *const srcImage;
1147 vk::Buffer *const dstBuffer;
1148 const VkBufferImageCopy2 region;
1149 };
1150
1151 class CmdCopyBufferToImage : public vk::CommandBuffer::Command
1152 {
1153 public:
CmdCopyBufferToImage(vk::Buffer * srcBuffer,vk::Image * dstImage,const VkBufferImageCopy2 & region)1154 CmdCopyBufferToImage(vk::Buffer *srcBuffer, vk::Image *dstImage, const VkBufferImageCopy2 ®ion)
1155 : srcBuffer(srcBuffer)
1156 , dstImage(dstImage)
1157 , region(region)
1158 {
1159 }
1160
execute(vk::CommandBuffer::ExecutionState & executionState)1161 void execute(vk::CommandBuffer::ExecutionState &executionState) override
1162 {
1163 dstImage->copyFrom(srcBuffer, region);
1164 }
1165
description()1166 std::string description() override { return "vkCmdCopyBufferToImage()"; }
1167
1168 private:
1169 vk::Buffer *const srcBuffer;
1170 vk::Image *const dstImage;
1171 const VkBufferImageCopy2 region;
1172 };
1173
1174 class CmdFillBuffer : public vk::CommandBuffer::Command
1175 {
1176 public:
CmdFillBuffer(vk::Buffer * dstBuffer,VkDeviceSize dstOffset,VkDeviceSize size,uint32_t data)1177 CmdFillBuffer(vk::Buffer *dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data)
1178 : dstBuffer(dstBuffer)
1179 , dstOffset(dstOffset)
1180 , size(size)
1181 , data(data)
1182 {
1183 }
1184
execute(vk::CommandBuffer::ExecutionState & executionState)1185 void execute(vk::CommandBuffer::ExecutionState &executionState) override
1186 {
1187 dstBuffer->fill(dstOffset, size, data);
1188 }
1189
description()1190 std::string description() override { return "vkCmdFillBuffer()"; }
1191
1192 private:
1193 vk::Buffer *const dstBuffer;
1194 const VkDeviceSize dstOffset;
1195 const VkDeviceSize size;
1196 const uint32_t data;
1197 };
1198
1199 class CmdUpdateBuffer : public vk::CommandBuffer::Command
1200 {
1201 public:
CmdUpdateBuffer(vk::Buffer * dstBuffer,VkDeviceSize dstOffset,VkDeviceSize dataSize,const uint8_t * pData)1202 CmdUpdateBuffer(vk::Buffer *dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const uint8_t *pData)
1203 : dstBuffer(dstBuffer)
1204 , dstOffset(dstOffset)
1205 , data(pData, &pData[dataSize])
1206 {
1207 }
1208
execute(vk::CommandBuffer::ExecutionState & executionState)1209 void execute(vk::CommandBuffer::ExecutionState &executionState) override
1210 {
1211 dstBuffer->update(dstOffset, data.size(), data.data());
1212 }
1213
description()1214 std::string description() override { return "vkCmdUpdateBuffer()"; }
1215
1216 private:
1217 vk::Buffer *const dstBuffer;
1218 const VkDeviceSize dstOffset;
1219 const std::vector<uint8_t> data; // FIXME(b/119409619): replace this vector by an allocator so we can control all memory allocations
1220 };
1221
1222 class CmdClearColorImage : public vk::CommandBuffer::Command
1223 {
1224 public:
CmdClearColorImage(vk::Image * image,const VkClearColorValue & color,const VkImageSubresourceRange & range)1225 CmdClearColorImage(vk::Image *image, const VkClearColorValue &color, const VkImageSubresourceRange &range)
1226 : image(image)
1227 , color(color)
1228 , range(range)
1229 {
1230 }
1231
execute(vk::CommandBuffer::ExecutionState & executionState)1232 void execute(vk::CommandBuffer::ExecutionState &executionState) override
1233 {
1234 image->clear(color, range);
1235 }
1236
description()1237 std::string description() override { return "vkCmdClearColorImage()"; }
1238
1239 private:
1240 vk::Image *const image;
1241 const VkClearColorValue color;
1242 const VkImageSubresourceRange range;
1243 };
1244
1245 class CmdClearDepthStencilImage : public vk::CommandBuffer::Command
1246 {
1247 public:
CmdClearDepthStencilImage(vk::Image * image,const VkClearDepthStencilValue & depthStencil,const VkImageSubresourceRange & range)1248 CmdClearDepthStencilImage(vk::Image *image, const VkClearDepthStencilValue &depthStencil, const VkImageSubresourceRange &range)
1249 : image(image)
1250 , depthStencil(depthStencil)
1251 , range(range)
1252 {
1253 }
1254
execute(vk::CommandBuffer::ExecutionState & executionState)1255 void execute(vk::CommandBuffer::ExecutionState &executionState) override
1256 {
1257 image->clear(depthStencil, range);
1258 }
1259
description()1260 std::string description() override { return "vkCmdClearDepthStencilImage()"; }
1261
1262 private:
1263 vk::Image *const image;
1264 const VkClearDepthStencilValue depthStencil;
1265 const VkImageSubresourceRange range;
1266 };
1267
1268 class CmdClearAttachment : public vk::CommandBuffer::Command
1269 {
1270 public:
CmdClearAttachment(const VkClearAttachment & attachment,const VkClearRect & rect)1271 CmdClearAttachment(const VkClearAttachment &attachment, const VkClearRect &rect)
1272 : attachment(attachment)
1273 , rect(rect)
1274 {
1275 }
1276
execute(vk::CommandBuffer::ExecutionState & executionState)1277 void execute(vk::CommandBuffer::ExecutionState &executionState) override
1278 {
1279 // attachment clears are drawing operations, and so have rasterization-order guarantees.
1280 // however, we don't do the clear through the rasterizer, so need to ensure prior drawing
1281 // has completed first.
1282 executionState.renderer->synchronize();
1283
1284 if(executionState.renderPassFramebuffer)
1285 {
1286 executionState.renderPassFramebuffer->clearAttachment(executionState.renderPass, executionState.subpassIndex, attachment, rect);
1287 }
1288 else if(executionState.dynamicRendering)
1289 {
1290 uint32_t viewMask = executionState.dynamicRendering->getViewMask();
1291
1292 if(attachment.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT)
1293 {
1294 ASSERT(attachment.colorAttachment < executionState.dynamicRendering->getColorAttachmentCount());
1295
1296 const VkRenderingAttachmentInfo *colorAttachment =
1297 executionState.dynamicRendering->getColorAttachment(attachment.colorAttachment);
1298
1299 if(colorAttachment)
1300 {
1301 vk::ImageView *imageView = vk::Cast(colorAttachment->imageView);
1302 if(imageView)
1303 {
1304 imageView->clear(attachment.clearValue, VK_IMAGE_ASPECT_COLOR_BIT, rect, viewMask);
1305 }
1306 }
1307 }
1308
1309 if(attachment.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT)
1310 {
1311 const VkRenderingAttachmentInfo &depthAttachment = executionState.dynamicRendering->getDepthAttachment();
1312
1313 vk::ImageView *imageView = vk::Cast(depthAttachment.imageView);
1314 if(imageView)
1315 {
1316 imageView->clear(attachment.clearValue, VK_IMAGE_ASPECT_DEPTH_BIT, rect, viewMask);
1317 }
1318 }
1319
1320 if(attachment.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT)
1321 {
1322 const VkRenderingAttachmentInfo &stencilAttachment = executionState.dynamicRendering->getStencilAttachment();
1323
1324 vk::ImageView *imageView = vk::Cast(stencilAttachment.imageView);
1325 if(imageView)
1326 {
1327 imageView->clear(attachment.clearValue, VK_IMAGE_ASPECT_STENCIL_BIT, rect, viewMask);
1328 }
1329 }
1330 }
1331 }
1332
description()1333 std::string description() override { return "vkCmdClearAttachment()"; }
1334
1335 private:
1336 const VkClearAttachment attachment;
1337 const VkClearRect rect;
1338 };
1339
1340 class CmdBlitImage : public vk::CommandBuffer::Command
1341 {
1342 public:
CmdBlitImage(const vk::Image * srcImage,vk::Image * dstImage,const VkImageBlit2 & region,VkFilter filter)1343 CmdBlitImage(const vk::Image *srcImage, vk::Image *dstImage, const VkImageBlit2 ®ion, VkFilter filter)
1344 : srcImage(srcImage)
1345 , dstImage(dstImage)
1346 , region(region)
1347 , filter(filter)
1348 {
1349 }
1350
execute(vk::CommandBuffer::ExecutionState & executionState)1351 void execute(vk::CommandBuffer::ExecutionState &executionState) override
1352 {
1353 srcImage->blitTo(dstImage, region, filter);
1354 }
1355
description()1356 std::string description() override { return "vkCmdBlitImage()"; }
1357
1358 private:
1359 const vk::Image *const srcImage;
1360 vk::Image *const dstImage;
1361 const VkImageBlit2 region;
1362 const VkFilter filter;
1363 };
1364
1365 class CmdResolveImage : public vk::CommandBuffer::Command
1366 {
1367 public:
CmdResolveImage(const vk::Image * srcImage,vk::Image * dstImage,const VkImageResolve2 & region)1368 CmdResolveImage(const vk::Image *srcImage, vk::Image *dstImage, const VkImageResolve2 ®ion)
1369 : srcImage(srcImage)
1370 , dstImage(dstImage)
1371 , region(region)
1372 {
1373 }
1374
execute(vk::CommandBuffer::ExecutionState & executionState)1375 void execute(vk::CommandBuffer::ExecutionState &executionState) override
1376 {
1377 srcImage->resolveTo(dstImage, region);
1378 }
1379
description()1380 std::string description() override { return "vkCmdBlitImage()"; }
1381
1382 private:
1383 const vk::Image *const srcImage;
1384 vk::Image *const dstImage;
1385 const VkImageResolve2 region;
1386 };
1387
1388 class CmdPipelineBarrier : public vk::CommandBuffer::Command
1389 {
1390 public:
execute(vk::CommandBuffer::ExecutionState & executionState)1391 void execute(vk::CommandBuffer::ExecutionState &executionState) override
1392 {
1393 // This is a very simple implementation that simply calls sw::Renderer::synchronize(),
1394 // since the driver is free to move the source stage towards the bottom of the pipe
1395 // and the target stage towards the top, so a full pipeline sync is spec compliant.
1396 executionState.renderer->synchronize();
1397
1398 // Right now all buffers are read-only in drawcalls but a similar mechanism will be required once we support SSBOs.
1399
1400 // Also note that this would be a good moment to update cube map borders or decompress compressed textures, if necessary.
1401 }
1402
description()1403 std::string description() override { return "vkCmdPipelineBarrier()"; }
1404 };
1405
1406 class CmdSignalEvent : public vk::CommandBuffer::Command
1407 {
1408 public:
CmdSignalEvent(vk::Event * ev)1409 CmdSignalEvent(vk::Event *ev)
1410 : ev(ev)
1411 {
1412 }
1413
execute(vk::CommandBuffer::ExecutionState & executionState)1414 void execute(vk::CommandBuffer::ExecutionState &executionState) override
1415 {
1416 executionState.renderer->synchronize();
1417 ev->signal();
1418 }
1419
description()1420 std::string description() override { return "vkCmdSignalEvent()"; }
1421
1422 private:
1423 vk::Event *const ev;
1424 };
1425
1426 class CmdResetEvent : public vk::CommandBuffer::Command
1427 {
1428 public:
CmdResetEvent(vk::Event * ev,VkPipelineStageFlags2 stageMask)1429 CmdResetEvent(vk::Event *ev, VkPipelineStageFlags2 stageMask)
1430 : ev(ev)
1431 , stageMask(stageMask)
1432 {
1433 }
1434
execute(vk::CommandBuffer::ExecutionState & executionState)1435 void execute(vk::CommandBuffer::ExecutionState &executionState) override
1436 {
1437 ev->reset();
1438 }
1439
description()1440 std::string description() override { return "vkCmdResetEvent()"; }
1441
1442 private:
1443 vk::Event *const ev;
1444 const VkPipelineStageFlags2 stageMask; // FIXME(b/117835459): We currently ignore the flags and reset the event at the last stage
1445 };
1446
1447 class CmdWaitEvent : public vk::CommandBuffer::Command
1448 {
1449 public:
CmdWaitEvent(vk::Event * ev)1450 CmdWaitEvent(vk::Event *ev)
1451 : ev(ev)
1452 {
1453 }
1454
execute(vk::CommandBuffer::ExecutionState & executionState)1455 void execute(vk::CommandBuffer::ExecutionState &executionState) override
1456 {
1457 executionState.renderer->synchronize();
1458 ev->wait();
1459 }
1460
description()1461 std::string description() override { return "vkCmdWaitEvent()"; }
1462
1463 private:
1464 vk::Event *const ev;
1465 };
1466
1467 class CmdBindDescriptorSets : public vk::CommandBuffer::Command
1468 {
1469 public:
CmdBindDescriptorSets(VkPipelineBindPoint pipelineBindPoint,uint32_t firstSet,uint32_t descriptorSetCount,const VkDescriptorSet * pDescriptorSets,uint32_t firstDynamicOffset,uint32_t dynamicOffsetCount,const uint32_t * pDynamicOffsets)1470 CmdBindDescriptorSets(VkPipelineBindPoint pipelineBindPoint,
1471 uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet *pDescriptorSets,
1472 uint32_t firstDynamicOffset, uint32_t dynamicOffsetCount, const uint32_t *pDynamicOffsets)
1473 : pipelineBindPoint(pipelineBindPoint)
1474 , firstSet(firstSet)
1475 , descriptorSetCount(descriptorSetCount)
1476 , firstDynamicOffset(firstDynamicOffset)
1477 , dynamicOffsetCount(dynamicOffsetCount)
1478 {
1479 for(uint32_t i = 0; i < descriptorSetCount; i++)
1480 {
1481 // We need both a descriptor set object for updates and a descriptor set data pointer for routines
1482 descriptorSetObjects[firstSet + i] = vk::Cast(pDescriptorSets[i]);
1483 descriptorSets[firstSet + i] = vk::Cast(pDescriptorSets[i])->getDataAddress();
1484 }
1485
1486 for(uint32_t i = 0; i < dynamicOffsetCount; i++)
1487 {
1488 dynamicOffsets[firstDynamicOffset + i] = pDynamicOffsets[i];
1489 }
1490 }
1491
execute(vk::CommandBuffer::ExecutionState & executionState)1492 void execute(vk::CommandBuffer::ExecutionState &executionState) override
1493 {
1494 ASSERT((size_t)pipelineBindPoint < executionState.pipelineState.size());
1495 ASSERT(firstSet + descriptorSetCount <= vk::MAX_BOUND_DESCRIPTOR_SETS);
1496 ASSERT(firstDynamicOffset + dynamicOffsetCount <= vk::MAX_DESCRIPTOR_SET_COMBINED_BUFFERS_DYNAMIC);
1497
1498 auto &pipelineState = executionState.pipelineState[pipelineBindPoint];
1499
1500 for(uint32_t i = firstSet; i < firstSet + descriptorSetCount; i++)
1501 {
1502 pipelineState.descriptorSetObjects[i] = descriptorSetObjects[i];
1503 pipelineState.descriptorSets[i] = descriptorSets[i];
1504 }
1505
1506 for(uint32_t i = firstDynamicOffset; i < firstDynamicOffset + dynamicOffsetCount; i++)
1507 {
1508 pipelineState.descriptorDynamicOffsets[i] = dynamicOffsets[i];
1509 }
1510 }
1511
description()1512 std::string description() override { return "vkCmdBindDescriptorSets()"; }
1513
1514 private:
1515 const VkPipelineBindPoint pipelineBindPoint;
1516 const uint32_t firstSet;
1517 const uint32_t descriptorSetCount;
1518 const uint32_t firstDynamicOffset;
1519 const uint32_t dynamicOffsetCount;
1520
1521 vk::DescriptorSet::Array descriptorSetObjects;
1522 vk::DescriptorSet::Bindings descriptorSets;
1523 vk::DescriptorSet::DynamicOffsets dynamicOffsets;
1524 };
1525
1526 class CmdSetPushConstants : public vk::CommandBuffer::Command
1527 {
1528 public:
CmdSetPushConstants(uint32_t offset,uint32_t size,const void * pValues)1529 CmdSetPushConstants(uint32_t offset, uint32_t size, const void *pValues)
1530 : offset(offset)
1531 , size(size)
1532 {
1533 ASSERT(offset < vk::MAX_PUSH_CONSTANT_SIZE);
1534 ASSERT(offset + size <= vk::MAX_PUSH_CONSTANT_SIZE);
1535
1536 memcpy(data, pValues, size);
1537 }
1538
execute(vk::CommandBuffer::ExecutionState & executionState)1539 void execute(vk::CommandBuffer::ExecutionState &executionState) override
1540 {
1541 memcpy(&executionState.pushConstants.data[offset], data, size);
1542 }
1543
description()1544 std::string description() override { return "vkCmdSetPushConstants()"; }
1545
1546 private:
1547 const uint32_t offset;
1548 const uint32_t size;
1549 unsigned char data[vk::MAX_PUSH_CONSTANT_SIZE];
1550 };
1551
1552 class CmdBeginQuery : public vk::CommandBuffer::Command
1553 {
1554 public:
CmdBeginQuery(vk::QueryPool * queryPool,uint32_t query,VkQueryControlFlags flags)1555 CmdBeginQuery(vk::QueryPool *queryPool, uint32_t query, VkQueryControlFlags flags)
1556 : queryPool(queryPool)
1557 , query(query)
1558 , flags(flags)
1559 {
1560 }
1561
execute(vk::CommandBuffer::ExecutionState & executionState)1562 void execute(vk::CommandBuffer::ExecutionState &executionState) override
1563 {
1564 // "If queries are used while executing a render pass instance that has multiview enabled, the query uses
1565 // N consecutive query indices in the query pool (starting at `query`)"
1566 for(uint32_t i = 0; i < executionState.viewCount(); i++)
1567 {
1568 queryPool->begin(query + i, flags);
1569 }
1570
1571 // The renderer accumulates the result into a single query.
1572 ASSERT(queryPool->getType() == VK_QUERY_TYPE_OCCLUSION);
1573 executionState.renderer->addQuery(queryPool->getQuery(query));
1574 }
1575
description()1576 std::string description() override { return "vkCmdBeginQuery()"; }
1577
1578 private:
1579 vk::QueryPool *const queryPool;
1580 const uint32_t query;
1581 const VkQueryControlFlags flags;
1582 };
1583
1584 class CmdEndQuery : public vk::CommandBuffer::Command
1585 {
1586 public:
CmdEndQuery(vk::QueryPool * queryPool,uint32_t query)1587 CmdEndQuery(vk::QueryPool *queryPool, uint32_t query)
1588 : queryPool(queryPool)
1589 , query(query)
1590 {
1591 }
1592
execute(vk::CommandBuffer::ExecutionState & executionState)1593 void execute(vk::CommandBuffer::ExecutionState &executionState) override
1594 {
1595 // The renderer accumulates the result into a single query.
1596 ASSERT(queryPool->getType() == VK_QUERY_TYPE_OCCLUSION);
1597 executionState.renderer->removeQuery(queryPool->getQuery(query));
1598
1599 // "implementations may write the total result to the first query and write zero to the other queries."
1600 for(uint32_t i = 1; i < executionState.viewCount(); i++)
1601 {
1602 queryPool->getQuery(query + i)->set(0);
1603 }
1604
1605 for(uint32_t i = 0; i < executionState.viewCount(); i++)
1606 {
1607 queryPool->end(query + i);
1608 }
1609 }
1610
description()1611 std::string description() override { return "vkCmdEndQuery()"; }
1612
1613 private:
1614 vk::QueryPool *const queryPool;
1615 const uint32_t query;
1616 };
1617
1618 class CmdResetQueryPool : public vk::CommandBuffer::Command
1619 {
1620 public:
CmdResetQueryPool(vk::QueryPool * queryPool,uint32_t firstQuery,uint32_t queryCount)1621 CmdResetQueryPool(vk::QueryPool *queryPool, uint32_t firstQuery, uint32_t queryCount)
1622 : queryPool(queryPool)
1623 , firstQuery(firstQuery)
1624 , queryCount(queryCount)
1625 {
1626 }
1627
execute(vk::CommandBuffer::ExecutionState & executionState)1628 void execute(vk::CommandBuffer::ExecutionState &executionState) override
1629 {
1630 queryPool->reset(firstQuery, queryCount);
1631 }
1632
description()1633 std::string description() override { return "vkCmdResetQueryPool()"; }
1634
1635 private:
1636 vk::QueryPool *const queryPool;
1637 const uint32_t firstQuery;
1638 const uint32_t queryCount;
1639 };
1640
1641 class CmdWriteTimeStamp : public vk::CommandBuffer::Command
1642 {
1643 public:
CmdWriteTimeStamp(vk::QueryPool * queryPool,uint32_t query,VkPipelineStageFlagBits2 stage)1644 CmdWriteTimeStamp(vk::QueryPool *queryPool, uint32_t query, VkPipelineStageFlagBits2 stage)
1645 : queryPool(queryPool)
1646 , query(query)
1647 , stage(stage)
1648 {
1649 }
1650
execute(vk::CommandBuffer::ExecutionState & executionState)1651 void execute(vk::CommandBuffer::ExecutionState &executionState) override
1652 {
1653 if(stage & ~(VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT | VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT))
1654 {
1655 // The `top of pipe` and `draw indirect` stages are handled in command buffer processing so a timestamp write
1656 // done in those stages can just be done here without any additional synchronization.
1657 // Everything else is deferred to the Renderer; we will treat those stages all as if they were
1658 // `bottom of pipe`.
1659 //
1660 // FIXME(chrisforbes): once Marl is integrated, do this in a task so we don't have to stall here.
1661 executionState.renderer->synchronize();
1662 }
1663
1664 // "the timestamp uses N consecutive query indices in the query pool (starting at `query`) where
1665 // N is the number of bits set in the view mask of the subpass the command is executed in."
1666 for(uint32_t i = 0; i < executionState.viewCount(); i++)
1667 {
1668 queryPool->writeTimestamp(query + i);
1669 }
1670 }
1671
description()1672 std::string description() override { return "vkCmdWriteTimeStamp()"; }
1673
1674 private:
1675 vk::QueryPool *const queryPool;
1676 const uint32_t query;
1677 const VkPipelineStageFlagBits2 stage;
1678 };
1679
1680 class CmdCopyQueryPoolResults : public vk::CommandBuffer::Command
1681 {
1682 public:
CmdCopyQueryPoolResults(const vk::QueryPool * queryPool,uint32_t firstQuery,uint32_t queryCount,vk::Buffer * dstBuffer,VkDeviceSize dstOffset,VkDeviceSize stride,VkQueryResultFlags flags)1683 CmdCopyQueryPoolResults(const vk::QueryPool *queryPool, uint32_t firstQuery, uint32_t queryCount,
1684 vk::Buffer *dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags)
1685 : queryPool(queryPool)
1686 , firstQuery(firstQuery)
1687 , queryCount(queryCount)
1688 , dstBuffer(dstBuffer)
1689 , dstOffset(dstOffset)
1690 , stride(stride)
1691 , flags(flags)
1692 {
1693 }
1694
execute(vk::CommandBuffer::ExecutionState & executionState)1695 void execute(vk::CommandBuffer::ExecutionState &executionState) override
1696 {
1697 queryPool->getResults(firstQuery, queryCount, dstBuffer->getSize() - dstOffset,
1698 dstBuffer->getOffsetPointer(dstOffset), stride, flags);
1699 }
1700
description()1701 std::string description() override { return "vkCmdCopyQueryPoolResults()"; }
1702
1703 private:
1704 const vk::QueryPool *const queryPool;
1705 const uint32_t firstQuery;
1706 const uint32_t queryCount;
1707 vk::Buffer *const dstBuffer;
1708 const VkDeviceSize dstOffset;
1709 const VkDeviceSize stride;
1710 const VkQueryResultFlags flags;
1711 };
1712
1713 } // anonymous namespace
1714
1715 namespace vk {
1716
DynamicRendering(const VkRenderingInfo * pRenderingInfo)1717 DynamicRendering::DynamicRendering(const VkRenderingInfo *pRenderingInfo)
1718 : renderArea(pRenderingInfo->renderArea)
1719 , layerCount(pRenderingInfo->layerCount)
1720 , viewMask(pRenderingInfo->viewMask)
1721 , colorAttachmentCount(pRenderingInfo->colorAttachmentCount)
1722 , flags(pRenderingInfo->flags)
1723 {
1724 if(colorAttachmentCount > 0)
1725 {
1726 for(uint32_t i = 0; i < colorAttachmentCount; ++i)
1727 {
1728 colorAttachments[i] = pRenderingInfo->pColorAttachments[i];
1729 }
1730 }
1731
1732 if(pRenderingInfo->pDepthAttachment)
1733 {
1734 depthAttachment = *pRenderingInfo->pDepthAttachment;
1735 }
1736
1737 if(pRenderingInfo->pStencilAttachment)
1738 {
1739 stencilAttachment = *pRenderingInfo->pStencilAttachment;
1740 }
1741 }
1742
getAttachments(Attachments * attachments) const1743 void DynamicRendering::getAttachments(Attachments *attachments) const
1744 {
1745 for(uint32_t i = 0; i < sw::MAX_COLOR_BUFFERS; ++i)
1746 {
1747 attachments->colorBuffer[i] =
1748 (i < colorAttachmentCount) ? vk::Cast(colorAttachments[i].imageView) : nullptr;
1749 }
1750 attachments->depthBuffer = vk::Cast(depthAttachment.imageView);
1751 attachments->stencilBuffer = vk::Cast(stencilAttachment.imageView);
1752 }
1753
CommandBuffer(Device * device,VkCommandBufferLevel pLevel)1754 CommandBuffer::CommandBuffer(Device *device, VkCommandBufferLevel pLevel)
1755 : device(device)
1756 , level(pLevel)
1757 {
1758 }
1759
destroy(const VkAllocationCallbacks * pAllocator)1760 void CommandBuffer::destroy(const VkAllocationCallbacks *pAllocator)
1761 {
1762 }
1763
resetState()1764 void CommandBuffer::resetState()
1765 {
1766 // FIXME (b/119409619): replace this vector by an allocator so we can control all memory allocations
1767 commands.clear();
1768
1769 state = INITIAL;
1770 }
1771
begin(VkCommandBufferUsageFlags flags,const VkCommandBufferInheritanceInfo * pInheritanceInfo)1772 VkResult CommandBuffer::begin(VkCommandBufferUsageFlags flags, const VkCommandBufferInheritanceInfo *pInheritanceInfo)
1773 {
1774 ASSERT((state != RECORDING) && (state != PENDING));
1775
1776 // Nothing interesting to do based on flags. We don't have any optimizations
1777 // to apply for ONE_TIME_SUBMIT or (lack of) SIMULTANEOUS_USE. RENDER_PASS_CONTINUE
1778 // must also provide a non-null pInheritanceInfo, which we don't implement yet, but is caught below.
1779 (void)flags;
1780
1781 // pInheritanceInfo merely contains optimization hints, so we currently ignore it
1782
1783 // "pInheritanceInfo is a pointer to a VkCommandBufferInheritanceInfo structure, used if commandBuffer is a
1784 // secondary command buffer. If this is a primary command buffer, then this value is ignored."
1785 if(level == VK_COMMAND_BUFFER_LEVEL_SECONDARY)
1786 {
1787 if(pInheritanceInfo->queryFlags != 0)
1788 {
1789 // "If the inherited queries feature is not enabled, queryFlags must be 0"
1790 UNSUPPORTED("VkPhysicalDeviceFeatures::inheritedQueries");
1791 }
1792 }
1793
1794 if(state != INITIAL)
1795 {
1796 // Implicit reset
1797 resetState();
1798 }
1799
1800 state = RECORDING;
1801
1802 return VK_SUCCESS;
1803 }
1804
end()1805 VkResult CommandBuffer::end()
1806 {
1807 ASSERT(state == RECORDING);
1808
1809 state = EXECUTABLE;
1810
1811 return VK_SUCCESS;
1812 }
1813
reset(VkCommandPoolResetFlags flags)1814 VkResult CommandBuffer::reset(VkCommandPoolResetFlags flags)
1815 {
1816 ASSERT(state != PENDING);
1817
1818 resetState();
1819
1820 return VK_SUCCESS;
1821 }
1822
1823 template<typename T, typename... Args>
addCommand(Args &&...args)1824 void CommandBuffer::addCommand(Args &&...args)
1825 {
1826 // FIXME (b/119409619): use an allocator here so we can control all memory allocations
1827 commands.push_back(std::make_unique<T>(std::forward<Args>(args)...));
1828 }
1829
beginRenderPass(RenderPass * renderPass,Framebuffer * framebuffer,VkRect2D renderArea,uint32_t clearValueCount,const VkClearValue * clearValues,VkSubpassContents contents,const VkRenderPassAttachmentBeginInfo * attachmentInfo)1830 void CommandBuffer::beginRenderPass(RenderPass *renderPass, Framebuffer *framebuffer, VkRect2D renderArea,
1831 uint32_t clearValueCount, const VkClearValue *clearValues, VkSubpassContents contents,
1832 const VkRenderPassAttachmentBeginInfo *attachmentInfo)
1833 {
1834 ASSERT(state == RECORDING);
1835
1836 addCommand<::CmdBeginRenderPass>(renderPass, framebuffer, renderArea, clearValueCount, clearValues, attachmentInfo);
1837 }
1838
nextSubpass(VkSubpassContents contents)1839 void CommandBuffer::nextSubpass(VkSubpassContents contents)
1840 {
1841 ASSERT(state == RECORDING);
1842
1843 addCommand<::CmdNextSubpass>();
1844 }
1845
endRenderPass()1846 void CommandBuffer::endRenderPass()
1847 {
1848 addCommand<::CmdEndRenderPass>();
1849 }
1850
executeCommands(uint32_t commandBufferCount,const VkCommandBuffer * pCommandBuffers)1851 void CommandBuffer::executeCommands(uint32_t commandBufferCount, const VkCommandBuffer *pCommandBuffers)
1852 {
1853 ASSERT(state == RECORDING);
1854
1855 for(uint32_t i = 0; i < commandBufferCount; ++i)
1856 {
1857 addCommand<::CmdExecuteCommands>(vk::Cast(pCommandBuffers[i]));
1858 }
1859 }
1860
beginRendering(const VkRenderingInfo * pRenderingInfo)1861 void CommandBuffer::beginRendering(const VkRenderingInfo *pRenderingInfo)
1862 {
1863 ASSERT(state == RECORDING);
1864
1865 addCommand<::CmdBeginRendering>(pRenderingInfo);
1866 }
1867
endRendering()1868 void CommandBuffer::endRendering()
1869 {
1870 ASSERT(state == RECORDING);
1871
1872 addCommand<::CmdEndRendering>();
1873 }
1874
setDeviceMask(uint32_t deviceMask)1875 void CommandBuffer::setDeviceMask(uint32_t deviceMask)
1876 {
1877 // SwiftShader only has one device, so we ignore the device mask
1878 }
1879
dispatchBase(uint32_t baseGroupX,uint32_t baseGroupY,uint32_t baseGroupZ,uint32_t groupCountX,uint32_t groupCountY,uint32_t groupCountZ)1880 void CommandBuffer::dispatchBase(uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ,
1881 uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ)
1882 {
1883 addCommand<::CmdDispatch>(baseGroupX, baseGroupY, baseGroupZ, groupCountX, groupCountY, groupCountZ);
1884 }
1885
pipelineBarrier(const VkDependencyInfo & pDependencyInfo)1886 void CommandBuffer::pipelineBarrier(const VkDependencyInfo &pDependencyInfo)
1887 {
1888 addCommand<::CmdPipelineBarrier>();
1889 }
1890
bindPipeline(VkPipelineBindPoint pipelineBindPoint,Pipeline * pipeline)1891 void CommandBuffer::bindPipeline(VkPipelineBindPoint pipelineBindPoint, Pipeline *pipeline)
1892 {
1893 switch(pipelineBindPoint)
1894 {
1895 case VK_PIPELINE_BIND_POINT_COMPUTE:
1896 case VK_PIPELINE_BIND_POINT_GRAPHICS:
1897 addCommand<::CmdPipelineBind>(pipelineBindPoint, pipeline);
1898 break;
1899 default:
1900 UNSUPPORTED("VkPipelineBindPoint %d", int(pipelineBindPoint));
1901 }
1902 }
1903
bindVertexBuffers(uint32_t firstBinding,uint32_t bindingCount,const VkBuffer * pBuffers,const VkDeviceSize * pOffsets,const VkDeviceSize * pSizes,const VkDeviceSize * pStrides)1904 void CommandBuffer::bindVertexBuffers(uint32_t firstBinding, uint32_t bindingCount,
1905 const VkBuffer *pBuffers, const VkDeviceSize *pOffsets,
1906 const VkDeviceSize *pSizes, const VkDeviceSize *pStrides)
1907 {
1908 for(uint32_t i = 0; i < bindingCount; ++i)
1909 {
1910 addCommand<::CmdVertexBufferBind>(i + firstBinding, vk::Cast(pBuffers[i]), pOffsets[i],
1911 pSizes ? pSizes[i] : 0,
1912 pStrides ? pStrides[i] : 0);
1913 }
1914 }
1915
beginQuery(QueryPool * queryPool,uint32_t query,VkQueryControlFlags flags)1916 void CommandBuffer::beginQuery(QueryPool *queryPool, uint32_t query, VkQueryControlFlags flags)
1917 {
1918 addCommand<::CmdBeginQuery>(queryPool, query, flags);
1919 }
1920
endQuery(QueryPool * queryPool,uint32_t query)1921 void CommandBuffer::endQuery(QueryPool *queryPool, uint32_t query)
1922 {
1923 addCommand<::CmdEndQuery>(queryPool, query);
1924 }
1925
resetQueryPool(QueryPool * queryPool,uint32_t firstQuery,uint32_t queryCount)1926 void CommandBuffer::resetQueryPool(QueryPool *queryPool, uint32_t firstQuery, uint32_t queryCount)
1927 {
1928 addCommand<::CmdResetQueryPool>(queryPool, firstQuery, queryCount);
1929 }
1930
writeTimestamp(VkPipelineStageFlags2 pipelineStage,QueryPool * queryPool,uint32_t query)1931 void CommandBuffer::writeTimestamp(VkPipelineStageFlags2 pipelineStage, QueryPool *queryPool, uint32_t query)
1932 {
1933 addCommand<::CmdWriteTimeStamp>(queryPool, query, pipelineStage);
1934 }
1935
copyQueryPoolResults(const QueryPool * queryPool,uint32_t firstQuery,uint32_t queryCount,Buffer * dstBuffer,VkDeviceSize dstOffset,VkDeviceSize stride,VkQueryResultFlags flags)1936 void CommandBuffer::copyQueryPoolResults(const QueryPool *queryPool, uint32_t firstQuery, uint32_t queryCount,
1937 Buffer *dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags)
1938 {
1939 addCommand<::CmdCopyQueryPoolResults>(queryPool, firstQuery, queryCount, dstBuffer, dstOffset, stride, flags);
1940 }
1941
pushConstants(PipelineLayout * layout,VkShaderStageFlags stageFlags,uint32_t offset,uint32_t size,const void * pValues)1942 void CommandBuffer::pushConstants(PipelineLayout *layout, VkShaderStageFlags stageFlags,
1943 uint32_t offset, uint32_t size, const void *pValues)
1944 {
1945 addCommand<::CmdSetPushConstants>(offset, size, pValues);
1946 }
1947
setViewport(uint32_t firstViewport,uint32_t viewportCount,const VkViewport * pViewports)1948 void CommandBuffer::setViewport(uint32_t firstViewport, uint32_t viewportCount, const VkViewport *pViewports)
1949 {
1950 if(firstViewport != 0 || viewportCount > 1)
1951 {
1952 UNSUPPORTED("VkPhysicalDeviceFeatures::multiViewport");
1953 }
1954
1955 for(uint32_t i = 0; i < viewportCount; i++)
1956 {
1957 addCommand<::CmdSetViewport>(pViewports[i], i + firstViewport);
1958 }
1959 }
1960
setScissor(uint32_t firstScissor,uint32_t scissorCount,const VkRect2D * pScissors)1961 void CommandBuffer::setScissor(uint32_t firstScissor, uint32_t scissorCount, const VkRect2D *pScissors)
1962 {
1963 if(firstScissor != 0 || scissorCount > 1)
1964 {
1965 UNSUPPORTED("VkPhysicalDeviceFeatures::multiViewport");
1966 }
1967
1968 for(uint32_t i = 0; i < scissorCount; i++)
1969 {
1970 addCommand<::CmdSetScissor>(pScissors[i], i + firstScissor);
1971 }
1972 }
1973
setLineWidth(float lineWidth)1974 void CommandBuffer::setLineWidth(float lineWidth)
1975 {
1976 addCommand<::CmdSetLineWidth>(lineWidth);
1977 }
1978
setDepthBias(float depthBiasConstantFactor,float depthBiasClamp,float depthBiasSlopeFactor)1979 void CommandBuffer::setDepthBias(float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor)
1980 {
1981 addCommand<::CmdSetDepthBias>(depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor);
1982 }
1983
setBlendConstants(const float blendConstants[4])1984 void CommandBuffer::setBlendConstants(const float blendConstants[4])
1985 {
1986 addCommand<::CmdSetBlendConstants>(blendConstants);
1987 }
1988
setDepthBounds(float minDepthBounds,float maxDepthBounds)1989 void CommandBuffer::setDepthBounds(float minDepthBounds, float maxDepthBounds)
1990 {
1991 addCommand<::CmdSetDepthBounds>(minDepthBounds, maxDepthBounds);
1992 }
1993
setStencilCompareMask(VkStencilFaceFlags faceMask,uint32_t compareMask)1994 void CommandBuffer::setStencilCompareMask(VkStencilFaceFlags faceMask, uint32_t compareMask)
1995 {
1996 // faceMask must not be 0
1997 ASSERT(faceMask != 0);
1998
1999 addCommand<::CmdSetStencilCompareMask>(faceMask, compareMask);
2000 }
2001
setStencilWriteMask(VkStencilFaceFlags faceMask,uint32_t writeMask)2002 void CommandBuffer::setStencilWriteMask(VkStencilFaceFlags faceMask, uint32_t writeMask)
2003 {
2004 // faceMask must not be 0
2005 ASSERT(faceMask != 0);
2006
2007 addCommand<::CmdSetStencilWriteMask>(faceMask, writeMask);
2008 }
2009
setStencilReference(VkStencilFaceFlags faceMask,uint32_t reference)2010 void CommandBuffer::setStencilReference(VkStencilFaceFlags faceMask, uint32_t reference)
2011 {
2012 // faceMask must not be 0
2013 ASSERT(faceMask != 0);
2014
2015 addCommand<::CmdSetStencilReference>(faceMask, reference);
2016 }
2017
setCullMode(VkCullModeFlags cullMode)2018 void CommandBuffer::setCullMode(VkCullModeFlags cullMode)
2019 {
2020 addCommand<::CmdSetCullMode>(cullMode);
2021 }
2022
setDepthBoundsTestEnable(VkBool32 depthBoundsTestEnable)2023 void CommandBuffer::setDepthBoundsTestEnable(VkBool32 depthBoundsTestEnable)
2024 {
2025 addCommand<::CmdSetDepthBoundsTestEnable>(depthBoundsTestEnable);
2026 }
2027
setDepthCompareOp(VkCompareOp depthCompareOp)2028 void CommandBuffer::setDepthCompareOp(VkCompareOp depthCompareOp)
2029 {
2030 addCommand<::CmdSetDepthCompareOp>(depthCompareOp);
2031 }
2032
setDepthTestEnable(VkBool32 depthTestEnable)2033 void CommandBuffer::setDepthTestEnable(VkBool32 depthTestEnable)
2034 {
2035 addCommand<::CmdSetDepthTestEnable>(depthTestEnable);
2036 }
2037
setDepthWriteEnable(VkBool32 depthWriteEnable)2038 void CommandBuffer::setDepthWriteEnable(VkBool32 depthWriteEnable)
2039 {
2040 addCommand<::CmdSetDepthWriteEnable>(depthWriteEnable);
2041 }
2042
setFrontFace(VkFrontFace frontFace)2043 void CommandBuffer::setFrontFace(VkFrontFace frontFace)
2044 {
2045 addCommand<::CmdSetFrontFace>(frontFace);
2046 }
2047
setPrimitiveTopology(VkPrimitiveTopology primitiveTopology)2048 void CommandBuffer::setPrimitiveTopology(VkPrimitiveTopology primitiveTopology)
2049 {
2050 addCommand<::CmdSetPrimitiveTopology>(primitiveTopology);
2051 }
2052
setScissorWithCount(uint32_t scissorCount,const VkRect2D * pScissors)2053 void CommandBuffer::setScissorWithCount(uint32_t scissorCount, const VkRect2D *pScissors)
2054 {
2055 addCommand<::CmdSetScissorWithCount>(scissorCount, pScissors);
2056 }
2057
setStencilOp(VkStencilFaceFlags faceMask,VkStencilOp failOp,VkStencilOp passOp,VkStencilOp depthFailOp,VkCompareOp compareOp)2058 void CommandBuffer::setStencilOp(VkStencilFaceFlags faceMask, VkStencilOp failOp, VkStencilOp passOp, VkStencilOp depthFailOp, VkCompareOp compareOp)
2059 {
2060 addCommand<::CmdSetStencilOp>(faceMask, failOp, passOp, depthFailOp, compareOp);
2061 }
2062
setStencilTestEnable(VkBool32 stencilTestEnable)2063 void CommandBuffer::setStencilTestEnable(VkBool32 stencilTestEnable)
2064 {
2065 addCommand<::CmdSetStencilTestEnable>(stencilTestEnable);
2066 }
2067
setViewportWithCount(uint32_t viewportCount,const VkViewport * pViewports)2068 void CommandBuffer::setViewportWithCount(uint32_t viewportCount, const VkViewport *pViewports)
2069 {
2070 addCommand<::CmdSetViewportWithCount>(viewportCount, pViewports);
2071 }
2072
setRasterizerDiscardEnable(VkBool32 rasterizerDiscardEnable)2073 void CommandBuffer::setRasterizerDiscardEnable(VkBool32 rasterizerDiscardEnable)
2074 {
2075 addCommand<::CmdSetRasterizerDiscardEnable>(rasterizerDiscardEnable);
2076 }
2077
setDepthBiasEnable(VkBool32 depthBiasEnable)2078 void CommandBuffer::setDepthBiasEnable(VkBool32 depthBiasEnable)
2079 {
2080 addCommand<::CmdSetDepthBiasEnable>(depthBiasEnable);
2081 }
2082
setPrimitiveRestartEnable(VkBool32 primitiveRestartEnable)2083 void CommandBuffer::setPrimitiveRestartEnable(VkBool32 primitiveRestartEnable)
2084 {
2085 addCommand<::CmdSetPrimitiveRestartEnable>(primitiveRestartEnable);
2086 }
2087
bindDescriptorSets(VkPipelineBindPoint pipelineBindPoint,const PipelineLayout * pipelineLayout,uint32_t firstSet,uint32_t descriptorSetCount,const VkDescriptorSet * pDescriptorSets,uint32_t dynamicOffsetCount,const uint32_t * pDynamicOffsets)2088 void CommandBuffer::bindDescriptorSets(VkPipelineBindPoint pipelineBindPoint, const PipelineLayout *pipelineLayout,
2089 uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet *pDescriptorSets,
2090 uint32_t dynamicOffsetCount, const uint32_t *pDynamicOffsets)
2091 {
2092 ASSERT(state == RECORDING);
2093
2094 auto firstDynamicOffset = (dynamicOffsetCount != 0) ? pipelineLayout->getDynamicOffsetIndex(firstSet, 0) : 0;
2095
2096 addCommand<::CmdBindDescriptorSets>(
2097 pipelineBindPoint, firstSet, descriptorSetCount, pDescriptorSets,
2098 firstDynamicOffset, dynamicOffsetCount, pDynamicOffsets);
2099 }
2100
bindIndexBuffer(Buffer * buffer,VkDeviceSize offset,VkIndexType indexType)2101 void CommandBuffer::bindIndexBuffer(Buffer *buffer, VkDeviceSize offset, VkIndexType indexType)
2102 {
2103 addCommand<::CmdIndexBufferBind>(buffer, offset, indexType);
2104 }
2105
dispatch(uint32_t groupCountX,uint32_t groupCountY,uint32_t groupCountZ)2106 void CommandBuffer::dispatch(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ)
2107 {
2108 addCommand<::CmdDispatch>(0, 0, 0, groupCountX, groupCountY, groupCountZ);
2109 }
2110
dispatchIndirect(Buffer * buffer,VkDeviceSize offset)2111 void CommandBuffer::dispatchIndirect(Buffer *buffer, VkDeviceSize offset)
2112 {
2113 addCommand<::CmdDispatchIndirect>(buffer, offset);
2114 }
2115
copyBuffer(const VkCopyBufferInfo2 & copyBufferInfo)2116 void CommandBuffer::copyBuffer(const VkCopyBufferInfo2 ©BufferInfo)
2117 {
2118 ASSERT(state == RECORDING);
2119
2120 for(uint32_t i = 0; i < copyBufferInfo.regionCount; i++)
2121 {
2122 addCommand<::CmdCopyBuffer>(
2123 vk::Cast(copyBufferInfo.srcBuffer),
2124 vk::Cast(copyBufferInfo.dstBuffer),
2125 copyBufferInfo.pRegions[i]);
2126 }
2127 }
2128
copyImage(const VkCopyImageInfo2 & copyImageInfo)2129 void CommandBuffer::copyImage(const VkCopyImageInfo2 ©ImageInfo)
2130 {
2131 ASSERT(state == RECORDING);
2132 ASSERT(copyImageInfo.srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL ||
2133 copyImageInfo.srcImageLayout == VK_IMAGE_LAYOUT_GENERAL);
2134 ASSERT(copyImageInfo.dstImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ||
2135 copyImageInfo.dstImageLayout == VK_IMAGE_LAYOUT_GENERAL);
2136
2137 for(uint32_t i = 0; i < copyImageInfo.regionCount; i++)
2138 {
2139 addCommand<::CmdCopyImage>(
2140 vk::Cast(copyImageInfo.srcImage),
2141 vk::Cast(copyImageInfo.dstImage),
2142 copyImageInfo.pRegions[i]);
2143 }
2144 }
2145
blitImage(const VkBlitImageInfo2 & blitImageInfo)2146 void CommandBuffer::blitImage(const VkBlitImageInfo2 &blitImageInfo)
2147 {
2148 ASSERT(state == RECORDING);
2149 ASSERT(blitImageInfo.srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL ||
2150 blitImageInfo.srcImageLayout == VK_IMAGE_LAYOUT_GENERAL);
2151 ASSERT(blitImageInfo.dstImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ||
2152 blitImageInfo.dstImageLayout == VK_IMAGE_LAYOUT_GENERAL);
2153
2154 for(uint32_t i = 0; i < blitImageInfo.regionCount; i++)
2155 {
2156 addCommand<::CmdBlitImage>(
2157 vk::Cast(blitImageInfo.srcImage),
2158 vk::Cast(blitImageInfo.dstImage),
2159 blitImageInfo.pRegions[i],
2160 blitImageInfo.filter);
2161 }
2162 }
2163
copyBufferToImage(const VkCopyBufferToImageInfo2 & copyBufferToImageInfo)2164 void CommandBuffer::copyBufferToImage(const VkCopyBufferToImageInfo2 ©BufferToImageInfo)
2165 {
2166 ASSERT(state == RECORDING);
2167
2168 for(uint32_t i = 0; i < copyBufferToImageInfo.regionCount; i++)
2169 {
2170 addCommand<::CmdCopyBufferToImage>(
2171 vk::Cast(copyBufferToImageInfo.srcBuffer),
2172 vk::Cast(copyBufferToImageInfo.dstImage),
2173 copyBufferToImageInfo.pRegions[i]);
2174 }
2175 }
2176
copyImageToBuffer(const VkCopyImageToBufferInfo2 & copyImageToBufferInfo)2177 void CommandBuffer::copyImageToBuffer(const VkCopyImageToBufferInfo2 ©ImageToBufferInfo)
2178 {
2179 ASSERT(state == RECORDING);
2180 ASSERT(copyImageToBufferInfo.srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL ||
2181 copyImageToBufferInfo.srcImageLayout == VK_IMAGE_LAYOUT_GENERAL);
2182
2183 for(uint32_t i = 0; i < copyImageToBufferInfo.regionCount; i++)
2184 {
2185 addCommand<::CmdCopyImageToBuffer>(
2186 vk::Cast(copyImageToBufferInfo.srcImage),
2187 vk::Cast(copyImageToBufferInfo.dstBuffer),
2188 copyImageToBufferInfo.pRegions[i]);
2189 }
2190 }
2191
updateBuffer(Buffer * dstBuffer,VkDeviceSize dstOffset,VkDeviceSize dataSize,const void * pData)2192 void CommandBuffer::updateBuffer(Buffer *dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const void *pData)
2193 {
2194 ASSERT(state == RECORDING);
2195
2196 addCommand<::CmdUpdateBuffer>(dstBuffer, dstOffset, dataSize, reinterpret_cast<const uint8_t *>(pData));
2197 }
2198
fillBuffer(Buffer * dstBuffer,VkDeviceSize dstOffset,VkDeviceSize size,uint32_t data)2199 void CommandBuffer::fillBuffer(Buffer *dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data)
2200 {
2201 ASSERT(state == RECORDING);
2202
2203 addCommand<::CmdFillBuffer>(dstBuffer, dstOffset, size, data);
2204 }
2205
clearColorImage(Image * image,VkImageLayout imageLayout,const VkClearColorValue * pColor,uint32_t rangeCount,const VkImageSubresourceRange * pRanges)2206 void CommandBuffer::clearColorImage(Image *image, VkImageLayout imageLayout, const VkClearColorValue *pColor,
2207 uint32_t rangeCount, const VkImageSubresourceRange *pRanges)
2208 {
2209 ASSERT(state == RECORDING);
2210
2211 for(uint32_t i = 0; i < rangeCount; i++)
2212 {
2213 addCommand<::CmdClearColorImage>(image, *pColor, pRanges[i]);
2214 }
2215 }
2216
clearDepthStencilImage(Image * image,VkImageLayout imageLayout,const VkClearDepthStencilValue * pDepthStencil,uint32_t rangeCount,const VkImageSubresourceRange * pRanges)2217 void CommandBuffer::clearDepthStencilImage(Image *image, VkImageLayout imageLayout, const VkClearDepthStencilValue *pDepthStencil,
2218 uint32_t rangeCount, const VkImageSubresourceRange *pRanges)
2219 {
2220 ASSERT(state == RECORDING);
2221
2222 for(uint32_t i = 0; i < rangeCount; i++)
2223 {
2224 addCommand<::CmdClearDepthStencilImage>(image, *pDepthStencil, pRanges[i]);
2225 }
2226 }
2227
clearAttachments(uint32_t attachmentCount,const VkClearAttachment * pAttachments,uint32_t rectCount,const VkClearRect * pRects)2228 void CommandBuffer::clearAttachments(uint32_t attachmentCount, const VkClearAttachment *pAttachments,
2229 uint32_t rectCount, const VkClearRect *pRects)
2230 {
2231 ASSERT(state == RECORDING);
2232
2233 for(uint32_t i = 0; i < attachmentCount; i++)
2234 {
2235 for(uint32_t j = 0; j < rectCount; j++)
2236 {
2237 addCommand<::CmdClearAttachment>(pAttachments[i], pRects[j]);
2238 }
2239 }
2240 }
2241
resolveImage(const VkResolveImageInfo2 & resolveImageInfo)2242 void CommandBuffer::resolveImage(const VkResolveImageInfo2 &resolveImageInfo)
2243 {
2244 ASSERT(state == RECORDING);
2245 ASSERT(resolveImageInfo.srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL ||
2246 resolveImageInfo.srcImageLayout == VK_IMAGE_LAYOUT_GENERAL);
2247 ASSERT(resolveImageInfo.dstImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ||
2248 resolveImageInfo.dstImageLayout == VK_IMAGE_LAYOUT_GENERAL);
2249
2250 for(uint32_t i = 0; i < resolveImageInfo.regionCount; i++)
2251 {
2252 addCommand<::CmdResolveImage>(
2253 vk::Cast(resolveImageInfo.srcImage),
2254 vk::Cast(resolveImageInfo.dstImage),
2255 resolveImageInfo.pRegions[i]);
2256 }
2257 }
2258
setEvent(Event * event,const VkDependencyInfo & pDependencyInfo)2259 void CommandBuffer::setEvent(Event *event, const VkDependencyInfo &pDependencyInfo)
2260 {
2261 ASSERT(state == RECORDING);
2262
2263 // TODO(b/117835459): We currently ignore the flags and signal the event at the last stage
2264
2265 addCommand<::CmdSignalEvent>(event);
2266 }
2267
resetEvent(Event * event,VkPipelineStageFlags2 stageMask)2268 void CommandBuffer::resetEvent(Event *event, VkPipelineStageFlags2 stageMask)
2269 {
2270 ASSERT(state == RECORDING);
2271
2272 addCommand<::CmdResetEvent>(event, stageMask);
2273 }
2274
waitEvents(uint32_t eventCount,const VkEvent * pEvents,const VkDependencyInfo & pDependencyInfo)2275 void CommandBuffer::waitEvents(uint32_t eventCount, const VkEvent *pEvents, const VkDependencyInfo &pDependencyInfo)
2276 {
2277 ASSERT(state == RECORDING);
2278
2279 // TODO(b/117835459): Since we always do a full barrier, all memory barrier related arguments are ignored
2280
2281 // Note: srcStageMask and dstStageMask are currently ignored
2282 for(uint32_t i = 0; i < eventCount; i++)
2283 {
2284 addCommand<::CmdWaitEvent>(vk::Cast(pEvents[i]));
2285 }
2286 }
2287
draw(uint32_t vertexCount,uint32_t instanceCount,uint32_t firstVertex,uint32_t firstInstance)2288 void CommandBuffer::draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance)
2289 {
2290 addCommand<::CmdDraw>(vertexCount, instanceCount, firstVertex, firstInstance);
2291 }
2292
drawIndexed(uint32_t indexCount,uint32_t instanceCount,uint32_t firstIndex,int32_t vertexOffset,uint32_t firstInstance)2293 void CommandBuffer::drawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance)
2294 {
2295 addCommand<::CmdDrawIndexed>(indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
2296 }
2297
drawIndirect(Buffer * buffer,VkDeviceSize offset,uint32_t drawCount,uint32_t stride)2298 void CommandBuffer::drawIndirect(Buffer *buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride)
2299 {
2300 addCommand<::CmdDrawIndirect>(buffer, offset, drawCount, stride);
2301 }
2302
drawIndexedIndirect(Buffer * buffer,VkDeviceSize offset,uint32_t drawCount,uint32_t stride)2303 void CommandBuffer::drawIndexedIndirect(Buffer *buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride)
2304 {
2305 addCommand<::CmdDrawIndexedIndirect>(buffer, offset, drawCount, stride);
2306 }
2307
beginDebugUtilsLabel(const VkDebugUtilsLabelEXT * pLabelInfo)2308 void CommandBuffer::beginDebugUtilsLabel(const VkDebugUtilsLabelEXT *pLabelInfo)
2309 {
2310 // Optional debug label region
2311 }
2312
endDebugUtilsLabel()2313 void CommandBuffer::endDebugUtilsLabel()
2314 {
2315 // Close debug label region opened with beginDebugUtilsLabel()
2316 }
2317
insertDebugUtilsLabel(const VkDebugUtilsLabelEXT * pLabelInfo)2318 void CommandBuffer::insertDebugUtilsLabel(const VkDebugUtilsLabelEXT *pLabelInfo)
2319 {
2320 // Optional single debug label
2321 }
2322
submit(CommandBuffer::ExecutionState & executionState)2323 void CommandBuffer::submit(CommandBuffer::ExecutionState &executionState)
2324 {
2325 // Perform recorded work
2326 state = PENDING;
2327
2328 for(auto &command : commands)
2329 {
2330 command->execute(executionState);
2331 }
2332
2333 // After work is completed
2334 state = EXECUTABLE;
2335 }
2336
submitSecondary(CommandBuffer::ExecutionState & executionState) const2337 void CommandBuffer::submitSecondary(CommandBuffer::ExecutionState &executionState) const
2338 {
2339 for(auto &command : commands)
2340 {
2341 command->execute(executionState);
2342 }
2343 }
2344
bindAttachments(Attachments * attachments)2345 void CommandBuffer::ExecutionState::bindAttachments(Attachments *attachments)
2346 {
2347 // Binds all the attachments for the current subpass
2348 // Ideally this would be performed by BeginRenderPass and NextSubpass, but
2349 // there is too much stomping of the renderer's state by setContext() in
2350 // draws.
2351
2352 if(renderPass)
2353 {
2354 const auto &subpass = renderPass->getSubpass(subpassIndex);
2355
2356 for(auto i = 0u; i < subpass.colorAttachmentCount; i++)
2357 {
2358 auto attachmentReference = subpass.pColorAttachments[i];
2359 if(attachmentReference.attachment != VK_ATTACHMENT_UNUSED)
2360 {
2361 attachments->colorBuffer[i] = renderPassFramebuffer->getAttachment(attachmentReference.attachment);
2362 }
2363 }
2364
2365 auto attachmentReference = subpass.pDepthStencilAttachment;
2366 if(attachmentReference && attachmentReference->attachment != VK_ATTACHMENT_UNUSED)
2367 {
2368 auto *attachment = renderPassFramebuffer->getAttachment(attachmentReference->attachment);
2369 if(attachment->hasDepthAspect())
2370 {
2371 attachments->depthBuffer = attachment;
2372 }
2373 if(attachment->hasStencilAspect())
2374 {
2375 attachments->stencilBuffer = attachment;
2376 }
2377 }
2378 }
2379 else if(dynamicRendering)
2380 {
2381 dynamicRendering->getAttachments(attachments);
2382 }
2383 }
2384
getRenderArea() const2385 VkRect2D CommandBuffer::ExecutionState::getRenderArea() const
2386 {
2387 VkRect2D renderArea = {};
2388
2389 if(renderPassFramebuffer)
2390 {
2391 renderArea.extent = renderPassFramebuffer->getExtent();
2392 }
2393 else if(dynamicRendering)
2394 {
2395 renderArea = dynamicRendering->getRenderArea();
2396 }
2397
2398 return renderArea;
2399 }
2400
2401 // The layer mask is the same as the view mask when multiview is enabled,
2402 // or 1 if multiview is disabled.
getLayerMask() const2403 uint32_t CommandBuffer::ExecutionState::getLayerMask() const
2404 {
2405 uint32_t layerMask = 1;
2406
2407 if(renderPass)
2408 {
2409 layerMask = renderPass->getViewMask(subpassIndex);
2410 }
2411 else if(dynamicRendering)
2412 {
2413 layerMask = dynamicRendering->getViewMask();
2414 }
2415
2416 return sw::max(layerMask, 1u);
2417 }
2418
2419 // Returns the number of bits set in the view mask, or 1 if multiview is disabled.
viewCount() const2420 uint32_t CommandBuffer::ExecutionState::viewCount() const
2421 {
2422 return static_cast<uint32_t>(std::bitset<32>(getLayerMask()).count());
2423 }
2424
2425 } // namespace vk
2426