// // Copyright 2019 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // // SecondaryCommandBuffer: // Lightweight, CPU-Side command buffers used to hold command state until // it has to be submitted to GPU. // #ifndef LIBANGLE_RENDERER_VULKAN_SECONDARYCOMMANDBUFFERVK_H_ #define LIBANGLE_RENDERER_VULKAN_SECONDARYCOMMANDBUFFERVK_H_ #include "common/vulkan/vk_headers.h" #include "libANGLE/renderer/vulkan/vk_command_buffer_utils.h" #include "libANGLE/renderer/vulkan/vk_wrapper.h" #if ANGLE_ENABLE_VULKAN_SHARED_RING_BUFFER_CMD_ALLOC # include "libANGLE/renderer/vulkan/AllocatorHelperRing.h" #else # include "libANGLE/renderer/vulkan/AllocatorHelperPool.h" #endif namespace rx { class ContextVk; namespace vk { class Context; class RenderPassDesc; class SecondaryCommandPool; #if ANGLE_ENABLE_VULKAN_SHARED_RING_BUFFER_CMD_ALLOC using SecondaryCommandMemoryAllocator = SharedCommandMemoryAllocator; using SecondaryCommandBlockPool = SharedCommandBlockPool; using SecondaryCommandBlockAllocator = SharedCommandBlockAllocator; #else using SecondaryCommandMemoryAllocator = DedicatedCommandMemoryAllocator; using SecondaryCommandBlockPool = DedicatedCommandBlockPool; using SecondaryCommandBlockAllocator = DedicatedCommandBlockAllocator; #endif namespace priv { // NOTE: Please keep command-related enums, structs, functions and other code dealing with commands // in alphabetical order. // This simplifies searching and updating commands. enum class CommandID : uint16_t { // Invalid cmd used to mark end of sequence of commands Invalid = 0, BeginDebugUtilsLabel, BeginQuery, BeginTransformFeedback, BindComputePipeline, BindDescriptorSets, BindGraphicsPipeline, BindIndexBuffer, BindTransformFeedbackBuffers, BindVertexBuffers, BindVertexBuffers2, BlitImage, BufferBarrier, BufferBarrier2, ClearAttachments, ClearColorImage, ClearDepthStencilImage, CopyBuffer, CopyBufferToImage, CopyImage, CopyImageToBuffer, Dispatch, DispatchIndirect, Draw, DrawIndexed, DrawIndexedBaseVertex, DrawIndexedIndirect, DrawIndexedInstanced, DrawIndexedInstancedBaseVertex, DrawIndexedInstancedBaseVertexBaseInstance, DrawIndirect, DrawInstanced, DrawInstancedBaseInstance, EndDebugUtilsLabel, EndQuery, EndTransformFeedback, FillBuffer, ImageBarrier, ImageBarrier2, ImageWaitEvent, InsertDebugUtilsLabel, MemoryBarrier, MemoryBarrier2, NextSubpass, PipelineBarrier, PipelineBarrier2, PushConstants, ResetEvent, ResetQueryPool, ResolveImage, SetBlendConstants, SetCullMode, SetDepthBias, SetDepthBiasEnable, SetDepthCompareOp, SetDepthTestEnable, SetDepthWriteEnable, SetEvent, SetFragmentShadingRate, SetFrontFace, SetLineWidth, SetLogicOp, SetPrimitiveRestartEnable, SetRasterizerDiscardEnable, SetScissor, SetStencilCompareMask, SetStencilOp, SetStencilReference, SetStencilTestEnable, SetStencilWriteMask, SetVertexInput, SetViewport, WaitEvents, WriteTimestamp, WriteTimestamp2, }; // Header for every cmd in custom cmd buffer struct CommandHeader { CommandID id; uint16_t size; }; static_assert(sizeof(CommandHeader) == 4, "Check CommandHeader size"); #define VERIFY_8_BYTE_ALIGNMENT(StructName) \ static_assert((sizeof(StructName) % 8) == 0, "Check " #StructName " alignment"); ANGLE_ENABLE_STRUCT_PADDING_WARNINGS // Structs to encapsulate parameters for different commands. This makes it easy to know the size of // params & to copy params. Each struct must be prefixed by a CommandHeader (which is 4 bytes) and // must be aligned to 8 bytes. struct BeginQueryParams { CommandHeader header; uint32_t query; VkQueryPool queryPool; }; VERIFY_8_BYTE_ALIGNMENT(BeginQueryParams) struct BeginTransformFeedbackParams { CommandHeader header; uint32_t bufferCount; }; VERIFY_8_BYTE_ALIGNMENT(BeginTransformFeedbackParams) struct BindDescriptorSetParams { CommandHeader header; VkPipelineBindPoint pipelineBindPoint : 8; uint32_t firstSet : 8; uint32_t descriptorSetCount : 8; uint32_t dynamicOffsetCount : 8; VkPipelineLayout layout; }; VERIFY_8_BYTE_ALIGNMENT(BindDescriptorSetParams) struct BindIndexBufferParams { CommandHeader header; VkIndexType indexType; VkBuffer buffer; VkDeviceSize offset; }; VERIFY_8_BYTE_ALIGNMENT(BindIndexBufferParams) struct BindPipelineParams { CommandHeader header; uint32_t padding; VkPipeline pipeline; }; VERIFY_8_BYTE_ALIGNMENT(BindPipelineParams) struct BindTransformFeedbackBuffersParams { CommandHeader header; // ANGLE always has firstBinding of 0 so not storing that currently uint32_t bindingCount; }; VERIFY_8_BYTE_ALIGNMENT(BindTransformFeedbackBuffersParams) using BindVertexBuffersParams = BindTransformFeedbackBuffersParams; using BindVertexBuffers2Params = BindVertexBuffersParams; struct BlitImageParams { CommandHeader header; VkFilter filter; VkImage srcImage; VkImage dstImage; VkImageBlit region; }; VERIFY_8_BYTE_ALIGNMENT(BlitImageParams) struct BufferBarrierParams { CommandHeader header; uint32_t padding; VkBufferMemoryBarrier bufferMemoryBarrier; }; VERIFY_8_BYTE_ALIGNMENT(BufferBarrierParams) struct BufferBarrier2Params { CommandHeader header; uint32_t padding; VkBufferMemoryBarrier2 bufferMemoryBarrier2; }; VERIFY_8_BYTE_ALIGNMENT(BufferBarrier2Params) struct ClearAttachmentsParams { CommandHeader header; uint32_t attachmentCount; VkClearRect rect; }; VERIFY_8_BYTE_ALIGNMENT(ClearAttachmentsParams) struct ClearColorImageParams { CommandHeader header; VkImageLayout imageLayout; VkImage image; VkClearColorValue color; VkImageSubresourceRange range; uint32_t padding; }; VERIFY_8_BYTE_ALIGNMENT(ClearColorImageParams) struct ClearDepthStencilImageParams { CommandHeader header; VkImageLayout imageLayout; VkImage image; VkClearDepthStencilValue depthStencil; VkImageSubresourceRange range; uint32_t padding; }; VERIFY_8_BYTE_ALIGNMENT(ClearDepthStencilImageParams) struct CopyBufferParams { CommandHeader header; uint32_t regionCount; VkBuffer srcBuffer; VkBuffer destBuffer; }; VERIFY_8_BYTE_ALIGNMENT(CopyBufferParams) struct CopyBufferToImageParams { CommandHeader header; VkImageLayout dstImageLayout; VkBuffer srcBuffer; VkImage dstImage; VkBufferImageCopy region; }; VERIFY_8_BYTE_ALIGNMENT(CopyBufferToImageParams) struct CopyImageParams { CommandHeader header; VkImageCopy region; VkImageLayout srcImageLayout; VkImageLayout dstImageLayout; VkImage srcImage; VkImage dstImage; }; VERIFY_8_BYTE_ALIGNMENT(CopyImageParams) struct CopyImageToBufferParams { CommandHeader header; VkImageLayout srcImageLayout; VkImage srcImage; VkBuffer dstBuffer; VkBufferImageCopy region; }; VERIFY_8_BYTE_ALIGNMENT(CopyImageToBufferParams) // This is a common struct used by both begin & insert DebugUtilsLabelEXT() functions struct DebugUtilsLabelParams { CommandHeader header; uint32_t padding; float color[4]; }; VERIFY_8_BYTE_ALIGNMENT(DebugUtilsLabelParams) struct DispatchParams { CommandHeader header; uint32_t groupCountX; uint32_t groupCountY; uint32_t groupCountZ; }; VERIFY_8_BYTE_ALIGNMENT(DispatchParams) struct DispatchIndirectParams { CommandHeader header; uint32_t padding; VkBuffer buffer; VkDeviceSize offset; }; VERIFY_8_BYTE_ALIGNMENT(DispatchIndirectParams) struct DrawParams { CommandHeader header; uint32_t padding; uint32_t vertexCount; uint32_t firstVertex; }; VERIFY_8_BYTE_ALIGNMENT(DrawParams) struct DrawIndexedParams { CommandHeader header; uint32_t indexCount; }; VERIFY_8_BYTE_ALIGNMENT(DrawIndexedParams) struct DrawIndexedBaseVertexParams { CommandHeader header; uint32_t padding; uint32_t indexCount; uint32_t vertexOffset; }; VERIFY_8_BYTE_ALIGNMENT(DrawIndexedBaseVertexParams) struct DrawIndexedIndirectParams { CommandHeader header; uint32_t padding; uint32_t drawCount; uint32_t stride; VkBuffer buffer; VkDeviceSize offset; }; VERIFY_8_BYTE_ALIGNMENT(DrawIndexedIndirectParams) struct DrawIndexedInstancedParams { CommandHeader header; uint32_t padding; uint32_t indexCount; uint32_t instanceCount; }; VERIFY_8_BYTE_ALIGNMENT(DrawIndexedInstancedParams) struct DrawIndexedInstancedBaseVertexParams { CommandHeader header; uint32_t indexCount; uint32_t instanceCount; uint32_t vertexOffset; }; VERIFY_8_BYTE_ALIGNMENT(DrawIndexedInstancedBaseVertexParams) struct DrawIndexedInstancedBaseVertexBaseInstanceParams { CommandHeader header; uint32_t indexCount; uint32_t instanceCount; uint32_t firstIndex; int32_t vertexOffset; uint32_t firstInstance; }; VERIFY_8_BYTE_ALIGNMENT(DrawIndexedInstancedBaseVertexBaseInstanceParams) struct DrawIndirectParams { CommandHeader header; uint32_t padding; uint32_t drawCount; uint32_t stride; VkBuffer buffer; VkDeviceSize offset; }; VERIFY_8_BYTE_ALIGNMENT(DrawIndirectParams) struct DrawInstancedParams { CommandHeader header; uint32_t vertexCount; uint32_t instanceCount; uint32_t firstVertex; }; VERIFY_8_BYTE_ALIGNMENT(DrawInstancedParams) struct DrawInstancedBaseInstanceParams { CommandHeader header; uint32_t padding; uint32_t vertexCount; uint32_t instanceCount; uint32_t firstVertex; uint32_t firstInstance; }; VERIFY_8_BYTE_ALIGNMENT(DrawInstancedBaseInstanceParams) // A special struct used with commands that don't have params struct EmptyParams { CommandHeader header; uint32_t padding; }; VERIFY_8_BYTE_ALIGNMENT(EmptyParams) struct EndQueryParams { CommandHeader header; uint32_t query; VkQueryPool queryPool; }; VERIFY_8_BYTE_ALIGNMENT(EndQueryParams) struct EndTransformFeedbackParams { CommandHeader header; uint32_t bufferCount; }; VERIFY_8_BYTE_ALIGNMENT(EndTransformFeedbackParams) struct FillBufferParams { CommandHeader header; uint32_t data; VkBuffer dstBuffer; VkDeviceSize dstOffset; VkDeviceSize size; }; VERIFY_8_BYTE_ALIGNMENT(FillBufferParams) struct ImageBarrierParams { CommandHeader header; uint32_t padding; VkPipelineStageFlags srcStageMask; VkPipelineStageFlags dstStageMask; }; VERIFY_8_BYTE_ALIGNMENT(ImageBarrierParams) struct ImageBarrier2Params { CommandHeader header; uint32_t padding; }; VERIFY_8_BYTE_ALIGNMENT(ImageBarrier2Params) struct ImageWaitEventParams { CommandHeader header; uint32_t padding; VkEvent event; VkPipelineStageFlags srcStageMask; VkPipelineStageFlags dstStageMask; }; VERIFY_8_BYTE_ALIGNMENT(ImageWaitEventParams) struct MemoryBarrierParams { CommandHeader header; uint32_t padding; VkPipelineStageFlags srcStageMask; VkPipelineStageFlags dstStageMask; }; VERIFY_8_BYTE_ALIGNMENT(MemoryBarrierParams) struct MemoryBarrier2Params { CommandHeader header; uint32_t padding; }; VERIFY_8_BYTE_ALIGNMENT(MemoryBarrierParams) struct PipelineBarrierParams { CommandHeader header; VkPipelineStageFlags srcStageMask; VkPipelineStageFlags dstStageMask; VkDependencyFlags dependencyFlags; uint32_t memoryBarrierCount; uint32_t imageMemoryBarrierCount; }; VERIFY_8_BYTE_ALIGNMENT(PipelineBarrierParams) struct PipelineBarrierParams2 { CommandHeader header; VkDependencyFlags dependencyFlags; uint32_t memoryBarrierCount; uint32_t imageMemoryBarrierCount; }; VERIFY_8_BYTE_ALIGNMENT(PipelineBarrierParams2) struct PushConstantsParams { CommandHeader header; VkShaderStageFlags flag; VkPipelineLayout layout; uint32_t offset; uint32_t size; }; VERIFY_8_BYTE_ALIGNMENT(PushConstantsParams) struct ResetEventParams { CommandHeader header; VkPipelineStageFlags stageMask; VkEvent event; }; VERIFY_8_BYTE_ALIGNMENT(ResetEventParams) struct ResetQueryPoolParams { CommandHeader header; uint32_t firstQuery : 24; uint32_t queryCount : 8; VkQueryPool queryPool; }; VERIFY_8_BYTE_ALIGNMENT(ResetQueryPoolParams) struct ResolveImageParams { CommandHeader header; VkImageResolve region; VkImage srcImage; VkImage dstImage; }; VERIFY_8_BYTE_ALIGNMENT(ResolveImageParams) struct SetBlendConstantsParams { CommandHeader header; uint32_t padding; float blendConstants[4]; }; VERIFY_8_BYTE_ALIGNMENT(SetBlendConstantsParams) struct SetCullModeParams { CommandHeader header; VkCullModeFlags cullMode; }; VERIFY_8_BYTE_ALIGNMENT(SetCullModeParams) struct SetDepthBiasParams { CommandHeader header; float depthBiasConstantFactor; float depthBiasClamp; float depthBiasSlopeFactor; }; VERIFY_8_BYTE_ALIGNMENT(SetDepthBiasParams) struct SetDepthBiasEnableParams { CommandHeader header; VkBool32 depthBiasEnable; }; VERIFY_8_BYTE_ALIGNMENT(SetDepthBiasEnableParams) struct SetDepthCompareOpParams { CommandHeader header; VkCompareOp depthCompareOp; }; VERIFY_8_BYTE_ALIGNMENT(SetDepthCompareOpParams) struct SetDepthTestEnableParams { CommandHeader header; VkBool32 depthTestEnable; }; VERIFY_8_BYTE_ALIGNMENT(SetDepthTestEnableParams) struct SetDepthWriteEnableParams { CommandHeader header; VkBool32 depthWriteEnable; }; VERIFY_8_BYTE_ALIGNMENT(SetDepthWriteEnableParams) struct SetEventParams { CommandHeader header; VkPipelineStageFlags stageMask; VkEvent event; }; VERIFY_8_BYTE_ALIGNMENT(SetEventParams) struct SetFragmentShadingRateParams { CommandHeader header; uint32_t fragmentWidth : 8; uint32_t fragmentHeight : 8; uint32_t vkFragmentShadingRateCombinerOp1 : 16; }; VERIFY_8_BYTE_ALIGNMENT(SetFragmentShadingRateParams) struct SetFrontFaceParams { CommandHeader header; VkFrontFace frontFace; }; VERIFY_8_BYTE_ALIGNMENT(SetFrontFaceParams) struct SetLineWidthParams { CommandHeader header; float lineWidth; }; VERIFY_8_BYTE_ALIGNMENT(SetLineWidthParams) struct SetLogicOpParams { CommandHeader header; VkLogicOp logicOp; }; VERIFY_8_BYTE_ALIGNMENT(SetLogicOpParams) struct SetPrimitiveRestartEnableParams { CommandHeader header; VkBool32 primitiveRestartEnable; }; VERIFY_8_BYTE_ALIGNMENT(SetPrimitiveRestartEnableParams) struct SetRasterizerDiscardEnableParams { CommandHeader header; VkBool32 rasterizerDiscardEnable; }; VERIFY_8_BYTE_ALIGNMENT(SetRasterizerDiscardEnableParams) struct SetScissorParams { CommandHeader header; uint32_t padding; VkRect2D scissor; }; VERIFY_8_BYTE_ALIGNMENT(SetScissorParams) struct SetStencilCompareMaskParams { CommandHeader header; uint16_t compareFrontMask; uint16_t compareBackMask; }; VERIFY_8_BYTE_ALIGNMENT(SetStencilCompareMaskParams) struct SetStencilOpParams { CommandHeader header; uint32_t faceMask : 4; uint32_t failOp : 3; uint32_t passOp : 3; uint32_t depthFailOp : 3; uint32_t compareOp : 3; uint32_t padding : 16; }; VERIFY_8_BYTE_ALIGNMENT(SetStencilOpParams) struct SetStencilReferenceParams { CommandHeader header; uint16_t frontReference; uint16_t backReference; }; VERIFY_8_BYTE_ALIGNMENT(SetStencilReferenceParams) struct SetStencilTestEnableParams { CommandHeader header; VkBool32 stencilTestEnable; }; VERIFY_8_BYTE_ALIGNMENT(SetStencilTestEnableParams) struct SetStencilWriteMaskParams { CommandHeader header; uint16_t writeFrontMask; uint16_t writeBackMask; }; VERIFY_8_BYTE_ALIGNMENT(SetStencilWriteMaskParams) struct SetVertexInputParams { CommandHeader header; uint16_t vertexBindingDescriptionCount; uint16_t vertexAttributeDescriptionCount; }; VERIFY_8_BYTE_ALIGNMENT(SetVertexInputParams) struct SetViewportParams { CommandHeader header; uint32_t padding; VkViewport viewport; }; VERIFY_8_BYTE_ALIGNMENT(SetViewportParams) struct WaitEventsParams { CommandHeader header; uint32_t eventCount; VkPipelineStageFlags srcStageMask; VkPipelineStageFlags dstStageMask; uint32_t memoryBarrierCount; uint32_t imageMemoryBarrierCount; }; VERIFY_8_BYTE_ALIGNMENT(WaitEventsParams) struct WriteTimestampParams { CommandHeader header; uint32_t query; VkQueryPool queryPool; }; VERIFY_8_BYTE_ALIGNMENT(WriteTimestampParams) #undef VERIFY_8_BYTE_ALIGNMENT ANGLE_DISABLE_STRUCT_PADDING_WARNINGS template ANGLE_INLINE DestT *Offset(T *ptr, size_t bytes) { return reinterpret_cast((reinterpret_cast(ptr) + bytes)); } template ANGLE_INLINE const DestT *Offset(const T *ptr, size_t bytes) { return reinterpret_cast((reinterpret_cast(ptr) + bytes)); } class SecondaryCommandBuffer final : angle::NonCopyable { public: SecondaryCommandBuffer(); ~SecondaryCommandBuffer(); static bool SupportsQueries(const VkPhysicalDeviceFeatures &features) { return true; } // SecondaryCommandBuffer replays its commands inline when executed on the primary command // buffer. static constexpr bool ExecutesInline() { return true; } static angle::Result InitializeCommandPool(Context *context, SecondaryCommandPool *pool, uint32_t queueFamilyIndex, ProtectionType protectionType) { return angle::Result::Continue; } static angle::Result InitializeRenderPassInheritanceInfo( ContextVk *contextVk, const Framebuffer &framebuffer, const RenderPassDesc &renderPassDesc, VkCommandBufferInheritanceInfo *inheritanceInfoOut, VkCommandBufferInheritanceRenderingInfo *renderingInfoOut, gl::DrawBuffersArray *colorFormatStorageOut) { *inheritanceInfoOut = {}; return angle::Result::Continue; } // Add commands void beginDebugUtilsLabelEXT(const VkDebugUtilsLabelEXT &label); void beginQuery(const QueryPool &queryPool, uint32_t query, VkQueryControlFlags flags); void beginTransformFeedback(uint32_t firstCounterBuffer, uint32_t bufferCount, const VkBuffer *counterBuffers, const VkDeviceSize *counterBufferOffsets); void bindComputePipeline(const Pipeline &pipeline); void bindDescriptorSets(const PipelineLayout &layout, VkPipelineBindPoint pipelineBindPoint, DescriptorSetIndex firstSet, uint32_t descriptorSetCount, const VkDescriptorSet *descriptorSets, uint32_t dynamicOffsetCount, const uint32_t *dynamicOffsets); void bindGraphicsPipeline(const Pipeline &pipeline); void bindIndexBuffer(const Buffer &buffer, VkDeviceSize offset, VkIndexType indexType); void bindTransformFeedbackBuffers(uint32_t firstBinding, uint32_t bindingCount, const VkBuffer *buffers, const VkDeviceSize *offsets, const VkDeviceSize *sizes); void bindVertexBuffers(uint32_t firstBinding, uint32_t bindingCount, const VkBuffer *buffers, const VkDeviceSize *offsets); void bindVertexBuffers2(uint32_t firstBinding, uint32_t bindingCount, const VkBuffer *buffers, const VkDeviceSize *offsets, const VkDeviceSize *sizes, const VkDeviceSize *strides); void blitImage(const Image &srcImage, VkImageLayout srcImageLayout, const Image &dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageBlit *regions, VkFilter filter); void bufferBarrier(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, const VkBufferMemoryBarrier *bufferMemoryBarrier); void bufferBarrier2(const VkBufferMemoryBarrier2 *bufferMemoryBarrier); void clearAttachments(uint32_t attachmentCount, const VkClearAttachment *attachments, uint32_t rectCount, const VkClearRect *rects); void clearColorImage(const Image &image, VkImageLayout imageLayout, const VkClearColorValue &color, uint32_t rangeCount, const VkImageSubresourceRange *ranges); void clearDepthStencilImage(const Image &image, VkImageLayout imageLayout, const VkClearDepthStencilValue &depthStencil, uint32_t rangeCount, const VkImageSubresourceRange *ranges); void copyBuffer(const Buffer &srcBuffer, const Buffer &destBuffer, uint32_t regionCount, const VkBufferCopy *regions); void copyBufferToImage(VkBuffer srcBuffer, const Image &dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkBufferImageCopy *regions); void copyImage(const Image &srcImage, VkImageLayout srcImageLayout, const Image &dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageCopy *regions); void copyImageToBuffer(const Image &srcImage, VkImageLayout srcImageLayout, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy *regions); void dispatch(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ); void dispatchIndirect(const Buffer &buffer, VkDeviceSize offset); void draw(uint32_t vertexCount, uint32_t firstVertex); void drawIndexed(uint32_t indexCount); void drawIndexedBaseVertex(uint32_t indexCount, uint32_t vertexOffset); void drawIndexedIndirect(const Buffer &buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride); void drawIndexedInstanced(uint32_t indexCount, uint32_t instanceCount); void drawIndexedInstancedBaseVertex(uint32_t indexCount, uint32_t instanceCount, uint32_t vertexOffset); void drawIndexedInstancedBaseVertexBaseInstance(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance); void drawIndirect(const Buffer &buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride); void drawInstanced(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex); void drawInstancedBaseInstance(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance); void endDebugUtilsLabelEXT(); void endQuery(const QueryPool &queryPool, uint32_t query); void endTransformFeedback(uint32_t firstCounterBuffer, uint32_t counterBufferCount, const VkBuffer *counterBuffers, const VkDeviceSize *counterBufferOffsets); void fillBuffer(const Buffer &dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data); void imageBarrier(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, const VkImageMemoryBarrier &imageMemoryBarrier); void imageBarrier2(const VkImageMemoryBarrier2 &imageMemoryBarrier2); void imageWaitEvent(const VkEvent &event, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, const VkImageMemoryBarrier &imageMemoryBarrier); void imageWaitEvent2(const VkEvent &event, const VkImageMemoryBarrier2 &imageMemoryBarrier2); void insertDebugUtilsLabelEXT(const VkDebugUtilsLabelEXT &label); void memoryBarrier(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, const VkMemoryBarrier &memoryBarrier); void memoryBarrier2(const VkMemoryBarrier2 &memoryBarrier2); void nextSubpass(VkSubpassContents subpassContents); void 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); void pipelineBarrier2(VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier2 *memoryBarriers2, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier2 *bufferMemoryBarriers2, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier2 *imageMemoryBarriers2); void pushConstants(const PipelineLayout &layout, VkShaderStageFlags flag, uint32_t offset, uint32_t size, const void *data); void resetEvent(VkEvent event, VkPipelineStageFlags stageMask); void resetQueryPool(const QueryPool &queryPool, uint32_t firstQuery, uint32_t queryCount); void resolveImage(const Image &srcImage, VkImageLayout srcImageLayout, const Image &dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageResolve *regions); void setBlendConstants(const float blendConstants[4]); void setCullMode(VkCullModeFlags cullMode); void setDepthBias(float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor); void setDepthBiasEnable(VkBool32 depthBiasEnable); void setDepthCompareOp(VkCompareOp depthCompareOp); void setDepthTestEnable(VkBool32 depthTestEnable); void setDepthWriteEnable(VkBool32 depthWriteEnable); void setEvent(VkEvent event, VkPipelineStageFlags stageMask); void setFragmentShadingRate(const VkExtent2D *fragmentSize, VkFragmentShadingRateCombinerOpKHR ops[2]); void setFrontFace(VkFrontFace frontFace); void setLineWidth(float lineWidth); void setLogicOp(VkLogicOp logicOp); void setPrimitiveRestartEnable(VkBool32 primitiveRestartEnable); void setRasterizerDiscardEnable(VkBool32 rasterizerDiscardEnable); void setScissor(uint32_t firstScissor, uint32_t scissorCount, const VkRect2D *scissors); void setStencilCompareMask(uint32_t compareFrontMask, uint32_t compareBackMask); void setStencilOp(VkStencilFaceFlags faceMask, VkStencilOp failOp, VkStencilOp passOp, VkStencilOp depthFailOp, VkCompareOp compareOp); void setStencilReference(uint32_t frontReference, uint32_t backReference); void setStencilTestEnable(VkBool32 stencilTestEnable); void setStencilWriteMask(uint32_t writeFrontMask, uint32_t writeBackMask); void setVertexInput(uint32_t vertexBindingDescriptionCount, const VkVertexInputBindingDescription2EXT *vertexBindingDescriptions, uint32_t vertexAttributeDescriptionCount, const VkVertexInputAttributeDescription2EXT *vertexAttributeDescriptions); void setViewport(uint32_t firstViewport, uint32_t viewportCount, const VkViewport *viewports); void 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); void writeTimestamp(VkPipelineStageFlagBits pipelineStage, const QueryPool &queryPool, uint32_t query); void writeTimestamp2(VkPipelineStageFlagBits2 pipelineStage, const QueryPool &queryPool, uint32_t query); // No-op for compatibility VkResult end() { return VK_SUCCESS; } // Parse the cmds in this cmd buffer into given primary cmd buffer for execution void executeCommands(PrimaryCommandBuffer *primary); // Calculate memory usage of this command buffer for diagnostics. void getMemoryUsageStats(size_t *usedMemoryOut, size_t *allocatedMemoryOut) const; void getMemoryUsageStatsForPoolAlloc(size_t blockSize, size_t *usedMemoryOut, size_t *allocatedMemoryOut) const; // Traverse the list of commands and build a summary for diagnostics. std::string dumpCommands(const char *separator) const; // Initialize the SecondaryCommandBuffer by setting the allocator it will use angle::Result initialize(vk::Context *context, vk::SecondaryCommandPool *pool, bool isRenderPassCommandBuffer, SecondaryCommandMemoryAllocator *allocator) { return mCommandAllocator.initialize(allocator); } void attachAllocator(vk::SecondaryCommandMemoryAllocator *source) { mCommandAllocator.attachAllocator(source); } void detachAllocator(vk::SecondaryCommandMemoryAllocator *destination) { mCommandAllocator.detachAllocator(destination); } angle::Result begin(Context *context, const VkCommandBufferInheritanceInfo &inheritanceInfo) { return angle::Result::Continue; } angle::Result end(Context *context) { return angle::Result::Continue; } void open() { mIsOpen = true; } void close() { mIsOpen = false; } void reset() { mCommands.clear(); mCommandAllocator.reset(&mCommandTracker); } // The SecondaryCommandBuffer is valid if it's been initialized bool valid() const { return mCommandAllocator.valid(); } bool empty() const { return mCommandAllocator.empty(); } bool checkEmptyForPoolAlloc() const { return mCommands.size() == 0 || mCommands[0]->id == CommandID::Invalid; } uint32_t getRenderPassWriteCommandCount() const { return mCommandTracker.getRenderPassWriteCommandCount(); } void clearCommands() { mCommands.clear(); } bool hasEmptyCommands() { return mCommands.empty(); } void pushToCommands(uint8_t *command) { mCommands.push_back(reinterpret_cast(command)); } private: void commonDebugUtilsLabel(CommandID cmd, const VkDebugUtilsLabelEXT &label); template ANGLE_INLINE StructType *commonInit(CommandID cmdID, size_t allocationSize, uint8_t *commandMemory) { ASSERT(mIsOpen); ASSERT(allocationSize <= std::numeric_limits::max()); StructType *command = reinterpret_cast(commandMemory); command->header.id = cmdID; command->header.size = static_cast(allocationSize); return command; } // Allocate and initialize memory for given commandID & variable param size, setting // variableDataOut to the byte following fixed cmd data where variable-sized ptr data will // be written and returning a pointer to the start of the command's parameter data template ANGLE_INLINE StructType *initCommand(CommandID cmdID, size_t variableSize, uint8_t **variableDataOut) { constexpr size_t fixedAllocationSize = sizeof(StructType); const size_t allocationSize = fixedAllocationSize + variableSize; // Make sure we have enough room to mark follow-on header "Invalid" const size_t requiredSize = allocationSize + sizeof(CommandHeader); uint8_t *commandMemory = nullptr; mCommandAllocator.onNewVariableSizedCommand(requiredSize, allocationSize, &commandMemory); StructType *command = commonInit(cmdID, allocationSize, commandMemory); *variableDataOut = Offset(commandMemory, fixedAllocationSize); return command; } // Initialize a command that doesn't have variable-sized ptr data template ANGLE_INLINE StructType *initCommand(CommandID cmdID) { constexpr size_t allocationSize = sizeof(StructType); // Make sure we have enough room to mark follow-on header "Invalid" const size_t requiredSize = allocationSize + sizeof(CommandHeader); uint8_t *commandMemory = nullptr; mCommandAllocator.onNewCommand(requiredSize, allocationSize, &commandMemory); return commonInit(cmdID, allocationSize, commandMemory); } // Return a pointer to the parameter type. Note that every param struct has the header as its // first member, so in fact the parameter type pointer is identical to the header pointer. template const StructType *getParamPtr(const CommandHeader *header) const { return reinterpret_cast(header); } struct ArrayParamSize { // Given an array of N elements of type T, N*sizeof(T) bytes need to be copied, but due to // alignment requirements, roundUp(size, 8) bytes need to be allocated for the array. size_t copyBytes; size_t allocateBytes; }; template ANGLE_INLINE ArrayParamSize calculateArrayParameterSize(size_t count) { ArrayParamSize size; size.copyBytes = sizeof(T) * count; size.allocateBytes = roundUpPow2(size.copyBytes, 8u); return size; } // Copy size.copyBytes data from paramData to writePointer and return writePointer plus // size.allocateBytes. template ANGLE_INLINE uint8_t *storeArrayParameter(uint8_t *writePointer, const T *data, const ArrayParamSize &size) { // See |PointerParamSize|. The size should always be calculated with // |calculatePointerParameterSize|, and that satisfies this condition. ASSERT(size.allocateBytes == roundUpPow2(size.copyBytes, 8u)); memcpy(writePointer, data, size.copyBytes); return writePointer + size.allocateBytes; } // Flag to indicate that commandBuffer is open for new commands. Initially open. bool mIsOpen; std::vector mCommands; // Allocator used by this class. If non-null then the class is valid. SecondaryCommandBlockPool mCommandAllocator; CommandBufferCommandTracker mCommandTracker; }; ANGLE_INLINE SecondaryCommandBuffer::SecondaryCommandBuffer() : mIsOpen(true) { mCommandAllocator.setCommandBuffer(this); } ANGLE_INLINE SecondaryCommandBuffer::~SecondaryCommandBuffer() { mCommandAllocator.resetCommandBuffer(); } // begin and insert DebugUtilsLabelEXT funcs share this same function body ANGLE_INLINE void SecondaryCommandBuffer::commonDebugUtilsLabel(CommandID cmd, const VkDebugUtilsLabelEXT &label) { uint8_t *writePtr; const ArrayParamSize stringSize = calculateArrayParameterSize(strlen(label.pLabelName) + 1); DebugUtilsLabelParams *paramStruct = initCommand(cmd, stringSize.allocateBytes, &writePtr); paramStruct->color[0] = label.color[0]; paramStruct->color[1] = label.color[1]; paramStruct->color[2] = label.color[2]; paramStruct->color[3] = label.color[3]; storeArrayParameter(writePtr, label.pLabelName, stringSize); } ANGLE_INLINE void SecondaryCommandBuffer::beginDebugUtilsLabelEXT(const VkDebugUtilsLabelEXT &label) { commonDebugUtilsLabel(CommandID::BeginDebugUtilsLabel, label); } ANGLE_INLINE void SecondaryCommandBuffer::beginQuery(const QueryPool &queryPool, uint32_t query, VkQueryControlFlags flags) { ASSERT(flags == 0); BeginQueryParams *paramStruct = initCommand(CommandID::BeginQuery); paramStruct->queryPool = queryPool.getHandle(); paramStruct->query = query; } ANGLE_INLINE void SecondaryCommandBuffer::beginTransformFeedback( uint32_t firstCounterBuffer, uint32_t bufferCount, const VkBuffer *counterBuffers, const VkDeviceSize *counterBufferOffsets) { ASSERT(firstCounterBuffer == 0); uint8_t *writePtr; const ArrayParamSize bufferSize = calculateArrayParameterSize(bufferCount); const ArrayParamSize offsetSize = calculateArrayParameterSize(bufferCount); BeginTransformFeedbackParams *paramStruct = initCommand( CommandID::BeginTransformFeedback, bufferSize.allocateBytes + offsetSize.allocateBytes, &writePtr); paramStruct->bufferCount = bufferCount; writePtr = storeArrayParameter(writePtr, counterBuffers, bufferSize); storeArrayParameter(writePtr, counterBufferOffsets, offsetSize); } ANGLE_INLINE void SecondaryCommandBuffer::bindComputePipeline(const Pipeline &pipeline) { BindPipelineParams *paramStruct = initCommand(CommandID::BindComputePipeline); paramStruct->pipeline = pipeline.getHandle(); } ANGLE_INLINE void SecondaryCommandBuffer::bindDescriptorSets(const PipelineLayout &layout, VkPipelineBindPoint pipelineBindPoint, DescriptorSetIndex firstSet, uint32_t descriptorSetCount, const VkDescriptorSet *descriptorSets, uint32_t dynamicOffsetCount, const uint32_t *dynamicOffsets) { const ArrayParamSize descSize = calculateArrayParameterSize(descriptorSetCount); const ArrayParamSize offsetSize = calculateArrayParameterSize(dynamicOffsetCount); uint8_t *writePtr; BindDescriptorSetParams *paramStruct = initCommand( CommandID::BindDescriptorSets, descSize.allocateBytes + offsetSize.allocateBytes, &writePtr); // Copy params into memory paramStruct->layout = layout.getHandle(); SetBitField(paramStruct->pipelineBindPoint, pipelineBindPoint); SetBitField(paramStruct->firstSet, ToUnderlying(firstSet)); SetBitField(paramStruct->descriptorSetCount, descriptorSetCount); SetBitField(paramStruct->dynamicOffsetCount, dynamicOffsetCount); // Copy variable sized data writePtr = storeArrayParameter(writePtr, descriptorSets, descSize); if (dynamicOffsetCount > 0) { storeArrayParameter(writePtr, dynamicOffsets, offsetSize); } } ANGLE_INLINE void SecondaryCommandBuffer::bindGraphicsPipeline(const Pipeline &pipeline) { BindPipelineParams *paramStruct = initCommand(CommandID::BindGraphicsPipeline); paramStruct->pipeline = pipeline.getHandle(); } ANGLE_INLINE void SecondaryCommandBuffer::bindIndexBuffer(const Buffer &buffer, VkDeviceSize offset, VkIndexType indexType) { BindIndexBufferParams *paramStruct = initCommand(CommandID::BindIndexBuffer); paramStruct->buffer = buffer.getHandle(); paramStruct->offset = offset; paramStruct->indexType = indexType; } ANGLE_INLINE void SecondaryCommandBuffer::bindTransformFeedbackBuffers(uint32_t firstBinding, uint32_t bindingCount, const VkBuffer *buffers, const VkDeviceSize *offsets, const VkDeviceSize *sizes) { ASSERT(firstBinding == 0); uint8_t *writePtr; const ArrayParamSize buffersSize = calculateArrayParameterSize(bindingCount); const ArrayParamSize offsetsSize = calculateArrayParameterSize(bindingCount); const ArrayParamSize sizesSize = offsetsSize; BindTransformFeedbackBuffersParams *paramStruct = initCommand( CommandID::BindTransformFeedbackBuffers, buffersSize.allocateBytes + offsetsSize.allocateBytes + sizesSize.allocateBytes, &writePtr); // Copy params paramStruct->bindingCount = bindingCount; writePtr = storeArrayParameter(writePtr, buffers, buffersSize); writePtr = storeArrayParameter(writePtr, offsets, offsetsSize); storeArrayParameter(writePtr, sizes, sizesSize); } ANGLE_INLINE void SecondaryCommandBuffer::bindVertexBuffers(uint32_t firstBinding, uint32_t bindingCount, const VkBuffer *buffers, const VkDeviceSize *offsets) { ASSERT(firstBinding == 0); uint8_t *writePtr; const ArrayParamSize buffersSize = calculateArrayParameterSize(bindingCount); const ArrayParamSize offsetsSize = calculateArrayParameterSize(bindingCount); BindVertexBuffersParams *paramStruct = initCommand( CommandID::BindVertexBuffers, buffersSize.allocateBytes + offsetsSize.allocateBytes, &writePtr); // Copy params paramStruct->bindingCount = bindingCount; writePtr = storeArrayParameter(writePtr, buffers, buffersSize); storeArrayParameter(writePtr, offsets, offsetsSize); } ANGLE_INLINE void SecondaryCommandBuffer::bindVertexBuffers2(uint32_t firstBinding, uint32_t bindingCount, const VkBuffer *buffers, const VkDeviceSize *offsets, const VkDeviceSize *sizes, const VkDeviceSize *strides) { ASSERT(firstBinding == 0); ASSERT(sizes == nullptr); uint8_t *writePtr; const ArrayParamSize buffersSize = calculateArrayParameterSize(bindingCount); const ArrayParamSize offsetsSize = calculateArrayParameterSize(bindingCount); const ArrayParamSize stridesSize = offsetsSize; BindVertexBuffers2Params *paramStruct = initCommand( CommandID::BindVertexBuffers2, buffersSize.allocateBytes + offsetsSize.allocateBytes + stridesSize.allocateBytes, &writePtr); // Copy params paramStruct->bindingCount = bindingCount; writePtr = storeArrayParameter(writePtr, buffers, buffersSize); writePtr = storeArrayParameter(writePtr, offsets, offsetsSize); storeArrayParameter(writePtr, strides, stridesSize); } ANGLE_INLINE void SecondaryCommandBuffer::blitImage(const Image &srcImage, VkImageLayout srcImageLayout, const Image &dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageBlit *regions, VkFilter filter) { // Currently ANGLE uses limited params so verify those assumptions and update if they change ASSERT(srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); ASSERT(dstImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); ASSERT(regionCount == 1); BlitImageParams *paramStruct = initCommand(CommandID::BlitImage); paramStruct->srcImage = srcImage.getHandle(); paramStruct->dstImage = dstImage.getHandle(); paramStruct->filter = filter; paramStruct->region = regions[0]; } ANGLE_INLINE void SecondaryCommandBuffer::bufferBarrier( VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, const VkBufferMemoryBarrier *bufferMemoryBarrier) { // Used only during queue family ownership transfers ASSERT(srcStageMask == VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); ASSERT(dstStageMask == VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); BufferBarrierParams *paramStruct = initCommand(CommandID::BufferBarrier); paramStruct->bufferMemoryBarrier = *bufferMemoryBarrier; } ANGLE_INLINE void SecondaryCommandBuffer::bufferBarrier2( const VkBufferMemoryBarrier2 *bufferMemoryBarrier2) { ASSERT(bufferMemoryBarrier2->srcStageMask == VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT); ASSERT(bufferMemoryBarrier2->dstStageMask == VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT); BufferBarrier2Params *paramStruct = initCommand(CommandID::BufferBarrier2); paramStruct->bufferMemoryBarrier2 = *bufferMemoryBarrier2; } ANGLE_INLINE void SecondaryCommandBuffer::clearAttachments(uint32_t attachmentCount, const VkClearAttachment *attachments, uint32_t rectCount, const VkClearRect *rects) { ASSERT(rectCount == 1); uint8_t *writePtr; const ArrayParamSize attachmentSize = calculateArrayParameterSize(attachmentCount); ClearAttachmentsParams *paramStruct = initCommand( CommandID::ClearAttachments, attachmentSize.allocateBytes, &writePtr); paramStruct->attachmentCount = attachmentCount; paramStruct->rect = rects[0]; // Copy variable sized data storeArrayParameter(writePtr, attachments, attachmentSize); mCommandTracker.onClearAttachments(); } ANGLE_INLINE void SecondaryCommandBuffer::clearColorImage(const Image &image, VkImageLayout imageLayout, const VkClearColorValue &color, uint32_t rangeCount, const VkImageSubresourceRange *ranges) { ASSERT(rangeCount == 1); ClearColorImageParams *paramStruct = initCommand(CommandID::ClearColorImage); paramStruct->image = image.getHandle(); paramStruct->imageLayout = imageLayout; paramStruct->color = color; paramStruct->range = ranges[0]; } ANGLE_INLINE void SecondaryCommandBuffer::clearDepthStencilImage( const Image &image, VkImageLayout imageLayout, const VkClearDepthStencilValue &depthStencil, uint32_t rangeCount, const VkImageSubresourceRange *ranges) { ASSERT(rangeCount == 1); ClearDepthStencilImageParams *paramStruct = initCommand(CommandID::ClearDepthStencilImage); paramStruct->image = image.getHandle(); paramStruct->imageLayout = imageLayout; paramStruct->depthStencil = depthStencil; paramStruct->range = ranges[0]; } ANGLE_INLINE void SecondaryCommandBuffer::copyBuffer(const Buffer &srcBuffer, const Buffer &destBuffer, uint32_t regionCount, const VkBufferCopy *regions) { uint8_t *writePtr; const ArrayParamSize regionSize = calculateArrayParameterSize(regionCount); CopyBufferParams *paramStruct = initCommand(CommandID::CopyBuffer, regionSize.allocateBytes, &writePtr); paramStruct->srcBuffer = srcBuffer.getHandle(); paramStruct->destBuffer = destBuffer.getHandle(); paramStruct->regionCount = regionCount; // Copy variable sized data storeArrayParameter(writePtr, regions, regionSize); } ANGLE_INLINE void SecondaryCommandBuffer::copyBufferToImage(VkBuffer srcBuffer, const Image &dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkBufferImageCopy *regions) { ASSERT(regionCount == 1); CopyBufferToImageParams *paramStruct = initCommand(CommandID::CopyBufferToImage); paramStruct->srcBuffer = srcBuffer; paramStruct->dstImage = dstImage.getHandle(); paramStruct->dstImageLayout = dstImageLayout; paramStruct->region = regions[0]; } ANGLE_INLINE void SecondaryCommandBuffer::copyImage(const Image &srcImage, VkImageLayout srcImageLayout, const Image &dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageCopy *regions) { ASSERT(regionCount == 1); CopyImageParams *paramStruct = initCommand(CommandID::CopyImage); paramStruct->srcImage = srcImage.getHandle(); paramStruct->srcImageLayout = srcImageLayout; paramStruct->dstImage = dstImage.getHandle(); paramStruct->dstImageLayout = dstImageLayout; paramStruct->region = regions[0]; } ANGLE_INLINE void SecondaryCommandBuffer::copyImageToBuffer(const Image &srcImage, VkImageLayout srcImageLayout, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy *regions) { ASSERT(regionCount == 1); CopyImageToBufferParams *paramStruct = initCommand(CommandID::CopyImageToBuffer); paramStruct->srcImage = srcImage.getHandle(); paramStruct->srcImageLayout = srcImageLayout; paramStruct->dstBuffer = dstBuffer; paramStruct->region = regions[0]; } ANGLE_INLINE void SecondaryCommandBuffer::dispatch(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) { DispatchParams *paramStruct = initCommand(CommandID::Dispatch); paramStruct->groupCountX = groupCountX; paramStruct->groupCountY = groupCountY; paramStruct->groupCountZ = groupCountZ; } ANGLE_INLINE void SecondaryCommandBuffer::dispatchIndirect(const Buffer &buffer, VkDeviceSize offset) { DispatchIndirectParams *paramStruct = initCommand(CommandID::DispatchIndirect); paramStruct->buffer = buffer.getHandle(); paramStruct->offset = offset; } ANGLE_INLINE void SecondaryCommandBuffer::draw(uint32_t vertexCount, uint32_t firstVertex) { DrawParams *paramStruct = initCommand(CommandID::Draw); paramStruct->vertexCount = vertexCount; paramStruct->firstVertex = firstVertex; mCommandTracker.onDraw(); } ANGLE_INLINE void SecondaryCommandBuffer::drawIndexed(uint32_t indexCount) { DrawIndexedParams *paramStruct = initCommand(CommandID::DrawIndexed); paramStruct->indexCount = indexCount; mCommandTracker.onDraw(); } ANGLE_INLINE void SecondaryCommandBuffer::drawIndexedBaseVertex(uint32_t indexCount, uint32_t vertexOffset) { DrawIndexedBaseVertexParams *paramStruct = initCommand(CommandID::DrawIndexedBaseVertex); paramStruct->indexCount = indexCount; paramStruct->vertexOffset = vertexOffset; mCommandTracker.onDraw(); } ANGLE_INLINE void SecondaryCommandBuffer::drawIndexedIndirect(const Buffer &buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride) { DrawIndexedIndirectParams *paramStruct = initCommand(CommandID::DrawIndexedIndirect); paramStruct->buffer = buffer.getHandle(); paramStruct->offset = offset; paramStruct->drawCount = drawCount; paramStruct->stride = stride; mCommandTracker.onDraw(); } ANGLE_INLINE void SecondaryCommandBuffer::drawIndexedInstanced(uint32_t indexCount, uint32_t instanceCount) { DrawIndexedInstancedParams *paramStruct = initCommand(CommandID::DrawIndexedInstanced); paramStruct->indexCount = indexCount; paramStruct->instanceCount = instanceCount; mCommandTracker.onDraw(); } ANGLE_INLINE void SecondaryCommandBuffer::drawIndexedInstancedBaseVertex(uint32_t indexCount, uint32_t instanceCount, uint32_t vertexOffset) { DrawIndexedInstancedBaseVertexParams *paramStruct = initCommand( CommandID::DrawIndexedInstancedBaseVertex); paramStruct->indexCount = indexCount; paramStruct->instanceCount = instanceCount; paramStruct->vertexOffset = vertexOffset; mCommandTracker.onDraw(); } ANGLE_INLINE void SecondaryCommandBuffer::drawIndexedInstancedBaseVertexBaseInstance( uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) { DrawIndexedInstancedBaseVertexBaseInstanceParams *paramStruct = initCommand( CommandID::DrawIndexedInstancedBaseVertexBaseInstance); paramStruct->indexCount = indexCount; paramStruct->instanceCount = instanceCount; paramStruct->firstIndex = firstIndex; paramStruct->vertexOffset = vertexOffset; paramStruct->firstInstance = firstInstance; mCommandTracker.onDraw(); } ANGLE_INLINE void SecondaryCommandBuffer::drawIndirect(const Buffer &buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride) { DrawIndirectParams *paramStruct = initCommand(CommandID::DrawIndirect); paramStruct->buffer = buffer.getHandle(); paramStruct->offset = offset; paramStruct->drawCount = drawCount; paramStruct->stride = stride; mCommandTracker.onDraw(); } ANGLE_INLINE void SecondaryCommandBuffer::drawInstanced(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex) { DrawInstancedParams *paramStruct = initCommand(CommandID::DrawInstanced); paramStruct->vertexCount = vertexCount; paramStruct->instanceCount = instanceCount; paramStruct->firstVertex = firstVertex; mCommandTracker.onDraw(); } ANGLE_INLINE void SecondaryCommandBuffer::drawInstancedBaseInstance(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) { DrawInstancedBaseInstanceParams *paramStruct = initCommand(CommandID::DrawInstancedBaseInstance); paramStruct->vertexCount = vertexCount; paramStruct->instanceCount = instanceCount; paramStruct->firstVertex = firstVertex; paramStruct->firstInstance = firstInstance; mCommandTracker.onDraw(); } ANGLE_INLINE void SecondaryCommandBuffer::endDebugUtilsLabelEXT() { initCommand(CommandID::EndDebugUtilsLabel); } ANGLE_INLINE void SecondaryCommandBuffer::endQuery(const QueryPool &queryPool, uint32_t query) { EndQueryParams *paramStruct = initCommand(CommandID::EndQuery); paramStruct->queryPool = queryPool.getHandle(); paramStruct->query = query; } ANGLE_INLINE void SecondaryCommandBuffer::endTransformFeedback( uint32_t firstCounterBuffer, uint32_t counterBufferCount, const VkBuffer *counterBuffers, const VkDeviceSize *counterBufferOffsets) { ASSERT(firstCounterBuffer == 0); uint8_t *writePtr; const ArrayParamSize buffersSize = calculateArrayParameterSize(counterBufferCount); const ArrayParamSize offsetsSize = calculateArrayParameterSize(counterBufferCount); EndTransformFeedbackParams *paramStruct = initCommand( CommandID::EndTransformFeedback, buffersSize.allocateBytes + offsetsSize.allocateBytes, &writePtr); paramStruct->bufferCount = counterBufferCount; writePtr = storeArrayParameter(writePtr, counterBuffers, buffersSize); storeArrayParameter(writePtr, counterBufferOffsets, offsetsSize); } ANGLE_INLINE void SecondaryCommandBuffer::fillBuffer(const Buffer &dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data) { FillBufferParams *paramStruct = initCommand(CommandID::FillBuffer); paramStruct->dstBuffer = dstBuffer.getHandle(); paramStruct->dstOffset = dstOffset; paramStruct->size = size; paramStruct->data = data; } ANGLE_INLINE void SecondaryCommandBuffer::imageBarrier( VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, const VkImageMemoryBarrier &imageMemoryBarrier) { ASSERT(imageMemoryBarrier.pNext == nullptr); uint8_t *writePtr; const ArrayParamSize imgBarrierSize = calculateArrayParameterSize(1); ImageBarrierParams *paramStruct = initCommand( CommandID::ImageBarrier, imgBarrierSize.allocateBytes, &writePtr); paramStruct->srcStageMask = srcStageMask; paramStruct->dstStageMask = dstStageMask; storeArrayParameter(writePtr, &imageMemoryBarrier, imgBarrierSize); } ANGLE_INLINE void SecondaryCommandBuffer::imageBarrier2( const VkImageMemoryBarrier2 &imageMemoryBarrier2) { ASSERT(imageMemoryBarrier2.pNext == nullptr); uint8_t *writePtr; const ArrayParamSize imgBarrier2Size = calculateArrayParameterSize(1); initCommand(CommandID::ImageBarrier2, imgBarrier2Size.allocateBytes, &writePtr); storeArrayParameter(writePtr, &imageMemoryBarrier2, imgBarrier2Size); } ANGLE_INLINE void SecondaryCommandBuffer::imageWaitEvent( const VkEvent &event, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, const VkImageMemoryBarrier &imageMemoryBarrier) { ASSERT(imageMemoryBarrier.pNext == nullptr); uint8_t *writePtr; const ArrayParamSize imgBarrierSize = calculateArrayParameterSize(1); ImageWaitEventParams *paramStruct = initCommand( CommandID::ImageWaitEvent, imgBarrierSize.allocateBytes, &writePtr); paramStruct->event = event; paramStruct->srcStageMask = srcStageMask; paramStruct->dstStageMask = dstStageMask; storeArrayParameter(writePtr, &imageMemoryBarrier, imgBarrierSize); } ANGLE_INLINE void SecondaryCommandBuffer::insertDebugUtilsLabelEXT( const VkDebugUtilsLabelEXT &label) { commonDebugUtilsLabel(CommandID::InsertDebugUtilsLabel, label); } ANGLE_INLINE void SecondaryCommandBuffer::memoryBarrier(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, const VkMemoryBarrier &memoryBarrier) { ASSERT(memoryBarrier.pNext == nullptr); uint8_t *writePtr; const ArrayParamSize memBarrierSize = calculateArrayParameterSize(1); MemoryBarrierParams *paramStruct = initCommand( CommandID::MemoryBarrier, memBarrierSize.allocateBytes, &writePtr); paramStruct->srcStageMask = srcStageMask; paramStruct->dstStageMask = dstStageMask; storeArrayParameter(writePtr, &memoryBarrier, memBarrierSize); } ANGLE_INLINE void SecondaryCommandBuffer::memoryBarrier2(const VkMemoryBarrier2 &memoryBarrier2) { ASSERT(memoryBarrier2.pNext == nullptr); uint8_t *writePtr; const ArrayParamSize memBarrierSize = calculateArrayParameterSize(1); initCommand(CommandID::MemoryBarrier2, memBarrierSize.allocateBytes, &writePtr); storeArrayParameter(writePtr, &memoryBarrier2, memBarrierSize); } ANGLE_INLINE void SecondaryCommandBuffer::nextSubpass(VkSubpassContents subpassContents) { ASSERT(subpassContents == VK_SUBPASS_CONTENTS_INLINE); initCommand(CommandID::NextSubpass); } ANGLE_INLINE void SecondaryCommandBuffer::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) { // Other than for QFOT (where bufferBarrier() is used), ANGLE doesn't use buffer barriers. // Memory barriers are used instead. ASSERT(bufferMemoryBarrierCount == 0); ASSERT(bufferMemoryBarriers == nullptr); uint8_t *writePtr; const ArrayParamSize memBarrierSize = calculateArrayParameterSize(memoryBarrierCount); const ArrayParamSize imgBarrierSize = calculateArrayParameterSize(imageMemoryBarrierCount); PipelineBarrierParams *paramStruct = initCommand( CommandID::PipelineBarrier, memBarrierSize.allocateBytes + imgBarrierSize.allocateBytes, &writePtr); paramStruct->srcStageMask = srcStageMask; paramStruct->dstStageMask = dstStageMask; paramStruct->dependencyFlags = dependencyFlags; paramStruct->memoryBarrierCount = memoryBarrierCount; paramStruct->imageMemoryBarrierCount = imageMemoryBarrierCount; // Copy variable sized data if (memoryBarrierCount > 0) { writePtr = storeArrayParameter(writePtr, memoryBarriers, memBarrierSize); } if (imageMemoryBarrierCount > 0) { storeArrayParameter(writePtr, imageMemoryBarriers, imgBarrierSize); } } ANGLE_INLINE void SecondaryCommandBuffer::pipelineBarrier2( VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier2 *memoryBarriers2, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier2 *bufferMemoryBarriers2, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier2 *imageMemoryBarriers2) { // Other than for QFOT (where bufferBarrier() is used), ANGLE doesn't use buffer barriers. // Memory barriers are used instead. ASSERT(bufferMemoryBarrierCount == 0); ASSERT(bufferMemoryBarriers2 == nullptr); uint8_t *writePtr; const ArrayParamSize memBarrier2Size = calculateArrayParameterSize(memoryBarrierCount); const ArrayParamSize imgBarrier2Size = calculateArrayParameterSize(imageMemoryBarrierCount); PipelineBarrierParams2 *paramStruct = initCommand( CommandID::PipelineBarrier2, memBarrier2Size.allocateBytes + imgBarrier2Size.allocateBytes, &writePtr); paramStruct->dependencyFlags = dependencyFlags; paramStruct->memoryBarrierCount = memoryBarrierCount; paramStruct->imageMemoryBarrierCount = imageMemoryBarrierCount; // Copy variable sized data if (memoryBarrierCount > 0) { writePtr = storeArrayParameter(writePtr, memoryBarriers2, memBarrier2Size); } if (imageMemoryBarrierCount > 0) { storeArrayParameter(writePtr, imageMemoryBarriers2, imgBarrier2Size); } } ANGLE_INLINE void SecondaryCommandBuffer::pushConstants(const PipelineLayout &layout, VkShaderStageFlags flag, uint32_t offset, uint32_t size, const void *data) { ASSERT(size == static_cast(size)); uint8_t *writePtr; const ArrayParamSize dataSize = calculateArrayParameterSize(size); PushConstantsParams *paramStruct = initCommand( CommandID::PushConstants, dataSize.allocateBytes, &writePtr); paramStruct->layout = layout.getHandle(); paramStruct->flag = flag; paramStruct->offset = offset; paramStruct->size = size; // Copy variable sized data storeArrayParameter(writePtr, data, dataSize); } ANGLE_INLINE void SecondaryCommandBuffer::resetEvent(VkEvent event, VkPipelineStageFlags stageMask) { ResetEventParams *paramStruct = initCommand(CommandID::ResetEvent); paramStruct->event = event; paramStruct->stageMask = stageMask; } ANGLE_INLINE void SecondaryCommandBuffer::resetQueryPool(const QueryPool &queryPool, uint32_t firstQuery, uint32_t queryCount) { ResetQueryPoolParams *paramStruct = initCommand(CommandID::ResetQueryPool); paramStruct->queryPool = queryPool.getHandle(); SetBitField(paramStruct->firstQuery, firstQuery); SetBitField(paramStruct->queryCount, queryCount); } ANGLE_INLINE void SecondaryCommandBuffer::resolveImage(const Image &srcImage, VkImageLayout srcImageLayout, const Image &dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageResolve *regions) { // Currently ANGLE uses limited params so verify those assumptions and update if they change. ASSERT(srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); ASSERT(dstImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); ASSERT(regionCount == 1); ResolveImageParams *paramStruct = initCommand(CommandID::ResolveImage); paramStruct->srcImage = srcImage.getHandle(); paramStruct->dstImage = dstImage.getHandle(); paramStruct->region = regions[0]; } ANGLE_INLINE void SecondaryCommandBuffer::setBlendConstants(const float blendConstants[4]) { SetBlendConstantsParams *paramStruct = initCommand(CommandID::SetBlendConstants); for (uint32_t channel = 0; channel < 4; ++channel) { paramStruct->blendConstants[channel] = blendConstants[channel]; } } ANGLE_INLINE void SecondaryCommandBuffer::setCullMode(VkCullModeFlags cullMode) { SetCullModeParams *paramStruct = initCommand(CommandID::SetCullMode); paramStruct->cullMode = cullMode; } ANGLE_INLINE void SecondaryCommandBuffer::setDepthBias(float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor) { SetDepthBiasParams *paramStruct = initCommand(CommandID::SetDepthBias); paramStruct->depthBiasConstantFactor = depthBiasConstantFactor; paramStruct->depthBiasClamp = depthBiasClamp; paramStruct->depthBiasSlopeFactor = depthBiasSlopeFactor; } ANGLE_INLINE void SecondaryCommandBuffer::setDepthBiasEnable(VkBool32 depthBiasEnable) { SetDepthBiasEnableParams *paramStruct = initCommand(CommandID::SetDepthBiasEnable); paramStruct->depthBiasEnable = depthBiasEnable; } ANGLE_INLINE void SecondaryCommandBuffer::setDepthCompareOp(VkCompareOp depthCompareOp) { SetDepthCompareOpParams *paramStruct = initCommand(CommandID::SetDepthCompareOp); paramStruct->depthCompareOp = depthCompareOp; } ANGLE_INLINE void SecondaryCommandBuffer::setDepthTestEnable(VkBool32 depthTestEnable) { SetDepthTestEnableParams *paramStruct = initCommand(CommandID::SetDepthTestEnable); paramStruct->depthTestEnable = depthTestEnable; } ANGLE_INLINE void SecondaryCommandBuffer::setDepthWriteEnable(VkBool32 depthWriteEnable) { SetDepthWriteEnableParams *paramStruct = initCommand(CommandID::SetDepthWriteEnable); paramStruct->depthWriteEnable = depthWriteEnable; } ANGLE_INLINE void SecondaryCommandBuffer::setEvent(VkEvent event, VkPipelineStageFlags stageMask) { SetEventParams *paramStruct = initCommand(CommandID::SetEvent); paramStruct->event = event; paramStruct->stageMask = stageMask; } ANGLE_INLINE void SecondaryCommandBuffer::setFragmentShadingRate( const VkExtent2D *fragmentSize, VkFragmentShadingRateCombinerOpKHR ops[2]) { ASSERT(fragmentSize != nullptr); // Supported parameter values - // 1. CombinerOp for ops[0] needs to be VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR // as there are no current usecases in ANGLE to use primitive fragment shading rates // 2. The largest fragment size supported is 4x4 ASSERT(ops[0] == VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR); ASSERT(fragmentSize->width <= 4); ASSERT(fragmentSize->height <= 4); SetFragmentShadingRateParams *paramStruct = initCommand(CommandID::SetFragmentShadingRate); paramStruct->fragmentWidth = static_cast(fragmentSize->width); paramStruct->fragmentHeight = static_cast(fragmentSize->height); paramStruct->vkFragmentShadingRateCombinerOp1 = static_cast(ops[1]); } ANGLE_INLINE void SecondaryCommandBuffer::setFrontFace(VkFrontFace frontFace) { SetFrontFaceParams *paramStruct = initCommand(CommandID::SetFrontFace); paramStruct->frontFace = frontFace; } ANGLE_INLINE void SecondaryCommandBuffer::setLineWidth(float lineWidth) { SetLineWidthParams *paramStruct = initCommand(CommandID::SetLineWidth); paramStruct->lineWidth = lineWidth; } ANGLE_INLINE void SecondaryCommandBuffer::setLogicOp(VkLogicOp logicOp) { SetLogicOpParams *paramStruct = initCommand(CommandID::SetLogicOp); paramStruct->logicOp = logicOp; } ANGLE_INLINE void SecondaryCommandBuffer::setPrimitiveRestartEnable(VkBool32 primitiveRestartEnable) { SetPrimitiveRestartEnableParams *paramStruct = initCommand(CommandID::SetPrimitiveRestartEnable); paramStruct->primitiveRestartEnable = primitiveRestartEnable; } ANGLE_INLINE void SecondaryCommandBuffer::setRasterizerDiscardEnable( VkBool32 rasterizerDiscardEnable) { SetRasterizerDiscardEnableParams *paramStruct = initCommand(CommandID::SetRasterizerDiscardEnable); paramStruct->rasterizerDiscardEnable = rasterizerDiscardEnable; } ANGLE_INLINE void SecondaryCommandBuffer::setScissor(uint32_t firstScissor, uint32_t scissorCount, const VkRect2D *scissors) { ASSERT(firstScissor == 0); ASSERT(scissorCount == 1); ASSERT(scissors != nullptr); SetScissorParams *paramStruct = initCommand(CommandID::SetScissor); paramStruct->scissor = scissors[0]; } ANGLE_INLINE void SecondaryCommandBuffer::setStencilCompareMask(uint32_t compareFrontMask, uint32_t compareBackMask) { SetStencilCompareMaskParams *paramStruct = initCommand(CommandID::SetStencilCompareMask); paramStruct->compareFrontMask = static_cast(compareFrontMask); paramStruct->compareBackMask = static_cast(compareBackMask); } ANGLE_INLINE void SecondaryCommandBuffer::setStencilOp(VkStencilFaceFlags faceMask, VkStencilOp failOp, VkStencilOp passOp, VkStencilOp depthFailOp, VkCompareOp compareOp) { SetStencilOpParams *paramStruct = initCommand(CommandID::SetStencilOp); SetBitField(paramStruct->faceMask, faceMask); SetBitField(paramStruct->failOp, failOp); SetBitField(paramStruct->passOp, passOp); SetBitField(paramStruct->depthFailOp, depthFailOp); SetBitField(paramStruct->compareOp, compareOp); } ANGLE_INLINE void SecondaryCommandBuffer::setStencilReference(uint32_t frontReference, uint32_t backReference) { SetStencilReferenceParams *paramStruct = initCommand(CommandID::SetStencilReference); paramStruct->frontReference = static_cast(frontReference); paramStruct->backReference = static_cast(backReference); } ANGLE_INLINE void SecondaryCommandBuffer::setStencilTestEnable(VkBool32 stencilTestEnable) { SetStencilTestEnableParams *paramStruct = initCommand(CommandID::SetStencilTestEnable); paramStruct->stencilTestEnable = stencilTestEnable; } ANGLE_INLINE void SecondaryCommandBuffer::setStencilWriteMask(uint32_t writeFrontMask, uint32_t writeBackMask) { SetStencilWriteMaskParams *paramStruct = initCommand(CommandID::SetStencilWriteMask); paramStruct->writeFrontMask = static_cast(writeFrontMask); paramStruct->writeBackMask = static_cast(writeBackMask); } ANGLE_INLINE void SecondaryCommandBuffer::setVertexInput( uint32_t vertexBindingDescriptionCount, const VkVertexInputBindingDescription2EXT *vertexBindingDescriptions, uint32_t vertexAttributeDescriptionCount, const VkVertexInputAttributeDescription2EXT *vertexAttributeDescriptions) { uint8_t *writePtr; const ArrayParamSize vertexBindingDescriptionSize = calculateArrayParameterSize( vertexBindingDescriptionCount); const ArrayParamSize vertexAttributeDescriptionSize = calculateArrayParameterSize( vertexAttributeDescriptionCount); SetVertexInputParams *paramStruct = initCommand( CommandID::SetVertexInput, vertexBindingDescriptionSize.allocateBytes + vertexAttributeDescriptionSize.allocateBytes, &writePtr); // Copy params SetBitField(paramStruct->vertexBindingDescriptionCount, vertexBindingDescriptionCount); SetBitField(paramStruct->vertexAttributeDescriptionCount, vertexAttributeDescriptionCount); if (vertexBindingDescriptionSize.copyBytes) { writePtr = storeArrayParameter(writePtr, vertexBindingDescriptions, vertexBindingDescriptionSize); } if (vertexAttributeDescriptionSize.copyBytes) { storeArrayParameter(writePtr, vertexAttributeDescriptions, vertexAttributeDescriptionSize); } } ANGLE_INLINE void SecondaryCommandBuffer::setViewport(uint32_t firstViewport, uint32_t viewportCount, const VkViewport *viewports) { ASSERT(firstViewport == 0); ASSERT(viewportCount == 1); ASSERT(viewports != nullptr); SetViewportParams *paramStruct = initCommand(CommandID::SetViewport); paramStruct->viewport = viewports[0]; } ANGLE_INLINE void SecondaryCommandBuffer::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) { // Other than for QFOT (where bufferBarrier() is used), ANGLE doesn't use buffer barriers. // Memory barriers are used instead. ASSERT(bufferMemoryBarrierCount == 0); ASSERT(bufferMemoryBarriers == nullptr); uint8_t *writePtr; const ArrayParamSize eventSize = calculateArrayParameterSize(eventCount); const ArrayParamSize memBarrierSize = calculateArrayParameterSize(memoryBarrierCount); const ArrayParamSize imgBarrierSize = calculateArrayParameterSize(imageMemoryBarrierCount); WaitEventsParams *paramStruct = initCommand( CommandID::WaitEvents, eventSize.allocateBytes + memBarrierSize.allocateBytes + imgBarrierSize.allocateBytes, &writePtr); paramStruct->eventCount = eventCount; paramStruct->srcStageMask = srcStageMask; paramStruct->dstStageMask = dstStageMask; paramStruct->memoryBarrierCount = memoryBarrierCount; paramStruct->imageMemoryBarrierCount = imageMemoryBarrierCount; // Copy variable sized data writePtr = storeArrayParameter(writePtr, events, eventSize); writePtr = storeArrayParameter(writePtr, memoryBarriers, memBarrierSize); storeArrayParameter(writePtr, imageMemoryBarriers, imgBarrierSize); } ANGLE_INLINE void SecondaryCommandBuffer::writeTimestamp(VkPipelineStageFlagBits pipelineStage, const QueryPool &queryPool, uint32_t query) { ASSERT(pipelineStage == VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT); WriteTimestampParams *paramStruct = initCommand(CommandID::WriteTimestamp); paramStruct->queryPool = queryPool.getHandle(); paramStruct->query = query; } ANGLE_INLINE void SecondaryCommandBuffer::writeTimestamp2(VkPipelineStageFlagBits2 pipelineStage, const QueryPool &queryPool, uint32_t query) { ASSERT(pipelineStage == VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT); WriteTimestampParams *paramStruct = initCommand(CommandID::WriteTimestamp2); paramStruct->queryPool = queryPool.getHandle(); paramStruct->query = query; } } // namespace priv } // namespace vk } // namespace rx #endif // LIBANGLE_RENDERER_VULKAN_SECONDARYCOMMANDBUFFERVK_H_