1 // 2 // Copyright 2016 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 // vk_format_utils: 7 // Helper for Vulkan format code. 8 9 #ifndef LIBANGLE_RENDERER_VULKAN_VK_FORMAT_UTILS_H_ 10 #define LIBANGLE_RENDERER_VULKAN_VK_FORMAT_UTILS_H_ 11 12 #include "common/SimpleMutex.h" 13 #include "common/vulkan/vk_headers.h" 14 #include "libANGLE/formatutils.h" 15 #include "libANGLE/renderer/Format.h" 16 #include "libANGLE/renderer/copyvertex.h" 17 #include "libANGLE/renderer/renderer_utils.h" 18 #include "platform/autogen/FeaturesVk_autogen.h" 19 20 #include <array> 21 22 namespace gl 23 { 24 struct SwizzleState; 25 class TextureCapsMap; 26 } // namespace gl 27 28 namespace rx 29 { 30 class ContextVk; 31 32 namespace vk 33 { 34 class Renderer; 35 36 // VkFormat values in range [0, kNumVkFormats) are used as indices in various tables. 37 constexpr uint32_t kNumVkFormats = 185; 38 39 enum ImageAccess 40 { 41 SampleOnly, 42 Renderable, 43 }; 44 45 struct ImageFormatInitInfo final 46 { 47 angle::FormatID format; 48 InitializeTextureDataFunction initializer; 49 }; 50 51 struct BufferFormatInitInfo final 52 { 53 angle::FormatID format; 54 bool vkFormatIsPacked; 55 VertexCopyFunction vertexLoadFunction; 56 bool vertexLoadRequiresConversion; 57 }; 58 59 VkFormat GetVkFormatFromFormatID(const Renderer *renderer, angle::FormatID actualFormatID); 60 angle::FormatID GetFormatIDFromVkFormat(VkFormat vkFormat); 61 62 // Returns buffer alignment for image-copy operations (to or from a buffer). 63 size_t GetImageCopyBufferAlignment(angle::FormatID actualFormatID); 64 size_t GetValidImageCopyBufferAlignment(angle::FormatID intendedFormatID, 65 angle::FormatID actualFormatID); 66 bool HasEmulatedImageChannels(const angle::Format &intendedFormat, 67 const angle::Format &actualFormat); 68 // Returns true if the image has a different image format than intended. 69 bool HasEmulatedImageFormat(angle::FormatID intendedFormatID, angle::FormatID actualFormatID); 70 71 // Describes a Vulkan format. For more information on formats in the Vulkan back-end please see 72 // https://chromium.googlesource.com/angle/angle/+/main/src/libANGLE/renderer/vulkan/doc/FormatTablesAndEmulation.md 73 class Format final : private angle::NonCopyable 74 { 75 public: 76 Format(); 77 valid()78 bool valid() const { return mIntendedGLFormat != 0; } getIntendedGLFormat()79 GLenum getIntendedGLFormat() const { return mIntendedGLFormat; } 80 81 // The intended format is the front-end format. For Textures this usually correponds to a 82 // GLenum in the headers. Buffer formats don't always have a corresponding GLenum type. 83 // Some Surface formats and unsized types also don't have a corresponding GLenum. getIntendedFormatID()84 angle::FormatID getIntendedFormatID() const { return mIntendedFormatID; } getIntendedFormat()85 const angle::Format &getIntendedFormat() const { return angle::Format::Get(mIntendedFormatID); } 86 87 // The actual Image format is used to implement the front-end format for Texture/Renderbuffers. getActualImageFormat(ImageAccess access)88 const angle::Format &getActualImageFormat(ImageAccess access) const 89 { 90 return angle::Format::Get(getActualImageFormatID(access)); 91 } 92 getActualRenderableImageFormatID()93 angle::FormatID getActualRenderableImageFormatID() const 94 { 95 return mActualRenderableImageFormatID; 96 } getActualRenderableImageFormat()97 const angle::Format &getActualRenderableImageFormat() const 98 { 99 return angle::Format::Get(mActualRenderableImageFormatID); 100 } getActualRenderableImageVkFormat(const Renderer * renderer)101 VkFormat getActualRenderableImageVkFormat(const Renderer *renderer) const 102 { 103 return GetVkFormatFromFormatID(renderer, mActualRenderableImageFormatID); 104 } 105 getActualImageFormatID(ImageAccess access)106 angle::FormatID getActualImageFormatID(ImageAccess access) const 107 { 108 return ImageAccess::Renderable == access ? mActualRenderableImageFormatID 109 : mActualSampleOnlyImageFormatID; 110 } getActualImageVkFormat(const Renderer * renderer,ImageAccess access)111 VkFormat getActualImageVkFormat(const Renderer *renderer, ImageAccess access) const 112 { 113 return GetVkFormatFromFormatID(renderer, getActualImageFormatID(access)); 114 } 115 getTextureLoadFunction(ImageAccess access,GLenum type)116 LoadImageFunctionInfo getTextureLoadFunction(ImageAccess access, GLenum type) const 117 { 118 return ImageAccess::Renderable == access ? mRenderableTextureLoadFunctions(type) 119 : mTextureLoadFunctions(type); 120 } 121 122 // The actual Buffer format is used to implement the front-end format for Buffers. This format 123 // is used by vertex buffers as well as texture buffers. Note that all formats required for 124 // GL_EXT_texture_buffer have mandatory support for vertex buffers in Vulkan, so they won't be 125 // using an emulated format. getActualBufferFormat(bool compressed)126 const angle::Format &getActualBufferFormat(bool compressed) const 127 { 128 return angle::Format::Get(compressed ? mActualCompressedBufferFormatID 129 : mActualBufferFormatID); 130 } 131 getActualBufferVkFormat(const Renderer * renderer,bool compressed)132 VkFormat getActualBufferVkFormat(const Renderer *renderer, bool compressed) const 133 { 134 return GetVkFormatFromFormatID( 135 renderer, compressed ? mActualCompressedBufferFormatID : mActualBufferFormatID); 136 } 137 getVertexLoadFunction(bool compressed)138 VertexCopyFunction getVertexLoadFunction(bool compressed) const 139 { 140 return compressed ? mCompressedVertexLoadFunction : mVertexLoadFunction; 141 } 142 getVertexLoadRequiresConversion(bool compressed)143 bool getVertexLoadRequiresConversion(bool compressed) const 144 { 145 return compressed ? mCompressedVertexLoadRequiresConversion : mVertexLoadRequiresConversion; 146 } 147 148 // |intendedGLFormat| always correponds to a valid GLenum type. For types that don't have a 149 // corresponding GLenum we do our best to specify a GLenum that is "close". getInternalFormatInfo(GLenum type)150 const gl::InternalFormat &getInternalFormatInfo(GLenum type) const 151 { 152 return gl::GetInternalFormatInfo(mIntendedGLFormat, type); 153 } 154 hasRenderableImageFallbackFormat()155 bool hasRenderableImageFallbackFormat() const 156 { 157 return mActualSampleOnlyImageFormatID != mActualRenderableImageFormatID; 158 } 159 canCompressBufferData()160 bool canCompressBufferData() const 161 { 162 return mActualCompressedBufferFormatID != angle::FormatID::NONE && 163 mActualBufferFormatID != mActualCompressedBufferFormatID; 164 } 165 166 // Returns the alignment for a buffer to be used with the vertex input stage in Vulkan. This 167 // calculation is listed in the Vulkan spec at the end of the section 'Vertex Input 168 // Description'. 169 size_t getVertexInputAlignment(bool compressed) const; 170 171 private: 172 friend class FormatTable; 173 174 // This is an auto-generated method in vk_format_table_autogen.cpp. 175 void initialize(Renderer *renderer, const angle::Format &intendedAngleFormat); 176 177 // These are used in the format table init. 178 void initImageFallback(Renderer *renderer, const ImageFormatInitInfo *info, int numInfo); 179 void initBufferFallback(Renderer *renderer, 180 const BufferFormatInitInfo *fallbackInfo, 181 int numInfo, 182 int compressedStartIndex); 183 184 angle::FormatID mIntendedFormatID; 185 GLenum mIntendedGLFormat; 186 angle::FormatID mActualSampleOnlyImageFormatID; 187 angle::FormatID mActualRenderableImageFormatID; 188 angle::FormatID mActualBufferFormatID; 189 angle::FormatID mActualCompressedBufferFormatID; 190 191 InitializeTextureDataFunction mImageInitializerFunction; 192 LoadFunctionMap mTextureLoadFunctions; 193 LoadFunctionMap mRenderableTextureLoadFunctions; 194 VertexCopyFunction mVertexLoadFunction; 195 VertexCopyFunction mCompressedVertexLoadFunction; 196 197 bool mVertexLoadRequiresConversion; 198 bool mCompressedVertexLoadRequiresConversion; 199 bool mVkBufferFormatIsPacked; 200 bool mVkCompressedBufferFormatIsPacked; 201 bool mVkFormatIsInt; 202 bool mVkFormatIsUnsigned; 203 }; 204 205 bool operator==(const Format &lhs, const Format &rhs); 206 bool operator!=(const Format &lhs, const Format &rhs); 207 208 class FormatTable final : angle::NonCopyable 209 { 210 public: 211 FormatTable(); 212 ~FormatTable(); 213 214 // Also initializes the TextureCapsMap and the compressedTextureCaps in the Caps instance. 215 void initialize(Renderer *renderer, gl::TextureCapsMap *outTextureCapsMap); 216 217 ANGLE_INLINE const Format &operator[](GLenum internalFormat) const 218 { 219 angle::FormatID formatID = angle::Format::InternalFormatToID(internalFormat); 220 return mFormatData[static_cast<size_t>(formatID)]; 221 } 222 223 ANGLE_INLINE const Format &operator[](angle::FormatID formatID) const 224 { 225 return mFormatData[static_cast<size_t>(formatID)]; 226 } 227 228 private: 229 // The table data is indexed by angle::FormatID. 230 std::array<Format, angle::kNumANGLEFormats> mFormatData; 231 }; 232 233 // Extra data required for a renderable external format, for EXT_yuv_target support. 234 // We have one of these structures per external format slot (angle::FormatID::EXTERNALn) 235 // and allocate them to particular actual external formats in the order we see them. 236 struct ExternalYuvFormatInfo 237 { 238 // Vendor-specific external format value to be passed in VkExternalFormatANDROID 239 uint64_t externalFormat; 240 // Format the driver wants us to use for a temporary color attachment in order to render into 241 // this external format 242 VkFormat colorAttachmentFormat; 243 VkFormatFeatureFlags formatFeatures; 244 }; 245 246 class ExternalFormatTable final : angle::NonCopyable 247 { 248 public: 249 // Convert externalFormat to one of angle::FormatID::EXTERNALn so that we can pass around in 250 // ANGLE 251 angle::FormatID getOrAllocExternalFormatID(uint64_t externalFormat, 252 VkFormat colorAttachmentFormat, 253 VkFormatFeatureFlags formatFeatures); 254 const ExternalYuvFormatInfo &getExternalFormatInfo(angle::FormatID format) const; 255 256 private: 257 static constexpr size_t kMaxExternalFormatCountSupported = 258 ToUnderlying(angle::FormatID::EXTERNAL7) - ToUnderlying(angle::FormatID::EXTERNAL0) + 1; 259 // YUV rendering format cache. We build this table at run time when external formats are used. 260 angle::FixedVector<ExternalYuvFormatInfo, kMaxExternalFormatCountSupported> mExternalYuvFormats; 261 mutable angle::SimpleMutex mExternalYuvFormatMutex; 262 }; 263 264 bool IsYUVExternalFormat(angle::FormatID formatID); 265 266 // This will return a reference to a VkFormatProperties with the feature flags supported 267 // if the format is a mandatory format described in section 31.3.3. Required Format Support 268 // of the Vulkan spec. If the vkFormat isn't mandatory, it will return a VkFormatProperties 269 // initialized to 0. 270 const VkFormatProperties &GetMandatoryFormatSupport(angle::FormatID formatID); 271 272 VkImageUsageFlags GetMaximalImageUsageFlags(Renderer *renderer, angle::FormatID formatID); 273 VkImageCreateFlags GetMinimalImageCreateFlags(Renderer *renderer, 274 gl::TextureType textureType, 275 VkImageUsageFlags usage); 276 277 } // namespace vk 278 279 // Checks if a Vulkan format supports all the features needed to use it as a GL texture format. 280 bool HasFullTextureFormatSupport(vk::Renderer *renderer, angle::FormatID formatID); 281 // Checks if a Vulkan format supports all the features except rendering. 282 bool HasNonRenderableTextureFormatSupport(vk::Renderer *renderer, angle::FormatID formatID); 283 // Checks if it is a ETC texture format 284 bool IsETCFormat(angle::FormatID formatID); 285 // Checks if it is a BC texture format 286 bool IsBCFormat(angle::FormatID formatID); 287 288 angle::FormatID GetTranscodeBCFormatID(angle::FormatID formatID); 289 290 VkFormat AdjustASTCFormatForHDR(const vk::Renderer *renderer, VkFormat vkFormat); 291 292 // Get Etc format cpu transcoding to Bc function. 293 LoadImageFunctionInfo GetEtcToBcTransCodingFunc(angle::FormatID formatID); 294 295 // Get the swizzle state based on format's requirements and emulations. 296 gl::SwizzleState GetFormatSwizzle(const angle::Format &angleFormat, const bool sized); 297 298 // Apply application's swizzle to the swizzle implied by format as received from GetFormatSwizzle. 299 gl::SwizzleState ApplySwizzle(const gl::SwizzleState &formatSwizzle, 300 const gl::SwizzleState &toApply); 301 302 } // namespace rx 303 304 #endif // LIBANGLE_RENDERER_VULKAN_VK_FORMAT_UTILS_H_ 305