This commit merges several related changes to make the layer

fully spec-compliant and avoid leaking unsupported symbols.

Extension enablement

* Only enable extensions promoted to core in Vulkan 1.1 when 
  the application’s API version is < 1.1.
* Filter the list passed to vkGet{Instance,Device}ProcAddr so
  that only _application_-enabled extensions affect symbol lookup. Internally-added
  extensions are ignored during GetProcAddr resolution.

Entrypoint exposure fixes

* getProcAddr now only returns pointers for entrypoints when _all_ of 
  their required extensions (or core version) are enabled:
  * vkGetPhysicalDevicePresentRectanglesKHR
  * vkAcquireNextImage2KHR
  * vkGetDeviceGroupSurfacePresentModesKHR
  * vkBindImageMemory2 / vkBindImageMemory2KHR
  * vkGetPhysicalDeviceFeatures2KHR
* Removed all OR-conditions that previously exposed these functions prematurely,
  replacing them with clear AND-checks per the spec.

Always-exposed device-level entrypoints

* Introduce INSTANCE_ENTRYPOINTS_LIST_EXPANSION for entrypoints that:
  * Come from device-level extensions,
  * Are looked up via instance APIs,
  * Are _not_ in core Vulkan.
* Assign them an empty extension string so they’re always exposed, regardless
  of which instance extensions the application requests.

Hiding non-intercepted functions

* Any entrypoint the layer lists internally but does _not_ intercept 
  is now hidden from applications, preventing calls into stubs.

These combined changes ensure the layer:

* advertises only the extensions it needs,
* obeys all cross-extension dependencies, and
* never leaks unsupported symbols via GetInstanceProcAddr/GetDeviceProcAddr.

Signed-off-by: Maged Elnaggar maged.elnaggar@arm.com 
Change-Id: I7a5e5cb210e017f1aed76b187db1f40537010914
This commit is contained in:
Maged Elnaggar 2025-06-27 15:21:58 +00:00 committed by Iason Paraskevopoulos
parent fb4b1b18bb
commit 4a6f61a72b
12 changed files with 241 additions and 139 deletions

View file

@ -143,13 +143,16 @@ VKAPI_ATTR VkResult create_instance(const VkInstanceCreateInfo *pCreateInfo, con
/* Create a list of extensions to enable, including the provided extensions and those required by the layer. */
TRY_LOG_CALL(extensions.add(pCreateInfo->ppEnabledExtensionNames, pCreateInfo->enabledExtensionCount));
uint32_t api_version =
pCreateInfo->pApplicationInfo != nullptr ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_3;
if (!layer_platforms_to_enable.empty())
{
if (!extensions.contains(VK_KHR_SURFACE_EXTENSION_NAME))
{
return VK_ERROR_EXTENSION_NOT_PRESENT;
}
TRY_LOG_CALL(wsi::add_instance_extensions_required_by_layer(layer_platforms_to_enable, extensions));
TRY_LOG_CALL(wsi::add_instance_extensions_required_by_layer(layer_platforms_to_enable, extensions, api_version));
}
TRY_LOG_CALL(extensions.get_extension_strings(modified_enabled_extensions));
@ -181,9 +184,6 @@ VKAPI_ATTR VkResult create_instance(const VkInstanceCreateInfo *pCreateInfo, con
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
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);
@ -196,7 +196,7 @@ VKAPI_ATTR VkResult create_instance(const VkInstanceCreateInfo *pCreateInfo, con
*/
VkResult result =
instance_private_data::get(*pInstance)
.set_instance_enabled_extensions(modified_enabled_extensions.data(), modified_enabled_extensions.size());
.set_instance_enabled_extensions(pCreateInfo->ppEnabledExtensionNames, pCreateInfo->enabledExtensionCount);
if (result != VK_SUCCESS)
{
instance_private_data::disassociate(*pInstance);
@ -249,7 +249,8 @@ VKAPI_ATTR VkResult create_device(VkPhysicalDevice physicalDevice, const VkDevic
if (!enabled_platforms.empty())
{
TRY_LOG_CALL(enabled_extensions.add(pCreateInfo->ppEnabledExtensionNames, pCreateInfo->enabledExtensionCount));
TRY_LOG_CALL(wsi::add_device_extensions_required_by_layer(physicalDevice, enabled_platforms, enabled_extensions));
TRY_LOG_CALL(wsi::add_device_extensions_required_by_layer(physicalDevice, enabled_platforms, enabled_extensions,
inst_data.api_version));
TRY_LOG_CALL(enabled_extensions.get_extension_strings(modified_enabled_extensions));
modified_info.ppEnabledExtensionNames = modified_enabled_extensions.data();
@ -339,8 +340,8 @@ VKAPI_ATTR VkResult create_device(VkPhysicalDevice physicalDevice, const VkDevic
auto &device_data = layer::device_private_data::get(*pDevice);
device_data.set_layer_frame_boundary_handling_enabled(should_layer_handle_frame_boundary_events);
result = device_data.set_device_enabled_extensions(modified_info.ppEnabledExtensionNames,
modified_info.enabledExtensionCount);
result = device_data.set_device_enabled_extensions(pCreateInfo->ppEnabledExtensionNames,
pCreateInfo->enabledExtensionCount);
if (result != VK_SUCCESS)
{
layer::device_private_data::disassociate(*pDevice);
@ -476,8 +477,8 @@ VWL_VKAPI_EXPORT wsi_layer_vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLay
}
VWL_VKAPI_CALL(void)
wsi_layer_vkGetPhysicalDeviceFeatures2KHR(VkPhysicalDevice physical_device,
VkPhysicalDeviceFeatures2 *pFeatures) VWL_API_POST
wsi_layer_vkGetPhysicalDeviceFeatures2(VkPhysicalDevice physical_device,
VkPhysicalDeviceFeatures2 *pFeatures) VWL_API_POST
{
auto &instance = layer::instance_private_data::get(physical_device);
@ -555,68 +556,114 @@ wsi_layer_vkGetPhysicalDeviceFeatures2KHR(VkPhysicalDevice physical_device,
if (!strcmp(funcName, #func)) \
return (PFN_vkVoidFunction)&wsi_layer_##func;
/**
* @brief Trampoline for **vkGetDeviceProcAddr** inside the WSI layer.
*
* Workflow:
* 1. Retrieve the devices private state (enabled extensions and downstream dispatch table).
* 2. If the function is one that this layer intercepts, return the layers handler.
* 3. Otherwise, forward to the downstream dispatch table (next layer or ICD), or return nullptr if unavailable.
*
* This layer never exposes entrypoints for disabled extensions, preserving the Vulkan dispatch-chain contract.
*
* @param device The VkDevice being queried.
* @param funcName Name of the device-level command to resolve.
* @return Pointer to the layers implementation, the next-layer/ICD function, or nullptr.
*/
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))
auto &device_data = layer::device_private_data::get(device);
const uint64_t api_version = device_data.instance_data.api_version;
const bool core_1_1 = api_version >= VK_API_VERSION_1_1;
if (device_data.is_device_extension_enabled(VK_KHR_SWAPCHAIN_EXTENSION_NAME))
{
GET_PROC_ADDR(vkCreateSwapchainKHR);
GET_PROC_ADDR(vkDestroySwapchainKHR);
GET_PROC_ADDR(vkGetSwapchainImagesKHR);
GET_PROC_ADDR(vkAcquireNextImageKHR);
GET_PROC_ADDR(vkQueuePresentKHR);
GET_PROC_ADDR(vkAcquireNextImage2KHR);
GET_PROC_ADDR(vkGetDeviceGroupPresentCapabilitiesKHR);
GET_PROC_ADDR(vkGetDeviceGroupSurfacePresentModesKHR);
if (device_data.is_device_extension_enabled(VK_KHR_DEVICE_GROUP_EXTENSION_NAME) || core_1_1)
{
GET_PROC_ADDR(vkAcquireNextImage2KHR);
}
if (core_1_1)
{
GET_PROC_ADDR(vkGetDeviceGroupSurfacePresentModesKHR);
GET_PROC_ADDR(vkGetDeviceGroupPresentCapabilitiesKHR);
}
}
if (layer::device_private_data::get(device).is_device_extension_enabled(
VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME))
if (device_data.is_device_extension_enabled(VK_KHR_DEVICE_GROUP_EXTENSION_NAME) &&
device_data.is_device_extension_enabled(VK_KHR_SURFACE_EXTENSION_NAME))
{
GET_PROC_ADDR(vkGetDeviceGroupSurfacePresentModesKHR);
GET_PROC_ADDR(vkGetDeviceGroupPresentCapabilitiesKHR);
}
if (device_data.is_device_extension_enabled(VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME))
{
GET_PROC_ADDR(vkGetSwapchainStatusKHR);
}
#if VULKAN_WSI_LAYER_EXPERIMENTAL
if (layer::device_private_data::get(device).is_device_extension_enabled(VK_EXT_PRESENT_TIMING_EXTENSION_NAME))
if (device_data.is_device_extension_enabled(VK_EXT_PRESENT_TIMING_EXTENSION_NAME))
{
GET_PROC_ADDR(vkSetSwapchainPresentTimingQueueSizeEXT);
GET_PROC_ADDR(vkGetSwapchainTimingPropertiesEXT);
GET_PROC_ADDR(vkGetSwapchainTimeDomainPropertiesEXT);
GET_PROC_ADDR(vkGetPastPresentationTimingEXT);
GET_PROC_ADDR(vkGetCalibratedTimestampsKHR);
if (layer::device_private_data::get(device).is_device_extension_enabled(
VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME))
if (device_data.is_device_extension_enabled(VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME))
{
GET_PROC_ADDR(vkGetCalibratedTimestampsEXT);
}
}
#endif
GET_PROC_ADDR(vkDestroyDevice);
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)
if (device_data.is_device_extension_enabled(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME))
{
return (PFN_vkVoidFunction)&wsi_layer_vkBindImageMemory2;
if (!strcmp(funcName, "vkBindImageMemory2KHR"))
{
return (PFN_vkVoidFunction)&wsi_layer_vkBindImageMemory2;
}
}
if (core_1_1)
{
GET_PROC_ADDR(vkBindImageMemory2);
}
/* VK_EXT_swapchain_maintenance1 */
if (layer::device_private_data::get(device).is_device_extension_enabled(
VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME))
if (device_data.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_KHR_PRESENT_WAIT_EXTENSION_NAME))
if (device_data.is_device_extension_enabled(VK_KHR_PRESENT_WAIT_EXTENSION_NAME))
{
GET_PROC_ADDR(vkWaitForPresentKHR);
}
return layer::device_private_data::get(device).disp.get_user_enabled_entrypoint(
device, layer::device_private_data::get(device).instance_data.api_version, funcName);
return device_data.disp.get_user_enabled_entrypoint(device, funcName);
}
/**
* @brief Trampoline for **vkGetInstanceProcAddr** inside the WSI layer.
*
* Workflow:
* 1. Publish loader-critical symbols (i.e. `vkGetDeviceProcAddr`, `vkGetInstanceProcAddr`).
* 2. Retrieve the instances private state (API version and enabled extensions)
* and intercept layer-handled commands.
* 3. Forward all other commands to the downstream instance dispatch table,
* or return nullptr if unavailable.
*
* This layer only exposes core commands and enabled-extension entrypoints,
* preserving the Vulkan dispatch-chain contract.
*
* @param instance The VkInstance being queried (may be VK_NULL_HANDLE).
* @param funcName Name of the instance-level command to resolve.
* @return Pointer to this layers handler, the next-layer/ICD function, or nullptr.
*/
VWL_VKAPI_CALL(PFN_vkVoidFunction)
wsi_layer_vkGetInstanceProcAddr(VkInstance instance, const char *funcName) VWL_API_POST
{
@ -625,18 +672,26 @@ wsi_layer_vkGetInstanceProcAddr(VkInstance instance, const char *funcName) VWL_A
GET_PROC_ADDR(vkCreateInstance);
GET_PROC_ADDR(vkDestroyInstance);
GET_PROC_ADDR(vkCreateDevice);
GET_PROC_ADDR(vkGetPhysicalDevicePresentRectanglesKHR);
if (!strcmp(funcName, "vkGetPhysicalDeviceFeatures2"))
{
return (PFN_vkVoidFunction)wsi_layer_vkGetPhysicalDeviceFeatures2KHR;
}
auto &instance_data = layer::instance_private_data::get(instance);
const bool core_1_1 = instance_data.api_version >= VK_API_VERSION_1_1;
if ((instance_data.is_instance_extension_enabled(VK_KHR_DEVICE_GROUP_EXTENSION_NAME) &&
instance_data.is_instance_extension_enabled(VK_KHR_SURFACE_EXTENSION_NAME)) ||
core_1_1)
{
GET_PROC_ADDR(vkGetPhysicalDevicePresentRectanglesKHR);
}
if (instance_data.is_instance_extension_enabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME))
{
GET_PROC_ADDR(vkGetPhysicalDeviceFeatures2KHR);
if (!strcmp(funcName, "vkGetPhysicalDeviceFeatures2KHR"))
{
return (PFN_vkVoidFunction)&wsi_layer_vkGetPhysicalDeviceFeatures2;
}
}
if (core_1_1)
{
GET_PROC_ADDR(vkGetPhysicalDeviceFeatures2);
}
if (instance_data.is_instance_extension_enabled(VK_KHR_SURFACE_EXTENSION_NAME))
@ -660,5 +715,5 @@ wsi_layer_vkGetInstanceProcAddr(VkInstance instance, const char *funcName) VWL_A
}
}
return instance_data.disp.get_user_enabled_entrypoint(instance, instance_data.api_version, funcName);
return instance_data.disp.get_user_enabled_entrypoint(instance, funcName);
}

View file

@ -98,23 +98,29 @@ void dispatch_table::set_user_enabled_extensions(const char *const *extension_na
}
}
PFN_vkVoidFunction instance_dispatch_table::get_user_enabled_entrypoint(VkInstance instance, uint32_t api_version,
const char *fn_name) const
/**
* @brief Decide whether we should expose this Vulkan entrypoint to the application.
*
* An entrypoint is exposable if any of the following are true:
* - The application explicitly enabled its extension/command.
* - Its part of core Vulkan 1.0.
* - It has no associated extension name (`ep.ext_name` is empty), e.g.
* `vkGetPhysicalDeviceCalibrateableTimeDomainsKHR`
*
* @param[in] ep The entrypoint metadata to evaluate.
* @return `true` if the layer should expose this entrypoint, `false` otherwise.
*/
static inline bool should_expose_entrypoint(const entrypoint &ep)
{
auto item = m_entrypoints->find(fn_name);
if (item != m_entrypoints->end())
return ep.user_visible || (ep.api_version == VK_API_VERSION_1_0) || (ep.ext_name && ep.ext_name[0] == '\0');
}
PFN_vkVoidFunction instance_dispatch_table::get_user_enabled_entrypoint(VkInstance instance, const char *fn_name) const
{
auto itr = m_entrypoints->find(fn_name);
if (itr != m_entrypoints->end())
{
/* An entrypoint is allowed to use if it has been enabled by the user or is included in the core specficiation of the API version.
* Entrypoints included in API version 1.0 are allowed by default. */
if (item->second.user_visible || item->second.api_version <= api_version ||
item->second.api_version == VK_API_VERSION_1_0)
{
return item->second.fn;
}
else
{
return nullptr;
}
return should_expose_entrypoint(itr->second) ? itr->second.fn : nullptr;
}
return GetInstanceProcAddr(instance, fn_name).value_or(nullptr);
@ -159,36 +165,12 @@ VkResult device_dispatch_table::populate(VkDevice dev, PFN_vkGetDeviceProcAddr g
return VK_SUCCESS;
}
PFN_vkVoidFunction device_dispatch_table::get_user_enabled_entrypoint(VkDevice device, uint32_t api_version,
const char *fn_name) const
PFN_vkVoidFunction device_dispatch_table::get_user_enabled_entrypoint(VkDevice device, const char *fn_name) const
{
auto itr = m_entrypoints->find(fn_name);
if (itr != m_entrypoints->end())
{
/* An entrypoint is allowed to be used:
* - if it has been enabled by the user,
* - or if is included in the core specficiation of the API version.
* Entrypoints included in API version 1.0 are allowed by default.
*/
const entrypoint &ep = itr->second;
if (ep.user_visible)
{
return ep.fn;
}
if (ep.api_version == VK_API_VERSION_1_0)
{
return ep.fn;
}
bool is_core = (ep.ext_name != nullptr && ep.ext_name[0] == '\0');
if (is_core && ep.api_version <= api_version)
{
return ep.fn;
}
return nullptr;
return should_expose_entrypoint(itr->second) ? itr->second.fn : nullptr;
}
return GetDeviceProcAddr(device, fn_name).value_or(nullptr);

View file

@ -277,9 +277,24 @@ static constexpr uint32_t API_VERSION_MAX = UINT32_MAX;
EP(SetDebugUtilsObjectNameEXT, VK_EXT_DEBUG_UTILS_EXTENSION_NAME, API_VERSION_MAX, false, ) \
EP(SetDebugUtilsObjectTagEXT, VK_EXT_DEBUG_UTILS_EXTENSION_NAME, API_VERSION_MAX, false, ) \
EP(SubmitDebugUtilsMessageEXT, VK_EXT_DEBUG_UTILS_EXTENSION_NAME, API_VERSION_MAX, false, ) \
/* VK_KHR_calibrated_timestamps */ \
EP(GetPhysicalDeviceCalibrateableTimeDomainsKHR, VK_KHR_CALIBRATED_TIMESTAMPS_EXTENSION_NAME, API_VERSION_MAX, \
false, )
/* Custom entrypoints */ \
INSTANCE_ENTRYPOINTS_LIST_EXPANSION(EP)
/*
* Extension list for INSTANCE_ENTRYPOINTS_LIST containing entrypoints that:
* - Are not part of core Vulkan,
* - Belong to device-level extensions,
* - Are queried via instance-level APIs.
*
* These entrypoints have an empty extension name ("") to ensure they are
* always exposed, regardless of extension enablement, as their use does not
* depend on any specific instance extension being advertised.
*/
#define INSTANCE_ENTRYPOINTS_LIST_EXPANSION(EP) \
/* VK_KHR_calibrated_timestamps */ \
EP(GetPhysicalDeviceCalibrateableTimeDomainsKHR, "", API_VERSION_MAX, false, ) \
/* VK_EXT_calibrated_timestamps */ \
EP(GetPhysicalDeviceCalibrateableTimeDomainsEXT, "", API_VERSION_MAX, false, )
/**
* @brief Struct representing the instance dispatch table.
@ -314,11 +329,10 @@ public:
* @brief Get the user enabled instance extension entrypoint by name
*
* @param instance The Vulkan instance that the extension was enabled on.
* @param api_version The API version of the Vulkan instance.
* @param fn_name The name of the function.
* @return pointer to the function if it is enabled by the user, otherwise nullptr.
*/
PFN_vkVoidFunction get_user_enabled_entrypoint(VkInstance instance, uint32_t api_version, const char *fn_name) const;
PFN_vkVoidFunction get_user_enabled_entrypoint(VkInstance instance, const char *fn_name) const;
/* Generate alias functions for internal use of the dispatch table entrypoints.
* These will be named as the entrypoint, but without the "vk" prefix.
@ -455,7 +469,7 @@ private:
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) \
false, GetImageSparseMemoryRequirements2) \
/* VK_EXT_swapchain_maintenance1 */ \
EP(ReleaseSwapchainImagesEXT, VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME, VK_API_VERSION_1_1, false, ) \
/* VK_EXT_calibrated_timestamps */ \
@ -500,11 +514,10 @@ public:
* @brief Get the user enabled device extension entrypoint by name
*
* @param device The Vulkan device that the extension was enabled on.
* @param api_version The API version of the Vulkan instance.
* @param fn_name The name of the function.
* @return pointer to the function if it is enabled by the user, otherwise nullptr.
*/
PFN_vkVoidFunction get_user_enabled_entrypoint(VkDevice device, uint32_t api_version, const char *fn_name) const;
PFN_vkVoidFunction get_user_enabled_entrypoint(VkDevice device, const char *fn_name) const;
/* Generate alias functions for internal use of the dispatch table entrypoints.
* These will be named as the entrypoint, but without the "vk" prefix.

View file

@ -507,23 +507,44 @@ PFN_vkVoidFunction surface_properties::get_proc_addr(const char *name)
return nullptr;
}
VkResult surface_properties::get_required_instance_extensions(util::extension_list &extension_list)
VkResult surface_properties::get_required_instance_extensions(util::extension_list &extension_list,
const uint32_t api_version)
{
const std::array required_instance_extensions{
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
};
return extension_list.add(required_instance_extensions.data(), required_instance_extensions.size());
VkResult result = VK_SUCCESS;
/* Enable extensions that were promoted to core in Vulkan 1.1 when using API versions < 1.1 */
if (api_version < VK_API_VERSION_1_1)
{
const std::array required_extensions_pre_vulkan_1_1{
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
};
result = extension_list.add(required_extensions_pre_vulkan_1_1.data(), required_extensions_pre_vulkan_1_1.size());
}
return result;
}
VkResult surface_properties::get_required_device_extensions(util::extension_list &extension_list)
VkResult surface_properties::get_required_device_extensions(util::extension_list &extension_list,
const uint32_t api_version)
{
VkResult result = VK_SUCCESS;
const std::array required_device_extensions{
VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,
VK_KHR_BIND_MEMORY_2_EXTENSION_NAME,
};
result = extension_list.add(required_device_extensions.data(), required_device_extensions.size());
if (result != VK_SUCCESS)
{
return result;
}
return extension_list.add(required_device_extensions.data(), required_device_extensions.size());
/* Enable extensions that were promoted to core in Vulkan 1.1 when using API versions < 1.1 */
if (api_version < VK_API_VERSION_1_1)
{
const std::array required_extensions_pre_vulkan_1_1{
VK_KHR_BIND_MEMORY_2_EXTENSION_NAME,
};
result = extension_list.add(required_extensions_pre_vulkan_1_1.data(), required_extensions_pre_vulkan_1_1.size());
}
return result;
}
bool surface_properties::is_surface_extension_enabled(const layer::instance_private_data &instance_data)

View file

@ -60,9 +60,9 @@ public:
PFN_vkVoidFunction get_proc_addr(const char *name) override;
VkResult get_required_instance_extensions(util::extension_list &extension_list) override;
VkResult get_required_instance_extensions(util::extension_list &extension_list, const uint32_t api_version) override;
VkResult get_required_device_extensions(util::extension_list &extension_list) override;
VkResult get_required_device_extensions(util::extension_list &extension_list, const uint32_t api_version) override;
bool is_surface_extension_enabled(const layer::instance_private_data &instance_data) override;

View file

@ -191,14 +191,21 @@ PFN_vkVoidFunction surface_properties::get_proc_addr(const char *name)
return nullptr;
}
VkResult surface_properties::get_required_instance_extensions(util::extension_list &extension_list)
VkResult surface_properties::get_required_instance_extensions(util::extension_list &extension_list,
const uint32_t api_version)
{
const std::array required_instance_extensions{
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME,
VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME,
};
return extension_list.add(required_instance_extensions.data(), required_instance_extensions.size());
VkResult result = VK_SUCCESS;
/* Enable extensions that were promoted to core in Vulkan 1.1 when using API versions < 1.1 */
if (api_version < VK_API_VERSION_1_1)
{
const std::array required_extensions_pre_vulkan_1_1{
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME,
VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME,
};
result = extension_list.add(required_extensions_pre_vulkan_1_1.data(), required_extensions_pre_vulkan_1_1.size());
}
return result;
}
bool surface_properties::is_surface_extension_enabled(const layer::instance_private_data &instance_data)

View file

@ -56,7 +56,7 @@ public:
PFN_vkVoidFunction get_proc_addr(const char *name) override;
VkResult get_required_instance_extensions(util::extension_list &extension_list) override;
VkResult get_required_instance_extensions(util::extension_list &extension_list, const uint32_t api_version) override;
bool is_surface_extension_enabled(const layer::instance_private_data &instance_data) override;

View file

@ -78,17 +78,19 @@ public:
/**
* @brief Return the device extensions that this surface_properties implementation needs.
*/
virtual VkResult get_required_device_extensions(util::extension_list &extension_list)
virtual VkResult get_required_device_extensions(util::extension_list &extension_list, const uint32_t api_version)
{
/* Requires no additional extensions */
UNUSED(extension_list);
UNUSED(api_version);
return VK_SUCCESS;
}
/**
* @brief Return the instance extensions that this surface_properties implementation needs.
*/
virtual VkResult get_required_instance_extensions(util::extension_list &extension_list) = 0;
virtual VkResult get_required_instance_extensions(util::extension_list &extension_list,
const uint32_t api_version) = 0;
/**
* @brief Implements vkGetProcAddr for entrypoints specific to the surface type.

View file

@ -251,34 +251,51 @@ VkResult surface_properties::get_surface_present_modes(VkPhysicalDevice physical
return get_surface_present_modes_common(pPresentModeCount, pPresentModes, m_supported_modes);
}
VkResult surface_properties::get_required_device_extensions(util::extension_list &extension_list)
VkResult surface_properties::get_required_device_extensions(util::extension_list &extension_list,
const uint32_t api_version)
{
VkResult result = VK_SUCCESS;
const std::array required_device_extensions{
VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME,
VK_KHR_BIND_MEMORY_2_EXTENSION_NAME,
VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME,
VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME,
VK_KHR_MAINTENANCE1_EXTENSION_NAME,
VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME,
VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME,
VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,
VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
VK_KHR_EXTERNAL_FENCE_EXTENSION_NAME,
VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME,
VK_KHR_CALIBRATED_TIMESTAMPS_EXTENSION_NAME,
VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME, VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME,
VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME, VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,
VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME, VK_KHR_CALIBRATED_TIMESTAMPS_EXTENSION_NAME,
};
return extension_list.add(required_device_extensions.data(), required_device_extensions.size());
result = extension_list.add(required_device_extensions.data(), required_device_extensions.size());
if (result != VK_SUCCESS)
{
return result;
}
/* Enable extensions that were promoted to core in Vulkan 1.1 when using API versions < 1.1 */
if (api_version < VK_API_VERSION_1_1)
{
const std::array required_extensions_pre_vulkan_1_1{
VK_KHR_BIND_MEMORY_2_EXTENSION_NAME, VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME,
VK_KHR_MAINTENANCE1_EXTENSION_NAME, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME,
VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME, VK_KHR_EXTERNAL_FENCE_EXTENSION_NAME
};
result = extension_list.add(required_extensions_pre_vulkan_1_1.data(), required_extensions_pre_vulkan_1_1.size());
}
return result;
}
VkResult surface_properties::get_required_instance_extensions(util::extension_list &extension_list)
VkResult surface_properties::get_required_instance_extensions(util::extension_list &extension_list,
const uint32_t api_version)
{
const std::array required_instance_extensions{
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME,
VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME,
VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
};
return extension_list.add(required_instance_extensions.data(), required_instance_extensions.size());
VkResult result = VK_SUCCESS;
/* Enable extensions that were promoted to core in Vulkan 1.1 when using API versions < 1.1 */
if (api_version < VK_API_VERSION_1_1)
{
const std::array required_extensions_pre_vulkan_1_1{
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME,
VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME,
VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
};
result = extension_list.add(required_extensions_pre_vulkan_1_1.data(), required_extensions_pre_vulkan_1_1.size());
}
return result;
}
struct required_properties

View file

@ -65,9 +65,9 @@ public:
VkResult get_surface_present_modes(VkPhysicalDevice physical_device, VkSurfaceKHR surface,
uint32_t *pPresentModeCount, VkPresentModeKHR *pPresentModes) override;
VkResult get_required_device_extensions(util::extension_list &extension_list) override;
VkResult get_required_device_extensions(util::extension_list &extension_list, const uint32_t api_version) override;
VkResult get_required_instance_extensions(util::extension_list &extension_list) override;
VkResult get_required_instance_extensions(util::extension_list &extension_list, const uint32_t api_version) override;
PFN_vkVoidFunction get_proc_addr(const char *name) override;

View file

@ -153,7 +153,7 @@ static VkResult get_available_device_extensions(VkPhysicalDevice physical_device
VkResult add_device_extensions_required_by_layer(VkPhysicalDevice phys_dev,
const util::wsi_platform_set enabled_platforms,
util::extension_list &extensions_to_enable)
util::extension_list &extensions_to_enable, const uint32_t api_version)
{
util::allocator allocator{ extensions_to_enable.get_allocator(), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND };
@ -198,7 +198,7 @@ VkResult add_device_extensions_required_by_layer(VkPhysicalDevice phys_dev,
return VK_ERROR_INITIALIZATION_FAILED;
}
TRY_LOG(props->get_required_device_extensions(extensions_required_by_layer),
TRY_LOG(props->get_required_device_extensions(extensions_required_by_layer, api_version),
"Failed to acquire required device extensions");
bool supported = available_device_extensions.contains(extensions_required_by_layer);
@ -219,7 +219,8 @@ VkResult add_device_extensions_required_by_layer(VkPhysicalDevice phys_dev,
}
VkResult add_instance_extensions_required_by_layer(const util::wsi_platform_set enabled_platforms,
util::extension_list &extensions_to_enable)
util::extension_list &extensions_to_enable,
const uint32_t api_version)
{
util::allocator allocator{ extensions_to_enable.get_allocator(), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND };
/* Requesting available instance extensions (as it happens with the device)
@ -241,7 +242,7 @@ VkResult add_instance_extensions_required_by_layer(const util::wsi_platform_set
return VK_ERROR_INITIALIZATION_FAILED;
}
TRY_LOG(props->get_required_instance_extensions(extensions_required_by_layer),
TRY_LOG(props->get_required_instance_extensions(extensions_required_by_layer, api_version),
"Failed to acquire required instance extensions");
TRY_LOG_CALL(extensions_to_enable.add(extensions_required_by_layer));

View file

@ -92,23 +92,27 @@ util::wsi_platform_set find_enabled_layer_platforms(const VkInstanceCreateInfo *
* @param[in] phys_dev The physical device to check.
* @param[in] enabled_platforms All the platforms that the layer must enable for @p phys_dev.
* @param[in,out] extensions_to_enable All the extensions required by the layer are added to this list.
* @param[in] api_version The Vulkan API version being used.
*
* @retval @c VK_SUCCESS if the operation was successful.
*/
VkResult add_device_extensions_required_by_layer(VkPhysicalDevice phys_dev,
const util::wsi_platform_set enabled_platforms,
util::extension_list &extensions_to_enable);
util::extension_list &extensions_to_enable,
const uint32_t api_version);
/**
* @brief Add required instance extensions by the layer.
*
* @param[in] enabled_platforms All the enabled platforms for the current instance.
* @param[in,out] extensions_to_enable All the extensions required by the layer are added to this list.
* @param[in] api_version The Vulkan API version being used.
*
* @retval @c VK_SUCCESS if the operation was successful.
*/
VkResult add_instance_extensions_required_by_layer(const util::wsi_platform_set enabled_platforms,
util::extension_list &extensions_to_enable);
util::extension_list &extensions_to_enable,
const uint32_t api_version);
/**
* @brief Return a function pointer for surface specific functions.