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