[extension_name](Extension const& ext) { return ext.extensionName == extension_name; });
}
+bool IsPhysicalDeviceExtensionAvailable(const char* extension_name) {
+ for (auto& phys_dev : icd.physical_devices) {
+ if (phys_dev.extensions.end() !=
+ std::find_if(phys_dev.extensions.begin(), phys_dev.extensions.end(),
+ [extension_name](Extension const& ext) { return ext.extensionName == extension_name; })) {
+ return true;
+ }
+ }
+ return false;
+}
+
// typename T must have '.get()' function that returns a type U
template <typename T, typename U>
VkResult FillCountPtr(std::vector<T> const& data_vec, uint32_t* pCount, U* pData) {
memcpy(pExternalFenceProperties, &phys_dev.external_fence_properties, sizeof(VkExternalFenceProperties));
}
}
+// Entry-points associated with the VK_KHR_performance_query extension
+VKAPI_ATTR VkResult VKAPI_CALL test_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR(
+ VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, uint32_t* pCounterCount, VkPerformanceCounterKHR* pCounters,
+ VkPerformanceCounterDescriptionKHR* pCounterDescriptions) {
+ return VK_SUCCESS;
+}
+VKAPI_ATTR void VKAPI_CALL test_vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR(
+ VkPhysicalDevice physicalDevice, const VkQueryPoolPerformanceCreateInfoKHR* pPerformanceQueryCreateInfo, uint32_t* pNumPasses) {
+}
+VKAPI_ATTR VkResult VKAPI_CALL test_vkAcquireProfilingLockKHR(VkDevice device, const VkAcquireProfilingLockInfoKHR* pInfo) {
+ return VK_SUCCESS;
+}
+VKAPI_ATTR void VKAPI_CALL test_vkReleaseProfilingLockKHR(VkDevice device) {}
+// Entry-points associated with the VK_EXT_sample_locations extension
+VKAPI_ATTR void VKAPI_CALL test_vkCmdSetSampleLocationsEXT(VkCommandBuffer commandBuffer,
+ const VkSampleLocationsInfoEXT* pSampleLocationsInfo) {}
+VKAPI_ATTR void VKAPI_CALL test_vkGetPhysicalDeviceMultisamplePropertiesEXT(VkPhysicalDevice physicalDevice,
+ VkSampleCountFlagBits samples,
+ VkMultisamplePropertiesEXT* pMultisampleProperties) {}
+// Entry-points associated with the VK_EXT_calibrated_timestamps extension
+VKAPI_ATTR VkResult VKAPI_CALL test_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT(VkPhysicalDevice physicalDevice,
+ uint32_t* pTimeDomainCount,
+ VkTimeDomainEXT* pTimeDomains) {
+ return VK_SUCCESS;
+}
+VKAPI_ATTR VkResult VKAPI_CALL test_vkGetCalibratedTimestampsEXT(VkDevice device, uint32_t timestampCount,
+ const VkCalibratedTimestampInfoEXT* pTimestampInfos,
+ uint64_t* pTimestamps, uint64_t* pMaxDeviation) {
+ return VK_SUCCESS;
+}
//// trampolines
if (string_eq(pName, "vkGetPhysicalDeviceImageFormatProperties"))
return TO_VOID_PFN(test_vkGetPhysicalDeviceImageFormatProperties);
- if (IsInstanceExtensionEnabled("VK_KHR_get_physical_device_properties2")) {
- if (string_eq(pName, "vkGetPhysicalDeviceFeatures2KHR")) return TO_VOID_PFN(test_vkGetPhysicalDeviceFeatures2);
- if (string_eq(pName, "vkGetPhysicalDeviceProperties2KHR")) return TO_VOID_PFN(test_vkGetPhysicalDeviceProperties2);
- if (string_eq(pName, "vkGetPhysicalDeviceFormatProperties2KHR"))
- return TO_VOID_PFN(test_vkGetPhysicalDeviceFormatProperties2);
- if (string_eq(pName, "vkGetPhysicalDeviceMemoryProperties2KHR"))
- return TO_VOID_PFN(test_vkGetPhysicalDeviceMemoryProperties2);
-
- if (string_eq(pName, "vkGetPhysicalDeviceQueueFamilyProperties2KHR"))
- return TO_VOID_PFN(test_vkGetPhysicalDeviceQueueFamilyProperties2);
-
- if (string_eq(pName, "vkGetPhysicalDeviceSparseImageFormatProperties2KHR"))
- return TO_VOID_PFN(test_vkGetPhysicalDeviceSparseImageFormatProperties2);
-
- if (string_eq(pName, "vkGetPhysicalDeviceImageFormatProperties2KHR")) {
- return TO_VOID_PFN(test_vkGetPhysicalDeviceImageFormatProperties2);
- }
- } else if (IsInstanceExtensionEnabled("VK_KHR_get_physical_device_properties2")) {
+ if (IsInstanceExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
if (string_eq(pName, "vkGetPhysicalDeviceFeatures2KHR")) return TO_VOID_PFN(test_vkGetPhysicalDeviceFeatures2);
if (string_eq(pName, "vkGetPhysicalDeviceProperties2KHR")) return TO_VOID_PFN(test_vkGetPhysicalDeviceProperties2);
if (string_eq(pName, "vkGetPhysicalDeviceFormatProperties2KHR"))
return TO_VOID_PFN(test_vkGetPhysicalDeviceImageFormatProperties2);
}
}
- if (IsInstanceExtensionEnabled("VK_KHR_external_memory_capabilities")) {
+ if (IsInstanceExtensionEnabled(VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME)) {
if (string_eq(pName, "vkGetPhysicalDeviceExternalBufferPropertiesKHR"))
return TO_VOID_PFN(test_vkGetPhysicalDeviceExternalBufferProperties);
}
- if (IsInstanceExtensionEnabled("VK_KHR_external_semaphore_capabilities")) {
+ if (IsInstanceExtensionEnabled(VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME)) {
if (string_eq(pName, "vkGetPhysicalDeviceExternalSemaphorePropertiesKHR"))
return TO_VOID_PFN(test_vkGetPhysicalDeviceExternalSemaphoreProperties);
}
- if (IsInstanceExtensionEnabled("VK_KHR_external_fence_capabilities")) {
+ if (IsInstanceExtensionEnabled(VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME)) {
if (string_eq(pName, "vkGetPhysicalDeviceExternalFencePropertiesKHR"))
return TO_VOID_PFN(test_vkGetPhysicalDeviceExternalFenceProperties);
}
+ // The following physical device extensions only need 1 device to support them for the ICD to export
+ // them
+ if (IsPhysicalDeviceExtensionAvailable(VK_KHR_PERFORMANCE_QUERY_EXTENSION_NAME)) {
+ if (string_eq(pName, "vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR"))
+ return TO_VOID_PFN(test_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR);
+ if (string_eq(pName, "vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR"))
+ return TO_VOID_PFN(test_vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR);
+ if (string_eq(pName, "vkAcquireProfilingLockKHR")) return TO_VOID_PFN(test_vkAcquireProfilingLockKHR);
+ if (string_eq(pName, "vkReleaseProfilingLockKHR")) return TO_VOID_PFN(test_vkReleaseProfilingLockKHR);
+ }
+ if (IsPhysicalDeviceExtensionAvailable(VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME)) {
+ if (string_eq(pName, "vkCmdSetSampleLocationsEXT")) return TO_VOID_PFN(test_vkCmdSetSampleLocationsEXT);
+ if (string_eq(pName, "vkGetPhysicalDeviceMultisamplePropertiesEXT"))
+ return TO_VOID_PFN(test_vkGetPhysicalDeviceMultisamplePropertiesEXT);
+ }
+ if (IsPhysicalDeviceExtensionAvailable(VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME)) {
+ if (string_eq(pName, "vkGetPhysicalDeviceCalibrateableTimeDomainsEXT"))
+ return TO_VOID_PFN(test_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT);
+ if (string_eq(pName, "vkGetCalibratedTimestampsEXT")) return TO_VOID_PFN(test_vkGetCalibratedTimestampsEXT);
+ }
+
if (icd.icd_api_version >= VK_MAKE_API_VERSION(0, 1, 1, 0)) {
if (string_eq(pName, "vkGetPhysicalDeviceFeatures2")) return TO_VOID_PFN(test_vkGetPhysicalDeviceFeatures2);
if (string_eq(pName, "vkGetPhysicalDeviceProperties2")) return TO_VOID_PFN(test_vkGetPhysicalDeviceProperties2);
/*
- * Copyright (c) 2021 The Khronos Group Inc.
- * Copyright (c) 2021 Valve Corporation
- * Copyright (c) 2021 LunarG, Inc.
+ * Copyright (c) 2021-2022 The Khronos Group Inc.
+ * Copyright (c) 2021-2022 Valve Corporation
+ * Copyright (c) 2021-2022 LunarG, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and/or associated documentation files (the "Materials"), to
}
}
}
-}
\ No newline at end of file
+}
+
+TEST(LoaderInstPhysDevExts, DifferentInstanceExtensions) {
+ FrameworkEnvironment env{};
+
+ // Add 3 drivers each of which supports a different instance extension
+ env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_0));
+ env.get_test_icd(0).add_instance_extension({VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME});
+ env.get_test_icd(0).physical_devices.push_back({"pd0", 7});
+ env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME, 0});
+
+ env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_0));
+ env.get_test_icd(1).add_instance_extension({VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME});
+ env.get_test_icd(1).physical_devices.push_back({"pd1", 0});
+ env.get_test_icd(1).physical_devices.back().extensions.push_back({VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME, 0});
+
+ env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_0));
+ env.get_test_icd(2).add_instance_extension({VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME});
+ env.get_test_icd(2).physical_devices.push_back({"pd2", 1});
+ env.get_test_icd(2).physical_devices.back().extensions.push_back({VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME, 0});
+
+ DebugUtilsLogger log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
+ InstWrapper inst{env.vulkan_functions};
+ inst.create_info.add_extensions({VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
+ VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME,
+ VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME});
+ FillDebugUtilsCreateDetails(inst.create_info, log);
+ inst.CheckCreate();
+
+ const uint32_t expected_device_count = 3;
+ auto physical_devices = inst.GetPhysDevs(expected_device_count);
+
+ auto GetPhysicalDeviceExternalBufferProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR>(
+ inst.functions->vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceExternalBufferPropertiesKHR"));
+ auto GetPhysicalDeviceExternalSemaphoreProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR>(
+ inst.functions->vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceExternalSemaphorePropertiesKHR"));
+ auto GetPhysicalDeviceExternalFenceProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR>(
+ inst.functions->vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceExternalFencePropertiesKHR"));
+ ASSERT_NE(nullptr, GetPhysicalDeviceExternalBufferProperties);
+ ASSERT_NE(nullptr, GetPhysicalDeviceExternalSemaphoreProperties);
+ ASSERT_NE(nullptr, GetPhysicalDeviceExternalFenceProperties);
+
+ // The above are instance extensions, so shouldn't crash even if only one physical device supports each
+ // extension.
+ for (uint32_t dev = 0; dev < expected_device_count; ++dev) {
+ VkPhysicalDeviceExternalBufferInfo ext_buf_info{};
+ VkExternalBufferProperties ext_buf_props{};
+ VkPhysicalDeviceExternalSemaphoreInfo ext_sem_info{};
+ VkExternalSemaphoreProperties ext_sem_props{};
+ VkPhysicalDeviceExternalFenceInfo ext_fence_info{};
+ VkExternalFenceProperties ext_fence_props{};
+ GetPhysicalDeviceExternalBufferProperties(physical_devices[dev], &ext_buf_info, &ext_buf_props);
+ GetPhysicalDeviceExternalSemaphoreProperties(physical_devices[dev], &ext_sem_info, &ext_sem_props);
+ GetPhysicalDeviceExternalFenceProperties(physical_devices[dev], &ext_fence_info, &ext_fence_props);
+ }
+}
+
+TEST(LoaderInstPhysDevExts, DifferentPhysicalDeviceExtensions) {
+ FrameworkEnvironment env{};
+
+ // Add 3 drivers each of which supports a different physical device extension
+ env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_0));
+ env.get_test_icd(0).physical_devices.push_back({"pd0", 7});
+ env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_PERFORMANCE_QUERY_EXTENSION_NAME, 0});
+
+ env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_0));
+ env.get_test_icd(1).physical_devices.push_back({"pd1", 0});
+ env.get_test_icd(1).physical_devices.back().extensions.push_back({VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME, 0});
+
+ env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_0));
+ env.get_test_icd(2).physical_devices.push_back({"pd2", 1});
+ env.get_test_icd(2).physical_devices.back().extensions.push_back({VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME, 0});
+
+ DebugUtilsLogger log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
+ InstWrapper inst{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst.create_info, log);
+ inst.CheckCreate();
+
+ const uint32_t expected_device_count = 3;
+ auto physical_devices = inst.GetPhysDevs(expected_device_count);
+
+ auto EnumeratePhysicalDeviceQueueFamilyPerformanceQueryCounters =
+ reinterpret_cast<PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR>(
+ inst.functions->vkGetInstanceProcAddr(inst, "vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR"));
+ auto GetPhysicalDeviceMultisampleProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT>(
+ inst.functions->vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceMultisamplePropertiesEXT"));
+ auto GetPhysicalDeviceCalibrateableTimeDomains = reinterpret_cast<PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT>(
+ inst.functions->vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceCalibrateableTimeDomainsEXT"));
+ ASSERT_NE(nullptr, EnumeratePhysicalDeviceQueueFamilyPerformanceQueryCounters);
+ ASSERT_NE(nullptr, GetPhysicalDeviceMultisampleProperties);
+ ASSERT_NE(nullptr, GetPhysicalDeviceCalibrateableTimeDomains);
+
+ for (uint32_t dev = 0; dev < expected_device_count; ++dev) {
+ uint32_t extension_count = 0;
+ std::vector<VkExtensionProperties> device_extensions;
+ bool supports_query = false;
+ bool supports_samples = false;
+ bool supports_timestamps = false;
+ ASSERT_EQ(VK_SUCCESS,
+ inst->vkEnumerateDeviceExtensionProperties(physical_devices[dev], nullptr, &extension_count, nullptr));
+ ASSERT_GT(extension_count, 0);
+ device_extensions.resize(extension_count);
+ ASSERT_EQ(VK_SUCCESS, inst->vkEnumerateDeviceExtensionProperties(physical_devices[dev], nullptr, &extension_count,
+ device_extensions.data()));
+ for (uint32_t ext = 0; ext < extension_count; ++ext) {
+ if (string_eq(VK_KHR_PERFORMANCE_QUERY_EXTENSION_NAME, &device_extensions[ext].extensionName[0])) {
+ supports_query = true;
+ }
+ if (string_eq(VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME, &device_extensions[ext].extensionName[0])) {
+ supports_samples = true;
+ }
+ if (string_eq(VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME, &device_extensions[ext].extensionName[0])) {
+ supports_timestamps = true;
+ }
+ }
+
+ // For physical device extensions, they should work for devices that support it and crash for those that don't.
+ if (supports_query) {
+ ASSERT_EQ(VK_SUCCESS, EnumeratePhysicalDeviceQueueFamilyPerformanceQueryCounters(physical_devices[dev], 0, nullptr,
+ nullptr, nullptr));
+ } else {
+ ASSERT_DEATH(
+ EnumeratePhysicalDeviceQueueFamilyPerformanceQueryCounters(physical_devices[dev], 0, nullptr, nullptr, nullptr),
+ "");
+ ASSERT_FALSE(
+ log.find("ICD associated with VkPhysicalDevice does not support "
+ "EnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR"));
+ }
+ if (supports_samples) {
+ GetPhysicalDeviceMultisampleProperties(physical_devices[dev], VK_SAMPLE_COUNT_2_BIT, nullptr);
+ } else {
+ ASSERT_DEATH(GetPhysicalDeviceMultisampleProperties(physical_devices[dev], VK_SAMPLE_COUNT_2_BIT, nullptr), "");
+ ASSERT_FALSE(
+ log.find("ICD associated with VkPhysicalDevice does not support GetPhysicalDeviceMultisamplePropertiesEXT"));
+ }
+ if (supports_timestamps) {
+ ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceCalibrateableTimeDomains(physical_devices[dev], nullptr, nullptr));
+ } else {
+ ASSERT_DEATH(GetPhysicalDeviceCalibrateableTimeDomains(physical_devices[dev], nullptr, nullptr), "");
+ ASSERT_FALSE(
+ log.find("ICD associated with VkPhysicalDevice does not support GetPhysicalDeviceCalibrateableTimeDomainsEXT"));
+ }
+ }
+}
inst->vkEnumeratePhysicalDeviceGroups(inst, &physical_device_group_count, &physical_device_group_properties));
}
-TEST_F(CreateDevice, ExtensionNotPresent) {
+// LX535 / MI-76: Device layers are deprecated.
+// Ensure that no errors occur if a bogus device layer list is passed to vkCreateDevice.
+// https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#extendingvulkan-layers-devicelayerdeprecation
+TEST_F(CreateDevice, LayersNotPresent) {
auto& driver = env->get_test_icd();
MockQueueFamilyProperties family_props{{VK_QUEUE_GRAPHICS_BIT, 1, 0, {1, 1, 1}}, true};
ASSERT_EQ(families, family_props.properties);
DeviceWrapper dev{inst};
- dev.create_info.add_extension("NotPresent").add_device_queue(DeviceQueueCreateInfo{}.add_priority(0.0f));
+ DeviceCreateInfo dev_create_info;
+ dev.create_info.add_layer("NotPresent").add_device_queue(DeviceQueueCreateInfo{}.add_priority(0.0f));
- dev.CheckCreate(phys_dev, VK_ERROR_EXTENSION_NOT_PRESENT);
+ dev.CheckCreate(phys_dev);
}
-// LX535 / MI-76: Device layers are deprecated.
-// Ensure that no errors occur if a bogus device layer list is passed to vkCreateDevice.
-// https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#extendingvulkan-layers-devicelayerdeprecation
-TEST_F(CreateDevice, LayersNotPresent) {
+TEST_F(CreateDevice, ExtensionNotPresent) {
auto& driver = env->get_test_icd();
MockQueueFamilyProperties family_props{{VK_QUEUE_GRAPHICS_BIT, 1, 0, {1, 1, 1}}, true};
ASSERT_EQ(families, family_props.properties);
DeviceWrapper dev{inst};
- DeviceCreateInfo dev_create_info;
- dev.create_info.add_layer("NotPresent").add_device_queue(DeviceQueueCreateInfo{}.add_priority(0.0f));
+ dev.create_info.add_extension("NotPresent").add_device_queue(DeviceQueueCreateInfo{}.add_priority(0.0f));
- dev.CheckCreate(phys_dev);
+ dev.CheckCreate(phys_dev, VK_ERROR_EXTENSION_NOT_PRESENT);
}
TEST(TryLoadWrongBinaries, WrongICD) {