mirror of
https://gitlab.freedesktop.org/mesa/vulkan-wsi-layer.git
synced 2026-05-05 04:08:09 +02:00
Merge remote-tracking branch 'main' into add_swapchain_image_creator
Change-Id: I22a4c697c8b1181127242848f37ea081243f0d03 Signed-off-by: Iason Paraskevopoulos <iason.paraskevopoulos@arm.com>
This commit is contained in:
commit
281049aa78
28 changed files with 900 additions and 207 deletions
|
|
@ -149,7 +149,9 @@ if(BUILD_WSI_WAYLAND)
|
|||
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)
|
||||
endif()
|
||||
|
||||
pkg_check_modules(WAYLAND_CLIENT REQUIRED wayland-client)
|
||||
|
|
@ -281,6 +283,7 @@ endif()
|
|||
|
||||
# Layer
|
||||
add_library(${PROJECT_NAME} SHARED
|
||||
layer/calibrated_timestamps_api.cpp
|
||||
layer/layer.cpp
|
||||
layer/private_data.cpp
|
||||
layer/surface_api.cpp
|
||||
|
|
@ -308,7 +311,7 @@ if (VULKAN_WSI_LAYER_EXPERIMENTAL)
|
|||
target_sources(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/wsi/extensions/present_timing.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)
|
||||
list(APPEND JSON_COMMANDS COMMAND sed -i '/VK_EXT_present_timing|VK_KHR_present_wait/d' ${CMAKE_CURRENT_BINARY_DIR}/VkLayer_window_system_integration.json)
|
||||
add_definitions("-DVULKAN_WSI_LAYER_EXPERIMENTAL=0")
|
||||
endif()
|
||||
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ The ICDs installed in the system are required to support the following extension
|
|||
|
||||
### Vulkan Header Version
|
||||
|
||||
The Vulkan WSI Layer has been validated against Vulkan header version 1.4.299.
|
||||
The Vulkan WSI Layer has been validated against Vulkan header version 1.4.305.
|
||||
|
||||
If you are using a Vulkan header version newer than this, a warning will appear during compilation.
|
||||
|
||||
|
|
|
|||
|
|
@ -53,10 +53,17 @@
|
|||
"vkGetSwapchainTimeDomainPropertiesEXT",
|
||||
"vkGetPastPresentationTimingEXT"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "VK_KHR_present_wait",
|
||||
"spec_version": "1",
|
||||
"entrypoints": [
|
||||
"vkWaitForPresentKHR"
|
||||
]
|
||||
}
|
||||
],
|
||||
"disable_environment": {
|
||||
"DISABLE_WSI_LAYER": "1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
112
layer/calibrated_timestamps_api.cpp
Normal file
112
layer/calibrated_timestamps_api.cpp
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright (c) 2025 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 calibrated_timestamps_api.cpp
|
||||
*
|
||||
* @brief Contains the Vulkan entrypoints for the calibrated timestamps extension.
|
||||
*/
|
||||
|
||||
#include <wsi/extensions/present_timing.hpp>
|
||||
#include <wsi/swapchain_base.hpp>
|
||||
|
||||
VWL_VKAPI_CALL(VkResult)
|
||||
wsi_layer_vkGetCalibratedTimestampsEXT(VkDevice device, uint32_t timestampCount,
|
||||
const VkCalibratedTimestampInfoKHR *pTimestampInfos, uint64_t *pTimestamps,
|
||||
uint64_t *pMaxDeviation) VWL_API_POST
|
||||
{
|
||||
auto &device_data = layer::device_private_data::get(device);
|
||||
auto get_calibrated_timestamps =
|
||||
device_data.disp.get_fn<PFN_vkGetCalibratedTimestampsEXT>("PFN_vkGetCalibratedTimestampsEXT").has_value() ?
|
||||
device_data.disp.get_fn<PFN_vkGetCalibratedTimestampsEXT>("vkGetCalibratedTimestampsEXT") :
|
||||
device_data.disp.get_fn<PFN_vkGetCalibratedTimestampsEXT>("vkGetCalibratedTimestampsKHR");
|
||||
assert(get_calibrated_timestamps.has_value());
|
||||
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||
struct stage_local_index_and_offset
|
||||
{
|
||||
uint32_t index;
|
||||
uint64_t calibration_offset;
|
||||
};
|
||||
util::vector<VkCalibratedTimestampInfoKHR> time_stamp_info{ util::allocator(device_data.get_allocator(),
|
||||
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT) };
|
||||
util::vector<stage_local_index_and_offset> calibration_index_and_offset{ util::allocator(
|
||||
device_data.get_allocator(), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT) };
|
||||
|
||||
for (uint32_t i = 0; i < timestampCount; ++i)
|
||||
{
|
||||
/* Intercept VkSwapchainCalibratedTimestampInfoEXT struct. */
|
||||
auto *ext = util::find_extension<VkSwapchainCalibratedTimestampInfoEXT>(
|
||||
VK_STRUCTURE_TYPE_SWAPCHAIN_CALIBRATED_TIMESTAMP_INFO_EXT, pTimestampInfos[i].pNext);
|
||||
|
||||
/* Make a copy of the pTimestampsInfo. */
|
||||
if (!time_stamp_info.try_push_back(pTimestampInfos[i]))
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
/* The layer is only handling for present stage local time domains,
|
||||
every other time domains including swapchain local (VK_TIME_DOMAIN_SWAPCHAIN_LOCAL_EXT)
|
||||
is not handled by the layer. */
|
||||
if ((ext != nullptr) && (pTimestampInfos[i].timeDomain == VK_TIME_DOMAIN_PRESENT_STAGE_LOCAL_EXT))
|
||||
{
|
||||
assert(ext->swapchain != VK_NULL_HANDLE);
|
||||
if (!device_data.layer_owns_swapchain(ext->swapchain))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
/* Check only one present stage is stated. */
|
||||
assert(((ext->presentStage & (~(ext->presentStage) + 1)) == ext->presentStage));
|
||||
auto *swapchain = reinterpret_cast<wsi::swapchain_base *>(ext->swapchain);
|
||||
auto *present_timing_extension = swapchain->get_swapchain_extension<wsi::wsi_ext_present_timing>(true);
|
||||
wsi::swapchain_calibrated_time calibrated_time;
|
||||
TRY_LOG_CALL(present_timing_extension->get_swapchain_time_domains().calibrate(
|
||||
static_cast<VkPresentStageFlagBitsEXT>(ext->presentStage), &calibrated_time));
|
||||
stage_local_index_and_offset index_and_offset = { i, calibrated_time.offset };
|
||||
|
||||
if (!calibration_index_and_offset.try_push_back(index_and_offset))
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
time_stamp_info[i].timeDomain = calibrated_time.time_domain;
|
||||
}
|
||||
}
|
||||
TRY_LOG_CALL((*get_calibrated_timestamps)(device, timestampCount, &time_stamp_info[0], pTimestamps, pMaxDeviation));
|
||||
|
||||
/* Loop through the calibration_index_and_offset vector and update the timestamps that are stage local
|
||||
with its respective offset. */
|
||||
for (const auto &iter : calibration_index_and_offset)
|
||||
{
|
||||
pTimestamps[iter.index] += iter.calibration_offset;
|
||||
}
|
||||
return VK_SUCCESS;
|
||||
#endif /* VULKAN_WSI_LAYER_EXPERIMENTAL */
|
||||
return (*get_calibrated_timestamps)(device, timestampCount, pTimestampInfos, pTimestamps, pMaxDeviation);
|
||||
}
|
||||
|
||||
VWL_VKAPI_CALL(VkResult)
|
||||
wsi_layer_vkGetCalibratedTimestampsKHR(VkDevice device, uint32_t timestampCount,
|
||||
const VkCalibratedTimestampInfoKHR *pTimestampInfos, uint64_t *pTimestamps,
|
||||
uint64_t *pMaxDeviation) VWL_API_POST
|
||||
{
|
||||
return wsi_layer_vkGetCalibratedTimestampsEXT(device, timestampCount, pTimestampInfos, pTimestamps, pMaxDeviation);
|
||||
}
|
||||
43
layer/calibrated_timestamps_api.hpp
Normal file
43
layer/calibrated_timestamps_api.hpp
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2025 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 calibrated_timestamps_api.hpp
|
||||
*
|
||||
* @brief Contains the Vulkan entrypoints for Calibrated Timestamps extension.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "util/macros.hpp"
|
||||
|
||||
VWL_VKAPI_CALL(VkResult)
|
||||
wsi_layer_vkGetCalibratedTimestampsEXT(VkDevice device, uint32_t timestampCount,
|
||||
const VkCalibratedTimestampInfoKHR *pTimestampInfos, uint64_t *pTimestamps,
|
||||
uint64_t *pMaxDeviation) VWL_API_POST;
|
||||
|
||||
VWL_VKAPI_CALL(VkResult)
|
||||
wsi_layer_vkGetCalibratedTimestampsKHR(VkDevice device, uint32_t timestampCount,
|
||||
const VkCalibratedTimestampInfoKHR *pTimestampInfos, uint64_t *pTimestamps,
|
||||
uint64_t *pMaxDeviation) VWL_API_POST;
|
||||
|
|
@ -30,6 +30,7 @@
|
|||
#include <vulkan/vk_layer.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#include "layer/calibrated_timestamps_api.hpp"
|
||||
#include "wsi_layer_experimental.hpp"
|
||||
#include "private_data.hpp"
|
||||
#include "surface_api.hpp"
|
||||
|
|
@ -41,7 +42,6 @@
|
|||
#include "util/log.hpp"
|
||||
#include "util/macros.hpp"
|
||||
#include "util/helpers.hpp"
|
||||
#include "wsi/unsupported_surfaces.hpp"
|
||||
|
||||
#define VK_LAYER_API_VERSION VK_MAKE_VERSION(1, 2, VK_HEADER_VERSION)
|
||||
|
||||
|
|
@ -155,18 +155,6 @@ VKAPI_ATTR VkResult create_instance(const VkInstanceCreateInfo *pCreateInfo, con
|
|||
modified_info.ppEnabledExtensionNames = modified_enabled_extensions.data();
|
||||
modified_info.enabledExtensionCount = modified_enabled_extensions.size();
|
||||
|
||||
bool maintainance1_support = true;
|
||||
/* Loop through unsupported extensions and check if they exist in enabled extensions */
|
||||
for (const auto &unsupported_surface_ext : wsi::unsupported_surfaces_ext_array)
|
||||
{
|
||||
if (extensions.contains(unsupported_surface_ext))
|
||||
{
|
||||
maintainance1_support = false;
|
||||
WSI_LOG_ERROR(
|
||||
"Warning: Swapchain maintenance feature is unsupported for the current surface and ICD configuration.\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Advance the link info for the next element on the chain. */
|
||||
layer_link_info->u.pLayerInfo = layer_link_info->u.pLayerInfo->pNext;
|
||||
|
||||
|
|
@ -192,17 +180,15 @@ VKAPI_ATTR VkResult create_instance(const VkInstanceCreateInfo *pCreateInfo, con
|
|||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
|
||||
TRY_LOG_CALL(table->populate(*pInstance, fpGetInstanceProcAddr));
|
||||
table->set_user_enabled_extensions(pCreateInfo->ppEnabledExtensionNames, pCreateInfo->enabledExtensionCount);
|
||||
|
||||
uint32_t api_version =
|
||||
pCreateInfo->pApplicationInfo != nullptr ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_3;
|
||||
|
||||
TRY_LOG_CALL(table->populate(*pInstance, fpGetInstanceProcAddr, api_version));
|
||||
table->set_user_enabled_extensions(pCreateInfo->ppEnabledExtensionNames, pCreateInfo->enabledExtensionCount);
|
||||
|
||||
TRY_LOG_CALL(instance_private_data::associate(*pInstance, std::move(*table), loader_callback,
|
||||
layer_platforms_to_enable, api_version, instance_allocator));
|
||||
|
||||
/* Set the swapchain maintenance flag to true or false based on the enabled extensions checked above*/
|
||||
instance_private_data::get(*pInstance).set_maintainance1_support(maintainance1_support);
|
||||
/*
|
||||
* Store the enabled instance extensions in order to return nullptr in
|
||||
* vkGetInstanceProcAddr for functions of disabled extensions.
|
||||
|
|
@ -328,7 +314,7 @@ VKAPI_ATTR VkResult create_device(VkPhysicalDevice physicalDevice, const VkDevic
|
|||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
|
||||
VkResult result = table->populate(*pDevice, fpGetDeviceProcAddr);
|
||||
VkResult result = table->populate(*pDevice, fpGetDeviceProcAddr, inst_data.api_version);
|
||||
if (result != VK_SUCCESS)
|
||||
{
|
||||
fn_destroy_device(*pDevice, pAllocator);
|
||||
|
|
@ -477,13 +463,23 @@ wsi_layer_vkGetPhysicalDeviceFeatures2KHR(VkPhysicalDevice physicalDevice,
|
|||
VkPhysicalDeviceFeatures2 *pFeatures) VWL_API_POST
|
||||
{
|
||||
auto &instance = layer::instance_private_data::get(physicalDevice);
|
||||
auto *physical_device_swapchain_maintenance1_features =
|
||||
util::find_extension<VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT>(
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_EXT, pFeatures->pNext);
|
||||
if (physical_device_swapchain_maintenance1_features != nullptr)
|
||||
|
||||
auto *swapchain_maintenance1_features = util::find_extension<VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT>(
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_EXT, pFeatures->pNext);
|
||||
if (swapchain_maintenance1_features != nullptr)
|
||||
{
|
||||
physical_device_swapchain_maintenance1_features->swapchainMaintenance1 = false;
|
||||
swapchain_maintenance1_features->swapchainMaintenance1 = VK_FALSE;
|
||||
}
|
||||
|
||||
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||
auto *present_wait_features = util::find_extension<VkPhysicalDevicePresentWaitFeaturesKHR>(
|
||||
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(physicalDevice, pFeatures);
|
||||
|
||||
auto *image_compression_control_swapchain_features =
|
||||
|
|
@ -499,12 +495,21 @@ wsi_layer_vkGetPhysicalDeviceFeatures2KHR(VkPhysicalDevice physicalDevice,
|
|||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_ID_FEATURES_KHR, pFeatures->pNext);
|
||||
if (present_id_features != nullptr)
|
||||
{
|
||||
present_id_features->presentId = true;
|
||||
present_id_features->presentId = VK_TRUE;
|
||||
}
|
||||
|
||||
wsi::set_swapchain_maintenance1_state(physicalDevice, physical_device_swapchain_maintenance1_features);
|
||||
wsi::set_swapchain_maintenance1_state(physicalDevice, 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 */
|
||||
if (!instance.is_unsupported_surface_extension_enabled())
|
||||
{
|
||||
present_wait_features->presentWait = VK_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
auto *present_timing_features = util::find_extension<VkPhysicalDevicePresentTimingFeaturesEXT>(
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_TIMING_FEATURES_EXT, pFeatures->pNext);
|
||||
if (present_timing_features != nullptr)
|
||||
|
|
@ -523,6 +528,7 @@ wsi_layer_vkGetPhysicalDeviceFeatures2KHR(VkPhysicalDevice physicalDevice,
|
|||
VWL_VKAPI_CALL(PFN_vkVoidFunction)
|
||||
wsi_layer_vkGetDeviceProcAddr(VkDevice device, const char *funcName) VWL_API_POST
|
||||
{
|
||||
uint64_t api_version = layer::device_private_data::get(device).instance_data.api_version;
|
||||
if (layer::device_private_data::get(device).is_device_extension_enabled(VK_KHR_SWAPCHAIN_EXTENSION_NAME))
|
||||
{
|
||||
GET_PROC_ADDR(vkCreateSwapchainKHR);
|
||||
|
|
@ -553,12 +559,27 @@ wsi_layer_vkGetDeviceProcAddr(VkDevice device, const char *funcName) VWL_API_POS
|
|||
GET_PROC_ADDR(vkCreateImage);
|
||||
GET_PROC_ADDR(vkBindImageMemory2);
|
||||
|
||||
if (!strcmp(funcName, "vkBindImageMemory2KHR") &&
|
||||
layer::device_private_data::get(device).disp.get_user_enabled_entrypoint(device, api_version, funcName) !=
|
||||
nullptr)
|
||||
{
|
||||
return (PFN_vkVoidFunction)&wsi_layer_vkBindImageMemory2;
|
||||
}
|
||||
|
||||
/* VK_EXT_swapchain_maintenance1 */
|
||||
if (layer::device_private_data::get(device).is_device_extension_enabled(
|
||||
VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME))
|
||||
{
|
||||
GET_PROC_ADDR(vkReleaseSwapchainImagesEXT);
|
||||
}
|
||||
if (layer::device_private_data::get(device).is_device_extension_enabled(VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME))
|
||||
{
|
||||
GET_PROC_ADDR(vkGetCalibratedTimestampsEXT);
|
||||
}
|
||||
if (layer::device_private_data::get(device).is_device_extension_enabled(VK_KHR_CALIBRATED_TIMESTAMPS_EXTENSION_NAME))
|
||||
{
|
||||
GET_PROC_ADDR(vkGetCalibratedTimestampsKHR);
|
||||
}
|
||||
|
||||
return layer::device_private_data::get(device).disp.get_user_enabled_entrypoint(
|
||||
device, layer::device_private_data::get(device).instance_data.api_version, funcName);
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "private_data.hpp"
|
||||
#include "wsi/wsi_factory.hpp"
|
||||
#include "wsi/surface.hpp"
|
||||
#include "wsi/unsupported_surfaces.hpp"
|
||||
#include "util/unordered_map.hpp"
|
||||
#include "util/log.hpp"
|
||||
#include "util/helpers.hpp"
|
||||
|
|
@ -44,17 +45,17 @@ static std::mutex g_data_lock;
|
|||
static util::unordered_map<void *, instance_private_data *> g_instance_data{ util::allocator::get_generic() };
|
||||
static util::unordered_map<void *, device_private_data *> g_device_data{ util::allocator::get_generic() };
|
||||
|
||||
VkResult instance_dispatch_table::populate(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc)
|
||||
VkResult instance_dispatch_table::populate(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc,
|
||||
uint32_t instance_api_version)
|
||||
{
|
||||
static constexpr entrypoint entrypoints_init[] = {
|
||||
#define DISPATCH_TABLE_ENTRY(name, ext_name, api_version, required) \
|
||||
{ "vk" #name, ext_name, nullptr, api_version, false, required },
|
||||
#define DISPATCH_TABLE_ENTRY(name, ext_name, api_version, required, alias) \
|
||||
{ "vk" #name, ext_name, nullptr, api_version, false, required, "vk" #alias },
|
||||
INSTANCE_ENTRYPOINTS_LIST(DISPATCH_TABLE_ENTRY)
|
||||
#undef DISPATCH_TABLE_ENTRY
|
||||
};
|
||||
|
||||
static constexpr auto num_entrypoints = std::distance(std::begin(entrypoints_init), std::end(entrypoints_init));
|
||||
|
||||
for (size_t i = 0; i < num_entrypoints; i++)
|
||||
{
|
||||
const entrypoint *entrypoint = &entrypoints_init[i];
|
||||
|
|
@ -67,6 +68,12 @@ VkResult instance_dispatch_table::populate(VkInstance instance, PFN_vkGetInstanc
|
|||
e.fn = ret;
|
||||
e.user_visible = false;
|
||||
|
||||
if (entrypoint->alias != nullptr && strcmp(entrypoint->alias, "vk") != 0 &&
|
||||
instance_api_version >= entrypoint->api_version)
|
||||
{
|
||||
e.fn = get_proc(instance, entrypoint->alias);
|
||||
}
|
||||
|
||||
if (!m_entrypoints->try_insert(std::make_pair(e.name, e)).has_value())
|
||||
{
|
||||
WSI_LOG_ERROR("Failed to allocate memory for instance dispatch table entry.");
|
||||
|
|
@ -113,11 +120,12 @@ PFN_vkVoidFunction instance_dispatch_table::get_user_enabled_entrypoint(VkInstan
|
|||
return GetInstanceProcAddr(instance, fn_name).value_or(nullptr);
|
||||
}
|
||||
|
||||
VkResult device_dispatch_table::populate(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc_fn)
|
||||
VkResult device_dispatch_table::populate(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc_fn,
|
||||
uint32_t instance_api_version)
|
||||
{
|
||||
static constexpr entrypoint entrypoints_init[] = {
|
||||
#define DISPATCH_TABLE_ENTRY(name, ext_name, api_version, required) \
|
||||
{ "vk" #name, ext_name, nullptr, api_version, false, required },
|
||||
#define DISPATCH_TABLE_ENTRY(name, ext_name, api_version, required, alias) \
|
||||
{ "vk" #name, ext_name, nullptr, api_version, false, required, "vk" #alias },
|
||||
DEVICE_ENTRYPOINTS_LIST(DISPATCH_TABLE_ENTRY)
|
||||
#undef DISPATCH_TABLE_ENTRY
|
||||
};
|
||||
|
|
@ -125,16 +133,22 @@ VkResult device_dispatch_table::populate(VkDevice dev, PFN_vkGetDeviceProcAddr g
|
|||
|
||||
for (size_t i = 0; i < num_entrypoints; i++)
|
||||
{
|
||||
const entrypoint entrypoint = entrypoints_init[i];
|
||||
PFN_vkVoidFunction ret = get_proc_fn(dev, entrypoint.name);
|
||||
if (!ret && entrypoint.required)
|
||||
const entrypoint *entrypoint = &entrypoints_init[i];
|
||||
PFN_vkVoidFunction ret = get_proc_fn(dev, entrypoint->name);
|
||||
if (!ret && entrypoint->required)
|
||||
{
|
||||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
struct entrypoint e = entrypoint;
|
||||
struct entrypoint e = *entrypoint;
|
||||
e.fn = ret;
|
||||
e.user_visible = false;
|
||||
|
||||
if (entrypoint->alias != nullptr && strcmp(entrypoint->alias, "vk") != 0 &&
|
||||
instance_api_version >= entrypoint->api_version)
|
||||
{
|
||||
e.fn = get_proc_fn(dev, entrypoint->alias);
|
||||
}
|
||||
|
||||
if (!m_entrypoints->try_insert(std::make_pair(e.name, e)).has_value())
|
||||
{
|
||||
WSI_LOG_ERROR("Failed to allocate memory for device dispatch table entry.");
|
||||
|
|
@ -385,7 +399,22 @@ bool instance_private_data::has_frame_boundary_support(VkPhysicalDevice phys_dev
|
|||
VkResult instance_private_data::set_instance_enabled_extensions(const char *const *extension_names,
|
||||
size_t extension_count)
|
||||
{
|
||||
return enabled_extensions.add(extension_names, extension_count);
|
||||
VkResult result = enabled_extensions.add(extension_names, extension_count);
|
||||
|
||||
/* Check for unsupported surface extension */
|
||||
has_enabled_unsupported_extension = false;
|
||||
for (const auto &unsupported_surface_ext : wsi::unsupported_surfaces_ext_array)
|
||||
{
|
||||
if (enabled_extensions.contains(unsupported_surface_ext))
|
||||
{
|
||||
has_enabled_unsupported_extension = true;
|
||||
WSI_LOG_ERROR(
|
||||
"Warning: Swapchain maintenance feature is unsupported for the current surface and ICD configuration.\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool instance_private_data::is_instance_extension_enabled(const char *extension_name) const
|
||||
|
|
@ -393,16 +422,6 @@ bool instance_private_data::is_instance_extension_enabled(const char *extension_
|
|||
return enabled_extensions.contains(extension_name);
|
||||
}
|
||||
|
||||
void instance_private_data::set_maintainance1_support(bool enabled_unsupport_ext)
|
||||
{
|
||||
enabled_unsupported_swapchain_maintenance1_extensions = enabled_unsupport_ext;
|
||||
}
|
||||
|
||||
bool instance_private_data::get_maintainance1_support()
|
||||
{
|
||||
return enabled_unsupported_swapchain_maintenance1_extensions;
|
||||
}
|
||||
|
||||
device_private_data::device_private_data(instance_private_data &inst_data, VkPhysicalDevice phys_dev, VkDevice dev,
|
||||
device_dispatch_table table, PFN_vkSetDeviceLoaderData set_loader_data,
|
||||
const util::allocator &alloc)
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ struct entrypoint
|
|||
uint32_t api_version;
|
||||
bool user_visible;
|
||||
bool required;
|
||||
const char *alias;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -210,55 +211,58 @@ static constexpr uint32_t API_VERSION_MAX = UINT32_MAX;
|
|||
* extension_name: Name of the extension that provides the entrypoint.
|
||||
* 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.
|
||||
* alias: Name of the promoted entrypoint alias if different to entrypoint_name.
|
||||
*/
|
||||
#define INSTANCE_ENTRYPOINTS_LIST(EP) \
|
||||
/* Vulkan 1.0 */ \
|
||||
EP(GetInstanceProcAddr, "", VK_API_VERSION_1_0, true) \
|
||||
EP(DestroyInstance, "", VK_API_VERSION_1_0, true) \
|
||||
EP(GetPhysicalDeviceProperties, "", VK_API_VERSION_1_0, true) \
|
||||
EP(GetPhysicalDeviceImageFormatProperties, "", VK_API_VERSION_1_0, true) \
|
||||
EP(EnumerateDeviceExtensionProperties, "", VK_API_VERSION_1_0, true) \
|
||||
/* VK_KHR_surface */ \
|
||||
EP(DestroySurfaceKHR, VK_KHR_SURFACE_EXTENSION_NAME, API_VERSION_MAX, false) \
|
||||
EP(GetPhysicalDeviceSurfaceCapabilitiesKHR, VK_KHR_SURFACE_EXTENSION_NAME, API_VERSION_MAX, false) \
|
||||
EP(GetPhysicalDeviceSurfaceFormatsKHR, VK_KHR_SURFACE_EXTENSION_NAME, API_VERSION_MAX, false) \
|
||||
EP(GetPhysicalDeviceSurfacePresentModesKHR, VK_KHR_SURFACE_EXTENSION_NAME, API_VERSION_MAX, false) \
|
||||
EP(GetPhysicalDeviceSurfaceSupportKHR, VK_KHR_SURFACE_EXTENSION_NAME, API_VERSION_MAX, false) \
|
||||
/* VK_EXT_headless_surface */ \
|
||||
EP(CreateHeadlessSurfaceEXT, VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME, API_VERSION_MAX, false) \
|
||||
/* VK_KHR_wayland_surface */ \
|
||||
EP(CreateWaylandSurfaceKHR, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME, API_VERSION_MAX, false) \
|
||||
/* VK_KHR_display */ \
|
||||
EP(CreateDisplayPlaneSurfaceKHR, VK_KHR_DISPLAY_EXTENSION_NAME, API_VERSION_MAX, false) \
|
||||
/* VK_KHR_get_surface_capabilities2 */ \
|
||||
EP(GetPhysicalDeviceSurfaceCapabilities2KHR, VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME, API_VERSION_MAX, \
|
||||
false) \
|
||||
EP(GetPhysicalDeviceSurfaceFormats2KHR, VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME, API_VERSION_MAX, false) \
|
||||
/* VK_KHR_get_physical_device_properties2 or */ \
|
||||
/* 1.1 (without KHR suffix) */ \
|
||||
EP(GetPhysicalDeviceImageFormatProperties2KHR, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, \
|
||||
VK_API_VERSION_1_1, false) \
|
||||
EP(GetPhysicalDeviceFormatProperties2KHR, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, \
|
||||
VK_API_VERSION_1_1, false) \
|
||||
EP(GetPhysicalDeviceFeatures2KHR, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, VK_API_VERSION_1_1, \
|
||||
false) \
|
||||
EP(GetPhysicalDeviceProperties2KHR, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, VK_API_VERSION_1_1, \
|
||||
false) \
|
||||
EP(GetPhysicalDeviceQueueFamilyProperties2KHR, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, \
|
||||
VK_API_VERSION_1_1, false) \
|
||||
EP(GetPhysicalDeviceMemoryProperties2KHR, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, \
|
||||
VK_API_VERSION_1_1, false) \
|
||||
EP(GetPhysicalDeviceSparseImageFormatProperties2KHR, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, \
|
||||
VK_API_VERSION_1_1, false) \
|
||||
/* VK_KHR_device_group + VK_KHR_surface or */ \
|
||||
/* 1.1 with VK_KHR_swapchain */ \
|
||||
EP(GetPhysicalDevicePresentRectanglesKHR, VK_KHR_DEVICE_GROUP_EXTENSION_NAME, VK_API_VERSION_1_1, false) \
|
||||
/* VK_KHR_external_fence_capabilities or */ \
|
||||
/* 1.1 (without KHR suffix) */ \
|
||||
EP(GetPhysicalDeviceExternalFencePropertiesKHR, VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME, \
|
||||
VK_API_VERSION_1_1, false) \
|
||||
EP(GetPhysicalDeviceExternalBufferPropertiesKHR, VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME, \
|
||||
VK_API_VERSION_1_1, false)
|
||||
#define INSTANCE_ENTRYPOINTS_LIST(EP) \
|
||||
/* Vulkan 1.0 */ \
|
||||
EP(GetInstanceProcAddr, "", VK_API_VERSION_1_0, true, ) \
|
||||
EP(DestroyInstance, "", VK_API_VERSION_1_0, true, ) \
|
||||
EP(GetPhysicalDeviceProperties, "", VK_API_VERSION_1_0, true, ) \
|
||||
EP(GetPhysicalDeviceImageFormatProperties, "", VK_API_VERSION_1_0, true, ) \
|
||||
EP(EnumerateDeviceExtensionProperties, "", VK_API_VERSION_1_0, true, ) \
|
||||
/* VK_KHR_surface */ \
|
||||
EP(DestroySurfaceKHR, VK_KHR_SURFACE_EXTENSION_NAME, API_VERSION_MAX, false, ) \
|
||||
EP(GetPhysicalDeviceSurfaceCapabilitiesKHR, VK_KHR_SURFACE_EXTENSION_NAME, API_VERSION_MAX, false, ) \
|
||||
EP(GetPhysicalDeviceSurfaceFormatsKHR, VK_KHR_SURFACE_EXTENSION_NAME, API_VERSION_MAX, false, ) \
|
||||
EP(GetPhysicalDeviceSurfacePresentModesKHR, VK_KHR_SURFACE_EXTENSION_NAME, API_VERSION_MAX, false, ) \
|
||||
EP(GetPhysicalDeviceSurfaceSupportKHR, VK_KHR_SURFACE_EXTENSION_NAME, API_VERSION_MAX, false, ) \
|
||||
/* VK_EXT_headless_surface */ \
|
||||
EP(CreateHeadlessSurfaceEXT, VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME, API_VERSION_MAX, false, ) \
|
||||
/* VK_KHR_wayland_surface */ \
|
||||
EP(CreateWaylandSurfaceKHR, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME, API_VERSION_MAX, false, ) \
|
||||
/* VK_KHR_display */ \
|
||||
EP(CreateDisplayPlaneSurfaceKHR, VK_KHR_DISPLAY_EXTENSION_NAME, API_VERSION_MAX, false, ) \
|
||||
/* VK_KHR_get_surface_capabilities2 */ \
|
||||
EP(GetPhysicalDeviceSurfaceCapabilities2KHR, VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME, API_VERSION_MAX, \
|
||||
false, ) \
|
||||
EP(GetPhysicalDeviceSurfaceFormats2KHR, VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME, API_VERSION_MAX, false, ) \
|
||||
/* VK_KHR_get_physical_device_properties2 or 1.1 (without KHR suffix) */ \
|
||||
/* Not all of these entrypoints are used by the layer but need to be listed here to hide them from the application. */ \
|
||||
EP(GetPhysicalDeviceImageFormatProperties2KHR, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, \
|
||||
VK_API_VERSION_1_1, false, GetPhysicalDeviceImageFormatProperties2) \
|
||||
EP(GetPhysicalDeviceFormatProperties2KHR, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, \
|
||||
VK_API_VERSION_1_1, false, GetPhysicalDeviceFormatProperties2) \
|
||||
EP(GetPhysicalDeviceFeatures2KHR, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, VK_API_VERSION_1_1, \
|
||||
false, GetPhysicalDeviceFeatures2) \
|
||||
EP(GetPhysicalDeviceProperties2KHR, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, VK_API_VERSION_1_1, \
|
||||
false, GetPhysicalDeviceProperties2) \
|
||||
EP(GetPhysicalDeviceQueueFamilyProperties2KHR, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, \
|
||||
VK_API_VERSION_1_1, false, GetPhysicalDeviceQueueFamilyProperties2) \
|
||||
EP(GetPhysicalDeviceMemoryProperties2KHR, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, \
|
||||
VK_API_VERSION_1_1, false, GetPhysicalDeviceMemoryProperties2) \
|
||||
EP(GetPhysicalDeviceSparseImageFormatProperties2KHR, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, \
|
||||
VK_API_VERSION_1_1, false, GetPhysicalDeviceSparseImageFormatProperties2) \
|
||||
/* VK_KHR_device_group + VK_KHR_surface or */ \
|
||||
/* 1.1 with VK_KHR_swapchain */ \
|
||||
EP(GetPhysicalDevicePresentRectanglesKHR, VK_KHR_DEVICE_GROUP_EXTENSION_NAME, VK_API_VERSION_1_1, false, ) \
|
||||
/* VK_KHR_external_fence_capabilities or 1.1 (without KHR suffix) */ \
|
||||
EP(GetPhysicalDeviceExternalFencePropertiesKHR, VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME, \
|
||||
VK_API_VERSION_1_1, false, GetPhysicalDeviceExternalFenceProperties) \
|
||||
/* VK_KHR_external_memory_capabilities or 1.1 (without KHR suffix) */ \
|
||||
/* The layer does not use these entrypoints directly but does use VkExternalImageFormatPropertiesKHR introduced by */ \
|
||||
/* this extension. These are listed here in order to hide them from the application. */ \
|
||||
EP(GetPhysicalDeviceExternalBufferPropertiesKHR, VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME, \
|
||||
VK_API_VERSION_1_1, false, GetPhysicalDeviceExternalBufferProperties)
|
||||
|
||||
/**
|
||||
* @brief Struct representing the instance dispatch table.
|
||||
|
|
@ -284,9 +288,10 @@ public:
|
|||
*
|
||||
* @param instance The instance for which the dispatch table will be populated.
|
||||
* @param get_proc The pointer to vkGetInstanceProcAddr function.
|
||||
* @param api_version The Vulkan API version being used.
|
||||
* @return VkResult VK_SUCCESS if successful, otherwise an error.
|
||||
*/
|
||||
VkResult populate(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc);
|
||||
VkResult populate(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc, uint32_t api_version);
|
||||
|
||||
/**
|
||||
* @brief Get the user enabled instance extension entrypoint by name
|
||||
|
|
@ -304,7 +309,7 @@ public:
|
|||
* disp.GetInstanceProcAddr(instance, fn_name);
|
||||
* The result type will be matching the function signature, so there is no need for casting.
|
||||
*/
|
||||
#define DISPATCH_TABLE_SHORTCUT(name, unused1, unused2, unused3) \
|
||||
#define DISPATCH_TABLE_SHORTCUT(name, unused1, unused2, unused3, unused4) \
|
||||
template <class... Args> \
|
||||
auto name(Args &&...args) const \
|
||||
{ \
|
||||
|
|
@ -340,13 +345,14 @@ private:
|
|||
* extension_name: Name of the extension that provides the entrypoint.
|
||||
* 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.
|
||||
* alias: Name of the promoted entrypoint alias if different to entrypoint_name.
|
||||
*/
|
||||
|
||||
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||
#define DEVICE_ENTRYPOINTS_LIST_EXPERIMENTAL(EP) \
|
||||
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)
|
||||
#define DEVICE_ENTRYPOINTS_LIST_EXPERIMENTAL(EP) \
|
||||
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, )
|
||||
#else
|
||||
#define DEVICE_ENTRYPOINTS_LIST_EXPERIMENTAL(EP)
|
||||
#endif
|
||||
|
|
@ -354,71 +360,84 @@ private:
|
|||
/* Define a list of custom entrypoints that might rely on preprocessor conditions and similar */
|
||||
#define DEVICE_ENTRYPOINTS_LIST_EXPANSION(EP) DEVICE_ENTRYPOINTS_LIST_EXPERIMENTAL(EP)
|
||||
|
||||
#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) \
|
||||
/* Custom entrypoints */ \
|
||||
#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, BindImageMemory2) \
|
||||
EP(BindBufferMemory2KHR, VK_KHR_BIND_MEMORY_2_EXTENSION_NAME, VK_API_VERSION_1_1, false, BindBufferMemory2) \
|
||||
/* 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_EXT_image_drm_format_modifier */ \
|
||||
/* Note the layer doesn't use these entrypoints directly but does use the structures introduced */ \
|
||||
/* by this extension. These entrypoints are listed to hide the entrypoints from the application. */ \
|
||||
EP(GetImageDrmFormatModifierPropertiesEXT, VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME, API_VERSION_MAX, \
|
||||
false, ) \
|
||||
/* VK_KHR_sampler_ycbcr_conversion (promoted in 1.1 with KHR suffix removed but the samplerYcbcrConversion capability */ \
|
||||
/* is still optional). */ \
|
||||
/* Note the layer doesn't use these entrypoints directly but does use VK_IMAGE_CREATE_DISJOINT_BIT_KHR introduced */ \
|
||||
/* by this extension. These entrypoints are listed to hide the entrypoints from the application. */ \
|
||||
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 */ \
|
||||
/* This extension is not used directly by the layer but is a dependency of VK_KHR_sampler_ycbcr_conversion */ \
|
||||
EP(TrimCommandPoolKHR, VK_KHR_MAINTENANCE1_EXTENSION_NAME, VK_API_VERSION_1_1, false, ) \
|
||||
/* VK_KHR_get_memory_requirements2 or 1.1 (without KHR suffix) \
|
||||
* This extension is not used directly by the layer but is a dependency of VK_KHR_sampler_ycbcr_conversion */ \
|
||||
EP(GetImageMemoryRequirements2KHR, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME, VK_API_VERSION_1_1, false, \
|
||||
GetImageMemoryRequirements2) \
|
||||
EP(GetBufferMemoryRequirements2KHR, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME, VK_API_VERSION_1_1, false, \
|
||||
GetBufferMemoryRequirements2) \
|
||||
EP(GetImageSparseMemoryRequirements2KHR, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME, VK_API_VERSION_1_1, \
|
||||
false, GetImageSparseMemoryRequirements2KHR) \
|
||||
/* VK_EXT_swapchain_maintenance1 */ \
|
||||
EP(ReleaseSwapchainImagesEXT, VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME, VK_API_VERSION_1_1, false, ) \
|
||||
EP(GetCalibratedTimestampsEXT, VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME, API_VERSION_MAX, false, ) \
|
||||
EP(GetCalibratedTimestampsKHR, VK_KHR_CALIBRATED_TIMESTAMPS_EXTENSION_NAME, API_VERSION_MAX, false, ) \
|
||||
/* Custom entrypoints */ \
|
||||
DEVICE_ENTRYPOINTS_LIST_EXPANSION(EP)
|
||||
|
||||
/**
|
||||
|
|
@ -445,9 +464,10 @@ public:
|
|||
*
|
||||
* @param device The device for which the dispatch table will be populated.
|
||||
* @param get_proc The pointer to vkGetDeviceProcAddr function.
|
||||
* @param api_version The Vulkan API version being used.
|
||||
* @return VkResult VK_SUCCESS if successful, otherwise an error.
|
||||
*/
|
||||
VkResult populate(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc);
|
||||
VkResult populate(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc, uint32_t api_version);
|
||||
|
||||
/**
|
||||
* @brief Get the user enabled device extension entrypoint by name
|
||||
|
|
@ -465,7 +485,7 @@ public:
|
|||
* disp.GetDeviceProcAddr(instance, fn_name);
|
||||
* The result type will be matching the function signature, so there is no need for casting.
|
||||
*/
|
||||
#define DISPATCH_TABLE_SHORTCUT(name, unused1, unused2, unused3) \
|
||||
#define DISPATCH_TABLE_SHORTCUT(name, unused1, unused2, unused3, unused4) \
|
||||
template <class... Args> \
|
||||
auto name(Args &&...args) const \
|
||||
{ \
|
||||
|
|
@ -634,7 +654,7 @@ public:
|
|||
/**
|
||||
* @brief Check whether an instance extension is enabled.
|
||||
*
|
||||
* param extension_name Extension's name.
|
||||
* @param extension_name Extension's name.
|
||||
*
|
||||
* @return true if is enabled, false otherwise.
|
||||
*/
|
||||
|
|
@ -644,12 +664,14 @@ public:
|
|||
const uint32_t api_version;
|
||||
|
||||
/**
|
||||
* @brief Set if swapchain maintainance1 support is enabled.
|
||||
*
|
||||
* @param enabled_unsupport_ext True if it is enabled, false otherwise.
|
||||
* @brief Check whether there is an enabled surface extension that is not supported by the layer.
|
||||
*
|
||||
* @return true if there is an unsupported, enabled surface extension
|
||||
*/
|
||||
void set_maintainance1_support(bool enabled_unsupport_ext);
|
||||
bool is_unsupported_surface_extension_enabled() const
|
||||
{
|
||||
return has_enabled_unsupported_extension;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if swapchain maintainance1 support is enabled.
|
||||
|
|
@ -657,7 +679,10 @@ public:
|
|||
* @return true if it is enabled, false otherwise.
|
||||
*
|
||||
*/
|
||||
bool get_maintainance1_support();
|
||||
bool get_maintainance1_support() const
|
||||
{
|
||||
return !has_enabled_unsupported_extension;
|
||||
}
|
||||
|
||||
private:
|
||||
/* Allow util::allocator to access the private constructor */
|
||||
|
|
@ -711,9 +736,9 @@ private:
|
|||
util::extension_list enabled_extensions;
|
||||
|
||||
/**
|
||||
* @brief True if unsupported extensions are enabled.
|
||||
* @brief True if any unsupported extensions are enabled.
|
||||
*/
|
||||
bool enabled_unsupported_swapchain_maintenance1_extensions;
|
||||
bool has_enabled_unsupported_extension;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2021-2022 Arm Limited.
|
||||
* Copyright (c) 2021-2022, 2025 Arm Limited.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
|
|
@ -26,6 +26,8 @@
|
|||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace util
|
||||
{
|
||||
|
||||
|
|
|
|||
|
|
@ -561,7 +561,7 @@ void swapchain::present_image(const pending_present_request &pending_present)
|
|||
if (m_device_data.is_present_id_enabled())
|
||||
{
|
||||
auto *ext = get_swapchain_extension<wsi_ext_present_id>(true);
|
||||
ext->set_present_id(pending_present.present_id);
|
||||
ext->mark_delivered(pending_present.present_id);
|
||||
}
|
||||
|
||||
/* And release the old one. */
|
||||
|
|
|
|||
|
|
@ -27,17 +27,18 @@
|
|||
*
|
||||
* @brief Contains the implementation for the VK_KHR_present_id extension.
|
||||
*/
|
||||
|
||||
#include "present_id.hpp"
|
||||
|
||||
namespace wsi
|
||||
{
|
||||
|
||||
void wsi_ext_present_id::set_present_id(uint64_t value)
|
||||
void wsi_ext_present_id::mark_delivered(uint64_t present_id)
|
||||
{
|
||||
if (value != 0)
|
||||
/* Stale reads are acceptable as we only care that the ID is increasing */
|
||||
if (present_id > m_last_delivered_id.load(std::memory_order_relaxed))
|
||||
{
|
||||
assert(value > m_present_id);
|
||||
m_present_id = value;
|
||||
m_last_delivered_id.store(present_id, std::memory_order_relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include <util/custom_allocator.hpp>
|
||||
#include <util/macros.hpp>
|
||||
#include <atomic>
|
||||
|
||||
#include "wsi_extension.hpp"
|
||||
|
||||
|
|
@ -53,17 +54,15 @@ public:
|
|||
WSI_DEFINE_EXTENSION(VK_KHR_PRESENT_ID_EXTENSION_NAME);
|
||||
|
||||
/**
|
||||
* @brief Set the present ID for the swapchain.
|
||||
*
|
||||
* @param value Value to set for the present_id.
|
||||
* @brief Marks the given present ID delivered (i.e. its image has been displayed).
|
||||
*/
|
||||
void set_present_id(uint64_t value);
|
||||
void mark_delivered(uint64_t present_id);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Current present ID for this swapchain.
|
||||
* @brief Most recently delivered present ID for this swapchain.
|
||||
*/
|
||||
uint64_t m_present_id{ 0 };
|
||||
std::atomic<uint64_t> m_last_delivered_id{ 0 };
|
||||
};
|
||||
|
||||
} /* namespace wsi */
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <array>
|
||||
|
||||
#include "wsi_extension.hpp"
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "present_timing_handler.hpp"
|
||||
#include <cstdint>
|
||||
#include <array>
|
||||
|
||||
wsi_ext_present_timing_headless::wsi_ext_present_timing_headless(const util::allocator &allocator)
|
||||
: wsi::wsi_ext_present_timing(allocator)
|
||||
|
|
|
|||
|
|
@ -201,8 +201,9 @@ void swapchain::present_image(const pending_present_request &pending_present)
|
|||
if (m_device_data.is_present_id_enabled())
|
||||
{
|
||||
auto *ext = get_swapchain_extension<wsi_ext_present_id>(true);
|
||||
ext->set_present_id(pending_present.present_id);
|
||||
ext->mark_delivered(pending_present.present_id);
|
||||
}
|
||||
|
||||
unpresent_image(pending_present.image_index);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
#include <vulkan/vulkan.h>
|
||||
#include <array>
|
||||
/* Define the patch version directly as macros */
|
||||
#define WSI_LAYER_VK_PATCH 299
|
||||
#define WSI_LAYER_VK_PATCH 305
|
||||
|
||||
/* Convert macros to string */
|
||||
#define STRINGIFY(x) #x
|
||||
|
|
|
|||
63
wsi/wayland/present_id_wayland.cpp
Normal file
63
wsi/wayland/present_id_wayland.cpp
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright (c) 2025 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 present_id_wayland.cpp
|
||||
*
|
||||
* @brief Contains the functionality to implement Wayland specific features for present ID extension.
|
||||
*/
|
||||
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||
|
||||
#include "present_id_wayland.hpp"
|
||||
|
||||
namespace wsi
|
||||
{
|
||||
namespace wayland
|
||||
{
|
||||
|
||||
presentation_feedback *wsi_ext_present_id_wayland::insert_into_pending_present_feedback_list(
|
||||
uint64_t present_id, struct wp_presentation_feedback *feedback_obj)
|
||||
{
|
||||
scoped_mutex lock(m_pending_presents_lock);
|
||||
bool ret = m_pending_presents.push_back(presentation_feedback(present_id, feedback_obj, this));
|
||||
if (!ret)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return m_pending_presents.back();
|
||||
}
|
||||
|
||||
void wsi_ext_present_id_wayland::remove_from_pending_present_feedback_list(uint64_t present_id)
|
||||
{
|
||||
scoped_mutex lock(m_pending_presents_lock);
|
||||
while (m_pending_presents.size() > 0 && m_pending_presents.front()->present_id() <= present_id)
|
||||
{
|
||||
m_pending_presents.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace wayland
|
||||
} // namespace wsi
|
||||
|
||||
#endif /* VULKAN_WSI_LAYER_EXPERIMENTAL */
|
||||
79
wsi/wayland/present_id_wayland.hpp
Normal file
79
wsi/wayland/present_id_wayland.hpp
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (c) 2025 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 present_id_wayland.hpp
|
||||
*
|
||||
* @brief Contains the functionality to implement Wayland specific features for present id extension.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||
|
||||
#include <wsi/extensions/present_id.hpp>
|
||||
#include <util/ring_buffer.hpp>
|
||||
#include "surface_properties.hpp"
|
||||
#include "wp_presentation_feedback.hpp"
|
||||
#include <mutex>
|
||||
|
||||
namespace wsi
|
||||
{
|
||||
namespace wayland
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Present ID extension class
|
||||
*
|
||||
* This class implements present ID features declarations that are specific to the Wayland backend.
|
||||
*/
|
||||
class wsi_ext_present_id_wayland : public wsi::wsi_ext_present_id
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Insert into pending present id list.
|
||||
*/
|
||||
presentation_feedback *insert_into_pending_present_feedback_list(uint64_t present_id,
|
||||
struct wp_presentation_feedback *feedback_obj);
|
||||
|
||||
/**
|
||||
* @brief Remove a present id from the pending present id list.
|
||||
*/
|
||||
void remove_from_pending_present_feedback_list(uint64_t present_id);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Mutex for synchronising accesses to the pending present id list.
|
||||
*/
|
||||
std::mutex m_pending_presents_lock;
|
||||
|
||||
/**
|
||||
* @brief Stores the presentation feedbacks that have been queued.
|
||||
*/
|
||||
util::ring_buffer<presentation_feedback, wsi::surface_properties::MAX_SWAPCHAIN_IMAGE_COUNT * 2> m_pending_presents;
|
||||
};
|
||||
|
||||
} // namespace wayland
|
||||
} // namespace wsi
|
||||
|
||||
#endif /* VULKAN_WSI_LAYER_EXPERIMENTAL */
|
||||
|
|
@ -29,6 +29,7 @@
|
|||
*/
|
||||
|
||||
#include "present_timing_handler.hpp"
|
||||
#include <array>
|
||||
|
||||
wsi_ext_present_timing_wayland::wsi_ext_present_timing_wayland(const util::allocator &allocator)
|
||||
: wsi_ext_present_timing(allocator)
|
||||
|
|
@ -36,11 +37,13 @@ wsi_ext_present_timing_wayland::wsi_ext_present_timing_wayland(const util::alloc
|
|||
}
|
||||
|
||||
util::unique_ptr<wsi_ext_present_timing_wayland> wsi_ext_present_timing_wayland::create(
|
||||
const util::allocator &allocator)
|
||||
VkTimeDomainKHR image_first_pixel_visible_time_domain, const util::allocator &allocator)
|
||||
{
|
||||
std::array<util::unique_ptr<wsi::vulkan_time_domain>, 1> time_domains_array = {
|
||||
std::array<util::unique_ptr<wsi::vulkan_time_domain>, 2> time_domains_array = {
|
||||
allocator.make_unique<wsi::vulkan_time_domain>(VK_PRESENT_STAGE_QUEUE_OPERATIONS_END_BIT_EXT,
|
||||
VK_TIME_DOMAIN_DEVICE_KHR)
|
||||
VK_TIME_DOMAIN_DEVICE_KHR),
|
||||
allocator.make_unique<wsi::vulkan_time_domain>(VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_VISIBLE_BIT_EXT,
|
||||
image_first_pixel_visible_time_domain)
|
||||
};
|
||||
|
||||
return wsi_ext_present_timing::create<wsi_ext_present_timing_wayland>(allocator, time_domains_array);
|
||||
|
|
@ -54,4 +57,4 @@ VkResult wsi_ext_present_timing_wayland::get_swapchain_timing_properties(
|
|||
timing_properties.variableRefreshDelay = 0;
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,8 @@
|
|||
class wsi_ext_present_timing_wayland : public wsi::wsi_ext_present_timing
|
||||
{
|
||||
public:
|
||||
static util::unique_ptr<wsi_ext_present_timing_wayland> create(const util::allocator &allocator);
|
||||
static util::unique_ptr<wsi_ext_present_timing_wayland> create(VkTimeDomainKHR image_first_pixel_visible_time_domain,
|
||||
const util::allocator &allocator);
|
||||
|
||||
VkResult get_swapchain_timing_properties(uint64_t &timing_properties_counter,
|
||||
VkSwapchainTimingPropertiesEXT &timing_properties) override;
|
||||
|
|
|
|||
|
|
@ -72,9 +72,21 @@ zwp_linux_dmabuf_v1_modifier_impl(void *data, struct zwp_linux_dmabuf_v1 *dma_bu
|
|||
drm_supported_formats->is_out_of_memory = !drm_supported_formats->formats->try_push_back(format);
|
||||
}
|
||||
}
|
||||
|
||||
/* Handler for clock_id event of the wp_presentation interface. */
|
||||
VWL_CAPI_CALL(void)
|
||||
wp_presentation_clock_id_impl(void *data, struct wp_presentation *wp_presentation,
|
||||
uint32_t compositor_clockid) VWL_API_POST
|
||||
{
|
||||
UNUSED(wp_presentation);
|
||||
|
||||
clockid_t *clockid = static_cast<clockid_t *>(data);
|
||||
*clockid = compositor_clockid;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
/*
|
||||
/**
|
||||
* @brief Get supported formats and modifiers using the zwp_linux_dmabuf_v1 interface.
|
||||
*
|
||||
* @param[in] display The wl_display that is being used.
|
||||
|
|
@ -122,6 +134,35 @@ static VkResult get_supported_formats_and_modifiers(wl_display *display, wl_even
|
|||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the clock_id using the wp_presentation interface
|
||||
*
|
||||
* @retval VK_SUCCESS Indicates success.
|
||||
* @retval VK_ERROR_UNKNOWN Indicates one of the Wayland functions failed.
|
||||
*/
|
||||
static VkResult get_clock_id(wl_display *display, wl_event_queue *queue, wp_presentation *presentation_interface,
|
||||
clockid_t *clockid)
|
||||
{
|
||||
const wp_presentation_listener presentation_listener = {
|
||||
.clock_id = wp_presentation_clock_id_impl,
|
||||
};
|
||||
|
||||
int res = wp_presentation_add_listener(presentation_interface, &presentation_listener, clockid);
|
||||
if (res < 0)
|
||||
{
|
||||
WSI_LOG_ERROR("Failed to add wp_presentation listener.");
|
||||
return VK_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
res = wl_display_roundtrip_queue(display, queue);
|
||||
if (res < 0)
|
||||
{
|
||||
WSI_LOG_ERROR("Roundtrip failed.");
|
||||
return VK_ERROR_UNKNOWN;
|
||||
}
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
struct surface::init_parameters
|
||||
{
|
||||
const util::allocator &allocator;
|
||||
|
|
@ -262,6 +303,12 @@ bool surface::init()
|
|||
return false;
|
||||
}
|
||||
|
||||
vk_res = get_clock_id(wayland_display, surface_queue.get(), presentation_time_interface.get(), &m_clockid);
|
||||
if (vk_res != VK_SUCCESS)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#ifndef __STDC_VERSION__
|
||||
#define __STDC_VERSION__ 0
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <wayland-client.h>
|
||||
|
||||
#include "wsi/surface.hpp"
|
||||
|
|
@ -113,6 +114,17 @@ public:
|
|||
return surface_sync_interface.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns a pointer to the Wayland wp_presentation interface obtained for the wayland
|
||||
* surface.
|
||||
*
|
||||
* The raw pointer is valid for the lifetime of the surface.
|
||||
*/
|
||||
struct wp_presentation *get_presentation_time_interface()
|
||||
{
|
||||
return presentation_time_interface.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns a reference to a list of DRM formats supported by the Wayland surface.
|
||||
*
|
||||
|
|
@ -140,6 +152,14 @@ public:
|
|||
*/
|
||||
bool wait_next_frame_event();
|
||||
|
||||
/**
|
||||
* @brief Return the clockid of the surface
|
||||
*/
|
||||
clockid_t clockid()
|
||||
{
|
||||
return m_clockid;
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Initialize the WSI surface by creating Wayland queues and linking to Wayland protocols.
|
||||
|
|
@ -180,7 +200,7 @@ private:
|
|||
wayland_owner<wp_presentation> presentation_time_interface;
|
||||
|
||||
/**
|
||||
* Container for a callback object for the latest frame done event.
|
||||
* @brief Container for a callback object for the latest frame done event.
|
||||
*
|
||||
* The callback object should be destroyed before the queue so any new events
|
||||
* on the queue will be discarded. If a proxy object is destroyed after a queue,
|
||||
|
|
@ -196,6 +216,11 @@ private:
|
|||
* callback to indicate the server is ready for the next buffer.
|
||||
*/
|
||||
bool present_pending;
|
||||
|
||||
/**
|
||||
* @brief Stores the clock ID reported by the wp_presentation interface
|
||||
*/
|
||||
clockid_t m_clockid;
|
||||
};
|
||||
|
||||
} // namespace wayland
|
||||
|
|
|
|||
|
|
@ -424,7 +424,8 @@ void surface_properties::get_present_timing_surface_caps(
|
|||
present_timing_surface_caps->presentTimingSupported = VK_TRUE;
|
||||
present_timing_surface_caps->presentAtAbsoluteTimeSupported = VK_FALSE;
|
||||
present_timing_surface_caps->presentAtRelativeTimeSupported = VK_FALSE;
|
||||
present_timing_surface_caps->presentStageQueries = VK_PRESENT_STAGE_QUEUE_OPERATIONS_END_BIT_EXT;
|
||||
present_timing_surface_caps->presentStageQueries =
|
||||
VK_PRESENT_STAGE_QUEUE_OPERATIONS_END_BIT_EXT | VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_VISIBLE_BIT_EXT;
|
||||
present_timing_surface_caps->presentStageTargets = 0;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -44,12 +44,14 @@
|
|||
#include "wl_helpers.hpp"
|
||||
|
||||
#include <wsi/extensions/image_compression_control.hpp>
|
||||
#include <wsi/extensions/present_id.hpp>
|
||||
#include <wsi/extensions/swapchain_maintenance.hpp>
|
||||
#include <wsi/extensions/present_id.hpp>
|
||||
|
||||
#include <wsi/swapchain_image_create_extensions/external_memory_extension.hpp>
|
||||
|
||||
#include "present_timing_handler.hpp"
|
||||
#include "present_id_wayland.hpp"
|
||||
#include "wp_presentation_feedback.hpp"
|
||||
|
||||
namespace wsi
|
||||
{
|
||||
|
|
@ -91,7 +93,11 @@ VkResult swapchain::add_required_extensions(VkDevice device, const VkSwapchainCr
|
|||
|
||||
if (m_device_data.is_present_id_enabled())
|
||||
{
|
||||
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||
if (!add_swapchain_extension(m_allocator.make_unique<wsi_ext_present_id_wayland>()))
|
||||
#else
|
||||
if (!add_swapchain_extension(m_allocator.make_unique<wsi_ext_present_id>()))
|
||||
#endif
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
|
|
@ -117,7 +123,18 @@ VkResult swapchain::add_required_extensions(VkDevice device, const VkSwapchainCr
|
|||
bool swapchain_support_enabled = swapchain_create_info->flags & VK_SWAPCHAIN_CREATE_PRESENT_TIMING_BIT_EXT;
|
||||
if (swapchain_support_enabled)
|
||||
{
|
||||
if (!add_swapchain_extension(wsi_ext_present_timing_wayland::create(m_allocator)))
|
||||
/*
|
||||
* Default to a raw hardware-based time that is not subject to NTP adjustments or
|
||||
* the incremental adjustments performed by adjtime(3)
|
||||
*/
|
||||
VkTimeDomainKHR image_first_pixel_visible_time_domain = VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR;
|
||||
|
||||
if (m_wsi_surface->clockid() == CLOCK_MONOTONIC)
|
||||
{
|
||||
image_first_pixel_visible_time_domain = VK_TIME_DOMAIN_CLOCK_MONOTONIC_KHR;
|
||||
}
|
||||
if (!add_swapchain_extension(
|
||||
wsi_ext_present_timing_wayland::create(image_first_pixel_visible_time_domain, m_allocator)))
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
|
|
@ -523,6 +540,28 @@ void swapchain::present_image(const pending_present_request &pending_present)
|
|||
}
|
||||
}
|
||||
|
||||
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||
if (m_device_data.is_present_id_enabled())
|
||||
{
|
||||
auto *ext = get_swapchain_extension<wsi_ext_present_id_wayland>(true);
|
||||
if (m_wsi_surface->get_presentation_time_interface() != nullptr)
|
||||
{
|
||||
wp_presentation *pres = m_wsi_surface->get_presentation_time_interface();
|
||||
struct wp_presentation_feedback *feedback = wp_presentation_feedback(pres, m_wsi_surface->get_wl_surface());
|
||||
wl_proxy_set_queue(reinterpret_cast<wl_proxy *>(feedback), m_buffer_queue);
|
||||
presentation_feedback *feedback_obj =
|
||||
ext->insert_into_pending_present_feedback_list(pending_present.present_id, feedback);
|
||||
if (feedback_obj == nullptr)
|
||||
{
|
||||
WSI_LOG_ERROR("Error adding to pending present feedback list");
|
||||
set_error_state(VK_ERROR_SURFACE_LOST_KHR);
|
||||
return;
|
||||
}
|
||||
register_wp_presentation_feedback_listener(feedback, feedback_obj);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
wl_surface_commit(m_surface);
|
||||
res = wl_display_flush(m_display);
|
||||
if (res < 0)
|
||||
|
|
@ -534,8 +573,15 @@ void swapchain::present_image(const pending_present_request &pending_present)
|
|||
|
||||
if (m_device_data.is_present_id_enabled())
|
||||
{
|
||||
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||
auto *ext = get_swapchain_extension<wsi_ext_present_id_wayland>(true);
|
||||
if (m_wsi_surface->get_presentation_time_interface() == nullptr)
|
||||
#else
|
||||
auto *ext = get_swapchain_extension<wsi_ext_present_id>(true);
|
||||
ext->set_present_id(pending_present.present_id);
|
||||
#endif
|
||||
{
|
||||
ext->mark_delivered(pending_present.present_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2021, 2024 Arm Limited.
|
||||
* Copyright (c) 2021-2025 Arm Limited.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
|
|
@ -31,7 +31,7 @@
|
|||
#include <linux-dmabuf-unstable-v1-client-protocol.h>
|
||||
#include <linux-explicit-synchronization-unstable-v1-protocol.h>
|
||||
#include <presentation-time-client-protocol.h>
|
||||
#include <memory.h>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
|
||||
namespace wsi
|
||||
|
|
@ -74,6 +74,11 @@ static inline void wayland_object_destroy(wl_event_queue *obj)
|
|||
wl_event_queue_destroy(obj);
|
||||
}
|
||||
|
||||
static inline void wayland_object_destroy(struct wp_presentation_feedback *obj)
|
||||
{
|
||||
wp_presentation_feedback_destroy(obj);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct wayland_deleter
|
||||
{
|
||||
|
|
|
|||
64
wsi/wayland/wp_presentation_feedback.cpp
Normal file
64
wsi/wayland/wp_presentation_feedback.cpp
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2025 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.
|
||||
*/
|
||||
|
||||
#include "wp_presentation_feedback.hpp"
|
||||
#include "present_id_wayland.hpp"
|
||||
|
||||
namespace wsi
|
||||
{
|
||||
namespace wayland
|
||||
{
|
||||
|
||||
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)
|
||||
{
|
||||
auto feedback_obj = reinterpret_cast<wsi::wayland::presentation_feedback *>(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,
|
||||
.presented = wp_presentation_feedback_presented,
|
||||
.discarded = NULL,
|
||||
};
|
||||
|
||||
VkResult register_wp_presentation_feedback_listener(struct wp_presentation_feedback *wp_presentation_feedback,
|
||||
void *data)
|
||||
{
|
||||
int res = wp_presentation_feedback_add_listener(wp_presentation_feedback, &presentation_listener, data);
|
||||
if (res < 0)
|
||||
{
|
||||
WSI_LOG_ERROR("Failed to add wp_presentation_feedback listener.");
|
||||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace wayland
|
||||
} // namespace wsi
|
||||
123
wsi/wayland/wp_presentation_feedback.hpp
Normal file
123
wsi/wayland/wp_presentation_feedback.hpp
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* Copyright (c) 2025 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
|
||||
* @brief Contains functions for handling the wp_presentation_feedback Wayland protocol
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <presentation-time-client-protocol.h>
|
||||
#include "wl_object_owner.hpp"
|
||||
|
||||
namespace wsi
|
||||
{
|
||||
namespace wayland
|
||||
{
|
||||
|
||||
class wsi_ext_present_id_wayland;
|
||||
|
||||
/**
|
||||
* @brief Registers the listeners for wp_presentation_feedback
|
||||
* @param wp_presentation_feedback - wp_presentation_feedback interface
|
||||
* @param data - Data to pass to the callbacks
|
||||
* @return VK_SUCCESS on success, error otherwise.
|
||||
*/
|
||||
VkResult register_wp_presentation_feedback_listener(struct wp_presentation_feedback *wp_presentation_feedback,
|
||||
void *data);
|
||||
|
||||
/**
|
||||
* @brief Class to hold a presentation feedback and associated attributes.
|
||||
*/
|
||||
class presentation_feedback
|
||||
{
|
||||
public:
|
||||
presentation_feedback(uint64_t present_id, struct wp_presentation_feedback *feedback,
|
||||
wsi_ext_present_id_wayland *ext)
|
||||
: m_present_id(present_id)
|
||||
, m_feedback(feedback)
|
||||
, m_ext(ext)
|
||||
{
|
||||
}
|
||||
|
||||
~presentation_feedback() = default;
|
||||
|
||||
presentation_feedback(const presentation_feedback &feedback_obj) = delete;
|
||||
presentation_feedback &operator=(const presentation_feedback &feedback_obj) = delete;
|
||||
|
||||
presentation_feedback(presentation_feedback &&feedback_obj)
|
||||
: m_present_id(feedback_obj.m_present_id)
|
||||
, m_feedback(std::move(feedback_obj.m_feedback))
|
||||
, m_ext(feedback_obj.m_ext)
|
||||
{
|
||||
feedback_obj.reset();
|
||||
}
|
||||
|
||||
presentation_feedback &operator=(presentation_feedback &&feedback_obj)
|
||||
{
|
||||
if (this == &feedback_obj)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
if (m_feedback != nullptr)
|
||||
{
|
||||
wp_presentation_feedback_destroy(m_feedback.get());
|
||||
}
|
||||
m_present_id = feedback_obj.m_present_id;
|
||||
m_feedback = std::move(feedback_obj.m_feedback);
|
||||
m_ext = feedback_obj.m_ext;
|
||||
feedback_obj.reset();
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
m_present_id = 0;
|
||||
m_feedback = nullptr;
|
||||
m_ext = nullptr;
|
||||
}
|
||||
|
||||
uint64_t present_id()
|
||||
{
|
||||
return m_present_id;
|
||||
}
|
||||
|
||||
struct wp_presentation_feedback *feedback()
|
||||
{
|
||||
return m_feedback.get();
|
||||
}
|
||||
|
||||
wsi_ext_present_id_wayland *ext()
|
||||
{
|
||||
return m_ext;
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t m_present_id;
|
||||
wayland_owner<struct wp_presentation_feedback> m_feedback;
|
||||
wsi_ext_present_id_wayland *m_ext;
|
||||
};
|
||||
|
||||
} // namespace wayland
|
||||
} // namespace wsi
|
||||
|
|
@ -171,6 +171,7 @@ VkResult add_device_extensions_required_by_layer(VkPhysicalDevice phys_dev,
|
|||
#if ENABLE_INSTRUMENTATION
|
||||
VK_EXT_FRAME_BOUNDARY_EXTENSION_NAME,
|
||||
#endif
|
||||
VK_KHR_BIND_MEMORY_2_EXTENSION_NAME,
|
||||
};
|
||||
|
||||
for (auto extension : optional_extensions)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue