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