• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "libANGLE/formatutils.h"
13 #include "libANGLE/renderer/Format.h"
14 #include "libANGLE/renderer/copyvertex.h"
15 #include "libANGLE/renderer/renderer_utils.h"
16 #include "libANGLE/renderer/vulkan/vk_headers.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 struct ImageFormatInitInfo final
38 {
39     angle::FormatID format;
40     VkFormat vkFormat;
41     InitializeTextureDataFunction initializer;
42 };
43 
44 struct BufferFormatInitInfo final
45 {
46     angle::FormatID format;
47     VkFormat vkFormat;
48     bool vkFormatIsPacked;
49     VertexCopyFunction vertexLoadFunction;
50     bool vertexLoadRequiresConversion;
51 };
52 
53 // Describes a Vulkan format. For more information on formats in the Vulkan back-end please see
54 // https://chromium.googlesource.com/angle/angle/+/master/src/libANGLE/renderer/vulkan/doc/FormatTablesAndEmulation.md
55 struct Format final : private angle::NonCopyable
56 {
57     Format();
58 
validfinal59     bool valid() const { return internalFormat != 0; }
60 
61     // The intended format is the front-end format. For Textures this usually correponds to a
62     // GLenum in the headers. Buffer formats don't always have a corresponding GLenum type.
63     // Some Surface formats and unsized types also don't have a corresponding GLenum.
intendedFormatfinal64     const angle::Format &intendedFormat() const { return angle::Format::Get(intendedFormatID); }
65 
66     // The actual Image format is used to implement the front-end format for Texture/Renderbuffers.
actualImageFormatfinal67     const angle::Format &actualImageFormat() const
68     {
69         return angle::Format::Get(actualImageFormatID);
70     }
71 
72     // The actual Buffer format is used to implement the front-end format for Buffers.
actualBufferFormatfinal73     const angle::Format &actualBufferFormat() const
74     {
75         return angle::Format::Get(actualBufferFormatID);
76     }
77 
78     // The |internalFormat| always correponds to a valid GLenum type. For types that don't have a
79     // corresponding GLenum we do our best to specify a GLenum that is "close".
getInternalFormatInfofinal80     const gl::InternalFormat &getInternalFormatInfo(GLenum type) const
81     {
82         return gl::GetInternalFormatInfo(internalFormat, type);
83     }
84 
85     // Returns buffer alignment for image-copy operations (to or from a buffer).
86     size_t getImageCopyBufferAlignment() const;
87 
88     // Returns true if the Image format has more channels than the ANGLE format.
89     bool hasEmulatedImageChannels() const;
90 
91     // This is an auto-generated method in vk_format_table_autogen.cpp.
92     void initialize(RendererVk *renderer, const angle::Format &angleFormat);
93 
94     // These are used in the format table init.
95     void initImageFallback(RendererVk *renderer, const ImageFormatInitInfo *info, int numInfo);
96     void initBufferFallback(RendererVk *renderer, const BufferFormatInitInfo *info, int numInfo);
97 
98     angle::FormatID intendedFormatID;
99     GLenum internalFormat;
100     angle::FormatID actualImageFormatID;
101     VkFormat vkImageFormat;
102     angle::FormatID actualBufferFormatID;
103     VkFormat vkBufferFormat;
104 
105     InitializeTextureDataFunction imageInitializerFunction;
106     LoadFunctionMap textureLoadFunctions;
107     VertexCopyFunction vertexLoadFunction;
108 
109     bool vertexLoadRequiresConversion;
110     bool vkBufferFormatIsPacked;
111     bool vkFormatIsInt;
112     bool vkFormatIsUnsigned;
113 };
114 
115 bool operator==(const Format &lhs, const Format &rhs);
116 bool operator!=(const Format &lhs, const Format &rhs);
117 
118 class FormatTable final : angle::NonCopyable
119 {
120   public:
121     FormatTable();
122     ~FormatTable();
123 
124     // Also initializes the TextureCapsMap and the compressedTextureCaps in the Caps instance.
125     void initialize(RendererVk *renderer,
126                     gl::TextureCapsMap *outTextureCapsMap,
127                     std::vector<GLenum> *outCompressedTextureFormats);
128 
129     ANGLE_INLINE const Format &operator[](GLenum internalFormat) const
130     {
131         angle::FormatID formatID = angle::Format::InternalFormatToID(internalFormat);
132         return mFormatData[static_cast<size_t>(formatID)];
133     }
134 
135     ANGLE_INLINE const Format &operator[](angle::FormatID formatID) const
136     {
137         return mFormatData[static_cast<size_t>(formatID)];
138     }
139 
140   private:
141     // The table data is indexed by angle::FormatID.
142     std::array<Format, angle::kNumANGLEFormats> mFormatData;
143 };
144 
145 // This will return a reference to a VkFormatProperties with the feature flags supported
146 // if the format is a mandatory format described in section 31.3.3. Required Format Support
147 // of the Vulkan spec. If the vkFormat isn't mandatory, it will return a VkFormatProperties
148 // initialized to 0.
149 const VkFormatProperties &GetMandatoryFormatSupport(VkFormat vkFormat);
150 
151 VkImageUsageFlags GetMaximalImageUsageFlags(RendererVk *renderer, VkFormat format);
152 
153 }  // namespace vk
154 
155 // Checks if a vkFormat supports all the features needed to use it as a GL texture format
156 bool HasFullTextureFormatSupport(RendererVk *renderer, VkFormat vkFormat);
157 // Checks if a vkFormat supports all the features except texture filtering
158 bool HasNonFilterableTextureFormatSupport(RendererVk *renderer, VkFormat vkFormat);
159 // Checks if a vkFormat supports all the features except rendering
160 bool HasNonRenderableTextureFormatSupport(RendererVk *renderer, VkFormat vkFormat);
161 
162 // Returns the alignment for a buffer to be used with the vertex input stage in Vulkan. This
163 // calculation is listed in the Vulkan spec at the end of the section 'Vertex Input Description'.
164 size_t GetVertexInputAlignment(const vk::Format &format);
165 
166 void MapSwizzleState(const ContextVk *contextVk,
167                      const vk::Format &format,
168                      const bool sized,
169                      const gl::SwizzleState &swizzleState,
170                      gl::SwizzleState *swizzleStateOut);
171 
172 namespace vk
173 {
174 
ConvertToNonLinear(VkFormat format)175 ANGLE_INLINE VkFormat ConvertToNonLinear(VkFormat format)
176 {
177     switch (format)
178     {
179         case VK_FORMAT_R8_UNORM:
180             return VK_FORMAT_R8_SRGB;
181         case VK_FORMAT_R8G8_UNORM:
182             return VK_FORMAT_R8G8_SRGB;
183         case VK_FORMAT_R8G8B8_UNORM:
184             return VK_FORMAT_R8G8B8_SRGB;
185         case VK_FORMAT_B8G8R8_UNORM:
186             return VK_FORMAT_B8G8R8_SRGB;
187         case VK_FORMAT_R8G8B8A8_UNORM:
188             return VK_FORMAT_R8G8B8A8_SRGB;
189         case VK_FORMAT_B8G8R8A8_UNORM:
190             return VK_FORMAT_B8G8R8A8_SRGB;
191         case VK_FORMAT_BC1_RGB_UNORM_BLOCK:
192             return VK_FORMAT_BC1_RGB_SRGB_BLOCK;
193         case VK_FORMAT_BC1_RGBA_UNORM_BLOCK:
194             return VK_FORMAT_BC1_RGBA_SRGB_BLOCK;
195         case VK_FORMAT_BC2_UNORM_BLOCK:
196             return VK_FORMAT_BC2_SRGB_BLOCK;
197         case VK_FORMAT_BC3_UNORM_BLOCK:
198             return VK_FORMAT_BC3_SRGB_BLOCK;
199         case VK_FORMAT_BC7_UNORM_BLOCK:
200             return VK_FORMAT_BC7_SRGB_BLOCK;
201         case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK:
202             return VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK;
203         case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK:
204             return VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK;
205         case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK:
206             return VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK;
207         case VK_FORMAT_ASTC_4x4_UNORM_BLOCK:
208             return VK_FORMAT_ASTC_4x4_SRGB_BLOCK;
209         case VK_FORMAT_ASTC_5x4_UNORM_BLOCK:
210             return VK_FORMAT_ASTC_5x4_SRGB_BLOCK;
211         case VK_FORMAT_ASTC_5x5_UNORM_BLOCK:
212             return VK_FORMAT_ASTC_5x5_SRGB_BLOCK;
213         case VK_FORMAT_ASTC_6x5_UNORM_BLOCK:
214             return VK_FORMAT_ASTC_6x5_SRGB_BLOCK;
215         case VK_FORMAT_ASTC_6x6_UNORM_BLOCK:
216             return VK_FORMAT_ASTC_6x6_SRGB_BLOCK;
217         case VK_FORMAT_ASTC_8x5_UNORM_BLOCK:
218             return VK_FORMAT_ASTC_8x5_SRGB_BLOCK;
219         case VK_FORMAT_ASTC_8x6_UNORM_BLOCK:
220             return VK_FORMAT_ASTC_8x6_SRGB_BLOCK;
221         case VK_FORMAT_ASTC_8x8_UNORM_BLOCK:
222             return VK_FORMAT_ASTC_8x8_SRGB_BLOCK;
223         case VK_FORMAT_ASTC_10x5_UNORM_BLOCK:
224             return VK_FORMAT_ASTC_10x5_SRGB_BLOCK;
225         case VK_FORMAT_ASTC_10x6_UNORM_BLOCK:
226             return VK_FORMAT_ASTC_10x6_SRGB_BLOCK;
227         case VK_FORMAT_ASTC_10x8_UNORM_BLOCK:
228             return VK_FORMAT_ASTC_10x8_SRGB_BLOCK;
229         case VK_FORMAT_ASTC_10x10_UNORM_BLOCK:
230             return VK_FORMAT_ASTC_10x10_SRGB_BLOCK;
231         case VK_FORMAT_ASTC_12x10_UNORM_BLOCK:
232             return VK_FORMAT_ASTC_12x10_SRGB_BLOCK;
233         case VK_FORMAT_ASTC_12x12_UNORM_BLOCK:
234             return VK_FORMAT_ASTC_12x12_SRGB_BLOCK;
235         default:
236             return VK_FORMAT_UNDEFINED;
237     }
238 }
239 
ConvertToLinear(VkFormat format)240 ANGLE_INLINE VkFormat ConvertToLinear(VkFormat format)
241 {
242     switch (format)
243     {
244         case VK_FORMAT_R8_SRGB:
245             return VK_FORMAT_R8_UNORM;
246         case VK_FORMAT_R8G8_SRGB:
247             return VK_FORMAT_R8G8_UNORM;
248         case VK_FORMAT_R8G8B8_SRGB:
249             return VK_FORMAT_R8G8B8_UNORM;
250         case VK_FORMAT_B8G8R8_SRGB:
251             return VK_FORMAT_B8G8R8_UNORM;
252         case VK_FORMAT_R8G8B8A8_SRGB:
253             return VK_FORMAT_R8G8B8A8_UNORM;
254         case VK_FORMAT_B8G8R8A8_SRGB:
255             return VK_FORMAT_B8G8R8A8_UNORM;
256         case VK_FORMAT_BC1_RGB_SRGB_BLOCK:
257             return VK_FORMAT_BC1_RGB_UNORM_BLOCK;
258         case VK_FORMAT_BC1_RGBA_SRGB_BLOCK:
259             return VK_FORMAT_BC1_RGBA_UNORM_BLOCK;
260         case VK_FORMAT_BC2_SRGB_BLOCK:
261             return VK_FORMAT_BC2_UNORM_BLOCK;
262         case VK_FORMAT_BC3_SRGB_BLOCK:
263             return VK_FORMAT_BC3_UNORM_BLOCK;
264         case VK_FORMAT_BC7_SRGB_BLOCK:
265             return VK_FORMAT_BC7_UNORM_BLOCK;
266         case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK:
267             return VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
268         case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK:
269             return VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK;
270         case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK:
271             return VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK;
272         case VK_FORMAT_ASTC_4x4_SRGB_BLOCK:
273             return VK_FORMAT_ASTC_4x4_UNORM_BLOCK;
274         case VK_FORMAT_ASTC_5x4_SRGB_BLOCK:
275             return VK_FORMAT_ASTC_5x4_UNORM_BLOCK;
276         case VK_FORMAT_ASTC_5x5_SRGB_BLOCK:
277             return VK_FORMAT_ASTC_5x5_UNORM_BLOCK;
278         case VK_FORMAT_ASTC_6x5_SRGB_BLOCK:
279             return VK_FORMAT_ASTC_6x5_UNORM_BLOCK;
280         case VK_FORMAT_ASTC_6x6_SRGB_BLOCK:
281             return VK_FORMAT_ASTC_6x6_UNORM_BLOCK;
282         case VK_FORMAT_ASTC_8x5_SRGB_BLOCK:
283             return VK_FORMAT_ASTC_8x5_UNORM_BLOCK;
284         case VK_FORMAT_ASTC_8x6_SRGB_BLOCK:
285             return VK_FORMAT_ASTC_8x6_UNORM_BLOCK;
286         case VK_FORMAT_ASTC_8x8_SRGB_BLOCK:
287             return VK_FORMAT_ASTC_8x8_UNORM_BLOCK;
288         case VK_FORMAT_ASTC_10x5_SRGB_BLOCK:
289             return VK_FORMAT_ASTC_10x5_UNORM_BLOCK;
290         case VK_FORMAT_ASTC_10x6_SRGB_BLOCK:
291             return VK_FORMAT_ASTC_10x6_UNORM_BLOCK;
292         case VK_FORMAT_ASTC_10x8_SRGB_BLOCK:
293             return VK_FORMAT_ASTC_10x8_UNORM_BLOCK;
294         case VK_FORMAT_ASTC_10x10_SRGB_BLOCK:
295             return VK_FORMAT_ASTC_10x10_UNORM_BLOCK;
296         case VK_FORMAT_ASTC_12x10_SRGB_BLOCK:
297             return VK_FORMAT_ASTC_12x10_UNORM_BLOCK;
298         case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:
299             return VK_FORMAT_ASTC_12x12_UNORM_BLOCK;
300         default:
301             return VK_FORMAT_UNDEFINED;
302     }
303 }
304 
IsNonLinearFormat(VkFormat format)305 ANGLE_INLINE bool IsNonLinearFormat(VkFormat format)
306 {
307     return ConvertToLinear(format) != VK_FORMAT_UNDEFINED;
308 }
IsOverridableLinearFormat(VkFormat format)309 ANGLE_INLINE bool IsOverridableLinearFormat(VkFormat format)
310 {
311     return ConvertToNonLinear(format) != VK_FORMAT_UNDEFINED;
312 }
IsLinearFormat(VkFormat format)313 ANGLE_INLINE bool IsLinearFormat(VkFormat format)
314 {
315     return !IsNonLinearFormat(format);
316 }
317 
318 }  // namespace vk
319 }  // namespace rx
320 
321 #endif  // LIBANGLE_RENDERER_VULKAN_VK_FORMAT_UTILS_H_
322