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