xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/vulkan/DisplayVk.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2016 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // DisplayVk.cpp:
7 //    Implements the class methods for DisplayVk.
8 //
9 
10 #include "libANGLE/renderer/vulkan/DisplayVk.h"
11 
12 #include "common/debug.h"
13 #include "common/system_utils.h"
14 #include "libANGLE/BlobCache.h"
15 #include "libANGLE/Context.h"
16 #include "libANGLE/Display.h"
17 #include "libANGLE/renderer/vulkan/BufferVk.h"
18 #include "libANGLE/renderer/vulkan/ContextVk.h"
19 #include "libANGLE/renderer/vulkan/DeviceVk.h"
20 #include "libANGLE/renderer/vulkan/ImageVk.h"
21 #include "libANGLE/renderer/vulkan/ShareGroupVk.h"
22 #include "libANGLE/renderer/vulkan/SurfaceVk.h"
23 #include "libANGLE/renderer/vulkan/SyncVk.h"
24 #include "libANGLE/renderer/vulkan/TextureVk.h"
25 #include "libANGLE/renderer/vulkan/VkImageImageSiblingVk.h"
26 #include "libANGLE/renderer/vulkan/vk_renderer.h"
27 
28 namespace rx
29 {
30 
31 namespace
32 {
33 // Query surface format and colorspace support.
GetSupportedFormatColorspaces(VkPhysicalDevice physicalDevice,const angle::FeaturesVk & featuresVk,VkSurfaceKHR surface,std::vector<VkSurfaceFormat2KHR> * surfaceFormatsOut)34 void GetSupportedFormatColorspaces(VkPhysicalDevice physicalDevice,
35                                    const angle::FeaturesVk &featuresVk,
36                                    VkSurfaceKHR surface,
37                                    std::vector<VkSurfaceFormat2KHR> *surfaceFormatsOut)
38 {
39     ASSERT(surfaceFormatsOut);
40     surfaceFormatsOut->clear();
41 
42     constexpr VkSurfaceFormat2KHR kSurfaceFormat2Initializer = {
43         VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR,
44         nullptr,
45         {VK_FORMAT_UNDEFINED, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR}};
46 
47     if (featuresVk.supportsSurfaceCapabilities2Extension.enabled)
48     {
49         VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo2 = {};
50         surfaceInfo2.sType          = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR;
51         surfaceInfo2.surface        = surface;
52         uint32_t surfaceFormatCount = 0;
53 
54         // Query the count first
55         VkResult result = vkGetPhysicalDeviceSurfaceFormats2KHR(physicalDevice, &surfaceInfo2,
56                                                                 &surfaceFormatCount, nullptr);
57         ASSERT(result == VK_SUCCESS);
58         ASSERT(surfaceFormatCount > 0);
59 
60         // Query the VkSurfaceFormat2KHR list
61         std::vector<VkSurfaceFormat2KHR> surfaceFormats2(surfaceFormatCount,
62                                                          kSurfaceFormat2Initializer);
63         result = vkGetPhysicalDeviceSurfaceFormats2KHR(physicalDevice, &surfaceInfo2,
64                                                        &surfaceFormatCount, surfaceFormats2.data());
65         ASSERT(result == VK_SUCCESS);
66 
67         *surfaceFormatsOut = std::move(surfaceFormats2);
68     }
69     else
70     {
71         uint32_t surfaceFormatCount = 0;
72         // Query the count first
73         VkResult result = vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface,
74                                                                &surfaceFormatCount, nullptr);
75         ASSERT(result == VK_SUCCESS);
76 
77         // Query the VkSurfaceFormatKHR list
78         std::vector<VkSurfaceFormatKHR> surfaceFormats(surfaceFormatCount);
79         result = vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &surfaceFormatCount,
80                                                       surfaceFormats.data());
81         ASSERT(result == VK_SUCCESS);
82 
83         // Copy over data from std::vector<VkSurfaceFormatKHR> to std::vector<VkSurfaceFormat2KHR>
84         std::vector<VkSurfaceFormat2KHR> surfaceFormats2(surfaceFormatCount,
85                                                          kSurfaceFormat2Initializer);
86         for (size_t index = 0; index < surfaceFormatCount; index++)
87         {
88             surfaceFormats2[index].surfaceFormat.format = surfaceFormats[index].format;
89         }
90 
91         *surfaceFormatsOut = std::move(surfaceFormats2);
92     }
93 }
94 
ShouldLoadDebugLayers(const egl::AttributeMap & attribs)95 vk::UseDebugLayers ShouldLoadDebugLayers(const egl::AttributeMap &attribs)
96 {
97     EGLAttrib debugSetting =
98         attribs.get(EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE, EGL_DONT_CARE);
99 
100 #if defined(ANGLE_ENABLE_VULKAN_VALIDATION_LAYERS_BY_DEFAULT)
101     const bool yes = ShouldUseDebugLayers(attribs);
102 #else
103     const bool yes = debugSetting == EGL_TRUE;
104 #endif  // defined(ANGLE_ENABLE_VULKAN_VALIDATION_LAYERS_BY_DEFAULT)
105 
106     const bool ifAvailable = debugSetting == EGL_DONT_CARE;
107 
108     return yes && ifAvailable ? vk::UseDebugLayers::YesIfAvailable
109            : yes              ? vk::UseDebugLayers::Yes
110                               : vk::UseDebugLayers::No;
111 }
112 
ChooseICDFromAttribs(const egl::AttributeMap & attribs)113 angle::vk::ICD ChooseICDFromAttribs(const egl::AttributeMap &attribs)
114 {
115 #if !defined(ANGLE_PLATFORM_ANDROID)
116     // Mock ICD does not currently run on Android
117     EGLAttrib deviceType = attribs.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE,
118                                        EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE);
119 
120     switch (deviceType)
121     {
122         case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE:
123             break;
124         case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE:
125             return angle::vk::ICD::Mock;
126         case EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE:
127             return angle::vk::ICD::SwiftShader;
128         default:
129             UNREACHABLE();
130             break;
131     }
132 #endif  // !defined(ANGLE_PLATFORM_ANDROID)
133 
134     return angle::vk::ICD::Default;
135 }
136 
InstallDebugAnnotator(egl::Display * display,vk::Renderer * renderer)137 void InstallDebugAnnotator(egl::Display *display, vk::Renderer *renderer)
138 {
139     bool installedAnnotator = false;
140 
141     // Ensure the appropriate global DebugAnnotator is used
142     ASSERT(renderer);
143     renderer->setGlobalDebugAnnotator(&installedAnnotator);
144 
145     if (!installedAnnotator)
146     {
147         std::unique_lock<angle::SimpleMutex> lock(gl::GetDebugMutex());
148         display->setGlobalDebugAnnotator();
149     }
150 }
151 }  // namespace
152 
DisplayVk(const egl::DisplayState & state)153 DisplayVk::DisplayVk(const egl::DisplayState &state)
154     : DisplayImpl(state),
155       vk::Context(new vk::Renderer()),
156       mScratchBuffer(1000u),
157       mSupportedColorspaceFormatsMap{}
158 {}
159 
~DisplayVk()160 DisplayVk::~DisplayVk()
161 {
162     delete mRenderer;
163 }
164 
initialize(egl::Display * display)165 egl::Error DisplayVk::initialize(egl::Display *display)
166 {
167     ASSERT(mRenderer != nullptr && display != nullptr);
168     const egl::AttributeMap &attribs = display->getAttributeMap();
169 
170     const vk::UseDebugLayers useDebugLayers = ShouldLoadDebugLayers(attribs);
171     const angle::vk::ICD desiredICD         = ChooseICDFromAttribs(attribs);
172     const uint32_t preferredVendorId =
173         static_cast<uint32_t>(attribs.get(EGL_PLATFORM_ANGLE_DEVICE_ID_HIGH_ANGLE, 0));
174     const uint32_t preferredDeviceId =
175         static_cast<uint32_t>(attribs.get(EGL_PLATFORM_ANGLE_DEVICE_ID_LOW_ANGLE, 0));
176 
177     angle::Result result = mRenderer->initialize(
178         this, this, desiredICD, preferredVendorId, preferredDeviceId, useDebugLayers,
179         getWSIExtension(), getWSILayer(), getWindowSystem(), mState.featureOverrides);
180     ANGLE_TRY(angle::ToEGL(result, EGL_NOT_INITIALIZED));
181 
182     mDeviceQueueIndex = mRenderer->getDeviceQueueIndex(egl::ContextPriority::Medium);
183 
184     InstallDebugAnnotator(display, mRenderer);
185 
186     // Query and cache supported surface format and colorspace for later use.
187     initSupportedSurfaceFormatColorspaces();
188     return egl::NoError();
189 }
190 
terminate()191 void DisplayVk::terminate()
192 {
193     mRenderer->reloadVolkIfNeeded();
194 
195     ASSERT(mRenderer);
196     mRenderer->onDestroy(this);
197 }
198 
makeCurrent(egl::Display * display,egl::Surface *,egl::Surface *,gl::Context *)199 egl::Error DisplayVk::makeCurrent(egl::Display *display,
200                                   egl::Surface * /*drawSurface*/,
201                                   egl::Surface * /*readSurface*/,
202                                   gl::Context * /*context*/)
203 {
204     InstallDebugAnnotator(display, mRenderer);
205     return egl::NoError();
206 }
207 
testDeviceLost()208 bool DisplayVk::testDeviceLost()
209 {
210     return mRenderer->isDeviceLost();
211 }
212 
restoreLostDevice(const egl::Display * display)213 egl::Error DisplayVk::restoreLostDevice(const egl::Display *display)
214 {
215     // A vulkan device cannot be restored, the entire renderer would have to be re-created along
216     // with any other EGL objects that reference it.
217     return egl::EglBadDisplay();
218 }
219 
getRendererDescription()220 std::string DisplayVk::getRendererDescription()
221 {
222     if (mRenderer)
223     {
224         return mRenderer->getRendererDescription();
225     }
226     return std::string();
227 }
228 
getVendorString()229 std::string DisplayVk::getVendorString()
230 {
231     if (mRenderer)
232     {
233         return mRenderer->getVendorString();
234     }
235     return std::string();
236 }
237 
getVersionString(bool includeFullVersion)238 std::string DisplayVk::getVersionString(bool includeFullVersion)
239 {
240     if (mRenderer)
241     {
242         return mRenderer->getVersionString(includeFullVersion);
243     }
244     return std::string();
245 }
246 
createDevice()247 DeviceImpl *DisplayVk::createDevice()
248 {
249     return new DeviceVk();
250 }
251 
waitClient(const gl::Context * context)252 egl::Error DisplayVk::waitClient(const gl::Context *context)
253 {
254     ANGLE_TRACE_EVENT0("gpu.angle", "DisplayVk::waitClient");
255     ContextVk *contextVk = vk::GetImpl(context);
256     return angle::ToEGL(contextVk->finishImpl(RenderPassClosureReason::EGLWaitClient),
257                         EGL_BAD_ACCESS);
258 }
259 
waitNative(const gl::Context * context,EGLint engine)260 egl::Error DisplayVk::waitNative(const gl::Context *context, EGLint engine)
261 {
262     ANGLE_TRACE_EVENT0("gpu.angle", "DisplayVk::waitNative");
263     return angle::ResultToEGL(waitNativeImpl());
264 }
265 
waitNativeImpl()266 angle::Result DisplayVk::waitNativeImpl()
267 {
268     return angle::Result::Continue;
269 }
270 
createWindowSurface(const egl::SurfaceState & state,EGLNativeWindowType window,const egl::AttributeMap & attribs)271 SurfaceImpl *DisplayVk::createWindowSurface(const egl::SurfaceState &state,
272                                             EGLNativeWindowType window,
273                                             const egl::AttributeMap &attribs)
274 {
275     return createWindowSurfaceVk(state, window);
276 }
277 
createPbufferSurface(const egl::SurfaceState & state,const egl::AttributeMap & attribs)278 SurfaceImpl *DisplayVk::createPbufferSurface(const egl::SurfaceState &state,
279                                              const egl::AttributeMap &attribs)
280 {
281     ASSERT(mRenderer);
282     return new OffscreenSurfaceVk(state, mRenderer);
283 }
284 
createPbufferFromClientBuffer(const egl::SurfaceState & state,EGLenum buftype,EGLClientBuffer clientBuffer,const egl::AttributeMap & attribs)285 SurfaceImpl *DisplayVk::createPbufferFromClientBuffer(const egl::SurfaceState &state,
286                                                       EGLenum buftype,
287                                                       EGLClientBuffer clientBuffer,
288                                                       const egl::AttributeMap &attribs)
289 {
290     UNIMPLEMENTED();
291     return static_cast<SurfaceImpl *>(0);
292 }
293 
createPixmapSurface(const egl::SurfaceState & state,NativePixmapType nativePixmap,const egl::AttributeMap & attribs)294 SurfaceImpl *DisplayVk::createPixmapSurface(const egl::SurfaceState &state,
295                                             NativePixmapType nativePixmap,
296                                             const egl::AttributeMap &attribs)
297 {
298     UNIMPLEMENTED();
299     return static_cast<SurfaceImpl *>(0);
300 }
301 
createImage(const egl::ImageState & state,const gl::Context * context,EGLenum target,const egl::AttributeMap & attribs)302 ImageImpl *DisplayVk::createImage(const egl::ImageState &state,
303                                   const gl::Context *context,
304                                   EGLenum target,
305                                   const egl::AttributeMap &attribs)
306 {
307     return new ImageVk(state, context);
308 }
309 
createShareGroup(const egl::ShareGroupState & state)310 ShareGroupImpl *DisplayVk::createShareGroup(const egl::ShareGroupState &state)
311 {
312     return new ShareGroupVk(state, mRenderer);
313 }
314 
isConfigFormatSupported(VkFormat format) const315 bool DisplayVk::isConfigFormatSupported(VkFormat format) const
316 {
317     // Requires VK_GOOGLE_surfaceless_query extension to be supported.
318     ASSERT(mRenderer->getFeatures().supportsSurfacelessQueryExtension.enabled);
319 
320     // A format is considered supported if it is supported in atleast 1 colorspace.
321     using ColorspaceFormatSetItem =
322         const std::pair<const VkColorSpaceKHR, std::unordered_set<VkFormat>>;
323     for (ColorspaceFormatSetItem &colorspaceFormatSetItem : mSupportedColorspaceFormatsMap)
324     {
325         if (colorspaceFormatSetItem.second.count(format) > 0)
326         {
327             return true;
328         }
329     }
330 
331     return false;
332 }
333 
isSurfaceFormatColorspacePairSupported(VkSurfaceKHR surface,VkFormat format,VkColorSpaceKHR colorspace) const334 bool DisplayVk::isSurfaceFormatColorspacePairSupported(VkSurfaceKHR surface,
335                                                        VkFormat format,
336                                                        VkColorSpaceKHR colorspace) const
337 {
338     if (mSupportedColorspaceFormatsMap.size() > 0)
339     {
340         return mSupportedColorspaceFormatsMap.count(colorspace) > 0 &&
341                mSupportedColorspaceFormatsMap.at(colorspace).count(format) > 0;
342     }
343     else
344     {
345         const angle::FeaturesVk &featuresVk = mRenderer->getFeatures();
346         std::vector<VkSurfaceFormat2KHR> surfaceFormats;
347         GetSupportedFormatColorspaces(mRenderer->getPhysicalDevice(), featuresVk, surface,
348                                       &surfaceFormats);
349 
350         if (!featuresVk.supportsSurfaceCapabilities2Extension.enabled)
351         {
352             if (surfaceFormats.size() == 1u &&
353                 surfaceFormats[0].surfaceFormat.format == VK_FORMAT_UNDEFINED)
354             {
355                 return true;
356             }
357         }
358 
359         for (const VkSurfaceFormat2KHR &surfaceFormat : surfaceFormats)
360         {
361             if (surfaceFormat.surfaceFormat.format == format &&
362                 surfaceFormat.surfaceFormat.colorSpace == colorspace)
363             {
364                 return true;
365             }
366         }
367     }
368 
369     return false;
370 }
371 
isColorspaceSupported(VkColorSpaceKHR colorspace) const372 bool DisplayVk::isColorspaceSupported(VkColorSpaceKHR colorspace) const
373 {
374     return mSupportedColorspaceFormatsMap.count(colorspace) > 0;
375 }
376 
initSupportedSurfaceFormatColorspaces()377 void DisplayVk::initSupportedSurfaceFormatColorspaces()
378 {
379     const angle::FeaturesVk &featuresVk = mRenderer->getFeatures();
380     if (featuresVk.supportsSurfacelessQueryExtension.enabled &&
381         featuresVk.supportsSurfaceCapabilities2Extension.enabled)
382     {
383         // Use the VK_GOOGLE_surfaceless_query extension to query supported surface formats and
384         // colorspaces by using a VK_NULL_HANDLE for the VkSurfaceKHR handle.
385         std::vector<VkSurfaceFormat2KHR> surfaceFormats;
386         GetSupportedFormatColorspaces(mRenderer->getPhysicalDevice(), featuresVk, VK_NULL_HANDLE,
387                                       &surfaceFormats);
388         for (const VkSurfaceFormat2KHR &surfaceFormat : surfaceFormats)
389         {
390             // Cache supported VkFormat and VkColorSpaceKHR for later use
391             VkFormat format            = surfaceFormat.surfaceFormat.format;
392             VkColorSpaceKHR colorspace = surfaceFormat.surfaceFormat.colorSpace;
393 
394             ASSERT(format != VK_FORMAT_UNDEFINED);
395 
396             mSupportedColorspaceFormatsMap[colorspace].insert(format);
397         }
398 
399         ASSERT(mSupportedColorspaceFormatsMap.size() > 0);
400     }
401     else
402     {
403         mSupportedColorspaceFormatsMap.clear();
404     }
405 }
406 
createContext(const gl::State & state,gl::ErrorSet * errorSet,const egl::Config * configuration,const gl::Context * shareContext,const egl::AttributeMap & attribs)407 ContextImpl *DisplayVk::createContext(const gl::State &state,
408                                       gl::ErrorSet *errorSet,
409                                       const egl::Config *configuration,
410                                       const gl::Context *shareContext,
411                                       const egl::AttributeMap &attribs)
412 {
413     return new ContextVk(state, errorSet, mRenderer);
414 }
415 
createStreamProducerD3DTexture(egl::Stream::ConsumerType consumerType,const egl::AttributeMap & attribs)416 StreamProducerImpl *DisplayVk::createStreamProducerD3DTexture(
417     egl::Stream::ConsumerType consumerType,
418     const egl::AttributeMap &attribs)
419 {
420     UNIMPLEMENTED();
421     return static_cast<StreamProducerImpl *>(0);
422 }
423 
createSync()424 EGLSyncImpl *DisplayVk::createSync()
425 {
426     return new EGLSyncVk();
427 }
428 
getMaxSupportedESVersion() const429 gl::Version DisplayVk::getMaxSupportedESVersion() const
430 {
431     return mRenderer->getMaxSupportedESVersion();
432 }
433 
getMaxConformantESVersion() const434 gl::Version DisplayVk::getMaxConformantESVersion() const
435 {
436     return mRenderer->getMaxConformantESVersion();
437 }
438 
validateImageClientBuffer(const gl::Context * context,EGLenum target,EGLClientBuffer clientBuffer,const egl::AttributeMap & attribs) const439 egl::Error DisplayVk::validateImageClientBuffer(const gl::Context *context,
440                                                 EGLenum target,
441                                                 EGLClientBuffer clientBuffer,
442                                                 const egl::AttributeMap &attribs) const
443 {
444     switch (target)
445     {
446         case EGL_VULKAN_IMAGE_ANGLE:
447         {
448             VkImage *vkImage = reinterpret_cast<VkImage *>(clientBuffer);
449             if (!vkImage || *vkImage == VK_NULL_HANDLE)
450             {
451                 return egl::EglBadParameter() << "clientBuffer is invalid.";
452             }
453 
454             GLenum internalFormat =
455                 static_cast<GLenum>(attribs.get(EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_NONE));
456             switch (internalFormat)
457             {
458                 case GL_RGBA:
459                 case GL_BGRA_EXT:
460                 case GL_RGB:
461                 case GL_RED_EXT:
462                 case GL_RG_EXT:
463                 case GL_RGB10_A2_EXT:
464                 case GL_R16_EXT:
465                 case GL_RG16_EXT:
466                 case GL_NONE:
467                     break;
468                 default:
469                     return egl::EglBadParameter() << "Invalid EGLImage texture internal format: 0x"
470                                                   << std::hex << internalFormat;
471             }
472 
473             uint64_t hi = static_cast<uint64_t>(attribs.get(EGL_VULKAN_IMAGE_CREATE_INFO_HI_ANGLE));
474             uint64_t lo = static_cast<uint64_t>(attribs.get(EGL_VULKAN_IMAGE_CREATE_INFO_LO_ANGLE));
475             uint64_t info = ((hi & 0xffffffff) << 32) | (lo & 0xffffffff);
476             if (reinterpret_cast<const VkImageCreateInfo *>(info)->sType !=
477                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO)
478             {
479                 return egl::EglBadParameter()
480                        << "EGL_VULKAN_IMAGE_CREATE_INFO_HI_ANGLE and "
481                           "EGL_VULKAN_IMAGE_CREATE_INFO_LO_ANGLE are not pointing to a "
482                           "valid VkImageCreateInfo structure.";
483             }
484 
485             return egl::NoError();
486         }
487         default:
488             return DisplayImpl::validateImageClientBuffer(context, target, clientBuffer, attribs);
489     }
490 }
491 
createExternalImageSibling(const gl::Context * context,EGLenum target,EGLClientBuffer buffer,const egl::AttributeMap & attribs)492 ExternalImageSiblingImpl *DisplayVk::createExternalImageSibling(const gl::Context *context,
493                                                                 EGLenum target,
494                                                                 EGLClientBuffer buffer,
495                                                                 const egl::AttributeMap &attribs)
496 {
497     switch (target)
498     {
499         case EGL_VULKAN_IMAGE_ANGLE:
500             return new VkImageImageSiblingVk(buffer, attribs);
501         default:
502             return DisplayImpl::createExternalImageSibling(context, target, buffer, attribs);
503     }
504 }
505 
generateExtensions(egl::DisplayExtensions * outExtensions) const506 void DisplayVk::generateExtensions(egl::DisplayExtensions *outExtensions) const
507 {
508     outExtensions->createContextRobustness  = getRenderer()->getNativeExtensions().robustnessAny();
509     outExtensions->surfaceOrientation       = true;
510     outExtensions->displayTextureShareGroup = true;
511     outExtensions->displaySemaphoreShareGroup        = true;
512     outExtensions->robustResourceInitializationANGLE = true;
513 
514     // The Vulkan implementation will always say that EGL_KHR_swap_buffers_with_damage is supported.
515     // When the Vulkan driver supports VK_KHR_incremental_present, it will use it.  Otherwise, it
516     // will ignore the hint and do a regular swap.
517     outExtensions->swapBuffersWithDamage = true;
518 
519     outExtensions->fenceSync            = true;
520     outExtensions->waitSync             = true;
521     outExtensions->globalFenceSyncANGLE = true;
522 
523     outExtensions->image                 = true;
524     outExtensions->imageBase             = true;
525     outExtensions->imagePixmap           = false;  // ANGLE does not support pixmaps
526     outExtensions->glTexture2DImage      = true;
527     outExtensions->glTextureCubemapImage = true;
528     outExtensions->glTexture3DImage      = getFeatures().supportsSampler2dViewOf3d.enabled;
529     outExtensions->glRenderbufferImage = true;
530     outExtensions->imageNativeBuffer     = getFeatures().supportsAndroidHardwareBuffer.enabled;
531     outExtensions->surfacelessContext = true;
532     outExtensions->glColorspace       = true;
533     outExtensions->imageGlColorspace =
534         outExtensions->glColorspace && getFeatures().supportsImageFormatList.enabled;
535 
536 #if defined(ANGLE_PLATFORM_ANDROID)
537     outExtensions->getNativeClientBufferANDROID = true;
538     outExtensions->framebufferTargetANDROID     = true;
539 
540     // Only expose EGL_ANDROID_front_buffer_auto_refresh on Android and when Vulkan supports
541     // VK_EXT_swapchain_maintenance1 (supportsSwapchainMaintenance1 feature), since we know that
542     // VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR and VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR
543     // are compatible on Android (does not require swapchain recreation).
544     outExtensions->frontBufferAutoRefreshANDROID =
545         getFeatures().supportsSwapchainMaintenance1.enabled;
546 #endif  // defined(ANGLE_PLATFORM_ANDROID)
547 
548     // EGL_EXT_image_dma_buf_import is only exposed if EGL_EXT_image_dma_buf_import_modifiers can
549     // also be exposed.  The Vulkan extensions that support these EGL extensions are not split in
550     // the same way; both Vulkan extensions are needed for EGL_EXT_image_dma_buf_import, and with
551     // both Vulkan extensions, EGL_EXT_image_dma_buf_import_modifiers is also supportable.
552     outExtensions->imageDmaBufImportEXT =
553         getFeatures().supportsExternalMemoryDmaBufAndModifiers.enabled;
554     outExtensions->imageDmaBufImportModifiersEXT = outExtensions->imageDmaBufImportEXT;
555 
556     // Disable context priority when non-zero memory init is enabled. This enforces a queue order.
557     outExtensions->contextPriority = !getFeatures().allocateNonZeroMemory.enabled;
558     outExtensions->noConfigContext = true;
559 
560 #if defined(ANGLE_PLATFORM_ANDROID) || defined(ANGLE_PLATFORM_LINUX)
561     outExtensions->nativeFenceSyncANDROID = getFeatures().supportsAndroidNativeFenceSync.enabled;
562 #endif  // defined(ANGLE_PLATFORM_ANDROID) || defined(ANGLE_PLATFORM_LINUX)
563 
564 #if defined(ANGLE_PLATFORM_GGP)
565     outExtensions->ggpStreamDescriptor = true;
566     outExtensions->swapWithFrameToken  = getFeatures().supportsGGPFrameToken.enabled;
567 #endif  // defined(ANGLE_PLATFORM_GGP)
568 
569     outExtensions->bufferAgeEXT = true;
570 
571     outExtensions->protectedContentEXT = (getFeatures().supportsProtectedMemory.enabled &&
572                                           getFeatures().supportsSurfaceProtectedSwapchains.enabled);
573 
574     outExtensions->createSurfaceSwapIntervalANGLE = true;
575 
576     outExtensions->mutableRenderBufferKHR =
577         getFeatures().supportsSharedPresentableImageExtension.enabled;
578 
579     outExtensions->vulkanImageANGLE = true;
580 
581     outExtensions->lockSurface3KHR = getFeatures().supportsLockSurfaceExtension.enabled;
582 
583     outExtensions->partialUpdateKHR = true;
584 
585     outExtensions->timestampSurfaceAttributeANGLE =
586         getFeatures().supportsTimestampSurfaceAttribute.enabled;
587 
588     outExtensions->eglColorspaceAttributePassthroughANGLE =
589         outExtensions->glColorspace && getFeatures().eglColorspaceAttributePassthrough.enabled;
590 
591     // If EGL_KHR_gl_colorspace extension is supported check if other colorspace extensions
592     // can be supported as well.
593     if (outExtensions->glColorspace)
594     {
595         if (isColorspaceSupported(VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT))
596         {
597             outExtensions->glColorspaceDisplayP3            = true;
598             outExtensions->glColorspaceDisplayP3Passthrough = true;
599         }
600 
601         outExtensions->glColorspaceDisplayP3Linear =
602             isColorspaceSupported(VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT);
603         outExtensions->glColorspaceScrgb =
604             isColorspaceSupported(VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT);
605         outExtensions->glColorspaceScrgbLinear =
606             isColorspaceSupported(VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT);
607         outExtensions->glColorspaceBt2020Linear =
608             isColorspaceSupported(VK_COLOR_SPACE_BT2020_LINEAR_EXT);
609         outExtensions->glColorspaceBt2020Pq =
610             isColorspaceSupported(VK_COLOR_SPACE_HDR10_ST2084_EXT);
611         outExtensions->glColorspaceBt2020Hlg = isColorspaceSupported(VK_COLOR_SPACE_HDR10_HLG_EXT);
612     }
613 }
614 
generateCaps(egl::Caps * outCaps) const615 void DisplayVk::generateCaps(egl::Caps *outCaps) const
616 {
617     outCaps->textureNPOT = true;
618     outCaps->stencil8    = getRenderer()->getNativeExtensions().textureStencil8OES;
619 }
620 
getWSILayer() const621 const char *DisplayVk::getWSILayer() const
622 {
623     return nullptr;
624 }
625 
handleError(VkResult result,const char * file,const char * function,unsigned int line)626 void DisplayVk::handleError(VkResult result,
627                             const char *file,
628                             const char *function,
629                             unsigned int line)
630 {
631     ASSERT(result != VK_SUCCESS);
632 
633     std::stringstream errorStream;
634     errorStream << "Internal Vulkan error (" << result << "): " << VulkanResultString(result)
635                 << ", in " << file << ", " << function << ":" << line << ".";
636     std::string errorString = errorStream.str();
637 
638     if (result == VK_ERROR_DEVICE_LOST)
639     {
640         WARN() << errorString;
641         mRenderer->notifyDeviceLost();
642     }
643 
644     // Note: the errorCode will be set later in angle::ToEGL where it's available.
645     *egl::Display::GetCurrentThreadErrorScratchSpace() = egl::Error(0, 0, std::move(errorString));
646 }
647 
initializeFrontendFeatures(angle::FrontendFeatures * features) const648 void DisplayVk::initializeFrontendFeatures(angle::FrontendFeatures *features) const
649 {
650     mRenderer->initializeFrontendFeatures(features);
651 }
652 
populateFeatureList(angle::FeatureList * features)653 void DisplayVk::populateFeatureList(angle::FeatureList *features)
654 {
655     mRenderer->getFeatures().populateFeatureList(features);
656 }
657 
658 // vk::GlobalOps
putBlob(const angle::BlobCacheKey & key,const angle::MemoryBuffer & value)659 void DisplayVk::putBlob(const angle::BlobCacheKey &key, const angle::MemoryBuffer &value)
660 {
661     getBlobCache()->putApplication(nullptr, key, value);
662 }
663 
getBlob(const angle::BlobCacheKey & key,angle::BlobCacheValue * valueOut)664 bool DisplayVk::getBlob(const angle::BlobCacheKey &key, angle::BlobCacheValue *valueOut)
665 {
666     return getBlobCache()->get(nullptr, &mScratchBuffer, key, valueOut);
667 }
668 
postMultiThreadWorkerTask(const std::shared_ptr<angle::Closure> & task)669 std::shared_ptr<angle::WaitableEvent> DisplayVk::postMultiThreadWorkerTask(
670     const std::shared_ptr<angle::Closure> &task)
671 {
672     return mState.multiThreadPool->postWorkerTask(task);
673 }
674 
notifyDeviceLost()675 void DisplayVk::notifyDeviceLost()
676 {
677     mState.notifyDeviceLost();
678 }
679 }  // namespace rx
680