third_party_vulkan-loader/tests/loader_phys_dev_inst_ext_tests.cpp
Charles Giessen 24ce547c83 Update tests function loading implementation
Remove the need for macros and use well crafted helper loading functions which
can figure out the type to convert to based on the type being assigned.
2022-02-15 10:48:53 -07:00

5393 lines
274 KiB
C++

/*
* 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
* deal in the Materials without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Materials, and to permit persons to whom the Materials are
* furnished to do so, subject to the following conditions:
*
* The above copyright notice(s) and this permission notice shall be included in
* all copies or substantial portions of the Materials.
*
* THE MATERIALS ARE 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 MATERIALS OR THE
* USE OR OTHER DEALINGS IN THE MATERIALS.
*
* Author: Charles Giessen <charles@lunarg.com>
* Author: Mark Young <marky@lunarg.com>
*/
#include "test_environment.h"
// These tests are all instance extension tests that touch physical devices. This was
// before the idea that physical device extensions were more appropriately found in the
// list of device extensions. Because of that, all these tests need to support devices
// that don't support the extension and have a fallback path in the loader that needs
// validation.
// Fill in random but valid data into the device properties struct for the current physical device
static void FillInRandomICDInfo(uint32_t& vendor_id, uint32_t& driver_vers) {
vendor_id = VK_MAKE_API_VERSION(0, rand() % 64, rand() % 255, rand() % 255);
driver_vers = VK_MAKE_API_VERSION(0, rand() % 64, rand() % 255, rand() % 255);
}
// Fill in random but valid data into the device properties struct for the current physical device
static void FillInRandomDeviceProps(VkPhysicalDeviceProperties& props, uint32_t api_vers, uint32_t vendor, uint32_t driver_vers) {
props.apiVersion = api_vers;
props.driverVersion = driver_vers;
props.vendorID = vendor;
props.deviceID = (static_cast<uint32_t>(rand()) >> 4) + (static_cast<uint32_t>(rand()) << 2);
props.deviceType = static_cast<VkPhysicalDeviceType>(rand() % 5);
for (uint8_t idx = 0; idx < VK_UUID_SIZE; ++idx) {
props.pipelineCacheUUID[idx] = static_cast<uint8_t>(rand() % 255);
}
}
//
// VK_KHR_get_physical_device_properties2
//
// Test vkGetPhysicalDeviceProperties2KHR where nothing supports it.
TEST(LoaderInstPhysDevExts, PhysDevProps2KHRNoSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.CheckCreate();
auto GetPhysDevProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties2KHR"));
ASSERT_EQ(GetPhysDevProps2, nullptr);
}
// Test vkGetPhysicalDeviceProperties2KHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevProps2KHRNoICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
auto GetPhysDevProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties2KHR"));
ASSERT_EQ(GetPhysDevProps2, nullptr);
}
// Test vkGetPhysicalDeviceProperties2KHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, PhysDevProps2KHRInstanceAndICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
env.get_test_icd(0).physical_devices.push_back({});
FillInRandomDeviceProps(env.get_test_icd(0).physical_devices.back().properties, VK_API_VERSION_1_0, 5, 123);
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
instance.CheckCreate();
auto GetPhysDevProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties2KHR"));
ASSERT_NE(GetPhysDevProps2, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
VkPhysicalDeviceProperties props{};
instance->vkGetPhysicalDeviceProperties(physical_device, &props);
VkPhysicalDeviceProperties2KHR props2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR};
GetPhysDevProps2(physical_device, &props2);
// Both properties should match
ASSERT_EQ(props.apiVersion, props2.properties.apiVersion);
ASSERT_EQ(props.driverVersion, props2.properties.driverVersion);
ASSERT_EQ(props.vendorID, props2.properties.vendorID);
ASSERT_EQ(props.deviceID, props2.properties.deviceID);
ASSERT_EQ(props.deviceType, props2.properties.deviceType);
ASSERT_EQ(0, memcmp(props.pipelineCacheUUID, props2.properties.pipelineCacheUUID, VK_UUID_SIZE));
}
// Test vkGetPhysicalDeviceProperties2 where instance supports, an ICD, and a device under that ICD
// also support, so everything should work and return properly.
TEST(LoaderInstPhysDevExts, PhysDevProps2Simple) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).icd_api_version = VK_API_VERSION_1_1;
env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
env.get_test_icd(0).physical_devices.push_back({});
env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
FillInRandomDeviceProps(env.get_test_icd(0).physical_devices.back().properties, VK_API_VERSION_1_1, 5, 123);
InstWrapper instance(env.vulkan_functions);
instance.create_info.set_api_version(VK_API_VERSION_1_1);
instance.CheckCreate();
auto GetPhysDevProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceProperties2>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties2"));
ASSERT_NE(GetPhysDevProps2, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
VkPhysicalDeviceProperties props{};
instance->vkGetPhysicalDeviceProperties(physical_device, &props);
VkPhysicalDeviceProperties2KHR props2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR};
GetPhysDevProps2(physical_device, &props2);
// Both properties should match
ASSERT_EQ(props.apiVersion, props2.properties.apiVersion);
ASSERT_EQ(props.driverVersion, props2.properties.driverVersion);
ASSERT_EQ(props.vendorID, props2.properties.vendorID);
ASSERT_EQ(props.deviceID, props2.properties.deviceID);
ASSERT_EQ(props.deviceType, props2.properties.deviceType);
ASSERT_EQ(0, memcmp(props.pipelineCacheUUID, props2.properties.pipelineCacheUUID, VK_UUID_SIZE));
}
// Test vkGetPhysicalDeviceProperties2 and vkGetPhysicalDeviceProperties2KHR where ICD is 1.0 and supports
// extension but the instance supports 1.1 and the extension
TEST(LoaderInstPhysDevExts, PhysDevProps2KHRInstanceSupports11) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6, VK_API_VERSION_1_0));
env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
env.get_test_icd(0).physical_devices.push_back({});
env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
FillInRandomDeviceProps(env.get_test_icd(0).physical_devices.back().properties, VK_API_VERSION_1_0, 5, 123);
InstWrapper instance(env.vulkan_functions);
instance.create_info.set_api_version(VK_API_VERSION_1_1);
instance.create_info.add_extensions(
{VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_EXTENSION_NAME});
instance.CheckCreate();
DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
CreateDebugUtilsMessenger(log);
auto GetPhysDevProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceProperties2>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties2"));
ASSERT_NE(GetPhysDevProps2, nullptr);
auto GetPhysDevProps2KHR = reinterpret_cast<PFN_vkGetPhysicalDeviceProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties2KHR"));
ASSERT_NE(GetPhysDevProps2KHR, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
VkPhysicalDeviceProperties props{};
instance->vkGetPhysicalDeviceProperties(physical_device, &props);
VkPhysicalDeviceProperties2 props2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2};
GetPhysDevProps2(physical_device, &props2);
// Both VkPhysicalDeviceProperties2 properties should match
ASSERT_EQ(props.apiVersion, props2.properties.apiVersion);
ASSERT_EQ(props.driverVersion, props2.properties.driverVersion);
ASSERT_EQ(props.vendorID, props2.properties.vendorID);
ASSERT_EQ(props.deviceID, props2.properties.deviceID);
ASSERT_EQ(props.deviceType, props2.properties.deviceType);
ASSERT_EQ(0, memcmp(props.pipelineCacheUUID, props2.properties.pipelineCacheUUID, VK_UUID_SIZE));
VkPhysicalDeviceProperties2KHR props2KHR{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR};
GetPhysDevProps2(physical_device, &props2KHR);
// Both VkPhysicalDeviceProperties2KHR properties should match
ASSERT_EQ(props.apiVersion, props2KHR.properties.apiVersion);
ASSERT_EQ(props.driverVersion, props2KHR.properties.driverVersion);
ASSERT_EQ(props.vendorID, props2KHR.properties.vendorID);
ASSERT_EQ(props.deviceID, props2KHR.properties.deviceID);
ASSERT_EQ(props.deviceType, props2KHR.properties.deviceType);
ASSERT_EQ(0, memcmp(props.pipelineCacheUUID, props2KHR.properties.pipelineCacheUUID, VK_UUID_SIZE));
ASSERT_FALSE(log.find("Emulating call in ICD"));
}
// Test vkGetPhysicalDeviceProperties2 where instance supports it with some ICDs that both support
// and don't support it:
// ICD 0 supports
// Physical device 0 does not
// Physical device 1 does
// Physical device 2 does not
// ICD 1 doesn't support
// Physical device 3 does not
// ICD 2 supports
// Physical device 4 does not
// Physical device 5 does not
// ICD 3 supports
// Physical device 6 does
TEST(LoaderInstPhysDevExts, PhysDevProps2Mixed) {
FrameworkEnvironment env{};
const uint32_t max_icd_count = 4;
const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
const uint32_t max_phys_devs = 7;
for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
auto& cur_icd = env.get_test_icd(icd);
// ICD 1 should not have 1.1
if (icd != 1) {
cur_icd.icd_api_version = VK_API_VERSION_1_1;
cur_icd.add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
} else {
cur_icd.icd_api_version = VK_API_VERSION_1_0;
}
uint32_t rand_vendor_id;
uint32_t rand_driver_vers;
FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
uint32_t device_version = VK_API_VERSION_1_0;
cur_icd.physical_devices.push_back({});
auto& cur_dev = cur_icd.physical_devices.back();
// 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
if ((icd == 0 && dev == 1) || icd == 3) {
cur_dev.extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
device_version = VK_API_VERSION_1_1;
}
FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
}
}
InstWrapper instance(env.vulkan_functions);
instance.create_info.set_api_version(VK_API_VERSION_1_1);
instance.CheckCreate();
auto GetPhysDevProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceProperties2>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties2"));
ASSERT_NE(GetPhysDevProps2, nullptr);
uint32_t device_count = max_phys_devs;
std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
ASSERT_EQ(device_count, max_phys_devs);
for (uint32_t dev = 0; dev < device_count; ++dev) {
VkPhysicalDeviceProperties props{};
instance->vkGetPhysicalDeviceProperties(physical_devices[dev], &props);
VkPhysicalDeviceProperties2KHR props2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2};
GetPhysDevProps2(physical_devices[dev], &props2);
// Both properties should match
ASSERT_EQ(props.apiVersion, props2.properties.apiVersion);
ASSERT_EQ(props.driverVersion, props2.properties.driverVersion);
ASSERT_EQ(props.vendorID, props2.properties.vendorID);
ASSERT_EQ(props.deviceID, props2.properties.deviceID);
ASSERT_EQ(props.deviceType, props2.properties.deviceType);
ASSERT_EQ(0, memcmp(props.pipelineCacheUUID, props2.properties.pipelineCacheUUID, VK_UUID_SIZE));
}
}
// Fill in random but valid data into the features struct for the current physical device
static void FillInRandomFeatures(VkPhysicalDeviceFeatures& feats) {
feats.robustBufferAccess = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.fullDrawIndexUint32 = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.imageCubeArray = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.independentBlend = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.geometryShader = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.tessellationShader = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.sampleRateShading = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.dualSrcBlend = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.logicOp = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.multiDrawIndirect = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.drawIndirectFirstInstance = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.depthClamp = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.depthBiasClamp = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.fillModeNonSolid = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.depthBounds = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.wideLines = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.largePoints = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.alphaToOne = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.multiViewport = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.samplerAnisotropy = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.textureCompressionETC2 = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.textureCompressionASTC_LDR = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.textureCompressionBC = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.occlusionQueryPrecise = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.pipelineStatisticsQuery = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.vertexPipelineStoresAndAtomics = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.fragmentStoresAndAtomics = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.shaderTessellationAndGeometryPointSize = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.shaderImageGatherExtended = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.shaderStorageImageExtendedFormats = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.shaderStorageImageMultisample = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.shaderStorageImageReadWithoutFormat = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.shaderStorageImageWriteWithoutFormat = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.shaderUniformBufferArrayDynamicIndexing = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.shaderSampledImageArrayDynamicIndexing = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.shaderStorageBufferArrayDynamicIndexing = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.shaderStorageImageArrayDynamicIndexing = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.shaderClipDistance = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.shaderCullDistance = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.shaderFloat64 = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.shaderInt64 = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.shaderInt16 = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.shaderResourceResidency = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.shaderResourceMinLod = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.sparseBinding = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.sparseResidencyBuffer = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.sparseResidencyImage2D = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.sparseResidencyImage3D = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.sparseResidency2Samples = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.sparseResidency4Samples = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.sparseResidency8Samples = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.sparseResidency16Samples = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.sparseResidencyAliased = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.variableMultisampleRate = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
feats.inheritedQueries = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
}
// Compare the contents of the feature structs
static bool CompareFeatures(const VkPhysicalDeviceFeatures& feats1, const VkPhysicalDeviceFeatures2& feats2) {
return feats1.robustBufferAccess == feats2.features.robustBufferAccess &&
feats1.fullDrawIndexUint32 == feats2.features.fullDrawIndexUint32 &&
feats1.imageCubeArray == feats2.features.imageCubeArray && feats1.independentBlend == feats2.features.independentBlend &&
feats1.geometryShader == feats2.features.geometryShader &&
feats1.tessellationShader == feats2.features.tessellationShader &&
feats1.sampleRateShading == feats2.features.sampleRateShading && feats1.dualSrcBlend == feats2.features.dualSrcBlend &&
feats1.logicOp == feats2.features.logicOp && feats1.multiDrawIndirect == feats2.features.multiDrawIndirect &&
feats1.drawIndirectFirstInstance == feats2.features.drawIndirectFirstInstance &&
feats1.depthClamp == feats2.features.depthClamp && feats1.depthBiasClamp == feats2.features.depthBiasClamp &&
feats1.fillModeNonSolid == feats2.features.fillModeNonSolid && feats1.depthBounds == feats2.features.depthBounds &&
feats1.wideLines == feats2.features.wideLines && feats1.largePoints == feats2.features.largePoints &&
feats1.alphaToOne == feats2.features.alphaToOne && feats1.multiViewport == feats2.features.multiViewport &&
feats1.samplerAnisotropy == feats2.features.samplerAnisotropy &&
feats1.textureCompressionETC2 == feats2.features.textureCompressionETC2 &&
feats1.textureCompressionASTC_LDR == feats2.features.textureCompressionASTC_LDR &&
feats1.textureCompressionBC == feats2.features.textureCompressionBC &&
feats1.occlusionQueryPrecise == feats2.features.occlusionQueryPrecise &&
feats1.pipelineStatisticsQuery == feats2.features.pipelineStatisticsQuery &&
feats1.vertexPipelineStoresAndAtomics == feats2.features.vertexPipelineStoresAndAtomics &&
feats1.fragmentStoresAndAtomics == feats2.features.fragmentStoresAndAtomics &&
feats1.shaderTessellationAndGeometryPointSize == feats2.features.shaderTessellationAndGeometryPointSize &&
feats1.shaderImageGatherExtended == feats2.features.shaderImageGatherExtended &&
feats1.shaderStorageImageExtendedFormats == feats2.features.shaderStorageImageExtendedFormats &&
feats1.shaderStorageImageMultisample == feats2.features.shaderStorageImageMultisample &&
feats1.shaderStorageImageReadWithoutFormat == feats2.features.shaderStorageImageReadWithoutFormat &&
feats1.shaderStorageImageWriteWithoutFormat == feats2.features.shaderStorageImageWriteWithoutFormat &&
feats1.shaderUniformBufferArrayDynamicIndexing == feats2.features.shaderUniformBufferArrayDynamicIndexing &&
feats1.shaderSampledImageArrayDynamicIndexing == feats2.features.shaderSampledImageArrayDynamicIndexing &&
feats1.shaderStorageBufferArrayDynamicIndexing == feats2.features.shaderStorageBufferArrayDynamicIndexing &&
feats1.shaderStorageImageArrayDynamicIndexing == feats2.features.shaderStorageImageArrayDynamicIndexing &&
feats1.shaderClipDistance == feats2.features.shaderClipDistance &&
feats1.shaderCullDistance == feats2.features.shaderCullDistance &&
feats1.shaderFloat64 == feats2.features.shaderFloat64 && feats1.shaderInt64 == feats2.features.shaderInt64 &&
feats1.shaderInt16 == feats2.features.shaderInt16 &&
feats1.shaderResourceResidency == feats2.features.shaderResourceResidency &&
feats1.shaderResourceMinLod == feats2.features.shaderResourceMinLod &&
feats1.sparseBinding == feats2.features.sparseBinding &&
feats1.sparseResidencyBuffer == feats2.features.sparseResidencyBuffer &&
feats1.sparseResidencyImage2D == feats2.features.sparseResidencyImage2D &&
feats1.sparseResidencyImage3D == feats2.features.sparseResidencyImage3D &&
feats1.sparseResidency2Samples == feats2.features.sparseResidency2Samples &&
feats1.sparseResidency4Samples == feats2.features.sparseResidency4Samples &&
feats1.sparseResidency8Samples == feats2.features.sparseResidency8Samples &&
feats1.sparseResidency16Samples == feats2.features.sparseResidency16Samples &&
feats1.sparseResidencyAliased == feats2.features.sparseResidencyAliased &&
feats1.variableMultisampleRate == feats2.features.variableMultisampleRate &&
feats1.inheritedQueries == feats2.features.inheritedQueries;
}
// Test vkGetPhysicalDeviceFeatures2KHR where nothing supports it.
TEST(LoaderInstPhysDevExts, PhysDevFeats2KHRNoSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.CheckCreate();
auto GetPhysDevFeats2 = reinterpret_cast<PFN_vkGetPhysicalDeviceFeatures2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFeatures2KHR"));
ASSERT_EQ(GetPhysDevFeats2, nullptr);
}
// Test vkGetPhysicalDeviceFeatures2KHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevFeatsKHRNoICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
auto GetPhysDevFeats2 = reinterpret_cast<PFN_vkGetPhysicalDeviceFeatures2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFeatures2KHR"));
ASSERT_EQ(GetPhysDevFeats2, nullptr);
}
// Test vkGetPhysicalDeviceFeatures2KHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, PhysDevFeats2KHRInstanceAndICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
env.get_test_icd(0).physical_devices.push_back({});
FillInRandomFeatures(env.get_test_icd(0).physical_devices.back().features);
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
instance.CheckCreate();
auto GetPhysDevFeats2 = reinterpret_cast<PFN_vkGetPhysicalDeviceFeatures2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFeatures2KHR"));
ASSERT_NE(GetPhysDevFeats2, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
VkPhysicalDeviceFeatures feats{};
instance->vkGetPhysicalDeviceFeatures(physical_device, &feats);
VkPhysicalDeviceFeatures2 feats2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR};
GetPhysDevFeats2(physical_device, &feats2);
ASSERT_TRUE(CompareFeatures(feats, feats2));
}
// Test vkGetPhysicalDeviceFeatures2 where instance supports, an ICD, and a device under that ICD
// also support, so everything should work and return properly.
TEST(LoaderInstPhysDevExts, PhysDevFeats2Simple) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).icd_api_version = VK_API_VERSION_1_1;
env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
env.get_test_icd(0).physical_devices.push_back({});
env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
FillInRandomFeatures(env.get_test_icd(0).physical_devices.back().features);
InstWrapper instance(env.vulkan_functions);
instance.create_info.set_api_version(VK_API_VERSION_1_1);
instance.CheckCreate();
auto GetPhysDevFeats2 = reinterpret_cast<PFN_vkGetPhysicalDeviceFeatures2>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFeatures2"));
ASSERT_NE(GetPhysDevFeats2, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
VkPhysicalDeviceFeatures feats{};
instance->vkGetPhysicalDeviceFeatures(physical_device, &feats);
VkPhysicalDeviceFeatures2 feats2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
GetPhysDevFeats2(physical_device, &feats2);
ASSERT_TRUE(CompareFeatures(feats, feats2));
}
// Test vkGetPhysicalDeviceFeatures2 and vkGetPhysicalDeviceFeatures2KHR where ICD is 1.0 and supports
// extension but the instance supports 1.1 and the extension
TEST(LoaderInstPhysDevExts, PhysDevFeats2KHRInstanceSupports11) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6, VK_API_VERSION_1_0));
env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
env.get_test_icd(0).physical_devices.push_back({});
env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
FillInRandomFeatures(env.get_test_icd(0).physical_devices.back().features);
InstWrapper instance(env.vulkan_functions);
instance.create_info.set_api_version(VK_API_VERSION_1_1);
instance.create_info.add_extensions(
{VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_EXTENSION_NAME});
instance.CheckCreate();
DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
CreateDebugUtilsMessenger(log);
auto GetPhysDevFeats2KHR = reinterpret_cast<PFN_vkGetPhysicalDeviceFeatures2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFeatures2KHR"));
ASSERT_NE(GetPhysDevFeats2KHR, nullptr);
auto GetPhysDevFeats2 = reinterpret_cast<PFN_vkGetPhysicalDeviceFeatures2>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFeatures2"));
ASSERT_NE(GetPhysDevFeats2, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
VkPhysicalDeviceFeatures feats{};
instance->vkGetPhysicalDeviceFeatures(physical_device, &feats);
VkPhysicalDeviceFeatures2KHR feats2KHR{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR};
GetPhysDevFeats2KHR(physical_device, &feats2KHR);
ASSERT_TRUE(CompareFeatures(feats, feats2KHR));
VkPhysicalDeviceFeatures2 feats2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
GetPhysDevFeats2(physical_device, &feats2);
ASSERT_TRUE(CompareFeatures(feats, feats2));
ASSERT_FALSE(log.find("Emulating call in ICD"));
}
// Test vkGetPhysicalDeviceFeatures2 where instance supports it with some ICDs that both support
// and don't support it:
// ICD 0 supports
// Physical device 0 does not
// Physical device 1 does
// Physical device 2 does not
// ICD 1 doesn't support
// Physical device 3 does not
// ICD 2 supports
// Physical device 4 does not
// Physical device 5 does not
// ICD 3 supports
// Physical device 6 does
TEST(LoaderInstPhysDevExts, PhysDevFeatsMixed) {
FrameworkEnvironment env{};
const uint32_t max_icd_count = 4;
const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
const uint32_t max_phys_devs = 7;
for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
auto& cur_icd = env.get_test_icd(icd);
// ICD 1 should not have 1.1
if (icd != 1) {
cur_icd.icd_api_version = VK_API_VERSION_1_1;
cur_icd.add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
} else {
cur_icd.icd_api_version = VK_API_VERSION_1_0;
}
uint32_t rand_vendor_id;
uint32_t rand_driver_vers;
FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
uint32_t device_version = VK_API_VERSION_1_0;
cur_icd.physical_devices.push_back({});
auto& cur_dev = cur_icd.physical_devices.back();
// 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
if ((icd == 0 && dev == 1) || icd == 3) {
cur_dev.extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
device_version = VK_API_VERSION_1_1;
}
// Still set physical device properties (so we can determine if device is correct API version)
FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
FillInRandomFeatures(cur_dev.features);
}
}
InstWrapper instance(env.vulkan_functions);
instance.create_info.set_api_version(VK_API_VERSION_1_1);
instance.CheckCreate();
auto GetPhysDevFeats2 = reinterpret_cast<PFN_vkGetPhysicalDeviceFeatures2>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFeatures2"));
ASSERT_NE(GetPhysDevFeats2, nullptr);
uint32_t device_count = max_phys_devs;
std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
ASSERT_EQ(device_count, max_phys_devs);
for (uint32_t dev = 0; dev < device_count; ++dev) {
VkPhysicalDeviceFeatures feats{};
instance->vkGetPhysicalDeviceFeatures(physical_devices[dev], &feats);
VkPhysicalDeviceFeatures2 feats2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
GetPhysDevFeats2(physical_devices[dev], &feats2);
ASSERT_TRUE(CompareFeatures(feats, feats2));
}
}
// Fill in random but valid data into the format properties struct for the current physical device
static void FillInRandomFormatProperties(std::vector<VkFormatProperties>& props) {
props.resize(5);
for (uint8_t form = 0; form < 5; ++form) {
props[form].bufferFeatures = static_cast<VkFormatFeatureFlags>(rand());
props[form].linearTilingFeatures = static_cast<VkFormatFeatureFlags>(rand());
props[form].optimalTilingFeatures = static_cast<VkFormatFeatureFlags>(rand());
}
}
// Test vkGetPhysicalDeviceFormatProperties2KHR where nothing supports it.
TEST(LoaderInstPhysDevExts, PhysDevFormatProps2KHRNoSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.CheckCreate();
auto GetPhysDevFormatProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceFormatProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFormatProperties2KHR"));
ASSERT_EQ(GetPhysDevFormatProps2, nullptr);
}
// Test vkGetPhysicalDeviceFormatProperties2KHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevFormatPropsKHRNoICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
auto GetPhysDevFormatProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceFormatProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFormatProperties2KHR"));
ASSERT_EQ(GetPhysDevFormatProps2, nullptr);
}
// Test vkGetPhysicalDeviceFormatProperties2KHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, PhysDevFormatProps2KHRInstanceAndICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
env.get_test_icd(0).physical_devices.push_back({});
FillInRandomFormatProperties(env.get_test_icd(0).physical_devices.back().format_properties);
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extensions(
{VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_EXTENSION_NAME});
instance.CheckCreate();
DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
CreateDebugUtilsMessenger(log);
auto GetPhysDevFormatProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceFormatProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFormatProperties2KHR"));
ASSERT_NE(GetPhysDevFormatProps2, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
VkFormatProperties props{};
instance->vkGetPhysicalDeviceFormatProperties(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, &props);
VkFormatProperties2 props2{VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2};
GetPhysDevFormatProps2(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, &props2);
ASSERT_EQ(props.bufferFeatures, props2.formatProperties.bufferFeatures);
ASSERT_EQ(props.linearTilingFeatures, props2.formatProperties.linearTilingFeatures);
ASSERT_EQ(props.optimalTilingFeatures, props2.formatProperties.optimalTilingFeatures);
}
// Test vkGetPhysicalDeviceFormatProperties2 where instance supports, an ICD, and a device under that ICD
// also support, so everything should work and return properly.
TEST(LoaderInstPhysDevExts, PhysDevFormatProps2Simple) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).icd_api_version = VK_API_VERSION_1_1;
env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
env.get_test_icd(0).physical_devices.push_back({});
env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
FillInRandomFormatProperties(env.get_test_icd(0).physical_devices.back().format_properties);
InstWrapper instance(env.vulkan_functions);
instance.create_info.set_api_version(VK_API_VERSION_1_1);
instance.CheckCreate();
auto GetPhysDevFormatProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceFormatProperties2>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFormatProperties2"));
ASSERT_NE(GetPhysDevFormatProps2, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
VkFormatProperties props{};
instance->vkGetPhysicalDeviceFormatProperties(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, &props);
VkFormatProperties2 props2{VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2};
GetPhysDevFormatProps2(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, &props2);
ASSERT_EQ(props.bufferFeatures, props2.formatProperties.bufferFeatures);
ASSERT_EQ(props.linearTilingFeatures, props2.formatProperties.linearTilingFeatures);
ASSERT_EQ(props.optimalTilingFeatures, props2.formatProperties.optimalTilingFeatures);
}
// Test vkGetPhysicalDeviceFormatProperties2 and vkGetPhysicalDeviceFormatProperties2KHR where ICD is 1.0 and supports
// extension but the instance supports 1.1 and the extension
TEST(LoaderInstPhysDevExts, PhysDevFormatProps2KHRInstanceSupports11) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
env.get_test_icd(0).physical_devices.push_back({});
env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
FillInRandomFormatProperties(env.get_test_icd(0).physical_devices.back().format_properties);
InstWrapper instance(env.vulkan_functions);
instance.create_info.set_api_version(VK_API_VERSION_1_1);
instance.create_info.add_extensions(
{VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_EXTENSION_NAME});
instance.CheckCreate();
DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
CreateDebugUtilsMessenger(log);
auto GetPhysDevFormatProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceFormatProperties2>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFormatProperties2"));
ASSERT_NE(GetPhysDevFormatProps2, nullptr);
auto GetPhysDevFormatProps2KHR = reinterpret_cast<PFN_vkGetPhysicalDeviceFormatProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFormatProperties2KHR"));
ASSERT_NE(GetPhysDevFormatProps2KHR, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
VkFormatProperties props{};
instance->vkGetPhysicalDeviceFormatProperties(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, &props);
VkFormatProperties2 props2{VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2};
GetPhysDevFormatProps2(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, &props2);
ASSERT_EQ(props.bufferFeatures, props2.formatProperties.bufferFeatures);
ASSERT_EQ(props.linearTilingFeatures, props2.formatProperties.linearTilingFeatures);
ASSERT_EQ(props.optimalTilingFeatures, props2.formatProperties.optimalTilingFeatures);
VkFormatProperties2KHR props2KHR{VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2};
GetPhysDevFormatProps2KHR(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, &props2KHR);
ASSERT_EQ(props.bufferFeatures, props2KHR.formatProperties.bufferFeatures);
ASSERT_EQ(props.linearTilingFeatures, props2KHR.formatProperties.linearTilingFeatures);
ASSERT_EQ(props.optimalTilingFeatures, props2KHR.formatProperties.optimalTilingFeatures);
ASSERT_FALSE(log.find("Emulating call in ICD"));
}
// Test vkGetPhysicalDeviceFormatProperties2 where instance supports it with some ICDs that both support
// and don't support it:
// ICD 0 supports
// Physical device 0 does not
// Physical device 1 does
// Physical device 2 does not
// ICD 1 doesn't support
// Physical device 3 does not
// ICD 2 supports
// Physical device 4 does not
// Physical device 5 does not
// ICD 3 supports
// Physical device 6 does
TEST(LoaderInstPhysDevExts, PhysDevFormatPropsMixed) {
FrameworkEnvironment env{};
const uint32_t max_icd_count = 4;
const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
const uint32_t max_phys_devs = 7;
for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
auto& cur_icd = env.get_test_icd(icd);
// ICD 1 should not have 1.1
if (icd != 1) {
cur_icd.icd_api_version = VK_API_VERSION_1_1;
cur_icd.add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
} else {
cur_icd.icd_api_version = VK_API_VERSION_1_0;
}
uint32_t rand_vendor_id;
uint32_t rand_driver_vers;
FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
uint32_t device_version = VK_API_VERSION_1_0;
cur_icd.physical_devices.push_back({});
auto& cur_dev = cur_icd.physical_devices.back();
// 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
if ((icd == 0 && dev == 1) || icd == 3) {
cur_dev.extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
device_version = VK_API_VERSION_1_1;
}
// Still set physical device properties (so we can determine if device is correct API version)
FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
FillInRandomFormatProperties(cur_dev.format_properties);
}
}
InstWrapper instance(env.vulkan_functions);
instance.create_info.set_api_version(VK_API_VERSION_1_1);
instance.CheckCreate();
auto GetPhysDevFormatProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceFormatProperties2>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFormatProperties2"));
ASSERT_NE(GetPhysDevFormatProps2, nullptr);
uint32_t device_count = max_phys_devs;
std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
ASSERT_EQ(device_count, max_phys_devs);
for (uint32_t dev = 0; dev < device_count; ++dev) {
VkFormat format = static_cast<VkFormat>((dev + 1) % 5);
VkFormatProperties props{};
instance->vkGetPhysicalDeviceFormatProperties(physical_devices[dev], format, &props);
VkFormatProperties2 props2{VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2};
GetPhysDevFormatProps2(physical_devices[dev], format, &props2);
ASSERT_EQ(props.bufferFeatures, props2.formatProperties.bufferFeatures);
ASSERT_EQ(props.linearTilingFeatures, props2.formatProperties.linearTilingFeatures);
ASSERT_EQ(props.optimalTilingFeatures, props2.formatProperties.optimalTilingFeatures);
}
}
// Fill in random but valid data into the image format data struct for the current physical device
static void FillInRandomImageFormatData(VkImageFormatProperties& props) {
props.maxExtent = {static_cast<uint32_t>(rand() % 512), static_cast<uint32_t>(rand() % 512),
static_cast<uint32_t>(rand() % 512)};
props.maxMipLevels = static_cast<uint32_t>(1 << (rand() % 16));
props.maxArrayLayers = static_cast<uint32_t>(1 << (rand() % 16));
props.sampleCounts = static_cast<VkSampleCountFlags>(1 << (rand() % 7));
props.maxResourceSize = static_cast<uint64_t>(rand());
}
// Test vkGetPhysicalDeviceImageFormatProperties2KHR where nothing supports it.
TEST(LoaderInstPhysDevExts, PhysDevImageFormatProps2KHRNoSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.CheckCreate();
auto GetPhysDevImageFormatProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceImageFormatProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceImageFormatProperties2KHR"));
ASSERT_EQ(GetPhysDevImageFormatProps2, nullptr);
}
// Test vkGetPhysicalDeviceImageFormatProperties2KHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevImageFormatPropsKHRNoICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
auto GetPhysDevImageFormatProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceImageFormatProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceImageFormatProperties2KHR"));
ASSERT_EQ(GetPhysDevImageFormatProps2, nullptr);
}
// Test vkGetPhysicalDeviceImageFormatProperties2KHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, PhysDevImageFormatProps2KHRInstanceAndICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
env.get_test_icd(0).physical_devices.push_back({});
FillInRandomImageFormatData(env.get_test_icd(0).physical_devices.back().image_format_properties);
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
instance.CheckCreate();
auto GetPhysDevImageFormatProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceImageFormatProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceImageFormatProperties2KHR"));
ASSERT_NE(GetPhysDevImageFormatProps2, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
VkImageFormatProperties props{};
ASSERT_EQ(VK_SUCCESS,
instance->vkGetPhysicalDeviceImageFormatProperties(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, VK_IMAGE_TYPE_2D,
VK_IMAGE_TILING_OPTIMAL, 0, 0, &props));
VkPhysicalDeviceImageFormatInfo2 info2{
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, // sType
nullptr, // pNext
VK_FORMAT_R4G4_UNORM_PACK8, // format
VK_IMAGE_TYPE_2D, // type
VK_IMAGE_TILING_OPTIMAL, // tiling
0, // usage
0, // flags
};
VkImageFormatProperties2 props2{VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2};
ASSERT_EQ(VK_SUCCESS, GetPhysDevImageFormatProps2(physical_device, &info2, &props2));
ASSERT_EQ(props.maxExtent.width, props2.imageFormatProperties.maxExtent.width);
ASSERT_EQ(props.maxExtent.height, props2.imageFormatProperties.maxExtent.height);
ASSERT_EQ(props.maxExtent.depth, props2.imageFormatProperties.maxExtent.depth);
ASSERT_EQ(props.maxMipLevels, props2.imageFormatProperties.maxMipLevels);
ASSERT_EQ(props.maxArrayLayers, props2.imageFormatProperties.maxArrayLayers);
ASSERT_EQ(props.sampleCounts, props2.imageFormatProperties.sampleCounts);
ASSERT_EQ(props.maxResourceSize, props2.imageFormatProperties.maxResourceSize);
}
// Test vkGetPhysicalDeviceImageFormatProperties2 where instance supports, an ICD, and a device under that ICD
// also support, so everything should work and return properly.
TEST(LoaderInstPhysDevExts, PhysDevImageFormatProps2Simple) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).icd_api_version = VK_API_VERSION_1_1;
env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
env.get_test_icd(0).physical_devices.push_back({});
env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
FillInRandomImageFormatData(env.get_test_icd(0).physical_devices.back().image_format_properties);
InstWrapper instance(env.vulkan_functions);
instance.create_info.set_api_version(VK_API_VERSION_1_1);
instance.CheckCreate();
auto GetPhysDevImageFormatProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceImageFormatProperties2>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceImageFormatProperties2"));
ASSERT_NE(GetPhysDevImageFormatProps2, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
VkImageFormatProperties props{};
ASSERT_EQ(VK_SUCCESS,
instance->vkGetPhysicalDeviceImageFormatProperties(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, VK_IMAGE_TYPE_2D,
VK_IMAGE_TILING_OPTIMAL, 0, 0, &props));
VkPhysicalDeviceImageFormatInfo2 info2{
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, // sType
nullptr, // pNext
VK_FORMAT_R4G4_UNORM_PACK8, // format
VK_IMAGE_TYPE_2D, // type
VK_IMAGE_TILING_OPTIMAL, // tiling
0, // usage
0, // flags
};
VkImageFormatProperties2 props2{VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2};
ASSERT_EQ(VK_SUCCESS, GetPhysDevImageFormatProps2(physical_device, &info2, &props2));
ASSERT_EQ(props.maxExtent.width, props2.imageFormatProperties.maxExtent.width);
ASSERT_EQ(props.maxExtent.height, props2.imageFormatProperties.maxExtent.height);
ASSERT_EQ(props.maxExtent.depth, props2.imageFormatProperties.maxExtent.depth);
ASSERT_EQ(props.maxMipLevels, props2.imageFormatProperties.maxMipLevels);
ASSERT_EQ(props.maxArrayLayers, props2.imageFormatProperties.maxArrayLayers);
ASSERT_EQ(props.sampleCounts, props2.imageFormatProperties.sampleCounts);
ASSERT_EQ(props.maxResourceSize, props2.imageFormatProperties.maxResourceSize);
}
// Test vkGetPhysicalDeviceImageFormatProperties2 and vkGetPhysicalDeviceImageFormatProperties2KHR where instance supports, an ICD,
// and a device under that ICD also support, so everything should work and return properly.
TEST(LoaderInstPhysDevExts, PhysDevImageFormatProps2KHRInstanceSupports11) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
env.get_test_icd(0).physical_devices.push_back({});
env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
FillInRandomImageFormatData(env.get_test_icd(0).physical_devices.back().image_format_properties);
InstWrapper instance(env.vulkan_functions);
instance.create_info.set_api_version(VK_API_VERSION_1_1);
instance.create_info.add_extensions(
{VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_EXTENSION_NAME});
instance.CheckCreate();
DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
CreateDebugUtilsMessenger(log);
auto GetPhysDevImageFormatProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceImageFormatProperties2>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceImageFormatProperties2"));
ASSERT_NE(GetPhysDevImageFormatProps2, nullptr);
auto GetPhysDevImageFormatProps2KHR = reinterpret_cast<PFN_vkGetPhysicalDeviceImageFormatProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceImageFormatProperties2KHR"));
ASSERT_NE(GetPhysDevImageFormatProps2KHR, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
VkImageFormatProperties props{};
ASSERT_EQ(VK_SUCCESS,
instance->vkGetPhysicalDeviceImageFormatProperties(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, VK_IMAGE_TYPE_2D,
VK_IMAGE_TILING_OPTIMAL, 0, 0, &props));
VkPhysicalDeviceImageFormatInfo2 info2{
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, // sType
nullptr, // pNext
VK_FORMAT_R4G4_UNORM_PACK8, // format
VK_IMAGE_TYPE_2D, // type
VK_IMAGE_TILING_OPTIMAL, // tiling
0, // usage
0, // flags
};
VkImageFormatProperties2 props2{VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2};
ASSERT_EQ(VK_SUCCESS, GetPhysDevImageFormatProps2(physical_device, &info2, &props2));
ASSERT_EQ(props.maxExtent.width, props2.imageFormatProperties.maxExtent.width);
ASSERT_EQ(props.maxExtent.height, props2.imageFormatProperties.maxExtent.height);
ASSERT_EQ(props.maxExtent.depth, props2.imageFormatProperties.maxExtent.depth);
ASSERT_EQ(props.maxMipLevels, props2.imageFormatProperties.maxMipLevels);
ASSERT_EQ(props.maxArrayLayers, props2.imageFormatProperties.maxArrayLayers);
ASSERT_EQ(props.sampleCounts, props2.imageFormatProperties.sampleCounts);
ASSERT_EQ(props.maxResourceSize, props2.imageFormatProperties.maxResourceSize);
VkImageFormatProperties2KHR props2KHR{VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR};
ASSERT_EQ(VK_SUCCESS, GetPhysDevImageFormatProps2KHR(physical_device, &info2, &props2KHR));
ASSERT_EQ(props.maxExtent.width, props2KHR.imageFormatProperties.maxExtent.width);
ASSERT_EQ(props.maxExtent.height, props2KHR.imageFormatProperties.maxExtent.height);
ASSERT_EQ(props.maxExtent.depth, props2KHR.imageFormatProperties.maxExtent.depth);
ASSERT_EQ(props.maxMipLevels, props2KHR.imageFormatProperties.maxMipLevels);
ASSERT_EQ(props.maxArrayLayers, props2KHR.imageFormatProperties.maxArrayLayers);
ASSERT_EQ(props.sampleCounts, props2KHR.imageFormatProperties.sampleCounts);
ASSERT_EQ(props.maxResourceSize, props2KHR.imageFormatProperties.maxResourceSize);
ASSERT_FALSE(log.find("Emulating call in ICD"));
}
// Test vkGetPhysicalDeviceImageFormatProperties2 where instance supports it with some ICDs that both support
// and don't support it:
// ICD 0 supports
// Physical device 0 does not
// Physical device 1 does
// Physical device 2 does not
// ICD 1 doesn't support
// Physical device 3 does not
// ICD 2 supports
// Physical device 4 does not
// Physical device 5 does not
// ICD 3 supports
// Physical device 6 does
TEST(LoaderInstPhysDevExts, PhysDevImageFormatPropsMixed) {
FrameworkEnvironment env{};
const uint32_t max_icd_count = 4;
const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
const uint32_t max_phys_devs = 7;
for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
auto& cur_icd = env.get_test_icd(icd);
// ICD 1 should not have 1.1
if (icd != 1) {
cur_icd.icd_api_version = VK_API_VERSION_1_1;
cur_icd.add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
} else {
cur_icd.icd_api_version = VK_API_VERSION_1_0;
}
uint32_t rand_vendor_id;
uint32_t rand_driver_vers;
FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
uint32_t device_version = VK_API_VERSION_1_0;
cur_icd.physical_devices.push_back({});
auto& cur_dev = cur_icd.physical_devices.back();
// 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
if ((icd == 0 && dev == 1) || icd == 3) {
cur_dev.extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
device_version = VK_API_VERSION_1_1;
}
// Still set physical device properties (so we can determine if device is correct API version)
FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
FillInRandomImageFormatData(cur_dev.image_format_properties);
}
}
InstWrapper instance(env.vulkan_functions);
instance.create_info.set_api_version(VK_API_VERSION_1_1);
instance.CheckCreate();
auto GetPhysDevImageFormatProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceImageFormatProperties2>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceImageFormatProperties2"));
ASSERT_NE(GetPhysDevImageFormatProps2, nullptr);
uint32_t device_count = max_phys_devs;
std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
ASSERT_EQ(device_count, max_phys_devs);
for (uint32_t dev = 0; dev < device_count; ++dev) {
VkImageFormatProperties props{};
ASSERT_EQ(VK_SUCCESS,
instance->vkGetPhysicalDeviceImageFormatProperties(physical_devices[dev], VK_FORMAT_R4G4_UNORM_PACK8,
VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, 0, 0, &props));
VkPhysicalDeviceImageFormatInfo2 info2{
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, // sType
nullptr, // pNext
VK_FORMAT_R4G4_UNORM_PACK8, // format
VK_IMAGE_TYPE_2D, // type
VK_IMAGE_TILING_OPTIMAL, // tiling
0, // usage
0, // flags
};
VkImageFormatProperties2 props2{VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2};
ASSERT_EQ(VK_SUCCESS, GetPhysDevImageFormatProps2(physical_devices[dev], &info2, &props2));
ASSERT_EQ(props.maxExtent.width, props2.imageFormatProperties.maxExtent.width);
ASSERT_EQ(props.maxExtent.height, props2.imageFormatProperties.maxExtent.height);
ASSERT_EQ(props.maxExtent.depth, props2.imageFormatProperties.maxExtent.depth);
ASSERT_EQ(props.maxMipLevels, props2.imageFormatProperties.maxMipLevels);
ASSERT_EQ(props.maxArrayLayers, props2.imageFormatProperties.maxArrayLayers);
ASSERT_EQ(props.sampleCounts, props2.imageFormatProperties.sampleCounts);
ASSERT_EQ(props.maxResourceSize, props2.imageFormatProperties.maxResourceSize);
}
}
// Test vkGetPhysicalDeviceMemoryProperties2KHR where nothing supports it.
TEST(LoaderInstPhysDevExts, PhysDevMemoryProps2KHRNoSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.CheckCreate();
auto GetPhysDevMemoryProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceMemoryProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceMemoryProperties2KHR"));
ASSERT_EQ(GetPhysDevMemoryProps2, nullptr);
}
// Test vkGetPhysicalDeviceMemoryProperties2KHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevMemoryPropsKHRNoICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
auto GetPhysDevMemoryProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceMemoryProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceMemoryProperties2KHR"));
ASSERT_EQ(GetPhysDevMemoryProps2, nullptr);
}
// Fill in random but valid data into the memory data struct for the current physical device
static void FillInRandomMemoryData(VkPhysicalDeviceMemoryProperties& props) {
props.memoryTypeCount = (rand() % 7) + 1;
props.memoryHeapCount = (rand() % 7) + 1;
for (uint32_t i = 0; i < props.memoryHeapCount; ++i) {
props.memoryHeaps[i].size = (rand() % 728) + (rand() % 728) + 1;
props.memoryHeaps[i].flags = (rand() % 2) + 1;
}
for (uint32_t i = 0; i < props.memoryTypeCount; ++i) {
props.memoryTypes[i].propertyFlags = static_cast<VkMemoryPropertyFlags>((rand() % 2) + 1);
props.memoryTypes[i].heapIndex = rand() % props.memoryHeapCount;
}
}
// Compare the memory structs
static bool CompareMemoryData(const VkPhysicalDeviceMemoryProperties& props1, const VkPhysicalDeviceMemoryProperties2& props2) {
bool equal = true;
equal = equal && props1.memoryTypeCount == props2.memoryProperties.memoryTypeCount;
equal = equal && props1.memoryHeapCount == props2.memoryProperties.memoryHeapCount;
for (uint32_t i = 0; i < props1.memoryHeapCount; ++i) {
equal = equal && props1.memoryHeaps[i].size == props2.memoryProperties.memoryHeaps[i].size;
equal = equal && props1.memoryHeaps[i].flags == props2.memoryProperties.memoryHeaps[i].flags;
}
for (uint32_t i = 0; i < props1.memoryTypeCount; ++i) {
equal = equal && props1.memoryTypes[i].propertyFlags == props2.memoryProperties.memoryTypes[i].propertyFlags;
equal = equal && props1.memoryTypes[i].heapIndex == props2.memoryProperties.memoryTypes[i].heapIndex;
}
return equal;
}
// Test vkGetPhysicalDeviceMemoryProperties2KHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, PhysDevMemoryProps2KHRInstanceAndICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
env.get_test_icd(0).physical_devices.push_back({});
FillInRandomMemoryData(env.get_test_icd(0).physical_devices.back().memory_properties);
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
instance.CheckCreate();
auto GetPhysDevMemoryProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceMemoryProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceMemoryProperties2KHR"));
ASSERT_NE(GetPhysDevMemoryProps2, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
VkPhysicalDeviceMemoryProperties props{};
instance->vkGetPhysicalDeviceMemoryProperties(physical_device, &props);
VkPhysicalDeviceMemoryProperties2 props2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2};
GetPhysDevMemoryProps2(physical_device, &props2);
ASSERT_TRUE(CompareMemoryData(props, props2));
}
// Test vkGetPhysicalDeviceMemoryProperties2 where instance supports, an ICD, and a device under that ICD
// also support, so everything should work and return properly.
TEST(LoaderInstPhysDevExts, PhysDevMemoryProps2Simple) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).icd_api_version = VK_API_VERSION_1_1;
env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
env.get_test_icd(0).physical_devices.push_back({});
env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
FillInRandomMemoryData(env.get_test_icd(0).physical_devices.back().memory_properties);
InstWrapper instance(env.vulkan_functions);
instance.create_info.set_api_version(VK_API_VERSION_1_1);
instance.CheckCreate();
auto GetPhysDevMemoryProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceMemoryProperties2>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceMemoryProperties2"));
ASSERT_NE(GetPhysDevMemoryProps2, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
VkPhysicalDeviceMemoryProperties props{};
instance->vkGetPhysicalDeviceMemoryProperties(physical_device, &props);
VkPhysicalDeviceMemoryProperties2 props2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2};
GetPhysDevMemoryProps2(physical_device, &props2);
ASSERT_TRUE(CompareMemoryData(props, props2));
}
// Test vkGetPhysicalDeviceMemoryProperties2 and vkGetPhysicalDeviceMemoryProperties2KHR where ICD is 1.0 and supports
// extension but the instance supports 1.1 and the extension
TEST(LoaderInstPhysDevExts, PhysDevMemoryProps2KHRInstanceSupports11) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
env.get_test_icd(0).physical_devices.push_back({});
env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
FillInRandomMemoryData(env.get_test_icd(0).physical_devices.back().memory_properties);
InstWrapper instance(env.vulkan_functions);
instance.create_info.set_api_version(VK_API_VERSION_1_1);
instance.create_info.add_extensions(
{VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_EXTENSION_NAME});
instance.CheckCreate();
DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
CreateDebugUtilsMessenger(log);
auto GetPhysDevMemoryProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceMemoryProperties2>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceMemoryProperties2"));
ASSERT_NE(GetPhysDevMemoryProps2, nullptr);
auto GetPhysDevMemoryProps2KHR = reinterpret_cast<PFN_vkGetPhysicalDeviceMemoryProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceMemoryProperties2KHR"));
ASSERT_NE(GetPhysDevMemoryProps2KHR, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
VkPhysicalDeviceMemoryProperties props{};
instance->vkGetPhysicalDeviceMemoryProperties(physical_device, &props);
VkPhysicalDeviceMemoryProperties2 props2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2};
GetPhysDevMemoryProps2(physical_device, &props2);
ASSERT_TRUE(CompareMemoryData(props, props2));
VkPhysicalDeviceMemoryProperties2KHR props2KHR{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR};
GetPhysDevMemoryProps2KHR(physical_device, &props2KHR);
ASSERT_TRUE(CompareMemoryData(props, props2KHR));
ASSERT_FALSE(log.find("Emulating call in ICD"));
}
// Test vkGetPhysicalDeviceMemoryProperties2 where instance supports it with some ICDs that both support
// and don't support it:
// ICD 0 supports
// Physical device 0 does not
// Physical device 1 does
// Physical device 2 does not
// ICD 1 doesn't support
// Physical device 3 does not
// ICD 2 supports
// Physical device 4 does not
// Physical device 5 does not
// ICD 3 supports
// Physical device 6 does
TEST(LoaderInstPhysDevExts, PhysDevMemoryPropsMixed) {
FrameworkEnvironment env{};
const uint32_t max_icd_count = 4;
const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
const uint32_t max_phys_devs = 7;
for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
auto& cur_icd = env.get_test_icd(icd);
// ICD 1 should not have 1.1
if (icd != 1) {
cur_icd.icd_api_version = VK_API_VERSION_1_1;
cur_icd.add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
} else {
cur_icd.icd_api_version = VK_API_VERSION_1_0;
}
uint32_t rand_vendor_id;
uint32_t rand_driver_vers;
FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
uint32_t device_version = VK_API_VERSION_1_0;
cur_icd.physical_devices.push_back({});
auto& cur_dev = cur_icd.physical_devices.back();
// 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
if ((icd == 0 && dev == 1) || icd == 3) {
cur_dev.extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
device_version = VK_API_VERSION_1_1;
}
// Still set physical device properties (so we can determine if device is correct API version)
FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
FillInRandomMemoryData(cur_dev.memory_properties);
}
}
InstWrapper instance(env.vulkan_functions);
instance.create_info.set_api_version(VK_API_VERSION_1_1);
instance.CheckCreate();
auto GetPhysDevMemoryProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceMemoryProperties2>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceMemoryProperties2"));
ASSERT_NE(GetPhysDevMemoryProps2, nullptr);
uint32_t device_count = max_phys_devs;
std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
ASSERT_EQ(device_count, max_phys_devs);
for (uint32_t dev = 0; dev < device_count; ++dev) {
VkPhysicalDeviceMemoryProperties props{};
instance->vkGetPhysicalDeviceMemoryProperties(physical_devices[dev], &props);
VkPhysicalDeviceMemoryProperties2 props2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2};
GetPhysDevMemoryProps2(physical_devices[dev], &props2);
ASSERT_TRUE(CompareMemoryData(props, props2));
}
}
// Test vkGetPhysicalDeviceQueueFamilyProperties2KHR where nothing supports it.
TEST(LoaderInstPhysDevExts, PhysDevQueueFamilyProps2KHRNoSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.CheckCreate();
auto GetPhysDevQueueFamilyProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceQueueFamilyProperties2KHR"));
ASSERT_EQ(GetPhysDevQueueFamilyProps2, nullptr);
}
// Test vkGetPhysicalDeviceQueueFamilyProperties2KHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevQueueFamilyPropsKHRNoICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
auto GetPhysDevQueueFamilyProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceQueueFamilyProperties2KHR"));
ASSERT_EQ(GetPhysDevQueueFamilyProps2, nullptr);
}
// Fill in random but valid data into the queue family data struct for the current physical device
static uint32_t FillInRandomQueueFamilyData(std::vector<MockQueueFamilyProperties>& props) {
props.resize((rand() % 4) + 1);
for (uint32_t i = 0; i < props.size(); ++i) {
props[i].properties.queueFlags = (rand() % 30) + 1;
props[i].properties.queueCount = (rand() % 7) + 1;
props[i].properties.timestampValidBits = (rand() % 30) + 7;
props[i].properties.minImageTransferGranularity.width = (rand() % 30) + 1;
props[i].properties.minImageTransferGranularity.height = (rand() % 30) + 1;
props[i].properties.minImageTransferGranularity.depth = (rand() % 30) + 1;
props[i].support_present = (rand() % 2);
}
return static_cast<uint32_t>(props.size());
}
// Compare the queue family structs
static bool CompareQueueFamilyData(const std::vector<VkQueueFamilyProperties>& props1,
const std::vector<VkQueueFamilyProperties2>& props2) {
if (props1.size() != props2.size()) return false;
bool equal = true;
for (uint32_t i = 0; i < props1.size(); ++i) {
equal = equal && props1[i].queueFlags == props2[i].queueFamilyProperties.queueFlags;
equal = equal && props1[i].queueCount == props2[i].queueFamilyProperties.queueCount;
equal = equal && props1[i].timestampValidBits == props2[i].queueFamilyProperties.timestampValidBits;
equal = equal &&
props1[i].minImageTransferGranularity.width == props2[i].queueFamilyProperties.minImageTransferGranularity.width;
equal = equal &&
props1[i].minImageTransferGranularity.height == props2[i].queueFamilyProperties.minImageTransferGranularity.height;
equal = equal &&
props1[i].minImageTransferGranularity.depth == props2[i].queueFamilyProperties.minImageTransferGranularity.depth;
}
return equal;
}
// Test vkGetPhysicalDeviceQueueFamilyProperties2KHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, PhysDevQueueFamilyProps2KHRInstanceAndICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
env.get_test_icd(0).physical_devices.push_back({});
uint32_t num_fam = FillInRandomQueueFamilyData(env.get_test_icd(0).physical_devices.back().queue_family_properties);
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
instance.CheckCreate();
auto GetPhysDevQueueFamilyProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceQueueFamilyProperties2KHR"));
ASSERT_NE(GetPhysDevQueueFamilyProps2, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
uint32_t ret_fam_1 = 0;
std::vector<VkQueueFamilyProperties> props{};
instance->vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &ret_fam_1, nullptr);
ASSERT_EQ(num_fam, ret_fam_1);
props.resize(ret_fam_1);
instance->vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &ret_fam_1, props.data());
std::vector<VkQueueFamilyProperties2> props2{};
uint32_t ret_fam_2 = 0;
GetPhysDevQueueFamilyProps2(physical_device, &ret_fam_2, nullptr);
ASSERT_EQ(ret_fam_1, ret_fam_2);
props2.resize(ret_fam_2, VkQueueFamilyProperties2{VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2});
GetPhysDevQueueFamilyProps2(physical_device, &ret_fam_2, props2.data());
ASSERT_TRUE(CompareQueueFamilyData(props, props2));
}
// Test vkGetPhysicalDeviceQueueFamilyProperties2 where instance supports, an ICD, and a device under that ICD
// also support, so everything should work and return properly.
TEST(LoaderInstPhysDevExts, PhysDevQueueFamilyProps2Simple) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).icd_api_version = VK_API_VERSION_1_1;
env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
env.get_test_icd(0).physical_devices.push_back({});
env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
uint32_t num_fam = FillInRandomQueueFamilyData(env.get_test_icd(0).physical_devices.back().queue_family_properties);
InstWrapper instance(env.vulkan_functions);
instance.create_info.set_api_version(VK_API_VERSION_1_1);
instance.CheckCreate();
auto GetPhysDevQueueFamilyProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceQueueFamilyProperties2>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceQueueFamilyProperties2"));
ASSERT_NE(GetPhysDevQueueFamilyProps2, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
uint32_t ret_fam_1 = 0;
std::vector<VkQueueFamilyProperties> props{};
instance->vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &ret_fam_1, nullptr);
ASSERT_EQ(num_fam, ret_fam_1);
props.resize(ret_fam_1);
instance->vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &ret_fam_1, props.data());
std::vector<VkQueueFamilyProperties2> props2{};
uint32_t ret_fam_2 = 0;
GetPhysDevQueueFamilyProps2(physical_device, &ret_fam_2, nullptr);
ASSERT_EQ(ret_fam_1, ret_fam_2);
props2.resize(ret_fam_2, VkQueueFamilyProperties2{VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2});
GetPhysDevQueueFamilyProps2(physical_device, &ret_fam_2, props2.data());
ASSERT_TRUE(CompareQueueFamilyData(props, props2));
}
// Test vkGetPhysicalDeviceQueueFamilyProperties2 and vkGetPhysicalDeviceQueueFamilyProperties2KHR where ICD is 1.0 and supports
// extension but the instance supports 1.1 and the extension
TEST(LoaderInstPhysDevExts, PhysDevQueueFamilyProps2KHRInstanceSupports11) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
env.get_test_icd(0).physical_devices.push_back({});
env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
uint32_t num_fam = FillInRandomQueueFamilyData(env.get_test_icd(0).physical_devices.back().queue_family_properties);
InstWrapper instance(env.vulkan_functions);
instance.create_info.set_api_version(VK_API_VERSION_1_1);
instance.create_info.add_extensions(
{VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_EXTENSION_NAME});
instance.CheckCreate();
DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
CreateDebugUtilsMessenger(log);
auto GetPhysDevQueueFamilyProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceQueueFamilyProperties2>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceQueueFamilyProperties2"));
ASSERT_NE(GetPhysDevQueueFamilyProps2, nullptr);
auto GetPhysDevQueueFamilyProps2KHR = reinterpret_cast<PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceQueueFamilyProperties2KHR"));
ASSERT_NE(GetPhysDevQueueFamilyProps2KHR, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
uint32_t ret_fam_1 = 0;
std::vector<VkQueueFamilyProperties> props{};
instance->vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &ret_fam_1, nullptr);
ASSERT_EQ(num_fam, ret_fam_1);
props.resize(ret_fam_1);
instance->vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &ret_fam_1, props.data());
std::vector<VkQueueFamilyProperties2> props2{};
uint32_t ret_fam_2 = 0;
GetPhysDevQueueFamilyProps2(physical_device, &ret_fam_2, nullptr);
ASSERT_EQ(ret_fam_1, ret_fam_2);
props2.resize(ret_fam_2, VkQueueFamilyProperties2{VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2});
GetPhysDevQueueFamilyProps2(physical_device, &ret_fam_2, props2.data());
ASSERT_TRUE(CompareQueueFamilyData(props, props2));
std::vector<VkQueueFamilyProperties2KHR> props2KHR{};
uint32_t ret_fam_2_khr = 0;
GetPhysDevQueueFamilyProps2KHR(physical_device, &ret_fam_2_khr, nullptr);
ASSERT_EQ(ret_fam_1, ret_fam_2_khr);
props2KHR.resize(ret_fam_2_khr, VkQueueFamilyProperties2KHR{VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR});
GetPhysDevQueueFamilyProps2KHR(physical_device, &ret_fam_2_khr, props2KHR.data());
ASSERT_TRUE(CompareQueueFamilyData(props, props2KHR));
ASSERT_FALSE(log.find("Emulating call in ICD"));
}
// Test vkGetPhysicalDeviceQueueFamilyProperties2 where instance supports it with some ICDs that both support
// and don't support it:
// ICD 0 supports
// Physical device 0 does not
// Physical device 1 does
// Physical device 2 does not
// ICD 1 doesn't support
// Physical device 3 does not
// ICD 2 supports
// Physical device 4 does not
// Physical device 5 does not
// ICD 3 supports
// Physical device 6 does
TEST(LoaderInstPhysDevExts, PhysDevQueueFamilyPropsMixed) {
FrameworkEnvironment env{};
const uint32_t max_icd_count = 4;
const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
const uint32_t max_phys_devs = 7;
for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
auto& cur_icd = env.get_test_icd(icd);
// ICD 1 should not have 1.1
if (icd != 1) {
cur_icd.icd_api_version = VK_API_VERSION_1_1;
cur_icd.add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
} else {
cur_icd.icd_api_version = VK_API_VERSION_1_0;
}
uint32_t rand_vendor_id;
uint32_t rand_driver_vers;
FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
uint32_t device_version = VK_API_VERSION_1_0;
cur_icd.physical_devices.push_back({});
auto& cur_dev = cur_icd.physical_devices.back();
// 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
if ((icd == 0 && dev == 1) || icd == 3) {
cur_dev.extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
device_version = VK_API_VERSION_1_1;
}
// Still set physical device properties (so we can determine if device is correct API version)
FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
FillInRandomQueueFamilyData(cur_dev.queue_family_properties);
}
}
InstWrapper instance(env.vulkan_functions);
instance.create_info.set_api_version(VK_API_VERSION_1_1);
instance.CheckCreate();
auto GetPhysDevQueueFamilyProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceQueueFamilyProperties2>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceQueueFamilyProperties2"));
ASSERT_NE(GetPhysDevQueueFamilyProps2, nullptr);
uint32_t device_count = max_phys_devs;
std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
ASSERT_EQ(device_count, max_phys_devs);
for (uint32_t dev = 0; dev < device_count; ++dev) {
uint32_t ret_fam_1 = 0;
std::vector<VkQueueFamilyProperties> props{};
instance->vkGetPhysicalDeviceQueueFamilyProperties(physical_devices[dev], &ret_fam_1, nullptr);
props.resize(ret_fam_1);
instance->vkGetPhysicalDeviceQueueFamilyProperties(physical_devices[dev], &ret_fam_1, props.data());
std::vector<VkQueueFamilyProperties2> props2{};
uint32_t ret_fam_2 = 0;
GetPhysDevQueueFamilyProps2(physical_devices[dev], &ret_fam_2, nullptr);
ASSERT_EQ(ret_fam_1, ret_fam_2);
props2.resize(ret_fam_2, VkQueueFamilyProperties2{VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2});
GetPhysDevQueueFamilyProps2(physical_devices[dev], &ret_fam_2, props2.data());
ASSERT_TRUE(CompareQueueFamilyData(props, props2));
}
}
// Test vkGetPhysicalDeviceSparseImageFormatProperties2KHR where nothing supports it.
TEST(LoaderInstPhysDevExts, PhysDevSparseImageFormatProps2KHRNoSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.CheckCreate();
auto GetPhysDevSparseImageFormatProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSparseImageFormatProperties2KHR"));
ASSERT_EQ(GetPhysDevSparseImageFormatProps2, nullptr);
}
// Test vkGetPhysicalDeviceSparseImageFormatProperties2KHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevSparseImageFormatPropsKHRNoICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
auto GetPhysDevSparseImageFormatProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSparseImageFormatProperties2KHR"));
ASSERT_EQ(GetPhysDevSparseImageFormatProps2, nullptr);
}
// Fill in random but valid data into the sparse image format data struct for the current physical device
static void FillInRandomSparseImageFormatData(std::vector<VkSparseImageFormatProperties>& props) {
props.resize((rand() % 4) + 1);
for (uint32_t i = 0; i < props.size(); ++i) {
props[i].aspectMask = static_cast<VkImageAspectFlags>((rand() % 0x7FE) + 1);
props[i].imageGranularity = {static_cast<uint32_t>(rand() % 512), static_cast<uint32_t>(rand() % 512),
static_cast<uint32_t>(rand() % 512)};
props[i].flags = static_cast<VkSparseImageFormatFlags>((rand() % 6) + 1);
}
}
// Compare the sparse image format structs
static bool CompareSparseImageFormatData(const std::vector<VkSparseImageFormatProperties>& props1,
const std::vector<VkSparseImageFormatProperties2>& props2) {
if (props1.size() != props2.size()) return false;
bool equal = true;
for (uint32_t i = 0; i < props1.size(); ++i) {
equal = equal && props1[i].aspectMask == props2[i].properties.aspectMask;
equal = equal && props1[i].imageGranularity.width == props2[i].properties.imageGranularity.width;
equal = equal && props1[i].imageGranularity.height == props2[i].properties.imageGranularity.height;
equal = equal && props1[i].imageGranularity.depth == props2[i].properties.imageGranularity.depth;
equal = equal && props1[i].flags == props2[i].properties.flags;
}
return equal;
}
// Test vkGetPhysicalDeviceSparseImageFormatProperties2KHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, PhysDevSparseImageFormatProps2KHRInstanceAndICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
env.get_test_icd(0).physical_devices.push_back({});
FillInRandomSparseImageFormatData(env.get_test_icd(0).physical_devices.back().sparse_image_format_properties);
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
instance.CheckCreate();
auto GetPhysDevSparseImageFormatProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSparseImageFormatProperties2KHR"));
ASSERT_NE(GetPhysDevSparseImageFormatProps2, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
std::vector<VkSparseImageFormatProperties> props{};
uint32_t sparse_count_1 = 0;
instance->vkGetPhysicalDeviceSparseImageFormatProperties(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, VK_IMAGE_TYPE_2D,
VK_SAMPLE_COUNT_4_BIT, VK_IMAGE_USAGE_STORAGE_BIT,
VK_IMAGE_TILING_OPTIMAL, &sparse_count_1, nullptr);
ASSERT_NE(sparse_count_1, 0);
props.resize(sparse_count_1);
instance->vkGetPhysicalDeviceSparseImageFormatProperties(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, VK_IMAGE_TYPE_2D,
VK_SAMPLE_COUNT_4_BIT, VK_IMAGE_USAGE_STORAGE_BIT,
VK_IMAGE_TILING_OPTIMAL, &sparse_count_1, props.data());
ASSERT_NE(sparse_count_1, 0);
VkPhysicalDeviceSparseImageFormatInfo2 info2{
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2, // sType
nullptr, // pNext
VK_FORMAT_R4G4_UNORM_PACK8, // format
VK_IMAGE_TYPE_2D, // type
VK_SAMPLE_COUNT_4_BIT, // samples
VK_IMAGE_USAGE_STORAGE_BIT, // usage
VK_IMAGE_TILING_OPTIMAL, // tiling
};
std::vector<VkSparseImageFormatProperties2> props2{};
uint32_t sparse_count_2 = 0;
GetPhysDevSparseImageFormatProps2(physical_device, &info2, &sparse_count_2, nullptr);
ASSERT_EQ(sparse_count_1, sparse_count_2);
props2.resize(sparse_count_2, VkSparseImageFormatProperties2{VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2});
GetPhysDevSparseImageFormatProps2(physical_device, &info2, &sparse_count_2, props2.data());
ASSERT_EQ(sparse_count_1, sparse_count_2);
ASSERT_TRUE(CompareSparseImageFormatData(props, props2));
}
// Test vkGetPhysicalDeviceSparseImageFormatProperties2 where instance supports, an ICD, and a device under that ICD
// also support, so everything should work and return properly.
TEST(LoaderInstPhysDevExts, PhysDevSparseImageFormatProps2Simple) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).icd_api_version = VK_API_VERSION_1_1;
env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
env.get_test_icd(0).physical_devices.push_back({});
env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
FillInRandomSparseImageFormatData(env.get_test_icd(0).physical_devices.back().sparse_image_format_properties);
InstWrapper instance(env.vulkan_functions);
instance.create_info.set_api_version(VK_API_VERSION_1_1);
instance.CheckCreate();
auto GetPhysDevSparseImageFormatProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceSparseImageFormatProperties2>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSparseImageFormatProperties2"));
ASSERT_NE(GetPhysDevSparseImageFormatProps2, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
std::vector<VkSparseImageFormatProperties> props{};
uint32_t sparse_count_1 = 0;
instance->vkGetPhysicalDeviceSparseImageFormatProperties(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, VK_IMAGE_TYPE_2D,
VK_SAMPLE_COUNT_4_BIT, VK_IMAGE_USAGE_STORAGE_BIT,
VK_IMAGE_TILING_OPTIMAL, &sparse_count_1, nullptr);
ASSERT_NE(sparse_count_1, 0);
props.resize(sparse_count_1);
instance->vkGetPhysicalDeviceSparseImageFormatProperties(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, VK_IMAGE_TYPE_2D,
VK_SAMPLE_COUNT_4_BIT, VK_IMAGE_USAGE_STORAGE_BIT,
VK_IMAGE_TILING_OPTIMAL, &sparse_count_1, props.data());
ASSERT_NE(sparse_count_1, 0);
VkPhysicalDeviceSparseImageFormatInfo2 info2{
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2, // sType
nullptr, // pNext
VK_FORMAT_R4G4_UNORM_PACK8, // format
VK_IMAGE_TYPE_2D, // type
VK_SAMPLE_COUNT_4_BIT, // samples
VK_IMAGE_USAGE_STORAGE_BIT, // usage
VK_IMAGE_TILING_OPTIMAL, // tiling
};
std::vector<VkSparseImageFormatProperties2> props2{};
uint32_t sparse_count_2 = 0;
GetPhysDevSparseImageFormatProps2(physical_device, &info2, &sparse_count_2, nullptr);
ASSERT_EQ(sparse_count_1, sparse_count_2);
props2.resize(sparse_count_2, VkSparseImageFormatProperties2{VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2});
GetPhysDevSparseImageFormatProps2(physical_device, &info2, &sparse_count_2, props2.data());
ASSERT_EQ(sparse_count_1, sparse_count_2);
ASSERT_TRUE(CompareSparseImageFormatData(props, props2));
}
// Test vkGetPhysicalDeviceSparseImageFormatProperties2 and vkGetPhysicalDeviceSparseImageFormatProperties2KHR where ICD is 1.0 and
// supports extension but the instance supports 1.1 and the extension
TEST(LoaderInstPhysDevExts, PhysDevSparseImageFormatProps2KHRInstanceSupports11) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
env.get_test_icd(0).physical_devices.push_back({});
env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
FillInRandomSparseImageFormatData(env.get_test_icd(0).physical_devices.back().sparse_image_format_properties);
InstWrapper instance(env.vulkan_functions);
instance.create_info.set_api_version(VK_API_VERSION_1_1);
instance.create_info.add_extensions(
{VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_EXTENSION_NAME});
instance.CheckCreate();
DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
CreateDebugUtilsMessenger(log);
auto GetPhysDevSparseImageFormatProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceSparseImageFormatProperties2>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSparseImageFormatProperties2"));
ASSERT_NE(GetPhysDevSparseImageFormatProps2, nullptr);
auto GetPhysDevSparseImageFormatProps2KHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSparseImageFormatProperties2KHR"));
ASSERT_NE(GetPhysDevSparseImageFormatProps2KHR, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
std::vector<VkSparseImageFormatProperties> props{};
uint32_t sparse_count_1 = 0;
instance->vkGetPhysicalDeviceSparseImageFormatProperties(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, VK_IMAGE_TYPE_2D,
VK_SAMPLE_COUNT_4_BIT, VK_IMAGE_USAGE_STORAGE_BIT,
VK_IMAGE_TILING_OPTIMAL, &sparse_count_1, nullptr);
ASSERT_NE(sparse_count_1, 0);
props.resize(sparse_count_1);
instance->vkGetPhysicalDeviceSparseImageFormatProperties(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, VK_IMAGE_TYPE_2D,
VK_SAMPLE_COUNT_4_BIT, VK_IMAGE_USAGE_STORAGE_BIT,
VK_IMAGE_TILING_OPTIMAL, &sparse_count_1, props.data());
ASSERT_NE(sparse_count_1, 0);
VkPhysicalDeviceSparseImageFormatInfo2 info2{
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2, // sType
nullptr, // pNext
VK_FORMAT_R4G4_UNORM_PACK8, // format
VK_IMAGE_TYPE_2D, // type
VK_SAMPLE_COUNT_4_BIT, // samples
VK_IMAGE_USAGE_STORAGE_BIT, // usage
VK_IMAGE_TILING_OPTIMAL, // tiling
};
std::vector<VkSparseImageFormatProperties2> props2{};
uint32_t sparse_count_2 = 0;
GetPhysDevSparseImageFormatProps2(physical_device, &info2, &sparse_count_2, nullptr);
ASSERT_EQ(sparse_count_1, sparse_count_2);
props2.resize(sparse_count_2, VkSparseImageFormatProperties2{VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2});
GetPhysDevSparseImageFormatProps2(physical_device, &info2, &sparse_count_2, props2.data());
ASSERT_EQ(sparse_count_1, sparse_count_2);
ASSERT_TRUE(CompareSparseImageFormatData(props, props2));
std::vector<VkSparseImageFormatProperties2KHR> props2KHR{};
uint32_t sparse_count_2_khr = 0;
GetPhysDevSparseImageFormatProps2KHR(physical_device, &info2, &sparse_count_2_khr, nullptr);
ASSERT_EQ(sparse_count_1, sparse_count_2_khr);
props2KHR.resize(sparse_count_2, VkSparseImageFormatProperties2KHR{VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2_KHR});
GetPhysDevSparseImageFormatProps2KHR(physical_device, &info2, &sparse_count_2_khr, props2KHR.data());
ASSERT_EQ(sparse_count_1, sparse_count_2_khr);
ASSERT_TRUE(CompareSparseImageFormatData(props, props2KHR));
ASSERT_FALSE(log.find("Emulating call in ICD"));
}
// Test vkGetPhysicalDeviceSparseImageFormatProperties2 where instance supports it with some ICDs that both support
// and don't support it:
// ICD 0 supports
// Physical device 0 does not
// Physical device 1 does
// Physical device 2 does not
// ICD 1 doesn't support
// Physical device 3 does not
// ICD 2 supports
// Physical device 4 does not
// Physical device 5 does not
// ICD 3 supports
// Physical device 6 does
TEST(LoaderInstPhysDevExts, PhysDevSparseImageFormatPropsMixed) {
FrameworkEnvironment env{};
const uint32_t max_icd_count = 4;
const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
const uint32_t max_phys_devs = 7;
for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
auto& cur_icd = env.get_test_icd(icd);
// ICD 1 should not have 1.1
if (icd != 1) {
cur_icd.icd_api_version = VK_API_VERSION_1_1;
cur_icd.add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
} else {
cur_icd.icd_api_version = VK_API_VERSION_1_0;
}
uint32_t rand_vendor_id;
uint32_t rand_driver_vers;
FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
uint32_t device_version = VK_API_VERSION_1_0;
cur_icd.physical_devices.push_back({});
auto& cur_dev = cur_icd.physical_devices.back();
// 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
if ((icd == 0 && dev == 1) || icd == 3) {
cur_dev.extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
device_version = VK_API_VERSION_1_1;
}
// Still set physical device properties (so we can determine if device is correct API version)
FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
FillInRandomSparseImageFormatData(cur_dev.sparse_image_format_properties);
}
}
InstWrapper instance(env.vulkan_functions);
instance.create_info.set_api_version(VK_API_VERSION_1_1);
instance.CheckCreate();
auto GetPhysDevSparseImageFormatProps2 = reinterpret_cast<PFN_vkGetPhysicalDeviceSparseImageFormatProperties2>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSparseImageFormatProperties2"));
ASSERT_NE(GetPhysDevSparseImageFormatProps2, nullptr);
uint32_t device_count = max_phys_devs;
std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
ASSERT_EQ(device_count, max_phys_devs);
for (uint32_t dev = 0; dev < device_count; ++dev) {
std::vector<VkSparseImageFormatProperties> props{};
uint32_t sparse_count_1 = 0;
instance->vkGetPhysicalDeviceSparseImageFormatProperties(
physical_devices[dev], VK_FORMAT_R4G4_UNORM_PACK8, VK_IMAGE_TYPE_2D, VK_SAMPLE_COUNT_4_BIT, VK_IMAGE_USAGE_STORAGE_BIT,
VK_IMAGE_TILING_OPTIMAL, &sparse_count_1, nullptr);
ASSERT_NE(sparse_count_1, 0);
props.resize(sparse_count_1);
instance->vkGetPhysicalDeviceSparseImageFormatProperties(
physical_devices[dev], VK_FORMAT_R4G4_UNORM_PACK8, VK_IMAGE_TYPE_2D, VK_SAMPLE_COUNT_4_BIT, VK_IMAGE_USAGE_STORAGE_BIT,
VK_IMAGE_TILING_OPTIMAL, &sparse_count_1, props.data());
ASSERT_NE(sparse_count_1, 0);
VkPhysicalDeviceSparseImageFormatInfo2 info2{
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2, // sType
nullptr, // pNext
VK_FORMAT_R4G4_UNORM_PACK8, // format
VK_IMAGE_TYPE_2D, // type
VK_SAMPLE_COUNT_4_BIT, // samples
VK_IMAGE_USAGE_STORAGE_BIT, // usage
VK_IMAGE_TILING_OPTIMAL, // tiling
};
std::vector<VkSparseImageFormatProperties2> props2{};
uint32_t sparse_count_2 = 0;
GetPhysDevSparseImageFormatProps2(physical_devices[dev], &info2, &sparse_count_2, nullptr);
ASSERT_EQ(sparse_count_1, sparse_count_2);
props2.resize(sparse_count_2, VkSparseImageFormatProperties2{VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2});
GetPhysDevSparseImageFormatProps2(physical_devices[dev], &info2, &sparse_count_2, props2.data());
ASSERT_EQ(sparse_count_1, sparse_count_2);
ASSERT_TRUE(CompareSparseImageFormatData(props, props2));
}
}
//
// VK_KHR_external_memory_capabilities
//
// Test vkGetPhysicalDeviceExternalBufferPropertiesKHR where nothing supports it.
TEST(LoaderInstPhysDevExts, PhysDevExtBufPropsKHRNoSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.CheckCreate();
auto GetPhysicalDeviceExternalBufferProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalBufferPropertiesKHR"));
ASSERT_EQ(GetPhysicalDeviceExternalBufferProperties, nullptr);
}
// Test vkGetPhysicalDeviceExternalBufferPropertiesKHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevExtBufPropsKHRNoICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME);
instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
auto GetPhysicalDeviceExternalBufferProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalBufferPropertiesKHR"));
ASSERT_EQ(GetPhysicalDeviceExternalBufferProperties, nullptr);
}
// Fill in random but valid data into the external memorydata struct for the current physical device
static void FillInRandomExtMemoryData(VkExternalMemoryProperties& props) {
props.externalMemoryFeatures = static_cast<VkExternalMemoryFeatureFlags>((rand() % 6) + 1);
props.exportFromImportedHandleTypes = static_cast<VkExternalMemoryHandleTypeFlags>((rand() % 0x1FFE) + 1);
props.compatibleHandleTypes = static_cast<VkExternalMemoryHandleTypeFlags>((rand() % 0x1FFE) + 1);
}
// Compare the external memory data structs
static bool CompareExtMemoryData(const VkExternalMemoryProperties& props1, const VkExternalMemoryProperties& props2,
bool supported = true) {
bool equal = true;
if (supported) {
equal = equal && props1.externalMemoryFeatures == props2.externalMemoryFeatures;
equal = equal && props1.exportFromImportedHandleTypes == props2.exportFromImportedHandleTypes;
equal = equal && props1.compatibleHandleTypes == props2.compatibleHandleTypes;
} else {
equal = equal && 0 == props2.externalMemoryFeatures;
equal = equal && 0 == props2.exportFromImportedHandleTypes;
equal = equal && 0 == props2.compatibleHandleTypes;
}
return equal;
}
// Test vkGetPhysicalDeviceExternalBufferPropertiesKHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, PhysDevExtBufProps2KHRInstanceAndICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).add_instance_extension({VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME});
env.get_test_icd(0).physical_devices.push_back({});
FillInRandomExtMemoryData(env.get_test_icd(0).physical_devices.back().external_memory_properties);
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME);
instance.CheckCreate();
auto GetPhysicalDeviceExternalBufferProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalBufferPropertiesKHR"));
ASSERT_NE(GetPhysicalDeviceExternalBufferProperties, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
VkPhysicalDeviceExternalBufferInfoKHR info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHR};
VkExternalBufferPropertiesKHR props{VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHR};
GetPhysicalDeviceExternalBufferProperties(physical_device, &info, &props);
ASSERT_TRUE(CompareExtMemoryData(env.get_test_icd(0).physical_devices.back().external_memory_properties,
props.externalMemoryProperties));
}
// Test vkGetPhysicalDeviceExternalBufferProperties where instance supports, an ICD, and a device under that ICD
// also support, so everything should work and return properly.
TEST(LoaderInstPhysDevExts, PhysDevExtBufProps2Simple) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).icd_api_version = VK_API_VERSION_1_1;
env.get_test_icd(0).add_instance_extension({VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME});
env.get_test_icd(0).physical_devices.push_back({});
env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME, 0});
FillInRandomExtMemoryData(env.get_test_icd(0).physical_devices.back().external_memory_properties);
InstWrapper instance(env.vulkan_functions);
instance.create_info.set_api_version(VK_API_VERSION_1_1);
instance.CheckCreate();
auto GetPhysicalDeviceExternalBufferProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceExternalBufferProperties>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalBufferProperties"));
ASSERT_NE(GetPhysicalDeviceExternalBufferProperties, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
VkPhysicalDeviceExternalBufferInfo info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO};
VkExternalBufferProperties props{VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES};
GetPhysicalDeviceExternalBufferProperties(physical_device, &info, &props);
ASSERT_TRUE(CompareExtMemoryData(env.get_test_icd(0).physical_devices.back().external_memory_properties,
props.externalMemoryProperties));
}
// Test vkGetPhysicalDeviceExternalBufferProperties where instance supports it with some ICDs that both support
// and don't support it:
// ICD 0 supports
// Physical device 0 does not
// Physical device 1 does
// Physical device 2 does not
// ICD 1 doesn't support
// Physical device 3 does not
// ICD 2 supports
// Physical device 4 does not
// Physical device 5 does not
// ICD 3 supports
// Physical device 6 does
TEST(LoaderInstPhysDevExts, PhysDevExtBufPropsMixed) {
FrameworkEnvironment env{};
const uint32_t max_icd_count = 4;
const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
const uint32_t max_phys_devs = 7;
for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
auto& cur_icd = env.get_test_icd(icd);
// ICD 1 should not have 1.1
if (icd != 1) {
cur_icd.icd_api_version = VK_API_VERSION_1_1;
cur_icd.add_instance_extension({VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME});
} else {
cur_icd.icd_api_version = VK_API_VERSION_1_0;
}
uint32_t rand_vendor_id;
uint32_t rand_driver_vers;
FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
uint32_t device_version = VK_API_VERSION_1_0;
cur_icd.physical_devices.push_back({});
auto& cur_dev = cur_icd.physical_devices.back();
// 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
if ((icd == 0 && dev == 1) || icd == 3) {
cur_dev.extensions.push_back({VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME, 0});
device_version = VK_API_VERSION_1_1;
}
// Still set physical device properties (so we can determine if device is correct API version)
FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
FillInRandomExtMemoryData(cur_dev.external_memory_properties);
}
}
InstWrapper instance(env.vulkan_functions);
instance.create_info.set_api_version(VK_API_VERSION_1_1);
instance.CheckCreate();
auto GetPhysicalDeviceExternalBufferProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceExternalBufferProperties>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalBufferProperties"));
ASSERT_NE(GetPhysicalDeviceExternalBufferProperties, nullptr);
uint32_t device_count = max_phys_devs;
std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
ASSERT_EQ(device_count, max_phys_devs);
for (uint32_t dev = 0; dev < device_count; ++dev) {
VkPhysicalDeviceProperties pd_props{};
instance->vkGetPhysicalDeviceProperties(physical_devices[dev], &pd_props);
for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
auto& cur_icd = env.get_test_icd(icd);
bool found = false;
for (uint32_t pd = 0; pd < dev_counts[icd]; ++pd) {
auto& cur_dev = cur_icd.physical_devices[pd];
// Find the ICD device matching the physical device we're looking at info for so we can compare the
// physical devices info with the returned info.
if (cur_dev.properties.apiVersion == pd_props.apiVersion && cur_dev.properties.deviceID == pd_props.deviceID &&
cur_dev.properties.deviceType == pd_props.deviceType &&
cur_dev.properties.driverVersion == pd_props.driverVersion &&
cur_dev.properties.vendorID == pd_props.vendorID) {
VkPhysicalDeviceExternalBufferInfo info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO};
VkExternalBufferProperties props{VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES};
GetPhysicalDeviceExternalBufferProperties(physical_devices[dev], &info, &props);
// No driver support for extension or 1.1 for ICD 1, all others support
ASSERT_TRUE(CompareExtMemoryData(cur_dev.external_memory_properties, props.externalMemoryProperties, icd != 1));
found = true;
break;
}
}
if (found) {
break;
}
}
}
}
//
// VK_KHR_external_semaphore_capabilities
//
// Test vkGetPhysicalDeviceExternalSemaphorePropertiesKHR where nothing supports it.
TEST(LoaderInstPhysDevExts, PhysDevExtSemPropsKHRNoSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.CheckCreate();
auto GetPhysicalDeviceExternalSemaphoreProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalSemaphorePropertiesKHR"));
ASSERT_EQ(GetPhysicalDeviceExternalSemaphoreProperties, nullptr);
}
// Test vkGetPhysicalDeviceExternalSemaphorePropertiesKHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevExtSemPropsKHRNoICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME);
instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
auto GetPhysicalDeviceExternalSemaphoreProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalSemaphorePropertiesKHR"));
ASSERT_EQ(GetPhysicalDeviceExternalSemaphoreProperties, nullptr);
}
// Fill in random but valid data into the external semaphore data struct for the current physical device
static void FillInRandomExtSemData(VkExternalSemaphoreProperties& props) {
props.sType = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES;
props.pNext = nullptr;
props.exportFromImportedHandleTypes = static_cast<VkExternalSemaphoreHandleTypeFlags>((rand() % 0xFFF) + 1);
props.compatibleHandleTypes = static_cast<VkExternalSemaphoreHandleTypeFlags>((rand() % 0xFFF) + 1);
props.externalSemaphoreFeatures = static_cast<VkExternalSemaphoreFeatureFlags>((rand() % 0xFFF) + 1);
}
// Compare the external semaphore data structs
static bool CompareExtSemaphoreData(const VkExternalSemaphoreProperties& props1, const VkExternalSemaphoreProperties& props2,
bool supported = true) {
bool equal = true;
if (supported) {
equal = equal && props1.externalSemaphoreFeatures == props2.externalSemaphoreFeatures;
equal = equal && props1.exportFromImportedHandleTypes == props2.exportFromImportedHandleTypes;
equal = equal && props1.compatibleHandleTypes == props2.compatibleHandleTypes;
} else {
equal = equal && 0 == props2.externalSemaphoreFeatures;
equal = equal && 0 == props2.exportFromImportedHandleTypes;
equal = equal && 0 == props2.compatibleHandleTypes;
}
return equal;
}
// Test vkGetPhysicalDeviceExternalSemaphorePropertiesKHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, PhysDevExtSemProps2KHRInstanceAndICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).add_instance_extension({VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME});
env.get_test_icd(0).physical_devices.push_back({});
FillInRandomExtSemData(env.get_test_icd(0).physical_devices.back().external_semaphore_properties);
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME);
instance.CheckCreate();
auto GetPhysicalDeviceExternalSemaphoreProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalSemaphorePropertiesKHR"));
ASSERT_NE(GetPhysicalDeviceExternalSemaphoreProperties, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
VkPhysicalDeviceExternalSemaphoreInfoKHR info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR};
VkExternalSemaphorePropertiesKHR props{VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR};
GetPhysicalDeviceExternalSemaphoreProperties(physical_device, &info, &props);
ASSERT_TRUE(CompareExtSemaphoreData(env.get_test_icd(0).physical_devices.back().external_semaphore_properties, props));
}
// Test vkGetPhysicalDeviceExternalSemaphoreProperties where instance supports, an ICD, and a device under that ICD
// also support, so everything should work and return properly.
TEST(LoaderInstPhysDevExts, PhysDevExtSemProps2Simple) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).icd_api_version = VK_API_VERSION_1_1;
env.get_test_icd(0).add_instance_extension({VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME});
env.get_test_icd(0).physical_devices.push_back({});
env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME, 0});
FillInRandomExtSemData(env.get_test_icd(0).physical_devices.back().external_semaphore_properties);
InstWrapper instance(env.vulkan_functions);
instance.create_info.set_api_version(VK_API_VERSION_1_1);
instance.CheckCreate();
auto GetPhysicalDeviceExternalSemaphoreProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceExternalSemaphoreProperties>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalSemaphoreProperties"));
ASSERT_NE(GetPhysicalDeviceExternalSemaphoreProperties, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
VkPhysicalDeviceExternalSemaphoreInfo info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO};
VkExternalSemaphoreProperties props{VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES};
GetPhysicalDeviceExternalSemaphoreProperties(physical_device, &info, &props);
ASSERT_TRUE(CompareExtSemaphoreData(env.get_test_icd(0).physical_devices.back().external_semaphore_properties, props));
}
// Test vkGetPhysicalDeviceExternalSemaphoreProperties where instance supports it with some ICDs that both support
// and don't support it:
// ICD 0 supports
// Physical device 0 does not
// Physical device 1 does
// Physical device 2 does not
// ICD 1 doesn't support
// Physical device 3 does not
// ICD 2 supports
// Physical device 4 does not
// Physical device 5 does not
// ICD 3 supports
// Physical device 6 does
TEST(LoaderInstPhysDevExts, PhysDevExtSemPropsMixed) {
FrameworkEnvironment env{};
const uint32_t max_icd_count = 4;
const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
const uint32_t max_phys_devs = 7;
for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
auto& cur_icd = env.get_test_icd(icd);
// ICD 1 should not have 1.1
if (icd != 1) {
cur_icd.icd_api_version = VK_API_VERSION_1_1;
cur_icd.add_instance_extension({VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME});
} else {
cur_icd.icd_api_version = VK_API_VERSION_1_0;
}
uint32_t rand_vendor_id;
uint32_t rand_driver_vers;
FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
uint32_t device_version = VK_API_VERSION_1_0;
cur_icd.physical_devices.push_back({});
auto& cur_dev = cur_icd.physical_devices.back();
// 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
if ((icd == 0 && dev == 1) || icd == 3) {
cur_dev.extensions.push_back({VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME, 0});
device_version = VK_API_VERSION_1_1;
}
// Still set physical device properties (so we can determine if device is correct API version)
FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
FillInRandomExtSemData(cur_dev.external_semaphore_properties);
}
}
InstWrapper instance(env.vulkan_functions);
instance.create_info.set_api_version(VK_API_VERSION_1_1);
instance.CheckCreate();
auto GetPhysicalDeviceExternalSemaphoreProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceExternalSemaphoreProperties>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalSemaphoreProperties"));
ASSERT_NE(GetPhysicalDeviceExternalSemaphoreProperties, nullptr);
uint32_t device_count = max_phys_devs;
std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
ASSERT_EQ(device_count, max_phys_devs);
for (uint32_t dev = 0; dev < device_count; ++dev) {
VkPhysicalDeviceProperties pd_props{};
instance->vkGetPhysicalDeviceProperties(physical_devices[dev], &pd_props);
for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
auto& cur_icd = env.get_test_icd(icd);
bool found = false;
for (uint32_t pd = 0; pd < dev_counts[icd]; ++pd) {
auto& cur_dev = cur_icd.physical_devices[pd];
// Find the ICD device matching the physical device we're looking at info for so we can compare the
// physical devices info with the returned info.
if (cur_dev.properties.apiVersion == pd_props.apiVersion && cur_dev.properties.deviceID == pd_props.deviceID &&
cur_dev.properties.deviceType == pd_props.deviceType &&
cur_dev.properties.driverVersion == pd_props.driverVersion &&
cur_dev.properties.vendorID == pd_props.vendorID) {
VkPhysicalDeviceExternalSemaphoreInfo info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO};
VkExternalSemaphoreProperties props{VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES};
GetPhysicalDeviceExternalSemaphoreProperties(physical_devices[dev], &info, &props);
// No driver support for extension or 1.1 for ICD 1, all others support
ASSERT_TRUE(CompareExtSemaphoreData(cur_dev.external_semaphore_properties, props, icd != 1));
found = true;
break;
}
}
if (found) {
break;
}
}
}
}
//
// VK_KHR_external_fence_capabilities
//
// Test vkGetPhysicalDeviceExternalFencePropertiesKHR where nothing supports it.
TEST(LoaderInstPhysDevExts, PhysDevExtFencePropsKHRNoSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.CheckCreate();
auto GetPhysicalDeviceExternalFenceProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalFencePropertiesKHR"));
ASSERT_EQ(GetPhysicalDeviceExternalFenceProperties, nullptr);
}
// Test vkGetPhysicalDeviceExternalFencePropertiesKHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevExtFencePropsKHRNoICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME);
instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
auto GetPhysicalDeviceExternalFenceProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalFencePropertiesKHR"));
ASSERT_EQ(GetPhysicalDeviceExternalFenceProperties, nullptr);
}
// Fill in random but valid data into the external fence data struct for the current physical device
static void FillInRandomExtFenceData(VkExternalFenceProperties& props) {
props.sType = VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES;
props.pNext = nullptr;
props.exportFromImportedHandleTypes = static_cast<VkExternalFenceHandleTypeFlags>((rand() % 0xFFF) + 1);
props.compatibleHandleTypes = static_cast<VkExternalFenceHandleTypeFlags>((rand() % 0xFFF) + 1);
props.externalFenceFeatures = static_cast<VkExternalFenceFeatureFlags>((rand() % 0xFFF) + 1);
}
// Compare the external fence data structs
static bool CompareExtFenceData(const VkExternalFenceProperties& props1, const VkExternalFenceProperties& props2,
bool supported = true) {
bool equal = true;
if (supported) {
equal = equal && props1.externalFenceFeatures == props2.externalFenceFeatures;
equal = equal && props1.exportFromImportedHandleTypes == props2.exportFromImportedHandleTypes;
equal = equal && props1.compatibleHandleTypes == props2.compatibleHandleTypes;
} else {
equal = equal && 0 == props2.externalFenceFeatures;
equal = equal && 0 == props2.exportFromImportedHandleTypes;
equal = equal && 0 == props2.compatibleHandleTypes;
}
return equal;
}
// Test vkGetPhysicalDeviceExternalFencePropertiesKHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, PhysDevExtFenceProps2KHRInstanceAndICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).add_instance_extension({VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME});
env.get_test_icd(0).physical_devices.push_back({});
FillInRandomExtFenceData(env.get_test_icd(0).physical_devices.back().external_fence_properties);
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME);
instance.CheckCreate();
auto GetPhysicalDeviceExternalFenceProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalFencePropertiesKHR"));
ASSERT_NE(GetPhysicalDeviceExternalFenceProperties, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
VkPhysicalDeviceExternalFenceInfoKHR info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO_KHR};
VkExternalFencePropertiesKHR props{VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES_KHR};
GetPhysicalDeviceExternalFenceProperties(physical_device, &info, &props);
ASSERT_TRUE(CompareExtFenceData(env.get_test_icd(0).physical_devices.back().external_fence_properties, props));
}
// Test vkGetPhysicalDeviceExternalFenceProperties where instance supports, an ICD, and a device under that ICD
// also support, so everything should work and return properly.
TEST(LoaderInstPhysDevExts, PhysDevExtFenceProps2Simple) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).icd_api_version = VK_API_VERSION_1_1;
env.get_test_icd(0).add_instance_extension({VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME});
env.get_test_icd(0).physical_devices.push_back({});
env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME, 0});
FillInRandomExtFenceData(env.get_test_icd(0).physical_devices.back().external_fence_properties);
InstWrapper instance(env.vulkan_functions);
instance.create_info.set_api_version(VK_API_VERSION_1_1);
instance.CheckCreate();
auto GetPhysicalDeviceExternalFenceProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceExternalFenceProperties>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalFenceProperties"));
ASSERT_NE(GetPhysicalDeviceExternalFenceProperties, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
VkPhysicalDeviceExternalFenceInfo info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO};
VkExternalFenceProperties props{VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES};
GetPhysicalDeviceExternalFenceProperties(physical_device, &info, &props);
ASSERT_TRUE(CompareExtFenceData(env.get_test_icd(0).physical_devices.back().external_fence_properties, props));
}
// Test vkGetPhysicalDeviceExternalFenceProperties where instance supports it with some ICDs that both support
// and don't support it:
// ICD 0 supports
// Physical device 0 does not
// Physical device 1 does
// Physical device 2 does not
// ICD 1 doesn't support
// Physical device 3 does not
// ICD 2 supports
// Physical device 4 does not
// Physical device 5 does not
// ICD 3 supports
// Physical device 6 does
TEST(LoaderInstPhysDevExts, PhysDevExtFencePropsMixed) {
FrameworkEnvironment env{};
const uint32_t max_icd_count = 4;
const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
const uint32_t max_phys_devs = 7;
for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
auto& cur_icd = env.get_test_icd(icd);
// ICD 1 should not have 1.1
if (icd != 1) {
cur_icd.icd_api_version = VK_API_VERSION_1_1;
cur_icd.add_instance_extension({VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME});
} else {
cur_icd.icd_api_version = VK_API_VERSION_1_0;
}
uint32_t rand_vendor_id;
uint32_t rand_driver_vers;
FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
uint32_t device_version = VK_API_VERSION_1_0;
cur_icd.physical_devices.push_back({});
auto& cur_dev = cur_icd.physical_devices.back();
// 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
if ((icd == 0 && dev == 1) || icd == 3) {
cur_dev.extensions.push_back({VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME, 0});
device_version = VK_API_VERSION_1_1;
}
// Still set physical device properties (so we can determine if device is correct API version)
FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
FillInRandomExtFenceData(cur_dev.external_fence_properties);
}
}
InstWrapper instance(env.vulkan_functions);
instance.create_info.set_api_version(VK_API_VERSION_1_1);
instance.CheckCreate();
auto GetPhysicalDeviceExternalFenceProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceExternalFenceProperties>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalFenceProperties"));
ASSERT_NE(GetPhysicalDeviceExternalFenceProperties, nullptr);
uint32_t device_count = max_phys_devs;
std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
ASSERT_EQ(device_count, max_phys_devs);
for (uint32_t dev = 0; dev < device_count; ++dev) {
VkPhysicalDeviceProperties pd_props{};
instance->vkGetPhysicalDeviceProperties(physical_devices[dev], &pd_props);
for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
auto& cur_icd = env.get_test_icd(icd);
bool found = false;
for (uint32_t pd = 0; pd < dev_counts[icd]; ++pd) {
auto& cur_dev = cur_icd.physical_devices[pd];
// Find the ICD device matching the physical device we're looking at info for so we can compare the
// physical devices info with the returned info.
if (cur_dev.properties.apiVersion == pd_props.apiVersion && cur_dev.properties.deviceID == pd_props.deviceID &&
cur_dev.properties.deviceType == pd_props.deviceType &&
cur_dev.properties.driverVersion == pd_props.driverVersion &&
cur_dev.properties.vendorID == pd_props.vendorID) {
VkPhysicalDeviceExternalFenceInfo info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO};
VkExternalFenceProperties props{VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES};
GetPhysicalDeviceExternalFenceProperties(physical_devices[dev], &info, &props);
// No driver support for extension or 1.1 for ICD 1, all others support
ASSERT_TRUE(CompareExtFenceData(cur_dev.external_fence_properties, props, icd != 1));
found = true;
break;
}
}
if (found) {
break;
}
}
}
}
//
// VK_KHR_get_surface_capabilities2
//
// Test vkGetPhysicalDeviceSurfaceCapabilities2KHR where nothing supports it.
TEST(LoaderInstPhysDevExts, PhysDevSurfaceCaps2KHRNoSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.CheckCreate();
auto GetPhysicalDeviceSurfaceCapabilities2 = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceCapabilities2KHR"));
ASSERT_EQ(GetPhysicalDeviceSurfaceCapabilities2, nullptr);
}
// Test vkGetPhysicalDeviceSurfaceCapabilities2KHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevSurfaceCaps2KHRNoICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME);
instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
auto GetPhysicalDeviceSurfaceCapabilities2 = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceCapabilities2KHR"));
ASSERT_EQ(GetPhysicalDeviceSurfaceCapabilities2, nullptr);
}
// Fill in random but valid data into the surface capability data struct for the current physical device
static void FillInRandomSurfaceCapsData(VkSurfaceCapabilitiesKHR& props) {
props.minImageCount = (rand() % 0xFFF) + 1;
props.maxImageCount = (rand() % 0xFFF) + 1;
props.currentExtent.width = (rand() % 0xFFF) + 1;
props.currentExtent.height = (rand() % 0xFFF) + 1;
props.minImageExtent.width = (rand() % 0xFFF) + 1;
props.minImageExtent.height = (rand() % 0xFFF) + 1;
props.maxImageExtent.width = (rand() % 0xFFF) + 1;
props.maxImageExtent.height = (rand() % 0xFFF) + 1;
props.maxImageArrayLayers = (rand() % 0xFFF) + 1;
props.supportedTransforms = static_cast<VkSurfaceTransformFlagsKHR>((rand() % 0xFFF) + 1);
props.currentTransform = static_cast<VkSurfaceTransformFlagBitsKHR>((rand() % 0xFFF) + 1);
props.supportedCompositeAlpha = static_cast<VkCompositeAlphaFlagsKHR>((rand() % 0xFFF) + 1);
props.supportedUsageFlags = static_cast<VkImageUsageFlags>((rand() % 0xFFF) + 1);
}
// Compare the surface capability data structs
static bool CompareSurfaceCapsData(const VkSurfaceCapabilitiesKHR& props1, const VkSurfaceCapabilitiesKHR& props2,
bool supported = true) {
bool equal = true;
if (supported) {
equal = equal && props1.minImageCount == props2.minImageCount;
equal = equal && props1.maxImageCount == props2.maxImageCount;
equal = equal && props1.currentExtent.width == props2.currentExtent.width;
equal = equal && props1.currentExtent.height == props2.currentExtent.height;
equal = equal && props1.minImageExtent.width == props2.minImageExtent.width;
equal = equal && props1.minImageExtent.height == props2.minImageExtent.height;
equal = equal && props1.maxImageExtent.width == props2.maxImageExtent.width;
equal = equal && props1.maxImageExtent.height == props2.maxImageExtent.height;
equal = equal && props1.maxImageArrayLayers == props2.maxImageArrayLayers;
equal = equal && props1.supportedTransforms == props2.supportedTransforms;
equal = equal && props1.currentTransform == props2.currentTransform;
equal = equal && props1.supportedCompositeAlpha == props2.supportedCompositeAlpha;
equal = equal && props1.supportedUsageFlags == props2.supportedUsageFlags;
} else {
equal = equal && 0 == props2.minImageCount;
equal = equal && 0 == props2.maxImageCount;
equal = equal && 0 == props2.currentExtent.width;
equal = equal && 0 == props2.currentExtent.height;
equal = equal && 0 == props2.minImageExtent.width;
equal = equal && 0 == props2.minImageExtent.height;
equal = equal && 0 == props2.maxImageExtent.width;
equal = equal && 0 == props2.maxImageExtent.height;
equal = equal && 0 == props2.maxImageArrayLayers;
equal = equal && 0 == props2.supportedTransforms;
equal = equal && 0 == props2.currentTransform;
equal = equal && 0 == props2.supportedCompositeAlpha;
equal = equal && 0 == props2.supportedUsageFlags;
}
return equal;
}
// Test vkGetPhysicalDeviceSurfaceCapabilities2KHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, PhysDevSurfaceCaps2KHRInstanceAndICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
Extension first_ext{VK_KHR_SURFACE_EXTENSION_NAME};
Extension second_ext{VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME};
Extension third_ext{VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME};
env.get_test_icd(0).add_instance_extensions({first_ext, second_ext, third_ext});
env.get_test_icd(0).physical_devices.push_back({});
FillInRandomSurfaceCapsData(env.get_test_icd(0).physical_devices.back().surface_capabilities);
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extensions(
{VK_KHR_SURFACE_EXTENSION_NAME, VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME, VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME});
instance.CheckCreate();
auto GetPhysicalDeviceSurfaceCapabilities = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR"));
ASSERT_NE(GetPhysicalDeviceSurfaceCapabilities, nullptr);
auto CreateHeadlessSurfaceEXT = reinterpret_cast<PFN_vkCreateHeadlessSurfaceEXT>(
instance.functions->vkGetInstanceProcAddr(instance, "vkCreateHeadlessSurfaceEXT"));
ASSERT_NE(CreateHeadlessSurfaceEXT, nullptr);
auto DestroySurfaceKHR =
reinterpret_cast<PFN_vkDestroySurfaceKHR>(instance.functions->vkGetInstanceProcAddr(instance, "vkDestroySurfaceKHR"));
ASSERT_NE(DestroySurfaceKHR, nullptr);
auto GetPhysicalDeviceSurfaceCapabilities2 = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceCapabilities2KHR"));
ASSERT_NE(GetPhysicalDeviceSurfaceCapabilities2, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
VkSurfaceKHR surface;
VkHeadlessSurfaceCreateInfoEXT create_info{VK_STRUCTURE_TYPE_HEADLESS_SURFACE_CREATE_INFO_EXT};
ASSERT_EQ(VK_SUCCESS, CreateHeadlessSurfaceEXT(instance.inst, &create_info, nullptr, &surface));
VkSurfaceCapabilitiesKHR props{};
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceSurfaceCapabilities(physical_device, surface, &props));
VkPhysicalDeviceSurfaceInfo2KHR info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR, nullptr, surface};
VkSurfaceCapabilities2KHR props2{VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR};
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceSurfaceCapabilities2(physical_device, &info, &props2));
ASSERT_TRUE(CompareSurfaceCapsData(props, props2.surfaceCapabilities));
DestroySurfaceKHR(instance.inst, surface, nullptr);
}
// Test vkGetPhysicalDeviceSurfaceCapabilities2 where instance supports it with some ICDs that both support
// and don't support it:
// ICD 0 supports
// Physical device 0 does not
// Physical device 1 does
// Physical device 2 does not
// ICD 1 doesn't support
// Physical device 3 does not
// ICD 2 supports
// Physical device 4 does not
// Physical device 5 does not
// ICD 3 supports
// Physical device 6 does
TEST(LoaderInstPhysDevExts, PhysDevSurfaceCaps2KHRMixed) {
FrameworkEnvironment env{};
const uint32_t max_icd_count = 4;
const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
const uint32_t max_phys_devs = 7;
Extension first_ext{VK_KHR_SURFACE_EXTENSION_NAME};
Extension second_ext{VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME};
Extension third_ext{VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME};
for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
auto& cur_icd = env.get_test_icd(icd);
cur_icd.icd_api_version = VK_API_VERSION_1_0;
cur_icd.add_instance_extensions({first_ext, third_ext});
// ICD 1 should not have 1.1
if (icd != 1) {
cur_icd.icd_api_version = VK_API_VERSION_1_1;
cur_icd.add_instance_extension(second_ext);
}
uint32_t rand_vendor_id;
uint32_t rand_driver_vers;
FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
uint32_t device_version = VK_API_VERSION_1_0;
cur_icd.physical_devices.push_back({});
auto& cur_dev = cur_icd.physical_devices.back();
cur_dev.extensions.push_back({VK_KHR_SURFACE_EXTENSION_NAME, 0});
cur_dev.extensions.push_back({VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME, 0});
// 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
if ((icd == 0 && dev == 1) || icd == 3) {
cur_dev.extensions.push_back({VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME, 0});
device_version = VK_API_VERSION_1_1;
}
// Still set physical device properties (so we can determine if device is correct API version)
FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
FillInRandomSurfaceCapsData(cur_dev.surface_capabilities);
}
}
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extensions(
{VK_KHR_SURFACE_EXTENSION_NAME, VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME, VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME});
instance.CheckCreate();
auto GetPhysicalDeviceSurfaceCapabilities = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR"));
ASSERT_NE(GetPhysicalDeviceSurfaceCapabilities, nullptr);
auto CreateHeadlessSurfaceEXT = reinterpret_cast<PFN_vkCreateHeadlessSurfaceEXT>(
instance.functions->vkGetInstanceProcAddr(instance, "vkCreateHeadlessSurfaceEXT"));
ASSERT_NE(CreateHeadlessSurfaceEXT, nullptr);
auto DestroySurfaceKHR =
reinterpret_cast<PFN_vkDestroySurfaceKHR>(instance.functions->vkGetInstanceProcAddr(instance, "vkDestroySurfaceKHR"));
ASSERT_NE(DestroySurfaceKHR, nullptr);
auto GetPhysicalDeviceSurfaceCapabilities2 = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceCapabilities2KHR"));
ASSERT_NE(GetPhysicalDeviceSurfaceCapabilities2, nullptr);
uint32_t device_count = max_phys_devs;
std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
ASSERT_EQ(device_count, max_phys_devs);
VkSurfaceKHR surface;
VkHeadlessSurfaceCreateInfoEXT create_info{VK_STRUCTURE_TYPE_HEADLESS_SURFACE_CREATE_INFO_EXT};
ASSERT_EQ(VK_SUCCESS, CreateHeadlessSurfaceEXT(instance.inst, &create_info, nullptr, &surface));
for (uint32_t dev = 0; dev < device_count; ++dev) {
VkSurfaceCapabilitiesKHR props{};
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceSurfaceCapabilities(physical_devices[dev], surface, &props));
VkPhysicalDeviceSurfaceInfo2KHR info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR, nullptr, surface};
VkSurfaceCapabilities2KHR props2{VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR};
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceSurfaceCapabilities2(physical_devices[dev], &info, &props2));
ASSERT_TRUE(CompareSurfaceCapsData(props, props2.surfaceCapabilities));
}
DestroySurfaceKHR(instance.inst, surface, nullptr);
}
// Test vkGetPhysicalDeviceSurfaceFormats2KHR where nothing supports it.
TEST(LoaderInstPhysDevExts, PhysDevSurfaceFormats2KHRNoSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.CheckCreate();
auto GetPhysicalDeviceSurfaceFormats2 = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceFormats2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceFormats2KHR"));
ASSERT_EQ(GetPhysicalDeviceSurfaceFormats2, nullptr);
}
// Test vkGetPhysicalDeviceSurfaceFormats2KHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevSurfaceFormats2KHRNoICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME);
instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
auto GetPhysicalDeviceSurfaceFormats2 = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceFormats2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceFormats2KHR"));
ASSERT_EQ(GetPhysicalDeviceSurfaceFormats2, nullptr);
}
// Fill in random but valid data into the surface formats data struct for the current physical device
static void FillInRandomSurfaceFormatsData(std::vector<VkSurfaceFormatKHR>& props) {
props.resize((rand() % 5) + 1);
for (uint32_t i = 0; i < props.size(); ++i) {
props[i].format = static_cast<VkFormat>((rand() % 0xFFF) + 1);
props[i].colorSpace = static_cast<VkColorSpaceKHR>((rand() % 0xFFF) + 1);
}
}
// Compare the surface formats data structs
static bool CompareSurfaceFormatsData(const std::vector<VkSurfaceFormatKHR>& props1, const std::vector<VkSurfaceFormat2KHR>& props2,
bool supported = true) {
if (props1.size() != props2.size()) return false;
bool equal = true;
for (uint32_t i = 0; i < props1.size(); ++i) {
if (supported) {
equal = equal && props1[i].format == props2[i].surfaceFormat.format;
equal = equal && props1[i].colorSpace == props2[i].surfaceFormat.colorSpace;
} else {
equal = equal && 0 == props2[i].surfaceFormat.format;
equal = equal && 0 == props2[i].surfaceFormat.colorSpace;
}
}
return equal;
}
// Test vkGetPhysicalDeviceSurfaceFormats2KHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, PhysDevSurfaceFormats2KHRInstanceAndICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
Extension first_ext{VK_KHR_SURFACE_EXTENSION_NAME};
Extension second_ext{VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME};
Extension third_ext{VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME};
env.get_test_icd(0).add_instance_extensions({first_ext, second_ext, third_ext});
env.get_test_icd(0).physical_devices.push_back({});
FillInRandomSurfaceFormatsData(env.get_test_icd(0).physical_devices.back().surface_formats);
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extensions(
{VK_KHR_SURFACE_EXTENSION_NAME, VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME, VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME});
instance.CheckCreate();
auto GetPhysicalDeviceSurfaceFormats = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceFormatsKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceFormatsKHR"));
ASSERT_NE(GetPhysicalDeviceSurfaceFormats, nullptr);
auto CreateHeadlessSurfaceEXT = reinterpret_cast<PFN_vkCreateHeadlessSurfaceEXT>(
instance.functions->vkGetInstanceProcAddr(instance, "vkCreateHeadlessSurfaceEXT"));
ASSERT_NE(CreateHeadlessSurfaceEXT, nullptr);
auto DestroySurfaceKHR =
reinterpret_cast<PFN_vkDestroySurfaceKHR>(instance.functions->vkGetInstanceProcAddr(instance, "vkDestroySurfaceKHR"));
ASSERT_NE(DestroySurfaceKHR, nullptr);
auto GetPhysicalDeviceSurfaceFormats2 = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceFormats2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceFormats2KHR"));
ASSERT_NE(GetPhysicalDeviceSurfaceFormats2, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
VkSurfaceKHR surface;
VkHeadlessSurfaceCreateInfoEXT create_info{VK_STRUCTURE_TYPE_HEADLESS_SURFACE_CREATE_INFO_EXT};
ASSERT_EQ(VK_SUCCESS, CreateHeadlessSurfaceEXT(instance.inst, &create_info, nullptr, &surface));
std::vector<VkSurfaceFormatKHR> props{};
uint32_t count_1 = 0;
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceSurfaceFormats(physical_device, surface, &count_1, nullptr));
ASSERT_EQ(env.get_test_icd(0).physical_devices.back().surface_formats.size(), count_1);
props.resize(count_1);
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceSurfaceFormats(physical_device, surface, &count_1, props.data()));
ASSERT_EQ(env.get_test_icd(0).physical_devices.back().surface_formats.size(), count_1);
VkPhysicalDeviceSurfaceInfo2KHR info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR, nullptr, surface};
std::vector<VkSurfaceFormat2KHR> props2{};
uint32_t count_2 = 0;
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceSurfaceFormats2(physical_device, &info, &count_2, nullptr));
ASSERT_EQ(count_1, count_2);
props2.resize(count_2, VkSurfaceFormat2KHR{VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR});
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceSurfaceFormats2(physical_device, &info, &count_2, props2.data()));
ASSERT_TRUE(CompareSurfaceFormatsData(props, props2));
DestroySurfaceKHR(instance.inst, surface, nullptr);
}
// Test vkGetPhysicalDeviceSurfaceFormats2 where instance supports it with some ICDs that both support
// and don't support it:
// ICD 0 supports
// Physical device 0 does not
// Physical device 1 does
// Physical device 2 does not
// ICD 1 doesn't support
// Physical device 3 does not
// ICD 2 supports
// Physical device 4 does not
// Physical device 5 does not
// ICD 3 supports
// Physical device 6 does
TEST(LoaderInstPhysDevExts, PhysDevSurfaceFormats2KHRMixed) {
FrameworkEnvironment env{};
const uint32_t max_icd_count = 4;
const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
const uint32_t max_phys_devs = 7;
Extension first_ext{VK_KHR_SURFACE_EXTENSION_NAME};
Extension second_ext{VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME};
Extension third_ext{VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME};
for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
auto& cur_icd = env.get_test_icd(icd);
cur_icd.icd_api_version = VK_API_VERSION_1_0;
cur_icd.add_instance_extensions({first_ext, third_ext});
// ICD 1 should not have 1.1
if (icd != 1) {
cur_icd.icd_api_version = VK_API_VERSION_1_1;
cur_icd.add_instance_extension(second_ext);
}
uint32_t rand_vendor_id;
uint32_t rand_driver_vers;
FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
uint32_t device_version = VK_API_VERSION_1_0;
cur_icd.physical_devices.push_back({});
auto& cur_dev = cur_icd.physical_devices.back();
cur_dev.extensions.push_back({VK_KHR_SURFACE_EXTENSION_NAME, 0});
cur_dev.extensions.push_back({VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME, 0});
// 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
if ((icd == 0 && dev == 1) || icd == 3) {
cur_dev.extensions.push_back({VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME, 0});
device_version = VK_API_VERSION_1_1;
}
// Still set physical device properties (so we can determine if device is correct API version)
FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
FillInRandomSurfaceFormatsData(cur_dev.surface_formats);
}
}
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extensions(
{VK_KHR_SURFACE_EXTENSION_NAME, VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME, VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME});
instance.CheckCreate();
auto GetPhysicalDeviceSurfaceFormats = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceFormatsKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceFormatsKHR"));
ASSERT_NE(GetPhysicalDeviceSurfaceFormats, nullptr);
auto CreateHeadlessSurfaceEXT = reinterpret_cast<PFN_vkCreateHeadlessSurfaceEXT>(
instance.functions->vkGetInstanceProcAddr(instance, "vkCreateHeadlessSurfaceEXT"));
ASSERT_NE(CreateHeadlessSurfaceEXT, nullptr);
auto DestroySurfaceKHR =
reinterpret_cast<PFN_vkDestroySurfaceKHR>(instance.functions->vkGetInstanceProcAddr(instance, "vkDestroySurfaceKHR"));
ASSERT_NE(DestroySurfaceKHR, nullptr);
auto GetPhysicalDeviceSurfaceFormats2 = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceFormats2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceFormats2KHR"));
ASSERT_NE(GetPhysicalDeviceSurfaceFormats2, nullptr);
uint32_t device_count = max_phys_devs;
std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
ASSERT_EQ(device_count, max_phys_devs);
VkSurfaceKHR surface;
VkHeadlessSurfaceCreateInfoEXT create_info{VK_STRUCTURE_TYPE_HEADLESS_SURFACE_CREATE_INFO_EXT};
ASSERT_EQ(VK_SUCCESS, CreateHeadlessSurfaceEXT(instance.inst, &create_info, nullptr, &surface));
for (uint32_t dev = 0; dev < device_count; ++dev) {
std::vector<VkSurfaceFormatKHR> props{};
uint32_t count_1 = 0;
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceSurfaceFormats(physical_devices[dev], surface, &count_1, nullptr));
ASSERT_NE(0, count_1);
props.resize(count_1);
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceSurfaceFormats(physical_devices[dev], surface, &count_1, props.data()));
ASSERT_NE(0, count_1);
VkPhysicalDeviceSurfaceInfo2KHR info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR, nullptr, surface};
std::vector<VkSurfaceFormat2KHR> props2{};
uint32_t count_2 = 0;
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceSurfaceFormats2(physical_devices[dev], &info, &count_2, nullptr));
ASSERT_EQ(count_1, count_2);
props2.resize(count_2, VkSurfaceFormat2KHR{VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR});
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceSurfaceFormats2(physical_devices[dev], &info, &count_2, props2.data()));
ASSERT_EQ(count_1, count_2);
ASSERT_TRUE(CompareSurfaceFormatsData(props, props2));
}
DestroySurfaceKHR(instance.inst, surface, nullptr);
}
//
// VK_KHR_display
//
// Test vkGetPhysicalDeviceDisplayPropertiesKHR where nothing supports it.
TEST(LoaderInstPhysDevExts, PhysDevDispPropsKHRNoSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.CheckCreate();
auto GetPhysicalDeviceDisplayProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceDisplayPropertiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPropertiesKHR"));
ASSERT_EQ(GetPhysicalDeviceDisplayProperties, nullptr);
}
// Test vkGetPhysicalDeviceDisplayPropertiesKHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevDispPropsKHRNoICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_DISPLAY_EXTENSION_NAME);
instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
auto GetPhysicalDeviceDisplayProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceDisplayPropertiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPropertiesKHR"));
ASSERT_EQ(GetPhysicalDeviceDisplayProperties, nullptr);
}
VkDisplayKHR CreateRandomDisplay() { return (VkDisplayKHR)(((rand() % 0xFFFFFFFBull) << 12) * (rand() % 0xFFFFFFFull) + 1); }
VkDisplayModeKHR CreateRandomDisplayMode() {
return (VkDisplayModeKHR)(((rand() % 0xFFFFFFFBull) << 12) * (rand() % 0xFFFFFFFull) + 1);
}
// Fill in random but valid data into the display property data struct for the current physical device
static void FillInRandomDisplayPropData(std::vector<VkDisplayPropertiesKHR>& props) {
props.resize((rand() % 5) + 1);
for (uint32_t i = 0; i < props.size(); ++i) {
props[i].display = CreateRandomDisplay();
props[i].physicalDimensions.width = static_cast<uint32_t>((rand() % 0xFFF) + 1);
props[i].physicalDimensions.height = static_cast<uint32_t>((rand() % 0xFFF) + 1);
props[i].physicalResolution.width = static_cast<uint32_t>((rand() % 0xFFF) + 1);
props[i].physicalResolution.height = static_cast<uint32_t>((rand() % 0xFFF) + 1);
props[i].supportedTransforms = static_cast<VkSurfaceTransformFlagsKHR>((rand() % 0xFFE) + 1);
props[i].planeReorderPossible = rand() % 2 > 0 ? VK_TRUE : VK_FALSE;
props[i].persistentContent = rand() % 2 > 0 ? VK_TRUE : VK_FALSE;
}
}
// Compare the display property data structs
static bool CompareDisplayPropData(const std::vector<VkDisplayPropertiesKHR>& props1,
const std::vector<VkDisplayPropertiesKHR>& props2) {
if (props1.size() != props2.size()) return false;
bool equal = true;
for (uint32_t i = 0; i < props1.size(); ++i) {
equal = equal && props1[i].display == props2[i].display;
equal = equal && props1[i].physicalDimensions.width == props2[i].physicalDimensions.width;
equal = equal && props1[i].physicalDimensions.height == props2[i].physicalDimensions.height;
equal = equal && props1[i].physicalResolution.width == props2[i].physicalResolution.width;
equal = equal && props1[i].physicalResolution.height == props2[i].physicalResolution.height;
equal = equal && props1[i].supportedTransforms == props2[i].supportedTransforms;
equal = equal && props1[i].planeReorderPossible == props2[i].planeReorderPossible;
equal = equal && props1[i].persistentContent == props2[i].persistentContent;
}
return equal;
}
// Test vGetPhysicalDeviceDisplayPropertiesKHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, PhysDevDispPropsKHRInstanceAndICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
env.get_test_icd(0).physical_devices.push_back({});
FillInRandomDisplayPropData(env.get_test_icd(0).physical_devices.back().display_properties);
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
instance.CheckCreate();
auto GetPhysicalDeviceDisplayProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceDisplayPropertiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPropertiesKHR"));
ASSERT_NE(GetPhysicalDeviceDisplayProperties, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
std::vector<VkDisplayPropertiesKHR> props{};
uint32_t prop_count = 0;
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayProperties(physical_device, &prop_count, nullptr));
ASSERT_EQ(env.get_test_icd(0).physical_devices.back().display_properties.size(), prop_count);
props.resize(prop_count);
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayProperties(physical_device, &prop_count, props.data()));
ASSERT_EQ(env.get_test_icd(0).physical_devices.back().display_properties.size(), prop_count);
ASSERT_TRUE(CompareDisplayPropData(props, env.get_test_icd(0).physical_devices.back().display_properties));
}
// Test vkGetPhysicalDeviceDisplayPropertiesKHR where instance supports it with some ICDs that both support
// and don't support it:
// ICD 0 supports
// Physical device 0 does not
// Physical device 1 does
// Physical device 2 does not
// ICD 1 doesn't support
// Physical device 3 does not
// ICD 2 supports
// Physical device 4 does not
// Physical device 5 does not
// ICD 3 supports
// Physical device 6 does
TEST(LoaderInstPhysDevExts, PhysDevDispPropsKHRMixed) {
FrameworkEnvironment env{};
const uint32_t max_icd_count = 4;
const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
const uint32_t max_phys_devs = 7;
for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
auto& cur_icd = env.get_test_icd(icd);
cur_icd.icd_api_version = VK_API_VERSION_1_0;
// ICD 1 should not have 1.1
if (icd != 1) {
cur_icd.icd_api_version = VK_API_VERSION_1_1;
cur_icd.add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
}
uint32_t rand_vendor_id;
uint32_t rand_driver_vers;
FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
uint32_t device_version = VK_API_VERSION_1_0;
cur_icd.physical_devices.push_back({});
auto& cur_dev = cur_icd.physical_devices.back();
// 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
if ((icd == 0 && dev == 1) || icd == 3) {
cur_dev.extensions.push_back({VK_KHR_DISPLAY_EXTENSION_NAME, 0});
device_version = VK_API_VERSION_1_1;
}
// Still set physical device properties (so we can determine if device is correct API version)
FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
FillInRandomDisplayPropData(cur_dev.display_properties);
}
}
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_DISPLAY_EXTENSION_NAME);
instance.CheckCreate();
auto GetPhysicalDeviceDisplayProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceDisplayPropertiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPropertiesKHR"));
ASSERT_NE(GetPhysicalDeviceDisplayProperties, nullptr);
uint32_t device_count = max_phys_devs;
std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
ASSERT_EQ(device_count, max_phys_devs);
for (uint32_t dev = 0; dev < device_count; ++dev) {
VkPhysicalDeviceProperties pd_props{};
instance->vkGetPhysicalDeviceProperties(physical_devices[dev], &pd_props);
for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
auto& cur_icd = env.get_test_icd(icd);
bool found = false;
for (uint32_t pd = 0; pd < dev_counts[icd]; ++pd) {
auto& cur_dev = cur_icd.physical_devices[pd];
// Find the ICD device matching the physical device we're looking at info for so we can compare the
// physical devices info with the returned info.
if (cur_dev.properties.apiVersion == pd_props.apiVersion && cur_dev.properties.deviceID == pd_props.deviceID &&
cur_dev.properties.deviceType == pd_props.deviceType &&
cur_dev.properties.driverVersion == pd_props.driverVersion &&
cur_dev.properties.vendorID == pd_props.vendorID) {
std::vector<VkDisplayPropertiesKHR> props{};
uint32_t prop_count = 0;
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayProperties(physical_devices[dev], &prop_count, nullptr));
if (icd == 1) {
// For this extension, if no support exists (like for ICD 1), the value of 0 should be returned by the
// loader.
ASSERT_EQ(0, prop_count);
} else {
ASSERT_EQ(cur_dev.display_properties.size(), prop_count);
props.resize(prop_count);
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayProperties(physical_devices[dev], &prop_count, props.data()));
ASSERT_EQ(cur_dev.display_properties.size(), prop_count);
ASSERT_TRUE(CompareDisplayPropData(props, cur_dev.display_properties));
}
found = true;
break;
}
}
if (found) {
break;
}
}
}
}
// Test vkGetPhysicalDeviceDisplayPlanePropertiesKHR where nothing supports it.
TEST(LoaderInstPhysDevExts, PhysDevDispPlanePropsKHRNoSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.CheckCreate();
auto GetPhysicalDeviceDisplayPlaneProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPlanePropertiesKHR"));
ASSERT_EQ(GetPhysicalDeviceDisplayPlaneProperties, nullptr);
}
// Test vkGetPhysicalDeviceDisplayPlanePropertiesKHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevDispPlanePropsKHRNoICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_DISPLAY_EXTENSION_NAME);
instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
auto GetPhysicalDeviceDisplayPlaneProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPlanePropertiesKHR"));
ASSERT_EQ(GetPhysicalDeviceDisplayPlaneProperties, nullptr);
}
// Fill in random but valid data into the display plane property data struct for the current physical device
static void FillInRandomDisplayPlanePropData(std::vector<VkDisplayPlanePropertiesKHR>& props) {
props.resize((rand() % 5) + 1);
for (uint32_t i = 0; i < props.size(); ++i) {
props[i].currentDisplay = CreateRandomDisplay();
props[i].currentStackIndex = static_cast<uint32_t>((rand() % 0xFFF) + (rand() % 0xFFF) + 1);
}
}
// Compare the display plane property data structs
static bool CompareDisplayPlanePropData(const std::vector<VkDisplayPlanePropertiesKHR>& props1,
const std::vector<VkDisplayPlanePropertiesKHR>& props2) {
if (props1.size() != props2.size()) return false;
bool equal = true;
for (uint32_t i = 0; i < props1.size(); ++i) {
equal = equal && props1[i].currentDisplay == props2[i].currentDisplay;
equal = equal && props1[i].currentStackIndex == props2[i].currentStackIndex;
}
return equal;
}
// Test vGetPhysicalDeviceDisplayPlanePropertiesKHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, PhysDevDispPlanePropsKHRInstanceAndICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
env.get_test_icd(0).physical_devices.push_back({});
FillInRandomDisplayPlanePropData(env.get_test_icd(0).physical_devices.back().display_plane_properties);
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
instance.CheckCreate();
auto GetPhysicalDeviceDisplayPlaneProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPlanePropertiesKHR"));
ASSERT_NE(GetPhysicalDeviceDisplayPlaneProperties, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
std::vector<VkDisplayPlanePropertiesKHR> props{};
uint32_t prop_count = 0;
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayPlaneProperties(physical_device, &prop_count, nullptr));
ASSERT_EQ(env.get_test_icd(0).physical_devices.back().display_plane_properties.size(), prop_count);
props.resize(prop_count);
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayPlaneProperties(physical_device, &prop_count, props.data()));
ASSERT_EQ(env.get_test_icd(0).physical_devices.back().display_plane_properties.size(), prop_count);
ASSERT_TRUE(CompareDisplayPlanePropData(props, env.get_test_icd(0).physical_devices.back().display_plane_properties));
}
// Test vkGetPhysicalDeviceDisplayPlanePropertiesKHR where instance supports it with some ICDs that both support
// and don't support it:
// ICD 0 supports
// Physical device 0 does not
// Physical device 1 does
// Physical device 2 does not
// ICD 1 doesn't support
// Physical device 3 does not
// ICD 2 supports
// Physical device 4 does not
// Physical device 5 does not
// ICD 3 supports
// Physical device 6 does
TEST(LoaderInstPhysDevExts, PhysDevDispPlanePropsKHRMixed) {
FrameworkEnvironment env{};
const uint32_t max_icd_count = 4;
const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
const uint32_t max_phys_devs = 7;
for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
auto& cur_icd = env.get_test_icd(icd);
cur_icd.icd_api_version = VK_API_VERSION_1_0;
// ICD 1 should not have 1.1
if (icd != 1) {
cur_icd.icd_api_version = VK_API_VERSION_1_1;
cur_icd.add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
}
uint32_t rand_vendor_id;
uint32_t rand_driver_vers;
FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
uint32_t device_version = VK_API_VERSION_1_0;
cur_icd.physical_devices.push_back({});
auto& cur_dev = cur_icd.physical_devices.back();
// 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
if ((icd == 0 && dev == 1) || icd == 3) {
cur_dev.extensions.push_back({VK_KHR_DISPLAY_EXTENSION_NAME, 0});
device_version = VK_API_VERSION_1_1;
}
// Still set physical device properties (so we can determine if device is correct API version)
FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
FillInRandomDisplayPlanePropData(cur_dev.display_plane_properties);
}
}
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_DISPLAY_EXTENSION_NAME);
instance.CheckCreate();
auto GetPhysicalDeviceDisplayPlaneProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPlanePropertiesKHR"));
ASSERT_NE(GetPhysicalDeviceDisplayPlaneProperties, nullptr);
uint32_t device_count = max_phys_devs;
std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
ASSERT_EQ(device_count, max_phys_devs);
for (uint32_t dev = 0; dev < device_count; ++dev) {
VkPhysicalDeviceProperties pd_props{};
instance->vkGetPhysicalDeviceProperties(physical_devices[dev], &pd_props);
for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
auto& cur_icd = env.get_test_icd(icd);
bool found = false;
for (uint32_t pd = 0; pd < dev_counts[icd]; ++pd) {
auto& cur_dev = cur_icd.physical_devices[pd];
// Find the ICD device matching the physical device we're looking at info for so we can compare the
// physical devices info with the returned info.
if (cur_dev.properties.apiVersion == pd_props.apiVersion && cur_dev.properties.deviceID == pd_props.deviceID &&
cur_dev.properties.deviceType == pd_props.deviceType &&
cur_dev.properties.driverVersion == pd_props.driverVersion &&
cur_dev.properties.vendorID == pd_props.vendorID) {
std::vector<VkDisplayPlanePropertiesKHR> props{};
uint32_t prop_count = 0;
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayPlaneProperties(physical_devices[dev], &prop_count, nullptr));
if (icd == 1) {
// For this extension, if no support exists (like for ICD 1), the value of 0 should be returned by the
// loader.
ASSERT_EQ(0, prop_count);
} else {
ASSERT_EQ(cur_dev.display_plane_properties.size(), prop_count);
props.resize(prop_count);
ASSERT_EQ(VK_SUCCESS,
GetPhysicalDeviceDisplayPlaneProperties(physical_devices[dev], &prop_count, props.data()));
ASSERT_EQ(cur_dev.display_plane_properties.size(), prop_count);
ASSERT_TRUE(CompareDisplayPlanePropData(props, cur_dev.display_plane_properties));
}
found = true;
break;
}
}
if (found) {
break;
}
}
}
}
// Test vkGetDisplayPlaneSupportedDisplaysKHR where nothing supports it.
TEST(LoaderInstPhysDevExts, GetDispPlaneSupDispsKHRNoSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.CheckCreate();
auto GetDisplayPlaneSupportedDisplays = reinterpret_cast<PFN_vkGetDisplayPlaneSupportedDisplaysKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetDisplayPlaneSupportedDisplaysKHR"));
ASSERT_EQ(GetDisplayPlaneSupportedDisplays, nullptr);
}
// Test vkGetDisplayPlaneSupportedDisplaysKHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, GetDispPlaneSupDispsKHRNoICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_DISPLAY_EXTENSION_NAME);
instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
auto GetDisplayPlaneSupportedDisplays = reinterpret_cast<PFN_vkGetDisplayPlaneSupportedDisplaysKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetDisplayPlaneSupportedDisplaysKHR"));
ASSERT_EQ(GetDisplayPlaneSupportedDisplays, nullptr);
}
// Fill in random but valid data into the display plane property data struct for the current physical device
static void GenerateRandomDisplays(std::vector<VkDisplayKHR>& disps) {
disps.resize((rand() % 5) + 1);
for (uint32_t i = 0; i < disps.size(); ++i) {
disps[i] = CreateRandomDisplay();
}
}
// Compare the display plane property data structs
static bool CompareDisplays(const std::vector<VkDisplayKHR>& disps1, const std::vector<VkDisplayKHR>& disps2) {
if (disps1.size() != disps2.size()) return false;
bool equal = true;
for (uint32_t i = 0; i < disps1.size(); ++i) {
equal = equal && disps1[i] == disps2[i];
}
return equal;
}
// Test vGetDisplayPlaneSupportedDisplaysKHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, GetDispPlaneSupDispsKHRInstanceAndICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
env.get_test_icd(0).physical_devices.push_back({});
GenerateRandomDisplays(env.get_test_icd(0).physical_devices.back().displays);
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
instance.CheckCreate();
auto GetDisplayPlaneSupportedDisplays = reinterpret_cast<PFN_vkGetDisplayPlaneSupportedDisplaysKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetDisplayPlaneSupportedDisplaysKHR"));
ASSERT_NE(GetDisplayPlaneSupportedDisplays, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
std::vector<VkDisplayKHR> disps{};
uint32_t disp_count = 0;
ASSERT_EQ(VK_SUCCESS, GetDisplayPlaneSupportedDisplays(physical_device, 0, &disp_count, nullptr));
ASSERT_EQ(env.get_test_icd(0).physical_devices.back().displays.size(), disp_count);
disps.resize(disp_count);
ASSERT_EQ(VK_SUCCESS, GetDisplayPlaneSupportedDisplays(physical_device, 0, &disp_count, disps.data()));
ASSERT_EQ(env.get_test_icd(0).physical_devices.back().displays.size(), disp_count);
ASSERT_TRUE(CompareDisplays(disps, env.get_test_icd(0).physical_devices.back().displays));
}
// Test vkGetDisplayPlaneSupportedDisplaysKHR where instance supports it with some ICDs that both support
// and don't support it:
// ICD 0 supports
// Physical device 0 does not
// Physical device 1 does
// Physical device 2 does not
// ICD 1 doesn't support
// Physical device 3 does not
// ICD 2 supports
// Physical device 4 does not
// Physical device 5 does not
// ICD 3 supports
// Physical device 6 does
TEST(LoaderInstPhysDevExts, GetDispPlaneSupDispsKHRMixed) {
FrameworkEnvironment env{};
const uint32_t max_icd_count = 4;
const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
const uint32_t max_phys_devs = 7;
for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
auto& cur_icd = env.get_test_icd(icd);
cur_icd.icd_api_version = VK_API_VERSION_1_0;
// ICD 1 should not have 1.1
if (icd != 1) {
cur_icd.icd_api_version = VK_API_VERSION_1_1;
cur_icd.add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
}
uint32_t rand_vendor_id;
uint32_t rand_driver_vers;
FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
uint32_t device_version = VK_API_VERSION_1_0;
cur_icd.physical_devices.push_back({});
auto& cur_dev = cur_icd.physical_devices.back();
// 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
if ((icd == 0 && dev == 1) || icd == 3) {
cur_dev.extensions.push_back({VK_KHR_DISPLAY_EXTENSION_NAME, 0});
device_version = VK_API_VERSION_1_1;
}
// Still set physical device properties (so we can determine if device is correct API version)
FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
GenerateRandomDisplays(cur_dev.displays);
}
}
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_DISPLAY_EXTENSION_NAME);
instance.CheckCreate();
auto GetDisplayPlaneSupportedDisplays = reinterpret_cast<PFN_vkGetDisplayPlaneSupportedDisplaysKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetDisplayPlaneSupportedDisplaysKHR"));
ASSERT_NE(GetDisplayPlaneSupportedDisplays, nullptr);
uint32_t device_count = max_phys_devs;
std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
ASSERT_EQ(device_count, max_phys_devs);
for (uint32_t dev = 0; dev < device_count; ++dev) {
VkPhysicalDeviceProperties pd_props{};
instance->vkGetPhysicalDeviceProperties(physical_devices[dev], &pd_props);
for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
auto& cur_icd = env.get_test_icd(icd);
bool found = false;
for (uint32_t pd = 0; pd < dev_counts[icd]; ++pd) {
auto& cur_dev = cur_icd.physical_devices[pd];
// Find the ICD device matching the physical device we're looking at info for so we can compare the
// physical devices info with the returned info.
if (cur_dev.properties.apiVersion == pd_props.apiVersion && cur_dev.properties.deviceID == pd_props.deviceID &&
cur_dev.properties.deviceType == pd_props.deviceType &&
cur_dev.properties.driverVersion == pd_props.driverVersion &&
cur_dev.properties.vendorID == pd_props.vendorID) {
std::vector<VkDisplayKHR> disps{};
uint32_t disp_count = 0;
ASSERT_EQ(VK_SUCCESS, GetDisplayPlaneSupportedDisplays(physical_devices[dev], 0, &disp_count, nullptr));
if (icd == 1) {
// For this extension, if no support exists (like for ICD 1), the value of 0 should be returned by the
// loader.
ASSERT_EQ(0, disp_count);
} else {
ASSERT_EQ(cur_dev.displays.size(), disp_count);
disps.resize(disp_count);
ASSERT_EQ(VK_SUCCESS,
GetDisplayPlaneSupportedDisplays(physical_devices[dev], 0, &disp_count, disps.data()));
ASSERT_EQ(cur_dev.displays.size(), disp_count);
ASSERT_TRUE(CompareDisplays(disps, cur_dev.displays));
}
found = true;
break;
}
}
if (found) {
break;
}
}
}
}
// Test vkGetDisplayModePropertiesKHR where nothing supports it.
TEST(LoaderInstPhysDevExts, GetDispModePropsKHRNoSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.CheckCreate();
auto GetDisplayModeProperties = reinterpret_cast<PFN_vkGetDisplayModePropertiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetDisplayModePropertiesKHR"));
ASSERT_EQ(GetDisplayModeProperties, nullptr);
}
// Test vkGetDisplayModePropertiesKHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, GetDispModePropsKHRNoICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_DISPLAY_EXTENSION_NAME);
instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
auto GetDisplayModeProperties = reinterpret_cast<PFN_vkGetDisplayModePropertiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetDisplayModePropertiesKHR"));
ASSERT_EQ(GetDisplayModeProperties, nullptr);
}
// Fill in random but valid data into the display mode properties data struct for the current physical device
static void GenerateRandomDisplayModeProps(std::vector<VkDisplayModePropertiesKHR>& disps) {
disps.resize((rand() % 5) + 1);
for (uint32_t i = 0; i < disps.size(); ++i) {
disps[i].displayMode = CreateRandomDisplayMode();
disps[i].parameters.visibleRegion.width = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
disps[i].parameters.visibleRegion.height = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
disps[i].parameters.refreshRate = 1 << (rand() % 8);
}
}
// Compare the display mode properties data structs
static bool CompareDisplayModeProps(const std::vector<VkDisplayModePropertiesKHR>& disps1,
const std::vector<VkDisplayModePropertiesKHR>& disps2) {
if (disps1.size() != disps2.size()) return false;
bool equal = true;
for (uint32_t i = 0; i < disps1.size(); ++i) {
equal = equal && disps1[i].displayMode == disps2[i].displayMode;
equal = equal && disps1[i].parameters.visibleRegion.width == disps2[i].parameters.visibleRegion.width;
equal = equal && disps1[i].parameters.visibleRegion.height == disps2[i].parameters.visibleRegion.height;
equal = equal && disps1[i].parameters.refreshRate == disps2[i].parameters.refreshRate;
}
return equal;
}
// Test vGetDisplayModePropertiesKHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, GetDispModePropsKHRInstanceAndICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
env.get_test_icd(0).physical_devices.push_back({});
GenerateRandomDisplayModeProps(env.get_test_icd(0).physical_devices.back().display_mode_properties);
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
instance.CheckCreate();
auto GetDisplayModeProperties = reinterpret_cast<PFN_vkGetDisplayModePropertiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetDisplayModePropertiesKHR"));
ASSERT_NE(GetDisplayModeProperties, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
std::vector<VkDisplayModePropertiesKHR> props{};
uint32_t props_count = 0;
ASSERT_EQ(VK_SUCCESS, GetDisplayModeProperties(physical_device, VK_NULL_HANDLE, &props_count, nullptr));
ASSERT_EQ(env.get_test_icd(0).physical_devices.back().display_mode_properties.size(), props_count);
props.resize(props_count);
ASSERT_EQ(VK_SUCCESS, GetDisplayModeProperties(physical_device, VK_NULL_HANDLE, &props_count, props.data()));
ASSERT_EQ(env.get_test_icd(0).physical_devices.back().display_mode_properties.size(), props_count);
ASSERT_TRUE(CompareDisplayModeProps(props, env.get_test_icd(0).physical_devices.back().display_mode_properties));
}
// Test vkGetDisplayModePropertiesKHR where instance supports it with some ICDs that both support
// and don't support it:
// ICD 0 supports
// Physical device 0 does not
// Physical device 1 does
// Physical device 2 does not
// ICD 1 doesn't support
// Physical device 3 does not
// ICD 2 supports
// Physical device 4 does not
// Physical device 5 does not
// ICD 3 supports
// Physical device 6 does
TEST(LoaderInstPhysDevExts, GetDispModePropsKHRMixed) {
FrameworkEnvironment env{};
const uint32_t max_icd_count = 4;
const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
const uint32_t max_phys_devs = 7;
for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
auto& cur_icd = env.get_test_icd(icd);
cur_icd.icd_api_version = VK_API_VERSION_1_0;
// ICD 1 should not have 1.1
if (icd != 1) {
cur_icd.icd_api_version = VK_API_VERSION_1_1;
cur_icd.add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
}
uint32_t rand_vendor_id;
uint32_t rand_driver_vers;
FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
uint32_t device_version = VK_API_VERSION_1_0;
cur_icd.physical_devices.push_back({});
auto& cur_dev = cur_icd.physical_devices.back();
// 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
if ((icd == 0 && dev == 1) || icd == 3) {
cur_dev.extensions.push_back({VK_KHR_DISPLAY_EXTENSION_NAME, 0});
device_version = VK_API_VERSION_1_1;
}
// Still set physical device properties (so we can determine if device is correct API version)
FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
GenerateRandomDisplayModeProps(cur_dev.display_mode_properties);
}
}
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_DISPLAY_EXTENSION_NAME);
instance.CheckCreate();
auto GetDisplayModeProperties = reinterpret_cast<PFN_vkGetDisplayModePropertiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetDisplayModePropertiesKHR"));
ASSERT_NE(GetDisplayModeProperties, nullptr);
uint32_t device_count = max_phys_devs;
std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
ASSERT_EQ(device_count, max_phys_devs);
for (uint32_t dev = 0; dev < device_count; ++dev) {
VkPhysicalDeviceProperties pd_props{};
instance->vkGetPhysicalDeviceProperties(physical_devices[dev], &pd_props);
for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
auto& cur_icd = env.get_test_icd(icd);
bool found = false;
for (uint32_t pd = 0; pd < dev_counts[icd]; ++pd) {
auto& cur_dev = cur_icd.physical_devices[pd];
// Find the ICD device matching the physical device we're looking at info for so we can compare the
// physical devices info with the returned info.
if (cur_dev.properties.apiVersion == pd_props.apiVersion && cur_dev.properties.deviceID == pd_props.deviceID &&
cur_dev.properties.deviceType == pd_props.deviceType &&
cur_dev.properties.driverVersion == pd_props.driverVersion &&
cur_dev.properties.vendorID == pd_props.vendorID) {
uint32_t props_count = 0;
ASSERT_EQ(VK_SUCCESS, GetDisplayModeProperties(physical_devices[dev], VK_NULL_HANDLE, &props_count, nullptr));
if (icd == 1) {
// For this extension, if no support exists (like for ICD 1), the value of 0 should be returned by the
// loader.
ASSERT_EQ(0, props_count);
} else {
std::vector<VkDisplayModePropertiesKHR> props{};
ASSERT_EQ(cur_dev.display_mode_properties.size(), props_count);
props.resize(props_count);
ASSERT_EQ(VK_SUCCESS,
GetDisplayModeProperties(physical_devices[dev], VK_NULL_HANDLE, &props_count, props.data()));
ASSERT_EQ(cur_dev.display_mode_properties.size(), props_count);
ASSERT_TRUE(CompareDisplayModeProps(props, cur_dev.display_mode_properties));
}
found = true;
break;
}
}
if (found) {
break;
}
}
}
}
// Test vkCreateDisplayModeKHR where nothing supports it.
TEST(LoaderInstPhysDevExts, GetDispModesKHRNoSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.CheckCreate();
auto CreateDisplayMode =
reinterpret_cast<PFN_vkCreateDisplayModeKHR>(instance.functions->vkGetInstanceProcAddr(instance, "vkCreateDisplayModeKHR"));
ASSERT_EQ(CreateDisplayMode, nullptr);
}
// Test vkCreateDisplayModeKHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, GetDispModesKHRNoICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_DISPLAY_EXTENSION_NAME);
instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
auto CreateDisplayMode =
reinterpret_cast<PFN_vkCreateDisplayModeKHR>(instance.functions->vkGetInstanceProcAddr(instance, "vkCreateDisplayModeKHR"));
ASSERT_EQ(CreateDisplayMode, nullptr);
}
// Compare the display modes
static bool CompareDisplayModes(const VkDisplayModeKHR& disps1, VkDisplayModeKHR& disps2) { return disps1 == disps2; }
// Test vkCreateDisplayModeKHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, GetDispModesKHRInstanceAndICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
env.get_test_icd(0).physical_devices.push_back({});
env.get_test_icd(0).physical_devices.back().display_mode = CreateRandomDisplayMode();
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
instance.CheckCreate();
auto CreateDisplayMode =
reinterpret_cast<PFN_vkCreateDisplayModeKHR>(instance.functions->vkGetInstanceProcAddr(instance, "vkCreateDisplayModeKHR"));
ASSERT_NE(CreateDisplayMode, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
VkDisplayModeKHR mode{};
VkDisplayModeCreateInfoKHR create_info{VK_STRUCTURE_TYPE_DISPLAY_MODE_CREATE_INFO_KHR};
ASSERT_EQ(VK_SUCCESS, CreateDisplayMode(physical_device, VK_NULL_HANDLE, &create_info, nullptr, &mode));
ASSERT_TRUE(CompareDisplayModes(mode, env.get_test_icd(0).physical_devices.back().display_mode));
}
// Test vkCreateDisplayModeKHR where instance supports it with some ICDs that both support
// and don't support it:
// ICD 0 supports
// Physical device 0 does not
// Physical device 1 does
// Physical device 2 does not
// ICD 1 doesn't support
// Physical device 3 does not
// ICD 2 supports
// Physical device 4 does not
// Physical device 5 does not
// ICD 3 supports
// Physical device 6 does
TEST(LoaderInstPhysDevExts, GetDispModesKHRMixed) {
FrameworkEnvironment env{};
const uint32_t max_icd_count = 4;
const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
const uint32_t max_phys_devs = 7;
for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
auto& cur_icd = env.get_test_icd(icd);
cur_icd.icd_api_version = VK_API_VERSION_1_0;
// ICD 1 should not have 1.1
if (icd != 1) {
cur_icd.icd_api_version = VK_API_VERSION_1_1;
cur_icd.add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
}
uint32_t rand_vendor_id;
uint32_t rand_driver_vers;
FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
uint32_t device_version = VK_API_VERSION_1_0;
cur_icd.physical_devices.push_back({});
auto& cur_dev = cur_icd.physical_devices.back();
// 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
if ((icd == 0 && dev == 1) || icd == 3) {
cur_dev.extensions.push_back({VK_KHR_DISPLAY_EXTENSION_NAME, 0});
device_version = VK_API_VERSION_1_1;
}
// Still set physical device properties (so we can determine if device is correct API version)
FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
cur_dev.display_mode = CreateRandomDisplayMode();
}
}
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_DISPLAY_EXTENSION_NAME);
instance.CheckCreate();
auto CreateDisplayMode =
reinterpret_cast<PFN_vkCreateDisplayModeKHR>(instance.functions->vkGetInstanceProcAddr(instance, "vkCreateDisplayModeKHR"));
ASSERT_NE(CreateDisplayMode, nullptr);
uint32_t device_count = max_phys_devs;
std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
ASSERT_EQ(device_count, max_phys_devs);
for (uint32_t dev = 0; dev < device_count; ++dev) {
VkPhysicalDeviceProperties pd_props{};
instance->vkGetPhysicalDeviceProperties(physical_devices[dev], &pd_props);
for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
auto& cur_icd = env.get_test_icd(icd);
bool found = false;
for (uint32_t pd = 0; pd < dev_counts[icd]; ++pd) {
auto& cur_dev = cur_icd.physical_devices[pd];
// Find the ICD device matching the physical device we're looking at info for so we can compare the
// physical devices info with the returned info.
if (cur_dev.properties.apiVersion == pd_props.apiVersion && cur_dev.properties.deviceID == pd_props.deviceID &&
cur_dev.properties.deviceType == pd_props.deviceType &&
cur_dev.properties.driverVersion == pd_props.driverVersion &&
cur_dev.properties.vendorID == pd_props.vendorID) {
VkDisplayModeKHR mode{};
VkDisplayModeCreateInfoKHR create_info{VK_STRUCTURE_TYPE_DISPLAY_MODE_CREATE_INFO_KHR};
if (icd == 1) {
// Unsupported ICD should return initialization failed (instead of crash)
ASSERT_EQ(VK_ERROR_INITIALIZATION_FAILED,
CreateDisplayMode(physical_devices[dev], VK_NULL_HANDLE, &create_info, nullptr, &mode));
} else {
ASSERT_EQ(VK_SUCCESS,
CreateDisplayMode(physical_devices[dev], VK_NULL_HANDLE, &create_info, nullptr, &mode));
ASSERT_TRUE(CompareDisplayModes(mode, cur_dev.display_mode));
}
found = true;
break;
}
}
if (found) {
break;
}
}
}
}
// Test vkGetDisplayPlaneCapabilitiesKHR where nothing supports it.
TEST(LoaderInstPhysDevExts, GetDispPlaneCapsKHRNoSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.CheckCreate();
auto GetDisplayPlaneCapabilities = reinterpret_cast<PFN_vkGetDisplayPlaneCapabilitiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetDisplayPlaneCapabilitiesKHR"));
ASSERT_EQ(GetDisplayPlaneCapabilities, nullptr);
}
// Test vkGetDisplayPlaneCapabilitiesKHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, GetDispPlaneCapsKHRNoICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_DISPLAY_EXTENSION_NAME);
instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
auto GetDisplayPlaneCapabilities = reinterpret_cast<PFN_vkGetDisplayPlaneCapabilitiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetDisplayPlaneCapabilitiesKHR"));
ASSERT_EQ(GetDisplayPlaneCapabilities, nullptr);
}
// Fill in random but valid data into the display plane caps for the current physical device
static void GenerateRandomDisplayPlaneCaps(VkDisplayPlaneCapabilitiesKHR& caps) {
caps.supportedAlpha = static_cast<VkDisplayPlaneAlphaFlagsKHR>((rand() % 0xFFFFFFF) + 1);
caps.minSrcPosition.x = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
caps.minSrcPosition.y = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
caps.maxSrcPosition.x = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
caps.maxSrcPosition.y = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
caps.minSrcExtent.width = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
caps.minSrcExtent.height = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
caps.maxSrcExtent.width = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
caps.maxSrcExtent.height = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
caps.minDstPosition.x = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
caps.minDstPosition.y = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
caps.maxDstPosition.x = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
caps.maxDstPosition.y = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
caps.minDstExtent.width = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
caps.minDstExtent.height = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
caps.maxDstExtent.width = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
caps.maxDstExtent.height = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
}
// Compare the display plane caps
static bool CompareDisplayPlaneCaps(const VkDisplayPlaneCapabilitiesKHR& caps1, VkDisplayPlaneCapabilitiesKHR& caps2,
bool supported = true) {
bool equal = true;
if (supported) {
equal = equal && caps1.supportedAlpha == caps2.supportedAlpha;
equal = equal && caps1.minSrcPosition.x == caps2.minSrcPosition.x;
equal = equal && caps1.minSrcPosition.y == caps2.minSrcPosition.y;
equal = equal && caps1.maxSrcPosition.x == caps2.maxSrcPosition.x;
equal = equal && caps1.maxSrcPosition.y == caps2.maxSrcPosition.y;
equal = equal && caps1.minSrcExtent.width == caps2.minSrcExtent.width;
equal = equal && caps1.minSrcExtent.height == caps2.minSrcExtent.height;
equal = equal && caps1.maxSrcExtent.width == caps2.maxSrcExtent.width;
equal = equal && caps1.maxSrcExtent.height == caps2.maxSrcExtent.height;
equal = equal && caps1.minDstPosition.x == caps2.minDstPosition.x;
equal = equal && caps1.minDstPosition.y == caps2.minDstPosition.y;
equal = equal && caps1.maxDstPosition.x == caps2.maxDstPosition.x;
equal = equal && caps1.maxDstPosition.y == caps2.maxDstPosition.y;
equal = equal && caps1.minDstExtent.width == caps2.minDstExtent.width;
equal = equal && caps1.minDstExtent.height == caps2.minDstExtent.height;
equal = equal && caps1.maxDstExtent.width == caps2.maxDstExtent.width;
equal = equal && caps1.maxDstExtent.height == caps2.maxDstExtent.height;
} else {
equal = equal && caps1.supportedAlpha == 0;
equal = equal && caps1.minSrcPosition.x == 0;
equal = equal && caps1.minSrcPosition.y == 0;
equal = equal && caps1.maxSrcPosition.x == 0;
equal = equal && caps1.maxSrcPosition.y == 0;
equal = equal && caps1.minSrcExtent.width == 0;
equal = equal && caps1.minSrcExtent.height == 0;
equal = equal && caps1.maxSrcExtent.width == 0;
equal = equal && caps1.maxSrcExtent.height == 0;
equal = equal && caps1.minDstPosition.x == 0;
equal = equal && caps1.minDstPosition.y == 0;
equal = equal && caps1.maxDstPosition.x == 0;
equal = equal && caps1.maxDstPosition.y == 0;
equal = equal && caps1.minDstExtent.width == 0;
equal = equal && caps1.minDstExtent.height == 0;
equal = equal && caps1.maxDstExtent.width == 0;
equal = equal && caps1.maxDstExtent.height == 0;
}
return equal;
}
// Test vkGetDisplayPlaneCapabilitiesKHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, GetDispPlaneCapsKHRInstanceAndICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
env.get_test_icd(0).physical_devices.push_back({});
GenerateRandomDisplayPlaneCaps(env.get_test_icd(0).physical_devices.back().display_plane_capabilities);
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
instance.CheckCreate();
auto GetDisplayPlaneCapabilities = reinterpret_cast<PFN_vkGetDisplayPlaneCapabilitiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetDisplayPlaneCapabilitiesKHR"));
ASSERT_NE(GetDisplayPlaneCapabilities, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
VkDisplayPlaneCapabilitiesKHR caps{};
ASSERT_EQ(VK_SUCCESS, GetDisplayPlaneCapabilities(physical_device, 0, 0, &caps));
ASSERT_TRUE(CompareDisplayPlaneCaps(caps, env.get_test_icd(0).physical_devices.back().display_plane_capabilities));
}
// Test vkGetDisplayPlaneCapabilitiesKHR where instance supports it with some ICDs that both support
// and don't support it:
// ICD 0 supports
// Physical device 0 does not
// Physical device 1 does
// Physical device 2 does not
// ICD 1 doesn't support
// Physical device 3 does not
// ICD 2 supports
// Physical device 4 does not
// Physical device 5 does not
// ICD 3 supports
// Physical device 6 does
TEST(LoaderInstPhysDevExts, GetDispPlaneCapsKHRMixed) {
FrameworkEnvironment env{};
const uint32_t max_icd_count = 4;
const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
const uint32_t max_phys_devs = 7;
for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
auto& cur_icd = env.get_test_icd(icd);
cur_icd.icd_api_version = VK_API_VERSION_1_0;
// ICD 1 should not have 1.1
if (icd != 1) {
cur_icd.icd_api_version = VK_API_VERSION_1_1;
cur_icd.add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
}
uint32_t rand_vendor_id;
uint32_t rand_driver_vers;
FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
uint32_t device_version = VK_API_VERSION_1_0;
cur_icd.physical_devices.push_back({});
auto& cur_dev = cur_icd.physical_devices.back();
// 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
if ((icd == 0 && dev == 1) || icd == 3) {
cur_dev.extensions.push_back({VK_KHR_DISPLAY_EXTENSION_NAME, 0});
device_version = VK_API_VERSION_1_1;
}
// Still set physical device properties (so we can determine if device is correct API version)
FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
GenerateRandomDisplayPlaneCaps(cur_dev.display_plane_capabilities);
}
}
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_DISPLAY_EXTENSION_NAME);
instance.CheckCreate();
auto GetDisplayPlaneCapabilities = reinterpret_cast<PFN_vkGetDisplayPlaneCapabilitiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetDisplayPlaneCapabilitiesKHR"));
ASSERT_NE(GetDisplayPlaneCapabilities, nullptr);
uint32_t device_count = max_phys_devs;
std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
ASSERT_EQ(device_count, max_phys_devs);
for (uint32_t dev = 0; dev < device_count; ++dev) {
VkPhysicalDeviceProperties pd_props{};
instance->vkGetPhysicalDeviceProperties(physical_devices[dev], &pd_props);
for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
auto& cur_icd = env.get_test_icd(icd);
bool found = false;
for (uint32_t pd = 0; pd < dev_counts[icd]; ++pd) {
auto& cur_dev = cur_icd.physical_devices[pd];
// Find the ICD device matching the physical device we're looking at info for so we can compare the
// physical devices info with the returned info.
if (cur_dev.properties.apiVersion == pd_props.apiVersion && cur_dev.properties.deviceID == pd_props.deviceID &&
cur_dev.properties.deviceType == pd_props.deviceType &&
cur_dev.properties.driverVersion == pd_props.driverVersion &&
cur_dev.properties.vendorID == pd_props.vendorID) {
VkDisplayPlaneCapabilitiesKHR caps{};
ASSERT_EQ(VK_SUCCESS, GetDisplayPlaneCapabilities(physical_devices[dev], 0, 0, &caps));
ASSERT_TRUE(CompareDisplayPlaneCaps(caps, cur_dev.display_plane_capabilities, icd != 1));
found = true;
break;
}
}
if (found) {
break;
}
}
}
}
//
// VK_KHR_get_display_properties2
//
// Test vkGetPhysicalDeviceDisplayProperties2KHR where nothing supports it.
TEST(LoaderInstPhysDevExts, PhysDevDispProps2KHRNoSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.CheckCreate();
auto GetPhysicalDeviceDisplayProperties2 = reinterpret_cast<PFN_vkGetPhysicalDeviceDisplayProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayProperties2KHR"));
ASSERT_EQ(GetPhysicalDeviceDisplayProperties2, nullptr);
}
// Test vkGetPhysicalDeviceDisplayProperties2KHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevDispProps2KHRNoICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME);
instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
auto GetPhysicalDeviceDisplayProperties2 = reinterpret_cast<PFN_vkGetPhysicalDeviceDisplayProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayProperties2KHR"));
ASSERT_EQ(GetPhysicalDeviceDisplayProperties2, nullptr);
}
// Compare the display property data structs
static bool CompareDisplayPropData(const std::vector<VkDisplayPropertiesKHR>& props1,
const std::vector<VkDisplayProperties2KHR>& props2) {
if (props1.size() != props2.size()) return false;
bool equal = true;
for (uint32_t i = 0; i < props1.size(); ++i) {
equal = equal && props1[i].display == props2[i].displayProperties.display;
equal = equal && props1[i].physicalDimensions.width == props2[i].displayProperties.physicalDimensions.width;
equal = equal && props1[i].physicalDimensions.height == props2[i].displayProperties.physicalDimensions.height;
equal = equal && props1[i].physicalResolution.width == props2[i].displayProperties.physicalResolution.width;
equal = equal && props1[i].physicalResolution.height == props2[i].displayProperties.physicalResolution.height;
equal = equal && props1[i].supportedTransforms == props2[i].displayProperties.supportedTransforms;
equal = equal && props1[i].planeReorderPossible == props2[i].displayProperties.planeReorderPossible;
equal = equal && props1[i].persistentContent == props2[i].displayProperties.persistentContent;
}
return equal;
}
// Test vGetPhysicalDeviceDisplayProperties2KHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, PhysDevDispProps2KHRInstanceAndICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
Extension first_ext{VK_KHR_DISPLAY_EXTENSION_NAME};
Extension second_ext{VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME};
env.get_test_icd(0).add_instance_extensions({first_ext, second_ext});
env.get_test_icd(0).physical_devices.push_back({});
FillInRandomDisplayPropData(env.get_test_icd(0).physical_devices.back().display_properties);
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extensions({VK_KHR_DISPLAY_EXTENSION_NAME, VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME});
instance.CheckCreate();
auto GetPhysicalDeviceDisplayProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceDisplayPropertiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPropertiesKHR"));
ASSERT_NE(GetPhysicalDeviceDisplayProperties, nullptr);
auto GetPhysicalDeviceDisplayProperties2 = reinterpret_cast<PFN_vkGetPhysicalDeviceDisplayProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayProperties2KHR"));
ASSERT_NE(GetPhysicalDeviceDisplayProperties2, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
std::vector<VkDisplayPropertiesKHR> props{};
uint32_t prop_count = 0;
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayProperties(physical_device, &prop_count, nullptr));
ASSERT_NE(0, prop_count);
props.resize(prop_count);
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayProperties(physical_device, &prop_count, props.data()));
std::vector<VkDisplayProperties2KHR> props2{};
uint32_t prop_count_2 = 0;
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayProperties2(physical_device, &prop_count_2, nullptr));
ASSERT_EQ(prop_count, prop_count_2);
props2.resize(prop_count_2, {VK_STRUCTURE_TYPE_DISPLAY_PROPERTIES_2_KHR});
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayProperties2(physical_device, &prop_count_2, props2.data()));
ASSERT_EQ(prop_count, prop_count_2);
ASSERT_TRUE(CompareDisplayPropData(props, props2));
}
// Test vkGetPhysicalDeviceDisplayProperties2KHR where instance supports it with some ICDs that both support
// and don't support it:
// ICD 0 supports
// Physical device 0 does not
// Physical device 1 does
// Physical device 2 does not
// ICD 1 doesn't support
// Physical device 3 does not
// ICD 2 supports
// Physical device 4 does not
// Physical device 5 does not
// ICD 3 supports
// Physical device 6 does
TEST(LoaderInstPhysDevExts, PhysDevDispProps2KHRMixed) {
FrameworkEnvironment env{};
const uint32_t max_icd_count = 4;
const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
const uint32_t max_phys_devs = 7;
for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
auto& cur_icd = env.get_test_icd(icd);
cur_icd.icd_api_version = VK_API_VERSION_1_0;
cur_icd.add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
// ICD 1 should not have 1.1
if (icd != 1) {
cur_icd.icd_api_version = VK_API_VERSION_1_1;
cur_icd.add_instance_extension({VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME});
}
uint32_t rand_vendor_id;
uint32_t rand_driver_vers;
FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
uint32_t device_version = VK_API_VERSION_1_0;
cur_icd.physical_devices.push_back({});
auto& cur_dev = cur_icd.physical_devices.back();
cur_dev.extensions.push_back({VK_KHR_DISPLAY_EXTENSION_NAME, 0});
// 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
if ((icd == 0 && dev == 1) || icd == 3) {
cur_dev.extensions.push_back({VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME, 0});
device_version = VK_API_VERSION_1_1;
}
// Still set physical device properties (so we can determine if device is correct API version)
FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
FillInRandomDisplayPropData(cur_dev.display_properties);
}
}
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extensions({VK_KHR_DISPLAY_EXTENSION_NAME, VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME});
instance.CheckCreate();
auto GetPhysicalDeviceDisplayProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceDisplayPropertiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPropertiesKHR"));
ASSERT_NE(GetPhysicalDeviceDisplayProperties, nullptr);
auto GetPhysicalDeviceDisplayProperties2 = reinterpret_cast<PFN_vkGetPhysicalDeviceDisplayProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayProperties2KHR"));
ASSERT_NE(GetPhysicalDeviceDisplayProperties2, nullptr);
uint32_t device_count = max_phys_devs;
std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
ASSERT_EQ(device_count, max_phys_devs);
for (uint32_t dev = 0; dev < device_count; ++dev) {
std::vector<VkDisplayPropertiesKHR> props{};
uint32_t prop_count = 0;
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayProperties(physical_devices[dev], &prop_count, nullptr));
ASSERT_NE(0, prop_count);
props.resize(prop_count);
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayProperties(physical_devices[dev], &prop_count, props.data()));
std::vector<VkDisplayProperties2KHR> props2{};
uint32_t prop_count_2 = 0;
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayProperties2(physical_devices[dev], &prop_count_2, nullptr));
ASSERT_EQ(prop_count, prop_count_2);
props2.resize(prop_count_2, {VK_STRUCTURE_TYPE_DISPLAY_PROPERTIES_2_KHR});
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayProperties2(physical_devices[dev], &prop_count_2, props2.data()));
ASSERT_EQ(prop_count, prop_count_2);
ASSERT_TRUE(CompareDisplayPropData(props, props2));
}
}
// Test vkGetPhysicalDeviceDisplayPlaneProperties2KHR where nothing supports it.
TEST(LoaderInstPhysDevExts, PhysDevDispPlaneProps2KHRNoSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.CheckCreate();
auto GetPhysicalDeviceDisplayPlaneProperties2 = reinterpret_cast<PFN_vkGetPhysicalDeviceDisplayPlaneProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPlaneProperties2KHR"));
ASSERT_EQ(GetPhysicalDeviceDisplayPlaneProperties2, nullptr);
}
// Test vkGetPhysicalDeviceDisplayPlaneProperties2KHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevDispPlaneProps2KHRNoICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME);
instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
auto GetPhysicalDeviceDisplayPlaneProperties2 = reinterpret_cast<PFN_vkGetPhysicalDeviceDisplayPlaneProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPlaneProperties2KHR"));
ASSERT_EQ(GetPhysicalDeviceDisplayPlaneProperties2, nullptr);
}
// Compare the display plane property data structs
static bool CompareDisplayPlanePropData(const std::vector<VkDisplayPlanePropertiesKHR>& props1,
const std::vector<VkDisplayPlaneProperties2KHR>& props2) {
if (props1.size() != props2.size()) return false;
bool equal = true;
for (uint32_t i = 0; i < props1.size(); ++i) {
equal = equal && props1[i].currentDisplay == props2[i].displayPlaneProperties.currentDisplay;
equal = equal && props1[i].currentStackIndex == props2[i].displayPlaneProperties.currentStackIndex;
}
return equal;
}
// Test vGetPhysicalDeviceDisplayPlaneProperties2KHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, PhysDevDispPlaneProps2KHRInstanceAndICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
Extension first_ext{VK_KHR_DISPLAY_EXTENSION_NAME};
Extension second_ext{VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME};
env.get_test_icd(0).add_instance_extensions({first_ext, second_ext});
env.get_test_icd(0).physical_devices.push_back({});
FillInRandomDisplayPlanePropData(env.get_test_icd(0).physical_devices.back().display_plane_properties);
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extensions({VK_KHR_DISPLAY_EXTENSION_NAME, VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME});
instance.CheckCreate();
auto GetPhysicalDeviceDisplayPlaneProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPlanePropertiesKHR"));
ASSERT_NE(GetPhysicalDeviceDisplayPlaneProperties, nullptr);
auto GetPhysicalDeviceDisplayPlaneProperties2 = reinterpret_cast<PFN_vkGetPhysicalDeviceDisplayPlaneProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPlaneProperties2KHR"));
ASSERT_NE(GetPhysicalDeviceDisplayPlaneProperties2, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
std::vector<VkDisplayPlanePropertiesKHR> props{};
uint32_t prop_count = 0;
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayPlaneProperties(physical_device, &prop_count, nullptr));
ASSERT_NE(0, prop_count);
props.resize(prop_count);
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayPlaneProperties(physical_device, &prop_count, props.data()));
std::vector<VkDisplayPlaneProperties2KHR> props2{};
uint32_t prop_count2 = 0;
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayPlaneProperties2(physical_device, &prop_count2, nullptr));
ASSERT_EQ(prop_count, prop_count2);
props2.resize(prop_count2, {VK_STRUCTURE_TYPE_DISPLAY_PLANE_PROPERTIES_2_KHR});
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayPlaneProperties2(physical_device, &prop_count2, props2.data()));
ASSERT_TRUE(CompareDisplayPlanePropData(props, props2));
}
// Test vkGetPhysicalDeviceDisplayPlaneProperties2KHR where instance supports it with some ICDs that both support
// and don't support it:
// ICD 0 supports
// Physical device 0 does not
// Physical device 1 does
// Physical device 2 does not
// ICD 1 doesn't support
// Physical device 3 does not
// ICD 2 supports
// Physical device 4 does not
// Physical device 5 does not
// ICD 3 supports
// Physical device 6 does
TEST(LoaderInstPhysDevExts, PhysDevDispPlaneProps2KHRMixed) {
FrameworkEnvironment env{};
const uint32_t max_icd_count = 4;
const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
const uint32_t max_phys_devs = 7;
for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
auto& cur_icd = env.get_test_icd(icd);
cur_icd.icd_api_version = VK_API_VERSION_1_0;
cur_icd.add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
// ICD 1 should not have 1.1
if (icd != 1) {
cur_icd.icd_api_version = VK_API_VERSION_1_1;
cur_icd.add_instance_extension({VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME});
}
uint32_t rand_vendor_id;
uint32_t rand_driver_vers;
FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
uint32_t device_version = VK_API_VERSION_1_0;
cur_icd.physical_devices.push_back({});
auto& cur_dev = cur_icd.physical_devices.back();
cur_dev.extensions.push_back({VK_KHR_DISPLAY_EXTENSION_NAME, 0});
// 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
if ((icd == 0 && dev == 1) || icd == 3) {
cur_dev.extensions.push_back({VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME, 0});
device_version = VK_API_VERSION_1_1;
}
// Still set physical device properties (so we can determine if device is correct API version)
FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
FillInRandomDisplayPlanePropData(cur_dev.display_plane_properties);
}
}
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extensions({VK_KHR_DISPLAY_EXTENSION_NAME, VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME});
instance.CheckCreate();
auto GetPhysicalDeviceDisplayPlaneProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPlanePropertiesKHR"));
ASSERT_NE(GetPhysicalDeviceDisplayPlaneProperties, nullptr);
auto GetPhysicalDeviceDisplayPlaneProperties2 = reinterpret_cast<PFN_vkGetPhysicalDeviceDisplayPlaneProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPlaneProperties2KHR"));
ASSERT_NE(GetPhysicalDeviceDisplayPlaneProperties2, nullptr);
uint32_t device_count = max_phys_devs;
std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
ASSERT_EQ(device_count, max_phys_devs);
for (uint32_t dev = 0; dev < device_count; ++dev) {
std::vector<VkDisplayPlanePropertiesKHR> props{};
uint32_t prop_count = 0;
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayPlaneProperties(physical_devices[dev], &prop_count, nullptr));
ASSERT_NE(0, prop_count);
props.resize(prop_count);
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayPlaneProperties(physical_devices[dev], &prop_count, props.data()));
std::vector<VkDisplayPlaneProperties2KHR> props2{};
uint32_t prop_count2 = 0;
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayPlaneProperties2(physical_devices[dev], &prop_count2, nullptr));
ASSERT_EQ(prop_count, prop_count2);
props2.resize(prop_count2, {VK_STRUCTURE_TYPE_DISPLAY_PLANE_PROPERTIES_2_KHR});
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayPlaneProperties2(physical_devices[dev], &prop_count2, props2.data()));
ASSERT_TRUE(CompareDisplayPlanePropData(props, props2));
}
}
// Test vkGetDisplayModeProperties2KHR where nothing supports it.
TEST(LoaderInstPhysDevExts, GetDispModeProps2KHRNoSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.CheckCreate();
auto GetDisplayModeProperties2 = reinterpret_cast<PFN_vkGetDisplayModeProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetDisplayModeProperties2KHR"));
ASSERT_EQ(GetDisplayModeProperties2, nullptr);
}
// Test vkGetDisplayModeProperties2KHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, GetDispModeProps2KHRNoICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME);
instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
auto GetDisplayModeProperties2 = reinterpret_cast<PFN_vkGetDisplayModeProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetDisplayModeProperties2KHR"));
ASSERT_EQ(GetDisplayModeProperties2, nullptr);
}
// Compare the display mode properties data structs
static bool CompareDisplayModeProps(const std::vector<VkDisplayModePropertiesKHR>& disps1,
const std::vector<VkDisplayModeProperties2KHR>& disps2) {
if (disps1.size() != disps2.size()) return false;
bool equal = true;
for (uint32_t i = 0; i < disps1.size(); ++i) {
equal = equal && disps1[i].displayMode == disps2[i].displayModeProperties.displayMode;
equal = equal && disps1[i].parameters.visibleRegion.width == disps2[i].displayModeProperties.parameters.visibleRegion.width;
equal =
equal && disps1[i].parameters.visibleRegion.height == disps2[i].displayModeProperties.parameters.visibleRegion.height;
equal = equal && disps1[i].parameters.refreshRate == disps2[i].displayModeProperties.parameters.refreshRate;
}
return equal;
}
// Test vGetDisplayModeProperties2KHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, GetDispModeProps2KHRInstanceAndICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
Extension first_ext{VK_KHR_DISPLAY_EXTENSION_NAME};
Extension second_ext{VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME};
env.get_test_icd(0).add_instance_extensions({first_ext, second_ext});
env.get_test_icd(0).physical_devices.push_back({});
GenerateRandomDisplayModeProps(env.get_test_icd(0).physical_devices.back().display_mode_properties);
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extensions({VK_KHR_DISPLAY_EXTENSION_NAME, VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME});
instance.CheckCreate();
auto GetDisplayModeProperties = reinterpret_cast<PFN_vkGetDisplayModePropertiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetDisplayModePropertiesKHR"));
ASSERT_NE(GetDisplayModeProperties, nullptr);
auto GetDisplayModeProperties2 = reinterpret_cast<PFN_vkGetDisplayModeProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetDisplayModeProperties2KHR"));
ASSERT_NE(GetDisplayModeProperties2, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
std::vector<VkDisplayModePropertiesKHR> props{};
uint32_t props_count1 = 0;
ASSERT_EQ(VK_SUCCESS, GetDisplayModeProperties(physical_device, VK_NULL_HANDLE, &props_count1, nullptr));
ASSERT_NE(0, props_count1);
props.resize(props_count1);
ASSERT_EQ(VK_SUCCESS, GetDisplayModeProperties(physical_device, VK_NULL_HANDLE, &props_count1, props.data()));
std::vector<VkDisplayModeProperties2KHR> props2{};
uint32_t props_count2 = 0;
ASSERT_EQ(VK_SUCCESS, GetDisplayModeProperties2(physical_device, VK_NULL_HANDLE, &props_count2, nullptr));
ASSERT_EQ(props_count1, props_count2);
props2.resize(props_count2, {VK_STRUCTURE_TYPE_DISPLAY_MODE_PROPERTIES_2_KHR});
ASSERT_EQ(VK_SUCCESS, GetDisplayModeProperties2(physical_device, VK_NULL_HANDLE, &props_count2, props2.data()));
ASSERT_TRUE(CompareDisplayModeProps(props, props2));
}
// Test vkGetDisplayModeProperties2KHR where instance supports it with some ICDs that both support
// and don't support it:
// ICD 0 supports
// Physical device 0 does not
// Physical device 1 does
// Physical device 2 does not
// ICD 1 doesn't support
// Physical device 3 does not
// ICD 2 supports
// Physical device 4 does not
// Physical device 5 does not
// ICD 3 supports
// Physical device 6 does
TEST(LoaderInstPhysDevExts, GetDispModeProps2KHRMixed) {
FrameworkEnvironment env{};
const uint32_t max_icd_count = 4;
const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
const uint32_t max_phys_devs = 7;
for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
auto& cur_icd = env.get_test_icd(icd);
cur_icd.icd_api_version = VK_API_VERSION_1_0;
cur_icd.add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
// ICD 1 should not have 1.1
if (icd != 1) {
cur_icd.icd_api_version = VK_API_VERSION_1_1;
cur_icd.add_instance_extension({VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME});
}
uint32_t rand_vendor_id;
uint32_t rand_driver_vers;
FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
uint32_t device_version = VK_API_VERSION_1_0;
cur_icd.physical_devices.push_back({});
auto& cur_dev = cur_icd.physical_devices.back();
cur_dev.extensions.push_back({VK_KHR_DISPLAY_EXTENSION_NAME, 0});
// 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
if ((icd == 0 && dev == 1) || icd == 3) {
cur_dev.extensions.push_back({VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME, 0});
device_version = VK_API_VERSION_1_1;
}
// Still set physical device properties (so we can determine if device is correct API version)
FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
GenerateRandomDisplayModeProps(cur_dev.display_mode_properties);
}
}
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extensions({VK_KHR_DISPLAY_EXTENSION_NAME, VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME});
instance.CheckCreate();
auto GetDisplayModeProperties = reinterpret_cast<PFN_vkGetDisplayModePropertiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetDisplayModePropertiesKHR"));
ASSERT_NE(GetDisplayModeProperties, nullptr);
auto GetDisplayModeProperties2 = reinterpret_cast<PFN_vkGetDisplayModeProperties2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetDisplayModeProperties2KHR"));
ASSERT_NE(GetDisplayModeProperties2, nullptr);
uint32_t device_count = max_phys_devs;
std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
ASSERT_EQ(device_count, max_phys_devs);
for (uint32_t dev = 0; dev < device_count; ++dev) {
std::vector<VkDisplayModePropertiesKHR> props{};
uint32_t props_count1 = 0;
ASSERT_EQ(VK_SUCCESS, GetDisplayModeProperties(physical_devices[dev], VK_NULL_HANDLE, &props_count1, nullptr));
ASSERT_NE(0, props_count1);
props.resize(props_count1);
ASSERT_EQ(VK_SUCCESS, GetDisplayModeProperties(physical_devices[dev], VK_NULL_HANDLE, &props_count1, props.data()));
std::vector<VkDisplayModeProperties2KHR> props2{};
uint32_t props_count2 = 0;
ASSERT_EQ(VK_SUCCESS, GetDisplayModeProperties2(physical_devices[dev], VK_NULL_HANDLE, &props_count2, nullptr));
ASSERT_EQ(props_count1, props_count2);
props2.resize(props_count2, {VK_STRUCTURE_TYPE_DISPLAY_MODE_PROPERTIES_2_KHR});
ASSERT_EQ(VK_SUCCESS, GetDisplayModeProperties2(physical_devices[dev], VK_NULL_HANDLE, &props_count2, props2.data()));
ASSERT_TRUE(CompareDisplayModeProps(props, props2));
}
}
// Test vkGetDisplayPlaneCapabilities2KHR where nothing supports it.
TEST(LoaderInstPhysDevExts, GetDispPlaneCaps2KHRNoSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.CheckCreate();
auto GetDisplayPlaneCapabilities = reinterpret_cast<PFN_vkGetDisplayPlaneCapabilitiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetDisplayPlaneCapabilitiesKHR"));
ASSERT_EQ(GetDisplayPlaneCapabilities, nullptr);
}
// Test vkGetDisplayPlaneCapabilities2KHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, GetDispPlaneCaps2KHRNoICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME);
instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
auto GetDisplayPlaneCapabilities = reinterpret_cast<PFN_vkGetDisplayPlaneCapabilitiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetDisplayPlaneCapabilitiesKHR"));
ASSERT_EQ(GetDisplayPlaneCapabilities, nullptr);
}
// Compare the display plane caps
static bool CompareDisplayPlaneCaps(const VkDisplayPlaneCapabilitiesKHR& caps1, VkDisplayPlaneCapabilities2KHR& caps2) {
bool equal = true;
equal = equal && caps1.supportedAlpha == caps2.capabilities.supportedAlpha;
equal = equal && caps1.minSrcPosition.x == caps2.capabilities.minSrcPosition.x;
equal = equal && caps1.minSrcPosition.y == caps2.capabilities.minSrcPosition.y;
equal = equal && caps1.maxSrcPosition.x == caps2.capabilities.maxSrcPosition.x;
equal = equal && caps1.maxSrcPosition.y == caps2.capabilities.maxSrcPosition.y;
equal = equal && caps1.minSrcExtent.width == caps2.capabilities.minSrcExtent.width;
equal = equal && caps1.minSrcExtent.height == caps2.capabilities.minSrcExtent.height;
equal = equal && caps1.maxSrcExtent.width == caps2.capabilities.maxSrcExtent.width;
equal = equal && caps1.maxSrcExtent.height == caps2.capabilities.maxSrcExtent.height;
equal = equal && caps1.minDstPosition.x == caps2.capabilities.minDstPosition.x;
equal = equal && caps1.minDstPosition.y == caps2.capabilities.minDstPosition.y;
equal = equal && caps1.maxDstPosition.x == caps2.capabilities.maxDstPosition.x;
equal = equal && caps1.maxDstPosition.y == caps2.capabilities.maxDstPosition.y;
equal = equal && caps1.minDstExtent.width == caps2.capabilities.minDstExtent.width;
equal = equal && caps1.minDstExtent.height == caps2.capabilities.minDstExtent.height;
equal = equal && caps1.maxDstExtent.width == caps2.capabilities.maxDstExtent.width;
equal = equal && caps1.maxDstExtent.height == caps2.capabilities.maxDstExtent.height;
return equal;
}
// Test vkGetDisplayPlaneCapabilities2KHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, GetDispPlaneCaps2KHRInstanceAndICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
Extension first_ext{VK_KHR_DISPLAY_EXTENSION_NAME};
Extension second_ext{VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME};
env.get_test_icd(0).add_instance_extensions({first_ext, second_ext});
env.get_test_icd(0).physical_devices.push_back({});
FillInRandomDisplayPropData(env.get_test_icd(0).physical_devices.back().display_properties);
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extensions({VK_KHR_DISPLAY_EXTENSION_NAME, VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME});
instance.CheckCreate();
auto GetDisplayPlaneCapabilities = reinterpret_cast<PFN_vkGetDisplayPlaneCapabilitiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetDisplayPlaneCapabilitiesKHR"));
ASSERT_NE(GetDisplayPlaneCapabilities, nullptr);
auto GetDisplayPlaneCapabilities2 = reinterpret_cast<PFN_vkGetDisplayPlaneCapabilities2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetDisplayPlaneCapabilities2KHR"));
ASSERT_NE(GetDisplayPlaneCapabilities2, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
VkDisplayPlaneCapabilitiesKHR caps{};
ASSERT_EQ(VK_SUCCESS, GetDisplayPlaneCapabilities(physical_device, 0, 0, &caps));
VkDisplayPlaneCapabilities2KHR caps2{};
VkDisplayPlaneInfo2KHR info{VK_STRUCTURE_TYPE_DISPLAY_PLANE_INFO_2_KHR};
ASSERT_EQ(VK_SUCCESS, GetDisplayPlaneCapabilities2(physical_device, &info, &caps2));
ASSERT_TRUE(CompareDisplayPlaneCaps(caps, caps2));
}
// Test vkGetDisplayPlaneCapabilities2KHR where instance supports it with some ICDs that both support
// and don't support it:
// ICD 0 supports
// Physical device 0 does not
// Physical device 1 does
// Physical device 2 does not
// ICD 1 doesn't support
// Physical device 3 does not
// ICD 2 supports
// Physical device 4 does not
// Physical device 5 does not
// ICD 3 supports
// Physical device 6 does
TEST(LoaderInstPhysDevExts, GetDispPlaneCaps2KHRMixed) {
FrameworkEnvironment env{};
const uint32_t max_icd_count = 4;
const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
const uint32_t max_phys_devs = 7;
for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
auto& cur_icd = env.get_test_icd(icd);
cur_icd.icd_api_version = VK_API_VERSION_1_0;
cur_icd.add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
// ICD 1 should not have 1.1
if (icd != 1) {
cur_icd.icd_api_version = VK_API_VERSION_1_1;
cur_icd.add_instance_extension({VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME});
}
uint32_t rand_vendor_id;
uint32_t rand_driver_vers;
FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
uint32_t device_version = VK_API_VERSION_1_0;
cur_icd.physical_devices.push_back({});
auto& cur_dev = cur_icd.physical_devices.back();
cur_dev.extensions.push_back({VK_KHR_DISPLAY_EXTENSION_NAME, 0});
// 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
if ((icd == 0 && dev == 1) || icd == 3) {
cur_dev.extensions.push_back({VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME, 0});
device_version = VK_API_VERSION_1_1;
}
// Still set physical device properties (so we can determine if device is correct API version)
FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
GenerateRandomDisplayPlaneCaps(cur_dev.display_plane_capabilities);
}
}
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extensions({VK_KHR_DISPLAY_EXTENSION_NAME, VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME});
instance.CheckCreate();
auto GetDisplayPlaneCapabilities = reinterpret_cast<PFN_vkGetDisplayPlaneCapabilitiesKHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetDisplayPlaneCapabilitiesKHR"));
ASSERT_NE(GetDisplayPlaneCapabilities, nullptr);
auto GetDisplayPlaneCapabilities2 = reinterpret_cast<PFN_vkGetDisplayPlaneCapabilities2KHR>(
instance.functions->vkGetInstanceProcAddr(instance, "vkGetDisplayPlaneCapabilities2KHR"));
ASSERT_NE(GetDisplayPlaneCapabilities2, nullptr);
uint32_t device_count = max_phys_devs;
std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
ASSERT_EQ(device_count, max_phys_devs);
for (uint32_t dev = 0; dev < device_count; ++dev) {
VkDisplayPlaneCapabilitiesKHR caps{};
ASSERT_EQ(VK_SUCCESS, GetDisplayPlaneCapabilities(physical_devices[dev], 0, 0, &caps));
VkDisplayPlaneCapabilities2KHR caps2{};
VkDisplayPlaneInfo2KHR info{VK_STRUCTURE_TYPE_DISPLAY_PLANE_INFO_2_KHR};
ASSERT_EQ(VK_SUCCESS, GetDisplayPlaneCapabilities2(physical_devices[dev], &info, &caps2));
CompareDisplayPlaneCaps(caps, caps2);
}
}
//
// VK_EXT_acquire_drm_display
//
// Test vkAcquireDrmDisplayEXT where nothing supports it.
TEST(LoaderInstPhysDevExts, AcquireDrmDisplayEXTNoSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.CheckCreate();
auto AcquireDrmDisplay =
reinterpret_cast<PFN_vkAcquireDrmDisplayEXT>(instance.functions->vkGetInstanceProcAddr(instance, "vkAcquireDrmDisplayEXT"));
ASSERT_EQ(AcquireDrmDisplay, nullptr);
}
// Test vkAcquireDrmDisplayEXT where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, AcquireDrmDisplayEXTNoICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_EXT_ACQUIRE_DRM_DISPLAY_EXTENSION_NAME);
instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
auto AcquireDrmDisplay =
reinterpret_cast<PFN_vkAcquireDrmDisplayEXT>(instance.functions->vkGetInstanceProcAddr(instance, "vkAcquireDrmDisplayEXT"));
ASSERT_EQ(AcquireDrmDisplay, nullptr);
}
// Test vkAcquireDrmDisplayEXT where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, AcquireDrmDisplayEXTInstanceAndICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
Extension first_ext{VK_KHR_DISPLAY_EXTENSION_NAME};
Extension second_ext{VK_EXT_ACQUIRE_DRM_DISPLAY_EXTENSION_NAME};
env.get_test_icd(0).add_instance_extensions({first_ext, second_ext});
env.get_test_icd(0).physical_devices.push_back({});
GenerateRandomDisplays(env.get_test_icd(0).physical_devices.back().displays);
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extensions({VK_KHR_DISPLAY_EXTENSION_NAME, VK_EXT_ACQUIRE_DRM_DISPLAY_EXTENSION_NAME});
instance.CheckCreate();
auto AcquireDrmDisplay =
reinterpret_cast<PFN_vkAcquireDrmDisplayEXT>(instance.functions->vkGetInstanceProcAddr(instance, "vkAcquireDrmDisplayEXT"));
ASSERT_NE(AcquireDrmDisplay, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
VkDisplayKHR display = VK_NULL_HANDLE;
ASSERT_EQ(VK_SUCCESS, AcquireDrmDisplay(physical_device, 0, display));
}
// Test vkAcquireDrmDisplayEXT where instance supports it with some ICDs that both support
// and don't support it:
// ICD 0 supports
// Physical device 0 does not
// Physical device 1 does
// Physical device 2 does not
// ICD 1 doesn't support
// Physical device 3 does not
// ICD 2 supports
// Physical device 4 does not
// Physical device 5 does not
// ICD 3 supports
// Physical device 6 does
TEST(LoaderInstPhysDevExts, AcquireDrmDisplayEXTMixed) {
FrameworkEnvironment env{};
const uint32_t max_icd_count = 4;
const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
const uint32_t max_phys_devs = 7;
for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
auto& cur_icd = env.get_test_icd(icd);
cur_icd.icd_api_version = VK_API_VERSION_1_0;
cur_icd.add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
// ICD 1 should not have 1.1
if (icd != 1) {
cur_icd.icd_api_version = VK_API_VERSION_1_1;
cur_icd.add_instance_extension({VK_EXT_ACQUIRE_DRM_DISPLAY_EXTENSION_NAME});
}
uint32_t rand_vendor_id;
uint32_t rand_driver_vers;
FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
uint32_t device_version = VK_API_VERSION_1_0;
cur_icd.physical_devices.push_back({});
auto& cur_dev = cur_icd.physical_devices.back();
cur_dev.extensions.push_back({VK_KHR_DISPLAY_EXTENSION_NAME, 0});
// 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
if ((icd == 0 && dev == 1) || icd == 3) {
cur_dev.extensions.push_back({VK_EXT_ACQUIRE_DRM_DISPLAY_EXTENSION_NAME, 0});
device_version = VK_API_VERSION_1_1;
}
// Still set physical device properties (so we can determine if device is correct API version)
FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
GenerateRandomDisplays(cur_dev.displays);
}
}
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extensions({VK_KHR_DISPLAY_EXTENSION_NAME, VK_EXT_ACQUIRE_DRM_DISPLAY_EXTENSION_NAME});
instance.CheckCreate();
auto AcquireDrmDisplay =
reinterpret_cast<PFN_vkAcquireDrmDisplayEXT>(instance.functions->vkGetInstanceProcAddr(instance, "vkAcquireDrmDisplayEXT"));
ASSERT_NE(AcquireDrmDisplay, nullptr);
uint32_t device_count = max_phys_devs;
std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
ASSERT_EQ(device_count, max_phys_devs);
for (uint32_t dev = 0; dev < device_count; ++dev) {
VkPhysicalDeviceProperties pd_props{};
instance->vkGetPhysicalDeviceProperties(physical_devices[dev], &pd_props);
for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
auto& cur_icd = env.get_test_icd(icd);
bool found = false;
for (uint32_t pd = 0; pd < dev_counts[icd]; ++pd) {
auto& cur_dev = cur_icd.physical_devices[pd];
// Find the ICD device matching the physical device we're looking at info for so we can compare the
// physical devices info with the returned info.
if (cur_dev.properties.apiVersion == pd_props.apiVersion && cur_dev.properties.deviceID == pd_props.deviceID &&
cur_dev.properties.deviceType == pd_props.deviceType &&
cur_dev.properties.driverVersion == pd_props.driverVersion &&
cur_dev.properties.vendorID == pd_props.vendorID) {
VkDisplayKHR display = VK_NULL_HANDLE;
if (icd == 1) {
// For this extension, if no support exists (like for ICD 1), the value of 0 should be returned by the
// loader.
ASSERT_EQ(VK_ERROR_INITIALIZATION_FAILED, AcquireDrmDisplay(physical_devices[dev], 0, display));
} else {
ASSERT_EQ(VK_SUCCESS, AcquireDrmDisplay(physical_devices[dev], 0, display));
}
found = true;
break;
}
}
if (found) {
break;
}
}
}
}
// Test vkGetDrmDisplayEXT where nothing supports it.
TEST(LoaderInstPhysDevExts, GetDrmDisplayEXTNoSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.CheckCreate();
auto GetDrmDisplay =
reinterpret_cast<PFN_vkGetDrmDisplayEXT>(instance.functions->vkGetInstanceProcAddr(instance, "vkGetDrmDisplayEXT"));
ASSERT_EQ(GetDrmDisplay, nullptr);
}
// Test vkGetDrmDisplayEXT where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, GetDrmDisplayEXTNoICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_EXT_ACQUIRE_DRM_DISPLAY_EXTENSION_NAME);
instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
auto GetDrmDisplay =
reinterpret_cast<PFN_vkGetDrmDisplayEXT>(instance.functions->vkGetInstanceProcAddr(instance, "vkGetDrmDisplayEXT"));
ASSERT_EQ(GetDrmDisplay, nullptr);
}
// Test vkGetDrmDisplayEXT where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, GetDrmDisplayEXTInstanceAndICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
Extension first_ext{VK_KHR_DISPLAY_EXTENSION_NAME};
Extension second_ext{VK_EXT_ACQUIRE_DRM_DISPLAY_EXTENSION_NAME};
env.get_test_icd(0).add_instance_extensions({first_ext, second_ext});
env.get_test_icd(0).physical_devices.push_back({});
GenerateRandomDisplays(env.get_test_icd(0).physical_devices.back().displays);
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extensions({VK_KHR_DISPLAY_EXTENSION_NAME, VK_EXT_ACQUIRE_DRM_DISPLAY_EXTENSION_NAME});
instance.CheckCreate();
auto GetDrmDisplay =
reinterpret_cast<PFN_vkGetDrmDisplayEXT>(instance.functions->vkGetInstanceProcAddr(instance, "vkGetDrmDisplayEXT"));
ASSERT_NE(GetDrmDisplay, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1);
VkDisplayKHR display = VK_NULL_HANDLE;
ASSERT_EQ(VK_SUCCESS, GetDrmDisplay(physical_device, 0, 0, &display));
ASSERT_EQ(display, env.get_test_icd(0).physical_devices.back().displays[0]);
}
// Test vkGetDrmDisplayEXT where instance supports it with some ICDs that both support
// and don't support it:
// ICD 0 supports
// Physical device 0 does not
// Physical device 1 does
// Physical device 2 does not
// ICD 1 doesn't support
// Physical device 3 does not
// ICD 2 supports
// Physical device 4 does not
// Physical device 5 does not
// ICD 3 supports
// Physical device 6 does
TEST(LoaderInstPhysDevExts, GetDrmDisplayEXTMixed) {
FrameworkEnvironment env{};
const uint32_t max_icd_count = 4;
const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
const uint32_t max_phys_devs = 7;
for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
auto& cur_icd = env.get_test_icd(icd);
cur_icd.icd_api_version = VK_API_VERSION_1_0;
cur_icd.add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
// ICD 1 should not have 1.1
if (icd != 1) {
cur_icd.icd_api_version = VK_API_VERSION_1_1;
cur_icd.add_instance_extension({VK_EXT_ACQUIRE_DRM_DISPLAY_EXTENSION_NAME});
}
uint32_t rand_vendor_id;
uint32_t rand_driver_vers;
FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
uint32_t device_version = VK_API_VERSION_1_0;
cur_icd.physical_devices.push_back({});
auto& cur_dev = cur_icd.physical_devices.back();
cur_dev.extensions.push_back({VK_KHR_DISPLAY_EXTENSION_NAME, 0});
// 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
if ((icd == 0 && dev == 1) || icd == 3) {
cur_dev.extensions.push_back({VK_EXT_ACQUIRE_DRM_DISPLAY_EXTENSION_NAME, 0});
device_version = VK_API_VERSION_1_1;
}
// Still set physical device properties (so we can determine if device is correct API version)
FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
GenerateRandomDisplays(cur_dev.displays);
}
}
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extensions({VK_KHR_DISPLAY_EXTENSION_NAME, VK_EXT_ACQUIRE_DRM_DISPLAY_EXTENSION_NAME});
instance.CheckCreate();
auto GetDrmDisplay =
reinterpret_cast<PFN_vkGetDrmDisplayEXT>(instance.functions->vkGetInstanceProcAddr(instance, "vkGetDrmDisplayEXT"));
ASSERT_NE(GetDrmDisplay, nullptr);
uint32_t device_count = max_phys_devs;
std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
ASSERT_EQ(device_count, max_phys_devs);
for (uint32_t dev = 0; dev < device_count; ++dev) {
VkPhysicalDeviceProperties pd_props{};
instance->vkGetPhysicalDeviceProperties(physical_devices[dev], &pd_props);
for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
auto& cur_icd = env.get_test_icd(icd);
bool found = false;
for (uint32_t pd = 0; pd < dev_counts[icd]; ++pd) {
auto& cur_dev = cur_icd.physical_devices[pd];
// Find the ICD device matching the physical device we're looking at info for so we can compare the
// physical devices info with the returned info.
if (cur_dev.properties.apiVersion == pd_props.apiVersion && cur_dev.properties.deviceID == pd_props.deviceID &&
cur_dev.properties.deviceType == pd_props.deviceType &&
cur_dev.properties.driverVersion == pd_props.driverVersion &&
cur_dev.properties.vendorID == pd_props.vendorID) {
VkDisplayKHR display = VK_NULL_HANDLE;
if (icd == 1) {
// For this extension, if no support exists (like for ICD 1), the value of 0 should be returned by the
// loader.
ASSERT_EQ(VK_ERROR_INITIALIZATION_FAILED, GetDrmDisplay(physical_devices[dev], 0, 0, &display));
} else {
ASSERT_EQ(VK_SUCCESS, GetDrmDisplay(physical_devices[dev], 0, 0, &display));
ASSERT_EQ(display, cur_dev.displays[0]);
}
found = true;
break;
}
}
if (found) {
break;
}
}
}
}
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, 0U);
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"));
}
}
}