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/FeaturesVk.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; } 77 78 // The intended format is the front-end format. For Textures this usually correponds to a 79 // GLenum in the headers. Buffer formats don't always have a corresponding GLenum type. 80 // Some Surface formats and unsized types also don't have a corresponding GLenum. getIntendedFormatID()81 angle::FormatID getIntendedFormatID() const { return mIntendedFormatID; } getIntendedFormat()82 const angle::Format &getIntendedFormat() const { return angle::Format::Get(mIntendedFormatID); } 83 84 // The actual Image format is used to implement the front-end format for Texture/Renderbuffers. getActualImageFormat(ImageAccess access)85 const angle::Format &getActualImageFormat(ImageAccess access) const 86 { 87 return angle::Format::Get(getActualImageFormatID(access)); 88 } 89 getActualRenderableImageFormatID()90 angle::FormatID getActualRenderableImageFormatID() const 91 { 92 return mActualRenderableImageFormatID; 93 } getActualRenderableImageFormat()94 const angle::Format &getActualRenderableImageFormat() const 95 { 96 return angle::Format::Get(mActualRenderableImageFormatID); 97 } getActualRenderableImageVkFormat()98 VkFormat getActualRenderableImageVkFormat() const 99 { 100 return GetVkFormatFromFormatID(mActualRenderableImageFormatID); 101 } 102 getActualImageFormatID(ImageAccess access)103 angle::FormatID getActualImageFormatID(ImageAccess access) const 104 { 105 return ImageAccess::Renderable == access ? mActualRenderableImageFormatID 106 : mActualSampleOnlyImageFormatID; 107 } getActualImageVkFormat(ImageAccess access)108 VkFormat getActualImageVkFormat(ImageAccess access) const 109 { 110 return GetVkFormatFromFormatID(getActualImageFormatID(access)); 111 } 112 getTextureLoadFunction(ImageAccess access,GLenum type)113 LoadImageFunctionInfo getTextureLoadFunction(ImageAccess access, GLenum type) const 114 { 115 return ImageAccess::Renderable == access ? mRenderableTextureLoadFunctions(type) 116 : mTextureLoadFunctions(type); 117 } 118 119 // The actual Buffer format is used to implement the front-end format for Buffers. This format 120 // is used by vertex buffers as well as texture buffers. Note that all formats required for 121 // GL_EXT_texture_buffer have mandatory support for vertex buffers in Vulkan, so they won't be 122 // using an emulated format. getActualBufferFormat(bool compressed)123 const angle::Format &getActualBufferFormat(bool compressed) const 124 { 125 return angle::Format::Get(compressed ? mActualCompressedBufferFormatID 126 : mActualBufferFormatID); 127 } 128 getActualBufferVkFormat(bool compressed)129 VkFormat getActualBufferVkFormat(bool compressed) const 130 { 131 return GetVkFormatFromFormatID(compressed ? mActualCompressedBufferFormatID 132 : mActualBufferFormatID); 133 } 134 getVertexLoadFunction(bool compressed)135 VertexCopyFunction getVertexLoadFunction(bool compressed) const 136 { 137 return compressed ? mCompressedVertexLoadFunction : mVertexLoadFunction; 138 } 139 getVertexLoadRequiresConversion(bool compressed)140 bool getVertexLoadRequiresConversion(bool compressed) const 141 { 142 return compressed ? mCompressedVertexLoadRequiresConversion : mVertexLoadRequiresConversion; 143 } 144 145 // |intendedGLFormat| always correponds to a valid GLenum type. For types that don't have a 146 // corresponding GLenum we do our best to specify a GLenum that is "close". getInternalFormatInfo(GLenum type)147 const gl::InternalFormat &getInternalFormatInfo(GLenum type) const 148 { 149 return gl::GetInternalFormatInfo(mIntendedGLFormat, type); 150 } 151 hasRenderableImageFallbackFormat()152 bool hasRenderableImageFallbackFormat() const 153 { 154 return mActualSampleOnlyImageFormatID != mActualRenderableImageFormatID; 155 } 156 canCompressBufferData()157 bool canCompressBufferData() const 158 { 159 return mActualCompressedBufferFormatID != angle::FormatID::NONE && 160 mActualBufferFormatID != mActualCompressedBufferFormatID; 161 } 162 163 // Returns the alignment for a buffer to be used with the vertex input stage in Vulkan. This 164 // calculation is listed in the Vulkan spec at the end of the section 'Vertex Input 165 // Description'. 166 size_t getVertexInputAlignment(bool compressed) const; 167 168 private: 169 friend class FormatTable; 170 171 // This is an auto-generated method in vk_format_table_autogen.cpp. 172 void initialize(RendererVk *renderer, const angle::Format &intendedAngleFormat); 173 174 // These are used in the format table init. 175 void initImageFallback(RendererVk *renderer, const ImageFormatInitInfo *info, int numInfo); 176 void initBufferFallback(RendererVk *renderer, 177 const BufferFormatInitInfo *fallbackInfo, 178 int numInfo, 179 int compressedStartIndex); 180 181 angle::FormatID mIntendedFormatID; 182 GLenum mIntendedGLFormat; 183 angle::FormatID mActualSampleOnlyImageFormatID; 184 angle::FormatID mActualRenderableImageFormatID; 185 angle::FormatID mActualBufferFormatID; 186 angle::FormatID mActualCompressedBufferFormatID; 187 188 InitializeTextureDataFunction mImageInitializerFunction; 189 LoadFunctionMap mTextureLoadFunctions; 190 LoadFunctionMap mRenderableTextureLoadFunctions; 191 VertexCopyFunction mVertexLoadFunction; 192 VertexCopyFunction mCompressedVertexLoadFunction; 193 194 bool mVertexLoadRequiresConversion; 195 bool mCompressedVertexLoadRequiresConversion; 196 bool mVkBufferFormatIsPacked; 197 bool mVkCompressedBufferFormatIsPacked; 198 bool mVkFormatIsInt; 199 bool mVkFormatIsUnsigned; 200 }; 201 202 bool operator==(const Format &lhs, const Format &rhs); 203 bool operator!=(const Format &lhs, const Format &rhs); 204 205 class FormatTable final : angle::NonCopyable 206 { 207 public: 208 FormatTable(); 209 ~FormatTable(); 210 211 // Also initializes the TextureCapsMap and the compressedTextureCaps in the Caps instance. 212 void initialize(RendererVk *renderer, 213 gl::TextureCapsMap *outTextureCapsMap, 214 std::vector<GLenum> *outCompressedTextureFormats); 215 216 ANGLE_INLINE const Format &operator[](GLenum internalFormat) const 217 { 218 angle::FormatID formatID = angle::Format::InternalFormatToID(internalFormat); 219 return mFormatData[static_cast<size_t>(formatID)]; 220 } 221 222 ANGLE_INLINE const Format &operator[](angle::FormatID formatID) const 223 { 224 return mFormatData[static_cast<size_t>(formatID)]; 225 } 226 227 private: 228 // The table data is indexed by angle::FormatID. 229 std::array<Format, angle::kNumANGLEFormats> mFormatData; 230 }; 231 232 // This will return a reference to a VkFormatProperties with the feature flags supported 233 // if the format is a mandatory format described in section 31.3.3. Required Format Support 234 // of the Vulkan spec. If the vkFormat isn't mandatory, it will return a VkFormatProperties 235 // initialized to 0. 236 const VkFormatProperties &GetMandatoryFormatSupport(angle::FormatID formatID); 237 238 VkImageUsageFlags GetMaximalImageUsageFlags(RendererVk *renderer, angle::FormatID formatID); 239 240 } // namespace vk 241 242 // Checks if a Vulkan format supports all the features needed to use it as a GL texture format. 243 bool HasFullTextureFormatSupport(RendererVk *renderer, angle::FormatID formatID); 244 // Checks if a Vulkan format supports all the features except rendering. 245 bool HasNonRenderableTextureFormatSupport(RendererVk *renderer, angle::FormatID formatID); 246 247 // Get the swizzle state based on format's requirements and emulations. 248 gl::SwizzleState GetFormatSwizzle(const ContextVk *contextVk, 249 const angle::Format &angleFormat, 250 const bool sized); 251 252 // Apply application's swizzle to the swizzle implied by format as received from GetFormatSwizzle. 253 gl::SwizzleState ApplySwizzle(const gl::SwizzleState &formatSwizzle, 254 const gl::SwizzleState &toApply); 255 256 } // namespace rx 257 258 #endif // LIBANGLE_RENDERER_VULKAN_VK_FORMAT_UTILS_H_ 259