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