1 //
2 // Copyright 2019 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // SecondaryCommandBuffer:
7 //    Lightweight, CPU-Side command buffers used to hold command state until
8 //    it has to be submitted to GPU.
9 //
10 
11 #ifndef LIBANGLE_RENDERER_VULKAN_SECONDARYCOMMANDBUFFERVK_H_
12 #define LIBANGLE_RENDERER_VULKAN_SECONDARYCOMMANDBUFFERVK_H_
13 
14 #include "common/PoolAlloc.h"
15 #include "common/vulkan/vk_headers.h"
16 #include "libANGLE/renderer/vulkan/vk_wrapper.h"
17 
18 namespace rx
19 {
20 namespace vk
21 {
22 namespace priv
23 {
24 
25 // NOTE: Please keep command-related enums, stucts, functions
26 //  and other code dealing with commands in alphabetical order
27 //  This simplifies searching and updating commands.
28 enum class CommandID : uint16_t
29 {
30     // Invalid cmd used to mark end of sequence of commands
31     Invalid = 0,
32     BeginDebugUtilsLabel,
33     BeginQuery,
34     BeginTransformFeedback,
35     BindComputePipeline,
36     BindDescriptorSets,
37     BindGraphicsPipeline,
38     BindIndexBuffer,
39     BindTransformFeedbackBuffers,
40     BindVertexBuffers,
41     BlitImage,
42     BufferBarrier,
43     ClearAttachments,
44     ClearColorImage,
45     ClearDepthStencilImage,
46     CopyBuffer,
47     CopyBufferToImage,
48     CopyImage,
49     CopyImageToBuffer,
50     Dispatch,
51     DispatchIndirect,
52     Draw,
53     DrawIndexed,
54     DrawIndexedBaseVertex,
55     DrawIndexedIndirect,
56     DrawIndexedInstanced,
57     DrawIndexedInstancedBaseVertex,
58     DrawIndexedInstancedBaseVertexBaseInstance,
59     DrawIndirect,
60     DrawInstanced,
61     DrawInstancedBaseInstance,
62     EndDebugUtilsLabel,
63     EndQuery,
64     EndTransformFeedback,
65     ExecutionBarrier,
66     FillBuffer,
67     ImageBarrier,
68     InsertDebugUtilsLabel,
69     MemoryBarrier,
70     NextSubpass,
71     PipelineBarrier,
72     PushConstants,
73     ResetEvent,
74     ResetQueryPool,
75     ResolveImage,
76     SetEvent,
77     SetScissor,
78     SetViewport,
79     WaitEvents,
80     WriteTimestamp,
81 };
82 
83 #define VERIFY_4_BYTE_ALIGNMENT(StructName) \
84     static_assert((sizeof(StructName) % 4) == 0, "Check StructName alignment");
85 
86 // Structs to encapsulate parameters for different commands
87 // This makes it easy to know the size of params & to copy params
88 // TODO: Could optimize the size of some of these structs through bit-packing
89 //  and customizing sizing based on limited parameter sets used by ANGLE
90 struct BeginQueryParams
91 {
92     VkQueryPool queryPool;
93     uint32_t query;
94     VkQueryControlFlags flags;
95 };
96 VERIFY_4_BYTE_ALIGNMENT(BeginQueryParams)
97 
98 struct BeginTransformFeedbackParams
99 {
100     uint32_t bufferCount;
101 };
102 VERIFY_4_BYTE_ALIGNMENT(BeginTransformFeedbackParams)
103 
104 struct BindDescriptorSetParams
105 {
106     VkPipelineLayout layout;
107     VkPipelineBindPoint pipelineBindPoint;
108     uint32_t firstSet;
109     uint32_t descriptorSetCount;
110     uint32_t dynamicOffsetCount;
111 };
112 VERIFY_4_BYTE_ALIGNMENT(BindDescriptorSetParams)
113 
114 struct BindIndexBufferParams
115 {
116     VkBuffer buffer;
117     VkDeviceSize offset;
118     VkIndexType indexType;
119 };
120 VERIFY_4_BYTE_ALIGNMENT(BindIndexBufferParams)
121 
122 struct BindPipelineParams
123 {
124     VkPipeline pipeline;
125 };
126 VERIFY_4_BYTE_ALIGNMENT(BindPipelineParams)
127 
128 struct BindTransformFeedbackBuffersParams
129 {
130     // ANGLE always has firstBinding of 0 so not storing that currently
131     uint32_t bindingCount;
132 };
133 VERIFY_4_BYTE_ALIGNMENT(BindTransformFeedbackBuffersParams)
134 
135 using BindVertexBuffersParams = BindTransformFeedbackBuffersParams;
136 
137 struct BlitImageParams
138 {
139     VkImage srcImage;
140     VkImage dstImage;
141     VkFilter filter;
142     VkImageBlit region;
143 };
144 VERIFY_4_BYTE_ALIGNMENT(BlitImageParams)
145 
146 struct BufferBarrierParams
147 {
148     VkPipelineStageFlags srcStageMask;
149     VkPipelineStageFlags dstStageMask;
150     VkBufferMemoryBarrier bufferMemoryBarrier;
151 };
152 VERIFY_4_BYTE_ALIGNMENT(BufferBarrierParams)
153 
154 struct ClearAttachmentsParams
155 {
156     uint32_t attachmentCount;
157     VkClearRect rect;
158 };
159 VERIFY_4_BYTE_ALIGNMENT(ClearAttachmentsParams)
160 
161 struct ClearColorImageParams
162 {
163     VkImage image;
164     VkImageLayout imageLayout;
165     VkClearColorValue color;
166     VkImageSubresourceRange range;
167 };
168 VERIFY_4_BYTE_ALIGNMENT(ClearColorImageParams)
169 
170 struct ClearDepthStencilImageParams
171 {
172     VkImage image;
173     VkImageLayout imageLayout;
174     VkClearDepthStencilValue depthStencil;
175     VkImageSubresourceRange range;
176 };
177 VERIFY_4_BYTE_ALIGNMENT(ClearDepthStencilImageParams)
178 
179 struct CopyBufferParams
180 {
181     VkBuffer srcBuffer;
182     VkBuffer destBuffer;
183     uint32_t regionCount;
184 };
185 VERIFY_4_BYTE_ALIGNMENT(CopyBufferParams)
186 
187 struct CopyBufferToImageParams
188 {
189     VkBuffer srcBuffer;
190     VkImage dstImage;
191     VkImageLayout dstImageLayout;
192     VkBufferImageCopy region;
193 };
194 VERIFY_4_BYTE_ALIGNMENT(CopyBufferToImageParams)
195 
196 struct CopyImageParams
197 {
198     VkImage srcImage;
199     VkImageLayout srcImageLayout;
200     VkImage dstImage;
201     VkImageLayout dstImageLayout;
202     VkImageCopy region;
203 };
204 VERIFY_4_BYTE_ALIGNMENT(CopyImageParams)
205 
206 struct CopyImageToBufferParams
207 {
208     VkImage srcImage;
209     VkImageLayout srcImageLayout;
210     VkBuffer dstBuffer;
211     VkBufferImageCopy region;
212 };
213 VERIFY_4_BYTE_ALIGNMENT(CopyImageToBufferParams)
214 
215 // This is a common struct used by both begin & insert DebugUtilsLabelEXT() functions
216 struct DebugUtilsLabelParams
217 {
218     float color[4];
219 };
220 VERIFY_4_BYTE_ALIGNMENT(DebugUtilsLabelParams)
221 
222 struct DispatchParams
223 {
224     uint32_t groupCountX;
225     uint32_t groupCountY;
226     uint32_t groupCountZ;
227 };
228 VERIFY_4_BYTE_ALIGNMENT(DispatchParams)
229 
230 struct DispatchIndirectParams
231 {
232     VkBuffer buffer;
233     VkDeviceSize offset;
234 };
235 VERIFY_4_BYTE_ALIGNMENT(DispatchIndirectParams)
236 
237 struct DrawParams
238 {
239     uint32_t vertexCount;
240     uint32_t firstVertex;
241 };
242 VERIFY_4_BYTE_ALIGNMENT(DrawParams)
243 
244 struct DrawIndexedParams
245 {
246     uint32_t indexCount;
247 };
248 VERIFY_4_BYTE_ALIGNMENT(DrawIndexedParams)
249 
250 struct DrawIndexedBaseVertexParams
251 {
252     uint32_t indexCount;
253     uint32_t vertexOffset;
254 };
255 VERIFY_4_BYTE_ALIGNMENT(DrawIndexedBaseVertexParams)
256 
257 struct DrawIndexedIndirectParams
258 {
259     VkBuffer buffer;
260     VkDeviceSize offset;
261 };
262 VERIFY_4_BYTE_ALIGNMENT(DrawIndexedIndirectParams)
263 
264 struct DrawIndexedInstancedParams
265 {
266     uint32_t indexCount;
267     uint32_t instanceCount;
268 };
269 VERIFY_4_BYTE_ALIGNMENT(DrawIndexedInstancedParams)
270 
271 struct DrawIndexedInstancedBaseVertexParams
272 {
273     uint32_t indexCount;
274     uint32_t instanceCount;
275     uint32_t vertexOffset;
276 };
277 VERIFY_4_BYTE_ALIGNMENT(DrawIndexedInstancedBaseVertexParams)
278 
279 struct DrawIndexedInstancedBaseVertexBaseInstanceParams
280 {
281     uint32_t indexCount;
282     uint32_t instanceCount;
283     uint32_t firstIndex;
284     int32_t vertexOffset;
285     uint32_t firstInstance;
286 };
287 VERIFY_4_BYTE_ALIGNMENT(DrawIndexedInstancedBaseVertexBaseInstanceParams)
288 
289 struct DrawIndirectParams
290 {
291     VkBuffer buffer;
292     VkDeviceSize offset;
293 };
294 VERIFY_4_BYTE_ALIGNMENT(DrawIndirectParams)
295 
296 struct DrawInstancedParams
297 {
298     uint32_t vertexCount;
299     uint32_t instanceCount;
300     uint32_t firstVertex;
301 };
302 VERIFY_4_BYTE_ALIGNMENT(DrawInstancedParams)
303 
304 struct DrawInstancedBaseInstanceParams
305 {
306     uint32_t vertexCount;
307     uint32_t instanceCount;
308     uint32_t firstVertex;
309     uint32_t firstInstance;
310 };
311 VERIFY_4_BYTE_ALIGNMENT(DrawInstancedBaseInstanceParams)
312 
313 // A special struct used with commands that don't have params
314 struct EmptyParams
315 {};
316 
317 struct EndQueryParams
318 {
319     VkQueryPool queryPool;
320     uint32_t query;
321 };
322 VERIFY_4_BYTE_ALIGNMENT(EndQueryParams)
323 
324 struct EndTransformFeedbackParams
325 {
326     uint32_t bufferCount;
327 };
328 VERIFY_4_BYTE_ALIGNMENT(EndTransformFeedbackParams)
329 
330 struct ExecutionBarrierParams
331 {
332     VkPipelineStageFlags stageMask;
333 };
334 VERIFY_4_BYTE_ALIGNMENT(ExecutionBarrierParams)
335 
336 struct FillBufferParams
337 {
338     VkBuffer dstBuffer;
339     VkDeviceSize dstOffset;
340     VkDeviceSize size;
341     uint32_t data;
342 };
343 VERIFY_4_BYTE_ALIGNMENT(FillBufferParams)
344 
345 struct ImageBarrierParams
346 {
347     VkPipelineStageFlags srcStageMask;
348     VkPipelineStageFlags dstStageMask;
349     VkImageMemoryBarrier imageMemoryBarrier;
350 };
351 VERIFY_4_BYTE_ALIGNMENT(ImageBarrierParams)
352 
353 struct MemoryBarrierParams
354 {
355     VkPipelineStageFlags srcStageMask;
356     VkPipelineStageFlags dstStageMask;
357     VkMemoryBarrier memoryBarrier;
358 };
359 VERIFY_4_BYTE_ALIGNMENT(MemoryBarrierParams)
360 
361 struct NextSubpassParams
362 {
363     VkSubpassContents subpassContents;
364 };
365 VERIFY_4_BYTE_ALIGNMENT(NextSubpassParams)
366 
367 struct PipelineBarrierParams
368 {
369     VkPipelineStageFlags srcStageMask;
370     VkPipelineStageFlags dstStageMask;
371     VkDependencyFlags dependencyFlags;
372     uint32_t memoryBarrierCount;
373     uint32_t bufferMemoryBarrierCount;
374     uint32_t imageMemoryBarrierCount;
375 };
376 VERIFY_4_BYTE_ALIGNMENT(PipelineBarrierParams)
377 
378 struct PushConstantsParams
379 {
380     VkPipelineLayout layout;
381     VkShaderStageFlags flag;
382     uint32_t offset;
383     uint32_t size;
384 };
385 VERIFY_4_BYTE_ALIGNMENT(PushConstantsParams)
386 
387 struct ResetEventParams
388 {
389     VkEvent event;
390     VkPipelineStageFlags stageMask;
391 };
392 VERIFY_4_BYTE_ALIGNMENT(ResetEventParams)
393 
394 struct ResetQueryPoolParams
395 {
396     VkQueryPool queryPool;
397     uint32_t firstQuery;
398     uint32_t queryCount;
399 };
400 VERIFY_4_BYTE_ALIGNMENT(ResetQueryPoolParams)
401 
402 struct ResolveImageParams
403 {
404     VkImage srcImage;
405     VkImage dstImage;
406     VkImageResolve region;
407 };
408 VERIFY_4_BYTE_ALIGNMENT(ResolveImageParams)
409 
410 struct SetEventParams
411 {
412     VkEvent event;
413     VkPipelineStageFlags stageMask;
414 };
415 VERIFY_4_BYTE_ALIGNMENT(SetEventParams)
416 
417 struct SetScissorParams
418 {
419     VkRect2D scissor;
420 };
421 VERIFY_4_BYTE_ALIGNMENT(SetScissorParams)
422 
423 struct SetViewportParams
424 {
425     VkViewport viewport;
426 };
427 VERIFY_4_BYTE_ALIGNMENT(SetViewportParams)
428 
429 struct WaitEventsParams
430 {
431     uint32_t eventCount;
432     VkPipelineStageFlags srcStageMask;
433     VkPipelineStageFlags dstStageMask;
434     uint32_t memoryBarrierCount;
435     uint32_t bufferMemoryBarrierCount;
436     uint32_t imageMemoryBarrierCount;
437 };
438 VERIFY_4_BYTE_ALIGNMENT(WaitEventsParams)
439 
440 struct WriteTimestampParams
441 {
442     VkPipelineStageFlagBits pipelineStage;
443     VkQueryPool queryPool;
444     uint32_t query;
445 };
446 VERIFY_4_BYTE_ALIGNMENT(WriteTimestampParams)
447 
448 // Header for every cmd in custom cmd buffer
449 struct CommandHeader
450 {
451     CommandID id;
452     uint16_t size;
453 };
454 static_assert(sizeof(CommandHeader) == 4, "Check CommandHeader size");
455 
456 template <typename DestT, typename T>
Offset(T * ptr,size_t bytes)457 ANGLE_INLINE DestT *Offset(T *ptr, size_t bytes)
458 {
459     return reinterpret_cast<DestT *>((reinterpret_cast<uint8_t *>(ptr) + bytes));
460 }
461 
462 template <typename DestT, typename T>
Offset(const T * ptr,size_t bytes)463 ANGLE_INLINE const DestT *Offset(const T *ptr, size_t bytes)
464 {
465     return reinterpret_cast<const DestT *>((reinterpret_cast<const uint8_t *>(ptr) + bytes));
466 }
467 
468 class SecondaryCommandBuffer final : angle::NonCopyable
469 {
470   public:
471     SecondaryCommandBuffer();
472     ~SecondaryCommandBuffer();
473 
SupportsQueries(const VkPhysicalDeviceFeatures & features)474     static bool SupportsQueries(const VkPhysicalDeviceFeatures &features) { return true; }
475 
476     // SecondaryCommandBuffer replays its commands inline when executed on the primary command
477     // buffer.
ExecutesInline()478     static constexpr bool ExecutesInline() { return true; }
479 
480     // Add commands
481     void beginDebugUtilsLabelEXT(const VkDebugUtilsLabelEXT &label);
482 
483     void beginQuery(const QueryPool &queryPool, uint32_t query, VkQueryControlFlags flags);
484 
485     void beginTransformFeedback(uint32_t firstCounterBuffer,
486                                 uint32_t bufferCount,
487                                 const VkBuffer *counterBuffers,
488                                 const VkDeviceSize *counterBufferOffsets);
489 
490     void bindComputePipeline(const Pipeline &pipeline);
491 
492     void bindDescriptorSets(const PipelineLayout &layout,
493                             VkPipelineBindPoint pipelineBindPoint,
494                             DescriptorSetIndex firstSet,
495                             uint32_t descriptorSetCount,
496                             const VkDescriptorSet *descriptorSets,
497                             uint32_t dynamicOffsetCount,
498                             const uint32_t *dynamicOffsets);
499 
500     void bindGraphicsPipeline(const Pipeline &pipeline);
501 
502     void bindIndexBuffer(const Buffer &buffer, VkDeviceSize offset, VkIndexType indexType);
503 
504     void bindTransformFeedbackBuffers(uint32_t firstBinding,
505                                       uint32_t bindingCount,
506                                       const VkBuffer *buffers,
507                                       const VkDeviceSize *offsets,
508                                       const VkDeviceSize *sizes);
509 
510     void bindVertexBuffers(uint32_t firstBinding,
511                            uint32_t bindingCount,
512                            const VkBuffer *buffers,
513                            const VkDeviceSize *offsets);
514 
515     void blitImage(const Image &srcImage,
516                    VkImageLayout srcImageLayout,
517                    const Image &dstImage,
518                    VkImageLayout dstImageLayout,
519                    uint32_t regionCount,
520                    const VkImageBlit *regions,
521                    VkFilter filter);
522 
523     void bufferBarrier(VkPipelineStageFlags srcStageMask,
524                        VkPipelineStageFlags dstStageMask,
525                        const VkBufferMemoryBarrier *bufferMemoryBarrier);
526 
527     void clearAttachments(uint32_t attachmentCount,
528                           const VkClearAttachment *attachments,
529                           uint32_t rectCount,
530                           const VkClearRect *rects);
531 
532     void clearColorImage(const Image &image,
533                          VkImageLayout imageLayout,
534                          const VkClearColorValue &color,
535                          uint32_t rangeCount,
536                          const VkImageSubresourceRange *ranges);
537 
538     void clearDepthStencilImage(const Image &image,
539                                 VkImageLayout imageLayout,
540                                 const VkClearDepthStencilValue &depthStencil,
541                                 uint32_t rangeCount,
542                                 const VkImageSubresourceRange *ranges);
543 
544     void copyBuffer(const Buffer &srcBuffer,
545                     const Buffer &destBuffer,
546                     uint32_t regionCount,
547                     const VkBufferCopy *regions);
548 
549     void copyBufferToImage(VkBuffer srcBuffer,
550                            const Image &dstImage,
551                            VkImageLayout dstImageLayout,
552                            uint32_t regionCount,
553                            const VkBufferImageCopy *regions);
554 
555     void copyImage(const Image &srcImage,
556                    VkImageLayout srcImageLayout,
557                    const Image &dstImage,
558                    VkImageLayout dstImageLayout,
559                    uint32_t regionCount,
560                    const VkImageCopy *regions);
561 
562     void copyImageToBuffer(const Image &srcImage,
563                            VkImageLayout srcImageLayout,
564                            VkBuffer dstBuffer,
565                            uint32_t regionCount,
566                            const VkBufferImageCopy *regions);
567 
568     void dispatch(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ);
569 
570     void dispatchIndirect(const Buffer &buffer, VkDeviceSize offset);
571 
572     void draw(uint32_t vertexCount, uint32_t firstVertex);
573 
574     void drawIndexed(uint32_t indexCount);
575     void drawIndexedBaseVertex(uint32_t indexCount, uint32_t vertexOffset);
576     void drawIndexedIndirect(const Buffer &buffer,
577                              VkDeviceSize offset,
578                              uint32_t drawCount,
579                              uint32_t stride);
580     void drawIndexedInstanced(uint32_t indexCount, uint32_t instanceCount);
581     void drawIndexedInstancedBaseVertex(uint32_t indexCount,
582                                         uint32_t instanceCount,
583                                         uint32_t vertexOffset);
584     void drawIndexedInstancedBaseVertexBaseInstance(uint32_t indexCount,
585                                                     uint32_t instanceCount,
586                                                     uint32_t firstIndex,
587                                                     int32_t vertexOffset,
588                                                     uint32_t firstInstance);
589 
590     void drawIndirect(const Buffer &buffer,
591                       VkDeviceSize offset,
592                       uint32_t drawCount,
593                       uint32_t stride);
594 
595     void drawInstanced(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex);
596     void drawInstancedBaseInstance(uint32_t vertexCount,
597                                    uint32_t instanceCount,
598                                    uint32_t firstVertex,
599                                    uint32_t firstInstance);
600 
601     void endDebugUtilsLabelEXT();
602 
603     void endQuery(const QueryPool &queryPool, uint32_t query);
604 
605     void endTransformFeedback(uint32_t firstCounterBuffer,
606                               uint32_t counterBufferCount,
607                               const VkBuffer *counterBuffers,
608                               const VkDeviceSize *counterBufferOffsets);
609 
610     void executionBarrier(VkPipelineStageFlags stageMask);
611 
612     void fillBuffer(const Buffer &dstBuffer,
613                     VkDeviceSize dstOffset,
614                     VkDeviceSize size,
615                     uint32_t data);
616 
617     void imageBarrier(VkPipelineStageFlags srcStageMask,
618                       VkPipelineStageFlags dstStageMask,
619                       const VkImageMemoryBarrier &imageMemoryBarrier);
620 
621     void insertDebugUtilsLabelEXT(const VkDebugUtilsLabelEXT &label);
622 
623     void memoryBarrier(VkPipelineStageFlags srcStageMask,
624                        VkPipelineStageFlags dstStageMask,
625                        const VkMemoryBarrier *memoryBarrier);
626 
627     void nextSubpass(VkSubpassContents subpassContents);
628 
629     void pipelineBarrier(VkPipelineStageFlags srcStageMask,
630                          VkPipelineStageFlags dstStageMask,
631                          VkDependencyFlags dependencyFlags,
632                          uint32_t memoryBarrierCount,
633                          const VkMemoryBarrier *memoryBarriers,
634                          uint32_t bufferMemoryBarrierCount,
635                          const VkBufferMemoryBarrier *bufferMemoryBarriers,
636                          uint32_t imageMemoryBarrierCount,
637                          const VkImageMemoryBarrier *imageMemoryBarriers);
638 
639     void pushConstants(const PipelineLayout &layout,
640                        VkShaderStageFlags flag,
641                        uint32_t offset,
642                        uint32_t size,
643                        const void *data);
644 
645     void resetEvent(VkEvent event, VkPipelineStageFlags stageMask);
646 
647     void resetQueryPool(const QueryPool &queryPool, uint32_t firstQuery, uint32_t queryCount);
648 
649     void resolveImage(const Image &srcImage,
650                       VkImageLayout srcImageLayout,
651                       const Image &dstImage,
652                       VkImageLayout dstImageLayout,
653                       uint32_t regionCount,
654                       const VkImageResolve *regions);
655 
656     void setEvent(VkEvent event, VkPipelineStageFlags stageMask);
657 
658     void setScissor(uint32_t firstScissor, uint32_t scissorCount, const VkRect2D *scissors);
659 
660     void setViewport(uint32_t firstViewport, uint32_t viewportCount, const VkViewport *viewports);
661 
662     void waitEvents(uint32_t eventCount,
663                     const VkEvent *events,
664                     VkPipelineStageFlags srcStageMask,
665                     VkPipelineStageFlags dstStageMask,
666                     uint32_t memoryBarrierCount,
667                     const VkMemoryBarrier *memoryBarriers,
668                     uint32_t bufferMemoryBarrierCount,
669                     const VkBufferMemoryBarrier *bufferMemoryBarriers,
670                     uint32_t imageMemoryBarrierCount,
671                     const VkImageMemoryBarrier *imageMemoryBarriers);
672 
673     void writeTimestamp(VkPipelineStageFlagBits pipelineStage,
674                         const QueryPool &queryPool,
675                         uint32_t query);
676 
677     // No-op for compatibility
end()678     VkResult end() { return VK_SUCCESS; }
679 
680     // Parse the cmds in this cmd buffer into given primary cmd buffer for execution
681     void executeCommands(VkCommandBuffer cmdBuffer);
682 
683     // Calculate memory usage of this command buffer for diagnostics.
684     void getMemoryUsageStats(size_t *usedMemoryOut, size_t *allocatedMemoryOut) const;
685 
686     // Traverse the list of commands and build a summary for diagnostics.
687     std::string dumpCommands(const char *separator) const;
688 
689     // Pool Alloc uses 16kB pages w/ 16byte header = 16368bytes. To minimize waste
690     //  using a 16368/12 = 1364. Also better perf than 1024 due to fewer block allocations
691     static constexpr size_t kBlockSize = 1364;
692     // Make sure block size is 4-byte aligned to avoid Android errors
693     static_assert((kBlockSize % 4) == 0, "Check kBlockSize alignment");
694 
695     // Initialize the SecondaryCommandBuffer by setting the allocator it will use
initialize(angle::PoolAllocator * allocator)696     void initialize(angle::PoolAllocator *allocator)
697     {
698         ASSERT(allocator);
699         ASSERT(mCommands.empty());
700         mAllocator = allocator;
701         allocateNewBlock();
702         // Set first command to Invalid to start
703         reinterpret_cast<CommandHeader *>(mCurrentWritePointer)->id = CommandID::Invalid;
704     }
705 
open()706     void open() { mIsOpen = true; }
close()707     void close() { mIsOpen = false; }
708 
reset()709     void reset()
710     {
711         mCommands.clear();
712         initialize(mAllocator);
713     }
714 
715     // This will cause the SecondaryCommandBuffer to become invalid by clearing its allocator
releaseHandle()716     void releaseHandle() { mAllocator = nullptr; }
717     // The SecondaryCommandBuffer is valid if it's been initialized
valid()718     bool valid() const { return mAllocator != nullptr; }
719 
CanKnowIfEmpty()720     static bool CanKnowIfEmpty() { return true; }
empty()721     bool empty() const { return mCommands.size() == 0 || mCommands[0]->id == CommandID::Invalid; }
722     // The following is used to give the size of the command buffer in bytes
getCommandSize()723     uint32_t getCommandSize() const
724     {
725         ASSERT(mCommands.size() > 0 || mCurrentBytesRemaining == 0);
726         uint32_t rtn =
727             static_cast<uint32_t>((mCommands.size() * kBlockSize) - mCurrentBytesRemaining);
728         return rtn;
729     }
730 
731   private:
732     void commonDebugUtilsLabel(CommandID cmd, const VkDebugUtilsLabelEXT &label);
733     template <class StructType>
commonInit(CommandID cmdID,size_t allocationSize)734     ANGLE_INLINE StructType *commonInit(CommandID cmdID, size_t allocationSize)
735     {
736         ASSERT(mIsOpen);
737         mCurrentBytesRemaining -= allocationSize;
738 
739         CommandHeader *header = reinterpret_cast<CommandHeader *>(mCurrentWritePointer);
740         header->id            = cmdID;
741         header->size          = static_cast<uint16_t>(allocationSize);
742         ASSERT(allocationSize <= std::numeric_limits<uint16_t>::max());
743 
744         mCurrentWritePointer += allocationSize;
745         // Set next cmd header to Invalid (0) so cmd sequence will be terminated
746         reinterpret_cast<CommandHeader *>(mCurrentWritePointer)->id = CommandID::Invalid;
747         return Offset<StructType>(header, sizeof(CommandHeader));
748     }
749     ANGLE_INLINE void allocateNewBlock(size_t blockSize = kBlockSize)
750     {
751         ASSERT(mAllocator);
752         mCurrentWritePointer   = mAllocator->fastAllocate(blockSize);
753         mCurrentBytesRemaining = blockSize;
754         mCommands.push_back(reinterpret_cast<CommandHeader *>(mCurrentWritePointer));
755     }
756 
757     // Allocate and initialize memory for given commandID & variable param size, setting
758     // variableDataPtr to the byte following fixed cmd data where variable-sized ptr data will
759     // be written and returning a pointer to the start of the command's parameter data
760     template <class StructType>
initCommand(CommandID cmdID,size_t variableSize,uint8_t ** variableDataPtr)761     ANGLE_INLINE StructType *initCommand(CommandID cmdID,
762                                          size_t variableSize,
763                                          uint8_t **variableDataPtr)
764     {
765         constexpr size_t fixedAllocationSize = sizeof(StructType) + sizeof(CommandHeader);
766         const size_t allocationSize          = fixedAllocationSize + variableSize;
767         // Make sure we have enough room to mark follow-on header "Invalid"
768         const size_t requiredSize = allocationSize + sizeof(CommandHeader);
769         if (mCurrentBytesRemaining < requiredSize)
770         {
771             // variable size command can potentially exceed default cmd allocation blockSize
772             if (requiredSize <= kBlockSize)
773                 allocateNewBlock();
774             else
775             {
776                 // Make sure allocation is 4-byte aligned
777                 const size_t alignedSize = roundUpPow2<size_t>(requiredSize, 4);
778                 ASSERT((alignedSize % 4) == 0);
779                 allocateNewBlock(alignedSize);
780             }
781         }
782         *variableDataPtr = Offset<uint8_t>(mCurrentWritePointer, fixedAllocationSize);
783         return commonInit<StructType>(cmdID, allocationSize);
784     }
785 
786     // Initialize a command that doesn't have variable-sized ptr data
787     template <class StructType>
initCommand(CommandID cmdID)788     ANGLE_INLINE StructType *initCommand(CommandID cmdID)
789     {
790         constexpr size_t paramSize =
791             std::is_same<StructType, EmptyParams>::value ? 0 : sizeof(StructType);
792         constexpr size_t allocationSize = paramSize + sizeof(CommandHeader);
793         // Make sure we have enough room to mark follow-on header "Invalid"
794         if (mCurrentBytesRemaining < (allocationSize + sizeof(CommandHeader)))
795         {
796             ASSERT((allocationSize + sizeof(CommandHeader)) < kBlockSize);
797             allocateNewBlock();
798         }
799         return commonInit<StructType>(cmdID, allocationSize);
800     }
801 
802     // Return a ptr to the parameter type
803     template <class StructType>
getParamPtr(const CommandHeader * header)804     const StructType *getParamPtr(const CommandHeader *header) const
805     {
806         return reinterpret_cast<const StructType *>(reinterpret_cast<const uint8_t *>(header) +
807                                                     sizeof(CommandHeader));
808     }
809     // Copy sizeInBytes data from paramData to writePointer & return writePointer plus sizeInBytes.
810     template <class PtrType>
storePointerParameter(uint8_t * writePointer,const PtrType * paramData,size_t sizeInBytes)811     ANGLE_INLINE uint8_t *storePointerParameter(uint8_t *writePointer,
812                                                 const PtrType *paramData,
813                                                 size_t sizeInBytes)
814     {
815         memcpy(writePointer, paramData, sizeInBytes);
816         return writePointer + sizeInBytes;
817     }
818 
819     // Flag to indicate that commandBuffer is open for new commands. Initially open.
820     bool mIsOpen;
821 
822     std::vector<CommandHeader *> mCommands;
823 
824     // Allocator used by this class. If non-null then the class is valid.
825     angle::PoolAllocator *mAllocator;
826 
827     uint8_t *mCurrentWritePointer;
828     size_t mCurrentBytesRemaining;
829 };
830 
SecondaryCommandBuffer()831 ANGLE_INLINE SecondaryCommandBuffer::SecondaryCommandBuffer()
832     : mIsOpen(true), mAllocator(nullptr), mCurrentWritePointer(nullptr), mCurrentBytesRemaining(0)
833 {}
834 
~SecondaryCommandBuffer()835 ANGLE_INLINE SecondaryCommandBuffer::~SecondaryCommandBuffer() {}
836 
837 // begin and insert DebugUtilsLabelEXT funcs share this same function body
commonDebugUtilsLabel(CommandID cmd,const VkDebugUtilsLabelEXT & label)838 ANGLE_INLINE void SecondaryCommandBuffer::commonDebugUtilsLabel(CommandID cmd,
839                                                                 const VkDebugUtilsLabelEXT &label)
840 {
841     uint8_t *writePtr;
842     const size_t stringSize        = strlen(label.pLabelName) + 1;
843     const size_t alignedStringSize = roundUpPow2<size_t>(stringSize, 4);
844     DebugUtilsLabelParams *paramStruct =
845         initCommand<DebugUtilsLabelParams>(cmd, alignedStringSize, &writePtr);
846     paramStruct->color[0] = label.color[0];
847     paramStruct->color[1] = label.color[1];
848     paramStruct->color[2] = label.color[2];
849     paramStruct->color[3] = label.color[3];
850     storePointerParameter(writePtr, label.pLabelName, alignedStringSize);
851 }
852 
beginDebugUtilsLabelEXT(const VkDebugUtilsLabelEXT & label)853 ANGLE_INLINE void SecondaryCommandBuffer::beginDebugUtilsLabelEXT(const VkDebugUtilsLabelEXT &label)
854 {
855     commonDebugUtilsLabel(CommandID::BeginDebugUtilsLabel, label);
856 }
857 
beginQuery(const QueryPool & queryPool,uint32_t query,VkQueryControlFlags flags)858 ANGLE_INLINE void SecondaryCommandBuffer::beginQuery(const QueryPool &queryPool,
859                                                      uint32_t query,
860                                                      VkQueryControlFlags flags)
861 {
862     BeginQueryParams *paramStruct = initCommand<BeginQueryParams>(CommandID::BeginQuery);
863     paramStruct->queryPool        = queryPool.getHandle();
864     paramStruct->query            = query;
865     paramStruct->flags            = flags;
866 }
867 
beginTransformFeedback(uint32_t firstCounterBuffer,uint32_t bufferCount,const VkBuffer * counterBuffers,const VkDeviceSize * counterBufferOffsets)868 ANGLE_INLINE void SecondaryCommandBuffer::beginTransformFeedback(
869     uint32_t firstCounterBuffer,
870     uint32_t bufferCount,
871     const VkBuffer *counterBuffers,
872     const VkDeviceSize *counterBufferOffsets)
873 {
874     ASSERT(firstCounterBuffer == 0);
875     ASSERT(counterBufferOffsets == nullptr);
876     uint8_t *writePtr;
877     size_t bufferSize                         = bufferCount * sizeof(VkBuffer);
878     BeginTransformFeedbackParams *paramStruct = initCommand<BeginTransformFeedbackParams>(
879         CommandID::BeginTransformFeedback, bufferSize, &writePtr);
880     paramStruct->bufferCount = bufferCount;
881     storePointerParameter(writePtr, counterBuffers, bufferSize);
882 }
883 
bindComputePipeline(const Pipeline & pipeline)884 ANGLE_INLINE void SecondaryCommandBuffer::bindComputePipeline(const Pipeline &pipeline)
885 {
886     BindPipelineParams *paramStruct =
887         initCommand<BindPipelineParams>(CommandID::BindComputePipeline);
888     paramStruct->pipeline = pipeline.getHandle();
889 }
890 
bindDescriptorSets(const PipelineLayout & layout,VkPipelineBindPoint pipelineBindPoint,DescriptorSetIndex firstSet,uint32_t descriptorSetCount,const VkDescriptorSet * descriptorSets,uint32_t dynamicOffsetCount,const uint32_t * dynamicOffsets)891 ANGLE_INLINE void SecondaryCommandBuffer::bindDescriptorSets(const PipelineLayout &layout,
892                                                              VkPipelineBindPoint pipelineBindPoint,
893                                                              DescriptorSetIndex firstSet,
894                                                              uint32_t descriptorSetCount,
895                                                              const VkDescriptorSet *descriptorSets,
896                                                              uint32_t dynamicOffsetCount,
897                                                              const uint32_t *dynamicOffsets)
898 {
899     size_t descSize   = descriptorSetCount * sizeof(VkDescriptorSet);
900     size_t offsetSize = dynamicOffsetCount * sizeof(uint32_t);
901     uint8_t *writePtr;
902     BindDescriptorSetParams *paramStruct = initCommand<BindDescriptorSetParams>(
903         CommandID::BindDescriptorSets, descSize + offsetSize, &writePtr);
904     // Copy params into memory
905     paramStruct->layout             = layout.getHandle();
906     paramStruct->pipelineBindPoint  = pipelineBindPoint;
907     paramStruct->firstSet           = ToUnderlying(firstSet);
908     paramStruct->descriptorSetCount = descriptorSetCount;
909     paramStruct->dynamicOffsetCount = dynamicOffsetCount;
910     // Copy variable sized data
911     writePtr = storePointerParameter(writePtr, descriptorSets, descSize);
912     storePointerParameter(writePtr, dynamicOffsets, offsetSize);
913 }
914 
bindGraphicsPipeline(const Pipeline & pipeline)915 ANGLE_INLINE void SecondaryCommandBuffer::bindGraphicsPipeline(const Pipeline &pipeline)
916 {
917     BindPipelineParams *paramStruct =
918         initCommand<BindPipelineParams>(CommandID::BindGraphicsPipeline);
919     paramStruct->pipeline = pipeline.getHandle();
920 }
921 
bindIndexBuffer(const Buffer & buffer,VkDeviceSize offset,VkIndexType indexType)922 ANGLE_INLINE void SecondaryCommandBuffer::bindIndexBuffer(const Buffer &buffer,
923                                                           VkDeviceSize offset,
924                                                           VkIndexType indexType)
925 {
926     BindIndexBufferParams *paramStruct =
927         initCommand<BindIndexBufferParams>(CommandID::BindIndexBuffer);
928     paramStruct->buffer    = buffer.getHandle();
929     paramStruct->offset    = offset;
930     paramStruct->indexType = indexType;
931 }
932 
bindTransformFeedbackBuffers(uint32_t firstBinding,uint32_t bindingCount,const VkBuffer * buffers,const VkDeviceSize * offsets,const VkDeviceSize * sizes)933 ANGLE_INLINE void SecondaryCommandBuffer::bindTransformFeedbackBuffers(uint32_t firstBinding,
934                                                                        uint32_t bindingCount,
935                                                                        const VkBuffer *buffers,
936                                                                        const VkDeviceSize *offsets,
937                                                                        const VkDeviceSize *sizes)
938 {
939     ASSERT(firstBinding == 0);
940     uint8_t *writePtr;
941     size_t buffersSize = bindingCount * sizeof(VkBuffer);
942     size_t offsetsSize = bindingCount * sizeof(VkDeviceSize);
943     size_t sizesSize   = offsetsSize;
944     BindTransformFeedbackBuffersParams *paramStruct =
945         initCommand<BindTransformFeedbackBuffersParams>(CommandID::BindTransformFeedbackBuffers,
946                                                         buffersSize + offsetsSize + sizesSize,
947                                                         &writePtr);
948     // Copy params
949     paramStruct->bindingCount = bindingCount;
950     writePtr                  = storePointerParameter(writePtr, buffers, buffersSize);
951     writePtr                  = storePointerParameter(writePtr, offsets, offsetsSize);
952     storePointerParameter(writePtr, sizes, sizesSize);
953 }
954 
bindVertexBuffers(uint32_t firstBinding,uint32_t bindingCount,const VkBuffer * buffers,const VkDeviceSize * offsets)955 ANGLE_INLINE void SecondaryCommandBuffer::bindVertexBuffers(uint32_t firstBinding,
956                                                             uint32_t bindingCount,
957                                                             const VkBuffer *buffers,
958                                                             const VkDeviceSize *offsets)
959 {
960     ASSERT(firstBinding == 0);
961     uint8_t *writePtr;
962     size_t buffersSize                   = bindingCount * sizeof(VkBuffer);
963     size_t offsetsSize                   = bindingCount * sizeof(VkDeviceSize);
964     BindVertexBuffersParams *paramStruct = initCommand<BindVertexBuffersParams>(
965         CommandID::BindVertexBuffers, buffersSize + offsetsSize, &writePtr);
966     // Copy params
967     paramStruct->bindingCount = bindingCount;
968     writePtr                  = storePointerParameter(writePtr, buffers, buffersSize);
969     storePointerParameter(writePtr, offsets, offsetsSize);
970 }
971 
blitImage(const Image & srcImage,VkImageLayout srcImageLayout,const Image & dstImage,VkImageLayout dstImageLayout,uint32_t regionCount,const VkImageBlit * regions,VkFilter filter)972 ANGLE_INLINE void SecondaryCommandBuffer::blitImage(const Image &srcImage,
973                                                     VkImageLayout srcImageLayout,
974                                                     const Image &dstImage,
975                                                     VkImageLayout dstImageLayout,
976                                                     uint32_t regionCount,
977                                                     const VkImageBlit *regions,
978                                                     VkFilter filter)
979 {
980     // Currently ANGLE uses limited params so verify those assumptions and update if they change
981     ASSERT(srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
982     ASSERT(dstImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
983     ASSERT(regionCount == 1);
984     BlitImageParams *paramStruct = initCommand<BlitImageParams>(CommandID::BlitImage);
985     paramStruct->srcImage        = srcImage.getHandle();
986     paramStruct->dstImage        = dstImage.getHandle();
987     paramStruct->filter          = filter;
988     paramStruct->region          = regions[0];
989 }
990 
bufferBarrier(VkPipelineStageFlags srcStageMask,VkPipelineStageFlags dstStageMask,const VkBufferMemoryBarrier * bufferMemoryBarrier)991 ANGLE_INLINE void SecondaryCommandBuffer::bufferBarrier(
992     VkPipelineStageFlags srcStageMask,
993     VkPipelineStageFlags dstStageMask,
994     const VkBufferMemoryBarrier *bufferMemoryBarrier)
995 {
996     BufferBarrierParams *paramStruct = initCommand<BufferBarrierParams>(CommandID::BufferBarrier);
997     paramStruct->srcStageMask        = srcStageMask;
998     paramStruct->dstStageMask        = dstStageMask;
999     paramStruct->bufferMemoryBarrier = *bufferMemoryBarrier;
1000 }
1001 
clearAttachments(uint32_t attachmentCount,const VkClearAttachment * attachments,uint32_t rectCount,const VkClearRect * rects)1002 ANGLE_INLINE void SecondaryCommandBuffer::clearAttachments(uint32_t attachmentCount,
1003                                                            const VkClearAttachment *attachments,
1004                                                            uint32_t rectCount,
1005                                                            const VkClearRect *rects)
1006 {
1007     ASSERT(rectCount == 1);
1008     uint8_t *writePtr;
1009     size_t attachSize = attachmentCount * sizeof(VkClearAttachment);
1010     ClearAttachmentsParams *paramStruct =
1011         initCommand<ClearAttachmentsParams>(CommandID::ClearAttachments, attachSize, &writePtr);
1012     paramStruct->attachmentCount = attachmentCount;
1013     paramStruct->rect            = rects[0];
1014     // Copy variable sized data
1015     storePointerParameter(writePtr, attachments, attachSize);
1016 }
1017 
clearColorImage(const Image & image,VkImageLayout imageLayout,const VkClearColorValue & color,uint32_t rangeCount,const VkImageSubresourceRange * ranges)1018 ANGLE_INLINE void SecondaryCommandBuffer::clearColorImage(const Image &image,
1019                                                           VkImageLayout imageLayout,
1020                                                           const VkClearColorValue &color,
1021                                                           uint32_t rangeCount,
1022                                                           const VkImageSubresourceRange *ranges)
1023 {
1024     ASSERT(rangeCount == 1);
1025     ClearColorImageParams *paramStruct =
1026         initCommand<ClearColorImageParams>(CommandID::ClearColorImage);
1027     paramStruct->image       = image.getHandle();
1028     paramStruct->imageLayout = imageLayout;
1029     paramStruct->color       = color;
1030     paramStruct->range       = ranges[0];
1031 }
1032 
clearDepthStencilImage(const Image & image,VkImageLayout imageLayout,const VkClearDepthStencilValue & depthStencil,uint32_t rangeCount,const VkImageSubresourceRange * ranges)1033 ANGLE_INLINE void SecondaryCommandBuffer::clearDepthStencilImage(
1034     const Image &image,
1035     VkImageLayout imageLayout,
1036     const VkClearDepthStencilValue &depthStencil,
1037     uint32_t rangeCount,
1038     const VkImageSubresourceRange *ranges)
1039 {
1040     ASSERT(rangeCount == 1);
1041     ClearDepthStencilImageParams *paramStruct =
1042         initCommand<ClearDepthStencilImageParams>(CommandID::ClearDepthStencilImage);
1043     paramStruct->image        = image.getHandle();
1044     paramStruct->imageLayout  = imageLayout;
1045     paramStruct->depthStencil = depthStencil;
1046     paramStruct->range        = ranges[0];
1047 }
1048 
copyBuffer(const Buffer & srcBuffer,const Buffer & destBuffer,uint32_t regionCount,const VkBufferCopy * regions)1049 ANGLE_INLINE void SecondaryCommandBuffer::copyBuffer(const Buffer &srcBuffer,
1050                                                      const Buffer &destBuffer,
1051                                                      uint32_t regionCount,
1052                                                      const VkBufferCopy *regions)
1053 {
1054     uint8_t *writePtr;
1055     size_t regionSize = regionCount * sizeof(VkBufferCopy);
1056     CopyBufferParams *paramStruct =
1057         initCommand<CopyBufferParams>(CommandID::CopyBuffer, regionSize, &writePtr);
1058     paramStruct->srcBuffer   = srcBuffer.getHandle();
1059     paramStruct->destBuffer  = destBuffer.getHandle();
1060     paramStruct->regionCount = regionCount;
1061     // Copy variable sized data
1062     storePointerParameter(writePtr, regions, regionSize);
1063 }
1064 
copyBufferToImage(VkBuffer srcBuffer,const Image & dstImage,VkImageLayout dstImageLayout,uint32_t regionCount,const VkBufferImageCopy * regions)1065 ANGLE_INLINE void SecondaryCommandBuffer::copyBufferToImage(VkBuffer srcBuffer,
1066                                                             const Image &dstImage,
1067                                                             VkImageLayout dstImageLayout,
1068                                                             uint32_t regionCount,
1069                                                             const VkBufferImageCopy *regions)
1070 {
1071     ASSERT(regionCount == 1);
1072     CopyBufferToImageParams *paramStruct =
1073         initCommand<CopyBufferToImageParams>(CommandID::CopyBufferToImage);
1074     paramStruct->srcBuffer      = srcBuffer;
1075     paramStruct->dstImage       = dstImage.getHandle();
1076     paramStruct->dstImageLayout = dstImageLayout;
1077     paramStruct->region         = regions[0];
1078 }
1079 
copyImage(const Image & srcImage,VkImageLayout srcImageLayout,const Image & dstImage,VkImageLayout dstImageLayout,uint32_t regionCount,const VkImageCopy * regions)1080 ANGLE_INLINE void SecondaryCommandBuffer::copyImage(const Image &srcImage,
1081                                                     VkImageLayout srcImageLayout,
1082                                                     const Image &dstImage,
1083                                                     VkImageLayout dstImageLayout,
1084                                                     uint32_t regionCount,
1085                                                     const VkImageCopy *regions)
1086 {
1087     ASSERT(regionCount == 1);
1088     CopyImageParams *paramStruct = initCommand<CopyImageParams>(CommandID::CopyImage);
1089     paramStruct->srcImage        = srcImage.getHandle();
1090     paramStruct->srcImageLayout  = srcImageLayout;
1091     paramStruct->dstImage        = dstImage.getHandle();
1092     paramStruct->dstImageLayout  = dstImageLayout;
1093     paramStruct->region          = regions[0];
1094 }
1095 
copyImageToBuffer(const Image & srcImage,VkImageLayout srcImageLayout,VkBuffer dstBuffer,uint32_t regionCount,const VkBufferImageCopy * regions)1096 ANGLE_INLINE void SecondaryCommandBuffer::copyImageToBuffer(const Image &srcImage,
1097                                                             VkImageLayout srcImageLayout,
1098                                                             VkBuffer dstBuffer,
1099                                                             uint32_t regionCount,
1100                                                             const VkBufferImageCopy *regions)
1101 {
1102     ASSERT(regionCount == 1);
1103     CopyImageToBufferParams *paramStruct =
1104         initCommand<CopyImageToBufferParams>(CommandID::CopyImageToBuffer);
1105     paramStruct->srcImage       = srcImage.getHandle();
1106     paramStruct->srcImageLayout = srcImageLayout;
1107     paramStruct->dstBuffer      = dstBuffer;
1108     paramStruct->region         = regions[0];
1109 }
1110 
dispatch(uint32_t groupCountX,uint32_t groupCountY,uint32_t groupCountZ)1111 ANGLE_INLINE void SecondaryCommandBuffer::dispatch(uint32_t groupCountX,
1112                                                    uint32_t groupCountY,
1113                                                    uint32_t groupCountZ)
1114 {
1115     DispatchParams *paramStruct = initCommand<DispatchParams>(CommandID::Dispatch);
1116     paramStruct->groupCountX    = groupCountX;
1117     paramStruct->groupCountY    = groupCountY;
1118     paramStruct->groupCountZ    = groupCountZ;
1119 }
1120 
dispatchIndirect(const Buffer & buffer,VkDeviceSize offset)1121 ANGLE_INLINE void SecondaryCommandBuffer::dispatchIndirect(const Buffer &buffer,
1122                                                            VkDeviceSize offset)
1123 {
1124     DispatchIndirectParams *paramStruct =
1125         initCommand<DispatchIndirectParams>(CommandID::DispatchIndirect);
1126     paramStruct->buffer = buffer.getHandle();
1127     paramStruct->offset = offset;
1128 }
1129 
draw(uint32_t vertexCount,uint32_t firstVertex)1130 ANGLE_INLINE void SecondaryCommandBuffer::draw(uint32_t vertexCount, uint32_t firstVertex)
1131 {
1132     DrawParams *paramStruct  = initCommand<DrawParams>(CommandID::Draw);
1133     paramStruct->vertexCount = vertexCount;
1134     paramStruct->firstVertex = firstVertex;
1135 }
1136 
drawIndexed(uint32_t indexCount)1137 ANGLE_INLINE void SecondaryCommandBuffer::drawIndexed(uint32_t indexCount)
1138 {
1139     DrawIndexedParams *paramStruct = initCommand<DrawIndexedParams>(CommandID::DrawIndexed);
1140     paramStruct->indexCount        = indexCount;
1141 }
1142 
drawIndexedBaseVertex(uint32_t indexCount,uint32_t vertexOffset)1143 ANGLE_INLINE void SecondaryCommandBuffer::drawIndexedBaseVertex(uint32_t indexCount,
1144                                                                 uint32_t vertexOffset)
1145 {
1146     DrawIndexedBaseVertexParams *paramStruct =
1147         initCommand<DrawIndexedBaseVertexParams>(CommandID::DrawIndexedBaseVertex);
1148     paramStruct->indexCount   = indexCount;
1149     paramStruct->vertexOffset = vertexOffset;
1150 }
1151 
drawIndexedIndirect(const Buffer & buffer,VkDeviceSize offset,uint32_t drawCount,uint32_t stride)1152 ANGLE_INLINE void SecondaryCommandBuffer::drawIndexedIndirect(const Buffer &buffer,
1153                                                               VkDeviceSize offset,
1154                                                               uint32_t drawCount,
1155                                                               uint32_t stride)
1156 {
1157     DrawIndexedIndirectParams *paramStruct =
1158         initCommand<DrawIndexedIndirectParams>(CommandID::DrawIndexedIndirect);
1159     paramStruct->buffer = buffer.getHandle();
1160     paramStruct->offset = offset;
1161     ASSERT(drawCount == 1);
1162 }
1163 
drawIndexedInstanced(uint32_t indexCount,uint32_t instanceCount)1164 ANGLE_INLINE void SecondaryCommandBuffer::drawIndexedInstanced(uint32_t indexCount,
1165                                                                uint32_t instanceCount)
1166 {
1167     DrawIndexedInstancedParams *paramStruct =
1168         initCommand<DrawIndexedInstancedParams>(CommandID::DrawIndexedInstanced);
1169     paramStruct->indexCount    = indexCount;
1170     paramStruct->instanceCount = instanceCount;
1171 }
1172 
drawIndexedInstancedBaseVertex(uint32_t indexCount,uint32_t instanceCount,uint32_t vertexOffset)1173 ANGLE_INLINE void SecondaryCommandBuffer::drawIndexedInstancedBaseVertex(uint32_t indexCount,
1174                                                                          uint32_t instanceCount,
1175                                                                          uint32_t vertexOffset)
1176 {
1177     DrawIndexedInstancedBaseVertexParams *paramStruct =
1178         initCommand<DrawIndexedInstancedBaseVertexParams>(
1179             CommandID::DrawIndexedInstancedBaseVertex);
1180     paramStruct->indexCount    = indexCount;
1181     paramStruct->instanceCount = instanceCount;
1182     paramStruct->vertexOffset  = vertexOffset;
1183 }
1184 
drawIndexedInstancedBaseVertexBaseInstance(uint32_t indexCount,uint32_t instanceCount,uint32_t firstIndex,int32_t vertexOffset,uint32_t firstInstance)1185 ANGLE_INLINE void SecondaryCommandBuffer::drawIndexedInstancedBaseVertexBaseInstance(
1186     uint32_t indexCount,
1187     uint32_t instanceCount,
1188     uint32_t firstIndex,
1189     int32_t vertexOffset,
1190     uint32_t firstInstance)
1191 {
1192     DrawIndexedInstancedBaseVertexBaseInstanceParams *paramStruct =
1193         initCommand<DrawIndexedInstancedBaseVertexBaseInstanceParams>(
1194             CommandID::DrawIndexedInstancedBaseVertexBaseInstance);
1195     paramStruct->indexCount    = indexCount;
1196     paramStruct->instanceCount = instanceCount;
1197     paramStruct->firstIndex    = firstIndex;
1198     paramStruct->vertexOffset  = vertexOffset;
1199     paramStruct->firstInstance = firstInstance;
1200 }
1201 
drawIndirect(const Buffer & buffer,VkDeviceSize offset,uint32_t drawCount,uint32_t stride)1202 ANGLE_INLINE void SecondaryCommandBuffer::drawIndirect(const Buffer &buffer,
1203                                                        VkDeviceSize offset,
1204                                                        uint32_t drawCount,
1205                                                        uint32_t stride)
1206 {
1207     DrawIndirectParams *paramStruct = initCommand<DrawIndirectParams>(CommandID::DrawIndirect);
1208     paramStruct->buffer             = buffer.getHandle();
1209     paramStruct->offset             = offset;
1210 
1211     // OpenGL ES doesn't have a way to specify a drawCount or stride, throw assert if something
1212     // changes.
1213     ASSERT(drawCount == 1);
1214 }
1215 
drawInstanced(uint32_t vertexCount,uint32_t instanceCount,uint32_t firstVertex)1216 ANGLE_INLINE void SecondaryCommandBuffer::drawInstanced(uint32_t vertexCount,
1217                                                         uint32_t instanceCount,
1218                                                         uint32_t firstVertex)
1219 {
1220     DrawInstancedParams *paramStruct = initCommand<DrawInstancedParams>(CommandID::DrawInstanced);
1221     paramStruct->vertexCount         = vertexCount;
1222     paramStruct->instanceCount       = instanceCount;
1223     paramStruct->firstVertex         = firstVertex;
1224 }
1225 
drawInstancedBaseInstance(uint32_t vertexCount,uint32_t instanceCount,uint32_t firstVertex,uint32_t firstInstance)1226 ANGLE_INLINE void SecondaryCommandBuffer::drawInstancedBaseInstance(uint32_t vertexCount,
1227                                                                     uint32_t instanceCount,
1228                                                                     uint32_t firstVertex,
1229                                                                     uint32_t firstInstance)
1230 {
1231     DrawInstancedBaseInstanceParams *paramStruct =
1232         initCommand<DrawInstancedBaseInstanceParams>(CommandID::DrawInstancedBaseInstance);
1233     paramStruct->vertexCount   = vertexCount;
1234     paramStruct->instanceCount = instanceCount;
1235     paramStruct->firstVertex   = firstVertex;
1236     paramStruct->firstInstance = firstInstance;
1237 }
1238 
endDebugUtilsLabelEXT()1239 ANGLE_INLINE void SecondaryCommandBuffer::endDebugUtilsLabelEXT()
1240 {
1241     initCommand<EmptyParams>(CommandID::EndDebugUtilsLabel);
1242 }
1243 
endQuery(const QueryPool & queryPool,uint32_t query)1244 ANGLE_INLINE void SecondaryCommandBuffer::endQuery(const QueryPool &queryPool, uint32_t query)
1245 {
1246     EndQueryParams *paramStruct = initCommand<EndQueryParams>(CommandID::EndQuery);
1247     paramStruct->queryPool      = queryPool.getHandle();
1248     paramStruct->query          = query;
1249 }
1250 
endTransformFeedback(uint32_t firstCounterBuffer,uint32_t counterBufferCount,const VkBuffer * counterBuffers,const VkDeviceSize * counterBufferOffsets)1251 ANGLE_INLINE void SecondaryCommandBuffer::endTransformFeedback(
1252     uint32_t firstCounterBuffer,
1253     uint32_t counterBufferCount,
1254     const VkBuffer *counterBuffers,
1255     const VkDeviceSize *counterBufferOffsets)
1256 {
1257     ASSERT(firstCounterBuffer == 0);
1258     ASSERT(counterBufferOffsets == nullptr);
1259     uint8_t *writePtr;
1260     size_t bufferSize                       = counterBufferCount * sizeof(VkBuffer);
1261     EndTransformFeedbackParams *paramStruct = initCommand<EndTransformFeedbackParams>(
1262         CommandID::EndTransformFeedback, bufferSize, &writePtr);
1263     paramStruct->bufferCount = counterBufferCount;
1264     storePointerParameter(writePtr, counterBuffers, bufferSize);
1265 }
1266 
executionBarrier(VkPipelineStageFlags stageMask)1267 ANGLE_INLINE void SecondaryCommandBuffer::executionBarrier(VkPipelineStageFlags stageMask)
1268 {
1269     ExecutionBarrierParams *paramStruct =
1270         initCommand<ExecutionBarrierParams>(CommandID::ExecutionBarrier);
1271     paramStruct->stageMask = stageMask;
1272 }
1273 
fillBuffer(const Buffer & dstBuffer,VkDeviceSize dstOffset,VkDeviceSize size,uint32_t data)1274 ANGLE_INLINE void SecondaryCommandBuffer::fillBuffer(const Buffer &dstBuffer,
1275                                                      VkDeviceSize dstOffset,
1276                                                      VkDeviceSize size,
1277                                                      uint32_t data)
1278 {
1279     FillBufferParams *paramStruct = initCommand<FillBufferParams>(CommandID::FillBuffer);
1280     paramStruct->dstBuffer        = dstBuffer.getHandle();
1281     paramStruct->dstOffset        = dstOffset;
1282     paramStruct->size             = size;
1283     paramStruct->data             = data;
1284 }
1285 
imageBarrier(VkPipelineStageFlags srcStageMask,VkPipelineStageFlags dstStageMask,const VkImageMemoryBarrier & imageMemoryBarrier)1286 ANGLE_INLINE void SecondaryCommandBuffer::imageBarrier(
1287     VkPipelineStageFlags srcStageMask,
1288     VkPipelineStageFlags dstStageMask,
1289     const VkImageMemoryBarrier &imageMemoryBarrier)
1290 {
1291     ImageBarrierParams *paramStruct = initCommand<ImageBarrierParams>(CommandID::ImageBarrier);
1292     ASSERT(imageMemoryBarrier.pNext == nullptr);
1293     paramStruct->srcStageMask       = srcStageMask;
1294     paramStruct->dstStageMask       = dstStageMask;
1295     paramStruct->imageMemoryBarrier = imageMemoryBarrier;
1296 }
1297 
insertDebugUtilsLabelEXT(const VkDebugUtilsLabelEXT & label)1298 ANGLE_INLINE void SecondaryCommandBuffer::insertDebugUtilsLabelEXT(
1299     const VkDebugUtilsLabelEXT &label)
1300 {
1301     commonDebugUtilsLabel(CommandID::InsertDebugUtilsLabel, label);
1302 }
1303 
memoryBarrier(VkPipelineStageFlags srcStageMask,VkPipelineStageFlags dstStageMask,const VkMemoryBarrier * memoryBarrier)1304 ANGLE_INLINE void SecondaryCommandBuffer::memoryBarrier(VkPipelineStageFlags srcStageMask,
1305                                                         VkPipelineStageFlags dstStageMask,
1306                                                         const VkMemoryBarrier *memoryBarrier)
1307 {
1308     MemoryBarrierParams *paramStruct = initCommand<MemoryBarrierParams>(CommandID::MemoryBarrier);
1309     paramStruct->srcStageMask        = srcStageMask;
1310     paramStruct->dstStageMask        = dstStageMask;
1311     paramStruct->memoryBarrier       = *memoryBarrier;
1312 }
1313 
nextSubpass(VkSubpassContents subpassContents)1314 ANGLE_INLINE void SecondaryCommandBuffer::nextSubpass(VkSubpassContents subpassContents)
1315 {
1316     NextSubpassParams *paramStruct = initCommand<NextSubpassParams>(CommandID::NextSubpass);
1317     paramStruct->subpassContents   = subpassContents;
1318 }
1319 
pipelineBarrier(VkPipelineStageFlags srcStageMask,VkPipelineStageFlags dstStageMask,VkDependencyFlags dependencyFlags,uint32_t memoryBarrierCount,const VkMemoryBarrier * memoryBarriers,uint32_t bufferMemoryBarrierCount,const VkBufferMemoryBarrier * bufferMemoryBarriers,uint32_t imageMemoryBarrierCount,const VkImageMemoryBarrier * imageMemoryBarriers)1320 ANGLE_INLINE void SecondaryCommandBuffer::pipelineBarrier(
1321     VkPipelineStageFlags srcStageMask,
1322     VkPipelineStageFlags dstStageMask,
1323     VkDependencyFlags dependencyFlags,
1324     uint32_t memoryBarrierCount,
1325     const VkMemoryBarrier *memoryBarriers,
1326     uint32_t bufferMemoryBarrierCount,
1327     const VkBufferMemoryBarrier *bufferMemoryBarriers,
1328     uint32_t imageMemoryBarrierCount,
1329     const VkImageMemoryBarrier *imageMemoryBarriers)
1330 {
1331     uint8_t *writePtr;
1332     size_t memBarrierSize              = memoryBarrierCount * sizeof(VkMemoryBarrier);
1333     size_t buffBarrierSize             = bufferMemoryBarrierCount * sizeof(VkBufferMemoryBarrier);
1334     size_t imgBarrierSize              = imageMemoryBarrierCount * sizeof(VkImageMemoryBarrier);
1335     PipelineBarrierParams *paramStruct = initCommand<PipelineBarrierParams>(
1336         CommandID::PipelineBarrier, memBarrierSize + buffBarrierSize + imgBarrierSize, &writePtr);
1337     paramStruct->srcStageMask             = srcStageMask;
1338     paramStruct->dstStageMask             = dstStageMask;
1339     paramStruct->dependencyFlags          = dependencyFlags;
1340     paramStruct->memoryBarrierCount       = memoryBarrierCount;
1341     paramStruct->bufferMemoryBarrierCount = bufferMemoryBarrierCount;
1342     paramStruct->imageMemoryBarrierCount  = imageMemoryBarrierCount;
1343     // Copy variable sized data
1344     writePtr = storePointerParameter(writePtr, memoryBarriers, memBarrierSize);
1345     writePtr = storePointerParameter(writePtr, bufferMemoryBarriers, buffBarrierSize);
1346     storePointerParameter(writePtr, imageMemoryBarriers, imgBarrierSize);
1347 }
1348 
pushConstants(const PipelineLayout & layout,VkShaderStageFlags flag,uint32_t offset,uint32_t size,const void * data)1349 ANGLE_INLINE void SecondaryCommandBuffer::pushConstants(const PipelineLayout &layout,
1350                                                         VkShaderStageFlags flag,
1351                                                         uint32_t offset,
1352                                                         uint32_t size,
1353                                                         const void *data)
1354 {
1355     ASSERT(size == static_cast<size_t>(size));
1356     uint8_t *writePtr;
1357     PushConstantsParams *paramStruct = initCommand<PushConstantsParams>(
1358         CommandID::PushConstants, static_cast<size_t>(size), &writePtr);
1359     paramStruct->layout = layout.getHandle();
1360     paramStruct->flag   = flag;
1361     paramStruct->offset = offset;
1362     paramStruct->size   = size;
1363     // Copy variable sized data
1364     storePointerParameter(writePtr, data, static_cast<size_t>(size));
1365 }
1366 
resetEvent(VkEvent event,VkPipelineStageFlags stageMask)1367 ANGLE_INLINE void SecondaryCommandBuffer::resetEvent(VkEvent event, VkPipelineStageFlags stageMask)
1368 {
1369     ResetEventParams *paramStruct = initCommand<ResetEventParams>(CommandID::ResetEvent);
1370     paramStruct->event            = event;
1371     paramStruct->stageMask        = stageMask;
1372 }
1373 
resetQueryPool(const QueryPool & queryPool,uint32_t firstQuery,uint32_t queryCount)1374 ANGLE_INLINE void SecondaryCommandBuffer::resetQueryPool(const QueryPool &queryPool,
1375                                                          uint32_t firstQuery,
1376                                                          uint32_t queryCount)
1377 {
1378     ResetQueryPoolParams *paramStruct =
1379         initCommand<ResetQueryPoolParams>(CommandID::ResetQueryPool);
1380     paramStruct->queryPool  = queryPool.getHandle();
1381     paramStruct->firstQuery = firstQuery;
1382     paramStruct->queryCount = queryCount;
1383 }
1384 
resolveImage(const Image & srcImage,VkImageLayout srcImageLayout,const Image & dstImage,VkImageLayout dstImageLayout,uint32_t regionCount,const VkImageResolve * regions)1385 ANGLE_INLINE void SecondaryCommandBuffer::resolveImage(const Image &srcImage,
1386                                                        VkImageLayout srcImageLayout,
1387                                                        const Image &dstImage,
1388                                                        VkImageLayout dstImageLayout,
1389                                                        uint32_t regionCount,
1390                                                        const VkImageResolve *regions)
1391 {
1392     // Currently ANGLE uses limited params so verify those assumptions and update if they change.
1393     ASSERT(srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
1394     ASSERT(dstImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
1395     ASSERT(regionCount == 1);
1396     ResolveImageParams *paramStruct = initCommand<ResolveImageParams>(CommandID::ResolveImage);
1397     paramStruct->srcImage           = srcImage.getHandle();
1398     paramStruct->dstImage           = dstImage.getHandle();
1399     paramStruct->region             = regions[0];
1400 }
1401 
setEvent(VkEvent event,VkPipelineStageFlags stageMask)1402 ANGLE_INLINE void SecondaryCommandBuffer::setEvent(VkEvent event, VkPipelineStageFlags stageMask)
1403 {
1404     SetEventParams *paramStruct = initCommand<SetEventParams>(CommandID::SetEvent);
1405     paramStruct->event          = event;
1406     paramStruct->stageMask      = stageMask;
1407 }
1408 
setScissor(uint32_t firstScissor,uint32_t scissorCount,const VkRect2D * scissors)1409 ANGLE_INLINE void SecondaryCommandBuffer::setScissor(uint32_t firstScissor,
1410                                                      uint32_t scissorCount,
1411                                                      const VkRect2D *scissors)
1412 {
1413     ASSERT(firstScissor == 0);
1414     ASSERT(scissorCount == 1);
1415     ASSERT(scissors != nullptr);
1416     SetScissorParams *paramStruct = initCommand<SetScissorParams>(CommandID::SetScissor);
1417     paramStruct->scissor          = scissors[0];
1418 }
1419 
setViewport(uint32_t firstViewport,uint32_t viewportCount,const VkViewport * viewports)1420 ANGLE_INLINE void SecondaryCommandBuffer::setViewport(uint32_t firstViewport,
1421                                                       uint32_t viewportCount,
1422                                                       const VkViewport *viewports)
1423 {
1424     ASSERT(firstViewport == 0);
1425     ASSERT(viewportCount == 1);
1426     ASSERT(viewports != nullptr);
1427     SetViewportParams *paramStruct = initCommand<SetViewportParams>(CommandID::SetViewport);
1428     paramStruct->viewport          = viewports[0];
1429 }
1430 
waitEvents(uint32_t eventCount,const VkEvent * events,VkPipelineStageFlags srcStageMask,VkPipelineStageFlags dstStageMask,uint32_t memoryBarrierCount,const VkMemoryBarrier * memoryBarriers,uint32_t bufferMemoryBarrierCount,const VkBufferMemoryBarrier * bufferMemoryBarriers,uint32_t imageMemoryBarrierCount,const VkImageMemoryBarrier * imageMemoryBarriers)1431 ANGLE_INLINE void SecondaryCommandBuffer::waitEvents(
1432     uint32_t eventCount,
1433     const VkEvent *events,
1434     VkPipelineStageFlags srcStageMask,
1435     VkPipelineStageFlags dstStageMask,
1436     uint32_t memoryBarrierCount,
1437     const VkMemoryBarrier *memoryBarriers,
1438     uint32_t bufferMemoryBarrierCount,
1439     const VkBufferMemoryBarrier *bufferMemoryBarriers,
1440     uint32_t imageMemoryBarrierCount,
1441     const VkImageMemoryBarrier *imageMemoryBarriers)
1442 {
1443     uint8_t *writePtr;
1444     size_t eventSize              = eventCount * sizeof(VkEvent);
1445     size_t memBarrierSize         = memoryBarrierCount * sizeof(VkMemoryBarrier);
1446     size_t buffBarrierSize        = bufferMemoryBarrierCount * sizeof(VkBufferMemoryBarrier);
1447     size_t imgBarrierSize         = imageMemoryBarrierCount * sizeof(VkImageMemoryBarrier);
1448     WaitEventsParams *paramStruct = initCommand<WaitEventsParams>(
1449         CommandID::WaitEvents, eventSize + memBarrierSize + buffBarrierSize + imgBarrierSize,
1450         &writePtr);
1451     paramStruct->eventCount               = eventCount;
1452     paramStruct->srcStageMask             = srcStageMask;
1453     paramStruct->dstStageMask             = dstStageMask;
1454     paramStruct->memoryBarrierCount       = memoryBarrierCount;
1455     paramStruct->bufferMemoryBarrierCount = bufferMemoryBarrierCount;
1456     paramStruct->imageMemoryBarrierCount  = imageMemoryBarrierCount;
1457     // Copy variable sized data
1458     writePtr = storePointerParameter(writePtr, events, eventSize);
1459     writePtr = storePointerParameter(writePtr, memoryBarriers, memBarrierSize);
1460     writePtr = storePointerParameter(writePtr, bufferMemoryBarriers, buffBarrierSize);
1461     storePointerParameter(writePtr, imageMemoryBarriers, imgBarrierSize);
1462 }
1463 
writeTimestamp(VkPipelineStageFlagBits pipelineStage,const QueryPool & queryPool,uint32_t query)1464 ANGLE_INLINE void SecondaryCommandBuffer::writeTimestamp(VkPipelineStageFlagBits pipelineStage,
1465                                                          const QueryPool &queryPool,
1466                                                          uint32_t query)
1467 {
1468     WriteTimestampParams *paramStruct =
1469         initCommand<WriteTimestampParams>(CommandID::WriteTimestamp);
1470     paramStruct->pipelineStage = pipelineStage;
1471     paramStruct->queryPool     = queryPool.getHandle();
1472     paramStruct->query         = query;
1473 }
1474 }  // namespace priv
1475 }  // namespace vk
1476 }  // namespace rx
1477 
1478 #endif  // LIBANGLE_RENDERER_VULKAN_SECONDARYCOMMANDBUFFERVK_H_
1479