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