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