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