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