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 #include "libANGLE/renderer/vulkan/vk_format_utils.h"
10
11 #include "libANGLE/Texture.h"
12 #include "libANGLE/formatutils.h"
13 #include "libANGLE/renderer/load_functions_table.h"
14 #include "libANGLE/renderer/load_texture_border_functions_table.h"
15 #include "libANGLE/renderer/vulkan/ContextVk.h"
16 #include "libANGLE/renderer/vulkan/RendererVk.h"
17 #include "libANGLE/renderer/vulkan/vk_caps_utils.h"
18
19 namespace rx
20 {
21 namespace
22 {
FillTextureFormatCaps(RendererVk * renderer,angle::FormatID formatID,gl::TextureCaps * outTextureCaps)23 void FillTextureFormatCaps(RendererVk *renderer,
24 angle::FormatID formatID,
25 gl::TextureCaps *outTextureCaps)
26 {
27 const VkPhysicalDeviceLimits &physicalDeviceLimits =
28 renderer->getPhysicalDeviceProperties().limits;
29 bool hasColorAttachmentFeatureBit =
30 renderer->hasImageFormatFeatureBits(formatID, VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT);
31 bool hasDepthAttachmentFeatureBit = renderer->hasImageFormatFeatureBits(
32 formatID, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT);
33
34 outTextureCaps->texturable =
35 renderer->hasImageFormatFeatureBits(formatID, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT);
36 outTextureCaps->filterable = renderer->hasImageFormatFeatureBits(
37 formatID, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT);
38 outTextureCaps->blendable =
39 renderer->hasImageFormatFeatureBits(formatID, VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT);
40
41 // For renderbuffer and texture attachments we require transfer and sampling for
42 // GLES 2.0 CopyTexImage support. Sampling is also required for other features like
43 // blits and EGLImages.
44 outTextureCaps->textureAttachment =
45 outTextureCaps->texturable &&
46 (hasColorAttachmentFeatureBit || hasDepthAttachmentFeatureBit);
47 outTextureCaps->renderbuffer = outTextureCaps->textureAttachment;
48
49 if (outTextureCaps->renderbuffer)
50 {
51 if (hasColorAttachmentFeatureBit)
52 {
53 vk_gl::AddSampleCounts(physicalDeviceLimits.framebufferColorSampleCounts,
54 &outTextureCaps->sampleCounts);
55 }
56 if (hasDepthAttachmentFeatureBit)
57 {
58 // Some drivers report different depth and stencil sample counts. We'll AND those
59 // counts together, limiting all depth and/or stencil formats to the lower number of
60 // sample counts.
61 vk_gl::AddSampleCounts((physicalDeviceLimits.framebufferDepthSampleCounts &
62 physicalDeviceLimits.framebufferStencilSampleCounts),
63 &outTextureCaps->sampleCounts);
64 }
65 }
66 }
67
HasFullBufferFormatSupport(RendererVk * renderer,angle::FormatID formatID)68 bool HasFullBufferFormatSupport(RendererVk *renderer, angle::FormatID formatID)
69 {
70 // Note: GL_EXT_texture_buffer support uses the same vkBufferFormat that is determined by
71 // Format::initBufferFallback, which uses this function. That relies on the fact that formats
72 // required for GL_EXT_texture_buffer all have mandatory VERTEX_BUFFER feature support in
73 // Vulkan. If this function is changed to test for more features in such a way that makes any
74 // of those formats use a fallback format, the implementation of GL_EXT_texture_buffer must be
75 // modified not to use vkBufferFormat.
76 return renderer->hasBufferFormatFeatureBits(formatID, VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT);
77 }
78
79 using SupportTest = bool (*)(RendererVk *renderer, angle::FormatID formatID);
80
81 template <class FormatInitInfo>
FindSupportedFormat(RendererVk * renderer,const FormatInitInfo * info,size_t skip,int numInfo,SupportTest hasSupport)82 int FindSupportedFormat(RendererVk *renderer,
83 const FormatInitInfo *info,
84 size_t skip,
85 int numInfo,
86 SupportTest hasSupport)
87 {
88 ASSERT(numInfo > 0);
89 const int last = numInfo - 1;
90
91 for (int i = static_cast<int>(skip); i < last; ++i)
92 {
93 ASSERT(info[i].format != angle::FormatID::NONE);
94 if (hasSupport(renderer, info[i].format))
95 return i;
96 }
97
98 if (skip > 0 && !hasSupport(renderer, info[last].format))
99 {
100 // We couldn't find a valid fallback, try again without skip
101 return FindSupportedFormat(renderer, info, 0, numInfo, hasSupport);
102 }
103
104 ASSERT(info[last].format != angle::FormatID::NONE);
105 ASSERT(hasSupport(renderer, info[last].format));
106 return last;
107 }
108
HasNonFilterableTextureFormatSupport(RendererVk * renderer,angle::FormatID formatID)109 bool HasNonFilterableTextureFormatSupport(RendererVk *renderer, angle::FormatID formatID)
110 {
111 constexpr uint32_t kBitsColor =
112 VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
113 constexpr uint32_t kBitsDepth = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
114
115 return renderer->hasImageFormatFeatureBits(formatID, kBitsColor) ||
116 renderer->hasImageFormatFeatureBits(formatID, kBitsDepth);
117 }
118 } // anonymous namespace
119
120 namespace vk
121 {
122 // Format implementation.
Format()123 Format::Format()
124 : intendedFormatID(angle::FormatID::NONE),
125 intendedGLFormat(GL_NONE),
126 actualImageFormatID(angle::FormatID::NONE),
127 actualBufferFormatID(angle::FormatID::NONE),
128 actualCompressedBufferFormatID(angle::FormatID::NONE),
129 imageInitializerFunction(nullptr),
130 textureLoadFunctions(),
131 vertexLoadFunction(nullptr),
132 compressedVertexLoadFunction(nullptr),
133 vertexLoadRequiresConversion(false),
134 compressedVertexLoadRequiresConversion(false),
135 vkBufferFormatIsPacked(false),
136 vkFormatIsInt(false),
137 vkFormatIsUnsigned(false)
138 {}
139
initImageFallback(RendererVk * renderer,const ImageFormatInitInfo * info,int numInfo)140 void Format::initImageFallback(RendererVk *renderer, const ImageFormatInitInfo *info, int numInfo)
141 {
142 size_t skip = renderer->getFeatures().forceFallbackFormat.enabled ? 1 : 0;
143 SupportTest testFunction = HasFullTextureFormatSupport;
144 const angle::Format &format = angle::Format::Get(info[0].format);
145 if (format.isInt() || (format.isFloat() && format.redBits >= 32))
146 {
147 // Integer formats don't support filtering in GL, so don't test for it.
148 // Filtering of 32-bit float textures is not supported on Android, and
149 // it's enabled by the extension OES_texture_float_linear, which is
150 // enabled automatically by examining format capabilities.
151 testFunction = HasNonFilterableTextureFormatSupport;
152 }
153 if (format.isSnorm() || format.isBlock)
154 {
155 // Rendering to SNORM textures is not supported on Android, and it's
156 // enabled by the extension EXT_render_snorm.
157 // Compressed textures also need to perform this check.
158 testFunction = HasNonRenderableTextureFormatSupport;
159 }
160 int i = FindSupportedFormat(renderer, info, skip, static_cast<uint32_t>(numInfo), testFunction);
161
162 actualImageFormatID = info[i].format;
163 imageInitializerFunction = info[i].initializer;
164 }
165
initBufferFallback(RendererVk * renderer,const BufferFormatInitInfo * info,int numInfo,int compressedStartIndex)166 void Format::initBufferFallback(RendererVk *renderer,
167 const BufferFormatInitInfo *info,
168 int numInfo,
169 int compressedStartIndex)
170 {
171 {
172 size_t skip = renderer->getFeatures().forceFallbackFormat.enabled ? 1 : 0;
173 int i = FindSupportedFormat(renderer, info, skip, compressedStartIndex,
174 HasFullBufferFormatSupport);
175
176 actualBufferFormatID = info[i].format;
177 vkBufferFormatIsPacked = info[i].vkFormatIsPacked;
178 vertexLoadFunction = info[i].vertexLoadFunction;
179 vertexLoadRequiresConversion = info[i].vertexLoadRequiresConversion;
180 }
181
182 if (renderer->getFeatures().compressVertexData.enabled && compressedStartIndex < numInfo)
183 {
184 int i = FindSupportedFormat(renderer, info, compressedStartIndex, numInfo,
185 HasFullBufferFormatSupport);
186
187 actualCompressedBufferFormatID = info[i].format;
188 vkCompressedBufferFormatIsPacked = info[i].vkFormatIsPacked;
189 compressedVertexLoadFunction = info[i].vertexLoadFunction;
190 compressedVertexLoadRequiresConversion = info[i].vertexLoadRequiresConversion;
191 }
192 }
193
getImageCopyBufferAlignment() const194 size_t Format::getImageCopyBufferAlignment() const
195 {
196 // vkCmdCopyBufferToImage must have an offset that is a multiple of 4 as well as a multiple
197 // of the texel size (if uncompressed) or pixel block size (if compressed).
198 // https://www.khronos.org/registry/vulkan/specs/1.0/man/html/VkBufferImageCopy.html
199 //
200 // We need lcm(4, texelSize) (lcm = least common multiplier). For compressed images,
201 // |texelSize| would contain the block size. Since 4 is constant, this can be calculated as:
202 //
203 // | texelSize texelSize % 4 == 0
204 // | 4 * texelSize texelSize % 4 == 1
205 // lcm(4, texelSize) = <
206 // | 2 * texelSize texelSize % 4 == 2
207 // | 4 * texelSize texelSize % 4 == 3
208 //
209 // This means:
210 //
211 // - texelSize % 2 != 0 gives a 4x multiplier
212 // - else texelSize % 4 != 0 gives a 2x multiplier
213 // - else there's no multiplier.
214 //
215 const angle::Format &format = actualImageFormat();
216
217 ASSERT(format.pixelBytes != 0);
218 const size_t texelSize = format.pixelBytes;
219 const size_t multiplier = texelSize % 2 != 0 ? 4 : texelSize % 4 != 0 ? 2 : 1;
220 const size_t alignment = multiplier * texelSize;
221
222 return alignment;
223 }
224
getValidImageCopyBufferAlignment() const225 size_t Format::getValidImageCopyBufferAlignment() const
226 {
227 constexpr size_t kMinimumAlignment = 16;
228 return (intendedFormatID == angle::FormatID::NONE) ? kMinimumAlignment
229 : getImageCopyBufferAlignment();
230 }
231
hasEmulatedImageChannels() const232 bool Format::hasEmulatedImageChannels() const
233 {
234 const angle::Format &angleFmt = intendedFormat();
235 const angle::Format &textureFmt = actualImageFormat();
236
237 return (angleFmt.alphaBits == 0 && textureFmt.alphaBits > 0) ||
238 (angleFmt.blueBits == 0 && textureFmt.blueBits > 0) ||
239 (angleFmt.greenBits == 0 && textureFmt.greenBits > 0) ||
240 (angleFmt.depthBits == 0 && textureFmt.depthBits > 0) ||
241 (angleFmt.stencilBits == 0 && textureFmt.stencilBits > 0);
242 }
243
operator ==(const Format & lhs,const Format & rhs)244 bool operator==(const Format &lhs, const Format &rhs)
245 {
246 return &lhs == &rhs;
247 }
248
operator !=(const Format & lhs,const Format & rhs)249 bool operator!=(const Format &lhs, const Format &rhs)
250 {
251 return &lhs != &rhs;
252 }
253
254 // FormatTable implementation.
FormatTable()255 FormatTable::FormatTable() {}
256
~FormatTable()257 FormatTable::~FormatTable() {}
258
initialize(RendererVk * renderer,gl::TextureCapsMap * outTextureCapsMap,std::vector<GLenum> * outCompressedTextureFormats)259 void FormatTable::initialize(RendererVk *renderer,
260 gl::TextureCapsMap *outTextureCapsMap,
261 std::vector<GLenum> *outCompressedTextureFormats)
262 {
263 for (size_t formatIndex = 0; formatIndex < angle::kNumANGLEFormats; ++formatIndex)
264 {
265 Format &format = mFormatData[formatIndex];
266 const auto formatID = static_cast<angle::FormatID>(formatIndex);
267 const angle::Format &angleFormat = angle::Format::Get(formatID);
268
269 format.initialize(renderer, angleFormat);
270 format.intendedFormatID = formatID;
271
272 if (!format.valid())
273 {
274 continue;
275 }
276
277 gl::TextureCaps textureCaps;
278 FillTextureFormatCaps(renderer, format.actualImageFormatID, &textureCaps);
279 outTextureCapsMap->set(formatID, textureCaps);
280
281 if (textureCaps.texturable)
282 {
283 format.textureLoadFunctions =
284 GetLoadFunctionsMap(format.intendedGLFormat, format.actualImageFormatID);
285 format.textureBorderLoadFunctions = GetLoadTextureBorderFunctionsMap(
286 format.intendedGLFormat, format.actualImageFormatID);
287 }
288
289 if (angleFormat.isBlock)
290 {
291 outCompressedTextureFormats->push_back(format.intendedGLFormat);
292 }
293 }
294 }
295
GetMaximalImageUsageFlags(RendererVk * renderer,angle::FormatID formatID)296 VkImageUsageFlags GetMaximalImageUsageFlags(RendererVk *renderer, angle::FormatID formatID)
297 {
298 constexpr VkFormatFeatureFlags kImageUsageFeatureBits =
299 VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT |
300 VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT |
301 VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT;
302 VkFormatFeatureFlags featureBits =
303 renderer->getImageFormatFeatureBits(formatID, kImageUsageFeatureBits);
304 VkImageUsageFlags imageUsageFlags = 0;
305 if (featureBits & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)
306 imageUsageFlags |= VK_IMAGE_USAGE_SAMPLED_BIT;
307 if (featureBits & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)
308 imageUsageFlags |= VK_IMAGE_USAGE_STORAGE_BIT;
309 if (featureBits & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)
310 imageUsageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
311 if (featureBits & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
312 imageUsageFlags |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
313 if (featureBits & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT)
314 imageUsageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
315 if (featureBits & VK_FORMAT_FEATURE_TRANSFER_DST_BIT)
316 imageUsageFlags |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
317 imageUsageFlags |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
318 return imageUsageFlags;
319 }
320 } // namespace vk
321
HasFullTextureFormatSupport(RendererVk * renderer,angle::FormatID formatID)322 bool HasFullTextureFormatSupport(RendererVk *renderer, angle::FormatID formatID)
323 {
324 constexpr uint32_t kBitsColor = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
325 VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT |
326 VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
327
328 // In OpenGL ES, all renderable formats except 32-bit floating-point support blending.
329 // 32-bit floating-point case validation is handled by ANGLE's frontend.
330 uint32_t kBitsColorFull = kBitsColor;
331 switch (formatID)
332 {
333 case angle::FormatID::R32_FLOAT:
334 case angle::FormatID::R32G32_FLOAT:
335 case angle::FormatID::R32G32B32A32_FLOAT:
336 break;
337 default:
338 kBitsColorFull |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT;
339 break;
340 }
341
342 constexpr uint32_t kBitsDepth = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
343
344 return renderer->hasImageFormatFeatureBits(formatID, kBitsColorFull) ||
345 renderer->hasImageFormatFeatureBits(formatID, kBitsDepth);
346 }
347
HasNonRenderableTextureFormatSupport(RendererVk * renderer,angle::FormatID formatID)348 bool HasNonRenderableTextureFormatSupport(RendererVk *renderer, angle::FormatID formatID)
349 {
350 constexpr uint32_t kBitsColor =
351 VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
352 constexpr uint32_t kBitsDepth = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
353
354 return renderer->hasImageFormatFeatureBits(formatID, kBitsColor) ||
355 renderer->hasImageFormatFeatureBits(formatID, kBitsDepth);
356 }
357
GetVertexInputAlignment(const vk::Format & format,bool compressed)358 size_t GetVertexInputAlignment(const vk::Format &format, bool compressed)
359 {
360 const angle::Format &bufferFormat = format.actualBufferFormat(compressed);
361 size_t pixelBytes = bufferFormat.pixelBytes;
362 return format.vkBufferFormatIsPacked ? pixelBytes : (pixelBytes / bufferFormat.channelCount);
363 }
364
GetSwizzleStateComponent(const gl::SwizzleState & swizzleState,GLenum component)365 GLenum GetSwizzleStateComponent(const gl::SwizzleState &swizzleState, GLenum component)
366 {
367 switch (component)
368 {
369 case GL_RED:
370 return swizzleState.swizzleRed;
371 case GL_GREEN:
372 return swizzleState.swizzleGreen;
373 case GL_BLUE:
374 return swizzleState.swizzleBlue;
375 case GL_ALPHA:
376 return swizzleState.swizzleAlpha;
377 default:
378 return component;
379 }
380 }
381
ApplySwizzle(const gl::SwizzleState & formatSwizzle,const gl::SwizzleState & toApply)382 gl::SwizzleState ApplySwizzle(const gl::SwizzleState &formatSwizzle,
383 const gl::SwizzleState &toApply)
384 {
385 gl::SwizzleState result;
386
387 result.swizzleRed = GetSwizzleStateComponent(formatSwizzle, toApply.swizzleRed);
388 result.swizzleGreen = GetSwizzleStateComponent(formatSwizzle, toApply.swizzleGreen);
389 result.swizzleBlue = GetSwizzleStateComponent(formatSwizzle, toApply.swizzleBlue);
390 result.swizzleAlpha = GetSwizzleStateComponent(formatSwizzle, toApply.swizzleAlpha);
391
392 return result;
393 }
394
GetFormatSwizzle(const ContextVk * contextVk,const vk::Format & format,const bool sized)395 gl::SwizzleState GetFormatSwizzle(const ContextVk *contextVk,
396 const vk::Format &format,
397 const bool sized)
398 {
399 const angle::Format &angleFormat = format.intendedFormat();
400
401 gl::SwizzleState internalSwizzle;
402
403 if (angleFormat.isLUMA())
404 {
405 GLenum swizzleRGB, swizzleA;
406 if (angleFormat.luminanceBits > 0)
407 {
408 swizzleRGB = GL_RED;
409 swizzleA = (angleFormat.alphaBits > 0 ? GL_GREEN : GL_ONE);
410 }
411 else
412 {
413 swizzleRGB = GL_ZERO;
414 swizzleA = GL_RED;
415 }
416 internalSwizzle.swizzleRed = swizzleRGB;
417 internalSwizzle.swizzleGreen = swizzleRGB;
418 internalSwizzle.swizzleBlue = swizzleRGB;
419 internalSwizzle.swizzleAlpha = swizzleA;
420 }
421 else
422 {
423 if (angleFormat.hasDepthOrStencilBits())
424 {
425 // In OES_depth_texture/ARB_depth_texture, depth
426 // textures are treated as luminance.
427 // If the internalformat was not sized, use OES_depth_texture behavior
428 bool hasGB = (angleFormat.depthBits > 0) && !sized;
429
430 internalSwizzle.swizzleRed = GL_RED;
431 internalSwizzle.swizzleGreen = hasGB ? GL_RED : GL_ZERO;
432 internalSwizzle.swizzleBlue = hasGB ? GL_RED : GL_ZERO;
433 internalSwizzle.swizzleAlpha = GL_ONE;
434 }
435 else
436 {
437 // Color bits are all zero for blocked formats
438 if (!angleFormat.isBlock)
439 {
440 // Set any missing channel to default in case the emulated format has that channel.
441 internalSwizzle.swizzleRed = angleFormat.redBits > 0 ? GL_RED : GL_ZERO;
442 internalSwizzle.swizzleGreen = angleFormat.greenBits > 0 ? GL_GREEN : GL_ZERO;
443 internalSwizzle.swizzleBlue = angleFormat.blueBits > 0 ? GL_BLUE : GL_ZERO;
444 internalSwizzle.swizzleAlpha = angleFormat.alphaBits > 0 ? GL_ALPHA : GL_ONE;
445 }
446 }
447 }
448
449 return internalSwizzle;
450 }
451 } // namespace rx
452