summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Harvey-Macaulay <david.harvey-macaulay@arm.com>2022-01-13 10:08:03 +0000
committerDavid Harvey-Macaulay <david.harvey-macaulay@arm.com>2022-02-08 15:27:29 +0000
commitba0684b5e0673d1c264ae4a1cc33fadda94f9775 (patch)
tree7bf34f97bba2f31175d2db9dd96a05b0eea40095
parente78252429a0a1e5a44b1c98b85fb948c28eecba9 (diff)
downloadvulkan-wsi-layer-ba0684b5e0673d1c264ae4a1cc33fadda94f9775.tar.gz
vulkan-wsi-layer-ba0684b5e0673d1c264ae4a1cc33fadda94f9775.tar.bz2
vulkan-wsi-layer-ba0684b5e0673d1c264ae4a1cc33fadda94f9775.zip
Mark fences and semaphores as already signalled in AcquireNextImage
The VK_KHR_external_[fence|semaphore]_fd extensions allow sync primitives to be signalled without the use of QueueSubmit. Using these extensions in AcquireNextImage instead of using QueueSubmit offers two advantages: (1) there is no waiting for work to complete in the queue before the primitives are signalled and (2) there is no data race if the application happens to call QueueSubmit on the same queue at the same time. The QueueSubmit method of signalling sync primitives continues to be used for ICDs that do not support the external FD extensions. Signed-off-by: David Harvey-Macaulay <david.harvey-macaulay@arm.com> Change-Id: Ib4a922d44430110e2353a4e0221e27017e72abab
-rw-r--r--layer/private_data.hpp6
-rw-r--r--util/extension_list.hpp7
-rw-r--r--util/helpers.hpp37
-rw-r--r--wsi/swapchain_base.cpp58
-rw-r--r--wsi/wsi_factory.cpp76
5 files changed, 147 insertions, 37 deletions
diff --git a/layer/private_data.hpp b/layer/private_data.hpp
index 11fa5ce..ee43338 100644
--- a/layer/private_data.hpp
+++ b/layer/private_data.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2021 Arm Limited.
+ * Copyright (c) 2018-2022 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -136,7 +136,9 @@ struct instance_dispatch_table
OPTIONAL(GetDeviceGroupSurfacePresentModesKHR) \
OPTIONAL(GetDeviceGroupPresentCapabilitiesKHR) \
OPTIONAL(AcquireNextImage2KHR) \
- OPTIONAL(GetFenceFdKHR)
+ OPTIONAL(GetFenceFdKHR) \
+ OPTIONAL(ImportFenceFdKHR) \
+ OPTIONAL(ImportSemaphoreFdKHR)
struct device_dispatch_table
{
diff --git a/util/extension_list.hpp b/util/extension_list.hpp
index 0268efa..8caecb6 100644
--- a/util/extension_list.hpp
+++ b/util/extension_list.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2021 Arm Limited.
+ * Copyright (c) 2019, 2021-2022 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -85,6 +85,11 @@ public:
VkResult add(const extension_list &ext_list);
VkResult add(const char *const *extensions, uint32_t count);
+ VkResult add(const char *extension)
+ {
+ return add(&extension, 1);
+ }
+
/**
* @brief Perform intersection between extensions and add them to the list.
*
diff --git a/util/helpers.hpp b/util/helpers.hpp
index 9b5932e..cbdc4e3 100644
--- a/util/helpers.hpp
+++ b/util/helpers.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Arm Limited.
+ * Copyright (c) 2021-2022 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -32,6 +32,41 @@
#include <vulkan/vulkan.h>
+/*
+ * Conditional return statement. This allows functions to return early for
+ * failing Vulkan commands with a terse syntax.
+ *
+ * Example usage:
+ *
+ * VkResult foo()
+ * {
+ * TRY(vkCommand());
+ * return VK_SUCCESS;
+ * }
+ *
+ * The above is equivalent to:
+ *
+ * VkResult foo()
+ * {
+ * VkResult result = vkCommand();
+ * if (result != VK_SUCCESS)
+ * {
+ * return result;
+ * }
+ * return VK_SUCCESS;
+ * }
+ */
+#define TRY(expression) \
+ do \
+ { \
+ VkResult try_result = expression; \
+ if (try_result != VK_SUCCESS) \
+ { \
+ return try_result; \
+ } \
+ } \
+ while (0)
+
namespace util
{
template <typename T>
diff --git a/wsi/swapchain_base.cpp b/wsi/swapchain_base.cpp
index ab24f0b..7fbbe68 100644
--- a/wsi/swapchain_base.cpp
+++ b/wsi/swapchain_base.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Arm Limited.
+ * Copyright (c) 2017-2022 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -404,6 +404,62 @@ VkResult swapchain_base::acquire_next_image(uint64_t timeout, VkSemaphore semaph
image_status_lock.unlock();
+ /* Try to signal fences/semaphores with a sync FD for optimal performance. */
+ if (m_device_data.disp.ImportFenceFdKHR != nullptr &&
+ m_device_data.disp.ImportSemaphoreFdKHR != nullptr)
+ {
+ if (fence != VK_NULL_HANDLE)
+ {
+ int already_signalled_sentinel_fd = -1;
+ auto info = VkImportFenceFdInfoKHR{};
+ {
+ info.sType = VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR;
+ info.fence = fence;
+ info.handleType = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT;
+ info.fd = already_signalled_sentinel_fd;
+ }
+
+ auto result = m_device_data.disp.ImportFenceFdKHR(m_device, &info);
+ switch (result)
+ {
+ case VK_SUCCESS:
+ fence = VK_NULL_HANDLE;
+ break;
+ case VK_ERROR_INVALID_EXTERNAL_HANDLE:
+ /* Leave to fallback. */
+ break;
+ default:
+ return result;
+ }
+ }
+
+ if (semaphore != VK_NULL_HANDLE)
+ {
+ int already_signalled_sentinel_fd = -1;
+ auto info = VkImportSemaphoreFdInfoKHR{};
+ {
+ info.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR;
+ info.semaphore = semaphore;
+ info.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
+ info.fd = already_signalled_sentinel_fd;
+ }
+
+ auto result = m_device_data.disp.ImportSemaphoreFdKHR(m_device, &info);
+ switch (result)
+ {
+ case VK_SUCCESS:
+ semaphore = VK_NULL_HANDLE;
+ break;
+ case VK_ERROR_INVALID_EXTERNAL_HANDLE:
+ /* Leave to fallback. */
+ break;
+ default:
+ return result;
+ }
+ }
+ }
+
+ /* Fallback for when importing fence/semaphore sync FDs is unsupported by the ICD. */
if (VK_NULL_HANDLE != semaphore || VK_NULL_HANDLE != fence)
{
VkSubmitInfo submit = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
diff --git a/wsi/wsi_factory.cpp b/wsi/wsi_factory.cpp
index 6d7013a..d62b1ca 100644
--- a/wsi/wsi_factory.cpp
+++ b/wsi/wsi_factory.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2021 Arm Limited.
+ * Copyright (c) 2019-2022 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -119,38 +119,58 @@ util::wsi_platform_set find_enabled_layer_platforms(const VkInstanceCreateInfo *
return ret;
}
+static VkResult get_available_device_extensions(VkPhysicalDevice physical_device,
+ util::extension_list &available_extensions)
+{
+ auto &instance_data = layer::instance_private_data::get(physical_device);
+ util::vector<VkExtensionProperties> properties{available_extensions.get_allocator()};
+ uint32_t count;
+ TRY(instance_data.disp.EnumerateDeviceExtensionProperties(physical_device, nullptr, &count, nullptr));
+
+ if (!properties.try_resize(count))
+ {
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+
+ TRY(instance_data.disp.EnumerateDeviceExtensionProperties(physical_device, nullptr, &count, properties.data()));
+ TRY(available_extensions.add(properties.data(), count));
+
+ return VK_SUCCESS;
+}
+
VkResult add_extensions_required_by_layer(VkPhysicalDevice phys_dev, const util::wsi_platform_set enabled_platforms,
util::extension_list &extensions_to_enable)
{
util::allocator allocator{extensions_to_enable.get_allocator(), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND};
- util::extension_list device_extensions{allocator};
- util::vector<VkExtensionProperties> ext_props{allocator};
- layer::instance_private_data &inst_data = layer::instance_private_data::get(phys_dev);
- uint32_t count;
- VkResult res = inst_data.disp.EnumerateDeviceExtensionProperties(phys_dev, nullptr, &count, nullptr);
+ util::extension_list available_device_extensions{allocator};
+ TRY(get_available_device_extensions(phys_dev, available_device_extensions));
- if (res == VK_SUCCESS)
+ /* Add optional extensions independent of winsys. */
{
- if (!ext_props.try_resize(count))
+ const char *optional_extensions[] =
{
- return VK_ERROR_OUT_OF_HOST_MEMORY;
- }
- res = inst_data.disp.EnumerateDeviceExtensionProperties(phys_dev, nullptr, &count, ext_props.data());
- }
+ VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME,
+ VK_KHR_EXTERNAL_FENCE_EXTENSION_NAME,
+ VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME,
- if (res != VK_SUCCESS)
- {
- return res;
- }
+ VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME,
+ VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME,
+ VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME,
- res = device_extensions.add(ext_props.data(), count);
+ VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
+ };
- if (res != VK_SUCCESS)
- {
- return res;
+ for (auto extension : optional_extensions)
+ {
+ if (available_device_extensions.contains(extension))
+ {
+ TRY(extensions_to_enable.add(extension));
+ }
+ }
}
+ layer::instance_private_data &inst_data = layer::instance_private_data::get(phys_dev);
for (const auto &wsi_ext : supported_wsi_extensions)
{
/* Skip iterating over platforms not enabled in the instance. */
@@ -166,13 +186,8 @@ VkResult add_extensions_required_by_layer(VkPhysicalDevice phys_dev, const util:
return VK_ERROR_INITIALIZATION_FAILED;
}
- res = props->get_required_device_extensions(extensions_required_by_layer);
- if (res != VK_SUCCESS)
- {
- return res;
- }
-
- bool supported = device_extensions.contains(extensions_required_by_layer);
+ TRY(props->get_required_device_extensions(extensions_required_by_layer));
+ bool supported = available_device_extensions.contains(extensions_required_by_layer);
if (!supported)
{
/* Can we accept failure? The layer unconditionally advertises support for this platform and the loader uses
@@ -183,12 +198,9 @@ VkResult add_extensions_required_by_layer(VkPhysicalDevice phys_dev, const util:
return VK_ERROR_INITIALIZATION_FAILED;
}
- res = extensions_to_enable.add(extensions_required_by_layer);
- if (res != VK_SUCCESS)
- {
- return res;
- }
+ TRY(extensions_to_enable.add(extensions_required_by_layer));
}
+
return VK_SUCCESS;
}