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/Context.h"
15 #include "libANGLE/Display.h"
16 #include "libANGLE/renderer/vulkan/BufferVk.h"
17 #include "libANGLE/renderer/vulkan/ContextVk.h"
18 #include "libANGLE/renderer/vulkan/DeviceVk.h"
19 #include "libANGLE/renderer/vulkan/ImageVk.h"
20 #include "libANGLE/renderer/vulkan/RendererVk.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
27 namespace rx
28 {
29
30 namespace
31 {
32 // Query surface format and colorspace support.
GetSupportedFormatColorspaces(VkPhysicalDevice physicalDevice,const angle::FeaturesVk & featuresVk,VkSurfaceKHR surface,std::vector<VkSurfaceFormat2KHR> * surfaceFormatsOut)33 void GetSupportedFormatColorspaces(VkPhysicalDevice physicalDevice,
34 const angle::FeaturesVk &featuresVk,
35 VkSurfaceKHR surface,
36 std::vector<VkSurfaceFormat2KHR> *surfaceFormatsOut)
37 {
38 ASSERT(surfaceFormatsOut);
39 surfaceFormatsOut->clear();
40
41 constexpr VkSurfaceFormat2KHR kSurfaceFormat2Initializer = {
42 VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR,
43 nullptr,
44 {VK_FORMAT_UNDEFINED, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR}};
45
46 if (featuresVk.supportsSurfaceCapabilities2Extension.enabled)
47 {
48 VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo2 = {};
49 surfaceInfo2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR;
50 surfaceInfo2.surface = surface;
51 uint32_t surfaceFormatCount = 0;
52
53 // Query the count first
54 VkResult result = vkGetPhysicalDeviceSurfaceFormats2KHR(physicalDevice, &surfaceInfo2,
55 &surfaceFormatCount, nullptr);
56 ASSERT(result == VK_SUCCESS);
57 ASSERT(surfaceFormatCount > 0);
58
59 // Query the VkSurfaceFormat2KHR list
60 std::vector<VkSurfaceFormat2KHR> surfaceFormats2(surfaceFormatCount,
61 kSurfaceFormat2Initializer);
62 result = vkGetPhysicalDeviceSurfaceFormats2KHR(physicalDevice, &surfaceInfo2,
63 &surfaceFormatCount, surfaceFormats2.data());
64 ASSERT(result == VK_SUCCESS);
65
66 *surfaceFormatsOut = std::move(surfaceFormats2);
67 }
68 else
69 {
70 uint32_t surfaceFormatCount = 0;
71 // Query the count first
72 VkResult result = vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface,
73 &surfaceFormatCount, nullptr);
74 ASSERT(result == VK_SUCCESS);
75
76 // Query the VkSurfaceFormatKHR list
77 std::vector<VkSurfaceFormatKHR> surfaceFormats(surfaceFormatCount);
78 result = vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &surfaceFormatCount,
79 surfaceFormats.data());
80 ASSERT(result == VK_SUCCESS);
81
82 // Copy over data from std::vector<VkSurfaceFormatKHR> to std::vector<VkSurfaceFormat2KHR>
83 std::vector<VkSurfaceFormat2KHR> surfaceFormats2(surfaceFormatCount,
84 kSurfaceFormat2Initializer);
85 for (size_t index = 0; index < surfaceFormatCount; index++)
86 {
87 surfaceFormats2[index].surfaceFormat.format = surfaceFormats[index].format;
88 }
89
90 *surfaceFormatsOut = std::move(surfaceFormats2);
91 }
92 }
93 } // namespace
94
DisplayVk(const egl::DisplayState & state)95 DisplayVk::DisplayVk(const egl::DisplayState &state)
96 : DisplayImpl(state),
97 vk::Context(new RendererVk()),
98 mScratchBuffer(1000u),
99 mSupportedColorspaceFormatsMap{}
100 {}
101
~DisplayVk()102 DisplayVk::~DisplayVk()
103 {
104 delete mRenderer;
105 }
106
initialize(egl::Display * display)107 egl::Error DisplayVk::initialize(egl::Display *display)
108 {
109 ASSERT(mRenderer != nullptr && display != nullptr);
110 angle::Result result = mRenderer->initialize(this, display, getWSIExtension(), getWSILayer());
111 ANGLE_TRY(angle::ToEGL(result, EGL_NOT_INITIALIZED));
112 // Query and cache supported surface format and colorspace for later use.
113 initSupportedSurfaceFormatColorspaces();
114 return egl::NoError();
115 }
116
terminate()117 void DisplayVk::terminate()
118 {
119 mRenderer->reloadVolkIfNeeded();
120
121 ASSERT(mRenderer);
122 mRenderer->onDestroy(this);
123 }
124
makeCurrent(egl::Display *,egl::Surface *,egl::Surface *,gl::Context *)125 egl::Error DisplayVk::makeCurrent(egl::Display * /*display*/,
126 egl::Surface * /*drawSurface*/,
127 egl::Surface * /*readSurface*/,
128 gl::Context * /*context*/)
129 {
130 // Ensure the appropriate global DebugAnnotator is used
131 ASSERT(mRenderer);
132 mRenderer->setGlobalDebugAnnotator();
133
134 return egl::NoError();
135 }
136
testDeviceLost()137 bool DisplayVk::testDeviceLost()
138 {
139 return mRenderer->isDeviceLost();
140 }
141
restoreLostDevice(const egl::Display * display)142 egl::Error DisplayVk::restoreLostDevice(const egl::Display *display)
143 {
144 // A vulkan device cannot be restored, the entire renderer would have to be re-created along
145 // with any other EGL objects that reference it.
146 return egl::EglBadDisplay();
147 }
148
getRendererDescription()149 std::string DisplayVk::getRendererDescription()
150 {
151 if (mRenderer)
152 {
153 return mRenderer->getRendererDescription();
154 }
155 return std::string();
156 }
157
getVendorString()158 std::string DisplayVk::getVendorString()
159 {
160 if (mRenderer)
161 {
162 return mRenderer->getVendorString();
163 }
164 return std::string();
165 }
166
getVersionString(bool includeFullVersion)167 std::string DisplayVk::getVersionString(bool includeFullVersion)
168 {
169 if (mRenderer)
170 {
171 return mRenderer->getVersionString(includeFullVersion);
172 }
173 return std::string();
174 }
175
createDevice()176 DeviceImpl *DisplayVk::createDevice()
177 {
178 return new DeviceVk();
179 }
180
waitClient(const gl::Context * context)181 egl::Error DisplayVk::waitClient(const gl::Context *context)
182 {
183 ANGLE_TRACE_EVENT0("gpu.angle", "DisplayVk::waitClient");
184 ContextVk *contextVk = vk::GetImpl(context);
185 return angle::ToEGL(contextVk->finishImpl(RenderPassClosureReason::EGLWaitClient),
186 EGL_BAD_ACCESS);
187 }
188
waitNative(const gl::Context * context,EGLint engine)189 egl::Error DisplayVk::waitNative(const gl::Context *context, EGLint engine)
190 {
191 ANGLE_TRACE_EVENT0("gpu.angle", "DisplayVk::waitNative");
192 return angle::ResultToEGL(waitNativeImpl());
193 }
194
waitNativeImpl()195 angle::Result DisplayVk::waitNativeImpl()
196 {
197 return angle::Result::Continue;
198 }
199
createWindowSurface(const egl::SurfaceState & state,EGLNativeWindowType window,const egl::AttributeMap & attribs)200 SurfaceImpl *DisplayVk::createWindowSurface(const egl::SurfaceState &state,
201 EGLNativeWindowType window,
202 const egl::AttributeMap &attribs)
203 {
204 return createWindowSurfaceVk(state, window);
205 }
206
createPbufferSurface(const egl::SurfaceState & state,const egl::AttributeMap & attribs)207 SurfaceImpl *DisplayVk::createPbufferSurface(const egl::SurfaceState &state,
208 const egl::AttributeMap &attribs)
209 {
210 ASSERT(mRenderer);
211 return new OffscreenSurfaceVk(state, mRenderer);
212 }
213
createPbufferFromClientBuffer(const egl::SurfaceState & state,EGLenum buftype,EGLClientBuffer clientBuffer,const egl::AttributeMap & attribs)214 SurfaceImpl *DisplayVk::createPbufferFromClientBuffer(const egl::SurfaceState &state,
215 EGLenum buftype,
216 EGLClientBuffer clientBuffer,
217 const egl::AttributeMap &attribs)
218 {
219 UNIMPLEMENTED();
220 return static_cast<SurfaceImpl *>(0);
221 }
222
createPixmapSurface(const egl::SurfaceState & state,NativePixmapType nativePixmap,const egl::AttributeMap & attribs)223 SurfaceImpl *DisplayVk::createPixmapSurface(const egl::SurfaceState &state,
224 NativePixmapType nativePixmap,
225 const egl::AttributeMap &attribs)
226 {
227 UNIMPLEMENTED();
228 return static_cast<SurfaceImpl *>(0);
229 }
230
createImage(const egl::ImageState & state,const gl::Context * context,EGLenum target,const egl::AttributeMap & attribs)231 ImageImpl *DisplayVk::createImage(const egl::ImageState &state,
232 const gl::Context *context,
233 EGLenum target,
234 const egl::AttributeMap &attribs)
235 {
236 return new ImageVk(state, context);
237 }
238
createShareGroup(const egl::ShareGroupState & state)239 ShareGroupImpl *DisplayVk::createShareGroup(const egl::ShareGroupState &state)
240 {
241 return new ShareGroupVk(state);
242 }
243
isConfigFormatSupported(VkFormat format) const244 bool DisplayVk::isConfigFormatSupported(VkFormat format) const
245 {
246 // Requires VK_GOOGLE_surfaceless_query extension to be supported.
247 ASSERT(mRenderer->getFeatures().supportsSurfacelessQueryExtension.enabled);
248
249 // A format is considered supported if it is supported in atleast 1 colorspace.
250 using ColorspaceFormatSetItem =
251 const std::pair<const VkColorSpaceKHR, std::unordered_set<VkFormat>>;
252 for (ColorspaceFormatSetItem &colorspaceFormatSetItem : mSupportedColorspaceFormatsMap)
253 {
254 if (colorspaceFormatSetItem.second.count(format) > 0)
255 {
256 return true;
257 }
258 }
259
260 return false;
261 }
262
isSurfaceFormatColorspacePairSupported(VkSurfaceKHR surface,VkFormat format,VkColorSpaceKHR colorspace) const263 bool DisplayVk::isSurfaceFormatColorspacePairSupported(VkSurfaceKHR surface,
264 VkFormat format,
265 VkColorSpaceKHR colorspace) const
266 {
267 if (mSupportedColorspaceFormatsMap.size() > 0)
268 {
269 return mSupportedColorspaceFormatsMap.count(colorspace) > 0 &&
270 mSupportedColorspaceFormatsMap.at(colorspace).count(format) > 0;
271 }
272 else
273 {
274 const angle::FeaturesVk &featuresVk = mRenderer->getFeatures();
275 std::vector<VkSurfaceFormat2KHR> surfaceFormats;
276 GetSupportedFormatColorspaces(mRenderer->getPhysicalDevice(), featuresVk, surface,
277 &surfaceFormats);
278
279 if (!featuresVk.supportsSurfaceCapabilities2Extension.enabled)
280 {
281 if (surfaceFormats.size() == 1u &&
282 surfaceFormats[0].surfaceFormat.format == VK_FORMAT_UNDEFINED)
283 {
284 return true;
285 }
286 }
287
288 for (const VkSurfaceFormat2KHR &surfaceFormat : surfaceFormats)
289 {
290 if (surfaceFormat.surfaceFormat.format == format &&
291 surfaceFormat.surfaceFormat.colorSpace == colorspace)
292 {
293 return true;
294 }
295 }
296 }
297
298 return false;
299 }
300
isColorspaceSupported(VkColorSpaceKHR colorspace) const301 bool DisplayVk::isColorspaceSupported(VkColorSpaceKHR colorspace) const
302 {
303 return mSupportedColorspaceFormatsMap.count(colorspace) > 0;
304 }
305
initSupportedSurfaceFormatColorspaces()306 void DisplayVk::initSupportedSurfaceFormatColorspaces()
307 {
308 const angle::FeaturesVk &featuresVk = mRenderer->getFeatures();
309 if (featuresVk.supportsSurfacelessQueryExtension.enabled &&
310 featuresVk.supportsSurfaceCapabilities2Extension.enabled)
311 {
312 // Use the VK_GOOGLE_surfaceless_query extension to query supported surface formats and
313 // colorspaces by using a VK_NULL_HANDLE for the VkSurfaceKHR handle.
314 std::vector<VkSurfaceFormat2KHR> surfaceFormats;
315 GetSupportedFormatColorspaces(mRenderer->getPhysicalDevice(), featuresVk, VK_NULL_HANDLE,
316 &surfaceFormats);
317 for (const VkSurfaceFormat2KHR &surfaceFormat : surfaceFormats)
318 {
319 // Cache supported VkFormat and VkColorSpaceKHR for later use
320 VkFormat format = surfaceFormat.surfaceFormat.format;
321 VkColorSpaceKHR colorspace = surfaceFormat.surfaceFormat.colorSpace;
322
323 ASSERT(format != VK_FORMAT_UNDEFINED);
324
325 mSupportedColorspaceFormatsMap[colorspace].insert(format);
326 }
327
328 ASSERT(mSupportedColorspaceFormatsMap.size() > 0);
329 }
330 else
331 {
332 mSupportedColorspaceFormatsMap.clear();
333 }
334 }
335
createContext(const gl::State & state,gl::ErrorSet * errorSet,const egl::Config * configuration,const gl::Context * shareContext,const egl::AttributeMap & attribs)336 ContextImpl *DisplayVk::createContext(const gl::State &state,
337 gl::ErrorSet *errorSet,
338 const egl::Config *configuration,
339 const gl::Context *shareContext,
340 const egl::AttributeMap &attribs)
341 {
342 return new ContextVk(state, errorSet, mRenderer);
343 }
344
createStreamProducerD3DTexture(egl::Stream::ConsumerType consumerType,const egl::AttributeMap & attribs)345 StreamProducerImpl *DisplayVk::createStreamProducerD3DTexture(
346 egl::Stream::ConsumerType consumerType,
347 const egl::AttributeMap &attribs)
348 {
349 UNIMPLEMENTED();
350 return static_cast<StreamProducerImpl *>(0);
351 }
352
createSync(const egl::AttributeMap & attribs)353 EGLSyncImpl *DisplayVk::createSync(const egl::AttributeMap &attribs)
354 {
355 return new EGLSyncVk(attribs);
356 }
357
getMaxSupportedESVersion() const358 gl::Version DisplayVk::getMaxSupportedESVersion() const
359 {
360 return mRenderer->getMaxSupportedESVersion();
361 }
362
getMaxConformantESVersion() const363 gl::Version DisplayVk::getMaxConformantESVersion() const
364 {
365 return mRenderer->getMaxConformantESVersion();
366 }
367
getMaxSupportedDesktopVersion() const368 Optional<gl::Version> DisplayVk::getMaxSupportedDesktopVersion() const
369 {
370 return gl::Version{4, 6};
371 }
372
validateImageClientBuffer(const gl::Context * context,EGLenum target,EGLClientBuffer clientBuffer,const egl::AttributeMap & attribs) const373 egl::Error DisplayVk::validateImageClientBuffer(const gl::Context *context,
374 EGLenum target,
375 EGLClientBuffer clientBuffer,
376 const egl::AttributeMap &attribs) const
377 {
378 switch (target)
379 {
380 case EGL_VULKAN_IMAGE_ANGLE:
381 {
382 VkImage *vkImage = reinterpret_cast<VkImage *>(clientBuffer);
383 if (!vkImage || *vkImage == VK_NULL_HANDLE)
384 {
385 return egl::EglBadParameter() << "clientBuffer is invalid.";
386 }
387
388 GLenum internalFormat =
389 static_cast<GLenum>(attribs.get(EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_NONE));
390 switch (internalFormat)
391 {
392 case GL_RGBA:
393 case GL_BGRA_EXT:
394 case GL_RGB:
395 case GL_RED_EXT:
396 case GL_RG_EXT:
397 case GL_RGB10_A2_EXT:
398 case GL_R16_EXT:
399 case GL_RG16_EXT:
400 case GL_NONE:
401 break;
402 default:
403 return egl::EglBadParameter() << "Invalid EGLImage texture internal format: 0x"
404 << std::hex << internalFormat;
405 }
406
407 uint64_t hi = static_cast<uint64_t>(attribs.get(EGL_VULKAN_IMAGE_CREATE_INFO_HI_ANGLE));
408 uint64_t lo = static_cast<uint64_t>(attribs.get(EGL_VULKAN_IMAGE_CREATE_INFO_LO_ANGLE));
409 uint64_t info = ((hi & 0xffffffff) << 32) | (lo & 0xffffffff);
410 if (reinterpret_cast<const VkImageCreateInfo *>(info)->sType !=
411 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO)
412 {
413 return egl::EglBadParameter()
414 << "EGL_VULKAN_IMAGE_CREATE_INFO_HI_ANGLE and "
415 "EGL_VULKAN_IMAGE_CREATE_INFO_LO_ANGLE are not pointing to a "
416 "valid VkImageCreateInfo structure.";
417 }
418
419 return egl::NoError();
420 }
421 default:
422 return DisplayImpl::validateImageClientBuffer(context, target, clientBuffer, attribs);
423 }
424 }
425
createExternalImageSibling(const gl::Context * context,EGLenum target,EGLClientBuffer buffer,const egl::AttributeMap & attribs)426 ExternalImageSiblingImpl *DisplayVk::createExternalImageSibling(const gl::Context *context,
427 EGLenum target,
428 EGLClientBuffer buffer,
429 const egl::AttributeMap &attribs)
430 {
431 switch (target)
432 {
433 case EGL_VULKAN_IMAGE_ANGLE:
434 return new VkImageImageSiblingVk(buffer, attribs);
435 default:
436 return DisplayImpl::createExternalImageSibling(context, target, buffer, attribs);
437 }
438 }
439
generateExtensions(egl::DisplayExtensions * outExtensions) const440 void DisplayVk::generateExtensions(egl::DisplayExtensions *outExtensions) const
441 {
442 outExtensions->createContextRobustness = getRenderer()->getNativeExtensions().robustnessEXT;
443 outExtensions->surfaceOrientation = true;
444 outExtensions->displayTextureShareGroup = true;
445 outExtensions->displaySemaphoreShareGroup = true;
446 outExtensions->robustResourceInitializationANGLE = true;
447
448 // The Vulkan implementation will always say that EGL_KHR_swap_buffers_with_damage is supported.
449 // When the Vulkan driver supports VK_KHR_incremental_present, it will use it. Otherwise, it
450 // will ignore the hint and do a regular swap.
451 outExtensions->swapBuffersWithDamage = true;
452
453 outExtensions->fenceSync = true;
454 outExtensions->waitSync = true;
455
456 outExtensions->image = true;
457 outExtensions->imageBase = true;
458 outExtensions->imagePixmap = false; // ANGLE does not support pixmaps
459 outExtensions->glTexture2DImage = true;
460 outExtensions->glTextureCubemapImage = true;
461 outExtensions->glTexture3DImage =
462 getRenderer()->getFeatures().supportsSampler2dViewOf3d.enabled;
463 outExtensions->glRenderbufferImage = true;
464 outExtensions->imageNativeBuffer =
465 getRenderer()->getFeatures().supportsAndroidHardwareBuffer.enabled;
466 outExtensions->surfacelessContext = true;
467 outExtensions->glColorspace = true;
468 outExtensions->imageGlColorspace =
469 outExtensions->glColorspace && getRenderer()->getFeatures().supportsImageFormatList.enabled;
470
471 #if defined(ANGLE_PLATFORM_ANDROID)
472 outExtensions->getNativeClientBufferANDROID = true;
473 outExtensions->framebufferTargetANDROID = true;
474 #endif // defined(ANGLE_PLATFORM_ANDROID)
475
476 // EGL_EXT_image_dma_buf_import is only exposed if EGL_EXT_image_dma_buf_import_modifiers can
477 // also be exposed. The Vulkan extensions that support these EGL extensions are not split in
478 // the same way; both Vulkan extensions are needed for EGL_EXT_image_dma_buf_import, and with
479 // both Vulkan extensions, EGL_EXT_image_dma_buf_import_modifiers is also supportable.
480 outExtensions->imageDmaBufImportEXT =
481 getRenderer()->getFeatures().supportsExternalMemoryDmaBufAndModifiers.enabled;
482 outExtensions->imageDmaBufImportModifiersEXT = outExtensions->imageDmaBufImportEXT;
483
484 // Disable context priority when non-zero memory init is enabled. This enforces a queue order.
485 outExtensions->contextPriority = !getRenderer()->getFeatures().allocateNonZeroMemory.enabled;
486 outExtensions->noConfigContext = true;
487
488 #if defined(ANGLE_PLATFORM_ANDROID) || defined(ANGLE_PLATFORM_LINUX)
489 outExtensions->nativeFenceSyncANDROID =
490 getRenderer()->getFeatures().supportsAndroidNativeFenceSync.enabled;
491 #endif // defined(ANGLE_PLATFORM_ANDROID) || defined(ANGLE_PLATFORM_LINUX)
492
493 #if defined(ANGLE_PLATFORM_GGP)
494 outExtensions->ggpStreamDescriptor = true;
495 outExtensions->swapWithFrameToken = getRenderer()->getFeatures().supportsGGPFrameToken.enabled;
496 #endif // defined(ANGLE_PLATFORM_GGP)
497
498 outExtensions->bufferAgeEXT = true;
499
500 outExtensions->protectedContentEXT =
501 (getRenderer()->getFeatures().supportsProtectedMemory.enabled &&
502 getRenderer()->getFeatures().supportsSurfaceProtectedSwapchains.enabled);
503
504 outExtensions->createSurfaceSwapIntervalANGLE = true;
505
506 outExtensions->mutableRenderBufferKHR =
507 getRenderer()->getFeatures().supportsSharedPresentableImageExtension.enabled;
508
509 outExtensions->vulkanImageANGLE = true;
510
511 outExtensions->lockSurface3KHR =
512 getRenderer()->getFeatures().supportsLockSurfaceExtension.enabled;
513
514 outExtensions->partialUpdateKHR = true;
515
516 outExtensions->timestampSurfaceAttributeANGLE =
517 getRenderer()->getFeatures().supportsTimestampSurfaceAttribute.enabled;
518
519 outExtensions->eglColorspaceAttributePassthroughANGLE =
520 outExtensions->glColorspace &&
521 getRenderer()->getFeatures().eglColorspaceAttributePassthrough.enabled;
522
523 // If EGL_KHR_gl_colorspace extension is supported check if other colorspace extensions
524 // can be supported as well.
525 if (outExtensions->glColorspace)
526 {
527 if (isColorspaceSupported(VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT))
528 {
529 outExtensions->glColorspaceDisplayP3 = true;
530 outExtensions->glColorspaceDisplayP3Passthrough = true;
531 }
532
533 outExtensions->glColorspaceDisplayP3Linear =
534 isColorspaceSupported(VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT);
535 outExtensions->glColorspaceScrgb =
536 isColorspaceSupported(VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT);
537 outExtensions->glColorspaceScrgbLinear =
538 isColorspaceSupported(VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT);
539 }
540 }
541
generateCaps(egl::Caps * outCaps) const542 void DisplayVk::generateCaps(egl::Caps *outCaps) const
543 {
544 outCaps->textureNPOT = true;
545 outCaps->stencil8 = getRenderer()->getNativeExtensions().textureStencil8OES;
546 }
547
getWSILayer() const548 const char *DisplayVk::getWSILayer() const
549 {
550 return nullptr;
551 }
552
isUsingSwapchain() const553 bool DisplayVk::isUsingSwapchain() const
554 {
555 return true;
556 }
557
getScratchBuffer(size_t requstedSizeBytes,angle::MemoryBuffer ** scratchBufferOut) const558 bool DisplayVk::getScratchBuffer(size_t requstedSizeBytes,
559 angle::MemoryBuffer **scratchBufferOut) const
560 {
561 return mScratchBuffer.get(requstedSizeBytes, scratchBufferOut);
562 }
563
handleError(VkResult result,const char * file,const char * function,unsigned int line)564 void DisplayVk::handleError(VkResult result,
565 const char *file,
566 const char *function,
567 unsigned int line)
568 {
569 ASSERT(result != VK_SUCCESS);
570
571 std::stringstream errorStream;
572 errorStream << "Internal Vulkan error (" << result << "): " << VulkanResultString(result)
573 << ", in " << file << ", " << function << ":" << line << ".";
574 std::string errorString = errorStream.str();
575
576 if (result == VK_ERROR_DEVICE_LOST)
577 {
578 WARN() << errorString;
579 mRenderer->notifyDeviceLost();
580 }
581
582 // Note: the errorCode will be set later in angle::ToEGL where it's available.
583 *egl::Display::GetCurrentThreadErrorScratchSpace() = egl::Error(0, 0, std::move(errorString));
584 }
585
initializeFrontendFeatures(angle::FrontendFeatures * features) const586 void DisplayVk::initializeFrontendFeatures(angle::FrontendFeatures *features) const
587 {
588 mRenderer->initializeFrontendFeatures(features);
589 }
590
populateFeatureList(angle::FeatureList * features)591 void DisplayVk::populateFeatureList(angle::FeatureList *features)
592 {
593 mRenderer->getFeatures().populateFeatureList(features);
594 }
595 } // namespace rx
596