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/vulkan/vk_headers.h" 13 #include "libANGLE/formatutils.h" 14 #include "libANGLE/renderer/Format.h" 15 #include "libANGLE/renderer/copyvertex.h" 16 #include "libANGLE/renderer/renderer_utils.h" 17 #include "platform/autogen/FeaturesVk_autogen.h" 18 19 #include <array> 20 21 namespace gl 22 { 23 struct SwizzleState; 24 class TextureCapsMap; 25 } // namespace gl 26 27 namespace rx 28 { 29 class RendererVk; 30 class ContextVk; 31 32 namespace vk 33 { 34 // VkFormat values in range [0, kNumVkFormats) are used as indices in various tables. 35 constexpr uint32_t kNumVkFormats = 185; 36 37 enum ImageAccess 38 { 39 SampleOnly, 40 Renderable, 41 }; 42 43 struct ImageFormatInitInfo final 44 { 45 angle::FormatID format; 46 InitializeTextureDataFunction initializer; 47 }; 48 49 struct BufferFormatInitInfo final 50 { 51 angle::FormatID format; 52 bool vkFormatIsPacked; 53 VertexCopyFunction vertexLoadFunction; 54 bool vertexLoadRequiresConversion; 55 }; 56 57 VkFormat GetVkFormatFromFormatID(angle::FormatID actualFormatID); 58 angle::FormatID GetFormatIDFromVkFormat(VkFormat vkFormat); 59 60 // Returns buffer alignment for image-copy operations (to or from a buffer). 61 size_t GetImageCopyBufferAlignment(angle::FormatID actualFormatID); 62 size_t GetValidImageCopyBufferAlignment(angle::FormatID intendedFormatID, 63 angle::FormatID actualFormatID); 64 bool HasEmulatedImageChannels(const angle::Format &intendedFormat, 65 const angle::Format &actualFormat); 66 // Returns true if the image has a different image format than intended. 67 bool HasEmulatedImageFormat(angle::FormatID intendedFormatID, angle::FormatID actualFormatID); 68 69 // Describes a Vulkan format. For more information on formats in the Vulkan back-end please see 70 // https://chromium.googlesource.com/angle/angle/+/main/src/libANGLE/renderer/vulkan/doc/FormatTablesAndEmulation.md 71 class Format final : private angle::NonCopyable 72 { 73 public: 74 Format(); 75 valid()76 bool valid() const { return mIntendedGLFormat != 0; } getIntendedGLFormat()77 GLenum getIntendedGLFormat() const { return mIntendedGLFormat; } 78 79 // The intended format is the front-end format. For Textures this usually correponds to a 80 // GLenum in the headers. Buffer formats don't always have a corresponding GLenum type. 81 // Some Surface formats and unsized types also don't have a corresponding GLenum. getIntendedFormatID()82 angle::FormatID getIntendedFormatID() const { return mIntendedFormatID; } getIntendedFormat()83 const angle::Format &getIntendedFormat() const { return angle::Format::Get(mIntendedFormatID); } 84 85 // The actual Image format is used to implement the front-end format for Texture/Renderbuffers. getActualImageFormat(ImageAccess access)86 const angle::Format &getActualImageFormat(ImageAccess access) const 87 { 88 return angle::Format::Get(getActualImageFormatID(access)); 89 } 90 getActualRenderableImageFormatID()91 angle::FormatID getActualRenderableImageFormatID() const 92 { 93 return mActualRenderableImageFormatID; 94 } getActualRenderableImageFormat()95 const angle::Format &getActualRenderableImageFormat() const 96 { 97 return angle::Format::Get(mActualRenderableImageFormatID); 98 } getActualRenderableImageVkFormat()99 VkFormat getActualRenderableImageVkFormat() const 100 { 101 return GetVkFormatFromFormatID(mActualRenderableImageFormatID); 102 } 103 getActualImageFormatID(ImageAccess access)104 angle::FormatID getActualImageFormatID(ImageAccess access) const 105 { 106 return ImageAccess::Renderable == access ? mActualRenderableImageFormatID 107 : mActualSampleOnlyImageFormatID; 108 } getActualImageVkFormat(ImageAccess access)109 VkFormat getActualImageVkFormat(ImageAccess access) const 110 { 111 return GetVkFormatFromFormatID(getActualImageFormatID(access)); 112 } 113 getTextureLoadFunction(ImageAccess access,GLenum type)114 LoadImageFunctionInfo getTextureLoadFunction(ImageAccess access, GLenum type) const 115 { 116 return ImageAccess::Renderable == access ? mRenderableTextureLoadFunctions(type) 117 : mTextureLoadFunctions(type); 118 } 119 120 // The actual Buffer format is used to implement the front-end format for Buffers. This format 121 // is used by vertex buffers as well as texture buffers. Note that all formats required for 122 // GL_EXT_texture_buffer have mandatory support for vertex buffers in Vulkan, so they won't be 123 // using an emulated format. getActualBufferFormat(bool compressed)124 const angle::Format &getActualBufferFormat(bool compressed) const 125 { 126 return angle::Format::Get(compressed ? mActualCompressedBufferFormatID 127 : mActualBufferFormatID); 128 } 129 getActualBufferVkFormat(bool compressed)130 VkFormat getActualBufferVkFormat(bool compressed) const 131 { 132 return GetVkFormatFromFormatID(compressed ? mActualCompressedBufferFormatID 133 : mActualBufferFormatID); 134 } 135 getVertexLoadFunction(bool compressed)136 VertexCopyFunction getVertexLoadFunction(bool compressed) const 137 { 138 return compressed ? mCompressedVertexLoadFunction : mVertexLoadFunction; 139 } 140 getVertexLoadRequiresConversion(bool compressed)141 bool getVertexLoadRequiresConversion(bool compressed) const 142 { 143 return compressed ? mCompressedVertexLoadRequiresConversion : mVertexLoadRequiresConversion; 144 } 145 146 // |intendedGLFormat| always correponds to a valid GLenum type. For types that don't have a 147 // corresponding GLenum we do our best to specify a GLenum that is "close". getInternalFormatInfo(GLenum type)148 const gl::InternalFormat &getInternalFormatInfo(GLenum type) const 149 { 150 return gl::GetInternalFormatInfo(mIntendedGLFormat, type); 151 } 152 hasRenderableImageFallbackFormat()153 bool hasRenderableImageFallbackFormat() const 154 { 155 return mActualSampleOnlyImageFormatID != mActualRenderableImageFormatID; 156 } 157 canCompressBufferData()158 bool canCompressBufferData() const 159 { 160 return mActualCompressedBufferFormatID != angle::FormatID::NONE && 161 mActualBufferFormatID != mActualCompressedBufferFormatID; 162 } 163 164 // Returns the alignment for a buffer to be used with the vertex input stage in Vulkan. This 165 // calculation is listed in the Vulkan spec at the end of the section 'Vertex Input 166 // Description'. 167 size_t getVertexInputAlignment(bool compressed) const; 168 169 private: 170 friend class FormatTable; 171 172 // This is an auto-generated method in vk_format_table_autogen.cpp. 173 void initialize(RendererVk *renderer, const angle::Format &intendedAngleFormat); 174 175 // These are used in the format table init. 176 void initImageFallback(RendererVk *renderer, const ImageFormatInitInfo *info, int numInfo); 177 void initBufferFallback(RendererVk *renderer, 178 const BufferFormatInitInfo *fallbackInfo, 179 int numInfo, 180 int compressedStartIndex); 181 182 angle::FormatID mIntendedFormatID; 183 GLenum mIntendedGLFormat; 184 angle::FormatID mActualSampleOnlyImageFormatID; 185 angle::FormatID mActualRenderableImageFormatID; 186 angle::FormatID mActualBufferFormatID; 187 angle::FormatID mActualCompressedBufferFormatID; 188 189 InitializeTextureDataFunction mImageInitializerFunction; 190 LoadFunctionMap mTextureLoadFunctions; 191 LoadFunctionMap mRenderableTextureLoadFunctions; 192 VertexCopyFunction mVertexLoadFunction; 193 VertexCopyFunction mCompressedVertexLoadFunction; 194 195 bool mVertexLoadRequiresConversion; 196 bool mCompressedVertexLoadRequiresConversion; 197 bool mVkBufferFormatIsPacked; 198 bool mVkCompressedBufferFormatIsPacked; 199 bool mVkFormatIsInt; 200 bool mVkFormatIsUnsigned; 201 }; 202 203 bool operator==(const Format &lhs, const Format &rhs); 204 bool operator!=(const Format &lhs, const Format &rhs); 205 206 class FormatTable final : angle::NonCopyable 207 { 208 public: 209 FormatTable(); 210 ~FormatTable(); 211 212 // Also initializes the TextureCapsMap and the compressedTextureCaps in the Caps instance. 213 void initialize(RendererVk *renderer, gl::TextureCapsMap *outTextureCapsMap); 214 215 ANGLE_INLINE const Format &operator[](GLenum internalFormat) const 216 { 217 angle::FormatID formatID = angle::Format::InternalFormatToID(internalFormat); 218 return mFormatData[static_cast<size_t>(formatID)]; 219 } 220 221 ANGLE_INLINE const Format &operator[](angle::FormatID formatID) const 222 { 223 return mFormatData[static_cast<size_t>(formatID)]; 224 } 225 226 private: 227 // The table data is indexed by angle::FormatID. 228 std::array<Format, angle::kNumANGLEFormats> mFormatData; 229 }; 230 231 // This will return a reference to a VkFormatProperties with the feature flags supported 232 // if the format is a mandatory format described in section 31.3.3. Required Format Support 233 // of the Vulkan spec. If the vkFormat isn't mandatory, it will return a VkFormatProperties 234 // initialized to 0. 235 const VkFormatProperties &GetMandatoryFormatSupport(angle::FormatID formatID); 236 237 VkImageUsageFlags GetMaximalImageUsageFlags(RendererVk *renderer, angle::FormatID formatID); 238 239 } // namespace vk 240 241 // Checks if a Vulkan format supports all the features needed to use it as a GL texture format. 242 bool HasFullTextureFormatSupport(RendererVk *renderer, angle::FormatID formatID); 243 // Checks if a Vulkan format supports all the features except rendering. 244 bool HasNonRenderableTextureFormatSupport(RendererVk *renderer, angle::FormatID formatID); 245 // Checks if it is a ETC texture format 246 bool IsETCFormat(angle::FormatID formatID); 247 // Checks if it is a BC texture format 248 bool IsBCFormat(angle::FormatID formatID); 249 250 angle::FormatID GetTranscodeBCFormatID(angle::FormatID formatID); 251 252 // Get the swizzle state based on format's requirements and emulations. 253 gl::SwizzleState GetFormatSwizzle(const angle::Format &angleFormat, const bool sized); 254 255 // Apply application's swizzle to the swizzle implied by format as received from GetFormatSwizzle. 256 gl::SwizzleState ApplySwizzle(const gl::SwizzleState &formatSwizzle, 257 const gl::SwizzleState &toApply); 258 259 } // namespace rx 260 261 #endif // LIBANGLE_RENDERER_VULKAN_VK_FORMAT_UTILS_H_ 262