chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_cache_utils.h

//
// 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_cache_utils.h:
//    Contains the classes for the Pipeline State Object cache as well as the RenderPass cache.
//    Also contains the structures for the packed descriptions for the RenderPass and Pipeline.
//

#ifndef LIBANGLE_RENDERER_VULKAN_VK_CACHE_UTILS_H_
#define LIBANGLE_RENDERER_VULKAN_VK_CACHE_UTILS_H_

#include "common/Color.h"
#include "common/FixedVector.h"
#include "common/SimpleMutex.h"
#include "common/WorkerThread.h"
#include "libANGLE/Uniform.h"
#include "libANGLE/renderer/vulkan/ShaderInterfaceVariableInfoMap.h"
#include "libANGLE/renderer/vulkan/vk_resource.h"
#include "libANGLE/renderer/vulkan/vk_utils.h"

namespace gl
{
class ProgramExecutable;
}  // namespace gl

namespace rx
{
class ShaderInterfaceVariableInfoMap;
class UpdateDescriptorSetsBuilder;

// Some descriptor set and pipeline layout constants.
//
// The set/binding assignment is done as following:
//
// - Set 0 contains uniform blocks created to encompass default uniforms.  1 binding is used per
//   pipeline stage.  Additionally, transform feedback buffers are bound from binding 2 and up.
//   For internal shaders, set 0 is used for all the needed resources.
// - Set 1 contains all textures (including texture buffers).
// - Set 2 contains all other shader resources, such as uniform and storage blocks, atomic counter
//   buffers, images and image buffers.

enum class DescriptorSetIndex : uint32_t
{};

namespace vk
{
class BufferHelper;
class DynamicDescriptorPool;
class SamplerHelper;
enum class ImageLayout;
class PipelineCacheAccess;
class RenderPassCommandBufferHelper;
class PackedClearValuesArray;
class AttachmentOpsArray;

RefCountedDescriptorSetLayout;
RefCountedPipelineLayout;
RefCountedSamplerYcbcrConversion;

// Packed Vk resource descriptions.
// Most Vk types use many more bits than required to represent the underlying data.
// Since ANGLE wants to cache things like RenderPasses and Pipeline State Objects using
// hashing (and also needs to check equality) we can optimize these operations by
// using fewer bits. Hence the packed types.
//
// One implementation note: these types could potentially be improved by using even
// fewer bits. For example, boolean values could be represented by a single bit instead
// of a uint8_t. However at the current time there are concerns about the portability
// of bitfield operators, and complexity issues with using bit mask operations. This is
// something we will likely want to investigate as the Vulkan implementation progresses.
//
// Second implementation note: the struct packing is also a bit fragile, and some of the
// packing requirements depend on using alignas and field ordering to get the result of
// packing nicely into the desired space. This is something we could also potentially fix
// with a redesign to use bitfields or bit mask operations.

// Enable struct padding warnings for the code below since it is used in caches.
ANGLE_ENABLE_STRUCT_PADDING_WARNINGS

enum class ResourceAccess
{};

inline void UpdateAccess(ResourceAccess *oldAccess, ResourceAccess newAccess)
{}
inline bool HasResourceWriteAccess(ResourceAccess access)
{}

enum class RenderPassLoadOp
{};
enum class RenderPassStoreOp
{};

// There can be a maximum of IMPLEMENTATION_MAX_DRAW_BUFFERS color and resolve attachments, plus -
// - one depth/stencil attachment
// - one depth/stencil resolve attachment
// - one fragment shading rate attachment
constexpr size_t kMaxFramebufferAttachments =;
FramebufferAttachmentArray;
FramebufferAttachmentsVector;
FramebufferAttachmentMask;

constexpr size_t kMaxFramebufferNonResolveAttachments =;
FramebufferNonResolveAttachmentArray;
FramebufferNonResolveAttachmentMask;

class PackedAttachmentIndex;

class alignas(4) RenderPassDesc final
{};

bool operator==(const RenderPassDesc &lhs, const RenderPassDesc &rhs);

constexpr size_t kRenderPassDescSize =;
static_assert;

enum class GraphicsPipelineSubset
{};

enum class CacheLookUpFeedback
{};

struct PackedAttachmentOpsDesc final
{};

static_assert;

class AttachmentOpsArray final
{};

bool operator==(const AttachmentOpsArray &lhs, const AttachmentOpsArray &rhs);

static_assert;

struct PackedAttribDesc final
{};

constexpr size_t kPackedAttribDescSize =;
static_assert;

struct PackedVertexInputAttributes final
{};

constexpr size_t kPackedVertexInputAttributesSize =;
static_assert;

struct PackedInputAssemblyState final
{};

constexpr size_t kPackedInputAssemblyStateSize =;
static_assert;

struct PackedStencilOpState final
{};

constexpr size_t kPackedStencilOpSize =;
static_assert;

struct PackedPreRasterizationAndFragmentStates final
{};

constexpr size_t kPackedPreRasterizationAndFragmentStatesSize =;
static_assert;

struct PackedMultisampleAndSubpassState final
{};

constexpr size_t kPackedMultisampleAndSubpassStateSize =;
static_assert;

struct PackedColorBlendAttachmentState final
{};

constexpr size_t kPackedColorBlendAttachmentStateSize =;
static_assert;

struct PackedColorBlendState final
{};

constexpr size_t kPackedColorBlendStateSize =;
static_assert;

struct PackedBlendMaskAndLogicOpState final
{};

constexpr size_t kPackedBlendMaskAndLogicOpStateSize =;
static_assert;

// The vertex input subset of the pipeline.
struct PipelineVertexInputState final
{};

// The pre-rasterization and fragment shader subsets of the pipeline.  This is excluding
// multisampled and render pass states which are shared with fragment output.
struct PipelineShadersState final
{};

// Multisampled and render pass states.
struct PipelineSharedNonVertexInputState final
{};

// The fragment output subset of the pipeline.  This is excluding multisampled and render pass
// states which are shared with the shader subsets.
struct PipelineFragmentOutputState final
{};

constexpr size_t kGraphicsPipelineVertexInputStateSize =;
constexpr size_t kGraphicsPipelineShadersStateSize =;
constexpr size_t kGraphicsPipelineSharedNonVertexInputStateSize =;
constexpr size_t kGraphicsPipelineFragmentOutputStateSize =;

constexpr size_t kGraphicsPipelineDescSumOfSizes =;

// Number of dirty bits in the dirty bit set.
constexpr size_t kGraphicsPipelineDirtyBitBytes =;
constexpr static size_t kNumGraphicsPipelineDirtyBits =;
static_assert;

// Set of dirty bits. Each bit represents kGraphicsPipelineDirtyBitBytes in the desc.
GraphicsPipelineTransitionBits;

GraphicsPipelineTransitionBits GetGraphicsPipelineTransitionBitsMask(GraphicsPipelineSubset subset);

// Disable padding warnings for a few helper structs that aggregate Vulkan state objects.  These are
// not used as hash keys, they just simplify passing them around to functions.
ANGLE_DISABLE_STRUCT_PADDING_WARNINGS

struct GraphicsPipelineVertexInputVulkanStructs
{};

struct GraphicsPipelineShadersVulkanStructs
{};

struct GraphicsPipelineSharedNonVertexInputVulkanStructs
{};

struct GraphicsPipelineFragmentOutputVulkanStructs
{};

ANGLE_ENABLE_STRUCT_PADDING_WARNINGS

GraphicsPipelineDynamicStateList;

enum class PipelineRobustness
{};

enum class PipelineProtectedAccess
{};

// State changes are applied through the update methods. Each update method can also have a
// sibling method that applies the update without marking a state transition. The non-transition
// update methods are used for internal shader pipelines. Not every non-transition update method
// is implemented yet as not every state is used in internal shaders.
class GraphicsPipelineDesc final
{};

// Verify the packed pipeline description has no gaps in the packing.
// This is not guaranteed by the spec, but is validated by a compile-time check.
// No gaps or padding at the end ensures that hashing and memcmp checks will not run
// into uninitialized memory regions.
constexpr size_t kGraphicsPipelineDescSize =;
static_assert;

// Values are based on data recorded here -> https://anglebug.com/42267114#comment5
constexpr size_t kDefaultDescriptorSetLayoutBindingsCount =;
constexpr size_t kDefaultImmutableSamplerBindingsCount    =;
DescriptorSetLayoutBindingVector;

// A packed description of a descriptor set layout. Use similarly to RenderPassDesc and
// GraphicsPipelineDesc. Currently we only need to differentiate layouts based on sampler and ubo
// usage. In the future we could generalize this.
class DescriptorSetLayoutDesc final
{};

// The following are for caching descriptor set layouts. Limited to max three descriptor set
// layouts. This can be extended in the future.
constexpr size_t kMaxDescriptorSetLayouts =;

PackedPushConstantRange;

static_assert;

DescriptorSetArray;
DescriptorSetLayoutPointerArray;

class PipelineLayoutDesc final
{};

// Verify the structure is properly packed.
static_assert;

enum class YcbcrLinearFilterSupport
{};

class YcbcrConversionDesc final
{};

static_assert;

// Packed sampler description for the sampler cache.
class SamplerDesc final
{};

static_assert;

// Disable warnings about struct padding.
ANGLE_DISABLE_STRUCT_PADDING_WARNINGS

class PipelineHelper;

struct GraphicsPipelineTransition
{};

ANGLE_INLINE GraphicsPipelineTransition::GraphicsPipelineTransition() = default;

ANGLE_INLINE GraphicsPipelineTransition::GraphicsPipelineTransition(
    const GraphicsPipelineTransition &other) = default;

ANGLE_INLINE GraphicsPipelineTransition::GraphicsPipelineTransition(
    GraphicsPipelineTransitionBits bits,
    const GraphicsPipelineDesc *desc,
    PipelineHelper *pipeline)
    :{}

ANGLE_INLINE bool GraphicsPipelineTransitionMatch(GraphicsPipelineTransitionBits bitsA,
                                                  GraphicsPipelineTransitionBits bitsB,
                                                  const GraphicsPipelineDesc &descA,
                                                  const GraphicsPipelineDesc &descB)
{}

// A class that encapsulates the vk::PipelineCache and associated mutex.  The mutex may be nullptr
// if synchronization is not necessary.
class PipelineCacheAccess
{};

// Monolithic pipeline creation tasks are created as soon as a pipeline is created out of libraries.
// However, they are not immediately posted to the worker queue to allow pacing.  One each use of a
// pipeline, an attempt is made to post the task.
class CreateMonolithicPipelineTask : public Context, public angle::Closure
{};

class WaitableMonolithicPipelineCreationTask
{};

class PipelineHelper final : public Resource
{};

class FramebufferHelper : public Resource
{};

ANGLE_INLINE PipelineHelper::PipelineHelper(Pipeline &&pipeline, CacheLookUpFeedback feedback)
    :{}

ANGLE_INLINE PipelineHelper &PipelineHelper::operator=(PipelineHelper &&other)
{}

struct ImageSubresourceRange
{};

static_assert;

inline bool operator==(const ImageSubresourceRange &a, const ImageSubresourceRange &b)
{}

constexpr ImageSubresourceRange kInvalidImageSubresourceRange =;

struct ImageOrBufferViewSubresourceSerial
{};

inline bool operator==(const ImageOrBufferViewSubresourceSerial &a,
                       const ImageOrBufferViewSubresourceSerial &b)
{}

constexpr ImageOrBufferViewSubresourceSerial kInvalidImageOrBufferViewSubresourceSerial =;

// Always starts with array element zero, with descriptorCount descriptors.
struct WriteDescriptorDesc
{};

static_assert;

struct DescriptorInfoDesc
{};

static_assert;

// Generic description of a descriptor set. Used as a key when indexing descriptor set caches. The
// key storage is an angle:FixedVector. Beyond a certain fixed size we'll end up using heap memory
// to store keys. Currently we specialize the structure for three use cases: uniforms, textures,
// and other shader resources. Because of the way the specialization works we can't currently cache
// programs that use some types of resources.
static constexpr size_t kFastDescriptorSetDescLimit =;

struct DescriptorDescHandles
{};

class WriteDescriptorDescs
{};

class DescriptorSetDesc
{};

class DescriptorPoolHelper;
RefCountedDescriptorPoolHelper;

// SharedDescriptorSetCacheKey.
// Because DescriptorSet must associate with a pool, we need to define a structure that wraps both.
struct DescriptorSetDescAndPool
{};
DescriptorSetAndPoolPointer;
SharedDescriptorSetCacheKey;
ANGLE_INLINE const SharedDescriptorSetCacheKey
CreateSharedDescriptorSetCacheKey(const DescriptorSetDesc &desc, DynamicDescriptorPool *pool)
{}

constexpr VkDescriptorType kStorageBufferDescriptorType =;

// Manages a descriptor set desc with a few helper routines and also stores object handles.
class DescriptorSetDescBuilder final
{};

// Specialized update for textures.
void UpdatePreCacheActiveTextures(const gl::ProgramExecutable &executable,
                                  const std::vector<gl::SamplerBinding> &samplerBindings,
                                  const gl::ActiveTextureMask &activeTextures,
                                  const gl::ActiveTextureArray<TextureVk *> &textures,
                                  const gl::SamplerBindingVector &samplers,
                                  DescriptorSetDesc *desc);

// In the FramebufferDesc object:
//  - Depth/stencil serial is at index 0
//  - Color serials are at indices [1, gl::IMPLEMENTATION_MAX_DRAW_BUFFERS]
//  - Depth/stencil resolve attachment is at index gl::IMPLEMENTATION_MAX_DRAW_BUFFERS+1
//  - Resolve attachments are at indices [gl::IMPLEMENTATION_MAX_DRAW_BUFFERS+2,
//                                        gl::IMPLEMENTATION_MAX_DRAW_BUFFERS*2+1]
//    Fragment shading rate attachment serial is at index
//    (gl::IMPLEMENTATION_MAX_DRAW_BUFFERS*2+1)+1
constexpr size_t kFramebufferDescDepthStencilIndex =;
constexpr size_t kFramebufferDescColorIndexOffset  =;
constexpr size_t kFramebufferDescDepthStencilResolveIndexOffset =;
constexpr size_t kFramebufferDescColorResolveIndexOffset =;
constexpr size_t kFramebufferDescFragmentShadingRateAttachmentIndexOffset =;

// Enable struct padding warnings for the code below since it is used in caches.
ANGLE_ENABLE_STRUCT_PADDING_WARNINGS

class FramebufferDesc
{};

constexpr size_t kFramebufferDescSize =;
static_assert;

// Disable warnings about struct padding.
ANGLE_DISABLE_STRUCT_PADDING_WARNINGS

// SharedFramebufferCacheKey
FramebufferDescPointer;
SharedFramebufferCacheKey;
ANGLE_INLINE const SharedFramebufferCacheKey
CreateSharedFramebufferCacheKey(const FramebufferDesc &desc)
{}

// The SamplerHelper allows a Sampler to be coupled with a serial.
// Must be included before we declare SamplerCache.
class SamplerHelper final : angle::NonCopyable
{};

RefCountedSampler;
SamplerBinding;

class RenderPassHelper final : angle::NonCopyable
{};

// Helper class manages the lifetime of various cache objects so that the cache entry can be
// destroyed when one of the components becomes invalid.
template <class SharedCacheKeyT>
class SharedCacheKeyManager
{};

FramebufferCacheManager;
DescriptorSetCacheManager;
}  // namespace vk
}  // namespace rx

// Introduce std::hash for the above classes.
std  // namespace std

namespace rx
{
// Cache types for various Vulkan objects
enum class VulkanCacheType
{};

// Base class for all caches. Provides cache hit and miss counters.
class CacheStats final : angle::NonCopyable
{};

template <VulkanCacheType CacheType>
class HasCacheStats : angle::NonCopyable
{};

VulkanCacheStats;

// FramebufferVk Cache
class FramebufferCache final : angle::NonCopyable
{};

// TODO(jmadill): Add cache trimming/eviction.
class RenderPassCache final : angle::NonCopyable
{};

enum class PipelineSource
{};

struct GraphicsPipelineDescCompleteHash
{};
struct GraphicsPipelineDescVertexInputHash
{};
struct GraphicsPipelineDescShadersHash
{};
struct GraphicsPipelineDescFragmentOutputHash
{};

struct GraphicsPipelineDescCompleteKeyEqual
{};
struct GraphicsPipelineDescVertexInputKeyEqual
{};
struct GraphicsPipelineDescShadersKeyEqual
{};
struct GraphicsPipelineDescFragmentOutputKeyEqual
{};

// Derive the KeyEqual and GraphicsPipelineSubset enum from the Hash struct
template <typename Hash>
struct GraphicsPipelineCacheTypeHelper
{};

template <>
struct GraphicsPipelineCacheTypeHelper<GraphicsPipelineDescVertexInputHash>
{};
template <>
struct GraphicsPipelineCacheTypeHelper<GraphicsPipelineDescShadersHash>
{};
template <>
struct GraphicsPipelineCacheTypeHelper<GraphicsPipelineDescFragmentOutputHash>
{};

// TODO(jmadill): Add cache trimming/eviction.
template <typename Hash>
class GraphicsPipelineCache final : public HasCacheStats<VulkanCacheType::GraphicsPipeline>
{};

CompleteGraphicsPipelineCache;
VertexInputGraphicsPipelineCache;
ShadersGraphicsPipelineCache;
FragmentOutputGraphicsPipelineCache;

class DescriptorSetLayoutCache final : angle::NonCopyable
{};

class PipelineLayoutCache final : public HasCacheStats<VulkanCacheType::PipelineLayout>
{};

class SamplerCache final : public HasCacheStats<VulkanCacheType::Sampler>
{};

// YuvConversion Cache
class SamplerYcbcrConversionCache final
    : public HasCacheStats<VulkanCacheType::SamplerYcbcrConversion>
{};

// Descriptor Set Cache
class DescriptorSetCache final : angle::NonCopyable
{};

// There is 1 default uniform binding used per stage.
constexpr uint32_t kReservedPerStageDefaultUniformBindingCount =;

class UpdateDescriptorSetsBuilder final : angle::NonCopyable
{};

}  // namespace rx

#endif  // LIBANGLE_RENDERER_VULKAN_VK_CACHE_UTILS_H_