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