// // Copyright 2018 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. // // vk_helpers: // Helper utility classes that manage Vulkan resources. #ifndef LIBANGLE_RENDERER_VULKAN_VK_HELPERS_H_ #define LIBANGLE_RENDERER_VULKAN_VK_HELPERS_H_ #include "common/MemoryBuffer.h" #include "common/SimpleMutex.h" #include "libANGLE/renderer/vulkan/MemoryTracking.h" #include "libANGLE/renderer/vulkan/Suballocation.h" #include "libANGLE/renderer/vulkan/vk_cache_utils.h" #include "libANGLE/renderer/vulkan/vk_format_utils.h" #include "libANGLE/renderer/vulkan/vk_ref_counted_event.h" #include <functional> namespace gl { class ImageIndex; } // namespace gl namespace rx { namespace vk { constexpr VkBufferUsageFlags kVertexBufferUsageFlags = …; constexpr VkBufferUsageFlags kIndexBufferUsageFlags = …; constexpr VkBufferUsageFlags kIndirectBufferUsageFlags = …; constexpr size_t kVertexBufferAlignment = …; constexpr size_t kIndexBufferAlignment = …; constexpr size_t kIndirectBufferAlignment = …; constexpr VkBufferUsageFlags kStagingBufferFlags = …; constexpr size_t kStagingBufferSize = …; constexpr VkImageCreateFlags kVkImageCreateFlagsNone = …; // Most likely initial chroma filter mode given GL_TEXTURE_EXTERNAL_OES default // min & mag filters are linear. constexpr VkFilter kDefaultYCbCrChromaFilter = …; constexpr VkPipelineStageFlags kSwapchainAcquireImageWaitStageFlags = …; // First use is a clear without scissor. // For each level, write layers that don't conflict in parallel. The layer is hashed to // `layer % kMaxParallelLayerWrites` and used to track whether that subresource is currently // being written. If so, a barrier is inserted; otherwise, the barrier is avoided. If the updated // layer count is greater than kMaxParallelLayerWrites, there will be a few unnecessary // barriers. constexpr uint32_t kMaxParallelLayerWrites = …; ImageLayerWriteMask; StagingBufferOffsetArray; // Imagine an image going through a few layout transitions: // // srcStage 1 dstStage 2 srcStage 2 dstStage 3 // Layout 1 ------Transition 1-----> Layout 2 ------Transition 2------> Layout 3 // srcAccess 1 dstAccess 2 srcAccess 2 dstAccess 3 // \_________________ ___________________/ // \/ // A transition // // Every transition requires 6 pieces of information: from/to layouts, src/dst stage masks and // src/dst access masks. At the moment we decide to transition the image to Layout 2 (i.e. // Transition 1), we need to have Layout 1, srcStage 1 and srcAccess 1 stored as history of the // image. To perform the transition, we need to know Layout 2, dstStage 2 and dstAccess 2. // Additionally, we need to know srcStage 2 and srcAccess 2 to retain them for the next transition. // // That is, with the history kept, on every new transition we need 5 pieces of new information: // layout/dstStage/dstAccess to transition into the layout, and srcStage/srcAccess for the future // transition out from it. Given the small number of possible combinations of these values, an // enum is used were each value encapsulates these 5 pieces of information: // // +--------------------------------+ // srcStage 1 | dstStage 2 srcStage 2 | dstStage 3 // Layout 1 ------Transition 1-----> Layout 2 ------Transition 2------> Layout 3 // srcAccess 1 |dstAccess 2 srcAccess 2| dstAccess 3 // +--------------- ---------------+ // \/ // One enum value // // Note that, while generally dstStage for the to-transition and srcStage for the from-transition // are the same, they may occasionally be BOTTOM_OF_PIPE and TOP_OF_PIPE respectively. enum class ImageLayout { … }; VkImageCreateFlags GetImageCreateFlags(gl::TextureType textureType); ImageLayout GetImageLayoutFromGLImageLayout(Context *context, GLenum layout); GLenum ConvertImageLayoutToGLImageLayout(ImageLayout imageLayout); VkImageLayout ConvertImageLayoutToVkImageLayout(Renderer *renderer, ImageLayout imageLayout); // A dynamic buffer is conceptually an infinitely long buffer. Each time you write to the buffer, // you will always write to a previously unused portion. After a series of writes, you must flush // the buffer data to the device. Buffer lifetime currently assumes that each new allocation will // last as long or longer than each prior allocation. // // Dynamic buffers are used to implement a variety of data streaming operations in Vulkan, such // as for immediate vertex array and element array data, uniform updates, and other dynamic data. // // Internally dynamic buffers keep a collection of VkBuffers. When we write past the end of a // currently active VkBuffer we keep it until it is no longer in use. We then mark it available // for future allocations in a free list. class BufferHelper; BufferHelperQueue; class DynamicBuffer : angle::NonCopyable { … }; // Class DescriptorSetHelper. This is a wrapper of VkDescriptorSet with GPU resource use tracking. class DescriptorSetHelper final : public Resource { … }; DescriptorSetList; // Uses DescriptorPool to allocate descriptor sets as needed. If a descriptor pool becomes full, we // allocate new pools internally as needed. Renderer takes care of the lifetime of the discarded // pools. Note that we used a fixed layout for descriptor pools in ANGLE. // Shared handle to a descriptor pool. Each helper is allocated from the dynamic descriptor pool. // Can be used to share descriptor pools between multiple ProgramVks and the ContextVk. class CommandBufferHelperCommon; class DescriptorPoolHelper final : public Resource { … }; RefCountedDescriptorPoolBinding; class DynamicDescriptorPool final : angle::NonCopyable { … }; RefCountedDescriptorPool; DescriptorPoolPointer; // Maps from a descriptor set layout (represented by DescriptorSetLayoutDesc) to a set of // DynamicDescriptorPools. The purpose of the class is so multiple GL Programs can share descriptor // set caches. We need to stratify the sets by the descriptor set layout to ensure compatibility. class MetaDescriptorPool final : angle::NonCopyable { … }; template <typename Pool> class DynamicallyGrowingPool : angle::NonCopyable { … }; // DynamicQueryPool allocates indices out of QueryPool as needed. Once a QueryPool is exhausted, // another is created. The query pools live permanently, but are recycled as indices get freed. // These are arbitrary default sizes for query pools. constexpr uint32_t kDefaultOcclusionQueryPoolSize = …; constexpr uint32_t kDefaultTimestampQueryPoolSize = …; constexpr uint32_t kDefaultTransformFeedbackQueryPoolSize = …; constexpr uint32_t kDefaultPrimitivesGeneratedQueryPoolSize = …; class QueryHelper; class DynamicQueryPool final : public DynamicallyGrowingPool<QueryPool> { … }; // Stores the result of a Vulkan query call. XFB queries in particular store two result values. class QueryResult final { … }; // Queries in Vulkan are identified by the query pool and an index for a query within that pool. // Unlike other pools, such as descriptor pools where an allocation returns an independent object // from the pool, the query allocations are not done through a Vulkan function and are only an // integer index. // // Furthermore, to support arbitrarily large number of queries, DynamicQueryPool creates query pools // of a fixed size as needed and allocates indices within those pools. // // The QueryHelper class below keeps the pool and index pair together. For multiview, multiple // consecutive query indices are implicitly written to by the driver, so the query count is // additionally kept. class QueryHelper final : public Resource { … }; // Semaphores that are allocated from the semaphore pool are encapsulated in a helper object, // keeping track of where in the pool they are allocated from. class SemaphoreHelper final : angle::NonCopyable { … }; // This defines enum for VkPipelineStageFlagBits so that we can use it to compare and index into // array. enum class PipelineStage : uint32_t { … }; PipelineStagesMask; PipelineStage GetPipelineStage(gl::ShaderType stage); struct ImageMemoryBarrierData { … }; // Initialize ImageLayout to ImageMemoryBarrierData mapping table. void InitializeImageLayoutAndMemoryBarrierDataMap( angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> *mapping, VkPipelineStageFlags supportedVulkanPipelineStageMask); bool EventAndPipelineBarrierHaveMatchingStageFlags( const angle::PackedEnumMap<EventStage, VkPipelineStageFlags> &eventStageMap, const angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> &barrierDataMap); // This wraps data and API for vkCmdPipelineBarrier call class PipelineBarrier : angle::NonCopyable { … }; class PipelineBarrierArray final { … }; enum class MemoryCoherency : uint8_t { … }; ANGLE_INLINE bool IsCached(MemoryCoherency coherency) { … } class BufferPool; class BufferHelper : public ReadWriteResource { … }; class BufferPool : angle::NonCopyable { … }; BufferPoolPointerArray; // Stores clear value In packed attachment index class PackedClearValuesArray final { … }; class ImageHelper; ImageHelperPtr; // Reference to a render pass attachment (color or depth/stencil) alongside render-pass-related // tracking such as when the attachment is last written to or invalidated. This is used to // determine loadOp and storeOp of the attachment, and enables optimizations that need to know // how the attachment has been used. class RenderPassAttachment final { … }; // Stores RenderPassAttachment In packed attachment index class PackedRenderPassAttachmentArray final { … }; class SecondaryCommandBufferCollector final { … }; struct CommandsState { … }; // How the ImageHelper object is being used by the renderpass enum class RenderPassUsage { … }; RenderPassUsageFlags; constexpr RenderPassUsageFlags kDepthStencilReadOnlyBits = …; constexpr RenderPassUsageFlags kDepthStencilFeedbackModeBits = …; // The following are used to help track the state of an invalidated attachment. // This value indicates an "infinite" CmdCount that is not valid for comparing constexpr uint32_t kInfiniteCmdCount = …; // CommandBufferHelperCommon and derivatives OutsideRenderPassCommandBufferHelper and // RenderPassCommandBufferHelper wrap the outside/inside render pass secondary command buffers, // together with other information such as barriers to issue before the command buffer, tracking of // resource usages, etc. When the asyncCommandQueue feature is enabled, objects of these classes // are handed off to the worker thread to be executed on the primary command buffer. class CommandBufferHelperCommon : angle::NonCopyable { … }; class SecondaryCommandBufferCollector; class OutsideRenderPassCommandBufferHelper final : public CommandBufferHelperCommon { … }; enum class ImagelessFramebuffer { … }; enum class RenderPassSource { … }; class RenderPassFramebuffer : angle::NonCopyable { … }; class RenderPassCommandBufferHelper final : public CommandBufferHelperCommon { … }; // The following class helps support both Vulkan and ANGLE secondary command buffers by // encapsulating their differences. template <typename CommandBufferHelperT> class CommandBufferRecycler { … }; // The source of update to an ImageHelper enum class UpdateSource { … }; enum class ApplyImageUpdate { … }; constexpr VkImageAspectFlagBits IMAGE_ASPECT_DEPTH_STENCIL = …; bool FormatHasNecessaryFeature(Renderer *renderer, angle::FormatID formatID, VkImageTiling tilingMode, VkFormatFeatureFlags featureBits); bool CanCopyWithTransfer(Renderer *renderer, angle::FormatID srcFormatID, VkImageTiling srcTilingMode, angle::FormatID dstFormatID, VkImageTiling dstTilingMode); class ImageViewHelper; class ImageHelper final : public Resource, public angle::Subject { … }; ANGLE_INLINE bool RenderPassCommandBufferHelper::usesImage(const ImageHelper &image) const { … } ANGLE_INLINE bool RenderPassCommandBufferHelper::startedAndUsesImageWithBarrier( const ImageHelper &image) const { … } // A vector of image views, such as one per level or one per layer. ImageViewVector; // A vector of vector of image views. Primary index is layer, secondary index is level. LayerLevelImageViewVector; // Address mode for layers: only possible to access either all layers, or up to // IMPLEMENTATION_ANGLE_MULTIVIEW_MAX_VIEWS layers. This enum uses 0 for all layers and the rest of // the values conveniently alias the number of layers. enum LayerMode { … }; static_assert …; LayerMode GetLayerMode(const vk::ImageHelper &image, uint32_t layerCount); // Sampler decode mode indicating if an attachment needs to be decoded in linear colorspace or sRGB enum class SrgbDecodeMode { … }; class ImageViewHelper final : angle::NonCopyable { … }; ImageSubresourceRange MakeImageSubresourceReadRange(gl::LevelIndex level, uint32_t levelCount, uint32_t layer, LayerMode layerMode, SrgbDecodeMode srgbDecodeMode, gl::SrgbOverride srgbOverrideMode); ImageSubresourceRange MakeImageSubresourceDrawRange(gl::LevelIndex level, uint32_t layer, LayerMode layerMode, gl::SrgbWriteControlMode srgbWriteControlMode); class BufferViewHelper final : public Resource { … }; // Context state that can affect a compute pipeline ComputePipelineOptions; static_assert …; ComputePipelineOptions GetComputePipelineOptions(vk::PipelineRobustness robustness, vk::PipelineProtectedAccess protectedAccess); ComputePipelineCache; class ShaderProgramHelper : angle::NonCopyable { … }; // Tracks current handle allocation counts in the back-end. Useful for debugging and profiling. // Note: not all handle types are currently implemented. class ActiveHandleCounter final : angle::NonCopyable { … }; // Sometimes ANGLE issues a command internally, such as copies, draws and dispatches that do not // directly correspond to the application draw/dispatch call. Before the command is recorded in the // command buffer, the render pass may need to be broken and/or appropriate barriers may need to be // inserted. The following struct aggregates all resources that such internal commands need. struct CommandBufferBufferAccess { … }; struct CommandBufferImageAccess { … }; struct CommandBufferImageSubresourceAccess { … }; struct CommandBufferBufferExternalAcquireRelease { … }; struct CommandBufferResourceAccess { … }; class CommandBufferAccess : angle::NonCopyable { … }; enum class PresentMode { … }; VkPresentModeKHR ConvertPresentModeToVkPresentMode(PresentMode presentMode); PresentMode ConvertVkPresentModeToPresentMode(VkPresentModeKHR vkPresentMode); } // namespace vk } // namespace rx #endif // LIBANGLE_RENDERER_VULKAN_VK_HELPERS_H_