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