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