diff --git a/CMakeLists.txt b/CMakeLists.txt index a998973..4dc800c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -275,6 +275,7 @@ add_library(${PROJECT_NAME} SHARED wsi/wsi_factory.cpp) if (VULKAN_WSI_LAYER_EXPERIMENTAL) target_sources(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/layer/present_timing.cpp) + target_sources(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/wsi/time_domains.cpp) add_definitions("-DVULKAN_WSI_LAYER_EXPERIMENTAL=1") else() list(APPEND JSON_COMMANDS COMMAND sed -i '/VK_EXT_present_timing/d' ${CMAKE_CURRENT_BINARY_DIR}/VkLayer_window_system_integration.json) diff --git a/layer/layer.cpp b/layer/layer.cpp index ca7b3ff..1d52a7b 100644 --- a/layer/layer.cpp +++ b/layer/layer.cpp @@ -534,7 +534,7 @@ wsi_layer_vkGetDeviceProcAddr(VkDevice device, const char *funcName) VWL_API_POS GET_PROC_ADDR(vkGetSwapchainStatusKHR); } #if VULKAN_WSI_LAYER_EXPERIMENTAL - if (layer::device_private_data::get(device).is_device_extension_enabled(VK_KHR_PRESENT_TIMING_EXTENSION_NAME)) + if (layer::device_private_data::get(device).is_device_extension_enabled(VK_EXT_PRESENT_TIMING_EXTENSION_NAME)) { GET_PROC_ADDR(vkSetSwapchainPresentTimingQueueSizeEXT); GET_PROC_ADDR(vkGetSwapchainTimingPropertiesEXT); diff --git a/layer/present_timing.cpp b/layer/present_timing.cpp index 1ae9446..db704c6 100644 --- a/layer/present_timing.cpp +++ b/layer/present_timing.cpp @@ -64,8 +64,15 @@ wsi_layer_vkGetSwapchainTimeDomainPropertiesEXT( VkDevice device, VkSwapchainKHR swapchain, uint64_t *pTimeDomainsCounter, VkSwapchainTimeDomainPropertiesEXT *pSwapchainTimeDomainProperties) VWL_API_POST { - VkResult result = VK_SUCCESS; - return result; + auto &device_data = layer::device_private_data::get(device); + + if (!device_data.layer_owns_swapchain(swapchain)) + { + return device_data.disp.GetSwapchainTimeDomainPropertiesEXT(device, swapchain, pTimeDomainsCounter, + pSwapchainTimeDomainProperties); + } + auto *sc = reinterpret_cast(swapchain); + return sc->set_swapchain_time_domain_properties(pSwapchainTimeDomainProperties, pTimeDomainsCounter); } /** diff --git a/layer/private_data.cpp b/layer/private_data.cpp index ac05dc1..080c831 100644 --- a/layer/private_data.cpp +++ b/layer/private_data.cpp @@ -50,7 +50,12 @@ VkResult instance_dispatch_table::populate(VkInstance instance, PFN_vkGetInstanc { "vk" #name, ext_name, nullptr, api_version, false, required }, INSTANCE_ENTRYPOINTS_LIST(DISPATCH_TABLE_ENTRY) #undef DISPATCH_TABLE_ENTRY +#if VULKAN_WSI_LAYER_EXPERIMENTAL + { "GetSwapchainTimeDomainPropertiesEXT", VK_EXT_PRESENT_TIMING_EXTENSION_NAME, nullptr, API_VERSION_MAX, false, + false } +#endif /* VULKAN_WSI_LAYER_EXPERIMENTAL */ }; + static constexpr auto num_entrypoints = std::distance(std::begin(entrypoints_init), std::end(entrypoints_init)); for (size_t i = 0; i < num_entrypoints; i++) diff --git a/layer/private_data.hpp b/layer/private_data.hpp index 3782d6a..2b293e0 100644 --- a/layer/private_data.hpp +++ b/layer/private_data.hpp @@ -41,7 +41,7 @@ #include #include #include - +#include "wsi_layer_experimental.hpp" using scoped_mutex = std::lock_guard; /** Forward declare stored objects */ @@ -339,72 +339,69 @@ private: * api_version: Vulkan API version where the entrypoint is part of the core specification, or API_VERSION_MAX. * required: Boolean to indicate whether the entrypoint is required by the WSI layer or optional. */ -#define DEVICE_ENTRYPOINTS_LIST(EP) \ - /* Vulkan 1.0 */ \ - EP(GetDeviceProcAddr, "", VK_API_VERSION_1_0, true) \ - EP(GetDeviceQueue, "", VK_API_VERSION_1_0, true) \ - EP(QueueSubmit, "", VK_API_VERSION_1_0, true) \ - EP(QueueWaitIdle, "", VK_API_VERSION_1_0, true) \ - EP(CreateCommandPool, "", VK_API_VERSION_1_0, true) \ - EP(DestroyCommandPool, "", VK_API_VERSION_1_0, true) \ - EP(AllocateCommandBuffers, "", VK_API_VERSION_1_0, true) \ - EP(FreeCommandBuffers, "", VK_API_VERSION_1_0, true) \ - EP(ResetCommandBuffer, "", VK_API_VERSION_1_0, true) \ - EP(BeginCommandBuffer, "", VK_API_VERSION_1_0, true) \ - EP(EndCommandBuffer, "", VK_API_VERSION_1_0, true) \ - EP(CreateImage, "", VK_API_VERSION_1_0, true) \ - EP(DestroyImage, "", VK_API_VERSION_1_0, true) \ - EP(GetImageMemoryRequirements, "", VK_API_VERSION_1_0, true) \ - EP(BindImageMemory, "", VK_API_VERSION_1_0, true) \ - EP(AllocateMemory, "", VK_API_VERSION_1_0, true) \ - EP(FreeMemory, "", VK_API_VERSION_1_0, true) \ - EP(CreateFence, "", VK_API_VERSION_1_0, true) \ - EP(DestroyFence, "", VK_API_VERSION_1_0, true) \ - EP(CreateSemaphore, "", VK_API_VERSION_1_0, true) \ - EP(DestroySemaphore, "", VK_API_VERSION_1_0, true) \ - EP(ResetFences, "", VK_API_VERSION_1_0, true) \ - EP(WaitForFences, "", VK_API_VERSION_1_0, true) \ - EP(DestroyDevice, "", VK_API_VERSION_1_0, true) \ - /* VK_KHR_swapchain */ \ - EP(CreateSwapchainKHR, VK_KHR_SWAPCHAIN_EXTENSION_NAME, API_VERSION_MAX, false) \ - EP(DestroySwapchainKHR, VK_KHR_SWAPCHAIN_EXTENSION_NAME, API_VERSION_MAX, false) \ - EP(GetSwapchainImagesKHR, VK_KHR_SWAPCHAIN_EXTENSION_NAME, API_VERSION_MAX, false) \ - EP(AcquireNextImageKHR, VK_KHR_SWAPCHAIN_EXTENSION_NAME, API_VERSION_MAX, false) \ - EP(QueuePresentKHR, VK_KHR_SWAPCHAIN_EXTENSION_NAME, API_VERSION_MAX, false) \ - /* VK_KHR_shared_presentable_image */ \ - EP(GetSwapchainStatusKHR, VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME, API_VERSION_MAX, false) \ - /* VK_KHR_device_group + VK_KHR_swapchain or */ \ - /* 1.1 with VK_KHR_swapchain */ \ - EP(AcquireNextImage2KHR, VK_KHR_DEVICE_GROUP_EXTENSION_NAME, VK_API_VERSION_1_1, false) \ - /* VK_KHR_device_group + VK_KHR_surface or */ \ - /* 1.1 with VK_KHR_swapchain */ \ - EP(GetDeviceGroupSurfacePresentModesKHR, VK_KHR_DEVICE_GROUP_EXTENSION_NAME, VK_API_VERSION_1_1, false) \ - EP(GetDeviceGroupPresentCapabilitiesKHR, VK_KHR_DEVICE_GROUP_EXTENSION_NAME, VK_API_VERSION_1_1, false) \ - /* VK_KHR_external_memory_fd */ \ - EP(GetMemoryFdKHR, VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, API_VERSION_MAX, false) \ - EP(GetMemoryFdPropertiesKHR, VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, API_VERSION_MAX, false) \ - /* VK_KHR_bind_memory2 or */ \ - /* 1.1 (without KHR suffix) */ \ - EP(BindImageMemory2KHR, VK_KHR_BIND_MEMORY_2_EXTENSION_NAME, VK_API_VERSION_1_1, false) \ - EP(BindBufferMemory2KHR, VK_KHR_BIND_MEMORY_2_EXTENSION_NAME, VK_API_VERSION_1_1, false) \ - /* VK_KHR_external_fence_fd */ \ - EP(GetFenceFdKHR, VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME, API_VERSION_MAX, false) \ - EP(ImportFenceFdKHR, VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME, API_VERSION_MAX, false) \ - /* VK_KHR_external_semaphore_fd */ \ - EP(ImportSemaphoreFdKHR, VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, API_VERSION_MAX, false) \ - EP(GetSemaphoreFdKHR, VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, API_VERSION_MAX, false) \ - /* VK_KHR_image_drm_format_modifier */ \ - EP(GetImageDrmFormatModifierPropertiesEXT, VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME, API_VERSION_MAX, false) \ - /* VK_KHR_sampler_ycbcr_conversion */ \ - EP(CreateSamplerYcbcrConversionKHR, VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, VK_API_VERSION_1_1, false) \ - EP(DestroySamplerYcbcrConversionKHR, VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, VK_API_VERSION_1_1, false) \ - /* VK_KHR_maintenance1 */ \ - EP(TrimCommandPoolKHR, VK_KHR_MAINTENANCE1_EXTENSION_NAME, VK_API_VERSION_1_1, false) \ - /* VK_KHR_get_memory_requirements2 */ \ - EP(GetImageMemoryRequirements2KHR, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME, VK_API_VERSION_1_1, false) \ - EP(GetBufferMemoryRequirements2KHR, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME, VK_API_VERSION_1_1, false) \ - EP(GetImageSparseMemoryRequirements2KHR, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME, VK_API_VERSION_1_1, \ - false) \ +#define DEVICE_ENTRYPOINTS_LIST(EP) \ + /* Vulkan 1.0 */ \ + EP(GetDeviceProcAddr, "", VK_API_VERSION_1_0, true) \ + EP(GetDeviceQueue, "", VK_API_VERSION_1_0, true) \ + EP(QueueSubmit, "", VK_API_VERSION_1_0, true) \ + EP(QueueWaitIdle, "", VK_API_VERSION_1_0, true) \ + EP(CreateCommandPool, "", VK_API_VERSION_1_0, true) \ + EP(DestroyCommandPool, "", VK_API_VERSION_1_0, true) \ + EP(AllocateCommandBuffers, "", VK_API_VERSION_1_0, true) \ + EP(FreeCommandBuffers, "", VK_API_VERSION_1_0, true) \ + EP(ResetCommandBuffer, "", VK_API_VERSION_1_0, true) \ + EP(BeginCommandBuffer, "", VK_API_VERSION_1_0, true) \ + EP(EndCommandBuffer, "", VK_API_VERSION_1_0, true) \ + EP(CreateImage, "", VK_API_VERSION_1_0, true) \ + EP(DestroyImage, "", VK_API_VERSION_1_0, true) \ + EP(GetImageMemoryRequirements, "", VK_API_VERSION_1_0, true) \ + EP(BindImageMemory, "", VK_API_VERSION_1_0, true) \ + EP(AllocateMemory, "", VK_API_VERSION_1_0, true) \ + EP(FreeMemory, "", VK_API_VERSION_1_0, true) \ + EP(CreateFence, "", VK_API_VERSION_1_0, true) \ + EP(DestroyFence, "", VK_API_VERSION_1_0, true) \ + EP(CreateSemaphore, "", VK_API_VERSION_1_0, true) \ + EP(DestroySemaphore, "", VK_API_VERSION_1_0, true) \ + EP(ResetFences, "", VK_API_VERSION_1_0, true) \ + EP(WaitForFences, "", VK_API_VERSION_1_0, true) \ + EP(DestroyDevice, "", VK_API_VERSION_1_0, true) \ + /* VK_KHR_swapchain */ \ + EP(CreateSwapchainKHR, VK_KHR_SWAPCHAIN_EXTENSION_NAME, API_VERSION_MAX, false) \ + EP(DestroySwapchainKHR, VK_KHR_SWAPCHAIN_EXTENSION_NAME, API_VERSION_MAX, false) \ + EP(GetSwapchainImagesKHR, VK_KHR_SWAPCHAIN_EXTENSION_NAME, API_VERSION_MAX, false) \ + EP(AcquireNextImageKHR, VK_KHR_SWAPCHAIN_EXTENSION_NAME, API_VERSION_MAX, false) \ + EP(QueuePresentKHR, VK_KHR_SWAPCHAIN_EXTENSION_NAME, API_VERSION_MAX, false) \ + /* VK_KHR_shared_presentable_image */ \ + EP(GetSwapchainStatusKHR, VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME, API_VERSION_MAX, false) \ + /* VK_KHR_device_group + VK_KHR_swapchain or */ /* 1.1 with VK_KHR_swapchain */ \ + EP(AcquireNextImage2KHR, VK_KHR_DEVICE_GROUP_EXTENSION_NAME, VK_API_VERSION_1_1, false) \ + /* VK_KHR_device_group + VK_KHR_surface or */ /* 1.1 with VK_KHR_swapchain */ \ + EP(GetDeviceGroupSurfacePresentModesKHR, VK_KHR_DEVICE_GROUP_EXTENSION_NAME, VK_API_VERSION_1_1, false) \ + EP(GetDeviceGroupPresentCapabilitiesKHR, VK_KHR_DEVICE_GROUP_EXTENSION_NAME, VK_API_VERSION_1_1, \ + false) /* VK_KHR_external_memory_fd */ \ + EP(GetMemoryFdKHR, VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, API_VERSION_MAX, false) \ + EP(GetMemoryFdPropertiesKHR, VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, API_VERSION_MAX, false) \ + /* VK_KHR_bind_memory2 or */ /* 1.1 (without KHR suffix) */ \ + EP(BindImageMemory2KHR, VK_KHR_BIND_MEMORY_2_EXTENSION_NAME, VK_API_VERSION_1_1, false) \ + EP(BindBufferMemory2KHR, VK_KHR_BIND_MEMORY_2_EXTENSION_NAME, VK_API_VERSION_1_1, \ + false) /* VK_KHR_external_fence_fd */ \ + EP(GetFenceFdKHR, VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME, API_VERSION_MAX, false) \ + EP(ImportFenceFdKHR, VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME, API_VERSION_MAX, \ + false) /* VK_KHR_external_semaphore_fd */ \ + EP(ImportSemaphoreFdKHR, VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, API_VERSION_MAX, false) \ + EP(GetSemaphoreFdKHR, VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, API_VERSION_MAX, \ + false) /* VK_KHR_image_drm_format_modifier */ \ + EP(GetImageDrmFormatModifierPropertiesEXT, VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME, API_VERSION_MAX, \ + false) /* VK_KHR_sampler_ycbcr_conversion */ \ + EP(CreateSamplerYcbcrConversionKHR, VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, VK_API_VERSION_1_1, false) \ + EP(DestroySamplerYcbcrConversionKHR, VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, VK_API_VERSION_1_1, \ + false) /* VK_KHR_maintenance1 */ \ + EP(TrimCommandPoolKHR, VK_KHR_MAINTENANCE1_EXTENSION_NAME, VK_API_VERSION_1_1, \ + false) /* VK_KHR_get_memory_requirements2 */ \ + EP(GetImageMemoryRequirements2KHR, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME, VK_API_VERSION_1_1, false) \ + EP(GetBufferMemoryRequirements2KHR, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME, VK_API_VERSION_1_1, false) \ + EP(GetImageSparseMemoryRequirements2KHR, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME, VK_API_VERSION_1_1, \ + false) \ EP(ReleaseSwapchainImagesEXT, VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME, VK_API_VERSION_1_1, false) /** @@ -461,6 +458,15 @@ public: DEVICE_ENTRYPOINTS_LIST(DISPATCH_TABLE_SHORTCUT) #undef DISPATCH_TABLE_SHORTCUT +#if VULKAN_WSI_LAYER_EXPERIMENTAL + template + auto GetSwapchainTimeDomainPropertiesEXT(Args &&...args) const + { + return call_fn("vkGetSwapchainTimeDomainPropertiesEXT", + std::forward(args)...); + }; +#endif + private: /** * @brief Construct instance dispatch table object diff --git a/layer/wsi_layer_experimental.hpp b/layer/wsi_layer_experimental.hpp index 81deedb..fecb12c 100644 --- a/layer/wsi_layer_experimental.hpp +++ b/layer/wsi_layer_experimental.hpp @@ -33,9 +33,9 @@ #include "util/macros.hpp" #if VULKAN_WSI_LAYER_EXPERIMENTAL -#define VK_KHR_present_timing 1 -#define VK_KHR_PRESENT_TIMING_SPEC_VERSION 1 -#define VK_KHR_PRESENT_TIMING_EXTENSION_NAME "VK_KHR_present_timing" +#define VK_EXT_present_timing 1 +#define VK_EXT_PRESENT_TIMING_SPEC_VERSION 1 +#define VK_EXT_PRESENT_TIMING_EXTENSION_NAME "VK_KHR_present_timing" #define VK_ERROR_PRESENT_TIMING_QUEUE_FULL_EXT ((VkResult)(-1000208000)) #define VK_TIME_DOMAIN_PRESENT_STAGE_LOCAL_EXT ((VkTimeDomainEXT)(1000208000)) @@ -168,6 +168,10 @@ typedef struct VkPresentTimingsInfoEXT const VkPresentTimingInfoEXT *pTimingInfos; } VkPresentTimingsInfoEXT; +typedef VkResult(VKAPI_PTR *PFN_vkGetSwapchainTimeDomainPropertiesEXT)( + VkDevice device, VkSwapchainKHR swapchain, uint64_t *pTimeDomainsCounter, + VkSwapchainTimeDomainPropertiesEXT *pSwapchainTimeDomainProperties); + VWL_VKAPI_CALL(VkResult) wsi_layer_vkSetSwapchainPresentTimingQueueSizeEXT(VkDevice device, VkSwapchainKHR swapchain, uint32_t size) VWL_API_POST; diff --git a/wsi/headless/swapchain.cpp b/wsi/headless/swapchain.cpp index f71ff62..52502d8 100644 --- a/wsi/headless/swapchain.cpp +++ b/wsi/headless/swapchain.cpp @@ -34,6 +34,8 @@ #include #include "swapchain.hpp" +#include "layer/wsi_layer_experimental.hpp" +#include "util/custom_allocator.hpp" namespace wsi { @@ -72,6 +74,27 @@ VkResult swapchain::init_platform(VkDevice device, const VkSwapchainCreateInfoKH { use_presentation_thread = true; } +#if VULKAN_WSI_LAYER_EXPERIMENTAL + std::array, 4> time_domains_array = { + m_allocator.make_unique(VK_PRESENT_STAGE_QUEUE_OPERATIONS_END_BIT_EXT, + VK_TIME_DOMAIN_DEVICE_KHR), + m_allocator.make_unique(VK_PRESENT_STAGE_IMAGE_LATCHED_BIT_EXT, + VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR), + m_allocator.make_unique(VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_OUT_BIT_EXT, + VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR), + m_allocator.make_unique(VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_VISIBLE_BIT_EXT, + VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR) + }; + + for (auto &time_domain : time_domains_array) + { + if (!m_time_domains.m_time_domains.try_push_back(std::move(time_domain))) + { + WSI_LOG_ERROR("Failed to add a time domain to m_time_domains."); + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + } +#endif return VK_SUCCESS; } diff --git a/wsi/swapchain_base.cpp b/wsi/swapchain_base.cpp index c99624a..eec5483 100644 --- a/wsi/swapchain_base.cpp +++ b/wsi/swapchain_base.cpp @@ -220,6 +220,9 @@ swapchain_base::swapchain_base(layer::device_private_data &dev_data, const VkAll , m_image_compression_control_params({ VK_IMAGE_COMPRESSION_DEFAULT_EXT, 0 }) #endif , m_image_create_info() +#if VULKAN_WSI_LAYER_EXPERIMENTAL + , m_time_domains(m_allocator) +#endif , m_image_acquire_lock() , m_error_state(VK_NOT_READY) , m_started_presenting(false) @@ -916,6 +919,12 @@ size_t swapchain_base::presentation_timing_get_num_outstanding_results() } return num_outstanding; } + +VkResult swapchain_base::set_swapchain_time_domain_properties( + VkSwapchainTimeDomainPropertiesEXT *pSwapchainTimeDomainProperties, uint64_t *pTimeDomainsCounter) +{ + return m_time_domains.set_swapchain_time_domain_properties(pSwapchainTimeDomainProperties, pTimeDomainsCounter); +} #endif } /* namespace wsi */ diff --git a/wsi/swapchain_base.hpp b/wsi/swapchain_base.hpp index fe087a4..b690694 100644 --- a/wsi/swapchain_base.hpp +++ b/wsi/swapchain_base.hpp @@ -44,6 +44,8 @@ #include "wsi/synchronization.hpp" #include "wsi/frame_boundary.hpp" #include "util/helpers.hpp" +#include "time_domains.hpp" +#include "layer/wsi_layer_experimental.hpp" namespace wsi { @@ -304,7 +306,18 @@ public: * @return VK_SUCCESS on success, VK_ERROR_OUT_OF_HOST_MEMORY when there is not enough memory, VK_NOT_READY otherwise. * . */ + VkResult presentation_timing_queue_set_size(size_t queue_size); + /** + * @brief Set swapchain time domain properties. + * + * @param pSwapchainTimeDomainProperties time domain struct to be set + * @param pTimeDomainsCounter size of the pSwapchainTimeDomainProperties + * + * @return Returns VK_SUCCESS on success, otherwise an appropriate error code. + */ + VkResult set_swapchain_time_domain_properties(VkSwapchainTimeDomainPropertiesEXT *pSwapchainTimeDomainProperties, + uint64_t *pTimeDomainsCounter); #endif protected: @@ -426,6 +439,13 @@ protected: */ VkImageCreateInfo m_image_create_info; +#if VULKAN_WSI_LAYER_EXPERIMENTAL + /** + * @brief Handle the backend specific time domains for each present stage. + */ + swapchain_time_domains m_time_domains; +#endif + /** * @brief Return the VkAllocationCallbacks passed in this object constructor. */ diff --git a/wsi/time_domains.cpp b/wsi/time_domains.cpp new file mode 100644 index 0000000..4f6eab6 --- /dev/null +++ b/wsi/time_domains.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2024 Arm Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * @file time_domains.cpp + * + * @brief Contains implemenations and details for the time domains per backend. + */ + +#include "time_domains.hpp" +#include +namespace wsi +{ +#if VULKAN_WSI_LAYER_EXPERIMENTAL + +VkResult swapchain_time_domains::calibrate(VkPresentStageFlagBitsEXT present_stage, + swapchain_calibrated_time *calibrated_time) +{ + for (auto &domain : m_time_domains) + { + if ((domain->get_present_stages() & present_stage) != 0) + { + *calibrated_time = domain->calibrate(); + return VK_SUCCESS; + } + } + + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +VkResult swapchain_time_domains::set_swapchain_time_domain_properties( + VkSwapchainTimeDomainPropertiesEXT *pSwapchainTimeDomainProperties, uint64_t *pTimeDomainsCounter) +{ + if (pTimeDomainsCounter != nullptr) + { + if (pSwapchainTimeDomainProperties == nullptr) + { + *pTimeDomainsCounter = 1; + return VK_SUCCESS; + } + pSwapchainTimeDomainProperties->timeDomainCount = 1; + pSwapchainTimeDomainProperties->pTimeDomains[0] = VK_TIME_DOMAIN_PRESENT_STAGE_LOCAL_EXT; + pSwapchainTimeDomainProperties->pTimeDomainIds = 0; + + return (*pTimeDomainsCounter < 1) ? VK_INCOMPLETE : VK_SUCCESS; + } + + if (pSwapchainTimeDomainProperties != nullptr) + { + if (pSwapchainTimeDomainProperties->pTimeDomains == nullptr && + pSwapchainTimeDomainProperties->pTimeDomainIds == nullptr) + { + pSwapchainTimeDomainProperties->timeDomainCount = 1; + return VK_SUCCESS; + } + if (pSwapchainTimeDomainProperties->pTimeDomains != nullptr && + pSwapchainTimeDomainProperties->pTimeDomainIds != nullptr) + { + pSwapchainTimeDomainProperties->timeDomainCount = 1; + pSwapchainTimeDomainProperties->pTimeDomains[0] = VK_TIME_DOMAIN_PRESENT_STAGE_LOCAL_EXT; + pSwapchainTimeDomainProperties->pTimeDomainIds = 0; + return VK_SUCCESS; + } + } + + return VK_SUCCESS; +} +#endif +} diff --git a/wsi/time_domains.hpp b/wsi/time_domains.hpp new file mode 100644 index 0000000..55e7880 --- /dev/null +++ b/wsi/time_domains.hpp @@ -0,0 +1,108 @@ + +/* + * Copyright (c) 2024 Arm Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * @file time_domains.hpp + * + * @brief Contains functions and details for the time domains per backend. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include "util/custom_allocator.hpp" +#include "layer/wsi_layer_experimental.hpp" +namespace wsi +{ +#if VULKAN_WSI_LAYER_EXPERIMENTAL + +// Predefined struct for calibrated time +struct swapchain_calibrated_time +{ + VkTimeDomainKHR time_domain; + uint64_t offset; +}; + +// Base struct for swapchain time domain +class swapchain_time_domain +{ +public: + swapchain_time_domain(VkPresentStageFlagsEXT presentStages) + : m_present_stages(presentStages) + { + } + + virtual swapchain_calibrated_time calibrate() = 0; + + VkPresentStageFlagsEXT get_present_stages() + { + return m_present_stages; + } + +private: + VkPresentStageFlagsEXT m_present_stages; +}; + +class vulkan_time_domain : public swapchain_time_domain +{ +public: + vulkan_time_domain(VkPresentStageFlagsEXT presentStages, VkTimeDomainKHR time_domain) + : swapchain_time_domain(presentStages) + , m_time_domain(time_domain) + { + } + + /* The calibrate function should return a Vulkan time domain + an offset.*/ + swapchain_calibrated_time calibrate() override + { + return { m_time_domain, 0 }; + } + +private: + VkTimeDomainKHR m_time_domain; +}; + +/* Class holding multiple time domains for a swapchain*/ +class swapchain_time_domains +{ +public: + swapchain_time_domains(const util::allocator &allocator) + : m_time_domains(allocator) + { + } + + util::vector> m_time_domains; + + VkResult calibrate(VkPresentStageFlagBitsEXT presentStages, swapchain_calibrated_time *calibrated_time); + + VkResult set_swapchain_time_domain_properties(VkSwapchainTimeDomainPropertiesEXT *pSwapchainTimeDomainProperties, + uint64_t *pTimeDomainsCounter); +}; +#endif +} \ No newline at end of file diff --git a/wsi/wayland/swapchain.cpp b/wsi/wayland/swapchain.cpp index 6392bb4..b83ace2 100644 --- a/wsi/wayland/swapchain.cpp +++ b/wsi/wayland/swapchain.cpp @@ -27,6 +27,7 @@ #include "swapchain.hpp" #include "wl_helpers.hpp" #include "surface_properties.hpp" +#include "layer/wsi_layer_experimental.hpp" #include #include @@ -80,6 +81,22 @@ swapchain::~swapchain() VkResult swapchain::init_platform(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info, bool &use_presentation_thread) { +#if VULKAN_WSI_LAYER_EXPERIMENTAL + std::array, 1> time_domains_array = { + m_allocator.make_unique(VK_PRESENT_STAGE_QUEUE_OPERATIONS_END_BIT_EXT, + VK_TIME_DOMAIN_DEVICE_KHR), + }; + + for (auto &time_domain : time_domains_array) + { + if (!m_time_domains.m_time_domains.try_push_back(std::move(time_domain))) + { + WSI_LOG_ERROR("Failed to add a time domain to m_time_domains."); + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + } +#endif + if ((m_display == nullptr) || (m_surface == nullptr) || (m_wsi_surface->get_dmabuf_interface() == nullptr)) { return VK_ERROR_INITIALIZATION_FAILED;