Vulkan: add workaround for VK_EXT_full_screen_exclusive on AMD

On outdated (but recent) AMD drivers, the Windows-only Vulkan extension
VK_EXT_full_screen_exclusive appeared to be implicitly enabled and set
to VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT mode. Even though
ANGLE did not enable or interact with this extension at all, the driver
was incorrectly returning VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT
error codes on various swapchain operations when the full screen window
focus was lost (i.e. alt-tab out and back in). Naturally, ANGLE was not
expecting these error codes and did not know how to handle them.
Depending on where the errors occurred, ANGLE might crash or retry
creating the swapchain repeatedly.

Treating the unexpected VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT
error code as VK_ERROR_OUT_OF_DATE_KHR/VK_SUBOPTIMAL_KHR was not
sufficient, because the driver would repeat the error on every swapchain
operation, apparently expecting the error to be handled by
a vkAcquireFullScreenExclusiveModeEXT call (even though that would make
no sense, since the extension was not enabled).

The incorrect driver behavior was reported to AMD and was fixed in
recent driver releases. The earliest driver I've tested and know to be
working is AMD's Adrenaline driver version 23.5.2
(VkPhysicalDeviceProperties calls this driverVersion 2.0.262/0x800106).
The last known bad version was 0x8000e9.

The simplest workaround on these older AMD graphics drivers is to
explicitly enable the extension, but set it to
VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT mode. On newer drivers we do not
need to do anything with the extension and can ignore it.

Bug: angleproject:8215
Change-Id: I7c58d47a0350f4b0bc1a77f200c1e2f72fcde8d8
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4627279
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
Reviewed-by: Charlie Lao <cclao@google.com>
This commit is contained in:
Steven Noonan
2023-06-19 12:26:44 -07:00
committed by Angle LUCI CQ
parent c23029d2fe
commit ac263582dd
6 changed files with 82 additions and 0 deletions

View File

@@ -1215,6 +1215,20 @@ struct FeaturesVk : FeatureSetBase
&members, "http://anglebug.com/8162"
};
FeatureInfo supportsFullScreenExclusive = {
"supportsFullScreenExclusive",
FeatureCategory::VulkanFeatures,
"VkDevice supports the VK_EXT_full_screen_exclusive extension",
&members, "http://anglebug.com/8215"
};
FeatureInfo forceDisableFullScreenExclusive = {
"forceDisableFullScreenExclusive",
FeatureCategory::VulkanWorkarounds,
"Device needs VK_EXT_full_screen_exclusive explicitly disabled",
&members, "http://anglebug.com/8215"
};
};
inline FeaturesVk::FeaturesVk() = default;

View File

@@ -1312,6 +1312,22 @@
"Limit sample count to 2 to save memory on low end devices."
],
"issue": "http://anglebug.com/8162"
},
{
"name": "supports_full_screen_exclusive",
"category": "Features",
"description": [
"VkDevice supports the VK_EXT_full_screen_exclusive extension"
],
"issue": "http://anglebug.com/8215"
},
{
"name": "force_disable_full_screen_exclusive",
"category": "Workarounds",
"description": [
"Device needs VK_EXT_full_screen_exclusive explicitly disabled"
],
"issue": "http://anglebug.com/8215"
}
]
}

View File

@@ -2597,6 +2597,7 @@ void RendererVk::queryDeviceExtensionFeatures(const vk::ExtensionNameList &devic
// - VK_EXT_external_memory_dma_buf
// - VK_EXT_image_drm_format_modifier
// - VK_EXT_blend_operation_advanced
// - VK_EXT_full_screen_exclusive
//
void RendererVk::enableDeviceExtensionsNotPromoted(
const vk::ExtensionNameList &deviceExtensionNames)
@@ -2847,6 +2848,17 @@ void RendererVk::enableDeviceExtensionsNotPromoted(
mEnabledDeviceExtensions.push_back(VK_EXT_LEGACY_DITHERING_EXTENSION_NAME);
vk::AddToPNextChain(&mEnabledFeatures, &mDitheringFeatures);
}
#if defined(ANGLE_PLATFORM_WINDOWS)
// We only need the VK_EXT_full_screen_exclusive extension if we are opting
// out of it via VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT (i.e. working
// around driver bugs).
if (getFeatures().supportsFullScreenExclusive.enabled &&
getFeatures().forceDisableFullScreenExclusive.enabled)
{
mEnabledDeviceExtensions.push_back(VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME);
}
#endif
}
// See comment above appendDeviceExtensionFeaturesPromotedTo11. Additional extensions are enabled
@@ -3983,6 +3995,22 @@ void RendererVk::initFeatures(DisplayVk *displayVk,
&mFeatures, supportsExternalMemoryFd,
ExtensionFound(VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, deviceExtensionNames));
#if defined(ANGLE_PLATFORM_WINDOWS)
ANGLE_FEATURE_CONDITION(
&mFeatures, supportsFullScreenExclusive,
ExtensionFound(VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME, deviceExtensionNames));
// On Windows+AMD, drivers before version 0x800106 (2.0.262) would
// implicitly enable VK_EXT_full_screen_exclusive and start returning
// extension-specific error codes in swapchain functions. Since the
// extension was not enabled by ANGLE, it was impossible to handle these
// error codes correctly. On these earlier drivers, we want to explicitly
// enable the extension and opt out of it to avoid seeing those error codes
// entirely.
ANGLE_FEATURE_CONDITION(&mFeatures, forceDisableFullScreenExclusive,
isAMD && mPhysicalDeviceProperties.driverVersion < 0x800106);
#endif
ANGLE_FEATURE_CONDITION(
&mFeatures, supportsExternalMemoryFuchsia,
ExtensionFound(VK_FUCHSIA_EXTERNAL_MEMORY_EXTENSION_NAME, deviceExtensionNames));

View File

@@ -1546,6 +1546,26 @@ angle::Result WindowSurfaceVk::createSwapChain(vk::Context *context,
swapchainInfo.clipped = VK_TRUE;
swapchainInfo.oldSwapchain = lastSwapchain;
#if defined(ANGLE_PLATFORM_WINDOWS)
// On some AMD drivers we need to explicitly enable the extension and set
// it to "disallowed" mode in order to avoid seeing impossible-to-handle
// extension-specific error codes from swapchain functions.
VkSurfaceFullScreenExclusiveInfoEXT fullscreen = {};
fullscreen.sType = VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT;
fullscreen.fullScreenExclusive = VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT;
VkSurfaceFullScreenExclusiveWin32InfoEXT fullscreenWin32 = {};
fullscreenWin32.sType = VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_WIN32_INFO_EXT;
fullscreenWin32.hmonitor = MonitorFromWindow((HWND)mNativeWindowType, MONITOR_DEFAULTTONEAREST);
if (renderer->getFeatures().supportsFullScreenExclusive.enabled &&
renderer->getFeatures().forceDisableFullScreenExclusive.enabled)
{
vk::AddToPNextChain(&swapchainInfo, &fullscreen);
vk::AddToPNextChain(&swapchainInfo, &fullscreenWin32);
}
#endif
if (context->getFeatures().supportsSwapchainMaintenance1.enabled)
{
swapchainInfo.flags |= VK_SWAPCHAIN_CREATE_DEFERRED_MEMORY_ALLOCATION_BIT_EXT;

View File

@@ -148,6 +148,7 @@ constexpr PackedEnumMap<Feature, const char *> kFeatureNames = {{
{Feature::ForceD16TexFilter, "forceD16TexFilter"},
{Feature::ForceD24S8AsUnsupported, "forceD24S8AsUnsupported"},
{Feature::ForceDepthAttachmentInitOnClear, "forceDepthAttachmentInitOnClear"},
{Feature::ForceDisableFullScreenExclusive, "forceDisableFullScreenExclusive"},
{Feature::ForceFallbackFormat, "forceFallbackFormat"},
{Feature::ForceFragmentShaderPrecisionHighpToMediump, "forceFragmentShaderPrecisionHighpToMediump"},
{Feature::ForceGlErrorChecking, "forceGlErrorChecking"},
@@ -273,6 +274,7 @@ constexpr PackedEnumMap<Feature, const char *> kFeatureNames = {{
{Feature::SupportsFragmentShaderOrderingINTEL, "supportsFragmentShaderOrderingINTEL"},
{Feature::SupportsFragmentShaderPixelInterlock, "supportsFragmentShaderPixelInterlock"},
{Feature::SupportsFragmentShadingRate, "supportsFragmentShadingRate"},
{Feature::SupportsFullScreenExclusive, "supportsFullScreenExclusive"},
{Feature::SupportsGeometryStreamsCapability, "supportsGeometryStreamsCapability"},
{Feature::SupportsGetMemoryRequirements2, "supportsGetMemoryRequirements2"},
{Feature::SupportsGGPFrameToken, "supportsGGPFrameToken"},

View File

@@ -148,6 +148,7 @@ enum class Feature
ForceD16TexFilter,
ForceD24S8AsUnsupported,
ForceDepthAttachmentInitOnClear,
ForceDisableFullScreenExclusive,
ForceFallbackFormat,
ForceFragmentShaderPrecisionHighpToMediump,
ForceGlErrorChecking,
@@ -273,6 +274,7 @@ enum class Feature
SupportsFragmentShaderOrderingINTEL,
SupportsFragmentShaderPixelInterlock,
SupportsFragmentShadingRate,
SupportsFullScreenExclusive,
SupportsGeometryStreamsCapability,
SupportsGetMemoryRequirements2,
SupportsGGPFrameToken,