xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/vulkan/vk_format_utils.h (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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