blob: aa8801ea96b6200bea6031f9fe6c432beed9aca3 [file]
//
// Copyright 2025 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.
//
#ifndef LIBANGLE_RENDERER_VULKAN_VK_BARRIER_DATA_H_
#define LIBANGLE_RENDERER_VULKAN_VK_BARRIER_DATA_H_
#include <atomic>
#include <limits>
#include <queue>
#include "libANGLE/renderer/vulkan/vk_cache_utils.h"
#include "libANGLE/renderer/vulkan/vk_ref_counted_event.h"
namespace angle
{
struct FeaturesVk;
}
namespace rx
{
namespace vk
{
class Renderer;
// Information useful for buffer-related barriers
struct BufferMemoryBarrierData
{
VkPipelineStageFlags pipelineStageFlags;
// EventStage::InvalidEnum indicates don't use VkEvent for barrier(i.e., use pipelineBarrier
// instead)
EventStage eventStage;
};
const BufferMemoryBarrierData &GetBufferMemoryBarrierData(PipelineStage stage);
// 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 ImageAccess
{
Undefined = 0,
// Framebuffer attachment accesses are placed first, so they can fit in fewer bits in
// PackedAttachmentOpsDesc.
// Color (Write):
ColorWrite,
// Used only with dynamic rendering, because it needs a different VkImageLayout
ColorWriteAndInput,
MSRTTEmulationColorUnresolveAndResolve,
// Depth (Write), Stencil (Write)
DepthWriteStencilWrite,
// Used only with dynamic rendering, because it needs a different VkImageLayout. For
// simplicity, depth/stencil attachments when used as input attachments don't attempt to
// distinguish read-only aspects. That's only useful for supporting feedback loops, but if an
// application is reading depth or stencil through an input attachment, it's safe to assume they
// wouldn't be accessing the other aspect through a sampler!
DepthStencilWriteAndInput,
// Depth (Write), Stencil (Read)
DepthWriteStencilRead,
DepthWriteStencilReadFragmentShaderStencilRead,
DepthWriteStencilReadAllShadersStencilRead,
// Depth (Read), Stencil (Write)
DepthReadStencilWrite,
DepthReadStencilWriteFragmentShaderDepthRead,
DepthReadStencilWriteAllShadersDepthRead,
// Depth (Read), Stencil (Read)
DepthReadStencilRead,
DepthReadStencilReadFragmentShaderRead,
DepthReadStencilReadAllShadersRead,
// The GENERAL layout is used when there's a feedback loop. For depth/stencil it doesn't matter
// which aspect is participating in feedback and whether the other aspect is read-only.
ColorWriteFragmentShaderFeedback,
ColorWriteAllShadersFeedback,
DepthStencilFragmentShaderFeedback,
DepthStencilAllShadersFeedback,
// Depth/stencil resolve is special because it uses the _color_ output stage and mask
DepthStencilResolve,
MSRTTEmulationDepthStencilUnresolveAndResolve,
Present,
SharedPresent,
// The rest of the accesses.
ExternalPreInitialized,
ExternalShadersReadOnly,
ExternalShadersWrite,
ForeignAccess,
TransferSrc,
TransferDst,
TransferSrcDst,
// Used when the image is transitioned on the host for use by host image copy
HostCopy,
VertexShaderReadOnly,
VertexShaderWrite,
// PreFragment == Vertex, Tessellation and Geometry stages
PreFragmentShadersReadOnly,
PreFragmentShadersWrite,
FragmentShadingRateAttachmentReadOnly,
FragmentShaderReadOnly,
FragmentShaderWrite,
ComputeShaderReadOnly,
ComputeShaderWrite,
AllGraphicsShadersReadOnly,
AllGraphicsShadersWrite,
TransferDstAndComputeWrite,
InvalidEnum,
EnumCount = InvalidEnum,
};
ImageAccess GetImageAccessFromGLImageLayout(ErrorContext *context, GLenum layout);
// Information useful for image-related barriers
struct ImageMemoryBarrierData
{
// The Vk layout corresponding to the ImageAccess key.
VkImageLayout layout;
// The stage in which the image is used (or Bottom/Top if not using any specific stage). Unless
// Bottom/Top (Bottom used for transition to and Top used for transition from), the two values
// should match.
VkPipelineStageFlags dstStageMask;
VkPipelineStageFlags srcStageMask;
// Access mask when transitioning into this layout.
VkAccessFlags dstAccessMask;
// Access mask when transitioning out from this layout. Note that source access mask never
// needs a READ bit, as WAR hazards don't need memory barriers (just execution barriers).
VkAccessFlags srcAccessMask;
// Read or write.
ResourceAccess type;
// *CommandBufferHelper track an array of PipelineBarriers. This indicates which array element
// this should be merged into. Right now we track individual barrier for every PipelineStage. If
// layout has a single stage mask bit, we use that stage as index. If layout has multiple stage
// mask bits, we pick the lowest stage as the index since it is the first stage that needs
// barrier.
PipelineStage barrierIndex;
EventStage eventStage;
// The pipeline stage flags group that used for heuristic.
PipelineStageGroup pipelineStageGroup;
};
using ImageAccessToMemoryBarrierDataMap = angle::PackedEnumMap<ImageAccess, ImageMemoryBarrierData>;
// Initialize EventStage to VkPipelineStageFlags mapping table.
void InitializeEventStageToVkPipelineStageFlagsMap(
EventStageToVkPipelineStageFlagsMap *map,
VkPipelineStageFlags supportedVulkanPipelineStageMask);
// Initialize ImageAccess to ImageMemoryBarrierData mapping table.
void InitializeImageLayoutAndMemoryBarrierDataMap(
const angle::FeaturesVk &features,
ImageAccessToMemoryBarrierDataMap *mapping,
VkPipelineStageFlags supportedVulkanPipelineStageMask);
} // namespace vk
} // namespace rx
#endif // LIBANGLE_RENDERER_VULKAN_VK_BARRIER_DATA_H_