diff --git a/CMakeLists.txt b/CMakeLists.txt index 4ef48f0..42032a8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -146,13 +146,13 @@ if(BUILD_WSI_WAYLAND) wsi/wayland/surface.cpp wsi/wayland/wl_helpers.cpp wsi/wayland/swapchain.cpp + wsi/wayland/present_wait_wayland.cpp wsi/swapchain_image_create_extensions/external_memory_extension.cpp) if(VULKAN_WSI_LAYER_EXPERIMENTAL) target_sources(wayland_wsi PRIVATE wsi/wayland/present_id_wayland.cpp) target_sources(wayland_wsi PRIVATE wsi/wayland/present_timing_handler.cpp) target_sources(wayland_wsi PRIVATE wsi/wayland/wp_presentation_feedback.cpp) - target_sources(wayland_wsi PRIVATE wsi/wayland/present_wait_wayland.cpp) endif() pkg_check_modules(WAYLAND_CLIENT REQUIRED wayland-client) @@ -229,11 +229,11 @@ if(BUILD_WSI_HEADLESS) add_library(wsi_headless STATIC wsi/headless/surface_properties.cpp wsi/headless/surface.cpp - wsi/headless/swapchain.cpp) + wsi/headless/swapchain.cpp + wsi/headless/present_wait_headless.cpp) if(VULKAN_WSI_LAYER_EXPERIMENTAL) target_sources(wsi_headless PRIVATE wsi/headless/present_timing_handler.cpp) - target_sources(wsi_headless PRIVATE wsi/headless/present_wait_headless.cpp) endif() target_include_directories(wsi_headless PRIVATE @@ -255,11 +255,8 @@ if (BUILD_WSI_DISPLAY) wsi/display/surface_properties.cpp wsi/display/swapchain.cpp wsi/display/surface.cpp - wsi/swapchain_image_create_extensions/external_memory_extension.cpp) - - if(VULKAN_WSI_LAYER_EXPERIMENTAL) - target_sources(wsi_display PRIVATE wsi/display/present_wait_display.cpp) - endif() + wsi/swapchain_image_create_extensions/external_memory_extension.cpp + wsi/display/present_wait_display.cpp) pkg_check_modules(LIBDRM REQUIRED libdrm) message(STATUS "Using libdrm include directories: ${LIBDRM_INCLUDE_DIRS}") @@ -295,6 +292,7 @@ add_library(${PROJECT_NAME} SHARED layer/surface_api.cpp layer/swapchain_api.cpp layer/swapchain_maintenance_api.cpp + layer/present_wait_api.cpp util/timed_semaphore.cpp util/custom_allocator.cpp util/extension_list.cpp @@ -303,6 +301,7 @@ add_library(${PROJECT_NAME} SHARED wsi/external_memory.cpp wsi/extensions/image_compression_control.cpp wsi/extensions/present_id.cpp + wsi/extensions/present_wait.cpp wsi/extensions/frame_boundary.cpp wsi/extensions/wsi_extension.cpp wsi/extensions/swapchain_maintenance.cpp @@ -315,11 +314,9 @@ add_library(${PROJECT_NAME} SHARED if (VULKAN_WSI_LAYER_EXPERIMENTAL) target_sources(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/layer/present_timing_api.cpp) target_sources(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/wsi/extensions/present_timing.cpp) - target_sources(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/layer/present_wait_api.cpp) - target_sources(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/wsi/extensions/present_wait.cpp) add_definitions("-DVULKAN_WSI_LAYER_EXPERIMENTAL=1") else() - list(APPEND JSON_COMMANDS COMMAND sed -Ei '/VK_EXT_present_timing|VK_KHR_present_wait|VK_EXT_present_mode_fifo_latest_ready/d' ${CMAKE_CURRENT_BINARY_DIR}/VkLayer_window_system_integration.json) + list(APPEND JSON_COMMANDS COMMAND sed -Ei '/VK_EXT_present_timing|VK_EXT_present_mode_fifo_latest_ready/d' ${CMAKE_CURRENT_BINARY_DIR}/VkLayer_window_system_integration.json) add_definitions("-DVULKAN_WSI_LAYER_EXPERIMENTAL=0") endif() diff --git a/README.md b/README.md index 59c32e7..bac0c13 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ implements the following extensions: * VK_KHR_shared_presentable_image * VK_EXT_image_compression_control_swapchain * VK_KHR_present_id + * VK_KHR_present_wait * VK_EXT_swapchain_maintenance1 ## Building diff --git a/layer/layer.cpp b/layer/layer.cpp index 94221a0..6be94af 100644 --- a/layer/layer.cpp +++ b/layer/layer.cpp @@ -384,14 +384,12 @@ VKAPI_ATTR VkResult create_device(VkPhysicalDevice physicalDevice, const VkDevic physical_device_swapchain_maintenance1_features->swapchainMaintenance1); } -#if VULKAN_WSI_LAYER_EXPERIMENTAL auto *present_wait_features = util::find_extension( VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_WAIT_FEATURES_KHR, pCreateInfo->pNext); if (present_wait_features != nullptr) { device_data.set_present_wait_enabled(present_wait_features->presentWait); } -#endif return VK_SUCCESS; } @@ -492,14 +490,12 @@ wsi_layer_vkGetPhysicalDeviceFeatures2KHR(VkPhysicalDevice physical_device, swapchain_maintenance1_features->swapchainMaintenance1 = VK_FALSE; } -#if VULKAN_WSI_LAYER_EXPERIMENTAL auto *present_wait_features = util::find_extension( VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_WAIT_FEATURES_KHR, pFeatures->pNext); if (present_wait_features != nullptr) { present_wait_features->presentWait = VK_FALSE; } -#endif instance.disp.GetPhysicalDeviceFeatures2KHR(physical_device, pFeatures); @@ -521,7 +517,6 @@ wsi_layer_vkGetPhysicalDeviceFeatures2KHR(VkPhysicalDevice physical_device, wsi::set_swapchain_maintenance1_state(physical_device, swapchain_maintenance1_features); -#if VULKAN_WSI_LAYER_EXPERIMENTAL if (present_wait_features != nullptr) { /* If there is an surface extension in use that is unsupported by the layer, defer to the ICD */ @@ -531,6 +526,7 @@ wsi_layer_vkGetPhysicalDeviceFeatures2KHR(VkPhysicalDevice physical_device, } } +#if VULKAN_WSI_LAYER_EXPERIMENTAL auto *present_timing_features = util::find_extension( VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_TIMING_FEATURES_EXT, pFeatures->pNext); if (present_timing_features != nullptr) @@ -614,12 +610,10 @@ wsi_layer_vkGetDeviceProcAddr(VkDevice device, const char *funcName) VWL_API_POS { GET_PROC_ADDR(vkReleaseSwapchainImagesEXT); } -#if VULKAN_WSI_LAYER_EXPERIMENTAL if (layer::device_private_data::get(device).is_device_extension_enabled(VK_KHR_PRESENT_WAIT_EXTENSION_NAME)) { GET_PROC_ADDR(vkWaitForPresentKHR); } -#endif return layer::device_private_data::get(device).disp.get_user_enabled_entrypoint( device, layer::device_private_data::get(device).instance_data.api_version, funcName); diff --git a/layer/present_wait_api.cpp b/layer/present_wait_api.cpp index 4f2c964..759c177 100644 --- a/layer/present_wait_api.cpp +++ b/layer/present_wait_api.cpp @@ -33,8 +33,6 @@ #include "present_wait_api.hpp" -#if VULKAN_WSI_LAYER_EXPERIMENTAL - /** * @brief Implements vkSetSwapchainPresentTimingQueueSizeEXT Vulkan entrypoint. */ @@ -55,5 +53,3 @@ wsi_layer_vkWaitForPresentKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_ return ext->wait_for_present_id(present_id, timeout); } - -#endif /* VULKAN_WSI_LAYER_EXPERIMENTAL */ diff --git a/layer/present_wait_api.hpp b/layer/present_wait_api.hpp index 5b78c19..d7fe31f 100644 --- a/layer/present_wait_api.hpp +++ b/layer/present_wait_api.hpp @@ -30,10 +30,6 @@ #include #include -#if VULKAN_WSI_LAYER_EXPERIMENTAL - VWL_VKAPI_CALL(VkResult) wsi_layer_vkWaitForPresentKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t present_id, uint64_t timeout) VWL_API_POST; - -#endif /* VULKAN_WSI_LAYER_EXPERIMENTAL */ diff --git a/layer/private_data.cpp b/layer/private_data.cpp index 9b874b0..2ecdf5a 100644 --- a/layer/private_data.cpp +++ b/layer/private_data.cpp @@ -634,7 +634,6 @@ bool device_private_data::is_swapchain_maintenance1_enabled() const return swapchain_maintenance1_enabled; } -#if VULKAN_WSI_LAYER_EXPERIMENTAL void device_private_data::set_present_wait_enabled(bool enable) { present_wait_enabled = enable; @@ -645,6 +644,7 @@ bool device_private_data::is_present_wait_enabled() return present_wait_enabled; } +#if VULKAN_WSI_LAYER_EXPERIMENTAL void device_private_data::set_present_mode_fifo_latest_ready_enabled(bool enable) { present_mode_fifo_latest_ready_enabled = enable; diff --git a/layer/private_data.hpp b/layer/private_data.hpp index e4df342..23983a7 100644 --- a/layer/private_data.hpp +++ b/layer/private_data.hpp @@ -370,7 +370,6 @@ private: EP(GetSwapchainTimeDomainPropertiesEXT, VK_EXT_PRESENT_TIMING_EXTENSION_NAME, API_VERSION_MAX, false, ) \ EP(GetSwapchainTimingPropertiesEXT, VK_EXT_PRESENT_TIMING_EXTENSION_NAME, API_VERSION_MAX, false, ) \ EP(SetSwapchainPresentTimingQueueSizeEXT, VK_EXT_PRESENT_TIMING_EXTENSION_NAME, API_VERSION_MAX, false, ) \ - EP(WaitForPresentKHR, VK_KHR_PRESENT_WAIT_EXTENSION_NAME, API_VERSION_MAX, false, ) \ EP(GetPastPresentationTimingEXT, VK_EXT_PRESENT_TIMING_EXTENSION_NAME, API_VERSION_MAX, false, ) #else #define DEVICE_ENTRYPOINTS_LIST_EXPERIMENTAL(EP) @@ -463,6 +462,8 @@ private: EP(GetCalibratedTimestampsEXT, VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME, API_VERSION_MAX, false, ) \ /* VK_KHR_calibrated_timestamps */ \ EP(GetCalibratedTimestampsKHR, VK_KHR_CALIBRATED_TIMESTAMPS_EXTENSION_NAME, API_VERSION_MAX, false, ) \ + /* VK_KHR_present_wait */ \ + EP(WaitForPresentKHR, VK_KHR_PRESENT_WAIT_EXTENSION_NAME, API_VERSION_MAX, false, ) \ /* Custom entrypoints */ \ DEVICE_ENTRYPOINTS_LIST_EXPANSION(EP) @@ -940,7 +941,6 @@ public: */ bool is_swapchain_maintenance1_enabled() const; -#if VULKAN_WSI_LAYER_EXPERIMENTAL /** * @brief Set whether present wait feature is enabled. * @@ -954,7 +954,6 @@ public: * @return true if supported, false otherwise. */ bool is_present_wait_enabled(); -#endif private: /* Allow util::allocator to access the private constructor */ @@ -1013,13 +1012,13 @@ private: */ bool swapchain_maintenance1_enabled{ false }; -#if VULKAN_WSI_LAYER_EXPERIMENTAL /** * @brief Stores whether the device supports the present wait feature. * */ bool present_wait_enabled{ false }; +#if VULKAN_WSI_LAYER_EXPERIMENTAL /** * @brief Stores whether the device has enabled support for the present timing features. */ diff --git a/wsi/display/present_wait_display.cpp b/wsi/display/present_wait_display.cpp index beb5a35..e78ab96 100644 --- a/wsi/display/present_wait_display.cpp +++ b/wsi/display/present_wait_display.cpp @@ -23,7 +23,7 @@ */ /** - * @file present_wait_headless.cpp + * @file present_wait_display.cpp * * @brief Contains the base class declaration for the VK_KHR_present_wait extension. */ @@ -42,8 +42,8 @@ wsi_ext_present_wait_display::wsi_ext_present_wait_display(wsi_ext_present_id &p VkResult wsi_ext_present_wait_display::wait_for_update(uint64_t present_id, uint64_t timeout_in_ns) { - return m_present_id_ext.wait_for_present_id(present_id, timeout_in_ns) ? VK_SUCCESS : VK_TIMEOUT; + return m_present_id_ext.wait_for_present_id(present_id, timeout_in_ns); } -} /* namespace wayland */ +} /* namespace display */ } /* namespace wsi */ \ No newline at end of file diff --git a/wsi/display/present_wait_display.hpp b/wsi/display/present_wait_display.hpp index 12aa2d9..0d358d0 100644 --- a/wsi/display/present_wait_display.hpp +++ b/wsi/display/present_wait_display.hpp @@ -23,7 +23,7 @@ */ /** - * @file present_wait_headless.hpp + * @file present_wait_display.hpp * * @brief Contains the base class declaration for the VK_KHR_present_wait extension. */ @@ -68,5 +68,5 @@ private: VkResult wait_for_update(uint64_t present_id, uint64_t timeout_in_ns) override; }; -} /* namespace wayland */ +} /* namespace display */ } /* namespace wsi */ diff --git a/wsi/display/swapchain.cpp b/wsi/display/swapchain.cpp index 1e2d29f..6560334 100644 --- a/wsi/display/swapchain.cpp +++ b/wsi/display/swapchain.cpp @@ -101,7 +101,6 @@ VkResult swapchain::add_required_extensions(VkDevice device, const VkSwapchainCr } } -#if VULKAN_WSI_LAYER_EXPERIMENTAL if (m_device_data.is_present_wait_enabled()) { if (!add_swapchain_extension( @@ -110,7 +109,6 @@ VkResult swapchain::add_required_extensions(VkDevice device, const VkSwapchainCr return VK_ERROR_OUT_OF_HOST_MEMORY; } } -#endif return VK_SUCCESS; } diff --git a/wsi/extensions/present_id.cpp b/wsi/extensions/present_id.cpp index d259527..0eccbd9 100644 --- a/wsi/extensions/present_id.cpp +++ b/wsi/extensions/present_id.cpp @@ -41,28 +41,66 @@ void wsi_ext_present_id::mark_delivered(uint64_t present_id) std::unique_lock lock(m_mutex); m_last_delivered_id.store(present_id, std::memory_order_relaxed); } - m_present_id_changed.notify_all(); + m_present_state_changed.notify_all(); } -bool wsi_ext_present_id::wait_for_present_id(uint64_t present_id, uint64_t timeout_in_ns) +void wsi_ext_present_id::set_error_state(VkResult error_code) +{ + std::unique_lock lock(m_mutex); + m_error_state.store(error_code); + m_present_state_changed.notify_all(); +} + +VkResult wsi_ext_present_id::get_error_state() +{ + return m_error_state; +} + +VkResult wsi_ext_present_id::wait_for_present_id(uint64_t present_id, uint64_t timeout_in_ns) { if (m_last_delivered_id.load() >= present_id) { return VK_SUCCESS; } - std::unique_lock lock(m_mutex); try { - return m_present_id_changed.wait_for(lock, std::chrono::nanoseconds(timeout_in_ns), - [&]() { return m_last_delivered_id.load() >= present_id; }); + std::unique_lock lock(m_mutex); + if (timeout_in_ns == UINT64_MAX) + { + /* Infinite wait */ + m_present_state_changed.wait( + lock, [&]() { return (m_last_delivered_id.load() >= present_id || m_error_state.load() != VK_SUCCESS); }); + + /* The condition can either return when present_id condition has been reached or there has been an error */ + return m_error_state; + } + else + { + /* Note: With very long timeouts it is possible that the clock in condition_variable will overflow. + * This will result in wait_for immediately returning with a failed result. Considering the + * duration needed to overflow the clock, we can probably ignore this. */ + bool wait_success = m_present_state_changed.wait_for(lock, std::chrono::nanoseconds(timeout_in_ns), [&]() { + return (m_last_delivered_id.load() >= present_id || m_error_state.load() != VK_SUCCESS); + }); + + if (!wait_success) + { + /* We timed out */ + return VK_TIMEOUT; + } + + /* The condition can either return when present_id condition has been reached or there has been an error */ + return m_error_state; + } } catch (const std::system_error &e) { WSI_LOG_ERROR("Failed to wait for conditional variable. Code: %d, message: %s\n", e.code().value(), e.what()); } - return false; + /* The mutex lock has failed */ + return VK_ERROR_SURFACE_LOST_KHR; } uint64_t wsi_ext_present_id::get_last_delivered_present_id() const diff --git a/wsi/extensions/present_id.hpp b/wsi/extensions/present_id.hpp index ec84ef6..dbcdd4d 100644 --- a/wsi/extensions/present_id.hpp +++ b/wsi/extensions/present_id.hpp @@ -60,15 +60,32 @@ public: */ void mark_delivered(uint64_t present_id); + /** + * @brief Sets the error state for all pending and future image requests. + * Any error state other than VK_SUCCESS will cause all current and + * future calls to vkWaitForPresentKHR to fail with @p error_code. + * + * @param error_code Vulkan error code + */ + void set_error_state(VkResult error_code); + + /** + * @brief Get the current error state + * + * @return VkResult error state + */ + VkResult get_error_state(); + /** * @brief Waits for present ID to be above or equal to the @p value. * - * @param value The value to wait for. + * @param present_id The value to wait for. * @param timeout_in_ns Timeout in nanoseconds. - * @return true The present ID value is equal or higher than @p value - * @return false The present ID is lower than @p value and timeout occured + * @return VK_SUCCESS The present ID value is equal or higher than @p present_id + * and there were no errors during present. + * Any other error code to indicate a timeout or error state for the present. */ - bool wait_for_present_id(uint64_t present_id, uint64_t timeout_in_ns); + VkResult wait_for_present_id(uint64_t present_id, uint64_t timeout_in_ns); /** * @brief Get the last delivered present ID value. @@ -83,12 +100,17 @@ private: std::atomic m_last_delivered_id{ 0 }; /** - * @brief Conditional variable that notifies whenever present ID value has changed. + * @brief Current error state of the swapchain */ - std::condition_variable m_present_id_changed; + std::atomic m_error_state{ VK_SUCCESS }; /** - * @brief Mutex for m_present_id_changed conditional variable. + * @brief Conditional variable that notifies whenever present state has changed. + */ + std::condition_variable m_present_state_changed; + + /** + * @brief Mutex for m_present_state_changed conditional variable. */ std::mutex m_mutex; }; diff --git a/wsi/extensions/present_wait.cpp b/wsi/extensions/present_wait.cpp index fb48982..7b571fc 100644 --- a/wsi/extensions/present_wait.cpp +++ b/wsi/extensions/present_wait.cpp @@ -41,7 +41,12 @@ wsi_ext_present_wait::wsi_ext_present_wait(wsi_ext_present_id &present_id_extens VkResult wsi_ext_present_wait::wait_for_present_id(uint64_t present_id, uint64_t timeout_in_ns) { - if (m_present_id_ext.get_last_delivered_present_id() >= present_id) + VkResult error_state = m_present_id_ext.get_error_state(); + if (error_state != VK_SUCCESS) + { + return error_state; + } + else if (m_present_id_ext.get_last_delivered_present_id() >= present_id) { return VK_SUCCESS; } diff --git a/wsi/headless/present_wait_headless.cpp b/wsi/headless/present_wait_headless.cpp index 333f468..fa96f8a 100644 --- a/wsi/headless/present_wait_headless.cpp +++ b/wsi/headless/present_wait_headless.cpp @@ -42,8 +42,8 @@ wsi_ext_present_wait_headless::wsi_ext_present_wait_headless(wsi_ext_present_id VkResult wsi_ext_present_wait_headless::wait_for_update(uint64_t present_id, uint64_t timeout_in_ns) { - return m_present_id_ext.wait_for_present_id(present_id, timeout_in_ns) ? VK_SUCCESS : VK_TIMEOUT; + return m_present_id_ext.wait_for_present_id(present_id, timeout_in_ns); } -} /* namespace wayland */ +} /* namespace headless */ } /* namespace wsi */ \ No newline at end of file diff --git a/wsi/headless/swapchain.cpp b/wsi/headless/swapchain.cpp index 3e7f41c..c250b9d 100644 --- a/wsi/headless/swapchain.cpp +++ b/wsi/headless/swapchain.cpp @@ -109,7 +109,6 @@ VkResult swapchain::add_required_extensions(VkDevice device, const VkSwapchainCr } #endif -#if VULKAN_WSI_LAYER_EXPERIMENTAL if (m_device_data.is_present_wait_enabled()) { if (!add_swapchain_extension(m_allocator.make_unique( @@ -118,7 +117,6 @@ VkResult swapchain::add_required_extensions(VkDevice device, const VkSwapchainCr return VK_ERROR_OUT_OF_HOST_MEMORY; } } -#endif return VK_SUCCESS; } diff --git a/wsi/swapchain_base.hpp b/wsi/swapchain_base.hpp index b86e9f4..409187b 100644 --- a/wsi/swapchain_base.hpp +++ b/wsi/swapchain_base.hpp @@ -41,15 +41,17 @@ #include #include #include +#include + #include #include "surface_properties.hpp" #include "synchronization.hpp" +#include "swapchain_image_creator.hpp" #include "extensions/frame_boundary.hpp" #include "extensions/wsi_extension.hpp" -#include "swapchain_image_creator.hpp" -#include "util/macros.hpp" +#include "extensions/present_id.hpp" namespace wsi { @@ -630,6 +632,12 @@ protected: void set_error_state(VkResult state) { m_error_state = state; + + auto *ext = get_swapchain_extension(); + if (ext) + { + ext->set_error_state(state); + } } private: diff --git a/wsi/wayland/present_wait_wayland.cpp b/wsi/wayland/present_wait_wayland.cpp index 106d3a3..6f5af61 100644 --- a/wsi/wayland/present_wait_wayland.cpp +++ b/wsi/wayland/present_wait_wayland.cpp @@ -60,7 +60,12 @@ VkResult wsi_ext_present_wait_wayland::wait_for_update(uint64_t present_id, uint do { - if (m_present_id_ext.get_last_delivered_present_id() >= present_id) + VkResult error_state = m_present_id_ext.get_error_state(); + if (error_state != VK_SUCCESS) + { + return error_state; + } + else if (m_present_id_ext.get_last_delivered_present_id() >= present_id) { return VK_SUCCESS; } diff --git a/wsi/wayland/swapchain.cpp b/wsi/wayland/swapchain.cpp index 68691d2..3d5660f 100644 --- a/wsi/wayland/swapchain.cpp +++ b/wsi/wayland/swapchain.cpp @@ -112,7 +112,6 @@ VkResult swapchain::add_required_extensions(VkDevice device, const VkSwapchainCr } } -#if VULKAN_WSI_LAYER_EXPERIMENTAL if (m_device_data.is_present_wait_enabled()) { if (!add_swapchain_extension( @@ -121,7 +120,6 @@ VkResult swapchain::add_required_extensions(VkDevice device, const VkSwapchainCr return VK_ERROR_OUT_OF_HOST_MEMORY; } } -#endif if (m_device_data.should_layer_handle_frame_boundary_events()) { @@ -200,13 +198,11 @@ VkResult swapchain::init_platform(VkDevice device, const VkSwapchainCreateInfoKH #endif && (m_present_mode != VK_PRESENT_MODE_MAILBOX_KHR); -#if VULKAN_WSI_LAYER_EXPERIMENTAL auto present_wait = get_swapchain_extension(); if (present_wait) { present_wait->set_wayland_dispatcher(m_display, m_buffer_queue); } -#endif return VK_SUCCESS; } diff --git a/wsi/wayland/wp_presentation_feedback.cpp b/wsi/wayland/wp_presentation_feedback.cpp index 62fc4a2..a84d0d5 100644 --- a/wsi/wayland/wp_presentation_feedback.cpp +++ b/wsi/wayland/wp_presentation_feedback.cpp @@ -30,6 +30,12 @@ namespace wsi namespace wayland { +VWL_CAPI_CALL(void) +wp_presentation_feedback_sync_output(void *, struct wp_presentation_feedback *, struct wl_output *) +{ + /* Not relevant */ +} + VWL_CAPI_CALL(void) wp_presentation_feedback_presented(void *data, struct wp_presentation_feedback *, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t) @@ -42,10 +48,24 @@ wp_presentation_feedback_presented(void *data, struct wp_presentation_feedback * } } +VWL_CAPI_CALL(void) +wp_presentation_feedback_discarded(void *data, struct wp_presentation_feedback *) +{ + /* If the presentation request has been discarded, we still want to notify that the image has reached the compositor + * as otherwise, any functions waiting on the present ID will never be notified. There is nothing more we can do + * with this request as it has been discarded. */ + auto feedback_obj = reinterpret_cast(data); + if (feedback_obj->ext() != nullptr) + { + feedback_obj->ext()->mark_delivered(feedback_obj->present_id()); + feedback_obj->ext()->remove_from_pending_present_feedback_list(feedback_obj->present_id()); + } +} + static const wp_presentation_feedback_listener presentation_listener = { - .sync_output = NULL, + .sync_output = wp_presentation_feedback_sync_output, .presented = wp_presentation_feedback_presented, - .discarded = NULL, + .discarded = wp_presentation_feedback_discarded, }; VkResult register_wp_presentation_feedback_listener(struct wp_presentation_feedback *wp_presentation_feedback,