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