Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 41 additions & 9 deletions impeller/renderer/backend/vulkan/capabilities_vk.cc
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,22 @@ static const char* GetExtensionName(RequiredCommonDeviceExtensionVK ext) {
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";
}
FML_UNREACHABLE();
}

static const char* GetExtensionName(RequiredAndroidDeviceExtensionVK ext) {
switch (ext) {
case RequiredAndroidDeviceExtensionVK::
Expand All @@ -180,14 +196,6 @@ 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";
}
Expand Down Expand Up @@ -278,12 +286,24 @@ CapabilitiesVK::GetEnabledDeviceExtensions(
return true;
};

auto for_each_optional_android_extension =
[&](OptionalAndroidDeviceExtensionVK ext) {
auto name = GetExtensionName(ext);
if (exts->find(name) != exts->end()) {
enabled.push_back(name);
}
return true;
};

const auto iterate_extensions =
IterateExtensions<RequiredCommonDeviceExtensionVK>(
for_each_common_extension) &&
IterateExtensions<RequiredAndroidDeviceExtensionVK>(
for_each_android_extension) &&
IterateExtensions<OptionalDeviceExtensionVK>(for_each_optional_extension);
IterateExtensions<OptionalDeviceExtensionVK>(
for_each_optional_extension) &&
IterateExtensions<OptionalAndroidDeviceExtensionVK>(
for_each_optional_android_extension);

if (!iterate_extensions) {
VALIDATION_LOG << "Device not suitable since required extensions are not "
Expand Down Expand Up @@ -549,6 +569,13 @@ bool CapabilitiesVK::SetPhysicalDevice(
}
return true;
});
IterateExtensions<OptionalAndroidDeviceExtensionVK>([&](auto ext) -> bool {
auto ext_name = GetExtensionName(ext);
if (exts->find(ext_name) != exts->end()) {
optional_android_device_extensions_.insert(ext);
}
return true;
});
}

supports_texture_fixed_rate_compression_ =
Expand Down Expand Up @@ -651,6 +678,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_;
}
Expand Down
71 changes: 44 additions & 27 deletions impeller/renderer/backend/vulkan/capabilities_vk.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,33 +80,6 @@ enum class RequiredAndroidDeviceExtensionVK : uint32_t {
///
kKHRDedicatedAllocation,

//----------------------------------------------------------------------------
/// For exporting file descriptors from fences to interact with platform APIs.
///
/// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_KHR_external_fence_fd.html
///
kKHRExternalFenceFd,

//----------------------------------------------------------------------------
/// Dependency of kKHRExternalFenceFd.
///
/// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_KHR_external_fence.html
///
kKHRExternalFence,

//----------------------------------------------------------------------------
/// For importing sync file descriptors as semaphores so the GPU can wait for
/// semaphore to be signaled.
///
/// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_KHR_external_semaphore_fd.html
kKHRExternalSemaphoreFd,

//----------------------------------------------------------------------------
/// Dependency of kKHRExternalSemaphoreFd
///
/// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_KHR_external_semaphore.html
kKHRExternalSemaphore,

kLast,
};

Expand Down Expand Up @@ -143,6 +116,46 @@ enum class OptionalDeviceExtensionVK : uint32_t {
kLast,
};

//------------------------------------------------------------------------------
/// @brief A device extensions that may be available on Android platforms.
/// Without the presence of these extensions on Android, certain
/// features cannot be used, like AHB swapchains.
///
/// Platform agnostic code can still check if these Android
/// extensions are present.
///
enum class OptionalAndroidDeviceExtensionVK : uint32_t {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is nothing Android specific about these extensions, you can move them to OptionalDeviceExtensionVK.


//----------------------------------------------------------------------------
/// For exporting file descriptors from fences to interact with platform APIs.
///
/// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_KHR_external_fence_fd.html
///
kKHRExternalFenceFd,

//----------------------------------------------------------------------------
/// Dependency of kKHRExternalFenceFd.
///
/// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_KHR_external_fence.html
///
kKHRExternalFence,

//----------------------------------------------------------------------------
/// For importing sync file descriptors as semaphores so the GPU can wait for
/// semaphore to be signaled.
///
/// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_KHR_external_semaphore_fd.html
kKHRExternalSemaphoreFd,

//----------------------------------------------------------------------------
/// Dependency of kKHRExternalSemaphoreFd
///
/// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_KHR_external_semaphore.html
kKHRExternalSemaphore,

kLast,
};

//------------------------------------------------------------------------------
/// @brief A pixel format and usage that is sufficient to check if images
/// of that format and usage are suitable for use with fixed-rate
Expand Down Expand Up @@ -182,6 +195,8 @@ class CapabilitiesVK final : public Capabilities,

bool HasExtension(RequiredAndroidDeviceExtensionVK ext) const;

bool HasExtension(OptionalAndroidDeviceExtensionVK ext) const;

bool HasExtension(OptionalDeviceExtensionVK ext) const;

std::optional<std::vector<std::string>> GetEnabledLayers() const;
Expand Down Expand Up @@ -276,6 +291,8 @@ class CapabilitiesVK final : public Capabilities,
std::set<RequiredAndroidDeviceExtensionVK>
required_android_device_extensions_;
std::set<OptionalDeviceExtensionVK> optional_device_extensions_;
std::set<OptionalAndroidDeviceExtensionVK>
optional_android_device_extensions_;
mutable PixelFormat default_color_format_ = PixelFormat::kUnknown;
PixelFormat default_stencil_format_ = PixelFormat::kUnknown;
PixelFormat default_depth_stencil_format_ = PixelFormat::kUnknown;
Expand Down
12 changes: 12 additions & 0 deletions impeller/renderer/backend/vulkan/context_vk.cc
Original file line number Diff line number Diff line change
Expand Up @@ -626,4 +626,16 @@ const std::unique_ptr<DriverInfoVK>& ContextVK::GetDriverInfo() const {
return driver_info_;
}

bool ContextVK::SupportsAHBSwapchain() const {
const CapabilitiesVK& caps = CapabilitiesVK::Cast(*device_capabilities_);
return caps.HasExtension(
OptionalAndroidDeviceExtensionVK::kKHRExternalFence) &&
caps.HasExtension(
OptionalAndroidDeviceExtensionVK::kKHRExternalFenceFd) &&
caps.HasExtension(
OptionalAndroidDeviceExtensionVK::kKHRExternalSemaphore) &&
caps.HasExtension(
OptionalAndroidDeviceExtensionVK::kKHRExternalSemaphoreFd);
}

} // namespace impeller
4 changes: 4 additions & 0 deletions impeller/renderer/backend/vulkan/context_vk.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ class ContextVK final : public Context,
// |Context|
void Shutdown() override;

/// @brief Whether the Vulkan context has sufficient capabilities to support
/// Android Hardware Buffer swapchains.
bool SupportsAHBSwapchain() const;

void SetOffscreenFormat(PixelFormat pixel_format);

template <typename T>
Expand Down
19 changes: 19 additions & 0 deletions impeller/renderer/backend/vulkan/context_vk_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -241,5 +241,24 @@ TEST(ContextVKTest, HasDefaultColorFormat) {
ASSERT_NE(capabilites_vk->GetDefaultColorFormat(), PixelFormat::kUnknown);
}

TEST(ContextVKTest, ChecksOptionalDeviceExtensionsForAndroid) {
auto context = MockVulkanContextBuilder().Build();
ASSERT_NE(context, nullptr);

EXPECT_FALSE(context->SupportsAHBSwapchain());

context = MockVulkanContextBuilder()
.SetDeviceExtensions({
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 //
})
.Build();
ASSERT_NE(context, nullptr);

EXPECT_TRUE(context->SupportsAHBSwapchain());
}

} // namespace testing
} // namespace impeller
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,6 @@ namespace impeller {

static constexpr size_t kMaxFramesInFlight = 3u;

// Number of frames to poll for orientation changes. For example `1u` means
// that the orientation will be polled every frame, while `2u` means that the
// orientation will be polled every other frame.
static constexpr size_t kPollFramesForOrientation = 1u;

struct KHRFrameSynchronizerVK {
vk::UniqueFence acquire;
vk::UniqueSemaphore render_ready;
Expand Down Expand Up @@ -335,10 +330,10 @@ KHRSwapchainImplVK::AcquireResult KHRSwapchainImplVK::AcquireNextDrawable() {
/// Get the next image index.
///
auto [acq_result, index] = context.GetDevice().acquireNextImageKHR(
*swapchain_, // swapchain
1'000'000'000, // timeout (ns) 1000ms
*sync->render_ready, // signal semaphore
nullptr // fence
*swapchain_, // swapchain
std::numeric_limits<uint64_t>::max(), // timeout (ns)
*sync->render_ready, // signal semaphore
nullptr // fence
);

switch (acq_result) {
Expand Down
3 changes: 2 additions & 1 deletion impeller/renderer/backend/vulkan/swapchain/swapchain_vk.cc
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ std::shared_ptr<SwapchainVK> SwapchainVK::Create(
const auto emulator = ContextVK::Cast(*context).GetDriverInfo()->IsEmulator();

// Try AHB swapchains first.
if (!emulator && AHBSwapchainVK::IsAvailableOnPlatform()) {
if (!emulator && ContextVK::Cast(*context).SupportsAHBSwapchain() &&
AHBSwapchainVK::IsAvailableOnPlatform()) {
auto ahb_swapchain = std::shared_ptr<AHBSwapchainVK>(new AHBSwapchainVK(
context, //
window.GetHandle(), //
Expand Down
17 changes: 14 additions & 3 deletions impeller/renderer/backend/vulkan/test/mock_vulkan.cc
Original file line number Diff line number Diff line change
Expand Up @@ -191,16 +191,23 @@ void vkGetPhysicalDeviceQueueFamilyProperties(
}
}

static thread_local std::vector<std::string> g_device_extensions;

VkResult vkEnumerateDeviceExtensionProperties(
VkPhysicalDevice physicalDevice,
const char* pLayerName,
uint32_t* pPropertyCount,
VkExtensionProperties* pProperties) {
if (!pProperties) {
*pPropertyCount = 1;
*pPropertyCount = g_device_extensions.size();
} else {
strcpy(pProperties[0].extensionName, "VK_KHR_swapchain");
pProperties[0].specVersion = 0;
uint32_t count = 0;
for (const std::string& ext : g_device_extensions) {
strncpy(pProperties[count].extensionName, ext.c_str(),
sizeof(VkExtensionProperties::extensionName));
pProperties[count].specVersion = 0;
count++;
}
}
return VK_SUCCESS;
}
Expand Down Expand Up @@ -916,7 +923,11 @@ std::shared_ptr<ContextVK> MockVulkanContextBuilder::Build() {
if (settings_callback_) {
settings_callback_(settings);
}
if (device_extensions_.empty()) {
device_extensions_.push_back("VK_KHR_swapchain");
}
g_instance_extensions = instance_extensions_;
g_device_extensions = device_extensions_;
g_instance_layers = instance_layers_;
g_format_properties_callback = format_properties_callback_;
std::shared_ptr<ContextVK> result = ContextVK::Create(std::move(settings));
Expand Down
8 changes: 8 additions & 0 deletions impeller/renderer/backend/vulkan/test/mock_vulkan.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,13 @@ class MockVulkanContextBuilder {
return *this;
}

MockVulkanContextBuilder& SetDeviceExtensions(
const std::vector<std::string>& device_extensions) {
device_extensions_ = device_extensions;
device_extensions_.push_back("VK_KHR_swapchain");
return *this;
}

MockVulkanContextBuilder& SetInstanceLayers(
const std::vector<std::string>& instance_layers) {
instance_layers_ = instance_layers;
Expand All @@ -103,6 +110,7 @@ class MockVulkanContextBuilder {
private:
std::function<void(ContextVK::Settings&)> settings_callback_;
std::vector<std::string> instance_extensions_;
std::vector<std::string> device_extensions_;
std::vector<std::string> instance_layers_;
std::function<void(VkPhysicalDevice physicalDevice,
VkFormat format,
Expand Down