OSDN Git Service

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