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/system_utils.h"
15 #include "common/utilities.h"
16 #include "libANGLE/Caps.h"
17 #include "libANGLE/formatutils.h"
18 #include "libANGLE/renderer/driver_utils.h"
19 #include "libANGLE/renderer/vulkan/DisplayVk.h"
20 #include "libANGLE/renderer/vulkan/vk_cache_utils.h"
21 #include "libANGLE/renderer/vulkan/vk_renderer.h"
22 #include "vk_format_utils.h"
23
24 namespace
25 {
26 constexpr unsigned int kComponentsPerVector = 4;
27 constexpr bool kEnableLogMissingExtensionsForGLES32 = false;
28 } // anonymous namespace
29
30 namespace rx
31 {
32
33 namespace vk
34 {
35 namespace
36 {
37 // Checks to see if each format can be reinterpreted to an equivalent format in a different
38 // colorspace. If all supported formats can be reinterpreted, it returns true. Formats which are not
39 // supported at all are ignored and not counted as failures.
FormatReinterpretationSupported(const std::vector<GLenum> & optionalSizedFormats,const Renderer * renderer,bool checkLinearColorspace)40 bool FormatReinterpretationSupported(const std::vector<GLenum> &optionalSizedFormats,
41 const Renderer *renderer,
42 bool checkLinearColorspace)
43 {
44 for (GLenum glFormat : optionalSizedFormats)
45 {
46 const gl::TextureCaps &baseCaps = renderer->getNativeTextureCaps().get(glFormat);
47 if (baseCaps.texturable && baseCaps.filterable)
48 {
49 const Format &vkFormat = renderer->getFormat(glFormat);
50 // For capability query, we use the renderable format since that is what we are capable
51 // of when we fallback.
52 angle::FormatID imageFormatID = vkFormat.getActualRenderableImageFormatID();
53
54 angle::FormatID reinterpretedFormatID = checkLinearColorspace
55 ? ConvertToLinear(imageFormatID)
56 : ConvertToSRGB(imageFormatID);
57
58 const Format &reinterpretedVkFormat = renderer->getFormat(reinterpretedFormatID);
59
60 if (reinterpretedVkFormat.getActualRenderableImageFormatID() != reinterpretedFormatID)
61 {
62 return false;
63 }
64
65 if (!renderer->haveSameFormatFeatureBits(imageFormatID, reinterpretedFormatID))
66 {
67 return false;
68 }
69 }
70 }
71
72 return true;
73 }
74
GetTextureSRGBDecodeSupport(const Renderer * renderer)75 bool GetTextureSRGBDecodeSupport(const Renderer *renderer)
76 {
77 static constexpr bool kLinearColorspace = true;
78
79 // GL_SRGB and GL_SRGB_ALPHA unsized formats are also required by the spec, but the only valid
80 // type for them is GL_UNSIGNED_BYTE, so they are fully included in the sized formats listed
81 // here
82 std::vector<GLenum> optionalSizedSRGBFormats = {
83 GL_SRGB8,
84 GL_SRGB8_ALPHA8_EXT,
85 GL_COMPRESSED_SRGB_S3TC_DXT1_EXT,
86 GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT,
87 GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT,
88 GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT,
89 };
90
91 if (!FormatReinterpretationSupported(optionalSizedSRGBFormats, renderer, kLinearColorspace))
92 {
93 return false;
94 }
95
96 return true;
97 }
98
GetTextureSRGBOverrideSupport(const Renderer * renderer,const gl::Extensions & supportedExtensions)99 bool GetTextureSRGBOverrideSupport(const Renderer *renderer,
100 const gl::Extensions &supportedExtensions)
101 {
102 static constexpr bool kNonLinearColorspace = false;
103
104 // If the given linear format is supported, we also need to support its corresponding nonlinear
105 // format. If the given linear format is NOT supported, we don't care about its corresponding
106 // nonlinear format.
107 std::vector<GLenum> optionalLinearFormats = {GL_RGB8,
108 GL_RGBA8,
109 GL_COMPRESSED_RGB8_ETC2,
110 GL_COMPRESSED_RGBA8_ETC2_EAC,
111 GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,
112 GL_COMPRESSED_RGBA_ASTC_4x4,
113 GL_COMPRESSED_RGBA_ASTC_5x4,
114 GL_COMPRESSED_RGBA_ASTC_5x5,
115 GL_COMPRESSED_RGBA_ASTC_6x5,
116 GL_COMPRESSED_RGBA_ASTC_6x6,
117 GL_COMPRESSED_RGBA_ASTC_8x5,
118 GL_COMPRESSED_RGBA_ASTC_8x6,
119 GL_COMPRESSED_RGBA_ASTC_8x8,
120 GL_COMPRESSED_RGBA_ASTC_10x5,
121 GL_COMPRESSED_RGBA_ASTC_10x6,
122 GL_COMPRESSED_RGBA_ASTC_10x8,
123 GL_COMPRESSED_RGBA_ASTC_10x10,
124 GL_COMPRESSED_RGBA_ASTC_12x10,
125 GL_COMPRESSED_RGBA_ASTC_12x12};
126 std::vector<GLenum> optionalS3TCLinearFormats = {
127 GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
128 GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT};
129 std::vector<GLenum> optionalR8LinearFormats = {GL_R8};
130 std::vector<GLenum> optionalRG8LinearFormats = {GL_RG8};
131 std::vector<GLenum> optionalBPTCLinearFormats = {GL_COMPRESSED_RGBA_BPTC_UNORM_EXT};
132
133 if (!FormatReinterpretationSupported(optionalLinearFormats, renderer, kNonLinearColorspace))
134 {
135 return false;
136 }
137
138 if (supportedExtensions.textureCompressionS3tcSrgbEXT)
139 {
140 if (!FormatReinterpretationSupported(optionalS3TCLinearFormats, renderer,
141 kNonLinearColorspace))
142 {
143 return false;
144 }
145 }
146
147 if (supportedExtensions.textureSRGBR8EXT)
148 {
149 if (!FormatReinterpretationSupported(optionalR8LinearFormats, renderer,
150 kNonLinearColorspace))
151 {
152 return false;
153 }
154 }
155
156 if (supportedExtensions.textureSRGBRG8EXT)
157 {
158 if (!FormatReinterpretationSupported(optionalRG8LinearFormats, renderer,
159 kNonLinearColorspace))
160 {
161 return false;
162 }
163 }
164
165 if (supportedExtensions.textureCompressionBptcEXT)
166 {
167 if (!FormatReinterpretationSupported(optionalBPTCLinearFormats, renderer,
168 kNonLinearColorspace))
169 {
170 return false;
171 }
172 }
173
174 return true;
175 }
176
CanSupportYuvInternalFormat(const Renderer * renderer)177 bool CanSupportYuvInternalFormat(const Renderer *renderer)
178 {
179 // The following formats are not mandatory in Vulkan, even when VK_KHR_sampler_ycbcr_conversion
180 // is supported. GL_ANGLE_yuv_internal_format requires support for sampling only the
181 // 8-bit 2-plane YUV format (VK_FORMAT_G8_B8R8_2PLANE_420_UNORM), if the ICD supports that we
182 // can expose the extension.
183 //
184 // Various test cases need multiple YUV formats. It would be preferrable to have support for the
185 // 3 plane 8 bit YUV format (VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM) as well.
186
187 const Format &twoPlane8bitYuvFormat = renderer->getFormat(GL_G8_B8R8_2PLANE_420_UNORM_ANGLE);
188 bool twoPlane8bitYuvFormatSupported = renderer->hasImageFormatFeatureBits(
189 twoPlane8bitYuvFormat.getActualImageFormatID(vk::ImageAccess::SampleOnly),
190 VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT);
191
192 const Format &threePlane8bitYuvFormat = renderer->getFormat(GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE);
193 bool threePlane8bitYuvFormatSupported = renderer->hasImageFormatFeatureBits(
194 threePlane8bitYuvFormat.getActualImageFormatID(vk::ImageAccess::SampleOnly),
195 VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT);
196
197 return twoPlane8bitYuvFormatSupported && threePlane8bitYuvFormatSupported;
198 }
199
GetTimestampValidBits(const std::vector<VkQueueFamilyProperties> & queueFamilyProperties,uint32_t queueFamilyIndex)200 uint32_t GetTimestampValidBits(const std::vector<VkQueueFamilyProperties> &queueFamilyProperties,
201 uint32_t queueFamilyIndex)
202 {
203 ASSERT(!queueFamilyProperties.empty());
204
205 if (queueFamilyIndex < queueFamilyProperties.size())
206 {
207 // If a queue family is already selected (which is only currently the case if there is only
208 // one family), get the timestamp valid bits from that queue.
209 return queueFamilyProperties[queueFamilyIndex].timestampValidBits;
210 }
211
212 // If a queue family is not already selected, we cannot know which queue family will end up
213 // being used until a surface is used. Take the minimum valid bits from all queues as a safe
214 // measure.
215 uint32_t timestampValidBits = queueFamilyProperties[0].timestampValidBits;
216 for (const VkQueueFamilyProperties &properties : queueFamilyProperties)
217 {
218 timestampValidBits = std::min(timestampValidBits, properties.timestampValidBits);
219 }
220 return timestampValidBits;
221 }
222
CanSupportGPUShader5(const VkPhysicalDeviceFeatures & features)223 bool CanSupportGPUShader5(const VkPhysicalDeviceFeatures &features)
224 {
225 // We use the following Vulkan features to implement EXT_gpu_shader5 and OES_gpu_shader5:
226 // - shaderImageGatherExtended: textureGatherOffset with non-constant offset and
227 // textureGatherOffsets family of functions.
228 // - shaderSampledImageArrayDynamicIndexing and shaderUniformBufferArrayDynamicIndexing:
229 // dynamically uniform indices for samplers and uniform buffers.
230 return features.shaderImageGatherExtended && features.shaderSampledImageArrayDynamicIndexing &&
231 features.shaderUniformBufferArrayDynamicIndexing;
232 }
233
GetRequiredGLES32ExtensionList(const gl::Extensions & nativeExtensions)234 ANGLE_INLINE std::vector<bool> GetRequiredGLES32ExtensionList(
235 const gl::Extensions &nativeExtensions)
236 {
237 // From the GLES 3.2 spec: Almost all features of [ANDROID_extension_pack_es31a], incorporating
238 // by reference all of the following features - with the exception of the sRGB decode features
239 // of EXT_texture_sRGB_decode.
240
241 // The extension debugKHR (also required for the Android extension pack) is a frontend feature
242 // and is unconditionally enabled as a supported feature (in generateSupportedExtensions()).
243 // Therefore, it is not included here.
244 return {
245 // From ANDROID_extension_pack_es31a
246 nativeExtensions.textureCompressionAstcLdrKHR,
247 nativeExtensions.blendEquationAdvancedKHR,
248 nativeExtensions.sampleShadingOES,
249 nativeExtensions.sampleVariablesOES,
250 nativeExtensions.shaderImageAtomicOES,
251 nativeExtensions.shaderMultisampleInterpolationOES,
252 nativeExtensions.textureStencil8OES,
253 nativeExtensions.textureStorageMultisample2dArrayOES,
254 nativeExtensions.copyImageEXT,
255 nativeExtensions.drawBuffersIndexedEXT,
256 nativeExtensions.geometryShaderEXT,
257 nativeExtensions.gpuShader5EXT,
258 nativeExtensions.primitiveBoundingBoxEXT,
259 nativeExtensions.shaderIoBlocksEXT,
260 nativeExtensions.tessellationShaderEXT,
261 nativeExtensions.textureBorderClampEXT,
262 nativeExtensions.textureBufferEXT,
263 nativeExtensions.textureCubeMapArrayEXT,
264
265 // Other extensions
266 nativeExtensions.drawElementsBaseVertexOES,
267 nativeExtensions.colorBufferFloatEXT,
268 nativeExtensions.robustnessKHR,
269 };
270 }
271
LogMissingExtensionsForGLES32(const gl::Extensions & nativeExtensions)272 void LogMissingExtensionsForGLES32(const gl::Extensions &nativeExtensions)
273 {
274 if (!kEnableLogMissingExtensionsForGLES32)
275 {
276 return;
277 }
278 std::vector<bool> requiredExtensions = GetRequiredGLES32ExtensionList(nativeExtensions);
279
280 constexpr const char *kRequiredExtensionNames[] = {
281 // From ANDROID_extension_pack_es31a
282 "textureCompressionAstcLdrKHR",
283 "blendEquationAdvancedKHR",
284 "sampleShadingOES",
285 "sampleVariablesOES",
286 "shaderImageAtomicOES",
287 "shaderMultisampleInterpolationOES",
288 "textureStencil8OES",
289 "textureStorageMultisample2dArrayOES",
290 "copyImageEXT",
291 "drawBuffersIndexedEXT",
292 "geometryShaderEXT",
293 "gpuShader5EXT",
294 "primitiveBoundingBoxEXT",
295 "shaderIoBlocksEXT",
296 "tessellationShaderEXT",
297 "textureBorderClampEXT",
298 "textureBufferEXT",
299 "textureCubeMapArrayEXT",
300
301 // Other extensions
302 "drawElementsBaseVertexOES",
303 "colorBufferFloatEXT",
304 "robustnessKHR",
305 };
306 ASSERT(std::end(kRequiredExtensionNames) - std::begin(kRequiredExtensionNames) ==
307 requiredExtensions.size());
308
309 for (uint32_t index = 0; index < requiredExtensions.size(); index++)
310 {
311 if (!requiredExtensions[index])
312 {
313 INFO() << "The following extension is required for GLES 3.2: "
314 << kRequiredExtensionNames[index];
315 }
316 }
317 }
318
319 } // namespace
320
ensureCapsInitialized() const321 void Renderer::ensureCapsInitialized() const
322 {
323 if (mCapsInitialized)
324 {
325 return;
326 }
327 mCapsInitialized = true;
328
329 const VkPhysicalDeviceLimits &limitsVk = mPhysicalDeviceProperties.limits;
330
331 mNativeExtensions.setTextureExtensionSupport(mNativeTextureCaps);
332
333 // Enable GL_EXT_buffer_storage
334 mNativeExtensions.bufferStorageEXT = true;
335
336 // When ETC2/EAC formats are natively supported, enable ANGLE-specific extension string to
337 // expose them to WebGL. In other case, mark potentially-available ETC1 extension as emulated.
338 if ((mPhysicalDeviceFeatures.textureCompressionETC2 == VK_TRUE) &&
339 gl::DetermineCompressedTextureETCSupport(mNativeTextureCaps))
340 {
341 mNativeExtensions.compressedTextureEtcANGLE = true;
342 }
343 else
344 {
345 mNativeLimitations.emulatedEtc1 = true;
346 }
347
348 // When ASTC formats are not natively supported
349 // mark potentially-available ASTC extension as emulated.
350 if (mPhysicalDeviceFeatures.textureCompressionASTC_LDR == VK_FALSE)
351 {
352 mNativeLimitations.emulatedAstc = true;
353 }
354
355 // Vulkan doesn't support ASTC 3D block textures, which are required by
356 // GL_OES_texture_compression_astc.
357 mNativeExtensions.textureCompressionAstcOES = false;
358 // Vulkan does not support sliced 3D ASTC textures either.
359 mNativeExtensions.textureCompressionAstcSliced3dKHR = false;
360
361 // Vulkan doesn't guarantee HDR blocks decoding without VK_EXT_texture_compression_astc_hdr.
362 mNativeExtensions.textureCompressionAstcHdrKHR = false;
363
364 // Enable EXT_compressed_ETC1_RGB8_sub_texture
365 mNativeExtensions.compressedETC1RGB8SubTextureEXT =
366 mNativeExtensions.compressedETC1RGB8TextureOES;
367
368 // Enable this for simple buffer readback testing, but some functionality is missing.
369 // TODO(jmadill): Support full mapBufferRangeEXT extension.
370 mNativeExtensions.mapbufferOES = true;
371 mNativeExtensions.mapBufferRangeEXT = true;
372 mNativeExtensions.textureStorageEXT = true;
373 mNativeExtensions.drawBuffersEXT = true;
374 mNativeExtensions.fragDepthEXT = true;
375 mNativeExtensions.conservativeDepthEXT = true;
376 mNativeExtensions.framebufferBlitANGLE = true;
377 mNativeExtensions.framebufferBlitNV = true;
378 mNativeExtensions.framebufferMultisampleANGLE = true;
379 mNativeExtensions.textureMultisampleANGLE = true;
380 mNativeExtensions.multisampledRenderToTextureEXT =
381 getFeatures().enableMultisampledRenderToTexture.enabled;
382 mNativeExtensions.multisampledRenderToTexture2EXT =
383 getFeatures().enableMultisampledRenderToTexture.enabled;
384 mNativeExtensions.textureStorageMultisample2dArrayOES =
385 (limitsVk.standardSampleLocations == VK_TRUE);
386 mNativeExtensions.copyTextureCHROMIUM = true;
387 mNativeExtensions.copyTexture3dANGLE = true;
388 mNativeExtensions.copyCompressedTextureCHROMIUM = true;
389 mNativeExtensions.debugMarkerEXT = true;
390 mNativeExtensions.robustnessEXT = true;
391 mNativeExtensions.robustnessKHR = true;
392 mNativeExtensions.translatedShaderSourceANGLE = true;
393 mNativeExtensions.discardFramebufferEXT = true;
394 mNativeExtensions.stencilTexturingANGLE = true;
395 mNativeExtensions.packReverseRowOrderANGLE = true;
396 mNativeExtensions.textureBorderClampOES = getFeatures().supportsCustomBorderColor.enabled;
397 mNativeExtensions.textureBorderClampEXT = getFeatures().supportsCustomBorderColor.enabled;
398 mNativeExtensions.polygonModeNV = mPhysicalDeviceFeatures.fillModeNonSolid == VK_TRUE;
399 mNativeExtensions.polygonModeANGLE = mPhysicalDeviceFeatures.fillModeNonSolid == VK_TRUE;
400 mNativeExtensions.polygonOffsetClampEXT = mPhysicalDeviceFeatures.depthBiasClamp == VK_TRUE;
401 mNativeExtensions.depthClampEXT = mPhysicalDeviceFeatures.depthClamp == VK_TRUE;
402 // Enable EXT_texture_type_2_10_10_10_REV
403 mNativeExtensions.textureType2101010REVEXT = true;
404
405 // Enable EXT_texture_mirror_clamp_to_edge
406 mNativeExtensions.textureMirrorClampToEdgeEXT =
407 getFeatures().supportsSamplerMirrorClampToEdge.enabled;
408
409 // Enable EXT_multi_draw_indirect
410 mNativeExtensions.multiDrawIndirectEXT = true;
411
412 // Enable EXT_base_instance
413 mNativeExtensions.baseInstanceEXT = true;
414
415 // Enable ANGLE_base_vertex_base_instance
416 mNativeExtensions.baseVertexBaseInstanceANGLE = true;
417 mNativeExtensions.baseVertexBaseInstanceShaderBuiltinANGLE = true;
418
419 // Enable OES/EXT_draw_elements_base_vertex
420 mNativeExtensions.drawElementsBaseVertexOES = true;
421 mNativeExtensions.drawElementsBaseVertexEXT = true;
422
423 // Enable EXT_blend_minmax
424 mNativeExtensions.blendMinmaxEXT = true;
425
426 // Enable OES/EXT_draw_buffers_indexed
427 mNativeExtensions.drawBuffersIndexedOES = mPhysicalDeviceFeatures.independentBlend == VK_TRUE;
428 mNativeExtensions.drawBuffersIndexedEXT = mNativeExtensions.drawBuffersIndexedOES;
429
430 mNativeExtensions.EGLImageOES = true;
431 mNativeExtensions.EGLImageExternalOES = true;
432 mNativeExtensions.EGLImageExternalWrapModesEXT = true;
433 mNativeExtensions.EGLImageExternalEssl3OES = true;
434 mNativeExtensions.EGLImageArrayEXT = true;
435 mNativeExtensions.EGLImageStorageEXT = true;
436 mNativeExtensions.memoryObjectEXT = true;
437 mNativeExtensions.memoryObjectFdEXT = getFeatures().supportsExternalMemoryFd.enabled;
438 mNativeExtensions.memoryObjectFlagsANGLE = true;
439 mNativeExtensions.memoryObjectFuchsiaANGLE =
440 getFeatures().supportsExternalMemoryFuchsia.enabled;
441
442 mNativeExtensions.semaphoreEXT = true;
443 mNativeExtensions.semaphoreFdEXT = getFeatures().supportsExternalSemaphoreFd.enabled;
444 mNativeExtensions.semaphoreFuchsiaANGLE =
445 getFeatures().supportsExternalSemaphoreFuchsia.enabled;
446
447 mNativeExtensions.vertexHalfFloatOES = true;
448
449 // Enabled in HW if VK_EXT_vertex_attribute_divisor available, otherwise emulated
450 mNativeExtensions.instancedArraysANGLE = true;
451 mNativeExtensions.instancedArraysEXT = true;
452
453 // Only expose robust buffer access if the physical device supports it.
454 mNativeExtensions.robustBufferAccessBehaviorKHR =
455 (mPhysicalDeviceFeatures.robustBufferAccess == VK_TRUE);
456
457 mNativeExtensions.EGLSyncOES = true;
458
459 mNativeExtensions.vertexType1010102OES = true;
460
461 // Occlusion queries are natively supported in Vulkan. ANGLE only issues this query inside a
462 // render pass, so there is no dependency to `inheritedQueries`.
463 mNativeExtensions.occlusionQueryBooleanEXT = true;
464
465 // From the Vulkan specs:
466 // > The number of valid bits in a timestamp value is determined by the
467 // > VkQueueFamilyProperties::timestampValidBits property of the queue on which the timestamp is
468 // > written. Timestamps are supported on any queue which reports a non-zero value for
469 // > timestampValidBits via vkGetPhysicalDeviceQueueFamilyProperties.
470 //
471 // This query is applicable to render passes, but the `inheritedQueries` feature may not be
472 // present. The extension is not exposed in that case.
473 // We use secondary command buffers almost everywhere and they require a feature to be
474 // able to execute in the presence of queries. As a result, we won't support timestamp queries
475 // unless that feature is available.
476 if (vk::OutsideRenderPassCommandBuffer::SupportsQueries(mPhysicalDeviceFeatures) &&
477 vk::RenderPassCommandBuffer::SupportsQueries(mPhysicalDeviceFeatures))
478 {
479 const uint32_t timestampValidBits =
480 vk::GetTimestampValidBits(mQueueFamilyProperties, mCurrentQueueFamilyIndex);
481
482 mNativeExtensions.disjointTimerQueryEXT = timestampValidBits > 0;
483 mNativeCaps.queryCounterBitsTimeElapsed = timestampValidBits;
484 mNativeCaps.queryCounterBitsTimestamp = timestampValidBits;
485 }
486
487 mNativeExtensions.textureFilterAnisotropicEXT =
488 mPhysicalDeviceFeatures.samplerAnisotropy && limitsVk.maxSamplerAnisotropy > 1.0f;
489 mNativeCaps.maxTextureAnisotropy =
490 mNativeExtensions.textureFilterAnisotropicEXT ? limitsVk.maxSamplerAnisotropy : 0.0f;
491
492 // Vulkan natively supports non power-of-two textures
493 mNativeExtensions.textureNpotOES = true;
494
495 mNativeExtensions.texture3DOES = true;
496
497 // Vulkan natively supports standard derivatives
498 mNativeExtensions.standardDerivativesOES = true;
499
500 // Vulkan natively supports texture LOD
501 mNativeExtensions.shaderTextureLodEXT = true;
502
503 // Vulkan natively supports noperspective interpolation
504 mNativeExtensions.shaderNoperspectiveInterpolationNV = true;
505
506 // Vulkan natively supports 32-bit indices, entry in kIndexTypeMap
507 mNativeExtensions.elementIndexUintOES = true;
508
509 mNativeExtensions.fboRenderMipmapOES = true;
510
511 // We support getting image data for Textures and Renderbuffers.
512 mNativeExtensions.getImageANGLE = true;
513
514 // Implemented in the translator
515 mNativeExtensions.shaderNonConstantGlobalInitializersEXT = true;
516
517 // Implemented in the front end. Enable SSO if not explicitly disabled.
518 mNativeExtensions.separateShaderObjectsEXT =
519 !getFeatures().disableSeparateShaderObjects.enabled;
520
521 // Vulkan has no restrictions of the format of cubemaps, so if the proper formats are supported,
522 // creating a cube of any of these formats should be implicitly supported.
523 mNativeExtensions.depthTextureCubeMapOES =
524 mNativeExtensions.depthTextureOES && mNativeExtensions.packedDepthStencilOES;
525
526 // Vulkan natively supports format reinterpretation, but we still require support for all
527 // formats we may reinterpret to
528 mNativeExtensions.textureFormatSRGBOverrideEXT =
529 vk::GetTextureSRGBOverrideSupport(this, mNativeExtensions);
530 mNativeExtensions.textureSRGBDecodeEXT = vk::GetTextureSRGBDecodeSupport(this);
531
532 // EXT_srgb_write_control requires image_format_list
533 mNativeExtensions.sRGBWriteControlEXT = getFeatures().supportsImageFormatList.enabled;
534
535 // Vulkan natively supports io interface block.
536 mNativeExtensions.shaderIoBlocksOES = true;
537 mNativeExtensions.shaderIoBlocksEXT = true;
538
539 bool gpuShader5Support = vk::CanSupportGPUShader5(mPhysicalDeviceFeatures);
540 mNativeExtensions.gpuShader5EXT = gpuShader5Support;
541 mNativeExtensions.gpuShader5OES = gpuShader5Support;
542
543 // Only expose texture cubemap array if the physical device supports it.
544 mNativeExtensions.textureCubeMapArrayOES = getFeatures().supportsImageCubeArray.enabled;
545 mNativeExtensions.textureCubeMapArrayEXT = mNativeExtensions.textureCubeMapArrayOES;
546
547 mNativeExtensions.shadowSamplersEXT = true;
548
549 // Enable EXT_external_buffer on Android. External buffers are implemented using Android
550 // hardware buffer (struct AHardwareBuffer).
551 mNativeExtensions.externalBufferEXT = IsAndroid() && GetAndroidSDKVersion() >= 26;
552
553 // From the Vulkan specs:
554 // sampleRateShading specifies whether Sample Shading and multisample interpolation are
555 // supported. If this feature is not enabled, the sampleShadingEnable member of the
556 // VkPipelineMultisampleStateCreateInfo structure must be set to VK_FALSE and the
557 // minSampleShading member is ignored. This also specifies whether shader modules can declare
558 // the SampleRateShading capability
559 bool supportSampleRateShading = mPhysicalDeviceFeatures.sampleRateShading == VK_TRUE;
560 mNativeExtensions.sampleShadingOES = supportSampleRateShading;
561
562 // From the SPIR-V spec at 3.21. BuiltIn, SampleId and SamplePosition needs
563 // SampleRateShading. https://www.khronos.org/registry/spir-v/specs/unified1/SPIRV.html
564 // To replace non-constant index to constant 0 index, this extension assumes that ANGLE only
565 // supports the number of samples less than or equal to 32.
566 constexpr unsigned int kNotSupportedSampleCounts = VK_SAMPLE_COUNT_64_BIT;
567 mNativeExtensions.sampleVariablesOES =
568 supportSampleRateShading && vk_gl::GetMaxSampleCount(kNotSupportedSampleCounts) == 0;
569
570 // EXT_multisample_compatibility is necessary for GLES1 conformance so calls like
571 // glDisable(GL_MULTISAMPLE) don't fail. This is not actually implemented in Vulkan. However,
572 // no CTS tests actually test this extension. GL_SAMPLE_ALPHA_TO_ONE requires the Vulkan
573 // alphaToOne feature.
574 mNativeExtensions.multisampleCompatibilityEXT =
575 mPhysicalDeviceFeatures.alphaToOne ||
576 mFeatures.exposeNonConformantExtensionsAndVersions.enabled;
577
578 // GL_KHR_blend_equation_advanced. According to the spec, only color attachment zero can be
579 // used with advanced blend:
580 //
581 // > Advanced blending equations are supported only when rendering to a single
582 // > color buffer using fragment color zero.
583 //
584 // Vulkan requires advancedBlendMaxColorAttachments to be at least one, so we can support
585 // advanced blend as long as the Vulkan extension is supported. Otherwise, the extension is
586 // emulated where possible.
587 mNativeExtensions.blendEquationAdvancedKHR = mFeatures.supportsBlendOperationAdvanced.enabled ||
588 mFeatures.emulateAdvancedBlendEquations.enabled;
589
590 // Enable EXT_unpack_subimage
591 mNativeExtensions.unpackSubimageEXT = true;
592
593 // Enable NV_pack_subimage
594 mNativeExtensions.packSubimageNV = true;
595
596 mNativeCaps.minInterpolationOffset = limitsVk.minInterpolationOffset;
597 mNativeCaps.maxInterpolationOffset = limitsVk.maxInterpolationOffset;
598 mNativeCaps.subPixelInterpolationOffsetBits = limitsVk.subPixelInterpolationOffsetBits;
599
600 // Enable GL_ANGLE_robust_fragment_shader_output
601 mNativeExtensions.robustFragmentShaderOutputANGLE = true;
602
603 // From the Vulkan spec:
604 //
605 // > The values minInterpolationOffset and maxInterpolationOffset describe the closed interval
606 // > of supported interpolation offsets : [ minInterpolationOffset, maxInterpolationOffset ].
607 // > The ULP is determined by subPixelInterpolationOffsetBits. If
608 // > subPixelInterpolationOffsetBits is 4, this provides increments of(1 / 2^4) = 0.0625, and
609 // > thus the range of supported interpolation offsets would be[-0.5, 0.4375]
610 //
611 // OES_shader_multisample_interpolation requires a maximum value of -0.5 for
612 // MIN_FRAGMENT_INTERPOLATION_OFFSET_OES and minimum 0.5 for
613 // MAX_FRAGMENT_INTERPOLATION_OFFSET_OES. Vulkan has an identical limit for
614 // minInterpolationOffset, but its limit for maxInterpolationOffset is 0.5-(1/ULP).
615 // OES_shader_multisample_interpolation is therefore only supported if
616 // maxInterpolationOffset is at least 0.5.
617 //
618 // The GL spec is not as precise as Vulkan's in this regard and that the requirements really
619 // meant to match. This is rectified in the GL spec.
620 // https://gitlab.khronos.org/opengl/API/-/issues/149
621 mNativeExtensions.shaderMultisampleInterpolationOES = mNativeExtensions.sampleVariablesOES;
622
623 // Always enable ANGLE_rgbx_internal_format to expose GL_RGBX8_ANGLE.
624 mNativeExtensions.rgbxInternalFormatANGLE = true;
625
626 // https://vulkan.lunarg.com/doc/view/1.0.30.0/linux/vkspec.chunked/ch31s02.html
627 mNativeCaps.maxElementIndex = std::numeric_limits<GLuint>::max() - 1;
628 mNativeCaps.max3DTextureSize = rx::LimitToInt(limitsVk.maxImageDimension3D);
629 mNativeCaps.max2DTextureSize =
630 std::min(limitsVk.maxFramebufferWidth, limitsVk.maxImageDimension2D);
631 mNativeCaps.maxArrayTextureLayers = rx::LimitToInt(limitsVk.maxImageArrayLayers);
632 mNativeCaps.maxLODBias = limitsVk.maxSamplerLodBias;
633 mNativeCaps.maxCubeMapTextureSize = rx::LimitToInt(limitsVk.maxImageDimensionCube);
634 mNativeCaps.maxRenderbufferSize =
635 std::min({limitsVk.maxImageDimension2D, limitsVk.maxFramebufferWidth,
636 limitsVk.maxFramebufferHeight});
637 mNativeCaps.minAliasedPointSize = std::max(1.0f, limitsVk.pointSizeRange[0]);
638 mNativeCaps.maxAliasedPointSize = limitsVk.pointSizeRange[1];
639
640 // Line width ranges and granularity
641 if (mPhysicalDeviceFeatures.wideLines && mFeatures.bresenhamLineRasterization.enabled)
642 {
643 mNativeCaps.minAliasedLineWidth = std::max(1.0f, limitsVk.lineWidthRange[0]);
644 mNativeCaps.maxAliasedLineWidth = limitsVk.lineWidthRange[1];
645 }
646 else
647 {
648 mNativeCaps.minAliasedLineWidth = 1.0f;
649 mNativeCaps.maxAliasedLineWidth = 1.0f;
650 }
651 mNativeCaps.minMultisampleLineWidth = mNativeCaps.minAliasedLineWidth;
652 mNativeCaps.maxMultisampleLineWidth = mNativeCaps.maxAliasedLineWidth;
653 mNativeCaps.lineWidthGranularity = limitsVk.lineWidthGranularity;
654
655 mNativeCaps.maxDrawBuffers =
656 std::min(limitsVk.maxColorAttachments, limitsVk.maxFragmentOutputAttachments);
657 mNativeCaps.maxFramebufferWidth = rx::LimitToInt(limitsVk.maxFramebufferWidth);
658 mNativeCaps.maxFramebufferHeight = rx::LimitToInt(limitsVk.maxFramebufferHeight);
659 mNativeCaps.maxColorAttachments = rx::LimitToInt(limitsVk.maxColorAttachments);
660 mNativeCaps.maxViewportWidth = rx::LimitToInt(limitsVk.maxViewportDimensions[0]);
661 mNativeCaps.maxViewportHeight = rx::LimitToInt(limitsVk.maxViewportDimensions[1]);
662 mNativeCaps.maxSampleMaskWords = rx::LimitToInt(limitsVk.maxSampleMaskWords);
663 mNativeCaps.maxColorTextureSamples =
664 vk_gl::GetMaxSampleCount(limitsVk.sampledImageColorSampleCounts);
665 mNativeCaps.maxDepthTextureSamples =
666 vk_gl::GetMaxSampleCount(limitsVk.sampledImageDepthSampleCounts);
667 mNativeCaps.maxIntegerSamples =
668 vk_gl::GetMaxSampleCount(limitsVk.sampledImageIntegerSampleCounts);
669
670 mNativeCaps.maxVertexAttributes = rx::LimitToInt(limitsVk.maxVertexInputAttributes);
671 mNativeCaps.maxVertexAttribBindings = rx::LimitToInt(limitsVk.maxVertexInputBindings);
672 // Offset and stride are stored as uint16_t in PackedAttribDesc.
673 mNativeCaps.maxVertexAttribRelativeOffset =
674 std::min((1u << kAttributeOffsetMaxBits) - 1, limitsVk.maxVertexInputAttributeOffset);
675 mNativeCaps.maxVertexAttribStride =
676 std::min(static_cast<uint32_t>(std::numeric_limits<uint16_t>::max()),
677 limitsVk.maxVertexInputBindingStride);
678
679 mNativeCaps.maxElementsIndices = std::numeric_limits<GLint>::max();
680 mNativeCaps.maxElementsVertices = std::numeric_limits<GLint>::max();
681
682 // Looks like all floats are IEEE according to the docs here:
683 // https://www.khronos.org/registry/vulkan/specs/1.0-wsi_extensions/html/vkspec.html#spirvenv-precision-operation
684 mNativeCaps.vertexHighpFloat.setIEEEFloat();
685 mNativeCaps.vertexMediumpFloat.setIEEEHalfFloat();
686 mNativeCaps.vertexLowpFloat.setIEEEHalfFloat();
687 mNativeCaps.fragmentHighpFloat.setIEEEFloat();
688 mNativeCaps.fragmentMediumpFloat.setIEEEHalfFloat();
689 mNativeCaps.fragmentLowpFloat.setIEEEHalfFloat();
690
691 // Vulkan doesn't provide such information. We provide the spec-required minimum here.
692 mNativeCaps.vertexHighpInt.setTwosComplementInt(32);
693 mNativeCaps.vertexMediumpInt.setTwosComplementInt(16);
694 mNativeCaps.vertexLowpInt.setTwosComplementInt(16);
695 mNativeCaps.fragmentHighpInt.setTwosComplementInt(32);
696 mNativeCaps.fragmentMediumpInt.setTwosComplementInt(16);
697 mNativeCaps.fragmentLowpInt.setTwosComplementInt(16);
698
699 // Compute shader limits.
700 mNativeCaps.maxComputeWorkGroupCount[0] = rx::LimitToInt(limitsVk.maxComputeWorkGroupCount[0]);
701 mNativeCaps.maxComputeWorkGroupCount[1] = rx::LimitToInt(limitsVk.maxComputeWorkGroupCount[1]);
702 mNativeCaps.maxComputeWorkGroupCount[2] = rx::LimitToInt(limitsVk.maxComputeWorkGroupCount[2]);
703 mNativeCaps.maxComputeWorkGroupSize[0] = rx::LimitToInt(limitsVk.maxComputeWorkGroupSize[0]);
704 mNativeCaps.maxComputeWorkGroupSize[1] = rx::LimitToInt(limitsVk.maxComputeWorkGroupSize[1]);
705 mNativeCaps.maxComputeWorkGroupSize[2] = rx::LimitToInt(limitsVk.maxComputeWorkGroupSize[2]);
706 mNativeCaps.maxComputeWorkGroupInvocations =
707 rx::LimitToInt(limitsVk.maxComputeWorkGroupInvocations);
708 mNativeCaps.maxComputeSharedMemorySize = rx::LimitToInt(limitsVk.maxComputeSharedMemorySize);
709
710 GLuint maxUniformBlockSize = limitsVk.maxUniformBufferRange;
711
712 // Clamp the maxUniformBlockSize to 64KB (majority of devices support up to this size
713 // currently), on AMD the maxUniformBufferRange is near uint32_t max.
714 maxUniformBlockSize = std::min(0x10000u, maxUniformBlockSize);
715
716 const GLuint maxUniformVectors = maxUniformBlockSize / (sizeof(GLfloat) * kComponentsPerVector);
717 const GLuint maxUniformComponents = maxUniformVectors * kComponentsPerVector;
718
719 // Uniforms are implemented using a uniform buffer, so the max number of uniforms we can
720 // support is the max buffer range divided by the size of a single uniform (4X float).
721 mNativeCaps.maxVertexUniformVectors = maxUniformVectors;
722 mNativeCaps.maxFragmentUniformVectors = maxUniformVectors;
723 for (gl::ShaderType shaderType : gl::AllShaderTypes())
724 {
725 mNativeCaps.maxShaderUniformComponents[shaderType] = maxUniformComponents;
726 }
727 mNativeCaps.maxUniformLocations = maxUniformVectors;
728
729 const int32_t maxPerStageUniformBuffers = rx::LimitToInt(
730 limitsVk.maxPerStageDescriptorUniformBuffers - kReservedPerStageDefaultUniformBindingCount);
731 for (gl::ShaderType shaderType : gl::AllShaderTypes())
732 {
733 mNativeCaps.maxShaderUniformBlocks[shaderType] = maxPerStageUniformBuffers;
734 }
735
736 // Reserved uniform buffer count depends on number of stages. Vertex and fragment shaders are
737 // always supported. The limit needs to be adjusted based on whether geometry and tessellation
738 // is supported.
739 int32_t maxCombinedUniformBuffers = rx::LimitToInt(limitsVk.maxDescriptorSetUniformBuffers) -
740 2 * kReservedPerStageDefaultUniformBindingCount;
741
742 mNativeCaps.maxUniformBlockSize = maxUniformBlockSize;
743 mNativeCaps.uniformBufferOffsetAlignment =
744 static_cast<GLint>(limitsVk.minUniformBufferOffsetAlignment);
745
746 // Note that Vulkan currently implements textures as combined image+samplers, so the limit is
747 // the minimum of supported samplers and sampled images.
748 const uint32_t maxPerStageTextures = std::min(limitsVk.maxPerStageDescriptorSamplers,
749 limitsVk.maxPerStageDescriptorSampledImages);
750 const uint32_t maxCombinedTextures =
751 std::min(limitsVk.maxDescriptorSetSamplers, limitsVk.maxDescriptorSetSampledImages);
752 for (gl::ShaderType shaderType : gl::AllShaderTypes())
753 {
754 mNativeCaps.maxShaderTextureImageUnits[shaderType] = rx::LimitToInt(maxPerStageTextures);
755 }
756 mNativeCaps.maxCombinedTextureImageUnits = rx::LimitToInt(maxCombinedTextures);
757
758 uint32_t maxPerStageStorageBuffers = limitsVk.maxPerStageDescriptorStorageBuffers;
759 uint32_t maxVertexStageStorageBuffers = maxPerStageStorageBuffers;
760 uint32_t maxCombinedStorageBuffers = limitsVk.maxDescriptorSetStorageBuffers;
761
762 // A number of storage buffer slots are used in the vertex shader to emulate transform feedback.
763 // Note that Vulkan requires maxPerStageDescriptorStorageBuffers to be at least 4 (i.e. the same
764 // as gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS).
765 // TODO(syoussefi): This should be conditioned to transform feedback extension not being
766 // present. http://anglebug.com/3206.
767 // TODO(syoussefi): If geometry shader is supported, emulation will be done at that stage, and
768 // so the reserved storage buffers should be accounted in that stage. http://anglebug.com/3606
769 static_assert(
770 gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS == 4,
771 "Limit to ES2.0 if supported SSBO count < supporting transform feedback buffer count");
772 if (mPhysicalDeviceFeatures.vertexPipelineStoresAndAtomics)
773 {
774 ASSERT(maxVertexStageStorageBuffers >= gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS);
775 maxVertexStageStorageBuffers -= gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS;
776 maxCombinedStorageBuffers -= gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS;
777
778 // Cap the per-stage limit of the other stages to the combined limit, in case the combined
779 // limit is now lower than that.
780 maxPerStageStorageBuffers = std::min(maxPerStageStorageBuffers, maxCombinedStorageBuffers);
781 }
782
783 // Reserve up to IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS storage buffers in the fragment and
784 // compute stages for atomic counters. This is only possible if the number of per-stage storage
785 // buffers is greater than 4, which is the required GLES minimum for compute.
786 //
787 // For each stage, we'll either not support atomic counter buffers, or support exactly
788 // IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS. This is due to restrictions in the shader
789 // translator where we can't know how many atomic counter buffers we would really need after
790 // linking so we can't create a packed buffer array.
791 //
792 // For the vertex stage, we could support atomic counters without storage buffers, but that's
793 // likely not very useful, so we use the same limit (4 + MAX_ATOMIC_COUNTER_BUFFERS) for the
794 // vertex stage to determine if we would want to add support for atomic counter buffers.
795 constexpr uint32_t kMinimumStorageBuffersForAtomicCounterBufferSupport =
796 gl::limits::kMinimumComputeStorageBuffers +
797 gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS;
798 uint32_t maxVertexStageAtomicCounterBuffers = 0;
799 uint32_t maxPerStageAtomicCounterBuffers = 0;
800 uint32_t maxCombinedAtomicCounterBuffers = 0;
801
802 if (maxPerStageStorageBuffers >= kMinimumStorageBuffersForAtomicCounterBufferSupport)
803 {
804 maxPerStageAtomicCounterBuffers = gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS;
805 maxCombinedAtomicCounterBuffers = gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS;
806 }
807
808 if (maxVertexStageStorageBuffers >= kMinimumStorageBuffersForAtomicCounterBufferSupport)
809 {
810 maxVertexStageAtomicCounterBuffers = gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS;
811 }
812
813 maxVertexStageStorageBuffers -= maxVertexStageAtomicCounterBuffers;
814 maxPerStageStorageBuffers -= maxPerStageAtomicCounterBuffers;
815 maxCombinedStorageBuffers -= maxCombinedAtomicCounterBuffers;
816
817 mNativeCaps.maxShaderStorageBlocks[gl::ShaderType::Vertex] =
818 mPhysicalDeviceFeatures.vertexPipelineStoresAndAtomics
819 ? rx::LimitToInt(maxVertexStageStorageBuffers)
820 : 0;
821 mNativeCaps.maxShaderStorageBlocks[gl::ShaderType::Fragment] =
822 mPhysicalDeviceFeatures.fragmentStoresAndAtomics ? rx::LimitToInt(maxPerStageStorageBuffers)
823 : 0;
824 mNativeCaps.maxShaderStorageBlocks[gl::ShaderType::Compute] =
825 rx::LimitToInt(maxPerStageStorageBuffers);
826 mNativeCaps.maxCombinedShaderStorageBlocks = rx::LimitToInt(maxCombinedStorageBuffers);
827
828 // Emulated as storage buffers, atomic counter buffers have the same size limit. However, the
829 // limit is a signed integer and values above int max will end up as a negative size. The
830 // storage buffer size is just capped to int unconditionally.
831 uint32_t maxStorageBufferRange = rx::LimitToInt(limitsVk.maxStorageBufferRange);
832 if (mFeatures.limitMaxStorageBufferSize.enabled)
833 {
834 constexpr uint32_t kStorageBufferLimit = 256 * 1024 * 1024;
835 maxStorageBufferRange = std::min(maxStorageBufferRange, kStorageBufferLimit);
836 }
837
838 mNativeCaps.maxShaderStorageBufferBindings = rx::LimitToInt(maxCombinedStorageBuffers);
839 mNativeCaps.maxShaderStorageBlockSize = maxStorageBufferRange;
840 mNativeCaps.shaderStorageBufferOffsetAlignment =
841 rx::LimitToInt(static_cast<uint32_t>(limitsVk.minStorageBufferOffsetAlignment));
842
843 mNativeCaps.maxShaderAtomicCounterBuffers[gl::ShaderType::Vertex] =
844 mPhysicalDeviceFeatures.vertexPipelineStoresAndAtomics
845 ? rx::LimitToInt(maxVertexStageAtomicCounterBuffers)
846 : 0;
847 mNativeCaps.maxShaderAtomicCounterBuffers[gl::ShaderType::Fragment] =
848 mPhysicalDeviceFeatures.fragmentStoresAndAtomics
849 ? rx::LimitToInt(maxPerStageAtomicCounterBuffers)
850 : 0;
851 mNativeCaps.maxShaderAtomicCounterBuffers[gl::ShaderType::Compute] =
852 rx::LimitToInt(maxPerStageAtomicCounterBuffers);
853 mNativeCaps.maxCombinedAtomicCounterBuffers = rx::LimitToInt(maxCombinedAtomicCounterBuffers);
854
855 mNativeCaps.maxAtomicCounterBufferBindings = rx::LimitToInt(maxCombinedAtomicCounterBuffers);
856 mNativeCaps.maxAtomicCounterBufferSize = maxStorageBufferRange;
857
858 // There is no particular limit to how many atomic counters there can be, other than the size of
859 // a storage buffer. We nevertheless limit this to something reasonable (4096 arbitrarily).
860 const int32_t maxAtomicCounters =
861 std::min<int32_t>(4096, maxStorageBufferRange / sizeof(uint32_t));
862 for (gl::ShaderType shaderType : gl::AllShaderTypes())
863 {
864 mNativeCaps.maxShaderAtomicCounters[shaderType] = maxAtomicCounters;
865 }
866
867 // Set maxShaderAtomicCounters to zero if atomic is not supported.
868 if (!mPhysicalDeviceFeatures.vertexPipelineStoresAndAtomics)
869 {
870 mNativeCaps.maxShaderAtomicCounters[gl::ShaderType::Vertex] = 0;
871 mNativeCaps.maxShaderAtomicCounters[gl::ShaderType::Geometry] = 0;
872 mNativeCaps.maxShaderAtomicCounters[gl::ShaderType::TessControl] = 0;
873 mNativeCaps.maxShaderAtomicCounters[gl::ShaderType::TessEvaluation] = 0;
874 }
875 if (!mPhysicalDeviceFeatures.fragmentStoresAndAtomics)
876 {
877 mNativeCaps.maxShaderAtomicCounters[gl::ShaderType::Fragment] = 0;
878 }
879
880 mNativeCaps.maxCombinedAtomicCounters = maxAtomicCounters;
881
882 // GL Images correspond to Vulkan Storage Images.
883 const int32_t maxPerStageImages = rx::LimitToInt(limitsVk.maxPerStageDescriptorStorageImages);
884 const int32_t maxCombinedImages = rx::LimitToInt(limitsVk.maxDescriptorSetStorageImages);
885 const int32_t maxVertexPipelineImages =
886 mPhysicalDeviceFeatures.vertexPipelineStoresAndAtomics ? maxPerStageImages : 0;
887
888 mNativeCaps.maxShaderImageUniforms[gl::ShaderType::Vertex] = maxVertexPipelineImages;
889 mNativeCaps.maxShaderImageUniforms[gl::ShaderType::TessControl] = maxVertexPipelineImages;
890 mNativeCaps.maxShaderImageUniforms[gl::ShaderType::TessEvaluation] = maxVertexPipelineImages;
891 mNativeCaps.maxShaderImageUniforms[gl::ShaderType::Geometry] = maxVertexPipelineImages;
892 mNativeCaps.maxShaderImageUniforms[gl::ShaderType::Fragment] =
893 mPhysicalDeviceFeatures.fragmentStoresAndAtomics ? maxPerStageImages : 0;
894 mNativeCaps.maxShaderImageUniforms[gl::ShaderType::Compute] = maxPerStageImages;
895
896 mNativeCaps.maxCombinedImageUniforms = maxCombinedImages;
897 mNativeCaps.maxImageUnits = maxCombinedImages;
898
899 mNativeCaps.minProgramTexelOffset = limitsVk.minTexelOffset;
900 mNativeCaps.maxProgramTexelOffset = limitsVk.maxTexelOffset;
901 mNativeCaps.minProgramTextureGatherOffset = limitsVk.minTexelGatherOffset;
902 mNativeCaps.maxProgramTextureGatherOffset = limitsVk.maxTexelGatherOffset;
903
904 // There is no additional limit to the combined number of components. We can have up to a
905 // maximum number of uniform buffers, each having the maximum number of components. Note that
906 // this limit includes both components in and out of uniform buffers.
907 //
908 // This value is limited to INT_MAX to avoid overflow when queried from glGetIntegerv().
909 const uint64_t maxCombinedUniformComponents =
910 std::min<uint64_t>(static_cast<uint64_t>(maxPerStageUniformBuffers +
911 kReservedPerStageDefaultUniformBindingCount) *
912 maxUniformComponents,
913 std::numeric_limits<GLint>::max());
914 for (gl::ShaderType shaderType : gl::AllShaderTypes())
915 {
916 mNativeCaps.maxCombinedShaderUniformComponents[shaderType] = maxCombinedUniformComponents;
917 }
918
919 // Total number of resources available to the user are as many as Vulkan allows minus everything
920 // that ANGLE uses internally. That is, one dynamic uniform buffer used per stage for default
921 // uniforms. Additionally, Vulkan uses up to IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS + 1
922 // buffers for transform feedback (Note: +1 is for the "counter" buffer of
923 // VK_EXT_transform_feedback).
924 constexpr uint32_t kReservedPerStageUniformBufferCount = 1;
925 constexpr uint32_t kReservedPerStageBindingCount =
926 kReservedPerStageUniformBufferCount + gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS + 1;
927
928 // Note: maxPerStageResources is required to be at least the sum of per stage UBOs, SSBOs etc
929 // which total a minimum of 44 resources, so no underflow is possible here. Limit the total
930 // number of resources reported by Vulkan to 2 billion though to avoid seeing negative numbers
931 // in applications that take the value as signed int (including dEQP).
932 const uint32_t maxPerStageResources = limitsVk.maxPerStageResources;
933 mNativeCaps.maxCombinedShaderOutputResources =
934 rx::LimitToInt(maxPerStageResources - kReservedPerStageBindingCount);
935
936 // Reserve 1 extra varying for transform feedback capture of gl_Position.
937 constexpr GLint kReservedVaryingComponentsForTransformFeedbackExtension = 4;
938
939 GLint reservedVaryingComponentCount = 0;
940
941 if (getFeatures().supportsTransformFeedbackExtension.enabled &&
942 (!getFeatures().supportsDepthClipControl.enabled ||
943 getFeatures().enablePreRotateSurfaces.enabled ||
944 getFeatures().emulatedPrerotation90.enabled ||
945 getFeatures().emulatedPrerotation180.enabled ||
946 getFeatures().emulatedPrerotation270.enabled))
947 {
948 reservedVaryingComponentCount += kReservedVaryingComponentsForTransformFeedbackExtension;
949 }
950
951 // The max varying vectors should not include gl_Position.
952 // The gles2.0 section 2.10 states that "gl_Position is not a varying variable and does
953 // not count against this limit.", but the Vulkan spec has no such mention in its Built-in
954 // vars section. It is implicit that we need to actually reserve it for Vulkan in that case.
955 //
956 // Note that this exception for gl_Position does not apply to MAX_VERTEX_OUTPUT_COMPONENTS and
957 // similar limits.
958 //
959 // Note also that the reserved components are for transform feedback capture only, so they don't
960 // apply to the _input_ component limit.
961 const GLint reservedVaryingVectorCount = reservedVaryingComponentCount / 4 + 1;
962
963 const GLint maxVaryingCount =
964 std::min(limitsVk.maxVertexOutputComponents, limitsVk.maxFragmentInputComponents);
965 mNativeCaps.maxVaryingVectors =
966 rx::LimitToInt((maxVaryingCount / kComponentsPerVector) - reservedVaryingVectorCount);
967 mNativeCaps.maxVertexOutputComponents =
968 rx::LimitToInt(limitsVk.maxVertexOutputComponents) - reservedVaryingComponentCount;
969 mNativeCaps.maxFragmentInputComponents = rx::LimitToInt(limitsVk.maxFragmentInputComponents);
970
971 mNativeCaps.maxTransformFeedbackInterleavedComponents =
972 gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS;
973 mNativeCaps.maxTransformFeedbackSeparateAttributes =
974 gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS;
975 mNativeCaps.maxTransformFeedbackSeparateComponents =
976 gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS;
977
978 mNativeCaps.minProgramTexelOffset = limitsVk.minTexelOffset;
979 mNativeCaps.maxProgramTexelOffset = rx::LimitToInt(limitsVk.maxTexelOffset);
980
981 const uint32_t sampleCounts =
982 limitsVk.framebufferColorSampleCounts & limitsVk.framebufferDepthSampleCounts &
983 limitsVk.framebufferStencilSampleCounts & vk_gl::kSupportedSampleCounts;
984
985 mNativeCaps.maxSamples = rx::LimitToInt(vk_gl::GetMaxSampleCount(sampleCounts));
986 mNativeCaps.maxFramebufferSamples = mNativeCaps.maxSamples;
987
988 mNativeCaps.subPixelBits = limitsVk.subPixelPrecisionBits;
989
990 if (getFeatures().supportsShaderFramebufferFetch.enabled)
991 {
992 // Enable GL_EXT_shader_framebuffer_fetch
993 // gl::IMPLEMENTATION_MAX_DRAW_BUFFERS is used to support the extension.
994 mNativeExtensions.shaderFramebufferFetchEXT =
995 mNativeCaps.maxDrawBuffers >= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS;
996 mNativeExtensions.shaderFramebufferFetchARM = mNativeExtensions.shaderFramebufferFetchEXT;
997 }
998
999 if (getFeatures().supportsShaderFramebufferFetchNonCoherent.enabled)
1000 {
1001 // Enable GL_EXT_shader_framebuffer_fetch_non_coherent
1002 // For supporting this extension, gl::IMPLEMENTATION_MAX_DRAW_BUFFERS is used.
1003 mNativeExtensions.shaderFramebufferFetchNonCoherentEXT =
1004 mNativeCaps.maxDrawBuffers >= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS;
1005 }
1006
1007 // Enable Program Binary extension.
1008 mNativeExtensions.getProgramBinaryOES = true;
1009 mNativeCaps.programBinaryFormats.push_back(GL_PROGRAM_BINARY_ANGLE);
1010
1011 // Enable Shader Binary extension.
1012 mNativeCaps.shaderBinaryFormats.push_back(GL_SHADER_BINARY_ANGLE);
1013
1014 // Enable GL_NV_pixel_buffer_object extension.
1015 mNativeExtensions.pixelBufferObjectNV = true;
1016
1017 // Enable GL_NV_fence extension.
1018 mNativeExtensions.fenceNV = true;
1019
1020 // Enable GL_EXT_copy_image
1021 mNativeExtensions.copyImageEXT = true;
1022 mNativeExtensions.copyImageOES = true;
1023
1024 // GL_EXT_clip_control
1025 mNativeExtensions.clipControlEXT = true;
1026
1027 // GL_ANGLE_read_only_depth_stencil_feedback_loops
1028 mNativeExtensions.readOnlyDepthStencilFeedbackLoopsANGLE = true;
1029
1030 // Enable GL_EXT_texture_buffer and OES variant. Nearly all formats required for this extension
1031 // are also required to have the UNIFORM_TEXEL_BUFFER feature bit in Vulkan, except for
1032 // R32G32B32_SFLOAT/UINT/SINT which are optional. For many formats, the STORAGE_TEXEL_BUFFER
1033 // feature is optional though. This extension is exposed only if the formats specified in
1034 // EXT_texture_buffer support the necessary feature bits.
1035 //
1036 // glTexBuffer page 187 table 8.18.
1037 // glBindImageTexture page 216 table 8.24.
1038 // https://www.khronos.org/registry/OpenGL/specs/es/3.2/es_spec_3.2.pdf.
1039 // https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/chap43.html#features-required-format-support
1040 // required image and texture access for texture buffer formats are
1041 // texture access image access
1042 // 8-bit components, all required by vulkan.
1043 //
1044 // GL_R8 Y N
1045 // GL_R8I Y N
1046 // GL_R8UI Y N
1047 // GL_RG8 Y N
1048 // GL_RG8I Y N
1049 // GL_RG8UI Y N
1050 // GL_RGBA8 Y Y
1051 // GL_RGBA8I Y Y
1052 // GL_RGBA8UI Y Y
1053 // GL_RGBA8_SNORM N Y
1054 //
1055 // 16-bit components, all required by vulkan.
1056 //
1057 // GL_R16F Y N
1058 // GL_R16I Y N
1059 // GL_R16UI Y N
1060 // GL_RG16F Y N
1061 // GL_RG16I Y N
1062 // GL_RG16UI Y N
1063 // GL_RGBA16F Y Y
1064 // GL_RGBA16I Y Y
1065 // GL_RGBA16UI Y Y
1066 //
1067 // 32-bit components, except RGB32 all others required by vulkan.
1068 // RGB32 is emulated by ANGLE
1069 //
1070 // GL_R32F Y Y
1071 // GL_R32I Y Y
1072 // GL_R32UI Y Y
1073 // GL_RG32F Y N
1074 // GL_RG32I Y N
1075 // GL_RG32UI Y N
1076 // GL_RGB32F Y N
1077 // GL_RGB32I Y N
1078 // GL_RGB32UI Y N
1079 // GL_RGBA32F Y Y
1080 // GL_RGBA32I Y Y
1081 // GL_RGBA32UI Y Y
1082 mNativeExtensions.textureBufferOES = true;
1083 mNativeExtensions.textureBufferEXT = true;
1084 mNativeCaps.maxTextureBufferSize = rx::LimitToInt(limitsVk.maxTexelBufferElements);
1085 mNativeCaps.textureBufferOffsetAlignment =
1086 rx::LimitToInt(limitsVk.minTexelBufferOffsetAlignment);
1087
1088 // Atomic image operations in the vertex and fragment shaders require the
1089 // vertexPipelineStoresAndAtomics and fragmentStoresAndAtomics Vulkan features respectively.
1090 // If either of these features is not present, the number of image uniforms for that stage is
1091 // advertised as zero, so image atomic operations support can be agnostic of shader stages.
1092 //
1093 // GL_OES_shader_image_atomic requires that image atomic functions have support for r32i and
1094 // r32ui formats. These formats have mandatory support for STORAGE_IMAGE_ATOMIC and
1095 // STORAGE_TEXEL_BUFFER_ATOMIC features in Vulkan. Additionally, it requires that
1096 // imageAtomicExchange supports r32f, which is emulated in ANGLE transforming the shader to
1097 // expect r32ui instead.
1098 mNativeExtensions.shaderImageAtomicOES = true;
1099
1100 // Tessellation shaders are required for ES 3.2.
1101 if (mPhysicalDeviceFeatures.tessellationShader)
1102 {
1103 constexpr uint32_t kReservedTessellationDefaultUniformBindingCount = 2;
1104
1105 bool tessellationShaderEnabled =
1106 mFeatures.supportsTransformFeedbackExtension.enabled &&
1107 (mFeatures.supportsPrimitivesGeneratedQuery.enabled ||
1108 mFeatures.exposeNonConformantExtensionsAndVersions.enabled);
1109 mNativeExtensions.tessellationShaderEXT = tessellationShaderEnabled;
1110 mNativeExtensions.tessellationShaderOES = tessellationShaderEnabled;
1111 mNativeCaps.maxPatchVertices = rx::LimitToInt(limitsVk.maxTessellationPatchSize);
1112 mNativeCaps.maxTessPatchComponents =
1113 rx::LimitToInt(limitsVk.maxTessellationControlPerPatchOutputComponents);
1114 mNativeCaps.maxTessGenLevel = rx::LimitToInt(limitsVk.maxTessellationGenerationLevel);
1115
1116 mNativeCaps.maxTessControlInputComponents =
1117 rx::LimitToInt(limitsVk.maxTessellationControlPerVertexInputComponents);
1118 mNativeCaps.maxTessControlOutputComponents =
1119 rx::LimitToInt(limitsVk.maxTessellationControlPerVertexOutputComponents);
1120 mNativeCaps.maxTessControlTotalOutputComponents =
1121 rx::LimitToInt(limitsVk.maxTessellationControlTotalOutputComponents);
1122 mNativeCaps.maxTessEvaluationInputComponents =
1123 rx::LimitToInt(limitsVk.maxTessellationEvaluationInputComponents);
1124 mNativeCaps.maxTessEvaluationOutputComponents =
1125 rx::LimitToInt(limitsVk.maxTessellationEvaluationOutputComponents) -
1126 reservedVaryingComponentCount;
1127
1128 // There is 1 default uniform binding used per tessellation stages.
1129 mNativeCaps.maxCombinedUniformBlocks = rx::LimitToInt(
1130 mNativeCaps.maxCombinedUniformBlocks + kReservedTessellationDefaultUniformBindingCount);
1131 mNativeCaps.maxUniformBufferBindings = rx::LimitToInt(
1132 mNativeCaps.maxUniformBufferBindings + kReservedTessellationDefaultUniformBindingCount);
1133
1134 if (mPhysicalDeviceFeatures.vertexPipelineStoresAndAtomics)
1135 {
1136 mNativeCaps.maxShaderStorageBlocks[gl::ShaderType::TessControl] =
1137 mNativeCaps.maxCombinedShaderOutputResources;
1138 mNativeCaps.maxShaderAtomicCounterBuffers[gl::ShaderType::TessControl] =
1139 maxCombinedAtomicCounterBuffers;
1140
1141 mNativeCaps.maxShaderStorageBlocks[gl::ShaderType::TessEvaluation] =
1142 mNativeCaps.maxCombinedShaderOutputResources;
1143 mNativeCaps.maxShaderAtomicCounterBuffers[gl::ShaderType::TessEvaluation] =
1144 maxCombinedAtomicCounterBuffers;
1145 }
1146
1147 // Reserve a uniform buffer binding for each tessellation stage
1148 if (tessellationShaderEnabled)
1149 {
1150 maxCombinedUniformBuffers -= 2 * kReservedPerStageDefaultUniformBindingCount;
1151 }
1152 }
1153
1154 // Geometry shaders are required for ES 3.2.
1155 if (mPhysicalDeviceFeatures.geometryShader)
1156 {
1157 bool geometryShaderEnabled = mFeatures.supportsTransformFeedbackExtension.enabled &&
1158 (mFeatures.supportsPrimitivesGeneratedQuery.enabled ||
1159 mFeatures.exposeNonConformantExtensionsAndVersions.enabled);
1160 mNativeExtensions.geometryShaderEXT = geometryShaderEnabled;
1161 mNativeExtensions.geometryShaderOES = geometryShaderEnabled;
1162 mNativeCaps.maxFramebufferLayers = rx::LimitToInt(limitsVk.maxFramebufferLayers);
1163
1164 // Use "undefined" which means APP would have to set gl_Layer identically.
1165 mNativeCaps.layerProvokingVertex = GL_UNDEFINED_VERTEX_EXT;
1166
1167 mNativeCaps.maxGeometryInputComponents =
1168 rx::LimitToInt(limitsVk.maxGeometryInputComponents);
1169 mNativeCaps.maxGeometryOutputComponents =
1170 rx::LimitToInt(limitsVk.maxGeometryOutputComponents) - reservedVaryingComponentCount;
1171 mNativeCaps.maxGeometryOutputVertices = rx::LimitToInt(limitsVk.maxGeometryOutputVertices);
1172 mNativeCaps.maxGeometryTotalOutputComponents =
1173 rx::LimitToInt(limitsVk.maxGeometryTotalOutputComponents);
1174 if (mPhysicalDeviceFeatures.vertexPipelineStoresAndAtomics)
1175 {
1176 mNativeCaps.maxShaderStorageBlocks[gl::ShaderType::Geometry] =
1177 mNativeCaps.maxCombinedShaderOutputResources;
1178 mNativeCaps.maxShaderAtomicCounterBuffers[gl::ShaderType::Geometry] =
1179 maxCombinedAtomicCounterBuffers;
1180 }
1181 mNativeCaps.maxGeometryShaderInvocations =
1182 rx::LimitToInt(limitsVk.maxGeometryShaderInvocations);
1183
1184 // Cap maxGeometryInputComponents by maxVertexOutputComponents and
1185 // maxTessellationEvaluationOutputComponents; there can't be more inputs than there are
1186 // outputs in the previous stage.
1187 mNativeCaps.maxGeometryInputComponents =
1188 std::min(mNativeCaps.maxGeometryInputComponents,
1189 std::min(mNativeCaps.maxVertexOutputComponents,
1190 mNativeCaps.maxTessEvaluationOutputComponents));
1191
1192 // Reserve a uniform buffer binding for the geometry stage
1193 if (geometryShaderEnabled)
1194 {
1195 maxCombinedUniformBuffers -= kReservedPerStageDefaultUniformBindingCount;
1196 }
1197 }
1198
1199 mNativeCaps.maxCombinedUniformBlocks = maxCombinedUniformBuffers;
1200 mNativeCaps.maxUniformBufferBindings = maxCombinedUniformBuffers;
1201
1202 // GL_APPLE_clip_distance / GL_EXT_clip_cull_distance / GL_ANGLE_clip_cull_distance
1203 // From the EXT_clip_cull_distance extension spec:
1204 //
1205 // > Modify Section 7.2, "Built-In Constants" (p. 126)
1206 // >
1207 // > const mediump int gl_MaxClipDistances = 8;
1208 // > const mediump int gl_MaxCullDistances = 8;
1209 // > const mediump int gl_MaxCombinedClipAndCullDistances = 8;
1210 constexpr uint32_t kMaxClipDistancePerSpec = 8;
1211 constexpr uint32_t kMaxCullDistancePerSpec = 8;
1212 constexpr uint32_t kMaxCombinedClipAndCullDistancePerSpec = 8;
1213
1214 // TODO: http://anglebug.com/5466
1215 // After implementing EXT_geometry_shader, EXT_clip_cull_distance should be additionally
1216 // implemented to support the geometry shader. Until then, EXT_clip_cull_distance is enabled
1217 // only in the experimental cases.
1218 if (mPhysicalDeviceFeatures.shaderClipDistance &&
1219 limitsVk.maxClipDistances >= kMaxClipDistancePerSpec)
1220 {
1221 mNativeExtensions.clipDistanceAPPLE = true;
1222 mNativeExtensions.clipCullDistanceANGLE = true;
1223 mNativeCaps.maxClipDistances = limitsVk.maxClipDistances;
1224
1225 if (mPhysicalDeviceFeatures.shaderCullDistance &&
1226 limitsVk.maxCullDistances >= kMaxCullDistancePerSpec &&
1227 limitsVk.maxCombinedClipAndCullDistances >= kMaxCombinedClipAndCullDistancePerSpec)
1228 {
1229 mNativeExtensions.clipCullDistanceEXT = true;
1230 mNativeCaps.maxCullDistances = limitsVk.maxCullDistances;
1231 mNativeCaps.maxCombinedClipAndCullDistances = limitsVk.maxCombinedClipAndCullDistances;
1232 }
1233 }
1234
1235 // GL_EXT_blend_func_extended
1236 mNativeExtensions.blendFuncExtendedEXT = mPhysicalDeviceFeatures.dualSrcBlend == VK_TRUE;
1237 mNativeCaps.maxDualSourceDrawBuffers = rx::LimitToInt(limitsVk.maxFragmentDualSrcAttachments);
1238
1239 // GL_ANGLE_relaxed_vertex_attribute_type
1240 mNativeExtensions.relaxedVertexAttributeTypeANGLE = true;
1241
1242 // GL_OVR_multiview*. Bresenham line emulation does not work with multiview. There's no
1243 // limitation in Vulkan to restrict an application to multiview 1.
1244 mNativeExtensions.multiviewOVR =
1245 mFeatures.supportsMultiview.enabled && mFeatures.bresenhamLineRasterization.enabled;
1246 mNativeExtensions.multiview2OVR = mNativeExtensions.multiviewOVR;
1247 // Max views affects the number of Vulkan queries per GL query in render pass, and
1248 // SecondaryCommandBuffer's ResetQueryPoolParams would like this to have an upper limit (of
1249 // 255).
1250 mNativeCaps.maxViews = std::min(mMultiviewProperties.maxMultiviewViewCount, 8u);
1251
1252 // GL_ANGLE_yuv_internal_format
1253 mNativeExtensions.yuvInternalFormatANGLE =
1254 getFeatures().supportsYUVSamplerConversion.enabled && vk::CanSupportYuvInternalFormat(this);
1255
1256 // GL_EXT_primitive_bounding_box
1257 mNativeExtensions.primitiveBoundingBoxEXT = true;
1258
1259 // GL_OES_primitive_bounding_box
1260 mNativeExtensions.primitiveBoundingBoxOES = true;
1261
1262 // GL_EXT_protected_textures
1263 mNativeExtensions.protectedTexturesEXT = mFeatures.supportsProtectedMemory.enabled;
1264
1265 // GL_ANGLE_vulkan_image
1266 mNativeExtensions.vulkanImageANGLE = true;
1267
1268 // GL_ANGLE_texture_usage
1269 mNativeExtensions.textureUsageANGLE = true;
1270
1271 // GL_KHR_parallel_shader_compile
1272 mNativeExtensions.parallelShaderCompileKHR = mFeatures.enableParallelCompileAndLink.enabled;
1273
1274 // GL_NV_read_depth, GL_NV_read_depth_stencil, GL_NV_read_stencil
1275 mNativeExtensions.readDepthNV = true;
1276 mNativeExtensions.readDepthStencilNV = true;
1277 mNativeExtensions.readStencilNV = true;
1278
1279 // GL_QCOM_shading_rate
1280 mNativeExtensions.shadingRateQCOM = mFeatures.supportsFragmentShadingRate.enabled;
1281
1282 // GL_QCOM_framebuffer_foveated
1283 mNativeExtensions.framebufferFoveatedQCOM = mFeatures.supportsFoveatedRendering.enabled;
1284 // GL_QCOM_texture_foveated
1285 mNativeExtensions.textureFoveatedQCOM = mFeatures.supportsFoveatedRendering.enabled;
1286
1287 // GL_ANGLE_shader_pixel_local_storage
1288 mNativeExtensions.shaderPixelLocalStorageANGLE = true;
1289 if (getFeatures().supportsShaderFramebufferFetch.enabled)
1290 {
1291 mNativeExtensions.shaderPixelLocalStorageCoherentANGLE = true;
1292 mNativePLSOptions.type = ShPixelLocalStorageType::FramebufferFetch;
1293 mNativePLSOptions.fragmentSyncType = ShFragmentSynchronizationType::Automatic;
1294 }
1295 else if (getFeatures().supportsFragmentShaderPixelInterlock.enabled)
1296 {
1297 // Use shader images with VK_EXT_fragment_shader_interlock, instead of attachments, if
1298 // they're our only option to be coherent.
1299 mNativeExtensions.shaderPixelLocalStorageCoherentANGLE = true;
1300 mNativePLSOptions.type = ShPixelLocalStorageType::ImageLoadStore;
1301 // GL_ARB_fragment_shader_interlock compiles to SPV_EXT_fragment_shader_interlock.
1302 mNativePLSOptions.fragmentSyncType =
1303 ShFragmentSynchronizationType::FragmentShaderInterlock_ARB_GL;
1304 mNativePLSOptions.supportsNativeRGBA8ImageFormats = true;
1305 }
1306 else
1307 {
1308 mNativePLSOptions.type = ShPixelLocalStorageType::FramebufferFetch;
1309 ASSERT(mNativePLSOptions.fragmentSyncType == ShFragmentSynchronizationType::NotSupported);
1310 }
1311
1312 mNativeExtensions.logicOpANGLE = mPhysicalDeviceFeatures.logicOp == VK_TRUE;
1313
1314 mNativeExtensions.YUVTargetEXT = mFeatures.supportsExternalFormatResolve.enabled;
1315
1316 // Log any missing extensions required for GLES 3.2.
1317 LogMissingExtensionsForGLES32(mNativeExtensions);
1318 }
1319
CanSupportGLES32(const gl::Extensions & nativeExtensions)1320 bool CanSupportGLES32(const gl::Extensions &nativeExtensions)
1321 {
1322 std::vector<bool> requiredExtensions = GetRequiredGLES32ExtensionList(nativeExtensions);
1323 for (uint32_t index = 0; index < requiredExtensions.size(); index++)
1324 {
1325 if (!requiredExtensions[index])
1326 {
1327 return false;
1328 }
1329 }
1330
1331 return true;
1332 }
1333
CanSupportTransformFeedbackExtension(const VkPhysicalDeviceTransformFeedbackFeaturesEXT & xfbFeatures)1334 bool CanSupportTransformFeedbackExtension(
1335 const VkPhysicalDeviceTransformFeedbackFeaturesEXT &xfbFeatures)
1336 {
1337 return xfbFeatures.transformFeedback == VK_TRUE;
1338 }
1339
CanSupportTransformFeedbackEmulation(const VkPhysicalDeviceFeatures & features)1340 bool CanSupportTransformFeedbackEmulation(const VkPhysicalDeviceFeatures &features)
1341 {
1342 return features.vertexPipelineStoresAndAtomics == VK_TRUE;
1343 }
1344
1345 } // namespace vk
1346
1347 namespace egl_vk
1348 {
1349
1350 namespace
1351 {
1352
ComputeMaximumPBufferPixels(const VkPhysicalDeviceProperties & physicalDeviceProperties)1353 EGLint ComputeMaximumPBufferPixels(const VkPhysicalDeviceProperties &physicalDeviceProperties)
1354 {
1355 // EGLints are signed 32-bit integers, it's fairly easy to overflow them, especially since
1356 // Vulkan's minimum guaranteed VkImageFormatProperties::maxResourceSize is 2^31 bytes.
1357 constexpr uint64_t kMaxValueForEGLint =
1358 static_cast<uint64_t>(std::numeric_limits<EGLint>::max());
1359
1360 // TODO(geofflang): Compute the maximum size of a pbuffer by using the maxResourceSize result
1361 // from vkGetPhysicalDeviceImageFormatProperties for both the color and depth stencil format and
1362 // the exact image creation parameters that would be used to create the pbuffer. Because it is
1363 // always safe to return out-of-memory errors on pbuffer allocation, it's fine to simply return
1364 // the number of pixels in a max width by max height pbuffer for now. http://anglebug.com/2622
1365
1366 // Storing the result of squaring a 32-bit unsigned int in a 64-bit unsigned int is safe.
1367 static_assert(std::is_same<decltype(physicalDeviceProperties.limits.maxImageDimension2D),
1368 uint32_t>::value,
1369 "physicalDeviceProperties.limits.maxImageDimension2D expected to be a uint32_t.");
1370 const uint64_t maxDimensionsSquared =
1371 static_cast<uint64_t>(physicalDeviceProperties.limits.maxImageDimension2D) *
1372 static_cast<uint64_t>(physicalDeviceProperties.limits.maxImageDimension2D);
1373
1374 return static_cast<EGLint>(std::min(maxDimensionsSquared, kMaxValueForEGLint));
1375 }
1376
GetMatchFormat(GLenum internalFormat)1377 EGLint GetMatchFormat(GLenum internalFormat)
1378 {
1379 // Lock Surface match format
1380 switch (internalFormat)
1381 {
1382 case GL_RGBA8:
1383 return EGL_FORMAT_RGBA_8888_KHR;
1384 case GL_BGRA8_EXT:
1385 return EGL_FORMAT_RGBA_8888_EXACT_KHR;
1386 case GL_RGB565:
1387 return EGL_FORMAT_RGB_565_EXACT_KHR;
1388 default:
1389 return EGL_NONE;
1390 }
1391 }
1392
1393 // Generates a basic config for a combination of color format, depth stencil format and sample
1394 // count.
GenerateDefaultConfig(DisplayVk * display,const gl::InternalFormat & colorFormat,const gl::InternalFormat & depthStencilFormat,EGLint sampleCount)1395 egl::Config GenerateDefaultConfig(DisplayVk *display,
1396 const gl::InternalFormat &colorFormat,
1397 const gl::InternalFormat &depthStencilFormat,
1398 EGLint sampleCount)
1399 {
1400 const vk::Renderer *renderer = display->getRenderer();
1401
1402 const VkPhysicalDeviceProperties &physicalDeviceProperties =
1403 renderer->getPhysicalDeviceProperties();
1404 gl::Version maxSupportedESVersion = renderer->getMaxSupportedESVersion();
1405 Optional<gl::Version> maxSupportedDesktopVersion = display->getMaxSupportedDesktopVersion();
1406
1407 // ES3 features are required to emulate ES1
1408 EGLint es1Support = (maxSupportedESVersion.major >= 3 ? EGL_OPENGL_ES_BIT : 0);
1409 EGLint es2Support = (maxSupportedESVersion.major >= 2 ? EGL_OPENGL_ES2_BIT : 0);
1410 EGLint es3Support = (maxSupportedESVersion.major >= 3 ? EGL_OPENGL_ES3_BIT : 0);
1411 EGLint desktopSupport = (maxSupportedDesktopVersion.valid() ? EGL_OPENGL_BIT : 0);
1412
1413 egl::Config config;
1414
1415 config.renderTargetFormat = colorFormat.internalFormat;
1416 config.depthStencilFormat = depthStencilFormat.internalFormat;
1417 config.bufferSize = colorFormat.getEGLConfigBufferSize();
1418 config.redSize = colorFormat.redBits;
1419 config.greenSize = colorFormat.greenBits;
1420 config.blueSize = colorFormat.blueBits;
1421 config.alphaSize = colorFormat.alphaBits;
1422 config.alphaMaskSize = 0;
1423 config.bindToTextureRGB = colorFormat.format == GL_RGB;
1424 config.bindToTextureRGBA = colorFormat.format == GL_RGBA || colorFormat.format == GL_BGRA_EXT;
1425 config.colorBufferType = EGL_RGB_BUFFER;
1426 config.configCaveat = GetConfigCaveat(colorFormat.internalFormat);
1427 config.conformant = es1Support | es2Support | es3Support;
1428 config.depthSize = depthStencilFormat.depthBits;
1429 config.stencilSize = depthStencilFormat.stencilBits;
1430 config.level = 0;
1431 config.matchNativePixmap = EGL_NONE;
1432 config.maxPBufferWidth = physicalDeviceProperties.limits.maxImageDimension2D;
1433 config.maxPBufferHeight = physicalDeviceProperties.limits.maxImageDimension2D;
1434 config.maxPBufferPixels = ComputeMaximumPBufferPixels(physicalDeviceProperties);
1435 config.maxSwapInterval = 1;
1436 config.minSwapInterval = 0;
1437 config.nativeRenderable = EGL_TRUE;
1438 config.nativeVisualID = static_cast<EGLint>(GetNativeVisualID(colorFormat));
1439 config.nativeVisualType = EGL_NONE;
1440 config.renderableType = es1Support | es2Support | es3Support | desktopSupport;
1441 config.sampleBuffers = (sampleCount > 0) ? 1 : 0;
1442 config.samples = sampleCount;
1443 config.surfaceType = EGL_WINDOW_BIT | EGL_PBUFFER_BIT;
1444 if (display->getExtensions().mutableRenderBufferKHR)
1445 {
1446 config.surfaceType |= EGL_MUTABLE_RENDER_BUFFER_BIT_KHR;
1447 }
1448 // Vulkan surfaces use a different origin than OpenGL, always prefer to be flipped vertically if
1449 // possible.
1450 config.optimalOrientation = EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE;
1451 config.transparentType = EGL_NONE;
1452 config.transparentRedValue = 0;
1453 config.transparentGreenValue = 0;
1454 config.transparentBlueValue = 0;
1455 config.colorComponentType =
1456 gl_egl::GLComponentTypeToEGLColorComponentType(colorFormat.componentType);
1457 // LockSurface matching
1458 config.matchFormat = GetMatchFormat(colorFormat.internalFormat);
1459 if (config.matchFormat != EGL_NONE)
1460 {
1461 config.surfaceType |= EGL_LOCK_SURFACE_BIT_KHR;
1462 }
1463
1464 // Vulkan always supports off-screen rendering. Check the config with display to see if it can
1465 // also have window support. If not, the following call should automatically remove
1466 // EGL_WINDOW_BIT.
1467 display->checkConfigSupport(&config);
1468
1469 return config;
1470 }
1471
1472 } // anonymous namespace
1473
GenerateConfigs(const GLenum * colorFormats,size_t colorFormatsCount,const GLenum * depthStencilFormats,size_t depthStencilFormatCount,DisplayVk * display)1474 egl::ConfigSet GenerateConfigs(const GLenum *colorFormats,
1475 size_t colorFormatsCount,
1476 const GLenum *depthStencilFormats,
1477 size_t depthStencilFormatCount,
1478 DisplayVk *display)
1479 {
1480 ASSERT(colorFormatsCount > 0);
1481 ASSERT(display != nullptr);
1482
1483 gl::SupportedSampleSet colorSampleCounts;
1484 gl::SupportedSampleSet depthStencilSampleCounts;
1485 gl::SupportedSampleSet sampleCounts;
1486
1487 const VkPhysicalDeviceLimits &limits =
1488 display->getRenderer()->getPhysicalDeviceProperties().limits;
1489 const uint32_t depthStencilSampleCountsLimit = limits.framebufferDepthSampleCounts &
1490 limits.framebufferStencilSampleCounts &
1491 vk_gl::kSupportedSampleCounts;
1492
1493 vk_gl::AddSampleCounts(limits.framebufferColorSampleCounts & vk_gl::kSupportedSampleCounts,
1494 &colorSampleCounts);
1495 vk_gl::AddSampleCounts(depthStencilSampleCountsLimit, &depthStencilSampleCounts);
1496
1497 // Always support 0 samples
1498 colorSampleCounts.insert(0);
1499 depthStencilSampleCounts.insert(0);
1500
1501 std::set_intersection(colorSampleCounts.begin(), colorSampleCounts.end(),
1502 depthStencilSampleCounts.begin(), depthStencilSampleCounts.end(),
1503 std::inserter(sampleCounts, sampleCounts.begin()));
1504
1505 egl::ConfigSet configSet;
1506
1507 for (size_t colorFormatIdx = 0; colorFormatIdx < colorFormatsCount; colorFormatIdx++)
1508 {
1509 const gl::InternalFormat &colorFormatInfo =
1510 gl::GetSizedInternalFormatInfo(colorFormats[colorFormatIdx]);
1511 ASSERT(colorFormatInfo.sized);
1512
1513 for (size_t depthStencilFormatIdx = 0; depthStencilFormatIdx < depthStencilFormatCount;
1514 depthStencilFormatIdx++)
1515 {
1516 const gl::InternalFormat &depthStencilFormatInfo =
1517 gl::GetSizedInternalFormatInfo(depthStencilFormats[depthStencilFormatIdx]);
1518 ASSERT(depthStencilFormats[depthStencilFormatIdx] == GL_NONE ||
1519 depthStencilFormatInfo.sized);
1520
1521 const gl::SupportedSampleSet *configSampleCounts = &sampleCounts;
1522 // If there is no depth/stencil buffer, use the color samples set.
1523 if (depthStencilFormats[depthStencilFormatIdx] == GL_NONE)
1524 {
1525 configSampleCounts = &colorSampleCounts;
1526 }
1527 // If there is no color buffer, use the depth/stencil samples set.
1528 else if (colorFormats[colorFormatIdx] == GL_NONE)
1529 {
1530 configSampleCounts = &depthStencilSampleCounts;
1531 }
1532
1533 for (EGLint sampleCount : *configSampleCounts)
1534 {
1535 egl::Config config = GenerateDefaultConfig(display, colorFormatInfo,
1536 depthStencilFormatInfo, sampleCount);
1537 configSet.add(config);
1538 }
1539 }
1540 }
1541
1542 return configSet;
1543 }
1544
1545 } // namespace egl_vk
1546
1547 } // namespace rx
1548