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