[Impeller] make swapchain related external fence/semaphore extensions optional. (#162205)

Fixes https://github.com/flutter/flutter/issues/162088

Since we will always support a fallback to the KHR swapchain on Android,
we can make the external fence/semaphore extensions optional.
This commit is contained in:
Jonah Williams 2025-01-27 15:55:45 -08:00 committed by GitHub
parent abd0d16232
commit 95811bd82a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 101 additions and 9 deletions

View File

@ -193,20 +193,27 @@ static const char* GetExtensionName(RequiredAndroidDeviceExtensionVK ext) {
return VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME;
case RequiredAndroidDeviceExtensionVK::kKHRDedicatedAllocation:
return VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME;
case RequiredAndroidDeviceExtensionVK::kKHRExternalFenceFd:
return VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME;
case RequiredAndroidDeviceExtensionVK::kKHRExternalFence:
return VK_KHR_EXTERNAL_FENCE_EXTENSION_NAME;
case RequiredAndroidDeviceExtensionVK::kKHRExternalSemaphoreFd:
return VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME;
case RequiredAndroidDeviceExtensionVK::kKHRExternalSemaphore:
return VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME;
case RequiredAndroidDeviceExtensionVK::kLast:
return "Unknown";
}
FML_UNREACHABLE();
}
static const char* GetExtensionName(OptionalAndroidDeviceExtensionVK ext) {
switch (ext) {
case OptionalAndroidDeviceExtensionVK::kKHRExternalFenceFd:
return VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME;
case OptionalAndroidDeviceExtensionVK::kKHRExternalFence:
return VK_KHR_EXTERNAL_FENCE_EXTENSION_NAME;
case OptionalAndroidDeviceExtensionVK::kKHRExternalSemaphoreFd:
return VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME;
case OptionalAndroidDeviceExtensionVK::kKHRExternalSemaphore:
return VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME;
case OptionalAndroidDeviceExtensionVK::kLast:
return "Unknown";
}
}
static const char* GetExtensionName(OptionalDeviceExtensionVK ext) {
switch (ext) {
case OptionalDeviceExtensionVK::kEXTPipelineCreationFeedback:
@ -549,6 +556,7 @@ bool CapabilitiesVK::SetPhysicalDevice(
required_common_device_extensions_.clear();
required_android_device_extensions_.clear();
optional_device_extensions_.clear();
optional_android_device_extensions_.clear();
std::set<std::string> exts;
if (!use_embedder_extensions_) {
@ -583,6 +591,14 @@ bool CapabilitiesVK::SetPhysicalDevice(
}
return true;
});
IterateExtensions<OptionalAndroidDeviceExtensionVK>(
[&](OptionalAndroidDeviceExtensionVK ext) {
auto name = GetExtensionName(ext);
if (exts.find(name) != exts.end()) {
optional_android_device_extensions_.insert(ext);
}
return true;
});
}
supports_texture_fixed_rate_compression_ =
@ -602,6 +618,14 @@ bool CapabilitiesVK::SetPhysicalDevice(
has_triangle_fans_ =
!HasExtension(OptionalDeviceExtensionVK::kVKKHRPortabilitySubset);
// External Fence/Semaphore for AHB swapchain
if (HasExtension(OptionalAndroidDeviceExtensionVK::kKHRExternalFenceFd) &&
HasExtension(OptionalAndroidDeviceExtensionVK::kKHRExternalFence) &&
HasExtension(OptionalAndroidDeviceExtensionVK::kKHRExternalSemaphore) &&
HasExtension(OptionalAndroidDeviceExtensionVK::kKHRExternalSemaphoreFd)) {
supports_external_fence_and_semaphore_ = true;
}
return true;
}
@ -695,6 +719,11 @@ bool CapabilitiesVK::HasExtension(OptionalDeviceExtensionVK ext) const {
optional_device_extensions_.end();
}
bool CapabilitiesVK::HasExtension(OptionalAndroidDeviceExtensionVK ext) const {
return optional_android_device_extensions_.find(ext) !=
optional_android_device_extensions_.end();
}
bool CapabilitiesVK::SupportsTextureFixedRateCompression() const {
return supports_texture_fixed_rate_compression_;
}
@ -765,4 +794,8 @@ void CapabilitiesVK::ApplyWorkarounds(const WorkaroundsVK& workarounds) {
has_framebuffer_fetch_ = !workarounds.input_attachment_self_dependency_broken;
}
bool CapabilitiesVK::SupportsExternalSemaphoreExtensions() const {
return supports_external_fence_and_semaphore_;
}
} // namespace impeller

View File

@ -81,6 +81,16 @@ enum class RequiredAndroidDeviceExtensionVK : uint32_t {
///
kKHRDedicatedAllocation,
kLast,
};
//------------------------------------------------------------------------------
/// @brief A device extension available on some Android platforms.
///
/// Platform agnostic code can still check if these Android
/// extensions are present.
///
enum class OptionalAndroidDeviceExtensionVK : uint32_t {
//----------------------------------------------------------------------------
/// For exporting file descriptors from fences to interact with platform APIs.
///
@ -188,6 +198,8 @@ class CapabilitiesVK final : public Capabilities,
bool HasExtension(OptionalDeviceExtensionVK ext) const;
bool HasExtension(OptionalAndroidDeviceExtensionVK ext) const;
std::optional<std::vector<std::string>> GetEnabledLayers() const;
std::optional<std::vector<std::string>> GetEnabledInstanceExtensions() const;
@ -269,6 +281,10 @@ class CapabilitiesVK final : public Capabilities,
///
bool SupportsTextureFixedRateCompression() const;
/// Whether the external fence and semaphore extensions used for AHB support
/// are available.
bool SupportsExternalSemaphoreExtensions() const;
//----------------------------------------------------------------------------
/// @brief Get the fixed compression rate supported by the context for
/// the given format and usage.
@ -292,6 +308,8 @@ class CapabilitiesVK final : public Capabilities,
std::set<RequiredCommonDeviceExtensionVK> required_common_device_extensions_;
std::set<RequiredAndroidDeviceExtensionVK>
required_android_device_extensions_;
std::set<OptionalAndroidDeviceExtensionVK>
optional_android_device_extensions_;
std::set<OptionalDeviceExtensionVK> optional_device_extensions_;
mutable PixelFormat default_color_format_ = PixelFormat::kUnknown;
PixelFormat default_stencil_format_ = PixelFormat::kUnknown;
@ -305,6 +323,7 @@ class CapabilitiesVK final : public Capabilities,
bool has_triangle_fans_ = true;
bool has_primitive_restart_ = true;
bool has_framebuffer_fetch_ = true;
bool supports_external_fence_and_semaphore_ = false;
bool is_valid_ = false;
// The embedder.h API is responsible for providing the instance and device

View File

@ -731,7 +731,9 @@ const std::unique_ptr<DriverInfoVK>& ContextVK::GetDriverInfo() const {
}
bool ContextVK::GetShouldEnableSurfaceControlSwapchain() const {
return should_enable_surface_control_;
return should_enable_surface_control_ &&
CapabilitiesVK::Cast(*device_capabilities_)
.SupportsExternalSemaphoreExtensions();
}
RuntimeStageBackend ContextVK::GetRuntimeStageBackend() const {

View File

@ -354,5 +354,43 @@ TEST(ContextVKTest, BatchSubmitCommandBuffersOnNonArm) {
"vkCreateFence") != functions->end());
}
TEST(ContextVKTest, AHBSwapchainCapabilitiesCanBeMissing) {
{
std::shared_ptr<ContextVK> context =
MockVulkanContextBuilder()
.SetSettingsCallback([](ContextVK::Settings& settings) {
settings.enable_surface_control = true;
})
.Build();
EXPECT_FALSE(context->GetShouldEnableSurfaceControlSwapchain());
}
ContextVK::EmbedderData data;
auto other_context = MockVulkanContextBuilder().Build();
data.instance = other_context->GetInstance();
data.device = other_context->GetDevice();
data.physical_device = other_context->GetPhysicalDevice();
data.queue = VkQueue{};
data.queue_family_index = 0;
data.instance_extensions = {"VK_KHR_surface", "VK_KHR_android_surface"};
data.device_extensions = {"VK_KHR_swapchain",
VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME,
VK_KHR_EXTERNAL_FENCE_EXTENSION_NAME,
VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME,
VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME};
auto context = MockVulkanContextBuilder()
.SetSettingsCallback([](ContextVK::Settings& settings) {
settings.enable_surface_control = true;
})
.SetEmbedderData(data)
.Build();
EXPECT_TRUE(context->GetShouldEnableSurfaceControlSwapchain());
} // namespace impeller
} // namespace testing
} // namespace impeller