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 ASSERT(counterBufferOffsets == nullptr);
903 uint8_t *writePtr;
904 size_t bufferSize = bufferCount * sizeof(VkBuffer);
905 BeginTransformFeedbackParams *paramStruct = initCommand<BeginTransformFeedbackParams>(
906 CommandID::BeginTransformFeedback, bufferSize, &writePtr);
907 paramStruct->bufferCount = bufferCount;
908 storePointerParameter(writePtr, counterBuffers, bufferSize);
909 }
910
bindComputePipeline(const Pipeline & pipeline)911 ANGLE_INLINE void SecondaryCommandBuffer::bindComputePipeline(const Pipeline &pipeline)
912 {
913 BindPipelineParams *paramStruct =
914 initCommand<BindPipelineParams>(CommandID::BindComputePipeline);
915 paramStruct->pipeline = pipeline.getHandle();
916 }
917
bindDescriptorSets(const PipelineLayout & layout,VkPipelineBindPoint pipelineBindPoint,DescriptorSetIndex firstSet,uint32_t descriptorSetCount,const VkDescriptorSet * descriptorSets,uint32_t dynamicOffsetCount,const uint32_t * dynamicOffsets)918 ANGLE_INLINE void SecondaryCommandBuffer::bindDescriptorSets(const PipelineLayout &layout,
919 VkPipelineBindPoint pipelineBindPoint,
920 DescriptorSetIndex firstSet,
921 uint32_t descriptorSetCount,
922 const VkDescriptorSet *descriptorSets,
923 uint32_t dynamicOffsetCount,
924 const uint32_t *dynamicOffsets)
925 {
926 size_t descSize = descriptorSetCount * sizeof(VkDescriptorSet);
927 size_t offsetSize = dynamicOffsetCount * sizeof(uint32_t);
928 uint8_t *writePtr;
929 BindDescriptorSetParams *paramStruct = initCommand<BindDescriptorSetParams>(
930 CommandID::BindDescriptorSets, descSize + offsetSize, &writePtr);
931 // Copy params into memory
932 paramStruct->layout = layout.getHandle();
933 paramStruct->pipelineBindPoint = pipelineBindPoint;
934 paramStruct->firstSet = ToUnderlying(firstSet);
935 paramStruct->descriptorSetCount = descriptorSetCount;
936 paramStruct->dynamicOffsetCount = dynamicOffsetCount;
937 // Copy variable sized data
938 writePtr = storePointerParameter(writePtr, descriptorSets, descSize);
939 storePointerParameter(writePtr, dynamicOffsets, offsetSize);
940 }
941
bindGraphicsPipeline(const Pipeline & pipeline)942 ANGLE_INLINE void SecondaryCommandBuffer::bindGraphicsPipeline(const Pipeline &pipeline)
943 {
944 BindPipelineParams *paramStruct =
945 initCommand<BindPipelineParams>(CommandID::BindGraphicsPipeline);
946 paramStruct->pipeline = pipeline.getHandle();
947 }
948
bindIndexBuffer(const Buffer & buffer,VkDeviceSize offset,VkIndexType indexType)949 ANGLE_INLINE void SecondaryCommandBuffer::bindIndexBuffer(const Buffer &buffer,
950 VkDeviceSize offset,
951 VkIndexType indexType)
952 {
953 BindIndexBufferParams *paramStruct =
954 initCommand<BindIndexBufferParams>(CommandID::BindIndexBuffer);
955 paramStruct->buffer = buffer.getHandle();
956 paramStruct->offset = offset;
957 paramStruct->indexType = indexType;
958 }
959
bindTransformFeedbackBuffers(uint32_t firstBinding,uint32_t bindingCount,const VkBuffer * buffers,const VkDeviceSize * offsets,const VkDeviceSize * sizes)960 ANGLE_INLINE void SecondaryCommandBuffer::bindTransformFeedbackBuffers(uint32_t firstBinding,
961 uint32_t bindingCount,
962 const VkBuffer *buffers,
963 const VkDeviceSize *offsets,
964 const VkDeviceSize *sizes)
965 {
966 ASSERT(firstBinding == 0);
967 uint8_t *writePtr;
968 size_t buffersSize = bindingCount * sizeof(VkBuffer);
969 size_t offsetsSize = bindingCount * sizeof(VkDeviceSize);
970 size_t sizesSize = offsetsSize;
971 BindTransformFeedbackBuffersParams *paramStruct =
972 initCommand<BindTransformFeedbackBuffersParams>(CommandID::BindTransformFeedbackBuffers,
973 buffersSize + offsetsSize + sizesSize,
974 &writePtr);
975 // Copy params
976 paramStruct->bindingCount = bindingCount;
977 writePtr = storePointerParameter(writePtr, buffers, buffersSize);
978 writePtr = storePointerParameter(writePtr, offsets, offsetsSize);
979 storePointerParameter(writePtr, sizes, sizesSize);
980 }
981
bindVertexBuffers(uint32_t firstBinding,uint32_t bindingCount,const VkBuffer * buffers,const VkDeviceSize * offsets)982 ANGLE_INLINE void SecondaryCommandBuffer::bindVertexBuffers(uint32_t firstBinding,
983 uint32_t bindingCount,
984 const VkBuffer *buffers,
985 const VkDeviceSize *offsets)
986 {
987 ASSERT(firstBinding == 0);
988 uint8_t *writePtr;
989 size_t buffersSize = bindingCount * sizeof(VkBuffer);
990 size_t offsetsSize = bindingCount * sizeof(VkDeviceSize);
991 BindVertexBuffersParams *paramStruct = initCommand<BindVertexBuffersParams>(
992 CommandID::BindVertexBuffers, buffersSize + offsetsSize, &writePtr);
993 // Copy params
994 paramStruct->bindingCount = bindingCount;
995 writePtr = storePointerParameter(writePtr, buffers, buffersSize);
996 storePointerParameter(writePtr, offsets, offsetsSize);
997 }
998
blitImage(const Image & srcImage,VkImageLayout srcImageLayout,const Image & dstImage,VkImageLayout dstImageLayout,uint32_t regionCount,const VkImageBlit * regions,VkFilter filter)999 ANGLE_INLINE void SecondaryCommandBuffer::blitImage(const Image &srcImage,
1000 VkImageLayout srcImageLayout,
1001 const Image &dstImage,
1002 VkImageLayout dstImageLayout,
1003 uint32_t regionCount,
1004 const VkImageBlit *regions,
1005 VkFilter filter)
1006 {
1007 // Currently ANGLE uses limited params so verify those assumptions and update if they change
1008 ASSERT(srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
1009 ASSERT(dstImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
1010 ASSERT(regionCount == 1);
1011 BlitImageParams *paramStruct = initCommand<BlitImageParams>(CommandID::BlitImage);
1012 paramStruct->srcImage = srcImage.getHandle();
1013 paramStruct->dstImage = dstImage.getHandle();
1014 paramStruct->filter = filter;
1015 paramStruct->region = regions[0];
1016 }
1017
bufferBarrier(VkPipelineStageFlags srcStageMask,VkPipelineStageFlags dstStageMask,const VkBufferMemoryBarrier * bufferMemoryBarrier)1018 ANGLE_INLINE void SecondaryCommandBuffer::bufferBarrier(
1019 VkPipelineStageFlags srcStageMask,
1020 VkPipelineStageFlags dstStageMask,
1021 const VkBufferMemoryBarrier *bufferMemoryBarrier)
1022 {
1023 BufferBarrierParams *paramStruct = initCommand<BufferBarrierParams>(CommandID::BufferBarrier);
1024 paramStruct->srcStageMask = srcStageMask;
1025 paramStruct->dstStageMask = dstStageMask;
1026 paramStruct->bufferMemoryBarrier = *bufferMemoryBarrier;
1027 }
1028
clearAttachments(uint32_t attachmentCount,const VkClearAttachment * attachments,uint32_t rectCount,const VkClearRect * rects)1029 ANGLE_INLINE void SecondaryCommandBuffer::clearAttachments(uint32_t attachmentCount,
1030 const VkClearAttachment *attachments,
1031 uint32_t rectCount,
1032 const VkClearRect *rects)
1033 {
1034 ASSERT(rectCount == 1);
1035 uint8_t *writePtr;
1036 size_t attachSize = attachmentCount * sizeof(VkClearAttachment);
1037 ClearAttachmentsParams *paramStruct =
1038 initCommand<ClearAttachmentsParams>(CommandID::ClearAttachments, attachSize, &writePtr);
1039 paramStruct->attachmentCount = attachmentCount;
1040 paramStruct->rect = rects[0];
1041 // Copy variable sized data
1042 storePointerParameter(writePtr, attachments, attachSize);
1043
1044 mCommandTracker.onClearAttachments();
1045 }
1046
clearColorImage(const Image & image,VkImageLayout imageLayout,const VkClearColorValue & color,uint32_t rangeCount,const VkImageSubresourceRange * ranges)1047 ANGLE_INLINE void SecondaryCommandBuffer::clearColorImage(const Image &image,
1048 VkImageLayout imageLayout,
1049 const VkClearColorValue &color,
1050 uint32_t rangeCount,
1051 const VkImageSubresourceRange *ranges)
1052 {
1053 ASSERT(rangeCount == 1);
1054 ClearColorImageParams *paramStruct =
1055 initCommand<ClearColorImageParams>(CommandID::ClearColorImage);
1056 paramStruct->image = image.getHandle();
1057 paramStruct->imageLayout = imageLayout;
1058 paramStruct->color = color;
1059 paramStruct->range = ranges[0];
1060 }
1061
clearDepthStencilImage(const Image & image,VkImageLayout imageLayout,const VkClearDepthStencilValue & depthStencil,uint32_t rangeCount,const VkImageSubresourceRange * ranges)1062 ANGLE_INLINE void SecondaryCommandBuffer::clearDepthStencilImage(
1063 const Image &image,
1064 VkImageLayout imageLayout,
1065 const VkClearDepthStencilValue &depthStencil,
1066 uint32_t rangeCount,
1067 const VkImageSubresourceRange *ranges)
1068 {
1069 ASSERT(rangeCount == 1);
1070 ClearDepthStencilImageParams *paramStruct =
1071 initCommand<ClearDepthStencilImageParams>(CommandID::ClearDepthStencilImage);
1072 paramStruct->image = image.getHandle();
1073 paramStruct->imageLayout = imageLayout;
1074 paramStruct->depthStencil = depthStencil;
1075 paramStruct->range = ranges[0];
1076 }
1077
copyBuffer(const Buffer & srcBuffer,const Buffer & destBuffer,uint32_t regionCount,const VkBufferCopy * regions)1078 ANGLE_INLINE void SecondaryCommandBuffer::copyBuffer(const Buffer &srcBuffer,
1079 const Buffer &destBuffer,
1080 uint32_t regionCount,
1081 const VkBufferCopy *regions)
1082 {
1083 uint8_t *writePtr;
1084 size_t regionSize = regionCount * sizeof(VkBufferCopy);
1085 CopyBufferParams *paramStruct =
1086 initCommand<CopyBufferParams>(CommandID::CopyBuffer, regionSize, &writePtr);
1087 paramStruct->srcBuffer = srcBuffer.getHandle();
1088 paramStruct->destBuffer = destBuffer.getHandle();
1089 paramStruct->regionCount = regionCount;
1090 // Copy variable sized data
1091 storePointerParameter(writePtr, regions, regionSize);
1092 }
1093
copyBufferToImage(VkBuffer srcBuffer,const Image & dstImage,VkImageLayout dstImageLayout,uint32_t regionCount,const VkBufferImageCopy * regions)1094 ANGLE_INLINE void SecondaryCommandBuffer::copyBufferToImage(VkBuffer srcBuffer,
1095 const Image &dstImage,
1096 VkImageLayout dstImageLayout,
1097 uint32_t regionCount,
1098 const VkBufferImageCopy *regions)
1099 {
1100 ASSERT(regionCount == 1);
1101 CopyBufferToImageParams *paramStruct =
1102 initCommand<CopyBufferToImageParams>(CommandID::CopyBufferToImage);
1103 paramStruct->srcBuffer = srcBuffer;
1104 paramStruct->dstImage = dstImage.getHandle();
1105 paramStruct->dstImageLayout = dstImageLayout;
1106 paramStruct->region = regions[0];
1107 }
1108
copyImage(const Image & srcImage,VkImageLayout srcImageLayout,const Image & dstImage,VkImageLayout dstImageLayout,uint32_t regionCount,const VkImageCopy * regions)1109 ANGLE_INLINE void SecondaryCommandBuffer::copyImage(const Image &srcImage,
1110 VkImageLayout srcImageLayout,
1111 const Image &dstImage,
1112 VkImageLayout dstImageLayout,
1113 uint32_t regionCount,
1114 const VkImageCopy *regions)
1115 {
1116 ASSERT(regionCount == 1);
1117 CopyImageParams *paramStruct = initCommand<CopyImageParams>(CommandID::CopyImage);
1118 paramStruct->srcImage = srcImage.getHandle();
1119 paramStruct->srcImageLayout = srcImageLayout;
1120 paramStruct->dstImage = dstImage.getHandle();
1121 paramStruct->dstImageLayout = dstImageLayout;
1122 paramStruct->region = regions[0];
1123 }
1124
copyImageToBuffer(const Image & srcImage,VkImageLayout srcImageLayout,VkBuffer dstBuffer,uint32_t regionCount,const VkBufferImageCopy * regions)1125 ANGLE_INLINE void SecondaryCommandBuffer::copyImageToBuffer(const Image &srcImage,
1126 VkImageLayout srcImageLayout,
1127 VkBuffer dstBuffer,
1128 uint32_t regionCount,
1129 const VkBufferImageCopy *regions)
1130 {
1131 ASSERT(regionCount == 1);
1132 CopyImageToBufferParams *paramStruct =
1133 initCommand<CopyImageToBufferParams>(CommandID::CopyImageToBuffer);
1134 paramStruct->srcImage = srcImage.getHandle();
1135 paramStruct->srcImageLayout = srcImageLayout;
1136 paramStruct->dstBuffer = dstBuffer;
1137 paramStruct->region = regions[0];
1138 }
1139
dispatch(uint32_t groupCountX,uint32_t groupCountY,uint32_t groupCountZ)1140 ANGLE_INLINE void SecondaryCommandBuffer::dispatch(uint32_t groupCountX,
1141 uint32_t groupCountY,
1142 uint32_t groupCountZ)
1143 {
1144 DispatchParams *paramStruct = initCommand<DispatchParams>(CommandID::Dispatch);
1145 paramStruct->groupCountX = groupCountX;
1146 paramStruct->groupCountY = groupCountY;
1147 paramStruct->groupCountZ = groupCountZ;
1148 }
1149
dispatchIndirect(const Buffer & buffer,VkDeviceSize offset)1150 ANGLE_INLINE void SecondaryCommandBuffer::dispatchIndirect(const Buffer &buffer,
1151 VkDeviceSize offset)
1152 {
1153 DispatchIndirectParams *paramStruct =
1154 initCommand<DispatchIndirectParams>(CommandID::DispatchIndirect);
1155 paramStruct->buffer = buffer.getHandle();
1156 paramStruct->offset = offset;
1157 }
1158
draw(uint32_t vertexCount,uint32_t firstVertex)1159 ANGLE_INLINE void SecondaryCommandBuffer::draw(uint32_t vertexCount, uint32_t firstVertex)
1160 {
1161 DrawParams *paramStruct = initCommand<DrawParams>(CommandID::Draw);
1162 paramStruct->vertexCount = vertexCount;
1163 paramStruct->firstVertex = firstVertex;
1164
1165 mCommandTracker.onDraw();
1166 }
1167
drawIndexed(uint32_t indexCount)1168 ANGLE_INLINE void SecondaryCommandBuffer::drawIndexed(uint32_t indexCount)
1169 {
1170 DrawIndexedParams *paramStruct = initCommand<DrawIndexedParams>(CommandID::DrawIndexed);
1171 paramStruct->indexCount = indexCount;
1172
1173 mCommandTracker.onDraw();
1174 }
1175
drawIndexedBaseVertex(uint32_t indexCount,uint32_t vertexOffset)1176 ANGLE_INLINE void SecondaryCommandBuffer::drawIndexedBaseVertex(uint32_t indexCount,
1177 uint32_t vertexOffset)
1178 {
1179 DrawIndexedBaseVertexParams *paramStruct =
1180 initCommand<DrawIndexedBaseVertexParams>(CommandID::DrawIndexedBaseVertex);
1181 paramStruct->indexCount = indexCount;
1182 paramStruct->vertexOffset = vertexOffset;
1183
1184 mCommandTracker.onDraw();
1185 }
1186
drawIndexedIndirect(const Buffer & buffer,VkDeviceSize offset,uint32_t drawCount,uint32_t stride)1187 ANGLE_INLINE void SecondaryCommandBuffer::drawIndexedIndirect(const Buffer &buffer,
1188 VkDeviceSize offset,
1189 uint32_t drawCount,
1190 uint32_t stride)
1191 {
1192 DrawIndexedIndirectParams *paramStruct =
1193 initCommand<DrawIndexedIndirectParams>(CommandID::DrawIndexedIndirect);
1194 paramStruct->buffer = buffer.getHandle();
1195 paramStruct->offset = offset;
1196 paramStruct->drawCount = drawCount;
1197 paramStruct->stride = stride;
1198
1199 mCommandTracker.onDraw();
1200 }
1201
drawIndexedInstanced(uint32_t indexCount,uint32_t instanceCount)1202 ANGLE_INLINE void SecondaryCommandBuffer::drawIndexedInstanced(uint32_t indexCount,
1203 uint32_t instanceCount)
1204 {
1205 DrawIndexedInstancedParams *paramStruct =
1206 initCommand<DrawIndexedInstancedParams>(CommandID::DrawIndexedInstanced);
1207 paramStruct->indexCount = indexCount;
1208 paramStruct->instanceCount = instanceCount;
1209
1210 mCommandTracker.onDraw();
1211 }
1212
drawIndexedInstancedBaseVertex(uint32_t indexCount,uint32_t instanceCount,uint32_t vertexOffset)1213 ANGLE_INLINE void SecondaryCommandBuffer::drawIndexedInstancedBaseVertex(uint32_t indexCount,
1214 uint32_t instanceCount,
1215 uint32_t vertexOffset)
1216 {
1217 DrawIndexedInstancedBaseVertexParams *paramStruct =
1218 initCommand<DrawIndexedInstancedBaseVertexParams>(
1219 CommandID::DrawIndexedInstancedBaseVertex);
1220 paramStruct->indexCount = indexCount;
1221 paramStruct->instanceCount = instanceCount;
1222 paramStruct->vertexOffset = vertexOffset;
1223
1224 mCommandTracker.onDraw();
1225 }
1226
drawIndexedInstancedBaseVertexBaseInstance(uint32_t indexCount,uint32_t instanceCount,uint32_t firstIndex,int32_t vertexOffset,uint32_t firstInstance)1227 ANGLE_INLINE void SecondaryCommandBuffer::drawIndexedInstancedBaseVertexBaseInstance(
1228 uint32_t indexCount,
1229 uint32_t instanceCount,
1230 uint32_t firstIndex,
1231 int32_t vertexOffset,
1232 uint32_t firstInstance)
1233 {
1234 DrawIndexedInstancedBaseVertexBaseInstanceParams *paramStruct =
1235 initCommand<DrawIndexedInstancedBaseVertexBaseInstanceParams>(
1236 CommandID::DrawIndexedInstancedBaseVertexBaseInstance);
1237 paramStruct->indexCount = indexCount;
1238 paramStruct->instanceCount = instanceCount;
1239 paramStruct->firstIndex = firstIndex;
1240 paramStruct->vertexOffset = vertexOffset;
1241 paramStruct->firstInstance = firstInstance;
1242
1243 mCommandTracker.onDraw();
1244 }
1245
drawIndirect(const Buffer & buffer,VkDeviceSize offset,uint32_t drawCount,uint32_t stride)1246 ANGLE_INLINE void SecondaryCommandBuffer::drawIndirect(const Buffer &buffer,
1247 VkDeviceSize offset,
1248 uint32_t drawCount,
1249 uint32_t stride)
1250 {
1251 DrawIndirectParams *paramStruct = initCommand<DrawIndirectParams>(CommandID::DrawIndirect);
1252 paramStruct->buffer = buffer.getHandle();
1253 paramStruct->offset = offset;
1254 paramStruct->drawCount = drawCount;
1255 paramStruct->stride = stride;
1256
1257 mCommandTracker.onDraw();
1258 }
1259
drawInstanced(uint32_t vertexCount,uint32_t instanceCount,uint32_t firstVertex)1260 ANGLE_INLINE void SecondaryCommandBuffer::drawInstanced(uint32_t vertexCount,
1261 uint32_t instanceCount,
1262 uint32_t firstVertex)
1263 {
1264 DrawInstancedParams *paramStruct = initCommand<DrawInstancedParams>(CommandID::DrawInstanced);
1265 paramStruct->vertexCount = vertexCount;
1266 paramStruct->instanceCount = instanceCount;
1267 paramStruct->firstVertex = firstVertex;
1268
1269 mCommandTracker.onDraw();
1270 }
1271
drawInstancedBaseInstance(uint32_t vertexCount,uint32_t instanceCount,uint32_t firstVertex,uint32_t firstInstance)1272 ANGLE_INLINE void SecondaryCommandBuffer::drawInstancedBaseInstance(uint32_t vertexCount,
1273 uint32_t instanceCount,
1274 uint32_t firstVertex,
1275 uint32_t firstInstance)
1276 {
1277 DrawInstancedBaseInstanceParams *paramStruct =
1278 initCommand<DrawInstancedBaseInstanceParams>(CommandID::DrawInstancedBaseInstance);
1279 paramStruct->vertexCount = vertexCount;
1280 paramStruct->instanceCount = instanceCount;
1281 paramStruct->firstVertex = firstVertex;
1282 paramStruct->firstInstance = firstInstance;
1283
1284 mCommandTracker.onDraw();
1285 }
1286
endDebugUtilsLabelEXT()1287 ANGLE_INLINE void SecondaryCommandBuffer::endDebugUtilsLabelEXT()
1288 {
1289 initCommand<EmptyParams>(CommandID::EndDebugUtilsLabel);
1290 }
1291
endQuery(const QueryPool & queryPool,uint32_t query)1292 ANGLE_INLINE void SecondaryCommandBuffer::endQuery(const QueryPool &queryPool, uint32_t query)
1293 {
1294 EndQueryParams *paramStruct = initCommand<EndQueryParams>(CommandID::EndQuery);
1295 paramStruct->queryPool = queryPool.getHandle();
1296 paramStruct->query = query;
1297 }
1298
endTransformFeedback(uint32_t firstCounterBuffer,uint32_t counterBufferCount,const VkBuffer * counterBuffers,const VkDeviceSize * counterBufferOffsets)1299 ANGLE_INLINE void SecondaryCommandBuffer::endTransformFeedback(
1300 uint32_t firstCounterBuffer,
1301 uint32_t counterBufferCount,
1302 const VkBuffer *counterBuffers,
1303 const VkDeviceSize *counterBufferOffsets)
1304 {
1305 ASSERT(firstCounterBuffer == 0);
1306 ASSERT(counterBufferOffsets == nullptr);
1307 uint8_t *writePtr;
1308 size_t bufferSize = counterBufferCount * sizeof(VkBuffer);
1309 EndTransformFeedbackParams *paramStruct = initCommand<EndTransformFeedbackParams>(
1310 CommandID::EndTransformFeedback, bufferSize, &writePtr);
1311 paramStruct->bufferCount = counterBufferCount;
1312 storePointerParameter(writePtr, counterBuffers, bufferSize);
1313 }
1314
fillBuffer(const Buffer & dstBuffer,VkDeviceSize dstOffset,VkDeviceSize size,uint32_t data)1315 ANGLE_INLINE void SecondaryCommandBuffer::fillBuffer(const Buffer &dstBuffer,
1316 VkDeviceSize dstOffset,
1317 VkDeviceSize size,
1318 uint32_t data)
1319 {
1320 FillBufferParams *paramStruct = initCommand<FillBufferParams>(CommandID::FillBuffer);
1321 paramStruct->dstBuffer = dstBuffer.getHandle();
1322 paramStruct->dstOffset = dstOffset;
1323 paramStruct->size = size;
1324 paramStruct->data = data;
1325 }
1326
imageBarrier(VkPipelineStageFlags srcStageMask,VkPipelineStageFlags dstStageMask,const VkImageMemoryBarrier & imageMemoryBarrier)1327 ANGLE_INLINE void SecondaryCommandBuffer::imageBarrier(
1328 VkPipelineStageFlags srcStageMask,
1329 VkPipelineStageFlags dstStageMask,
1330 const VkImageMemoryBarrier &imageMemoryBarrier)
1331 {
1332 ImageBarrierParams *paramStruct = initCommand<ImageBarrierParams>(CommandID::ImageBarrier);
1333 ASSERT(imageMemoryBarrier.pNext == nullptr);
1334 paramStruct->srcStageMask = srcStageMask;
1335 paramStruct->dstStageMask = dstStageMask;
1336 paramStruct->imageMemoryBarrier = imageMemoryBarrier;
1337 }
1338
insertDebugUtilsLabelEXT(const VkDebugUtilsLabelEXT & label)1339 ANGLE_INLINE void SecondaryCommandBuffer::insertDebugUtilsLabelEXT(
1340 const VkDebugUtilsLabelEXT &label)
1341 {
1342 commonDebugUtilsLabel(CommandID::InsertDebugUtilsLabel, label);
1343 }
1344
memoryBarrier(VkPipelineStageFlags srcStageMask,VkPipelineStageFlags dstStageMask,const VkMemoryBarrier * memoryBarrier)1345 ANGLE_INLINE void SecondaryCommandBuffer::memoryBarrier(VkPipelineStageFlags srcStageMask,
1346 VkPipelineStageFlags dstStageMask,
1347 const VkMemoryBarrier *memoryBarrier)
1348 {
1349 MemoryBarrierParams *paramStruct = initCommand<MemoryBarrierParams>(CommandID::MemoryBarrier);
1350 paramStruct->srcStageMask = srcStageMask;
1351 paramStruct->dstStageMask = dstStageMask;
1352 paramStruct->memoryBarrier = *memoryBarrier;
1353 }
1354
nextSubpass(VkSubpassContents subpassContents)1355 ANGLE_INLINE void SecondaryCommandBuffer::nextSubpass(VkSubpassContents subpassContents)
1356 {
1357 NextSubpassParams *paramStruct = initCommand<NextSubpassParams>(CommandID::NextSubpass);
1358 paramStruct->subpassContents = subpassContents;
1359 }
1360
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)1361 ANGLE_INLINE void SecondaryCommandBuffer::pipelineBarrier(
1362 VkPipelineStageFlags srcStageMask,
1363 VkPipelineStageFlags dstStageMask,
1364 VkDependencyFlags dependencyFlags,
1365 uint32_t memoryBarrierCount,
1366 const VkMemoryBarrier *memoryBarriers,
1367 uint32_t bufferMemoryBarrierCount,
1368 const VkBufferMemoryBarrier *bufferMemoryBarriers,
1369 uint32_t imageMemoryBarrierCount,
1370 const VkImageMemoryBarrier *imageMemoryBarriers)
1371 {
1372 uint8_t *writePtr;
1373 size_t memBarrierSize = memoryBarrierCount * sizeof(VkMemoryBarrier);
1374 size_t buffBarrierSize = bufferMemoryBarrierCount * sizeof(VkBufferMemoryBarrier);
1375 size_t imgBarrierSize = imageMemoryBarrierCount * sizeof(VkImageMemoryBarrier);
1376 PipelineBarrierParams *paramStruct = initCommand<PipelineBarrierParams>(
1377 CommandID::PipelineBarrier, memBarrierSize + buffBarrierSize + imgBarrierSize, &writePtr);
1378 paramStruct->srcStageMask = srcStageMask;
1379 paramStruct->dstStageMask = dstStageMask;
1380 paramStruct->dependencyFlags = dependencyFlags;
1381 paramStruct->memoryBarrierCount = memoryBarrierCount;
1382 paramStruct->bufferMemoryBarrierCount = bufferMemoryBarrierCount;
1383 paramStruct->imageMemoryBarrierCount = imageMemoryBarrierCount;
1384 // Copy variable sized data
1385 writePtr = storePointerParameter(writePtr, memoryBarriers, memBarrierSize);
1386 writePtr = storePointerParameter(writePtr, bufferMemoryBarriers, buffBarrierSize);
1387 storePointerParameter(writePtr, imageMemoryBarriers, imgBarrierSize);
1388 }
1389
pushConstants(const PipelineLayout & layout,VkShaderStageFlags flag,uint32_t offset,uint32_t size,const void * data)1390 ANGLE_INLINE void SecondaryCommandBuffer::pushConstants(const PipelineLayout &layout,
1391 VkShaderStageFlags flag,
1392 uint32_t offset,
1393 uint32_t size,
1394 const void *data)
1395 {
1396 ASSERT(size == static_cast<size_t>(size));
1397 uint8_t *writePtr;
1398 PushConstantsParams *paramStruct = initCommand<PushConstantsParams>(
1399 CommandID::PushConstants, static_cast<size_t>(size), &writePtr);
1400 paramStruct->layout = layout.getHandle();
1401 paramStruct->flag = flag;
1402 paramStruct->offset = offset;
1403 paramStruct->size = size;
1404 // Copy variable sized data
1405 storePointerParameter(writePtr, data, static_cast<size_t>(size));
1406 }
1407
resetEvent(VkEvent event,VkPipelineStageFlags stageMask)1408 ANGLE_INLINE void SecondaryCommandBuffer::resetEvent(VkEvent event, VkPipelineStageFlags stageMask)
1409 {
1410 ResetEventParams *paramStruct = initCommand<ResetEventParams>(CommandID::ResetEvent);
1411 paramStruct->event = event;
1412 paramStruct->stageMask = stageMask;
1413 }
1414
resetQueryPool(const QueryPool & queryPool,uint32_t firstQuery,uint32_t queryCount)1415 ANGLE_INLINE void SecondaryCommandBuffer::resetQueryPool(const QueryPool &queryPool,
1416 uint32_t firstQuery,
1417 uint32_t queryCount)
1418 {
1419 ResetQueryPoolParams *paramStruct =
1420 initCommand<ResetQueryPoolParams>(CommandID::ResetQueryPool);
1421 paramStruct->queryPool = queryPool.getHandle();
1422 paramStruct->firstQuery = firstQuery;
1423 paramStruct->queryCount = queryCount;
1424 }
1425
resolveImage(const Image & srcImage,VkImageLayout srcImageLayout,const Image & dstImage,VkImageLayout dstImageLayout,uint32_t regionCount,const VkImageResolve * regions)1426 ANGLE_INLINE void SecondaryCommandBuffer::resolveImage(const Image &srcImage,
1427 VkImageLayout srcImageLayout,
1428 const Image &dstImage,
1429 VkImageLayout dstImageLayout,
1430 uint32_t regionCount,
1431 const VkImageResolve *regions)
1432 {
1433 // Currently ANGLE uses limited params so verify those assumptions and update if they change.
1434 ASSERT(srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
1435 ASSERT(dstImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
1436 ASSERT(regionCount == 1);
1437 ResolveImageParams *paramStruct = initCommand<ResolveImageParams>(CommandID::ResolveImage);
1438 paramStruct->srcImage = srcImage.getHandle();
1439 paramStruct->dstImage = dstImage.getHandle();
1440 paramStruct->region = regions[0];
1441 }
1442
setEvent(VkEvent event,VkPipelineStageFlags stageMask)1443 ANGLE_INLINE void SecondaryCommandBuffer::setEvent(VkEvent event, VkPipelineStageFlags stageMask)
1444 {
1445 SetEventParams *paramStruct = initCommand<SetEventParams>(CommandID::SetEvent);
1446 paramStruct->event = event;
1447 paramStruct->stageMask = stageMask;
1448 }
1449
setScissor(uint32_t firstScissor,uint32_t scissorCount,const VkRect2D * scissors)1450 ANGLE_INLINE void SecondaryCommandBuffer::setScissor(uint32_t firstScissor,
1451 uint32_t scissorCount,
1452 const VkRect2D *scissors)
1453 {
1454 ASSERT(firstScissor == 0);
1455 ASSERT(scissorCount == 1);
1456 ASSERT(scissors != nullptr);
1457 SetScissorParams *paramStruct = initCommand<SetScissorParams>(CommandID::SetScissor);
1458 paramStruct->scissor = scissors[0];
1459 }
1460
setViewport(uint32_t firstViewport,uint32_t viewportCount,const VkViewport * viewports)1461 ANGLE_INLINE void SecondaryCommandBuffer::setViewport(uint32_t firstViewport,
1462 uint32_t viewportCount,
1463 const VkViewport *viewports)
1464 {
1465 ASSERT(firstViewport == 0);
1466 ASSERT(viewportCount == 1);
1467 ASSERT(viewports != nullptr);
1468 SetViewportParams *paramStruct = initCommand<SetViewportParams>(CommandID::SetViewport);
1469 paramStruct->viewport = viewports[0];
1470 }
1471
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)1472 ANGLE_INLINE void SecondaryCommandBuffer::waitEvents(
1473 uint32_t eventCount,
1474 const VkEvent *events,
1475 VkPipelineStageFlags srcStageMask,
1476 VkPipelineStageFlags dstStageMask,
1477 uint32_t memoryBarrierCount,
1478 const VkMemoryBarrier *memoryBarriers,
1479 uint32_t bufferMemoryBarrierCount,
1480 const VkBufferMemoryBarrier *bufferMemoryBarriers,
1481 uint32_t imageMemoryBarrierCount,
1482 const VkImageMemoryBarrier *imageMemoryBarriers)
1483 {
1484 uint8_t *writePtr;
1485 size_t eventSize = eventCount * sizeof(VkEvent);
1486 size_t memBarrierSize = memoryBarrierCount * sizeof(VkMemoryBarrier);
1487 size_t buffBarrierSize = bufferMemoryBarrierCount * sizeof(VkBufferMemoryBarrier);
1488 size_t imgBarrierSize = imageMemoryBarrierCount * sizeof(VkImageMemoryBarrier);
1489 WaitEventsParams *paramStruct = initCommand<WaitEventsParams>(
1490 CommandID::WaitEvents, eventSize + memBarrierSize + buffBarrierSize + imgBarrierSize,
1491 &writePtr);
1492 paramStruct->eventCount = eventCount;
1493 paramStruct->srcStageMask = srcStageMask;
1494 paramStruct->dstStageMask = dstStageMask;
1495 paramStruct->memoryBarrierCount = memoryBarrierCount;
1496 paramStruct->bufferMemoryBarrierCount = bufferMemoryBarrierCount;
1497 paramStruct->imageMemoryBarrierCount = imageMemoryBarrierCount;
1498 // Copy variable sized data
1499 writePtr = storePointerParameter(writePtr, events, eventSize);
1500 writePtr = storePointerParameter(writePtr, memoryBarriers, memBarrierSize);
1501 writePtr = storePointerParameter(writePtr, bufferMemoryBarriers, buffBarrierSize);
1502 storePointerParameter(writePtr, imageMemoryBarriers, imgBarrierSize);
1503 }
1504
writeTimestamp(VkPipelineStageFlagBits pipelineStage,const QueryPool & queryPool,uint32_t query)1505 ANGLE_INLINE void SecondaryCommandBuffer::writeTimestamp(VkPipelineStageFlagBits pipelineStage,
1506 const QueryPool &queryPool,
1507 uint32_t query)
1508 {
1509 WriteTimestampParams *paramStruct =
1510 initCommand<WriteTimestampParams>(CommandID::WriteTimestamp);
1511 paramStruct->pipelineStage = pipelineStage;
1512 paramStruct->queryPool = queryPool.getHandle();
1513 paramStruct->query = query;
1514 }
1515 } // namespace priv
1516 } // namespace vk
1517 } // namespace rx
1518
1519 #endif // LIBANGLE_RENDERER_VULKAN_SECONDARYCOMMANDBUFFERVK_H_
1520