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 struct ImageFormatInitInfo final
38 {
39     angle::FormatID format;
40     InitializeTextureDataFunction initializer;
41 };
42 
43 struct BufferFormatInitInfo final
44 {
45     angle::FormatID format;
46     bool vkFormatIsPacked;
47     VertexCopyFunction vertexLoadFunction;
48     bool vertexLoadRequiresConversion;
49 };
50 
51 VkFormat GetVkFormatFromFormatID(angle::FormatID formatID);
52 angle::FormatID GetFormatIDFromVkFormat(VkFormat vkFormat);
53 
54 // Describes a Vulkan format. For more information on formats in the Vulkan back-end please see
55 // https://chromium.googlesource.com/angle/angle/+/master/src/libANGLE/renderer/vulkan/doc/FormatTablesAndEmulation.md
56 struct Format final : private angle::NonCopyable
57 {
58     Format();
59 
validfinal60     bool valid() const { return intendedGLFormat != 0; }
61 
62     // The intended format is the front-end format. For Textures this usually correponds to a
63     // GLenum in the headers. Buffer formats don't always have a corresponding GLenum type.
64     // Some Surface formats and unsized types also don't have a corresponding GLenum.
intendedFormatfinal65     const angle::Format &intendedFormat() const { return angle::Format::Get(intendedFormatID); }
66 
67     // The actual Image format is used to implement the front-end format for Texture/Renderbuffers.
actualImageFormatfinal68     const angle::Format &actualImageFormat() const
69     {
70         return angle::Format::Get(actualImageFormatID);
71     }
72 
actualImageVkFormatfinal73     VkFormat actualImageVkFormat() const { return GetVkFormatFromFormatID(actualImageFormatID); }
74 
75     // The actual Buffer format is used to implement the front-end format for Buffers.  This format
76     // is used by vertex buffers as well as texture buffers.  Note that all formats required for
77     // GL_EXT_texture_buffer have mandatory support for vertex buffers in Vulkan, so they won't be
78     // using an emulated format.
actualBufferFormatfinal79     const angle::Format &actualBufferFormat(bool compressed) const
80     {
81         return angle::Format::Get(compressed ? actualCompressedBufferFormatID
82                                              : actualBufferFormatID);
83     }
84 
actualBufferVkFormatfinal85     VkFormat actualBufferVkFormat(bool compressed) const
86     {
87         return GetVkFormatFromFormatID(compressed ? actualCompressedBufferFormatID
88                                                   : actualBufferFormatID);
89     }
90 
getVertexLoadFunctionfinal91     VertexCopyFunction getVertexLoadFunction(bool compressed) const
92     {
93         return compressed ? compressedVertexLoadFunction : vertexLoadFunction;
94     }
95 
getVertexLoadRequiresConversionfinal96     bool getVertexLoadRequiresConversion(bool compressed) const
97     {
98         return compressed ? compressedVertexLoadRequiresConversion : vertexLoadRequiresConversion;
99     }
100 
101     // |intendedGLFormat| always correponds to a valid GLenum type. For types that don't have a
102     // corresponding GLenum we do our best to specify a GLenum that is "close".
getInternalFormatInfofinal103     const gl::InternalFormat &getInternalFormatInfo(GLenum type) const
104     {
105         return gl::GetInternalFormatInfo(intendedGLFormat, type);
106     }
107 
108     // Returns buffer alignment for image-copy operations (to or from a buffer).
109     size_t getImageCopyBufferAlignment() const;
110     size_t getValidImageCopyBufferAlignment() const;
111 
112     // Returns true if the image format has more channels than the ANGLE format.
113     bool hasEmulatedImageChannels() const;
114 
115     // Returns true if the image has a different image format than intended.
hasEmulatedImageFormatfinal116     bool hasEmulatedImageFormat() const { return actualImageFormatID != intendedFormatID; }
117 
118     // This is an auto-generated method in vk_format_table_autogen.cpp.
119     void initialize(RendererVk *renderer, const angle::Format &angleFormat);
120 
121     // These are used in the format table init.
122     void initImageFallback(RendererVk *renderer, const ImageFormatInitInfo *info, int numInfo);
123     void initBufferFallback(RendererVk *renderer,
124                             const BufferFormatInitInfo *fallbackInfo,
125                             int numInfo,
126                             int compressedStartIndex);
127 
128     angle::FormatID intendedFormatID;
129     GLenum intendedGLFormat;
130     angle::FormatID actualImageFormatID;
131     angle::FormatID actualBufferFormatID;
132     angle::FormatID actualCompressedBufferFormatID;
133 
134     InitializeTextureDataFunction imageInitializerFunction;
135     LoadFunctionMap textureLoadFunctions;
136     LoadTextureBorderFunctionMap textureBorderLoadFunctions;
137     VertexCopyFunction vertexLoadFunction;
138     VertexCopyFunction compressedVertexLoadFunction;
139 
140     bool vertexLoadRequiresConversion;
141     bool compressedVertexLoadRequiresConversion;
142     bool vkBufferFormatIsPacked;
143     bool vkCompressedBufferFormatIsPacked;
144     bool vkFormatIsInt;
145     bool vkFormatIsUnsigned;
146 };
147 
148 bool operator==(const Format &lhs, const Format &rhs);
149 bool operator!=(const Format &lhs, const Format &rhs);
150 
151 class FormatTable final : angle::NonCopyable
152 {
153   public:
154     FormatTable();
155     ~FormatTable();
156 
157     // Also initializes the TextureCapsMap and the compressedTextureCaps in the Caps instance.
158     void initialize(RendererVk *renderer,
159                     gl::TextureCapsMap *outTextureCapsMap,
160                     std::vector<GLenum> *outCompressedTextureFormats);
161 
162     ANGLE_INLINE const Format &operator[](GLenum internalFormat) const
163     {
164         angle::FormatID formatID = angle::Format::InternalFormatToID(internalFormat);
165         return mFormatData[static_cast<size_t>(formatID)];
166     }
167 
168     ANGLE_INLINE const Format &operator[](angle::FormatID formatID) const
169     {
170         return mFormatData[static_cast<size_t>(formatID)];
171     }
172 
173   private:
174     // The table data is indexed by angle::FormatID.
175     std::array<Format, angle::kNumANGLEFormats> mFormatData;
176 };
177 
178 // This will return a reference to a VkFormatProperties with the feature flags supported
179 // if the format is a mandatory format described in section 31.3.3. Required Format Support
180 // of the Vulkan spec. If the vkFormat isn't mandatory, it will return a VkFormatProperties
181 // initialized to 0.
182 const VkFormatProperties &GetMandatoryFormatSupport(angle::FormatID formatID);
183 
184 VkImageUsageFlags GetMaximalImageUsageFlags(RendererVk *renderer, angle::FormatID formatID);
185 
186 }  // namespace vk
187 
188 // Checks if a Vulkan format supports all the features needed to use it as a GL texture format.
189 bool HasFullTextureFormatSupport(RendererVk *renderer, angle::FormatID formatID);
190 // Checks if a Vulkan format supports all the features except rendering.
191 bool HasNonRenderableTextureFormatSupport(RendererVk *renderer, angle::FormatID formatID);
192 
193 // Returns the alignment for a buffer to be used with the vertex input stage in Vulkan. This
194 // calculation is listed in the Vulkan spec at the end of the section 'Vertex Input Description'.
195 size_t GetVertexInputAlignment(const vk::Format &format, bool compressed);
196 
197 // Get the swizzle state based on format's requirements and emulations.
198 gl::SwizzleState GetFormatSwizzle(const ContextVk *contextVk,
199                                   const vk::Format &format,
200                                   const bool sized);
201 
202 // Apply application's swizzle to the swizzle implied by format as received from GetFormatSwizzle.
203 gl::SwizzleState ApplySwizzle(const gl::SwizzleState &formatSwizzle,
204                               const gl::SwizzleState &toApply);
205 
206 }  // namespace rx
207 
208 #endif  // LIBANGLE_RENDERER_VULKAN_VK_FORMAT_UTILS_H_
209