1 //
2 // Copyright 2018 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_utils:
7 // Helper functions for the Vulkan Caps.
8 //
9
10 #include "libANGLE/renderer/vulkan/vk_caps_utils.h"
11
12 #include <type_traits>
13
14 #include "common/utilities.h"
15 #include "libANGLE/Caps.h"
16 #include "libANGLE/formatutils.h"
17 #include "libANGLE/renderer/driver_utils.h"
18 #include "libANGLE/renderer/vulkan/DisplayVk.h"
19 #include "libANGLE/renderer/vulkan/RendererVk.h"
20 #include "libANGLE/renderer/vulkan/vk_cache_utils.h"
21 #include "vk_format_utils.h"
22
23 namespace
24 {
25 constexpr unsigned int kComponentsPerVector = 4;
26 } // anonymous namespace
27
28 namespace rx
29 {
30
31 namespace vk
32 {
33 namespace
34 {
35 // Checks to see if each format can be reinterpreted to an equivalent format in a different
36 // colorspace. If all supported formats can be reinterpreted, it returns true. Formats which are not
37 // supported at all are ignored and not counted as failures.
FormatReinterpretationSupported(const std::vector<GLenum> & optionalSizedFormats,const RendererVk * rendererVk,bool checkLinearColorspace)38 bool FormatReinterpretationSupported(const std::vector<GLenum> &optionalSizedFormats,
39 const RendererVk *rendererVk,
40 bool checkLinearColorspace)
41 {
42 for (GLenum glFormat : optionalSizedFormats)
43 {
44 const gl::TextureCaps &baseCaps = rendererVk->getNativeTextureCaps().get(glFormat);
45 if (baseCaps.texturable && baseCaps.filterable)
46 {
47 const Format &vkFormat = rendererVk->getFormat(glFormat);
48
49 angle::FormatID reinterpretedFormatID =
50 checkLinearColorspace ? ConvertToLinear(vkFormat.actualImageFormatID)
51 : ConvertToSRGB(vkFormat.actualImageFormatID);
52
53 const Format &reinterpretedVkFormat = rendererVk->getFormat(reinterpretedFormatID);
54
55 if (reinterpretedVkFormat.actualImageFormatID != reinterpretedFormatID)
56 {
57 return false;
58 }
59
60 if (!rendererVk->haveSameFormatFeatureBits(vkFormat.actualImageFormatID,
61 reinterpretedFormatID))
62 {
63 return false;
64 }
65 }
66 }
67
68 return true;
69 }
70
GetTextureSRGBDecodeSupport(const RendererVk * rendererVk)71 bool GetTextureSRGBDecodeSupport(const RendererVk *rendererVk)
72 {
73 static constexpr bool kLinearColorspace = true;
74
75 // GL_SRGB and GL_SRGB_ALPHA unsized formats are also required by the spec, but the only valid
76 // type for them is GL_UNSIGNED_BYTE, so they are fully included in the sized formats listed
77 // here
78 std::vector<GLenum> optionalSizedSRGBFormats = {
79 GL_SRGB8,
80 GL_SRGB8_ALPHA8_EXT,
81 GL_COMPRESSED_SRGB_S3TC_DXT1_EXT,
82 GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT,
83 GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT,
84 GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT,
85 };
86
87 if (!FormatReinterpretationSupported(optionalSizedSRGBFormats, rendererVk, kLinearColorspace))
88 {
89 return false;
90 }
91
92 return true;
93 }
94
GetTextureSRGBOverrideSupport(const RendererVk * rendererVk,const gl::Extensions & supportedExtensions)95 bool GetTextureSRGBOverrideSupport(const RendererVk *rendererVk,
96 const gl::Extensions &supportedExtensions)
97 {
98 static constexpr bool kNonLinearColorspace = false;
99
100 // If the given linear format is supported, we also need to support its corresponding nonlinear
101 // format. If the given linear format is NOT supported, we don't care about its corresponding
102 // nonlinear format.
103 std::vector<GLenum> optionalLinearFormats = {GL_RGB8,
104 GL_RGBA8,
105 GL_COMPRESSED_RGB8_ETC2,
106 GL_COMPRESSED_RGBA8_ETC2_EAC,
107 GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,
108 GL_COMPRESSED_RGBA_ASTC_4x4,
109 GL_COMPRESSED_RGBA_ASTC_5x4,
110 GL_COMPRESSED_RGBA_ASTC_5x5,
111 GL_COMPRESSED_RGBA_ASTC_6x5,
112 GL_COMPRESSED_RGBA_ASTC_6x6,
113 GL_COMPRESSED_RGBA_ASTC_8x5,
114 GL_COMPRESSED_RGBA_ASTC_8x6,
115 GL_COMPRESSED_RGBA_ASTC_8x8,
116 GL_COMPRESSED_RGBA_ASTC_10x5,
117 GL_COMPRESSED_RGBA_ASTC_10x6,
118 GL_COMPRESSED_RGBA_ASTC_10x8,
119 GL_COMPRESSED_RGBA_ASTC_10x10,
120 GL_COMPRESSED_RGBA_ASTC_12x10,
121 GL_COMPRESSED_RGBA_ASTC_12x12};
122 std::vector<GLenum> optionalS3TCLinearFormats = {
123 GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
124 GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT};
125 std::vector<GLenum> optionalR8LinearFormats = {GL_R8};
126 std::vector<GLenum> optionalRG8LinearFormats = {GL_RG8};
127 std::vector<GLenum> optionalBPTCLinearFormats = {GL_COMPRESSED_RGBA_BPTC_UNORM_EXT};
128
129 if (!FormatReinterpretationSupported(optionalLinearFormats, rendererVk, kNonLinearColorspace))
130 {
131 return false;
132 }
133
134 if (supportedExtensions.textureCompressionS3TCsRGB)
135 {
136 if (!FormatReinterpretationSupported(optionalS3TCLinearFormats, rendererVk,
137 kNonLinearColorspace))
138 {
139 return false;
140 }
141 }
142
143 if (supportedExtensions.sRGBR8EXT)
144 {
145 if (!FormatReinterpretationSupported(optionalR8LinearFormats, rendererVk,
146 kNonLinearColorspace))
147 {
148 return false;
149 }
150 }
151
152 if (supportedExtensions.sRGBRG8EXT)
153 {
154 if (!FormatReinterpretationSupported(optionalRG8LinearFormats, rendererVk,
155 kNonLinearColorspace))
156 {
157 return false;
158 }
159 }
160
161 if (supportedExtensions.textureCompressionBPTC)
162 {
163 if (!FormatReinterpretationSupported(optionalBPTCLinearFormats, rendererVk,
164 kNonLinearColorspace))
165 {
166 return false;
167 }
168 }
169
170 return true;
171 }
172
HasTexelBufferSupport(const RendererVk * rendererVk,GLenum formatGL)173 bool HasTexelBufferSupport(const RendererVk *rendererVk, GLenum formatGL)
174 {
175 const Format &formatVk = rendererVk->getFormat(formatGL);
176
177 return rendererVk->hasBufferFormatFeatureBits(
178 formatVk.actualBufferFormatID,
179 VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT);
180 }
181
HasTextureBufferSupport(const RendererVk * rendererVk)182 bool HasTextureBufferSupport(const RendererVk *rendererVk)
183 {
184 // The following formats don't have mandatory UNIFORM_TEXEL_BUFFER support in Vulkan.
185 //
186 // VK_FORMAT_R32G32B32_UINT
187 // VK_FORMAT_R32G32B32_SINT
188 // VK_FORMAT_R32G32B32_SFLOAT
189 //
190 // Additionally, the following formats don't have mandatory STORAGE_TEXEL_BUFFER support:
191 //
192 // VK_FORMAT_R8_UINT
193 // VK_FORMAT_R8_SINT
194 // VK_FORMAT_R8_UNORM
195 // VK_FORMAT_R8G8_UINT
196 // VK_FORMAT_R8G8_SINT
197 // VK_FORMAT_R8G8_UNORM
198 // VK_FORMAT_R16_UINT
199 // VK_FORMAT_R16_SINT
200 // VK_FORMAT_R16_SFLOAT
201 // VK_FORMAT_R16G16_UINT
202 // VK_FORMAT_R16G16_SINT
203 // VK_FORMAT_R16G16_SFLOAT
204 // VK_FORMAT_R32G32B32_UINT
205 // VK_FORMAT_R32G32B32_SINT
206 // VK_FORMAT_R32G32B32_SFLOAT
207 //
208 // The formats that have mandatory support for both features (and don't need to be checked) are:
209 //
210 // VK_FORMAT_R8G8B8A8_UINT
211 // VK_FORMAT_R8G8B8A8_SINT
212 // VK_FORMAT_R8G8B8A8_UNORM
213 // VK_FORMAT_R16G16B16A16_UINT
214 // VK_FORMAT_R16G16B16A16_SINT
215 // VK_FORMAT_R16G16B16A16_SFLOAT
216 // VK_FORMAT_R32_UINT
217 // VK_FORMAT_R32_SINT
218 // VK_FORMAT_R32_SFLOAT
219 // VK_FORMAT_R32G32_UINT
220 // VK_FORMAT_R32G32_SINT
221 // VK_FORMAT_R32G32_SFLOAT
222 // VK_FORMAT_R32G32B32A32_UINT
223 // VK_FORMAT_R32G32B32A32_SINT
224 // VK_FORMAT_R32G32B32A32_SFLOAT
225 //
226
227 const std::array<GLenum, 12> &optionalFormats = {
228 GL_R8, GL_R8I, GL_R8UI, GL_RG8, GL_RG8I, GL_RG8UI,
229 GL_R16F, GL_R16I, GL_R16UI, GL_RG16F, GL_RG16I, GL_RG16UI,
230 };
231
232 for (GLenum formatGL : optionalFormats)
233 {
234 if (!HasTexelBufferSupport(rendererVk, formatGL))
235 {
236 return false;
237 }
238 }
239
240 // TODO: RGB32 formats currently don't have STORAGE_TEXEL_BUFFER support on any known platform.
241 // Despite this limitation, we expose EXT_texture_buffer. http://anglebug.com/3573
242 if (rendererVk->getFeatures().exposeNonConformantExtensionsAndVersions.enabled)
243 {
244 return true;
245 }
246
247 const std::array<GLenum, 3> &optionalFormats2 = {
248 GL_RGB32F,
249 GL_RGB32I,
250 GL_RGB32UI,
251 };
252
253 for (GLenum formatGL : optionalFormats2)
254 {
255 if (!HasTexelBufferSupport(rendererVk, formatGL))
256 {
257 return false;
258 }
259 }
260
261 return true;
262 }
263
CanSupportYuvInternalFormat(const RendererVk * rendererVk)264 bool CanSupportYuvInternalFormat(const RendererVk *rendererVk)
265 {
266 // The following formats are not mandatory in Vulkan, even when VK_KHR_sampler_ycbcr_conversion
267 // is supported. GL_ANGLE_yuv_internal_format requires support for sampling only the
268 // 8-bit 2-plane YUV format (VK_FORMAT_G8_B8R8_2PLANE_420_UNORM), if the ICD supports that we
269 // can expose the extension.
270 //
271 // Various test cases need multiple YUV formats. It would be preferrable to have support for the
272 // 3 plane 8 bit YUV format (VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM) as well.
273
274 const Format &twoPlane8bitYuvFormat = rendererVk->getFormat(GL_G8_B8R8_2PLANE_420_UNORM_ANGLE);
275 bool twoPlane8bitYuvFormatSupported = rendererVk->hasImageFormatFeatureBits(
276 twoPlane8bitYuvFormat.actualImageFormatID, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT);
277
278 const Format &threePlane8bitYuvFormat =
279 rendererVk->getFormat(GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE);
280 bool threePlane8bitYuvFormatSupported = rendererVk->hasImageFormatFeatureBits(
281 threePlane8bitYuvFormat.actualImageFormatID, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT);
282
283 return twoPlane8bitYuvFormatSupported && threePlane8bitYuvFormatSupported;
284 }
285 } // namespace
286 } // namespace vk
287
288 template <typename LargerInt>
LimitToInt(const LargerInt physicalDeviceValue)289 GLint LimitToInt(const LargerInt physicalDeviceValue)
290 {
291 static_assert(sizeof(LargerInt) >= sizeof(int32_t), "Incorrect usage of LimitToInt");
292
293 // Limit to INT_MAX / 2 instead of INT_MAX. If the limit is queried as float, the imprecision
294 // in floating point can cause the value to exceed INT_MAX. This trips dEQP up.
295 return static_cast<GLint>(std::min(
296 physicalDeviceValue, static_cast<LargerInt>(std::numeric_limits<int32_t>::max() / 2)));
297 }
298
ensureCapsInitialized() const299 void RendererVk::ensureCapsInitialized() const
300 {
301 if (mCapsInitialized)
302 return;
303 mCapsInitialized = true;
304
305 ASSERT(mCurrentQueueFamilyIndex < mQueueFamilyProperties.size());
306 const VkQueueFamilyProperties &queueFamilyProperties =
307 mQueueFamilyProperties[mCurrentQueueFamilyIndex];
308 const VkPhysicalDeviceLimits &limitsVk = mPhysicalDeviceProperties.limits;
309
310 mNativeExtensions.setTextureExtensionSupport(mNativeTextureCaps);
311
312 // Enable GL_EXT_buffer_storage
313 mNativeExtensions.bufferStorageEXT = true;
314
315 // When ETC2/EAC formats are natively supported, enable ANGLE-specific extension string to
316 // expose them to WebGL. In other case, mark potentially-available ETC1 extension as emulated.
317 if ((mPhysicalDeviceFeatures.textureCompressionETC2 == VK_TRUE) &&
318 gl::DetermineCompressedTextureETCSupport(mNativeTextureCaps))
319 {
320 mNativeExtensions.compressedTextureETC = true;
321 }
322 else
323 {
324 mNativeLimitations.emulatedEtc1 = true;
325 }
326
327 // Vulkan doesn't support ASTC 3D block textures, which are required by
328 // GL_OES_texture_compression_astc.
329 mNativeExtensions.textureCompressionASTCOES = false;
330 // Vulkan does not support sliced 3D ASTC textures either.
331 mNativeExtensions.textureCompressionSliced3dASTCKHR = false;
332
333 // Vulkan doesn't guarantee HDR blocks decoding without VK_EXT_texture_compression_astc_hdr.
334 mNativeExtensions.textureCompressionASTCHDRKHR = false;
335
336 // Enable EXT_compressed_ETC1_RGB8_sub_texture
337 mNativeExtensions.compressedETC1RGB8SubTexture = mNativeExtensions.compressedETC1RGB8TextureOES;
338
339 // Enable this for simple buffer readback testing, but some functionality is missing.
340 // TODO(jmadill): Support full mapBufferRange extension.
341 mNativeExtensions.mapBufferOES = true;
342 mNativeExtensions.mapBufferRange = true;
343 mNativeExtensions.textureStorage = true;
344 mNativeExtensions.drawBuffers = true;
345 mNativeExtensions.fragDepth = true;
346 mNativeExtensions.framebufferBlitANGLE = true;
347 mNativeExtensions.framebufferMultisample = true;
348 mNativeExtensions.multisampledRenderToTexture =
349 getFeatures().enableMultisampledRenderToTexture.enabled;
350 mNativeExtensions.multisampledRenderToTexture2 =
351 getFeatures().enableMultisampledRenderToTexture.enabled;
352 mNativeExtensions.textureStorageMultisample2DArrayOES =
353 (limitsVk.standardSampleLocations == VK_TRUE);
354 mNativeExtensions.copyTexture = true;
355 mNativeExtensions.copyTexture3d = true;
356 mNativeExtensions.copyCompressedTexture = true;
357 mNativeExtensions.debugMarker = true;
358 mNativeExtensions.robustness =
359 !IsSwiftshader(mPhysicalDeviceProperties.vendorID, mPhysicalDeviceProperties.deviceID) &&
360 !IsARM(mPhysicalDeviceProperties.vendorID);
361 mNativeExtensions.discardFramebuffer = true;
362 mNativeExtensions.textureBorderClampOES = getFeatures().supportsCustomBorderColorEXT.enabled;
363 mNativeExtensions.textureBorderClampEXT = getFeatures().supportsCustomBorderColorEXT.enabled;
364 // Enable EXT_texture_type_2_10_10_10_REV
365 mNativeExtensions.textureFormat2101010REV = true;
366
367 // Enable ANGLE_base_vertex_base_instance
368 mNativeExtensions.baseVertexBaseInstance = true;
369
370 // Enable OES/EXT_draw_elements_base_vertex
371 mNativeExtensions.drawElementsBaseVertexOES = true;
372 mNativeExtensions.drawElementsBaseVertexEXT = true;
373
374 // Enable EXT_blend_minmax
375 mNativeExtensions.blendMinMax = true;
376
377 // Enable OES/EXT_draw_buffers_indexed
378 mNativeExtensions.drawBuffersIndexedOES = mPhysicalDeviceFeatures.independentBlend == VK_TRUE;
379 mNativeExtensions.drawBuffersIndexedEXT = mNativeExtensions.drawBuffersIndexedOES;
380
381 mNativeExtensions.eglImageOES = true;
382 mNativeExtensions.eglImageExternalOES = true;
383 mNativeExtensions.eglImageExternalWrapModesEXT = true;
384 mNativeExtensions.eglImageExternalEssl3OES = true;
385 mNativeExtensions.eglImageArray = true;
386 mNativeExtensions.memoryObject = true;
387 mNativeExtensions.memoryObjectFd = getFeatures().supportsExternalMemoryFd.enabled;
388 mNativeExtensions.memoryObjectFlagsANGLE = true;
389 mNativeExtensions.memoryObjectFuchsiaANGLE =
390 getFeatures().supportsExternalMemoryFuchsia.enabled;
391
392 mNativeExtensions.semaphore = true;
393 mNativeExtensions.semaphoreFd = getFeatures().supportsExternalSemaphoreFd.enabled;
394 mNativeExtensions.semaphoreFuchsiaANGLE =
395 getFeatures().supportsExternalSemaphoreFuchsia.enabled;
396
397 mNativeExtensions.vertexHalfFloatOES = true;
398
399 // Enabled in HW if VK_EXT_vertex_attribute_divisor available, otherwise emulated
400 mNativeExtensions.instancedArraysANGLE = true;
401 mNativeExtensions.instancedArraysEXT = true;
402
403 // Only expose robust buffer access if the physical device supports it.
404 mNativeExtensions.robustBufferAccessBehavior =
405 (mPhysicalDeviceFeatures.robustBufferAccess == VK_TRUE);
406
407 mNativeExtensions.eglSyncOES = true;
408
409 mNativeExtensions.vertexAttribType1010102OES = true;
410
411 // We use secondary command buffers almost everywhere and they require a feature to be
412 // able to execute in the presence of queries. As a result, we won't support queries
413 // unless that feature is available.
414 mNativeExtensions.occlusionQueryBoolean =
415 vk::CommandBuffer::SupportsQueries(mPhysicalDeviceFeatures);
416
417 // From the Vulkan specs:
418 // > The number of valid bits in a timestamp value is determined by the
419 // > VkQueueFamilyProperties::timestampValidBits property of the queue on which the timestamp is
420 // > written. Timestamps are supported on any queue which reports a non-zero value for
421 // > timestampValidBits via vkGetPhysicalDeviceQueueFamilyProperties.
422 mNativeExtensions.disjointTimerQuery = queueFamilyProperties.timestampValidBits > 0;
423 mNativeExtensions.queryCounterBitsTimeElapsed = queueFamilyProperties.timestampValidBits;
424 mNativeExtensions.queryCounterBitsTimestamp = queueFamilyProperties.timestampValidBits;
425
426 mNativeExtensions.textureFilterAnisotropic =
427 mPhysicalDeviceFeatures.samplerAnisotropy && limitsVk.maxSamplerAnisotropy > 1.0f;
428 mNativeExtensions.maxTextureAnisotropy =
429 mNativeExtensions.textureFilterAnisotropic ? limitsVk.maxSamplerAnisotropy : 0.0f;
430
431 // Vulkan natively supports non power-of-two textures
432 mNativeExtensions.textureNPOTOES = true;
433
434 mNativeExtensions.texture3DOES = true;
435
436 // Vulkan natively supports standard derivatives
437 mNativeExtensions.standardDerivativesOES = true;
438
439 // Vulkan natively supports texture LOD
440 mNativeExtensions.shaderTextureLOD = true;
441
442 // Vulkan natively supports noperspective interpolation
443 mNativeExtensions.noperspectiveInterpolationNV = true;
444
445 // Vulkan natively supports 32-bit indices, entry in kIndexTypeMap
446 mNativeExtensions.elementIndexUintOES = true;
447
448 mNativeExtensions.fboRenderMipmapOES = true;
449
450 // We support getting image data for Textures and Renderbuffers.
451 mNativeExtensions.getImageANGLE = true;
452
453 // Implemented in the translator
454 mNativeExtensions.shaderNonConstGlobalInitializersEXT = true;
455
456 // Implemented in the front end
457 mNativeExtensions.separateShaderObjects = true;
458
459 // Vulkan has no restrictions of the format of cubemaps, so if the proper formats are supported,
460 // creating a cube of any of these formats should be implicitly supported.
461 mNativeExtensions.depthTextureCubeMapOES =
462 mNativeExtensions.depthTextureOES && mNativeExtensions.packedDepthStencilOES;
463
464 // Vulkan natively supports format reinterpretation, but we still require support for all
465 // formats we may reinterpret to
466 mNativeExtensions.textureSRGBOverride =
467 vk::GetTextureSRGBOverrideSupport(this, mNativeExtensions);
468 mNativeExtensions.textureSRGBDecode = vk::GetTextureSRGBDecodeSupport(this);
469
470 // EXT_srgb_write_control requires image_format_list
471 mNativeExtensions.sRGBWriteControl = getFeatures().supportsImageFormatList.enabled;
472
473 // Vulkan natively supports io interface block.
474 mNativeExtensions.shaderIoBlocksOES = true;
475 mNativeExtensions.shaderIoBlocksEXT = true;
476
477 mNativeExtensions.gpuShader5EXT = vk::CanSupportGPUShader5EXT(mPhysicalDeviceFeatures);
478
479 mNativeExtensions.textureFilteringCHROMIUM = getFeatures().supportsFilteringPrecision.enabled;
480
481 // Only expose texture cubemap array if the physical device supports it.
482 mNativeExtensions.textureCubeMapArrayOES = getFeatures().supportsImageCubeArray.enabled;
483 mNativeExtensions.textureCubeMapArrayEXT = mNativeExtensions.textureCubeMapArrayOES;
484
485 mNativeExtensions.shadowSamplersEXT = true;
486
487 // Enable EXT_external_buffer on Andoid. External buffers are implemented using Android hadware
488 // buffer (struct AHardwareBuffer).
489 mNativeExtensions.externalBufferEXT = IsAndroid() && GetAndroidSDKVersion() >= 26;
490
491 // From the Vulkan specs:
492 // sampleRateShading specifies whether Sample Shading and multisample interpolation are
493 // supported. If this feature is not enabled, the sampleShadingEnable member of the
494 // VkPipelineMultisampleStateCreateInfo structure must be set to VK_FALSE and the
495 // minSampleShading member is ignored. This also specifies whether shader modules can declare
496 // the SampleRateShading capability
497 bool supportSampleRateShading = mPhysicalDeviceFeatures.sampleRateShading == VK_TRUE;
498 mNativeExtensions.sampleShadingOES = supportSampleRateShading;
499
500 // From the SPIR-V spec at 3.21. BuiltIn, SampleId and SamplePosition needs
501 // SampleRateShading. https://www.khronos.org/registry/spir-v/specs/unified1/SPIRV.html
502 // To replace non-constant index to constant 0 index, this extension assumes that ANGLE only
503 // supports the number of samples less than or equal to 32.
504 constexpr unsigned int kNotSupportedSampleCounts = VK_SAMPLE_COUNT_64_BIT;
505 mNativeExtensions.sampleVariablesOES =
506 supportSampleRateShading && vk_gl::GetMaxSampleCount(kNotSupportedSampleCounts) == 0;
507
508 // Enable EXT_unpack_subimage
509 mNativeExtensions.unpackSubimage = true;
510
511 // Enable NV_pack_subimage
512 mNativeExtensions.packSubimage = true;
513
514 mNativeCaps.minInterpolationOffset = limitsVk.minInterpolationOffset;
515 mNativeCaps.maxInterpolationOffset = limitsVk.maxInterpolationOffset;
516 mNativeCaps.subPixelInterpolationOffsetBits = limitsVk.subPixelInterpolationOffsetBits;
517
518 // From the Vulkan spec:
519 //
520 // > The values minInterpolationOffset and maxInterpolationOffset describe the closed interval
521 // > of supported interpolation offsets : [ minInterpolationOffset, maxInterpolationOffset ].
522 // > The ULP is determined by subPixelInterpolationOffsetBits. If
523 // > subPixelInterpolationOffsetBits is 4, this provides increments of(1 / 2^4) = 0.0625, and
524 // > thus the range of supported interpolation offsets would be[-0.5, 0.4375]
525 //
526 // OES_shader_multisample_interpolation requires a maximum value of -0.5 for
527 // MIN_FRAGMENT_INTERPOLATION_OFFSET_OES and minimum 0.5 for
528 // MAX_FRAGMENT_INTERPOLATION_OFFSET_OES. Vulkan has an identical limit for
529 // minInterpolationOffset, but its limit for maxInterpolationOffset is 0.5-(1/ULP).
530 // OES_shader_multisample_interpolation is therefore only supported if
531 // maxInterpolationOffset is at least 0.5.
532 //
533 // It's suspected that the GL spec is not as precise as Vulkan's in this regard and that the
534 // requirements really meant to match. The extension is exposed as non-conformant either way to
535 // increase testing coverage). Discussion with the GL working group ongoing at
536 // https://gitlab.khronos.org/opengl/API/-/issues/149
537 mNativeExtensions.multisampleInterpolationOES =
538 mNativeExtensions.sampleVariablesOES &&
539 (mNativeCaps.maxInterpolationOffset >= 0.5 ||
540 mFeatures.exposeNonConformantExtensionsAndVersions.enabled);
541
542 // https://vulkan.lunarg.com/doc/view/1.0.30.0/linux/vkspec.chunked/ch31s02.html
543 mNativeCaps.maxElementIndex = std::numeric_limits<GLuint>::max() - 1;
544 mNativeCaps.max3DTextureSize = LimitToInt(limitsVk.maxImageDimension3D);
545 mNativeCaps.max2DTextureSize =
546 std::min(limitsVk.maxFramebufferWidth, limitsVk.maxImageDimension2D);
547 mNativeCaps.maxArrayTextureLayers = LimitToInt(limitsVk.maxImageArrayLayers);
548 mNativeCaps.maxLODBias = limitsVk.maxSamplerLodBias;
549 mNativeCaps.maxCubeMapTextureSize = LimitToInt(limitsVk.maxImageDimensionCube);
550 mNativeCaps.maxRenderbufferSize =
551 std::min({limitsVk.maxImageDimension2D, limitsVk.maxFramebufferWidth,
552 limitsVk.maxFramebufferHeight});
553 mNativeCaps.minAliasedPointSize = std::max(1.0f, limitsVk.pointSizeRange[0]);
554 mNativeCaps.maxAliasedPointSize = limitsVk.pointSizeRange[1];
555
556 mNativeCaps.minAliasedLineWidth = 1.0f;
557 mNativeCaps.maxAliasedLineWidth = 1.0f;
558
559 mNativeCaps.maxDrawBuffers =
560 std::min(limitsVk.maxColorAttachments, limitsVk.maxFragmentOutputAttachments);
561 mNativeCaps.maxFramebufferWidth = LimitToInt(limitsVk.maxFramebufferWidth);
562 mNativeCaps.maxFramebufferHeight = LimitToInt(limitsVk.maxFramebufferHeight);
563 mNativeCaps.maxColorAttachments = LimitToInt(limitsVk.maxColorAttachments);
564 mNativeCaps.maxViewportWidth = LimitToInt(limitsVk.maxViewportDimensions[0]);
565 mNativeCaps.maxViewportHeight = LimitToInt(limitsVk.maxViewportDimensions[1]);
566 mNativeCaps.maxSampleMaskWords = LimitToInt(limitsVk.maxSampleMaskWords);
567 mNativeCaps.maxColorTextureSamples =
568 limitsVk.sampledImageColorSampleCounts & vk_gl::kSupportedSampleCounts;
569 mNativeCaps.maxDepthTextureSamples =
570 limitsVk.sampledImageDepthSampleCounts & vk_gl::kSupportedSampleCounts;
571 mNativeCaps.maxIntegerSamples =
572 limitsVk.sampledImageIntegerSampleCounts & vk_gl::kSupportedSampleCounts;
573
574 mNativeCaps.maxVertexAttributes = LimitToInt(limitsVk.maxVertexInputAttributes);
575 mNativeCaps.maxVertexAttribBindings = LimitToInt(limitsVk.maxVertexInputBindings);
576 // Offset and stride are stored as uint16_t in PackedAttribDesc.
577 mNativeCaps.maxVertexAttribRelativeOffset =
578 std::min((1u << kAttributeOffsetMaxBits) - 1, limitsVk.maxVertexInputAttributeOffset);
579 mNativeCaps.maxVertexAttribStride =
580 std::min(static_cast<uint32_t>(std::numeric_limits<uint16_t>::max()),
581 limitsVk.maxVertexInputBindingStride);
582
583 mNativeCaps.maxElementsIndices = std::numeric_limits<GLint>::max();
584 mNativeCaps.maxElementsVertices = std::numeric_limits<GLint>::max();
585
586 // Looks like all floats are IEEE according to the docs here:
587 // https://www.khronos.org/registry/vulkan/specs/1.0-wsi_extensions/html/vkspec.html#spirvenv-precision-operation
588 mNativeCaps.vertexHighpFloat.setIEEEFloat();
589 mNativeCaps.vertexMediumpFloat.setIEEEFloat();
590 mNativeCaps.vertexLowpFloat.setIEEEFloat();
591 mNativeCaps.fragmentHighpFloat.setIEEEFloat();
592 mNativeCaps.fragmentMediumpFloat.setIEEEFloat();
593 mNativeCaps.fragmentLowpFloat.setIEEEFloat();
594
595 // Can't find documentation on the int precision in Vulkan.
596 mNativeCaps.vertexHighpInt.setTwosComplementInt(32);
597 mNativeCaps.vertexMediumpInt.setTwosComplementInt(32);
598 mNativeCaps.vertexLowpInt.setTwosComplementInt(32);
599 mNativeCaps.fragmentHighpInt.setTwosComplementInt(32);
600 mNativeCaps.fragmentMediumpInt.setTwosComplementInt(32);
601 mNativeCaps.fragmentLowpInt.setTwosComplementInt(32);
602
603 // Compute shader limits.
604 mNativeCaps.maxComputeWorkGroupCount[0] = LimitToInt(limitsVk.maxComputeWorkGroupCount[0]);
605 mNativeCaps.maxComputeWorkGroupCount[1] = LimitToInt(limitsVk.maxComputeWorkGroupCount[1]);
606 mNativeCaps.maxComputeWorkGroupCount[2] = LimitToInt(limitsVk.maxComputeWorkGroupCount[2]);
607 mNativeCaps.maxComputeWorkGroupSize[0] = LimitToInt(limitsVk.maxComputeWorkGroupSize[0]);
608 mNativeCaps.maxComputeWorkGroupSize[1] = LimitToInt(limitsVk.maxComputeWorkGroupSize[1]);
609 mNativeCaps.maxComputeWorkGroupSize[2] = LimitToInt(limitsVk.maxComputeWorkGroupSize[2]);
610 mNativeCaps.maxComputeWorkGroupInvocations =
611 LimitToInt(limitsVk.maxComputeWorkGroupInvocations);
612 mNativeCaps.maxComputeSharedMemorySize = LimitToInt(limitsVk.maxComputeSharedMemorySize);
613
614 // TODO(lucferron): This is something we'll need to implement custom in the back-end.
615 // Vulkan doesn't do any waiting for you, our back-end code is going to manage sync objects,
616 // and we'll have to check that we've exceeded the max wait timeout. Also, this is ES 3.0 so
617 // we'll defer the implementation until we tackle the next version.
618 // mNativeCaps.maxServerWaitTimeout
619
620 GLuint maxUniformBlockSize = limitsVk.maxUniformBufferRange;
621
622 // Clamp the maxUniformBlockSize to 64KB (majority of devices support up to this size
623 // currently), on AMD the maxUniformBufferRange is near uint32_t max.
624 maxUniformBlockSize = std::min(0x10000u, maxUniformBlockSize);
625
626 const GLuint maxUniformVectors = maxUniformBlockSize / (sizeof(GLfloat) * kComponentsPerVector);
627 const GLuint maxUniformComponents = maxUniformVectors * kComponentsPerVector;
628
629 // Uniforms are implemented using a uniform buffer, so the max number of uniforms we can
630 // support is the max buffer range divided by the size of a single uniform (4X float).
631 mNativeCaps.maxVertexUniformVectors = maxUniformVectors;
632 mNativeCaps.maxFragmentUniformVectors = maxUniformVectors;
633 for (gl::ShaderType shaderType : gl::AllShaderTypes())
634 {
635 mNativeCaps.maxShaderUniformComponents[shaderType] = maxUniformComponents;
636 }
637 mNativeCaps.maxUniformLocations = maxUniformVectors;
638
639 // Every stage has 1 reserved uniform buffer for the default uniforms, and 1 for the driver
640 // uniforms.
641 constexpr uint32_t kTotalReservedPerStageUniformBuffers =
642 kReservedDriverUniformBindingCount + kReservedPerStageDefaultUniformBindingCount;
643 constexpr uint32_t kTotalReservedUniformBuffers =
644 kReservedDriverUniformBindingCount + kReservedDefaultUniformBindingCount;
645
646 const int32_t maxPerStageUniformBuffers = LimitToInt(
647 limitsVk.maxPerStageDescriptorUniformBuffers - kTotalReservedPerStageUniformBuffers);
648 const int32_t maxCombinedUniformBuffers =
649 LimitToInt(limitsVk.maxDescriptorSetUniformBuffers - kTotalReservedUniformBuffers);
650 for (gl::ShaderType shaderType : gl::AllShaderTypes())
651 {
652 mNativeCaps.maxShaderUniformBlocks[shaderType] = maxPerStageUniformBuffers;
653 }
654 mNativeCaps.maxCombinedUniformBlocks = maxCombinedUniformBuffers;
655
656 mNativeCaps.maxUniformBufferBindings = maxCombinedUniformBuffers;
657 mNativeCaps.maxUniformBlockSize = maxUniformBlockSize;
658 mNativeCaps.uniformBufferOffsetAlignment =
659 static_cast<GLint>(limitsVk.minUniformBufferOffsetAlignment);
660
661 // Note that Vulkan currently implements textures as combined image+samplers, so the limit is
662 // the minimum of supported samplers and sampled images.
663 const uint32_t maxPerStageTextures = std::min(limitsVk.maxPerStageDescriptorSamplers,
664 limitsVk.maxPerStageDescriptorSampledImages);
665 const uint32_t maxCombinedTextures =
666 std::min(limitsVk.maxDescriptorSetSamplers, limitsVk.maxDescriptorSetSampledImages);
667 for (gl::ShaderType shaderType : gl::AllShaderTypes())
668 {
669 mNativeCaps.maxShaderTextureImageUnits[shaderType] = LimitToInt(maxPerStageTextures);
670 }
671 mNativeCaps.maxCombinedTextureImageUnits = LimitToInt(maxCombinedTextures);
672
673 uint32_t maxPerStageStorageBuffers = limitsVk.maxPerStageDescriptorStorageBuffers;
674 uint32_t maxVertexStageStorageBuffers = maxPerStageStorageBuffers;
675 uint32_t maxCombinedStorageBuffers = limitsVk.maxDescriptorSetStorageBuffers;
676
677 // A number of storage buffer slots are used in the vertex shader to emulate transform feedback.
678 // Note that Vulkan requires maxPerStageDescriptorStorageBuffers to be at least 4 (i.e. the same
679 // as gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS).
680 // TODO(syoussefi): This should be conditioned to transform feedback extension not being
681 // present. http://anglebug.com/3206.
682 // TODO(syoussefi): If geometry shader is supported, emulation will be done at that stage, and
683 // so the reserved storage buffers should be accounted in that stage. http://anglebug.com/3606
684 static_assert(
685 gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS == 4,
686 "Limit to ES2.0 if supported SSBO count < supporting transform feedback buffer count");
687 if (mPhysicalDeviceFeatures.vertexPipelineStoresAndAtomics)
688 {
689 ASSERT(maxVertexStageStorageBuffers >= gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS);
690 maxVertexStageStorageBuffers -= gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS;
691 maxCombinedStorageBuffers -= gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS;
692
693 // Cap the per-stage limit of the other stages to the combined limit, in case the combined
694 // limit is now lower than that.
695 maxPerStageStorageBuffers = std::min(maxPerStageStorageBuffers, maxCombinedStorageBuffers);
696 }
697
698 // Reserve up to IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS storage buffers in the fragment and
699 // compute stages for atomic counters. This is only possible if the number of per-stage storage
700 // buffers is greater than 4, which is the required GLES minimum for compute.
701 //
702 // For each stage, we'll either not support atomic counter buffers, or support exactly
703 // IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS. This is due to restrictions in the shader
704 // translator where we can't know how many atomic counter buffers we would really need after
705 // linking so we can't create a packed buffer array.
706 //
707 // For the vertex stage, we could support atomic counters without storage buffers, but that's
708 // likely not very useful, so we use the same limit (4 + MAX_ATOMIC_COUNTER_BUFFERS) for the
709 // vertex stage to determine if we would want to add support for atomic counter buffers.
710 constexpr uint32_t kMinimumStorageBuffersForAtomicCounterBufferSupport =
711 gl::limits::kMinimumComputeStorageBuffers +
712 gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS;
713 uint32_t maxVertexStageAtomicCounterBuffers = 0;
714 uint32_t maxPerStageAtomicCounterBuffers = 0;
715 uint32_t maxCombinedAtomicCounterBuffers = 0;
716
717 if (maxPerStageStorageBuffers >= kMinimumStorageBuffersForAtomicCounterBufferSupport)
718 {
719 maxPerStageAtomicCounterBuffers = gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS;
720 maxCombinedAtomicCounterBuffers = gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS;
721 }
722
723 if (maxVertexStageStorageBuffers >= kMinimumStorageBuffersForAtomicCounterBufferSupport)
724 {
725 maxVertexStageAtomicCounterBuffers = gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS;
726 }
727
728 maxVertexStageStorageBuffers -= maxVertexStageAtomicCounterBuffers;
729 maxPerStageStorageBuffers -= maxPerStageAtomicCounterBuffers;
730 maxCombinedStorageBuffers -= maxCombinedAtomicCounterBuffers;
731
732 mNativeCaps.maxShaderStorageBlocks[gl::ShaderType::Vertex] =
733 mPhysicalDeviceFeatures.vertexPipelineStoresAndAtomics
734 ? LimitToInt(maxVertexStageStorageBuffers)
735 : 0;
736 mNativeCaps.maxShaderStorageBlocks[gl::ShaderType::Fragment] =
737 mPhysicalDeviceFeatures.fragmentStoresAndAtomics ? LimitToInt(maxPerStageStorageBuffers)
738 : 0;
739 mNativeCaps.maxShaderStorageBlocks[gl::ShaderType::Compute] =
740 LimitToInt(maxPerStageStorageBuffers);
741 mNativeCaps.maxCombinedShaderStorageBlocks = LimitToInt(maxCombinedStorageBuffers);
742
743 mNativeCaps.maxShaderStorageBufferBindings = LimitToInt(maxCombinedStorageBuffers);
744 mNativeCaps.maxShaderStorageBlockSize = limitsVk.maxStorageBufferRange;
745 mNativeCaps.shaderStorageBufferOffsetAlignment =
746 LimitToInt(static_cast<uint32_t>(limitsVk.minStorageBufferOffsetAlignment));
747
748 mNativeCaps.maxShaderAtomicCounterBuffers[gl::ShaderType::Vertex] =
749 mPhysicalDeviceFeatures.vertexPipelineStoresAndAtomics
750 ? LimitToInt(maxVertexStageAtomicCounterBuffers)
751 : 0;
752 mNativeCaps.maxShaderAtomicCounterBuffers[gl::ShaderType::Fragment] =
753 mPhysicalDeviceFeatures.fragmentStoresAndAtomics
754 ? LimitToInt(maxPerStageAtomicCounterBuffers)
755 : 0;
756 mNativeCaps.maxShaderAtomicCounterBuffers[gl::ShaderType::Compute] =
757 LimitToInt(maxPerStageAtomicCounterBuffers);
758 mNativeCaps.maxCombinedAtomicCounterBuffers = LimitToInt(maxCombinedAtomicCounterBuffers);
759
760 mNativeCaps.maxAtomicCounterBufferBindings = LimitToInt(maxCombinedAtomicCounterBuffers);
761 // Emulated as storage buffers, atomic counter buffers have the same size limit. However, the
762 // limit is a signed integer and values above int max will end up as a negative size.
763 mNativeCaps.maxAtomicCounterBufferSize = LimitToInt(limitsVk.maxStorageBufferRange);
764
765 // There is no particular limit to how many atomic counters there can be, other than the size of
766 // a storage buffer. We nevertheless limit this to something reasonable (4096 arbitrarily).
767 const int32_t maxAtomicCounters =
768 std::min<int32_t>(4096, limitsVk.maxStorageBufferRange / sizeof(uint32_t));
769 for (gl::ShaderType shaderType : gl::AllShaderTypes())
770 {
771 mNativeCaps.maxShaderAtomicCounters[shaderType] = maxAtomicCounters;
772 }
773
774 // Set maxShaderAtomicCounters to zero if atomic is not supported.
775 if (!mPhysicalDeviceFeatures.vertexPipelineStoresAndAtomics)
776 {
777 mNativeCaps.maxShaderAtomicCounters[gl::ShaderType::Vertex] = 0;
778 }
779 if (!mPhysicalDeviceFeatures.fragmentStoresAndAtomics)
780 {
781 mNativeCaps.maxShaderAtomicCounters[gl::ShaderType::Fragment] = 0;
782 }
783
784 mNativeCaps.maxCombinedAtomicCounters = maxAtomicCounters;
785
786 // GL Images correspond to Vulkan Storage Images.
787 const int32_t maxPerStageImages = LimitToInt(limitsVk.maxPerStageDescriptorStorageImages);
788 const int32_t maxCombinedImages = LimitToInt(limitsVk.maxDescriptorSetStorageImages);
789 const int32_t maxVertexPipelineImages =
790 mPhysicalDeviceFeatures.vertexPipelineStoresAndAtomics ? maxPerStageImages : 0;
791
792 mNativeCaps.maxShaderImageUniforms[gl::ShaderType::Vertex] = maxVertexPipelineImages;
793 mNativeCaps.maxShaderImageUniforms[gl::ShaderType::TessControl] = maxVertexPipelineImages;
794 mNativeCaps.maxShaderImageUniforms[gl::ShaderType::TessEvaluation] = maxVertexPipelineImages;
795 mNativeCaps.maxShaderImageUniforms[gl::ShaderType::Geometry] = maxVertexPipelineImages;
796 mNativeCaps.maxShaderImageUniforms[gl::ShaderType::Fragment] =
797 mPhysicalDeviceFeatures.fragmentStoresAndAtomics ? maxPerStageImages : 0;
798 mNativeCaps.maxShaderImageUniforms[gl::ShaderType::Compute] = maxPerStageImages;
799
800 mNativeCaps.maxCombinedImageUniforms = maxCombinedImages;
801 mNativeCaps.maxImageUnits = maxCombinedImages;
802
803 mNativeCaps.minProgramTexelOffset = limitsVk.minTexelOffset;
804 mNativeCaps.maxProgramTexelOffset = limitsVk.maxTexelOffset;
805 mNativeCaps.minProgramTextureGatherOffset = limitsVk.minTexelGatherOffset;
806 mNativeCaps.maxProgramTextureGatherOffset = limitsVk.maxTexelGatherOffset;
807
808 // There is no additional limit to the combined number of components. We can have up to a
809 // maximum number of uniform buffers, each having the maximum number of components. Note that
810 // this limit includes both components in and out of uniform buffers.
811 //
812 // This value is limited to INT_MAX to avoid overflow when queried from glGetIntegerv().
813 const uint64_t maxCombinedUniformComponents =
814 std::min<uint64_t>(static_cast<uint64_t>(maxPerStageUniformBuffers +
815 kReservedPerStageDefaultUniformBindingCount) *
816 maxUniformComponents,
817 std::numeric_limits<GLint>::max());
818 for (gl::ShaderType shaderType : gl::AllShaderTypes())
819 {
820 mNativeCaps.maxCombinedShaderUniformComponents[shaderType] = maxCombinedUniformComponents;
821 }
822
823 // Total number of resources available to the user are as many as Vulkan allows minus everything
824 // that ANGLE uses internally. That is, one dynamic uniform buffer used per stage for default
825 // uniforms and a single dynamic uniform buffer for driver uniforms. Additionally, Vulkan uses
826 // up to IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS + 1 buffers for transform feedback (Note:
827 // +1 is for the "counter" buffer of transform feedback, which will be necessary for transform
828 // feedback extension and ES3.2 transform feedback emulation, but is not yet present).
829 constexpr uint32_t kReservedPerStageUniformBufferCount = 1;
830 constexpr uint32_t kReservedPerStageBindingCount =
831 kReservedDriverUniformBindingCount + kReservedPerStageUniformBufferCount +
832 gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS + 1;
833
834 // Note: maxPerStageResources is required to be at least the sum of per stage UBOs, SSBOs etc
835 // which total a minimum of 44 resources, so no underflow is possible here. Limit the total
836 // number of resources reported by Vulkan to 2 billion though to avoid seeing negative numbers
837 // in applications that take the value as signed int (including dEQP).
838 const uint32_t maxPerStageResources = limitsVk.maxPerStageResources;
839 mNativeCaps.maxCombinedShaderOutputResources =
840 LimitToInt(maxPerStageResources - kReservedPerStageBindingCount);
841
842 // Reserve 1 extra varying for ANGLEPosition when GLLineRasterization is enabled
843 constexpr GLint kReservedVaryingComponentsForGLLineRasterization = 4;
844 // Reserve 1 extra varying for transform feedback capture of gl_Position.
845 constexpr GLint kReservedVaryingComponentsForTransformFeedbackExtension = 4;
846
847 GLint reservedVaryingComponentCount = 0;
848
849 if (getFeatures().basicGLLineRasterization.enabled)
850 {
851 reservedVaryingComponentCount += kReservedVaryingComponentsForGLLineRasterization;
852 }
853 if (getFeatures().supportsTransformFeedbackExtension.enabled)
854 {
855 reservedVaryingComponentCount += kReservedVaryingComponentsForTransformFeedbackExtension;
856 }
857
858 // The max varying vectors should not include gl_Position.
859 // The gles2.0 section 2.10 states that "gl_Position is not a varying variable and does
860 // not count against this limit.", but the Vulkan spec has no such mention in its Built-in
861 // vars section. It is implicit that we need to actually reserve it for Vulkan in that case.
862 //
863 // Note that this exception for gl_Position does not apply to MAX_VERTEX_OUTPUT_COMPONENTS and
864 // similar limits.
865 const GLint reservedVaryingVectorCount = reservedVaryingComponentCount / 4 + 1;
866
867 const GLint maxVaryingCount =
868 std::min(limitsVk.maxVertexOutputComponents, limitsVk.maxFragmentInputComponents);
869 mNativeCaps.maxVaryingVectors =
870 LimitToInt((maxVaryingCount / kComponentsPerVector) - reservedVaryingVectorCount);
871 mNativeCaps.maxVertexOutputComponents =
872 LimitToInt(limitsVk.maxVertexOutputComponents) - reservedVaryingComponentCount;
873 mNativeCaps.maxFragmentInputComponents =
874 LimitToInt(limitsVk.maxFragmentInputComponents) - reservedVaryingComponentCount;
875
876 mNativeCaps.maxTransformFeedbackInterleavedComponents =
877 gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS;
878 mNativeCaps.maxTransformFeedbackSeparateAttributes =
879 gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS;
880 mNativeCaps.maxTransformFeedbackSeparateComponents =
881 gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS;
882
883 mNativeCaps.minProgramTexelOffset = limitsVk.minTexelOffset;
884 mNativeCaps.maxProgramTexelOffset = LimitToInt(limitsVk.maxTexelOffset);
885
886 const uint32_t sampleCounts =
887 limitsVk.framebufferColorSampleCounts & limitsVk.framebufferDepthSampleCounts &
888 limitsVk.framebufferStencilSampleCounts & vk_gl::kSupportedSampleCounts;
889
890 mNativeCaps.maxSamples = LimitToInt(vk_gl::GetMaxSampleCount(sampleCounts));
891 mNativeCaps.maxFramebufferSamples = mNativeCaps.maxSamples;
892
893 mNativeCaps.subPixelBits = limitsVk.subPixelPrecisionBits;
894
895 // Important games are not checking supported extensions properly, and are confusing the
896 // GL_EXT_shader_framebuffer_fetch_non_coherent as the GL_EXT_shader_framebuffer_fetch
897 // extension. Therefore, don't enable the extension on Arm and Qualcomm.
898 // https://issuetracker.google.com/issues/186643966
899 if (!(IsARM(mPhysicalDeviceProperties.vendorID) ||
900 IsQualcomm(mPhysicalDeviceProperties.vendorID)))
901 {
902 // Enable GL_EXT_shader_framebuffer_fetch_non_coherent
903 // For supporting this extension, gl::IMPLEMENTATION_MAX_DRAW_BUFFERS is used.
904 mNativeExtensions.shaderFramebufferFetchNonCoherentEXT =
905 mNativeCaps.maxDrawBuffers >= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS;
906 }
907
908 // Enable Program Binary extension.
909 mNativeExtensions.getProgramBinaryOES = true;
910 mNativeCaps.programBinaryFormats.push_back(GL_PROGRAM_BINARY_ANGLE);
911
912 // Enable GL_NV_pixel_buffer_object extension.
913 mNativeExtensions.pixelBufferObjectNV = true;
914
915 // Enable GL_NV_fence extension.
916 mNativeExtensions.fenceNV = true;
917
918 // Enable GL_EXT_copy_image
919 mNativeExtensions.copyImageEXT = true;
920
921 // GL_EXT_clip_control
922 mNativeExtensions.clipControlEXT = true;
923
924 // Enable GL_EXT_texture_buffer and OES variant. Nearly all formats required for this extension
925 // are also required to have the UNIFORM_TEXEL_BUFFER feature bit in Vulkan, except for
926 // R32G32B32_SFLOAT/UINT/SINT which are optional. For many formats, the STORAGE_TEXEL_BUFFER
927 // feature is optional though. This extension is exposed only if the formats specified in
928 // EXT_texture_buffer support the necessary feature bits.
929 if (vk::HasTextureBufferSupport(this))
930 {
931 mNativeExtensions.textureBufferOES = true;
932 mNativeExtensions.textureBufferEXT = true;
933 mNativeCaps.maxTextureBufferSize = LimitToInt(limitsVk.maxTexelBufferElements);
934 mNativeCaps.textureBufferOffsetAlignment =
935 LimitToInt(limitsVk.minTexelBufferOffsetAlignment);
936 }
937
938 // Atomic image operations in the vertex and fragment shaders require the
939 // vertexPipelineStoresAndAtomics and fragmentStoresAndAtomics Vulkan features respectively.
940 // If either of these features is not present, the number of image uniforms for that stage is
941 // advertized as zero, so image atomic operations support can be agnostic of shader stages.
942 //
943 // GL_OES_shader_image_atomic requires that image atomic functions have support for r32i and
944 // r32ui formats. These formats have mandatory support for STORAGE_IMAGE_ATOMIC and
945 // STORAGE_TEXEL_BUFFER_ATOMIC features in Vulkan. Additionally, it requires that
946 // imageAtomicExchange supports r32f, which is emulated in ANGLE transforming the shader to
947 // expect r32ui instead.
948 mNativeExtensions.shaderImageAtomicOES = true;
949
950 // Geometry shaders are required for ES 3.2.
951 // We don't support GS when we are emulating line raster due to the tricky position varying.
952 if (mPhysicalDeviceFeatures.geometryShader && !mFeatures.basicGLLineRasterization.enabled)
953 {
954 // TODO: geometry shader support is incomplete. http://anglebug.com/3571
955 bool geometryShader = mFeatures.supportsTransformFeedbackExtension.enabled &&
956 mFeatures.exposeNonConformantExtensionsAndVersions.enabled;
957 mNativeExtensions.geometryShaderEXT = geometryShader;
958 mNativeExtensions.geometryShaderOES = geometryShader;
959 mNativeCaps.maxFramebufferLayers = LimitToInt(limitsVk.maxFramebufferLayers);
960
961 // If the provoking vertex feature is enabled, angle specifies to use
962 // the "last" convention in order to match GL behavior. Otherwise, use
963 // "first" as vulkan follows this convention for provoking vertex.
964 mNativeCaps.layerProvokingVertex = (mFeatures.provokingVertex.enabled)
965 ? GL_LAST_VERTEX_CONVENTION_EXT
966 : GL_FIRST_VERTEX_CONVENTION_EXT;
967
968 mNativeCaps.maxGeometryInputComponents =
969 LimitToInt(limitsVk.maxGeometryInputComponents) - reservedVaryingComponentCount;
970 mNativeCaps.maxGeometryOutputComponents =
971 LimitToInt(limitsVk.maxGeometryOutputComponents) - reservedVaryingComponentCount;
972 mNativeCaps.maxGeometryOutputVertices = LimitToInt(limitsVk.maxGeometryOutputVertices);
973 mNativeCaps.maxGeometryTotalOutputComponents =
974 LimitToInt(limitsVk.maxGeometryTotalOutputComponents);
975 mNativeCaps.maxShaderStorageBlocks[gl::ShaderType::Geometry] =
976 mNativeCaps.maxCombinedShaderOutputResources;
977 mNativeCaps.maxShaderAtomicCounterBuffers[gl::ShaderType::Geometry] =
978 maxCombinedAtomicCounterBuffers;
979 mNativeCaps.maxGeometryShaderInvocations =
980 LimitToInt(limitsVk.maxGeometryShaderInvocations);
981 }
982
983 // We don't support TS when we are emulating line raster due to the tricky position varying.
984 if (mPhysicalDeviceFeatures.tessellationShader && !mFeatures.basicGLLineRasterization.enabled)
985 {
986 constexpr uint32_t kReservedTessellationDefaultUniformBindingCount = 2;
987
988 // TODO: tessellation shader support is incomplete. http://anglebug.com/3572
989 mNativeExtensions.tessellationShaderEXT =
990 mFeatures.supportsTransformFeedbackExtension.enabled &&
991 mFeatures.exposeNonConformantExtensionsAndVersions.enabled;
992 mNativeCaps.maxPatchVertices = LimitToInt(limitsVk.maxTessellationPatchSize);
993 mNativeCaps.maxTessPatchComponents =
994 LimitToInt(limitsVk.maxTessellationControlPerPatchOutputComponents);
995 mNativeCaps.maxTessGenLevel = LimitToInt(limitsVk.maxTessellationGenerationLevel);
996
997 mNativeCaps.maxTessControlInputComponents =
998 LimitToInt(limitsVk.maxTessellationControlPerVertexInputComponents);
999 mNativeCaps.maxTessControlOutputComponents =
1000 LimitToInt(limitsVk.maxTessellationControlPerVertexOutputComponents);
1001 mNativeCaps.maxTessControlTotalOutputComponents =
1002 LimitToInt(limitsVk.maxTessellationControlTotalOutputComponents);
1003 mNativeCaps.maxTessEvaluationInputComponents =
1004 LimitToInt(limitsVk.maxTessellationEvaluationInputComponents);
1005 mNativeCaps.maxTessEvaluationOutputComponents =
1006 LimitToInt(limitsVk.maxTessellationEvaluationOutputComponents);
1007
1008 // There is 1 default uniform binding used per tessellation stages.
1009 mNativeCaps.maxCombinedUniformBlocks = LimitToInt(
1010 mNativeCaps.maxCombinedUniformBlocks + kReservedTessellationDefaultUniformBindingCount);
1011 mNativeCaps.maxUniformBufferBindings = LimitToInt(
1012 mNativeCaps.maxUniformBufferBindings + kReservedTessellationDefaultUniformBindingCount);
1013
1014 mNativeCaps.maxShaderStorageBlocks[gl::ShaderType::TessControl] =
1015 mNativeCaps.maxCombinedShaderOutputResources;
1016 mNativeCaps.maxShaderAtomicCounterBuffers[gl::ShaderType::TessControl] =
1017 maxCombinedAtomicCounterBuffers;
1018
1019 mNativeCaps.maxShaderStorageBlocks[gl::ShaderType::TessEvaluation] =
1020 mNativeCaps.maxCombinedShaderOutputResources;
1021 mNativeCaps.maxShaderAtomicCounterBuffers[gl::ShaderType::TessEvaluation] =
1022 maxCombinedAtomicCounterBuffers;
1023 }
1024
1025 // GL_APPLE_clip_distance/GL_EXT_clip_cull_distance
1026 // From the EXT_clip_cull_distance extension spec:
1027 //
1028 // > Modify Section 7.2, "Built-In Constants" (p. 126)
1029 // >
1030 // > const mediump int gl_MaxClipDistances = 8;
1031 // > const mediump int gl_MaxCullDistances = 8;
1032 // > const mediump int gl_MaxCombinedClipAndCullDistances = 8;
1033 constexpr uint32_t kMaxClipDistancePerSpec = 8;
1034 constexpr uint32_t kMaxCullDistancePerSpec = 8;
1035 constexpr uint32_t kMaxCombinedClipAndCullDistancePerSpec = 8;
1036
1037 // TODO: http://anglebug.com/5466
1038 // After implementing EXT_geometry_shader, EXT_clip_cull_distance should be additionally
1039 // implemented to support the geometry shader. Until then, EXT_clip_cull_distance is enabled
1040 // only in the experimental cases.
1041 if (mPhysicalDeviceFeatures.shaderClipDistance &&
1042 limitsVk.maxClipDistances >= kMaxClipDistancePerSpec)
1043 {
1044 mNativeExtensions.clipDistanceAPPLE = true;
1045 mNativeCaps.maxClipDistances =
1046 std::min<GLuint>(limitsVk.maxClipDistances, gl::IMPLEMENTATION_MAX_CLIP_DISTANCES);
1047
1048 if (mPhysicalDeviceFeatures.shaderCullDistance &&
1049 limitsVk.maxCullDistances >= kMaxCullDistancePerSpec &&
1050 limitsVk.maxCombinedClipAndCullDistances >= kMaxCombinedClipAndCullDistancePerSpec)
1051 {
1052 mNativeExtensions.clipCullDistanceEXT = true;
1053 mNativeCaps.maxCullDistances = limitsVk.maxCullDistances;
1054 mNativeCaps.maxCombinedClipAndCullDistances = limitsVk.maxCombinedClipAndCullDistances;
1055 }
1056 }
1057
1058 // GL_EXT_blend_func_extended
1059 mNativeExtensions.blendFuncExtended = (mPhysicalDeviceFeatures.dualSrcBlend == VK_TRUE);
1060 mNativeExtensions.maxDualSourceDrawBuffers = LimitToInt(limitsVk.maxFragmentDualSrcAttachments);
1061
1062 // GL_ANGLE_relaxed_vertex_attribute_type
1063 mNativeExtensions.relaxedVertexAttributeTypeANGLE = true;
1064
1065 // GL_OVR_multiview*. Bresenham line emulation does not work with multiview. There's no
1066 // limitation in Vulkan to restrict an application to multiview 1.
1067 mNativeExtensions.multiview =
1068 mMultiviewFeatures.multiview && mFeatures.bresenhamLineRasterization.enabled;
1069 mNativeExtensions.multiview2 = mNativeExtensions.multiview;
1070 mNativeExtensions.maxViews = mMultiviewProperties.maxMultiviewViewCount;
1071
1072 // GL_ANGLE_yuv_internal_format
1073 mNativeExtensions.yuvInternalFormatANGLE =
1074 getFeatures().supportsYUVSamplerConversion.enabled && vk::CanSupportYuvInternalFormat(this);
1075 }
1076
1077 namespace vk
1078 {
1079
CanSupportGPUShader5EXT(const VkPhysicalDeviceFeatures & features)1080 bool CanSupportGPUShader5EXT(const VkPhysicalDeviceFeatures &features)
1081 {
1082 // We use the following Vulkan features to implement EXT_gpu_shader5:
1083 // - shaderImageGatherExtended: textureGatherOffset with non-constant offset and
1084 // textureGatherOffsets family of functions.
1085 // - shaderSampledImageArrayDynamicIndexing and shaderUniformBufferArrayDynamicIndexing:
1086 // dynamically uniform indices for samplers and uniform buffers.
1087 return features.shaderImageGatherExtended && features.shaderSampledImageArrayDynamicIndexing &&
1088 features.shaderUniformBufferArrayDynamicIndexing;
1089 }
1090
1091 } // namespace vk
1092
1093 namespace egl_vk
1094 {
1095
1096 namespace
1097 {
1098
ComputeMaximumPBufferPixels(const VkPhysicalDeviceProperties & physicalDeviceProperties)1099 EGLint ComputeMaximumPBufferPixels(const VkPhysicalDeviceProperties &physicalDeviceProperties)
1100 {
1101 // EGLints are signed 32-bit integers, it's fairly easy to overflow them, especially since
1102 // Vulkan's minimum guaranteed VkImageFormatProperties::maxResourceSize is 2^31 bytes.
1103 constexpr uint64_t kMaxValueForEGLint =
1104 static_cast<uint64_t>(std::numeric_limits<EGLint>::max());
1105
1106 // TODO(geofflang): Compute the maximum size of a pbuffer by using the maxResourceSize result
1107 // from vkGetPhysicalDeviceImageFormatProperties for both the color and depth stencil format and
1108 // the exact image creation parameters that would be used to create the pbuffer. Because it is
1109 // always safe to return out-of-memory errors on pbuffer allocation, it's fine to simply return
1110 // the number of pixels in a max width by max height pbuffer for now. http://anglebug.com/2622
1111
1112 // Storing the result of squaring a 32-bit unsigned int in a 64-bit unsigned int is safe.
1113 static_assert(std::is_same<decltype(physicalDeviceProperties.limits.maxImageDimension2D),
1114 uint32_t>::value,
1115 "physicalDeviceProperties.limits.maxImageDimension2D expected to be a uint32_t.");
1116 const uint64_t maxDimensionsSquared =
1117 static_cast<uint64_t>(physicalDeviceProperties.limits.maxImageDimension2D) *
1118 static_cast<uint64_t>(physicalDeviceProperties.limits.maxImageDimension2D);
1119
1120 return static_cast<EGLint>(std::min(maxDimensionsSquared, kMaxValueForEGLint));
1121 }
1122
1123 // Generates a basic config for a combination of color format, depth stencil format and sample
1124 // count.
GenerateDefaultConfig(DisplayVk * display,const gl::InternalFormat & colorFormat,const gl::InternalFormat & depthStencilFormat,EGLint sampleCount)1125 egl::Config GenerateDefaultConfig(DisplayVk *display,
1126 const gl::InternalFormat &colorFormat,
1127 const gl::InternalFormat &depthStencilFormat,
1128 EGLint sampleCount)
1129 {
1130 const RendererVk *renderer = display->getRenderer();
1131
1132 const VkPhysicalDeviceProperties &physicalDeviceProperties =
1133 renderer->getPhysicalDeviceProperties();
1134 gl::Version maxSupportedESVersion = renderer->getMaxSupportedESVersion();
1135
1136 // ES3 features are required to emulate ES1
1137 EGLint es1Support = (maxSupportedESVersion.major >= 3 ? EGL_OPENGL_ES_BIT : 0);
1138 EGLint es2Support = (maxSupportedESVersion.major >= 2 ? EGL_OPENGL_ES2_BIT : 0);
1139 EGLint es3Support = (maxSupportedESVersion.major >= 3 ? EGL_OPENGL_ES3_BIT : 0);
1140
1141 egl::Config config;
1142
1143 config.renderTargetFormat = colorFormat.internalFormat;
1144 config.depthStencilFormat = depthStencilFormat.internalFormat;
1145 config.bufferSize = colorFormat.pixelBytes * 8;
1146 config.redSize = colorFormat.redBits;
1147 config.greenSize = colorFormat.greenBits;
1148 config.blueSize = colorFormat.blueBits;
1149 config.alphaSize = colorFormat.alphaBits;
1150 config.alphaMaskSize = 0;
1151 config.bindToTextureRGB = colorFormat.format == GL_RGB;
1152 config.bindToTextureRGBA = colorFormat.format == GL_RGBA || colorFormat.format == GL_BGRA_EXT;
1153 config.colorBufferType = EGL_RGB_BUFFER;
1154 config.configCaveat = GetConfigCaveat(colorFormat.internalFormat);
1155 config.conformant = es1Support | es2Support | es3Support;
1156 config.depthSize = depthStencilFormat.depthBits;
1157 config.stencilSize = depthStencilFormat.stencilBits;
1158 config.level = 0;
1159 config.matchNativePixmap = EGL_NONE;
1160 config.maxPBufferWidth = physicalDeviceProperties.limits.maxImageDimension2D;
1161 config.maxPBufferHeight = physicalDeviceProperties.limits.maxImageDimension2D;
1162 config.maxPBufferPixels = ComputeMaximumPBufferPixels(physicalDeviceProperties);
1163 config.maxSwapInterval = 1;
1164 config.minSwapInterval = 0;
1165 config.nativeRenderable = EGL_TRUE;
1166 config.nativeVisualID = static_cast<EGLint>(GetNativeVisualID(colorFormat));
1167 config.nativeVisualType = EGL_NONE;
1168 config.renderableType = es1Support | es2Support | es3Support;
1169 config.sampleBuffers = (sampleCount > 0) ? 1 : 0;
1170 config.samples = sampleCount;
1171 config.surfaceType = EGL_WINDOW_BIT | EGL_PBUFFER_BIT;
1172 // Vulkan surfaces use a different origin than OpenGL, always prefer to be flipped vertically if
1173 // possible.
1174 config.optimalOrientation = EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE;
1175 config.transparentType = EGL_NONE;
1176 config.transparentRedValue = 0;
1177 config.transparentGreenValue = 0;
1178 config.transparentBlueValue = 0;
1179 config.colorComponentType =
1180 gl_egl::GLComponentTypeToEGLColorComponentType(colorFormat.componentType);
1181
1182 // Vulkan always supports off-screen rendering. Check the config with display to see if it can
1183 // also have window support. If not, the following call should automatically remove
1184 // EGL_WINDOW_BIT.
1185 display->checkConfigSupport(&config);
1186
1187 return config;
1188 }
1189
1190 } // anonymous namespace
1191
GenerateConfigs(const GLenum * colorFormats,size_t colorFormatsCount,const GLenum * depthStencilFormats,size_t depthStencilFormatCount,DisplayVk * display)1192 egl::ConfigSet GenerateConfigs(const GLenum *colorFormats,
1193 size_t colorFormatsCount,
1194 const GLenum *depthStencilFormats,
1195 size_t depthStencilFormatCount,
1196 DisplayVk *display)
1197 {
1198 ASSERT(colorFormatsCount > 0);
1199 ASSERT(display != nullptr);
1200
1201 gl::SupportedSampleSet colorSampleCounts;
1202 gl::SupportedSampleSet depthStencilSampleCounts;
1203 gl::SupportedSampleSet sampleCounts;
1204
1205 const VkPhysicalDeviceLimits &limits =
1206 display->getRenderer()->getPhysicalDeviceProperties().limits;
1207 const uint32_t depthStencilSampleCountsLimit = limits.framebufferDepthSampleCounts &
1208 limits.framebufferStencilSampleCounts &
1209 vk_gl::kSupportedSampleCounts;
1210
1211 vk_gl::AddSampleCounts(limits.framebufferColorSampleCounts & vk_gl::kSupportedSampleCounts,
1212 &colorSampleCounts);
1213 vk_gl::AddSampleCounts(depthStencilSampleCountsLimit, &depthStencilSampleCounts);
1214
1215 // Always support 0 samples
1216 colorSampleCounts.insert(0);
1217 depthStencilSampleCounts.insert(0);
1218
1219 std::set_intersection(colorSampleCounts.begin(), colorSampleCounts.end(),
1220 depthStencilSampleCounts.begin(), depthStencilSampleCounts.end(),
1221 std::inserter(sampleCounts, sampleCounts.begin()));
1222
1223 egl::ConfigSet configSet;
1224
1225 for (size_t colorFormatIdx = 0; colorFormatIdx < colorFormatsCount; colorFormatIdx++)
1226 {
1227 const gl::InternalFormat &colorFormatInfo =
1228 gl::GetSizedInternalFormatInfo(colorFormats[colorFormatIdx]);
1229 ASSERT(colorFormatInfo.sized);
1230
1231 for (size_t depthStencilFormatIdx = 0; depthStencilFormatIdx < depthStencilFormatCount;
1232 depthStencilFormatIdx++)
1233 {
1234 const gl::InternalFormat &depthStencilFormatInfo =
1235 gl::GetSizedInternalFormatInfo(depthStencilFormats[depthStencilFormatIdx]);
1236 ASSERT(depthStencilFormats[depthStencilFormatIdx] == GL_NONE ||
1237 depthStencilFormatInfo.sized);
1238
1239 const gl::SupportedSampleSet *configSampleCounts = &sampleCounts;
1240 // If there is no depth/stencil buffer, use the color samples set.
1241 if (depthStencilFormats[depthStencilFormatIdx] == GL_NONE)
1242 {
1243 configSampleCounts = &colorSampleCounts;
1244 }
1245 // If there is no color buffer, use the depth/stencil samples set.
1246 else if (colorFormats[colorFormatIdx] == GL_NONE)
1247 {
1248 configSampleCounts = &depthStencilSampleCounts;
1249 }
1250
1251 for (EGLint sampleCount : *configSampleCounts)
1252 {
1253 egl::Config config = GenerateDefaultConfig(display, colorFormatInfo,
1254 depthStencilFormatInfo, sampleCount);
1255 configSet.add(config);
1256 }
1257 }
1258 }
1259
1260 return configSet;
1261 }
1262
1263 } // namespace egl_vk
1264
1265 } // namespace rx
1266