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
ShouldUseValidationLayers(const egl::AttributeMap & attribs)95 vk::UseValidationLayers ShouldUseValidationLayers(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::UseValidationLayers::YesIfAvailable
109 : yes ? vk::UseValidationLayers::Yes
110 : vk::UseValidationLayers::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::UseValidationLayers useValidationLayers = ShouldUseValidationLayers(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, useValidationLayers,
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);
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
getMaxSupportedDesktopVersion() const439 Optional<gl::Version> DisplayVk::getMaxSupportedDesktopVersion() const
440 {
441 return gl::Version{4, 6};
442 }
443
validateImageClientBuffer(const gl::Context * context,EGLenum target,EGLClientBuffer clientBuffer,const egl::AttributeMap & attribs) const444 egl::Error DisplayVk::validateImageClientBuffer(const gl::Context *context,
445 EGLenum target,
446 EGLClientBuffer clientBuffer,
447 const egl::AttributeMap &attribs) const
448 {
449 switch (target)
450 {
451 case EGL_VULKAN_IMAGE_ANGLE:
452 {
453 VkImage *vkImage = reinterpret_cast<VkImage *>(clientBuffer);
454 if (!vkImage || *vkImage == VK_NULL_HANDLE)
455 {
456 return egl::EglBadParameter() << "clientBuffer is invalid.";
457 }
458
459 GLenum internalFormat =
460 static_cast<GLenum>(attribs.get(EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_NONE));
461 switch (internalFormat)
462 {
463 case GL_RGBA:
464 case GL_BGRA_EXT:
465 case GL_RGB:
466 case GL_RED_EXT:
467 case GL_RG_EXT:
468 case GL_RGB10_A2_EXT:
469 case GL_R16_EXT:
470 case GL_RG16_EXT:
471 case GL_NONE:
472 break;
473 default:
474 return egl::EglBadParameter() << "Invalid EGLImage texture internal format: 0x"
475 << std::hex << internalFormat;
476 }
477
478 uint64_t hi = static_cast<uint64_t>(attribs.get(EGL_VULKAN_IMAGE_CREATE_INFO_HI_ANGLE));
479 uint64_t lo = static_cast<uint64_t>(attribs.get(EGL_VULKAN_IMAGE_CREATE_INFO_LO_ANGLE));
480 uint64_t info = ((hi & 0xffffffff) << 32) | (lo & 0xffffffff);
481 if (reinterpret_cast<const VkImageCreateInfo *>(info)->sType !=
482 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO)
483 {
484 return egl::EglBadParameter()
485 << "EGL_VULKAN_IMAGE_CREATE_INFO_HI_ANGLE and "
486 "EGL_VULKAN_IMAGE_CREATE_INFO_LO_ANGLE are not pointing to a "
487 "valid VkImageCreateInfo structure.";
488 }
489
490 return egl::NoError();
491 }
492 default:
493 return DisplayImpl::validateImageClientBuffer(context, target, clientBuffer, attribs);
494 }
495 }
496
createExternalImageSibling(const gl::Context * context,EGLenum target,EGLClientBuffer buffer,const egl::AttributeMap & attribs)497 ExternalImageSiblingImpl *DisplayVk::createExternalImageSibling(const gl::Context *context,
498 EGLenum target,
499 EGLClientBuffer buffer,
500 const egl::AttributeMap &attribs)
501 {
502 switch (target)
503 {
504 case EGL_VULKAN_IMAGE_ANGLE:
505 return new VkImageImageSiblingVk(buffer, attribs);
506 default:
507 return DisplayImpl::createExternalImageSibling(context, target, buffer, attribs);
508 }
509 }
510
generateExtensions(egl::DisplayExtensions * outExtensions) const511 void DisplayVk::generateExtensions(egl::DisplayExtensions *outExtensions) const
512 {
513 outExtensions->createContextRobustness = getRenderer()->getNativeExtensions().robustnessAny();
514 outExtensions->surfaceOrientation = true;
515 outExtensions->displayTextureShareGroup = true;
516 outExtensions->displaySemaphoreShareGroup = true;
517 outExtensions->robustResourceInitializationANGLE = true;
518
519 // The Vulkan implementation will always say that EGL_KHR_swap_buffers_with_damage is supported.
520 // When the Vulkan driver supports VK_KHR_incremental_present, it will use it. Otherwise, it
521 // will ignore the hint and do a regular swap.
522 outExtensions->swapBuffersWithDamage = true;
523
524 outExtensions->fenceSync = true;
525 outExtensions->waitSync = true;
526 outExtensions->globalFenceSyncANGLE = true;
527
528 outExtensions->image = true;
529 outExtensions->imageBase = true;
530 outExtensions->imagePixmap = false; // ANGLE does not support pixmaps
531 outExtensions->glTexture2DImage = true;
532 outExtensions->glTextureCubemapImage = true;
533 outExtensions->glTexture3DImage =
534 getRenderer()->getFeatures().supportsSampler2dViewOf3d.enabled;
535 outExtensions->glRenderbufferImage = true;
536 outExtensions->imageNativeBuffer =
537 getRenderer()->getFeatures().supportsAndroidHardwareBuffer.enabled;
538 outExtensions->surfacelessContext = true;
539 outExtensions->glColorspace = true;
540 outExtensions->imageGlColorspace =
541 outExtensions->glColorspace && getRenderer()->getFeatures().supportsImageFormatList.enabled;
542
543 #if defined(ANGLE_PLATFORM_ANDROID)
544 outExtensions->getNativeClientBufferANDROID = true;
545 outExtensions->framebufferTargetANDROID = true;
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 getRenderer()->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 = !getRenderer()->getFeatures().allocateNonZeroMemory.enabled;
558 outExtensions->noConfigContext = true;
559
560 #if defined(ANGLE_PLATFORM_ANDROID) || defined(ANGLE_PLATFORM_LINUX)
561 outExtensions->nativeFenceSyncANDROID =
562 getRenderer()->getFeatures().supportsAndroidNativeFenceSync.enabled;
563 #endif // defined(ANGLE_PLATFORM_ANDROID) || defined(ANGLE_PLATFORM_LINUX)
564
565 #if defined(ANGLE_PLATFORM_GGP)
566 outExtensions->ggpStreamDescriptor = true;
567 outExtensions->swapWithFrameToken = getRenderer()->getFeatures().supportsGGPFrameToken.enabled;
568 #endif // defined(ANGLE_PLATFORM_GGP)
569
570 outExtensions->bufferAgeEXT = true;
571
572 outExtensions->protectedContentEXT =
573 (getRenderer()->getFeatures().supportsProtectedMemory.enabled &&
574 getRenderer()->getFeatures().supportsSurfaceProtectedSwapchains.enabled);
575
576 outExtensions->createSurfaceSwapIntervalANGLE = true;
577
578 outExtensions->mutableRenderBufferKHR =
579 getRenderer()->getFeatures().supportsSharedPresentableImageExtension.enabled;
580
581 outExtensions->vulkanImageANGLE = true;
582
583 outExtensions->lockSurface3KHR =
584 getRenderer()->getFeatures().supportsLockSurfaceExtension.enabled;
585
586 outExtensions->partialUpdateKHR = true;
587
588 outExtensions->timestampSurfaceAttributeANGLE =
589 getRenderer()->getFeatures().supportsTimestampSurfaceAttribute.enabled;
590
591 outExtensions->eglColorspaceAttributePassthroughANGLE =
592 outExtensions->glColorspace &&
593 getRenderer()->getFeatures().eglColorspaceAttributePassthrough.enabled;
594
595 // If EGL_KHR_gl_colorspace extension is supported check if other colorspace extensions
596 // can be supported as well.
597 if (outExtensions->glColorspace)
598 {
599 if (isColorspaceSupported(VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT))
600 {
601 outExtensions->glColorspaceDisplayP3 = true;
602 outExtensions->glColorspaceDisplayP3Passthrough = true;
603 }
604
605 outExtensions->glColorspaceDisplayP3Linear =
606 isColorspaceSupported(VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT);
607 outExtensions->glColorspaceScrgb =
608 isColorspaceSupported(VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT);
609 outExtensions->glColorspaceScrgbLinear =
610 isColorspaceSupported(VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT);
611 outExtensions->glColorspaceBt2020Linear =
612 isColorspaceSupported(VK_COLOR_SPACE_BT2020_LINEAR_EXT);
613 outExtensions->glColorspaceBt2020Pq =
614 isColorspaceSupported(VK_COLOR_SPACE_HDR10_ST2084_EXT);
615 outExtensions->glColorspaceBt2020Hlg = isColorspaceSupported(VK_COLOR_SPACE_HDR10_HLG_EXT);
616 }
617 }
618
generateCaps(egl::Caps * outCaps) const619 void DisplayVk::generateCaps(egl::Caps *outCaps) const
620 {
621 outCaps->textureNPOT = true;
622 outCaps->stencil8 = getRenderer()->getNativeExtensions().textureStencil8OES;
623 }
624
getWSILayer() const625 const char *DisplayVk::getWSILayer() const
626 {
627 return nullptr;
628 }
629
handleError(VkResult result,const char * file,const char * function,unsigned int line)630 void DisplayVk::handleError(VkResult result,
631 const char *file,
632 const char *function,
633 unsigned int line)
634 {
635 ASSERT(result != VK_SUCCESS);
636
637 std::stringstream errorStream;
638 errorStream << "Internal Vulkan error (" << result << "): " << VulkanResultString(result)
639 << ", in " << file << ", " << function << ":" << line << ".";
640 std::string errorString = errorStream.str();
641
642 if (result == VK_ERROR_DEVICE_LOST)
643 {
644 WARN() << errorString;
645 mRenderer->notifyDeviceLost();
646 }
647
648 // Note: the errorCode will be set later in angle::ToEGL where it's available.
649 *egl::Display::GetCurrentThreadErrorScratchSpace() = egl::Error(0, 0, std::move(errorString));
650 }
651
initializeFrontendFeatures(angle::FrontendFeatures * features) const652 void DisplayVk::initializeFrontendFeatures(angle::FrontendFeatures *features) const
653 {
654 mRenderer->initializeFrontendFeatures(features);
655 }
656
populateFeatureList(angle::FeatureList * features)657 void DisplayVk::populateFeatureList(angle::FeatureList *features)
658 {
659 mRenderer->getFeatures().populateFeatureList(features);
660 }
661
662 // vk::GlobalOps
putBlob(const angle::BlobCacheKey & key,const angle::MemoryBuffer & value)663 void DisplayVk::putBlob(const angle::BlobCacheKey &key, const angle::MemoryBuffer &value)
664 {
665 getBlobCache()->putApplication(key, value);
666 }
667
getBlob(const angle::BlobCacheKey & key,angle::BlobCacheValue * valueOut)668 bool DisplayVk::getBlob(const angle::BlobCacheKey &key, angle::BlobCacheValue *valueOut)
669 {
670 return getBlobCache()->get(&mScratchBuffer, key, valueOut);
671 }
672
postMultiThreadWorkerTask(const std::shared_ptr<angle::Closure> & task)673 std::shared_ptr<angle::WaitableEvent> DisplayVk::postMultiThreadWorkerTask(
674 const std::shared_ptr<angle::Closure> &task)
675 {
676 return mState.multiThreadPool->postWorkerTask(task);
677 }
678
notifyDeviceLost()679 void DisplayVk::notifyDeviceLost()
680 {
681 mState.notifyDeviceLost();
682 }
683 } // namespace rx
684