OSDN Git Service

Allow subpasses to use secondary command buffers
[android-x86/external-swiftshader.git] / src / Vulkan / VkCommandBuffer.cpp
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 "VkFramebuffer.hpp"
19 #include "VkImage.hpp"
20 #include "VkImageView.hpp"
21 #include "VkPipeline.hpp"
22 #include "VkPipelineLayout.hpp"
23 #include "VkRenderPass.hpp"
24 #include "Device/Renderer.hpp"
25
26 #include <cstring>
27
28 namespace vk
29 {
30
31 class CommandBuffer::Command
32 {
33 public:
34         // FIXME (b/119421344): change the commandBuffer argument to a CommandBuffer state
35         virtual void play(CommandBuffer::ExecutionState& executionState) = 0;
36         virtual ~Command() {}
37 };
38
39 class BeginRenderPass : public CommandBuffer::Command
40 {
41 public:
42         BeginRenderPass(VkRenderPass renderPass, VkFramebuffer framebuffer, VkRect2D renderArea,
43                         uint32_t clearValueCount, const VkClearValue* pClearValues) :
44                 renderPass(Cast(renderPass)), framebuffer(Cast(framebuffer)), renderArea(renderArea),
45                 clearValueCount(clearValueCount)
46         {
47                 // FIXME (b/119409619): use an allocator here so we can control all memory allocations
48                 clearValues = new VkClearValue[clearValueCount];
49                 memcpy(clearValues, pClearValues, clearValueCount * sizeof(VkClearValue));
50         }
51
52         ~BeginRenderPass() override
53         {
54                 delete [] clearValues;
55         }
56
57 protected:
58         void play(CommandBuffer::ExecutionState& executionState) override
59         {
60                 executionState.renderPass = renderPass;
61                 executionState.renderPassFramebuffer = framebuffer;
62                 renderPass->begin();
63                 framebuffer->clear(executionState.renderPass, clearValueCount, clearValues, renderArea);
64         }
65
66 private:
67         RenderPass* renderPass;
68         Framebuffer* framebuffer;
69         VkRect2D renderArea;
70         uint32_t clearValueCount;
71         VkClearValue* clearValues;
72 };
73
74 class NextSubpass : public CommandBuffer::Command
75 {
76 public:
77         NextSubpass()
78         {
79         }
80
81 protected:
82         void play(CommandBuffer::ExecutionState& executionState) override
83         {
84                 bool hasResolveAttachments = (executionState.renderPass->getCurrentSubpass().pResolveAttachments != nullptr);
85                 if(hasResolveAttachments)
86                 {
87                         // FIXME(sugoi): remove the following lines and resolve in Renderer::finishRendering()
88                         //               for a Draw command or after the last command of the current subpass
89                         //               which modifies pixels.
90                         executionState.renderer->synchronize();
91                         executionState.renderPassFramebuffer->resolve(executionState.renderPass);
92                 }
93
94                 executionState.renderPass->nextSubpass();
95         }
96
97 private:
98 };
99
100 class EndRenderPass : public CommandBuffer::Command
101 {
102 public:
103         EndRenderPass()
104         {
105         }
106
107 protected:
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);
118
119                 executionState.renderPass->end();
120                 executionState.renderPass = nullptr;
121                 executionState.renderPassFramebuffer = nullptr;
122         }
123
124 private:
125 };
126
127 class ExecuteCommands : public CommandBuffer::Command
128 {
129 public:
130         ExecuteCommands(const VkCommandBuffer& commandBuffer) : commandBuffer(commandBuffer)
131         {
132         }
133
134 protected:
135         void play(CommandBuffer::ExecutionState& executionState) override
136         {
137                 Cast(commandBuffer)->submitSecondary(executionState);
138         }
139
140 private:
141         const VkCommandBuffer commandBuffer;
142 };
143
144 class PipelineBind : public CommandBuffer::Command
145 {
146 public:
147         PipelineBind(VkPipelineBindPoint pPipelineBindPoint, VkPipeline pPipeline) :
148                 pipelineBindPoint(pPipelineBindPoint), pipeline(pPipeline)
149         {
150         }
151
152 protected:
153         void play(CommandBuffer::ExecutionState& executionState) override
154         {
155                 executionState.pipelines[pipelineBindPoint] = Cast(pipeline);
156         }
157
158 private:
159         VkPipelineBindPoint pipelineBindPoint;
160         VkPipeline pipeline;
161 };
162
163 class Dispatch : public CommandBuffer::Command
164 {
165 public:
166         Dispatch(uint32_t pGroupCountX, uint32_t pGroupCountY, uint32_t pGroupCountZ) :
167                         groupCountX(pGroupCountX), groupCountY(pGroupCountY), groupCountZ(pGroupCountZ)
168         {
169         }
170
171 protected:
172         void play(CommandBuffer::ExecutionState& executionState) override
173         {
174                 ComputePipeline* pipeline = static_cast<ComputePipeline*>(
175                         executionState.pipelines[VK_PIPELINE_BIND_POINT_COMPUTE]);
176                 pipeline->run(groupCountX, groupCountY, groupCountZ,
177                         MAX_BOUND_DESCRIPTOR_SETS,
178                         executionState.boundDescriptorSets[VK_PIPELINE_BIND_POINT_COMPUTE],
179                         executionState.pushConstants);
180         }
181
182 private:
183         uint32_t groupCountX;
184         uint32_t groupCountY;
185         uint32_t groupCountZ;
186 };
187
188 struct VertexBufferBind : public CommandBuffer::Command
189 {
190         VertexBufferBind(uint32_t pBinding, const VkBuffer pBuffer, const VkDeviceSize pOffset) :
191                 binding(pBinding), buffer(pBuffer), offset(pOffset)
192         {
193         }
194
195         void play(CommandBuffer::ExecutionState& executionState) override
196         {
197                 executionState.vertexInputBindings[binding] = { buffer, offset };
198         }
199
200         uint32_t binding;
201         const VkBuffer buffer;
202         const VkDeviceSize offset;
203 };
204
205 struct IndexBufferBind : public CommandBuffer::Command
206 {
207         IndexBufferBind(const VkBuffer buffer, const VkDeviceSize offset, const VkIndexType indexType) :
208                 buffer(buffer), offset(offset), indexType(indexType)
209         {
210
211         }
212
213         void play(CommandBuffer::ExecutionState& executionState) override
214         {
215                 executionState.indexBufferBinding = {buffer, offset};
216                 executionState.indexType = indexType;
217         }
218
219         const VkBuffer buffer;
220         const VkDeviceSize offset;
221         const VkIndexType indexType;
222 };
223
224 void CommandBuffer::ExecutionState::bindVertexInputs(sw::Context& context, int firstVertex, int firstInstance)
225 {
226         for(uint32_t i = 0; i < MAX_VERTEX_INPUT_BINDINGS; i++)
227         {
228                 auto &attrib = context.input[i];
229                 if (attrib.count)
230                 {
231                         const auto &vertexInput = vertexInputBindings[attrib.binding];
232                         Buffer *buffer = Cast(vertexInput.buffer);
233                         attrib.buffer = buffer ? buffer->getOffsetPointer(
234                                         attrib.offset + vertexInput.offset + attrib.vertexStride * firstVertex + attrib.instanceStride * firstInstance) : nullptr;
235                 }
236         }
237 }
238
239 void CommandBuffer::ExecutionState::bindAttachments()
240 {
241         // Binds all the attachments for the current subpass
242         // Ideally this would be performed by BeginRenderPass and NextSubpass, but
243         // there is too much stomping of the renderer's state by setContext() in
244         // draws.
245
246         for (auto i = 0u; i < renderPass->getCurrentSubpass().colorAttachmentCount; i++)
247         {
248                 auto attachmentReference = renderPass->getCurrentSubpass().pColorAttachments[i];
249                 if (attachmentReference.attachment != VK_ATTACHMENT_UNUSED)
250                 {
251                         auto attachment = renderPassFramebuffer->getAttachment(attachmentReference.attachment);
252                         renderer->setRenderTarget(i, attachment, 0);
253                 }
254         }
255
256         auto attachmentReference = renderPass->getCurrentSubpass().pDepthStencilAttachment;
257         if (attachmentReference && attachmentReference->attachment != VK_ATTACHMENT_UNUSED)
258         {
259                 auto attachment = renderPassFramebuffer->getAttachment(attachmentReference->attachment);
260                 if (attachment->hasDepthAspect())
261                 {
262                         renderer->setDepthBuffer(attachment, 0);
263                 }
264                 if (attachment->hasStencilAspect())
265                 {
266                         renderer->setStencilBuffer(attachment, 0);
267                 }
268         }
269 }
270
271 struct Draw : public CommandBuffer::Command
272 {
273         Draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance)
274                 : vertexCount(vertexCount), instanceCount(instanceCount), firstVertex(firstVertex), firstInstance(firstInstance)
275         {
276         }
277
278         void play(CommandBuffer::ExecutionState& executionState) override
279         {
280                 GraphicsPipeline* pipeline = static_cast<GraphicsPipeline*>(
281                         executionState.pipelines[VK_PIPELINE_BIND_POINT_GRAPHICS]);
282
283                 sw::Context context = pipeline->getContext();
284                 executionState.bindVertexInputs(context, firstVertex, firstInstance);
285
286                 const auto& boundDescriptorSets = executionState.boundDescriptorSets[VK_PIPELINE_BIND_POINT_GRAPHICS];
287                 for(int i = 0; i < vk::MAX_BOUND_DESCRIPTOR_SETS; i++)
288                 {
289                         context.descriptorSets[i] = reinterpret_cast<vk::DescriptorSet*>(boundDescriptorSets[i]);
290                 }
291
292                 context.pushConstants = executionState.pushConstants;
293
294                 executionState.renderer->setContext(context);
295                 executionState.renderer->setScissor(pipeline->getScissor());
296                 executionState.renderer->setViewport(pipeline->getViewport());
297                 executionState.renderer->setBlendConstant(pipeline->getBlendConstants());
298
299                 executionState.bindAttachments();
300
301                 const uint32_t primitiveCount = pipeline->computePrimitiveCount(vertexCount);
302                 for(uint32_t instance = firstInstance; instance != firstInstance + instanceCount; instance++)
303                 {
304                         executionState.renderer->setInstanceID(instance);
305                         executionState.renderer->draw(context.drawType, primitiveCount);
306                         executionState.renderer->advanceInstanceAttributes();
307                 }
308         }
309
310         uint32_t vertexCount;
311         uint32_t instanceCount;
312         uint32_t firstVertex;
313         uint32_t firstInstance;
314 };
315
316 struct DrawIndexed : public CommandBuffer::Command
317 {
318         DrawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance)
319                         : indexCount(indexCount), instanceCount(instanceCount), firstIndex(firstIndex), vertexOffset(vertexOffset), firstInstance(firstInstance)
320         {
321         }
322
323         void play(CommandBuffer::ExecutionState& executionState) override
324         {
325                 GraphicsPipeline* pipeline = static_cast<GraphicsPipeline*>(
326                                 executionState.pipelines[VK_PIPELINE_BIND_POINT_GRAPHICS]);
327
328                 sw::Context context = pipeline->getContext();
329
330                 executionState.bindVertexInputs(context, vertexOffset, firstInstance);
331
332                 const auto& boundDescriptorSets = executionState.boundDescriptorSets[VK_PIPELINE_BIND_POINT_GRAPHICS];
333                 for(int i = 0; i < vk::MAX_BOUND_DESCRIPTOR_SETS; i++)
334                 {
335                         context.descriptorSets[i] = reinterpret_cast<vk::DescriptorSet*>(boundDescriptorSets[i]);
336                 }
337
338                 context.pushConstants = executionState.pushConstants;
339
340                 context.indexBuffer = Cast(executionState.indexBufferBinding.buffer)->getOffsetPointer(
341                                 executionState.indexBufferBinding.offset + firstIndex * (executionState.indexType == VK_INDEX_TYPE_UINT16 ? 2 : 4));
342
343                 executionState.renderer->setContext(context);
344                 executionState.renderer->setScissor(pipeline->getScissor());
345                 executionState.renderer->setViewport(pipeline->getViewport());
346                 executionState.renderer->setBlendConstant(pipeline->getBlendConstants());
347
348                 executionState.bindAttachments();
349
350                 auto drawType = executionState.indexType == VK_INDEX_TYPE_UINT16
351                                 ? (context.drawType | sw::DRAW_INDEXED16) : (context.drawType | sw::DRAW_INDEXED32);
352
353                 const uint32_t primitiveCount = pipeline->computePrimitiveCount(indexCount);
354                 for(uint32_t instance = firstInstance; instance != firstInstance + instanceCount; instance++)
355                 {
356                         executionState.renderer->setInstanceID(instance);
357                         executionState.renderer->draw(static_cast<sw::DrawType>(drawType), primitiveCount);
358                         executionState.renderer->advanceInstanceAttributes();
359                 }
360         }
361
362         uint32_t indexCount;
363         uint32_t instanceCount;
364         uint32_t firstIndex;
365         int32_t vertexOffset;
366         uint32_t firstInstance;
367 };
368
369 struct ImageToImageCopy : public CommandBuffer::Command
370 {
371         ImageToImageCopy(VkImage pSrcImage, VkImage pDstImage, const VkImageCopy& pRegion) :
372                 srcImage(pSrcImage), dstImage(pDstImage), region(pRegion)
373         {
374         }
375
376         void play(CommandBuffer::ExecutionState& executionState) override
377         {
378                 Cast(srcImage)->copyTo(dstImage, region);
379         }
380
381 private:
382         VkImage srcImage;
383         VkImage dstImage;
384         const VkImageCopy region;
385 };
386
387 struct BufferToBufferCopy : public CommandBuffer::Command
388 {
389         BufferToBufferCopy(VkBuffer pSrcBuffer, VkBuffer pDstBuffer, const VkBufferCopy& pRegion) :
390                 srcBuffer(pSrcBuffer), dstBuffer(pDstBuffer), region(pRegion)
391         {
392         }
393
394         void play(CommandBuffer::ExecutionState& executionState) override
395         {
396                 Cast(srcBuffer)->copyTo(Cast(dstBuffer), region);
397         }
398
399 private:
400         VkBuffer srcBuffer;
401         VkBuffer dstBuffer;
402         const VkBufferCopy region;
403 };
404
405 struct ImageToBufferCopy : public CommandBuffer::Command
406 {
407         ImageToBufferCopy(VkImage pSrcImage, VkBuffer pDstBuffer, const VkBufferImageCopy& pRegion) :
408                 srcImage(pSrcImage), dstBuffer(pDstBuffer), region(pRegion)
409         {
410         }
411
412         void play(CommandBuffer::ExecutionState& executionState) override
413         {
414                 Cast(srcImage)->copyTo(dstBuffer, region);
415         }
416
417 private:
418         VkImage srcImage;
419         VkBuffer dstBuffer;
420         const VkBufferImageCopy region;
421 };
422
423 struct BufferToImageCopy : public CommandBuffer::Command
424 {
425         BufferToImageCopy(VkBuffer pSrcBuffer, VkImage pDstImage, const VkBufferImageCopy& pRegion) :
426                 srcBuffer(pSrcBuffer), dstImage(pDstImage), region(pRegion)
427         {
428         }
429
430         void play(CommandBuffer::ExecutionState& executionState) override
431         {
432                 Cast(dstImage)->copyFrom(srcBuffer, region);
433         }
434
435 private:
436         VkBuffer srcBuffer;
437         VkImage dstImage;
438         const VkBufferImageCopy region;
439 };
440
441 struct FillBuffer : public CommandBuffer::Command
442 {
443         FillBuffer(VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data) :
444                 dstBuffer(dstBuffer), dstOffset(dstOffset), size(size), data(data)
445         {
446         }
447
448         void play(CommandBuffer::ExecutionState& executionState) override
449         {
450                 Cast(dstBuffer)->fill(dstOffset, size, data);
451         }
452
453 private:
454         VkBuffer dstBuffer;
455         VkDeviceSize dstOffset;
456         VkDeviceSize size;
457         uint32_t data;
458 };
459
460 struct UpdateBuffer : public CommandBuffer::Command
461 {
462         UpdateBuffer(VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const void* pData) :
463                 dstBuffer(dstBuffer), dstOffset(dstOffset), dataSize(dataSize), pData(pData)
464         {
465         }
466
467         void play(CommandBuffer::ExecutionState& executionState) override
468         {
469                 Cast(dstBuffer)->update(dstOffset, dataSize, pData);
470         }
471
472 private:
473         VkBuffer dstBuffer;
474         VkDeviceSize dstOffset;
475         VkDeviceSize dataSize;
476         const void* pData;
477 };
478
479 struct ClearColorImage : public CommandBuffer::Command
480 {
481         ClearColorImage(VkImage image, const VkClearColorValue& color, const VkImageSubresourceRange& range) :
482                 image(image), color(color), range(range)
483         {
484         }
485
486         void play(CommandBuffer::ExecutionState& executionState) override
487         {
488                 Cast(image)->clear(color, range);
489         }
490
491 private:
492         VkImage image;
493         const VkClearColorValue color;
494         const VkImageSubresourceRange range;
495 };
496
497 struct ClearDepthStencilImage : public CommandBuffer::Command
498 {
499         ClearDepthStencilImage(VkImage image, const VkClearDepthStencilValue& depthStencil, const VkImageSubresourceRange& range) :
500                 image(image), depthStencil(depthStencil), range(range)
501         {
502         }
503
504         void play(CommandBuffer::ExecutionState& executionState) override
505         {
506                 Cast(image)->clear(depthStencil, range);
507         }
508
509 private:
510         VkImage image;
511         const VkClearDepthStencilValue depthStencil;
512         const VkImageSubresourceRange range;
513 };
514
515 struct ClearAttachment : public CommandBuffer::Command
516 {
517         ClearAttachment(const VkClearAttachment& attachment, const VkClearRect& rect) :
518                 attachment(attachment), rect(rect)
519         {
520         }
521
522         void play(CommandBuffer::ExecutionState& executionState) override
523         {
524                 executionState.renderPassFramebuffer->clear(executionState.renderPass, attachment, rect);
525         }
526
527 private:
528         const VkClearAttachment attachment;
529         const VkClearRect rect;
530 };
531
532 struct BlitImage : public CommandBuffer::Command
533 {
534         BlitImage(VkImage srcImage, VkImage dstImage, const VkImageBlit& region, VkFilter filter) :
535                 srcImage(srcImage), dstImage(dstImage), region(region), filter(filter)
536         {
537         }
538
539         void play(CommandBuffer::ExecutionState& executionState) override
540         {
541                 Cast(srcImage)->blit(dstImage, region, filter);
542         }
543
544 private:
545         VkImage srcImage;
546         VkImage dstImage;
547         VkImageBlit region;
548         VkFilter filter;
549 };
550
551 struct PipelineBarrier : public CommandBuffer::Command
552 {
553         PipelineBarrier()
554         {
555         }
556
557         void play(CommandBuffer::ExecutionState& executionState) override
558         {
559                 // This is a very simple implementation that simply calls sw::Renderer::synchronize(),
560                 // since the driver is free to move the source stage towards the bottom of the pipe
561                 // and the target stage towards the top, so a full pipeline sync is spec compliant.
562                 executionState.renderer->synchronize();
563
564                 // Right now all buffers are read-only in drawcalls but a similar mechanism will be required once we support SSBOs.
565
566                 // Also note that this would be a good moment to update cube map borders or decompress compressed textures, if necessary.
567         }
568
569 private:
570 };
571
572 struct SignalEvent : public CommandBuffer::Command
573 {
574         SignalEvent(VkEvent ev, VkPipelineStageFlags stageMask) : ev(ev), stageMask(stageMask)
575         {
576         }
577
578         void play(CommandBuffer::ExecutionState& executionState) override
579         {
580                 if(Cast(ev)->signal())
581                 {
582                         // Was waiting for signal on this event, sync now
583                         executionState.renderer->synchronize();
584                 }
585         }
586
587 private:
588         VkEvent ev;
589         VkPipelineStageFlags stageMask; // FIXME(b/117835459) : We currently ignore the flags and signal the event at the last stage
590 };
591
592 struct ResetEvent : public CommandBuffer::Command
593 {
594         ResetEvent(VkEvent ev, VkPipelineStageFlags stageMask) : ev(ev), stageMask(stageMask)
595         {
596         }
597
598         void play(CommandBuffer::ExecutionState& executionState) override
599         {
600                 Cast(ev)->reset();
601         }
602
603 private:
604         VkEvent ev;
605         VkPipelineStageFlags stageMask; // FIXME(b/117835459) : We currently ignore the flags and reset the event at the last stage
606 };
607
608 struct WaitEvent : public CommandBuffer::Command
609 {
610         WaitEvent(VkEvent ev) : ev(ev)
611         {
612         }
613
614         void play(CommandBuffer::ExecutionState& executionState) override
615         {
616                 if(!Cast(ev)->wait())
617                 {
618                         // Already signaled, sync now
619                         executionState.renderer->synchronize();
620                 }
621         }
622
623 private:
624         VkEvent ev;
625 };
626
627 struct BindDescriptorSet : public CommandBuffer::Command
628 {
629         BindDescriptorSet(VkPipelineBindPoint pipelineBindPoint, uint32_t set, const VkDescriptorSet& descriptorSet)
630                 : pipelineBindPoint(pipelineBindPoint), set(set), descriptorSet(descriptorSet)
631         {
632         }
633
634         void play(CommandBuffer::ExecutionState& executionState)
635         {
636                 ASSERT((pipelineBindPoint < VK_PIPELINE_BIND_POINT_RANGE_SIZE) && (set < MAX_BOUND_DESCRIPTOR_SETS));
637                 executionState.boundDescriptorSets[pipelineBindPoint][set] = descriptorSet;
638         }
639
640 private:
641         VkPipelineBindPoint pipelineBindPoint;
642         uint32_t set;
643         const VkDescriptorSet descriptorSet;
644 };
645
646 struct SetPushConstants : public CommandBuffer::Command
647 {
648         SetPushConstants(uint32_t offset, uint32_t size, void const *pValues)
649                 : offset(offset), size(size)
650         {
651                 ASSERT(offset < MAX_PUSH_CONSTANT_SIZE);
652                 ASSERT(offset + size <= MAX_PUSH_CONSTANT_SIZE);
653
654                 memcpy(data, pValues, size);
655         }
656
657         void play(CommandBuffer::ExecutionState& executionState)
658         {
659                 memcpy(&executionState.pushConstants.data[offset], data, size);
660         }
661
662 private:
663         uint32_t offset;
664         uint32_t size;
665         unsigned char data[MAX_PUSH_CONSTANT_SIZE];
666 };
667
668 CommandBuffer::CommandBuffer(VkCommandBufferLevel pLevel) : level(pLevel)
669 {
670         // FIXME (b/119409619): replace this vector by an allocator so we can control all memory allocations
671         commands = new std::vector<std::unique_ptr<Command> >();
672 }
673
674 void CommandBuffer::destroy(const VkAllocationCallbacks* pAllocator)
675 {
676         delete commands;
677 }
678
679 void CommandBuffer::resetState()
680 {
681         // FIXME (b/119409619): replace this vector by an allocator so we can control all memory allocations
682         commands->clear();
683
684         state = INITIAL;
685 }
686
687 VkResult CommandBuffer::begin(VkCommandBufferUsageFlags flags, const VkCommandBufferInheritanceInfo* pInheritanceInfo)
688 {
689         ASSERT((state != RECORDING) && (state != PENDING));
690
691         // Nothing interesting to do based on flags. We don't have any optimizations
692         // to apply for ONE_TIME_SUBMIT or (lack of) SIMULTANEOUS_USE. RENDER_PASS_CONTINUE
693         // must also provide a non-null pInheritanceInfo, which we don't implement yet, but is caught below.
694         (void) flags;
695
696         // pInheritanceInfo merely contains optimization hints, so we currently ignore it
697
698         if(state != INITIAL)
699         {
700                 // Implicit reset
701                 resetState();
702         }
703
704         state = RECORDING;
705
706         return VK_SUCCESS;
707 }
708
709 VkResult CommandBuffer::end()
710 {
711         ASSERT(state == RECORDING);
712
713         state = EXECUTABLE;
714
715         return VK_SUCCESS;
716 }
717
718 VkResult CommandBuffer::reset(VkCommandPoolResetFlags flags)
719 {
720         ASSERT(state != PENDING);
721
722         resetState();
723
724         return VK_SUCCESS;
725 }
726
727 template<typename T, typename... Args>
728 void CommandBuffer::addCommand(Args&&... args)
729 {
730         commands->push_back(std::unique_ptr<T>(new T(std::forward<Args>(args)...)));
731 }
732
733 void CommandBuffer::beginRenderPass(VkRenderPass renderPass, VkFramebuffer framebuffer, VkRect2D renderArea,
734                                     uint32_t clearValueCount, const VkClearValue* clearValues, VkSubpassContents contents)
735 {
736         ASSERT(state == RECORDING);
737
738         addCommand<BeginRenderPass>(renderPass, framebuffer, renderArea, clearValueCount, clearValues);
739 }
740
741 void CommandBuffer::nextSubpass(VkSubpassContents contents)
742 {
743         ASSERT(state == RECORDING);
744
745         addCommand<NextSubpass>();
746 }
747
748 void CommandBuffer::endRenderPass()
749 {
750         addCommand<EndRenderPass>();
751 }
752
753 void CommandBuffer::executeCommands(uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers)
754 {
755         ASSERT(state == RECORDING);
756
757         for(uint32_t i = 0; i < commandBufferCount; ++i)
758         {
759                 addCommand<ExecuteCommands>(pCommandBuffers[i]);
760         }
761 }
762
763 void CommandBuffer::setDeviceMask(uint32_t deviceMask)
764 {
765         UNIMPLEMENTED("setDeviceMask");
766 }
767
768 void CommandBuffer::dispatchBase(uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ,
769                                  uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ)
770 {
771         UNIMPLEMENTED("dispatchBase");
772 }
773
774 void CommandBuffer::pipelineBarrier(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
775                                     VkDependencyFlags dependencyFlags,
776                                     uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers,
777                                     uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers,
778                                     uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers)
779 {
780         addCommand<PipelineBarrier>();
781 }
782
783 void CommandBuffer::bindPipeline(VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline)
784 {
785         switch(pipelineBindPoint)
786         {
787                 case VK_PIPELINE_BIND_POINT_COMPUTE:
788                 case VK_PIPELINE_BIND_POINT_GRAPHICS:
789                         addCommand<PipelineBind>(pipelineBindPoint, pipeline);
790                         break;
791                 default:
792                         UNIMPLEMENTED("pipelineBindPoint");
793         }
794 }
795
796 void CommandBuffer::bindVertexBuffers(uint32_t firstBinding, uint32_t bindingCount,
797                                       const VkBuffer* pBuffers, const VkDeviceSize* pOffsets)
798 {
799         for(uint32_t i = 0; i < bindingCount; ++i)
800         {
801                 addCommand<VertexBufferBind>(i + firstBinding, pBuffers[i], pOffsets[i]);
802         }
803 }
804
805 void CommandBuffer::beginQuery(VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags)
806 {
807         UNIMPLEMENTED("beginQuery");
808 }
809
810 void CommandBuffer::endQuery(VkQueryPool queryPool, uint32_t query)
811 {
812         UNIMPLEMENTED("endQuery");
813 }
814
815 void CommandBuffer::resetQueryPool(VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount)
816 {
817         UNIMPLEMENTED("resetQueryPool");
818 }
819
820 void CommandBuffer::writeTimestamp(VkPipelineStageFlagBits pipelineStage, VkQueryPool queryPool, uint32_t query)
821 {
822         UNIMPLEMENTED("writeTimestamp");
823 }
824
825 void CommandBuffer::copyQueryPoolResults(VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount,
826         VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags)
827 {
828         UNIMPLEMENTED("copyQueryPoolResults");
829 }
830
831 void CommandBuffer::pushConstants(VkPipelineLayout layout, VkShaderStageFlags stageFlags,
832         uint32_t offset, uint32_t size, const void* pValues)
833 {
834         addCommand<SetPushConstants>(offset, size, pValues);
835 }
836
837 void CommandBuffer::setViewport(uint32_t firstViewport, uint32_t viewportCount, const VkViewport* pViewports)
838 {
839         // Note: The bound graphics pipeline must have been created with the VK_DYNAMIC_STATE_VIEWPORT dynamic state enabled
840         UNIMPLEMENTED("setViewport");
841 }
842
843 void CommandBuffer::setScissor(uint32_t firstScissor, uint32_t scissorCount, const VkRect2D* pScissors)
844 {
845         // Note: The bound graphics pipeline must have been created with the VK_DYNAMIC_STATE_SCISSOR dynamic state enabled
846         UNIMPLEMENTED("setScissor");
847 }
848
849 void CommandBuffer::setLineWidth(float lineWidth)
850 {
851         // Note: The bound graphics pipeline must have been created with the VK_DYNAMIC_STATE_LINE_WIDTH dynamic state enabled
852
853         // If the wide lines feature is not enabled, lineWidth must be 1.0
854         ASSERT(lineWidth == 1.0f);
855
856         UNIMPLEMENTED("setLineWidth");
857 }
858
859 void CommandBuffer::setDepthBias(float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor)
860 {
861         // Note: The bound graphics pipeline must have been created with the VK_DYNAMIC_STATE_DEPTH_BIAS dynamic state enabled
862
863         // If the depth bias clamping feature is not enabled, depthBiasClamp must be 0.0
864         ASSERT(depthBiasClamp == 0.0f);
865
866         UNIMPLEMENTED("setDepthBias");
867 }
868
869 void CommandBuffer::setBlendConstants(const float blendConstants[4])
870 {
871         // Note: The bound graphics pipeline must have been created with the VK_DYNAMIC_STATE_BLEND_CONSTANTS dynamic state enabled
872
873         // blendConstants is an array of four values specifying the R, G, B, and A components
874         // of the blend constant color used in blending, depending on the blend factor.
875
876         UNIMPLEMENTED("setBlendConstants");
877 }
878
879 void CommandBuffer::setDepthBounds(float minDepthBounds, float maxDepthBounds)
880 {
881         // Note: The bound graphics pipeline must have been created with the VK_DYNAMIC_STATE_DEPTH_BOUNDS dynamic state enabled
882
883         // Unless the VK_EXT_depth_range_unrestricted extension is enabled minDepthBounds and maxDepthBounds must be between 0.0 and 1.0, inclusive
884         ASSERT(minDepthBounds >= 0.0f && minDepthBounds <= 1.0f);
885         ASSERT(maxDepthBounds >= 0.0f && maxDepthBounds <= 1.0f);
886
887         UNIMPLEMENTED("setDepthBounds");
888 }
889
890 void CommandBuffer::setStencilCompareMask(VkStencilFaceFlags faceMask, uint32_t compareMask)
891 {
892         // Note: The bound graphics pipeline must have been created with the VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK dynamic state enabled
893
894         // faceMask must not be 0
895         ASSERT(faceMask != 0);
896
897         UNIMPLEMENTED("setStencilCompareMask");
898 }
899
900 void CommandBuffer::setStencilWriteMask(VkStencilFaceFlags faceMask, uint32_t writeMask)
901 {
902         // Note: The bound graphics pipeline must have been created with the VK_DYNAMIC_STATE_STENCIL_WRITE_MASK dynamic state enabled
903
904         // faceMask must not be 0
905         ASSERT(faceMask != 0);
906
907         UNIMPLEMENTED("setStencilWriteMask");
908 }
909
910 void CommandBuffer::setStencilReference(VkStencilFaceFlags faceMask, uint32_t reference)
911 {
912         // Note: The bound graphics pipeline must have been created with the VK_DYNAMIC_STATE_STENCIL_REFERENCE dynamic state enabled
913
914         // faceMask must not be 0
915         ASSERT(faceMask != 0);
916
917         UNIMPLEMENTED("setStencilReference");
918 }
919
920 void CommandBuffer::bindDescriptorSets(VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout,
921         uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets,
922         uint32_t dynamicOffsetCount, const uint32_t* pDynamicOffsets)
923 {
924         ASSERT(state == RECORDING);
925
926         if(dynamicOffsetCount > 0)
927         {
928                 UNIMPLEMENTED("bindDescriptorSets");
929         }
930
931         for(uint32_t i = 0; i < descriptorSetCount; i++)
932         {
933                 addCommand<BindDescriptorSet>(pipelineBindPoint, firstSet + i, pDescriptorSets[i]);
934         }
935 }
936
937 void CommandBuffer::bindIndexBuffer(VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType)
938 {
939         addCommand<IndexBufferBind>(buffer, offset, indexType);
940 }
941
942 void CommandBuffer::dispatch(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ)
943 {
944         addCommand<Dispatch>(groupCountX, groupCountY, groupCountZ);
945 }
946
947 void CommandBuffer::dispatchIndirect(VkBuffer buffer, VkDeviceSize offset)
948 {
949         UNIMPLEMENTED("dispatchIndirect");
950 }
951
952 void CommandBuffer::copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferCopy* pRegions)
953 {
954         ASSERT(state == RECORDING);
955
956         for(uint32_t i = 0; i < regionCount; i++)
957         {
958                 addCommand<BufferToBufferCopy>(srcBuffer, dstBuffer, pRegions[i]);
959         }
960 }
961
962 void CommandBuffer::copyImage(VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout,
963         uint32_t regionCount, const VkImageCopy* pRegions)
964 {
965         ASSERT(state == RECORDING);
966         ASSERT(srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL ||
967                srcImageLayout == VK_IMAGE_LAYOUT_GENERAL);
968         ASSERT(dstImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ||
969                dstImageLayout == VK_IMAGE_LAYOUT_GENERAL);
970
971         for(uint32_t i = 0; i < regionCount; i++)
972         {
973                 addCommand<ImageToImageCopy>(srcImage, dstImage, pRegions[i]);
974         }
975 }
976
977 void CommandBuffer::blitImage(VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout,
978         uint32_t regionCount, const VkImageBlit* pRegions, VkFilter filter)
979 {
980         ASSERT(state == RECORDING);
981         ASSERT(srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL ||
982                srcImageLayout == VK_IMAGE_LAYOUT_GENERAL);
983         ASSERT(dstImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ||
984                dstImageLayout == VK_IMAGE_LAYOUT_GENERAL);
985
986         for(uint32_t i = 0; i < regionCount; i++)
987         {
988                 addCommand<BlitImage>(srcImage, dstImage, pRegions[i], filter);
989         }
990 }
991
992 void CommandBuffer::copyBufferToImage(VkBuffer srcBuffer, VkImage dstImage, VkImageLayout dstImageLayout,
993         uint32_t regionCount, const VkBufferImageCopy* pRegions)
994 {
995         ASSERT(state == RECORDING);
996
997         for(uint32_t i = 0; i < regionCount; i++)
998         {
999                 addCommand<BufferToImageCopy>(srcBuffer, dstImage, pRegions[i]);
1000         }
1001 }
1002
1003 void CommandBuffer::copyImageToBuffer(VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer dstBuffer,
1004         uint32_t regionCount, const VkBufferImageCopy* pRegions)
1005 {
1006         ASSERT(state == RECORDING);
1007         ASSERT(srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
1008
1009         for(uint32_t i = 0; i < regionCount; i++)
1010         {
1011                 addCommand<ImageToBufferCopy>(srcImage, dstBuffer, pRegions[i]);
1012         }
1013 }
1014
1015 void CommandBuffer::updateBuffer(VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const void* pData)
1016 {
1017         ASSERT(state == RECORDING);
1018
1019         addCommand<UpdateBuffer>(dstBuffer, dstOffset, dataSize, pData);
1020 }
1021
1022 void CommandBuffer::fillBuffer(VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data)
1023 {
1024         ASSERT(state == RECORDING);
1025
1026         addCommand<FillBuffer>(dstBuffer, dstOffset, size, data);
1027 }
1028
1029 void CommandBuffer::clearColorImage(VkImage image, VkImageLayout imageLayout, const VkClearColorValue* pColor,
1030         uint32_t rangeCount, const VkImageSubresourceRange* pRanges)
1031 {
1032         ASSERT(state == RECORDING);
1033
1034         for(uint32_t i = 0; i < rangeCount; i++)
1035         {
1036                 addCommand<ClearColorImage>(image, pColor[i], pRanges[i]);
1037         }
1038 }
1039
1040 void CommandBuffer::clearDepthStencilImage(VkImage image, VkImageLayout imageLayout, const VkClearDepthStencilValue* pDepthStencil,
1041         uint32_t rangeCount, const VkImageSubresourceRange* pRanges)
1042 {
1043         ASSERT(state == RECORDING);
1044
1045         for(uint32_t i = 0; i < rangeCount; i++)
1046         {
1047                 addCommand<ClearDepthStencilImage>(image, pDepthStencil[i], pRanges[i]);
1048         }
1049 }
1050
1051 void CommandBuffer::clearAttachments(uint32_t attachmentCount, const VkClearAttachment* pAttachments,
1052         uint32_t rectCount, const VkClearRect* pRects)
1053 {
1054         ASSERT(state == RECORDING);
1055
1056         for(uint32_t i = 0; i < attachmentCount; i++)
1057         {
1058                 for(uint32_t j = 0; j < rectCount; j++)
1059                 {
1060                         addCommand<ClearAttachment>(pAttachments[i], pRects[j]);
1061                 }
1062         }
1063 }
1064
1065 void CommandBuffer::resolveImage(VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout,
1066         uint32_t regionCount, const VkImageResolve* pRegions)
1067 {
1068         UNIMPLEMENTED("resolveImage");
1069 }
1070
1071 void CommandBuffer::setEvent(VkEvent event, VkPipelineStageFlags stageMask)
1072 {
1073         ASSERT(state == RECORDING);
1074
1075         addCommand<SignalEvent>(event, stageMask);
1076 }
1077
1078 void CommandBuffer::resetEvent(VkEvent event, VkPipelineStageFlags stageMask)
1079 {
1080         ASSERT(state == RECORDING);
1081
1082         addCommand<ResetEvent>(event, stageMask);
1083 }
1084
1085 void CommandBuffer::waitEvents(uint32_t eventCount, const VkEvent* pEvents, VkPipelineStageFlags srcStageMask,
1086         VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers,
1087         uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers,
1088         uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers)
1089 {
1090         ASSERT(state == RECORDING);
1091
1092         // TODO(b/117835459): Since we always do a full barrier, all memory barrier related arguments are ignored
1093
1094         // Note: srcStageMask and dstStageMask are currently ignored
1095         for(uint32_t i = 0; i < eventCount; i++)
1096         {
1097                 addCommand<WaitEvent>(pEvents[i]);
1098         }
1099 }
1100
1101 void CommandBuffer::draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance)
1102 {
1103         addCommand<Draw>(vertexCount, instanceCount, firstVertex, firstInstance);
1104 }
1105
1106 void CommandBuffer::drawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance)
1107 {
1108         addCommand<DrawIndexed>(indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
1109 }
1110
1111 void CommandBuffer::drawIndirect(VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride)
1112 {
1113         UNIMPLEMENTED("drawIndirect");
1114 }
1115
1116 void CommandBuffer::drawIndexedIndirect(VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride)
1117 {
1118         UNIMPLEMENTED("drawIndexedIndirect");
1119 }
1120
1121 void CommandBuffer::submit(CommandBuffer::ExecutionState& executionState)
1122 {
1123         // Perform recorded work
1124         state = PENDING;
1125
1126         for(auto& command : *commands)
1127         {
1128                 command->play(executionState);
1129         }
1130
1131         // After work is completed
1132         state = EXECUTABLE;
1133 }
1134
1135 void CommandBuffer::submitSecondary(CommandBuffer::ExecutionState& executionState) const
1136 {
1137         for(auto& command : *commands)
1138         {
1139                 command->play(executionState);
1140         }
1141 }
1142
1143 } // namespace vk